<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
text/plain
.txt .text .js .vbs .asp .cgi .pl
----
text/html
.htm .html .hta .htx .mht
----
text/comma-separated-values
.csv
----
text/javascript
.js
----
text/css
.css
----
text/xml
.xml .xsl .xslt
----
image/gif
.gif
----
image/jpeg
.jpg .jpe .jpeg
----
image/png
.png
----
image/bmp
.bmp
----
image/tiff
.tif .tiff
----
audio/basic
.au .snd
----
audio/wav
.wav
----
audio/x-pn-realaudio
.ra .rm .ram
----
audio/x-midi
.mid .midi
----
audio/mp3
.mp3
----
audio/m3u
.m3u
----
video/x-ms-asf
.asf
----
video/avi
.avi
----
video/mpeg
.mpg .mpeg
----
video/quicktime
.qt .mov .qtvr
----
application/pdf
.pdf
----
application/rtf
.rtf
----
application/postscript
.ai .eps .ps
----
application/wordperfect
.wpd
----
application/mswrite
.wri
----
application/msexcel
.xls .xls3 .xls4 .xls5 .xlw
----
application/msword
.doc
----
application/mspowerpoint
.ppt .pps
----
application/x-director
.swa
----
application/x-shockwave-flash
.swf
----
application/x-zip-compressed
.zip
----
application/x-gzip
.gz
----
application/x-rar-compressed
.rar
----
application/octet-stream
.com .exe .dll .ocx
----
application/java-archive
.jar
/***
|Name|AttachFilePlugin|
|Source|http://www.TiddlyTools.com/#AttachFilePlugin|
|Documentation|http://www.TiddlyTools.com/#AttachFilePluginInfo|
|Version|4.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|AttachFilePluginFormatters, AttachFileMIMETypes|
|Overrides||
|Description|Store binary files as base64-encoded tiddlers with fallback links for separate local and/or remote file storage|
Store or link binary files (such as jpg, gif, pdf or even mp3) within your TiddlyWiki document and then use them as images or links from within your tiddler content.
> Important note: As of version 3.6.0, in order to //render// images and other binary attachments created with this plugin, you must also install [[AttachFilePluginFormatters]], which extends the behavior of the TiddlyWiki core formatters for embedded images ({{{[img[tooltip|image]]}}}), linked embedded images ({{{[img[tooltip|image][link]]}}}), and external/"pretty" links ({{{[[label|link]]}}}), so that these formatter will process references to attachment tiddlers as if a normal file reference had been provided. |
!!!!!Documentation
>see [[AttachFilePluginInfo]]
!!!!!Inline interface (live)
>see [[AttachFile]] (shadow tiddler)
><<tiddler AttachFile>>
!!!!!Revisions
<<<
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
|please see [[AttachFilePluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.AttachFilePlugin= {major: 4, minor: 0, revision: 0, date: new Date(2009,6,4)};

// shadow tiddler
config.shadowTiddlers.AttachFile="<<attach inline>>";

// add 'attach' backstage task (insert before built-in 'importTask')
if (config.tasks) { // for TW2.2b or above
	config.tasks.attachTask = {
		text: "attach",
		tooltip: "Attach a binary file as a tiddler",
		content: "<<attach inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask"),0,"attachTask");
}

config.macros.attach = {
// // lingo
//{{{
	label: "attach file",
	tooltip: "Attach a file to this document",
	linkTooltip: "Attachment: ",

	typeList: "AttachFileMIMETypes",

	titlePrompt: " enter tiddler title...",
	MIMEPrompt: "<option value=''>select MIME type...</option><option value='editlist'>[edit list...]</option>",
	localPrompt: " enter local path/filename...",
	URLPrompt: " enter remote URL...",

	tiddlerErr: "Please enter a tiddler title",
	sourceErr: "Please enter a source path/filename",
	storageErr: "Please select a storage method: embedded, local or remote",
	MIMEErr: "Unrecognized file format.  Please select a MIME type",
	localErr: "Please enter a local path/filename",
	URLErr: "Please enter a remote URL",
	fileErr: "Invalid path/file or file not found",

	tiddlerFormat: '!usage\n{{{%0}}}\n%0\n!notes\n%1\n!type\n%2\n!file\n%3\n!url\n%4\n!data\n%5\n',

//}}}
// // macro definition
//{{{
	handler:
	function(place,macroName,params) {
		if (params && !params[0])
			{ createTiddlyButton(place,this.label,this.tooltip,this.toggleAttachPanel); return; }
		var id=params.shift();
		this.createAttachPanel(place,id+"_attachPanel",params);
		document.getElementById(id+"_attachPanel").style.position="static";
		document.getElementById(id+"_attachPanel").style.display="block";
	},
//}}}
//{{{
	createAttachPanel:
	function(place,panel_id,params) {
		if (!panel_id || !panel_id.length) var panel_id="_attachPanel";
		// remove existing panel (if any)
		var panel=document.getElementById(panel_id); if (panel) panel.parentNode.removeChild(panel);
		// set styles for this panel
		setStylesheet(this.css,"attachPanel");
		// create new panel
		var title=""; if (params && params[0]) title=params.shift();
		var types=this.MIMEPrompt+this.formatListOptions(store.getTiddlerText(this.typeList)); // get MIME types
		panel=createTiddlyElement(place,"span",panel_id,"attachPanel",null);
		var html=this.html.replace(/%id%/g,panel_id);
		html=html.replace(/%title%/g,title);
		html=html.replace(/%disabled%/g,title.length?"disabled":"");
		html=html.replace(/%IEdisabled%/g,config.browser.isIE?"disabled":"");
		html=html.replace(/%types%/g,types);
		panel.innerHTML=html;
		if (config.browser.isGecko) { // FF3 FIXUP
			document.getElementById("attachSource").style.display="none";
			document.getElementById("attachFixPanel").style.display="block";
		}
		return panel;
	},
//}}}
//{{{
	toggleAttachPanel:
	function (e) {
		if (!e) var e = window.event;
		var parent=resolveTarget(e).parentNode;
		var panel = document.getElementById("_attachPanel");
		if (panel==undefined || panel.parentNode!=parent)
			panel=config.macros.attach.createAttachPanel(parent,"_attachPanel");
		var isOpen = panel.style.display=="block";
		if(config.options.chkAnimate)
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
		else
			panel.style.display = isOpen ? "none" : "block" ;
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
		return(false);
	},
//}}}
//{{{
	formatListOptions:
	function(text) {
		if (!text || !text.trim().length) return "";
		// get MIME list content from text
		var parts=text.split("\n----\n");
		var out="";
		for (var p=0; p<parts.length; p++) {
			var lines=parts[p].split("\n");
			var label=lines.shift(); // 1st line=display text
			var value=lines.shift(); // 2nd line=item value
			out +='<option value="%1">%0</option>'.format([label,value]);
		}
		return out;
	},
//}}}
// // interface definition
//{{{
	css:
	".attachPanel { display: none; position:absolute; z-index:10; width:35em; right:105%; top:0em;\
		background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
		border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
		padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em; text-align:left }\
	.attachPanel form { display:inline;border:0;padding:0;margin:0; }\
	.attachPanel select { width:99%;margin:0px;font-size:8pt;line-height:110%;}\
	.attachPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
	.attachPanel textarea { width:98%;margin:0px;height:2em;font-size:8pt;line-height:110%}\
	.attachPanel table { width:100%;border:0;margin:0;padding:0;color:inherit; }\
	.attachPanel tbody, .attachPanel tr, .attachPanel td { border:0;margin:0;padding:0;color:#000; }\
	.attachPanel .box { border:1px solid black; padding:.3em; margin:.3em 0px; background:#f8f8f8; \
		-moz-border-radius:5px;-webkit-border-radius:5px; }\
	.attachPanel .chk { width:auto;border:0; }\
	.attachPanel .btn { width:auto; }\
	.attachPanel .btn2 { width:49%; }\
	",
//}}}
//{{{
	html:
	'<form>\
		attach from source file\
		<input type="file" id="attachSource" name="source" size="56"\
			onChange="config.macros.attach.onChangeSource(this)">\
		<div id="attachFixPanel" style="display:none"><!-- FF3 FIXUP -->\
			<input type="text" id="attachFixSource" style="width:90%"\
				title="Enter a path/file to attach"\
				onChange="config.macros.attach.onChangeSource(this);">\
			<input type="button" style="width:7%" value="..."\
				title="Enter a path/file to attach"\
				onClick="config.macros.attach.askForFilename(document.getElementById(\'attachFixSource\'));">\
		</div><!--end FF3 FIXUP-->\
		<div class="box">\
		<table style="border:0"><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			embed data <input type=checkbox class=chk name="useData" %IEdisabled% \
				onclick="if (!this.form.MIMEType.value.length)\
					this.form.MIMEType.selectedIndex=this.checked?1:0; ">&nbsp;\
		</td><td style="border:0">\
			<select size=1 name="MIMEType" \
				onchange="this.title=this.value; if (this.value==\'editlist\')\
					{ this.selectedIndex=this.form.useData.checked?1:0; story.displayTiddler(null,config.macros.attach.typeList,2); return; }">\
				<option value=""></option>\
				%types%\
			</select>\
		</td></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			local link <input type=checkbox class=chk name="useLocal"\
				onclick="this.form.local.value=this.form.local.defaultValue=this.checked?config.macros.attach.localPrompt:\'\';">&nbsp;\
		</td><td style="border:0">\
			<input type=text name="local" size=15 autocomplete=off value=""\
				onchange="this.form.useLocal.checked=this.value.length" \
				onkeyup="this.form.useLocal.checked=this.value.length" \
				onfocus="if (!this.value.length) this.value=config.macros.attach.localPrompt; this.select()">\
		</td></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			remote link <input type=checkbox class=chk name="useURL"\
				onclick="this.form.URL.value=this.form.URL.defaultValue=this.checked?config.macros.attach.URLPrompt:\'\';\">&nbsp;\
		</td><td style="border:0">\
			<input type=text name="URL" size=15 autocomplete=off value=""\
				onfocus="if (!this.value.length) this.value=config.macros.attach.URLPrompt; this.select()"\
				onchange="this.form.useURL.checked=this.value.length;"\
				onkeyup="this.form.useURL.checked=this.value.length;">\
		</td></tr></table>\
		</div>\
		<table style="border:0"><tr style="border:0"><td style="border:0;text-align:right;vertical-align:top;width:1%;white-space:nowrap">\
			notes&nbsp;\
		</td><td style="border:0" colspan=2>\
			<textarea name="notes" style="width:98%;height:3.5em;margin-bottom:2px"></textarea>\
		</td><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			attach as&nbsp;\
		</td><td style="border:0" colspan=2>\
			<input type=text name="tiddlertitle" size=15 autocomplete=off value="%title%"\
				onkeyup="if (!this.value.length) { this.value=config.macros.attach.titlePrompt; this.select(); }"\
				onfocus="if (!this.value.length) this.value=config.macros.attach.titlePrompt; this.select()" %disabled%>\
		</td></tr></tr><tr style="border:0"><td style="border:0;text-align:right;width:1%;white-space:nowrap">\
			add tags&nbsp;\
		</td><td style="border:0">\
			<input type=text name="tags" size=15 autocomplete=off value="" onfocus="this.select()">\
		</td><td style="width:40%;text-align:right;border:0">\
			<input type=button class=btn2 value="attach"\
				onclick="config.macros.attach.onClickAttach(this)"><!--\
			--><input type=button class=btn2 value="close"\
				onclick="var panel=document.getElementById(\'%id%\'); if (panel) panel.parentNode.removeChild(panel);">\
		</td></tr></table>\
	</form>',
//}}}
// // control processing
//{{{
	onChangeSource:
	function(here) {
		var form=here.form;
		var list=form.MIMEType;
		var theFilename  = here.value;
		var theExtension = theFilename.substr(theFilename.lastIndexOf('.')).toLowerCase();
		// if theFilename is in current document folder, remove path prefix and use relative reference
		var h=document.location.href; folder=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)));
		if (theFilename.substr(0,folder.length)==folder) theFilename='./'+theFilename.substr(folder.length);
		else theFilename='file:///'+theFilename; // otherwise, use absolute reference
		theFilename=theFilename.replace(/\\/g,"/"); // fixup: change \ to /
		form.useLocal.checked = true;
		form.local.value = theFilename;
		form.useData.checked = !form.useData.disabled;
		list.selectedIndex=1;
		for (var i=0; i<list.options.length; i++) // find matching MIME type
			if (list.options[i].value.indexOf(theExtension)!=-1) { list.selectedIndex = i; break; }
		if (!form.tiddlertitle.disabled)
			form.tiddlertitle.value=theFilename.substr(theFilename.lastIndexOf('/')+1); // get tiddlername from filename
	},
//}}}
//{{{
	onClickAttach:
	function (here) {
		clearMessage();
		// get input values
		var form=here.form;
		var src=form.source; if (config.browser.isGecko) src=document.getElementById("attachFixSource");
		src=src.value!=src.defaultValue?src.value:"";
		var when=(new Date()).formatString(config.macros.timeline.dateFormat);
		var title=form.tiddlertitle.value;
		var local = form.local.value!=form.local.defaultValue?form.local.value:"";
		var url = form.URL.value!=form.URL.defaultValue?form.URL.value:"";
		var notes = form.notes.value;
		var tags = "attachment excludeMissing "+form.tags.value;
		var useData=form.useData.checked;
		var useLocal=form.useLocal.checked;
		var useURL=form.useURL.checked;
		var mimetype = form.MIMEType.value.length?form.MIMEType.options[form.MIMEType.selectedIndex].text:"";
		// validate checkboxes and get filename
		if (useData) {
			if (src.length) { if (!theLocation) var theLocation=src; }
			else { alert(this.sourceErr); src.focus(); return false; }
		}
		if (useLocal) {
			if (local.length) { if (!theLocation) var theLocation = local; }
			else { alert(this.localErr); form.local.focus(); return false; }
		}
		if (useURL) {
			if (url.length) { if (!theLocation) var theLocation = url; }
			else { alert(this.URLErr); form.URL.focus(); return false; }
		}
		if (!(useData||useLocal||useURL))
			{ form.useData.focus(); alert(this.storageErr); return false; }
		if (!theLocation)
			{ src.focus(); alert(this.sourceErr); return false; }
		if (!title || !title.trim().length || title==this.titlePrompt)
			{ form.tiddlertitle.focus(); alert(this.tiddlerErr); return false; }
		// if not already selected, determine MIME type based on filename extension (if any)
		if (useData && !mimetype.length && theLocation.lastIndexOf('.')!=-1) {
			var theExt = theLocation.substr(theLocation.lastIndexOf('.')).toLowerCase();
			var theList=form.MIMEType;
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].value.indexOf(theExt)!=-1)
					{ var mimetype=theList.options[i].text; theList.selectedIndex=i; break; }
		}
		// attach the file
		return this.createAttachmentTiddler(src, when, notes, tags, title,
			useData, useLocal, useURL, local, url, mimetype);
	},
	getMIMEType:
	function(src,def) {
		var ext = src.substr(src.lastIndexOf('.')).toLowerCase();
		var list=store.getTiddlerText(this.typeList);
		if (!list || !list.trim().length) return def;
		// get MIME list content from tiddler
		var parts=list.split("\n----\n");
		for (var p=0; p<parts.length; p++) {
			var lines=parts[p].split("\n");
			var mime=lines.shift(); // 1st line=MIME type
			var match=lines.shift(); // 2nd line=matching extensions
			if (match.indexOf(ext)!=-1) return mime;
		}
		return def;
	},
	createAttachmentTiddler:
	function (src, when, notes, tags, title, useData, useLocal, useURL, local, url, mimetype, noshow) {
		if (useData) { // encode the data
			if (!mimetype.length) {
				alert(this.MIMEErr);
				form.MIMEType.selectedIndex=1; form.MIMEType.focus();
				return false;
			}
			var d = this.readFile(src); if (!d) { return false; }
			displayMessage('encoding '+src);
			var encoded = this.encodeBase64(d);
			displayMessage('file size='+d.length+' bytes, encoded size='+encoded.length+' bytes');
		}
		var usage=(mimetype.substr(0,5)=="image"?'[img[%0]]':'[[%0|%0]]').format([title]);
		var theText=this.tiddlerFormat.format([
			usage, notes.length?notes:'//none//', mimetype,
			useLocal?local.replace(/\\/g,'/'):'', useURL?url:'',
			useData?('data:'+mimetype+';base64,'+encoded):'' ]);
		store.saveTiddler(title,title,theText,config.options.txtUserName,new Date(),tags);
		var panel=document.getElementById("attachPanel"); if (panel) panel.style.display="none";
		if (!noshow) { story.displayTiddler(null,title); story.refreshTiddler(title,null,true); }
		displayMessage('attached "'+title+'"');
		return true;
	},
//}}}
// // base64 conversion
//{{{
	encodeBase64:
	function (d) {
		if (!d) return null;
		// encode as base64
		var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var out="";
		var chr1,chr2,chr3="";
		var enc1,enc2,enc3,enc4="";
		for (var count=0,i=0; i<d.length; ) {
			chr1=d.charCodeAt(i++);
			chr2=d.charCodeAt(i++);
			chr3=d.charCodeAt(i++);
			enc1=chr1 >> 2;
			enc2=((chr1 & 3) << 4) | (chr2 >> 4);
			enc3=((chr2 & 15) << 2) | (chr3 >> 6);
			enc4=chr3 & 63;
			if (isNaN(chr2)) enc3=enc4=64;
			else if (isNaN(chr3)) enc4=64;
			out+=keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4);
			chr1=chr2=chr3=enc1=enc2=enc3=enc4="";
		}
		return out;
	},
	decodeBase64: function(input) {
		var out="";
		var chr1,chr2,chr3;
		var enc1,enc2,enc3,enc4;
		var i = 0;
		// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
		input=input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		do {
			enc1=keyStr.indexOf(input.charAt(i++));
			enc2=keyStr.indexOf(input.charAt(i++));
			enc3=keyStr.indexOf(input.charAt(i++));
			enc4=keyStr.indexOf(input.charAt(i++));
			chr1=(enc1 << 2) | (enc2 >> 4);
			chr2=((enc2 & 15) << 4) | (enc3 >> 2);
			chr3=((enc3 & 3) << 6) | enc4;
			out=out+String.fromCharCode(chr1);
			if (enc3!=64) out=out+String.fromCharCode(chr2);
			if (enc4!=64) out=out+String.fromCharCode(chr3);
		} while (i<input.length);
		return out;
	},
//}}}
// // I/O functions
//{{{
	readFile: // read local BINARY file data
	function(filePath) {
		if(!window.Components) { return null; }
		try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
		catch(e) { alert("access denied: "+filePath); return null; }
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		try { file.initWithPath(filePath); } catch(e) { alert("cannot read file - invalid path: "+filePath); return null; }
		if (!file.exists()) { alert("cannot read file - not found: "+filePath); return null; }
		var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
		inputStream.init(file, 0x01, 00004, null);
		var bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);
		bInputStream.setInputStream(inputStream);
		return(bInputStream.readBytes(inputStream.available()));
	},
//}}}
//{{{
	writeFile:
	function(filepath,data) {
		// TBD: decode base64 and write BINARY data to specified local path/filename
		return(false);
	},
//}}}
//{{{
	askForFilename: // for FF3 fixup
	function(target) {
		var msg=config.messages.selectFile;
		if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
		// get local path for current document
		var path=getLocalPath(document.location.href);
		var p=path.lastIndexOf("/"); if (p==-1) p=path.lastIndexOf("\\"); // Unix or Windows
		if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
		var file=""
		var result=window.mozAskForFilename(msg,path,file,true); // FF3 FIXUP ONLY
		if (target && result.length) // set target field and trigger handling
			{ target.value=result; target.onchange(); }
		return result; 
	}
};
//}}}
//{{{
if (window.mozAskForFilename===undefined) { // also defined by CoreTweaks (for ticket #604)
	window.mozAskForFilename=function(msg,path,file,mustExist) {
		if(!window.Components) return false;
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, mustExist?nsIFilePicker.modeOpen:nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel)
				var result=picker.file.persistentDescriptor;
		}
		catch(ex) { displayMessage(ex.toString()); }
		return result;
	}
}
//}}}
/***
|Name|AttachFilePluginFormatters|
|Source|http://www.TiddlyTools.com/#AttachFilePluginFormatters|
|Version|4.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1.3|
|Type|plugin|
|Requires||
|Overrides|'image' and 'prettyLink' formatters, TiddlyWiki.prototype.getRecursiveTiddlerText|
|Description|run-time library for displaying attachment tiddlers|

This plugin provides "stand-alone" processing for //rendering// attachment tiddlers created by [[AttachFilePlugin]].   Attachment tiddlers are tagged with<<tag attachment>>and contain binary file content (e.g., jpg, gif, pdf, mp3, etc.) that has been stored directly as base64 text-encoded data or can be loaded from external files stored on a local filesystem or remote web server.

NOTE: This plugin does not include the "control panel" and supporting functions needed to //create// new attachment tiddlers.  Those features are provided by [[AttachFilePlugin]], which can be installed while building your document, and then safely omitted to reduce the overall file size when you publish your finished document (assuming you don't intend to create any additional attachment tiddlers in that document)
!!!!!Formatters
<<<
This plugin extends the behavior of the following TiddlyWiki core "wikify()" formatters:
* embedded images: {{{[img[tooltip|image]]}}}
* linked embedded images: {{{[img[tooltip|image][link]]}}}
* external/"pretty" links: {{{[[label|link]]}}}
''Please refer to AttachFilePlugin (source: http://www.TiddlyTools.com/#AttachFilePlugin) for additional information.''
<<<
!!!!!Revisions
<<<
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.10.29 [3.7.0] more code reduction: removed upload handling from AttachFilePlugin (saves ~7K!)
2007.10.28 [3.6.0] removed duplicate formatter code from AttachFilePlugin (saves ~10K!) and updated documentation accordingly.  This plugin ([[AttachFilePluginFormatters]]) is now //''required''// in order to display attached images/binary files within tiddler content.
2006.05.20 [3.4.0] through 2007.03.01 [3.5.3] sync with AttachFilePlugin
2006.05.13 [3.2.0] created from AttachFilePlugin v3.2.0
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.AttachFilePluginFormatters= {major: 4, minor: 0, revision: 0, date: new Date(2009,6,4)};
//}}}

//{{{
if (config.macros.attach==undefined) config.macros.attach= { };
//}}}
//{{{
if (config.macros.attach.isAttachment==undefined) config.macros.attach.isAttachment=function (title) {
	var tiddler = store.getTiddler(title);
	if (tiddler==undefined || tiddler.tags==undefined) return false;
	return (tiddler.tags.indexOf("attachment")!=-1);
}
//}}}

//{{{
// test for local file existence - returns true/false without visible error display
if (config.macros.attach.fileExists==undefined) config.macros.attach.fileExists=function(f) {
	if(window.Components) { // MOZ
		try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
		catch(e) { return false; } // security access denied
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		try { file.initWithPath(f); }
		catch(e) { return false; } // invalid directory
		return file.exists();
	}
	else { // IE
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		return fso.FileExists(f);
	}
}
//}}}

//{{{
if (config.macros.attach.getAttachment==undefined) config.macros.attach.getAttachment=function(title) {

	// extract embedded data, local and remote links (if any)
	var text=store.getTiddlerText(title,'');
	var embedded=store.getTiddlerText(title+'##data','').trim();
	var locallink=store.getTiddlerText(title+'##file','').trim();
	var remotelink=store.getTiddlerText(title+'##url','').trim();

	// backward-compatibility for older attachments (pre 4.0.0)
	var startmarker="---BEGIN_DATA---\n";
	var endmarker="\n---END_DATA---";
	var pos=0; var endpos=0;
	if ((pos=text.indexOf(startmarker))!=-1 && (endpos=text.indexOf(endmarker))!=-1)
		embedded="data:"+(text.substring(pos+startmarker.length,endpos)).replace(/\n/g,'');
	if ((pos=text.indexOf("/%LOCAL_LINK%/"))!=-1)
		locallink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));
	if ((pos=text.indexOf("/%REMOTE_LINK%/"))!=-1)
		remotelink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));

	// if there is a data: URI defined (not supported by IE)
	if (embedded.length && !config.browser.isIE) return embedded;

	// document is being served remotely... use remote URL (if any)  (avoids security alert)
	if (remotelink.length && document.location.protocol!="file:")
		return remotelink;  

	// local link only... return link without checking file existence (avoids security alert)
	if (locallink.length && !remotelink.length) 
		return locallink; 

	// local link, check for file exist... use local link if found
	if (locallink.length) { 
		locallink=locallink.replace(/^\.[\/\\]/,''); // strip leading './' or '.\' (if any)
		if (this.fileExists(getLocalPath(locallink))) return locallink;
		// maybe local link is relative... add path from current document and try again
		var pathPrefix=document.location.href;  // get current document path and trim off filename
		var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
		if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
		if (this.fileExists(getLocalPath(pathPrefix+locallink))) return locallink;
	}

	// no embedded data, no local (or not found), fallback to remote URL (if any)
	if (remotelink.length) return remotelink;

	// attachment URL doesn't resolve, just return input as is
	return title;
}
//}}}
//{{{
if (config.macros.attach.init_formatters==undefined) config.macros.attach.init_formatters=function() {
	if (this.initialized) return;

	// find the formatter for "image" and replace the handler
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="image"; i++);
	if (i<config.formatters.length)	config.formatters[i].handler=function(w) {
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link
			{
			var e = w.output;
			if(lookaheadMatch[5])
				{
				var link = lookaheadMatch[5];
				// ELS -------------
				var external=config.formatterHelpers.isExternalLink(link);
				if (external)
					{
					if (config.macros.attach.isAttachment(link))
						{
						e = createExternalLink(w.output,link);
						e.href=config.macros.attach.getAttachment(link);
						e.title = config.macros.attach.linkTooltip + link;
						}
					else
						e = createExternalLink(w.output,link);
					}
				else 
					e = createTiddlyLink(w.output,link,false,null,w.isStatic);
				// ELS -------------
				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];
			// ELS -------------
			if (config.macros.attach.isAttachment(lookaheadMatch[4]))
				img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);
			// ELS -------------
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
//}}}
//{{{
	// find the formatter for "prettyLink" and replace the handler
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="prettyLink"; i++);
	if (i<config.formatters.length)	{
		config.formatters[i].handler=function(w) {
			this.lookaheadRegExp.lastIndex = w.matchStart;
			var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
			if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
				var e;
				var text = lookaheadMatch[1];
				if(lookaheadMatch[3]) {
					// Pretty bracketted link
					var link = lookaheadMatch[3];
					if (config.macros.attach.isAttachment(link)) {
						e = createExternalLink(w.output,link);
						e.href=config.macros.attach.getAttachment(link);
						e.title=config.macros.attach.linkTooltip+link;
					}
					else e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link))
						? createExternalLink(w.output,link)
						: createTiddlyLink(w.output,link,false,null,w.isStatic);
				} else {
					e = createTiddlyLink(w.output,text,false,null,w.isStatic);
				}
				createTiddlyText(e,text);
				w.nextMatch = this.lookaheadRegExp.lastIndex;
			}
		}
	} // if "prettyLink" formatter found
	this.initialized=true;
}
//}}}
//{{{
config.macros.attach.init_formatters(); // load time init
//}}}
//{{{
if (TiddlyWiki.prototype.coreGetRecursiveTiddlerText==undefined) {
	TiddlyWiki.prototype.coreGetRecursiveTiddlerText = TiddlyWiki.prototype.getRecursiveTiddlerText;
	TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth) {
		return config.macros.attach.isAttachment(title)?
			config.macros.attach.getAttachment(title):this.coreGetRecursiveTiddlerText.apply(this,arguments);
	}
}
//}}}
/***
|Name|BreadcrumbsPlugin|
|Author|Eric Shulman|
|Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|
|Documentation|http://www.TiddlyTools.com/#BreadcrumbsPluginInfo|
|Version|2.1.0|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler,TiddlyWiki.prototype.deleteTiddler|
|Options|##Configuration|
|Description|list/jump to tiddlers viewed during this session plus "back" button/macro|
This plugin provides a list of links to all tiddlers opened during the session, creating a "trail of breadcrumbs" from one tiddler to the next, allowing you to quickly navigate to any previously viewed tiddler, or select 'home' to reset the display to the initial set of tiddlers that were open at the start of the session (i.e., when the document was loaded into the browser).
!!!!!Documentation
<<<
see [[BreadcrumbsPluginInfo]]
<<<
!!!!!Configuration
<<<
<<option chkCreateDefaultBreadcrumbs>> automatically create breadcrumbs display (if needed)
<<option chkShowBreadcrumbs>> show/hide breadcrumbs display
<<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler
<<option chkBreadcrumbsHideHomeLink>> omit 'Home' link from breadcrumbs display
<<option chkBreadcrumbsSave>> prompt to save breadcrumbs when 'Home' link is pressed
<<option chkShowStartupBreadcrumbs>> show breadcrumbs for 'startup' tiddlers
<<option chkBreadcrumbsReverse>> show breadcrumbs in reverse order (most recent first)
<<option chkBreadcrumbsLimit>> limit breadcrumbs display to {{twochar{<<option txtBreadcrumbsLimit>>}}} items
<<option chkBreadcrumbsLimitOpenTiddlers>> limit open tiddlers to {{twochar{<<option txtBreadcrumbsLimitOpenTiddlers>>}}} items

<<<
!!!!!Revisions
<<<
2009.03.22 [2.1.0] added 'save breadcrumbs to tiddler' feature
| Please see [[BreadcrumbsPluginInfo]] for previous revision details |
2006.02.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.BreadcrumbsPlugin= {major: 2, minor: 1, revision: 0, date: new Date("March 2, 2009")};

var co=config.options; // abbreviation

// show/hide display option (default is to SHOW breadcrumbs)
if (co.chkShowBreadcrumbs===undefined) co.chkShowBreadcrumbs=true;

// REORDER breadcrumbs when visiting previously viewed tiddler (default)
if (co.chkReorderBreadcrumbs===undefined) co.chkReorderBreadcrumbs=true;

// create default breadcrumbs display as needed (default is to CREATE)
if (co.chkCreateDefaultBreadcrumbs===undefined) co.chkCreateDefaultBreadcrumbs=true;

// show breadcrumbs for 'startup' tiddlers (default is FALSE = only show crumbs for tiddlers opened after startup)
if (co.chkShowStartupBreadcrumbs===undefined) co.chkShowStartupBreadcrumbs=false;

// show crumbs in reverse order (most recent first)
if (co.chkBreadcrumbsReverse===undefined) co.chkBreadcrumbsReverse=false;

// limit number of crumbs displayed
if (co.chkBreadcrumbsLimit===undefined) co.chkBreadcrumbsLimit=false;
if (co.txtBreadcrumbsLimit===undefined) co.txtBreadcrumbsLimit=5;

// limit number of open tiddlers
if (co.chkBreadcrumbsLimitOpenTiddlers===undefined) co.chkBreadcrumbsLimitOpenTiddlers=false;
if (co.txtBreadcrumbsLimitOpenTiddlers===undefined) co.txtBreadcrumbsLimitOpenTiddlers=3;

// omit home link from breadcrumbs display
if (co.chkBreadcrumbsHideHomeLink===undefined) co.chkBreadcrumbsHideHomeLink=false;

// prompt for 'save crumbs' when 'home' button is pressed
if (co.chkBreadcrumbsSave===undefined) co.chkBreadcrumbsSave=false;

config.macros.breadcrumbs =  {
	crumbs: [], // the list of current breadcrumbs
	askMsg: "Save current breadcrumbs before clearing?\nPress OK to save, or CANCEL to continue without saving.",
	saveMsg: 'Enter the name of a tiddler in which to save the current breadcrumbs',
	saveTitle: 'SavedBreadcrumbs',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var area=createTiddlyElement(place,"span",null,"breadCrumbs",null);
		area.setAttribute("homeSep",params[0]?params[0]:this.homeSeparator); // custom home separator
		area.setAttribute("crumbSep",params[1]?params[1]:this.crumbSeparator); // custom crumb separator
		this.render(area);
	},
	add: function (title) {
		var thisCrumb = title;
		var ind = this.crumbs.indexOf(thisCrumb);
		if(ind === -1)
			this.crumbs.push(thisCrumb);
		else if (config.options.chkReorderBreadcrumbs)
			this.crumbs.push(this.crumbs.splice(ind,1)[0]); // reorder crumbs
		else
			this.crumbs=this.crumbs.slice(0,ind+1); // trim crumbs
		if (config.options.chkBreadcrumbsLimitOpenTiddlers)
			this.limitOpenTiddlers();
		this.refresh();
		return false;
	},
	getAreas: function() {
		var crumbAreas=[];
		// find all DIVs with classname=="breadCrumbs"
		// Note: use try/catch to avoid "Bad NPObject as private data" fatal error  caused when
		// some versions of embedded QuickTime player element is accessed by hasClass() function.
		var all=document.getElementsByTagName("*");
		for (var i=0; i<all.length; i++)
			try{ if (hasClass(all[i],"breadCrumbs")) crumbAreas.push(all[i]); } catch(e) {;}
		// find single DIV w/fixed ID (backward compatibility)
		var byID=document.getElementById("breadCrumbs")
		if (byID && !hasClass(byID,"breadCrumbs")) crumbAreas.push(byID);
		if (!crumbAreas.length && config.options.chkCreateDefaultBreadcrumbs) {
			// no existing crumbs display areas... create one...
			var defaultArea = createTiddlyElement(null,"span",null,"breadCrumbs",null);
		 	defaultArea.style.display= "none";
			var targetArea= document.getElementById("tiddlerDisplay");
		 	targetArea.parentNode.insertBefore(defaultArea,targetArea);
			crumbAreas.push(defaultArea);
		}
		return crumbAreas;
	},
	refresh: function() {
		var crumbAreas=this.getAreas();
		for (var i=0; i<crumbAreas.length; i++) {
			crumbAreas[i].style.display = config.options.chkShowBreadcrumbs?"block":"none";
			removeChildren(crumbAreas[i]);
			this.render(crumbAreas[i]);
		}
	},
	render: function(here) {
		var co=config.options; var out=""
		var homeSep=here.getAttribute("homeSep"); if (!homeSep) homeSep=this.homeSeparator;
		var crumbSep=here.getAttribute("crumbSep"); if (!crumbSep) crumbSep=this.crumbSeparator;
		if (!co.chkBreadcrumbsHideHomeLink) {
			createTiddlyButton(here,"Home",null,this.home,"tiddlyLink tiddlyLinkExisting");
			out+=homeSep;
		}
		for (c=0; c<this.crumbs.length; c++) // remove non-existing tiddlers from crumbs
			if (!store.tiddlerExists(this.crumbs[c]) && !store.isShadowTiddler(this.crumbs[c]))
				this.crumbs.splice(c,1);
		var count=this.crumbs.length;
		if (co.chkBreadcrumbsLimit && co.txtBreadcrumbsLimit<count) count=co.txtBreadcrumbsLimit;
		var list=[];
		for (c=this.crumbs.length-count; c<this.crumbs.length; c++) list.push('[['+this.crumbs[c]+']]');
		if (co.chkBreadcrumbsReverse) list.reverse();
		out+=list.join(crumbSep);
		wikify(out,here);
	},
	home: function() {
		var cmb=config.macros.breadcrumbs;
		if (config.options.chkBreadcrumbsSave && confirm(cmb.askMsg)) cmb.saveCrumbs();
		story.closeAllTiddlers(); restart();
		cmb.crumbs = []; var crumbAreas=cmb.getAreas();
		for (var i=0; i<crumbAreas.length; i++) crumbAreas[i].style.display = "none";
		return false;
	},
	saveCrumbs: function() {
		var tid=prompt(this.saveMsg,this.saveTitle); if (!tid||!tid.length) return; // cancelled by user
		var t=store.getTiddler(tid);
		if(t && !confirm(config.messages.overwriteWarning.format([tid]))) return;
		var who=config.options.txtUserName;
		var when=new Date();
		var text='[['+this.crumbs.join(']]\n[[')+']]';
		var tags=t?t.tags:[]; tags.pushUnique('story');
		var fields=t?t.fields:{};
		store.saveTiddler(tid,tid,text,who,when,tags,fields);
		story.displayTiddler(null,tid);
		story.refreshTiddler(tid,null,true);
		displayMessage(tid+' has been '+(t?'updated':'created'));
	},
	limitOpenTiddlers: function() {
		var limit=config.options.txtBreadcrumbsLimitOpenTiddlers; if (limit<1) limit=1;
		for (c=this.crumbs.length-1; c>=0; c--) {
			var tid=this.crumbs[c];
			var elem=document.getElementById(story.idPrefix+tid);
			if (elem) { // tiddler is displayed
				if (limit <=0) { // display limit has been reached
					if (elem.getAttribute("dirty")=="true") { // tiddler is being edited
						var msg="'"+tid+"' is currently being edited.\n\n";
						msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
						if (confirm(msg)) { story.saveTiddler(tid); story.closeTiddler(tid); }
					}
					else
						story.closeTiddler(this.crumbs[c]);
				}
				limit--;
			}
		}
	}
};
if (config.macros.breadcrumbs.homeSeparator==undefined) // note: not a cookie
	config.macros.breadcrumbs.homeSeparator=" | ";
if (config.macros.breadcrumbs.crumbSeparator==undefined)  // note: not a cookie
	config.macros.breadcrumbs.crumbSeparator=" > ";

config.commands.previousTiddler = {
	text: 'back',
	tooltip: 'view the previous tiddler',
	hideReadOnly: false,
	dateFormat: 'DDD, MMM DDth YYYY hh:0mm:0ss',
	handler: function(event,src,title) {
		var here=story.findContainingTiddler(src); if (!here) return;
		var crumbs=config.macros.breadcrumbs.crumbs;
		if (crumbs.length>1) {
			var crumb=crumbs[crumbs.length-2];
			story.displayTiddler(here,crumb);
		}
		else
			config.macros.breadcrumbs.home();
		return false;
	}
};

config.macros.previousTiddler= {
	label: 'back',
	prompt: 'view the previous tiddler',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var label=params.shift(); if (!label) label=this.label;
		var prompt=params.shift(); if (!prompt) prompt=this.prompt;
		createTiddlyButton(place,label,prompt,function() {
			var crumbs=config.macros.breadcrumbs.crumbs;
			if (crumbs.length>1) {
				var crumb=crumbs[crumbs.length-2];
				story.displayTiddler(place,crumb);
			}
			else
				config.macros.breadcrumbs.home();
		});
	}
}

// hijack story.displayTiddler() so crumbs can be refreshed when a tiddler is displayed
if (Story.prototype.breadCrumbs_coreDisplayTiddler==undefined)
	Story.prototype.breadCrumbs_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
{
	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
	this.breadCrumbs_coreDisplayTiddler.apply(this,arguments);
	// if not displaying tiddler during document startup, then add it to the breadcrumbs
	// note: 'startingUp' flag is a global, set/reset by the core init() function
	if (!startingUp || config.options.chkShowStartupBreadcrumbs) config.macros.breadcrumbs.add(title);
}

// hijack store.removeTiddler() so crumbs can be refreshed when a tiddler is deleted
if (TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler==undefined)
	TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler=TiddlyWiki.prototype.removeTiddler;
TiddlyWiki.prototype.removeTiddler= function(title)
{
	this.breadCrumbs_coreRemoveTiddler.apply(this,arguments);
	config.macros.breadcrumbs.refresh();
}
//}}}
/***
|''Name''|DeprecatedFunctionsPlugin|
|''Description''|Provides support for functions removed from the TiddlyWiki core|
|''Version''|1.0.0|
|''Status''|stable|
|''Source''|http://www.tiddlywiki.com/coreplugins.html#DeprecatedFunctionsPlugin|
|''~CodeRepository:''|http://svn.tiddlywiki.org/Trunk/association/plugins/DeprecatedFunctionsPlugin/DeprecatedFunctionsPlugin.js |
|''License''|[[BSD open source license]]|
|''~CoreVersion''|2.3.0|
|''Feedback''|[[TiddlyWiki community|http://groups.google.com/group/TiddlyWiki]] |
|''Keywords''|legacySupport|
!Code
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.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");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
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");

}
//}}}
<!--{{{-->
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
/***
|''Name''|FiveStarsPlugin|
|''Description''|Five stars rating system for tiddlywiki|
|''Icon''|<...>|
|''Author''|Jelly Chen|
|''Contributors''|<...>|
|''Version''|0.1.8|
|''Date''|Sep 10 2009|
|''Status''|stable|
|''Source''|http://sinojellyempty.TiddlySpot.com/#FiveStarsPlugin|
|''CodeRepository''|<...>|
|''Copyright''|Guodong Workshop. 2009-2019. All rights reserved.|
|''License''|GPL v2|
|''CoreVersion''|2.1.0|
|''Requires''|<...>|
|''Overrides''|<...>|
|''Feedback''|sinojelly@163.com|
|''Documentation''|http://sinojelly.blog.51cto.com/479153/197110|
|''Keywords''|FiveStars, vote, rating|
!Description
Five stars rating system for tiddlywiki, the rating info associate with one tiddler are stored in the tiddler's extended fields. 
!Notes
Thanks to FND for answering my question in Google TiddlyWikiDev Group.
Thanks to BramChen for providing many valuable improvements.
Save the files star1.png, star2.png and empty.html in the same directory.
You can find the files star1.png, star2.png at:
http://sinojelly.blog.51cto.com/479153/197110
or:
http://sinojelly.20x.cc/TiddlyPedia/
!Usage
You can add macro invoke in the tiddler as follows. 
{{{
<<rating>>
}}}
Also, if you want to add fivestar to every tiddlers, you should modify ViewTemplate as follows:
modify:
{{{
<div class='viewer' macro='view text wikified'></div>
}}}
to:
{{{
<div class='viewer' macro='view text wikified'><span macro="rating"></span><br/></div>
}}}
!!Parameters
None
!!Examples
<<rating>>
!Configuration Options
None
!Search Rating
''Search rating: ''<html><input id="i_1" type="text" size=6/><a id="a_1" class="button" href="javascript:;";>go</a></html>
{{r_1{<br />}}}
<<tiddler - with:{{
function search_rating(n) {
	var titles=[];
	store.forEachTiddler(function(title, tiddler){
	if (tiddler.fields["rating"] == n.toString())
		titles.push(tiddler.title);});
	return titles;
}

(function($){
	$("#a_1").click(function(){
		var input=$("#i_1")[0].value,
			titles=search_rating(input),
			li=(titles.length==0) ? "* Not found." : "#[[" + titles.join("]]\n#[[")+"]]",
			r=$("#tiddler"+tiddler.title).find(".r_1")
		;
		r.text(" ");
		wikify(li,r[0]);
	})
})(jQuery);
}}>>
!Search Rating Notes
Thanks to BramChen for providing scenario and code.
You can use Search Rating in other tiddlers as this:
{{{
<<tiddler [[FiveStarsPlugin##Search Rating]]>>
}}}
!Revision History
!!v0.0.1 (2009-08-27)  Client OK.
* View fivestar ok.
* Can be clicked to vote, but not any rating info stored.
!!v0.1.0 (2009-09-01)  Write rating info tiddler OK.
* Rating info store in *_fivestar_rating tiddler.
!!v0.1.1 (2009-09-02)  Fixed bugs of vote and stars.
* Support voting more than one tiddler insight.
!!v0.1.2 (2009-09-02)  Record voting info in tiddler's extended fields.
* Record voting info in tiddler's extended fields.
* Load the rating info while displying a tiddler and display the rating info as "(Rated 4 with 176 votes)".
!!v0.1.3 (2009-09-03)  Picture URL.
* Record the last rating as average.
* Use URL to specify  pictures .
!!v0.1.4 (2009-09-06)  Make the simplest version for persional using.
* Only record the last rating info.
!!v0.1.5 (2009-09-06)  Not lose highlight if the stars have been highlighted.
* Not lose highlight if the stars have been highlighted.
!!v0.1.6 (2009-09-10)  Support search the specified rating tiddler.
* You can search the specified rating tiddler.
!!v0.1.7 (2009-09-10)  Support search rating in other tiddlers.
* Support search rating in other tiddlers.
!!v0.1.8 (2009-09-10)  Include pictures data in this tiddler.
* Include pictures(star1.png, star2.png) data in this tiddler.
!To Do for Server Side Using
# Can not vote WelcomeToTiddlyspot and GettingStarted.
# Using lock to support more than one user at the same time to vote the same tiddler.
# Get the real IP address.
# Auto save and upload rating info after voting.
# How to get all the tiddlers with the same rating?
# Bug: The stars become unhighlighted after voting.(if alert a message box such as alert(n), no problem. Message box avoid mouse rollover the stars.)
# Make others can vote the tiddlers, not only the owner can.
/%# 比较奇怪:每次我修改这个Tiddler之后,保存刷新,然后搜索rating,则搜索不出任何东西。必须关闭FireFox,再重新打开该文件,才能正常使用。%/
You're welcome to make these ToDo's implemented.
!Code
***/
//{{{
//var set=false;
var init_highlightnum = 0;
var v=0;  
var RatingLevel = new Array("poor", "below average", "average", "above average", "excellent", "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp");
function loadStars()
{
	star1 = new Image();
	star1.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gJGxQpCZ4Equ4AAASsSURBVDjLlZVdiF1XFcd/a+9z7p2vOy8d0zY6TSWaxii0NlXQttJqHzSKiFhpoab6oogW+yBFUXxQKCj4Uaoogk+KKRWlfkAfhIIKpgZtTam2xKTJpM183Zl7Z+7H+dp7r+XDnQljlQY3nKdz9m+vs/b//1/y6A9+xGsvgVgi4jDfdmAGGNjkrfNsXjjN6rnTLC/9g5VX+vS64K5IFUc2fvmwqzYWEe+AjL37RP7nxiuAxSRW2UJ46dFr5prPqakBU3vhFsPOT/wfYEMgFAfuvOe+O254y/4PpBBfB8wAOYigiXqwgabwX5W/FtgZxkzcfFdnoZO9/s1HDmfN8LAhU8A0kJmpXLEVJk5M3G4PM8Cban5wsfXJvJ3RzlNrNq2+3/BTwNxOS1q7305u+VVgE6HV9M2PuxqjxpgkBfVBi8H1B48ceqc4odXOOHBNflcMYTaqWFQhqNdoLkaVBOSC5LvgDHFkxdqhg/v9J9qzHd/f7NcIvgmpmW6Pb77q2ps7qOC845Y777qx/7unvmj59Ip3EsQ0+FllebQ93tLweNT0ihk5EDMDLIWWrT17/B33fvo6P51hCTBDEPKWhzSpYn4+yz78sffei05k5hDGvXWeePEPTzd1/VtNoW1GwEiZmPo0t/j8maZzrHPybz+88dZbbp+eb4MKqEGy3UtARGi125NuhobTv3xY//hPTpzdnHpkXK6OY1NPx0A0A3/sgx8SwVrqp7cvbuRPvvTXU3Ld4huOtqcyL8jkGtQmWrUIqaIe9PjN9x5c//0L899fqeYeG2+vV4PechwOxsVoSNXUJAcooA71eTsPW3Nv/c7PHz/1wOr55QIADeBbmG+Dnya5OX72rS+debr39m+OmP3TaGMp29q42IyG/XFVUseAArYrtwRUYKV3FmN74eTm8tIANwMuBwtgEVMFhUGcXy9jurC9dt563YtbW73u9mioo6qkSZEkAg4RMFXTkExjpaab7WbjbW86esfVWDU5NTosCYLgnLA4s3ZD2VvpjEf9wWiwVYwGVhRj6rok7qgXF4sBoRoSq7GFYjvW40Fzdae5rd02QZWyEH78lc8+c+Lr959vwkQpxx76xUIe1g9WdVVUFaEoCNWYlAKKTdydlYMuIoJpshBqTUFm3vP5j9wNiVM/fbB88qR/YtMf+nXT7c1f+sI9xx/49mO3tTOR/bOjm85dan6lisYA4VVZ5NbO/Z3Vs8+ydv456b581qqVZ45a0V1YXloZnXgq/+py3fnJYO3Mdr+79K+/XPRfe+hTH/3uxqULev+XH3kfqZxPiYQhtpPQu4/cfeu1O0c4KcYDu/4qd3zfTPj4i/19D0dxg1Buz5bFoK7K0IAk8y7tm3PvvumAfObPZ5pvXFrldDlkVDUUXLYSyO1vZG9mu8xLx8TnGFNImg2NxaqkrGsCQCunJRnWypkLDWk8YlgXDBulsb3gI3P/mXaqiPdMZZ4pA0mR2NSElIgA3pPlLVpqGIbEhhASjUK4PK+ATHWHKNDUaIg4geDcBGSGqk1MBJCUGANBJrYkGao73txbYXY5p2UiEwNVCFHZNTQGJpenCilBUptEvOydrHvWvwGT9K2B/6ho5wAAAABJRU5ErkJggg==";
	star2 = new Image();
	star2.src= "data:image/png;base64,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";
}
function highlight(id)
{
	//if (set==false)
	{
		var s=id.split("_star_");
		y=s[1]*1+1;
		for (i=1;i<y;i++)
		{
			document.getElementById(s[0]+'_star_'+i.toString()).src= star2.src;
		}
		document.getElementById(s[0]+'_vote').innerHTML=RatingLevel[s[1] - 1];
   }
}
function losehighlight(id)
{
	//if (set==false)
	{
		var s=id.split("_star_");
		for (i=1 + init_highlightnum;i<6;i++) // 已高亮的不变暗 
		{
			document.getElementById(s[0]+'_star_'+i.toString()).src=star1.src;
			document.getElementById(s[0]+'_vote').innerHTML=RatingLevel[5];//""
		}
	}
}
function setStar(id)
{
	var s=id.split("_star_");
	y = s[1] * 1 + 1;
	for (i=1;i<y;i++) 
	{
		document.getElementById(s[0]+'_star_'+i.toString()).src= star2.src;
	}
}
function saveStar(id)
{
    var s=id.split("_star_");
    var title = s[0],
        n=s[1];
    setStar(id);

    document.getElementById(title+'_vote').innerHTML="Thank you for your vote!";

    var tiddler = store.getTiddler(title);
    tiddler.fields["rating"] = n;
}
config.macros.rating = { 
	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
                star1_data=store.getTiddlerText("star1.png##data");
                star2_data=store.getTiddlerText("star2.png##data");
		loadStars();
                highlightnum = parseInt((tiddler.fields["rating"] || 0));
                init_highlightnum = highlightnum;
		var starsHtml='<html>',
                // 使用网络路径
			star='<img src= "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gJGxQpCZ4Equ4AAASsSURBVDjLlZVdiF1XFcd/a+9z7p2vOy8d0zY6TSWaxii0NlXQttJqHzSKiFhpoab6oogW+yBFUXxQKCj4Uaoogk+KKRWlfkAfhIIKpgZtTam2xKTJpM183Zl7Z+7H+dp7r+XDnQljlQY3nKdz9m+vs/b//1/y6A9+xGsvgVgi4jDfdmAGGNjkrfNsXjjN6rnTLC/9g5VX+vS64K5IFUc2fvmwqzYWEe+AjL37RP7nxiuAxSRW2UJ46dFr5prPqakBU3vhFsPOT/wfYEMgFAfuvOe+O254y/4PpBBfB8wAOYigiXqwgabwX5W/FtgZxkzcfFdnoZO9/s1HDmfN8LAhU8A0kJmpXLEVJk5M3G4PM8Cban5wsfXJvJ3RzlNrNq2+3/BTwNxOS1q7305u+VVgE6HV9M2PuxqjxpgkBfVBi8H1B48ceqc4odXOOHBNflcMYTaqWFQhqNdoLkaVBOSC5LvgDHFkxdqhg/v9J9qzHd/f7NcIvgmpmW6Pb77q2ps7qOC845Y777qx/7unvmj59Ip3EsQ0+FllebQ93tLweNT0ihk5EDMDLIWWrT17/B33fvo6P51hCTBDEPKWhzSpYn4+yz78sffei05k5hDGvXWeePEPTzd1/VtNoW1GwEiZmPo0t/j8maZzrHPybz+88dZbbp+eb4MKqEGy3UtARGi125NuhobTv3xY//hPTpzdnHpkXK6OY1NPx0A0A3/sgx8SwVrqp7cvbuRPvvTXU3Ld4huOtqcyL8jkGtQmWrUIqaIe9PjN9x5c//0L899fqeYeG2+vV4PechwOxsVoSNXUJAcooA71eTsPW3Nv/c7PHz/1wOr55QIADeBbmG+Dnya5OX72rS+debr39m+OmP3TaGMp29q42IyG/XFVUseAArYrtwRUYKV3FmN74eTm8tIANwMuBwtgEVMFhUGcXy9jurC9dt563YtbW73u9mioo6qkSZEkAg4RMFXTkExjpaab7WbjbW86esfVWDU5NTosCYLgnLA4s3ZD2VvpjEf9wWiwVYwGVhRj6rok7qgXF4sBoRoSq7GFYjvW40Fzdae5rd02QZWyEH78lc8+c+Lr959vwkQpxx76xUIe1g9WdVVUFaEoCNWYlAKKTdydlYMuIoJpshBqTUFm3vP5j9wNiVM/fbB88qR/YtMf+nXT7c1f+sI9xx/49mO3tTOR/bOjm85dan6lisYA4VVZ5NbO/Z3Vs8+ydv456b581qqVZ45a0V1YXloZnXgq/+py3fnJYO3Mdr+79K+/XPRfe+hTH/3uxqULev+XH3kfqZxPiYQhtpPQu4/cfeu1O0c4KcYDu/4qd3zfTPj4i/19D0dxg1Buz5bFoK7K0IAk8y7tm3PvvumAfObPZ5pvXFrldDlkVDUUXLYSyO1vZG9mu8xLx8TnGFNImg2NxaqkrGsCQCunJRnWypkLDWk8YlgXDBulsb3gI3P/mXaqiPdMZZ4pA0mR2NSElIgA3pPlLVpqGIbEhhASjUK4PK+ATHWHKNDUaIg4geDcBGSGqk1MBJCUGANBJrYkGao73txbYXY5p2UiEwNVCFHZNTQGJpenCilBUptEvOydrHvWvwGT9K2B/6ho5wAAAABJRU5ErkJggg==" onmouseover="highlight(this.id)" onclick="setStar(this.id)" onmouseout="losehighlight(this.id)" onmouseup="saveStar(id,title)" id="%id%"  title='+tiddler.title+' style="width:30px; height:30px; float:left;" />';
		for (var i=1; i<6; i++)
		{                     
                        if (i <= highlightnum)
                        {
                            starsHtml += star.replace("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gJGxQpCZ4Equ4AAASsSURBVDjLlZVdiF1XFcd/a+9z7p2vOy8d0zY6TSWaxii0NlXQttJqHzSKiFhpoab6oogW+yBFUXxQKCj4Uaoogk+KKRWlfkAfhIIKpgZtTam2xKTJpM183Zl7Z+7H+dp7r+XDnQljlQY3nKdz9m+vs/b//1/y6A9+xGsvgVgi4jDfdmAGGNjkrfNsXjjN6rnTLC/9g5VX+vS64K5IFUc2fvmwqzYWEe+AjL37RP7nxiuAxSRW2UJ46dFr5prPqakBU3vhFsPOT/wfYEMgFAfuvOe+O254y/4PpBBfB8wAOYigiXqwgabwX5W/FtgZxkzcfFdnoZO9/s1HDmfN8LAhU8A0kJmpXLEVJk5M3G4PM8Cban5wsfXJvJ3RzlNrNq2+3/BTwNxOS1q7305u+VVgE6HV9M2PuxqjxpgkBfVBi8H1B48ceqc4odXOOHBNflcMYTaqWFQhqNdoLkaVBOSC5LvgDHFkxdqhg/v9J9qzHd/f7NcIvgmpmW6Pb77q2ps7qOC845Y777qx/7unvmj59Ip3EsQ0+FllebQ93tLweNT0ihk5EDMDLIWWrT17/B33fvo6P51hCTBDEPKWhzSpYn4+yz78sffei05k5hDGvXWeePEPTzd1/VtNoW1GwEiZmPo0t/j8maZzrHPybz+88dZbbp+eb4MKqEGy3UtARGi125NuhobTv3xY//hPTpzdnHpkXK6OY1NPx0A0A3/sgx8SwVrqp7cvbuRPvvTXU3Ld4huOtqcyL8jkGtQmWrUIqaIe9PjN9x5c//0L899fqeYeG2+vV4PechwOxsVoSNXUJAcooA71eTsPW3Nv/c7PHz/1wOr55QIADeBbmG+Dnya5OX72rS+debr39m+OmP3TaGMp29q42IyG/XFVUseAArYrtwRUYKV3FmN74eTm8tIANwMuBwtgEVMFhUGcXy9jurC9dt563YtbW73u9mioo6qkSZEkAg4RMFXTkExjpaab7WbjbW86esfVWDU5NTosCYLgnLA4s3ZD2VvpjEf9wWiwVYwGVhRj6rok7qgXF4sBoRoSq7GFYjvW40Fzdae5rd02QZWyEH78lc8+c+Lr959vwkQpxx76xUIe1g9WdVVUFaEoCNWYlAKKTdydlYMuIoJpshBqTUFm3vP5j9wNiVM/fbB88qR/YtMf+nXT7c1f+sI9xx/49mO3tTOR/bOjm85dan6lisYA4VVZ5NbO/Z3Vs8+ydv456b581qqVZ45a0V1YXloZnXgq/+py3fnJYO3Mdr+79K+/XPRfe+hTH/3uxqULev+XH3kfqZxPiYQhtpPQu4/cfeu1O0c4KcYDu/4qd3zfTPj4i/19D0dxg1Buz5bFoK7K0IAk8y7tm3PvvumAfObPZ5pvXFrldDlkVDUUXLYSyO1vZG9mu8xLx8TnGFNImg2NxaqkrGsCQCunJRnWypkLDWk8YlgXDBulsb3gI3P/mXaqiPdMZZ4pA0mR2NSElIgA3pPlLVpqGIbEhhASjUK4PK+ATHWHKNDUaIg4geDcBGSGqk1MBJCUGANBJrYkGao73txbYXY5p2UiEwNVCFHZNTQGJpenCilBUptEvOydrHvWvwGT9K2B/6ho5wAAAABJRU5ErkJggg==", "data:image/png;base64,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").replace("%id%",tiddler.title+'_star_'+i.toString());   
                        }
                        else
                        {                        
			     starsHtml += star.replace("%id%",tiddler.title+'_star_'+i.toString());
                        }
		}
		starsHtml += '<div id="'+tiddler.title+'_vote">&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp</div></html>';
		wikify(starsHtml, place);
	}
};
//}}}
/***
|Name|FoldHeadingsPlugin|
|Source|http://www.TiddlyTools.com/#FoldHeadingsPlugin|
|Version|1.1.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|automatically turn headings into slider-like panels that can be folded/unfolded with a single click|
This plugin defines a macro that automatically converts heading-formatted content into sliders that let you expand/collapse their content by clicking on individual headings.
!!!!!Usage
<<<
{{{
<<foldHeadings opened|closed tag tag tag...>>
}}}
where: ''opened'' or ''closed'' is a keyword indicating the initial state of the sections (default: opened), and ''tag tag tag...'' is an optional list of tags to match, so that the foldable effect is only applied to tiddlers that contain one (or more) of the indicated tags.  

When you place the macro in a tiddler, any heading-formatted content (i.e, "!" through "!!!!!") in that tiddler will automatically become //'fold-able'//, allowing you to expand/collapse the content that follows each heading simply by clicking on that heading.  Each content section begins with the first element following a heading, and continues until either another heading is found or the end of the tiddler is reached.  For example:
{{{
<<foldHeadings closed>>
}}}
is embedded in ''this'' tiddler in order to make all the headings it contains 'fold-able'.  Note that the macro has been placed at the //end// of the tiddler because it only operates on *rendered* content.  Thus, only headings that //precede// it in the same tiddler will become fold-able, as any headings that //follow// it are not actually rendered until //after// the macro has been processed.

You can further limit the effect of the macro within the tiddler by surrounding several headings in a "CSS class wrapper" ("""{{classname{...}}}""") or other containing DOM element (e.g., """@@display:inline;...@@""") and then embedding the {{{<<foldHeadings>>}}} macro inside that container (at the end)... only those headings that are also within that container will be made fold-able, instead of converting ''all'' the headings in that tiddler.

Conversely, if you want the fold-able ability to apply to the headings in //all// tiddlers, ''without having to alter //any// of those individual tiddlers'', you can add the macro to the end of your [[ViewTemplate]], so that it will be invoked after the content in each tiddler has been rendered, causing all headings they contain to automatically become fold-able.  For example:
{{{
<span macro="foldHeadings closed"></span>
}}}
You can also limit this effect to selected tiddlers by specifying one or more tags as additional macro parameters.  For example:
{{{
<span macro="foldHeadings closed systemConfig"></span>
}}}
is only applied to headings contained in //plugin tiddlers// (i.e., tiddlers tagged with <<tag systemConfig>>), while headings in other tiddlers remain unaffected by the macro, even though it is embedded in the common [[ViewTemplate]] definition.
<<<
!!!!!Revisions
<<<
2009.01.06 [1.1.1] removed hijack of scrollToSection() (see [[SectionLinksPlugin]] for equivalent code)
2008.11.17 [1.1.0] added hijack of 'scrollToSection()' function (see [[CoreTweaks]] and http://trac.tiddlywiki.org/ticket/784)
2007.12.06 [1.0.2] fix handling for empty sections when checking for sliderPanel/floatingPanel
2007.12.02 [1.0.1] fix handling when content following a heading is already a sliderPanel/floatingPanel
2007.12.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.FoldHeadingsPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2009,1,6)};

config.macros.foldHeadings = {
	guideText: "opened|closed className",
	showtip: "click to show '%0'",
	hidetip: "click to hide '%0'",
	showlabel: "more...",
	hidelabel: "[x]",
	html: "<span style='float:right;text-weight:normal;font-size:80%;' class='TiddlyLinkExisting'>%0&nbsp;</span>",
	handler: function(place,macroName,params) {
		var show=params[0] && params.shift().toLowerCase()!="closed";
		if (params.length) { // if filtering by tag(s)
			var here=story.findContainingTiddler(place);
			if (here) var tid=store.getTiddler(here.getAttribute("tiddler"));
			if (!tid || !tid.tags.containsAny(params)) return; // in a tiddler and not tagged... do nothing...
		}
		var elems=place.parentNode.getElementsByTagName("*");
		var heads=[]; for (var i=0; i<elems.length; i++) { // get non-foldable heading elements
			var n=elems[i].nodeName; var foldable=hasClass(elems[i],"foldable");
			if ((n=="H1"||n=="H2"||n=="H3"||n=="H4"||n=="H5")&&!foldable)
				heads.push(elems[i]);
			}
		for (var i=0; i<heads.length; i++) { var h=heads[i]; // for each heading element...
			// find start/end of section content (up to next heading or end of content)
			var start=end=h.nextSibling; while (end && end.nextSibling) {
				var n=end.nextSibling.nodeName.toUpperCase();
				if (n=="H1"||n=="H2"||n=="H3"||n=="H4"||n=="H5") break;
				end=end.nextSibling;
			}
			if (start && hasClass(start,"sliderPanel")||hasClass(start,"floatingPanel")) continue; // heading is already a slider!
			var span=createTiddlyElement(null,"span",null,"sliderPanel"); // create container
			span.style.display=show?"inline":"none"; // set initial display state
			h.parentNode.insertBefore(span,start); // and insert it following the heading element
			// move section elements into container...
			var e=start; while (e) { var next=e.nextSibling; span.insertBefore(e,null); if (e==end) break; e=next; }
			// set heading label/tip/cursor...
			h.title=(show?this.hidetip:this.showtip).format([h.textContent])
			h.innerHTML=this.html.format([show?this.hidelabel:this.showlabel])+h.innerHTML;
			h.style.cursor='pointer';
			addClass(h,"foldable"); // so we know it been done (and to add extra styles)
			h.onclick=function() {
				var panel=this.nextSibling; var show=panel.style.display=="none";
				// update panel display state
				if (config.options.chkAnimate) anim.startAnimating(new Slider(panel,show));
				else panel.style.display = show?"inline":"none";
				// update heading label/tip
				this.removeChild(this.firstChild); // remove existing label
				var fh=config.macros.foldHeadings; // abbreviation for readability...
				this.title=(show?fh.hidetip:fh.showtip).format([this.textContent])
				this.innerHTML=fh.html.format([show?fh.hidelabel:fh.showlabel])+this.innerHTML;
			}
		}		
	}
}

if (story.scrollToSection) {
Story.prototype.foldheadings_scrollToSection=Story.prototype.scrollToSection;
Story.prototype.scrollToSection=function(title,section) {
	var e=this.foldheadings_scrollToSection.apply(this,arguments);
	// if scrolling to a folded section heading, click to expand it
	if (e && hasClass(e,'foldable') && e.nextSibling.style.display=='none') e.onclick();
}
}
//}}}
// //<<foldHeadings closed>>
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
[[WelcomeToTiddlyspot]] 
[[GettingStarted]]
<!--{{{-->
<div id='header'>
</div>
<div id='sidebar'>
<div id='titleLine'></div>
<span id='siteTitle' refresh='content' tiddler='SiteTitle'></span>- <span id='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'
};

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			config.macros.option.genericCreate(place,'pas',opt,className,desc);
			// checkbox linked with this password "save this password on this computer"
			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);			
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
		},
		onChange: config.macros.option.genericOnChange
	}
});

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
			saveOptionCookie(opt);
		return config.options[name] ? "true" : "false";
	}
});

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
			}
		},
		set: function(name,value) {config.options[name] = decodeCookie(value);}
	}
});

// need to reload options to load passwordOptions
loadOptionsCookie();

/*
if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
/***
|Name|SearchOptionsPlugin|
|Source|http://www.TiddlyTools.com/#SearchOptionsPlugin|
|Documentation|http://www.TiddlyTools.com/#SearchOptionsPluginInfo|
|Version|3.0.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.search, TiddlyWiki.prototype.search, config.macros.search.onKeyPress|
|Options|##Configuration|
|Description|extend core search function with additional user-configurable options|
Adds extra options to core search function including selecting which data items to search, enabling/disabling incremental key-by-key searches, and generating a ''list of matching tiddlers'' instead of immediately displaying all matches.  This plugin also adds syntax for rendering 'search links' within tiddler content to embed one-click searches using pre-defined 'hard-coded' search terms.
!!!!!Documentation
>see [[SearchOptionsPluginInfo]]
!!!!!Configuration
<<<
Search in:
<<option chkSearchTitles>> titles <<option chkSearchText>> text <<option chkSearchTags>> tags <<option chkSearchFields>> fields <<option chkSearchShadows>> shadows
<<option chkSearchHighlight>> Highlight matching text in displayed tiddlers
<<option chkSearchList>> Show list of matches
<<option chkSearchListTiddler>> Write list to [[SearchResults]] tiddler
<<option chkSearchTitlesFirst>> Show title matches first
<<option chkSearchByDate>> Sort matching tiddlers by modification date (most recent first)
<<option chkIncrementalSearch>> Incremental key-by-key search: {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters,  {{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay
<<option chkSearchOpenTiddlers>> Search only in tiddlers that are currently displayed
<<option chkSearchExcludeTags>> Exclude tiddlers tagged with: <<option txtSearchExcludeTags>>
<<<
!!!!!Revisions
<<<
2009.01.16 [3.0.5] added chkSearchOpenTiddlers option to limit searches to displayed tiddlers only
|please see [[SearchOptionsPluginInfo]] for additional revision details|
2005.10.18 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.SearchOptionsPlugin= {major: 3, minor: 0, revision: 5, date: new Date(2009,1,16)};

var co=config.options; // abbrev
if (co.chkSearchTitles===undefined) co.chkSearchTitles=true;
if (co.chkSearchText===undefined) co.chkSearchText=true;
if (co.chkSearchTags===undefined) co.chkSearchTags=true;
if (co.chkSearchFields===undefined) co.chkSearchFields=true;
if (co.chkSearchTitlesFirst===undefined) co.chkSearchTitlesFirst=true;
if (co.chkSearchList===undefined) co.chkSearchList=true;
if (co.chkSearchHighlight===undefined) co.chkSearchHighlight=true;
if (co.chkSearchListTiddler===undefined) co.chkSearchListTiddler=false;
if (co.chkSearchByDate===undefined) co.chkSearchByDate=false;
if (co.chkIncrementalSearch===undefined) co.chkIncrementalSearch=true;
if (co.chkSearchShadows===undefined) co.chkSearchShadows=true;
if (co.txtIncrementalSearchDelay===undefined) co.txtIncrementalSearchDelay=500;
if (co.txtIncrementalSearchMin===undefined) co.txtIncrementalSearchMin=3;
if (co.chkSearchOpenTiddlers===undefined) co.chkSearchOpenTiddlers=false;
if (co.chkSearchExcludeTags===undefined) co.chkSearchExcludeTags=true;
if (co.txtSearchExcludeTags===undefined) co.txtSearchExcludeTags="excludeSearch";
if (config.macros.search.reportTitle==undefined)
	config.macros.search.reportTitle="SearchResults"; // note: not a cookie!
config.macros.search.label+="\xa0"; // a little bit of space just because it looks better
//}}}
// // searchLink: {{{[search[text to find]] OR [search[text to display|text to find]]}}}
//{{{
config.formatters.push( {
	name: "searchLink",
	match: "\\[search\\[",
	lookaheadRegExp: /\[search\[(.*?)(?:\|(.*?))?\]\]/mg,
	prompt: "search for: '%0'",
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var label=lookaheadMatch[1];
			var text=lookaheadMatch[2]||label;
			var prompt=this.prompt.format([text]);
			var btn=createTiddlyButton(w.output,label,prompt,
				function(){story.search(this.getAttribute("searchText"))},"searchLink");
			btn.setAttribute("searchText",text);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
});
//}}}
// // incremental search uses option settings instead of hard-coded delay and minimum input values
//{{{
var fn=config.macros.search.onKeyPress;
fn=fn.toString().replace(/500/g, "config.options.txtIncrementalSearchDelay||500");
fn=fn.toString().replace(/> 2/g, ">=(config.options.txtIncrementalSearchMin||3)");
eval("config.macros.search.onKeyPress="+fn);
//}}}
// // REPLACE story.search() for option to "show search results in a list"
//{{{
Story.prototype.search = function(text,useCaseSensitive,useRegExp)
{
	var co=config.options; // abbrev
	var re=new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
	if (config.options.chkSearchHighlight) highlightHack=re;
	var matches = store.search(re,co.chkSearchByDate?"modified":"title","");
	if (co.chkSearchByDate) matches=matches.reverse(); // most recent first
	var q = useRegExp ? "/" : "'";
	clearMessage();
	if (!matches.length) {
		if (co.chkSearchListTiddler) discardSearchResults();
		displayMessage(config.macros.search.failureMsg.format([q+text+q]));
	} else {
		if (co.chkSearchList||co.chkSearchListTiddler) 
			reportSearchResults(text,matches);
		else {
			var titles = []; for(var t=0; t<matches.length; t++) titles.push(matches[t].title);
			this.closeAllTiddlers(); story.displayTiddlers(null,titles);
			displayMessage(config.macros.search.successMsg.format([matches.length, q+text+q]));
		}
	}
	highlightHack = null;
}
//}}}
// // REPLACE store.search() for enhanced searching/sorting options
//{{{
TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
{
	var co=config.options; // abbrev
	var tids = this.reverseLookup("tags",excludeTag,false,sortField);
	var opened=[]; story.forEachTiddler(function(tid,elem){opened.push(tid);});

	// eliminate tiddlers tagged with excluded tags
	if (co.chkSearchExcludeTags&&co.txtSearchExcludeTags.length) {
		var ex=co.txtSearchExcludeTags.readBracketedList();
		var temp=[]; for(var t=tids.length-1; t>=0; t--)
			if (!tids[t].tags.containsAny(ex)) temp.push(tids[t]);
		tids=temp;
	}

	// scan for matching titles first...
	var results = [];
	if (co.chkSearchTitles) {
		for(var t=0; t<tids.length; t++) {
			if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue; 
			if(tids[t].title.search(searchRegExp)!=-1) results.push(tids[t]);
		}
		if (co.chkSearchShadows)
			for (var t in config.shadowTiddlers) {
				if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue; 
				if ((t.search(searchRegExp)!=-1) && !store.tiddlerExists(t))
					results.push((new Tiddler()).assign(t,config.shadowTiddlers[t]));
			}
	}
	// then scan for matching text, tags, or field data
	for(var t=0; t<tids.length; t++) {
		if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue; 
		if (co.chkSearchText && tids[t].text.search(searchRegExp)!=-1)
			results.pushUnique(tids[t]);
		if (co.chkSearchTags && tids[t].tags.join(" ").search(searchRegExp)!=-1)
			results.pushUnique(tids[t]);
		if (co.chkSearchFields && store.forEachField!=undefined)
			store.forEachField(tids[t],
				function(tid,field,val) {
					if (val.search(searchRegExp)!=-1) results.pushUnique(tids[t]);
				},
				true); // extended fields only
	}
	// then check for matching text in shadows
	if (co.chkSearchShadows)
		for (var t in config.shadowTiddlers) {
			if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue; 
			if ((config.shadowTiddlers[t].search(searchRegExp)!=-1) && !store.tiddlerExists(t))
				results.pushUnique((new Tiddler()).assign(t,config.shadowTiddlers[t]));
		}

	// if not 'titles first', or sorting by modification date,
	// re-sort results to so titles, text, tag and field matches are mixed together
	if(!sortField) sortField = "title";
	var bySortField=function(a,b){
		if(a[sortField]==b[sortField])return(0);else return(a[sortField]<b[sortField])?-1:+1;
	}
	if (!co.chkSearchTitlesFirst || co.chkSearchByDate) results.sort(bySortField);

	return results;
}
//}}}
// // HIJACK core {{{<<search>>}}} macro to add "report" and "simple inline" output
//{{{
config.macros.search.SOP_handler=config.macros.search.handler;
config.macros.search.handler = function(place,macroName,params)
{
	// if "report", use SearchOptionsPlugin report generator for inline output
	if (params[1]&&params[1].substr(0,6)=="report") {
		var keyword=params[0];
		var options=params[1].split("=")[1]; // split "report=option+option+..."
		var heading=params[2]?params[2].unescapeLineBreaks():"";
		var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
		if (matches.length) wikify(heading+window.formatSearchResults(keyword,matches,options),place);
	} else if (params[1]) {
		var keyword=params[0];
		var heading=params[1]?params[1].unescapeLineBreaks():"";
		var seperator=params[2]?params[2].unescapeLineBreaks():", ";
		var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
		if (matches.length) {
			var out=[];
			for (var m=0; m<matches.length; m++) out.push("[["+matches[m].title+"]]");
			wikify(heading+out.join(seperator),place);
		}
	} else
		config.macros.search.SOP_handler.apply(this,arguments);
};
//}}}
// // SearchResults panel handling
//{{{
setStylesheet(".searchResults { padding:1em 1em 0 1em; }","searchResults"); // matches std tiddler padding

config.macros.search.createPanel=function(text,matches,body) {

	function getByClass(e,c) { var d=e.getElementsByTagName("div");
		for (var i=0;i<d.length;i++) if (hasClass(d[i],c)) return d[i]; }
	var panel=createTiddlyElement(null,"div","searchPanel","searchPanel");
	this.renderPanel(panel,text,matches,body);
	var oldpanel=document.getElementById("searchPanel");
	if (!oldpanel) { // insert new panel just above tiddlers
		var da=document.getElementById("displayArea");
		da.insertBefore(panel,da.firstChild);
	} else { // if panel exists
		var oldwrap=getByClass(oldpanel,"searchResults");
		var newwrap=getByClass(panel,"searchResults");
		// if no prior content, just insert new content
		if (!oldwrap) oldpanel.insertBefore(newwrap,null);
		else {	// swap search results content but leave containing panel intact
			oldwrap.style.display='block'; // unfold wrapper if needed
			var i=oldwrap.getElementsByTagName("input")[0]; // get input field
			if (i) { var pos=this.getCursorPos(i); i.onblur=null; } // get cursor pos, ignore blur
			oldpanel.replaceChild(newwrap,oldwrap);
			panel=oldpanel; // use existing panel
		} 
	}
	this.showPanel(true,pos);
	return panel;
}

config.macros.search.renderPanel=function(panel,text,matches,body) {

	var wrap=createTiddlyElement(panel,"div",null,"searchResults");
	wrap.onmouseover = function(e){ addClass(this,"selected"); }
	wrap.onmouseout = function(e){ removeClass(this,"selected"); }
	// create toolbar: "open all", "fold/unfold", "close"
	var tb=createTiddlyElement(wrap,"div",null,"toolbar");
	var b=createTiddlyButton(tb, "open all", "open all matching tiddlers", function() {
		story.displayTiddlers(null,this.getAttribute("list").readBracketedList()); return false; },"button");
	var list=""; for(var t=0;t<matches.length;t++) list+='[['+matches[t].title+']] ';
	b.setAttribute("list",list);
	var b=createTiddlyButton(tb, "fold", "toggle display of search results", function() {
		config.macros.search.foldPanel(this); return false; },"button");
	var b=createTiddlyButton(tb, "close", "dismiss search results",	function() {
		config.macros.search.showPanel(false); return false; },"button");
	createTiddlyText(createTiddlyElement(wrap,"div",null,"title"),"Search for: "+text); // title
	wikify(body,createTiddlyElement(wrap,"div",null,"viewer")); // report
	return panel;
}

config.macros.search.showPanel=function(show,pos) {
	var panel=document.getElementById("searchPanel");
	var i=panel.getElementsByTagName("input")[0];
	i.onfocus=show?function(){config.macros.search.stayFocused(true);}:null;
	i.onblur=show?function(){config.macros.search.stayFocused(false);}:null;
	if (show && panel.style.display=="block") { // if shown, grab focus, restore cursor
		if (i&&this.stayFocused()) { i.focus(); this.setCursorPos(i,pos); }
		return;
	}
	if(!config.options.chkAnimate) {
		panel.style.display=show?"block":"none";
		if (!show) { removeChildren(panel); config.macros.search.stayFocused(false); }
	} else {
		var s=new Slider(panel,show,false,show?"none":"children");
		s.callback=function(e,p){e.style.overflow="visible";}
		anim.startAnimating(s);
	}
	return panel;
}

config.macros.search.foldPanel=function(button) {
	var d=document.getElementById("searchPanel").getElementsByTagName("div");
	for (var i=0;i<d.length;i++) if (hasClass(d[i],"viewer")) var v=d[i]; if (!v) return;
	var show=v.style.display=="none";
	if(!config.options.chkAnimate)
		v.style.display=show?"block":"none";
	else {
		var s=new Slider(v,show,false,"none");
		s.callback=function(e,p){e.style.overflow="visible";}
		anim.startAnimating(s);
	}
	button.innerHTML=show?"fold":"unfold";
	return false;
}

config.macros.search.stayFocused=function(keep) { // TRUE/FALSE=set value, no args=get value
	if (keep===undefined) return this.keepReportInFocus;
	this.keepReportInFocus=keep;
	return keep
}	

config.macros.search.getCursorPos=function(i) {
	var s=0; var e=0; if (!i) return { start:s, end:e };
	try {
		if (i.setSelectionRange) // FF
			{ s=i.selectionStart; e=i.selectionEnd; }
		if (document.selection && document.selection.createRange) { // IE
			var r=document.selection.createRange().duplicate();
			var len=r.text.length; s=0-r.moveStart('character',-100000); e=s+len;
		}
	}catch(e){};
	return { start:s, end:e };
}
config.macros.search.setCursorPos=function(i,pos) {
	if (!i||!pos) return; var s=pos.start; var e=pos.end;
	if (i.setSelectionRange) //FF
		i.setSelectionRange(s,e);
	if (i.createTextRange) // IE
		{ var r=i.createTextRange(); r.collapse(true); r.moveStart("character",s); r.select(); }
}
//}}}
// // SearchResults report generation
// note: these functions are defined globally, so they can be more easily redefined to customize report formats//
//{{{
if (!window.reportSearchResults) window.reportSearchResults=function(text,matches)
{
	var cms=config.macros.search; // abbrev
	var body=window.formatSearchResults(text,matches);
	if (!config.options.chkSearchListTiddler) // show #searchResults panel
		window.scrollTo(0,ensureVisible(cms.createPanel(text,matches,body)));
	else { // write [[SearchResults]] tiddler
		var title=cms.reportTitle;
		var who=config.options.txtUserName;
		var when=new Date();
		var tags="excludeLists excludeSearch temporary";
		var tid=store.getTiddler(title); if (!tid) tid=new Tiddler();
		tid.set(title,body,who,when,tags);
		store.addTiddler(tid);
		story.closeTiddler(title);
		story.displayTiddler(null,title);
	}
}

if (!window.formatSearchResults) window.formatSearchResults=function(text,matches,opt)
{
	var body='';
	var title=config.macros.search.reportTitle
	var q = config.options.chkRegExpSearch ? "/" : "'";
	if (!opt) var opt="all";
	var parts=opt.split("+");
	for (var i=0; i<parts.length; i++) { var p=parts[i].toLowerCase();
		if (p=="again"||p=="all")   body+=window.formatSearchResults_again(text,matches);
		if (p=="summary"||p=="all") body+=window.formatSearchResults_summary(text,matches);
		if (p=="list"||p=="all")    body+=window.formatSearchResults_list(text,matches);
		if (p=="buttons"||p=="all") body+=window.formatSearchResults_buttons(text,matches);
	}
	return body;
}

if (!window.formatSearchResults_again) window.formatSearchResults_again=function(text,matches)
{
	var title=config.macros.search.reportTitle
	var body='';
	// search again
	body+='{{span{<<search "'+text.replace(/"/g,'&#x22;')+'">> /%\n';
	body+='%/<html><input type="button" value="search again"';
	body+=' onclick="var t=this.parentNode.parentNode.getElementsByTagName(\'input\')[0];';
	body+=' config.macros.search.doSearch(t); return false;">';
	body+=' <a href="javascript:;" onclick="';
	body+=' var e=this.parentNode.nextSibling;';
	body+=' var show=e.style.display!=\'block\';';
	body+=' if(!config.options.chkAnimate) e.style.display=show?\'block\':\'none\';';
	body+=' else anim.startAnimating(new Slider(e,show,false,\'none\'));';
	body+=' return false;">options...</a>';
	body+='</html>@@display:none;border-left:1px dotted;margin-left:1em;padding:0;padding-left:.5em;font-size:90%;/%\n';
	body+='	%/<<option chkSearchTitles>>titles /%\n';
	body+='	%/<<option chkSearchText>>text /%\n';
	body+='	%/<<option chkSearchTags>>tags /%\n';
	body+='	%/<<option chkSearchFields>>fields /%\n';
	body+='	%/<<option chkSearchShadows>>shadows\n';
	body+='	<<option chkCaseSensitiveSearch>>case-sensitive /%\n';
	body+='	%/<<option chkRegExpSearch>>text patterns /%\n';
	body+='	%/<<option chkSearchByDate>>sorted by date\n';
	body+='	<<option chkSearchHighlight>> highlight matching text in displayed tiddlers\n';
	body+='	<<option chkIncrementalSearch>>incremental key-by-key search: /%\n';
	body+='	%/{{twochar{<<option txtIncrementalSearchMin>>}}} or more characters, /%\n';
	body+='	%/{{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay\n';
	body+='	<<option chkSearchOpenTiddlers>> search only in tiddlers that are currently displayed\n';
	body+='	<<option chkSearchExcludeTags>>exclude tiddlers tagged with:\n';
	body+='	{{editor{<<option txtSearchExcludeTags>>}}}/%\n';
	body+='%/@@}}}\n\n';
	return body;
}

if (!window.formatSearchResults_summary) window.formatSearchResults_summary=function(text,matches)
{
	// summary: nn tiddlers found matching '...', options used
	var body='';
	var co=config.options; // abbrev
	var title=config.macros.search.reportTitle
	var q = co.chkRegExpSearch ? "/" : "'";
	body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\n";
	var opts=[];
	if (co.chkSearchTitles) opts.push("titles");
	if (co.chkSearchText) opts.push("text");
	if (co.chkSearchTags) opts.push("tags");
	if (co.chkSearchFields) opts.push("fields");
	if (co.chkSearchShadows) opts.push("shadows");
	if (co.chkSearchOpenTiddlers) body+="^^//search limited to displayed tiddlers only//^^\n";
	body+="~~&nbsp; searched in "+opts.join(" + ")+"~~\n";
	body+=(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"^^&nbsp; using ":"")
		+(co.chkCaseSensitiveSearch?"case-sensitive ":"")
		+(co.chkRegExpSearch?"pattern ":"")
		+(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"matching^^\n":"");
	return body;
}

if (!window.formatSearchResults_list) window.formatSearchResults_list=function(text,matches)
{
	// bullet list of links to matching tiddlers
	var body='';
	var pattern=co.chkRegExpSearch?text:text.escapeRegExp();
	var sensitive=co.chkCaseSensitiveSearch?"mg":"img";
	var link='{{tiddlyLinkExisting{<html><nowiki><a href="javascript:;" onclick="'
		+'if(config.options.chkSearchHighlight)'
		+'	highlightHack=new RegExp(\x27'+pattern+'\x27.escapeRegExp(),\x27'+sensitive+'\x27);'
		+'story.displayTiddler(null,\x27%0\x27);'
		+'highlightHack = null; return false;'
		+'" title="%2">%1</a></html>}}}';
	for(var t=0;t<matches.length;t++) {
		body+="* ";
		if (config.options.chkSearchByDate)
			body+=matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" ";
		var title=matches[t].title;
		var fixup=title.replace(/'/g,"\\x27").replace(/"/g,"\\x22");
		var tid=store.getTiddler(title);
		var tip=tid?tid.getSubtitle():''; tip=tip.replace(/"/g,"&quot;");
		body+=link.format([fixup,title,tip])+'\n';
	}
	return body;
}

if (!window.formatSearchResults_buttons) window.formatSearchResults_buttons=function(text,matches)
{
	// embed buttons only if writing SearchResults to tiddler
	if (!config.options.chkSearchListTiddler) return "";
	// "open all" button
	var title=config.macros.search.reportTitle;
	var body="";
	body+="@@diplay:block;<html><input type=\"button\" href=\"javascript:;\" "
		+"onclick=\"story.displayTiddlers(null,[";
	for(var t=0;t<matches.length;t++)
		body+="'"+matches[t].title.replace(/\'/mg,"\\'")+"'"+((t<matches.length-1)?", ":"");
	body+="],1);\" accesskey=\"O\" value=\"open all matching tiddlers\"></html> ";
	// "discard SearchResults" button
	body+="<html><input type=\"button\" href=\"javascript:;\" "
		+"onclick=\"discardSearchResults()\" value=\"discard "+title+"\"></html>";
	body+="@@\n";
	return body;
}

if (!window.discardSearchResults) window.discardSearchResults=function()
{
	// remove the tiddler
	story.closeTiddler(config.macros.search.reportTitle);
	store.deleteTiddler(config.macros.search.reportTitle);
	store.notify(config.macros.search.reportTitle,true);
}
//}}}
/***
|Name|SectionLinksPlugin|
|Source|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Documentation|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Version|1.3.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|allow tiddler sections in TiddlyLinks to be used as anchor points|
This plugin enhances the processing of section references so they can be used in links to auto-scroll to the indicated heading within a tiddler (i.e., similar to the 'anchor' behavior provided in HTML by {{{<a name="foo">}}} and {{{<a href="#foo">...</a>}}})
!!!Usage
<<<
!!!!!{{{<<tiddler>>}}} macro 
>The {{{<<tiddler SomeTiddler##SomeSection>>}}} syntax has been extended so that when the tiddler title is omitted or the 'here' keyword is used (e.g., {{{<<tiddler ##SomeSection>>}}} or {{{<<tiddler here##SomeSection>>}}}), then the current containing tiddler is implied by default.
!!!!!~TiddlyLink syntax
>the standard link syntax has been extended so that a section name can included in a tiddler link (e.g., {{{[[SomeTiddler##SomeSection]]}}}).  When clicked, the tiddler is displayed and the specified section heading will be automatically scrolled into view. If the tiddler title is omitted or the 'here' keyword is used (e.g., {{{[[##SomeSection]]}}} or {{{[[here##SomeSection]]>>}}}), then the current containing tiddler is implied by default.
!!!!!"""<<sectionTOC>>""" macro
>This macro generates a 'Table of Contents'-style numbered-bullet list with links to all sections within the current tiddler.  Simply place the following macro at the //end of the tiddler content// (i.e., following all section headings):
{{{
<<sectionTOC>> or <<sectionTOC className>>
}}}
>Note: The macro must occur at the end of the tiddler in order to locate the rendered section headings that precede it. In addition, to position the macro's //output// within the tiddler, you must create a special 'target element' that uses a specified classname (default='sectionTOC'), like this:
{{{
{{sectionTOC{}}}
}}}
>When the {{{<<sectionTOC>>}}} macro is rendered, it will find the matching 'sectionTOC'-classed element and writes it's output there.  You can also add the macro and/or target elements directly to the [[ViewTemplate]] definition, so that every tiddler can automatically display the table of contents:
{{{
<span class='sectionTOC'></span> <!-- target element -->
...
<span macro='sectionTOC'></span> <!-- must be at end of tiddler -->
}}}
<<<
!!!Revisions
<<<
2009.08.21 [1.3.4] added handling to ignore leading/trailing whitespace in section references
2009.08.21 [1.3.3] in createTiddlyLink(), add tiddlyLinkNonExistingSection class if matching section is not found
2009.08.14 [1.3.2] in createTiddlyLink(), don't override core value for ~TiddlyLink attribute
2009.08.02 [1.3.1] in sectionTOC.handler(), trim leading/trailing whitespace from generated section links
2009.08.01 [1.3.0] in scrollToSection(), apply 3-tier section matching (exact, startsWith, contains)
2009.07.06 [1.2.2] fixed displayTiddler() hijack
2009.07.03 [1.2.1] in {{{<<sectionTOC>>}}}, suppress output if target is not found
2009.06.02 [1.2.0] added support for 'here' keyword in {{{[[here##section]]}}} links and {{{<<tiddler here##section>>}}} macro
2009.04.09 [1.1.1] in sectionTOC macro, make target visible when TOC is rendered.
2009.01.18 [1.1.0] added {{{<<sectionTOC>>}}} macro to generate numbered-bullet links to sections of current tiddler
2009.01.06 [1.0.0] converted to stand-alone plugin
2008.10.14 [0.0.0] initial release (as [[CoreTweaks]] #784 - http://trac.tiddlywiki.org/ticket/784)
<<<
!!!Code
***/
//{{{
version.extensions.SectionLinksPlugin= {major: 1, minor: 3, revision: 4, date: new Date(2009,8,21)};

