Index: trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js |
— | — | @@ -1,39 +0,0 @@ |
2 | | -/** |
3 | | - * Simple noinclude / onlyinclude implementation. Strips all tokens in |
4 | | - * noinclude sections. |
5 | | - * |
6 | | - * @author Gabriel Wicke <gwicke@wikimedia.org> |
7 | | - */ |
8 | | - |
9 | | -var TokenCollector = require( './ext.util.TokenCollector.js' ).TokenCollector; |
10 | | - |
11 | | -function NoInclude( manager ) { |
12 | | - new TokenCollector( |
13 | | - manager, |
14 | | - function ( tokens ) { |
15 | | - manager.env.dp( 'noinclude stripping', tokens ); |
16 | | - return {}; |
17 | | - }, // just strip it all.. |
18 | | - true, // match the end-of-input if </noinclude> is missing |
19 | | - 0.01, // very early in stage 1, to avoid any further processing. |
20 | | - 'tag', |
21 | | - 'noinclude' |
22 | | - ); |
23 | | -} |
24 | | - |
25 | | -function OnlyInclude( manager ) { |
26 | | - new TokenCollector( |
27 | | - manager, |
28 | | - function ( ) { return {} }, // just strip it all.. |
29 | | - true, // match the end-of-input if </noinclude> is missing |
30 | | - 0.01, // very early in stage 1, to avoid any further processing. |
31 | | - 'tag', |
32 | | - 'onlyinclude' |
33 | | - ); |
34 | | -} |
35 | | - |
36 | | - |
37 | | -if (typeof module == "object") { |
38 | | - module.exports.NoInclude = NoInclude; |
39 | | - module.exports.OnlyInclude = OnlyInclude; |
40 | | -} |
Index: trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js |
— | — | @@ -0,0 +1,59 @@ |
| 2 | +/** |
| 3 | + * Simple noinclude / onlyinclude implementation. Strips all tokens in |
| 4 | + * noinclude sections. |
| 5 | + * |
| 6 | + * @author Gabriel Wicke <gwicke@wikimedia.org> |
| 7 | + */ |
| 8 | + |
| 9 | +var TokenCollector = require( './ext.util.TokenCollector.js' ).TokenCollector; |
| 10 | + |
| 11 | +function NoInclude( manager, isInclude ) { |
| 12 | + new TokenCollector( |
| 13 | + manager, |
| 14 | + function ( tokens ) { |
| 15 | + if ( isInclude ) { |
| 16 | + manager.env.dp( 'noinclude stripping', tokens ); |
| 17 | + return {}; |
| 18 | + } else { |
| 19 | + tokens.shift(); |
| 20 | + if ( tokens.length && |
| 21 | + tokens[tokens.length - 1].type !== 'END' ) { |
| 22 | + tokens.pop(); |
| 23 | + } |
| 24 | + return { tokens: tokens }; |
| 25 | + } |
| 26 | + }, // just strip it all.. |
| 27 | + true, // match the end-of-input if </noinclude> is missing |
| 28 | + 0.01, // very early in stage 1, to avoid any further processing. |
| 29 | + 'tag', |
| 30 | + 'noinclude' |
| 31 | + ); |
| 32 | +} |
| 33 | + |
| 34 | +function IncludeOnly( manager, isInclude ) { |
| 35 | + new TokenCollector( |
| 36 | + manager, |
| 37 | + function ( tokens ) { |
| 38 | + if ( isInclude ) { |
| 39 | + tokens.shift(); |
| 40 | + if ( tokens.length && |
| 41 | + tokens[tokens.length - 1].type !== 'END' ) { |
| 42 | + tokens.pop(); |
| 43 | + } |
| 44 | + return { tokens: tokens }; |
| 45 | + } else { |
| 46 | + return {}; |
| 47 | + } |
| 48 | + }, |
| 49 | + true, // match the end-of-input if </noinclude> is missing |
| 50 | + 0.01, // very early in stage 1, to avoid any further processing. |
| 51 | + 'tag', |
| 52 | + 'includeonly' |
| 53 | + ); |
| 54 | +} |
| 55 | + |
| 56 | + |
| 57 | +if (typeof module == "object") { |
| 58 | + module.exports.NoInclude = NoInclude; |
| 59 | + module.exports.IncludeOnly = IncludeOnly; |
| 60 | +} |
Property changes on: trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 61 | + native |
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js |
— | — | @@ -664,7 +664,7 @@ |
665 | 665 | } |
666 | 666 | } |
667 | 667 | this.env.dp( 'SyncTokenTransformManager.onChunk: emitting ' + |
668 | | - JSON.stringify( localAccum ) ); |
| 668 | + JSON.stringify( localAccum, null, 2 ) ); |
669 | 669 | this.emit( 'chunk', localAccum ); |
670 | 670 | }; |
671 | 671 | |
— | — | @@ -698,7 +698,7 @@ |
699 | 699 | function AttributeTransformManager ( manager, callback ) { |
700 | 700 | this.manager = manager; |
701 | 701 | this.callback = callback; |
702 | | - this.outstanding = 0; |
| 702 | + this.outstanding = 1; |
703 | 703 | this.kvs = []; |
704 | 704 | //this.pipe = manager.getAttributePipeline( manager.args ); |
705 | 705 | } |
— | — | @@ -726,7 +726,7 @@ |
727 | 727 | pipe.addListener( 'end', |
728 | 728 | this.onEnd.bind( this, this._returnAttributeKey.bind( this, i ) ) |
729 | 729 | ); |
730 | | - pipe.process( attributes[i][0] ); |
| 730 | + pipe.process( attributes[i][0].concat([{type:'END'}]) ); |
731 | 731 | |
732 | 732 | // transform the value |
733 | 733 | pipe = this.manager.getAttributePipeline( this.manager.args ); |
— | — | @@ -737,8 +737,12 @@ |
738 | 738 | this.onEnd.bind( this, this._returnAttributeValue.bind( this, i ) ) |
739 | 739 | ); |
740 | 740 | //console.log('starting attribute transform of ' + JSON.stringify( attributes[i][1] ) ); |
741 | | - pipe.process( attributes[i][1] ); |
| 741 | + pipe.process( attributes[i][1].concat([{type:'END'}]) ); |
742 | 742 | } |
| 743 | + this.outstanding--; |
| 744 | + if ( this.outstanding == 0 ) { |
| 745 | + this._returnAttributes(); |
| 746 | + } |
743 | 747 | }; |
744 | 748 | |
745 | 749 | AttributeTransformManager.prototype._returnAttributes = function ( ) { |
— | — | @@ -758,6 +762,9 @@ |
759 | 763 | * Collect chunks returned from the pipeline |
760 | 764 | */ |
761 | 765 | AttributeTransformManager.prototype.onChunk = function ( cb, chunk ) { |
| 766 | + if ( chunk.length && chunk[chunk.length - 1].type === 'END' ) { |
| 767 | + chunk.pop(); |
| 768 | + } |
762 | 769 | cb( chunk, true ); |
763 | 770 | }; |
764 | 771 | |
— | — | @@ -773,7 +780,8 @@ |
774 | 781 | * Callback for async argument value expansions |
775 | 782 | */ |
776 | 783 | AttributeTransformManager.prototype._returnAttributeValue = function ( ref, tokens, notYetDone ) { |
777 | | - //console.log( 'check _returnAttributeValue: ' + JSON.stringify( tokens ) ); |
| 784 | + //console.log( 'check _returnAttributeValue: ' + JSON.stringify( tokens ) + |
| 785 | + // ' notYetDone:' + notYetDone ); |
778 | 786 | this.kvs[ref].value = this.kvs[ref].value.concat( tokens ); |
779 | 787 | if ( ! notYetDone ) { |
780 | 788 | this.outstanding--; |
— | — | @@ -788,6 +796,8 @@ |
789 | 797 | * Callback for async argument key expansions |
790 | 798 | */ |
791 | 799 | AttributeTransformManager.prototype._returnAttributeKey = function ( ref, tokens, notYetDone ) { |
| 800 | + //console.log( 'check _returnAttributeKey: ' + JSON.stringify( tokens ) + |
| 801 | + // ' notYetDone:' + notYetDone ); |
792 | 802 | this.kvs[ref].key = this.kvs[ref].key.concat( tokens ); |
793 | 803 | if ( ! notYetDone ) { |
794 | 804 | this.outstanding--; |
Index: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt |
— | — | @@ -480,7 +480,11 @@ |
481 | 481 | / & { return syntaxFlags['extlink']; } "]" { return true; } |
482 | 482 | / & { return syntaxFlags['linkdesc']; } link_end { return true; } |
483 | 483 | / & { return syntaxFlags['h']; } '='+ space* newline { return true; } |
484 | | - / & { return syntaxFlags['template']; } ('|' / '}}') { return true; } |
| 484 | + / & { return syntaxFlags['template']; } ('|' / '}}' ) { return true; } |
| 485 | + / & { return syntaxFlags['equal']; } '=' { |
| 486 | + //console.log( 'equal stop!' ); |
| 487 | + return true; |
| 488 | + } |
485 | 489 | |
486 | 490 | inline |
487 | 491 | = c:(urltext / (! inline_breaks (inline_element / . )))+ { |
— | — | @@ -539,6 +543,7 @@ |
540 | 544 | = //& { dp('inline_element enter' + input.substr(pos, 10)); return true; } |
541 | 545 | & '<' ( comment / xmlish_tag ) |
542 | 546 | / & '{' ( & '{{{{{' template / tplarg / template ) |
| 547 | + /// & '{' ( tplarg / template ) |
543 | 548 | // Eat three opening brackets as text. |
544 | 549 | / '[[[' { return { type: 'TEXT', value: '[[[' } } |
545 | 550 | / & '[' ( wikilink / extlink ) |
— | — | @@ -711,25 +716,26 @@ |
712 | 717 | name: 'template', |
713 | 718 | attribs: [['data-target', JSON.stringify(target)]], |
714 | 719 | orderedArgs: params, |
715 | | - args: {}, |
| 720 | + //args: {}, |
716 | 721 | target: target |
717 | 722 | }; |
718 | | - if (params && params.length) { |
719 | | - var position = 1; |
720 | | - for ( var i = 0, l = params.length; i < l; i++ ) { |
721 | | - var param = params[i]; |
722 | | - if ( param[0] === null ) { |
723 | | - obj.args[position] = param[1]; |
724 | | - position++; |
725 | | - } else { |
726 | | - // Last value wins for duplicates. |
727 | | - obj.args[param[0]] = param[1]; |
728 | | - } |
729 | | - } |
730 | | - // HACK: temporarily also push the args into an attribute |
731 | | - // (just for debugging) |
732 | | - obj.attribs.push(['data-json-args', JSON.stringify(obj.args)]); |
733 | | - } |
| 723 | + // XXX: this is kind of broken, as arg keys need to be expanded |
| 724 | + //if (params && params.length) { |
| 725 | + // var position = 1; |
| 726 | + // for ( var i = 0, l = params.length; i < l; i++ ) { |
| 727 | + // var param = params[i]; |
| 728 | + // if ( param[0] === null ) { |
| 729 | + // obj.args[position] = param[1]; |
| 730 | + // position++; |
| 731 | + // } else { |
| 732 | + // // Last value wins for duplicates. |
| 733 | + // obj.args[param[0]] = param[1]; |
| 734 | + // } |
| 735 | + // } |
| 736 | + // // HACK: temporarily also push the args into an attribute |
| 737 | + // // (just for debugging) |
| 738 | + // obj.attribs.push(['data-json-args', JSON.stringify(obj.args)]); |
| 739 | + //} |
734 | 740 | // Should actually use a self-closing tag here, but the Node HTML5 |
735 | 741 | // parser only recognizes known self-closing tags for now, so use an |
736 | 742 | // explicit end tag for now. |
— | — | @@ -738,18 +744,14 @@ |
739 | 745 | } |
740 | 746 | |
741 | 747 | // XXX: support template and args in target! |
742 | | -template_target |
743 | | - = h:( !"}}" x:([^|\n]) { return x } )* { return { type: 'TEXT', value: h.join('') } } |
| 748 | +//template_target |
| 749 | +// = h:( !"}}" x:([^|\n]) { return x } )* { return { type: 'TEXT', value: h.join('') } } |
744 | 750 | |
745 | | -template_param |
746 | | - = name:template_param_name space* "=" space* c:template_param_text { |
747 | | - return [[{ type: 'TEXT', value: name }], flatten( c )]; |
748 | | - } / c:template_param_text { |
749 | | - return [[], flatten( c ) ]; |
750 | | - } |
751 | | - |
752 | 751 | tplarg |
753 | | - = "{{{" name:template_param_text params:("|" p:template_param { return p })* "}}}" { |
| 752 | + = "{{{" |
| 753 | + name:template_param_text |
| 754 | + params:( newline? "|" newline? p:template_param { return p })* |
| 755 | + "}}}" { |
754 | 756 | name = flatten( name ); |
755 | 757 | var obj = { |
756 | 758 | type: 'SELFCLOSINGTAG', |
— | — | @@ -764,21 +766,39 @@ |
765 | 767 | obj.attribs.push(['data-json-args', JSON.stringify(params)]); |
766 | 768 | obj.defaultvalue = params[0][1]; |
767 | 769 | } |
768 | | - //console.log( 'tokenizer templatearg ' + JSON.stringify( obj )); |
| 770 | + console.log( 'tokenizer tplarg ' + JSON.stringify( obj )); |
769 | 771 | return obj; |
770 | 772 | } |
771 | 773 | |
| 774 | +template_param |
| 775 | + = name:template_param_name space* "=" space* c:template_param_text { |
| 776 | + //console.log( 'named template_param matched' + pp([name, flatten( c )]) ); |
| 777 | + return [name, flatten( c )]; |
| 778 | + } / c:template_param_text { |
| 779 | + return [[], flatten( c ) ]; |
| 780 | + } |
| 781 | + |
| 782 | + |
772 | 783 | // FIXME: handle template args and templates in key! (or even parser functions?) |
773 | 784 | template_param_name |
774 | | - = h:( !"}}" x:([^=|\n]) { return x } )* { return h.join(''); } |
| 785 | + = & { return setFlag( 'equal' ) } |
| 786 | + tpt:template_param_text |
| 787 | + & { clearFlag( 'equal' ); return true; } |
| 788 | + { |
| 789 | + //console.log( 'template param name matched: ' + pp( tpt ) ); |
| 790 | + return tpt; |
| 791 | + } |
775 | 792 | |
| 793 | + / & { return clearFlag( 'equal' ) } |
| 794 | + //= h:( !"}}" x:([^=|\n]) { return x } )* { return h.join(''); } |
| 795 | + |
776 | 796 | template_param_text |
777 | 797 | = & { return setFlag('template') } |
778 | | - il:inline+ { |
| 798 | + il:inline { |
779 | 799 | clearFlag('template'); |
780 | 800 | return il; |
781 | 801 | } |
782 | | - / & { clearFlag('template'); return false; } |
| 802 | + / & { return clearFlag('template'); } |
783 | 803 | |
784 | 804 | // TODO: handle link prefixes as in al[[Razi]] |
785 | 805 | wikilink |
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js |
— | — | @@ -16,9 +16,9 @@ |
17 | 17 | PegTokenizer = require('./mediawiki.tokenizer.peg.js').PegTokenizer, |
18 | 18 | TokenTransformManager = require('./mediawiki.TokenTransformManager.js'), |
19 | 19 | |
20 | | - NoOnlyInclude = require('./ext.core.NoOnlyInclude.js'), |
21 | | - OnlyInclude = NoOnlyInclude.OnlyInclude, |
22 | | - NoInclude = NoOnlyInclude.NoInclude, |
| 20 | + NoIncludeOnly = require('./ext.core.NoIncludeOnly.js'), |
| 21 | + IncludeOnly = NoIncludeOnly.IncludeOnly, |
| 22 | + NoInclude = NoIncludeOnly.NoInclude, |
23 | 23 | QuoteTransformer = require('./ext.core.QuoteTransformer.js').QuoteTransformer, |
24 | 24 | PostExpandParagraphHandler = require('./ext.core.PostExpandParagraphHandler.js') |
25 | 25 | .PostExpandParagraphHandler, |
— | — | @@ -65,7 +65,7 @@ |
66 | 66 | }; |
67 | 67 | |
68 | 68 | // Create an input pipeline for the given input type. |
69 | | - this.inputPipeline = this.makeInputPipeline ( inputType ); |
| 69 | + this.inputPipeline = this.makeInputPipeline ( inputType, {}, true ); |
70 | 70 | this.inputPipeline.atTopLevel = true; |
71 | 71 | |
72 | 72 | |
— | — | @@ -137,7 +137,7 @@ |
138 | 138 | * accepts the wiki text this way. The last stage of the input pipeline is |
139 | 139 | * always an AsyncTokenTransformManager, which emits its output in events. |
140 | 140 | */ |
141 | | -ParserPipeline.prototype.makeInputPipeline = function ( inputType, args ) { |
| 141 | +ParserPipeline.prototype.makeInputPipeline = function ( inputType, args, isNoInclude ) { |
142 | 142 | switch ( inputType ) { |
143 | 143 | case 'text/wiki': |
144 | 144 | //console.log( 'makeInputPipeline ' + JSON.stringify( args ) ); |
— | — | @@ -158,8 +158,9 @@ |
159 | 159 | var tokenPreProcessor = new TokenTransformManager.SyncTokenTransformManager ( this.env ); |
160 | 160 | tokenPreProcessor.listenForTokensFrom ( wikiTokenizer ); |
161 | 161 | |
| 162 | + new IncludeOnly( tokenPreProcessor, ! isNoInclude ); |
162 | 163 | // Add noinclude transform for now |
163 | | - new NoInclude( tokenPreProcessor ); |
| 164 | + new NoInclude( tokenPreProcessor, ! isNoInclude ); |
164 | 165 | |
165 | 166 | var tokenExpander = new TokenTransformManager.AsyncTokenTransformManager ( |
166 | 167 | { |
Index: trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js |
— | — | @@ -75,8 +75,8 @@ |
76 | 76 | var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]] |
77 | 77 | .concat( this._nameArgs( token.orderedArgs ) ); |
78 | 78 | |
79 | | - //console.log( 'before AttributeTransformManager: ' + |
80 | | - // JSON.stringify( attributes, null, 2 ) ); |
| 79 | + this.manager.env.dp( 'before AttributeTransformManager: ' + |
| 80 | + JSON.stringify( attributes, null, 2 ) ); |
81 | 81 | new AttributeTransformManager( |
82 | 82 | this.manager, |
83 | 83 | this._returnAttributes.bind( this, tplExpandData ) |
— | — | @@ -85,7 +85,10 @@ |
86 | 86 | // Unblock finish |
87 | 87 | if ( ! tplExpandData.attribsAsync ) { |
88 | 88 | // Attributes were transformed synchronously |
89 | | - this.manager.env.dp( 'sync attribs for ' + JSON.stringify( token )); |
| 89 | + this.manager.env.dp ( |
| 90 | + 'sync attribs for ' + JSON.stringify( tplExpandData.target ), |
| 91 | + tplExpandData.expandedArgs |
| 92 | + ); |
90 | 93 | // All attributes are fully expanded synchronously (no IO was needed) |
91 | 94 | return this._expandTemplate ( tplExpandData ); |
92 | 95 | } else { |
— | — | @@ -110,7 +113,7 @@ |
111 | 114 | out.push( orderedArgs[i] ); |
112 | 115 | } |
113 | 116 | } |
114 | | - //console.log( '_nameArgs: ' + JSON.stringify( out ) ); |
| 117 | + this.manager.env.dp( '_nameArgs: ' + JSON.stringify( out ) ); |
115 | 118 | return out; |
116 | 119 | }; |
117 | 120 | |
— | — | @@ -190,6 +193,7 @@ |
191 | 194 | this.manager.env.KVtoHash( tplExpandData.expandedArgs ), |
192 | 195 | tplExpandData.target |
193 | 196 | ); |
| 197 | + this.manager.env.dp( 'argHash:', this.manager.env.KVtoHash( tplExpandData.expandedArgs ) ); |
194 | 198 | |
195 | 199 | // Hook up the inputPipeline output events to our handlers |
196 | 200 | inputPipeline.addListener( 'chunk', this._onChunk.bind ( this, tplExpandData ) ); |
— | — | @@ -359,8 +363,8 @@ |
360 | 364 | // ' vs. ' + JSON.stringify( this.manager.args ) ); |
361 | 365 | res = this.manager.args[argName]; |
362 | 366 | } else { |
363 | | - //console.log( 'templateArg not found: ' + argName + |
364 | | - // ' vs. ' + JSON.stringify( this.manager.args ) ); |
| 367 | + console.log( 'templateArg not found: ' + argName + |
| 368 | + ' vs. ' + JSON.stringify( this.manager.args ) ); |
365 | 369 | if ( token.attribs.length > 1 ) { |
366 | 370 | res = defaultValue; |
367 | 371 | } else { |