r101972 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r101971‎ | r101972 | r101973 >
Date:10:02, 4 November 2011
Author:gwicke
Status:deferred
Tags:
Comment:
Add basic list serialization to HtmlSerializer

* Added 'definitionterm' and 'definitiondata' styles to support definition
lists, and special-case handling in the serializer to wrap both in dls.
Modified paths:
  • /trunk/extensions/VisualEditor/modules/es/serializers/es.HtmlSerializer.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/pegParser.pegjs.txt (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/modules/es/serializers/es.HtmlSerializer.js
@@ -91,8 +91,81 @@
9292 };
9393
9494 es.HtmlSerializer.prototype.list = function( node ) {
95 - // TODO: Convert list from flat to structured format and output it as HTML
96 - return '<!-- TODO: Support list and listItem nodes -->';
 95+ var out = [], // List of list nodes
 96+ bstack = [], // Bullet stack, previous element's listStyles
 97+ bnext = [], // Next element's listStyles
 98+ closeTags = []; // Stack of close tags for currently active lists
 99+
 100+ var commonPrefixLength = function (x, y) {
 101+ var minLength = Math.min(x.length, y.length);
 102+ for(var i = 0; i < minLength; i++) {
 103+ if (x[i] !== y[i]
 104+ // Both definitiondata and definitionterm are
 105+ // inside dls, so consider them equivalent here.
 106+ && [x[i], y[i]].sort()
 107+ !== ['definitiondata', 'definitionterm'] )
 108+ {
 109+ break;
 110+ }
 111+ }
 112+ return i;
 113+ }
 114+
 115+ var popTags = function ( n ) {
 116+ for (var i = 0; i < n; i++ ) {
 117+ out.push(closeTags.pop());
 118+ }
 119+ }
 120+
 121+ var openLists = function ( bs, bn, attribs ) {
 122+ var prefix = commonPrefixLength (bs, bn);
 123+ // pop close tags from stack
 124+ popTags(closeTags.length - prefix);
 125+ for(var i = prefix; i < bn.length; i++) {
 126+ var c = bn[i];
 127+ switch (c) {
 128+ case 'bullet':
 129+ out.push(es.Html.makeOpeningTag('ul', attribs));
 130+ closeTags.push(es.Html.makeClosingTag('ul'));
 131+ break;
 132+ case 'number':
 133+ out.push(es.Html.makeOpeningTag('ol', attribs));
 134+ closeTags.push(es.Html.makeClosingTag('ol'));
 135+ break;
 136+ case 'definitionterm':
 137+ case 'definitiondata':
 138+ out.push(es.Html.makeOpeningTag('dl', attribs));
 139+ closeTags.push(es.Html.makeClosingTag('dl'));
 140+ break;
 141+ default:
 142+ throw("Unknown node prefix " + c);
 143+ }
 144+ };
 145+ }
 146+
 147+ var childrenLength = node.children.length;
 148+ for (var i = 0; i < childrenLength; i++) {
 149+ var e = node.children[i];
 150+ bnext = e.attributes.styles;
 151+ delete e.attributes['styles'];
 152+ openLists( bstack, bnext, e.attributes );
 153+ var tag;
 154+ switch(bnext[bnext.length - 1]) {
 155+ case 'definitionterm':
 156+ tag = 'dt'; break;
 157+ case 'definitiondata':
 158+ tag = 'dd'; break;
 159+ default:
 160+ tag = 'li'; break;
 161+ }
 162+ out.push( es.Html.makeTag(tag, e.attributes,
 163+ this.content(e.content)
 164+ )
 165+ );
 166+ bstack = bnext;
 167+ };
 168+ popTags(closeTags.length);
 169+ return out.join("\n");
97170 };
98171
99172 es.HtmlSerializer.prototype.table = function( node ) {
Index: trunk/extensions/VisualEditor/modules/parser/pegParser.pegjs.txt
@@ -81,6 +81,25 @@
8282 return dumped_text;
8383
8484 }
 85+
 86+ // Convert list prefixes to a list of WikiDom list styles
 87+ var bulletsToTypes = function (bullets) {
 88+ var bTypes = [];
 89+ var blen = bullets.length;
 90+ for (var i = 0; i < bullets.length; i++) {
 91+ switch (bullets[i]) {
 92+ case '*':
 93+ bTypes.push('bullet'); break;
 94+ case '#':
 95+ bTypes.push('number'); break;
 96+ case ';':
 97+ bTypes.push('definitionterm'); break;
 98+ case ':':
 99+ bTypes.push('definitiondata'); break;
 100+ }
 101+ }
 102+ return bTypes;
 103+ }
85104 }
86105
87106 start
@@ -93,7 +112,7 @@
94113 else
95114 es.push(ei);
96115 });
97 - dp(print_r(es));
 116+ dp(es);
98117 return {
99118 type: 'page',
100119 content: es
@@ -547,86 +566,32 @@
548567
549568 lists = es:(dtdd / li)+
550569 {
551 - var out = [], // List of list nodes
552 - bstack = "", // Bullet stack, previous element's listStyle
553 - bnext = "", // Next element's listStyle
554 - nodes = []; // Stack of currently active, nested list nodes
555 -
556 - var commonPrefixLength = function (x, y) {
557 - var minLength = Math.min(x.length, y.length);
558 - for(var i = 0; i < minLength; i++) {
559 - if (x[i] != y[i])
560 - break;
561 - }
562 - return i;
563 - }
564 -
565 - var pushN = function ( n ) {
566 - if (nodes.length > 0) {
567 - nodes[nodes.length - 1].content.push(n);
 570+ // flatten es
 571+ var esLen = es.length;
 572+ var flatEs = [];
 573+ for (var i = 0; i < esLen; i++) {
 574+ if (es[i].constructor === Array) {
 575+ flatEs.concat(es[i]);
568576 } else {
569 - out.push(n);
570 - nodes.push(n);
 577+ flatEs.push(es[i]);
571578 }
572 -
573579 }
574 -
575 - var openLists = function ( bs, bn ) {
576 - var prefix = commonPrefixLength (bs, bn);
577 - nodes = nodes.slice(0, prefix);
578 - $.each(bn.slice(prefix, bn.length), function (i, c) {
579 - switch (c) {
580 - case '*':
581 - pushN({type: 'ul', content: []});
582 - break;
583 - case '#':
584 - pushN({type: 'ol', content: []});
585 - break;
586 - case ';':
587 - case ':':
588 - pushN({type: 'dl', content: []});
589 - break;
590 - default:
591 - throw("Unknown node prefix " + c);
592 - }
593 - });
 580+ return {
 581+ type: 'list',
 582+ children: es
594583 }
595 -
596 -
597 - $.each(es, function(i, e) {
598 - if (e.type == 'dtdd') {
599 - bnext = e.content[0].listStyle;
600 - lnode = openLists( bstack, bnext );
601 -
602 - nodes[nodes.length - 1].content =
603 - nodes[nodes.length - 1].content.concat(e.content);
604 - } else {
605 - bnext = e.listStyle;
606 - openLists( bstack, bnext, nodes );
607 - nodes[nodes.length - 1].content.push(e);
608 - }
609 - bstack = bnext;
610 - });
611 - //dp("out: " + print_r(out, 5));
612 - return out;
613584 }
614585
615586 li = bullets:list_char+
616587 c:(inlineline / anyline)
617588 newline
618589 {
619 - var type;
620 - switch (bullets[bullets.length - 1]) {
621 - case '#':
622 - case '*':
623 - type = 'li'; break;
624 - case ';': type = 'dt'; break;
625 - case ':': type = 'dd'; break;
626 - }
627590 return {
628 - type: type,
629 - listStyle: bullets,
630 - content: c
 591+ type: 'listItem',
 592+ attributes: {
 593+ styles: bulletsToTypes(bullets)
 594+ },
 595+ content: c[0]
631596 };
632597 }
633598
@@ -640,21 +605,18 @@
641606 if (bullets[bullets.length - 1] != ';') {
642607 return null;
643608 } else {
644 - return {
645 - type: 'dtdd',
646 - content: [
647 - {
648 - type: 'dt',
649 - listStyle: bullets,
650 - content: c
651 - }, {
652 - type: 'dd',
653 - listStyle: bullets.slice(0, bullets.length - 1) + ':',
654 - content: d
655 - }
656 -
657 - ]
658 - }
 609+ return [
 610+ {
 611+ type: 'listItem',
 612+ attributes: {styles: bulletsToTypes(bullets)},
 613+ content: c[0]
 614+ }, {
 615+ type: 'listItem',
 616+ attributes: {styles: bulletsToTypes(
 617+ bullets.slice(0, bullets.length - 1) + ':')},
 618+ content: d[0]
 619+ }
 620+ ]
659621 }
660622 }
661623

Status & tagging log