Story.prototype.scrollToSection = function(title,section) {
	if (!title||!section) return; var t=this.getTiddler(title); if (!t) return null;
	var elems=t.getElementsByTagName('*'); var heads=[];
	for (var i=0; i<elems.length; i++)
		if (['H1','H2','H3','H4','H5'].contains(elems[i].nodeName)) heads.push(elems[i]);
	for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim()==section) break;
	if (i==heads.length) for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim().startsWith(section)) break;
	if (i==heads.length) for (var i=0; i<heads.length; i++)
		if (getPlainText(heads[i]).trim().indexOf(section)!=-1) break;
	if (i<heads.length) { var h=heads[i];
		// if section heading is collapsed, click to expand it - see [[FoldHeadingsPlugin]]
		if (hasClass(h,'foldable') && h.nextSibling.style.display=='none') h.onclick();
		// scroll *after* tiddler animation
		var delay=config.options.chkAnimate?config.animDuration+100:0;
		setTimeout('window.scrollTo('+findPosX(h)+','+findPosY(h)+')',delay);
		return h;
	}
}
//}}}
/***
!!!!core hijacks
***/
/***
!!!!!createTiddlyLink
***/
//{{{
// [[tiddlername##section]] and [[##section]]
if (!window.createTiddlyLink_section)
	window.createTiddlyLink_section=window.createTiddlyLink;
