====== Definition List Syntax Plugin ====== ---- plugin ---- description: Another (X)HTML definition list. IMHO with better (simpler and smarter) syntax author : Marc Wäckerlin email : marc@waeckerlin.org type : syntax lastupdate : compatible : depends : conflicts : similar : definition, deflist, dl, definitions tags : list, definitions ---- There are at least two other plugins for definition lists with different syntax and different implementation. Choose which you prefer: [[doku>plugin:definitionlist]], [[doku>plugin:deflist]]. The reason for a new implementation is the following: Simple and good looking syntax, high flexibility. The definition list created with this plugin can be linked by the [[plugin:explain|plugin for explanation of terms]]. ===== Flexibility ===== The definition list is as flexible, as the XHTML definition list (''%%
%%''). It offers the same possiblilities, including: * you can have multiple lines for a text * you can have multiple titles * you can have multiple descriptions * and you can have any other element nested inside the definition list * including lists * and the definition list itself ===== Syntax ===== It works very similar to the ordered and unordered list that come with the DokuWiki. All definition titles ("''
''" in XHTML) start with a question mark "''?''" and all definition definitions ("''
''" in XHTML) start with an exclamation mark "''!''". As in list, indentation is important. You can indent any number of spaces, even zero, for a definition list. If you indent more, you create a nested definition list inside the definition list. Other than for lists, the definition list ends only after an empty line. This is necessary, because a definition text (title or definition) can be written on several lines. ===== Example ===== The following code: ? Definition Title Multiple lines are possible ! Definition Description ? Definition Title1 ? Definition Title2 ! Definition Description1 ! Definition Description2 ! Definition Description3 ? Subdefinition ! Description ! Back ? Again deeper !Can also start at first line with description only. Is translated to:
Definition Title Multiple lines are possible
Definition Description
Definition Title1
Definition Title2
Definition Description1
Definition Description2
Definition Description3
Subdefinition
Description
Back
Again deeper
Can also start at first line with description only.
===== Installation ===== ==== The Template's PHP Code ==== To install the functionality, copy the following code into a new file named ''lib/plugins/dl/syntax.php'': 'Marc Wäckerlin', 'email' => 'marc [at] waeckerlin [dot-org]', 'name' => 'Definition List Plugin', 'desc' => 'HTML Definition List', 'url' => 'http://marc.waeckerlin.org'); } function getType() { return 'container'; } // function getPType() { // return 'block'; // } function getSort() { return 3; } function accepts($mode) { if (!count($this->allowedModes)) { global $PARSER_MODES; $this->allowedModes = array_merge($PARSER_MODES['container'], $PARSER_MODES['baseonly'], $PARSER_MODES['formatting'], $PARSER_MODES['substition'], $PARSER_MODES['protected'], $PARSER_MODES['disabled'], $PARSER_MODES['paragraphs']); unset($this->allowedModes[array_search('preformatted', $this->allowedModes)]); } return parent::accepts($mode); } function connectTo($mode) { $this->Lexer->addEntryPattern('^ *\!', $mode, 'plugin_dl'); $this->Lexer->addEntryPattern('^ *\?[^\n]*', $mode, 'plugin_dl'); } function postConnect() { $this->Lexer->addPattern('\n *\!', 'plugin_dl'); $this->Lexer->addPattern('^ *\!', 'plugin_dl'); $this->Lexer->addPattern('\n *\?[^\n]*', 'plugin_dl'); $this->Lexer->addPattern('^ *\?[^\n]*', 'plugin_dl'); $this->Lexer->addExitPattern('\n$', 'plugin_dl'); } function handle($match, $state, $pos, &$handler){ if (($state==DOKU_LEXER_MATCHED || $state==DOKU_LEXER_ENTER) && ereg('\?', $match)) { $title = htmlspecialchars(ereg_replace("\n* *\?(.*)", '\1', $match)); $match = ereg_replace("(\n* *\?).*", '\1', $match); } else { $title = ''; } return array($match, $state, $title); } function render($format, &$renderer, $data) { static $close = ''; static $level = 0; static $last_neesting = 0; static $indent = array(); static $dlstart = "\n
"; static $dlend = "\n
"; static $dtstart = "\n
"; static $dtend = "
"; static $ddstart = "\n
"; static $ddend = "
"; list($match, $state, $title) = $data; while ($match[0]=="\n") $match=substr($match, 1); $neesting = strlen($match); if ($state==DOKU_LEXER_MATCHED) { if ($last_neesting<$neesting) { $renderer->doc .= $close.$ddstart.$dlstart; $close = ''; $indent[++$level] = $neesting; } else if ($last_neesting>$neesting) { $renderer->doc .= $close.$dlend.($level?$ddend:''); $close = ''; while ($level && $indent[--$level]>$neesting) $renderer->doc .= $dlend.($level?$ddend:''); } $last_neesting = $neesting; } switch ($state) { case DOKU_LEXER_ENTER: { $last_neesting = $neesting; if ($level>0) $renderer->doc .= $close; for (; $level>0; --$level) $renderer->doc .= $dlend.($level!=1?$ddend:''); $renderer->doc .= $dlstart; if (ereg('\?', $match)) { $renderer->doc .= $dtstart; $close = $dtend; if ($title!='') $renderer->doc .= ''.$title; } else if (ereg('!', $match)) { $renderer->doc .= $ddstart; $close = $ddend; } else return false; $indent[++$level] = $neesting; } return true; case DOKU_LEXER_EXIT: { $renderer->doc .= $close; for (; $level>0; --$level) $renderer->doc .= $dlend.($level!=1?$ddend:''); $renderer->doc .= "\n"; } return true; case DOKU_LEXER_MATCHED: { if (ereg('\?', $match)) { $renderer->doc .= $close; $renderer->doc .= $dtstart; $close = $dtend; if ($title!='') $renderer->doc .= ''.$title; } else if (ereg('!', $match)) { $renderer->doc .= $close; $renderer->doc .= $ddstart; $close = $ddend; } else return false; } return true; case DOKU_LEXER_UNMATCHED: { $renderer->doc .= htmlspecialchars($match); } return true; } return false; } } ?>
==== Optional CSS Definition ==== For the look and feel, put the following code in a new file ''lib/plugins/dl/style.css''. Or optionally add the styles to your template's ''design.css'' file (if the name of your template is ''default'', then it is in ''lib/tpl/default/design.css'', also copy it to ''lib/tpl/default/print.css'' for the printing): dl { padding: 0.1em; margin: 0.2em; } dl > dl { margin: 0em 0em 0em 4em; border: 0px; padding: 0px; } dt { margin-top: .2em; font-weight: bold; } dt:before { content: "→ "; font-weight: bold; } dt:after { content: ":"; font-weight: bold; margin-top: 0.2em; } dd { margin-bottom: .2em; margin-left: 4em; } ===== Known Bugs ===== It is not XHTML valid, because it is nested inside a ''%%

%%'', where I have no influence on it. What can I do? (see also the discussion below) ===== Discussion ===== * Neat, simple nesting, I should have put that in mine :-). You may want to include links to the alternate definition list plugins (there are three others) and add yours on the pages of those plugins. * Some coding notes. * The addPattern() method should really be moved from connectTo() to postConnect(). connectTo is called for each syntax mode and adds patterns to those modes. addPattern() is used to add patterns to your plugin's mode so only needs to be called once. * I take it you are not using getAllowedModes() and are overriding accepts() as you wish the plugin to be able to enter its own mode. However you are also using addPattern() to add the same patterns to your mode, which implies you want to handle them without nesting. That seems contradictory. * as an aside, should getAllowedModes() be updated to allow a plugin to easily indicate that it wishes to include itself in the list of syntax modes it accepts? --- //[[chris@jalakai.co.uk|Christopher Smith]] 2006-01-12 13:39// ==== Answer by Marc Wäckerlin ==== (There's no special "Discussion" button, is there?) In fact, it is my first try on writing a plugin for the [[doku>DokuWiki]], just to warm up. I've also written a cool page navigator, which is derieved from the index, but that's not a plugin, but in the template's main.php. Is anyone interested? Where's the right way to publish? Also I aded a "next" and "previous" page link in the navigator and the page header, so that one can step through all pages. All I know, I got from the info-plugin sample, the online docs and code reading (especially the existing lists). Some things were hard to fiddle out, and for some things, I don't really know, why they are this way and not that way, so please educate me, when I'm wrong. To your comments: - Moved addPattern() to postConnect(). - I've overwritten accepts(), because I read somewhere that I should do it that way -- if I remember right, I read that getAllowedModes() were deprecated? Anyway, it work's, and that's all I need ;-) - That's a question? Well, where should **I** know from? > See the [[devel:Syntax Plugins]]. The plugin interface has moved forward since its initial implementation, some of the older plugins may not take advantage of those changes. accepts() needed to be overridden until the Sep release when getAllowedModes() was introduced. getAllowedModes() and an accepts() method in the syntax plugin class overcame the original issue (the first plugin(s) loaded didn't see the syntax modes of plugins loaded later). Yes, it works, but it would work one way or the other, both aren't needed. I suspect you can do away with nesting. The last question was for debate, right now there is no answer just opinions ;-) > For your other functions, yes thats a problem. For now you could add something via the tips page. Tell me more about the index navigator thingy. It might dovetail well with the sidebar plugin, when no special sidebar page is provided. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2006-01-13 02:47// >>> Hmm, did you ever bother to check whether the generated markup is valid? As far as I can see from the example given above at least the "nested" lists are not marked up correctly (the "nested" DL should be part of either DT or DD).\\ >> Actually, it can only be the DD. DT is quite restricted in what it can contain, much like a P. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2006-01-19 03:58// > That problem, I have locally fixed and I'll upload as soon, as the following is fixed too: >>> Markup is incorrect for another reason too: The whole ''%%

