WikiRenderer

fran├žais

Creating rules

Principles

You want to create a new rule, to convert from a specific wiki syntax to another syntax markup. In summary, here what you should do:

  1. Create a file, with a new configuration object, inheriting from WikiRendererConfig (or from one of an existing rule).
  2. Create some new object which will convert a wiki tag to the corresponding target markup. This objects can inherit from those of an existing rule.
  3. Register this objects into the configuration object
  4. Then you can use WikiRenderer with your new rule.

Don't hesitate to open a rule file, to see how it is organized.

Different type of tags

In a wiki syntax, or in other markup language such HTML, we have two type of tag:

  1. Those to identify a type of block of content. Types of block of content can be a list, a table, a paragraph, a title. We can say that it corresponds to HTML elements which have a style like display:block;. We will call them, "block tags".
  2. Those to format words or to insert specific behaviors inside sentences. This is for example to specify emphasis, links, code, etc. We will call it "inline tags".

To summary, inline tags are used inside sentences, and block tags are use outside sentence, to specify the type of the content.

To implement a converter, we will inherit from a different class, depending of the type of tag: WikiTag for inline tags, and WikiRendererBloc for block tags.

There are also objects call "line handlers". This objects are responsible to process text content which are outside inline tags in a line of text.

Creating inline tags

A WikiTag object represents a specific wiki tag. An inline tag has a markup to indicate the begin of the tag, an other markup for the end of the tag. Some of wiki tag contain often different parts, separated by a specific character. For example, for a link, the writer can indicate an URL and a title:

