code replacement plugin

experimental

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

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

Syntax

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

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

See the page in action here

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

To install, put the following PHP file in lib/plugins/code/syntax/.

<?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'   => '2005-08-18',
        '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://wiki.splitbrain.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]*?\x3E.*?\x3C/code\x3E)',$mode,'plugin_code_code');
    }
 
    function postConnect() {
      $this->Lexer->addExitPattern('\x3C/code\x3E', '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($mode == 'xhtml'){
        if (count($data) == 4) {
 
            list($syntax, $lang, $title, $content) = $data;
            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>";
        }
 
        return true;
      }
      return false;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

syntax/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'   => '2005-08-18',
        '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://wiki.splitbrain.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]*?\x3E.*?\x3C/file\x3E)',$mode,'plugin_code_file');
    }
 
    function postConnect() {
      $this->Lexer->addExitPattern('\x3C/file\x3E', '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 <file ... to ... </file >
                // 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($mode == 'xhtml'){
        if (count($data) == 4) {
 
            list($syntax, $lang, $title, $content) = $data;
            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>";
        }
 
        return true;
      }
      return false;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

style.css

These may be modified to suit your own requirements.

/*
 * 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

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

</file> nested within <code> ... </code> and </code> nested within <file> ... </file> — FIXED

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)

Your example syntax to make it work is not entirely the same as the syntax that does make it work. - Monjo

Square brackets ("[]") removed from syntax. — Christopher Smith 2005/08/19 22:30
 
tutorials/codeplugin.txt · Last modified: 2012/06/08 16:53 by 24.39.174.1
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki