├── .gitignore ├── doc ├── index.html ├── files │ ├── init-js.html │ ├── fx-js.html │ ├── wikifier-js.html │ ├── passage-js.html │ ├── tale-js.html │ ├── history-js.html │ └── functions-js.html ├── index │ ├── Classes.html │ ├── Properties.html │ └── Functions.html ├── javascript │ └── main.js └── styles │ └── main.css ├── targets ├── jonah │ └── plugins │ │ ├── debug │ │ ├── source.tw │ │ └── compiled.html │ │ ├── multimedia │ │ └── source.tw │ │ ├── singleview │ │ ├── source.tw │ │ └── compiled.html │ │ └── socialbookmarks │ │ ├── source.tw │ │ └── compiled.html └── tw2 │ └── tw22 │ └── header.html ├── untwee ├── README.markdown ├── toward ├── twee └── lib ├── tiddlywiki.py └── PyRSS2Gen.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | lib/*.pyc 3 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /targets/jonah/plugins/debug/source.tw: -------------------------------------------------------------------------------- 1 | :: __plugin__Debug [script] 2 | 3 | document.onKeyUp = function() 4 | { 5 | console.log('hi'); 6 | }; -------------------------------------------------------------------------------- /targets/jonah/plugins/debug/compiled.html: -------------------------------------------------------------------------------- 1 |
document.onKeyUp = function()\n{\n console.log('hi');\n};
2 | 3 | -------------------------------------------------------------------------------- /targets/jonah/plugins/multimedia/source.tw: -------------------------------------------------------------------------------- 1 | :: Multimedia [script] 2 | 3 | // Pop-Up Embedder Script by David Battino, www.batmosphere.com 4 | // Version 2006-05-31 5 | // OK to use if this notice is included 6 | 7 | macros['song'] = 8 | { 9 | handler: function (place, name, params) 10 | { 11 | var player = insertElement(place, 'div'); 12 | 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /targets/jonah/plugins/singleview/source.tw: -------------------------------------------------------------------------------- 1 | :: __plugin__SingleView [script] 2 | History.prototype.originalDisplay = History.prototype.display; 3 | 4 | History.prototype.display = function (title, link, render) 5 | { 6 | if ((render != 'quietly') && (render != 'offscreen')) 7 | removeChildren($('passages')); 8 | 9 | this.originalDisplay.apply(this, arguments); 10 | }; -------------------------------------------------------------------------------- /targets/jonah/plugins/socialbookmarks/source.tw: -------------------------------------------------------------------------------- 1 | :: __plugin__SocialBookmarks [script] 2 | 3 | var title = tale.get('StoryTitle').text + '%3a%20' + tale.get('StorySubtitle').text; 4 | 5 | var links = document.getElementsByTagName('a'); 6 | 7 | for (var i = 0; i < links.length; i++) 8 | if (links[i].href.indexOf('socialbookmark')) 9 | links[i].href += '?title=' + title + '&url=' + location.href; 10 | -------------------------------------------------------------------------------- /targets/jonah/plugins/singleview/compiled.html: -------------------------------------------------------------------------------- 1 |
History.prototype.originalDisplay = History.prototype.display;\n\nHistory.prototype.display = function (title, link, render)\n{\n if ((render != 'quietly') && (render != 'offscreen'))\n removeChildren($('passages'));\n \n this.originalDisplay.apply(this, arguments);\n};
2 | 3 | -------------------------------------------------------------------------------- /targets/jonah/plugins/socialbookmarks/compiled.html: -------------------------------------------------------------------------------- 1 |
var title = tale.get('StoryTitle').text + '%3a%20' + tale.get('StorySubtitle').text;\n\nvar links = document.getElementsByTagName('a');\n\nfor (var i = 0; i < links.length; i++)\n if (links[i].href.indexOf('socialbookmark'))\n links[i].href += '?title=' + title + '&url=' + location.href;
2 | 3 | -------------------------------------------------------------------------------- /untwee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os 4 | scriptPath = os.path.dirname(os.path.realpath(__file__)) 5 | sys.path.append(scriptPath + os.sep + 'lib') 6 | from tiddlywiki import TiddlyWiki 7 | 8 | def usage(): 9 | print 'usage: untwee source' 10 | 11 | 12 | def main (argv): 13 | if len(argv) == 0: 14 | usage() 15 | sys.exit(2) 16 | 17 | file = open(argv[0]) 18 | tw = TiddlyWiki() 19 | tw.addHtml(file.read()) 20 | print tw.toTwee() 21 | 22 | 23 | if __name__ == '__main__': 24 | main(sys.argv[1:]) 25 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | README : tweecode/twee 2 | ====== 3 | 4 | To run twee, you will need a copy of this code, a local Python installation, and a .tw file. You can get this fork from github using, for example, the ZIP button. Python should come pre-installed on a Mac; a Windows installer is available at [python.org](http://www.python.org/getit/). 5 | 6 | Once you have all those, open the Terminal or a command prompt, change to the twee directory, and type something like: 7 | 8 | ./twee my-input-file.tw > my-output-file.html 9 | 10 | To compile to Sugarcane instead of Jonah, use the -t flag: 11 | 12 | ./twee -t sugarcane my-input-file.tw > my-other-output-file.html 13 | 14 | To export the story data to JSON (which could be used by third-party programs like [Twine for AS3](https://github.com/emmett9001/twine-as3)), simply use 15 | 16 | ./twee -t json my-input-file.tw > my-story-output.json 17 | -------------------------------------------------------------------------------- /toward: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os, getopt, glob 4 | scriptPath = os.path.dirname(os.path.realpath(__file__)) 5 | sys.path.append(scriptPath + os.sep + 'lib') 6 | from project import Project 7 | 8 | def usage(): 9 | print 'usage: toward source1 [source2..]' 10 | 11 | 12 | def main (argv): 13 | 14 | proj = Project() 15 | proj.destination = 'proof.rtf' 16 | 17 | # arguments 18 | 19 | try: 20 | opts, args = getopt.getopt(argv, 'o', ['output=']) 21 | except getopt.GetoptError: 22 | usage() 23 | sys.exit(2) 24 | 25 | for opt, arg in opts: 26 | if (opt in ('-o', '--output')): 27 | proj.destination = arg 28 | 29 | # add source files to project 30 | 31 | for arg in args: 32 | for file in glob.glob(arg): 33 | proj.sources.append(file) 34 | 35 | if len(proj.sources) == 0: 36 | print 'toward: no source files specified\n' 37 | sys.exit(2) 38 | 39 | # build the proof 40 | 41 | proj.proof() 42 | 43 | 44 | if __name__ == '__main__': 45 | main(sys.argv[1:]) 46 | -------------------------------------------------------------------------------- /twee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os, getopt, glob 4 | scriptPath = os.path.dirname(os.path.realpath(__file__)) 5 | sys.path.append(scriptPath + os.sep + 'lib') 6 | from tiddlywiki import TiddlyWiki 7 | 8 | 9 | def usage(): 10 | print 'usage: twee [-a author] [-t target] [-m mergefile] [-r rss] source1 [source2..]' 11 | 12 | 13 | def main (argv): 14 | 15 | # defaults 16 | 17 | author = 'twee' 18 | target = 'jonah' 19 | merge = rss_output = '' 20 | plugins = [] 21 | 22 | # read command line switches 23 | 24 | try: 25 | opts, args = getopt.getopt(argv, 'a:m:p:r:t:', ['author=', 'merge=', 'plugins=', 'rss=', 'target=']) 26 | except getopt.GetoptError: 27 | usage() 28 | sys.exit(2) 29 | 30 | for opt, arg in opts: 31 | if (opt in ('-a', '--author')): 32 | author = arg 33 | elif (opt in ('-m', '--merge')): 34 | merge = arg 35 | elif (opt in ('-p', '--plugins')): 36 | plugins = arg.split(',') 37 | elif (opt in ('-r', '--rss')): 38 | rss_output = arg 39 | elif (opt in ('-t', '--target')): 40 | target = arg 41 | 42 | # construct a TW object 43 | 44 | tw = TiddlyWiki(author) 45 | 46 | # read in a file to be merged 47 | 48 | if merge != '': 49 | file = open(merge) 50 | tw.addHtml(file.read()) 51 | file.close() 52 | 53 | # read source files 54 | 55 | sources = [] 56 | 57 | for arg in args: 58 | for file in glob.glob(arg): 59 | sources.append(file) 60 | 61 | if len(sources) == 0: 62 | print 'twee: no source files specified\n' 63 | sys.exit(2) 64 | 65 | for source in sources: 66 | file = open(source) 67 | tw.addTwee(file.read()) 68 | file.close() 69 | 70 | # generate RSS if requested 71 | 72 | if rss_output != '': 73 | rss_file = open(rss_output, 'w') 74 | tw.toRss().write_xml(rss_file) 75 | rss_file.close() 76 | 77 | # output the target header 78 | 79 | if (target != 'none') and (target != 'plugin') and (target != 'json'): 80 | file = open(scriptPath + os.sep + 'targets' + os.sep + target \ 81 | + os.sep + 'header.html') 82 | print(file.read()) 83 | file.close() 84 | 85 | # the tiddlers 86 | 87 | if (target == 'json'): 88 | print tw.toJson() 89 | else: 90 | print tw.toHtml() 91 | 92 | # plugins 93 | 94 | for plugin in plugins: 95 | if target != 'json': 96 | file = open(scriptPath + os.sep + 'targets' + os.sep + target \ 97 | + os.sep + 'plugins' + os.sep + plugin + os.sep + 'compiled.html') 98 | print(file.read()) 99 | file.close() 100 | 101 | # and close it up 102 | 103 | if target != 'json': 104 | print '' 105 | 106 | 107 | if __name__ == '__main__': 108 | main(sys.argv[1:]) 109 | 110 | -------------------------------------------------------------------------------- /doc/files/init-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | main 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 |

main

function main()

Loads the story from the storage div, initializes macros and custom stylesheets, and displays the first passages of the story.

Returns

nothing

14 | 15 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /doc/index/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Class Index 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Class Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
H
 History
P
 Passage
T
 Tale
W
 Wikifier
12 | 13 |
A class used to manage the state of the story -- displaying new passages and rewinding to the past.
14 | 15 | 16 | 17 |
This class represents an individual passage.
18 | 19 | 20 | 21 |
Used to provide access to passages.
22 | 23 | 24 | 25 |
Used to display text on the page.
26 | 27 |
-------------------------------------------------------------------------------- /doc/index/Properties.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Property Index 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Property Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
H
 History, History
I
 id, Passage
 initialText, Passage
P
 passages, Tale
T
 tags, Passage
 text, Passage
 title, Passage
12 | 13 |
An array representing the state of the story.
14 | 15 | 16 | 17 |
An internal id of the passage.
The initial text of the passage.
18 | 19 | 20 | 21 |
An associative array of Passage objects in the story.
22 | 23 | 24 | 25 |
An array of strings, each corresponding to a tag the passage belongs to.
The current text of the passage.
The title of the passage, displayed at its top.
26 | 27 |
-------------------------------------------------------------------------------- /doc/files/fx-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Effects 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 |

Effects

Summary
Fades a DOM element in or out.
This scrolls the browser window to ensure that a DOM element is in view.
14 | 15 |

Functions

16 | 17 |

fade

function fade (el,
options)

Fades a DOM element in or out.

Parameters

elthe element to fade
optionsan object of options to use.  This object must have a fade property, which should be either the string ‘in’ or ‘out’, corresponding to the direction of the fade.  The second property used here, onComplete, is a function that is called once the fade is complete.  This is optional.

Returns

nothing

18 | 19 |

scrollWindowTo

function scrollWindowTo (el)

This scrolls the browser window to ensure that a DOM element is in view.  Make sure that the element has been added to the page before calling this function.

Parameters

elthe element to scroll to.

Returns

nothing

20 | 21 |
24 | 25 |
function fade (el,
options)
Fades a DOM element in or out.
function scrollWindowTo (el)
This scrolls the browser window to ensure that a DOM element is in view.
26 | 27 | -------------------------------------------------------------------------------- /doc/javascript/main.js: -------------------------------------------------------------------------------- 1 | // This file is part of Natural Docs, which is Copyright (C) 2003-2005 Greg Valure 2 | // Natural Docs is licensed under the GPL 3 | 4 | // 5 | // Browser Styles 6 | // ____________________________________________________________________________ 7 | 8 | var agt=navigator.userAgent.toLowerCase(); 9 | var browserType; 10 | var browserVer; 11 | 12 | if (agt.indexOf("opera") != -1) 13 | { 14 | browserType = "Opera"; 15 | 16 | if (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1) 17 | { browserVer = "Opera5"; } 18 | else if (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1) 19 | { browserVer = "Opera6"; } 20 | else if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1) 21 | { browserVer = "Opera7"; } 22 | } 23 | 24 | else if (agt.indexOf("khtml") != -1 || agt.indexOf("konq") != -1 || agt.indexOf("safari") != -1) 25 | { 26 | browserType = "KHTML"; 27 | } 28 | 29 | else if (agt.indexOf("msie") != -1) 30 | { 31 | browserType = "IE"; 32 | 33 | if (agt.indexOf("msie 4") != -1) 34 | { browserVer = "IE4"; } 35 | else if (agt.indexOf("msie 5") != -1) 36 | { browserVer = "IE5"; } 37 | else if (agt.indexOf("msie 6") != -1) 38 | { browserVer = "IE6"; } 39 | } 40 | 41 | else if (agt.indexOf("gecko") != -1) 42 | { 43 | browserType = "Gecko"; 44 | } 45 | 46 | // Opera already taken care of. 47 | else if (agt.indexOf("mozilla") != -1 && agt.indexOf("compatible") == -1 && agt.indexOf("spoofer") == -1 && 48 | agt.indexOf("webtv") == -1 && agt.indexOf("hotjava") == -1) 49 | { 50 | browserType = "Netscape"; 51 | 52 | if (agt.indexOf("mozilla/4") != -1) 53 | { browserVer = "Netscape4"; } 54 | } 55 | 56 | 57 | // 58 | // Menu 59 | // ____________________________________________________________________________ 60 | 61 | 62 | function ToggleMenu(id) 63 | { 64 | if (!window.document.getElementById) 65 | { return; }; 66 | 67 | var display = window.document.getElementById(id).style.display; 68 | 69 | if (display == "none") 70 | { display = "block"; } 71 | else 72 | { display = "none"; } 73 | 74 | window.document.getElementById(id).style.display = display; 75 | } 76 | 77 | 78 | // 79 | // Tooltips 80 | // ____________________________________________________________________________ 81 | 82 | 83 | var tooltipTimer = 0; 84 | 85 | function ShowTip(event, tooltipID, linkID) 86 | { 87 | if (tooltipTimer) 88 | { clearTimeout(tooltipTimer); }; 89 | 90 | var docX = event.clientX + window.pageXOffset; 91 | var docY = event.clientY + window.pageYOffset; 92 | 93 | var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")"; 94 | 95 | // KHTML cant handle showing on a timer right now. 96 | 97 | if (browserType != "KHTML") 98 | { tooltipTimer = setTimeout(showCommand, 1000); } 99 | else 100 | { eval(showCommand); }; 101 | } 102 | 103 | function ReallyShowTip(tooltipID, linkID, docX, docY) 104 | { 105 | tooltipTimer = 0; 106 | 107 | var tooltip; 108 | var link; 109 | 110 | if (document.getElementById) 111 | { 112 | tooltip = document.getElementById(tooltipID); 113 | link = document.getElementById(linkID); 114 | } 115 | else if (document.all) 116 | { 117 | tooltip = eval("document.all['" + tooltipID + "']"); 118 | link = eval("document.all['" + linkID + "']"); 119 | } 120 | 121 | if (tooltip) 122 | { 123 | var left = 0; 124 | var top = 0; 125 | 126 | // Not everything supports offsetTop/Left/Width, and some, like Konqueror and Opera 5, think they do but do it badly. 127 | 128 | if (link && link.offsetWidth != null && browserType != "KHTML" && browserVer != "Opera5") 129 | { 130 | var item = link; 131 | while (item != document.body) 132 | { 133 | left += item.offsetLeft; 134 | item = item.offsetParent; 135 | } 136 | 137 | item = link; 138 | while (item != document.body) 139 | { 140 | top += item.offsetTop; 141 | item = item.offsetParent; 142 | } 143 | top += link.offsetHeight; 144 | } 145 | 146 | // The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number 147 | // in case some browser snuck through the above if statement but didn't support everything. 148 | 149 | if (!isFinite(top) || top == 0) 150 | { 151 | left = docX; 152 | top = docY; 153 | } 154 | 155 | // Some spacing to get it out from under the cursor. 156 | 157 | top += 10; 158 | 159 | // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the 160 | // page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right. 161 | 162 | if (tooltip.offsetWidth != null) 163 | { 164 | var width = tooltip.offsetWidth; 165 | var docWidth = document.body.clientWidth; 166 | 167 | if (left + width > docWidth) 168 | { left = docWidth - width - 1; } 169 | } 170 | 171 | // Opera 5 chokes on the px extension, so it can use the Microsoft one instead. 172 | 173 | if (tooltip.style.left != null && browserVer != "Opera5") 174 | { 175 | tooltip.style.left = left + "px"; 176 | tooltip.style.top = top + "px"; 177 | } 178 | else if (tooltip.style.pixelLeft != null) 179 | { 180 | tooltip.style.pixelLeft = left; 181 | tooltip.style.pixelTop = top; 182 | } 183 | 184 | tooltip.style.visibility = "visible"; 185 | } 186 | } 187 | 188 | function HideTip(tooltipID) 189 | { 190 | if (tooltipTimer) 191 | { 192 | clearTimeout(tooltipTimer); 193 | tooltipTimer = 0; 194 | } 195 | 196 | var tooltip; 197 | 198 | if (document.getElementById) 199 | { tooltip = document.getElementById(tooltipID); } 200 | else if (document.all) 201 | { tooltip = eval("document.all['" + tooltipID + "']"); } 202 | 203 | if (tooltip) 204 | { tooltip.style.visibility = "hidden"; } 205 | } 206 | 207 | 208 | // 209 | // Event Handlers 210 | // ____________________________________________________________________________ 211 | 212 | 213 | function NDOnLoad() 214 | { 215 | if (browserType == "IE") 216 | { 217 | var scrollboxes = document.getElementsByTagName('blockquote'); 218 | 219 | if (scrollboxes.item(0)) 220 | { 221 | var width = scrollboxes.item(0).parentNode.offsetWidth - scrollboxes.item(0).offsetLeft; 222 | 223 | var i = 0; 224 | var item; 225 | 226 | while (item = scrollboxes.item(i)) 227 | { 228 | item.style.width = width; 229 | i++; 230 | }; 231 | 232 | window.onresize=NDOnResize; 233 | }; 234 | }; 235 | } 236 | 237 | 238 | var resizeTimer = 0; 239 | 240 | function NDOnResize() 241 | { 242 | if (browserType == "IE") 243 | { 244 | if (resizeTimer != 0) 245 | { clearTimeout(resizeTimer); }; 246 | 247 | resizeTimer = setTimeout(NDDoResize, 500); 248 | }; 249 | }; 250 | 251 | function NDDoResize() 252 | { 253 | var scrollboxes = document.getElementsByTagName('blockquote'); 254 | 255 | var i; 256 | var item; 257 | 258 | i = 0; 259 | while (item = scrollboxes.item(i)) 260 | { 261 | item.style.width = "100px"; 262 | i++; 263 | }; 264 | 265 | var width = scrollboxes.item(0).parentNode.offsetWidth - scrollboxes.item(0).offsetLeft; 266 | 267 | i = 0; 268 | while (item = scrollboxes.item(i)) 269 | { 270 | item.style.width = width; 271 | i++; 272 | }; 273 | 274 | clearTimeout(resizeTimer); 275 | resizeTimer = 0; 276 | } 277 | -------------------------------------------------------------------------------- /doc/files/wikifier-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wikifier 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 26 | 27 |

Wikifier

Used to display text on the page.  This is taken more or less verbatim from the TiddlyWiki core code, though not all formatters are available (notably the WikiWord link).

Summary
Used to display text on the page.
Wikifies source text into a DOM element.
Meant to be called by macros, this returns the text passed to the currently executing macro.
Creates a link to a passage.
Creates a link to an external URL.
14 | 15 |

Functions

16 | 17 |

Wikifier

function Wikifier(place,
source)

Wikifies source text into a DOM element.  Any pre-existing contents are appended to.  This should be used in place of TiddlyWiki’s wikify() function.

Parameters

placethe DOM element to render into
sourcethe source text to render

Returns

nothing

18 | 19 |

fullArgs

Wikifier.prototype.fullArgs = function()

Meant to be called by macros, this returns the text passed to the currently executing macro.  Unlike TiddlyWiki’s default mechanism, this does not attempt to split up the arguments into an array, thought it does do some magic with certain Twee operators (like gt, eq, and $variable).

Parameters

none

Returns

a parsed string of arguments

20 | 21 |

createInternalLink

Wikifier.createInternalLink = function (place,
title)

Creates a link to a passage.  It automatically classes it so that broken links appear broken.

Parameters

placethe DOM element to render into
titlethe title of the passage to link to

Returns

the newly created link as a DOM element

22 | 23 |

createExternalLink

Wikifier.createExternalLink = function (place,
url)

Creates a link to an external URL.

Parameters

placethe DOM element to render into
urlthe URL to link to

Returns

the newly created link as a DOM element

24 | 25 |
28 | 29 |
function Wikifier(place,
source)
Wikifies source text into a DOM element.
Wikifier.prototype.fullArgs = function()
Meant to be called by macros, this returns the text passed to the currently executing macro.
Wikifier.createInternalLink = function (place,
title)
Creates a link to a passage.
Wikifier.createExternalLink = function (place,
url)
Creates a link to an external URL.
30 | 31 | -------------------------------------------------------------------------------- /lib/tiddlywiki.py: -------------------------------------------------------------------------------- 1 | # 2 | # TiddlyWiki.py 3 | # 4 | # A Python implementation of the Twee compiler. 5 | # 6 | # This code was written by Chris Klimas 7 | # It is licensed under the GNU General Public License v2 8 | # http://creativecommons.org/licenses/GPL/2.0/ 9 | # 10 | # This file defines two classes: Tiddler and TiddlyWiki. These match what 11 | # you'd normally see in a TiddlyWiki; the goal here is to provide classes 12 | # that translate between Twee and TiddlyWiki output seamlessly. 13 | # 14 | 15 | import re, datetime, time, os, sys, json 16 | import PyRSS2Gen as rss 17 | 18 | # 19 | # TiddlyWiki class 20 | # 21 | 22 | class TiddlyWiki: 23 | """An entire TiddlyWiki.""" 24 | 25 | def __init__ (self, author = 'twee'): 26 | """Optionally pass an author name.""" 27 | self.author = author 28 | self.tiddlers = {} 29 | 30 | def tryGetting (self, names, default = ''): 31 | """Tries retrieving the text of several tiddlers by name; returns default if none exist.""" 32 | for name in names: 33 | if name in self.tiddlers: 34 | return self.tiddlers[name].text 35 | 36 | return default 37 | 38 | def toTwee (self, order = None): 39 | """Returns Twee source code for this TiddlyWiki.""" 40 | if not order: order = self.tiddlers.keys() 41 | output = '' 42 | 43 | for i in order: 44 | output += self.tiddlers[i].toTwee() 45 | 46 | return output 47 | 48 | def toHtml (self, app = None, target = None, order = None): 49 | """Returns HTML code for this TiddlyWiki. If target is passed, adds a header.""" 50 | if not order: order = self.tiddlers.keys() 51 | output = '' 52 | 53 | if (target): 54 | header = open(app.getPath() + os.sep + 'targets' + os.sep + target + os.sep + 'header.html') 55 | output = header.read() 56 | header.close() 57 | 58 | for i in order: 59 | output += self.tiddlers[i].toHtml(self.author) 60 | 61 | if (target): 62 | output += '' 63 | 64 | return output 65 | 66 | def toJson (self): 67 | output = {"data": []} 68 | order = self.tiddlers.keys() 69 | for i in order: 70 | output['data'].append(self.tiddlers[i].toJson(self.author)) 71 | return json.dumps(output) 72 | 73 | def toRtf (self, order = None): 74 | """Returns RTF source code for this TiddlyWiki.""" 75 | if not order: order = self.tiddlers.keys() 76 | 77 | # preamble 78 | 79 | output = r'{\rtf1\ansi\ansicpg1251' + '\n' 80 | output += r'{\fonttbl\f0\fswiss\fcharset0 Arial;}' + '\n' 81 | output += r'{\colortbl;\red128\green128\blue128;}' + '\n' 82 | output += r'\margl1440\margr1440\vieww9000\viewh8400\viewkind0' + '\n' 83 | output += r'\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx792' + '\n' 84 | output += r'\tx8640\ql\qnatural\pardirnatural\pgnx720\pgny720' + '\n' 85 | 86 | # content 87 | 88 | for i in order: 89 | text = self.tiddlers[i].text 90 | text = re.sub(r'\n', '\\\n', text) # newlines 91 | text = re.sub(r'\[\[(.*?)\]\]', r'\ul \1\ulnone ', text) # links 92 | text = re.sub(r'\/\/(.*?)\/\/', r'\i \1\i0 ', text) # italics 93 | text = re.sub(r'(\<\<.*?\>\>)', r'\cf1 \i \1\i0 \cf0', text) # macros 94 | 95 | output += r'\fs24\b1' + self.tiddlers[i].title + r'\b0\fs20' + '\\\n' 96 | output += text + '\\\n\\\n' 97 | 98 | output += '}' 99 | 100 | return output 101 | 102 | def toRss (self, num_items = 5): 103 | """Returns an RSS2 object of recently changed tiddlers.""" 104 | url = self.tryGetting(['StoryUrl', 'SiteUrl']) 105 | title = self.tryGetting(['StoryTitle', 'SiteTitle'], 'Untitled Story') 106 | subtitle = self.tryGetting(['StorySubtitle', 'SiteSubtitle']) 107 | 108 | # build a date-sorted list of tiddler titles 109 | 110 | sorted_keys = self.tiddlers.keys() 111 | sorted_keys.sort(key = lambda i: self.tiddlers[i].modified) 112 | 113 | # and then generate our items 114 | 115 | rss_items = [] 116 | 117 | for i in sorted_keys[:num_items]: 118 | rss_items.append(self.tiddlers[i].toRss()) 119 | 120 | return rss.RSS2( 121 | title = title, 122 | link = url, 123 | description = subtitle, 124 | pubDate = datetime.datetime.now(), 125 | items = rss_items 126 | ) 127 | 128 | def addTwee (self, source): 129 | """Adds Twee source code to this TiddlyWiki.""" 130 | source = source.replace("\r\n", "\n") 131 | tiddlers = source.split('\n::') 132 | 133 | for i in tiddlers: 134 | self.addTiddler(Tiddler('::' + i)) 135 | 136 | def addHtml (self, source): 137 | """Adds HTML source code to this TiddlyWiki.""" 138 | divs_re = re.compile(r'
(.*)
\s*', 139 | re.DOTALL) 140 | divs = divs_re.search(source) 141 | 142 | if divs: 143 | for div in divs.group(1).split(' self.tiddlers[tiddler.title].modified): 152 | self.tiddlers[tiddler.title] = tiddler 153 | else: 154 | self.tiddlers[tiddler.title] = tiddler 155 | 156 | # 157 | # Tiddler class 158 | # 159 | 160 | class Tiddler: 161 | """A single tiddler in a TiddlyWiki.""" 162 | 163 | def __init__ (self, source, type = 'twee'): 164 | """Pass source code, and optionally 'twee' or 'html'""" 165 | if type == 'twee': 166 | self.initTwee(source) 167 | else: 168 | self.initHtml(source) 169 | 170 | def __repr__ (self): 171 | return "" 172 | 173 | def __cmp__ (self, other): 174 | """Compares a Tiddler to another.""" 175 | return self.text == other.text 176 | 177 | def initTwee (self, source): 178 | """Initializes a Tiddler from Twee source code.""" 179 | 180 | # we were just born 181 | 182 | self.created = self.modified = time.localtime() 183 | 184 | # figure out our title 185 | 186 | lines = source.strip().split('\n') 187 | 188 | meta_bits = lines[0].split('[') 189 | self.title = meta_bits[0].strip(' :') 190 | 191 | # find tags 192 | 193 | self.tags = [] 194 | 195 | if len(meta_bits) > 1: 196 | tag_bits = meta_bits[1].split(' ') 197 | 198 | for tag in tag_bits: 199 | self.tags.append(tag.strip('[]')) 200 | 201 | # and then the body text 202 | 203 | self.text = '' 204 | 205 | for line in lines[1:]: 206 | self.text += line + "\n" 207 | 208 | self.text = self.text.strip() 209 | 210 | 211 | def initHtml (self, source): 212 | """Initializes a Tiddler from HTML source code.""" 213 | 214 | # title 215 | 216 | self.title = 'untitled passage' 217 | title_re = re.compile(r'tiddler="(.*?)"') 218 | title = title_re.search(source) 219 | if title: 220 | self.title = title.group(1) 221 | 222 | # tags 223 | 224 | self.tags = [] 225 | tags_re = re.compile(r'tags="(.*?)"') 226 | tags = tags_re.search(source) 227 | if tags and tags.group(1) != '': 228 | self.tags = tags.group(1).split(' ') 229 | 230 | # creation date 231 | 232 | self.created = time.localtime() 233 | created_re = re.compile(r'created="(.*?)"') 234 | created = created_re.search(source) 235 | if created: 236 | self.created = decode_date(created.group(1)) 237 | 238 | # modification date 239 | 240 | self.modified = time.localtime() 241 | modified_re = re.compile(r'modified="(.*?)"') 242 | modified = modified_re.search(source) 243 | if (modified): 244 | self.modified = decode_date(modified.group(1)) 245 | 246 | # body text 247 | 248 | self.text = '' 249 | text_re = re.compile(r'(.*)') 250 | text = text_re.search(source) 251 | if (text): 252 | self.text = decode_text(text.group(1)) 253 | 254 | 255 | def toHtml (self, author = 'twee'): 256 | """Returns an HTML representation of this tiddler.""" 257 | 258 | now = time.localtime() 259 | output = '
' 268 | output += encode_text(self.text) + '
' 269 | 270 | return output 271 | 272 | 273 | def toJson (self, author = 'twee'): 274 | now = time.localtime() 275 | ret = {} 276 | 277 | ret['title'] = self.title 278 | ret['tags'] = [] 279 | for tag in self.tags: 280 | ret['tags'].append(tag) 281 | ret['modified'] = encode_date(self.modified) 282 | ret['created'] = encode_date(self.created) 283 | ret['modifier'] = author 284 | ret['text'] = self.text 285 | 286 | return ret 287 | 288 | 289 | def toTwee (self): 290 | """Returns a Twee representation of this tiddler.""" 291 | output = ':: ' + self.title 292 | 293 | if len(self.tags) > 0: 294 | output += ' [' 295 | for tag in self.tags: 296 | output += tag + ' ' 297 | output = output.strip() 298 | output += ']' 299 | 300 | output += "\n" + self.text + "\n\n\n" 301 | return output 302 | 303 | 304 | def toRss (self, author = 'twee'): 305 | """Returns an RSS representation of this tiddler.""" 306 | return rss.RSSItem( 307 | title = self.title, 308 | link = '', 309 | description = self.text, 310 | pubDate = datetime.datetime.now() 311 | ) 312 | 313 | def links (self, includeExternal = False): 314 | """ 315 | Returns a list of all passages linked to by this one. By default, 316 | only returns internal links, but you can override it with the includeExternal 317 | parameter. 318 | """ 319 | 320 | # regular hyperlinks 321 | 322 | links = re.findall(r'\[\[(.+?)\]\]', self.text) 323 | 324 | # check for [[title|target]] formats 325 | 326 | def filterPrettyLinks (text): 327 | if '|' in text: return re.sub('.*\|', '', text) 328 | else: return text 329 | 330 | # remove external links 331 | 332 | def isInternalLink (text): 333 | return not re.match('http://', text) 334 | 335 | links = map(filterPrettyLinks, links) 336 | if not includeExternal: links = filter(isInternalLink, links) 337 | 338 | # <> 339 | 340 | displays = re.findall(r'\<\\>', self.text, re.IGNORECASE) 341 | 342 | # <> 343 | 344 | choices = re.findall(r'\<\\>', self.text, re.IGNORECASE) 345 | 346 | # <> 347 | 348 | actions = list() 349 | actionBlocks = re.findall(r'\<\\>', self.text, re.IGNORECASE) 350 | for block in actionBlocks: 351 | actions = actions + re.findall(r'[\'"](.*?)[\'"]', block) 352 | 353 | # remove duplicates by converting to a set 354 | 355 | return list(set(links + displays + choices + actions)) 356 | 357 | # 358 | # Helper functions 359 | # 360 | 361 | 362 | def encode_text (text): 363 | """Encodes a string for use in HTML output.""" 364 | output = text 365 | output = output.replace('\\', '\s') 366 | output = re.sub(r'\r?\n', r'\\n', output) 367 | output = output.replace('<', '<') 368 | output = output.replace('>', '>') 369 | output = output.replace('"', '"') 370 | 371 | return output 372 | 373 | 374 | def decode_text (text): 375 | """Decodes a string from HTML.""" 376 | output = text 377 | output = output.replace('\\n', '\n') 378 | output = output.replace('\s', '\\') 379 | output = output.replace('<', '<') 380 | output = output.replace('>', '>') 381 | output = output.replace('"', '"') 382 | 383 | return output 384 | 385 | 386 | def encode_date (date): 387 | """Encodes a datetime in TiddlyWiki format.""" 388 | return time.strftime('%Y%m%d%H%M', date) 389 | 390 | 391 | def decode_date (date): 392 | """Decodes a datetime from TiddlyWiki format.""" 393 | return time.strptime(date, '%Y%m%d%H%M') 394 | -------------------------------------------------------------------------------- /doc/files/passage-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Passage 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 38 | 39 |

Passage

This class represents an individual passage.  This is analogous to the Tiddler class in the core TiddlyWiki code.

Summary
This class represents an individual passage.
The title of the passage, displayed at its top.
An internal id of the passage.
The initial text of the passage.
The current text of the passage.
An array of strings, each corresponding to a tag the passage belongs to.
Initializes a new Passage object.
Renders the passage to a DOM element, including its title, toolbar, and content.
Resets the passage’s text property to its initialText property.
A static function used by the constructor to convert string literals used by TiddlyWiki to indicate newlines into actual newlines.
14 | 15 |

Properties

16 | 17 |

title

The title of the passage, displayed at its top.

18 | 19 |

id

An internal id of the passage.  This is never seen by the reader, but it is used by the History class.

20 | 21 |

initialText

The initial text of the passage.  This is used by the reset method.

22 | 23 |

text

The current text of the passage.  This is usually the same as the initialText property, though macros such as <<choice>> may alter it.

24 | 25 |

tags

An array of strings, each corresponding to a tag the passage belongs to.

26 | 27 |

Functions

28 | 29 |

Passage

function Passage (title,
el,
order)

Initializes a new Passage object.  You may either call this with a DOM element, which creates the passage from the text stored in the element, or you may pass only a title,

Parameters

titlethe title of the passage to create.  This parameter is required.
elthe DOM element storing the content of the passage.  This parameter is optional.  If it is omitted, “this passage does not exist” is used as the passage’s content.
orderthe order in which this passage was retrieved from the document’s storeArea div.  This is used to generate the passage’s id.  This parameter is optional, but should be included if el is specified.
30 | 31 |

render

Passage.prototype.render = function()

Renders the passage to a DOM element, including its title, toolbar, and content.  It’s up to the caller to add this to the DOM tree appropriately and animate its appearance.

Parameters

none

Returns

nothing

32 | 33 |

reset

Passage.prototype.reset = function()

Resets the passage’s text property to its initialText property.  This does not directly affect anything displayed on the page.

Parameters

none

Returns

nothing

34 | 35 |

unescapeLineBreaks

Passage.unescapeLineBreaks = function (text)

A static function used by the constructor to convert string literals used by TiddlyWiki to indicate newlines into actual newlines.

Parameters

texta string to unescape

Returns

a converted string

36 | 37 |
40 | 41 |
function Passage (title,
el,
order)
Initializes a new Passage object.
Passage.prototype.render = function()
Renders the passage to a DOM element, including its title, toolbar, and content.
Passage.prototype.reset = function()
Resets the passage’s text property to its initialText property.
The current text of the passage.
The initial text of the passage.
Passage.unescapeLineBreaks = function (text)
A static function used by the constructor to convert string literals used by TiddlyWiki to indicate newlines into actual newlines.
A class used to manage the state of the story -- displaying new passages and rewinding to the past.
42 | 43 | -------------------------------------------------------------------------------- /doc/files/tale-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tale 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 32 | 33 |

Tale

Used to provide access to passages.  This is analogous to the TiddlyWiki class in the core TiddlyWiki code.

Summary
Used to provide access to passages.
An associative array of Passage objects in the story.
Initializes a new Tale object with the contents of the DOM element with the id storeArea, constructing new Passages as it traverses the tree.
Checks whether the tale has a passage with either the title passed (if the key parameter is a string) or an id (if a number is passed instead).
A getter function that returns a certain Passage object belonging to the tale.
Searches the Tale for all passages matching a certain criteria.
Calls the Passage.reset method on all Passages in the tale, restoring the story to its initial state.
14 | 15 |

Properties

16 | 17 |

passages

An associative array of Passage objects in the story.  The key for this array is the title of the passage.

18 | 19 |

Functions

20 | 21 |

Tale

function Tale()

Initializes a new Tale object with the contents of the DOM element with the id storeArea, constructing new Passages as it traverses the tree.

Parameters

none

22 | 23 |

has

Tale.prototype.has = function (key)

Checks whether the tale has a passage with either the title passed (if the key parameter is a string) or an id (if a number is passed instead).

Parameters

keythe title or id of the passage to search for

Returns

boolean

24 | 25 |

get

Tale.prototype.get = function (key)

A getter function that returns a certain Passage object belonging to the tale.  You may either retrieve a passage by its title or id.

Parameters

keythe title or id of the passage to retrieve

Returns

A Passage object.  If no passage exists matching the passed key, a null value is returned.

See also

Tale.lookup

26 | 27 |

lookup

Tale.prototype.lookup = function(field,
value,
sortField)

Searches the Tale for all passages matching a certain criteria.  You may optionally specify a secondary field to sort the results on.

Parameters

fieldthe name of the Passage property to search on
valuethe value to match
sortFieldthe name of the Passage property to sort matches on.  This always sorts in descending order.  If you need ascending order, use the Array class’s reverse() method.

Returns

An array of Passages.  If no passages met the search criteria, an empty array is returned.

See also

Tale.get

28 | 29 |

reset

Tale.prototype.reset = function()

Calls the Passage.reset method on all Passages in the tale, restoring the story to its initial state.

Parameters

none

Returns

nothing

30 | 31 |
34 | 35 |
This class represents an individual passage.
function Tale()
Initializes a new Tale object with the contents of the DOM element with the id storeArea, constructing new Passages as it traverses the tree.
Tale.prototype.has = function (key)
Checks whether the tale has a passage with either the title passed (if the key parameter is a string) or an id (if a number is passed instead).
Tale.prototype.get = function (key)
A getter function that returns a certain Passage object belonging to the tale.
Tale.prototype.lookup = function(field,
value,
sortField)
Searches the Tale for all passages matching a certain criteria.
Tale.prototype.reset = function()
Calls the Passage.reset method on all Passages in the tale, restoring the story to its initial state.
Passage.prototype.reset = function()
Resets the passage’s text property to its initialText property.
36 | 37 | -------------------------------------------------------------------------------- /lib/PyRSS2Gen.py: -------------------------------------------------------------------------------- 1 | """PyRSS2Gen - A Python library for generating RSS 2.0 feeds.""" 2 | 3 | __name__ = "PyRSS2Gen" 4 | __version__ = (1, 0, 0) 5 | __author__ = "Andrew Dalke " 6 | 7 | _generator_name = __name__ + "-" + ".".join(map(str, __version__)) 8 | 9 | import datetime 10 | 11 | # Could make this the base class; will need to add 'publish' 12 | class WriteXmlMixin: 13 | def write_xml(self, outfile, encoding = "iso-8859-1"): 14 | from xml.sax import saxutils 15 | handler = saxutils.XMLGenerator(outfile, encoding) 16 | handler.startDocument() 17 | self.publish(handler) 18 | handler.endDocument() 19 | 20 | def to_xml(self, encoding = "iso-8859-1"): 21 | try: 22 | import cStringIO as StringIO 23 | except ImportError: 24 | import StringIO 25 | f = StringIO.StringIO() 26 | self.write_xml(f, encoding) 27 | return f.getvalue() 28 | 29 | 30 | def _element(handler, name, obj, d = {}): 31 | if isinstance(obj, basestring) or obj is None: 32 | # special-case handling to make the API easier 33 | # to use for the common case. 34 | handler.startElement(name, d) 35 | if obj is not None: 36 | handler.characters(obj) 37 | handler.endElement(name) 38 | else: 39 | # It better know how to emit the correct XML. 40 | obj.publish(handler) 41 | 42 | def _opt_element(handler, name, obj): 43 | if obj is None: 44 | return 45 | _element(handler, name, obj) 46 | 47 | 48 | def _format_date(dt): 49 | """convert a datetime into an RFC 822 formatted date 50 | 51 | Input date must be in GMT. 52 | """ 53 | # Looks like: 54 | # Sat, 07 Sep 2002 00:00:01 GMT 55 | # Can't use strftime because that's locale dependent 56 | # 57 | # Isn't there a standard way to do this for Python? The 58 | # rfc822 and email.Utils modules assume a timestamp. The 59 | # following is based on the rfc822 module. 60 | return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( 61 | ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()], 62 | dt.day, 63 | ["Jan", "Feb", "Mar", "Apr", "May", "Jun", 64 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1], 65 | dt.year, dt.hour, dt.minute, dt.second) 66 | 67 | 68 | ## 69 | # A couple simple wrapper objects for the fields which 70 | # take a simple value other than a string. 71 | class IntElement: 72 | """implements the 'publish' API for integers 73 | 74 | Takes the tag name and the integer value to publish. 75 | 76 | (Could be used for anything which uses str() to be published 77 | to text for XML.) 78 | """ 79 | element_attrs = {} 80 | def __init__(self, name, val): 81 | self.name = name 82 | self.val = val 83 | def publish(self, handler): 84 | handler.startElement(self.name, self.element_attrs) 85 | handler.characters(str(self.val)) 86 | handler.endElement(self.name) 87 | 88 | class DateElement: 89 | """implements the 'publish' API for a datetime.datetime 90 | 91 | Takes the tag name and the datetime to publish. 92 | 93 | Converts the datetime to RFC 2822 timestamp (4-digit year). 94 | """ 95 | def __init__(self, name, dt): 96 | self.name = name 97 | self.dt = dt 98 | def publish(self, handler): 99 | _element(handler, self.name, _format_date(self.dt)) 100 | #### 101 | 102 | class Category: 103 | """Publish a category element""" 104 | def __init__(self, category, domain = None): 105 | self.category = category 106 | self.domain = domain 107 | def publish(self, handler): 108 | d = {} 109 | if self.domain is not None: 110 | d["domain"] = self.domain 111 | _element(handler, "category", self.category, d) 112 | 113 | class Cloud: 114 | """Publish a cloud""" 115 | def __init__(self, domain, port, path, 116 | registerProcedure, protocol): 117 | self.domain = domain 118 | self.port = port 119 | self.path = path 120 | self.registerProcedure = registerProcedure 121 | self.protocol = protocol 122 | def publish(self, handler): 123 | _element(handler, "cloud", None, { 124 | "domain": self.domain, 125 | "port": str(self.port), 126 | "path": self.path, 127 | "registerProcedure": self.registerProcedure, 128 | "protocol": self.protocol}) 129 | 130 | class Image: 131 | """Publish a channel Image""" 132 | element_attrs = {} 133 | def __init__(self, url, title, link, 134 | width = None, height = None, description = None): 135 | self.url = url 136 | self.title = title 137 | self.link = link 138 | self.width = width 139 | self.height = height 140 | self.description = description 141 | 142 | def publish(self, handler): 143 | handler.startElement("image", self.element_attrs) 144 | 145 | _element(handler, "url", self.url) 146 | _element(handler, "title", self.title) 147 | _element(handler, "link", self.link) 148 | 149 | width = self.width 150 | if isinstance(width, int): 151 | width = IntElement("width", width) 152 | _opt_element(handler, "width", width) 153 | 154 | height = self.height 155 | if isinstance(height, int): 156 | height = IntElement("height", height) 157 | _opt_element(handler, "height", height) 158 | 159 | _opt_element(handler, "description", self.description) 160 | 161 | handler.endElement("image") 162 | 163 | class Guid: 164 | """Publish a guid 165 | 166 | Defaults to being a permalink, which is the assumption if it's 167 | omitted. Hence strings are always permalinks. 168 | """ 169 | def __init__(self, guid, isPermaLink = 1): 170 | self.guid = guid 171 | self.isPermaLink = isPermaLink 172 | def publish(self, handler): 173 | d = {} 174 | if self.isPermaLink: 175 | d["isPermaLink"] = "true" 176 | else: 177 | d["isPermaLink"] = "false" 178 | _element(handler, "guid", self.guid, d) 179 | 180 | class TextInput: 181 | """Publish a textInput 182 | 183 | Apparently this is rarely used. 184 | """ 185 | element_attrs = {} 186 | def __init__(self, title, description, name, link): 187 | self.title = title 188 | self.description = description 189 | self.name = name 190 | self.link = link 191 | 192 | def publish(self, handler): 193 | handler.startElement("textInput", self.element_attrs) 194 | _element(handler, "title", self.title) 195 | _element(handler, "description", self.description) 196 | _element(handler, "name", self.name) 197 | _element(handler, "link", self.link) 198 | handler.endElement("textInput") 199 | 200 | 201 | class Enclosure: 202 | """Publish an enclosure""" 203 | def __init__(self, url, length, type): 204 | self.url = url 205 | self.length = length 206 | self.type = type 207 | def publish(self, handler): 208 | _element(handler, "enclosure", None, 209 | {"url": self.url, 210 | "length": str(self.length), 211 | "type": self.type, 212 | }) 213 | 214 | class Source: 215 | """Publish the item's original source, used by aggregators""" 216 | def __init__(self, name, url): 217 | self.name = name 218 | self.url = url 219 | def publish(self, handler): 220 | _element(handler, "source", self.name, {"url": self.url}) 221 | 222 | class SkipHours: 223 | """Publish the skipHours 224 | 225 | This takes a list of hours, as integers. 226 | """ 227 | element_attrs = {} 228 | def __init__(self, hours): 229 | self.hours = hours 230 | def publish(self, handler): 231 | if self.hours: 232 | handler.startElement("skipHours", self.element_attrs) 233 | for hour in self.hours: 234 | _element(handler, "hour", str(hour)) 235 | handler.endElement("skipHours") 236 | 237 | class SkipDays: 238 | """Publish the skipDays 239 | 240 | This takes a list of days as strings. 241 | """ 242 | element_attrs = {} 243 | def __init__(self, days): 244 | self.days = days 245 | def publish(self, handler): 246 | if self.days: 247 | handler.startElement("skipDays", self.element_attrs) 248 | for day in self.days: 249 | _element(handler, "day", day) 250 | handler.endElement("skipDays") 251 | 252 | class RSS2(WriteXmlMixin): 253 | """The main RSS class. 254 | 255 | Stores the channel attributes, with the "category" elements under 256 | ".categories" and the RSS items under ".items". 257 | """ 258 | 259 | rss_attrs = {"version": "2.0"} 260 | element_attrs = {} 261 | def __init__(self, 262 | title, 263 | link, 264 | description, 265 | 266 | language = None, 267 | copyright = None, 268 | managingEditor = None, 269 | webMaster = None, 270 | pubDate = None, # a datetime, *in* *GMT* 271 | lastBuildDate = None, # a datetime 272 | 273 | categories = None, # list of strings or Category 274 | generator = _generator_name, 275 | docs = "http://blogs.law.harvard.edu/tech/rss", 276 | cloud = None, # a Cloud 277 | ttl = None, # integer number of minutes 278 | 279 | image = None, # an Image 280 | rating = None, # a string; I don't know how it's used 281 | textInput = None, # a TextInput 282 | skipHours = None, # a SkipHours with a list of integers 283 | skipDays = None, # a SkipDays with a list of strings 284 | 285 | items = None, # list of RSSItems 286 | ): 287 | self.title = title 288 | self.link = link 289 | self.description = description 290 | self.language = language 291 | self.copyright = copyright 292 | self.managingEditor = managingEditor 293 | 294 | self.webMaster = webMaster 295 | self.pubDate = pubDate 296 | self.lastBuildDate = lastBuildDate 297 | 298 | if categories is None: 299 | categories = [] 300 | self.categories = categories 301 | self.generator = generator 302 | self.docs = docs 303 | self.cloud = cloud 304 | self.ttl = ttl 305 | self.image = image 306 | self.rating = rating 307 | self.textInput = textInput 308 | self.skipHours = skipHours 309 | self.skipDays = skipDays 310 | 311 | if items is None: 312 | items = [] 313 | self.items = items 314 | 315 | def publish(self, handler): 316 | handler.startElement("rss", self.rss_attrs) 317 | handler.startElement("channel", self.element_attrs) 318 | _element(handler, "title", self.title) 319 | _element(handler, "link", self.link) 320 | _element(handler, "description", self.description) 321 | 322 | self.publish_extensions(handler) 323 | 324 | _opt_element(handler, "language", self.language) 325 | _opt_element(handler, "copyright", self.copyright) 326 | _opt_element(handler, "managingEditor", self.managingEditor) 327 | _opt_element(handler, "webMaster", self.webMaster) 328 | 329 | pubDate = self.pubDate 330 | if isinstance(pubDate, datetime.datetime): 331 | pubDate = DateElement("pubDate", pubDate) 332 | _opt_element(handler, "pubDate", pubDate) 333 | 334 | lastBuildDate = self.lastBuildDate 335 | if isinstance(lastBuildDate, datetime.datetime): 336 | lastBuildDate = DateElement("lastBuildDate", lastBuildDate) 337 | _opt_element(handler, "lastBuildDate", lastBuildDate) 338 | 339 | for category in self.categories: 340 | if isinstance(category, basestring): 341 | category = Category(category) 342 | category.publish(handler) 343 | 344 | _opt_element(handler, "generator", self.generator) 345 | _opt_element(handler, "docs", self.docs) 346 | 347 | if self.cloud is not None: 348 | self.cloud.publish(handler) 349 | 350 | ttl = self.ttl 351 | if isinstance(self.ttl, int): 352 | ttl = IntElement("ttl", ttl) 353 | _opt_element(handler, "tt", ttl) 354 | 355 | if self.image is not None: 356 | self.image.publish(handler) 357 | 358 | _opt_element(handler, "rating", self.rating) 359 | if self.textInput is not None: 360 | self.textInput.publish(handler) 361 | if self.skipHours is not None: 362 | self.skipHours.publish(handler) 363 | if self.skipDays is not None: 364 | self.skipDays.publish(handler) 365 | 366 | for item in self.items: 367 | item.publish(handler) 368 | 369 | handler.endElement("channel") 370 | handler.endElement("rss") 371 | 372 | def publish_extensions(self, handler): 373 | # Derived classes can hook into this to insert 374 | # output after the three required fields. 375 | pass 376 | 377 | 378 | 379 | class RSSItem(WriteXmlMixin): 380 | """Publish an RSS Item""" 381 | element_attrs = {} 382 | def __init__(self, 383 | title = None, # string 384 | link = None, # url as string 385 | description = None, # string 386 | author = None, # email address as string 387 | categories = None, # list of string or Category 388 | comments = None, # url as string 389 | enclosure = None, # an Enclosure 390 | guid = None, # a unique string 391 | pubDate = None, # a datetime 392 | source = None, # a Source 393 | ): 394 | 395 | if title is None and description is None: 396 | raise TypeError( 397 | "must define at least one of 'title' or 'description'") 398 | self.title = title 399 | self.link = link 400 | self.description = description 401 | self.author = author 402 | if categories is None: 403 | categories = [] 404 | self.categories = categories 405 | self.comments = comments 406 | self.enclosure = enclosure 407 | self.guid = guid 408 | self.pubDate = pubDate 409 | self.source = source 410 | # It sure does get tedious typing these names three times... 411 | 412 | def publish(self, handler): 413 | handler.startElement("item", self.element_attrs) 414 | _opt_element(handler, "title", self.title) 415 | _opt_element(handler, "link", self.link) 416 | self.publish_extensions(handler) 417 | _opt_element(handler, "description", self.description) 418 | _opt_element(handler, "author", self.author) 419 | 420 | for category in self.categories: 421 | if isinstance(category, basestring): 422 | category = Category(category) 423 | category.publish(handler) 424 | 425 | _opt_element(handler, "comments", self.comments) 426 | if self.enclosure is not None: 427 | self.enclosure.publish(handler) 428 | _opt_element(handler, "guid", self.guid) 429 | 430 | pubDate = self.pubDate 431 | if isinstance(pubDate, datetime.datetime): 432 | pubDate = DateElement("pubDate", pubDate) 433 | _opt_element(handler, "pubDate", pubDate) 434 | 435 | if self.source is not None: 436 | self.source.publish(handler) 437 | 438 | handler.endElement("item") 439 | 440 | def publish_extensions(self, handler): 441 | # Derived classes can hook into this to insert 442 | # output after the title and link elements 443 | pass 444 | -------------------------------------------------------------------------------- /doc/styles/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | IMPORTANT: If you're editing this file in the output directory of one of 3 | your projects, your changes will be overwritten the next time you run 4 | Natural Docs. Instead, copy this file to your project directory, make your 5 | changes, and you can use it with -s. Even better would be to make a CSS 6 | file in your project directory with only your changes, which you can then 7 | use with -s [original style] [your changes]. 8 | 9 | On the other hand, if you're editing this file in the Natural Docs styles 10 | directory, the changes will automatically be applied to all your projects 11 | that use this style the next time Natural Docs is run on them. 12 | 13 | This file is part of Natural Docs, which is Copyright (C) 2003-2005 Greg Valure 14 | Natural Docs is licensed under the GPL 15 | */ 16 | 17 | body { 18 | font-family: Verdana, Arial, sans-serif; 19 | color: #000000; 20 | margin: 0px; padding: 0px } 21 | 22 | body.UnframedPage { 23 | background-color: #E8E8E8 } 24 | 25 | 26 | a:link, 27 | a:visited { color: #900000; text-decoration: none } 28 | a:hover { color: #900000; text-decoration: underline } 29 | a:active { color: #FF0000; text-decoration: underline } 30 | 31 | td { 32 | vertical-align: top } 33 | 34 | /* 35 | Comment out this line to use web-style paragraphs (blank line between 36 | paragraphs, no indent) instead of print-style paragraphs (no blank line, 37 | indented.) 38 | */ 39 | p { 40 | text-indent: 5ex; margin: 0 } 41 | 42 | 43 | /* Can't use something like display: none or it won't break. */ 44 | .HB { 45 | font-size: 1px; 46 | visibility: hidden; 47 | } 48 | 49 | /* Blockquotes are used as containers for things that may need to scroll. */ 50 | blockquote { 51 | padding: 0; 52 | margin: 0; 53 | overflow: auto; 54 | } 55 | /* This will be fixed in JavaScript. We just need a default if it's turned off. */ 56 | .IE blockquote { 57 | width: 400px; } 58 | 59 | .Gecko blockquote { 60 | padding-bottom: .5em; 61 | } 62 | 63 | /* Turn off scrolling when printing. */ 64 | @media print { 65 | blockquote { 66 | overflow: visible; 67 | } 68 | .IE blockquote { 69 | width: auto; 70 | } 71 | } 72 | 73 | 74 | 75 | body.FramedMenuPage, 76 | .MenuSection { 77 | font-size: 9pt; 78 | background-color: #E8E8E8; 79 | padding: 10px 0 0 0 } 80 | 81 | .MenuSection { 82 | width: 27ex } 83 | 84 | 85 | .MTitle { 86 | font-size: 16pt; font-weight: bold; font-variant: small-caps; 87 | text-align: center; 88 | padding: 5px 10px 15px 10px; 89 | border-bottom: 1px dotted #000000; 90 | margin-bottom: 15px } 91 | 92 | .MSubTitle { 93 | font-size: 9pt; font-weight: normal; font-variant: normal; 94 | margin-top: 1ex; margin-bottom: 5px } 95 | 96 | 97 | .MEntry a:link, 98 | .MEntry a:hover, 99 | .MEntry a:visited { color: #606060; margin-right: 0 } 100 | .MEntry a:active { color: #A00000; margin-right: 0 } 101 | 102 | 103 | .MGroup { 104 | font-variant: small-caps; font-weight: bold; 105 | margin: 1em 0 1em 10px } 106 | 107 | /* Konqueror just can't do margins. */ 108 | .KHTML .MGroup { 109 | margin-bottom: 0; padding-bottom: 1em } 110 | 111 | .MGroupContent { 112 | font-variant: normal; font-weight: normal } 113 | 114 | .MGroup a:link, 115 | .MGroup a:hover, 116 | .MGroup a:visited { color: #545454; margin-right: 10px } 117 | .MGroup a:active { color: #A00000; margin-right: 10px } 118 | 119 | 120 | .MFile, 121 | .MText, 122 | .MLink, 123 | .MIndex { 124 | padding: 1px 17px 2px 10px; 125 | margin: .25em 0 .25em 0 } 126 | 127 | .MText { 128 | font-size: 8pt; font-style: italic } 129 | 130 | .MLink { 131 | font-style: italic } 132 | 133 | #MSelected { 134 | color: #000000; background-color: #FFFFFF; 135 | /* Replace padding with border. */ 136 | padding: 0 10px 0 10px; 137 | border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000; 138 | margin-right: 5px } 139 | 140 | /* Close off the left side when its in a group. */ 141 | .MGroup #MSelected { 142 | padding-left: 9px; border-left-width: 1px } 143 | 144 | /* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */ 145 | .Gecko #MSelected { 146 | -moz-border-radius-topright: 10px; 147 | -moz-border-radius-bottomright: 10px } 148 | .Gecko .MGroup #MSelected { 149 | -moz-border-radius-topleft: 10px; 150 | -moz-border-radius-bottomleft: 10px } 151 | 152 | 153 | 154 | 155 | body.FramedContentPage, 156 | .ContentSection { 157 | background-color: #FFFFFF; 158 | padding-bottom: 15px } 159 | 160 | .ContentSection { 161 | border-width: 0 0 1px 1px; border-style: solid; border-color: #000000 } 162 | 163 | 164 | .CTopic { 165 | font-size: 10pt; 166 | /* This should be a margin but Konq 3.1.1 sucks. */ 167 | padding-bottom: 3em } 168 | 169 | 170 | .CTitle { 171 | font-size: 12pt; font-weight: bold; 172 | border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0; 173 | margin: 0 15px .5em 15px } 174 | 175 | .CGroup .CTitle { 176 | font-size: 16pt; font-variant: small-caps; 177 | padding-left: 15px; padding-right: 15px; 178 | border-width: 0 0 2px 0; border-color: #000000; 179 | margin-left: 0; margin-right: 0 } 180 | 181 | .CClass .CTitle, 182 | .CInterface .CTitle, 183 | .CDatabase .CTitle, 184 | .CDatabaseTable .CTitle, 185 | .CSection .CTitle { 186 | font-size: 18pt; 187 | color: #FFFFFF; background-color: #A0A0A0; 188 | padding: 10px 15px 10px 15px; 189 | border-width: 2px 0; border-color: #000000; 190 | margin-left: 0; margin-right: 0 } 191 | 192 | #MainTopic .CTitle { 193 | font-size: 20pt; 194 | color: #FFFFFF; background-color: #7070C0; 195 | padding: 10px 15px 10px 15px; 196 | border-width: 0 0 3px 0; border-color: #000000; 197 | margin-left: 0; margin-right: 0 } 198 | 199 | .CBody { 200 | margin-left: 15px; margin-right: 15px } 201 | 202 | 203 | .CToolTip { 204 | position: absolute; visibility: hidden; 205 | left: 0; top: 0; max-width: 50%; 206 | background-color: #FFFFE0; 207 | padding: 5px; 208 | border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000; 209 | font-size: 8pt } 210 | 211 | /* Opera 6 gives it a huge height otherwise. */ 212 | .Opera6 .CTooltip, .Opera5 .CTooltip { 213 | max-width: 100% } 214 | 215 | /* Scrollbars would be useless. */ 216 | .CToolTip blockquote { 217 | overflow: hidden; 218 | } 219 | 220 | .CHeading { 221 | font-weight: bold; font-size: 10pt; 222 | margin-top: 1.5em; margin-bottom: .5em } 223 | 224 | .CCode { 225 | font: 10pt "Courier New", Courier, monospace; 226 | } 227 | 228 | .CBulletList { 229 | /* I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever. 230 | Reapply it here as padding. */ 231 | padding-left: 15px; padding-right: 15px; 232 | margin: .5em 5ex .5em 5ex; 233 | } 234 | 235 | .CDescriptionList { 236 | margin: .5em 5ex 0 5ex } 237 | 238 | /* IE 4 and Konqueror always makes it too long. */ 239 | .IE4 .CDescriptionList, 240 | .KHTML .CDescriptionList { 241 | width: 85% } 242 | 243 | .CDLEntry { 244 | font: 10pt "Courier New", Courier, monospace; color: #808080; 245 | padding-bottom: .25em; 246 | white-space: nowrap } 247 | 248 | .CDLDescription { 249 | font-size: 10pt; /* For browsers that don't inherit correctly, like Opera 5. */ 250 | padding-bottom: .5em; padding-left: 5ex } 251 | 252 | 253 | 254 | 255 | .Prototype { 256 | font: 10pt "Courier New", Courier, monospace; 257 | padding: 5px 3ex; 258 | border-width: 1px; border-style: solid; 259 | margin: 0 5ex 1.5em 5ex; 260 | } 261 | 262 | .Prototype td { 263 | font-size: 10pt; 264 | } 265 | 266 | .PDefaultValue, 267 | .PDefaultValuePrefix, 268 | .PTypePrefix { 269 | color: #8F8F8F; 270 | } 271 | .PTypePrefix { 272 | text-align: right; 273 | } 274 | .PAfterParameters { 275 | vertical-align: bottom; 276 | } 277 | 278 | .IE .Prototype table { 279 | padding: 0; 280 | } 281 | 282 | .CFunction .Prototype { 283 | background-color: #F4F4F4; border-color: #D0D0D0 } 284 | .CProperty .Prototype { 285 | background-color: #F4F4FF; border-color: #C0C0E8 } 286 | .CVariable .Prototype { 287 | background-color: #FFFFF0; border-color: #E0E0A0 } 288 | 289 | .CDatabaseIndex .Prototype, 290 | .CConstant .Prototype { 291 | background-color: #D0D0D0; border-color: #000000 } 292 | .CType .Prototype { 293 | background-color: #FFF8F8; border-color: #E8C8C8 } 294 | .CDatabaseTrigger .Prototype, 295 | .CEvent .Prototype, 296 | .CDelegate .Prototype { 297 | background-color: #F0FCF0; border-color: #B8E4B8 } 298 | 299 | .CToolTip .Prototype { 300 | margin: 0 0 .5em 0; 301 | white-space: nowrap; 302 | } 303 | 304 | 305 | 306 | 307 | 308 | .Summary { 309 | margin: 1.5em 5ex 0 5ex } 310 | 311 | .STitle { 312 | font-size: 12pt; font-weight: bold; 313 | margin-bottom: .5em } 314 | 315 | 316 | .SBorder { 317 | background-color: #FFFFF0; 318 | padding: 15px; 319 | border: 1px solid #C0C060 } 320 | 321 | /* Let's observe the evolution of IE's brokeness, shall we? 322 | IE 4 always makes them too long, there's no way around it. */ 323 | .IE4 .SBorder { 324 | width: 85% } 325 | /* IE 5 will make them too long unless you set the width to 100%. Isn't this implied for a div? */ 326 | .IE5 .SBorder { 327 | width: 100% } 328 | /* IE 6 behaves like 5 when it's in a frame, but without frames it will be correct without a width or slightly too long 329 | (but not enough to scroll) with a width. This arbitrary weirdness simply astounds me. */ 330 | body.FramedContentPage .IE6 .SBorder { 331 | width: 100% } 332 | 333 | /* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */ 334 | .Gecko .SBorder { 335 | -moz-border-radius: 20px } 336 | 337 | 338 | .STable { 339 | font-size: 9pt; width: 100% } 340 | 341 | .SEntrySize { 342 | width: 30% } 343 | .SDescriptionSize { 344 | width: 70% } 345 | 346 | 347 | .SMarked { 348 | background-color: #F8F8D8 } 349 | 350 | 351 | .SEntry .SIndent1 { 352 | margin-left: 1.5ex } 353 | .SEntry .SIndent2 { 354 | margin-left: 3ex } 355 | .SEntry .SIndent3 { 356 | margin-left: 4.5ex } 357 | .SEntry .SIndent4 { 358 | margin-left: 6ex } 359 | .SEntry .SIndent5 { 360 | margin-left: 7.5ex } 361 | 362 | .SDescription { 363 | padding-left: 3ex } 364 | 365 | .SDescription a { color: #800000} 366 | .SDescription a:active { color: #A00000 } 367 | 368 | 369 | .SGroup { 370 | margin-top: .5em; margin-bottom: .25em } 371 | 372 | .SGroup .SEntry { 373 | font-weight: bold; font-variant: small-caps } 374 | 375 | .SGroup .SEntry a { color: #800000 } 376 | .SGroup .SEntry a:active { color: #F00000 } 377 | 378 | 379 | .SMain .SEntry, 380 | .SClass .SEntry, 381 | .SDatabase .SEntry, 382 | .SDatabaseTable .SEntry, 383 | .SSection .SEntry { 384 | font-weight: bold; font-size: 10pt; 385 | margin-bottom: .25em } 386 | 387 | .SClass, 388 | .SDatabase, 389 | .SDatabaseTable, 390 | .SSection { 391 | margin-top: 1em } 392 | 393 | .SMain .SEntry a, 394 | .SClass .SEntry a, 395 | .SDatabase .SEntry a, 396 | .SDatabaseTable .SEntry a, 397 | .SSection .SEntry a { color: #000000 } 398 | 399 | .SMain .SEntry a:active, 400 | .SClass .SEntry a:active, 401 | .SDatabase .SEntry a:active, 402 | .SDatabaseTable .SEntry a:active, 403 | .SSection .SEntry a:active { color: #A00000 } 404 | 405 | 406 | 407 | 408 | 409 | .ClassHierarchy { 410 | margin: 0 15px 1em 15px } 411 | 412 | .CHEntry { 413 | border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0; 414 | margin-bottom: 3px; 415 | padding: 2px 2ex; 416 | font-size: 10pt; 417 | background-color: #F4F4F4; color: #606060; 418 | } 419 | 420 | .Gecko .CHEntry { 421 | -moz-border-radius: 4px; 422 | } 423 | 424 | .CHCurrent .CHEntry { 425 | font-weight: bold; 426 | border-color: #000000; 427 | color: #000000; 428 | } 429 | 430 | .CHChildNote .CHEntry { 431 | font-style: italic; 432 | font-size: 8pt; 433 | } 434 | 435 | .CHIndent { 436 | margin-left: 3ex; 437 | } 438 | 439 | .CHEntry a:link, 440 | .CHEntry a:visited, 441 | .CHEntry a:hover { 442 | color: #606060; 443 | } 444 | .CHEntry a:active { 445 | color: #800000; 446 | } 447 | 448 | 449 | 450 | 451 | 452 | body.FramedIndexPage, 453 | .IndexSection { 454 | background-color: #FFFFFF; 455 | font-size: 10pt; 456 | padding: 15px } 457 | 458 | .IndexSection { 459 | border-width: 0 0 1px 1px; border-style: solid; border-color: #000000 } 460 | 461 | .IPageTitle { 462 | font-size: 20pt; font-weight: bold; 463 | color: #FFFFFF; background-color: #7070C0; 464 | padding: 10px 15px 10px 15px; 465 | border-width: 0 0 3px 0; border-color: #000000; border-style: solid; 466 | margin: -15px -15px 0 -15px } 467 | 468 | .INavigationBar { 469 | text-align: center; 470 | background-color: #FFFFF0; 471 | padding: 5px; 472 | border-bottom: solid 1px black; 473 | margin: 0 -15px 15px -15px } 474 | 475 | .INavigationBar a { 476 | font-weight: bold } 477 | 478 | .IHeading { 479 | font-size: 16pt; font-weight: bold; 480 | padding: 2.5em 0 .5em 0; 481 | text-align: center; 482 | width: 3.5ex; 483 | } 484 | #IFirstHeading { 485 | padding-top: 0; 486 | } 487 | 488 | .IEntry { 489 | padding-left: 1ex; } 490 | 491 | .ISubIndex { 492 | padding-left: 3ex; padding-bottom: .5em } 493 | 494 | /* While it may cause some entries to look like links when they aren't, I found it's much easier to read the 495 | index if everything's the same color. */ 496 | .ISymbol { 497 | font-weight: bold; color: #900000 } 498 | 499 | .ISymbolPrefix { 500 | text-align: right; 501 | color: #C47C7C; 502 | background-color: #F8F8F8; 503 | border-right: 3px solid #E0E0E0; 504 | border-left: 1px solid #E0E0E0; 505 | padding: 0 1px 0 2px; 506 | } 507 | #IFirstSymbolPrefix { 508 | border-top: 1px solid #E0E0E0; 509 | } 510 | #ILastSymbolPrefix { 511 | border-bottom: 1px solid #E0E0E0; 512 | } 513 | #IOnlySymbolPrefix { 514 | border-top: 1px solid #E0E0E0; 515 | border-bottom: 1px solid #E0E0E0; 516 | } 517 | 518 | a.IParent, 519 | a.IFile { 520 | display: block; 521 | } 522 | 523 | 524 | 525 | 526 | .Footer { 527 | font-size: 8pt; color: #909090 } 528 | 529 | body.UnframedPage .Footer { 530 | text-align: right; 531 | margin: 2px } 532 | 533 | body.FramedMenuPage .Footer { 534 | text-align: center; 535 | margin: 5em 10px 0 10px} 536 | 537 | .Footer a:link, 538 | .Footer a:hover, 539 | .Footer a:visited { color: #909090 } 540 | .Footer a:active { color: #A00000 } 541 | -------------------------------------------------------------------------------- /doc/files/history-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | History 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 38 | 39 |

History

A class used to manage the state of the story -- displaying new passages and rewinding to the past.

Summary
A class used to manage the state of the story -- displaying new passages and rewinding to the past.
An array representing the state of the story.
Initializes a History object.
This first attempts to restore the state of the story via the restore method.
This removes a passage from display onscreen.
Displays a passage on the page.
Restarts the story from the beginning.
Returns a hash to append to the page’s URL that will be later read by the restore method.
Attempts to restore the state of the story as saved by save.
Rewinds the state of the story to a particular Passage.
14 | 15 |

Properties

16 | 17 |

History

An array representing the state of the story. history[0] is the current state, history[1] is the state just before the present, and so on.  Each entry in the history is an object with two properties: passage, which corresponds to the Passage just displayed, and variables.  Variables is in itself an object.  Each property is a variable set by the story via the <<set>> macro.

18 | 19 |

Functions

20 | 21 |

History

function History()

Initializes a History object.

Parameters

none

22 | 23 |

init

History.prototype.init = function()

This first attempts to restore the state of the story via the restore method.  If that fails, it then either displays the passages linked in the StartPassages passage, or gives up and tries to display a passage named Start.

Parameters

none

Returns

nothing

24 | 25 |

close

History.prototype.close = function (passage)

This removes a passage from display onscreen.  This does not animate its disappearance.

Parameters

passagethe Passage to remove

Returns

nothing

26 | 27 |

display

History.prototype.display = function (title,
link,
render)

Displays a passage on the page.  If a passage has previously been displayed, the browser window is scrolled so it is in view.

Parameters

titlethe title of the passage to display.
linkthe DOM element corresponding to the link that was clicked to view the passage.  The new passage is displayed immediately below the passage enclosed by the link.  This parameter is optional.  If it is omitted, the passage is displayed at the bottom of the page.
rendermay be either “quietly” or “offscreen”.  If a “quietly” value is passed, the passage’s appearance is not animated.  “offscreen” asks that the passage be rendered, but not displayed at all.  This parameter is optional.  If it is omitted, then the passage’s appearance is animated.

Returns

The DOM element containing the passage on the page.

28 | 29 |

restart

History.prototype.restart = function()

Restarts the story from the beginning.  This actually forces the browser to refresh the page.

Parameters

none

Returns

none

30 | 31 |

save

History.prototype.save = function (passage)

Returns a hash to append to the page’s URL that will be later read by the restore method.  How this is generated is not guaranteed to remain constant in future releases -- but it is guaranteed to be understood by restore.

Parameters

passagea Passage whose point in the history to save.  This parameter is optional -- if omitted, then the entire story’s history is saved.

Returns

A hash to append to the page’s URL.

32 | 33 |

restore

History.prototype.restore = function ()

Attempts to restore the state of the story as saved by save.

Parameters

none

Returns

Whether this method actually restored anything.

34 | 35 |

rewindTo

History.prototype.rewindTo = function (passage)

Rewinds the state of the story to a particular Passage.

Parameters

passagea Passage to rewind to.

Returns

nothing

36 | 37 |
40 | 41 |
function History()
Initializes a History object.
History.prototype.init = function()
This first attempts to restore the state of the story via the restore method.
History.prototype.restore = function ()
Attempts to restore the state of the story as saved by save.
History.prototype.close = function (passage)
This removes a passage from display onscreen.
History.prototype.display = function (title,
link,
render)
Displays a passage on the page.
History.prototype.restart = function()
Restarts the story from the beginning.
History.prototype.save = function (passage)
Returns a hash to append to the page’s URL that will be later read by the restore method.
History.prototype.rewindTo = function (passage)
Rewinds the state of the story to a particular Passage.
This class represents an individual passage.
42 | 43 | -------------------------------------------------------------------------------- /doc/files/functions-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | General-purpose functions 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 42 | 43 |

General-purpose functions

Summary
Returns the DOM element with the id passed.
Performs a shallow copy of an object.
A shortcut function for creating a DOM element.
Places text in a DOM element.
Removes all child elements from a DOM element.
Wikifies a passage into a DOM element.
Adds CSS styles to the document.
Displays an error message on the page.
Eases a decimal number from 0 to 1.
Parses a list of macro parameters.
Parses a list of bracketed links -- e.g.
Removes whitespace from the beginning and end of a string.
14 | 15 |

Functions

16 | 17 |

$

function $ (id)

Returns the DOM element with the id passed.

Parameters

idthe id to look up

Returns

A DOM element, or null if none with the id exist.

18 | 19 |

clone

function clone (original)

Performs a shallow copy of an object.

Parameters

originalthe object to copy

Returns

The copied object.

20 | 21 |

insertElement

function insertElement (place,
type,
id,
className,
text)

A shortcut function for creating a DOM element.  All parameters are optional.

Parameters

placethe parent element
typethe type of element to create -- e.g.  ‘div’ or ‘span’
idthe id to give the element
classNamethe CSS class to give the element
texttext to place inside the element.  This is not interpreted as HTML.

Returns

The newly created element.

22 | 23 |

insertText

function insertText (place,
text)

Places text in a DOM element.

Parameters

placethe element to add text to
texttext to insert

Returns

The newly created DOM text node.

24 | 25 |

removeChildren

function removeChildren (el)

Removes all child elements from a DOM element.

Parameters

elthe element to strip

Returns

nothing

26 | 27 |

setPageElement

function setPageElement (id,
title,
defaultText)

Wikifies a passage into a DOM element.

Parameters

idthe id of the element
titlethe title of the passage
defaultTexttext to use if the passage doesn’t exist

Returns

a DOM element, or null if none with the id exist.

See also

Wikifier

28 | 29 |

addStyle

function addStyle (source)

Adds CSS styles to the document.

Parameters

sourcethe CSS styles to add

Returns

nothing

30 | 31 |

throwError

function throwError (place,
message)

Displays an error message on the page.

Parameters

placethe place to show the error message
messagethe message to display

Returns

nothing

32 | 33 |

Math. easeInOut

Math.easeInOut = function (i)

Eases a decimal number from 0 to 1.

Parameters

ithe number to ease.  Must be between 0 and 1.

Returns

The eased value.

34 | 35 |

String. readMacroParams

Parses a list of macro parameters.

Parameters

none

Returns

An array of parameters.

36 | 37 |

String. readBracketedList

Parses a list of bracketed links -- e.g.  [[my link]].

Parameters

none

Returns

an array of link titles.

38 | 39 |

String.trim

Removes whitespace from the beginning and end of a string.

Parameters

none

Returns

The trimmed string.

40 | 41 |
44 | 45 |
function $ (id)
Returns the DOM element with the id passed.
function clone (original)
Performs a shallow copy of an object.
function insertElement (place,
type,
id,
className,
text)
A shortcut function for creating a DOM element.
function insertText (place,
text)
Places text in a DOM element.
function removeChildren (el)
Removes all child elements from a DOM element.
function setPageElement (id,
title,
defaultText)
Wikifies a passage into a DOM element.
function addStyle (source)
Adds CSS styles to the document.
function throwError (place,
message)
Displays an error message on the page.
Math.easeInOut = function (i)
Eases a decimal number from 0 to 1.
Used to display text on the page.
46 | 47 | -------------------------------------------------------------------------------- /targets/tw2/tw22/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | TiddlyWiki - a reusable non-linear personal web notebook 46 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 66 | 69 |
70 |
71 |
72 | 73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
Background: #fff
 82 | Foreground: #000
 83 | PrimaryPale: #8cf
 84 | PrimaryLight: #18f
 85 | PrimaryMid: #04b
 86 | PrimaryDark: #014
 87 | SecondaryPale: #ffc
 88 | SecondaryLight: #fe8
 89 | SecondaryMid: #db4
 90 | SecondaryDark: #841
 91 | TertiaryPale: #eee
 92 | TertiaryLight: #ccc
 93 | TertiaryMid: #999
 94 | TertiaryDark: #666
 95 | Error: #f88
96 |
97 |
98 |
/*{{{*/
 99 | body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
100 | 
101 | a {color:[[ColorPalette::PrimaryMid]];}
102 | a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
103 | a img {border:0;}
104 | 
105 | h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
106 | h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
107 | h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}
108 | 
109 | .button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
110 | .button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
111 | .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}
112 | 
113 | .header {background:[[ColorPalette::PrimaryMid]];}
114 | .headerShadow {color:[[ColorPalette::Foreground]];}
115 | .headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
116 | .headerForeground {color:[[ColorPalette::Background]];}
117 | .headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}
118 | 
119 | .tabSelected{color:[[ColorPalette::PrimaryDark]];
120 | 	background:[[ColorPalette::TertiaryPale]];
121 | 	border-left:1px solid [[ColorPalette::TertiaryLight]];
122 | 	border-top:1px solid [[ColorPalette::TertiaryLight]];
123 | 	border-right:1px solid [[ColorPalette::TertiaryLight]];
124 | }
125 | .tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
126 | .tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
127 | .tabContents .button {border:0;}
128 | 
129 | #sidebar {}
130 | #sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
131 | #sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
132 | #sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
133 | #sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
134 | #sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
135 | 
136 | .wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
137 | .wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
138 | .wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
139 | .wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
140 | 	border:1px solid [[ColorPalette::PrimaryMid]];}
141 | .wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
142 | .wizardFooter {background:[[ColorPalette::PrimaryPale]];}
143 | .wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
144 | .wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
145 | 	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
146 | .wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
147 | .wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
148 | 	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
149 | 
150 | #messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
151 | #messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
152 | 
153 | .popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
154 | 
155 | .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]];}
156 | .popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
157 | .popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
158 | .popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
159 | .popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
160 | .popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
161 | .popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
162 | .listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
163 | 
164 | .tiddler .defaultCommand {font-weight:bold;}
165 | 
166 | .shadow .title {color:[[ColorPalette::TertiaryDark]];}
167 | 
168 | .title {color:[[ColorPalette::SecondaryDark]];}
169 | .subtitle {color:[[ColorPalette::TertiaryDark]];}
170 | 
171 | .toolbar {color:[[ColorPalette::PrimaryMid]];}
172 | .toolbar a {color:[[ColorPalette::TertiaryLight]];}
173 | .selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
174 | .selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
175 | 
176 | .tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
177 | .selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
178 | .tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
179 | .tagging .button, .tagged .button {border:none;}
180 | 
181 | .footer {color:[[ColorPalette::TertiaryLight]];}
182 | .selected .footer {color:[[ColorPalette::TertiaryMid]];}
183 | 
184 | .sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
185 | .sparktick {background:[[ColorPalette::PrimaryDark]];}
186 | 
187 | .error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
188 | .warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
189 | .lowlight {background:[[ColorPalette::TertiaryLight]];}
190 | 
191 | .zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}
192 | 
193 | .imageLink, #displayArea .imageLink {background:transparent;}
194 | 
195 | .annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}
196 | 
197 | .viewer .listTitle {list-style-type:none; margin-left:-2em;}
198 | .viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
199 | .viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}
200 | 
201 | .viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
202 | .viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
203 | .viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}
204 | 
205 | .viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
206 | .viewer code {color:[[ColorPalette::SecondaryDark]];}
207 | .viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}
208 | 
209 | .highlight, .marked {background:[[ColorPalette::SecondaryLight]];}
210 | 
211 | .editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
212 | .editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
213 | .editorFooter {color:[[ColorPalette::TertiaryMid]];}
214 | 
215 | #backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
216 | #backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
217 | #backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
218 | #backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
219 | #backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
220 | #backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
221 | #backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
222 | .backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
223 | .backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
224 | #backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
225 | /*}}}*/
226 |
227 |
228 | 229 |
/*{{{*/
230 | * html .tiddler {height:1%;}
231 | 
232 | body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}
233 | 
234 | h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
235 | h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
236 | h4,h5,h6 {margin-top:1em;}
237 | h1 {font-size:1.35em;}
238 | h2 {font-size:1.25em;}
239 | h3 {font-size:1.1em;}
240 | h4 {font-size:1em;}
241 | h5 {font-size:.9em;}
242 | 
243 | hr {height:1px;}
244 | 
245 | a {text-decoration:none;}
246 | 
247 | dt {font-weight:bold;}
248 | 
249 | ol {list-style-type:decimal;}
250 | ol ol {list-style-type:lower-alpha;}
251 | ol ol ol {list-style-type:lower-roman;}
252 | ol ol ol ol {list-style-type:decimal;}
253 | ol ol ol ol ol {list-style-type:lower-alpha;}
254 | ol ol ol ol ol ol {list-style-type:lower-roman;}
255 | ol ol ol ol ol ol ol {list-style-type:decimal;}
256 | 
257 | .txtOptionInput {width:11em;}
258 | 
259 | #contentWrapper .chkOptionInput {border:0;}
260 | 
261 | .externalLink {text-decoration:underline;}
262 | 
263 | .indent {margin-left:3em;}
264 | .outdent {margin-left:3em; text-indent:-3em;}
265 | code.escaped {white-space:nowrap;}
266 | 
267 | .tiddlyLinkExisting {font-weight:bold;}
268 | .tiddlyLinkNonExisting {font-style:italic;}
269 | 
270 | /* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
271 | a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
272 | 
273 | #mainMenu .tiddlyLinkExisting,
274 | 	#mainMenu .tiddlyLinkNonExisting,
275 | 	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
276 | #sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
277 | 
278 | .header {position:relative;}
279 | .header a:hover {background:transparent;}
280 | .headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
281 | .headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}
282 | 
283 | .siteTitle {font-size:3em;}
284 | .siteSubtitle {font-size:1.2em;}
285 | 
286 | #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;}
287 | 
288 | #sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
289 | #sidebarOptions {padding-top:0.3em;}
290 | #sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
291 | #sidebarOptions input {margin:0.4em 0.5em;}
292 | #sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
293 | #sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
294 | #sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
295 | #sidebarTabs .tabContents {width:15em; overflow:hidden;}
296 | 
297 | .wizard {padding:0.1em 1em 0em 2em;}
298 | .wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
299 | .wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
300 | .wizardStep {padding:1em 1em 1em 1em;}
301 | .wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
302 | .wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
303 | .wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
304 | .wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}
305 | 
306 | #messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
307 | .messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
308 | #messageArea a {text-decoration:underline;}
309 | 
310 | .tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
311 | .popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}
312 | 
313 | .popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
314 | .popup .popupMessage {padding:0.4em;}
315 | .popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
316 | .popup li.disabled {padding:0.4em;}
317 | .popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
318 | .listBreak {font-size:1px; line-height:1px;}
319 | .listBreak div {margin:2px 0;}
320 | 
321 | .tabset {padding:1em 0em 0em 0.5em;}
322 | .tab {margin:0em 0em 0em 0.25em; padding:2px;}
323 | .tabContents {padding:0.5em;}
324 | .tabContents ul, .tabContents ol {margin:0; padding:0;}
325 | .txtMainTab .tabContents li {list-style:none;}
326 | .tabContents li.listLink { margin-left:.75em;}
327 | 
328 | #contentWrapper {display:block;}
329 | #splashScreen {display:none;}
330 | 
331 | #displayArea {margin:1em 17em 0em 14em;}
332 | 
333 | .toolbar {text-align:right; font-size:.9em;}
334 | 
335 | .tiddler {padding:1em 1em 0em 1em;}
336 | 
337 | .missing .viewer,.missing .title {font-style:italic;}
338 | 
339 | .title {font-size:1.6em; font-weight:bold;}
340 | 
341 | .missing .subtitle {display:none;}
342 | .subtitle {font-size:1.1em;}
343 | 
344 | .tiddler .button {padding:0.2em 0.4em;}
345 | 
346 | .tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
347 | .isTag .tagging {display:block;}
348 | .tagged {margin:0.5em; float:right;}
349 | .tagging, .tagged {font-size:0.9em; padding:0.25em;}
350 | .tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
351 | .tagClear {clear:both;}
352 | 
353 | .footer {font-size:.9em;}
354 | .footer li {display:inline;}
355 | 
356 | .annotation {padding:0.5em; margin:0.5em;}
357 | 
358 | * html .viewer pre {width:99%; padding:0 0 1em 0;}
359 | .viewer {line-height:1.4em; padding-top:0.5em;}
360 | .viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
361 | .viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
362 | .viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
363 | 
364 | .viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
365 | .viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
366 | table.listView {font-size:0.85em; margin:0.8em 1.0em;}
367 | table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}
368 | 
369 | .viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
370 | .viewer code {font-size:1.2em; line-height:1.4em;}
371 | 
372 | .editor {font-size:1.1em;}
373 | .editor input, .editor textarea {display:block; width:100%; font:inherit;}
374 | .editorFooter {padding:0.25em 0em; font-size:.9em;}
375 | .editorFooter .button {padding-top:0px; padding-bottom:0px;}
376 | 
377 | .fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}
378 | 
379 | .sparkline {line-height:1em;}
380 | .sparktick {outline:0;}
381 | 
382 | .zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
383 | .zoomer div {padding:1em;}
384 | 
385 | * html #backstage {width:99%;}
386 | * html #backstageArea {width:99%;}
387 | #backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
388 | #backstageToolbar {position:relative;}
389 | #backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
390 | #backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
391 | #backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
392 | #backstage {position:relative; width:100%; z-index:50;}
393 | #backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
394 | .backstagePanelFooter {padding-top:0.2em; float:right;}
395 | .backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
396 | #backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
397 | 
398 | .whenBackstage {display:none;}
399 | .backstageVisible .whenBackstage {display:block;}
400 | /*}}}*/
401 |
402 |
403 |
/***
404 | StyleSheet for use when a translation requires any css style changes.
405 | This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which use a logographic writing system and need larger font sizes.
406 | ***/
407 | 
408 | /*{{{*/
409 | body {font-size:0.8em;}
410 | 
411 | #sidebarOptions {font-size:1.05em;}
412 | #sidebarOptions a {font-style:normal;}
413 | #sidebarOptions .sliderPanel {font-size:0.95em;}
414 | 
415 | .subtitle {font-size:0.8em;}
416 | 
417 | .viewer table.listView {font-size:0.95em;}
418 | 
419 | .htmlarea .toolbarHA table {border:1px solid ButtonFace; margin:0em 0em;}
420 | /*}}}*/
421 |
422 |
423 |
/*{{{*/
424 | @media print {
425 | #mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
426 | #displayArea {margin: 1em 1em 0em 1em;}
427 | /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
428 | noscript {display:none;}
429 | }
430 | /*}}}*/
431 |
432 |
433 |
<!--{{{-->
434 | <div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
435 | <div class='headerShadow'>
436 | 
437 | <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
438 | <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
439 | </div>
440 | <div class='headerForeground'>
441 | <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
442 | <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
443 | </div>
444 | 
445 | </div>
446 | <div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
447 | <div id='sidebar'>
448 | <div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
449 | <div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
450 | </div>
451 | <div id='displayArea'>
452 | 
453 | <div id='messageArea'></div>
454 | <div id='tiddlerDisplay'></div>
455 | </div>
456 | <!--}}}-->
457 |
458 |
459 |
<!--{{{-->
460 | <div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
461 | 
462 | <div class='title' macro='view title'></div>
463 | <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>
464 | 
465 | <div class='tagging' macro='tagging'></div>
466 | <div class='tagged' macro='tags'></div>
467 | <div class='viewer' macro='view text wikified'></div>
468 | <div class='tagClear'></div>
469 | <!--}}}-->
470 |
471 |
472 |
<!--{{{-->
473 | 
474 | <div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
475 | <div class='title' macro='view title'></div>
476 | <div class='editor' macro='edit title'></div>
477 | <div macro='annotations'></div>
478 | <div class='editor' macro='edit text'></div>
479 | <div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
480 | 
481 | <!--}}}-->
482 |
483 |
484 |
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
485 | * SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
486 | * MainMenu: The menu (usually on the left)
487 | * DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
488 | You'll also need to enter your username for signing your edits: <<option txtUserName>>
489 |
490 |
491 |
These InterfaceOptions for customising TiddlyWiki are saved in your browser
492 | 
493 | Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)
494 | 
495 | <<option txtUserName>>
496 | <<option chkSaveBackups>> SaveBackups
497 | 
498 | <<option chkAutoSave>> AutoSave
499 | <<option chkRegExpSearch>> RegExpSearch
500 | <<option chkCaseSensitiveSearch>> CaseSensitiveSearch
501 | <<option chkAnimate>> EnableAnimations
502 | 
503 | ----
504 | Also see AdvancedOptions
505 |
506 |
507 | 508 |
509 | -------------------------------------------------------------------------------- /doc/index/Functions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Function Index 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Function Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
$#!
 $
