https://www.mediawiki.org/wiki/Special:Code/MediaWiki/109653

Revision: 109653
Author:   gwicke
Date:     2012-01-20 22:02:23 +0000 (Fri, 20 Jan 2012)
Log Message:
-----------
* NoInclude and IncludeOnly improvements
* Tokenizer support for templates and template args in template arguments and 
titles
* Async attribute expansion fixes

Modified Paths:
--------------
    trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
    
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
    trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
    trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt

Added Paths:
-----------
    trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js

Removed Paths:
-------------
    trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js

Copied: trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js 
(from rev 109633, 
trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js)
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js      
                        (rev 0)
+++ trunk/extensions/VisualEditor/modules/parser/ext.core.NoIncludeOnly.js      
2012-01-20 22:02:23 UTC (rev 109653)
@@ -0,0 +1,59 @@
+/**
+ * Simple noinclude / onlyinclude implementation. Strips all tokens in
+ * noinclude sections.
+ *
+ * @author Gabriel Wicke <[email protected]>
+ */
+
+var TokenCollector = require( './ext.util.TokenCollector.js' ).TokenCollector;
+
+function NoInclude( manager, isInclude ) {
+       new TokenCollector( 
+                       manager,
+                       function ( tokens ) { 
+                               if ( isInclude ) {
+                                       manager.env.dp( 'noinclude stripping', 
tokens );
+                                       return {};
+                               } else {
+                                       tokens.shift();
+                                       if ( tokens.length &&
+                                               tokens[tokens.length - 1].type 
!== 'END' ) {
+                                               tokens.pop();
+                                       }
+                                       return { tokens: tokens };
+                               }
+                       }, // just strip it all..
+                       true, // match the end-of-input if </noinclude> is 
missing
+                       0.01, // very early in stage 1, to avoid any further 
processing.
+                       'tag',
+                       'noinclude'
+                       );
+}
+
+function IncludeOnly( manager, isInclude ) {
+       new TokenCollector( 
+                       manager,
+                       function ( tokens ) { 
+                               if ( isInclude ) {
+                                       tokens.shift();
+                                       if ( tokens.length &&
+                                               tokens[tokens.length - 1].type 
!== 'END' ) {
+                                                       tokens.pop();
+                                       }
+                                       return { tokens: tokens };
+                               } else {
+                                       return {};
+                               }
+                       },
+                       true, // match the end-of-input if </noinclude> is 
missing
+                       0.01, // very early in stage 1, to avoid any further 
processing.
+                       'tag',
+                       'includeonly'
+                       );
+}
+
+
+if (typeof module == "object") {
+       module.exports.NoInclude = NoInclude;
+       module.exports.IncludeOnly = IncludeOnly;
+}

Deleted: trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js      
2012-01-20 21:55:15 UTC (rev 109652)
+++ trunk/extensions/VisualEditor/modules/parser/ext.core.NoOnlyInclude.js      
2012-01-20 22:02:23 UTC (rev 109653)
@@ -1,39 +0,0 @@
-/**
- * Simple noinclude / onlyinclude implementation. Strips all tokens in
- * noinclude sections.
- *
- * @author Gabriel Wicke <[email protected]>
- */
-
-var TokenCollector = require( './ext.util.TokenCollector.js' ).TokenCollector;
-
-function NoInclude( manager ) {
-       new TokenCollector( 
-                       manager,
-                       function ( tokens ) { 
-                               manager.env.dp( 'noinclude stripping', tokens );
-                               return {};
-                       }, // just strip it all..
-                       true, // match the end-of-input if </noinclude> is 
missing
-                       0.01, // very early in stage 1, to avoid any further 
processing.
-                       'tag',
-                       'noinclude'
-                       );
-}
-
-function OnlyInclude( manager ) {
-       new TokenCollector( 
-                       manager,
-                       function ( ) { return {} }, // just strip it all..
-                       true, // match the end-of-input if </noinclude> is 
missing
-                       0.01, // very early in stage 1, to avoid any further 
processing.
-                       'tag',
-                       'onlyinclude'
-                       );
-}
-
-
-if (typeof module == "object") {
-       module.exports.NoInclude = NoInclude;
-       module.exports.OnlyInclude = OnlyInclude;
-}

Modified: 
trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js    
2012-01-20 21:55:15 UTC (rev 109652)
+++ trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js    
2012-01-20 22:02:23 UTC (rev 109653)
@@ -75,8 +75,8 @@
        var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]]
                        .concat( this._nameArgs( token.orderedArgs ) );
 
