Custom markup language

Derek Jones edited this page Jul 5, 2012 · 3 revisions
Clone this wiki locally

In a project for one of my customers, I ran into a problem: traditional WYSIWYG editors fubar'ed the output, resulting in different output in different browsers, total nightmares when somebody copied from MS Word and more trouble. The main reason for this trouble was that a lot of users were able to edit the same pages. In order to overcome this problem, I wrote a custom markup language.


[h1]heading 1[h1]
[h2]heading 2[h2]

**bold**
//emphasize//
[strike]strike-through[strike]
__underline__

[url]http://www.google.nl|title|link_name[url]
[url]http://www.google.nl|link_name[url]

[sub]subscript[sub]
[sup]superscript[sup]

The parser automatically detects the differnce between line-breaks and paragraphs.

I call the language 'dyn_code', since I'm totally out of inspiration. The lang consists only of the few elements I needed for the editors, so it's extremely light weight. Take a look at the (few) available codes.

As you can see it's a bit of a mixture of BB code and Markdown, but hell, it works! Below you see the helper function. If you autoload it, you can call it from anywhere. There's one 'hidden' gem, the 'parser' is fully customizable. You can config your own preferred translation set, I build two of them in: xhtml and html (traditional). Just pass one of those as the second parameter.

In my app I also wrote a jquery based WYM editor, to accompany this 'language'. If it proofs to work properly, I'll post it online!

You can also create your own translation set. Pass an array of the following markup into the second parameter:


    $custom = array(
        'b'     => array('opening tag', 'closing tag'),
        'i'     => array('opening tag', 'closing tag'),
        'u'     => array('opening tag', 'closing tag'),
        's'     => array('opening tag', 'closing tag'),
        'h1'     => array('opening tag', 'closing tag'),
        'h2'     => array('opening tag', 'closing tag'),
        'sup'     => array('opening tag', 'closing tag'),
        'sub'     => array('opening tag', 'closing tag')
    );

    echo dyn_code($str, $custom);

The parser function


function dyn_code($html, $doctype = 'xhtml') {
    $set['xhtml'] = array(
        'b'     => array('<strong>', '</strong>'),
        'i'     => array('<em>', '</em>'),
        'u'     => array('<span style="text-decoration: underline;">', '</span>'),
        's'     => array('<span style="text-decoration: line-through;">', '</span>'),
        'h1'     => array('<h1>', '</h1>'),
        'h2'     => array('<h2>', '</h2>'),
        'sup'     => array('<sup>', '</sup>'),
        'sub'     => array('<sub>', '</sub>')
    );
    
    $set['html'] = array(
        'b'     => array('<B>', '</B>'),
        'i'     => array('<I>', '</I>'),
        'u'     => array('<U>', '</U>'),
        's'     => array('<S>', '</S>'),
        'h1'     => array('<H1>', '</H1>'),
        'h2'     => array('<H2>', '</H2>'),
        'sup'     => array('<SUP>', '</SUP>'),
        'sub'     => array('<SUB>', '</SUB>')
    );
    
    $a = $set['xhtml'];
    
    if(!is_array($doctype)) {
        if(in_array($doctype, $set)) {
            $a = $set[$doctype];
        }
    } else {
        foreach($set['xhtml'] as $k => $v) {
            if(isset($doctype[$k])) {
                $a[$k] = $doctype[$k];
            }
        }
    }
    
    $html = preg_replace("/\*\*(.{1,})\*\*/", $a['b'][0]."$1".$a['b'][1], $html);
    $html = preg_replace("/\/\/(.{1,})\/\//", $a['i'][0]."$1".$a['i'][1], $html);
    $html = preg_replace("/__(.{1,})__/", $a['u'][0]."$1".$a['u'][1], $html);
    $html = preg_replace("/\[sub\](.{1,})\[sub\]/", $a['sub'][0]."$1".$a['sub'][1], $html);
    $html = preg_replace("/\[sup\](.{1,})\[sup\]/", $a['sup'][0]."$1".$a['sup'][1], $html);
    $html = preg_replace("/\[url\](.+)\|(.+)\|(.{1,})\[url\]/", "<a >$3</a>", $html);
    $html = preg_replace("/\[url\](.+)\|(.{1,})\[url\]/", "<a >$2</a>", $html);
    $html = preg_replace("/\[(.+)\](.{1,})\[b\]/", "<a >$2</a>", $html);
    $html = preg_replace("/\[strike\](.{1,})\[strike\]/", $a['s'][0]."$1".$a['s'][1], $html);
    $html = preg_replace("/\[h1\](.{1,})\[h1\]/", $a['h1'][0]."$1".$a['h1'][1], $html);
    $html = preg_replace("/\[h2\](.{1,})\[h2\]/", $a['h2'][0]."$1".$a['h2'][1], $html);
    
    $html = '<p>' . $html . '</p>';
    $html = str_replace("\n\n", "</p><p>", $html);
    $html = str_replace("\n", "<br />", $html);
    
    return $html;
}