This page is part of a static HTML representation of the TiddlyWiki at http://tiddlywiki.com/dev/

12th January 2016 at 5:50pm

Not all browsers support the latest features of ES2015. The Babel project offers a polyfill that can be included into your TiddlyWiki so those features can be available to your plugins. To do this you will need a copy of the polyfill source.

You can obtain the source either through or downloaded/saved. See the Babel Polyfill documentation for specific information on installing it.

In your TiddlyWiki editions folder make sure you have a plugins/babel-polyfill folder. Then create the plugins/babel-polyfill/plugin.info file with the following in it:

{
  "title": "$:/plugins/babel/babel-polyfill",
  "description": "Babel Polyfills for ES2015 support",
  "author": "Your Name Here",
  "core-version": ">=5.0.0"
}

Create the folder plugins/babel-polyfill/files folder. Then create the plugins/babel-polyfill/files/tiddlywiki.files file with the following in it:

{
  "tiddlers": [
    {
      "file": "polyfill.min.js",
      "fields": {
        "title": "$:/plugins/babel/babel-polyfill/polyfill.min.js",
        "type": "application/javascript",
        "module-type": "library",
        "global-module": "true"
      }
    }
  ]
}

Now copy the polyfill.min.js you downloaded/saved.

Lastly you need a initializer so create the plugins/babel-polyfill/plugin.js file with the following in it:

/*\
title: $:/plugins/babel/babel-polyfill/plugin.js
type: application/javascript
module-type: startup

Load the babel-polyfill library on startup

\*/

exports.startup = function() {
  $tw.modules.execute('$:/plugins/babel/babel-polyfill/polyfill.min.js');
}

Now all the runtime ES2015 features are available like using Promise in your plugin code.

See Using ES2016 for Writing Plugins on how to use the ES2015 syntax for your plugin code.

apptree.svg

8th July 2014 at 4:54pm

arch.svg

17th July 2014 at 8:41pm

BootMechanism

2nd May 2014 at 3:29pm
Mechanisms

Introduction

At its heart, TiddlyWiki5 is a relatively small boot kernel that runs either under Node.js or in the browser with all other functionality added via dynamically loaded modules.

The kernel boots just enough of the TiddlyWiki environment to allow it to load and execute module tiddlers. The module system is compatible with CommonJS and Node.js.

There are many different types of module: parsers, deserializers, widgets etc. It goes much further than you might expect. For example, individual tiddler fields are modules, too: there's a module that knows how to handle the tags field, and another that knows how to handle the special behaviour of the modified and created fields. Some plugin modules have further sub-plugins: the wikitext parser, for instance, accepts parsing rules as individual plugin modules.

Plugins

In TiddlyWiki5, Plugins are bundles of tiddlers that are distributed and managed as one; Modules are JavaScript tiddlers with a module type identifying when and how they should be executed.

The tiddler $:/boot/boot.js is a barebones TiddlyWiki kernel that is just sufficient to load the core plugin modules and trigger a startup module to load up the rest of the application.

The boot kernel includes:

  • Several short shared utility functions
  • A handful of methods implementing the module mechanism
  • The $tw.Tiddler class (and field definition plugins)
  • The $tw.Wiki class (and tiddler deserialization methods)
  • Code for the browser to load tiddlers from the HTML DOM
  • Code for the server to load tiddlers from the file system

Each module is an ordinary CommonJS module, using the require() function to access other modules and the exports global to return JavaScript values. The boot kernel smooths over the differences between Node.js and the browser, allowing the same plugin modules to execute in both environments.

In the browser, core/boot.js is packed into a template HTML file that contains the following elements in order:

  • Ordinary and system tiddlers, packed as HTML <DIV> elements
  • core/bootprefix.js, containing a few lines to set up the plugin environment
  • Optional JavaScript modules, packed as HTML <SCRIPT> blocks
  • core/boot.js, containing the boot kernel

On the server, core/boot.js is executed directly. It uses the Node.js local file API to load plugins directly from the file system in the core/modules directory. The code loading is performed synchronously for brevity (and because the system is in any case inherently blocked until plugins are loaded).

The boot process sets up the $tw global variable that is used to store all the state data of the system.

At the end of the boot process the StartupMechanism schedules the execution of startup modules to bring up the rest of TiddlyWiki.

Caching

17th July 2014 at 7:09pm
doc new

The core plug-in adds two caches to the wiki store. A global cache and a cache for each tiddler. While the global cache is cleared whenever any tiddler changes, the tiddler cache is only cleared when the associated tiddler changes. The idea of the tiddler cache is, that sometimes we want to calculate information from a tiddler but don't want to recalculate every time we need this information. Imagine a tiddler which contains links to other tiddlers and at one point we want to have a list of the linked tiddlers (LinksFilter). With the tiddler cache we can parse the WikiText, extract the linked tiddlers and put this list in the cache. Until the tiddler is changed, the cache can be used to access this information in the next requests.

The same idea holds for the global cache. For example when a filter string is parsed and a list of matching tiddlers is constructed. This list can be put in the global cache for later reuse until something changes in the store.

Like the Event Mechanism, the cache needs hook functions in the microkernel. The microkernel calls clearGlobalCache() and clearCache(tiddlertitle) when a tiddler changes. The core's cache mechanism overwrites this functions. The functions providing the cache system are added via the wikimethod module type.

Conclusion

17th July 2014 at 10:18pm
doc section

TiddlyWiki consists in its heart only of a basic microkernel providing bare tiddlerstore and module system. It is written in JavaScript and suited to run in a browser or as node.js application. The core plug-in extends the microkernel with powerful functions from a central event system to a sophisticated widget system transforming WikiText to dynamic HTML. Because of it's microkernel architecture the application is highly customizable. The plug-in system not only allows to add new modules but also to override existing modules. Most of the components don't refer directly to modules but load them by type, allowing developers to inject additional modules including new saver implementations, widgets or even rules for the WikiText parser. The user interface of TiddlyWiki is written in WikiText and can be customized with the same language, a user normally uses when just writing wiki entries.

A drawback of the core plug-in is it's high complexity. While the microkernel provides just the bare some bare functions and structures, the core plug-in adds a whole bunch of components at once. It can be challenging to decompose the core architecture and understand the connections between the components. This documentation could only cover the most important parts. This gives a developer the choice of building a whole new application on the microkernel or building the application on the core plug-in, including all modules and UI tiddlers.

In conclusion, TiddlyWiki is a interesting piece of software. The focus on tiddlers, the functionality provided in the core and the fact that the core comes with a full blown wiki application puts TiddlyWiki into a personal information management domain, especially when using TiddlyWiki as a single file application storing code and data in a single HTML file. But the highly customizable nature makes TiddlyWiki perfect for this exact domain. A casual user can organize information with tags and metadata and customize the UI to a grade, that he is able to implement and test his own workflows just by using WikiText. JavaScript developers can add whole new features and create completely new single page applications by building on the microkernel or customizing the core plug-in.

Contributing to the TiddlyWiki Core

7th November 2014 at 9:32pm

The TiddlyWiki core is the container for all the generic features of TiddlyWiki that are of universal utility. Concretely, it comprises the tiddlers in the $:/core plugin.

Core Contribution Requirements