[[http://foo.bar|my link]]

We have here the delimiters of the tag : [[ and ]]. And we have a separator, |. So we have two parts, we call them "attributes". The first attribute is the URL, the second is the title of the link.

A class for an inline tag

To create a handler for your wiki tag, you should create a class which inherits from WikiTag, and set some properties with the delimiters of your tag, attributes list, and the separator. For our link tag:


class my_link extends WikiTag {

    // the left delimiter of our tag
    public $beginTag='[[';

    // the right delimiter of our tag
    public $endTag=']]';

    // the name of attributes
    protected $attribute=array('href', '$$');

    // the separator
    public $separators=array('|');

}

Attributes and separators

In the $attribute property, you have to indicate the name you give for each attribute allowed in your wiki tag. You can give any name. However, there is one name which have a special meaning: "$$". This name indicates to the parser that the content of the attribute can contain other wiki tags.

In the $separators property, you give the list of separators. In most of time, you use only one type of separator to separate attributes. But some time it is not the case, so you will indicate all different separators, in the same order of attributes. For example, you have 4 attributes on your wiki tag, and the separator between the third and the fourth is different (% for example) than the others (| for example), you will indicate:


    public $separators=array('|','|','%');

If this is the first which is different, you don't have to list all the next separators:


    public $separators=array('%','|');
    // is equivalent to 
    public $separators=array('%','|', '|');

Generating the content

Our previous class is not finished. We still have to indicate how the corresponding content for the target markup should be generated. For that, we have to redefine the getContent() method. We assume that we want to generate XHTML:


    public function getContent(){

        if($this->separatorCount == 0){
            // only the URL is given
            $href = $this->wikiContentArr[0];
            $title = htmlspecialchars($href);
        }else{
            $href = $this->wikiContentArr[0];
            $title = $this->contents[1];
        }
        
        return '<a href="'.htmlspecialchars($href).'">'.$title.'</a>';
    }

For example, if in our wiki syntax, **bla** means an emphasis, and we write [[http://foo.bar|my **super** link]], the value of $this->wikiContentArr[1] will be my **super** link, and the value of $this->contents[1] will be my <strong>super</strong> link.

Note that in the case of a link for example, you will have to check the URL, to avoid javascript code for example, or you may have to generate a different URL if the syntax of the URL has a special meaning. This is often the case in a wiki CMS. For example in Dokuwiki, we can indicate "URL" like "foo:bar", and then the URL in the generated content should be "http://mysite.local/wiki/index.php?page=foo/bar" or something like that.

Generating XHTML and XML content

To generate XHTML markup or any other XML markup, there is a child class of WikiTag, named WikiTagXhtml, which have a generic getContent() method to generate XML markup.

So in most of case, you don't have to create a getContent(). Just inherits from WikiTagXhtml, indicate the name of the X(HT)ML element in the $name property. And in the $attribute property, indicate names which will be names of the X(HT)ML attributes on the element ('$$' indicate that the wiki attribute will be the content of the element).

For example, to implement a generator for the <strong> markup, this class is enough:



class wr3xhtml_strong extends WikiTagXhtml {
    protected $name='strong';
    public $beginTag='**';
    public $endTag='**';
}

For a wiki tag with attributes, here an example to generate the <acronym> XHTML element:



class wr3xhtml_acronym extends WikiTagXhtml {
    protected $name='acronym';
    public $beginTag='??';
    public $endTag='??';
    protected $attribute=array('$$','title');
    public $separators=array('|');
}

With this handler, we can write in the wiki content a standard: ??CSS|Cascading Style Sheets??, and this will be converted to a standard: <acronym title="Cascading Style Sheets">CSS</acronym>.

Generating complex content

There are other possibilities on WikiTag, and other methods you can redefine. It is too long to explain all of them. If features explained above are not enough to implement your wiki tag, see the implementation of wiki tags in the existing rules. You will discover that almost everything is possible :-)

Declaring the inline tag handler

Once you create the class, you have to declare it in the configuration. Just add its name into the inline tags list of one ore more line handler. See below.

Creating a line handler

A line handler is a class which handle the text on a line, which is outside wiki inline tags. There is a default line handler (which does nothing), WikiTextLine. There is an other, WikiHtmlTextLine, which escapes the content with htmlspecialhars. And in some rules, you have some specific line handlers to parse complex line of text, like a wiki line which defines a table row, because on such lines, all contents are separated by a specific caracters, to define values in each columns.

A line handler is in fact a class which inherits from WikiTag, with the property public $isTextLineTag=true;.

See examples in some rules, for table row.

To declare a line handler, you have two properties on the configuration class:

$defaultTextLineContainer
contain the class name of the default line handler, or more precisely, the current line handler used during the parsing.
$textLineContainers
is an array which declare all possible line handlers for the wiki syntax. It also defines, for each of them, the allowed inline tags inside lines. This definition is an array of class name of inline tags.

Note that you must declare at least one line handler in the configuration. Example


    public $defaultTextLineContainer = 'WikiHtmlTextLine';

    public $textLineContainers = array(
            'WikiHtmlTextLine'=>array( 'dkxhtml_strong','dkxhtml_emphasis','dkxhtml_underlined','dkxhtml_monospaced',
        'dkxhtml_subscript', 'dkxhtml_superscript', 'dkxhtml_del', 'dkxhtml_link', 'dkxhtml_footnote', 'dkxhtml_image',
        'dkxhtml_nowiki_inline',),
        
            'dkxhtml_table_row'=>array( 'dkxhtml_strong','dkxhtml_emphasis','dkxhtml_underlined','dkxhtml_monospaced',
        'dkxhtml_subscript', 'dkxhtml_superscript', 'dkxhtml_del', 'dkxhtml_link', 'dkxhtml_footnote', 'dkxhtml_image',
        'dkxhtml_nowiki_inline',)
    );

Creating block tags

Tag for blocks in a wiki syntax is a tag which starts at the begining of the line, and which defines the type of the block of text. For some tags, you should repeat it at the begining of each lines of the block, and sometimes, you have only to write a delimiter at the start and at the end of the block of lines.

To create a block tag handler, create a class which inherits from WikiRendererBloc. It should have a property, $type which contains a type identifer. Each blocks should have a unique name.

Then you have to specify how the parser will detect the begin and the end of the block.

Recognizing the block

You have two ways.

If the block is always only on one line, set the $_closeNow property to true.

Generating content

During the parsing, some methods on your class are called:

open()
When the parser detect (with the help of the detect() method) that the block starts, this method is called. You can redefine it to do some additionnal process. It can return a string which will be added to the generated content. By default, it returns the value of the property $_openTag (you can set it if you don't want to redefine the method).
close()
When the parser detect (with the help of the detect() method) that the block ends, this method is called. You can redefine it to do some additionnal process at this step. It can return a string which will be added to the generated content. By default, it returns the value of the property $_closeTag (you can set it if you don't want to redefine the method).
closeNow()
Returns a boolean indicating if the block should be close immediately after the opening (so in the case of a block which is defined only on one line). By default, it returns the value of $_closeNow property.
getRenderedLine()
This method is responsible to generate the content of the current parsed line. It should return the resulting string. If the content of the line can have some inline wiki tags, you should call $this->engine->inlineParser->parse($string);, where $string is the part of the line (or the entire, it depends of your syntax), which should be parsed.

Declaring the class

Just add its name into the list of the $bloctags property of the configuration class.

To know more about how to create such of classes, don't hesitate to read the source of the existing rules.