kopia lustrzana https://github.com/miklobit/TiddlyWiki5
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 functionprint-window-tiddler
rodzic
3412580af3
commit
9a73b0a6aa
|
@ -79,8 +79,13 @@ var App = function() {
|
||||||
} else {
|
} else {
|
||||||
this.store.jsParser = new JavaScriptParser(require("fs").readFileSync("parsers/javascript.pegjs","utf8"));
|
this.store.jsParser = new JavaScriptParser(require("fs").readFileSync("parsers/javascript.pegjs","utf8"));
|
||||||
}
|
}
|
||||||
// Hack to install standard macros
|
// Bit of a hack to set up the macros
|
||||||
this.store.installMacros();
|
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
|
// Set up navigation if we're in the browser
|
||||||
if(this.isBrowser) {
|
if(this.isBrowser) {
|
||||||
// Install the standard navigators
|
// Install the standard navigators
|
||||||
|
|
193
js/WikiStore.js
193
js/WikiStore.js
|
@ -19,6 +19,7 @@ var WikiStore = function WikiStore(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.tiddlers = {};
|
this.tiddlers = {};
|
||||||
this.parsers = {};
|
this.parsers = {};
|
||||||
|
this.macros = {};
|
||||||
this.tiddlerSerializers = {};
|
this.tiddlerSerializers = {};
|
||||||
this.tiddlerDeserializers = {};
|
this.tiddlerDeserializers = {};
|
||||||
this.sandbox = options.sandbox;
|
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 "<a href='" + utils.htmlEncode(tiddler.fields[field]) + "'" + this.classesForLink(tiddler.fields[field]) + ">" + utils.htmlEncode(tiddler.fields[field]) + "</a>";
|
|
||||||
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) {
|
WikiStore.prototype.classesForLink = function(target) {
|
||||||
var className = "",
|
var className = "",
|
||||||
externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
|
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 + "\"" : "";
|
return className !== "" ? " class=\"" + className + "\"" : "";
|
||||||
};
|
};
|
||||||
|
|
||||||
WikiStore.prototype.listTiddlers = function(type,template,emptyMessage) {
|
|
||||||
return "<span>Listing!</span>";
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = "<<view title link>>",
|
|
||||||
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<tiddlers.length; t++) {
|
|
||||||
var li = {
|
|
||||||
type: "li",
|
|
||||||
children: [ {
|
|
||||||
type: "context",
|
|
||||||
tiddler: tiddlers[t],
|
|
||||||
children: []
|
|
||||||
} ]
|
|
||||||
};
|
|
||||||
li.children[0].children = this.store.parseText(templateType,templateText).children;
|
|
||||||
ul.children.push(li);
|
|
||||||
}
|
|
||||||
if(ul.children.length > 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) {
|
WikiStore.prototype.parseText = function(type,text) {
|
||||||
var parser = this.parsers[type];
|
var parser = this.parsers[type];
|
||||||
if(!parser) {
|
if(!parser) {
|
||||||
|
@ -343,94 +240,10 @@ WikiStore.prototype.renderTiddler = function(type,title,asTitle) {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
WikiStore.prototype.installMacros = function() {
|
WikiStore.prototype.installMacro = function(macro) {
|
||||||
this.macros = {
|
this.macros[macro.name] = macro;
|
||||||
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 <<list>> 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);")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
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; t<withTokens.length; t++) {
|
|
||||||
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
|
|
||||||
text = text.replace(placeholderRegExp,withTokens[t]);
|
|
||||||
}
|
|
||||||
macroNode.output = this.store.parseText(tiddler.fields.type,text).children;
|
|
||||||
// Execute any macros in the copy
|
|
||||||
this.executeMacros(macroNode.output,title);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.WikiStore = WikiStore;
|
exports.WikiStore = WikiStore;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -84,23 +84,48 @@ WikiTextParseTree.prototype.compileMacroCall = function(type,name,params) {
|
||||||
var macroCall = {
|
var macroCall = {
|
||||||
type: "FunctionCall",
|
type: "FunctionCall",
|
||||||
name: {
|
name: {
|
||||||
type: "Function",
|
"base": {
|
||||||
name: null,
|
"base": {
|
||||||
params: ["params"],
|
"base": {
|
||||||
elements: []},
|
"name": "store",
|
||||||
|
"type": "Variable"
|
||||||
|
},
|
||||||
|
"name": "macros",
|
||||||
|
"type": "PropertyAccess"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "StringLiteral",
|
||||||
|
"value": name
|
||||||
|
},
|
||||||
|
"type": "PropertyAccess"
|
||||||
|
},
|
||||||
|
"name": "code",
|
||||||
|
"type": "PropertyAccess"
|
||||||
|
},
|
||||||
"arguments": [ {
|
"arguments": [ {
|
||||||
|
"type": "StringLiteral",
|
||||||
|
"value": type
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Variable",
|
||||||
|
"name": "tiddler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Variable",
|
||||||
|
"name": "store"
|
||||||
|
},
|
||||||
|
{
|
||||||
type: "ObjectLiteral",
|
type: "ObjectLiteral",
|
||||||
properties: []
|
properties: []
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
macroCall.name.elements = macro.code[type].tree.elements;
|
|
||||||
for(p in params) {
|
for(p in params) {
|
||||||
if(params[p].type === "string") {
|
if(params[p].type === "string") {
|
||||||
n = {type: "StringLiteral", value: params[p].value};
|
n = {type: "StringLiteral", value: params[p].value};
|
||||||
} else {
|
} else {
|
||||||
n = this.store.jsParser.parse(params[p].value).tree.elements[0];
|
n = this.store.jsParser.parse(params[p].value).tree.elements[0];
|
||||||
}
|
}
|
||||||
macroCall["arguments"][0].properties.push({
|
macroCall["arguments"][3].properties.push({
|
||||||
type: "PropertyAssignment",
|
type: "PropertyAssignment",
|
||||||
name: p,
|
name: p,
|
||||||
value: n
|
value: n
|
||||||
|
@ -108,7 +133,7 @@ WikiTextParseTree.prototype.compileMacroCall = function(type,name,params) {
|
||||||
}
|
}
|
||||||
this.output.push(macroCall);
|
this.output.push(macroCall);
|
||||||
} else {
|
} else {
|
||||||
this.pushString("<span class='error errorUnknownMacro'>Unknown macro '" + name + "'</span>");
|
this.pushString("{{** Unknown macro '" + name + "' **}}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -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 <<list>> 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!";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -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";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
|
@ -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 "<a href='" + encoder(v) + "'" + store.classesForLink(v) + ">" + encoder(v) + "</a>";
|
||||||
|
} 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 "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
|
@ -23,6 +23,13 @@ jsmodule: ../js/Navigators.js
|
||||||
jsmodule: ../js/StoryNavigator.js
|
jsmodule: ../js/StoryNavigator.js
|
||||||
jsmodule: ../js/App.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
|
jsmodule: ../node_modules/pegjs/lib/peg.js
|
||||||
title: pegjs
|
title: pegjs
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue