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 npm 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:

Because the polyfill is meant to be used in the browser we need to conditionally load the library which ES2016 doesn't allow. This is why it is written using TiddlyWiki's dependency resolver instead of using ES2015 import statements.

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

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

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.

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.

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.

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.

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.

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.

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.

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}).

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.

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.

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.

Step by step

1. Installation

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.

1. Add all files

2. Commit to your local repository

3. Copy local changes to github

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.

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.

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.

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(null, "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.

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 "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.

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:

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:

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.

Welcome to the developer documentation for TiddlyWiki (https://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:

An assignment by Christian Jurke and Christian Heigele, two students working on their Master's degree in Information Technology at the Gießen University of Applied Sciences (Technische Hochschule Mittelhessen). Their work can be seen in the Introduction and the tiddlers that link from it.

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.

This hook allows plugins to inspect or modify the details of files imported via drag and drop or the "import" button. It is invoked as each File object provided by the browser in response to an import or drag and drop is being read. The hook function can choose to ignore the file, in which case TiddlyWiki's default processing proceeds to read and import the content of the file. Alternatively, the hook function can process the file to extract the tiddlers itself, and then pass them back to TiddlyWiki to be handled by the rest of the import process.

Use this hook if you want to control how tiddlers are extracted from files during an import. See Hook: th-importing-tiddler if you want to process each imported tiddler after they have been extracted from the files.

Hook function parameters:

info: an object with properties containing information relating to the current file:

This hook allows plugins to inspect or modify tiddlers as they are imported via the import mechanism. It is invoked when the final "Import" button is clicked, and the selected tiddlers are being imported into the store.

Use this hook if you want to process each imported tiddler after they have been extracted from the files. See Hook: th-importing-file if you want to control how tiddlers are extracted from files during an import.

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.

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.

This hook allows plugins to extend the TiddlyWiki server command after it initializes. The two
most obvious use cases are adding routes (such as an attachments folder for external files)
to the SimpleServer instance and adding a websockets handler to the HTTP server.

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.

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:

Overview

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:

Either "plugin" for a regular plugin, "theme" for a theme, or "language" for a language pack

type

Set to "application/json"

version

Set 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:

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:

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.

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.

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.

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.

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 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.

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.

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.

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.

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.

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.

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.

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.

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.

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.