window.createTiddlyLink=function(place,title) {
	var t=story.findContainingTiddler(place); var tid=t?t.getAttribute('tiddler'):'';
	var parts=title.split(config.textPrimitives.sectionSeparator);
	var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
	if (!title.length || title.toLowerCase()=='here') title=tid;  // default=current tiddler
	arguments[1]=title;
	var btn=createTiddlyLink_section.apply(this,arguments);
	if (section) {
		btn.setAttribute('section',section);
		if (store.getTiddlerText(title+config.textPrimitives.sectionSeparator+section)===null)
			addClass(btn,'tiddlyLinkNonExistingSection');
	}
	return btn;
}
//}}}
/***
!!!!!onClickTiddlerLink
***/
//{{{
if (!window.onClickTiddlerLink_section)
	window.onClickTiddlerLink_section=window.onClickTiddlerLink;
window.onClickTiddlerLink=function(ev) {
	var e=ev||window.event;	var target=resolveTarget(e); var title=null;
	while (target!=null && title==null) {
		title=target.getAttribute('tiddlyLink');
		section=target.getAttribute('section');
		target=target.parentNode;
	} 
	var t=story.findContainingTiddler(target); var tid=t?t.getAttribute('tiddler'):'';
	if (title!=tid||!section) // avoid excess scrolling for intra-tiddler links
		onClickTiddlerLink_section.apply(this,arguments);
	story.scrollToSection(title,section);
	return false;
}
//}}}
/***
!!!!! displayTiddler
***/
//{{{
if (!Story.prototype.displayTiddler_section)
	Story.prototype.displayTiddler_section=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler)
{
	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
	var parts=title.split(config.textPrimitives.sectionSeparator);
	var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
	if (!title.length || title.toLowerCase()=='here') {
		var t=story.findContainingTiddler(place);
		title=t?t.getAttribute('tiddler'):'';
	}
	arguments[1]=title;  // default=current tiddler
	this.displayTiddler_section.apply(this,arguments);
	story.scrollToSection(title,section);
}
//}}}
/***
!!!!!isExternalLink
***/
//{{{
if (!config.formatterHelpers.isExternalLink_section)
	config.formatterHelpers.isExternalLink_section=config.formatterHelpers.isExternalLink;