There are requirements that must be met for any contribution that is to be accepted into the core:

  • If appropriate, the new functionality must support both standalone and Node.js configurations. For example, any new widgets must be capable of being rendered on the server
  • The contribution must not compromise the backwards compatibility of the existing code
  • Code contributions must comply with the TiddlyWiki Coding Style Guidelines
  • Generic components are preferred over point solutions for specific problems (which belong in plugins)

The Core and Innovation

If you've created something new and innovative, don't try to rush to get it included into the core. Once new stuff is in the core it is subject to the core policies of strict backwards compatibility, making it frozen as far as radical innovation is concerned. It's usually better to release the new thing as a plugin so that it can be shared with the rest of the community for feedback.

The expected model of innovation is that the core development will move relatively slowly as more and more of the initial planned functionality is implemented. Innovation can take place in the much more unconstrained environment of plugins. Over time, as these third party plugins gain popularity and become more polished, some or all of their functionality will be migrated into the core.

Improving Hackability of the Core

Don't be afraid to submit issues or pull requests that add hooks or other points of extensibility to help your plugin integrate with the core. An important goal for TiddlyWiki is for the core to be infinitely adaptable through plugins. It is expected that many more points of extension will need to be added to support a healthy ecosystem of plugins.

Contributing to the TiddlyWiki Plugin Library

16th October 2014 at 9:33am

The TiddlyWiki Plugin library is the set of plugins, themes and languages that are distributed via http://tiddlywiki.com.

The plugin library is intended to help end users of TiddlyWiki in the following ways:

  • By being a reliable, official source of community assets
  • Permitting automatic upgrading of plugins during the upgrade process
  • Providing a guarantee of backwards compatibility

Plugins in the library need a maintainer who is prepared to make a commitment to keep them tested and fully operational with successive releases of the core code. Many plugins are maintained by the core team.

Data Management during Runtime

8th July 2014 at 9:56am
doc

During the runtime the data of Tiddlywiki is stored in javascript objects. These objects are synchronized with the DOM-Representation of Tiddlywiki. This means every change of the original data of a Tiddler, fires an event which changes all DOM-Representations of the Tiddler and the javascript object. The bare-bones Wiki store is created during the boot process and is kept in a object called \$tw.Wiki. This object contains amongst others a hashmap of the different Tiddlers of Tiddlywiki. The Hashmap is used to store the javascript object representation of the different Tiddlers. Furthermore this object is used to manage the tiddlers during runtime, it provides methods for adding tiddlers, search tiddlers by name and delete tiddlers. As shown in the picture below, every change at the DOM triggers an event which changes the corresponding widget which again changes the store of the tiddlers. The whole image shows how WikiText is parsed by a set of rules into the parse tree and this parse tree is rendered as a tree of widgets. This Rendertree is synchronised to the DOM. Every modification on the Rendertree provokes a start of the rendering-pipeline. As well as every change on the wikiText triggers an event at the RenderTree. This Process uses a selective updating so that only the changed parts are updated. This means only widgets which have to change the DOM in consequence of a changed tiddler are refreshed.

Data Persistence

17th July 2014 at 8:57pm
doc

The next important part of the application are deserializers. Deserializers are responsible to load tiddlers from various sources. One of the deserializers provided by the microkernel for example can load new tiddlers from the current DOM tree. The counterpart of deserializers are saver. A saver is used to save the complete store or the complete TiddlyWiki for that matter at once. After a user made changes to some tiddlers, this method can be used to download the current state of the store as a completely new TiddlyWiki application.

Another way of persisting data are syncadaptors. Like deserializer and saver, a syncadaptor can load tiddlers into the store and can persist changed tiddlers. But in contrast to deserializer and saver it can load and persist single tiddlers. A syncadaptor can provide a list of loadable tiddlers registers at the store for changes. Now when a tiddler is changed and these changes are written to the store, the syncadaptor is triggered and persists the new changes, for each tiddler individually.

Tiddlers can be persisted from/to harddisk or synced with a remote server.

Data-Storage

10th July 2014 at 9:10am
doc

TW has two approaches to save the user data. These approaches depends on way you use TW. either you use node.js as a server for TW its saves the tiddlers as plain text in different files or you use TW as standalone in a browser it persists the data within the HTML-File in two Div-Areas depending on whether the encryption of the TiddlyWiki is activated or not. If the TiddlyWiki is not encrypted the data is stored in the Div-Area called "StoreArea". Every created Tiddler is stored in a own Div-area with a few custom values. An example of a saved Tiddler is shown below (\prettyref{lst:data-div}).

<div created="20140611153703343" modified="20140611153734589" tags="testTag" testfield="testvalue" title="TestTiddler" type="text/plain">
	<pre>testText</pre>
</div>

The Div-Area has the same attributes like the standard tillder fields, listed in TiddlerFields, all attributes which are not in this list are parsed as a custom field. The only required attribute is the name attribute, all other attributes are optional.\\ With a activated encryption the data is stored in a special Div-Area called "encryptedStoreArea". TiddlyWiki uses the Standford JavaScript Crypto Libary. The encrypted Tiddlers are saved in a JSON string within this Div-Area.

Datamodel

15th July 2014 at 9:38am
doc Microkernel Architecture new

The micro-kernel creates a TiddlyWiki specific data-structure called tiddler. Here you have to separate the different definition of tiddlers. In the architectural view a tiddler is a JavaScript object holding some data. In the overall concept a tiddler is similar to a wiki page in a normal wiki application like wikipedia. In this section we describe the architectural view of a tiddler. The listing below shows the JSON representation of a tiddler object. During the runtime of the TiddlyWiki everything is saved an object like this. Without any plug-in the architecture is not able to persist any kind of data. All the data is stored in a store. This store is a JavaScript object. This store is constructed like a Map with a bunch of key value pairs. Every tiddler has its name as the key in the map and the JavaScript-Object as the value. The tiddler concept is the main data-model within TiddlyWiki, everything from data up to plug-ins is stored as a tiddler.

{"fields":{
   "text":"example Text",
   "title":"Infrastruktur",
   "tags":["vs"],
   "modified":"2014-07-01T16:25:01.230Z",
   "myField":"myFieldValue",
   "created":"2014-07-01T16:22:10.673Z"
   }
}

Deserializer

15th July 2014 at 7:48pm
doc

Modules with module-type: tiddlerdeserializer can provide functions to create tiddlers out of any textual representation. Each function must be associated with a type like application/json or text/html. They get the textual representation of the tiddlers, some default field values and the type of the text block as arguments. They return an array of JavaScript objects representing the resulting tiddlers.

Deserializers are not managed by the syncer module. Instead the concept of deserializers is in fact part of the microkernel. This is necessary because the microkernel needs a way of loading tiddlers before it can load the core plug-in and execute it's startup modules. (Due to the fact that the core plug-in and it's modules are represented as tiddlers.)

The load-modules startup module loads additional deserializers and pushes them into the store. The core plug-in for example contains a few deserializers which can read a whole TiddlyWiki 5 or classic HTML file and load the individual tiddlers into the store.

Developing plugins using Node.js and GitHub

22nd October 2014 at 3:52pm
howto

The most practical way to develop plugins is to use Node.js with the tiddlywiki5 repository to build your plugins, and to use GitHub to manage you files.

Step by step

1. Installation

First read http://tiddlywiki.com/static/PluginMechanism.html.

Install Git from http://git-scm.com/downloads

Install Node.js from http://nodejs.org/

2. Create a new blank repository on GitHub

