From dad7756f65d18708fd270e6c6a2775593bff8166 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 25 Jan 2012 10:51:04 +0000 Subject: [PATCH] Getting selective refresh working A bunch of changes, and we're halfway there --- js/App.js | 15 ++---- js/Utils.js | 5 +- js/WikiStore.js | 107 ++++++++++++++++++++++------------------ js/WikiTextParseTree.js | 10 ++-- js/macros/story.js | 14 +----- readme.md | 12 ++--- 6 files changed, 77 insertions(+), 86 deletions(-) diff --git a/js/App.js b/js/App.js index 4efa219ac..0fa63c64d 100644 --- a/js/App.js +++ b/js/App.js @@ -109,24 +109,19 @@ var App = function() { navigators.install("a","StoryNavigator"); // Open the PageTemplate var div = document.createElement("div"); - div.innerHTML = this.store.renderMacro("tiddler", - "text/html", - this.store.getTiddler("PageTemplate"), - { - target: "PageTemplate" - }); + div.innerHTML = this.store.renderTiddler("text/html","PageTemplate"); document.body.appendChild(div); // Set up a timer to change the value of a tiddler var me = this; window.setInterval(function() { me.store.addTiddler(new Tiddler({ - title: "TiddlyWiki5", - text: "This is a newly created tiddler!" + title: "HelloThere", + text: "This tiddler is growing\n" + me.store.getTiddlerText("HelloThere") })); },3000); // Register an event handler to handle refreshing the DOM - this.store.addEventListener("",function() { - me.store.refreshDomNode(div,me.store.getTiddler("PageTemplate")); + this.store.addEventListener("",function(changes) { + me.store.refreshDomNode(div,changes); }); } }; diff --git a/js/Utils.js b/js/Utils.js index 39871a034..e52ccd12d 100755 --- a/js/Utils.js +++ b/js/Utils.js @@ -276,11 +276,8 @@ utils.stitchElement = function(element,attributes,options) { if(options.classNames) { output.push(" class='",options.classNames.join(" "),"'"); } - if(options.selfClosing) { - output.push(" /"); - } output.push(">"); - if(options.content) { + if("content" in options) { output.push(options.content); output.push(""); } diff --git a/js/WikiStore.js b/js/WikiStore.js index ea00ea472..2dc18b969 100755 --- a/js/WikiStore.js +++ b/js/WikiStore.js @@ -85,16 +85,6 @@ If the tiddler is already marked "deleted", */ WikiStore.prototype.touchTiddler = function(type,title) { - var existingType = this.changedTiddlers[title]; - if(existingType === undefined && type === "modified") { - type = "created"; - } - if(existingType === "modified" && type === "created") { - type = "modified"; - } - if(existingType === "deleted" && type === "created") { - type = "modified"; - } this.changedTiddlers[title] = type; this.triggerEvents(); }; @@ -149,8 +139,10 @@ WikiStore.prototype.tiddlerExists = function(title) { }; WikiStore.prototype.addTiddler = function(tiddler) { + var status = tiddler.title in this.tiddlers ? "modified" : "created"; + this.clearCache(tiddler.title); this.tiddlers[tiddler.title] = tiddler; - this.touchTiddler("modified",tiddler.title); + this.touchTiddler(status,tiddler.title); }; WikiStore.prototype.forEachTiddler = function(/* [sortField,[excludeTag,]]callback */) { @@ -279,6 +271,13 @@ WikiStore.prototype.getCacheForTiddler = function(title,cacheName,initializer) { } }; +// Clear all caches associated with a particular tiddler +WikiStore.prototype.clearCache = function(title) { + if(title in this.caches) { + delete this.caches[title]; + } +}; + WikiStore.prototype.parseText = function(type,text) { var parser = this.parsers[type]; if(!parser) { @@ -341,8 +340,10 @@ Render a tiddler to a particular MIME type. Optionally render it with a differen as the context. This option is used to render a tiddler through a template eg store.renderTiddler("text/html",templateTitle,tiddlerTitle) */ -WikiStore.prototype.renderTiddler = function(targetType,title,asTitle) { - var tiddler = this.getTiddler(title), +WikiStore.prototype.renderTiddler = function(targetType,title,asTitle,options) { + options = options || {}; + var stitcher = ((targetType === "text/html") && !options.noWrap) ? utils.stitchElement : function(a,b,c) {return c.content;}, + tiddler = this.getTiddler(title), renderer = this.compileTiddler(title,targetType), renditions = this.getCacheForTiddler(title,"renditions",function() { return {}; @@ -350,12 +351,21 @@ WikiStore.prototype.renderTiddler = function(targetType,title,asTitle) { if(tiddler) { if(asTitle) { var asTiddler = this.getTiddler(asTitle); - return renderer.render(asTiddler,this); + return stitcher("div",{ + "data-tw-render-tiddler": title, + "data-tw-render-as": asTitle + },{ + content: renderer.render(asTiddler,this) + }); } else { if(!renditions[targetType]) { renditions[targetType] = renderer.render(tiddler,this); } - return renditions[targetType]; + return stitcher("div",{ + "data-tw-render-tiddler": title + },{ + content: renditions[targetType] + }); } } return null; @@ -367,48 +377,47 @@ Executes a macro and returns the result WikiStore.prototype.renderMacro = function(macroName,targetType,tiddler,params,content) { var macro = this.macros[macroName]; if(macro) { - var wrapperTag = macro.wrapperTag || "div"; - return utils.stitchElement(wrapperTag,{ - "data-tw-macro": macroName, - "data-tw-render-tiddler": tiddler.title - },{ - content: macro.handler(targetType,tiddler,this,params,content) - }); + return macro.handler(targetType,tiddler,this,params,content); } else { return null; } }; /* -Refresh a DOM node so that it reflects the current state of the store - -The refresh processing is: - -1. If the node is a link, check the link classes correctly reflect the status of the target tiddler. Recursively process any children. Exit -2. If the node is a macro, and dependencies have changed, re-render the macro into the DOM node. Exit -3. If the node is a macro and the dependencies haven't changed, recursively process each child node of the macro. Exit - -Arguments - node - the DOM node to be processed - tiddler - the tiddler providing context for the rendering - +Refresh a DOM node and it's children so that it reflects the current state of the store + node: reference to the DOM node to be refreshed + changes: hashmap of {title: "created|modified|deleted"} */ -WikiStore.prototype.refreshDomNode = function(node,tiddler) { - // Process macros - var macro = node.getAttribute && node.getAttribute("data-tw-macro"), - params = node.getAttribute && node.getAttribute("data-tw-params"); - if(macro && params) { - } - // Process children - if(node.hasChildNodes()) { - this.refreshDomChildren(node,tiddler); - } -}; +WikiStore.prototype.refreshDomNode = function(node,changes) { + var me = this, + refreshChildNodes = function(node) { + if(node.hasChildNodes()) { + for(var c=0; c"); + pushString(output,utils.stitchElement(wrapperTag,{ + "data-tw-macro": name, + "data-tw-render-step": renderStepIndex + })); } output.push({ type: "FunctionCall", @@ -343,7 +343,6 @@ WikiTextParseTree.prototype.toString = function(type) { if(node.children) { utils.renderObject(output,type,node.children,customTemplates); } - output.push(""); return true; } return false; @@ -377,6 +376,7 @@ WikiTextParseTree.prototype.toString = function(type) { classNames: ["splitLabelRight"] })); } + output.push(""); } if(node.children) { utils.renderObject(output,type,node.children,customTemplates); diff --git a/js/macros/story.js b/js/macros/story.js index c29e129c2..d5d3f9b31 100644 --- a/js/macros/story.js +++ b/js/macros/story.js @@ -24,19 +24,9 @@ exports.macro = { var title = tiddlers[t].trim(); if(title !== "") { if(params.template) { - output.push(store.renderMacro("tiddler", - type, - store.getTiddler(title), - { - target: params.template - })); + output.push(store.renderTiddler(type,params.template,title)); } else { - output.push(store.renderMacro("tiddler", - type, - store.getTiddler(title), - { - target: title - })); + output.push(store.renderTiddler(type,title)); } } } diff --git a/readme.md b/readme.md index c1f3e24f7..09b2838ac 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,12 @@ -