A
 addStyle
C
 clone
 close, History
 createExternalLink, Wikifier
 createInternalLink, Wikifier
D
 display, History
E
 easeInOut, Math
F
 fade
 fullArgs, Wikifier
G
 get, Tale
H
 has, Tale
I
 init, History
 insertElement
 insertText
L
 lookup, Tale
M
 main
P
 Passage, Passage
R
 readBracketedList, String
 readMacroParams, String
 removeChildren
 render, Passage
 reset
 restart, History
 restore, History
 rewindTo, History
S
 save, History
 scrollWindowTo
 setPageElement
T
 Tale, Tale
 throwError
 trim, String
U
 unescapeLineBreaks, Passage
W
 Wikifier, Wikifier
12 | 13 |
function $ (id)
Returns the DOM element with the id passed.
14 | 15 | 16 | 17 |
function addStyle (source)
Adds CSS styles to the document.
18 | 19 | 20 | 21 |
function clone (original)
Performs a shallow copy of an object.
History.prototype.close = function (passage)
This removes a passage from display onscreen.
Wikifier.createExternalLink = function (place,
url)
Creates a link to an external URL.
Wikifier.createInternalLink = function (place,
title)
Creates a link to a passage.
22 | 23 | 24 | 25 |
History.prototype.display = function (title,
link,
render)
Displays a passage on the page.
26 | 27 | 28 | 29 |
Math.easeInOut = function (i)
Eases a decimal number from 0 to 1.
30 | 31 | 32 | 33 |
function fade (el,
options)
Fades a DOM element in or out.
Wikifier.prototype.fullArgs = function()
Meant to be called by macros, this returns the text passed to the currently executing macro.
34 | 35 | 36 | 37 |
Tale.prototype.get = function (key)
A getter function that returns a certain Passage object belonging to the tale.
38 | 39 | 40 | 41 |
Tale.prototype.has = function (key)
Checks whether the tale has a passage with either the title passed (if the key parameter is a string) or an id (if a number is passed instead).
42 | 43 | 44 | 45 |
History.prototype.init = function()
This first attempts to restore the state of the story via the restore method.
function insertElement (place,
type,
id,
className,
text)
A shortcut function for creating a DOM element.
function insertText (place,
text)
Places text in a DOM element.
46 | 47 | 48 | 49 |
Tale.prototype.lookup = function(field,
value,
sortField)
Searches the Tale for all passages matching a certain criteria.
50 | 51 | 52 | 53 |
function main()
Loads the story from the storage div, initializes macros and custom stylesheets, and displays the first passages of the story.
54 | 55 | 56 | 57 |
function Passage (title,
el,
order)
Initializes a new Passage object.
58 | 59 | 60 | 61 |
Parses a list of bracketed links -- e.g.
Parses a list of macro parameters.
function removeChildren (el)
Removes all child elements from a DOM element.
Passage.prototype.render = function()
Renders the passage to a DOM element, including its title, toolbar, and content.
Passage.prototype.reset = function()
Resets the passage’s text property to its initialText property.
Tale.prototype.reset = function()
Calls the Passage.reset method on all Passages in the tale, restoring the story to its initial state.
History.prototype.restart = function()
Restarts the story from the beginning.
History.prototype.restore = function ()
Attempts to restore the state of the story as saved by save.
History.prototype.rewindTo = function (passage)
Rewinds the state of the story to a particular Passage.
62 | 63 | 64 | 65 |
History.prototype.save = function (passage)
Returns a hash to append to the page’s URL that will be later read by the restore method.
function scrollWindowTo (el)
This scrolls the browser window to ensure that a DOM element is in view.
function setPageElement (id,
title,
defaultText)
Wikifies a passage into a DOM element.
66 | 67 | 68 | 69 |
function Tale()
Initializes a new Tale object with the contents of the DOM element with the id storeArea, constructing new Passages as it traverses the tree.
function throwError (place,
message)
Displays an error message on the page.
Removes whitespace from the beginning and end of a string.
70 | 71 | 72 | 73 |
Passage.unescapeLineBreaks = function (text)
A static function used by the constructor to convert string literals used by TiddlyWiki to indicate newlines into actual newlines.
74 | 75 | 76 | 77 |
function Wikifier(place,
source)
Wikifies source text into a DOM element.
78 | 79 |
--------------------------------------------------------------------------------