-       //console.log( 'before AttributeTransformManager: ' + 
-       //                                      JSON.stringify( attributes, 
null, 2 ) );
+       this.manager.env.dp( 'before AttributeTransformManager: ' + 
+                                               JSON.stringify( attributes, 
null, 2 ) );
        new AttributeTransformManager( 
                                this.manager, 
                                this._returnAttributes.bind( this, 
tplExpandData ) 
@@ -85,7 +85,10 @@
        // Unblock finish
        if ( ! tplExpandData.attribsAsync ) {
                // Attributes were transformed synchronously
-               this.manager.env.dp( 'sync attribs for ' + JSON.stringify( 
token ));
+               this.manager.env.dp ( 
+                               'sync attribs for ' + JSON.stringify( 
tplExpandData.target ),
+                               tplExpandData.expandedArgs
+               );
                // All attributes are fully expanded synchronously (no IO was 
needed)
                return this._expandTemplate ( tplExpandData );
        } else {
@@ -110,7 +113,7 @@
                        out.push( orderedArgs[i] );
                }
        }
-       //console.log( '_nameArgs: ' + JSON.stringify( out ) );
+       this.manager.env.dp( '_nameArgs: ' + JSON.stringify( out ) );
        return out;
 };
 
@@ -190,6 +193,7 @@
                                this.manager.env.KVtoHash( 
tplExpandData.expandedArgs ),
                                tplExpandData.target
                        );
+       this.manager.env.dp( 'argHash:', this.manager.env.KVtoHash( 
tplExpandData.expandedArgs ) );
 
        // Hook up the inputPipeline output events to our handlers
        inputPipeline.addListener( 'chunk', this._onChunk.bind ( this, 
tplExpandData ) );
@@ -359,8 +363,8 @@
                //              ' vs. ' + JSON.stringify( this.manager.args ) 
); 
                res = this.manager.args[argName];
        } else {
-               //console.log( 'templateArg not found: ' + argName + 
-               //              ' vs. ' + JSON.stringify( this.manager.args ) );
+               console.log( 'templateArg not found: ' + argName + 
+                               ' vs. ' + JSON.stringify( this.manager.args ) );
                if ( token.attribs.length > 1 ) {
                        res = defaultValue;
                } else {

Modified: 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
===================================================================
--- 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js 
    2012-01-20 21:55:15 UTC (rev 109652)
+++ 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js 
    2012-01-20 22:02:23 UTC (rev 109653)
@@ -664,7 +664,7 @@
                }
        }
        this.env.dp( 'SyncTokenTransformManager.onChunk: emitting ' + 
-                       JSON.stringify( localAccum ) );
+                       JSON.stringify( localAccum, null, 2 ) );
        this.emit( 'chunk', localAccum );
 };
 
@@ -698,7 +698,7 @@
 function AttributeTransformManager ( manager, callback ) {
        this.manager = manager;
        this.callback = callback;
-       this.outstanding = 0;
+       this.outstanding = 1;
        this.kvs = [];
        //this.pipe = manager.getAttributePipeline( manager.args );
 }
@@ -726,7 +726,7 @@
                pipe.addListener( 'end', 
                                this.onEnd.bind( this, 
this._returnAttributeKey.bind( this, i ) ) 
                                );
-               pipe.process( attributes[i][0] );
+               pipe.process( attributes[i][0].concat([{type:'END'}]) );
 
                // transform the value
                pipe = this.manager.getAttributePipeline( this.manager.args );
@@ -737,8 +737,12 @@
                                this.onEnd.bind( this, 
this._returnAttributeValue.bind( this, i ) ) 
                                );
                //console.log('starting attribute transform of ' + 
JSON.stringify( attributes[i][1] ) );
-               pipe.process( attributes[i][1] );
+               pipe.process( attributes[i][1].concat([{type:'END'}]) );
        }
