DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:explain

Explain a Term Plugin

Compatible with DokuWiki

No compatibility info given!

plugin Explains terms and links to two alternative definitions. Terms are defined in a configuration file for the whole wiki. Just like acronyms.

Last updated on
2017-06-12
Provides
Syntax
Repository
Source

Tagged with definitions, terms

Just like for the acronyms you can define a file containing a table which declares terms, a short explanation and two links to a longer definition. This automatically works for all those terms in the whole wiki.

Download and Installation

A CosmoCode Plugin

Download and install the plugin using the Plugin Manager using the URL given above. Refer to Plugins on how to install plugins manually.

Syntax

The terms are defined in the file conf/explain.conf. The syntax of the file is a table format. The table rows are the lines and the table cells are separated by tabulators. The table has the following four columns:

Term to be defined Short explanation (ca. 80 characters) first URL second URL

Only the second URL is optional, all other fields are mandatory.

  • Term to be defined” just the term, may contain spaces. E.g. “Carpe Diem
  • Short explanation” a short tool-tip explanation, used in the link title. E.g. “Latin for 'pluck the day'
  • first URL” normally the first URL is an intra-wiki link, means should go to a definition inside of your wiki. I recommend the use of my definition list plugin for this. If the first URL links to an external page, then the second URL is not used at all. E.g. “Introduction:Definitions#Carpe_Diem
  • second URL” the second URL is used, if your actual position is already inside of the first URL, in the example above, if you are actually on page Introduction:Definitions. Use the second URL to link to a more detailed or external definition. E.g. “http://en.wikipedia.org/wiki/carpe_diem

Note: Lines starting with # are treated as comments. Empty lines are allowed.

Example

A definition line in conf/explain.conf:

Carpe Diem <TAB> Latin for "pluck the day". <TAB> Introduction:Definitions#Carpe_Diem <TAB> http://en.wikipedia.org/wiki/carpe_diem

Here, <TAB> means a tabulator.

Known Bugs

With very large numbers of entries in the explain.conf file, with some configurations of PHP 4.4.6 an error can be generated by the preg-match() function running out of compilation space. That is not a bug of the explain plugin, but I have encountered it. The fix was for the hosting provider to roll back to their previous version of PHP!

- Edward Barker

ChangeLog

  • 2006-01-25 mrw
    • no more accepts()
  • 2006-01-25 mrw
    • initial release

Discussion

As this is a substitution plugin it doesn't (can't even) accept other modes. The accepts override function is not necessary. Also as I mentioned on your dl plugin page, overriding accepts is not necessary unless you want something other than default behaviour, getAllowedTypes() is the preferred method. — Christopher Smith 2006-01-25 10:55

You're so right!

Tried it and liked it

Tremendously simplifies migration of documentation from an old website to wiki where you have have existing lookup tables for the old detail pages. Stick the lookup tables into explain.conf format and migrate the pages one by one. As they are done there is only one place to change the links to the topic.

Also greatly simplifies writing the text as the links just fall into place once the explain.conf file has been constructed.

Works fine with an explain.conf file of 400k.

If you install the plugin and get a bunch of php errors on your pages, don't worry. The explain.conf must be present with at least one valid line and that fixes it. Alternatively, if you have more sense than me, install the explain.conf file before installing the plugin.

Bear in mind the second URL values in the explain.conf file are optional. Very useful, but don't worry if you don't have them for some of the terms to be explained. In fact it looks a bit odd, but even if neither URL is specified, the short description can be applied to a multi word phrase somewhat in the same way the acronym function works with single words/acronyms - though the appearance of the term in the text is as a local link, not the same style as for an acronym.

Edward Barker


Base on the style of plugins, I have changed the CSS to plugins/explain/style.css as below:

  div.dokuwiki a.explain {
    color: __black__;
    border-bottom: 1px dotted __black__;
    padding-top: 0;
  }
 
  div.dokuwiki a.explain:hover {
    background-color: __light__;
  }

I have also changed the code a little bit to use comma separated instead of TAB separated s.t. the file can be soft linked to the pages and edit via dokuwiki, just like the hint for the standard acronyms.conf editing.

<?php
    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');
 
/** Explain Terms and Definitions
 
    It works like acronym.conf, but for any term (even with more than
    one word).
 
    Evaluates con/explain.conf which is in the following syntax:
 
      term TAB explanation TAB wiki-link
 
    term:        regular expression of the term to explain
    explanation: a short description of the term
    wiki-link:   link in wiki syntax (A:B:C) to the definition
 
    License: GPL
    */
