Add support for macro modules

Now JavaScript macros can be defined in "macro" modules
This commit is contained in:
Jeremy Ruston 2013-10-17 16:57:07 +01:00
parent 55d479c540
commit 3f151ba70e
6 changed files with 142 additions and 25 deletions

View File

@ -0,0 +1,44 @@
/*\
title: $:/core/modules/macros/makedatauri.js
type: application/javascript
module-type: macro
Macro to convert the content of a tiddler to a data URI
<<makedatauri text:"Text to be converted" type:"text/vnd.tiddlywiki">>
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Information about this macro
*/
exports.name = "makedatauri";
exports.params = [
{name: "text"},
{name: "type"}
];
/*
Run the macro
*/
exports.run = function(text,type) {
type = type || "text/vnd.tiddlywiki";
var typeInfo = $tw.config.contentTypeInfo[type] || $tw.config.contentTypeInfo["text/plain"],
isBase64 = typeInfo.encoding === "base64",
parts = [];
parts.push("data:");
parts.push(type);
parts.push(isBase64 ? ";base64" : "");
parts.push(",");
parts.push(isBase64 ? text : encodeURIComponent(text));
return parts.join("");
};
})();

View File

@ -0,0 +1,30 @@
/*\
title: $:/core/modules/macros/version.js
type: application/javascript
module-type: macro
Macro to return the TiddlyWiki core version number
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Information about this macro
*/
exports.name = "version";
exports.params = [];
/*
Run the macro
*/
exports.run = function() {
return $tw.version;
};
})();

View File

