mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-19 08:14:50 +00:00
29 lines
24 KiB
Markdown
29 lines
24 KiB
Markdown
<h1>Welcome to <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></h1><div data-tiddler-target='HelloThere' data-tiddler-template='HelloThere' class='tw-tiddler-frame'>Welcome to <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a>, a reboot of <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a>, the venerable, reusable non-linear personal web notebook first released in 2004. It is a complete interactive wiki that can run from a single HTML file in the browser or as a powerful <a href='What%20is%20node.js%3F' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>node.js application</a>.<br><br><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> is currently at version 5.0.0.a2 and is under active development, which is to say that it is useful but incomplete. You can try out the prototype at <a href='http://tiddlywiki.com/tiddlywiki5' class='tw-tiddlylink tw-tiddlylink-external'>http://tiddlywiki.com/tiddlywiki5</a>, get involved in the <a href='https://github.com/Jermolene/TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-external'>development on GitHub</a> or the discussions on <a href='http://groups.google.com/group/TiddlyWikiDev' class='tw-tiddlylink tw-tiddlylink-external'>the TiddlyWikiDev Google Group</a>.<br></div><br><h1>Usage</h1><div data-tiddler-target='CommandLineInterface' data-tiddler-template='CommandLineInterface' class='tw-tiddler-frame'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> can be used on the command line to perform an extensive set of operations based on <a href='RecipeFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>RecipeFiles</a>, <a href='TiddlerFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlerFiles</a> and <a href='TiddlyWikiFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWikiFiles</a>.<br><br><h2>Usage</h2><code>
|
|
node core/boot.js <options>
|
|
</code><br>This boots the <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> kernel and loads the core plugins. The wiki store is initially empty.<br><br>The command line options are processed sequentially from left to right. Processing pauses during long operations and then resumes with the next command line option in sequence.<br><br>The following options are available:<br><table class='table'><tbody><tr class='evenRow'><td align='left'><code>--load <filepath></code></td><td align='left'>Load tiddlers from 2.x.x <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> files (<code>.html</code>), <code>.tiddler</code>, <code>.tid</code>, <code>.json</code> or other files</td></tr><tr class='oddRow'><td align='left'><code>--savetiddler <title> <filename> [<type>]</code></td><td align='left'>Save an individual tiddler as a specified MIME type, defaults to <code>text/html</code></td></tr><tr class='evenRow'><td align='left'><code>--wikitest <dir> [save]</code></td><td align='left'>Run wikification tests against the tiddlers in the given directory. Include the <code>save</code> flag to save the test result files as the new targets</td></tr><tr class='oddRow'><td align='left'><code>--dump tiddlers</code></td><td align='left'>Dump the titles of the tiddlers in the wiki store</td></tr><tr class='evenRow'><td align='left'><code>--dump tiddler <title></code></td><td align='left'>Dump the fields of an individual tiddler</td></tr><tr class='oddRow'><td align='left'><code>--dump shadows</code></td><td align='left'>Dump the titles of the shadow tiddlers in the wiki store</td></tr><tr class='evenRow'><td align='left'><code>--dump config</code></td><td align='left'>Dump the current core configuration</td></tr><tr class='oddRow'><td align='left'><code>--verbose</code></td><td align='left'>Triggers verbose output, useful for debugging</td></tr></tbody></table><h2> Examples</h2>This example loads the tiddlers from a <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> HTML file and then saves one of them in HTML:<br><code>
|
|
node tiddlywiki.js --verbose --load mywiki.html --savetiddler ReadMe ./readme.html
|
|
</code><br><h2> Notes</h2><code>--wikitest</code> looks for <code>*.tid</code> 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 <code>*.html</code> and <code>*.txt</code> files in the same directory.<br><h2>Try it out</h2>The easiest way to try out the code is to visit <a href='http://tiddlywiki.com/tiddlywiki5/' class='tw-tiddlylink tw-tiddlylink-external'>http://tiddlywiki.com/tiddlywiki5/</a><br><br>For trying it out under <code>node.js</code>, two batch files are provided:<br><br><ul><li> <code>run.sh</code> boots the kernel and loads the core modules and then outputs the <code>$tw</code> global for inspection</li><li> <code>bld.sh</code> builds the new <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> 5 HTML file (placed in the <code>tmp/tw5/</code> directory by default)</li></ul></div><br><h1>Architecture</h1><div data-tiddler-target='TiddlyWikiArchitecture' data-tiddler-template='TiddlyWikiArchitecture' class='tw-tiddler-frame'><h2> Overview</h2><br>The heart of <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> can be seen as an extensible representation transformation engine. Given the text of a tiddler and its associated MIME type, the engine can produce a rendering of the tiddler in a new MIME type. Furthermore, it can efficiently selectively update the rendering to track any changes in the tiddler or its dependents.<br><br>The most important transformations are from <code>text/x-tiddlywiki</code> wikitext into <code>text/html</code> or <code>text/plain</code> but the engine is used throughout the system for other transformations, such as converting images for display in HTML, sanitising fragments of <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a>, and processing CSS.<br><br>The key feature of wikitext is the ability to include one tiddler within another (usually referred to as <em>transclusion</em>). For example, one could have a tiddler called <em>Disclaimer</em> that contains the boilerplate of a legal disclaimer, and then include it within lots of different tiddlers with the macro call <code><<tiddler Disclaimer>></code>. This simple feature brings great power in terms of encapsulating and reusing content, and evolving a clean, usable implementation architecture to support it efficiently is a key objective of the <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> design.<br><br>It turns out that the transclusion capability combined with the selective refreshing mechanism provides a good foundation for building <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a>'s user interface itself. Consider, for example, the <a href='StoryMacro' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>StoryMacro</a> in its simplest form:<br><pre><<story story:MyStoryTiddler>>
|
|
</pre>The story macro looks for a list of tiddler titles in the tiddler <code>MyStoryTiddler</code>, and displays them in sequence. The subtle part is that subsequently, if <code>MyStoryTiddler</code> changes, the <code><<story>></code> macro is selectively re-rendered. So, to navigate to a new tiddler, code merely needs to add the name of the tiddler and a line break to the top of <code>MyStoryTiddler</code>:<br><pre>var storyTiddler = store.getTiddler("MyStoryTiddler");
|
|
store.addTiddler(new Tiddler(storyTiddler,{text: navigateTo + "\n" + storyTiddler.text}));
|
|
</pre>The mechanisms that allow all of this to work are fairly intricate. The sections below progressively build the key architectural concepts of <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> in a way that should provide a good basis for exploring the code directly.<br><h2> Tiddlers</h2>Tiddlers are an immutable dictionary of name:value pairs called fields.<br><br>The only field that is required is the <code>title</code> field, but useful tiddlers also have a <code>text</code> field, and some or all of the standard fields <code>modified</code>, <code>modifier</code>, <code>created</code>, <code>creator</code>, <code>tags</code> and <code>type</code>.<br><br>Hardcoded in the system is the knowledge that the <code>tags</code> field is a string array, and that the <code>modified</code> and <code>created</code> fields are <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> <code>Date</code> objects. All other fields are strings.<br><br>The <code>type</code> field identifies the representation of the tiddler text with a MIME type.<br><h2> WikiStore</h2>Groups of uniquely titled tiddlers are contained in <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> objects.<br><br>The <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> also manages the plugin modules used for macros, and operations like serializing, deserializing, parsing and rendering tiddlers.<br><br>Each <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> is connected to another shadow store that is used to provide default content. Under usual circumstances, when an attempt is made to retrieve a tiddler that doesn't exist in the store, the search continues into its shadow store (and so on, if the shadow store itself has a shadow store).<br><h2> WikiStore Events</h2>Clients can register event handlers with the <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> object. Event handlers can be registered to be triggered for modifications to any tiddler in the store, or with a filter to only be invoked when a particular tiddler or set of tiddlers changes.<br><br>Whenever a change is made to a tiddler, the wikistore registers a <code>nexttick</code> handler (if it hasn't already done so). The <code>nexttick</code> handler looks back at all the tiddler changes, and dispatches any matching event handlers. <br><h2> Parsing and Rendering</h2><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> parses the content of tiddlers to build an internal tree representation that is used for several purposes:<br><ul><li> Rendering a tiddler to other formats (e.g. converting wikitext to HTML)</li><li> Detecting outgoing links from a tiddler, and from them...</li><li> ...computing incoming links to a tiddler</li><li> Detecting tiddlers that are orphans with no incoming links</li><li> Detecting tiddlers that are referred to but missing</li></ul>The parse tree is built when needed, and then cached by the <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> until the tiddler changes.<br><br><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> uses multiple parsers:<br><ul><li> Wikitext (<code>text/x-tiddlywiki</code>) in <code>js/WikiTextParser.js</code></li><li> <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> (<code>text/javascript</code>) in <code>js/JavaScriptParser.js</code></li><li> Images (<code>image/png</code> and <code>image/jpg</code>) in <code>js/ImageParser.js</code></li><li> JSON (<code>application/json</code>) in <code>js/JSONParser.js</code></li></ul>Additional parsers are planned:<br><ul><li> CSS (<code>text/css</code>)</li><li> Recipe (<code>text/x-tiddlywiki-recipe</code>)</li></ul>One global instance of each parser is instantiated in <code>js/App.js</code> and registered with the main <a href='WikiStore' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiStore</a> object.<br><br>The parsers are all used the same way:<br>The parse tree object exposes the following fields:<br>The dependencies are returned as an object like this:<br><pre>{
|
|
tiddlers: {"tiddlertitle1": true, "tiddlertitle2": false},
|
|
dependentAll: false
|
|
}
|
|
</pre>The <code>tiddlers</code> field is a hashmap of the title of each tiddler that is linked or included in the current one. The value is <code>true</code> if the tiddler is a <em>'fat'</em> dependency (ie the text is included in some way) or <code>false</code> if the tiddler is a <em><code>skinny</code></em> dependency.<br><br>The <code>dependentAll</code> field is used to indicate that the tiddler contains a macro that scans the entire pool of tiddlers (for example the <code><<list>></code> macro), and is potentially dependent on any of them. The effect is that the tiddler should be rerendered whenever any other tiddler changes.<br><h2> Rendering</h2>The <code>parseTree.compile(type)</code> method returns a renderer object that contains a <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> function that generates the new representation of the original parsed text.<br><br>The renderer is invoked as follows:<br>The <code>tiddler</code> parameter to the <code>render</code> method identifies the tiddler that is acting as the context for this rendering — for example, it provides the fields displayed by the <code><<view>></code> macro. The <code>store</code> parameter is used to resolve any references to other tiddlers.<br><h2> Rerendering</h2>When rendering to the HTML/SVG DOM in the browser, <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> also allows a previous rendering to be selectively updated in response to changes in dependent tiddlers. At the moment, only the <a href='WikiTextRenderer' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiTextRenderer</a> supports rerendering.<br><br>The rerender method on the renderer is called as follows:<br><pre>var node = document.getElementById("myNode");
|
|
var renderer = parseTree.compile("text/html");
|
|
myNode.innerHTML = renderer.render(tiddler,store);
|
|
// And then, later:
|
|
renderer.rerender(node,changes,tiddler,store,renderStep);
|
|
</pre>The parameters to <code>rerender()</code> are:<br><table class='table'><tbody><tr class='evenRow'><th align='left'>Name</th><th align='left'>Description</th></tr><tr class='oddRow'><td align='left'>node</td><td align='left'>A reference to the DOM node containing the rendering to be rerendered</td></tr><tr class='evenRow'><td align='left'>changes</td><td align='left'>A hashmap of <code>{title: "created|modified|deleted"}</code> indicating which tiddlers have changed since the original rendering</td></tr><tr class='oddRow'><td align='left'>tiddler</td><td align='left'>The tiddler providing the rendering context</td></tr><tr class='evenRow'><td align='left'>store</td><td align='left'>The store to use for resolving references to other tiddlers</td></tr><tr class='oddRow'><td align='left'>renderStep</td><td align='left'>See below</td></tr></tbody></table>Currently, the only macro that supports rerendering is the <code><<story>></code> macro; all other macros are rerendered by calling the ordinary <code>render()</code> method again. The reason that the <code><<story>></code> macro goes to the trouble of having a <code>rerender()</code> method is so that it can be carefully selective about not disturbing tiddlers in the DOM that aren't affected by the change. If there were, for instance, a video playing in one of the open tiddlers it would be reset to the beginning if the tiddler were rerendered.<br><br><br></div><br><h1>Plugin Mechanism</h1><div data-tiddler-target='PluginMechanism' data-tiddler-template='PluginMechanism' class='tw-tiddler-frame'><h1>Introduction</h1><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> is based on a 500 line boot kernel that runs on node.js or in the browser, and everything<br>else is plugins.<br><br>The kernel boots just enough of the <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> environment to allow it to load tiddlers as plugins and execute them (a barebones tiddler class, a barebones wiki store class, some utilities etc.). Plugin modules are written like <code>node.js</code> modules; you can use <code>require()</code> to invoke sub components and to control load order.<br><br>There are several different types of plugins: parsers, serializers, deserializers, macros etc. It goes much further than you might expect. For example, individual tiddler fields are plugins, too: there's a plugin that knows how to handle the <code>tags</code> field, and another that knows how to handle the special behaviour of<br>the <code>modified</code> and <code>created</code> fields.<br><br>Some plugins have further sub-plugins: the wikitext parser, for instance, accepts rules as individual plugins.<br><br><h1>Plugins and Modules</h1>In <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a>, a plugin is a bundle of related tiddlers that are distributed together as a single unit. Plugins can include tiddlers which are <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> modules. <br><br>The file <code>core/boot.js</code> is a barebones <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> kernel that is just sufficient to load the core plugin modules and trigger a startup plugin module to load up the rest of the application.<br><br>The kernel includes:<br><ul><li> Eight short shared utility functions</li><li> Three methods implementing the plugin module mechanism</li><li> The <code>$tw.Tiddler</code> class (and three field definition plugins)</li><li> The <code>$tw.Wiki</code> class (and three tiddler deserialization methods)</li><li> Code for the browser to load tiddlers from the HTML DOM</li><li> Code for the server to load tiddlers from the file system</li></ul><br>Each module is an ordinary <code>node.js</code>-style module, using the <code>require()</code> function to access other modules and the <code>exports</code> global to return <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> values. The boot kernel smooths over the differences between <code>node.js</code> and the browser, allowing the same plugin modules to execute in both environments.<br><br>In the browser, <code>core/boot.js</code> is packed into a template HTML file that contains the following elements in order:<br><br><ul><li> Ordinary and shadow tiddlers, packed as HTML <code><DIV></code> elements</li><li> <code>core/bootprefix.js</code>, containing a few lines to set up the plugin environment</li><li> Plugin <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> modules, packed as HTML <code><SCRIPT></code> blocks</li><li> <code>core/boot.js</code>, containing the boot kernel</li></ul><br>On the server, <code>core/boot.js</code> is executed directly. It uses the <code>node.js</code> local file API to load plugins directly from the file system in the <code>core/modules</code> directory. The code loading is performed synchronously for brevity (and because the system is in any case inherently blocked until plugins are loaded).<br><br>The boot kernel sets up the <code>$tw</code> global variable that is used to store all the state data of the system.<br><br><h1>Core </h1><br>The 'core' is the boot kernel plus the set of plugin modules that it loads. It contains plugins of the following types:<br><ul><li> <code>tiddlerfield</code> - defines the characteristics of tiddler fields of a particular name</li><li> <code>tiddlerdeserializer</code> - methods to extract tiddlers from text representations or the DOM</li><li> <code>startup</code> - functions to be called by the kernel after booting</li><li> <code>global</code> - members of the <code>$tw</code> global</li><li> <code>config</code> - values to be merged over the <code>$tw.config</code> global</li><li> <code>utils</code> - general purpose utility functions residing in <code>$tw.utils</code></li><li> <code>tiddlermethod</code> - additional methods for the <code>$tw.Tiddler</code> class</li><li> <code>wikimethod</code> - additional methods for the <code>$tw.Wiki</code> class</li><li> <code>treeutils</code> - static utility methods for parser tree nodes </li><li> <code>treenode</code> - classes of parser tree nodes</li><li> <code>macro</code> - macro definitions</li><li> <code>editor</code> - interactive editors for different types of content</li><li> <code>parser</code> - parsers for different types of content</li><li> <code>wikitextrule</code> - individual rules for the wikitext parser</li><li> <code>command</code> - individual commands for the <code>$tw.Commander</code> class</li></ul><br><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a> makes extensive use of <a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a> inheritance:<br><ul><li> Tree nodes defined in <code>$:/core/treenodes/</code> all inherit from <code>$:/core/treenodes/node.js</code></li><li> Macros defined in <code>$:/core/macros/</code> all inherit from <code>$:/core/treenodes/macro.js</code></li></ul><br><code>tiddlywiki.plugin</code> files<br><br></div><br><h1>Planned <a href='WikiText' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiText</a> Features</h1><div data-tiddler-target='NewWikiTextFeatures' data-tiddler-template='NewWikiTextFeatures' class='tw-tiddler-frame'>It is proposed to extend the existing <a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlyWiki</a> <a href='WikiText' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiText</a> syntax with the following extensions<br><br><ol><li> Addition of <code>**bold**</code> character formatting</li><li> Addition of <code>`backtick for code`</code> character formatting</li><li> Addition of <a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a> forced line break, e.g. <code>force\\linebreak</code></li><li> Addition of <a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a> headings, e.g. <code>==Heading</code></li><li> Addition of <a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a> headings in tables, e.g. <code>|=|=table|=header|</code></li><li> Addition of white-listed HTML and SVG tags intermixed with wikitext</li><li> Addition of <a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a> pretty links, e.g. <code>[[description -> link]]</code></li><li> Addition of multiline macros, e.g.</li></ol><pre><<myMacro
|
|
param1: Parameter value
|
|
param2: value
|
|
"unnamed parameter"
|
|
param4: ((
|
|
A multiline parameter that can go on for as long as it likes
|
|
and contain linebreaks.
|
|
))
|
|
>>
|
|
</pre><ol><li> Addition of typed text blocks, e.g.</li></ol><pre> $$$.js
|
|
return "This will have syntax highlighting applied"
|
|
$$$
|
|
</pre></div><br><br><em>This <code>readme</code> file was automatically generated by <a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></em><br> |