DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:definitions

Definition List plugin 2

Compatible with DokuWiki

No compatibility info given!

plugin Adds definition lists to DokuWiki's syntax.

Last updated on
2005-08-17
Provides
Syntax

1. Description

With this plugin the syntax of DokuWiki is extended to allow definition lists. <dl><dt>term</dt><dd>Term definition</dd></dl>

2. Syntax

  = Term : Definition of term.

There should be at least two spaces before '='.

3. Example

  = Item 1 : Definition of item 1.
  = Item 2 : Definition of item 2.
  = : Second definition of item 2.
  = Item 3 : Definition of item 3.
  = Item 4 : 
  = Item 5 : 
  = Item 6 : Definition of items 4 through 6.

Will be rendered as HTML code:

<dl>
  <dt>Item 1</dt>
    <dd>Definition of item 1.</dd>
  <dt>Item 2</dt>
    <dd>Definition of item 2.</dd>
    <dd>Second definition of item 2.</dd>
  <dt>Item 3</dt>
    <dd>Definition of item 3.</dd>
  <dt>Item 4</dt>
  <dt>Item 5</dt>
  <dt>Item 6</dt>
    <dd>Definition of items 4 through 6.</dd>
</dl>

4. Plugin

Put the following PHP file in /lib/plugins/definitions/syntax.php.