@ -81,8 +81,9 @@ Widget.prototype.getVariable = function(name,actualParams,defaultValue) {
while(node && !$tw.utils.hop(node.variables,name)) {
node = node.parentWidget;
}
// If we get to the root then look for a macro module
if(!node) {
return defaultValue;
return this.evaluateMacroModule(name,actualParams,defaultValue);
}
// Get the value
var value = node.variables[name].value;
@ -129,6 +130,40 @@ Widget.prototype.substituteVariableReferences = function(text) {
});
};
Widget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue) {
if($tw.utils.hop($tw.macros,name)) {
var macro = $tw.macros[name],
args = [];
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
paramInfo, paramValue;
// Step through each of the parameters in the macro definition
for(var p=0; p<macro.params.length; p++) {
// Check if we've got a macro call parameter with the same name
paramInfo = macro.params[p];
paramValue = undefined;
for(var m=0; m<actualParams.length; m++) {
if(actualParams[m].name === paramInfo.name) {
paramValue = actualParams[m].value;
}
}
// If not, use the next available anonymous macro call parameter
while(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {
nextAnonParameter++;
}
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
paramValue = actualParams[nextAnonParameter++].value;
}
// If we've still not got a value, use the default, if any
paramValue = paramValue || paramInfo["default"] || "";
// Save the parameter
args.push(paramValue);
}
return macro.run.apply(null,args)
} else {
return defaultValue;
}
};
/*
Set the value of a context variable
name: name of the variable

View File

@ -28,6 +28,7 @@ exports.startup = function() {
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
// Set up the parsers
$tw.wiki.initParsers();
// Set up the syncer object

View File

@ -282,6 +282,21 @@ describe("Widget module", function() {
expect(wrapper.innerHTML).toBe("<p>\n<div class='My something something, or other thing'>\nContent</div></p>");
});
it("should deal with built-in macros", function() {
var wiki = new $tw.Wiki();
// Add some tiddlers
wiki.addTiddlers([
{title: "TiddlerOne", text: "Jolly Old World", type: "text/vnd.tiddlywiki"}
]);
// Construct the widget node
var text = "\\define makelink(text,type)\n<a href=<<makedatauri text:\"$text$\" type:\"$type$\">>>My linky link</a>\n\\end\n\n<$macrocall $name=\"makelink\" text={{TiddlerOne}} type={{TiddlerOne!!type}}/>";
var widgetNode = createWidgetNode(parseText(text,wiki),wiki);
// Render the widget node to the DOM
var wrapper = renderWidgetNode(widgetNode);
// Test the rendering
expect(wrapper.innerHTML).toBe("<p>\n<a href='data:text/vnd.tiddlywiki,Jolly%20Old%20World'>\nMy linky link</a></p>");
});
it("should deal with the list widget", function() {
var wiki = new $tw.Wiki();
// Add some tiddlers

View File

@ -128,8 +128,7 @@ The following commands are available:</p><div class='tw-list-frame'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/LoadCommand.html'>
LoadCommand</a></span></h3><div>
<div class='tw-transclude'>
LoadCommand</a></span></h3><div class='tw-transclude'>
<p>
Load tiddlers from 2.x.x <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/TiddlyWiki.html'>
TiddlyWiki</a> files (<code>
@ -137,22 +136,20 @@ TiddlyWiki</a> files (<code>
.tiddler</code>, <code>
.tid</code>, <code>
.json</code> or other files </p><pre>
--load &lt;filepath&gt;</pre></div></div></div></div><div class='tw-list-element'>
--load &lt;filepath&gt;</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/PasswordCommand.html'>
PasswordCommand</a></span></h3><div>
<div class='tw-transclude'>
PasswordCommand</a></span></h3><div class='tw-transclude'>
<p>
Set a password for subsequent crypto operations</p><pre>
--password &lt;password&gt;</pre></div></div></div></div><div class='tw-list-element'>
--password &lt;password&gt;</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/PrintCommand.html'>
PrintCommand</a></span></h3><div>
<div class='tw-transclude'>
PrintCommand</a></span></h3><div class='tw-transclude'>
<p>
The <code>
print</code> command outputs specified information. </p><h3 class=''>
@ -167,24 +164,22 @@ Print the titles of the system tiddlers in the wiki store </p><pre>
--print system</pre><h3 class=''>
print config</h3><p>
Print the current core configuration </p><pre>
--print config</pre></div></div></div></div><div class='tw-list-element'>
--print config</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/RenderTiddlerCommand.html'>
RenderTiddlerCommand</a></span></h3><div>
<div class='tw-transclude'>
RenderTiddlerCommand</a></span></h3><div class='tw-transclude'>
<p>
Render an individual tiddler as a specified <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/ContentType.html'>
ContentType</a>, defaults to <code>
text/html</code> and save it to the specified filename </p><pre>
--rendertiddler &lt;title&gt; &lt;filename&gt; [&lt;type&gt;]</pre></div></div></div></div><div class='tw-list-element'>
--rendertiddler &lt;title&gt; &lt;filename&gt; [&lt;type&gt;]</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/RenderTiddlersCommand.html'>
RenderTiddlersCommand</a></span></h3><div>
<div class='tw-transclude'>
RenderTiddlersCommand</a></span></h3><div class='tw-transclude'>
<p>
Render a set of tiddlers matching a filter to separate files of a specified <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/ContentType.html'>
ContentType</a> (defaults to <code>
@ -192,13 +187,12 @@ text/html</code>) and extension (defaults to <code>
.html</code>).</p><pre>
--rendertiddlers &lt;filter&gt; &lt;template&gt; &lt;pathname&gt; [&lt;type&gt;] [&lt;extension&gt;]</pre><p>
For example:</p><pre>
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain</pre></div></div></div></div><div class='tw-list-element'>
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/ServerCommand.html'>
ServerCommand</a></span></h3><div>
<div class='tw-transclude'>
ServerCommand</a></span></h3><div class='tw-transclude'>
<p>
The server built in to <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/TiddlyWiki5.html'>
TiddlyWiki5</a> is very simple. Although compatible with <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/TiddlyWeb.html'>
@ -222,26 +216,24 @@ servetype</strong> - the content type with which the root tiddler should be serv
<strong>
username</strong> - the default username for signing edits</li></ul><p>
For example:</p><pre>
--server 8080 $:/core/tiddlywiki5.template.html text/plain text/html MyUserName</pre></div></div></div></div><div class='tw-list-element'>
--server 8080 $:/core/tiddlywiki5.template.html text/plain text/html MyUserName</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/VerboseCommand.html'>
VerboseCommand</a></span></h3><div>
<div class='tw-transclude'>
VerboseCommand</a></span></h3><div class='tw-transclude'>
<p>
Triggers verbose output, useful for debugging </p><pre>
--verbose</pre></div></div></div></div><div class='tw-list-element'>
--verbose</pre></div></div></div><div class='tw-list-element'>
<div class='tw-tiddler'>
<h3 class=''>
<span class='tw-view-link'>
<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/VersionCommand.html'>
VersionCommand</a></span></h3><div>
<div class='tw-transclude'>
VersionCommand</a></span></h3><div class='tw-transclude'>
<p>
Displays the version number of <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/TiddlyWiki.html'>
TiddlyWiki</a>.</p><pre>
--version</pre></div></div></div></div></div></div></div><p>
--version</pre></div></div></div></div></div></div><p>
<em>
This readme file was automatically generated by <a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves' href='http://five.tiddlywiki.com/static/TiddlyWiki5.html'>
TiddlyWiki5</a></em>