tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject svn commit: r448401 [2/3] - in /tapestry/tapestry5/tapestry-core/trunk/src/site: apt/index.apt resources/tap5devwiki.html site.xml
Date Wed, 20 Sep 2006 23:23:26 GMT
Added: tapestry/tapestry5/tapestry-core/trunk/src/site/resources/tap5devwiki.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/resources/tap5devwiki.html?view=auto&rev=448401
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/resources/tap5devwiki.html (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/resources/tap5devwiki.html Wed Sep 20 16:23:25 2006
@@ -0,0 +1,5179 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<script type="text/javascript">
+var version = {major: 2, minor: 0, revision: 11, date: new Date("May 11, 2006"), extensions: {}};
+</script>
+<!--
+TiddlyWiki 2.0.11 by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
+
+Copyright (c) Osmosoft Limited 2004-2006
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+Neither the name of the Osmosoft Limited nor the names of its contributors may be
+used to endorse or promote products derived from this software without specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+<!--PRE-HEAD-START-->
+<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'>
+<!--PRE-HEAD-END-->
+<title> Tapestry 5 Brain Dump - The quick and dirty one-stop shopping of random ideas for Tapestry 5. </title>
+<script type="text/javascript">
+
+// ---------------------------------------------------------------------------------
+// Configuration repository
+// ---------------------------------------------------------------------------------
+
+// Miscellaneous options
+var config = {
+	numRssItems: 20, // Number of items in the RSS feed
+	animFast: 0.12, // Speed for animations (lower == slower)
+	animSlow: 0.01, // Speed for EasterEgg animations
+	cascadeFast: 20, // Speed for cascade animations (higher == slower)
+	cascadeSlow: 60, // Speed for EasterEgg cascade animations
+	cascadeDepth: 5 // Depth of cascade animation
+	};
+
+// Messages
+config.messages = {
+	messageClose: {},
+	dates: {}
+};
+
+// Options that can be set in the options panel and/or cookies
+config.options = {
+	chkRegExpSearch: false,
+	chkCaseSensitiveSearch: false,
+	chkAnimate: true,
+	txtUserName: "YourName",
+	chkSaveBackups: true,
+	chkAutoSave: false,
+	chkGenerateAnRssFeed: false,
+	chkSaveEmptyTemplate: false,
+	chkOpenInNewWindow: true,
+	chkToggleLinks: false,
+	chkHttpReadOnly: true,
+	chkForceMinorUpdate: false,
+	chkConfirmDelete: true,
+	txtBackupFolder: "",
+	txtMainTab: "tabTimeline",
+	txtMoreTab: "moreTabAll",
+	txtMaxEditRows: "30"
+	};
+	
+// List of notification functions to be called when certain tiddlers are changed or deleted
+config.notifyTiddlers = [
+	{name: "StyleSheetLayout", notify: refreshStyles},
+	{name: "StyleSheetColors", notify: refreshStyles},
+	{name: "StyleSheet", notify: refreshStyles},
+	{name: "StyleSheetPrint", notify: refreshStyles},
+	{name: "PageTemplate", notify: refreshPageTemplate},
+	{name: null, notify: refreshDisplay}
+	];
+
+// Default tiddler templates
+var DEFAULT_VIEW_TEMPLATE = 1;
+var DEFAULT_EDIT_TEMPLATE = 2;
+config.tiddlerTemplates = {
+	1: "ViewTemplate",
+	2: "EditTemplate"
+	};
+
+// More messages (rather a legacy layout that shouldn't really be like this)
+config.views = {
+	wikified: {
+		tag: {}
+		},
+	editor: {
+		tagChooser: {}
+		}
+	};
+
+// Macros; each has a 'handler' member that is inserted later
+config.macros = {
+	today: {},
+	version: {},
+	search: {sizeTextbox: 15},
+	tiddler: {},
+	tag: {},
+	tags: {},
+	tagging: {},
+	timeline: {},
+	allTags: {},
+	list: {
+		all: {},
+		missing: {},
+		orphans: {},
+		shadowed: {}
+		},
+	closeAll: {},
+	permaview: {},
+	saveChanges: {},
+	slider: {},
+	option: {},
+	newTiddler: {},
+	newJournal: {},
+	sparkline: {},
+	tabs: {},
+	gradient: {},
+	message: {},
+	view: {},
+	edit: {},
+	tagChooser: {},
+	toolbar: {},
+	br: {}
+	};
+
+// Commands supported by the toolbar macro
+config.commands = {
+	closeTiddler: {},
+	closeOthers: {},
+	editTiddler: {},
+	saveTiddler: {hideReadOnly: true},
+	cancelTiddler: {},
+	deleteTiddler: {hideReadOnly: true},
+	permalink: {},
+	references: {},
+	jump: {}
+	};
+
+// Browser detection... In a very few places, there's nothing else for it but to
+// know what browser we're using.
+config.userAgent = navigator.userAgent.toLowerCase();
+config.browser = {
+	isIE: config.userAgent.indexOf("msie") != -1 && config.userAgent.indexOf("opera") == -1,
+	isSafari: config.userAgent.indexOf("applewebkit") != -1,
+	isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
+	firefoxDate: /Gecko\/(\d{8})/i.exec(config.userAgent),
+	isLinux: config.userAgent.indexOf("linux") != -1,
+	isUnix: config.userAgent.indexOf("x11") != -1,
+	isMac: config.userAgent.indexOf("mac") != -1,
+	isWindows: config.userAgent.indexOf("win") != -1
+	};
+
+// Basic regular expressions
+config.textPrimitives = {
+	upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
+	lowerLetter: "[a-z\u00df-\u00ff_0-9\\-\u0151\u0171]",
+	anyLetter: "[A-Za-z\u00c0-\u00de\u00df-\u00ff_0-9\\-\u0150\u0170\u0151\u0171]"
+	};
+if(config.browser.isBadSafari)
+	config.textPrimitives = {
+		upperLetter: "[A-Z\u00c0-\u00de]",
+		lowerLetter: "[a-z\u00df-\u00ff_0-9\\-]",
+		anyLetter: "[A-Za-z\u00c0-\u00de\u00df-\u00ff_0-9\\-]"
+		}
+config.textPrimitives.anyDigit = "[0-9]";
+config.textPrimitives.anyNumberChar = "[0-9\\.E]";
+config.textPrimitives.urlPattern = "(?:file|http|https|mailto|ftp):[^\\s'\"]+(?:/|\\b)";
+config.textPrimitives.unWikiLink = "~";
+config.textPrimitives.wikiLink = "(?:" + config.textPrimitives.unWikiLink + "{0,1})(?:(?:" + config.textPrimitives.upperLetter + "+" +
+												  config.textPrimitives.lowerLetter + "+" +
+												  config.textPrimitives.upperLetter +
+												  config.textPrimitives.anyLetter + "*)|(?:" +
+												  config.textPrimitives.upperLetter + "{2,}" +
+												  config.textPrimitives.lowerLetter + "+))";
+
+// ---------------------------------------------------------------------------------
+// Shadow tiddlers for emergencies
+// ---------------------------------------------------------------------------------
+
+config.shadowTiddlers = {
+	StyleSheet: "/***\nPlace your custom CSS here\n***/\n/*{{{*/\n\n/*}}}*/\n",
+	StyleSheetColors: "/***\n!Colors Used\n*@@bgcolor(#8cf): #8cf - Background blue@@\n*@@bgcolor(#18f): #18f - Top blue@@\n*@@bgcolor(#04b): #04b - Mid blue@@\n*@@bgcolor(#014):color(#fff): #014 - Bottom blue@@\n*@@bgcolor(#ffc): #ffc - Bright yellow@@\n*@@bgcolor(#fe8): #fe8 - Highlight yellow@@\n*@@bgcolor(#db4): #db4 - Background yellow@@\n*@@bgcolor(#841): #841 - Border yellow@@\n*@@bgcolor(#703):color(#fff): #703 - Title red@@\n*@@bgcolor(#866): #866 - Subtitle grey@@\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n	background: #fff;\n	color: #000;\n}\n\na{\n	color: #04b;\n}\n\na:hover{\n	background: #04b;\n	color: #fff;\n}\n\na img{\n	border: 0;\n}\n\nh1,h2,h3,h4,h5 {\n	color: #703;\n	background: #8cf;\n}\n\n.button {\n	color: #014;\n	border: 1px solid #fff;\n}\n\n.button:hover {\n	color: #014;\n	background: #fe8;\n	border-color: #db4;\n}\n\n.button:active {\n	color: #fff;\n	background: #db4;\n	border: 1px solid #841;\n}\n\n/*}}
 }*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n.header {\n	background: #04b;\n}\n\n.headerShadow {\n	color: #000;\n}\n\n.headerShadow a {\n	font-weight: normal;\n	color: #000;\n}\n\n.headerForeground {\n	color: #fff;\n}\n\n.headerForeground a {\n	font-weight: normal;\n	color: #8cf;\n}\n\n/*}}}*/\n/***\n!General tabs /%=================================================%/\n***/\n/*{{{*/\n\n.tabSelected{\n	color: #014;\n	background: #eee;\n	border-left: 1px solid #ccc;\n	border-top: 1px solid #ccc;\n	border-right: 1px solid #ccc;\n}\n\n.tabUnselected {\n	color: #fff;\n	background: #999;\n}\n\n.tabContents {\n	color: #014;\n	background: #eee;\n	border: 1px solid #ccc;\n}\n\n.tabContents .button {\n	 border: 0;}\n\n/*}}}*/\n/***\n!Sidebar options /%=================================================%/\n~TiddlyLinks and buttons are treated identically in the sidebar and slider panel\n***/\n/*{{{*/\n#sidebar {\n}\n\n#sidebarOptions input {\n	
 border: 1px solid #04b;\n}\n\n#sidebarOptions .sliderPanel {\n	background: #8cf;\n}\n\n#sidebarOptions .sliderPanel a {\n	border: none;\n	color: #04b;\n}\n\n#sidebarOptions .sliderPanel a:hover {\n	color: #fff;\n	background: #04b;\n}\n\n#sidebarOptions .sliderPanel a:active {\n	color: #04b;\n	background: #fff;\n}\n/*}}}*/\n/***\n!Message Area /%=================================================%/\n***/\n/*{{{*/\n#messageArea {\n	border: 1px solid #841;\n	background: #db4;\n	color: #014;\n}\n\n#messageArea .button {\n	padding: 0.2em 0.2em 0.2em 0.2em;\n	color: #014;\n	background: #fff;\n}\n\n/*}}}*/\n/***\n!Popup /%=================================================%/\n***/\n/*{{{*/\n.popup {\n	background: #18f;\n	border: 1px solid #04b;\n}\n\n.popup hr {\n	color: #014;\n	background: #014;\n	border-bottom: 1px;\n}\n\n.popup li.disabled {\n	color: #04b;\n}\n\n.popup li a, .popup li a:visited {\n	color: #eee;\n	border: none;\n}\n\n.popup li a:hover {\n	background: #014;\n	color: #
 fff;\n	border: none;\n}\n/*}}}*/\n/***\n!Tiddler Display /%=================================================%/\n***/\n/*{{{*/\n.tiddler .defaultCommand {\n font-weight: bold;\n}\n\n.shadow .title {\n	color: #866;\n}\n\n.title {\n	color: #703;\n}\n\n.subtitle {\n	color: #866;\n}\n\n.toolbar {\n	color: #04b;\n}\n\n.tagging, .tagged {\n	border: 1px solid #eee;\n	background-color: #eee;\n}\n\n.selected .tagging, .selected .tagged {\n	background-color: #ddd;\n	border: 1px solid #bbb;\n}\n\n.tagging .listTitle, .tagged .listTitle {\n	color: #014;\n}\n\n.tagging .button, .tagged .button {\n		border: none;\n}\n\n.footer {\n	color: #ddd;\n}\n\n.selected .footer {\n	color: #888;\n}\n\n.sparkline {\n	background: #8cf;\n	border: 0;\n}\n\n.sparktick {\n	background: #014;\n}\n\n.errorButton {\n	color: #ff0;\n	background: #f00;\n}\n\n.cascade {\n	background: #eef;\n	color: #aac;\n	border: 1px solid #aac;\n}\n\n.imageLink, #displayArea .imageLink {\n	background: transparent;\n}\n\n/*}}}*/\n
 /***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n\n.viewer .listTitle {list-style-type: none; margin-left: -2em;}\n\n.viewer .button {\n	border: 1px solid #db4;\n}\n\n.viewer blockquote {\n	border-left: 3px solid #666;\n}\n\n.viewer table {\n	border: 2px solid #333;\n}\n\n.viewer th, thead td {\n	background: #db4;\n	border: 1px solid #666;\n	color: #fff;\n}\n\n.viewer td, .viewer tr {\n	border: 1px solid #666;\n}\n\n.viewer pre {\n	border: 1px solid #fe8;\n	background: #ffc;\n}\n\n.viewer code {\n	color: #703;\n}\n\n.viewer hr {\n	border: 0;\n	border-top: dashed 1px #666;\n	color: #666;\n}\n\n.highlight, .marked {\n	background: #fe8;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor input {\n	border: 1px solid #04b;\n}\n\n.editor textarea {\n	border: 1px solid #04b;\n	width: 100%;\n}\n\n.editorFoote
 r {\n	color: #aaa;\n}\n\n/*}}}*/",
+	StyleSheetLayout: "/***\n!Sections in this Tiddler:\n*Generic rules\n**Links styles\n**Link Exceptions\n*Header\n*Main menu\n*Sidebar\n**Sidebar options\n**Sidebar tabs\n*Message area\n*Popup\n*Tabs\n*Tiddler display\n**Viewer\n**Editor\n*Misc. rules\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n	font-size: .75em;\n	font-family: arial,helvetica;\n	position: relative;\n	margin: 0;\n	padding: 0;\n}\n\nh1,h2,h3,h4,h5 {\n	font-weight: bold;\n	text-decoration: none;\n	padding-left: 0.4em;\n}\n\nh1 {font-size: 1.35em;}\nh2 {font-size: 1.25em;}\nh3 {font-size: 1.1em;}\nh4 {font-size: 1em;}\nh5 {font-size: .9em;}\n\nhr {\n	height: 1px;\n}\n\na{\n	text-decoration: none;\n}\n\nol { list-style-type: decimal }\nol ol { list-style-type: lower-alpha }\nol ol ol { list-style-type: lower-roman }\nol ol ol ol { list-style-type: decimal }\nol ol ol ol ol { list-style-type: lower-alpha }\nol ol ol ol ol ol { list-style-type: lower-roman }\nol ol ol
  ol ol ol ol { list-style-type: decimal }\n/*}}}*/\n/***\n''General Link Styles'' /%-----------------------------------------------------------------------------%/\n***/\n/*{{{*/\n.externalLink {\n	text-decoration: underline;\n}\n\n.tiddlyLinkExisting {\n	font-weight: bold;\n}\n\n.tiddlyLinkNonExisting {\n	font-style: italic;\n}\n\n/* the 'a' is required for IE, otherwise it renders the whole tiddler a bold */\na.tiddlyLinkNonExisting.shadow {\n	font-weight: bold;\n}\n/*}}}*/\n/***\n''Exceptions to common link styles'' /%------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#mainMenu .tiddlyLinkExisting, \n#mainMenu .tiddlyLinkNonExisting,\n#sidebarTabs .tiddlyLinkExisting,\n#sidebarTabs .tiddlyLinkNonExisting{\n font-weight: normal;\n font-style: normal;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n\n.header {\n		position: relative;\n}\n\n.header a:hover {\n	background: transparent;\n}\n
 \n.headerShadow {\n	position: relative;\n	padding: 4.5em 0em 1em 1em;\n	left: -1px;\n	top: -1px;\n}\n\n.headerForeground {\n	position: absolute;\n	padding: 4.5em 0em 1em 1em;\n	left: 0px;\n	top: 0px;\n}\n\n.siteTitle {\n	font-size: 3em;\n}\n\n.siteSubtitle {\n	font-size: 1.2em;\n}\n\n/*}}}*/\n/***\n!Main menu /%==================================================%/\n***/\n/*{{{*/\n#mainMenu {\n	position: absolute;\n	left: 0;\n	width: 10em;\n	text-align: right;\n	line-height: 1.6em;\n	padding: 1.5em 0.5em 0.5em 0.5em;\n	font-size: 1.1em;\n}\n\n/*}}}*/\n/***\n!Sidebar rules /%==================================================%/\n***/\n/*{{{*/\n#sidebar {\n	position: absolute;\n	right: 3px;\n	width: 16em;\n	font-size: .9em;\n}\n/*}}}*/\n/***\n''Sidebar options'' /%----------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n#sidebarOptions {\n	padding-top: 0.3em;\n}\n\n#sidebarOptions a {\n	margin: 0em 0.2em;\n	padding: 0.2em 0.3em;\n	displ
 ay: block;\n}\n\n#sidebarOptions input {\n	margin: 0.4em 0.5em;\n}\n\n#sidebarOptions .sliderPanel {\n	margin-left: 1em;\n	padding: 0.5em;\n	font-size: .85em;\n}\n\n#sidebarOptions .sliderPanel a {\n	font-weight: bold;\n	display: inline;\n	padding: 0;\n}\n\n#sidebarOptions .sliderPanel input {\n	margin: 0 0 .3em 0;\n}\n/*}}}*/\n/***\n''Sidebar tabs'' /%-------------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#sidebarTabs .tabContents {\n	width: 15em;\n	overflow: hidden;\n}\n\n/*}}}*/\n/***\n!Message area /%==================================================%/\n***/\n/*{{{*/\n#messageArea {\nposition:absolute; top:0; right:0; margin: 0.5em; padding: 0.5em;\n}\n\n*[id='messageArea'] {\nposition:fixed !important; z-index:99;}\n\n.messageToolbar {\ndisplay: block;\ntext-align: right;\n}\n\n#messageArea a{\n	text-decoration: underline;\n}\n/*}}}*/\n/***\n!Popup /%==================================================%/\n***/\n/*{{{*/\n.
 popup {\n	font-size: .9em;\n	padding: 0.2em;\n	list-style: none;\n	margin: 0;\n}\n\n.popup hr {\n	display: block;\n	height: 1px;\n	width: auto;\n	padding: 0;\n	margin: 0.2em 0em;\n}\n\n.popup li.disabled {\n	padding: 0.2em;\n}\n\n.popup li a{\n	display: block;\n	padding: 0.2em;\n}\n/*}}}*/\n/***\n!Tabs /%==================================================%/\n***/\n/*{{{*/\n.tabset {\n	padding: 1em 0em 0em 0.5em;\n}\n\n.tab {\n	margin: 0em 0em 0em 0.25em;\n	padding: 2px;\n}\n\n.tabContents {\n	padding: 0.5em;\n}\n\n.tabContents ul, .tabContents ol {\n	margin: 0;\n	padding: 0;\n}\n\n.txtMainTab .tabContents li {\n	list-style: none;\n}\n\n.tabContents li.listLink {\n	 margin-left: .75em;\n}\n/*}}}*/\n/***\n!Tiddler display rules /%==================================================%/\n***/\n/*{{{*/\n#displayArea {\n	margin: 1em 17em 0em 14em;\n}\n\n\n.toolbar {\n	text-align: right;\n	font-size: .9em;\n	visibility: hidden;\n}\n\n.selected .toolbar {\n	visibility: visible;\n}\n\n.t
 iddler {\n	padding: 1em 1em 0em 1em;\n}\n\n.missing .viewer,.missing .title {\n	font-style: italic;\n}\n\n.title {\n	font-size: 1.6em;\n	font-weight: bold;\n}\n\n.missing .subtitle {\n display: none;\n}\n\n.subtitle {\n	font-size: 1.1em;\n}\n\n/* I'm not a fan of how button looks in tiddlers... */\n.tiddler .button {\n	padding: 0.2em 0.4em;\n}\n\n.tagging {\nmargin: 0.5em 0.5em 0.5em 0;\nfloat: left;\ndisplay: none;\n}\n\n.isTag .tagging {\ndisplay: block;\n}\n\n.tagged {\nmargin: 0.5em;\nfloat: right;\n}\n\n.tagging, .tagged {\nfont-size: 0.9em;\npadding: 0.25em;\n}\n\n.tagging ul, .tagged ul {\nlist-style: none;margin: 0.25em;\npadding: 0;\n}\n\n.tagClear {\nclear: both;\n}\n\n.footer {\n	font-size: .9em;\n}\n\n.footer li {\ndisplay: inline;\n}\n/***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n* html .viewer pre {\n	width: 99%;\n	padding: 0 0 1em 0;\n}\n\n.viewer {\n	line-height: 1.4em;\n	pa
 dding-top: 0.5em;\n}\n\n.viewer .button {\n	margin: 0em 0.25em;\n	padding: 0em 0.25em;\n}\n\n.viewer blockquote {\n	line-height: 1.5em;\n	padding-left: 0.8em;\n	margin-left: 2.5em;\n}\n\n.viewer ul, .viewer ol{\n	margin-left: 0.5em;\n	padding-left: 1.5em;\n}\n\n.viewer table {\n	border-collapse: collapse;\n	margin: 0.8em 1.0em;\n}\n\n.viewer th, .viewer td, .viewer tr,.viewer caption{\n	padding: 3px;\n}\n\n.viewer pre {\n	padding: 0.5em;\n	margin-left: 0.5em;\n	font-size: 1.2em;\n	line-height: 1.4em;\n	overflow: auto;\n}\n\n.viewer code {\n	font-size: 1.2em;\n	line-height: 1.4em;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor {\nfont-size: 1.1em;\n}\n\n.editor input, .editor textarea {\n	display: block;\n	width: 100%;\n	font: inherit;\n}\n\n.editorFooter {\n	padding: 0.25em 0em;\n	font-size: .9em;\n}\n\n.editorFooter .button {\npadding-top: 0px; padding-bottom: 0px;}\n\n.fields
 etFix {border: 0;\npadding: 0;\nmargin: 1px 0px 1px 0px;\n}\n/*}}}*/\n/***\n!Misc rules /%==================================================%/\n***/\n/*{{{*/\n.sparkline {\n	line-height: 1em;\n}\n\n.sparktick {\n	outline: 0;\n}\n\n.zoomer {\n	font-size: 1.1em;\n	position: absolute;\n	padding: 1em;\n}\n\n.cascade {\n	font-size: 1.1em;\n	position: absolute;\n	overflow: hidden;\n}\n/*}}}*/",
+	StyleSheetPrint: "@media print {\n#mainMenu, #sidebar, #messageArea {display: none ! important;}\n#displayArea {margin: 1em 1em 0em 1em;}\n/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */\nnoscript {display:none;}\n}",
+	PageTemplate: "<div class='header' macro='gradient vert #18f #04b'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>",
+	ViewTemplate: "<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (created <span macro='view created date [[DD MMM YYYY]]'></span>)</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>",
+	EditTemplate: "<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>",
+	MarkupPreHead: "<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'>",
+	MarkupPostHead: "",
+	MarkupPreBody: "",
+	MarkupPostBody: ""
+	};
+
+// ---------------------------------------------------------------------------------
+// Translateable strings
+// ---------------------------------------------------------------------------------
+
+// Messages
+merge(config.messages,{
+	customConfigError: "Error in systemConfig tiddler '%1' - %0",
+	savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see http://www.tiddlywiki.com/#DownloadSoftware for details",
+	subtitleUnknown: "(unknown)",
+	undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
+	shadowedTiddlerToolTip: "The tiddler '%0' doesn't yet exist, but has a pre-defined shadow value",
+	tiddlerLinkTooltip: "%0 - %1, %2",
+	externalLinkTooltip: "External link to %0",
+	noTags: "There are no tagged tiddlers",
+	notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
+	cantSaveError: "It's not possible to save changes. This could be because your browser doesn't support saving (instead, use FireFox if you can), or because the pathname to your TiddlyWiki file contains illegal characters",
+	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
+	backupSaved: "Backup saved",
+	backupFailed: "Failed to save backup file",
+	rssSaved: "RSS feed saved",
+	rssFailed: "Failed to save RSS feed file",
+	emptySaved: "Empty template saved",
+	emptyFailed: "Failed to save empty template file",
+	mainSaved: "Main TiddlyWiki file saved",
+	mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
+	macroError: "Error in macro <<%0>>",
+	macroErrorDetails: "Error while executing macro <<%0>>:\n%1",
+	missingMacro: "No such macro",
+	overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
+	unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
+	confirmExit: "--------------------------------\n\nThere are unsaved changes in TiddlyWiki. If you continue you will lose those changes\n\n--------------------------------",
+	saveInstructions: "SaveChanges"});
+
+merge(config.messages.messageClose,{
+	text: "close",
+	tooltip: "close this message area"});
+
+config.messages.dates.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"];
+config.messages.dates.days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
+
+merge(config.views.wikified.tag,{
+	labelNoTags: "no tags",
+	labelTags: "tags: ",
+	openTag: "Open tag '%0'",
+	tooltip: "Show tiddlers tagged with '%0'",
+	openAllText: "Open all",
+	openAllTooltip: "Open all of these tiddlers",
+	popupNone: "No other tiddlers tagged with '%0'"});
+
+merge(config.views.wikified,{
+	defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it",
+	defaultModifier: "(missing)",
+	shadowModifier: "(shadow)"});
+
+merge(config.views.editor,{
+	tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
+	defaultText: "Type the text for '%0'"});
+
+merge(config.views.editor.tagChooser,{
+	text: "tags",
+	tooltip: "Choose existing tags to add to this tiddler",
+	popupNone: "There are no tags defined",
+	tagTooltip: "Add the tag '%0'"});
+
+merge(config.macros.search,{
+	label: "search",
+	prompt: "Search this TiddlyWiki",
+	accessKey: "F",
+	successMsg: "%0 tiddlers found matching %1",
+	failureMsg: "No tiddlers found matching %0"});
+
+merge(config.macros.tagging,{
+	label: "tagging:",
+	labelNotTag: "not tagging",
+	tooltip: "List of tiddlers tagged with '%0'"});
+
+merge(config.macros.timeline,{
+	dateFormat: "DD MMM YYYY"});
+
+merge(config.macros.allTags,{
+	tooltip: "Show tiddlers tagged with '%0'",
+	noTags: "There are no tagged tiddlers"});
+
+config.macros.list.all.prompt = "All tiddlers in alphabetical order";
+config.macros.list.missing.prompt = "Tiddlers that have links to them but are not defined";
+config.macros.list.orphans.prompt = "Tiddlers that are not linked to from any other tiddlers";
+config.macros.list.shadowed.prompt = "Tiddlers shadowed with default contents";
+
+merge(config.macros.closeAll,{
+	label: "close all",
+	prompt: "Close all displayed tiddlers (except any that are being edited)"});
+
+merge(config.macros.permaview,{
+	label: "permaview",
+	prompt: "Link to an URL that retrieves all the currently displayed tiddlers"});
+
+merge(config.macros.saveChanges,{
+	label: "save changes",
+	prompt: "Save all tiddlers to create a new TiddlyWiki",
+	accessKey: "S"});
+
+merge(config.macros.newTiddler,{
+	label: "new tiddler",
+	prompt: "Create a new tiddler",
+	title: "New Tiddler",
+	accessKey: "N"});
+
+merge(config.macros.newJournal,{
+	label: "new journal",
+	prompt: "Create a new tiddler from the current date and time",
+	accessKey: "J"});
+
+merge(config.commands.closeTiddler,{
+	text: "close",
+	tooltip: "Close this tiddler"});
+
+merge(config.commands.closeOthers,{
+	text: "close others",
+	tooltip: "Close all other tiddlers"});
+
+merge(config.commands.editTiddler,{
+	text: "edit",
+	tooltip: "Edit this tiddler",
+	readOnlyText: "view",
+	readOnlyTooltip: "View the source of this tiddler"});
+
+merge(config.commands.saveTiddler,{
+	text: "done",
+	tooltip: "Save changes to this tiddler"});
+
+merge(config.commands.cancelTiddler,{
+	text: "cancel",
+	tooltip: "Undo changes to this tiddler",
+	warning: "Are you sure you want to abandon your changes to '%0'?",
+	readOnlyText: "done",
+	readOnlyTooltip: "View this tiddler normally"});
+
+merge(config.commands.deleteTiddler,{
+	text: "delete",
+	tooltip: "Delete this tiddler",
+	warning: "Are you sure you want to delete '%0'?"});
+
+merge(config.commands.permalink,{
+	text: "permalink",
+	tooltip: "Permalink for this tiddler"});
+
+merge(config.commands.references,{
+	text: "references",
+	tooltip: "Show tiddlers that link to this one",
+	popupNone: "No references"});
+
+merge(config.commands.jump,{
+	text: "jump",
+	tooltip: "Jump to another open tiddler"});
+
+merge(config.shadowTiddlers,{
+	DefaultTiddlers: "GettingStarted",
+	MainMenu: "GettingStarted",
+	SiteTitle: "My TiddlyWiki",
+	SiteSubtitle: "a reusable non-linear personal web notebook",
+	SiteUrl: "http://www.tiddlywiki.com/",
+	GettingStarted: "To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:\n* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)\n* MainMenu: The menu (usually on the left)\n* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened\nYou'll also need to enter your username for signing your edits: <<option txtUserName>>",
+	SideBarOptions: "<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>",
+	OptionsPanel: "These InterfaceOptions for customising TiddlyWiki are saved in your browser\n\nYour username for signing your edits. Write it as a WikiWord (eg JoeBloggs)\n\n<<option txtUserName>>\n<<option chkSaveBackups>> SaveBackups\n<<option chkAutoSave>> AutoSave\n<<option chkRegExpSearch>> RegExpSearch\n<<option chkCaseSensitiveSearch>> CaseSensitiveSearch\n<<option chkAnimate>> EnableAnimations\n\nSee AdvancedOptions",
+	AdvancedOptions: "<<option chkGenerateAnRssFeed>> GenerateAnRssFeed\n<<option chkOpenInNewWindow>> OpenLinksInNewWindow\n<<option chkSaveEmptyTemplate>> SaveEmptyTemplate\n<<option chkToggleLinks>> Clicking on links to tiddlers that are already open causes them to close\n^^(override with Control or other modifier key)^^\n<<option chkHttpReadOnly>> HideEditingFeatures when viewed over HTTP\n<<option chkForceMinorUpdate>> Treat edits as MinorChanges by preserving date and time\n^^(override with Shift key when clicking 'done' or by pressing Ctrl-Shift-Enter^^\n<<option chkConfirmDelete>> ConfirmBeforeDeleting\nMaximum number of lines in a tiddler edit box: <<option txtMaxEditRows>>\nFolder name for backup files: <<option txtBackupFolder>>\n",
+	SideBarTabs: "<<tabs txtMainTab Timeline Timeline TabTimeline All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>",
+	TabTimeline: "<<timeline>>",
+	TabAll: "<<list all>>",
+	TabTags: "<<allTags>>",
+	TabMore: "<<tabs txtMoreTab Missing 'Missing tiddlers' TabMoreMissing Orphans 'Orphaned tiddlers' TabMoreOrphans Shadowed 'Shadowed tiddlers' TabMoreShadowed>>",
+	TabMoreMissing: "<<list missing>>",
+	TabMoreOrphans: "<<list orphans>>",
+	TabMoreShadowed: "<<list shadowed>>"});
+
+// ---------------------------------------------------------------------------------
+// Main
+// ---------------------------------------------------------------------------------
+
+var params = null; // Command line parameters
+var store = null; // TiddlyWiki storage
+var story = null; // Main story
+var formatter = null; // Default formatters for the wikifier
+var anim = new Animator(); // Animation engine
+var readOnly = false; // Whether we're in readonly mode
+var highlightHack = null; // Embarrassing hack department...
+var hadConfirmExit = false; // Don't warn more than once
+var safeMode = false; // Disable all plugins and cookies
+
+// Starting up
+function main()
+{
+	params = getParameters();
+	if(params)
+		params = params.parseParams("open",null,false);
+	store = new TiddlyWiki();
+	invokeParamifier(params,"oninit");
+	story = new Story("tiddlerDisplay","tiddler");
+	addEvent(document,"click",Popup.onDocumentClick);
+	saveTest();
+	loadOptionsCookie();
+	for(var s=0; s<config.notifyTiddlers.length; s++)
+		store.addNotification(config.notifyTiddlers[s].name,config.notifyTiddlers[s].notify);
+	store.loadFromDiv("storeArea","store");
+	invokeParamifier(params,"onload");
+	loadSystemConfig();
+	formatter = new Formatter(config.formatters);
+	readOnly = (window.location.protocol == "file:") ? false : config.options.chkHttpReadOnly;
+	invokeParamifier(params,"onconfig");
+	store.notifyAll();
+	restart();
+}
+
+// Restarting
+function restart()
+{
+	invokeParamifier(params,"onstart");
+	if(story.isEmpty())
+		{
+		var defaultParams = store.getTiddlerText("DefaultTiddlers").parseParams("open",null,false);
+		invokeParamifier(defaultParams,"onstart");
+		}
+	window.scrollTo(0,0);
+}
+
+function saveTest()
+{
+	var saveTest = document.getElementById("saveTest");
+	if(saveTest.hasChildNodes())
+		alert(config.messages.savedSnapshotError);
+	saveTest.appendChild(document.createTextNode("savetest"));
+}
+
+function loadSystemConfig()
+{
+	if(safeMode)
+		return;
+	var configTiddlers = store.getTaggedTiddlers("systemConfig");
+	for(var t=0; t<configTiddlers.length; t++)
+		{
+		var ex = processConfig(configTiddlers[t].text);
+		if(ex)
+			displayMessage(config.messages.customConfigError.format([ex,configTiddlers[t].title]));
+		}
+}
+
+// Merge a custom configuration over the top of the current configuration
+// Returns a string error message or null if it went OK
+function processConfig(customConfig)
+{
+	try
+		{
+		if(customConfig && customConfig != "")
+			window.eval(customConfig);
+		}
+	catch(e)
+		{
+		return(e.description ? e.description : e.toString());
+		}
+	return null;
+}
+
+function invokeMacro(place,macro,params,wikifier,tiddler)
+{
+	try
+		{
+		var m = config.macros[macro];
+		if(m && m.handler)
+			m.handler(place,macro,params.readMacroParams(),wikifier,params,tiddler);
+		else
+			createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,config.messages.missingMacro]));
+		}
+	catch(ex)
+		{
+		createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,ex.toString()]));
+		}
+}
+
+// ---------------------------------------------------------------------------------
+// Paramifiers
+// ---------------------------------------------------------------------------------
+
+function getParameters()
+{
+	var p = null;
+	if(window.location.hash)
+		{
+		p = decodeURI(window.location.hash.substr(1));
+		if(config.browser.firefoxDate == null || config.browser.firefoxDate[1] < "20051111")
+			p = convertUTF8ToUnicode(p);
+		}
+	return p;
+}
+
+function invokeParamifier(params,handler)
+{
+	if(!params || params.length == undefined || params.length <= 1)
+		return;
+	for(var t=1; t<params.length; t++)
+		{
+		var p = config.paramifiers[params[t].name];
+		if(p && p[handler] instanceof Function)
+			p[handler](params[t].value);
+		}
+}
+
+config.paramifiers = {};
+
+config.paramifiers.start = {
+	oninit: function(v) {
+		safeMode = v.toLowerCase() == "safe";
+		}
+};
+
+config.paramifiers.open = {
+	onstart: function(v) {
+		story.displayTiddler("bottom",v,null,false,false);
+		}
+};
+
+config.paramifiers.search = {
+	onstart: function(v) {
+		story.search(v,false,false);
+		}
+};
+
+config.paramifiers.tag = {
+	onstart: function(v) {
+		var tagged = store.getTaggedTiddlers(v,"title");
+		for(var t=0; t<tagged.length; t++)
+			story.displayTiddler("bottom",tagged[t].title,null,false,false);
+		}
+};
+
+config.paramifiers.newTiddler = {
+	onstart: function(v) {
+		if(!readOnly)
+			{
+			story.displayTiddler(null,v,DEFAULT_EDIT_TEMPLATE);
+			story.focusTiddler(v,"text");
+			}
+		}
+};
+
+config.paramifiers.newJournal = {
+	onstart: function(v) {
+		if(!readOnly)
+			{
+			var now = new Date();
+			var title = now.formatString(v.trim());
+			story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
+			story.focusTiddler(title,"text");
+			}
+		}
+};
+
+// ---------------------------------------------------------------------------------
+// Formatters
+// ---------------------------------------------------------------------------------
+
+function Formatter(formatters)
+{
+	this.formatters = [];
+	var pattern = [];
+	for(var n=0; n<formatters.length; n++)
+		{
+		pattern.push("(" + formatters[n].match + ")");
+		this.formatters.push(formatters[n]);
+		}
+	this.formatterRegExp = new RegExp(pattern.join("|"),"mg");
+}
+
+config.formatterHelpers = {
+
+	charFormatHelper: function(w)
+	{
+		var e = createTiddlyElement(w.output,this.element);
+		w.subWikify(e,this.terminator);
+	},
+	
+	inlineCssHelper:  function(w)
+	{
+		var styles = [];
+		var lookahead = "(?:(" + config.textPrimitives.anyLetter + "+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + config.textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
+		var lookaheadRegExp = new RegExp(lookahead,"mg");
+		var hadStyle = false;
+		do {
+			lookaheadRegExp.lastIndex = w.nextMatch;
+			var lookaheadMatch = lookaheadRegExp.exec(w.source);
+			var gotMatch = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
+			if(gotMatch)
+				{
+				var s,v;
+				hadStyle = true;
+				if(lookaheadMatch[1])
+					{
+					s = lookaheadMatch[1].unDash();
+					v = lookaheadMatch[2];
+					}
+				else
+					{
+					s = lookaheadMatch[3].unDash();
+					v = lookaheadMatch[4];
+					}
+				switch(s)
+					{
+					case "bgcolor": s = "backgroundColor"; break;
+					}
+				styles.push({style: s, value: v});
+				w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+				}
+		} while(gotMatch);
+		return styles;
+	},
+
+	applyCssHelper: function(e,styles)
+	{
+		for(var t=0; t<styles.length; t++)
+			{
+			try
+				{
+				e.style[styles[t].style] = styles[t].value;
+				}
+			catch (ex)
+				{
+				}
+			}
+	},
+
+	monospacedByLineHelper: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source);
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
+			{
+			var text = lookaheadMatch[1];
+			if(config.browser.isIE)
+				text = text.replace(/\n/g,"\r");
+			var e = createTiddlyElement(w.output,"pre",null,null,text);
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			}
+	}
+
+};
+
+config.formatters = [
+{
+	name: "table",
+	match: "^\\|(?:[^\\n]*)\\|(?:[fhck]?)$",
+	lookahead: "^\\|([^\\n]*)\\|([fhck]?)$",
+	rowTerminator: "\\|(?:[fhck]?)$\\n?",
+	cellPattern: "(?:\\|([^\\n\\|]*)\\|)|(\\|[fhck]?$\\n?)",
+	cellTerminator: "(?:\\x20*)\\|",
+	rowTypes: {"c": "caption", "h": "thead", "": "tbody", "f": "tfoot"},
+	handler: function(w)
+	{
+		var table = createTiddlyElement(w.output,"table");
+		w.nextMatch = w.matchStart;
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		var currRowType = null, nextRowType;
+		var rowContainer, rowElement;
+		var prevColumns = [];
+		var rowCount = 0;
+		do {
+			lookaheadRegExp.lastIndex = w.nextMatch;
+			var lookaheadMatch = lookaheadRegExp.exec(w.source);
+			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
+			if(matched)
+				{
+				nextRowType = lookaheadMatch[2];
+				if(nextRowType == "k")
+					{
+					table.className = lookaheadMatch[1];
+					w.nextMatch += lookaheadMatch[0].length+1;
+					continue;
+					}
+				if(nextRowType != currRowType)
+					rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);
+				currRowType = nextRowType;
+				if(currRowType == "c")
+					{
+					if(rowCount == 0)
+						rowContainer.setAttribute("align","top");
+					else
+						rowContainer.setAttribute("align","bottom");
+					w.nextMatch = w.nextMatch + 1;
+					w.subWikify(rowContainer,this.rowTerminator);
+					table.insertBefore(rowContainer,table.firstChild);
+					}
+				else
+					{
+					var rowClass = (rowCount & 1) ? "oddRow" : "evenRow";
+					rowElement = createTiddlyElement(rowContainer,"tr",null,rowClass);
+					this.rowHandler(w,rowElement,prevColumns);
+					}
+				rowCount++;
+				}
+		} while(matched);
+	},
+	rowHandler: function(w,e,prevColumns)
+	{
+		var col = 0;
+		var currColCount = 1;
+		var matched;
+		var cellRegExp = new RegExp(this.cellPattern,"mg");
+		do {
+			cellRegExp.lastIndex = w.nextMatch;
+			var cellMatch = cellRegExp.exec(w.source);
+			matched = cellMatch && cellMatch.index == w.nextMatch;
+			if(matched)
+				{
+				if(cellMatch[1] == "~")
+					{
+					var last = prevColumns[col];
+					if(last)
+						{
+						last.rowCount++;
+						last.element.setAttribute("rowSpan",last.rowCount);
+						last.element.setAttribute("rowspan",last.rowCount);
+						last.element.valign = "center";
+						}
+					w.nextMatch = cellMatch.index + cellMatch[0].length-1;
+					}
+				else if(cellMatch[1] == ">")
+					{
+					currColCount++;
+					w.nextMatch = cellMatch.index + cellMatch[0].length-1;
+					}
+				else if(cellMatch[2])
+					{
+					w.nextMatch = cellMatch.index + cellMatch[0].length;;
+					break;
+					}
+				else
+					{
+					var spaceLeft = false, spaceRight = false;
+					w.nextMatch++;
+					var styles = config.formatterHelpers.inlineCssHelper(w);
+					while(w.source.substr(w.nextMatch,1) == " ")
+						{
+						spaceLeft = true;
+						w.nextMatch++;
+						}
+					var cell;
+					if(w.source.substr(w.nextMatch,1) == "!")
+						{
+						cell = createTiddlyElement(e,"th");
+						w.nextMatch++;
+						}
+					else
+						cell = createTiddlyElement(e,"td");
+					prevColumns[col] = {rowCount: 1, element: cell};
+					if(currColCount > 1)
+						{
+						cell.setAttribute("colSpan",currColCount);
+						cell.setAttribute("colspan",currColCount);
+						currColCount = 1;
+						}
+					config.formatterHelpers.applyCssHelper(cell,styles);
+					w.subWikify(cell,this.cellTerminator);
+					if(w.matchText.substr(w.matchText.length-2,1) == " ")
+						spaceRight = true;
+					if(spaceLeft && spaceRight)
+						cell.align = "center";
+					else if (spaceLeft)
+						cell.align = "right";
+					else if (spaceRight)
+						cell.align = "left";
+					w.nextMatch = w.nextMatch-1;
+					}
+				col++;
+				}
+		} while(matched);		
+	}
+},
+
+{
+	name: "rule",
+	match: "^----+$\\n?",
+	handler: function(w)
+	{
+		createTiddlyElement(w.output,"hr");
+	}
+},
+
+{
+	name: "heading",
+	match: "^!{1,5}",
+	terminator: "\\n",
+	handler: function(w)
+	{
+		var e = createTiddlyElement(w.output,"h" + w.matchLength);
+		w.subWikify(e,this.terminator);
+	}
+},
+
+{
+	name: "monospacedByLine",
+	match: "^\\{\\{\\{\\n",
+	lookahead: "^\\{\\{\\{\\n((?:^[^\\n]*\\n)+?)(^\\}\\}\\}$\\n?)",
+	handler: config.formatterHelpers.monospacedByLineHelper
+},
+
+{
+	name: "monospacedByLineForCSS",
+	match: "^/\\*[\\{]{3}\\*/\\n",
+	lookahead: "/\\*[\\{]{3}\\*/\\n*((?:^[^\\n]*\\n)+?)(\\n*^/\\*[\\}]{3}\\*/$\\n?)", 
+	handler: config.formatterHelpers.monospacedByLineHelper
+},
+
+{
+	name: "monospacedByLineForPlugin",
+	match: "^//\\{\\{\\{\\n",
+	lookahead: "^//\\{\\{\\{\\n\\n*((?:^[^\\n]*\\n)+?)(\\n*^//\\}\\}\\}$\\n?)",
+	handler: config.formatterHelpers.monospacedByLineHelper
+},
+
+{
+	name: "monospacedByLineForTemplate",
+	match: "^<!--[\\{]{3}-->\\n",
+	lookahead: "<!--[\\{]{3}-->\\n*((?:^[^\\n]*\\n)+?)(\\n*^<!--[\\}]{3}-->$\\n?)", 
+	handler: config.formatterHelpers.monospacedByLineHelper
+},
+
+{
+	name: "wikifyCommentForPlugin", 
+	match: "^/\\*\\*\\*\\n",
+	terminator: "^\\*\\*\\*/\\n",
+	handler: function(w)
+	{
+		w.subWikify(w.output,this.terminator);
+	}
+},
+
+{
+	name: "wikifyCommentForTemplate", 
+	match: "^<!---\\n",
+	terminator: "^--->\\n",
+	handler: function(w) 
+	{
+		w.subWikify(w.output,this.terminator);
+	}
+},
+
+{
+	name: "quoteByBlock",
+	match: "^<<<\\n",
+	terminator: "^<<<(\\n|$)",
+	handler: function(w)
+	{
+		var e = createTiddlyElement(w.output,"blockquote");
+		w.subWikify(e,this.terminator);
+	}
+},
+
+{
+	name: "quoteByLine",
+	match: "^>+",
+	terminator: "\\n",
+	element: "blockquote",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.match,"mg");
+		var placeStack = [w.output];
+		var currLevel = 0;
+		var newLevel = w.matchLength;
+		var t;
+		do {
+			if(newLevel > currLevel)
+				{
+				for(t=currLevel; t<newLevel; t++)
+					placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],this.element));
+				}
+			else if(newLevel < currLevel)
+				{
+				for(t=currLevel; t>newLevel; t--)
+					placeStack.pop();
+				}
+			currLevel = newLevel;
+			w.subWikify(placeStack[placeStack.length-1],this.terminator);
+			createTiddlyElement(placeStack[placeStack.length-1],"br");
+			lookaheadRegExp.lastIndex = w.nextMatch;
+			var lookaheadMatch = lookaheadRegExp.exec(w.source);
+			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
+			if(matched)
+				{
+				newLevel = lookaheadMatch[0].length;
+				w.nextMatch += lookaheadMatch[0].length;
+				}
+		} while(matched);
+	}
+},
+
+{
+	name: "list",
+	match: "^(?:(?:\\*+)|(?:#+))",
+	lookahead: "^(?:(\\*+)|(#+))",
+	terminator: "\\n",
+	outerElement: "ul",
+	itemElement: "li",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		w.nextMatch = w.matchStart;
+		var placeStack = [w.output];
+		var currType = null, newType;
+		var currLevel = 0, newLevel;
+		var t;
+		do {
+			lookaheadRegExp.lastIndex = w.nextMatch;
+			var lookaheadMatch = lookaheadRegExp.exec(w.source);
+			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
+			if(matched)
+				{
+				if(lookaheadMatch[1])
+					newType = "ul";
+				if(lookaheadMatch[2])
+					newType = "ol";
+				newLevel = lookaheadMatch[0].length;
+				w.nextMatch += lookaheadMatch[0].length;
+				if(newLevel > currLevel)
+					{
+					for(t=currLevel; t<newLevel; t++)
+						placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],newType));
+					}
+				else if(newLevel < currLevel)
+					{
+					for(t=currLevel; t>newLevel; t--)
+						placeStack.pop();
+					}
+				else if(newLevel == currLevel && newType != currType)
+					{
+						placeStack.pop();
+						placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],newType));
+					}
+				currLevel = newLevel;
+				currType = newType;
+				var e = createTiddlyElement(placeStack[placeStack.length-1],"li");
+				w.subWikify(e,this.terminator);
+				}
+		} while(matched);
+	}
+},
+
+{
+	name: "wikiLink",
+	match: config.textPrimitives.wikiLink,
+	badPrefix: config.textPrimitives.anyLetter,
+	handler: function(w)
+	{
+		var preRegExp = new RegExp(config.textPrimitives.anyLetter,"mg");
+		var preMatch = null;
+		if(w.matchStart > 0)
+			{
+			preRegExp.lastIndex = w.matchStart-1;
+			preMatch = preRegExp.exec(w.source);
+			}
+		if(preMatch && preMatch.index == w.matchStart-1)
+			w.outputText(w.output,w.matchStart,w.nextMatch);
+		else if(w.matchText.substr(0,1) == config.textPrimitives.unWikiLink)
+			w.outputText(w.output,w.matchStart + 1,w.nextMatch);
+		else
+			{
+			var link = createTiddlyLink(w.output,w.matchText,false);
+			w.outputText(link,w.matchStart,w.nextMatch);
+			}
+	}
+},
+
+{
+	name: "prettyLink",
+	match: "\\[\\[",
+	lookahead: "\\[\\[([^\\|\\]]*?)(?:(\\]\\])|(\\|(.*?)\\]\\]))",
+	terminator: "\\|",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source)
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[2]) // Simple bracketted link
+			{
+			var link = createTiddlyLink(w.output,lookaheadMatch[1],false);
+			w.outputText(link,w.nextMatch,w.nextMatch + lookaheadMatch[1].length);
+			w.nextMatch += lookaheadMatch[1].length + 2;
+			}
+		else if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[3]) // Pretty bracketted link
+			{
+			var e;
+			if(store.tiddlerExists(lookaheadMatch[4]) || store.isShadowTiddler(lookaheadMatch[4]))
+				e = createTiddlyLink(w.output,lookaheadMatch[4],false);
+			else
+				e = createExternalLink(w.output,lookaheadMatch[4]);
+			w.outputText(e,w.nextMatch,w.nextMatch + lookaheadMatch[1].length);
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			}
+	}
+},
+
+{
+	name: "urlLink",
+	match: config.textPrimitives.urlPattern,
+	handler: function(w)
+	{
+		var e = createExternalLink(w.output,w.matchText);
+		w.outputText(e,w.matchStart,w.nextMatch);
+	}
+},
+
+{
+	name: "image",
+	match: "\\[(?:[<]{0,1})(?:[>]{0,1})[Ii][Mm][Gg]\\[",
+	lookahead: "\\[([<]{0,1})([>]{0,1})[Ii][Mm][Gg]\\[(?:([^\\|\\]]+)\\|)?([^\\[\\]\\|]+)\\](?:\\[([^\\]]*)\\]?)?(\\])",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source);
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link
+			{
+			var e = w.output;
+			if(lookaheadMatch[5])
+				{
+				if(store.tiddlerExists(lookaheadMatch[5]) || store.isShadowTiddler(lookaheadMatch[5]))
+					e = createTiddlyLink(w.output,lookaheadMatch[5],false);
+				else
+					e = createExternalLink(w.output,lookaheadMatch[5]);
+				addClass(e,"imageLink");
+				}
+			var img = createTiddlyElement(e,"img");
+			if(lookaheadMatch[1])
+				img.align = "left";
+			else if(lookaheadMatch[2])
+				img.align = "right";
+			if(lookaheadMatch[3])
+				img.title = lookaheadMatch[3];
+			img.src = lookaheadMatch[4];
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			}
+	}
+},
+
+{
+	name: "macro",
+	match: "<<",
+	lookahead: "<<([^>\\s]+)(?:\\s*)((?:[^>]|(?:>(?!>)))*)>>",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source)
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1])
+			{		
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
+			}
+	}
+},
+
+{
+	name: "html",
+	match: "<[Hh][Tt][Mm][Ll]>",
+	lookahead: "<[Hh][Tt][Mm][Ll]>((?:.|\\n)*?)</[Hh][Tt][Mm][Ll]>",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source)
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
+			{
+			var e = createTiddlyElement(w.output,"span");
+			e.innerHTML = lookaheadMatch[1];
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			}
+	}
+},
+
+{
+	name: "commentByBlock",
+	match: "/%",
+	lookahead: "/%((?:.|\\n)*?)%/",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source)
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+	}
+},
+
+{
+	name: "boldByChar",
+	match: "''",
+	terminator: "''",
+	element: "strong",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "strikeByChar",
+	match: "==",
+	terminator: "==",
+	element: "strike",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "underlineByChar",
+	match: "__",
+	terminator: "__",
+	element: "u",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "italicByChar",
+	match: "//",
+	terminator: "//",
+	element: "em",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "subscriptByChar",
+	match: "~~",
+	terminator: "~~",
+	element: "sub",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "superscriptByChar",
+	match: "\\^\\^",
+	terminator: "\\^\\^",
+	element: "sup",
+	handler: config.formatterHelpers.charFormatHelper
+},
+
+{
+	name: "monospacedByChar",
+	match: "\\{\\{\\{",
+	lookahead: "\\{\\{\\{((?:.|\\n)*?)\\}\\}\\}",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"mg");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source)
+		if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
+			{
+			var e = createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]);
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			}
+	}
+},
+
+{
+	name: "styleByChar",
+	match: "@@",
+	terminator: "@@",
+	lookahead: "(?:([^\\(@]+)\\(([^\\)]+)(?:\\):))|(?:([^:@]+):([^;]+);)",
+	handler:  function(w)
+	{
+		var e = createTiddlyElement(w.output,"span",null,null,null);
+		var styles = config.formatterHelpers.inlineCssHelper(w);
+		if(styles.length == 0)
+			e.className = "marked";
+		else
+			config.formatterHelpers.applyCssHelper(e,styles);
+		w.subWikify(e,this.terminator);
+	}
+},
+
+{
+	name: "lineBreak",
+	match: "\\n",
+	handler: function(w)
+	{
+		createTiddlyElement(w.output,"br");
+	}
+},
+
+{
+	name: "htmlEntitiesEncoding",
+	match: "&#?[a-zA-Z0-9]{2,8};",
+	handler: function(w)
+		{
+		var e = createTiddlyElement(w.output,"span");
+		e.innerHTML = w.matchText ;
+		}
+},
+
+{
+	name: "customClasses",
+	match: "\\{\\{",
+	terminator: "\\}\\}\\}",
+	lookahead: "\\{\\{[\\s]*([\\w]+[\\s\\w]*)[\\s]*\\{(\\n{0,1})",
+	handler: function(w)
+	{
+		var lookaheadRegExp = new RegExp(this.lookahead,"g");
+		lookaheadRegExp.lastIndex = w.matchStart;
+		var lookaheadMatch = lookaheadRegExp.exec(w.source);
+		if(lookaheadMatch)
+			{
+			var isByLine = lookaheadMatch[2] == "\n";
+			var p = createTiddlyElement(w.output,isByLine ? "div" : "span",null,lookaheadMatch[1]);
+			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
+			w.subWikify(p,this.terminator);
+			}
+	}
+}
+
+];
+
+// ---------------------------------------------------------------------------------
+// Wikifier
+// ---------------------------------------------------------------------------------
+
+function wikify(source,output,highlightRegExp,tiddler)
+{
+	if(source && source != "")
+		{
+		var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler);
+		wikifier.subWikify(output,null);
+		}
+}
+
+// Wikify a named tiddler to plain text
+function wikifyPlain(title)
+{
+	if(store.tiddlerExists(title) || store.isShadowTiddler(title))
+		{
+		var wikifier = new Wikifier(store.getTiddlerText(title),formatter,null,store.getTiddler(title));
+		return wikifier.wikifyPlain();
+		}
+	else
+		return "";
+}
+
+// Highlight plain text into an element
+function highlightify(source,output,highlightRegExp)
+{
+	if(source && source != "")
+		{
+		var wikifier = new Wikifier(source,formatter,highlightRegExp,null);
+		wikifier.outputText(output,0,source.length);
+		}
+}
+
+// Construct a wikifier object
+// source - source string that's going to be wikified
+// formatter - Formatter() object containing the list of formatters to be used
+// highlightRegExp - regular expression of the text string to highlight
+// tiddler - reference to the tiddler that's taken to be the container for this wikification
+function Wikifier(source,formatter,highlightRegExp,tiddler)
+{
+	this.source = source;
+	this.output = null;
+	this.formatter = formatter;
+	this.nextMatch = 0;
+	this.highlightRegExp = highlightRegExp;
+	this.highlightMatch = null;	
+	if(highlightRegExp)
+		{
+		highlightRegExp.lastIndex = 0;
+		this.highlightMatch = highlightRegExp.exec(source);
+		}
+	this.tiddler = tiddler;
+}
+
+Wikifier.prototype.wikifyPlain = function()
+{
+	var e = createTiddlyElement(document.body,"div");
+	e.style.display = "none";
+	this.subWikify(e,null);
+	var text = getPlainText(e);
+	e.parentNode.removeChild(e);
+	return text;
+}
+
+Wikifier.prototype.subWikify = function(output,terminator)
+{
+	// Temporarily replace the output pointer
+	var oldOutput = this.output;
+	this.output = output;
+	// Prepare the terminator RegExp
+	var terminatorRegExp = terminator ? new RegExp("(" + terminator + ")","mg") : null;
+	do {
+		// Prepare the RegExp match positions
+		this.formatter.formatterRegExp.lastIndex = this.nextMatch;
+		if(terminatorRegExp)
+			terminatorRegExp.lastIndex = this.nextMatch;
+		// Get the first matches
+		var formatterMatch = this.formatter.formatterRegExp.exec(this.source);
+		var terminatorMatch = terminatorRegExp ? terminatorRegExp.exec(this.source) : null;
+		// Check for a terminator match
+		if(terminatorMatch && (!formatterMatch || terminatorMatch.index <= formatterMatch.index))
+			{
+			// Output any text before the match
+			if(terminatorMatch.index > this.nextMatch)
+				this.outputText(this.output,this.nextMatch,terminatorMatch.index);
+			// Set the match parameters
+			this.matchStart = terminatorMatch.index;
+			this.matchLength = terminatorMatch[1].length;
+			this.matchText = terminatorMatch[1];
+			this.nextMatch = terminatorMatch.index + terminatorMatch[1].length;
+			// Restore the output pointer and exit
+			this.output = oldOutput;
+			return;		
+			}
+		// Check for a formatter match
+		else if(formatterMatch)
+			{
+			// Output any text before the match
+			if(formatterMatch.index > this.nextMatch)
+				this.outputText(this.output,this.nextMatch,formatterMatch.index);
+			// Set the match parameters
+			this.matchStart = formatterMatch.index;
+			this.matchLength = formatterMatch[0].length;
+			this.matchText = formatterMatch[0];
+			this.nextMatch = this.formatter.formatterRegExp.lastIndex;
+			// Figure out which formatter matched
+			var matchingFormatter = -1;
+			for(var t=1; t<formatterMatch.length; t++)
+				if(formatterMatch[t])
+					matchingFormatter = t-1;
+			// Call the formatter
+			if(matchingFormatter != -1)
+				this.formatter.formatters[matchingFormatter].handler(this);
+			}
+	} while(terminatorMatch || formatterMatch);
+	// Output any text after the last match
+	if(this.nextMatch < this.source.length)
+		{
+		this.outputText(this.output,this.nextMatch,this.source.length);
+		this.nextMatch = this.source.length;
+		}
+	// Restore the output pointer
+	this.output = oldOutput;
+}
+
+Wikifier.prototype.outputText = function(place,startPos,endPos)
+{
+	// Check for highlights
+	while(this.highlightMatch && (this.highlightRegExp.lastIndex > startPos) && (this.highlightMatch.index < endPos) && (startPos < endPos))
+		{
+		// Deal with any plain text before the highlight
+		if(this.highlightMatch.index > startPos)
+			{
+			createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index));
+			startPos = this.highlightMatch.index;
+			}
+		// Deal with the highlight
+		var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos);
+		var theHighlight = createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd));
+		startPos = highlightEnd;
+		// Nudge along to the next highlight if we're done with this one
+		if(startPos >= this.highlightRegExp.lastIndex)
+			this.highlightMatch = this.highlightRegExp.exec(this.source);
+		}
+	// Do the unhighlighted text left over
+	if(startPos < endPos)
+		{
+		createTiddlyText(place,this.source.substring(startPos,endPos));
+		}
+}
+
+// ---------------------------------------------------------------------------------
+// Macro definitions
+// ---------------------------------------------------------------------------------
+
+config.macros.today.handler = function(place,macroName,params)
+{
+	var now = new Date();
+	var text;
+	if(params[0])
+		text = now.formatString(params[0].trim());
+	else
+		text = now.toLocaleString();
+	createTiddlyElement(place,"span",null,null,text);
+}
+
+config.macros.version.handler = function(place)
+{
+	createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : ""));
+}
+
+config.macros.list.handler = function(place,macroName,params)
+{
+	var type = params[0] ? params[0] : "all";
+	var theList = document.createElement("ul");
+	place.appendChild(theList);
+	if(this[type].prompt)
+		createTiddlyElement(theList,"li",null,"listTitle",this[type].prompt);
+	var results;
+	if(this[type].handler)
+		results = this[type].handler(params);
+	for (var t = 0; t < results.length; t++)
+		{
+		theListItem = document.createElement("li")
+		theList.appendChild(theListItem);
+		if(typeof results[t] == "string")
+			createTiddlyLink(theListItem,results[t],true);
+		else
+			createTiddlyLink(theListItem,results[t].title,true);
+		}
+}
+
+config.macros.list.all.handler = function(params)
+{
+	return store.reverseLookup("tags","excludeLists",false,"title");
+}
+
+config.macros.list.missing.handler = function(params)
+{
+	return store.getMissingLinks();
+}
+
+config.macros.list.orphans.handler = function(params)
+{
+	return store.getOrphans();
+}
+
+config.macros.list.shadowed.handler = function(params)
+{
+	return store.getShadowed();
+}
+
+config.macros.allTags.handler = function(place,macroName,params)
+{
+	var tags = store.getTags();
+	var theDateList = createTiddlyElement(place,"ul",null,null,null);
+	if(tags.length == 0)
+		createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);
+	for(var t=0; t<tags.length; t++)
+		{
+		var theListItem =createTiddlyElement(theDateList,"li",null,null,null);
+		var theTag = createTiddlyButton(theListItem,tags[t][0] + " (" + tags[t][1] + ")",this.tooltip.format([tags[t][0]]),onClickTag);
+		theTag.setAttribute("tag",tags[t][0]);
+		}
+}
+
+config.macros.timeline.handler = function(place,macroName,params)
+{
+	var field = params[0] ? params[0] : "modified";
+	var tiddlers = store.reverseLookup("tags","excludeLists",false,field);
+	var lastDay = "";
+	var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1])) : 0;
+	for(var t=tiddlers.length-1; t>=last; t--)
+		{
+		var tiddler = tiddlers[t];
+		var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
+		if(theDay != lastDay)
+			{
+			var theDateList = document.createElement("ul");
+			place.appendChild(theDateList);
+			createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(this.dateFormat));
+			lastDay = theDay;
+			}
+		var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink",null);
+		theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
+		}
+}
+
+config.macros.search.handler = function(place,macroName,params)
+{
+	var searchTimeout = null;
+	var btn = createTiddlyButton(place,this.label,this.prompt,this.onClick);
+	var txt = createTiddlyElement(place,"input",null,null,null);
+	if(params[0])
+		txt.value = params[0];
+	txt.onkeyup = this.onKeyPress;
+	txt.onfocus = this.onFocus;
+	txt.setAttribute("size",this.sizeTextbox);
+	txt.setAttribute("accessKey",this.accessKey);
+	txt.setAttribute("autocomplete","off");
+	txt.setAttribute("lastSearchText","");
+	if(config.browser.isSafari)
+		{
+		txt.setAttribute("type","search");
+		txt.setAttribute("results","5");
+		}
+	else
+		txt.setAttribute("type","text");
+}
+
+// Global because there's only ever one outstanding incremental search timer
+config.macros.search.timeout = null;
+
+config.macros.search.doSearch = function(txt)
+{
+	if(txt.value.length > 0)
+		{
+		story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);
+		txt.setAttribute("lastSearchText",txt.value);
+		}
+}
+
+config.macros.search.onClick = function(e)
+{
+	config.macros.search.doSearch(this.nextSibling);
+	return false;
+}
+
+config.macros.search.onKeyPress = function(e)
+{
+	if (!e) var e = window.event;
+	switch(e.keyCode)
+		{
+		case 27:
+			this.value = "";
+			clearMessage();
+			break;
+		}
+	if(this.value.length > 2)
+		{
+		if(this.value != this.getAttribute("lastSearchText"))
+			{
+			if(config.macros.search.timeout)
+				clearTimeout(config.macros.search.timeout);
+			var txt = this;
+			config.macros.search.timeout = setTimeout(function() {config.macros.search.doSearch(txt);},500);
+			}
+		}
+	else
+		{
+		if(config.macros.search.timeout)
+			clearTimeout(config.macros.search.timeout);
+		}
+}
+
+config.macros.search.onFocus = function(e)
+{
+	this.select();
+}
+
+config.macros.tiddler.handler = function(place,macroName,params)
+{
+	var wrapper = createTiddlyElement(place,"span",null,params[1] ? params[1] : null,null);
+	var text = store.getTiddlerText(params[0]);
+	if(text)
+		{
+		var tiddlerName = params[0];
+		var stack = config.macros.tiddler.tiddlerStack;
+		if(stack.find(tiddlerName) !== null)
+			return;
+		stack.push(tiddlerName);
+		try
+			{
+			wikify(text,wrapper,null,store.getTiddler(tiddlerName));
+			}
+		finally
+			{
+			stack.pop();
+			}
+		}
+}
+
+config.macros.tiddler.tiddlerStack = [];
+
+config.macros.tag.handler = function(place,macroName,params)
+{
+	createTagButton(place,params[0]);
+}
+
+config.macros.tags.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	var theList = createTiddlyElement(place,"ul");
+	if(params[0] && store.tiddlerExists[params[0]])
+		tiddler = store.getTiddler(params[0]);
+	var lingo = config.views.wikified.tag;
+	var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;
+	createTiddlyElement(theList,"li",null,"listTitle",prompt.format([tiddler.title]));
+	for(var t=0; t<tiddler.tags.length; t++)
+		createTagButton(createTiddlyElement(theList,"li"),tiddler.tags[t],tiddler.title);
+}
+
+config.macros.tagging.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	var theList = createTiddlyElement(place,"ul");
+	var title = "";
+	if(tiddler instanceof Tiddler)
+        title = tiddler.title;
+	if(params[0])
+        title = params[0];
+	theList.setAttribute("title",this.tooltip.format([title]));
+	var tagged = store.getTaggedTiddlers(title);
+	var prompt = tagged.length == 0 ? this.labelNotTag : this.label;
+	createTiddlyElement(theList,"li",null,"listTitle",prompt.format([title]));
+	for(var t=0; t<tagged.length; t++)
+		createTiddlyLink(createTiddlyElement(theList,"li"),tagged[t].title,true);
+}
+
+config.macros.closeAll.handler = function(place)
+{
+	createTiddlyButton(place,this.label,this.prompt,this.onClick);
+}
+
+config.macros.closeAll.onClick = function(e)
+{
+	story.closeAllTiddlers();
+	return false;
+}
+
+config.macros.permaview.handler = function(place)
+{
+	createTiddlyButton(place,this.label,this.prompt,this.onClick);
+}
+
+config.macros.permaview.onClick = function(e)
+{
+	story.permaView();
+	return false;
+}
+
+config.macros.saveChanges.handler = function(place)
+{
+	if(!readOnly)
+		createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);
+}
+
+config.macros.saveChanges.onClick = function(e)
+{
+	saveChanges();
+	return false;
+}
+
+config.macros.slider.onClickSlider = function(e)
+{
+	if (!e) var e = window.event;
+	var n = this.nextSibling;
+	var cookie = n.getAttribute("cookie");
+	var isOpen = n.style.display != "none";
+	if(config.options.chkAnimate)
+		anim.startAnimating(new Slider(n,!isOpen,e.shiftKey || e.altKey,"none"));
+	else
+		n.style.display = isOpen ? "none" : "block";
+	config.options[cookie] = !isOpen;
+	saveOptionCookie(cookie);
+	return false;
+}
+
+config.macros.slider.createSlider = function(place,cookie,title,tooltip)
+{
+	var cookie = cookie ? cookie : "";
+	var btn = createTiddlyButton(place,title,tooltip,this.onClickSlider);
+	var panel = createTiddlyElement(place,"div",null,"sliderPanel",null);
+	panel.setAttribute("cookie",cookie);
+	panel.style.display = config.options[cookie] ? "block" : "none";
+	return panel;
+}
+
+config.macros.slider.handler = function(place,macroName,params)
+{
+	var panel = this.createSlider(place,params[0],params[2],params[3]);
+	var text = store.getTiddlerText(params[1]);
+	if(text)
+		wikify(text,panel,null,store.getTiddler(params[1]));
+}
+
+config.macros.option.onChangeOption = function(e)
+{
+	var opt = this.getAttribute("option");
+	var elementType,valueField;
+	if(opt)
+		{
+		switch(opt.substr(0,3))
+			{
+			case "txt":
+				elementType = "input";
+				valueField = "value";
+				break;
+			case "chk":
+				elementType = "input";
+				valueField = "checked";
+				break;
+			}
+		config.options[opt] = this[valueField];
+		saveOptionCookie(opt);
+		var nodes = document.getElementsByTagName(elementType);
+		for(var t=0; t<nodes.length; t++)
+			{
+			var optNode = nodes[t].getAttribute("option");
+			if(opt == optNode)
+				nodes[t][valueField] = this[valueField];
+			}
+		}
+	return(true);
+}
+
+config.macros.option.handler = function(place,macroName,params)
+{
+	var opt = params[0];
+	if(config.options[opt] == undefined)
+		return;
+	var c;
+	switch(opt.substr(0,3))
+		{
+		case "txt":
+			c = document.createElement("input");
+			c.onkeyup = this.onChangeOption;
+			c.setAttribute("option",opt);
+			c.size = 15;
+			place.appendChild(c);
+			c.value = config.options[opt];
+			break;
+		case "chk":
+			c = document.createElement("input");
+			c.setAttribute("type","checkbox");
+			c.onclick = this.onChangeOption;
+			c.setAttribute("option",opt);
+			place.appendChild(c);
+			c.checked = config.options[opt];
+			break;
+		}
+}
+
+config.macros.newTiddler.onClick = function()
+{
+	story.displayTiddler(null,config.macros.newTiddler.title,DEFAULT_EDIT_TEMPLATE);
+	story.focusTiddler(config.macros.newTiddler.title,"title");
+	return false;
+}
+
+config.macros.newTiddler.handler = function(place)
+{
+	if(!readOnly)
+		createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);
+}
+
+config.macros.newJournal.handler = function(place,macroName,params)
+{
+	if(!readOnly)
+		{
+		var now = new Date();
+		var title = now.formatString(params[0].trim());
+		var btn = createTiddlyButton(place,this.label,this.prompt,this.createJournal,null,null,this.accessKey);
+		btn.setAttribute("journalTitle",title);
+		btn.setAttribute("params",params.join("|"));
+		}
+}
+
+config.macros.newJournal.createJournal = function(e)
+{
+	var title = this.getAttribute("journalTitle");
+	var params = this.getAttribute("params").split("|");
+	story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
+	for(var t=1;t<params.length;t++)
+		story.setTiddlerTag(title,params[t],+1);
+	story.focusTiddler(title,"text");
+	return false;
+}
+
+config.macros.sparkline.handler = function(place,macroName,params)
+{
+	var data = [];
+	var min = 0;
+	var max = 0;
+	for(var t=0; t<params.length; t++)
+		{
+		var v = parseInt(params[t]);
+		if(v < min)
+			min = v;
+		if(v > max)
+			max = v;
+		data.push(v);
+		}
+	if(data.length < 1)
+		return;
+	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
+	box.title = data.join(",");
+	var w = box.offsetWidth;
+	var h = box.offsetHeight;
+	box.style.paddingRight = (data.length * 2 - w) + "px";
+	box.style.position = "relative";
+	for(var d=0; d<data.length; d++)
+		{
+		var tick = document.createElement("img");
+		tick.border = 0;
+		tick.className = "sparktick";
+		tick.style.position = "absolute";
+		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
+		tick.style.left = d*2 + "px";
+		tick.style.width = "2px";
+		var v = Math.floor(((data[d] - min)/(max-min)) * h);
+		tick.style.top = (h-v) + "px";
+		tick.style.height = v + "px";
+		box.appendChild(tick);
+		}
+}
+
+config.macros.tabs.handler = function(place,macroName,params)
+{
+	var cookie = params[0];
+	var numTabs = (params.length-1)/3;
+	var wrapper = createTiddlyElement(place,"div",null,cookie,null);
+	var tabset = createTiddlyElement(wrapper,"div",null,"tabset",null);
+	tabset.setAttribute("cookie",cookie);
+	var validTab = false;
+	for(var t=0; t<numTabs; t++)
+		{
+		var label = params[t*3+1];
+		var prompt = params[t*3+2];
+		var content = params[t*3+3];
+		var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,"tab tabUnselected");
+		tab.setAttribute("tab",label);
+		tab.setAttribute("content",content);
+		tab.title = prompt;
+		if(config.options[cookie] == label)
+			validTab = true;
+		}
+	if(!validTab)
+		config.options[cookie] = params[1];
+	this.switchTab(tabset,config.options[cookie]);
+}
+
+config.macros.tabs.onClickTab = function(e)
+{
+	config.macros.tabs.switchTab(this.parentNode,this.getAttribute("tab"));
+	return false;
+}
+
+config.macros.tabs.switchTab = function(tabset,tab)
+{
+	var cookie = tabset.getAttribute("cookie");
+	var theTab = null
+	var nodes = tabset.childNodes;
+	for(var t=0; t<nodes.length; t++)
+		if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
+			{
+			theTab = nodes[t];
+			theTab.className = "tab tabSelected";
+			}
+		else
+			nodes[t].className = "tab tabUnselected"
+	if(theTab)
+		{
+		if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
+			tabset.parentNode.removeChild(tabset.nextSibling);
+		var tabContent = createTiddlyElement(null,"div",null,"tabContents",null);
+		tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
+		var contentTitle = theTab.getAttribute("content");
+		wikify(store.getTiddlerText(contentTitle),tabContent,null,store.getTiddler(contentTitle));
+		if(cookie)
+			{
+			config.options[cookie] = tab;
+			saveOptionCookie(cookie);
+			}
+		}
+}
+
+// <<gradient [[tiddler name]] vert|horiz rgb rgb rgb rgb... >>
+config.macros.gradient.handler = function(place,macroName,params,wikifier)
+{
+	var terminator = ">>";
+	var panel;
+	if(wikifier)
+		panel = createTiddlyElement(place,"div",null,"gradient",null);
+	else
+		panel = place;
+	panel.style.position = "relative";
+	panel.style.overflow = "hidden";
+	panel.style.zIndex = "0";
+	var t;
+	if(wikifier)
+		{
+		var styles = config.formatterHelpers.inlineCssHelper(wikifier);
+		config.formatterHelpers.applyCssHelper(panel,styles);
+		}
+	var colours = [];
+	for(t=1; t<params.length; t++)
+		{
+		var c = new RGB(params[t]);
+		if(c)
+			colours.push(c);
+		}
+	drawGradient(panel,params[0] != "vert",colours);
+	if(wikifier)
+		wikifier.subWikify(panel,terminator);
+	if(document.all)
+		{
+		panel.style.height = "100%";
+		panel.style.width = "100%";
+		}
+}
+
+config.macros.message.handler = function(place,macroName,params)
+{
+	if(params[0])
+		{
+		var m = config;
+		var p = params[0].split(".");
+		for(var t=0; t<p.length; t++)
+			{
+			if(p[t] in m)
+				m = m[p[t]];
+			else
+				break;
+			}
+		createTiddlyText(place,m.toString().format(params.splice(1)));
+		}
+}
+
+config.macros.view.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	if((tiddler instanceof Tiddler) && params[0] && (tiddler[params[0]] != undefined))
+		{
+		switch(params[1])
+			{
+			case undefined:
+				highlightify(tiddler[params[0]],place,highlightHack);
+				break;
+			case "link":
+				createTiddlyLink(place,tiddler[params[0]],true);
+				break;
+			case "wikified":
+				wikify(tiddler[params[0]],place,highlightHack,tiddler);
+				break;
+			case "date":
+				if(params[2])
+					createTiddlyText(place,tiddler[params[0]].formatString(params[2]));
+				else
+					createTiddlyText(place,tiddler[params[0]]);
+				break;
+			}
+		}
+}
+
+config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	var field = params[0];
+	if((tiddler instanceof Tiddler) && field && (tiddler[field] != undefined))
+		{
+		story.setDirty(tiddler.title,true);
+		switch(field)
+			{
+			case "title":
+				var e = createTiddlyElement(place,"input");
+				if(tiddler.isReadOnly())
+					e.setAttribute("readOnly","readOnly");
+				e.setAttribute("edit","title");
+				e.setAttribute("type","text");
+				e.value = tiddler.title;
+				e.setAttribute("size","40");
+				e.setAttribute("autocomplete","off");
+				break;
+			case "text":
+				var wrapper1 = createTiddlyElement(place,"fieldset",null,"fieldsetFix",null);
+				var wrapper2 = createTiddlyElement(wrapper1,"div",null,null,null);
+				var e = createTiddlyElement(wrapper2,"textarea");
+				if(tiddler.isReadOnly())
+					e.setAttribute("readOnly","readOnly");
+				e.value = tiddler.text;
+				var rows = 10;
+				var lines = tiddler.text.match(regexpNewLine);
+				var maxLines = Math.max(parseInt(config.options.txtMaxEditRows),5);
+				if(lines != null && lines.length > rows)
+					rows = lines.length + 5;
+				rows = Math.min(rows,maxLines);
+				e.setAttribute("rows",rows);
+				e.setAttribute("edit","text");
+				break;
+			case "tags":
+				var e = createTiddlyElement(place,"input");
+				if(tiddler.isReadOnly())
+					e.setAttribute("readOnly","readOnly");
+				e.setAttribute("edit","tags");
+				e.setAttribute("type","text");
+				e.value = tiddler.getTags();
+				e.setAttribute("size","40");
+				e.setAttribute("autocomplete","off");
+				break;
+			}
+		}
+}
+
+config.macros.tagChooser.onClick = function(e)
+{
+	if (!e) var e = window.event;
+	var lingo = config.views.editor.tagChooser;
+	var popup = Popup.create(this);
+	var tags = store.getTags();
+	if(tags.length == 0)
+		createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);
+	for (var t=0; t<tags.length; t++)
+		{
+		var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),config.macros.tagChooser.onTagClick);
+		theTag.setAttribute("tag",tags[t][0]);
+		theTag.setAttribute("tiddler", this.getAttribute("tiddler"));
+		}
+	Popup.show(popup,false);
+	e.cancelBubble = true;
+	if (e.stopPropagation) e.stopPropagation();
+	return(false);
+}
+
+config.macros.tagChooser.onTagClick = function(e)
+{
+	if (!e) var e = window.event;
+	var tag = this.getAttribute("tag");
+	var title = this.getAttribute("tiddler");
+	var tiddler = store.getTiddler(title);
+	if(!readOnly)
+		story.setTiddlerTag(title,tag,0);
+	return(false);
+}
+
+config.macros.tagChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	if(tiddler instanceof Tiddler)
+		{
+		var title = tiddler.title;
+		var lingo = config.views.editor.tagChooser;
+		var btn = createTiddlyButton(place,lingo.text,lingo.tooltip,this.onClick);
+		btn.setAttribute("tiddler", title);
+		}
+}
+
+// Create a toolbar command button
+// place - parent DOM element
+// command - reference to config.commands[] member -or- name of member
+// tiddler - reference to tiddler that toolbar applies to
+// theClass - the class to give the button
+config.macros.toolbar.createCommand = function(place,commandName,tiddler,theClass)
+{
+	if(typeof commandName != "string")
+		{
+		var c = null;
+		for(var t in config.commands)
+			if(config.commands[t] == commandName)
+				c = t;
+		commandName = c;
+		}
+	if((tiddler instanceof Tiddler) && (typeof commandName == "string"))
+		{
+		var title = tiddler.title;
+		var command = config.commands[commandName];
+		var ro = tiddler.isReadOnly();
+		var text = ro && command.readOnlyText ? command.readOnlyText : command.text;
+		var tooltip = ro && command.readOnlyTooltip ? command.readOnlyTooltip : command.tooltip;
+		if(!ro || (ro && !command.hideReadOnly))
+			{
+			var btn = createTiddlyButton(place,text,tooltip,this.onClickCommand);
+			btn.setAttribute("commandName", commandName);
+			btn.setAttribute("tiddler", title);
+			if(theClass)
+				addClass(btn,theClass);
+			}
+		}
+}
+
+config.macros.toolbar.onClickCommand = function(e)
+{
+	if (!e) var e = window.event;
+	var command = config.commands[this.getAttribute("commandName")];
+	return command.handler(e,this,this.getAttribute("tiddler"));
+}
+
+// Invoke the first command encountered from a given place that is tagged with a specified class
+config.macros.toolbar.invokeCommand = function(place,theClass,event)
+{
+	var children = place.getElementsByTagName("a")
+	for (var t=0; t<children.length; t++)
+		{
+		var c = children[t];
+		if(hasClass(c,theClass) && c.getAttribute && c.getAttribute("commandName"))
+			{
+			if(c.onclick instanceof Function)
+				c.onclick.call(c,event);
+			break;
+			}
+		}
+}
+
+config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler)
+{
+	for(var t=0; t<params.length; t++)
+		{
+		var c = params[t];
+		var theClass = "";
+		switch(c.substr(0,1))
+			{
+			case "+":
+				theClass = "defaultCommand";
+				c = c.substr(1);
+				break;
+			case "-":
+				theClass = "cancelCommand";
+				c = c.substr(1);
+				break;
+			}
+		if(c in config.commands)
+			this.createCommand(place,c,tiddler,theClass);
+		}
+}
+
+config.macros.br.handler = function(place)
+{
+	createTiddlyElement(place,"br");
+}
+
+// ---------------------------------------------------------------------------------
+// Menu and toolbar commands
+// ---------------------------------------------------------------------------------
+
+config.commands.closeTiddler.handler = function(event,src,title)
+{
+	story.closeTiddler(title,true,event.shiftKey || event.altKey);
+	return false;
+}
+
+config.commands.closeOthers.handler = function(event,src,title)
+{
+	story.closeAllTiddlers(title);
+	return false;
+}
+
+config.commands.editTiddler.handler = function(event,src,title)
+{
+	clearMessage();
+	story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
+	story.focusTiddler(title,"text");
+	return false;
+}
+
+config.commands.saveTiddler.handler = function(event,src,title)
+{
+	var newTitle = story.saveTiddler(title,event.shiftKey);
+	if(newTitle)
+	   story.displayTiddler(null,newTitle);
+	return false;
+}
+
+config.commands.cancelTiddler.handler = function(event,src,title)
+{
+	if(story.hasChanges(title) && !readOnly)
+		if(!confirm(this.warning.format([title])))
+			return false;
+	story.setDirty(title,false);
+	story.displayTiddler(null,title);
+	return false;
+}
+
+config.commands.deleteTiddler.handler = function(event,src,title)
+{
+	var deleteIt = true;
+	if (config.options.chkConfirmDelete)
+		deleteIt = confirm(this.warning.format([title]));
+	if (deleteIt)
+		{
+		store.removeTiddler(title);
+		story.closeTiddler(title,true,event.shiftKey || event.altKey);
+		if(config.options.chkAutoSave)
+			saveChanges();
+		}
+	return false;
+}
+
+config.commands.permalink.handler = function(event,src,title)
+{
+	var t = encodeURIComponent(String.encodeTiddlyLink(title));
+	if(window.location.hash != t)
+		window.location.hash = t;
+	return false;
+}
+
+config.commands.references.handler = function(event,src,title)
+{
+	var popup = Popup.create(src);
+	if(popup)
+		{
+		var references = store.getReferringTiddlers(title);
+		var c = false;
+		for(var r=0; r<references.length; r++)
+			if(references[r].title != title && !references[r].isTagged("excludeLists"))
+				{
+				createTiddlyLink(createTiddlyElement(popup,"li"),references[r].title,true);
+				c = true;
+				}
+		if(!c)
+			createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),this.popupNone);
+		}
+	Popup.show(popup,false);
+	event.cancelBubble = true;
+	if (event.stopPropagation) event.stopPropagation();
+	return false;
+}
+
+config.commands.jump.handler = function(event,src,title)
+{
+	var popup = Popup.create(src);
+	if(popup)
+		{
+		story.forEachTiddler(function(title,element) {
+			createTiddlyLink(createTiddlyElement(popup,"li"),title,true);
+			});
+		}
+	Popup.show(popup,false);
+	event.cancelBubble = true;
+	if (event.stopPropagation) event.stopPropagation();
+	return false;
+}
+
+// ---------------------------------------------------------------------------------
+// Tiddler() object
+// ---------------------------------------------------------------------------------
+
+function Tiddler()
+{
+	this.title = null;
+	this.text = null;
+	this.modifier = null;
+	this.modified = new Date();
+	this.created = new Date();
+	this.links = [];
+	this.tags = [];
+	return this;
+}
+
+// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
+Tiddler.prototype.loadFromDiv = function(divRef,title)
+{
+	var text = Tiddler.unescapeLineBreaks(divRef.firstChild ? divRef.firstChild.nodeValue : "");
+	var modifier = divRef.getAttribute("modifier");
+	var modified = Date.convertFromYYYYMMDDHHMM(divRef.getAttribute("modified"));
+	var c = divRef.getAttribute("created");
+	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : modified;
+	var tags = divRef.getAttribute("tags");
+	this.assign(title,text,modifier,modified,tags,created);
+	return this;
+}
+
+// Format the text for storage in an HTML DIV
+Tiddler.prototype.saveToDiv = function()
+{
+	return '<div tiddler="%0" modifier="%1" modified="%2" created="%3" tags="%4">%5</div>'.format([
+			this.title.htmlEncode(),
+			this.modifier.htmlEncode(),
+			this.modified.convertToYYYYMMDDHHMM(),
+			this.created.convertToYYYYMMDDHHMM(),
+			this.getTags().htmlEncode(),
+			this.escapeLineBreaks().htmlEncode()
+		]);
+}
+
+// Format the text for storage in an RSS item
+Tiddler.prototype.saveToRss = function(url)
+{
+	var s = [];
+	s.push("<item>");
+	s.push("<title>" + this.title.htmlEncode() + "</title>");
+	s.push("<description>" + this.text.replace(regexpNewLine,"<br />").htmlEncode() + "</description>");
+	for(var t=0; t<this.tags.length; t++)
+		s.push("<category>" + this.tags[t] + "</category>");
+	s.push("<link>" + url + "#" + encodeURIComponent(String.encodeTiddlyLink(this.title)) + "</link>");
+	s.push("<pubDate>" + this.modified.toGMTString() + "</pubDate>");
+	s.push("</item>");
+	return(s.join("\n"));
+}
+
+// Change the text and other attributes of a tiddler
+Tiddler.prototype.set = function(title,text,modifier,modified,tags,created)
+{
+	this.assign(title,text,modifier,modified,tags,created);
+	this.changed();
+	return this;
+}
+
+// Change the text and other attributes of a tiddler without triggered a tiddler.changed() call
+Tiddler.prototype.assign = function(title,text,modifier,modified,tags,created)
+{
+	if(title != undefined)
+		this.title = title;
+	if(text != undefined)
+		this.text = text;
+	if(modifier != undefined)
+		this.modifier = modifier;
+	if(modified != undefined)
+		this.modified = modified;
+	if(created != undefined)
+		this.created = created;
+	if(tags != undefined)
+		this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags;
+	else if(this.tags == undefined)
+		this.tags = [];
+	return this;
+}
+
+// Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces)
+Tiddler.prototype.getTags = function()
+{
+	if(this.tags)
+		{
+		var results = [];
+		for(var t=0; t<this.tags.length; t++)
+			results.push(String.encodeTiddlyLink(this.tags[t]));
+		return results.join(" ");
+		}
+	else
+		return "";
+}
+
+// Test if a tiddler carries a tag
+Tiddler.prototype.isTagged = function(tag)
+{
+	return this.tags.find(tag) != null;
+}
+
+var regexpBackSlashEn = new RegExp("\\\\n","mg");
+var regexpBackSlash = new RegExp("\\\\","mg");
+var regexpBackSlashEss = new RegExp("\\\\s","mg");
+var regexpNewLine = new RegExp("\n","mg");
+var regexpCarriageReturn = new RegExp("\r","mg");
+
+// Static method to Convert "\n" to newlines, "\s" to "\"
+Tiddler.unescapeLineBreaks = function(text)
+{
+	if(text && text != "")
+		return text.replace(regexpBackSlashEn,"\n").replace(regexpBackSlashEss,"\\").replace(regexpCarriageReturn,"");
+	else
+		return "";
+}
+
+// Convert newlines to "\n", "\" to "\s"
+Tiddler.prototype.escapeLineBreaks = function()
+{
+	return this.text.replace(regexpBackSlash,"\\s").replace(regexpNewLine,"\\n").replace(regexpCarriageReturn,"");
+}
+
+// Updates the secondary information (like links[] array) after a change to a tiddler
+Tiddler.prototype.changed = function()
+{
+	this.links = [];
+	var nextPos = 0;
+	var theLink;
+	var aliasedPrettyLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
+	var prettyLink = "\\[\\[([^\\]]+)\\]\\]";
+	var wikiNameRegExp = new RegExp("(" + config.textPrimitives.wikiLink + ")|(?:" + aliasedPrettyLink + ")|(?:" + prettyLink + ")","mg");
+	do {
+		var formatMatch = wikiNameRegExp.exec(this.text);
+		if(formatMatch)
+			{
+			if(formatMatch[1] && formatMatch[1].substr(0,1) != config.textPrimitives.unWikiLink && formatMatch[1] != this.title)
+				this.links.pushUnique(formatMatch[1]);
+			else if(formatMatch[2] && (store.tiddlerExists(formatMatch[3]) || store.isShadowTiddler(formatMatch[3])))
+				this.links.pushUnique(formatMatch[3]);
+			else if(formatMatch[4] && formatMatch[4] != this.title)
+				this.links.pushUnique(formatMatch[4]);
+			}
+	} while(formatMatch);
+	return;
+}
+
+Tiddler.prototype.getSubtitle = function()
+{
+	var theModifier = this.modifier;
+	if(!theModifier)
+		theModifier = config.messages.subtitleUnknown;
+	var theModified = this.modified;
+	if(theModified)
+		theModified = theModified.toLocaleString();
+	else
+		theModified = config.messages.subtitleUnknown;
+	return(config.messages.tiddlerLinkTooltip.format([this.title,theModifier,theModified]));
+}
+
+Tiddler.prototype.isReadOnly = function()
+{
+	return readOnly;
+}
+
+// ---------------------------------------------------------------------------------
+// TiddlyWiki() object contains Tiddler()s
+// ---------------------------------------------------------------------------------
+
+function TiddlyWiki()
+{
+	var tiddlers = {}; // Hashmap by name of tiddlers
+	this.namedNotifications = []; // Array of {name:,notify:} of notification functions
+	this.notificationLevel = 0;
+	this.clear = function() {
+		tiddlers = {};
+		this.setDirty(false);
+		};
+	this.fetchTiddler = function(title) {
+		return tiddlers[title];
+		};
+	this.deleteTiddler = function(title) {
+		 delete tiddlers[title];
+		};
+	this.addTiddler = function(tiddler) {
+		 tiddlers[tiddler.title] = tiddler;
+		};
+	this.forEachTiddler = function(callback) {
+		for(var t in tiddlers)
+			{
+			var tiddler = tiddlers[t];
+			if(tiddler instanceof Tiddler)
+				callback.call(this,t,tiddler);
+			}
+		};
+}
+
+// Set the dirty flag
+TiddlyWiki.prototype.setDirty = function(dirty)
+{
+	this.dirty = dirty;
+}
+
+TiddlyWiki.prototype.isDirty = function()
+{
+	return this.dirty;
+}
+
+TiddlyWiki.prototype.suspendNotifications = function()
+{
+	this.notificationLevel--;
+}
+
+TiddlyWiki.prototype.resumeNotifications = function()
+{
+	this.notificationLevel++;
+}
+
+// Invoke the notification handlers for a particular tiddler
+TiddlyWiki.prototype.notify = function(title,doBlanket)
+{
+	if(!this.notificationLevel)
+		for(var t=0; t<this.namedNotifications.length; t++)
+			{
+			var n = this.namedNotifications[t];

[... 2735 lines stripped ...]


Mime
View raw message