r108887 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r108886‎ | r108887 | r108888 >
Date:00:58, 14 January 2012
Author:gwicke
Status:deferred
Tags:
Comment:
First template expansion tests start working, and a bug fix in
DOMPostProcessor paragraph wrapper. 187 parser tests now passing.
Modified paths:
  • /trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.DOMPostProcessor.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt (modified) (history)
  • /trunk/extensions/VisualEditor/tests/parser/parserTests.js (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/parser/parserTests.js
@@ -184,7 +184,8 @@
185185
186186 this.currentItem = undefined;
187187
188 - return this;
 188+ // Create a new parser environment
 189+ this.env = new MWParserEnvironment({});
189190 }
190191
191192
@@ -269,29 +270,17 @@
270271 return undefined;
271272 };
272273
273 -
274 -ParserTests.prototype.normalizeTitle = function(name) {
275 - if (typeof name !== 'string') {
276 - throw new Error('nooooooooo not a string');
277 - }
278 - name = name.replace(/[\s_]+/g, '_');
279 - name = name.substr(0, 1).toUpperCase() + name.substr(1);
280 - if (name === '') {
281 - throw new Error('Invalid/empty title');
282 - }
283 - return name;
284 -};
285 -
286274 ParserTests.prototype.fetchArticle = function(name) {
287275 // very simple for now..
288 - var norm = normalizeTitle(name);
 276+ var norm = this.env.normalizeTitle(name);
289277 if (norm in this.articles) {
290278 return this.articles[norm];
291279 }
292280 };
293281
294282 ParserTests.prototype.processArticle = function(item) {
295 - var norm = this.normalizeTitle(item.title);
 283+ var norm = this.env.normalizeTitle(item.title);
 284+ //console.log( 'processArticle ' + norm );
296285 this.articles[norm] = item.text;
297286 };
298287
@@ -552,8 +541,8 @@
553542 // }
554543 //});
555544
556 - var env = new MWParserEnvironment({});
557 - var parserPipeline = new ParserPipeline( env );
 545+ this.env.pageCache = this.articles;
 546+ var parserPipeline = new ParserPipeline( this.env );
558547
559548 var comments = [],
560549 pt = this;
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
@@ -314,7 +314,7 @@
315315 this._construct();
316316 this._reset( args, env );
317317 // FIXME: pass actual title?
318 - this.loopCheck = new LoopCheck ( null );
 318+ this.loopCheck = new LoopCheck( null );
319319 }
320320
321321 // Inherit from TokenTransformManager, and thus also from EventEmitter.
@@ -337,7 +337,10 @@
338338 var child = pipe.last;
339339 // We assume that the title was already checked against this.loopCheck
340340 // before!
341 - child.loopCheck = new LoopCheck ( title, this.loopCheck );
 341+ child.loopCheck = new LoopCheck (
 342+ this.env.normalizeTitle( this.env.tokensToString ( title ) ),
 343+ this.loopCheck
 344+ );
