* 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 = 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 .= ' ';
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 :
?>