From 9a73b0a6aaa64b42ad76e7608319b256ce942426 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sat, 7 Jan 2012 17:33:42 +0000 Subject: [PATCH] Rejigged macro implementation Now each macro is in a separate file, and is implemented as a function, rather than being inlined into the compiled tiddler rendering function --- js/App.js | 9 +- js/WikiStore.js | 193 +-------------------------------- js/WikiTextParseTree.js | 39 +++++-- js/macros/echo.js | 27 +++++ js/macros/info.js | 33 ++++++ js/macros/list.js | 26 +++++ js/macros/tiddler.js | 25 +++++ js/macros/version.js | 22 ++++ js/macros/view.js | 45 ++++++++ tiddlywiki5/tiddlywiki5.recipe | 7 ++ 10 files changed, 227 insertions(+), 199 deletions(-) create mode 100644 js/macros/echo.js create mode 100644 js/macros/info.js create mode 100644 js/macros/list.js create mode 100644 js/macros/tiddler.js create mode 100644 js/macros/version.js create mode 100644 js/macros/view.js diff --git a/js/App.js b/js/App.js index f5b174239..a77763beb 100644 --- a/js/App.js +++ b/js/App.js @@ -79,8 +79,13 @@ var App = function() { } else { this.store.jsParser = new JavaScriptParser(require("fs").readFileSync("parsers/javascript.pegjs","utf8")); } - // Hack to install standard macros - this.store.installMacros(); + // Bit of a hack to set up the macros + this.store.installMacro(require("./macros/echo.js").macro); + this.store.installMacro(require("./macros/info.js").macro); + this.store.installMacro(require("./macros/list.js").macro); + this.store.installMacro(require("./macros/tiddler.js").macro); + this.store.installMacro(require("./macros/version.js").macro); + this.store.installMacro(require("./macros/view.js").macro); // Set up navigation if we're in the browser if(this.isBrowser) { // Install the standard navigators diff --git a/js/WikiStore.js b/js/WikiStore.js index 83e5bb1d0..8bc926f64 100755 --- a/js/WikiStore.js +++ b/js/WikiStore.js @@ -19,6 +19,7 @@ var WikiStore = function WikiStore(options) { options = options || {}; this.tiddlers = {}; this.parsers = {}; + this.macros = {}; this.tiddlerSerializers = {}; this.tiddlerDeserializers = {}; this.sandbox = options.sandbox; @@ -162,26 +163,6 @@ WikiStore.prototype.deserializeTiddlers = function(type,text,srcFields) { } }; -WikiStore.prototype.getFormattedTiddlerField = function(title,field,format,template) { - format = format || "text"; - var tiddler = this.getTiddler(title); - if(tiddler && tiddler.fields[field]) { - switch(format) { - case "text": - return utils.htmlEncode(tiddler.fields[field]); - case "link": - // xxx: Attribute encoding is wrong - return "" + utils.htmlEncode(tiddler.fields[field]) + ""; - case "wikified": - return this.renderTiddler("text/html",tiddler.fields.title); - case "date": - template = template || "DD MMM YYYY"; - return utils.htmlEncode(utils.formatDateString(tiddler.fields[field],template)); - } - } - return ""; -}; - WikiStore.prototype.classesForLink = function(target) { var className = "", externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i; @@ -195,90 +176,6 @@ WikiStore.prototype.classesForLink = function(target) { return className !== "" ? " class=\"" + className + "\"" : ""; }; -WikiStore.prototype.listTiddlers = function(type,template,emptyMessage) { - return "Listing!"; -}; - -WikiStore.prototype.tiddlerInfo = function(title) { - var tiddler = this.getTiddler(title), - parseTree = this.parseTiddler(title); - if(tiddler && parseTree) { - var d = parseTree.dependencies; - if(d === null) { - return "Dependencies: *"; - } else { - return "Dependencies: " + d.join(", "); - } - } else { - return ""; - } -}; - -/* - - argOptions: {defaultName:"type"}, - handler: function(macroNode,args,title) { - var type = args.getValueByName("type","all"), - template = args.getValueByName("template",null), - templateType = "text/x-tiddlywiki", templateText = "<>", - emptyMessage = args.getValueByName("emptyMessage",null); - // Get the template to use - template = template ? this.store.getTiddler(template) : null; - if(template) { - templateType = template.fields.type; - templateText = template.fields.text; - } - // Get the handler and the tiddlers - var handler = WikiTextRenderer.macros.list.types[type]; - handler = handler || WikiTextRenderer.macros.list.types.all; - var tiddlers = handler.call(this); - // Render them as a list - var ul = {type: "ul", children: []}; - for(var t=0; t 0) { - macroNode.output.push(ul); - this.executeMacros(macroNode.output,title); - } else if (emptyMessage) { - macroNode.output.push({type: "text", value: emptyMessage}); - } - }, - types: { - all: function() { - return this.store.getTitles("title","excludeLists"); - }, - missing: function() { - return this.store.getMissingTitles(); - }, - orphans: function() { - return this.store.getOrphanTitles(); - }, - shadowed: function() { - return this.store.getShadowTitles(); - }, - touched: function() { - // Server syncing isn't implemented yet - return []; - }, - filter: function() { - // Filters aren't implemented yet - return []; - } - } - }, - -*/ - WikiStore.prototype.parseText = function(type,text) { var parser = this.parsers[type]; if(!parser) { @@ -343,94 +240,10 @@ WikiStore.prototype.renderTiddler = function(type,title,asTitle) { return null; }; -WikiStore.prototype.installMacros = function() { - this.macros = { - echo: { - params: { - text: {byPos: 0, type: "text", optional: false} - }, - code: { - "text/html": this.jsParser.parse("return utils.htmlEncode(params.text);"), - "text/plain": this.jsParser.parse("return params.text;") - } - }, - view: { - params: { - field: {byPos: 0, type: "text", optional: false}, - format: {byPos: 1, type: "text", optional: true}, - template: {byPos: 2, type: "text", optional: true} - }, - code: { - "text/html": this.jsParser.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);"), - "text/plain": this.jsParser.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);") - } - }, - list: { - dependantAll: true, // Tiddlers containing <> macro are dependent on every tiddler - params: { - type: {byName: "default", type: "text", optional: false}, - template: {byName: true, type: "tiddler", optional: true}, - emptyMessage: {byName: true, type: "text", optional: true} - }, - code: { - "text/html": this.jsParser.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);"), - "text/plain": this.jsParser.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);") - } - }, - version: { - params: { - }, - code: { - "text/html": this.jsParser.parse("return utils.htmlEncode('5.0.0');"), - "text/plain": this.jsParser.parse("return '5.0.0';") - } - }, - tiddler: { - cascadeParams: true, // Cascade names of named parameters to following anonymous parameters - params: { - target: {byName: "default", type: "tiddler", optional: false}, - "with": {byName: true, type: "text", optional: true} - }, - code: { - "text/html": this.jsParser.parse("return store.renderTiddler('text/html',params.target);"), - "text/plain": this.jsParser.parse("return store.renderTiddler('text/plain',params.target);") - } - }, - info: { - params: { - }, - code: { - "text/html": this.jsParser.parse("return utils.htmlEncode(store.tiddlerInfo(tiddler.fields.title));"), - "text/plain": this.jsParser.parse("return store.tiddlerInfo(tiddler.fields.title);") - } - } - }; +WikiStore.prototype.installMacro = function(macro) { + this.macros[macro.name] = macro; }; -/* - -tiddler: { - argOptions: {defaultName:"name",cascadeDefaults:true}, - handler: function(macroNode,args,title) { - var targetTitle = args.getValueByName("name",null), - withTokens = args.getValuesByName("with",[]), - tiddler = this.store.getTiddler(targetTitle), - text = this.store.getTiddlerText(targetTitle,""), - t; - for(t=0; tUnknown macro '" + name + "'"); + this.pushString("{{** Unknown macro '" + name + "' **}}"); } }; diff --git a/js/macros/echo.js b/js/macros/echo.js new file mode 100644 index 000000000..0f9bcf275 --- /dev/null +++ b/js/macros/echo.js @@ -0,0 +1,27 @@ +/*\ +title: js/macros/echo.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "echo", + types: ["text/html","text/plain"], + params: { + text: {byPos: 0, type: "text", optional: false} + }, + code: function(type,tiddler,store,params) { + if(type === "text/html") { + return utils.htmlEncode(params.text); + } else { + return params.text; + } + } +}; + +})(); diff --git a/js/macros/info.js b/js/macros/info.js new file mode 100644 index 000000000..a1113e55d --- /dev/null +++ b/js/macros/info.js @@ -0,0 +1,33 @@ +/*\ +title: js/macros/info.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "info", + types: ["text/html","text/plain"], + params: { + }, + code: function(type,tiddler,store,params) { + var encoder = type === "text/html" ? utils.htmlEncode : function(x) {return x;}, + parseTree = store.parseTiddler(tiddler.fields.title); + if(parseTree) { + var d = parseTree.dependencies; + if(d === null) { + return encoder("Dependencies: *"); + } else { + return encoder("Dependencies: " + d.join(", ")); + } + } else { + return ""; + } + } +}; + +})(); diff --git a/js/macros/list.js b/js/macros/list.js new file mode 100644 index 000000000..7c323b7b3 --- /dev/null +++ b/js/macros/list.js @@ -0,0 +1,26 @@ +/*\ +title: js/macros/list.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "list", + types: ["text/html","text/plain"], + dependantAll: true, // Tiddlers containing <> macro are dependent on every tiddler + params: { + type: {byName: "default", type: "text", optional: false}, + template: {byName: true, type: "tiddler", optional: true}, + emptyMessage: {byName: true, type: "text", optional: true} + }, + code: function(type,tiddler,store,params) { + return "Listing!"; + } +}; + +})(); diff --git a/js/macros/tiddler.js b/js/macros/tiddler.js new file mode 100644 index 000000000..19792829b --- /dev/null +++ b/js/macros/tiddler.js @@ -0,0 +1,25 @@ +/*\ +title: js/macros/tiddler.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "tiddler", + types: ["text/html","text/plain"], + cascadeParams: true, // Cascade names of named parameters to following anonymous parameters + params: { + target: {byName: "default", type: "tiddler", optional: false}, + "with": {byName: true, type: "text", optional: true} + }, + code: function(type,tiddler,store,params) { + return store.renderTiddler(type,params.target); + } +}; + +})(); diff --git a/js/macros/version.js b/js/macros/version.js new file mode 100644 index 000000000..ebc9e0af6 --- /dev/null +++ b/js/macros/version.js @@ -0,0 +1,22 @@ +/*\ +title: js/macros/version.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "version", + types: ["text/html","text/plain"], + params: { + }, + code: function(type,tiddler,store,params) { + return "5.0.0"; + } +}; + +})(); diff --git a/js/macros/view.js b/js/macros/view.js new file mode 100644 index 000000000..6bcbb8b7f --- /dev/null +++ b/js/macros/view.js @@ -0,0 +1,45 @@ +/*\ +title: js/macros/view.js + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var utils = require("../Utils.js"); + +exports.macro = { + name: "view", + types: ["text/html","text/plain"], + params: { + field: {byPos: 0, type: "text", optional: false}, + format: {byPos: 1, type: "text", optional: true}, + template: {byPos: 2, type: "text", optional: true} + }, + code: function(type,tiddler,store,params) { + var v = tiddler.fields[params.field], + encoder = type === "text/html" ? utils.htmlEncode : function(x) {return x;}; + if(v) { + switch(params.format) { + case "link": + if(type === "text/html") { + return "" + encoder(v) + ""; + } else { + return v; + } + case "wikified": + return store.renderTiddler(type,tiddler.fields.title); + case "date": + var template = params.template || "DD MMM YYYY"; + return encoder(utils.formatDateString(v,template)); + default: // "text" + return encoder(v); + } + } + return ""; + } +}; + +})(); + diff --git a/tiddlywiki5/tiddlywiki5.recipe b/tiddlywiki5/tiddlywiki5.recipe index 72db9b379..cd5b98b95 100644 --- a/tiddlywiki5/tiddlywiki5.recipe +++ b/tiddlywiki5/tiddlywiki5.recipe @@ -23,6 +23,13 @@ jsmodule: ../js/Navigators.js jsmodule: ../js/StoryNavigator.js jsmodule: ../js/App.js +jsmodule: ../js/macros/echo.js +jsmodule: ../js/macros/info.js +jsmodule: ../js/macros/list.js +jsmodule: ../js/macros/tiddler.js +jsmodule: ../js/macros/version.js +jsmodule: ../js/macros/view.js + jsmodule: ../node_modules/pegjs/lib/peg.js title: pegjs