Hint: GitHub repositories cannot be grouped together into directories, so it is only possible to group by using a naming scheme, e.g. use 'TW5-' as a name prefix with tiddlywiki5 projects to group them together.

Go to https://github.com/ and create new a repository 'pluginname' - choose to add a readme file.

3. Setup a working environment

Choose a location in your file system (eg TW5) for your plugin project; issue commands to:

1. Create the directory

mkdir TW5

2. Make a local read-only copy of the TiddlyWiki5 repository

git clone https://github.com/Jermolene/TiddlyWiki5.git TW5

3. Make a directory for your plugin

cd TW5
cd plugins
mkdir yourname
cd yourname
mkdir pluginname

4. Make a local copy of your plugin repository

git clone https://github.com/yourgithub/pluginname.git pluginname

5. Go to your files

cd pluginname

Create the file plugin.info with content:

{
	"title": "$:/plugins/yourgithub/pluginname",
	"description": "summary of the plugin's purpose",
	"author": "yourname",
	"version": "0.0.1",
	"core-version": ">=5.0.8",
	"source": "https://github.com/yourgithub/pluginname",
	"plugin-type": "plugin"
}

4. Create the files for your plugin

For example files see the plugins in the TiddlyWiki5 repository i.e. those located at plugins/tiddlywiki/. See TiddlerFiles for details of the supported tiddler file formats.

5. Build your files into a TiddlyWiki

Modify editions/tw5.com/tiddlywiki.info to include a reference to your plugin directory, i.e. find "plugins": [ and add "yourname/pluginname".

From the TW5 directory issue the command

node ./tiddlywiki.js editions/tw5.com --build index

The resultant file (index.html) will be placed in the editions/tw5.com/output directory of the TW5 repo.

6. Save your work on GitHub

From plugins/yourname/pluginname/ issue commands to:

1. Add all files

git add -A

2. Commit to your local repository

git commit -am "something meaningful about this check in"

3. Copy local changes to github

git push

EncryptionMechanism

29th November 2013 at 4:36pm
Mechanisms

TiddlyWiki5 allows the entire content of a TiddlyWiki HTML file to be encrypted with the Stanford JavaScript Crypto Library. Opening an encrypted TiddlyWiki in the browser prompts for a password before decrypting and displaying the content.

For instructions on how to use TiddlyWiki5's encryption features, see Encryption.

The EncryptionMechanism is implemented with the following elements:

  • A PasswordVault within the BootMechanism that holds the current encryption password
  • The ability of the BootMechanism to read a block of encrypted tiddlers from the TiddlyWiki file, to prompt the user for a password, and to decrypt the tiddlers
  • Handlers for the messages WidgetMessage: tm-set-password and WidgetMessage: tm-clear-password that handle the user interface for password changes
  • The EncryptWidget within the main file template that encrypts a filtered list of tiddlers with the currently held password
  • The $:/isEncrypted tiddler that contains "yes" or "no" according to whether there is a password in the password vault
    • The availability of this tiddler allows the RevealWidget to be used to selectively display user interface elements according to whether encryption is in force

Event Mechanism

17th July 2014 at 9:14pm
doc new

Most of the following mechanisms need a way to get notified, when anything in the wiki store changes. The core -plug-in adds an event system to the bare wiki store. The event system provides the ability to listen to events. The most important is the "change" event which notifies the listeners when tiddlers have changed, with a list of the changed tiddlers. The event mechanism is one of the few mechanisms which needs a hook at the microkernel: The microkernel contains an empty function "enqueueTiddlerEvent(event)" and calls this function when a tiddler is added or deleted. The event mechanism from the core plug-in overwrites this function with it's own implementation. The functions providing the event system are added via the wikimethod module type.

Extended Persistence

17th July 2014 at 7:11pm
doc

The microkernel only contains a bare store and some deserializers to load tiddlers from JSON files or from the DOM of the current HTML file. The core plug-in adds some more deserializers and a new mechanism for persisting and synchronising tiddlers.

This mechanism is provided as a global module in $:/core/modules/syncer.js. The saver module has three responsibilities:

  1. Save the whole wiki.
  2. Provide the ability to download single tiddlers as files.
  3. Synchronise the local wiki store with a remote wiki store, i.e. running in Node.js

The syncer module is connected mainly to two other modules. For one it registers to changes at the wiki store (Event Mechanism) and if any changes occur they are synced to the remote store. Then it provides a function saveWiki(options). This function can be used by other modules. For example the RootWidget uses this function to save the whole wiki or start downloading single tiddlers.

The syncer itself does not provide a concrete implementation of saving, downloading or syncing the tiddlers. Instead it loads modules of type saver and syncadaptor and manages the saving/syncing process.

Deserializer

Modules with module-type: tiddlerdeserializer can provide functions to create tiddlers out of any textual representation. Each function must be associated with a type like application/json or text/html. They get the textual representation of the tiddlers, some default field values and the type of the text block as arguments. They return an array of JavaScript objects representing the resulting tiddlers.

Deserializers are not managed by the syncer module. Instead the concept of deserializers is in fact part of the microkernel. This is necessary because the microkernel needs a way of loading tiddlers before it can load the core plug-in and execute it's startup modules. (Due to the fact that the core plug-in and it's modules are represented as tiddlers.)

The load-modules startup module loads additional deserializers and pushes them into the store. The core plug-in for example contains a few deserializers which can read a whole TiddlyWiki 5 or classic HTML file and load the individual tiddlers into the store.

Saver

Modules with module-type: saver provide functionality to save the whole wiki. There are three methods a saver can support:

save
This method is used, when the user requests a save, for example by clicking the save button in the sidebar.
autosave
This method is used automatically by TW when tiddlers are changed, created or deleted by the user.
download
This message is used when the wiki or a single tiddler should explicitly be downloaded. The control panel for example uses this method to provide a button which saves the wiki as a static HTML file.

A saver module has to export two functions. canSave(wiki) returning true if this module is capable of working and create(wiki} returning an instance of a saver object. This saver object has to provide an info property containing a name, a priority, an array of methods it supports and a method save(text,method,callback). This method is called from TW with the actual text which should be saved, the method which is used and a callback function to report errors: callback("Error while saving") or to notify that saving went well: callback("Saving went well :)"). If the saver method successfully saved the file it has to return true, or false otherwise. Saves are triggered by messages from the UI. The syncer module uses the saver with the highest priority capable of the requested method to save the file.

The core plug-in contains a saver capable of saving the current state of the wiki to the local hard drive by using a special Firefox extension called Tiddlyfox. If this extension is not available, the savers canSave method would return false. A saver with a lower priority would then ask the user to save the current state as a new HTML file.

Syncadaptor

A module with module-type: syncadaptor provides functionality to get a list of tiddlers (this list is provided as SkinnyTiddlers, which are normal tiddlers without the text field) and to load, save and delete single tiddlers. A syncadaptor can also provide functions to login and logout so that syncadaptor modules can be used to synchronize tiddlers with a remote server.

The syncer module only uses one syncadaptor and honours a special system tiddler $:/config/SyncFilter containing a filter string. Tiddlers matching this filter string are not synced with a syncadapter.

Extending the Store

17th July 2014 at 6:56pm
doc

Event Mechanism