config.formatterHelpers.isExternalLink=function(link) {
	if (link.indexOf(config.textPrimitives.sectionSeparator)!=-1) return false;
	return config.formatterHelpers.isExternalLink_section.apply(this,arguments);
}
//}}}
/***
!!!!!tiddler.handler
***/
//{{{
if (!config.macros.tiddler.handler_section)
	config.macros.tiddler.handler_section=config.macros.tiddler.handler;
config.macros.tiddler.handler=function(place,macroName,params,wikifier,paramString,tiddler)
{
	if (!params[0]) return;
	var sep=config.textPrimitives.sectionSeparator;
	var parts=params[0].split(sep); var tid=parts[0]; var sec=parts[1]; if (sec) sec=sec.trim();
	if ((tid.toLowerCase()=='here'||!tid.length) && sec) { // fixup for 'here##section' and '##section'
		var here=story.findContainingTiddler(place)
		var tid=here?here.getAttribute('tiddler'):tiddler?tiddler.title:'';
		arguments[2][0]=tid+sep+sec;
		arguments[4]=paramString.replace(new RegExp('(here)?'+sep+sec),tid+sep+sec);
	}
	config.macros.tiddler.handler_section.apply(this,arguments);
}
//}}}
/***
!!!!sectionTOC macro
***/
//{{{
config.macros.sectionTOC = {
	targetClass: 'sectionTOC',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var out=[];
		var targetClass=params[0]||this.targetClass;
		var t=story.findContainingTiddler(place); if (!t) return;
		var elems=t.getElementsByTagName('*');
		var level=5; // topmost heading level
		for (var i=0; i<elems.length; i++) {
			var txt=getPlainText(elems[i]).trim();
			var link='[['+txt+'|##'+txt+']]';
			switch(elems[i].nodeName) {
				case 'H1': out.push('#'+link);		level=1; break;
				case 'H2': out.push('##'+link);		level=level<2?level:2; break;
				case 'H3': out.push('###'+link);	level=level<3?level:3; break;
				case 'H4': out.push('####'+link);	level=level<4?level:4; break;
				case 'H5': out.push('#####'+link);	level=level<5?level:5; break;
				default: if (hasClass(elems[i],targetClass)) var target=elems[i];
			}
		}
		// trim excess bullet levels
		if (level>1) for (var i=0; i<out.length; i++) out[i]=out[i].substr(level-1);
		// show numbered list
		if (out.length && target) {
			if (target.style.display=='none') target.style.display='block';
			wikify(out.join('\n'),target);
		}
	}
}
//}}}
/***
!!!Invoke macro
{{{
<<sectionTOC>>
}}}
***/
// //<<sectionTOC>>
//{{{
// 设置默认的主题为TiddlyPedia
config.options.txtTheme = "TiddlyPedia"; 
//}}}
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.6|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler(), Story.prototype.displayTiddlers()|
|Options|##Configuration|
|Description|Show tiddlers one at a time with automatic permalink, or always open tiddlers at top/bottom of page.|
This plugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one tiddler displayed at a time.
!!!!!Documentation
>see [[SinglePageModePluginInfo]]
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)