342345 // Same for depth!
343346 child.depth = this.depth + 1;
344347 return pipe;
@@ -926,6 +929,7 @@
927930 LoopCheck.prototype.check = function ( title ) {
928931 var elem = this;
929932 do {
 933+ //console.log( 'loop check: ' + title + ' vs ' + elem.title );
930934 if ( elem.title === title ) {
931935 // Loop detected
932936 return true;
Index: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt
@@ -455,7 +455,7 @@
456456
457457 para
458458 = s1:sol s2:sol c:inlineline {
459 - return s1.concat(s2, [{type: 'TAG', name: 'p'}], c);
 459+ return s1.concat(s2, /* [{type: 'TAG', name: 'p'}],*/ c);
460460 }
461461
462462 br = space* &newline { return {type: 'SELFCLOSINGTAG', name: 'br'} }
@@ -488,7 +488,7 @@
489489 c = flatten(c);
490490 for (var i = 0, l = c.length; i < l; i++) {
491491 var ci = c[i];
492 - if (typeof ci == 'string') {
 492+ if (typeof ci === 'string') {
493493 if(ci !== '') {
494494 text.push(ci);
495495 }
@@ -686,13 +686,14 @@
687687 }
688688
689689 template
690 - = "{{" target:template_target
 690+ = "{{" target:template_param_text
691691 params:(newline? "|" newline? p:template_param { return p })*
692692 "}}" {
 693+ target = flatten( target );
693694 var obj = {
694695 type: 'SELFCLOSINGTAG',
695696 name: 'template',
696 - attribs: [['data-target', target]],
 697+ attribs: [['data-target', JSON.stringify(target)]],
697698 orderedArgs: params,
698699 args: {},
699700 target: target
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.DOMPostProcessor.js
@@ -46,7 +46,7 @@
4747 var body = document.body,
4848 newP = document.createElement('p'),
4949 cnodes = body.childNodes,
50 - haveInlines = false,
 50+ inParagraph = false,
5151 deleted = 0;
5252
5353 function isElementContentWhitespace ( e ) {
@@ -57,22 +57,26 @@
5858 var child = cnodes[i - deleted],
5959 ctype = child.nodeType;
6060 //console.log(child + ctype);
61 - if ((ctype === 3 && (haveInlines || !isElementContentWhitespace(child))) ||
62 - (ctype !== Node.TEXT_NODE &&
63 - ctype !== Node.COMMENT_NODE &&
64 - !isBlock(child.nodeName))) {
65 - // text node
 61+ if ((ctype === 3 && (inParagraph || !isElementContentWhitespace( child ))) ||
 62+ (ctype === Node.COMMENT_NODE && inParagraph ) ||
 63+ (ctype !== Node.TEXT_NODE &&
 64+ ctype !== Node.COMMENT_NODE &&
 65+ !isBlock(child.nodeName))
 66+ )
 67+ {
 68+ // wrap in paragraph
6669 newP.appendChild(child);
67 - haveInlines = true;
 70+ inParagraph = true;
6871 deleted++;
69 - } else if (haveInlines) {
 72+ } else if (inParagraph) {
7073 body.insertBefore(newP, child);
 74+ deleted--;
7175 newP = document.createElement('p');
72 - haveInlines = false;
73 - }
 76+ inParagraph = false;
 77+ }
7478 }
7579
76 - if (haveInlines) {
 80+ if (inParagraph) {
7781 body.appendChild(newP);
7882 }
7983 };
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
@@ -156,6 +156,7 @@
157157 tokenExpander.listenForTokensFrom ( tokenPreProcessor );
158158 // XXX: hack.
159159 tokenExpander.inputType = inputType;
 160+ tokenPreProcessor.inputType = inputType;
160161
161162 return new CachedTokenPipeline(
162163 this.cachePipeline.bind( this, 'text/wiki', 'input' ),
Index: trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
@@ -47,7 +47,7 @@
4848 * processes the template.
4949 */
5050 TemplateHandler.prototype.onTemplate = function ( token, cb ) {
51 - //console.log('onTemplate!');
 51+ //console.log('onTemplate! ' + JSON.stringify( token, null, 2 ) );
5252
5353 this.parentCB = cb;
5454
@@ -71,7 +71,8 @@
7272 res,
7373 kv;
7474
75 - var attributes = [[{ type: 'TEXT', value: '' } , token.target ]].concat( token.orderedArgs );
 75+ var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]]
 76+ .concat( token.orderedArgs );
7677
7778 //console.log( 'before AttributeTransformManager: ' + JSON.stringify( attributes, null, 2 ) );
7879 new AttributeTransformManager(
@@ -109,7 +110,20 @@
110111 //console.log('TemplateHandler.expandTemplate: ' +
111112 // JSON.stringify( templateTokenTransformData, null, 2 ) );
112113 // First, check the target for loops
113 - this.manager.loopCheck.check( templateTokenTransformData.target );
 114+ var target = this.manager.env.normalizeTitle(
 115+ this.manager.env.tokensToString( templateTokenTransformData.target )
 116+ );
 117+ if( this.manager.loopCheck.check( target ) ) {
 118+ // Loop detected, abort!
 119+ return {
 120+ tokens: [
 121+ {
 122+ type: 'TEXT',
 123+ value: 'Template expansion loop detected!'
 124+ }
 125+ ]
 126+ };
 127+ }
114128
115129 // Create a new nested transformation pipeline for the input type
116130 // (includes the tokenizer and synchronous stage-1 transforms for
@@ -117,8 +131,9 @@
118132 // Returned pipe (for now):
119133 // { first: tokenizer, last: AsyncTokenTransformManager }
120134 this.inputPipeline = this.manager.newChildPipeline(
121 - this.manager.inputType,
122 - templateTokenTransformData.expandedArgs
 135+ this.manager.inputType || 'text/wiki',
 136+ templateTokenTransformData.expandedArgs,
 137+ templateTokenTransformData.target
123138 );
124139
125140 // Hook up the inputPipeline output events to call back our parentCB.
@@ -128,7 +143,7 @@
129144
130145 // Resolve a possibly relative link
131146 var templateName = this.manager.env.resolveTitle(
132 - this.manager.env.tokensToString( templateTokenTransformData.target ),
 147+ target,
133148 'Template'
134149 );
135150 this._fetchTemplateAndTitle( templateName, this._processTemplateAndTitle.bind( this ) );
@@ -176,7 +191,8 @@
177192 TemplateHandler.prototype._onEnd = function( ) {
178193 // Encapsulate the template in a single token, which contains all the
179194 // information needed for the editor.
180 - var res =
 195+ var res = this.resultTokens;
 196+ /*
181197 [{
182198 type: 'TAG',
183199 name: 'div',
@@ -188,6 +204,7 @@
189205 this.resultTokens,
190206 [{ type: 'ENDTAG', name: 'div' }]
191207 );
 208+ */
192209 //console.log( 'TemplateHandler._onEnd: ' + JSON.stringify( res, null, 2 ) );
193210
194211 if ( this.isAsync ) {
@@ -219,7 +236,7 @@
220237 // @fixme normalize name?
221238 if (title in this.manager.env.pageCache) {
222239 // @fixme should this be forced to run on next event?
223 - callback( this.env.manager.pageCache[title], title );
 240+ callback( this.manager.env.pageCache[title], title );
224241 } else {
225242 // whee fun hack!
226243 //console.log(title);
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js
@@ -58,6 +58,19 @@
5959 }
6060 };
6161
 62+MWParserEnvironment.prototype.normalizeTitle = function( name ) {
 63+ if (typeof name !== 'string') {
 64+ throw new Error('nooooooooo not a string');
 65+ }
 66+ name = name.replace(/[\s_]+/g, '_');
 67+ function upperFirst( s ) { return s.substr(0, 1).toUpperCase() + s.substr(1); }
 68+ name = name.split(':').map( upperFirst ).join(':');
 69+ //if (name === '') {
 70+ // throw new Error('Invalid/empty title');
 71+ //}
 72+ return name;
 73+};
 74+
6275 /**
6376 * @fixme do this for real eh
6477 */
@@ -65,28 +78,30 @@
6679 // hack!
6780 if (name.indexOf(':') == -1 && typeof namespace ) {
6881 // hack hack hack
69 - name = namespace + ':' + name;
 82+ name = namespace + ':' + this.normalizeTitle( name );
7083 }
7184 return name;
7285 };
7386
7487 MWParserEnvironment.prototype.tokensToString = function ( tokens ) {
7588 var out = [];
 89+ //console.log( 'MWParserEnvironment.tokensToString, tokens: ' + JSON.stringify( tokens ) );
7690 // XXX: quick hack, track down non-array sources later!
7791 if ( ! $.isArray( tokens ) ) {
7892 tokens = [ tokens ];
7993 }
8094 for ( var i = 0, l = tokens.length; i < l; i++ ) {
81 - console.log( 'MWParserEnvironment.tokensToString: ' + token );
8295 var token = tokens[i];
 96+ //console.log( 'MWParserEnvironment.tokensToString, token: ' + JSON.stringify( token ) );
8397 if ( token.type === 'TEXT' ) {
8498 out.push( token.value );
8599 } else {
86100 var tstring = JSON.stringify( token );
87 - console.log ( 'MWParserEnvironment::tokensToString: ' + tstring );
88 - out.push( tstring );
 101+ //console.log ( 'MWParserEnvironment.tokensToString, non-text token: ' + tstring );
 102+ //out.push( tstring );
89103 }
90104 }
 105+ //console.log( 'MWParserEnvironment.tokensToString result: ' + out.join('') );
91106 return out.join('');
92107 };
93108

Status & tagging log