class syntax_plugin_explain extends DokuWiki_Syntax_Plugin {
 
/* csv_explode is founded by a google search, forget where it comes from. Sorry! */
function csv_explode($str, $delim = ',', $qual = "\"")
{
    $len = strlen($str);
    $inside = false;
    $word = '';
    for ($i = 0; $i < $len; ++$i) {
        if ($str[$i]==$delim && !$inside) {
            $out[] = $word;
            $word = '';
        } else if ($inside && $str[$i]==$qual && ($i<$len && $str[$i+1]==$qual)) {
            $word .= $qual;
            ++$i;
        } else if ($str[$i] == $qual) {
            $inside = !$inside;
        } else {
            $word .= $str[$i];
        }
    }
    $out[] = $word;
    return $out;
} /*-------csv_explode()------------*/
 
  function syntax_plugin_explain() {
    // "static" not allowed in PHP4?!?
    //if (isset($keys[0]) return; // evaluate at most once
    $lines = @file(DOKU_CONF.'explain.conf');
    foreach ($lines as $line) {
      $line = trim($line);
      if (empty($line)) continue;
      /* changed the explode to cvs_explode here, others remain unchanged. */
      $parts = $this->csv_explode($line);
      $this->map[$parts[0]] = array(htmlspecialchars($parts[0]),
                                    htmlspecialchars($parts[1]),
                                    $this->link($parts[2], $parts[3]));
      $this->keys[] = $parts[0];
    }
    $this->pattern = join('|', $this->keys);
  }
 
  function link($target, $other) {
    global $ID;
    static $url = '^http://';
    // '^(http://)?[-_[:alnum:]]+[-_.[:alnum:]]*\.[a-z]{2}'
    // '(/[-_./[:alnum:]&%?=#]*)?';
    if (ereg($url, $target))
      return $target;
    list($id, $hash) = split('#', $target, 2);
    resolve_pageid(getNS($ID), $id, $exists);
    if ($other!='' && $ID==$id)
      if (ereg($url, $other))
        return $other;
      else {
        list($id, $hash) = split('#', $other, 2);
        resolve_pageid(getNS($ID), $id, $exists);
        return wl($id).'#'.$hash;
      }
    else
      return wl($id).'#'.$hash;
  }
 
  function getInfo() {
    return array('author' => 'Marc Wäckerlin',
                 'email'  => 'marc [at] waeckerlin [dot-org]',
                 'name'   => 'Explain',
                 'desc'   => 'Explain terms',
                 'url'    => 'http://marc.waeckerlin.org');
  }
 
  function getType() {
    return 'substition';
  }
 
  function getSort() {
    return 239; // before 'acronym'
  }
 
  function connectTo($mode) {
     if ($this->pattern!='')
       $this->Lexer->addSpecialPattern($this->pattern, $mode,
                                       'plugin_explain');
  }
 
  function handle($match, $state, $pos, &$handler) {
    return $this->map[$match];
  }
 
  function render($format, &$renderer, $data) {
    $renderer->doc .= '<a href="'.$data[2]
      .'" title="'.$data[1].'" class="explain">'
      .$data[0].'</a>';
    return true;
  }
}
?>

Ken Cheung 2007-04-30

regular expressions

Currently the term searched for is case sensitive. Is there a way to change the search regular expression to case insensitive? — Peter Cobcroft 2008-01-15 03:50
By default, the explain plugin isn't really working with regular expressions, just with words. If you use “(?i)Carpe ?Diem” in your explain.conf, anything from “carpediem” to “Carpe Diem” will be matched. However, in the wikipage, the matching word will also be replaced by “(?i)Carpe ?Diem”, which is not what you want :-)

To change that, modify the handle() method like this:

function handle($match, $state, $pos, &$handler) {
  foreach (array_keys($this->map) as $rxmatch) {
    if (preg_match('/^('.$rxmatch.')$/',$match)) {
      return array($match,$this->map[$rxmatch][1],$this->map[$rxmatch][2]);
    }
  }
}

I've tested it and it sort of works, but round brackets and slashes loose meaning in your regexp (as they are escaped by the DokuWiki lexer). backslashes don't work either, for reasons beyond me.
*-pike 2008/03/22

explain like footnote

To make the explain 'tooltip' look more like the footnote (so it can also contain more text and behave better across browsers), I changed the render() method like this :

function render($format,&$renderer,$data) {
  $renderer->doc .= '<a class="explain" href="'.$data[2].'">';
  $renderer->doc .= $data[0];
  $renderer->doc .= '<span class="tooltip">'.$data[1].'</span>';
  $renderer->doc .= '</a>';
  return true;
}

and changed the style.css like this:

div.dokuwiki a.explain {
  position: relative;
  text-decoration:none;
  border-bottom: 1px dotted __border__;
}