Notes:
* The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}.
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2008.10.17 [2.9.6] changed chkSinglePageAutoScroll default to false
| Please see [[SinglePageModePluginInfo]] for previous revision details |
2005.08.15 [1.0.0] Initial Release.  Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts.
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageModePlugin= {major: 2, minor: 9, revision: 6, date: new Date(2008,10,17)};
//}}}
//{{{
config.paramifiers.SPM = { onstart: function(v) {
	config.options.chkSinglePageMode=eval(v);
	if (config.options.chkSinglePageMode && config.options.chkSinglePagePermalink && !config.browser.isSafari) {
		config.lastURL = window.location.hash;
		if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
	}
} };
//}}}
//{{{
if (config.options.chkSinglePageMode==undefined)
	config.options.chkSinglePageMode=false;
if (config.options.chkSinglePagePermalink==undefined)
	config.options.chkSinglePagePermalink=true;
if (config.options.chkSinglePageKeepFoldedTiddlers==undefined)
	config.options.chkSinglePageKeepFoldedTiddlers=false;
if (config.options.chkSinglePageKeepEditedTiddlers==undefined)
	config.options.chkSinglePageKeepEditedTiddlers=false;
if (config.options.chkTopOfPageMode==undefined)
	config.options.chkTopOfPageMode=false;
