diff --git a/copyright.txt b/copyright.txt new file mode 100644 index 000000000..ead03be52 --- /dev/null +++ b/copyright.txt @@ -0,0 +1,29 @@ +TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com) + +Copyright (c) Jeremy Ruston 2004-2007 +Copyright (c) UnaMesa Association 2007-2011 + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. + +Neither the name of the UnaMesa Association nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/js/ArgParser.js b/js/ArgParser.js index b1d354359..deb1be5dd 100755 --- a/js/ArgParser.js +++ b/js/ArgParser.js @@ -1,23 +1,23 @@ -(function(){ +/*\ +title: js/ArgParser.js -/* - Parse a space-separated string of name:value parameters. Values can be quoted with single quotes, double quotes, - double square brackets, or double curly braces. +Parse a space-separated string of name:value parameters. Values can be quoted with single quotes, double quotes, double square brackets, or double curly braces. - The parameters are returned in a structure that can be referenced like this: +The parameters are returned in a structure that can be referenced like this: - (return).byName["name"][0] - First occurance of parameter with a given name - (return).byPos[0].n - Name of parameter in first position - (return).byPos[0].v - Value of parameter in first position + (return).byName["name"][0] - First occurance of parameter with a given name + (return).byPos[0].n - Name of parameter in first position + (return).byPos[0].v - Value of parameter in first position Options and their defaults are: - defaultName: null, - defaultValue: null, - noNames: false, - cascadeDefaults: false + defaultName: null, + defaultValue: null, + noNames: false, + cascadeDefaults: false -*/ +\*/ +(function(){ /*jslint node: true */ "use strict"; diff --git a/js/FileRetriever.js b/js/FileRetriever.js index ce4d7570c..a19a24f1a 100644 --- a/js/FileRetriever.js +++ b/js/FileRetriever.js @@ -1,8 +1,10 @@ -(function(){ +/*\ +title: js/FileRetriever.js -/* FileRetriever can asynchronously retrieve files from HTTP URLs or the local file system -*/ + +\*/ +(function(){ /*jslint node: true */ "use strict"; diff --git a/js/Main.js b/js/Main.js new file mode 100644 index 000000000..fd1da8da9 --- /dev/null +++ b/js/Main.js @@ -0,0 +1,82 @@ +/*\ +title: js/Main.js + +This is the main() function in the browser + +\*/ +(function(){ + +/*jslint node: true */ +"use strict"; + +var WikiStore = require("./WikiStore.js").WikiStore, + Tiddler = require("./Tiddler.js").Tiddler, + tiddlerInput = require("./TiddlerInput.js"), + tiddlerOutput = require("./TiddlerOutput.js"), + TextProcessors = require("./TextProcessors.js").TextProcessors, + WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor, + TiddlerConverters = require("./TiddlerConverters.js").TiddlerConverters; + +var textProcessors = new TextProcessors(), + tiddlerConverters = new TiddlerConverters(), + store = new WikiStore({ + textProcessors: textProcessors + }), + t; + +// Register the wikitext processor +textProcessors.registerTextProcessor("text/x-tiddlywiki",new WikiTextProcessor({ + textProcessors: textProcessors +})); + +// Register the standard tiddler serializers and deserializers +tiddlerInput.register(tiddlerConverters); +tiddlerOutput.register(tiddlerConverters); + +// Add the shadow tiddlers that are built into TiddlyWiki +var shadowShadowStore = new WikiStore({ + textProcessors: textProcessors, + shadowStore: null + }), + shadowShadows = [ + {title: "StyleSheet", text: ""}, + {title: "MarkupPreHead", text: ""}, + {title: "MarkupPostHead", text: ""}, + {title: "MarkupPreBody", text: ""}, + {title: "MarkupPostBody", text: ""}, + {title: "TabTimeline", text: "<>"}, + {title: "TabAll", text: "<>"}, + {title: "TabTags", text: "<>"}, + {title: "TabMoreMissing", text: "<>"}, + {title: "TabMoreOrphans", text: "<>"}, + {title: "TabMoreShadowed", text: "<>"}, + {title: "AdvancedOptions", text: "<>"}, + {title: "PluginManager", text: "<>"}, + {title: "SystemSettings", text: ""}, + {title: "ToolbarCommands", text: "|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|\n|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|"}, + {title: "WindowTitle", text: "<> - <>"}, + {title: "DefaultTiddlers", text: "[[GettingStarted]]"}, + {title: "MainMenu", text: "[[GettingStarted]]"}, + {title: "SiteTitle", text: "My TiddlyWiki"}, + {title: "SiteSubtitle", text: "a reusable non-linear personal web notebook"}, + {title: "SiteUrl", text: ""}, + {title: "SideBarOptions", text: '<><><><><><><>'}, + {title: "SideBarTabs", text: '<>'}, + {title: "TabMore", text: '<>'} + ]; +store.shadows.shadows = shadowShadowStore; +for(t=0; t").html(store.renderTiddler("text/html","HelloThere")).appendTo("body"); + +})(); \ No newline at end of file diff --git a/js/Recipe.js b/js/Recipe.js index 9ce8020d9..c69cd961d 100755 --- a/js/Recipe.js +++ b/js/Recipe.js @@ -1,6 +1,7 @@ -(function(){ +/*\ +title: js/Recipe.js -/* +FileRetriever can asynchronously retrieve files from HTTP URLs or the local file system Recipe processing is in four parts: @@ -32,7 +33,8 @@ At this point tiddlers are placed in the store so that they can be referenced by 4) Finally, the template is processed by replacing the markers with the text of the associated tiddlers -*/ +\*/ +(function(){ /*jslint node: true */ "use strict"; @@ -224,7 +226,8 @@ Recipe.tiddlerOutputMapper = { jsdeprecated: "javascript", jquery: "javascript", shadow: "shadow", - title: "title" + title: "title", + jsmodule: "jsmodule" }; Recipe.tiddlerOutputter = { @@ -269,6 +272,16 @@ Recipe.tiddlerOutputter = { }, title: function(out,tiddlers) { out.push(this.store.renderTiddler("text/plain","WindowTitle")); + }, + jsmodule: function(out,tiddlers) { + // JavaScript modules are output as a special script tag + for(var t=0; t"); + out.push(tid.fields.text); + out.push(""); + } } }; diff --git a/js/TextProcessors.js b/js/TextProcessors.js index a8b04abc4..11f81bf97 100644 --- a/js/TextProcessors.js +++ b/js/TextProcessors.js @@ -1,3 +1,7 @@ +/*\ +title: js/TextProcessors.js + +\*/ (function(){ /*jslint node: true */ diff --git a/js/Tiddler.js b/js/Tiddler.js index f36ef046a..627378bfc 100755 --- a/js/Tiddler.js +++ b/js/Tiddler.js @@ -1,6 +1,5 @@ -(function(){ - -/* +/*\ +title: js/Tiddler.js Tiddlers are an immutable dictionary of name:value pairs called fields. Values can be a string, an array of strings, or a date. The only field that is required is the `title` field, but useful tiddlers also @@ -21,7 +20,8 @@ The hashmap(s) can specify the "modified" and "created" fields as strings in YY format or as JavaScript date objects. The "tags" field can be given as a JavaScript array of strings or as a TiddlyWiki quoted string (eg, "one [[two three]]"). -*/ +\*/ +(function(){ /*jslint node: true */ "use strict"; @@ -49,6 +49,21 @@ var Tiddler = function(/* tiddler,fields */) { } }; +Tiddler.standardFields = { + title: { type: "string"}, + modifier: { type: "string"}, + modified: { type: "date"}, + creator: { type: "string"}, + created: { type: "date"}, + tags: { type: "tags"}, + type: { type: "string"}, + text: { type: "string"} +} + +Tiddler.isStandardField = function(name) { + return name in Tiddler.standardFields; +}; + Tiddler.prototype.hasTag = function(tag) { if(this.tags) { for(var t=0; t= 0; i--) { + if(attrs[i].specified) { + var value = attrs[i].value, + name = attrs[i].name; + if(!Tiddler.isStandardField(name)) { + value = utils.unescapeLineBreaks(value); + } + tiddler[name] = value; + } + } + return tiddler; + } else { + return null; + } + }, + t,tiddlers = []; + for(t = 0; t < node.childNodes.length; t++) { + var tiddler = extractTiddler(node.childNodes[t]); + if(tiddler) { + tiddlers.push(tiddler); + } + } + return tiddlers; +}; + tiddlerInput.register = function(tiddlerConverters) { tiddlerConverters.registerDeserializer(".txt","text/plain",inputTiddlerPlain); + tiddlerConverters.registerDeserializer(".js","application/javascript",inputTiddlerJavaScript); tiddlerConverters.registerDeserializer(".tiddler","application/x-tiddler-html-div",inputTiddlerDiv); tiddlerConverters.registerDeserializer(".tid","application/x-tiddler",inputTiddler); tiddlerConverters.registerDeserializer(".json","application/json",inputTiddlerJSON); tiddlerConverters.registerDeserializer(".tiddlywiki","application/x-tiddlywiki",inputTiddlyWiki); + tiddlerConverters.registerDeserializer("(DOM)","(DOM)",inputTiddlerDOM); }; })(); diff --git a/js/TiddlerOutput.js b/js/TiddlerOutput.js index aae93c74e..1b0a5d11e 100755 --- a/js/TiddlerOutput.js +++ b/js/TiddlerOutput.js @@ -1,8 +1,10 @@ -(function(){ +/*\ +title: js/TiddlerOutput.js -/* Functions concerned with parsing representations of tiddlers -*/ + +\*/ +(function(){ /*jslint node: true */ "use strict"; diff --git a/js/Utils.js b/js/Utils.js index b68407043..f89762ba1 100755 --- a/js/Utils.js +++ b/js/Utils.js @@ -1,17 +1,18 @@ -(function(){ +/*\ +title: js/Utils.js -/* Various static utility functions. This file is a bit of a dumping ground; the expectation is that most of these functions will be refactored. -*/ + +\*/ +(function(){ /*jslint node: true */ "use strict"; var utils = exports; - utils.deepCopy = function(v) { var r,t; if(v instanceof Array) { @@ -30,7 +31,6 @@ utils.deepCopy = function(v) { return r; }; - // Pad a string to a certain length with zeros utils.zeroPad = function(n,d) { @@ -186,4 +186,8 @@ utils.entityDecode = function(s) { utils.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 }; +utils.unescapeLineBreaks = function(s) { + return s.replace(/\\n/mg,"\n").replace(/\\b/mg," ").replace(/\\s/mg,"\\").replace(/\r/mg,""); +}; + })(); diff --git a/js/WikiStore.js b/js/WikiStore.js index 3ef529fd9..b7da6a086 100755 --- a/js/WikiStore.js +++ b/js/WikiStore.js @@ -1,3 +1,7 @@ +/*\ +title: js/WikiStore.js + +\*/ (function(){ /*jslint node: true */ diff --git a/js/WikiTextParser.js b/js/WikiTextParser.js index 97158c0ba..9640c041e 100644 --- a/js/WikiTextParser.js +++ b/js/WikiTextParser.js @@ -1,8 +1,5 @@ -(function(){ - -/* - -WikiTextParser.js +/*\ +title: js/WikiTextParser.js Parses a block of tiddlywiki-format wiki text into a parse tree object. @@ -23,7 +20,8 @@ Text nodes are: {type: "text", value: "string of text node"} -*/ +\*/ +(function(){ /*jslint node: true */ "use strict"; diff --git a/js/WikiTextProcessor.js b/js/WikiTextProcessor.js index 7f209415d..f43a6a2a2 100644 --- a/js/WikiTextProcessor.js +++ b/js/WikiTextProcessor.js @@ -1,3 +1,7 @@ +/*\ +title: js/WikiTextProcessor.js + +\*/ (function(){ /*jslint node: true */ @@ -8,7 +12,11 @@ var WikiTextRules = require("./WikiTextRules.js"), /* Creates a new instance of the wiki text processor with the specified options. The -options are a hashmap of optional members as follows: +options are a hashmap of mandatory members as follows: + + textProcessors: The TextProcessors object to use to parse any cascaded content (eg transclusion) + +Planned: enableRules: An array of names of wiki text rules to enable. If not specified, all rules are available extraRules: An array of additional rule handlers to add @@ -16,6 +24,7 @@ options are a hashmap of optional members as follows: extraMacros: An array of additional macro handlers to add */ var WikiTextProcessor = function(options) { + this.textProcessors = options.textProcessors; this.rules = WikiTextRules.rules; var pattern = []; for(var n=0; n", + executed: true + }, + module2: { + text: "" + } + } +*/ +var modules = {}; + +/* +The built in modules +*/ +var builtInModules = { + util: { + + }, + path: { + + }, + fs: { + + }, + url: { + + }, + http: { + + }, + https: { + + } +}; + +/* +Given the absolute path of a srcModule, and a relative reference to a dstModule, return the fully resolved module name +*/ +function resolveModuleName(srcModule,dstModule) { + var src = srcModule.split("/"), + dst = dstModule.split("/"), + c; + // If the destination starts with / or ./ then it's a reference to an ordinary module + if(dstModule.substr(0,1) === "/" || dstModule.substr(0,2) === "./" ) { + // Remove the filename part of the src path + src.splice(src.length-1,1); + // Process the destination path bit by bit + while(dst.length > 0) { + c = dst.shift(); + switch(c) { + case ".": // Ignore dots + break; + case "..": // Slice off the last src directory for a double dot + src.splice(src.length-1,1); + break; + default: // Copy everything else across + src.push(c); + break; + } + } + return src.join("/"); + } else { + // If there was no / or ./ then it's a built in module + return dstModule; + } +} + +function executeModule(name) { + var require = function(filepath) { + return executeModule(resolveModuleName(name,filepath)); + }, + exports = {}, + module = modules[name]; + if(!module) { + throw new Error("Cannot find module named '" + name + "'"); + } + if(module.executed) { + return module.exports; + } else { + // This way of executing modules isn't perfect. Everything that is in scope here is available to the + // scripts, so this mechanism should only be used for trusted code + var script = "(function (require,exports){" + modules[name].text + "})(require,exports);" + eval(script); + module.executed = true; + module.exports = exports; + return exports; + } +} + +function findModules(childNodes) { + // Iterate using the DOM directly; jQuery methods seem to bypass comment nodes + childNodes = childNodes || document.childNodes; + for(var t=0; t 0) { + findModules(childNodes[t].childNodes); + } + } +} + +$(function() { + // Start with the embedded JavaScript modules + for(var t in builtInModules) { + modules[t] = builtInModules; + } + // Add any modules packed into script tags in the page + findModules(); + // Execute the main module + executeModule("js/Main.js"); +}) + +})(); \ No newline at end of file diff --git a/tiddlywiki5/tiddlywiki5.recipe b/tiddlywiki5/tiddlywiki5.recipe new file mode 100644 index 000000000..aefcc1f4a --- /dev/null +++ b/tiddlywiki5/tiddlywiki5.recipe @@ -0,0 +1,24 @@ +template: tiddlywiki5.template.html +copyright: ../copyright.txt + +jslib: ../test/tiddlywiki.2.6.5/source/tiddlywiki/jquery/jquery.js + +jsmodule: ../js/ArgParser.js +jsmodule: ../js/FileRetriever.js +jsmodule: ../js/Utils.js +jsmodule: ../js/Tiddler.js +jsmodule: ../js/TiddlerConverters.js +jsmodule: ../js/TiddlerInput.js +jsmodule: ../js/TiddlerOutput.js +jsmodule: ../js/WikiStore.js +jsmodule: ../js/TextProcessors.js +jsmodule: ../js/WikiTextProcessor.js +jsmodule: ../js/WikiTextParser.js +jsmodule: ../js/WikiTextRules.js +jsmodule: ../js/WikiTextRenderer.js +jsmodule: ../js/Main.js + +jsboot: BootLoader.js + +recipe: ../test/tiddlywiki.2.6.5/source/tiddlywiki.com/tiddlywiki-com-ref/split.recipe +recipe: ../test/tiddlywiki.2.6.5/source/tiddlywiki.com/tiddlywiki-com/split.recipe diff --git a/tiddlywiki5/tiddlywiki5.template.html b/tiddlywiki5/tiddlywiki5.template.html new file mode 100644 index 000000000..895aef7c9 --- /dev/null +++ b/tiddlywiki5/tiddlywiki5.template.html @@ -0,0 +1,32 @@ + + + + + +<!--@@title@@--> + + + + + + + + + + + + diff --git a/tw5.sh b/tw5.sh new file mode 100755 index 000000000..7b3f3ad12 --- /dev/null +++ b/tw5.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# build TiddlyWiki5 + +# create a temporary directory if it doesn't already exist +mkdir -p tmp + +mkdir -p tmp/tw5 +node tiddlywiki.js --recipe $PWD/tiddlywiki5/tiddlywiki5.recipe --savewiki tmp/tw5 || exit 1 + +# open the result +open -a /Applications/Google\ Chrome.app tmp/tw5/index.html diff --git a/wikitest.js b/wikitest.js index 834810c8c..0e3ed4f82 100644 --- a/wikitest.js +++ b/wikitest.js @@ -35,7 +35,9 @@ var testdirectory = process.argv[2], titles = [], f,t,extname,basename; -textProcessors.registerTextProcessor("text/x-tiddlywiki",new WikiTextProcessor({})); +textProcessors.registerTextProcessor("text/x-tiddlywiki",new WikiTextProcessor({ + textProcessors: textProcessors +})); tiddlerInput.register(tiddlerConverters); for(f=0; f