From 2bef7c2c5c98e80ad56396bdd355ec41fe03c7be Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Fri, 14 Dec 2012 15:44:19 +0000 Subject: [PATCH] Further improvements to parser rule implementation --- core/boot.js | 15 +++++++++++++++ .../parsers/wikiparser/rules/block/heading.js | 3 ++- .../parsers/wikiparser/rules/block/list.js | 3 ++- .../wikiparser/rules/pragma/macrodef.js | 3 ++- .../parsers/wikiparser/rules/run/entity.js | 3 ++- .../parsers/wikiparser/rules/run/html.js | 3 ++- .../parsers/wikiparser/rules/run/macrocall.js | 3 ++- .../parsers/wikiparser/rules/run/wikilink.js | 3 ++- .../parsers/wikiparser/rules/wikirule.js | 16 ++++++++++------ core/modules/parsers/wikiparser/wikiparser.js | 8 ++++---- core/modules/wikivocabulary.js | 18 +++--------------- 11 files changed, 46 insertions(+), 32 deletions(-) diff --git a/core/boot.js b/core/boot.js index 04d677b74..7ebe32eab 100644 --- a/core/boot.js +++ b/core/boot.js @@ -444,6 +444,21 @@ $tw.modules.applyMethods = function(moduleType,targetObject) { return targetObject; }; +/* +Return an array of subclasses created from the modules of a specified type +*/ +$tw.modules.createSubclassesFromModules = function(moduleType,baseClass) { + var classes = {}; + $tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) { + var newClass = function() {}; + newClass.prototype = new baseClass(); + newClass.prototype.constructor = baseClass; + $tw.utils.extend(newClass.prototype,moduleExports); + classes[moduleExports.name] = newClass; + }); + return classes; +}; + /////////////////////////// Barebones tiddler object /* diff --git a/core/modules/parsers/wikiparser/rules/block/heading.js b/core/modules/parsers/wikiparser/rules/block/heading.js index c2277a265..88098eea7 100644 --- a/core/modules/parsers/wikiparser/rules/block/heading.js +++ b/core/modules/parsers/wikiparser/rules/block/heading.js @@ -14,7 +14,8 @@ Wiki text block rule for headings exports.name = "heading"; -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /(!{1,6})/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/block/list.js b/core/modules/parsers/wikiparser/rules/block/list.js index 2e4ce6952..9b1907918 100644 --- a/core/modules/parsers/wikiparser/rules/block/list.js +++ b/core/modules/parsers/wikiparser/rules/block/list.js @@ -48,7 +48,8 @@ A CSS class can be applied to a list item as follows: exports.name = "list"; -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /([\\*#;:]+)/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/pragma/macrodef.js b/core/modules/parsers/wikiparser/rules/pragma/macrodef.js index c90d351a9..769882c3b 100644 --- a/core/modules/parsers/wikiparser/rules/pragma/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/pragma/macrodef.js @@ -23,7 +23,8 @@ exports.name = "macrodef"; /* Instantiate parse rule */ -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /^\\define\s*([^(\s]+)\(\s*([^)]*)\)(\r?\n)?/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/run/entity.js b/core/modules/parsers/wikiparser/rules/run/entity.js index 6d7a6acf8..fb2881c53 100644 --- a/core/modules/parsers/wikiparser/rules/run/entity.js +++ b/core/modules/parsers/wikiparser/rules/run/entity.js @@ -18,7 +18,8 @@ Wiki text run rule for HTML entities. For example: exports.name = "entity"; -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /(&#?[a-zA-Z0-9]{2,8};)/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/run/html.js b/core/modules/parsers/wikiparser/rules/run/html.js index afc4e6690..2e794299c 100644 --- a/core/modules/parsers/wikiparser/rules/run/html.js +++ b/core/modules/parsers/wikiparser/rules/run/html.js @@ -27,7 +27,8 @@ exports.name = "html"; var voidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(","); -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /<(_)?([A-Za-z]+)(\s*[^>]*?)(\/)?>/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/run/macrocall.js b/core/modules/parsers/wikiparser/rules/run/macrocall.js index 21b4ae39b..b8fc89142 100644 --- a/core/modules/parsers/wikiparser/rules/run/macrocall.js +++ b/core/modules/parsers/wikiparser/rules/run/macrocall.js @@ -18,7 +18,8 @@ Wiki rule for macro calls exports.name = "macrocall"; -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = /<<([^\s>]+)\s*([\s\S]*?)>>/mg; }; diff --git a/core/modules/parsers/wikiparser/rules/run/wikilink.js b/core/modules/parsers/wikiparser/rules/run/wikilink.js index b719a5315..5d5e7aeae 100644 --- a/core/modules/parsers/wikiparser/rules/run/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/run/wikilink.js @@ -35,7 +35,8 @@ textPrimitives.wikiLink = textPrimitives.upperLetter + "+" + textPrimitives.upperLetter + textPrimitives.anyLetter + "*"; -exports.init = function() { +exports.init = function(parser) { + this.parser = parser; // Regexp to match this.matchRegExp = new RegExp(textPrimitives.unWikiLink + "?" + textPrimitives.wikiLink,"mg"); }; diff --git a/core/modules/parsers/wikiparser/rules/wikirule.js b/core/modules/parsers/wikiparser/rules/wikirule.js index f8427881d..dfec85a39 100644 --- a/core/modules/parsers/wikiparser/rules/wikirule.js +++ b/core/modules/parsers/wikiparser/rules/wikirule.js @@ -12,24 +12,28 @@ Base class for wiki parser rules /*global $tw: false */ "use strict"; -var WikiRuleDefaultProperties = {}; +/* +This constructor is always overridden with a blank constructor, and so shouldn't be used +*/ +var WikiRule = function() { +}; /* To be overridden by individual rules */ -WikiRuleDefaultProperties.init = function() { - +WikiRule.prototype.init = function(parser) { + this.parser = parser; }; /* -Default implementation of findNextMatch looks uses RegExp matching +Default implementation of findNextMatch uses RegExp matching */ -WikiRuleDefaultProperties.findNextMatch = function(startPos) { +WikiRule.prototype.findNextMatch = function(startPos) { this.matchRegExp.lastIndex = startPos; this.match = this.matchRegExp.exec(this.parser.source); return this.match ? this.match.index : undefined; }; -exports.WikiRuleDefaultProperties = WikiRuleDefaultProperties; +exports.WikiRule = WikiRule; })(); diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index e133b475c..673776604 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -38,12 +38,12 @@ var WikiParser = function(vocabulary,type,text,options) { // Initialise the things that pragma rules can change this.macroDefinitions = {}; // Hash map of macro definitions // Instantiate the pragma parse rules - this.pragmaRules = this.instantiateRules(this.vocabulary.pragmaRules,0); + this.pragmaRules = this.instantiateRules(this.vocabulary.pragmaRuleClasses,0); // Parse any pragmas this.parsePragmas(); // Instantiate the parser block and run rules - this.blockRules = this.instantiateRules(this.vocabulary.blockRules,this.pos); - this.runRules = this.instantiateRules(this.vocabulary.runRules,this.pos); + this.blockRules = this.instantiateRules(this.vocabulary.blockRuleClasses,this.pos); + this.runRules = this.instantiateRules(this.vocabulary.runRuleClasses,this.pos); // Parse the text into runs or blocks if(this.type === "text/vnd.tiddlywiki-run") { this.tree = this.parseRun(); @@ -61,7 +61,7 @@ WikiParser.prototype.instantiateRules = function(classes,startPos) { $tw.utils.each(classes,function(RuleClass) { // Instantiate the rule var rule = new RuleClass(self); - rule.init(); + rule.init(self); var matchIndex = rule.findNextMatch(startPos); if(matchIndex !== undefined) { rulesInfo.push({ diff --git a/core/modules/wikivocabulary.js b/core/modules/wikivocabulary.js index f9cab2936..127ec3278 100644 --- a/core/modules/wikivocabulary.js +++ b/core/modules/wikivocabulary.js @@ -13,27 +13,15 @@ module-type: global var WikiVocabulary = function(options) { this.wiki = options.wiki; // Hashmaps of the various parse rule classes - this.pragmaRules = this.createRuleClasses("wikipragmarule"); - this.blockRules = this.createRuleClasses("wikiblockrule"); - this.runRules = this.createRuleClasses("wikirunrule"); + this.pragmaRuleClasses = $tw.modules.createSubclassesFromModules("wikipragmarule",$tw.WikiRule); + this.blockRuleClasses = $tw.modules.createSubclassesFromModules("wikiblockrule",$tw.WikiRule); + this.runRuleClasses = $tw.modules.createSubclassesFromModules("wikirunrule",$tw.WikiRule); // Hashmap of the various renderer classes this.rendererClasses = $tw.modules.applyMethods("wikirenderer"); // Hashmap of the available widgets this.widgetClasses = $tw.modules.applyMethods("widget"); }; -WikiVocabulary.prototype.createRuleClasses = function(moduleType) { - var ruleClasses = {}; - $tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) { - var ruleClass = function(parser) { - this.parser = parser; - } - $tw.utils.extend(ruleClass.prototype,$tw.WikiRuleDefaultProperties,moduleExports); - ruleClasses[moduleExports.name] = ruleClass; - }); - return ruleClasses; -}; - WikiVocabulary.prototype.parseText = function(type,text) { return new $tw.WikiParser(this,type,text,{wiki: this.wiki}); };