if (config.options.chkBottomOfPageMode==undefined)
	config.options.chkBottomOfPageMode=false;
if (config.options.chkSinglePageAutoScroll==undefined)
	config.options.chkSinglePageAutoScroll=false;
//}}}
//{{{
config.SPMTimer = 0;
config.lastURL = window.location.hash;
function checkLastURL()
{
	if (!config.options.chkSinglePageMode)
		{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
	if (config.lastURL == window.location.hash) return; // no change in hash
	var tids=decodeURIComponent(window.location.hash.substr(1)).readBracketedList();
	if (tids.length==1) // permalink (single tiddler in URL)
		story.displayTiddler(null,tids[0]);
	else { // restore permaview or default view
		config.lastURL = window.location.hash;
		if (!tids.length) tids=store.getTiddlerText("DefaultTiddlers").readBracketedList();
		story.closeAllTiddlers();
		story.displayTiddlers(null,tids);
	}
}


if (Story.prototype.SPM_coreDisplayTiddler==undefined)
	Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
{
	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
	var tiddlerElem=document.getElementById(story.idPrefix+title); // ==null unless tiddler is already displayed
	var opt=config.options;
	var single=opt.chkSinglePageMode && !startingUp;
	var top=opt.chkTopOfPageMode && !startingUp;
	var bottom=opt.chkBottomOfPageMode && !startingUp;
	if (single) {
		story.forEachTiddler(function(tid,elem) {
			// skip current tiddler and, optionally, tiddlers that are folded.
			if (	tid==title
				|| (opt.chkSinglePageKeepFoldedTiddlers && elem.getAttribute("folded")=="true"))
				return;
			// if a tiddler is being edited, ask before closing
			if (elem.getAttribute("dirty")=="true") {
				if (opt.chkSinglePageKeepEditedTiddlers) return;
				// if tiddler to be displayed is already shown, then leave active tiddler editor as is
				// (occurs when switching between view and edit modes)
				if (tiddlerElem) return;
				// otherwise, ask for permission
				var msg="'"+tid+"' is currently being edited.\n\n";
				msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
				if (!confirm(msg)) return; else story.saveTiddler(tid);
			}
			story.closeTiddler(tid);
		});
	}
	else if (top)
		arguments[0]=null;
	else if (bottom)
		arguments[0]="bottom";
	if (single && opt.chkSinglePagePermalink && !config.browser.isSafari) {
		window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
		config.lastURL = window.location.hash;
		document.title = wikifyPlain("SiteTitle") + " - " + title;
		if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
	}
	if (tiddlerElem && tiddlerElem.getAttribute("dirty")=="true") { // editing... move tiddler without re-rendering
		var isTopTiddler=(tiddlerElem.previousSibling==null);
		if (!isTopTiddler && (single || top))
			tiddlerElem.parentNode.insertBefore(tiddlerElem,tiddlerElem.parentNode.firstChild);
		else if (bottom)
			tiddlerElem.parentNode.insertBefore(tiddlerElem,null);
		else this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
	} else
		this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
	var tiddlerElem=document.getElementById(story.idPrefix+title);
	if (tiddlerElem&&opt.chkSinglePageAutoScroll) {
		// scroll to top of page or top of tiddler
		var isTopTiddler=(tiddlerElem.previousSibling==null);
		var yPos=isTopTiddler?0:ensureVisible(tiddlerElem);
		// if animating, defer scroll until after animation completes
		var delay=opt.chkAnimate?config.animDuration+10:0;
		setTimeout("window.scrollTo(0,"+yPos+")",delay); 
	}
}

if (Story.prototype.SPM_coreDisplayTiddlers==undefined)
	Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function() {
	// suspend single/top/bottom modes when showing multiple tiddlers
	var opt=config.options;
	var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
	var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
	var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
	this.SPM_coreDisplayTiddlers.apply(this,arguments);
	opt.chkBottomOfPageMode=saveBPM;
	opt.chkTopOfPageMode=saveTPM;
	opt.chkSinglePageMode=saveSPM;
}
//}}}
a reusable empty tiddlywiki.
''Jelly's TiddlyWiki''
/***
|''Name:''|~TaggerPlugin|
|''Version:''|1.0.1 (2006-06-01)|
|''Source:''|http://tw.lewcid.org//#TaggerPlugin|
|''Author:''|SaqImtiaz|
|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|
|''Documentation:''|[[TaggerPluginDocumentation]]|
|''Source Code:''|[[TaggerPluginSource]]|
|''~TiddlyWiki:''|Version 2.0.8 or better|
***/
//{{{

config.tagger={
       defaults:{
              label: 'Tags: ',
              tooltip: 'Manage tiddler tags',
              taglist: 'true',
              excludeTags: '',
              notags: 'tiddler has no tags',
              aretags: 'current tiddler tags:',
              toggletext: 'add tags:'
       }
};

config.macros.tagger={};
config.macros.tagger.arrow = (document.all?"▼":"?"); // the fat one is the only one that works in IE
config.macros.tagger.handler =  function(place,macroName,params,wikifier,paramString,tiddler) {
       var defaults = config.tagger.defaults;
       var nAV = paramString.parseParams('tagman', null, true);
       var label = ((nAV[0].label)&&(nAV[0].label[0])!='.')?nAV[0].label[0]+this.arrow: defaults.label+this.arrow;
       var tooltip = ((nAV[0].tooltip)&&(nAV[0].tooltip[0])!='.')?nAV[0].tooltip[0]: defaults.tooltip;
       var taglist = ((nAV[0].taglist)&&(nAV[0].taglist[0])!='.')?nAV[0].taglist[0]: defaults.taglist;
       var exclude = ((nAV[0].exclude)&&(nAV[0].exclude[0])!='.')?(nAV[0].exclude[0]).readBracketedList(): defaults.excludeTags.readBracketedList();
       if ((nAV[0].source)&&(nAV[0].source[0])!='.')var source = nAV[0].source[0];
       if (source&&!store.getTiddler(source)) return false;

       var onclick = function(e) {
                   if (!e) var e = window.event;
                   var popup = Popup.create(this);
                   var tagsarray = store.getTags();
                   var tags=new Array();

                   for (var i=0; i<tagsarray.length; i++){
                       tags.push(tagsarray[i][0]);}

                   if (source)
                      {var sourcetiddler=store.getTiddler(source);
                       tags=sourcetiddler.tags.sort();}

                   var currentTags = tiddler.tags.sort();

                   var createButtons=function(text,theTag,tooltipPrefix){
                       var sp = createTiddlyElement(createTiddlyElement(popup,"li"),"span",null,"tagger");
                       var theToggle = createTiddlyButton(sp,text,tooltipPrefix+" '"+theTag+"'",taggerOnToggle,"button","toggleButton");
                       theToggle.setAttribute("tiddler",tiddler.title);
                       theToggle.setAttribute("tag",theTag);
                       insertSpacer(sp);
                       if (window.createTagButton_orig_mptw)
                           createTagButton_orig_mptw(sp,theTag);
                       else
                           createTagButton(sp,theTag);
                       }

                   createTiddlyElement(popup,"li",null,"listTitle",(tiddler.tags.length == 0 ? defaults.notags : defaults.aretags));

                   for (var t=0; t<currentTags.length; t++){
                      createButtons("[x]",currentTags[t],"remove tag ");
                       }

                   createTiddlyElement(createTiddlyElement(popup,"li"),"hr");

                   if (taglist!='false')
                      { createTiddlyElement(popup,"li",null,"listTitle",defaults.toggletext);
                        for (var i=0; i<tags.length; i++){
                          if (!tiddler.tags.contains(tags[i])&&!exclude.contains(tags[i]))
                                  {createButtons("[ ]",tags[i],"add tag ");
                                  }
                          }
                          createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
                      }

                   var newTagButton = createTiddlyButton(createTiddlyElement(popup,"li"),("Create new tag"),null,taggerOnToggle);
                   newTagButton.setAttribute("tiddler",tiddler.title);
                   if (source) newTagButton.setAttribute("source",source);

                   Popup.show(popup,false);
                   e.cancelBubble = true;
                   if (e.stopPropagation) e.stopPropagation();
                   return(false);
                   };

       createTiddlyButton(place,label,tooltip,onclick,"button","taggerDrpBtn");
};

window.taggerOnToggle = function(e) {
              var tag = this.getAttribute("tag");
              var title = this.getAttribute("tiddler");
              var tiddler = store.getTiddler(title);
              if (!tag)
                 {
                 var newtag=prompt("Enter new tag:","");
                 if (newtag!=''&&newtag!=null)
                    {
                    var tag=newtag;
                    if (this.getAttribute("source"))
                    {var sourcetiddler =  store.getTiddler(this.getAttribute("source"));
                    sourcetiddler.tags.pushUnique(newtag);}
                    }
                 else
                     {return false;};
                 }
              if (!tiddler || !tiddler.tags)
                 {store.saveTiddler(title,title,'',config.options.txtUserName,new Date(),tag);}
              else
                  {if (tiddler.tags.find(tag)==null)
                     {tiddler.tags.push(tag)}
                  else if(!newtag)
                      {tiddler.tags.splice(tiddler.tags.find(tag),1)};
                  store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags);};
              story.refreshTiddler(title,null,true);
              if(config.options.chkAutoSave)
                  saveChanges();
              return false;
};