Welcome to TiddlyWiki5

Welcome to TiddlyWiki5, an interactive wiki written in JavaScript to run in the browser or under node.js. It is a reboot of TiddlyWiki (http://www.tiddlywiki.com/), the now venerable, reusable non-linear personal web notebook first released in 2004.

TiddlyWiki is based on the idea of making information more useful by modelling it in the smallest meaningful semantic units, referred to as "tiddlers". Structure comes from links, tags, and stories (sequences of tiddlers). Tiddlers use a wikitext notation that concisely represents a wide range of text formatting and hypertext features.

TiddlyWiki has earned an enduring place as a tool that people love using for its rich, interactive interface to manipulate complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors. Because people can use it without needing any complicated server infrastructure, and because it is open source, it has bought unprecedented freedom to people to keep their precious information under their own control. TiddlyWiki was originally created by JeremyRuston and is now a thriving open source project with a busy Community of independent developers.

Usage

TiddlyWiki5 can be used on the command line to perform an extensive set of operations based on RecipeFiles, TiddlerFiles and TiddlyWikiFiles.

Usage:
+

Welcome to TiddlyWiki5

Welcome to TiddlyWiki5, an interactive wiki written in JavaScript to run in the browser or under node.js. It is a reboot of TiddlyWiki (http://www.tiddlywiki.com/), the now venerable, reusable non-linear personal web notebook first released in 2004.

TiddlyWiki is based on the idea of making information more useful by modelling it in the smallest meaningful semantic units, referred to as "tiddlers". Structure comes from links, tags, and stories (sequences of tiddlers). Tiddlers use a wikitext notation that concisely represents a wide range of text formatting and hypertext features.

TiddlyWiki has earned an enduring place as a tool that people love using for its rich, interactive interface to manipulate complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors. Because people can use it without needing any complicated server infrastructure, and because it is open source, it has bought unprecedented freedom to people to keep their precious information under their own control. TiddlyWiki was originally created by JeremyRuston and is now a thriving open source project with a busy Community of independent developers.

Usage

TiddlyWiki5 can be used on the command line to perform an extensive set of operations based on RecipeFiles, TiddlerFiles and TiddlyWikiFiles.

Usage:
node tiddlywiki.js <options> -
The command line options are processed sequentially from left to right. Processing pauses during long operations, like loading a recipe file and all the subrecipes and tiddlers that it references. The following options are available:
--recipe <filepath>Loads a specfied .recipe file
--load <filepath>Load additional tiddlers from 2.x.x TiddlyWiki files (.html), .tiddler, .tid, .json or other files
--savewiki <dirpath>Saves all the loaded tiddlers as a single file TiddlyWiki called index.html and an RSS feed called index.xml in a new directory of the specified name
--savetiddler <title> <filename> [<type>]Save an individual tiddler as a specified MIME type, defaults to text/html
--savetiddlers <outdir>Saves all the loaded tiddlers as .tid files in the specified directory
--servewiki <port>Serve the cooked TiddlyWiki over HTTP at /
--servetiddlers <port>Serve individual tiddlers over HTTP at /tiddlertitle
--wikitest <dir>Run wikification tests against the tiddlers in the given directory
--dumpstoreDump the TiddlyWiki store in JSON format
--dumprecipeDump the current recipe in JSON format
--verboseverbose output, useful for debugging

Examples

This example loads the tiddlers from a TiddlyWiki HTML file and makes them available over HTTP:
+
The command line options are processed sequentially from left to right. Processing pauses during long operations, like loading a recipe file and all the subrecipes and tiddlers that it references. The following options are available:
--recipe <filepath>Loads a specfied .recipe file
--load <filepath>Load additional tiddlers from 2.x.x TiddlyWiki files (.html), .tiddler, .tid, .json or other files
--savewiki <dirpath>Saves all the loaded tiddlers as a single file TiddlyWiki called index.html and an RSS feed called index.xml in a new directory of the specified name
--savetiddler <title> <filename> [<type>]Save an individual tiddler as a specified MIME type, defaults to text/html
--savetiddlers <outdir>Saves all the loaded tiddlers as .tid files in the specified directory
--servewiki <port>Serve the cooked TiddlyWiki over HTTP at /
--servetiddlers <port>Serve individual tiddlers over HTTP at /tiddlertitle
--wikitest <dir>Run wikification tests against the tiddlers in the given directory
--dumpstoreDump the TiddlyWiki store in JSON format
--dumprecipeDump the current recipe in JSON format
--verboseverbose output, useful for debugging

Examples

This example loads the tiddlers from a TiddlyWiki HTML file and makes them available over HTTP:
node tiddlywiki.js --load mywiki.html --servewiki 127.0.0.1:8000 -
This example cooks a TiddlyWiki from a recipe:
+
This example cooks a TiddlyWiki from a recipe:
node tiddlywiki.js --recipe tiddlywiki.com/index.recipe --savewiki tmp/ -
This example ginsus a TiddlyWiki into its constituent tiddlers:
+
This example ginsus a TiddlyWiki into its constituent tiddlers:
node tiddlywiki.js --load mywiki.html --savetiddlers tmp/tiddlers -

Notes

--servewiki and --servertiddlers are for different purposes and should not be used together. The former is for TiddlyWiki core developers who want to be able to edit the TiddlyWiki source files in a text editor and view the results in the browser by clicking refresh; it is slow because it reloads all the TiddlyWiki JavaScript files each time the page is loaded. The latter is for experimenting with the new wikification engine.

--wikitest looks for *.tid files in the specified folder. It then wikifies the tiddlers to both "text/plain" and "text/html" format and checks the results against the content of the *.html and *.txt files in the same directory.

Testing

test.sh contains a simple test script that cooks the main tiddlywiki.com recipe and compares it with the results of the old build process (ie, running cook.rb and then opening the file in a browser and performing a 'save changes' operation). It also runs a series of wikifications tests that work off the data in test/wikitests/.

Planned WikiText Features

It is proposed to extend the existing TiddlyWiki wikitext syntax with the following extensions

  1. Addition of **bold** character formatting
  2. Addition of `backtick for code` character formatting
  3. Addition of WikiCreole-style forced line break, e.g. force\\linebreak
  4. Addition of WikiCreole-style headings, e.g. ==Heading
  5. Addition of WikiCreole-style headings in tables, e.g. |=|=table|=header|
  6. Addition of white-listed HTML tags intermixed with wikitext
  7. Addition of WikiCreole-style pretty links, e.g. [[description -> link]]
  8. Addition of multiline macros, e.g.
<<myMacro
+

Notes

--servewiki and --servertiddlers are for different purposes and should not be used together. The former is for TiddlyWiki core developers who want to be able to edit the TiddlyWiki source files in a text editor and view the results in the browser by clicking refresh; it is slow because it reloads all the TiddlyWiki JavaScript files each time the page is loaded. The latter is for experimenting with the new wikification engine.

--wikitest looks for *.tid files in the specified folder. It then wikifies the tiddlers to both "text/plain" and "text/html" format and checks the results against the content of the *.html and *.txt files in the same directory.

Testing

test.sh contains a simple test script that cooks the main tiddlywiki.com recipe and compares it with the results of the old build process (ie, running cook.rb and then opening the file in a browser and performing a 'save changes' operation). It also runs a series of wikifications tests that work off the data in test/wikitests/.

Planned WikiText Features

It is proposed to extend the existing TiddlyWiki wikitext syntax with the following extensions

  1. Addition of **bold** character formatting
  2. Addition of `backtick for code` character formatting
  3. Addition of WikiCreole-style forced line break, e.g. force\\linebreak
  4. Addition of WikiCreole-style headings, e.g. ==Heading
  5. Addition of WikiCreole-style headings in tables, e.g. |=|=table|=header|
  6. Addition of white-listed HTML tags intermixed with wikitext
  7. Addition of WikiCreole-style pretty links, e.g. [[description -> link]]
  8. Addition of multiline macros, e.g.
<<myMacro
 param1: Parameter value
 param2: value
 "unnamed parameter"
@@ -15,4 +15,4 @@ A multiline parameter that can go on for as long as it likes
 and contain linebreaks.
 ))
 >>
-


This readme file was automatically generated by TiddlyWiki5
\ No newline at end of file +


This readme file was automatically generated by TiddlyWiki5
\ No newline at end of file