Translations of this page?:

SVG Support

Dokuwiki is centered around collaborative project documentation. An important part of documentation is image editing. Unfortunately, everyone seems to have a different set of tools and fonts for creating images and has different styles for drawing and encoding the images. Scalable Vector Graphics (SVG) offers a highly-promising way for people to produce high, print-quality graphics in a way that also allows for collaborative effort. Unfortuately, SVG is not widely supported in web browsers at the time of this writing. So, a plugin I propose, is to allow SVG input into the text, but then convert the code into a displable image format such as PNG or GIF.

Example SVG for playing with

<svg width="30cm" height="10cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example rect01 - rectangle with sharp corners</desc>
  <!-- Show outline of canvas using 'rect' element -->
  <rect x="1" y="1" width="1198" height="398"
        fill="red" stroke="blue" stroke-width="5"/>
  <rect x="400" y="100" width="400" height="50"
        fill="red" stroke="navy" stroke-width="10"  />
</svg>

Installation prerequisites

  • SVG Convert requires ImageMagick to be installed with support for GIF (unless you change the output format) and for SVG.

Changes to DokuWiki

  • Create a directory under the /inc directory; I called it svgconvert.
  • Create a directory under /inc/svgconvert called tmp.
  • Make the tmp directory writable by the webserver.
  • Put svg.php into the svgconvert directory.
  • Create a directory under the /media directory; I also called it svgconvert.
  • Make the /media/svgconvert directory writable by the webserver.
  • Add the following three lines to /conf/dokuwiki.php.
$conf['svgdir']    = './inc/svgconvert';                // where SVGConvert is located
$conf['svgmedia']  = $conf['mediadir'] . '/svgconvert'; // where does SVGConvert store its images? (currently not used)
$conf['svgok']     = 1;                                 // may SVG code be converted to images? 0|1
  • Edit /inc/parser.php
[...]
  // In 'parse()', around line 53, add this line:
  firstpass($table,$text,"#(<svg.*?/svg>)#se","preformat('\\1', 'svg')");
[...]
 
  // In 'preparse()', around line 175, add this line:
      $line = preg_replace("#(<svg(.*?)/svg>)#","",$line);
[...]
 
  // And around line 177, change the if-condition to this:
  if(preg_match('#^.*?<(nowiki|code|php|html|file|svg)( (\w+))?>#',$line,$matches)){
[...]
 
  // In 'preformat()', around line 755, add this line:
  if($type == 'svg' && !$conf['svgok']) $type='code'; 
[...]
 
  // and around line 803, add this case to the switch-case-statement:
    case 'svg':
        include_once($conf['svgdir'] . '/svg.php');
        $text = svg_content($text);
        break;
[...]

Security Problem

As it is right now, it is possible for someone to make an image that is arbitrarily large. This could cause an incredible load on the webserver and could use up all the disk space. Also, this is a new way for messages to be embedded that might be inappropriate without proper filtering. I am seeking help with these and possibly other issues that I'm not prepared to deal with. For me, I will just restrict access to the page.

  • With a publicly-editable wiki, any file can get arbitrarily large (or users can repeatedly create new ones). So it seems that the problem is moot anyway. –Justin

Plugin hack

I hacked this into a plugin (using graphviz and plot as examples)…it ain't pretty but it works for me (may extend it to allow a filename as well). You need to create an area under /data/media (mkdir -p data/media/svg/tmp) and ensure that your webserver can write to it. =G=

<?php
/**
 * svg-Plugin: Parses svg-blocks
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Galen Johnson <solitaryr@gmail.com>
 * @version    1.0.0
 */
 
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_svgin extends DokuWiki_Syntax_Plugin {
 
    function getInfo(){
        return array(
            'author' => 'Galen Johnson',
            'email'  => 'solitaryr@gmail.com',
            'date'   => '2005-12-27',
            'name'   => 'SVG Plugin',
            'desc'   => 'Parses blocks of SVG code and converts it to an image',
            'url'    => '',
        );
    }
 
    /**
    * What kind of syntax are we?
    */
    function getType(){
        return 'protected';
    }
 
    /**
    * Where to sort in?
    */
    function getSort(){
        return 101;
    }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addEntryPattern('<svgin(?=.*\x3C/svgin\x3E)',$mode,'plugin_svgin');
    }
 
    function postConnect() {
    $this->Lexer->addExitPattern('</svgin>','plugin_svgin');
    }
 
    /**
    * Handle the match
    */
    function handle($match, $state, $pos) {
        if ( $state == DOKU_LEXER_UNMATCHED ) {
            $matches = preg_split('/>/u',$match,2);
            $matches[0] = trim($matches[0]);
            if ( trim($matches[0]) == '' ) {
                $matches[0] = NULL;
            }
            return array($matches[1],$matches[0]);
        }
        return TRUE;
    }
 
    /**
    * Create output
    */
    function render($mode, &$renderer, $data) {
        global $conf;
        if($mode == 'xhtml' && strlen($data[0]) > 1) {
            if ( !is_dir($conf['mediadir'] . '/svg') ) mkdir($conf['mediadir'] . '/svg', $conf['dmask'], true);
            $hash = md5(serialize($data[0]));
            $filename = $conf['mediadir'] . '/svg/'.$hash.'.png';
            $url = DOKU_BASE.'/lib/exe/fetch.php?cache='.$cache.'&amp;media='.urlencode('svg:'.$hash.'.png');
 
            $size_str=$data[1];
 
            if ( is_readable($filename) ) {
                $renderer->doc .= '<img src="'.$url.'" class="media" title="SVG" alt="SVG" />';
                return true;
            }
 
            if (!$this->createImage($filename, $data[0], $data[1])) {
                $renderer->doc .= '<img src="'.$url.'" class="media" title="SVG" alt="SVG" />';
            } else {
                $renderer->doc .= '**ERROR RENDERING SVG**';
            }
            return true;
        }
        return false;
    }
 
    function createImage($filename, &$data) {
        global $conf;
        $tempdir = $conf['mediadir'].'/svg/tmp';
        $tmpfname = tempnam($tempdir, "svg.");
        file_put_contents($tmpfname, $data);
        $retval = exec('/usr/bin/convert svg:'.$tmpfname.' png:'.$filename);
        unlink($tmpfname);
        return $retval;
    }
 
}
 
?>
 
wiki/tips/svg_support.txt · Last modified: 2007/10/09 12:18 by 83.61.221.155
 
Imprint Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki
WikiForumIRCBugsTranslate