setStylesheet(
 ".tagger a.button {font-weight: bold;display:inline; padding:0px;}\n"+
 ".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\n"+
 "#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\n"+
 ".popup .listTitle {color:#000;}\n"+
 "",
"TaggerStyles");

window.lewcidTiddlerSwapTag =  function (tiddler, oldTag, newTag){
                    for (var i = 0; i < tiddler.tags.length; i++)
			  if (tiddler.tags[i] == oldTag) {
				  tiddler.tags[i] = newTag;
				  return true;}
                         return false;
}

window.lewcidRenameTag = function(e) {
                    var tag=this.getAttribute("tag");
                    var newtag=prompt("Rename tag '"+tag+"' to:",tag);

                    if ((newtag==tag)||(newtag==null)) {return false;}

                    if(store.tiddlerExists(newtag))
                               {if(confirm(config.messages.overwriteWarning.format([newtag.toString()])))
                                             story.closeTiddler(newtag,false,false);
                               else
                                             return null;}

                    tagged=store.getTaggedTiddlers(tag);
                    if (tagged.length!=0){
                          for (var j = 0; j < tagged.length; j++)
                              lewcidTiddlerSwapTag(tagged[j],tag,newtag);}

                    if (store.tiddlerExists(tag))
                       {store.saveTiddler(tag,newtag);}
                    if (document.getElementById("tiddler"+tag))
                       {var oldTagTiddler =  document.getElementById(story.idPrefix + tag);
                       var before= story.positionTiddler(oldTagTiddler);
                       var place = document.getElementById(story.container);
                       story.closeTiddler(tag,false,false);
                       story.createTiddler(place,before,newtag,null);
                       story.saveTiddler(newtag);}
                    if(config.options.chkAutoSave)
                                                      saveChanges();
                    return false;
}


window.onClickTag=function(e)
{
	if (!e) var e = window.event;
	var theTarget = resolveTarget(e);

        var nested = (!isNested(theTarget));
        if ((Popup.stack.length > 1)&&(nested==true)) {Popup.removeFrom(1);}
        else if(Popup.stack.length > 0 && nested==false) {Popup.removeFrom(0);};

        var theId = (nested==false)? "popup" : "nestedtagger";
        var popup = createTiddlyElement(document.body,"ol",theId,"popup",null);
        Popup.stack.push({root: this, popup: popup});

	var tag = this.getAttribute("tag");
	var title = this.getAttribute("tiddler");
	if(popup && tag)
		{
		var tagged = store.getTaggedTiddlers(tag);
		var titles = [];
		var li,r;
		for(r=0;r<tagged.length;r++)
			if(tagged[r].title != title)
				titles.push(tagged[r].title);
		var lingo = config.views.wikified.tag;
		if(titles.length > 0)
			{
			var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
			openAll.setAttribute("tag",tag);
			createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
			for(r=0; r<titles.length; r++)
				{
				createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
				}
			}
		else
			createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));
		createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
		var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
		createTiddlyText(h,lingo.openTag.format([tag]));

		createTiddlyElement(createTiddlyElement(popup,"li"),"hr");

		var renameTagButton = createTiddlyButton(createTiddlyElement(popup,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);
		renameTagButton.setAttribute("tag",tag)
		}
	Popup.show(popup,false);
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}

if (!window.isNested)
   window.isNested = function(e) {
        while (e != null) {
                var contentWrapper = document.getElementById("contentWrapper");
                if (contentWrapper == e) return true;
                e = e.parentNode;
                }
        return false;
   };

config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://tw.lewcid.org/#TaggerPluginDocumentation]]";

config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://tw.lewcid.org/#TaggerPluginSource]]";
//}}}
/***
|StyleSheet|TiddlyPedia|
***/

/***
http://tiddlystyles.com/#theme:TiddlyPedia
***/
[[StyleSheetSyntaxHighlighter]]
/*{{{*/
body{
 background: #f9f9f9 url(headbg.jpg) no-repeat top left;
}

#titleLine{
 display: block;
 background: transparent url(data:image/gif;base64,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
) no-repeat 18px 15px;
 _background: transparent;
 height: 120px;
 _height: 135px;
 width: 150px;
 color: #000;
 border: 1px;
 padding: 0;
 margin: 0;
}

* html #titleLine{
 filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='ubuntu_linux110.gif',sizingMethod='scale');
}

#contentWrapper #siteTitle a{
 display: inline;
 font-weight: bold;
 color: #000;
 font-size: 13px;
}

#siteSubtitle{
 padding: 0;
}

#siteTitle, #mainMenu{
 position: static;
}

#contentWrapper #sidebar{
 top: 0;
 left: 0;
}

#displayArea {
 margin: 0 0 0 15em;
}

#messageArea{
 position: fixed;
 top: 0;
 right: 0;
 font-size: 10px;
 border: 1px solid #aaa;
 background: #fff;
 z-index: 25;
}

#messageArea a:link{
 color: #002bb8;
 text-decoration: none;
}

#messageArea a:hover{
 text-decoration: underline;
}

.viewer{
 background: #fff;
 border: 1px solid #aaa;
 padding: 1em;
margin: 0;
}

.body{
 padding: 1px;
}

.title{
 background: #fff;
 border: 1px solid #aaa;
 display: inline;
 margin-left: .5em;
 padding: 2px .5em;
 border-bottom: 0;
 font-weight: bold;
 color: #000;
 font-size: 1.2em;
}

.toolbar{
 visibility: visible;
 display: inline;
 padding: 0;
 font-family: sans-serif;
}

.toolbar a.button:link,.toolbar a.button:visited{
 background: #fff;
 border: 1px solid #aaa;
 color:#002bb8;
 font-size: 11px;
 padding-bottom: 0;
 margin-right: .25em;
}

/* TiddlyPedia was Created by Clinton Checketts based on the Monobook skin of Wikipedia */

#contentWrapper .toolbar .button:hover{
 border-bottom: 1px solid #fff;
 background: #fff;
 color:#002bb8;
}

.toolbar a.button:hover{
 border-bottom: 1px solid #fff;
 background: #fff;
 color:#000;
}

#displayArea .viewer a,a.button:link,a.button:visited,
a.tiddlyLink:link,a.tiddlyLink:visited,
#sidebarOptions .sliderPanel a{
 color:#002bb8;
 background: transparent;
 border: 0;
}

.viewer a:hover,a.button:hover,a.button:active,
a.tiddlyLink:hover,a.tiddlyLink:active,
.viewer a.button:hover,
#sidebarOptions .sliderPanel a:hover{
 color:#002bb8;
 background: transparent;
 text-decoration: underline;
}

#mainMenu{
 font-family: sans-serif;
 text-align: left;
 font-size: x-small;
 width: 100%;
 margin: 0;
 padding: 0;
}

#mainMenu h1{
 font-size: 11px;
 font-weight: normal;
 padding: 0;
 margin: 0;
 background: transparent;
}

#mainMenu ul{
 font-size: 11px;
 border: 1px solid #aaa;
 padding: .25em 0;
 margin: 0;
 list-style-type: square;
 list-style-image: url(bullet.gif);
 background: #fff;
 width: 100%;
}

#mainMenu li{
 margin: 0 0 0 2em;
 padding: 0;
}

#contentWrapper #mainMenu a:link,#contentWrapper #mainMenu a:visited{
 color:#002bb8;
 padding: 0;
 margin: 0;
 background: transparent;
}

#mainMenu .externalLink {
 text-decoration: none;
}

#mainMenu .externalLink:hover {
 text-decoration: underline;
}

#sidebar{
 padding: .5em;
 font-family: sans-serif;
}

#sidebarOptions{
 border: 1px solid #aaa;
 background: #fff;
 margin-top: .5em;
 width: 100%;
}

#sidebar .sliderPanel{
 margin: 0;
}

#contentWrapper #sidebarOptions .button,#contentWrapper #sidebarOptions .button:hover{
 color:#002bb8;
 padding: .1em 0 .1em 2em;
 background: transparent url(bullet.gif) 10px -2px no-repeat;
}

#sidebarOptions input{
 width: 80%;
 margin: 0 .5em;
}

#sidebarTabs{
 background: #fff;
 margin-top: .5em;
 width: 100%;
}

#sidebarTabs .tabContents,#sidebarTabs .tabContents .tabContents{
 border: 1px solid #aaa;
 background: #fff;
}

#sidebarTabs .tabSelected,#sidebarTabs .tabcontents .tabSelected {
 background: #fff;
 border: 1px solid #aaa;
 border-bottom: 0;
 cursor: default;
 padding-bottom: 3px;
 color: #000;
}

#sidebarTabs .tabUnselected,#sidebarTabs .tabContents .tabUnselected{
 background: #aaa;
 padding-bottom: 0;
 color: #000; 
}

#contentWrapper #sidebarTabs .tiddlyLink,#contentWrapper #sidebarTabs .button,
#contentWrapper #sidebarTabs a.tiddlyLink:hover,#contentWrapper #sidebarTabs a.button:hover{
 background: transparent;
 color: #002bb8;
}

.footer{
 margin: -1em 0 1em 0; 
}

.footer .button:hover,.editorFooter .button:hover{
background: transparent;
 color: #002bb8;
 border-bottom: 1px solid #002bb8;
}

#popup{
 background: #e9e9e9;
 color: #000;
}

#popup hr{
 border-color: #aaa;
 background-color: #aaa;
}

#popup a{
 color: #000;
}

#popup a:hover,#contentWrapper #sidebarTabs #popup a:hover{
 background: #666;
 color: #fff;
 text-decoration: none;
}

#displayArea .tiddler a.tiddlyLinkNonExisting{
 color: #ba0000;
}

#displayArea .tiddler a.externalLink{
 text-decoration: none;
 color:#002bb8;
 padding-right: 1em;
 background: transparent url(external.png) 100% 50% no-repeat;
}

#displayArea .tiddler a.externalLink:hover{
 text-decoration: underline;
}

.viewer pre{
 background: #e9e9e9;
 border: 1px solid #666;
}

.viewer h1, .viewer h2, .viewer h3, .viewer h4, .viewer h5, .viewer h6{
 background: transparent;
 border-bottom: .2em solid #aaa;
}

#sidebar .sliderPanel{
 background: #e9e9e9;
}

#sidebar .sliderPanel input{width: auto;}

.tagged, .tagging, .listTitle{
 float: none;
 display: inline;
}

.tagged li, .tagging li,
.tagged ul, .tagging ul{
 display: inline;
}

