* Content of 'comma' including [[:syntax|wiki syntax]] * Content of 'separated' and here **is** //some// ''formatting'' * Content of 'list' * * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_simpletabs extends DokuWiki_Syntax_Plugin { // The name of currently rendering tab - useful for ensuring syntax (no // close tab before open, for example) var $current_tab; var $current_tab_number; // Print debug messages var $debug; // The count of tabbed areas encountered on this page (so we can ensure a // unique identifier is assigned) var $tab_area_counter; var $tab_counter; var $tabs; var $divide_edit_section; function __construct() { global $PARSER_MODES; $this->allowedModes = array_merge($PARSER_MODES['container'], $PARSER_MODES['formatting'], $PARSER_MODES['substition'], $PARSER_MODES['protected'], $PARSER_MODES['disabled'], $PARSER_MODES['paragraphs']); // Init $this->debug = true; //false; $this->divide_edit_section = false; $this->tab_area_counter = 0; $this->tab_counter = 0; } /** __construct() **/ /** @function * */ function _debugPrint($msg) { if ($this->debug) { echo "

[DEBUG] " . $msg . "

\n"; } } /** _debugPrint() **/ /** * Should return the type of syntax this plugin defines. */ function getType() { return 'container'; } /** getType() **/ /** * Returns a number used to determine in which order modes are added. */ function getSort() { return 45; } /** * What kind of syntax do we allow (optional) */ function getAllowedTypes() { return array('container','formatting','substition','protected','disabled','paragraphs'); } /** getAllowedTypes() **/ /** * Define how this plugin is handled regarding paragraphs. * *

* This method is important for correct XHTML nesting. It returns * one of the following values: *

*
*
normal
The plugin can be used inside paragraphs.
*
block
Open paragraphs need to be closed before * plugin output.
*
stack
Special case: Plugin wraps other paragraphs.
*
*/ function getPType() { return 'normal'; } /** * Connect lookup pattern to lexer. */ function connectTo($mode) { $this->Lexer->addEntryPattern('(?=.*?)$',$mode,'plugin_simpletabs'); // The tabs $this->Lexer->addPattern('', 'plugin_simpletabs'); $this->Lexer->addPattern('', 'plugin_simpletabs'); // Hide comments always (sometimes used as separator) $this->Lexer->addPattern('', 'plugin_simpletabs'); // Special things inside the content we want to manually handle. $this->Lexer->addPattern( '^[ \t]*={2,6}\s?[^\n]+={2,6}[ \t]*(?=\n)', 'plugin_simpletabs'); } function postConnect() { $this->Lexer->addExitPattern('','plugin_simpletabs'); } /** * Handler to prepare matched data for the rendering process. * *

* The $aState parameter gives the type of pattern * which triggered the call to this method: *

*
*
DOKU_LEXER_ENTER
*
a pattern set by addEntryPattern()
*
DOKU_LEXER_MATCHED
*
a pattern set by addPattern()
*
DOKU_LEXER_EXIT
*
a pattern set by addExitPattern()
*
DOKU_LEXER_SPECIAL
*
a pattern set by addSpecialPattern()
*
DOKU_LEXER_UNMATCHED
*
ordinary text encountered within the plugin's syntax mode * which doesn't match any pattern.
*
* @param $aMatch String The text matched by the patterns. * @param $aState Integer The lexer state for the match. * @param $aPos Integer The character position of the matched text. * @param $aHandler Object Reference to the Doku_Handler object. * @return Integer The current lexer state for the match. * @public * @see render() * @static */ function handle($match, $state, $pos, &$handler) { switch ($state) { case DOKU_LEXER_ENTER: // Increment the counter for tabbed area identifiers $this->tab_area_counter++; // Reset these two variables used to track progress through tabbed area $this->current_tab = ''; $this->tab_counter = 0; // Separate the tab names - hopefully there are the same number as tabbed // areas otherwise things will go strange $this->tab_names = array(); if (preg_match('/tabs="(.+)"/', $match, $matches)) { $this->tab_names = explode(',', $matches[1]); } // When rendered this command will create the unordered list that acts as // the tabs themselves as well as the precursor for the tabbed content. $this->_debugPrint("Handler=>enter tabbed area: " . $matches[1]); return array($state, array('action' => 'open tabbed area', 'tab_area_id' => $this->tab_area_counter, 'tab_names' => $this->tab_names, 'default_tab' => $this->getConf('defaulttab'), 'bytepos' => $pos)); break; case DOKU_LEXER_MATCHED: // Open tab area if ($match == '' && $this->current_tab == '') { $this->current_tab = $this->tab_names[$this->tab_counter]; $this->tab_counter++; $this->current_tab_number = $this->tab_counter; $active = false; if ($this->current_tab == $this->getConf('defaulttab')) { $active = true; } // When rendered this command will open the div serving as a tabbed // area's content $this->_debugPrint("Handler=>open tab: " . $this->current_tab); return array($state, array('action' => 'open tab', 'tab_area_id' => $this->tab_area_counter, 'tab_number' => $this->tab_counter, 'active' => $active, 'bytepos' => $pos)); } if ($match == '') { $this->_debugPrint("Handler=>close tab: " . $this->current_tab); // Housekeeping $this->current_tab = ''; $this->current_tab_number = 0; // When rendered this command closes the tabbed area content div return array($state, array('action' => 'close tab', 'bytepos' => $pos + strlen($match))); } // note: we only handle comments inside tabbed area but outside of tabs if (empty($this->current_tab) && preg_match('//s', $match, $matches)) { $this->_debugPrint("Handler=>comment: " . htmlspecialchars($matches[1])); $params = array(); $params['action'] = 'comment'; $params['comment'] = $matches[1]; return array($state, $params); } if (preg_match('/(={2,6})\s*(.+?)\s*={2,6}/', $match, $matches)) { $this->_debugPrint("Handler=>header: " . htmlspecialchars($match)); $params = array(); $params['action'] = 'heading'; $params['title'] = $matches[2]; $params['level'] = 7 - strlen($matches[1]); return array($state, $params); //$handler->_addCall('header',array($params['title'],$params['level'],$pos),$pos); //return false; } break; case DOKU_LEXER_EXIT: $this->_debugPrint("Handler=>exit tabbed area"); return array($state, array('action' => 'close tabbed area', 'bytepos' => $pos + strlen($match))); break; case DOKU_LEXER_UNMATCHED: $this->_debugPrint("Handler=>unmatched: " . htmlspecialchars($match)); return array($state, $match); break; } $this->_debugPrint("Unhandled: " . htmlspecialchars($match)); return array(DOKU_LEXER_UNMATCHED, $match); } /** * Handle the actual output creation. * *

* The method checks for the given $aFormat and returns * FALSE when a format isn't supported. $aRenderer * contains a reference to the renderer object which is currently * handling the rendering. The contents of $aData is the * return value of the handle() method. *

* @see handle() */ function render($mode, &$renderer, $data) { if($mode == 'xhtml') { list($state, $params) = $data; switch ($state) { case DOKU_LEXER_ENTER: if ($this->divide_edit_section && method_exists($renderer, 'finishSectionEdit')) { $renderer->finishSectionEdit($params['bytepos']); } $renderer->doc .= '

'; // Provide match for illegal wrapping

$renderer->doc .= '

'; break; case DOKU_LEXER_MATCHED: switch($params['action']) { case 'open tab': $extra_classy = ''; if ($this->divide_edit_section && method_exists($renderer, 'startSectionEdit')) { $extra_classy = ' ' . $renderer->startSectionEdit($params['bytepos'], 'plugin_simpletabs'); } $renderer->doc .= '
doc .= ' style="display:none;"'; } $renderer->doc .= '>'; $renderer->doc .= '

'; // Open bogus

break; case 'close tab': if ($this->divide_edit_section && method_exists($renderer, 'finishSectionEdit')) { $renderer->finishSectionEdit($params['bytepos']); } $renderer->doc .= '

'; // Close bogus

$renderer->doc .= '

'; $renderer->doc .= '
'; break; case 'comment': $renderer->doc .= ''; break; case 'heading': $renderer->doc .= '' . $params['title'] . ''; break; default: $renderer->doc .= '

Error! Unknown action: ' . $params['action'] . '

'; } break; case DOKU_LEXER_EXIT: $renderer->doc .= '
'; $renderer->doc .= '

'; // Provide match for illegal wrapping

if ($this->divide_edit_section && method_exists($renderer, 'startSectionEdit')) { $class = $renderer->startSectionEdit($params['bytepos'], 'plugin_simpletabs'); $renderer->doc .= '

'; } break; case DOKU_LEXER_UNMATCHED: $renderer->doc .= $params; break; } return true; } return false; } } //Setup VIM: ex: et ts=4 enc=utf-8 : ?>