*/
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');
/**
* Settings:
*
* Define the trigger characters:
* ";" & ":" are the mediawiki settings.
* "=" & ":" are the settings for the original plugin by Pavel.
*/
if (!defined('DL_DT')) define('DL_DT', ';'); // character to indicate a term (dt)
if (!defined('DL_DD')) define('DL_DD', ':'); // character to indicate a definition (dd)
/**
*
*/
class syntax_plugin_definitionlist extends DokuWiki_Syntax_Plugin {
protected $stack = array(); // stack of currently open definition list items - used by handle() method
public function getType() { return 'container'; }
public function getAllowedTypes() { return array('container','substition','protected','disabled','formatting'); }
public function getPType() { return 'block'; } // block, so not surrounded by tags
public function getSort() { return 10; } // before preformatted (20)
/**
* Connect pattern to lexer
*/
public function connectTo($mode) {
$this->Lexer->addEntryPattern('\n {2,}'.DL_DT, $mode, 'plugin_definitionlist');
$this->Lexer->addEntryPattern('\n\t{1,}'.DL_DT, $mode, 'plugin_definitionlist');
$this->Lexer->addPattern('(?: '.DL_DD.' )', 'plugin_definitionlist');
$this->Lexer->addPattern('\n {2,}(?:'.DL_DT.'|'.DL_DD.')', 'plugin_definitionlist');
$this->Lexer->addPattern('\n\t{1,}(?:'.DL_DT.'|'.DL_DD.')', 'plugin_definitionlist');
}
public function postConnect() {
// we end the definition list when we encounter a blank line
$this->Lexer->addExitPattern('\n(?=[ \t]*\n)','plugin_definitionlist');
}
/**
* Handle the match
*/
public function handle($match, $state, $pos, Doku_Handler $handler) {
switch ( $state ) {
case DOKU_LEXER_ENTER:
array_push($this->stack, 'dt');
$this->_writeCall('dl',DOKU_LEXER_ENTER,$pos,$match,$handler); // open a new DL
$this->_writeCall('dt',DOKU_LEXER_ENTER,$pos,$match,$handler); // always start with a DT
break;
case DOKU_LEXER_MATCHED:
$oldtag = array_pop($this->stack);
$newtag = (substr(rtrim($match), -1) == DL_DT) ? 'dt' : 'dd';
array_push($this->stack, $newtag);
$this->_writeCall($oldtag,DOKU_LEXER_EXIT,$pos,$match,$handler); // close the current definition list item...
$this->_writeCall($newtag,DOKU_LEXER_ENTER,$pos,$match,$handler); // ...and open the new dl item
break;
case DOKU_LEXER_EXIT:
// clean up & close any dl items on the stack
while ($tag = array_pop($this->stack)) {
$this->_writeCall($tag,DOKU_LEXER_EXIT,$pos,$match,$handler);
}
// and finally close the surrounding DL
$this->_writeCall('dl',DOKU_LEXER_EXIT,$pos,$match,$handler);
break;
case DOKU_LEXER_UNMATCHED:
$handler->base($match, $state, $pos); // cdata --- use base() as _writeCall() is prefixed for private/protected
break;
}
return false;
}
/**
* helper function to simplify writing plugin calls to the instruction list
*
* instruction params are of the format:
* 0 => tag (string) 'dl','dt','dd'
* 1 => state (int) DOKU_LEXER_??? state constant
* 2 => match (string) expected to be empty
*/
protected function _writeCall($tag, $state, $pos, $match, &$handler) {
$handler->addPluginCall('definitionlist', array($tag, $state, ''), $state, $pos, $match);
}
/**
* Create output
*/
public function render($format, Doku_Renderer $renderer, $data) {
if (empty($data)) return false;
switch ($format) {
case 'xhtml' : return $this->render_xhtml($renderer,$data);
case 'odt' :
if (!method_exists ($renderer, 'getODTPropertiesFromElement')) {
return $this->render_odt_old($renderer,$data);
} else {
return $this->render_odt_new($renderer,$data);
}
default :
// handle unknown formats generically - map both 'dt' & 'dd' to paragraphs; ingnore the 'dl' container
list ($tag, $state, $match) = $data;
switch ( $state ) {
case DOKU_LEXER_ENTER:
if ($tag != 'dl') $renderer->p_open();
break;
case DOKU_LEXER_MATCHED: // fall-thru
case DOKU_LEXER_UNMATCHED: // defensive, shouldn't occur
$renderer->cdata($match);
break;
case DOKU_LEXER_EXIT:
if ($tag != 'dl') $renderer->p_close();
break;
}
return true;
}
return false;
}
/**
* create output for the xhtml renderer
*
*/
protected function render_xhtml(Doku_Renderer $renderer, $data) {
list($tag,$state,$match) = $data;
switch ( $state ) {
case DOKU_LEXER_ENTER:
$renderer->doc .= $this->_open($tag);
break;
case DOKU_LEXER_MATCHED:
case DOKU_LEXER_UNMATCHED: // defensive, shouldn't occur
$renderer->cdata($tag);
break;
case DOKU_LEXER_EXIT:
$renderer->doc .= $this->_close($tag);
break;
}
return true;
}
/**
* create output for ODT renderer
*
* @author: Gabriel Birke
*/
protected function render_odt_old(Doku_Renderer $renderer, $data) {
static $param_styles = array('dd' => 'def_f5_list', 'dt' => 'def_f5_term');
$this->_set_odt_styles_old($renderer);
list ($tag, $state, $match) = $data;
switch ( $state ) {
case DOKU_LEXER_ENTER:
if ($tag == 'dl') {
$renderer->p_close();
} else {
$renderer->p_open($param_styles[$tag]);
}
break;
case DOKU_LEXER_MATCHED:
case DOKU_LEXER_UNMATCHED: // defensive, shouldn't occur
$renderer->cdata($match);
break;
case DOKU_LEXER_EXIT:
if ($tag != 'dl') {
$renderer->p_close();
} else {
$renderer->p_open();
}
break;
}
return true;
}
/**
* Create output for ODT renderer (newer version)
* @author: LarsDW223
*/
protected function render_odt_new(Doku_Renderer $renderer, $data) {
static $style_data = array();
static $dl_properties = array();
$this->_set_odt_styles_new($renderer, $style_data, $dl_properties);
list ($tag, $state, $match) = $data;
switch ( $state ) {
case DOKU_LEXER_ENTER:
if ($tag == 'dl') {
$properties = array();
$renderer->_odtTableOpenUseProperties($dl_properties);
$properties ['width'] = $style_data ['margin-left'];
$renderer->_odtTableAddColumnUseProperties($properties);
} else {
if ($tag == 'dt') {
$renderer->tablerow_open();
$properties = array();
$properties ['border-left'] = 'none';
$properties ['border-right'] = 'none';
$properties ['border-top'] = 'none';
$properties ['border-bottom'] = $style_data ['border-bottom'];
$renderer->_odtTableCellOpenUseProperties ($properties);
$renderer->_odtSpanOpen('Plugin_DefinitionList_Term');
} else {
$properties = array();
$properties ['border-left'] = 'none';
$properties ['border-right'] = 'none';
$properties ['border-top'] = 'none';
$properties ['border-bottom'] = $style_data ['border-bottom'];
$renderer->_odtTableCellOpenUseProperties ($properties);
if (!empty($style_data ['image'])) {
$properties = array();
$properties ['margin-right'] = $style_data ['padding-left'];
$renderer->_odtAddImageUseProperties($style_data ['image'], $properties);
}
$renderer->_odtSpanOpen('Plugin_DefinitionList_Description');
}
}
break;
case DOKU_LEXER_MATCHED:
case DOKU_LEXER_UNMATCHED: // defensive, shouldn't occur
$renderer->cdata($match);
break;
case DOKU_LEXER_EXIT:
if ($tag != 'dl') {
$renderer->_odtSpanClose();
$renderer->tablecell_close();
if ($tag == 'dd') {
$renderer->p_close();
$renderer->tablerow_close();
}
} else {
$renderer->table_close();
}
break;
}
return true;
}
/**
* set definition list styles, used by render_odt_old()
*
* add definition list styles to the renderer's autostyles property (once only)
*
* @param $renderer current (odt) renderer object
* @return void
*/
protected function _set_odt_styles_old(Doku_Renderer $renderer) {
static $do_once = true;
if ($do_once) {
$renderer->autostyles["def_f5_term"] = '
';
$renderer->autostyles["def_f5_list"] = '
';
$do_once = false;
}
}
/**
* Create definition list styles, used by render_odt_new():
* Adds definition list styles to the ODT documents common styles (once only)
*
* @param Doku_renderer $renderer current (odt) renderer object
* @param Array $style_data Array for returning relevant properties to the caller
* @author: LarsDW223
*/
protected function _set_odt_styles_new(Doku_Renderer $renderer, &$style_data, &$dl_properties) {
static $do_once = true;
if ($do_once) {
// Create parent style to group the others beneath it
if (!$renderer->styleExists('Plugin_DivAlign2')) {
$parent_properties = array();
$parent_properties ['style-parent'] = NULL;
$parent_properties ['style-class'] = 'Plugin_DefinitionList';
$parent_properties ['style-name'] = 'Plugin_DefinitionList';
$parent_properties ['style-display-name'] = 'Plugin DefinitionList';
$renderer->createTextStyle($parent_properties);
}
// Get the current HTML stack from the ODT renderer
$stack = $renderer->getHTMLStack ();
// Save state to restore it later
$state = array();
$stack->getState ($state);
// Only for debugging ==> see end of this function
//$renderer->dumpHTMLStack ();
$stack->open('dl', 'class="plugin_definitionlist"', NULL, NULL);
$renderer->getODTPropertiesFromElement ($dl_properties, $stack->getCurrentElement(), 'screen', true);
$stack->open('dd', NULL, NULL, NULL);
// Get CSS properties for ODT export.
$dd_properties = array ();
$renderer->getODTPropertiesFromElement ($dd_properties, $stack->getCurrentElement(), 'screen', true);
$stack->close('dd');
$stack->open('dt', NULL, NULL, NULL);
// Get CSS properties for ODT export.
$dt_properties = array ();
$renderer->getODTPropertiesFromElement ($dt_properties, $stack->getCurrentElement(), 'screen', true);
// Set style data to be returned to caller
$style_data ['border-bottom'] = $dt_properties ['border-top'];
$style_data ['image'] = $dd_properties ['background-image'];
$style_data ['margin-left'] = $dd_properties ['margin-left'];
$style_data ['padding-left'] = $dd_properties ['padding-left'];
// Create text style for term
$dt_properties ['border-top'] = NULL;
$dt_properties ['style-class'] = NULL;
$dt_properties ['style-parent'] = 'Plugin_DefinitionList';
$dt_properties ['style-name'] = 'Plugin_DefinitionList_Term';
$dt_properties ['style-display-name'] = 'Term';
$renderer->createTextStyle($dt_properties);
// Create text style for description
$dd_properties ['border-bottom'] = $dt_properties ['border-top'];
$dd_properties ['style-class'] = NULL;
$dd_properties ['style-parent'] = 'Plugin_DefinitionList';
$dd_properties ['style-name'] = 'Plugin_DefinitionList_Description';
$dd_properties ['style-display-name'] = 'Description';
$dd_properties ['background'] = NULL;
$renderer->createTextStyle($dd_properties);
$stack->restoreState ($state);
// Only for debugging to check if the ODT plugins HTML stack
// is restored to the start state
//$renderer->dumpHTMLStack ();
$do_once = false;
}
}
/**
* open a definition list tag, used by render_xhtml()
*
* @param $tag (string) 'dl', 'dt' or 'dd'
* @return (string) html used to open the tag
*/
protected function _open($tag) {
if ($tag == 'dl') {
if ($this->getConf('classname')) {
$tag .= ' class="'.$this->getConf('classname').'"';
}
$wrap = NL;
} else {
$wrap = ($tag == 'dt' && $this->getConf('dt_fancy')) ? '' : '';
}
return "<$tag>$wrap";
}
/**
* close a definition list tag, used by render_xhtml()
*
* @param $tag (string) 'dl', 'dt' or 'dd'
* @return (string) html used to close the tag
*/
protected function _close($tag) {
$wrap = ($tag == 'dt' && $this->getConf('dt_fancy')) ? '' : '';
return "$wrap$tag>\n";
}
}
//Setup VIM: ex: et ts=4 enc=utf-8 :