/*}}}*/
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'sinojellyempty';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n")

});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 06/09/2009 22:50:43 | Jelly Chen | [[sinojellylearn.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellylearn/sinojellylearn.html]] | [[store.cgi|http://sinojellylearn.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellylearn.tiddlyspot.com/index.html]] | . | ok |
| 07/09/2009 00:55:04 | Jelly Chen | [[sinojellylearn.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellylearn/sinojellylearn.html#TiddlyWiki%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E3%80%82]] | [[store.cgi|http://sinojellylearn.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellylearn.tiddlyspot.com/index.html]] | . | ok |
| 07/09/2009 01:12:02 | Jelly Chen | [[sinojellylearn.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellylearn/sinojellylearn.html#%E5%86%85%E5%AE%B9%E6%8F%90%E8%A6%81]] | [[store.cgi|http://sinojellylearn.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellylearn.tiddlyspot.com/index.html]] | . | ok |
| 07/09/2009 01:37:10 | Jelly Chen | [[sinojellylearn.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellylearn/sinojellylearn.html#%E3%80%8A%E5%A4%A9%E4%B8%8B%E6%B2%A1%E6%9C%89%E9%9A%BE%E5%AD%A6%E7%9A%84Linux.zip%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0%E3%80%82]] | [[store.cgi|http://sinojellylearn.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellylearn.tiddlyspot.com/index.html]] | . | ok |
| 10/09/2009 19:29:09 | Jelly Chen | [[empty.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellyempty/empty.html#FiveStarsPlugin]] | [[store.cgi|http://sinojellyempty.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellyempty.tiddlyspot.com/index.html]] | . | ok |
| 10/09/2009 19:49:04 | Jelly Chen | [[empty.html|file:///D:/Users/Jelly/Documents/My%20Dropbox/TiddlyWiki/sinojellyempty/empty.html#TspotSetupPlugin]] | [[store.cgi|http://sinojellyempty.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellyempty.tiddlyspot.com/index.html]] | . |
| 13/09/2009 23:38:45 | YourName | [[/|http://sinojellyempty.tiddlyspot.com/]] | [[store.cgi|http://sinojellyempty.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellyempty.tiddlyspot.com/index.html]] | . |
| 13/09/2009 23:58:09 | YourName | [[/|http://sinojellyempty.tiddlyspot.com/]] | [[store.cgi|http://sinojellyempty.tiddlyspot.com/store.cgi]] | . | [[index.html | http://sinojellyempty.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
	
//
// Upload Macro
//

config.macros.upload = {
// default values
	defaultBackupDir: '',	//no backup
	defaultStoreScript: "store.php",
	defaultToFilename: "index.html",
	defaultUploadDir: ".",
	authenticateUser: true	// UploadService Authenticate User
};
	
config.macros.upload.label = {
	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
	saveLabel: "save to web", 
	saveToDisk: "save to disk",
	uploadLabel: "upload"	
};

config.macros.upload.messages = {
	noStoreUrl: "No store URL in parmeters or options",
	usernameOrPasswordMissing: "Username or password missing"
};

config.macros.upload.handler = function(place,macroName,params) {
	if (readOnly)
		return;
	var label;
	if (document.location.toString().substr(0,4) == "http") 
		label = this.label.saveLabel;
	else
		label = this.label.uploadLabel;
	var prompt;
	if (params[0]) {
		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0], 
			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
	} else {
		prompt = this.label.promptOption;
	}
	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};

config.macros.upload.action = function(params)
{
		// for missing macro parameter set value from options
		if (!params) params = {};
		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
		var username = params[4] ? params[4] : config.options.txtUploadUserName;
		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter	
		// for still missing parameter set default value
		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		if (storeUrl.substr(0,4) != "http")
			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
		if (!toFilename)
			toFilename = bidix.basename(window.location.toString());
		if (!toFilename)
			toFilename = config.macros.upload.defaultToFilename;
		if (!uploadDir)
			uploadDir = config.macros.upload.defaultUploadDir;
		if (!backupDir)
			backupDir = config.macros.upload.defaultBackupDir;
		// report error if still missing
		if (!storeUrl) {
			alert(config.macros.upload.messages.noStoreUrl);
			clearMessage();
			return false;
		}
		if (config.macros.upload.authenticateUser && (!username || !password)) {
			alert(config.macros.upload.messages.usernameOrPasswordMissing);
			clearMessage();
			return false;
		}
		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password); 
		return false; 
};

config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir) 
{
	if (!storeUrl)
		return null;
		var dest = bidix.dirname(storeUrl);
		if (uploadDir && uploadDir != '.')
			dest = dest + '/' + uploadDir;
		dest = dest + '/' + toFilename;
	return dest;
};

//
// uploadOptions Macro
//

config.macros.uploadOptions = {
	handler: function(place,macroName,params) {
		var wizard = new Wizard();
		wizard.createWizard(place,this.wizardTitle);
		wizard.addStep(this.step1Title,this.step1Html);
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper,markList);
		wizard.setValue("listWrapper",listWrapper);
		this.refreshOptions(listWrapper,false);
		var uploadCaption;
		if (document.location.toString().substr(0,4) == "http") 
			uploadCaption = config.macros.upload.label.saveLabel;
		else
			uploadCaption = config.macros.upload.label.uploadLabel;
		
		wizard.setButtons([
				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption, 
					onClick: config.macros.upload.action},
				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
				
			]);
	},
	options: [
		"txtUploadUserName",
		"pasUploadPassword",
		"txtUploadStoreUrl",
		"txtUploadDir",
		"txtUploadFilename",
		"txtUploadBackupDir",
		"chkUploadLog",
		"txtUploadLogMaxLine"		
	],
	refreshOptions: function(listWrapper) {
		var opts = [];
		for(i=0; i<this.options.length; i++) {
			var opt = {};
			opts.push();
			opt.option = "";
			n = this.options[i];
			opt.name = n;
			opt.lowlight = !config.optionsDesc[n];
			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
			opts.push(opt);
		}
		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
		for(n=0; n<opts.length; n++) {
			var type = opts[n].name.substr(0,3);
			var h = config.macros.option.types[type];
			if (h && h.create) {
				h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
			}
		}
		
	},
	onCancel: function(e)
	{
		backstage.switchTab(null);
		return false;
	},
	
	wizardTitle: "Upload with options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "<input type='hidden' name='markList'></input><br>",
	cancelButton: "Cancel",
	cancelButtonPrompt: "Cancel prompt",
	listViewTemplate: {
		columns: [
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'} 
			]}
};

//
// upload functions
//

if (!bidix.upload) bidix.upload = {};

if (!bidix.upload.messages) bidix.upload.messages = {
	//from saving
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to upload backup file",
	rssSaved: "RSS feed uploaded",
	rssFailed: "Failed to upload RSS feed file",
	emptySaved: "Empty template uploaded",
	emptyFailed: "Failed to upload empty template file",
	mainSaved: "Main TiddlyWiki file uploaded",
	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
	//specific upload
	loadOriginalHttpPostError: "Can't get original file",
	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
	storePhpNotFound: "The store script '%0' was not found."
};

bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
	var callback = function(status,uploadParams,original,url,xhr) {
		if (!status) {
			displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
			return;
		}
		if (bidix.debugMode) 
			alert(original.substr(0,500)+"\n...");
		// Locate the storeArea div's 
		var posDiv = locateStoreArea(original);
		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
			alert(config.messages.invalidFileError.format([localPath]));
			return;
		}
		bidix.upload.uploadRss(uploadParams,original,posDiv);
	};
	
	if(onlyIfDirty && !store.isDirty())
		return;
	clearMessage();
	// save on localdisk ?
	if (document.location.toString().substr(0,4) == "file") {
		var path = document.location.toString();
		var localPath = getLocalPath(path);
		saveChanges();
	}
	// get original
	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
	var originalPath = document.location.toString();
	// If url is a directory : add index.html
	if (originalPath.charAt(originalPath.length-1) == "/")
		originalPath = originalPath + "index.html";
	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
	var log = new bidix.UploadLog();
	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
	displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
	if (bidix.debugMode) 
		alert("about to execute Http - GET on "+originalPath);
	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

bidix.upload.uploadRss = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		if(status) {
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
			bidix.upload.uploadMain(params[0],params[1],params[2]);
		} else {
			displayMessage(bidix.upload.messages.rssFailed);			
		}
	};
	// do uploadRss
	if(config.options.chkGenerateAnRssFeed) {
		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
		var rssString = generateRss();
		// no UnicodeToUTF8 conversion needed when location is "file" !!!
		if (document.location.toString().substr(0,4) != "file")
			rssString = convertUnicodeToUTF8(rssString);	
		bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
	} else {
		bidix.upload.uploadMain(uploadParams,original,posDiv);
	}
};

bidix.upload.uploadMain = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		var log = new bidix.UploadLog();
		if(status) {
			// if backupDir specified
			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
				displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
			}
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
			store.setDirty(false);
			log.endUpload("ok");
		} else {
			alert(bidix.upload.messages.mainFailed);
			displayMessage(bidix.upload.messages.mainFailed);
			log.endUpload("failed");			
		}
	};
	// do uploadMain
	var revised = bidix.upload.updateOriginal(original,posDiv);
	bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};

bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
	var localCallback = function(status,params,responseText,url,xhr) {
		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
		if (xhr.status == 404)
			alert(bidix.upload.messages.storePhpNotFound.format([url]));
		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
			alert(responseText);
			if (responseText.indexOf("Debug mode") >= 0 )
				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
		} else if (responseText.charAt(0) != '0') 
			alert(responseText);
		if (responseText.charAt(0) != '0')
			status = null;
		callback(status,params,responseText,url,xhr);
	};
	// do httpUpload
	var boundary = "---------------------------"+"AaB03x";	
	var uploadFormName = "UploadPlugin";
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += uploadFormName +"\"\r\n\r\n";
	sheader += "backupDir="+uploadParams[3] +
				";user=" + uploadParams[4] +
				";password=" + uploadParams[5] +
				";uploaddir=" + uploadParams[2];
	if (bidix.debugMode)
		sheader += ";debug=1";
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
	sheader += "Content-Length: " + data.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	data = sheader + data + strailer;
	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
	if (!posDiv)
		posDiv = locateStoreArea(original);
	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
		alert(config.messages.invalidFileError.format([localPath]));
		return;
	}
	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
				store.allTiddlersAsHtml() + "\n" +
				original.substr(posDiv[1]);
	var newSiteTitle = getPageTitle().htmlEncode();
	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
	return revised;
};

//
// UploadLog
// 
// config.options.chkUploadLog :
//		false : no logging
//		true : logging
// config.options.txtUploadLogMaxLine :
//		-1 : no limit
//      0 :  no Log lines but UploadLog is still in place
//		n :  the last n lines are only kept
//		NaN : no limit (-1)

bidix.UploadLog = function() {
	if (!config.options.chkUploadLog) 
		return; // this.tiddler = null
	this.tiddler = store.getTiddler("UploadLog");
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = "UploadLog";
		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
		store.addTiddler(this.tiddler);
	}
	return this;
};

bidix.UploadLog.prototype.addText = function(text) {
	if (!this.tiddler)
		return;
	// retrieve maxLine when we need it
	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
	if (isNaN(maxLine))
		maxLine = -1;
	// add text
	if (maxLine != 0) 
		this.tiddler.text = this.tiddler.text + text;
	// Trunck to maxLine
	if (maxLine >= 0) {
		var textArray = this.tiddler.text.split('\n');
		if (textArray.length > maxLine + 1)
			textArray.splice(1,textArray.length-1-maxLine);
			this.tiddler.text = textArray.join('\n');		
	}
	// update tiddler fields
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	store.addTiddler(this.tiddler);
	// refresh and notifiy for immediate update
	story.refreshTiddler(this.tiddler.title);
	store.notify(this.tiddler.title, true);
};

bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	if (!this.tiddler)
		return;
	var now = new Date();
	var text = "\n| ";
	var filename = bidix.basename(document.location.toString());
	if (!filename) filename = '/';
	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
	text += config.options.txtUserName + " | ";
	text += "[["+filename+"|"+location + "]] |";
	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
	text += uploadDir + " | ";
	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
	text += backupDir + " |";
	this.addText(text);
};

bidix.UploadLog.prototype.endUpload = function(status) {
	if (!this.tiddler)
		return;
	this.addText(" "+status+" |");
};

//
// Utilities
// 

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
	}
};

bidix.dirname = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));
	}
};

bidix.basename = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("#")) != -1) 
		filePath = filePath.substring(0, lastpos);
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(lastpos + 1);
	} else
		return filePath.substring(filePath.lastIndexOf("\\")+1);
};

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

//
// Initializations
//

// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

//optionsDesc
merge(config.optionsDesc,{
	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
	txtUploadUserName: "Upload Username",
	pasUploadPassword: "Upload Password",
	chkUploadLog: "do Logging in UploadLog (default: true)",
	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});

// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');


// Backstage
merge(config.tasks,{
	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");


//}}}

<!--{{{-->
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span macro='tagger exclude:"exdcludeLists systemConfig"'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<span class='sectionTOC'></span> <!-- target element -->
<div class='viewer' macro='view text wikified'><span macro="rating"></span><br/></div>
<div class='tagClear'></div>
<span macro="foldHeadings opened|closed"></span>
<span macro='sectionTOC'></span> <!-- must be at end of tiddler -->
<!--}}}-->
!usage
{{{[img[linux_ubuntu110.gif]]}}}
[img[linux_ubuntu110.gif]]
!notes
//none//
!type
image/gif
!file
file:///D:/Users/Jelly/Documents/My Dropbox/TiddlyWiki/sinojellyempty/linux_ubuntu110.gif
!url

!data
data:image/gif;base64,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
!usage
{{{[img[star1.png]]}}}
[img[star1.png]]
!notes
//none//
!type
image/png
!file
./star1.png
!url

!data
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gJGxQpCZ4Equ4AAASsSURBVDjLlZVdiF1XFcd/a+9z7p2vOy8d0zY6TSWaxii0NlXQttJqHzSKiFhpoab6oogW+yBFUXxQKCj4Uaoogk+KKRWlfkAfhIIKpgZtTam2xKTJpM183Zl7Z+7H+dp7r+XDnQljlQY3nKdz9m+vs/b//1/y6A9+xGsvgVgi4jDfdmAGGNjkrfNsXjjN6rnTLC/9g5VX+vS64K5IFUc2fvmwqzYWEe+AjL37RP7nxiuAxSRW2UJ46dFr5prPqakBU3vhFsPOT/wfYEMgFAfuvOe+O254y/4PpBBfB8wAOYigiXqwgabwX5W/FtgZxkzcfFdnoZO9/s1HDmfN8LAhU8A0kJmpXLEVJk5M3G4PM8Cban5wsfXJvJ3RzlNrNq2+3/BTwNxOS1q7305u+VVgE6HV9M2PuxqjxpgkBfVBi8H1B48ceqc4odXOOHBNflcMYTaqWFQhqNdoLkaVBOSC5LvgDHFkxdqhg/v9J9qzHd/f7NcIvgmpmW6Pb77q2ps7qOC845Y777qx/7unvmj59Ip3EsQ0+FllebQ93tLweNT0ihk5EDMDLIWWrT17/B33fvo6P51hCTBDEPKWhzSpYn4+yz78sffei05k5hDGvXWeePEPTzd1/VtNoW1GwEiZmPo0t/j8maZzrHPybz+88dZbbp+eb4MKqEGy3UtARGi125NuhobTv3xY//hPTpzdnHpkXK6OY1NPx0A0A3/sgx8SwVrqp7cvbuRPvvTXU3Ld4huOtqcyL8jkGtQmWrUIqaIe9PjN9x5c//0L899fqeYeG2+vV4PechwOxsVoSNXUJAcooA71eTsPW3Nv/c7PHz/1wOr55QIADeBbmG+Dnya5OX72rS+debr39m+OmP3TaGMp29q42IyG/XFVUseAArYrtwRUYKV3FmN74eTm8tIANwMuBwtgEVMFhUGcXy9jurC9dt563YtbW73u9mioo6qkSZEkAg4RMFXTkExjpaab7WbjbW86esfVWDU5NTosCYLgnLA4s3ZD2VvpjEf9wWiwVYwGVhRj6rok7qgXF4sBoRoSq7GFYjvW40Fzdae5rd02QZWyEH78lc8+c+Lr959vwkQpxx76xUIe1g9WdVVUFaEoCNWYlAKKTdydlYMuIoJpshBqTUFm3vP5j9wNiVM/fbB88qR/YtMf+nXT7c1f+sI9xx/49mO3tTOR/bOjm85dan6lisYA4VVZ5NbO/Z3Vs8+ydv456b581qqVZ45a0V1YXloZnXgq/+py3fnJYO3Mdr+79K+/XPRfe+hTH/3uxqULev+XH3kfqZxPiYQhtpPQu4/cfeu1O0c4KcYDu/4qd3zfTPj4i/19D0dxg1Buz5bFoK7K0IAk8y7tm3PvvumAfObPZ5pvXFrldDlkVDUUXLYSyO1vZG9mu8xLx8TnGFNImg2NxaqkrGsCQCunJRnWypkLDWk8YlgXDBulsb3gI3P/mXaqiPdMZZ4pA0mR2NSElIgA3pPlLVpqGIbEhhASjUK4PK+ATHWHKNDUaIg4geDcBGSGqk1MBJCUGANBJrYkGao73txbYXY5p2UiEwNVCFHZNTQGJpenCilBUptEvOydrHvWvwGT9K2B/6ho5wAAAABJRU5ErkJggg==
!usage
{{{[img[star2.png]]}}}
[img[star2.png]]
!notes
//none//
!type
image/png
!file
./star2.png
!url

!data
data:image/png;base64,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