Converting Between Wiki Markup & HTML with Prototype
December 18th, 2008Wiki’s are amazing and powerful tools, unfortunately their dependence on specialized markup creates a huge barrier to their general adoption in many organizations. This is a first step at building a wysiwyg editor for wiki markup. While I will be focussing on the syntax unique to the popular MediaWiki platform, these techniques should be applicable to any wiki system.
The general flow of the converter is as follows:
- Converter is passed the root node of an html fragment to translate.
- Converter recurses through each of the child nodes and converts them.
- Root node tag is replaced with wiki markup.
There’s really only 2 key components involved in this first pass. A converter object and the recursive method.
The Converter Object
The converter object is little more than a collection of name value pairs. The name corresponds to an html tag. The value is a Prototype template to use in the direct replacement of the given node. By convention we’ll write all of the tag names for the converter object in lower case.
var Converter = {
strong: new Template("'''#{body}'''"),
b: new Template("'''#{body}'''"),
em: new Template("''#{body}''"),
i: new Template("''#{body}''"),
h1: new Template('=#{body}='),
h2: new Template('===#{body}=='),
h3: new Template(’===#{body}===’),
h4: new Template(’====#{body}====’),
h5: new Template(’=====#{body}=====’),
h6: new Template(’======#{body}======’) }
The Converter Function
The Converter function always performs 2 checks before attempting to convert a given node. First it ensures that the node is in fact a node and not a stray function from the Prototype enhanced object. Next it verifies that a converter exists for the tag. The toLowerCase() on the tagName is necessary due to the inconsistent behavior browsers demonstrate with this attribute. While all browsers return the variable in all caps for traditional html, they are not reliable about returning lower case values for xhtml markup.
function convertToWiki( textNode ){
//make sure textNode isn't a function on the object
if( typeof textNode != 'function'){
//provide a way to stop execution on select sub trees
if( !textNode.hasClassName( 'stop')){
$(textNode).childElements().each( convertToWiki );
}
//make sure a converter exists for the given tag
if( liteConverter[ textNode.tagName.toLowerCase() ] ){
//replace the text node with a converted version of itself
textNode.replace( liteConverter[textNode.tagName.toLowerCase()]
.evaluate({body:textNode.innerHTML}));
} } }




Most of us are familiar with Firebug, the powerful & straightforward debugging extension for firefox. You may not be familiar with it’s little brother, Firebug lite.