http://www.mediawiki.org/wiki/Special:Code/MediaWiki/88751

Revision: 88751
Author:   tparscal
Date:     2011-05-24 21:08:41 +0000 (Tue, 24 May 2011)
Log Message:
-----------
Reorganized wikidom code.

Modified Paths:
--------------
    trunk/parsers/wikidom/demos/renderers/index.html
    trunk/parsers/wikidom/tests/wikidom.test.js
    trunk/parsers/wikidom/wikidom.js

Modified: trunk/parsers/wikidom/demos/renderers/index.html
===================================================================
--- trunk/parsers/wikidom/demos/renderers/index.html    2011-05-24 21:04:50 UTC 
(rev 88750)
+++ trunk/parsers/wikidom/demos/renderers/index.html    2011-05-24 21:08:41 UTC 
(rev 88751)
@@ -60,12 +60,12 @@
                <script>
                        $( document ).ready( function() {
                                $.getJSON( 'document.js', function( data ) {
-                                       var htmlRenderer = new HtmlRenderer();
+                                       var htmlRenderer = new 
wiki.HtmlRenderer();
                                        var html = htmlRenderer.render( data );
                                        $( '#html-rendering' ).append( html );
                                        $( '#html-source' ).text( html );
                                        
-                                       var wikitextRenderer = new 
WikitextRenderer();
+                                       var wikitextRenderer = new 
wiki.WikitextRenderer();
                                        var wikitext = wikitextRenderer.render( 
data );
                                        $( '#wikitext-source' ).text( wikitext 
);
                                        

Modified: trunk/parsers/wikidom/tests/wikidom.test.js
===================================================================
--- trunk/parsers/wikidom/tests/wikidom.test.js 2011-05-24 21:04:50 UTC (rev 
88750)
+++ trunk/parsers/wikidom/tests/wikidom.test.js 2011-05-24 21:08:41 UTC (rev 
88751)
@@ -1,8 +1,8 @@
 module( 'Wikidom Serialization' );
 
 function assertSerializations( tests ) {
-       var htmlRenderer = new HtmlRenderer();
-       var wikitextRenderer = new WikitextRenderer();
+       var htmlRenderer = new wiki.HtmlRenderer();
+       var wikitextRenderer = new wiki.WikitextRenderer();
        for ( var i = 0; i < tests.length; i++ ) {
                equals(
                        htmlRenderer.render( tests[i].dom ),
@@ -38,7 +38,7 @@
                {
                        'subject': 'horizontal rule',
                        'dom': { 'blocks': [ {
-                               'type': 'rule',
+                               'type': 'horizontal-rule',
                        } ] },
                        'html': '<hr />',
                        'wikitext': '----'

Modified: trunk/parsers/wikidom/wikidom.js
===================================================================
--- trunk/parsers/wikidom/wikidom.js    2011-05-24 21:04:50 UTC (rev 88750)
+++ trunk/parsers/wikidom/wikidom.js    2011-05-24 21:08:41 UTC (rev 88751)
@@ -1,250 +1,301 @@
-/* Utilities */
+/*
+ * Wikitext document object models
+ * 
+ * document
+ *   blocks: Array
+ *   attributes: Plain object
+ * 
+ * // Blocks
+ * 
+ * comment
+ *   text: String
+ * horizontal-rule
+ * heading
+ *   level: Integer (1..6)
+ *   line: Line object
+ * paragraph
+ *   lines: Array of line objects
+ * list
+ *   style: String ("bullet" or "number")
+ *   items: Array of item objects
+ * table
+ *   rows: Array of arrays of cell objects
+ *   attributes: Plain object
+ * 
+ * // Components
+ * 
+ * line
+ *   text: String
+ * item
+ *   line: Line object
+ *   lists: Array of list objects
+ * range
+ *   offset: Integer
+ *   length: Integer
+ * annotation
+ *   type: String
+ *   range: Range object
+ *   data: Plain object
+ * cell
+ *   document: Object
+ *   attributes: Plain object
+ */
 
-var Xml = {
-       'esc': function( text ) {
-               return text
-                       .replace( /&/g, '&amp;' )
-                       .replace( /</g, '&lt;' )
-                       .replace( />/g, '&gt;' )
-                       .replace( /"/g, '&quot;' )
-                       .replace( /'/g, '&#039;' );
-       },
-       'attr': function( attributes ) {
-               var attr = '';
-               if ( attributes ) {
-                       for ( var name in attributes ) {
-                               attr += ' ' + name + '="' + attributes[name] + 
'"';
-                       }
+var wiki = {};
+
+/**
+ * Serializes offset-based annotations.
+ */
+wiki.AnnotationRenderer = function() {
+
+       /* Private Members */
+
+       var that = this;
+       var insertions = {};
+
+       /* Methods */
+
+       this.wrapWithText = function( range, pre, post ) {
+               var start = range.offset;
+               if ( !( start in insertions ) ) {
+                       insertions[start] = [pre];
+               } else {
+                       insertions[start].push( pre );
                }
-               return attr;
-       },
-       'open': function( tag, attributes ) {
-               return '<' + tag + Xml.attr( attributes ) + '>';
-       },
-       'close': function( tag ) {
-               return '</' + tag + '>';
-       },
-       'tag': function( tag, attributes, value, escape ) {
-               if ( value === false ) {
-                       return '<' + tag + Xml.attr( attributes ) + ' />';
+               var end = range.offset + range.length;
+               if ( !( end in insertions ) ) {
+                       insertions[end] = [post];
                } else {
-                       if ( escape ) {
-                               value = Xml.esc( value );
-                       }
-                       return '<' + tag + Xml.attr( attributes ) + '>' + value 
+ '</' + tag + '>';
+                       insertions[end].unshift( post );
                }
-       }
-};
+       };
 
-function repeat( pattern, count ) {
-       if ( count < 1 ) return '';
-       var result = '';
-       while ( count > 0 ) {
-               if ( count & 1 ) result += pattern;
-               count >>= 1, pattern += pattern;
+       this.wrapWithXml = function( range, tag, attributes ) {
+               that.wrapWithText(
+                       range, wiki.util.xml.open( tag, attributes ), 
wiki.util.xml.close( tag )
+               );
        };
-       return result;
-};
 
-function AnnotationSerialization() {
-       this.insertions = {};
-}
-
-AnnotationSerialization.prototype.wrapWithText = function( range, pre, post ) {
-       var start = range.offset;
-       if ( !( start in this.insertions ) ) {
-               this.insertions[start] = [pre];
-       } else {
-               this.insertions[start].push( pre );
-       }
-       var end = range.offset + range.length;
-       if ( !( end in this.insertions ) ) {
-               this.insertions[end] = [post];
-       } else {
-               this.insertions[end].unshift( post );
-       }
+       this.apply = function( text ) {
+               var out = '';
+               for ( var i = 0, iMax = text.length; i <= iMax; i++ ) {
+                       if ( i in insertions ) {
+                               out += insertions[i].join( '' );
+                       }
+                       if ( i < iMax ) {
+                               out += text[i];
+                       }
+               }
+               return out;
+       };
 };
 
-AnnotationSerialization.prototype.wrapWithXml = function( range, tag, 
attributes ) {
-       this.wrapWithText( range, Xml.open( tag, attributes ), Xml.close( tag ) 
);
-};
+/**
+ * Serializes a WikiDom into HTML.
+ */
+wiki.HtmlRenderer = function() {
 
-AnnotationSerialization.prototype.apply = function( text ) {
-       var out = '';
-       for ( var i = 0, iMax = text.length; i <= iMax; i++ ) {
-               if ( i in this.insertions ) {
-                       out += this.insertions[i].join( '' );
-               }
-               if ( i < iMax ) {
-                       out += text[i];
-               }
-       }
-       return out;
-};
+       /* Private Members */
 
-/* Renderers */
+       var that = this;
+       var blockRenderers = {
+               'comment': renderComment,
+               'horizontal-rule': renderHorizontalRule,
+               'heading': renderHeading,
+               'paragraph': renderParagraph,
+               'list': renderList,
+               'table': renderTable
+       };
 
-function HtmlRenderer() { }
+       /* Private Methods */
 
-HtmlRenderer.prototype.render = function( doc ) {
-       return HtmlRenderer.renderers.document( doc );
-};
-
-HtmlRenderer.renderers = {
-       'document': function( doc, rawFirstParagraph ) {
+       function renderDocument( doc, rawFirstParagraph ) {
                var out = [];
                for ( var b = 0, bMax = doc.blocks.length; b < bMax; b++ ) {
                        var block = doc.blocks[b];
-                       if ( block.type in HtmlRenderer.renderers ) {
+                       if ( block.type in blockRenderers ) {
                                if ( block.type === 'paragraph' ) {
                                        out.push(
-                                               
HtmlRenderer.renderers.paragraph( block, rawFirstParagraph && b === 0 )
+                                               renderParagraph( block, 
rawFirstParagraph && b === 0 )
                                        );
                                } else {
-                                       out.push( 
HtmlRenderer.renderers[block.type]( block ) );
+                                       out.push( blockRenderers[block.type]( 
block ) );
                                }
                        }
                }
                return out.join( '\n' );
-       },
-       'comment': function( comment ) {
+       }
+
+       function renderComment( comment ) {
                return '<!--' + comment.text + '-->';
-       },
-       'rule': function( rule ) {
-               return Xml.tag( 'hr', {}, false );
-       },
-       'heading': function( heading ) {
-               return Xml.tag( 'h' + heading.level, {}, 
HtmlRenderer.renderers.line( heading.line ) );
-       },
-       'paragraph': function( paragraph, raw ) {
+       }
+
+       function renderHorizontalRule( rule ) {
+               return wiki.util.xml.tag( 'hr', {}, false );
+       }
+
+       function renderHeading( heading ) {
+               return wiki.util.xml.tag( 'h' + heading.level, {}, renderLine( 
heading.line ) );
+       }
+
+       function renderParagraph( paragraph, raw ) {
                var out = [];
                for ( var l = 0, lMax = paragraph.lines.length; l < lMax; l++ ) 
{
-                       out.push( HtmlRenderer.renderers.line( 
paragraph.lines[l] ) );
+                       out.push( renderLine( paragraph.lines[l] ) );
                }
                if ( raw ) {
                        return out.join( '\n' );
                } else {
-                       return Xml.tag( 'p', {}, out.join( '\n' ) );
+                       return wiki.util.xml.tag( 'p', {}, out.join( '\n' ) );
                }
-       },
-       'list': function( list ) {
+       }
+
+       function renderList( list ) {
                var tags = {
                        'bullet': 'ul',
                        'number': 'ol'
                };
                var out = [];
-               out.push( Xml.open( tags[list.style] ) );
+               out.push( wiki.util.xml.open( tags[list.style] ) );
                for ( var i = 0, iMax = list.items.length; i < iMax; i++ ) {
-                       out.push( HtmlRenderer.renderers.item( list.items[i] ) 
);
+                       out.push( renderItem( list.items[i] ) );
                }
-               out.push( Xml.close( tags[list.style] ) );
+               out.push( wiki.util.xml.close( tags[list.style] ) );
                return out.join( '\n' );
-       },
-       'table': function( table ) {
+       }
+
+       function renderTable( table ) {
                var out = [];
                var types = {
                        'heading': 'th',
                        'data': 'td'
                };
-               out.push( Xml.open( 'table', table.attributes ) );
+               out.push( wiki.util.xml.open( 'table', table.attributes ) );
                for ( var r = 0, rMax = table.rows.length; r < rMax; r++ ) {
-                       out.push( Xml.open( 'tr' ) );
+                       out.push( wiki.util.xml.open( 'tr' ) );
                        var row = table.rows[r];
                        for ( var c = 0, cMax = row.length; c < cMax; c++ ) {
                                var type = types[row[c].type || 'data'];
-                               out.push( Xml.tag(
+                               out.push( wiki.util.xml.tag(
                                        type,
                                        row[c].attributes,
-                                       HtmlRenderer.renderers.document( 
row[c].document, true )
+                                       renderDocument( row[c].document, true )
                                ) );
                        }
-                       out.push( Xml.close( 'tr' ) );
+                       out.push( wiki.util.xml.close( 'tr' ) );
                }
-               out.push( Xml.close( 'table' ) );
+               out.push( wiki.util.xml.close( 'table' ) );
                return out.join( '\n' );
-       },
-       'item': function( item ) {
+       }
+
+       function renderItem( item ) {
                if ( 'lists' in item && item.lists.length ) {
                        var out = [];
-                       out.push( Xml.open( 'li' ) + 
HtmlRenderer.renderers.line( item.line ) );
+                       out.push( wiki.util.xml.open( 'li' ) + renderLine( 
item.line ) );
                        for ( var l = 0, lMax = item.lists.length; l < lMax; 
l++ ) {
-                               out.push( HtmlRenderer.renderers.list( 
item.lists[l] ) );
+                               out.push( renderList( item.lists[l] ) );
                        }
-                       out.push( Xml.close( 'li' ) )
+                       out.push( wiki.util.xml.close( 'li' ) )
                        return out.join( '\n' );
                } else {
-                       return Xml.tag( 'li', {}, HtmlRenderer.renderers.line( 
item.line ) );
+                       return wiki.util.xml.tag( 'li', {}, renderLine( 
item.line ) );
                }
-       },
-       'line': function( line ) {
+       }
+
+       function renderLine( line ) {
                if ( 'annotations' in line && line.annotations.length ) {
-                       var as = new AnnotationSerialization();
+                       var ar = new wiki.AnnotationRenderer();
                        for ( var a = 0, aMax = line.annotations.length; a < 
aMax; a++ ) {
                                var an = line.annotations[a];
                                switch ( an.type ) {
                                        case 'bold':
-                                               as.wrapWithXml( an.range, 
'strong' );
+                                               ar.wrapWithXml( an.range, 
'strong' );
                                                break;
                                        case 'italic':
-                                               as.wrapWithXml( an.range, 'em' 
);
+                                               ar.wrapWithXml( an.range, 'em' 
);
                                                break;
                                        case 'xlink':
-                                               as.wrapWithXml( an.range, 'a', 
{ 'href': an.data.url } );
+                                               ar.wrapWithXml( an.range, 'a', 
{ 'href': an.data.url } );
                                                break;
                                        case 'ilink':
-                                               as.wrapWithXml( an.range, 'a', 
{ 'href': '/wiki/' + an.data.title } );
+                                               ar.wrapWithXml( an.range, 'a', 
{ 'href': '/wiki/' + an.data.title } );
                                                break;
                                }
                        }
-                       return as.apply( line.text );
+                       return ar.apply( line.text );
                } else {
                        return line.text;
                }
        }
-};
 
-function WikitextRenderer() { }
+       /* Methods */
 
-WikitextRenderer.prototype.render = function( doc ) {
-       return WikitextRenderer.renderers.document( doc );
+       this.render = function( doc ) {
+               return renderDocument( doc );
+       };
 };
 
-WikitextRenderer.renderers = {
-       'document': function( doc, rawFirstParagraph ) {
+/**
+ * Serializes a WikiDom into Wikitext.
+ */
+wiki.WikitextRenderer = function() {
+
+       /* Private Members */
+
+       var that = this;
+       var blockRenderers = {
+               'comment': renderComment,
+               'horizontal-rule': renderHorizontalRule,
+               'heading': renderHeading,
+               'paragraph': renderParagraph,
+               'list': renderList,
+               'table': renderTable
+       };
+
+       /* Private Methods */
+
+       function renderDocument( doc, rawFirstParagraph ) {
                var out = [];
                for ( var b = 0, bMax = doc.blocks.length; b < bMax; b++ ) {
                        var block = doc.blocks[b];
-                       if ( block.type in WikitextRenderer.renderers ) {
+                       if ( block.type in blockRenderers ) {
                                if ( block.type === 'paragraph' ) {
                                        out.push(
-                                               
WikitextRenderer.renderers.paragraph( block, rawFirstParagraph && b === 0 )
+                                               renderParagraph( block, 
rawFirstParagraph && b === 0 )
                                        );
                                        if ( b + 1 < bMax /* && doc.blocks[b + 
1].type === 'paragraph' */ ) {
                                                out.push( '' );
                                        }
                                } else {
-                                       out.push( 
WikitextRenderer.renderers[block.type]( block ) );
+                                       out.push( blockRenderers[block.type]( 
block ) );
                                }
                        }
                }
                return out.join( '\n' );
-       },
-       'comment': HtmlRenderer.renderers.comment,
-       'rule': function( rule ) {
+       }
+
+       function renderComment( comment ) {
+               return '<!--' + comment.text + '-->';
+       }
+
+       function renderHorizontalRule( rule ) {
                return '----';
-       },
-       'heading': function( heading ) {
-               var symbols = repeat( '=', heading.level );
-               return symbols + WikitextRenderer.renderers.line( heading.line 
) + symbols;
-       },
-       'paragraph': function( paragraph ) {
+       }
+
+       function renderHeading( heading ) {
+               var symbols = wiki.util.str.repeat( '=', heading.level );
+               return symbols + renderLine( heading.line ) + symbols;
+       }
+
+       function renderParagraph( paragraph ) {
                var out = [];
                for ( var l = 0, lMax = paragraph.lines.length; l < lMax; l++ ) 
{
-                       out.push( WikitextRenderer.renderers.line( 
paragraph.lines[l] ) );
+                       out.push( renderLine( paragraph.lines[l] ) );
                }
                return out.join( '\n' );
-       },
-       'list': function( list, path ) {
+       }
+
+       function renderList( list, path ) {
                if ( typeof path === 'undefined' ) {
                        path = '';
                }
@@ -255,17 +306,18 @@
                path += symbols[list.style];
                var out = [];
                for ( var i = 0, iMax = list.items.length; i < iMax; i++ ) {
-                       out.push( WikitextRenderer.renderers.item( 
list.items[i], path ) );
+                       out.push( renderItem( list.items[i], path ) );
                }
                return out.join( '\n' );
-       },
-       'table': function( table ) {
+       }
+
+       function renderTable( table ) {
                var out = [];
                var types = {
                        'heading': '!',
                        'data': '|'
                };
-               out.push( '{|' + Xml.attr( table.attributes ) );
+               out.push( '{|' + wiki.util.xml.attr( table.attributes ) );
                for ( var r = 0, rMax = table.rows.length; r < rMax; r++ ) {
                        var row = table.rows[r];
                        if ( r ) {
@@ -275,57 +327,110 @@
                                var type = types[row[c].type || 'data'];
                                out.push(
                                        type
-                                       + ( row[c].attributes ? Xml.attr( 
row[c].attributes ) + '|' : '' )
-                                       + WikitextRenderer.renderers.document( 
row[c].document, true )
+                                       + ( row[c].attributes ? 
wiki.util.xml.attr( row[c].attributes ) + '|' : '' )
+                                       + renderDocument( row[c].document, true 
)
                                );
                        }
                }
                out.push( '|}' );
                return out.join( '\n' );
-       },
-       'item': function( item, path ) {
+       }
+
+       function renderItem( item, path ) {
                if ( 'lists' in item && item.lists.length ) {
                        var out = [];
-                       out.push( path + ' ' + WikitextRenderer.renderers.line( 
item.line ) );
+                       out.push( path + ' ' + renderLine( item.line ) );
                        for ( var l = 0, lMax = item.lists.length; l < lMax; 
l++ ) {
-                               out.push( WikitextRenderer.renderers.list( 
item.lists[l], path ) );
+                               out.push( renderList( item.lists[l], path ) );
                        }
                        return out.join( '\n' );
                } else {
-                       return path + ' ' + WikitextRenderer.renderers.line( 
item.line );
+                       return path + ' ' + renderLine( item.line );
                }
-       },
-       'line': function( line ) {
+       }
+
+       function renderLine( line ) {
                if ( 'annotations' in line && line.annotations.length ) {
-                       var as = new AnnotationSerialization();
+                       var ar = new wiki.AnnotationRenderer();
                        for ( var a = 0, aMax = line.annotations.length; a < 
aMax; a++ ) {
                                var an = line.annotations[a];
                                switch ( an.type ) {
                                        case 'bold':
-                                               as.wrapWithText( an.range, 
'\'\'\'', '\'\'\'' );
+                                               ar.wrapWithText( an.range, 
'\'\'\'', '\'\'\'' );
                                                break;
                                        case 'italic':
-                                               as.wrapWithText( an.range, 
'\'\'', '\'\'' );
+                                               ar.wrapWithText( an.range, 
'\'\'', '\'\'' );
                                                break;
                                        case 'xlink':
-                                               as.wrapWithText( an.range, '[' 
+ an.data.url + ' ', ']' );
+                                               ar.wrapWithText( an.range, '[' 
+ an.data.url + ' ', ']' );
                                                break;
                                        case 'ilink':
-                                               as.wrapWithText( an.range, '[[' 
+ an.data.title + '|', ']]' );
+                                               ar.wrapWithText( an.range, '[[' 
+ an.data.title + '|', ']]' );
                                                break;
                                }
                        }
-                       return as.apply( line.text );
+                       return ar.apply( line.text );
                } else {
                        return line.text;
                }
        }
-};
 
-/* Parsers */
+       /* Methods */
 
-function WikitextParser() { }
+       this.render = function( doc ) {
+               return renderDocument( doc );
+       };
+};
 
-WikitextParser.prototype.parse = function( text ) {
-       //
+/**
+ * Utilities used by WikiDom renderers and parsers.
+ */
+wiki.util = {
+       'str': {
+               'repeat': function( pattern, count ) {
+                       if ( count < 1 ) return '';
+                       var result = '';
+                       while ( count > 0 ) {
+                               if ( count & 1 ) result += pattern;
+                               count >>= 1, pattern += pattern;
+                       };
+                       return result;
+               }
+       },
+       'xml': {
+               'esc': function( text ) {
+                       return text
+                               .replace( /&/g, '&amp;' )
+                               .replace( /</g, '&lt;' )
+                               .replace( />/g, '&gt;' )
+                               .replace( /"/g, '&quot;' )
+                               .replace( /'/g, '&#039;' );
+               },
+               'attr': function( attributes ) {
+                       var attr = '';
+                       if ( attributes ) {
+                               for ( var name in attributes ) {
+                                       attr += ' ' + name + '="' + 
attributes[name] + '"';
+                               }
+                       }
+                       return attr;
+               },
+               'open': function( tag, attributes ) {
+                       return '<' + tag + wiki.util.xml.attr( attributes ) + 
'>';
+               },
+               'close': function( tag ) {
+                       return '</' + tag + '>';
+               },
+               'tag': function( tag, attributes, value, escape ) {
+                       if ( value === false ) {
+                               return '<' + tag + wiki.util.xml.attr( 
attributes ) + ' />';
+                       } else {
+                               if ( escape ) {
+                                       value = wiki.util.xml.esc( value );
+                               }
+                               return '<' + tag + wiki.util.xml.attr( 
attributes ) + '>' + value
+                                       + '</' + tag + '>';
+                       }
+               }
+       }
 };


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to