DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:code

Code Replacement Plugin

Compatible with DokuWiki

2005-09-22 and later

plugin Enhancements for the normal <code> syntax

Last updated on
2008-08-13
Provides
Syntax
Conflicts with
jquery-syntax

This plugin replaces the current DokuWiki handlers for <code> </code> & <file> </file> markup. It adds ability to recognize and render a title above the code box.

This plugin was inspired by 477 and my own curiosity to see if it was possible to override DokuWiki's native syntax handling.

There is another Code Plugin which adds line numbers, console mode and can highlight diff output.


See the plugin in action here (or below)

Syntax

<code lang |title> some code </code>
<file |title> some text </file>

lang

The lang parameter causes the syntax highlighting according to the language you specify

Supported parameters (fileextensions given if differ from lang):

FIXME - this list is incomplete, please add any supported language thats not listed

A full list of supported languages can be found here.

  • actionscript as
  • c
  • cpp
  • css
  • html
  • ini
  • java
  • javascript js (including JSON)
  • nsis
  • php
  • plsql
  • python py
  • sql
  • xml
  • bash
  • delphi
  • asp.net asp
  • coldfusion cfm

title

Adding a title will add a small flag ontop of the codebox to enable the direct downloading of the sourcecode

If no title is given the plugin will render the <code> or <file> markup identically to the native DokuWiki handler.

Installation

Plugin sources: zip format (4k), tar.gz format (2k) | darcs (requires darcs plugin)

Download the source to your plugin folder, lib/plugins and extract its contents. That will create a new plugin folder, lib/plugins/code, and install the plugin.

The folder will contain:

style.css                              styles for the new boxes and titles
syntax/                                syntax plugin folder
syntax/code.php                        plugin script for <code>
syntax/file.php                        plugin script for <file>

The plugin is now installed.

Details

The plugin consists of three files, two (almost identical) syntax plugins files, syntax/code.php & syntax/file.php and some CSS styles, style.css.

syntax/code.php