+       this.outstanding--;
+       if ( this.outstanding == 0 ) {
+               this._returnAttributes();
+       }
 };
 
 AttributeTransformManager.prototype._returnAttributes = function ( ) {
@@ -758,6 +762,9 @@
  * Collect chunks returned from the pipeline
  */
 AttributeTransformManager.prototype.onChunk = function ( cb, chunk ) {
+       if ( chunk.length && chunk[chunk.length - 1].type === 'END' ) {
+               chunk.pop();
+       }
        cb( chunk, true );
 };
 
@@ -773,7 +780,8 @@
  * Callback for async argument value expansions
  */
 AttributeTransformManager.prototype._returnAttributeValue = function ( ref, 
tokens, notYetDone ) {
-       //console.log( 'check _returnAttributeValue: ' + JSON.stringify( tokens 
) );
+       //console.log( 'check _returnAttributeValue: ' + JSON.stringify( tokens 
) + 
+       //              ' notYetDone:' + notYetDone );
        this.kvs[ref].value = this.kvs[ref].value.concat( tokens );
        if ( ! notYetDone ) {
                this.outstanding--;
@@ -788,6 +796,8 @@
  * Callback for async argument key expansions
  */
 AttributeTransformManager.prototype._returnAttributeKey = function ( ref, 
tokens, notYetDone ) {
+       //console.log( 'check _returnAttributeKey: ' + JSON.stringify( tokens ) 
+ 
+       //              ' notYetDone:' + notYetDone );
        this.kvs[ref].key = this.kvs[ref].key.concat( tokens );
        if ( ! notYetDone ) {
                this.outstanding--;

Modified: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js    
2012-01-20 21:55:15 UTC (rev 109652)
+++ trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js    
2012-01-20 22:02:23 UTC (rev 109653)
@@ -16,9 +16,9 @@
        PegTokenizer                = 
require('./mediawiki.tokenizer.peg.js').PegTokenizer,
        TokenTransformManager       = 
require('./mediawiki.TokenTransformManager.js'),
 
-       NoOnlyInclude                           = 
require('./ext.core.NoOnlyInclude.js'),
-       OnlyInclude                                     = 
NoOnlyInclude.OnlyInclude,
-       NoInclude                                       = 
NoOnlyInclude.NoInclude,
+       NoIncludeOnly                           = 
require('./ext.core.NoIncludeOnly.js'),
+       IncludeOnly                                     = 
NoIncludeOnly.IncludeOnly,
+       NoInclude                                       = 
NoIncludeOnly.NoInclude,
        QuoteTransformer            = 
require('./ext.core.QuoteTransformer.js').QuoteTransformer,
        PostExpandParagraphHandler  = 
require('./ext.core.PostExpandParagraphHandler.js')
                                                                                
                                                .PostExpandParagraphHandler,
@@ -65,7 +65,7 @@
        };
 
        // Create an input pipeline for the given input type.
-       this.inputPipeline = this.makeInputPipeline ( inputType );
+       this.inputPipeline = this.makeInputPipeline ( inputType, {}, true );
        this.inputPipeline.atTopLevel = true;
 
 
@@ -137,7 +137,7 @@
  * accepts the wiki text this way. The last stage of the input pipeline is
  * always an AsyncTokenTransformManager, which emits its output in events.
  */
-ParserPipeline.prototype.makeInputPipeline = function ( inputType, args ) {
+ParserPipeline.prototype.makeInputPipeline = function ( inputType, args, 
isNoInclude ) {
        switch ( inputType ) {
                case 'text/wiki':
                        //console.log( 'makeInputPipeline ' + JSON.stringify( 
args ) );
@@ -158,8 +158,9 @@
                                var tokenPreProcessor = new 
TokenTransformManager.SyncTokenTransformManager ( this.env );
                                tokenPreProcessor.listenForTokensFrom ( 
wikiTokenizer );
 
+                               new IncludeOnly( tokenPreProcessor, ! 
isNoInclude );
                                // Add noinclude transform for now
-                               new NoInclude( tokenPreProcessor );
+                               new NoInclude( tokenPreProcessor, ! isNoInclude 
);
 
                                var tokenExpander = new 
TokenTransformManager.AsyncTokenTransformManager (
                                                        {

Modified: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt 
2012-01-20 21:55:15 UTC (rev 109652)
+++ trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt 
2012-01-20 22:02:23 UTC (rev 109653)
@@ -480,7 +480,11 @@
   / & { return syntaxFlags['extlink']; } "]" { return true; }
   / & { return syntaxFlags['linkdesc']; } link_end { return true; }
   / & { return syntaxFlags['h']; } '='+ space* newline { return true; }
-  / & { return syntaxFlags['template']; } ('|' / '}}') { return true; }
+  / & { return syntaxFlags['template']; } ('|' / '}}' ) { return true; }
+  / & { return syntaxFlags['equal']; } '=' { 
+                    //console.log( 'equal stop!' );
+                    return true; 
+                }
 
 inline
   = c:(urltext / (! inline_breaks (inline_element / . )))+ {
@@ -539,6 +543,7 @@
   = //& { dp('inline_element enter' + input.substr(pos, 10)); return true; }
       & '<' ( comment / xmlish_tag )
     / & '{' ( & '{{{{{' template / tplarg / template )
+    /// & '{' ( tplarg / template )
      // Eat three opening brackets as text.
     / '[[[' { return { type: 'TEXT', value: '[[[' } }
     / & '[' ( wikilink / extlink )
@@ -711,25 +716,26 @@
             name: 'template', 
             attribs: [['data-target', JSON.stringify(target)]],
             orderedArgs: params,
-            args: {},
+            //args: {},
             target: target
       };
-      if (params && params.length) {
-          var position = 1;
-          for ( var i = 0, l = params.length; i < l; i++ ) {
-              var param = params[i];
-              if ( param[0] === null ) {
-                  obj.args[position] = param[1];
-                  position++;
-              } else {
-                  // Last value wins for duplicates.
-                  obj.args[param[0]] = param[1];
-              }
-          }
-          // HACK: temporarily also push the args into an attribute
-          // (just for debugging)
-          obj.attribs.push(['data-json-args', JSON.stringify(obj.args)]);
-      }
+      // XXX: this is kind of broken, as arg keys need to be expanded
+      //if (params && params.length) {
+      //    var position = 1;
+      //    for ( var i = 0, l = params.length; i < l; i++ ) {
+      //        var param = params[i];
+      //        if ( param[0] === null ) {
+      //            obj.args[position] = param[1];
+      //            position++;
+      //        } else {
+      //            // Last value wins for duplicates.
+      //            obj.args[param[0]] = param[1];
+      //        }
+      //    }
+      //    // HACK: temporarily also push the args into an attribute
+      //    // (just for debugging)
+      //    obj.attribs.push(['data-json-args', JSON.stringify(obj.args)]);
+      //}
       // Should actually use a self-closing tag here, but the Node HTML5
       // parser only recognizes known self-closing tags for now, so use an
       // explicit end tag for now.
@@ -738,18 +744,14 @@
   }
 
 // XXX: support template and args in target!
-template_target
-  = h:( !"}}" x:([^|\n]) { return x } )* { return { type: 'TEXT', value: 
h.join('') } }
+//template_target
+//  = h:( !"}}" x:([^|\n]) { return x } )* { return { type: 'TEXT', value: 
h.join('') } }
 
-template_param
-  = name:template_param_name space* "=" space* c:template_param_text {
-      return [[{ type: 'TEXT', value: name }], flatten( c )];
-  } / c:template_param_text {
-      return [[], flatten( c ) ];
-  }
-
 tplarg 
-  = "{{{" name:template_param_text params:("|" p:template_param { return p })* 
"}}}" {
+  = "{{{" 
+    name:template_param_text 
+    params:( newline? "|" newline? p:template_param { return p })* 
+    "}}}" {
       name = flatten( name );
       var obj = { 
             type: 'SELFCLOSINGTAG', 
@@ -764,21 +766,39 @@
           obj.attribs.push(['data-json-args', JSON.stringify(params)]);
           obj.defaultvalue = params[0][1];
       }
-      //console.log( 'tokenizer templatearg ' + JSON.stringify( obj ));
+      console.log( 'tokenizer tplarg ' + JSON.stringify( obj ));
       return obj;
   }
 
+template_param
+  = name:template_param_name space* "=" space* c:template_param_text {
+      //console.log( 'named template_param matched' + pp([name, flatten( c )]) 
);
+      return [name, flatten( c )];
+  } / c:template_param_text {
+      return [[], flatten( c ) ];
+  }
+
+
 // FIXME: handle template args and templates in key! (or even parser 
functions?)
 template_param_name
-  = h:( !"}}" x:([^=|\n]) { return x } )* { return h.join(''); }
+  = & { return setFlag( 'equal' ) }
+    tpt:template_param_text
+    & { clearFlag( 'equal' ); return true; }
+    {
+        //console.log( 'template param name matched: ' + pp( tpt ) );
+        return tpt;
+    }
 
+  / & { return clearFlag( 'equal' ) }
+  //= h:( !"}}" x:([^=|\n]) { return x } )* { return h.join(''); }
+
 template_param_text
   = & { return setFlag('template') }
-    il:inline+ {
+    il:inline {
         clearFlag('template');
         return il;
     }
-  / & { clearFlag('template'); return false; }
+  / & { return clearFlag('template'); }
 
 // TODO: handle link prefixes as in al[[Razi]]
 wikilink


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

Reply via email to