div.dokuwiki a.explain span.tooltip {
  display: none;
  background-color:__background_neu__;
  color:__text_neu__;
  border:1px solid __border__;
  font-size:80%;
  line-height:1.2em;
  padding:4px 4px 8px 8px;
  text-align:left;
}

/* IE/Win requires this */
div.dokuwiki a.explain:hover {font-size: 100%;}

/*the span will display just on :hover state*/
div.dokuwiki a.explain:hover span.tooltip {
  display: block !important;
  position: absolute;
  top: 5px;
  left: 40px;
  width: 150px;
  z-index:99;
}

This trick is based on http://www.communitymx.com/content/article.cfm?cid=4E2C0 , and it works nice, except for older (1.3.9) safari's.

*-pike 2008/03/22

Two feature requests

I have a couple requests for the awesome explain plugin.

  • Can I automatically turn off links to pages that are self-referential? In other words, I don't want to link to the page on X from the page on X.
  • Due to the number of times a given term is used, some of the longer articles may link to the same article twelve or even twenty times or more. This is somewhat distracting. Is there any possible way I could link to only the first time a given term is used? –Paul Albert, 27 July 2009
    • The version of 2015-02-26 has this feature. –Art Carlson, Max Planck Institute of Biochemistry, Munich, Germany, 2015-07-08

When do changes take effect?

When I add an entry to explain.conf, it sometimes (usually?) has no effect on pages already containing that term, even if these are reloaded. If I make a change and save the page, the explain term becomes active. Is there any way to control or at least predict when the changes will take effect? Is there any way to force the changes in explain.conf to be propagated to all the pages on the wiki? –Art Carlson, Max Planck Institute of Biochemistry, Munich, Germany, 2015-07-08

A solution I can live with is purging the cache. After making my changes, I go to Admin > Configuration Settings > Save (without making any changes). That apparently forces dokuwiki to re-render every page before displaying it the next time, using the new version of the explain.config file. –Art Carlson, Max Planck Institute of Biochemistry, Munich, Germany, 2015-07-15

My experience is that you have to change and re-change the template to force it. Only saving the configuration isn't enough in all cases. Also see my git issue at GIT Cache problem #1 for this.
Juergen_aus_ZuendorfJuergen_aus_Zuendorf

2015-07-15 14:31

Use with deflist plugin

I decided to use this plugin in conjunction with the deflist plugin to provide direct internal links to my glossary page. I ran into a problem because one of my terms was PAGE (Polyacrylamide gel electrophoresis), and explain was linking every use of the ordinary word “page”. What I needed was a way to turn off the linkage to a term for most cases, but still specify linkage in the few cases where it was appropriate.

What I discovered was a hack consisting up two parts.

First, add a space character at the end of the line of containing the term on the glossary page, like this:

  ?? PAGE<SPACE><NEWLINE>
:: Polyacrylamide gel electrophoresis !!

Second, add a space after the term in the explain.conf file, like this:

PAGE<SPACE><TAB>Polyacrylamide gel electrophoresis<TAB>:glossary#page

For reasons undocumented, this turns off the recognition of the word “page”, unless it is followed by a double space (“the PAGE<SPACE><SPACE>technique”) or a space plus a character that is not a letter or a digit or an underscore.

This will usually give the right result, namely no link, but it will still give a false link if, for example, the normal word page is followed by a parenthetical comment. For the few instances that PAGE really does refer to electrophoresis and should be linked, an extra space must be added in the wiki markup.

–Art Carlson, Max Planck Institute of Biochemistry, Munich, Germany, 2015-07-13

Very simple ODT-Plugin support

At the moment, the terms are not exported via the plugin odt. Fixed it.

    public function render($format, Doku_Renderer $renderer, $data) {
        if(is_null($data['desc'])) {
            $renderer->doc .= hsc($data['content']);
            return true;
        }
        if ($format == 'xhtml') {
            $renderer->doc .= '<a class="explain"';
            if(($data['target']) !== '') {
                $renderer->doc .= ' href="' . hsc($data['target']) . '"';
            }
            $renderer->doc .= '>' . hsc($data['content']);
            if ($data['desc'] !== '') {
                $renderer->doc .= '<span class="tooltip">'.hsc($data['desc']).'</span>';
            }
            $renderer->doc .= '</a>';
            return true;
        }
        // generate output for ODT export
        if ($format == 'odt') {
            $renderer->doc .= hsc($data['content']);
            return true;
        }
        return false;
    }

– Alois Hockenschlohe, Germany

plugin/explain.txt · Last modified: 2017-06-13 23:50 by andi