%%'' is placed inside a ''%%

%%'', which is not allowed. Question: **Why?** What can I do to have ''%%%%'' as parent? --- //Marc// >> Its a restriction on the

element. Strictly that means your plugin should be defined as ''PType="block"'', however block seems flaky. Checkout how the other plugins manage it. iirc, precede your plugin's markup with ''

'' and finish it with ''

''. You should also have a look back at before adding the ''

'' to check for an empty

and if found remove it rather thank writing the closing tag. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2006-01-24 02:03// > No, unfortunately that's a solution that inserts a new problem. > 1. I don't want an empty paragraf in front and after. It is the last possibility to get it XHTML compliant, but not a good solution. > 2. Returning ''%%'block'%%'' in function ''%%getPType%%'', resolves the problem of the ''%%

%%'' in front and ''%%

%%'' after, which are both gone, but unfortunately it introduces a new problem: All recogized elements within the ''%%
%%'', e.g. ''%%%%''-links are now enclosed in ''%%

%%''-paragrafs, which is absolutely not acceptable. I'd declare this as a bug of DokuWiki -- What do you think? > 3. Scanning and removing the preceding ''%%

%%'', I supose in the ''%%$renderer->doc%%'', would work, even though it's a very dirty hack, but it's not a solution for the closing ''%%

%%'', because I can't remove it in advance... --- //Marc// I don't seem to be able to get the multi-line DEFINITION TITLE to work. I copied the sample code, as is, ans multi-line definition title displays on a single line. --- //[[walter@torres.ws|Walter]] 2008-01-11 02:20// It seems that doku links inside the definition title are not supported, in the definition definition they are. Is this intended or could this be improved? --- //[[sven@meiers.net|Sven]]//