This is the first in a 3-part series on the internal design of Tiddlywiki. The series is more or less stream of consciousness - I’m a green Tiddlywiki developer, so I’ve been making these notes as I trawl through the source and learn it myself. Thanks to various people at Osmosoft for explaining some of this, and special thanks to Jeremy for some overviews and reviewing the writing here, Saq for a great overview on many feature, and Fred for reviewing the initially published version.
A Tiddlywiki is a collection of “tiddlers”, small blocks of content typically a paragaph or so in length. At any time, a subset of these tiddlers is displayed in the UI (between zero and the total number of stored tiddlers).
In the file, all the tiddlers are stored inside invisible DIVs, which are read on startup into a “TiddlyWiki” data structure. When you invoke the save feature, for example by hitting the “save changes” control, the invisible DIVs are refreshed with latest content from memory, and the entire file is written out to the hard drive.
TiddlyWiki is much more than a specialised wiki - due to its flexible architecture and the possibility of plugins, it is more like a platform. Examples of apps built on Tiddlywiki.
TiddlyWeb, though not discussed specifically here, marks an important step in the future of TiddlyWiki development. It’s a RESTful server of Tiddlers which would allow for great flexibility in the kinds of UIs you end up with, as well as allowing non-UI clients.
Anatomy of a Tiddlywiki
The image below shows an Tiddlywiki in editable mode. As for the UI, you can see it consists of a main area with two sidebars. The main area is a “Story” - a story is a sequence of visible tiddlers.
A lot of this is configurable by changing special tiddlers. In particular, the tiddler called “PageTemplate” provides the overall structure, with references to other tiddlers, and “Stylesheet” the CSS styles.
Object-Oriented Concepts in Tiddlywiki
Tiddlywiki’s OO relies on the constructor function pattern, where you create new objects using the new keyword.
All of the attributes above are public, but Tiddlywiki also uses closures to ensure some attributes are only available externally via declared methods. For example, the tiddlers of a Tiddlywiki is a declared as a local variable, so there’s no direct reference to it outside the methods declared in the same scope.
The above methods will also be available on each instance created with new, just as with those declared using the prototype assignment. They are used in exactly the same way. The only difference is that all these functions are re-created with each new instance, so they will consume more memory. That’s the price we pay for the encapsulation.
And that’s how Tiddlywiki handles basic OO.
Tiddlywiki uses the fragment identifier pattern (described here) to provide flexible loading strategies.
Normally, the “DefaultTiddlers” shadow tiddler is used to specify which tiddlers are shown on startup. However, this can be overridden via URL params. For example, use http://www.tiddlywiki.com/#Examples to load with just the Examples tiddler showing. Or, for multiple tiddlers, just separate with a space (%20 in URL-5peak) http://www.tiddlywiki.com/#Examples%20Plugins. (An interesting possibility would be for Tiddlywiki to keep updating the URL to ensure its sync’d with the state of the app, so you could bookmark it at any time to save that configuration.)
But maybe you don’t want to manually list all the tiddlers - instead, you might want to show all tiddlers matching some criteria. Then you’d want an automated mechanism for auto-selecting those criteria (think iTunes Smart Playlist for dramatic effect.) This would make the URL shorter, easier to understand the true purpose of the configuation, and future-proof it against any changes to the set of tiddlers we’re interested in.
In Tiddlywiki, that mechanism is achieved with a URL “filter” prefix. For example, show all tiddlers with “systemConfig” tag - http://tiddlywiki.com/#filter:[tag[systemConfig]].
Other things you can do - http://tiddlywiki.com/#newTiddler:tiddlername - create a new tiddler, specifying the name
The URL is modelled as a map, i.e. key-value pairs. In the case of http://www.tiddlywiki.com/#Examples%20Plugins, that’s just an alias for the canonical map form, http://www.tiddlywiki.com/#open:Examples%20open:Plugins. All this is managed by the Paramifiers class.