Most of the following mechanisms need a way to get notified, when anything in the wiki store changes. The core -plug-in adds an event system to the bare wiki store. The event system provides the ability to listen to events. The most important is the "change" event which notifies the listeners when tiddlers have changed, with a list of the changed tiddlers. The event mechanism is one of the few mechanisms which needs a hook at the microkernel: The microkernel contains an empty function "enqueueTiddlerEvent(event)" and calls this function when a tiddler is added or deleted. The event mechanism from the core plug-in overwrites this function with it's own implementation. The functions providing the event system are added via the wikimethod module type.

Caching

The core plug-in adds two caches to the wiki store. A global cache and a cache for each tiddler. While the global cache is cleared whenever any tiddler changes, the tiddler cache is only cleared when the associated tiddler changes. The idea of the tiddler cache is, that sometimes we want to calculate information from a tiddler but don't want to recalculate every time we need this information. Imagine a tiddler which contains links to other tiddlers and at one point we want to have a list of the linked tiddlers (LinksFilter). With the tiddler cache we can parse the WikiText, extract the linked tiddlers and put this list in the cache. Until the tiddler is changed, the cache can be used to access this information in the next requests.

The same idea holds for the global cache. For example when a filter string is parsed and a list of matching tiddlers is constructed. This list can be put in the global cache for later reuse until something changes in the store.

Like the Event Mechanism, the cache needs hook functions in the microkernel. The microkernel calls clearGlobalCache() and clearCache(tiddlertitle) when a tiddler changes. The core's cache mechanism overwrites this functions. The functions providing the cache system are added via the wikimethod module type.

System Tiddlers

The core plug-in introduces a segregation of tiddlers. The tiddler model is central in the whole TiddlyWiki application and can be used in various roles. Because of the fact that a TiddlyWiki user works with tiddlers (taking the role of a wiki page) and tiddlers are the building blocks of the whole application (including modules, UI elements, etc.) we need to identify the internal tiddlers.

The core plug-in introduces the concept of system tiddlers. It builds on the convention that application internal tiddler names start with $:/. Then the core plug-in introduces a set of new functions to the wiki store which are used to retrieve tiddlers like getTiddlers(options) and forEachTiddler(callback, options). These functions work with all tiddlers in the store but the options parameter provides the ability to sort tiddlers by a field-name and exclude tiddlers with a specific tag. By default it doesn't return system tiddlers. To get a list of all tiddlers including system tiddlers, this must be requested explicitly via the options. If a function wants to present a list of tiddlers to the user it can use this new functions so that internal application tiddlers wouldn't clutter the resulting list. These functions are added via the wikimethod module type.

Tags and Filter Mechanism

Tags

The core plug-in extends the store by a simple mechanism to tag a tiddler. This provides the functionality to

  • retrieve tiddlers with a specific tag
  • retreive a hashmap of { tag: [tiddler1, tiddler3, tiddler3] }
  • list or iterate tiddlers not tagged with a specific tag

The tags are stored directly in the tiddler. Each tiddler can have a field named "tag", which contains an array of its tags. The above functions use this field to calculate their results and cache them in a global cache.

Organising information with tags is easy, intuitive and is common throughout the web. In most cases the functions mentioned above are not enough and a more sophisticated way of querying is needed. But instead of focusing only on tags TiddlyWiki introduces a querying system that isn't bound to tags or single tiddlers.

Filter mechanism

This filter mechanism is build on the idea of a pipeline of single filter operators. Filters are noted as strings and can look like

[tag[task]!tag[done]interesting[very]]

This example would (implicitly) put all available tiddlers into the pipe. The first operator tag[task] would only pass tiddlers which are tagged with "task". The !tag[done] operator is negated and only passes tiddlers which are not tagged with "done". The last filter operator passes only tiddlers with a field "interesting" set to "very". So as a result this filter would be used to obtain all tiddlers which are marked as task, aren't already done and are very interesting.

There are many filter operators already build into the core plug-in including the mentioned tag- and field operators, filter operators to sort the tiddlerlist by a specified field, etc. But more sophisticated operators are possible, too. An example would be the search-operator. This filter operator looks for the searched string in the text and in the tags of the tiddlers. If the provided filter operators are not enough, a developer can add new filters by adding a module with the filteroperator type.

System Tags

Tags and the filter mechanism are used throughout the core plug-in for internal puproses. Tags which start with $:/ are normally hidden from the casual user, similar to System Tiddlers

The filter mechanism is added to the wiki store with the wikimethod module type.

FakeDomMechanism

19th October 2014 at 1:23pm

The "fake DOM" is a simplified JavaScript implementation of the DOM that can be run on the server. Its use allows modules that need to run under Node.js to generate and manipulate HTML through the DOM API, rather than having to stitch HTML strings together.

The fake DOM only implements a small subset of the full DOM APIs but it is sufficient for the core widgets to be able to be run under Node.js.

Because the fake DOM is faster than the real DOM, it is also used in the browser when interactive rendering to the DOM isn't needed. The best example is stylesheet processing, where WikiText stylesheet content is parsed and rendered, and the plain text extracted from the fake DOM for use as the stylesheet content.

Filter Operators

dev

Overview

Filter operators are modules (tiddlers of type application/javascript) with their module-type field set to filteroperator, exporting one or more functions implementing a filter.

Each function will be called with three arguments:

  • A tiddler iterator representing the results of the previous filter step (or all tiddlers, if this filter appears first in an expression), conventionally named source.
  • An object, conventionally called operator, representing the arguments for this filter step, with the following keys:
    • operator: the name of the filter operator specified in the WikiText;
    • operand: the operand for the filter step (as a string; if the filter specified it in angle brackets or braces, the text reference or variable name will have already been resolved);
    • prefix: (optional) a string containing a single exclamation mark if the filter operator is to be negated;
    • suffix: (optional) a string containing an additional filter argument (typically a tiddler field name) following the filter name (separated by a colon in the filter syntax);
    • regexp: (optional, deprecated) used instead of operand if the filter operand is a regexp.
  • An object, conventionally called options, with the following keys:
    • wiki: The $tw.Wiki object;
    • widget: (optional) a widget node.

The function should return either a new tiddler iterator, or else an array of tiddler titles (as strings). The underlying filter mechanism will convert back and forth between iterators and arrays as needed.

References

There are several filter operators built into the core which can serve as a jumping off point for your own filter operators:

https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/filters

Example

Suppose we want to make a filter operator that returns every other tiddler from the input list. A typical invocation might look like [tags[interesting]everyother[]].

We make a new tiddler, set its type and module-type appropriately, and begin writing the code:

(function(){
"use strict";
    
exports.everyother = function(source, operator, options) {
    // TODO
}
})();

For the example filter syntax, our function will be called with

  • source: an iterator over all the tiddlers tagged as interesting
  • operator: an object {operator: "everyother", operand: ""}
  • options: an object with the current Wiki object and a widget object, neither of which we need

As is usually the case, we don't care about operator.operator here (since that information has already been used to look up our function); we also don't care about operator.operand, since there is no meaningful operand for this operation.

We could implement the operator by iterating over the input tiddlers and explicitly building a result array of titles:

(function(){
"use strict";
    
exports.everyother = function(source, operator, options) {
    var result = [];
    var include = true;
    source(function(tiddler, title) {
        if (include) { result.push(title); }
        include = !include;
    });
    return result;
}
})();

That is, we supply a callback to source that negates include each time through (in order to grab every other result) and pushes the title of every other tiddler onto the result.