code.php
<?php
/**
 * Code Plugin: replaces DokuWiki's own code syntax
 *
 * Syntax:     <code lang |title>
 *   lang      (optional) programming language name, is passed to geshi for code highlighting
 *             if not provided, the plugin will attempt to derive a value from the file name
 *             (refer $extensions in render() method)
 *   title     (optional) all text after '|' will be rendered above the main code text with a
 *             different style.
 *
 * if no title is provided will render as native DokuWiki code syntax mode, e.g.
 *   <pre class='code {lang}'> ... </pre>
 *
 * if title is provide will render as follows
 *   <div class='source'>
 *     <p>{title}</p>
 *     <pre class='code {lang}'> ... </pre>
 *   </div>
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Christopher Smith <chris@jalakai.co.uk>
 */
 
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_code_code extends DokuWiki_Syntax_Plugin {
 
    var $syntax = "";
 
    /**
     * return some info
     */
    function getInfo(){
      return array(
        'author' => 'Christopher Smith',
        'email'  => 'chris@jalakai.co.uk',
        'date'   => '2008-08-13',
        'name'   => 'Code Replacement Plugin',
        'desc'   => 'Replacement for DokuWiki\'s own <code> handler, adds a title to the box.
                     Syntax: <code lang|title>, lang and title are optional. title does not support any DokuWiki markup.',
        'url'    => 'http://www.dokuwiki.org/plugin:code',
      );
    }
 
    function getType(){ return 'protected';}
    function getPType(){ return 'block';}
 
    // must return a number lower than returned by native 'code' mode (200)
    function getSort(){ return 195; }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
      $this->Lexer->addEntryPattern('<code(?=[^\r\n]*?>.*?</ code>)',$mode,'plugin_code_code');
    }
 
    function postConnect() {
      $this->Lexer->addExitPattern('</ code>', 'plugin_code_code');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
 
        switch ($state) {
          case DOKU_LEXER_ENTER:
            $this->syntax = substr($match, 1);
            return false;
 
          case DOKU_LEXER_UNMATCHED:
             // will include everything from <code ... to ... </code >
             // e.g. ... [lang] [|title] > [content]
             list($attr, $content) = preg_split('/>/u',$match,2);
             list($lang, $title) = preg_split('/\|/u',$attr,2);
 
             if ($this->syntax == 'code') {
               $lang = trim($lang);
               if ($lang == 'html') $lang = 'html4strict';
               if (!$lang) $lang = NULL;
             } else {
               $lang = NULL;
             }
 
             return array($this->syntax, $lang, trim($title), $content);
        }
        return false;
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
 
        if (count($data) == 4) {
          list($syntax, $lang, $title, $content) = $data;
 
          if($mode == 'xhtml'){
            if ($title) $renderer->doc .= "<div class='$syntax'><p>".$renderer->_xmlEntities($title)."</p>";
            if ($syntax == 'code') $renderer->code($content, $lang); else $renderer->file($content);
            if ($title) $renderer->doc .= "</div>";
        } else {
            if ($syntax == 'code') $renderer->code($content, $lang); else $renderer->file($content);
        }
 
        return true;
      }
      return false;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

syntax/file.php

file.php
<?php
/**
 * File Plugin: replaces DokuWiki's own file syntax
 *
 * Syntax:     <file |title>
 *   title     (optional) all text after '|' will be rendered above the main code text with a
 *             different style.
 *
 * if no title is provided will render as native DokuWiki code syntax mode, e.g.
 *   <pre class='file'> ... </pre>
 *
 * if title is provide will render as follows
 *   <div class='file'>
 *     <p>{title}</p>
 *     <pre class='file'> ... </pre>
 *   </div>
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Christopher Smith <chris@jalakai.co.uk>
 */
 
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_code_file extends DokuWiki_Syntax_Plugin {
 
    var $syntax = "";
 
    /**
     * return some info
     */
    function getInfo(){
      return array(
        'author' => 'Christopher Smith',
        'email'  => 'chris@jalakai.co.uk',
        'date'   => '2008-08-13',
        'name'   => '<file> replacement plugin',
        'desc'   => 'Replacement for DokuWiki\'s own <file> handler, adds a title to the box.
                     Syntax: <file|title>, title is optional and does not support any DokuWiki markup.',
        'url'    => 'http://www.dokuwiki.org/plugin:code',
      );
    }
 
    function getType(){ return 'protected';}
    function getPType(){ return 'block'; }
 
    // must return a number lower than returned by native 'file' mode (210)
    function getSort(){ return 194; }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
      $this->Lexer->addEntryPattern('<file(?=[^\r\n]*?>.*?</file>)',$mode,'plugin_code_file');
    }
 
    function postConnect() {
    $this->Lexer->addExitPattern('</file>', 'plugin_code_file');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
 
        switch ($state) {
            case DOKU_LEXER_ENTER:
                $this->syntax = substr($match, 1);
                return false;
 
            case DOKU_LEXER_UNMATCHED:
                // will include everything from <code ... to ... </code >
                // e.g. ... [lang] [|title] > [content]
                list($attr, $content) = preg_split('/>/u',$match,2);
                list($lang, $title) = preg_split('/\|/u',$attr,2);
 
                if ($this->syntax == 'code') {
                    $lang = trim($lang);
                    if ($lang == 'html') $lang = 'html4strict';
                    if (!$lang) $lang = NULL;
                } else {
                    $lang = NULL;
                }
 
                return array($this->syntax, $lang, trim($title), $content);
        }
        return false;
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
 
      if (count($data) == 4) {
        list($syntax, $lang, $title, $content) = $data;
 
        if($mode == 'xhtml'){
            if ($title) $renderer->doc .= "<div class='$syntax'><p>".$renderer->_xmlEntities($title)."</p>";
            if ($syntax == 'code') $renderer->code($content, $lang); else $renderer->file($content);
            if ($title) $renderer->doc .= "</div>";
        } else {
            if ($syntax == 'code') $renderer->code($content, $lang); else $renderer->file($content);
        }
 
        return true;
      }
      return false;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

style.css

These may be modified to suit your own requirements.

style.css
/*
 * code plugin extension - style additions
 *
 * @author  Christopher Smith  chris@jalakai.co.uk
 * @link    http://wiki.jalakai.co.uk/dokuwiki/doku.php/tutorials/codeplugin
 */
 
/* layout */
div.code, div.file {
  width: 92%;
  margin: 1em auto;
  border: 1px solid;
  padding: 4px;
}
 
div.code p, div.file p {
  font-size: 90%;
  margin: 0;
  padding: 2px;
}
 
div.code pre.code, div.file pre.file {
  margin: 4px 0 0 0;
}
 
/* colours */
div.code {
  border-color:  #bbd;
  background: #e4ecf8;
}
 
div.code p {
  background: #cad0ee;
}
 
div.file {
  border-color: #dbb;
  background: #f8ece4;
}
 
div.file p {
  background: #eed0ca;
}
 
div.file pre.file {
  background: #fdf4ec;
  border-color: #dbb;
}
 
/* end code plugin style additions */

Revision History

  • 2008-08-13 — Update plugin URL
    • — Add support for unknown render formats (e.g. ODT plugin)
  • 2006-12-17 — Sync below darcs update into main package.
  • 2006-01-24 — Minor update, darcs only (package release held until after next DokuWiki update)
    • replace hex entities in patterns with < & >
  • 2005-08-19 — Updated, split into two plugin scripts to allow nesting of <code> within <file> and vice versa. Downloadable plugin package released.
  • 2005-08-01 — Updated, adds titles to the ”<file>” syntax.
  • 2005-07-30 — Released.

To Do

Bugs

Discussion

What would be nice is if it automatically generates a title based on the language attribute set if no title is explicitly set. — ta' lajzar 2005-07-30 05:06

Modify handle() …
                if (!$lang) $lang = NULL;
// add one line
                if (!trim($title) && $lang) $title = "Language: $lang";
// end addition
            } else {

ChrisS 2005-07-31 (updated 2005-08-01)


Can you make the class search for java code search java 1.5 (or let me config what i want as 1.6 is around the corner)?

DokuWiki uses the GeSHi syntax highlighter to provide the highlighting. Refer to DokuWiki's syntax page and to GeSHi for details. — Christopher Smith 2006-10-20 12:32

Is there a list of supported code types for this plugin? That would be really handy! Cool plugin.

See GeSHi.

Cool plug-in, but would be even better with line numbering.

See the other Code plugin which provides just that.
Matthias Watermann 2007-01-31 21:59

I love this plugin, but I often find myself documenting console instructions, is it possible to add a <console> version of the file/code but with the <console> its black background with white writing similar to a console I guess :) just and idea or perhaps someone has all ready done this.

You might want to install the other Code Plugin which provides a console mode.
Matthias Watermann 2008/04/05 19:35

Great plugin but i have an issue: if i write

<code bash | title>
${something}
...

in a <code bash> tag the output is

${something}|>

this happen with the bash syntax highlight, but without this plugin (with the default code render) it does not happen. I've watched the HTML of the page

<span class="re0">$<span class="br0">&#123;</span>something<span class="br0">&#125;</span><span class="sy0">|</span>></pre></div>

Is this a bug?
Enrico 2008/12/16 2:16

It doesn't happen for me, see test page. — Christopher Smith 2008/12/17 01:09
In your page the code is grey it is not highlighted. In my page something is blue and the {} are green. I can't figure where is the problem. Thanks for the reply. Enrico 2008/12/21 18:06
here it is the HTML code that i get
<div class='code'><p>title</p><pre class="code bash"><span class="re0">$<span class="br0">&#123;</span>something<span class="br0">&#125;</span><span class="sy0">|</span>></pre></div> </div>
The code plugin does very little. Its a wrapper around DokuWiki's code syntax to provide a title and different appearance. The syntax highlighting itself is provided by a separate module, GeSHI, included with the DokuWiki core. The code plugin doesn't change the highlighting colours, they are typically part of the template. Any different in highlighting colours may be due to a different template. All I can suggest is you update to the latest DokuWiki, the latest version of the code plugin and check that all syntax modes in the page are closed properly. Also, you may want to see how the page looks in the default template. — Christopher Smith 2008/12/25 15:13
I've already the latest DokuWiki and, I'm using the default template… by the way it can be a GeSHI bug?
Enrico 2009/1/4 16:00
I have the same problem, I suspect it is a geshi issue. I checked first it wasn't other plugins by turning them all off. Still there. Turned off this plugin and just used the default code format in DokuWiki. Problem still there. Then dug through the geshi code. Line 2304 (pasted below) in inc/geshi.php causes the problem. It runs into a problem parsing the span markers when there are curly brackets in the expression (geshi uses |> as a temporary span marker) and so the HTML above is missing a closing span.
preg_match_all("/<\|(?:<DOT>|[^>])+>(?:(?!\|>).*?)\|>|<\/a>/", $stuff_to_parse, $highlighted_in_stuff, PREG_OFFSET_CAPTURE);
This code is embedded inside an if statement for symbol highlighting. Immediately preceding that is an if statement that handles bracket highlighting. You can fix it by moving the bracket highlighting so that it is done after the symbol highlighting - testing this now to see if I ever have other odd effects creep in because of the shift. Note, my geshi version (defined at the top of inc/geshi.php) is 1.0.7.21.
Snorri 2009/3/19
Tried to update my wiki to 2009-02-14. Now the plugin produces invalid XHTML (strict) markup due open paragraph won't be closed before the (optional div) and pre tags are insert. Any idea or hint what the problem may be?
Gunther 2009/4/6 23:24
plugin/code.txt · Last modified: 2013/12/11 07:06 by 219.133.170.93