syntax.php
<?php
/**
 * Allow creating of HTML definition lists:
 * <DL>
 *   <DT>term</DT><DD>Term explanation</DD>
 * </DL>
 *
 * Syntax:
 *   = term : definition
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Pavel Vitis <pavel [dot] vitis [at] seznam [dot] cz>
 */
 
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_definitions extends DokuWiki_Syntax_Plugin {
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Pavel Vitis',
            'email'  => 'pavel [dot] vitis [at] seznam [dot] cz',
            'date'   => '2005-08-17',
            'name'   => 'Definition list plugin',
            'desc'   => 'Add HTML style definition list = term : definition',
            'url'    => 'http://www.dokuwiki.org/plugin:definitions',
        );
    }
 
    /**
     * What kind of syntax are we?
     */
    function getType(){
        return 'container';
    }
 
    function getAllowedTypes() {
        // allow all types inside <DD></DD> descriptions
        return array('container','substition','protected','disabled','formatting');
    }
 
   /**
    * Paragraph Type
    *
    * Defines how this syntax is handled regarding paragraphs. This is important
    * for correct XHTML nesting. Should return one of the following:
    *
    * '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.
    *
    * @see Doku_Handler_Block
    */
    function getPType(){
        // Normal because we don't want to have <p></p> around each block
        return 'normal';
    }
 
    /**
     * Where to sort in?
     */
    function getSort(){
        // just make sure that we render before 'code' parser otherwise it ends up as code block
        return 11;
    }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
       // let's get all from '=' to ':' inclusive
       $this->Lexer->addEntryPattern('\n {2,}=[^:]+:',$mode,'plugin_definitions');
       $this->Lexer->addEntryPattern('\n\t{1,}=[^:]+:',$mode,'plugin_definitions');
 
       // and match all forthcoming '= term :' as well
       $this->Lexer->addPattern('\n {2,}=[^:]+:', 'plugin_definitions');
       $this->Lexer->addPattern('\n\t{1,}=[^:]+:', 'plugin_definitions');
    }
 
    function postConnect() {
        // end each definition with new line
        $this->Lexer->addExitPattern('\n','plugin_definitions');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
        switch ( $state ) {
            case DOKU_LEXER_ENTER:
                // we are at the start of whole list, so strip off '=' at the beginning and ':'
                // at the end and we get the 'term'
                $match = substr(trim($match),1,-1);
                return array($match, $state);
                break;
            case DOKU_LEXER_MATCHED:
                // we are at another = line, so strip off '=' at the beginning and ':'
                // at the end and we get another 'term'
                $match = substr(trim($match),1,-1);
                return array($match, $state);
                break;
            case DOKU_LEXER_UNMATCHED:
                // we are inside description here so do nothing special
                return array($match, $state);
                break;
            case DOKU_LEXER_EXIT:
                // we are at the end of whole list so do nothing special
                return array($match, $state);
                break;
        }
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
        if($mode == 'xhtml'){
            if ($data[1] == DOKU_LEXER_ENTER) {
                // output starting tag and first term and start description
                $renderer->doc .= "<dl>\n\t<dt>".$data[0]."</dt>\n\t\t<dd>";
            } else if ($data[1] == DOKU_LEXER_MATCHED){
                // close previous description and output term and start another description
		if (trim($data[0]) != '') {
                    $renderer->doc .= "</dd>\n\t<dt>".$data[0]."</dt>\n\t\t<dd>";
		}
		else {
                    $renderer->doc .= "</dd>\n\t\t<dd>";
		}    
            } else if ($data[1] == DOKU_LEXER_UNMATCHED){
                // we are inside description, so pass it to renderer unchanged
                $renderer->doc .= ''.$data[0].'';
            } else if ($data[1] == DOKU_LEXER_EXIT){
                // close last description and close whole block
                $renderer->doc .= "</dd>\n</dl>\n";
            }
            return true;
        }
        return false;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :
?>

5. Stylesheet (optional)

Put the following css into file /lib/plugins/definitions/style.css (optional).

style.css
dl {
}
dt {
  font-size: 90%;
  font-weight:bold;
}
dd {
  font-size: 95%;
  margin-left:10pt;
}
 
dd p {
  display: inline;
  margin: 0px;
  padding:0px;
}

6. Bugs

None so far.

7. ToDo

8. Discussion

You can see it working on my page. — Pavel Vitis 2005-08-18 02:21

Pavel, you shouldn't pass raw wiki data unfiltered to the output document - it should at least go through an entity conversion function, e.g. $renderer→xmlEntities(). That will convert ”<” & ”>” to &lt; & &gt; and ensure no malicious HTML (or JavaScript) can be embedded in the wiki page. — Christopher Smith 2005-08-25 20:09

Omniting empty definition

If you wan to create something like this:

<dl>
  <dt>First Term</dt>
  <dt>Second Term</dt>
  <dd>Their definition</dt>
</dl>

You try to do this:

= First Term : 
= Second Term : Their definition

This is problematic when you try create something like this.

So, I prepare patch for this (correctDefinitions.patch):

correctDefinitions.patch
diff -crB definitions/syntax.php definitions-ng/syntax.php
*** definitions/syntax.php	Tue Jun 23 13:50:00 2009
--- definitions-ng/syntax.php	Tue Jun 23 14:09:40 2009
***************
*** 130,150 ****
          if($mode == 'xhtml'){
              if ($data[1] == DOKU_LEXER_ENTER) {
                  // output starting tag and first term and start description
!                 $renderer->doc .= "<dl>\n\t<dt>".$data[0]."</dt>\n\t\t<dd>";
              } else if ($data[1] == DOKU_LEXER_MATCHED){
                  // close previous description and output term and start another description
  		if (trim($data[0]) != '') {
!                     $renderer->doc .= "</dd>\n\t<dt>".$data[0]."</dt>\n\t\t<dd>";
  		}
- 		else {
-                     $renderer->doc .= "</dd>\n\t\t<dd>";
- 		}    
              } else if ($data[1] == DOKU_LEXER_UNMATCHED){
                  // we are inside description, so pass it to renderer unchanged
!                 $renderer->doc .= ''.$data[0].'';
              } else if ($data[1] == DOKU_LEXER_EXIT){
                  // close last description and close whole block
!                 $renderer->doc .= "</dd>\n</dl>\n";
              }
              return true;
          }
--- 130,149 ----
          if($mode == 'xhtml'){
              if ($data[1] == DOKU_LEXER_ENTER) {
                  // output starting tag and first term and start description
!                 $renderer->doc .= "<dl>\n\t<dt>".$data[0]."</dt>\n";
              } else if ($data[1] == DOKU_LEXER_MATCHED){
                  // close previous description and output term and start another description
  		if (trim($data[0]) != '') {
!                     $renderer->doc .= "\t<dt>".$data[0]."</dt>\n";
  		}
              } else if ($data[1] == DOKU_LEXER_UNMATCHED){
                  // we are inside description, so pass it to renderer unchanged
!                 if (trim($data[0]) != '') {
!                         $renderer->doc .= "\t\t<dd>".$data[0]."</dd>\n";
!                 }
              } else if ($data[1] == DOKU_LEXER_EXIT){
                  // close last description and close whole block
!                 $renderer->doc .= "</dl>\n";
              }
              return true;
          }

To apply this patch, run in the dir of definition plugin

patch -p1 -i correctDefinitions.patch

You can view patch in action on my page

plugin/definitions.txt · Last modified: 2012/11/20 23:36 by Klap-in