Alternatively, we can return our own iterator, by returning a function that accepts a similar callback and only calls it on every other tiddler:

(function(){
"use strict";
    
exports.everyother = function(source, operator, options) {
    return function(callback) {
        var include = true;
        source(function(tiddler, title) {
            if (include) { callback(tiddler, title); }
            include = !include;
        });
    };
}
})();

Either way, we could interpret the ! flag on the filter, if present, to mean that we want the other half of the tiddlers, by using it to set the initial value of include: var include = operator.prefix !== "!";

Filter Behaviour

As with JavaScript Macros, filter operators should not make modifications to tiddlers, but only return a list of tiddlers or a tiddler iterator.

HelloThere

22nd November 2014 at 8:03pm
TableOfContents

Welcome to the developer documentation for TiddlyWiki (http://tiddlywiki.com/). It is currently a work in progress as material from two different sources is adapted and merged in addition to original content being added:

Hook: th-deleting-tiddler

9th February 2017 at 2:59pm
HookMechanism

This hook allows plugins to inspect tiddlers before they are deleted via the delete toolbar button. When the delete button is used from the edit toolbar there are actually two invocations of the th-deleting-tiddler hook function: one for the original tiddler and one for the draft.

Note that this hook is not invoked for tiddlers deleted by other means such as the ActionDeleteTiddlerWidget.

Hook function parameters:

  • tiddler: tiddler object about to be deleted

Return value:

  • unmodified tiddler to be deleted

Hook: th-importing-tiddler

9th February 2017 at 2:55pm
HookMechanism

This hook allows plugins to inspect or modify tiddlers before they are imported via the import mechanism.

Hook function parameters:

  • tiddler: tiddler object about to be imported

Return value:

  • tiddler object to be imported

The original tiddler object can be returned unmodified by the hook. If the hook needs to modify the tiddler then it should return a new tiddler object, for example:

	return new $tw.Tiddler(tiddler,{"my-field": value});

Hooks must not change the title field but can freely modify any other field of the tiddler.

Hook: th-navigating

19th February 2017 at 2:55pm
HookMechanism

This hook allows plugins to monitor and modify navigation events.

Hook function parameters:

  • event: object describing the navigation event:
    • event.navigateTo: title of target tiddler
    • event.navigateFromTitle: title of tiddler containing the
    • event.navigateSuppressNavigation: boolean; when true the target tiddler opens without the usual scrolling
    • event.navigateFromClientRect: rectange in client coordinates of the DOM node triggering the navigation

Return value:

  • possibly modified event object

Hook: th-opening-default-tiddlers-list

9th February 2017 at 11:55am
HookMechanism

This hook allows plugins to add to or remove from the list of tiddlers that are opened when the wiki is first loaded or the home button is clicked.

Hook function parameters:

  • list: array of tiddler titles to be opened

Return value:

  • modified array of tiddler titles to be opened

Note that this hook is invoked with the tiddler titles that are generated from the filter in $:/DefaultTiddlers. Any added entries must be tiddler titles, not filter expressions.

Hook: th-relinking-tiddler

9th February 2017 at 3:00pm
HookMechanism

This hook allows plugins to inspect tiddlers before they are relinked ("relinking" is the optional operation of relinking references to a tiddler when it is renamed).

Hook function parameters:

  • newTiddler: tiddler object incorporating the relinking
  • oldTiddler: optional existing tiddler object that will be overwritten

Return value:

  • newTiddler: tiddler object to be used for the relinking operation.

The original tiddler object can be returned unmodified by the hook. If the hook needs to modify the tiddler then it should return a new tiddler object, for example:

	return new $tw.Tiddler(tiddler,{"my-field": value});

Hooks must not change the title field but can freely modify any other field of the tiddler.

Hook: th-renaming-tiddler

9th February 2017 at 2:56pm
HookMechanism

This hook allows plugins to inspect tiddlers before they are modified by the tm-rename-tiddler message.

Hook function parameters:

  • newTiddler: tiddler object incorporating the rename
  • oldTiddler: optional existing tiddler object that will be overwritten

Return value:

  • newTiddler: tiddler object to be used for the renaming operation.

The original tiddler object can be returned unmodified by the hook. If the hook needs to modify the tiddler then it should return a new tiddler object, for example:

	return new $tw.Tiddler(tiddler,{"my-field": value});

Hooks must not change the title field but can freely modify any other field of the tiddler.

Hook: th-saving-tiddler

9th February 2017 at 2:55pm
HookMechanism

This hook allows plugins to inspect or modify tiddlers before they are saved via the confirm toolbar button; the hook is not invoked for tiddlers that are saved through other means, such as state tiddlers created by the ActionSetFieldWidget.

Hook function parameters:

  • tiddler: tiddler object about to be saved

Return value:

  • tiddler object to be saved

The original tiddler object can be returned unmodified by the hook. If the hook needs to modify the tiddler then it should return a new tiddler object, for example:

	return new $tw.Tiddler(tiddler,{"my-field": value});

Hooks must not change the title field but can freely modify any other field of the tiddler.

HookMechanism

9th February 2017 at 1:08pm

The hook mechanism provides a way for plugins to intercept and modify default functionality. Hooks are added as follows:

$tw.hooks.addHook(name,handler);

Multiple handlers can be assigned to the same name using repeated calls. When a hook is invoked by name all registered functions will be called sequentially in their order of addition.

Though not essential care should be taken to ensure that hooks are added before they are invoked. For example: Hook: tc-opening-default-tiddlers-list should ideally be added before the story startup module is invoked otherwise any hook specified additions to the default tiddlers will not be seen on the initial loading of the page, though will be visible if the user clicks the home button.

Example

A working example of a hook that adds "test" to the default tiddlers.

$tw.hooks.addHook("th-opening-default-tiddlers-list",function(list) { 
    list.push("test");
    return list; 
});

How to create a translation for TiddlyWiki

22nd October 2014 at 3:52pm
howto

Prerequisites

Setting Up

  1. Fork the TiddlyWiki GitHub repository (https://github.com/Jermolene/TiddlyWiki5)
  2. Create a branch with the name of the translation you intend to create (eg "cy-GB" for "Welsh (United Kingdom)")
  3. Clone your forked repository to your computer (eg, /MyTranslation/TiddlyWiki5)
  4. Create a sibling directory /MyTranslation/jermolene.github.io
  5. Create a new folder in <repo>/languages for your translation
  6. Copy the contents of <repo>/core/language/en-GB into your translation folder
  7. Create a plugin.info file (see below) in your translation folder
  8. Edit <repo>/editions/tw5.com/tiddlywiki.info to add your language to the list
  9. Run ../build.jermolene.github.io/quick-bld.sh to build TiddlyWiki
  10. Open the TiddlyWiki file at /MyTranslation/jermolene.github.io/index.html
  11. You should see your translation listed in the control panel, but the text of the translation will still be in British English
  12. Edit the .tid and .multids files in your language folder to translate the English text

Content of plugin.info for Joe Bloggs' Welsh translation:

{
	"title": "$:/languages/cy-GB",
	"name": "cy-GB",
	"plugin-type": "language",
	"description": "Welsh (British)",
	"author": "JoeBloggs",
	"core-version": ">=5.0.0"
}

MultiTiddlerFiles make it possible to pack the text of several tiddlers in a single text file, simplifying some editing tasks.

Handling Updates

Sometimes the master en-GB language tiddlers are updated with revised content or new items. The best way to keep track of language-related commits to TiddlyWiki5:master is to monitor this RSS/Atom feed:

https://github.com/Jermolene/TiddlyWiki5/commits/master/core/language.atom

How to create plugins in the browser

2nd May 2015 at 9:24am
howto

The recommended technique for building TiddlyWiki plugins involves running TiddlyWiki on Node.js, but there is now an experimental technique for creating plugins directly in the browser.

Overview

Loading a plugin in the browser has several consequences:

  • The original plugin tiddler itself is unchanged
  • The payload tiddlers are set up as individual ShadowTiddlers

To make a modified copy of a plugin, one edits the constituent shadow tiddlers (doing this actually overrides the shadow tiddler with a new non-shadow tiddler containing the modified content). The repacking process retrieves the current value of all the shadow tiddlers included in the plugin, and then bundles the new values back into the original plugin tiddler.

Step by step

1. Setup your development environment

Start with a blank TiddlyWiki. It is useful to create a HelloThere tiddler that contains links to various tiddlers that you'll be opening frequently during plugin development:

  • The plugin itself (eg $:/plugins/yourname/pluginname)
  • The payload tiddlers that are to be packed into the plugin (eg $:/plugins/yourname/pluginname/mywidget.js)

2. Create the plugin tiddler

Click the link to the plugin tiddler to open it. Assuming it doesn't currently exist, it will open with an italicised title, indicating that it is a missing tiddler. Then switch to edit mode and set the following fields on the tiddler:

FieldValue
dependentsSpace separated list of dependent plugins (use square brackets for titles containing spaces)
descriptionPlugin description
namePlugin name (only needed for themes)
plugin-typeEither "plugin" for a regular plugin, "theme" for a theme, or "language" for a language pack
typeSet to "application/json"
versionSet to the version number of the plugin (eg "0.0.1")

Then in the body of the tiddler, insert:

{"tiddlers": {}}

Save the plugin tiddler

3. Modify the payload tiddlers

Create the payload tiddlers by clicking on the links in the HelloThere tiddler from step 1.

4. Pack the plugin

Open the browser developer console, and type the following JavaScript statement, but first change the first parameter to the name of your plugin. The second parameter is an optional array of tiddler titles to be added to the plugin:

$tw.utils.repackPlugin("$:/plugins/yourname/pluginname",["$:/plugins/yourname/pluginname/mywidget.js"])

You should see a confirmation message, and then if you inspect the plugin tiddler you should see that it has been filled with the payload tiddlers.

Each time you save the plugin the last portion of the version number is automatically incremented. This will ensure that users with an older version of your plugin will be able to install the new version.

5. Testing the plugin

To test the plugin, first make sure that it has been packed. Then save changes and refresh the page in order to load the new plugin.

6. Repacking the plugin

Once you've built the plugin for the first time you can omit the second parameter to repackPlugin() unless you are adding a new tiddler:

$tw.utils.repackPlugin("$:/plugins/yourname/pluginname")

7. Removing tiddlers from the plugin

To remove tiddlers from the plugin specify their titles in the optional third parameter:

$tw.utils.repackPlugin("$:/plugins/yourname/pluginname",null,["$:/plugins/yourname/pluginname/mywidget.js"])

Notes

Creating theme and language plugins

Before attempting to repack your plugin you should ensure that the plugin is selected as the current theme or language. Otherwise the shadow tiddlers will not be present.

How to customise the password prompt

6th October 2014 at 9:55am
howto

You can customise the text and appearance of the password prompt that is displayed when encrypted TiddlyWiki files are first opened.

To do so, create a tiddler tagged $:/core/wiki/rawmarkup containing:

  1. A JavaScript <script> tag containing code to override the configuration variable $tw.boot.encryptionPrompts.decrypt
  2. CSS <style> definitions targeting the tc-password-wrapper class to apply styles to the form

Raw markup tiddlers are spliced into the top of the standalone HTML file, and are executed before the boot prefix and boot kernel.

See $:/PatchEncryptionPrompt for an example.

ImportLogging

14th November 2014 at 10:00am

Browsers still have significant variations in their handling of drag and drop and clipboard operations.

You can switch on special logging to help debug issues:

  1. Open your browser JavaScript console
  2. Type:

    $tw.log.IMPORT = true

  3. Drag or paste a file to import it
  4. Look for debug information in the console. For example:

    Importing file 'my-image.png', type: 'image/png', isBinary: true

index.svg

8th July 2014 at 9:38am

Introduction

17th July 2014 at 10:26pm
doc

TiddlyWiki is a personal notebook application based on a wiki application. In addition to a static Web-Site, TiddlyWiki is implemented as a single page application. This is a approach to build rich internet applications, it includes the possibility to put application logic into web-pages to make them dynamically. Furthermore this means the whole application is delivered in one HTML file, consisting of source code to dynamically change the view and behaviour of the application as well as the data of the application. During the runtime nothing must be loaded from a server to the TiddlyWiki application. The HTML file contains everything needed to start the application. TiddlyWiki is highly customisable because of a very sophisticated module concept. Except of a micro-kernel written in JavaScript the whole application consist of a own data-structure called tiddlers and a own markup language called wikiText. Even the modules are realised as tiddlers.

The aim of this documentation is to overview the idea behind the TiddlyWiki application as well as give a overview of the architecture to the reader. This means after reading the documentation the reader is has the knowledge how the overall application works and where the points are where the reader can extend the functionality of the application.

Section Overview:

TiddlyWiki - A quick Overview
This section describes the idea of the TiddlyWiki application. This should give the reader a overview over what TiddlyWiki consists of give a brief introduction to the topics of the main documentation.

Microkernel Architecture
The heart of TiddlyWiki is it's microkernel. This section will describe what bare mechanisms are included in the microkernel and how additional modules are loaded.

TiddlyWiki Core Application
After the microkernel has been explained this section focuses on the core plug-in. It describes the central modules of the core and explains how they work together to build a single file application.

Conclusion
A briefly summary about this documentation bringing out the advantages, disadvantages and experiences with TiddlyWiki.

JavaScript Macros

24th April 2014 at 2:01pm
dev

Macros can be implemented as JavaScript modules as well as via the wikitext syntax.

Overview

JavaScript macros are modules with their module-type field set to macro. They must export these three properties:

  • name: A string giving the name used to invoke the macro
  • params: An array of objects with the following properties:
    • name: name of the parameter
    • default: (optional) default value for the parameter
  • run: Function called when the macro requires evaluation. The parameters are pulled from the macro call and arranged according to the params array. The run function should return the string value of the macro. When invoked, this points to the widget node invoking the macro.

Note that if the params array is missing or blank, then all the supplied parameters are passed to the run() method.

Writing JavaScript macros

There are several JavaScript macros built into the core which can serve as a jumping off point for your own macros:

https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/macros

Note that JavaScript macros work on both the client and the server, and so do not have access to the browser DOM.

Macro Behaviour

Macros are just used to return a chunk of wikitext for further processing. They should not make modifications to tiddlers in the wiki store. The reason is that you cannott control when the macro is called; it may be called repeatedly as part of refresh processing. So it is important that macros do not have any other side effects beyond generating their text.

LazyLoadingMechanism

6th February 2014 at 10:19pm
Mechanisms

TiddlyWiki currently only implements LazyLoading when it is running in the browser talking to a TiddlyWeb-compatible server.

In the configuration for TiddlyWeb, the browser first requests a "skinny" version of each tiddler (consisting of all the fields apart from the text field). Subsequently, an attempt to read those skinny tiddlers with wiki.getTiddler() returns just the skinny fields, but an attempt to read one using wiki.getTiddlerText() will trigger an asynchronous load of the full tiddler text, which in turn triggers a refresh cycle, updating the display to reflect the newly loaded tiddler. Widgets that loop through all tiddlers are fine; it's only if they trigger wiki.getTiddlerText() for a tiddler that it will get loaded.

Lazy loading can also be used with TiddlyWiki's own server. The core provides a template that enables images to be lazily loaded while other tiddlers are packaged into the initial HTML file in the usual way.

The browser-based search built into TiddlyWiki5 will only search the text of tiddlers that have been fully loaded. The expectation is that when lazy loading is used in a client-server configuration, then it is the server that really needs to handle search operations, because it is only the server that can "see" the text of all tiddlers. So, the plan is to integrate the built in search with TiddlyWeb's search API. The simplest approach is that any local search triggers an asynchronous server side search. The results of the search would be asynchronously loaded such that they would dynamically appear in the local search results.

Messages

17th July 2014 at 7:16pm
doc

Messages are events that are triggered by the user. They are generated by widgets for example when the user clicks on a ButtonWidget. Each message has a type property like "tm-delete-tiddler" and a parameter.

{type: "tm-delete-tiddler", param: "MyOldTiddler"}

When such a message is created by a widget it sends the message to it's parent widget which sends it to it's own parent widget and so on. On this way each widget can try to dispatch the message. This concept is realised in the base widget object. It provides a function dispatchEvent(message) which is called by the children to bubble the message up the widget tree. Another function addEventListener(type,listener) can be used to bind a function to a specific message type. If the listener returns false, the message is send to the parent widget.

The TiddlyWiki core plug-in handles a lot of messages in the NavigatorWidget.

Microkernel

17th July 2014 at 8:55pm
doc

In the universe of TiddlyWiki everything is a tiddler. Even the application logic is stored in tiddlers that are marked as "application/javascript". These tiddlers, which contain application logic, are called modules and a CommonJS compatible module system is responsible for assembling the individual modules into the TiddlyWiki application. The result is a tree representing the whole TiddlyWiki application containing module tiddlers, data tiddlers and some JavaScript functions and objects.

Only a small part of the TiddlyWiki is not managed as tiddlers, the microkernel. The microkernel is the first thing to run, when the application is started and it puts some initial objects and functions into the application tree, which are needed to load and manage tiddlers. After the microkernel built this initial application tree, the remaining parts of the application can be loaded as module tiddlers. Beside some utility functions the most important object that is contributed by the boot kernel is "$tw.wiki", consisting of JavaScript structures and functions that are used to store and manage the loaded tiddlers. Among other things this store can be used to add new tiddlers, remove tiddlers and retrieve tiddlers by name.

The microkernel constructs a initial $tw object containing the needed structures and functions.

Microkernel and Datamodel

9th July 2014 at 10:36am
redo

The microkernel is responsible for creating a bare-bones TW environment. It is running under Node.js or in a HTML5 Browser. The Bootkernel just loads enough functionality to load the modules containing the main logic of the application. This boot-kernel contains a few helper methods, the module mechanism as well as the function to create a tiddler and manage them. The boot-kernel also creates the bare-bones wiki store, which holds all the information of the wiki during the runtime. After creating the store, the boot-kernel is in charge of decrypting the encrypted tiddlers and extracting all the tiddlers e.g. the core module tiddlers embedded in the DOM structure of the HTML file. Furthermore the boot kernel offers the functionality to load tiddlers from a file, when you run TW with Node.js.

Microkernel Architecture

17th July 2014 at 10:16pm
doc section

This section describes the architecture of the TiddlyWiki-kernel. TiddlyWiki is based on a micro-kernel which provides only a small stack of functions. This design decision was made to introduce a cleaner mechanism for customization of TiddlyWiki. This section also describes the data-model of TiddlyWiki called tiddler. And it gives a overview to the modul system which developers can use to extend the functionality of the TiddlyWiki application.

Microkernel Description

The TiddlyWiki application is based on a microkernel architecture, that means it separate minimal functional core from the extended functionality. The microkernel provides the functionality to load external extensions to extend its core features. The TiddlyWiki microkernel provides a few helper methods but the main task of the TiddlyWiki kernel is to provide a basic functionality for storing data and loading the extension plug-ins. Within the TiddlyWiki architecture everything is stored as a tiddler. How the architecture of TiddlyWiki stores his data during the runtime of the application is shown in Datamodel, but the kernel provides this datamodel. It also prepares the functionality to store and create these tiddlers. In favour it creates a store to manage the tiddlers during the runtime. Without any extensions the microkernel is not able to persist the tiddlers, this means the data is only holded in the RAM. Here are some example interfaces for working with tiddlers in memory which are provided by the kernel:

  • $tw.Tiddler = function(/* [fields,] fields */)
  • $tw.Wiki.addTiddler = function(tiddler)
  • $tw.Wiki.deleteTiddler = function(title)
  • $tw.Wiki.getTiddler = function(title)

An additional feature of the microkernel is the ability to encrypt and decrypt a block of text. To provide this functionality the microkernel has a built in password-vault to store the current used password. The library used to encrypt and decrypt data is the StandfordJavaScript Crypto Libary. This feature allows the micro-kernel to load encrypted tiddlers from the TiddlyWiki file, but it also allows extension plug-ins to use the encrypt functionality e.g. to persist an encrypted TiddlyWiki.

In order to load extension plug-ins the kernel prepares a interface to load and execute these plug-ins. Therefore the micro-kernel provides some deserializers to extract different type of tiddlers e.g. from the TiddlyWiki-File. Within the microkernel a bunch of different deserializer are installed. These deserializer are needed because every tiddler can include a different type of data for example tiddlers can contain javaScript-code, text, html-text or ~JSON-data. Even after packaging a TiddlyWiki application every plug-in is stored as a tiddler within the TiddlyWiki-Document. This feature is specified in the Module System section. Therefore the micro-kernel need the functionality to parse all the different type of tiddlers. To differ between the different type of tiddlers every tiddler has a file type which are generated by the microkernel

The image below shows the startup process of the TiddlyWiki-kernel. The bootprefix is responsible for preparing the kernel to boot on different engines e.g. browsers and node.js. Afterwards the main boot process which includes the microkernel, with the startup-method, is started. After successfully running these steps the main architecture is loaded. The last step is to run the startup modules. These modules are described later. But in brief this is the point where the TiddlyWiki microkernel can be extended by own functionality. Every module marked as "startup" is started after finishing the boot process of the kernel.

The microkernel builds up the essential functions and structures and initiates a startup sequence.

Datamodel

The micro-kernel creates a TiddlyWiki specific data-structure called tiddler. Here you have to separate the different definition of tiddlers. In the architectural view a tiddler is a JavaScript object holding some data. In the overall concept a tiddler is similar to a wiki page in a normal wiki application like wikipedia. In this section we describe the architectural view of a tiddler. The listing below shows the JSON representation of a tiddler object. During the runtime of the TiddlyWiki everything is saved an object like this. Without any plug-in the architecture is not able to persist any kind of data. All the data is stored in a store. This store is a JavaScript object. This store is constructed like a Map with a bunch of key value pairs. Every tiddler has its name as the key in the map and the JavaScript-Object as the value. The tiddler concept is the main data-model within TiddlyWiki, everything from data up to plug-ins is stored as a tiddler.

{"fields":{
   "text":"example Text",
   "title":"Infrastruktur",
   "tags":["vs"],
   "modified":"2014-07-01T16:25:01.230Z",
   "myField":"myFieldValue",
   "created":"2014-07-01T16:22:10.673Z"
   }
}

Module System

After the boot kernel provides the functions used to load tiddlers, the rest of the TiddlyWiki application is loaded as modules. A module is a tiddler which has the type application/javascript and contains CommonJS compatible JavaScript code. This means a single module provides its public structures and functions in a variable called export. Other modules can obtain these structures and functions by using a global require function.

var Widget = require("$:/core/modules/widgets/widget.js").widget;
// ...
ButtonWidget.prototype = new Widget();

In most cases these module tiddlers are packed into a plug-in. Following the "everything is a tiddler" concept, a plug-in is a tiddler, which contains a bunch of other tiddlers. These tiddlers are first converted into a JSON structure which then becomes the body of the plug-in tiddler. This is not restricted to module tiddlers. A plug-in can contain any tiddlers. This way a developer can put for example simple modules, widgets, UI parts written with WikiText, even new filter operators or extensions to the WikiText parser into a plug-in tiddler. In fact the whole TW core is provided as a single plug-in. Tiddlers provided in a plug-in are called shadow tiddlers and can not be edited. Instead, when trying to edit a shadow tiddler, a new tiddler with the same name is created which then "overrides" the shadow tiddler.

Instead of requiring a specific module directly, a module developer can specify the type of the module he is developing by setting the field "module-type" of the containing tiddler. For example, by providing a module-type of "saver", TiddlyWiki knows that this module implements a way of saving the whole wiki and when the user clicks on the save button, TiddlyWiki automaticly considers the provided module to save the current state.

Microkernel Description

17th July 2014 at 10:33pm
doc new

The TiddlyWiki application is based on a microkernel architecture, that means it separate minimal functional core from the extended functionality. The microkernel provides the functionality to load external extensions to extend its core features. The TiddlyWiki microkernel provides a few helper methods but the main task of the TiddlyWiki kernel is to provide a basic functionality for storing data and loading the extension plug-ins. Within the TiddlyWiki architecture everything is stored as a tiddler. How the architecture of TiddlyWiki stores his data during the runtime of the application is shown in Datamodel, but the kernel provides this datamodel. It also prepares the functionality to store and create these tiddlers. In favour it creates a store to manage the tiddlers during the runtime. Without any extensions the microkernel is not able to persist the tiddlers, this means the data is only holded in the RAM. Here are some example interfaces for working with tiddlers in memory which are provided by the kernel:

  • $tw.Tiddler = function(/* [fields,] fields */)
  • $tw.Wiki.addTiddler = function(tiddler)
  • $tw.Wiki.deleteTiddler = function(title)
  • $tw.Wiki.getTiddler = function(title)

An additional feature of the microkernel is the ability to encrypt and decrypt a block of text. To provide this functionality the microkernel has a built in password-vault to store the current used password. The library used to encrypt and decrypt data is the StandfordJavaScript Crypto Libary. This feature allows the micro-kernel to load encrypted tiddlers from the TiddlyWiki file, but it also allows extension plug-ins to use the encrypt functionality e.g. to persist an encrypted TiddlyWiki.

In order to load extension plug-ins the kernel prepares a interface to load and execute these plug-ins. Therefore the micro-kernel provides some deserializers to extract different type of tiddlers e.g. from the TiddlyWiki-File. Within the microkernel a bunch of different deserializer are installed. These deserializer are needed because every tiddler can include a different type of data for example tiddlers can contain javaScript-code, text, html-text or ~JSON-data. Even after packaging a TiddlyWiki application every plug-in is stored as a tiddler within the TiddlyWiki-Document. This feature is specified in the Module System section. Therefore the micro-kernel need the functionality to parse all the different type of tiddlers. To differ between the different type of tiddlers every tiddler has a file type which are generated by the microkernel

The image below shows the startup process of the TiddlyWiki-kernel. The bootprefix is responsible for preparing the kernel to boot on different engines e.g. browsers and node.js. Afterwards the main boot process which includes the microkernel, with the startup-method, is started. After successfully running these steps the main architecture is loaded. The last step is to run the startup modules. These modules are described later. But in brief this is the point where the TiddlyWiki microkernel can be extended by own functionality. Every module marked as "startup" is started after finishing the boot process of the kernel.

The microkernel builds up the essential functions and structures and initiates a startup sequence.

Modularization

15th July 2014 at 9:34am
doc

The whole application is basically built from three parts. At first, the microkernel provides the basic functionality to handle tiddlers. The second part are tiddlers representing core functionality. These are for example modules which extend the store by more sophisticated functions, UI tiddlers and widget modules, a WikiText parser, sophisticated deserializers, savers, syncadapters, etc. These core modules are provided as plug-in to the microkernel. Consequently, a plug-in is a single tiddler which itself contains multiple tiddlers, forming the plug-in. Each of this tiddler might be a module providing new functionality (i.e. a module tiddler marked with "module-type: saver" can extend the application with new methods of saving the current wiki state.). Tiddlers provided in plug-ins are called shadow tiddlers. They are immutable and can not be edited or deleted but we can create a new tiddler with the same name to override a shadow tiddler.

Module System

15th July 2014 at 10:48am
doc Microkernel Architecture

After the boot kernel provides the functions used to load tiddlers, the rest of the TiddlyWiki application is loaded as modules. A module is a tiddler which has the type application/javascript and contains CommonJS compatible JavaScript code. This means a single module provides its public structures and functions in a variable called export. Other modules can obtain these structures and functions by using a global require function.

var Widget = require("$:/core/modules/widgets/widget.js").widget;
// ...
ButtonWidget.prototype = new Widget();

In most cases these module tiddlers are packed into a plug-in. Following the "everything is a tiddler" concept, a plug-in is a tiddler, which contains a bunch of other tiddlers. These tiddlers are first converted into a JSON structure which then becomes the body of the plug-in tiddler. This is not restricted to module tiddlers. A plug-in can contain any tiddlers. This way a developer can put for example simple modules, widgets, UI parts written with WikiText, even new filter operators or extensions to the WikiText parser into a plug-in tiddler. In fact the whole TW core is provided as a single plug-in. Tiddlers provided in a plug-in are called shadow tiddlers and can not be edited. Instead, when trying to edit a shadow tiddler, a new tiddler with the same name is created which then "overrides" the shadow tiddler.

Instead of requiring a specific module directly, a module developer can specify the type of the module he is developing by setting the field "module-type" of the containing tiddler. For example, by providing a module-type of "saver", TiddlyWiki knows that this module implements a way of saving the whole wiki and when the user clicks on the save button, TiddlyWiki automaticly considers the provided module to save the current state.

NEW NEW TOC

17th July 2014 at 7:29pm
$:/tags/SideBar
  1. Introduction
  2. TiddlyWiki - A quick Overview
  3. Microkernel Architecture
  4. TiddlyWiki Core Application
  5. Conclusion

overview.svg

8th July 2014 at 4:54pm