[[Syntaxify Demos]]
Derived from [[this|http://www.squarefree.com/shell/?ignoreReferrerFrom=shell1.4]]\nstore.fetchTiddler("Test").revisionKey\ntime(f, n)\n<html>\n<div>\n Features: autocompletion of property names with Tab, multiline input with Shift+Enter, input history with (Ctrl+) Up/Down, \n <a accesskey="M" href="javascript:jsshell.go('scope(Math); mathHelp();');" title="Accesskey: M">Math</a>\n</div>\n<div>\nValues and functions: ans, print(string), \n <a accesskey="P" href="javascript:jsshell.go('props(ans)')" title="Accesskey: P">props(object)</a>, \n <a accesskey="B" href="javascript:jsshell.go('blink(ans)')" title="Accesskey: B">blink(node)</a>, \n <a href="javascript:jsshell.go('wikify(ans)')">wikify(text)</a>\n <a href="javascript:jsshell.go('print(ans)')">print(text)</a>\n <a accesskey="C" href="javascript:jsshell.go('clear()')" title="Accesskey: C">clear()</a>, \n load(scriptURL), \n scope(object)</div>\n<div class="shell">\n <div id="output"></div>\n <div><textarea id="input" class="input" wrap="off" onkeydown="jsshell.inputKeydown(event)" rows="1"></textarea></div>\n</div>\n</html><script>\nwindow.jsshell = {}; // Put our functions in the global namespace.\n\nwindow.jsshell.refocus = function()\n{\n jsshell._in.blur(); // Needed for Mozilla to scroll correctly.\n jsshell._in.focus();\n}\n\nwindow.jsshell.initTarget = function()\n{\n window.print = jsshell.shellCommands.print;\n}\n\n// Unless the user is selected something, refocus the textbox.\n// (requested by caillon, brendan, asa)\nwindow.jsshell.keepFocusInTextbox = function(e) \n{\n var g = e.srcElement ? e.srcElement : e.target; // IE vs. standard\n \n while (!g.tagName)\n g = g.parentNode;\n var t = g.tagName.toUpperCase();\n if (t=="A" || t=="INPUT")\n return;\n \n if (window.getSelection) {\n // Mozilla\n if (String(window.getSelection()))\n return;\n }\n else if (document.getSelection) {\n // Opera? Netscape 4?\n if (document.getSelection())\n return;\n }\n else {\n // IE\n if ( document.selection.createRange().text )\n return;\n }\n \n jsshell.refocus();\n}\n\n//function inputKeydown(e) {\nwindow.jsshell.inputKeydown = function(e) {\n // Use onkeydown because IE doesn't support onkeypress for arrow keys\n\n //alert(e.keyCode + " ^ " + e.keycode);\n\n if (e.shiftKey && e.keyCode == 13) { // shift-enter\n // don't do anything; allow the shift-enter to insert a line break as normal\n } else if (e.keyCode == 13) { // enter\n // execute the input on enter\n try { jsshell.go(); } catch(er) { alert(er); };\n setTimeout(function() { jsshell._in.value = ""; }, 0); // can't preventDefault on input, so clear it later\n } else if (e.keyCode == 38) { // up\n // go up in history if at top or ctrl-up\n if (e.ctrlKey || jsshell.caretInFirstLine(jsshell._in))\n jsshell.hist(true);\n } else if (e.keyCode == 40) { // down\n // go down in history if at end or ctrl-down\n if (e.ctrlKey || jsshell.caretInLastLine(jsshell._in))\n jsshell.hist(false);\n } else if (e.keyCode == 9) { // tab\n jsshell.tabcomplete();\n setTimeout(function() { jsshell.refocus(); }, 0); // refocus because tab was hit\n } else { }\n\n setTimeout(jsshell.recalculateInputHeight, 0);\n \n //return true;\n};\n\nwindow.jsshell.caretInFirstLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionStart == undefined)\n return true;\n\n var firstLineBreak = textbox.value.indexOf("\sn");\n\n return ((firstLineBreak == -1) || (textbox.selectionStart <= firstLineBreak));\n}\n\nwindow.jsshell.caretInLastLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionEnd == undefined)\n return true;\n\n var lastLineBreak = textbox.value.lastIndexOf("\sn");\n \n return (textbox.selectionEnd > lastLineBreak);\n}\n\nwindow.jsshell.recalculateInputHeight = function()\n{\n var rows = jsshell._in.value.split(/\sn/).length\n + 1 // prevent scrollbar flickering in Mozilla\n + (window.opera ? 1 : 0); // leave room for scrollbar in Opera\n\n if (jsshell._in.rows != rows) // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0.\n jsshell._in.rows = rows;\n}\n\nwindow.jsshell.println = function(s, type)\n{\n if((s=String(s)))\n {\n var newdiv = document.createElement("div");\n newdiv.appendChild(document.createTextNode(s));\n newdiv.className = type;\n jsshell._out.appendChild(newdiv);\n return newdiv;\n }\n}\n\nwindow.jsshell.printWithRunin = function(h, s, type)\n{\n var div = jsshell.println(s, type);\n var head = document.createElement("strong");\n head.appendChild(document.createTextNode(h + ": "));\n div.insertBefore(head, div.firstChild);\n}\n\nwindow.jsshell.shellCommands = \n{\nload : function load(url)\n{\n var s = document.createElement("script");\n s.type = "text/javascript";\n s.src = url;\n document.getElementsByTagName("head")[0].appendChild(s);\n jsshell.println("Loading " + url + "...", "message");\n},\n\nclear : function clear()\n{\n jsshell._out.innerHTML = "";\n},\n\nwikify : function wikify(text)\n{\n window.wikify(text, jsshell._out);\n},\n\nprint : function print(s) { jsshell.println(s, "print"); },\n\n// the normal function, "print", shouldn't return a value\n// (suggested by brendan; later noticed it was a problem when showing others)\npr : function pr(s) \n{ \n jsshell.shellCommands.print(s); // need to specify shellCommands so it doesn't try window.print()!\n return s;\n},\n\nprops : function props(e, onePerLine)\n{\n if (e === null) {\n jsshell.println("props called with null argument", "error");\n return;\n }\n\n if (e === undefined) {\n jsshell.println("props called with undefined argument", "error");\n return;\n }\n\n var ns = ["Methods", "Fields", "Unreachables"];\n var as = [[], [], []]; // array of (empty) arrays of arrays!\n var p, j, i; // loop variables, several used multiple times\n\n var protoLevels = 0;\n\n for (p = e; p; p = p.__proto__)\n {\n for (i=0; i<ns.length; ++i)\n as[i][protoLevels] = [];\n ++protoLevels;\n }\n\n for(var a in e)\n {\n // Shortcoming: doesn't check that VALUES are the same in object and prototype.\n\n var protoLevel = -1;\n try\n {\n for (p = e; p && (a in p); p = p.__proto__)\n ++protoLevel;\n }\n catch(er) { protoLevel = 0; } // "in" operator throws when param to props() is a string\n\n var type = 1;\n try\n {\n if ((typeof e[a]) == "function")\n type = 0;\n }\n catch (er) { type = 2; }\n\n as[type][protoLevel].push(a);\n }\n\n function times(s, n) { return n ? s + times(s, n-1) : ""; }\n\n for (j=0; j<protoLevels; ++j)\n for (i=0;i<ns.length;++i)\n if (as[i][j].length) \n jsshell.printWithRunin(\n ns[i] + times(" of prototype", j), \n (onePerLine ? "\sn\sn" : "") + as[i][j].sort().join(onePerLine ? "\sn" : ", ") + (onePerLine ? "\sn\sn" : ""), \n "propList"\n );\n},\n\nblink : function blink(node)\n{\n if (!node) throw("blink: argument is null or undefined.");\n if (node.nodeType == null) throw("blink: argument must be a node.");\n if (node.nodeType == 3) throw("blink: argument must not be a text node");\n if (node.documentElement) throw("blink: argument must not be the document object");\n\n function setOutline(o) { \n return function() {\n if (node.style.outline != node.style.bogusProperty) {\n // browser supports outline (Firefox 1.1 and newer, CSS3, Opera 8).\n node.style.outline = o;\n }\n else if (node.style.MozOutline != node.style.bogusProperty) {\n // browser supports MozOutline (Firefox 1.0.x and older)\n node.style.MozOutline = o;\n }\n else {\n // browser only supports border (IE). border is a fallback because it moves things around.\n node.style.border = o;\n }\n }\n } \n \n function focusIt(a) {\n return function() {\n a.focus(); \n }\n }\n\n if (node.ownerDocument) {\n var windowToFocusNow = (node.ownerDocument.defaultView || node.ownerDocument.parentWindow); // Moz vs. IE\n if (windowToFocusNow)\n setTimeout(focusIt(windowToFocusNow.top), 0);\n }\n\n for(var i=1;i<7;++i)\n setTimeout(setOutline((i%2)?'3px solid red':'none'), i*100);\n\n setTimeout(focusIt(window), 800);\n setTimeout(focusIt(jsshell._in), 810);\n},\n\ntime: function (f, n) { \n var start = new Date(); \n if (typeof n != typeof undefined) { \n for (var i = 0; i < n; i++) { f(); } } \n else { f(); } \n var stop = new Date(); \n return stop - start; \n},\n\nscope : function scope(sc)\n{\n if (!sc) sc = {};\n jsshell._scope = sc;\n jsshell.println("Scope is now " + sc + ". If a variable is not found in this scope, window will also be searched. New variables will still go on window.", "message");\n},\n\nmathHelp : function mathHelp()\n{\n jsshell.printWithRunin("Math constants", "E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2", "propList");\n jsshell.printWithRunin("Math methods", "abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan", "propList");\n},\n\nans : undefined\n};\n\n\nwindow.jsshell.hist = function(up)\n{\n // histList[0] = first command entered, [1] = second, etc.\n // type something, press up --> thing typed is now in "limbo"\n // (last item in histList) and should be reachable by pressing \n // down again.\n\n var L = jsshell.histList.length;\n\n if (L == 1)\n return;\n\n if (up)\n {\n if (jsshell.histPos == L-1)\n {\n // Save this entry in case the user hits the down key.\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n }\n\n if (jsshell.histPos > 0)\n {\n jsshell.histPos--;\n // Use a timeout to prevent up from moving cursor within new text\n // Set to nothing first for the same reason\n setTimeout(\n function() {\n jsshell._in.value = ''; \n jsshell._in.value = jsshell.histList[jsshell.histPos];\n var caretPos = jsshell._in.value.length;\n if (jsshell._in.setSelectionRange) \n jsshell._in.setSelectionRange(caretPos, caretPos);\n },\n 0\n );\n }\n } \n else // down\n {\n if (jsshell.histPos < L-1)\n {\n jsshell.histPos++;\n jsshell._in.value = jsshell.histList[jsshell.histPos];\n }\n else if (jsshell.histPos == L-1)\n {\n // Already on the current entry: clear but save\n if (jsshell._in.value)\n {\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n ++jsshell.histPos;\n jsshell._in.value = "";\n }\n }\n }\n}\n\nwindow.jsshell.tabcomplete = function()\n{\n /*\n * Working backwards from s[from], find the spot\n * where this expression starts. It will scan\n * until it hits a mismatched ( or a space,\n * but it skips over quoted strings.\n * If stopAtDot is true, stop at a '.'\n */\n function findbeginning(s, from, stopAtDot)\n {\n /*\n * Complicated function.\n *\n * Return true if s[i] == q BUT ONLY IF\n * s[i-1] is not a backslash.\n */\n function equalButNotEscaped(s,i,q)\n {\n if(s.charAt(i) != q) // not equal go no further\n return false;\n\n if(i==0) // beginning of string\n return true;\n\n if(s.charAt(i-1) == '\s\s') // escaped?\n return false;\n\n return true;\n }\n\n var nparens = 0;\n var i;\n for(i=from; i>=0; i--)\n {\n if(s.charAt(i) == ' ')\n break;\n\n if(stopAtDot && s.charAt(i) == '.')\n break;\n \n if(s.charAt(i) == ')')\n nparens++;\n else if(s.charAt(i) == '(')\n nparens--;\n\n if(nparens < 0)\n break;\n\n // skip quoted strings\n if(s.charAt(i) == '\s'' || s.charAt(i) == '\s"')\n {\n //dump("skipping quoted chars: ");\n var quot = s.charAt(i);\n i--;\n while(i >= 0 && !equalButNotEscaped(s,i,quot)) {\n //dump(s.charAt(i));\n i--;\n }\n //dump("\sn");\n }\n }\n return i;\n }\n\n // XXX should be used more consistently (instead of using selectionStart/selectionEnd throughout code)\n // XXX doesn't work in IE, even though it contains IE-specific code\n function getcaretpos(inp)\n {\n if(inp.selectionEnd != null)\n return inp.selectionEnd;\n \n if(inp.createTextRange)\n {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n if (inprange.setEndPoint)\n {\n inprange.setEndPoint('EndToStart', docrange);\n return inprange.text.length;\n }\n }\n\n return inp.value.length; // sucks, punt\n }\n\n function setselectionto(inp,pos)\n {\n if(inp.selectionStart) {\n inp.selectionStart = inp.selectionEnd = pos;\n }\n else if(inp.createTextRange) {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n inprange.move('character',pos);\n inprange.select();\n }\n else { // err...\n /*\n inp.select();\n if(document.getSelection())\n document.getSelection() = "";\n */\n }\n }\n // get position of cursor within the input box\n var caret = getcaretpos(jsshell._in);\n\n if(caret) {\n //dump("----\sn");\n var dotpos, spacepos, complete, obj;\n //dump("caret pos: " + caret + "\sn");\n // see if there's a dot before here\n dotpos = findbeginning(jsshell._in.value, caret-1, true);\n //dump("dot pos: " + dotpos + "\sn");\n if(dotpos == -1 || jsshell._in.value.charAt(dotpos) != '.') {\n dotpos = caret;\n//dump("changed dot pos: " + dotpos + "\sn");\n }\n\n // look backwards for a non-variable-name character\n spacepos = findbeginning(jsshell._in.value, dotpos-1, false);\n //dump("space pos: " + spacepos + "\sn");\n // get the object we're trying to complete on\n if(spacepos == dotpos || spacepos+1 == dotpos || dotpos == caret)\n {\n // try completing function args\n if(jsshell._in.value.charAt(dotpos) == '(' ||\n (jsshell._in.value.charAt(spacepos) == '(' && (spacepos+1) == dotpos))\n {\n var fn,fname;\n var from = (jsshell._in.value.charAt(dotpos) == '(') ? dotpos : spacepos;\n spacepos = findbeginning(jsshell._in.value, from-1, false);\n\n fname = jsshell._in.value.substr(spacepos+1,from-(spacepos+1));\n //dump("fname: " + fname + "\sn");\n try {\n with(window)\n with(jsshell._scope)\n with(jsshell.shellCommands)\n fn = eval(fname);\n }\n catch(er) {\n //dump('fn is not a valid object\sn');\n return;\n }\n if(fn == undefined) {\n //dump('fn is undefined');\n return;\n }\n if(fn instanceof Function)\n {\n // Print function definition, including argument names, but not function body\n if(!fn.toString().match(/function .+?\s(\s) +\s{\sn +\s[native code\s]\sn\s}/))\n jsshell.println(fn.toString().match(/function .+?\s(.*?\s)/), "tabcomplete");\n }\n\n return;\n }\n else\n obj = window;\n }\n else\n {\n var objname = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n //dump("objname: |" + objname + "|\sn");\n try {\n with(jsshell._scope)\n with(window)\n obj = eval(objname);\n }\n catch(er) {\n jsshell.printError(er); \n return;\n }\n if(obj == undefined) {\n // sometimes this is tabcomplete's fault, so don't print it :(\n // e.g. completing from "print(document.getElements"\n // jsshell.println("Can't complete from null or undefined expression " + objname, "error");\n return;\n }\n }\n //dump("obj: " + obj + "\sn");\n // get the thing we're trying to complete\n if(dotpos == caret)\n {\n if(spacepos+1 == dotpos || spacepos == dotpos)\n {\n // nothing to complete\n //dump("nothing to complete\sn");\n return;\n }\n\n complete = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n }\n else {\n complete = jsshell._in.value.substr(dotpos+1,caret-(dotpos+1));\n }\n //dump("complete: " + complete + "\sn");\n // ok, now look at all the props/methods of this obj\n // and find ones starting with 'complete'\n var matches = [];\n var bestmatch = null;\n for(var a in obj)\n {\n //a = a.toString();\n //XXX: making it lowercase could help some cases,\n // but screws up my general logic.\n if(a.substr(0,complete.length) == complete) {\n matches.push(a);\n ////dump("match: " + a + "\sn");\n // if no best match, this is the best match\n if(bestmatch == null)\n {\n bestmatch = a;\n }\n else {\n // the best match is the longest common string\n function min(a,b){ return ((a<b)?a:b); }\n var i;\n for(i=0; i< min(bestmatch.length, a.length); i++)\n {\n if(bestmatch.charAt(i) != a.charAt(i))\n break;\n }\n bestmatch = bestmatch.substr(0,i);\n ////dump("bestmatch len: " + i + "\sn");\n }\n ////dump("bestmatch: " + bestmatch + "\sn");\n }\n }\n bestmatch = (bestmatch || "");\n ////dump("matches: " + matches + "\sn");\n var objAndComplete = (objname || obj) + "." + bestmatch;\n //dump("matches.length: " + matches.length + ", jsshell.tooManyMatches: " + jsshell.tooManyMatches + ", objAndComplete: " + objAndComplete + "\sn");\n if(matches.length > 1 && (jsshell.tooManyMatches == objAndComplete || matches.length <= 10)) {\n\n jsshell.printWithRunin("Matches: ", matches.join(', '), "tabcomplete");\n jsshell.tooManyMatches = null;\n }\n else if(matches.length > 10)\n {\n jsshell.println(matches.length + " matches. Press tab again to see them all", "tabcomplete");\n jsshell.tooManyMatches = objAndComplete;\n }\n else {\n jsshell.tooManyMatches = null;\n }\n if(bestmatch != "")\n {\n var sstart;\n if(dotpos == caret) {\n sstart = spacepos+1;\n }\n else {\n sstart = dotpos+1;\n }\n jsshell._in.value = jsshell._in.value.substr(0, sstart)\n + bestmatch\n + jsshell._in.value.substr(caret);\n setselectionto(jsshell._in,caret + (bestmatch.length - complete.length));\n }\n }\n}\n\nwindow.jsshell.printQuestion = function(q)\n{\n jsshell.println(q, "input");\n}\n\nwindow.jsshell.printAnswer = function(a)\n{\n if (a !== undefined) {\n jsshell.println(a, "normalOutput");\n jsshell.shellCommands.ans = a;\n }\n}\n\nwindow.jsshell.printError = function(er)\n{ \n var lineNumberString;\n\n lastError = er; // for debugging the shell\n if (er.name)\n {\n // lineNumberString should not be "", to avoid a very wacky bug in IE 6.\n lineNumberString = (er.lineNumber != undefined) ? (" on line " + er.lineNumber + ": ") : ": ";\n jsshell.println(er.name + lineNumberString + er.message, "error"); // Because IE doesn't have error.toString.\n }\n else\n jsshell.println(er, "error"); // Because security errors in Moz /only/ have toString.\n}\n\nwindow.jsshell.go = function(s)\n{\n jsshell._in.value = jsshell.question = s ? s : jsshell._in.value;\n\n if (jsshell.question == "")\n return;\n\n jsshell.histList[jsshell.histList.length-1] = jsshell.question;\n jsshell.histList[jsshell.histList.length] = "";\n jsshell.histPos = jsshell.histList.length - 1;\n \n // Unfortunately, this has to happen *before* the JavaScript is run, so that \n // print() output will go in the right place.\n jsshell._in.value='';\n jsshell.recalculateInputHeight();\n jsshell.printQuestion(jsshell.question);\n\n if (window.closed) {\n jsshell.printError("Target window has been closed.");\n return;\n }\n \n try { ("jsshell" in window) }\n catch(er) {\n jsshell.printError("The JavaScript Shell cannot access variables in the target window. The most likely reason is that the target window now has a different page loaded and that page has a different hostname than the original page.");\n return;\n }\n\n if (!("jsshell" in window))\n initTarget(); // silent\n\n // Evaluate Shell.question using _win's eval (this is why eval isn't in the |with|, IIRC).\n// window.location.href = "javascript:try{ jsshell.printAnswer(eval('with(jsshell._scope) with(jsshell.shellCommands) {' + jsshell.question + String.fromCharCode(10) + '}')); } catch(er) { jsshell.printError(er); }; setTimeout(jsshell.refocus, 0); void 0";\n try { \n jsshell.printAnswer(eval(\n 'with(jsshell._scope) with(jsshell.shellCommands) {' \n + jsshell.question + String.fromCharCode(10) + \n '}')); \n } catch(er) { \n jsshell.printError(er); \n }; \n setTimeout(jsshell.refocus, 0);\n}\n\nwindow.jsshell.histList = [""]; \nwindow.jsshell.histPos = 0; \nwindow.jsshell._scope = {}; \nwindow.jsshell.question;\nwindow.jsshell._in;\nwindow.jsshell._out;\nwindow.jsshell.tooManyMatches = null;\nwindow.jsshell.lastError = null;\n\njsshell._in = document.getElementById("input");\njsshell._out = document.getElementById("output");\n\njsshell.initTarget();\n\njsshell.recalculateInputHeight();\njsshell.refocus();\n\n</script>\n
[[Plugin: Syntaxify]]\n[[Plugin: Syntaxify Haskell]]\n[[Syntaxify Demos]]\n----\nStyleSheetColors\nStyleSheetLayout\nStyleSheetPrint\nStyleSheetSyntaxify\nEditTemplate\nViewTemplate\nPageTemplate\n
/***\n''InlineJavascriptPlugin for ~TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#InlineJavascriptPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nInsert Javascript executable code directly into your tiddler content. Lets you ''call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.\n\n''Deferred execution from an 'onClick' link''\nBy including a label="..." parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered.\n\n''External script source files:''\nYou can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.\n\n''Display script source in tiddler output''\nBy including the keyword parameter "show", in the initial {{{<script>}}} marker, the plugin will include the script source code in the output that it displays in the tiddler.\n\n''Defining javascript functions and libraries:''\nAlthough the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).\n\nTo ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.\n\nSince the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.\n\n''Creating dynamic tiddler content''\nAn important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:\n* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.\n* However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire ~TiddlyWiki document in your browser window.\n* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.\n\nIf your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display. For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.\n\n//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//\n\n''Accessing the ~TiddlyWiki DOM''\nThe plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.\n\nAccess to this DOM element allows you to create scripts that can:\n* vary their actions based upon the specific location in which they are embedded\n* access 'tiddler-relative' information (use findContainingTiddler(place))\n* perform direct DOM manipulations (when returning wikified text is not enough)\n<<<\n!!!!!Examples\n<<<\nan "alert" message box:\n><script show>\n alert('InlineJavascriptPlugin: this is a demonstration message');\n</script>\ndynamic output:\n><script show>\n return (new Date()).toString();\n</script>\nwikified dynamic output:\n><script show>\n return "link to current user: [["+config.options.txtUserName+"]]";\n</script>\ndynamic output using 'place' to get size information for current tiddler:\n><script show>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\ncreating an 'onclick' button/link that runs a script:\n><script label="click here" show>\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\nloading a script from a source url:\n>http://www.TiddlyTools.com/demo.js contains:\n>>{{{function demo() { alert('this output is from demo(), defined in demo.js') } }}}\n>>{{{alert('InlineJavascriptPlugin: demo.js has been loaded'); }}}\n><script src="demo.js" show>\n return "loading demo.js..."\n</script>\n><script label="click to execute demo() function" show>\n demo()\n</script>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.06.01 [1.5.1]'' when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly\n''2006.04.19 [1.5.0]'' added 'show' parameter to force display of javascript source code in tiddler output\n''2006.01.05 [1.4.0]'' added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.\n''2005.12.13 [1.3.1]'' when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski\n''2005.11.09 [1.3.0]'' for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck\n''2005.11.08 [1.2.0]'' handle loading of javascript from an external URL via src="..." syntax\n''2005.11.08 [1.1.0]'' pass 'place' param into scripts to provide direct DOM access \n''2005.11.08 [1.0.0]'' initial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.inlineJavascript= {major: 1, minor: 5, revision: 1, date: new Date(2006,6,1)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: src=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: label=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?( show)?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\n\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n if (lookaheadMatch[1]) { // load a script library\n // make script tag, set src, add to body to execute, then remove for cleanup\n var script = document.createElement("script"); script.src = lookaheadMatch[1];\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (lookaheadMatch[4]) { // there is script code\n if (lookaheadMatch[3]) // show inline script code in tiddler output\n wikify("//{{{\sn"+lookaheadMatch[0]+"\sn//}}}\sn",w.output);\n if (lookaheadMatch[2]) { // create a link to an 'onclick' script\n // add a link, define click handler, save code in link (pass 'place'), set link attributes\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);\n link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}\n link.code="function _out(place){"+lookaheadMatch[4]+"};_out(this);"\n link.setAttribute("href","javascript:;"); link.setAttribute("title",""); link.style.cursor="pointer";\n }\n else { // run inline script code\n var code="function _out(place){"+lookaheadMatch[4]+"};_out(w.output);"\n code=code.replace(/document.write\s(/gi,'place.innerHTML+=(');\n try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }\n if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);\n }\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n} )\n//}}}\n
/***\n|''Name:''|Plugin: Syntaxify|\n|''Description:''|Performs syntax highlighting on CSS, JavaScript, and HTML/XML|\n|''Version:''|1.2|\n|''Date:''|January 29, 2007|\n|''Source:''|http://bob.mcelrath.org/syntaxify.html|\n|''Author:''|BobMcElrath|\n|''Email:''|my first name at my last name dot org|\n|''License:''|[[GPL open source license|http://www.gnu.org/licenses/gpl.html]]|\n|''~CoreVersion:''|2.0.0|\n!Description\nThis plugin will syntax highlight ("pretty-print") source code used by TiddlyWiki. To activate CSS markup, enclose the code in the CSS code in the delimiters \n<html><code>\n/&#42;{{{&#42;/<br/>\n/&#42; CSS code here &#42/<br/>\n/&#42;}}}&#42;/<br/>\n</code></html>\nTo activate XML markup, enclose your HTML/XML in the delimiters\n<html><code>\n&lt;!--{{{--&gt;<br/>\n&lt;!-- XML/HTML code here --&gt;<br/>\n&lt;!--}}}--&gt;<br/>\n</code></html>\nAnd to activate JavaScript markup, enclose your code in the delimiters\n<html><code>\n//{{{<br/>\n// JavaScript code here.<br/>\n//}}}<br/>\n</code></html>\n\nIn addition, all of the above languages can be syntaxified by using the custom class formatter\n<html><code>\n{{foo{<br/>\n code for language "foo" here<br/>\n}}}<br/>\n</code></html>\nwhere {{{foo}}} is the name of the language: {{{css}}}, {{{javascript}}}, or {{{xml}}}. This plugin can be extended with new languages by creating a data structure like those below (in {{{syntaxify.languages}}} and then calling {{{syntaxify.addLanguages}}}.\n!History\n* 1.2 Release\n** Now syntaxifies in-line style code (thanks [[Conal Elliott|http://conal.net]]).\n** Fix multi-line comments in CSS.\n** Consolidate customClassesHelper and monospacedByLineHelper which had lots of duplicated code.\n** Fix autoLinkWikiWords bug when using custom classes and the tag formatter.\n** Fix compatibility problems between 2.1 and 2.0 (termRegExp vs. terminator)\n* 1.1 Release\n** Rewrite things to make it easier to add new languages.\n** Override customClasses to syntaxify when the class corresponds to a known language.\n** TiddlyWiki 2.1 beta compatibility\n* 1.0.2 Release\n** Don't use {{{class}}} as a variable name, dummy.\n* 1.0.1 Release\n** Simplified stylesheet and removed line numbering.\n** Fixed highlighting when <html><code>&#42;/</code></html> appeared at the beginning of a line.\n** Fixed blank lines not being shown if {{{list-style-type: none}}} was turned on.\n** Small speedups\n* 1.0.0 Initial Release\n!Code\n***/\n//{{{\nversion.extensions.Syntaxify = { major: 1, minor: 2, revision: 0, date: new Date("2007","01","29"),\n source: "http://bob.mcelrath.org/syntaxify.html"\n};\n\nvar syntaxify = {};\n\nsyntaxify.regexpSpace = new RegExp(" ", "mg");\nsyntaxify.regexpTab = new RegExp("\st", "mg");\nsyntaxify.regexpAmp = new RegExp("&","mg");\nsyntaxify.regexpLessThan = new RegExp("<","mg");\nsyntaxify.regexpGreaterThan = new RegExp(">","mg");\nsyntaxify.regexpQuote = new RegExp("\s"","mg");\nsyntaxify.regexpDoubleQuotedString = new RegExp("\s"(?:\s\s\s\s.|[^\s\s\s\s\s"])*?\s"", "mg");\nsyntaxify.regexpSingleQuotedString = new RegExp("'(?:\s\s\s\s.|[^\s\s\s\s'])*?'", "mg");\nsyntaxify.regexpCSingleLineComment = new RegExp('//.*$', "g");\nsyntaxify.regexpCMultiLineComment \n = new RegExp('/\s\s*(?:(?:.|(?:\s\sr)?\s\sn)(?!\s\s*/))*(?:.|(?:\s\sr)?\s\sn)?\s\s*/',"mg");\nString.prototype.htmlListMono = function() {\n return(this.replace(syntaxify.regexpAmp,"&amp;")\n .replace(syntaxify.regexpLessThan,"&lt;")\n .replace(syntaxify.regexpGreaterThan,"&gt;")\n .replace(syntaxify.regexpQuote,"&quot;")\n .replace(syntaxify.regexpSpace,"&nbsp;")\n .replace(syntaxify.regexpTab,"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"));\n}\n\nsyntaxify.handleSpanClass = function(w) {\n var match, lastPos=0;\n if(this.lookahead) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg"); \n lookaheadRegExp.lastIndex = w.matchStart; \n var lookaheadMatch = lookaheadRegExp.exec(w.source); \n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { \n createTiddlyText(w.output, lookaheadMatch[1]);\n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?lookaheadMatch[2].htmlListMono():lookaheadMatch[2];\n }\n } else {\n while((match = regexpNewLine.exec(w.matchText)) != null) { // multi-line\n var alt = "";\n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?w.matchText.substr(lastPos,match.index-lastPos).htmlListMono()\n :w.matchText.substr(lastPos,match.index-lastPos);\n if(w.output.className != "alt") alt = "alt";\n w.output = createTiddlyElement(w.output.parentNode, "li", null, alt);\n lastPos = match.index;\n } \n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?w.matchText.substr(lastPos, w.matchText.length-lastPos).htmlListMono()\n :w.matchText.substr(lastPos, w.matchText.length-lastPos)\n }\n}\n\n/* This is a shadow tiddler. Do not edit it here. Instead, open the tiddler StyleSheetSyntaxify \n * and edit it instead. (go to the toolbar on the right and select "More"->"Shadowed") */\nconfig.shadowTiddlers.StyleSheetSyntaxify = "/*{{{*/\sn"\n+".viewer .syntaxify {\sn"\n+" font-family: monospace;\sn"\n+"}\sn"\n+".viewer div.syntaxify {\sn"\n+" background-color: #ffc;\sn"\n+" border: 1px solid #fe8;\sn"\n+" padding: 0.5em;\sn"\n+" margin: 0 0 1em 0.5em;\sn"\n+" font-size: 1.2em;\sn"\n+" overflow: auto;\sn"\n+"}\sn\sn"\n+".syntaxify ol {\sn"\n+" margin: 0;\sn"\n+" padding: 1px;\sn"\n+" color: #2B91AF;\sn"\n+"}\sn\sn"\n+".syntaxify ol li {\sn"\n+" background-color: #ffc;\sn"\n+" color: black;\sn"\n+" list-style-type: none;\sn"\n+"/* An alternate style to enable line numbering -- remove the line above and uncomment below if desired */\sn"\n+"/*\sn"\n+" list-style-type: 1;\sn"\n+" border-left: 3px solid #fe8;\sn"\n+" margin-left: 3.5em;\sn"\n+"*/\sn"\n+"}\sn\sn"\n+"/* To disable alternating lines having a different colors, comment out the following line. */\sn"\n+".syntaxify ol li.alt { background-color: #ffe; }\sn\sn"\n+".syntaxify ol li span { color: black; }\sn"\n+".syntaxify .singleLineComments { color: green; }\sn"\n+".syntaxify .multiLineComments { color: green; }\sn"\n+".syntaxify .multiLineComments1 { color: red; }\sn"\n+".syntaxify .tag { font-weight: bold; color: blue; }\sn"\n+".syntaxify .tagname { font-weight: bold; color: black; }\sn"\n+".syntaxify .attribute { color: rgb(127,0,85); }\sn"\n+".syntaxify .value { color: rgb(42,0,255); }\sn"\n+".syntaxify .keywords { color: #006699; }\sn"\n+".syntaxify .keywords1 { color: red; }\sn"\n+".syntaxify .delimiters { color: maroon; }\sn"\n+".syntaxify .delimiters1 { color: olive; }\sn"\n+".syntaxify .literals { color: maroon; }\sn"\n+".syntaxify .literals1 { color: blue; }\sn"\n+".syntaxify .literals2 { color: blue; }\sn"\n+".syntaxify .literals3 { color: #129; }\sn"\n+".syntaxify .identifiers { font-weight: bold; color: blue; }\sn"\n+".syntaxify .identifiers1 { font-weight: bold; color: black; }\sn"\n+"/*}}}*/";\n\nstore.addNotification("StyleSheetSyntaxify",refreshStyles);\nconfig.shadowTiddlers.ViewTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.ViewTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.EditTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.EditTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.PageTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.PageTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.StyleSheetPrint = "/*{{{*/\sn"+config.shadowTiddlers.StyleSheetPrint+"\sn/*}}}*/";\n\nsyntaxify.commonFormatters = [\n{ name: "spaces",\n match: "[ \s\st]+",\n handler: function(w) {\n w.output.innerHTML += w.matchText.htmlListMono();\n }\n},{ name: "newline",\n match: "\s\sn",\n handler: function(w) {\n var alt = ""\n if(w.output.className != "alt") alt = "alt";\n if(!w.output.hasChildNodes()) w.output.innerHTML = "&nbsp;";\n w.output = createTiddlyElement(w.output.parentNode, "li", null, alt);\n }\n}];\n\nsyntaxify.xmlTagFormatters = syntaxify.commonFormatters;\nsyntaxify.xmlTagFormatters = syntaxify.xmlTagFormatters.concat([\n{ name: "tagname",\n match: '<[/\s\s?]?\s\ss*(?:[\s\sw-\s\s.]+)',\n lookahead: '(<[/\s\s?]?\s\ss*)([\s\sw-\s\s.]+)',\n handler: syntaxify.handleSpanClass\n},{\n name: "attribute-value",\n match: '[\s\sw-\s.]+(?:\s\ss*=\s\ss*"[^"]*?"|\s'[^\s']*?\s'|\s\sw+)?',\n lookahead: '([\s\sw-\s.]+)(?:(\s\ss*=\s\ss*)("[^"]*?"|\s'[^\s']*?\s'|\s\sw+))?',\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg"); \n lookaheadRegExp.lastIndex = w.matchStart; \n var lookaheadMatch = lookaheadRegExp.exec(w.source); \n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { \n var e = createTiddlyElement(w.output, "span", null, "attribute");\n e.innerHTML = lookaheadMatch[1];\n if(lookaheadMatch[2]) {\n var e = createTiddlyElement(w.output, "span");\n e.innerHTML = lookaheadMatch[2].htmlListMono();\n e = createTiddlyElement(w.output, "span", null, "value");\n e.innerHTML = lookaheadMatch[3].htmlListMono();\n }\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length; \n }\n}]);\n\n\n// A rather huge data structure to store languages. Add to it!\nsyntaxify.languages = {\njavascript: {\n singleLineComments: [[syntaxify.regexpCSingleLineComment.source]],\n multiLineComments: [[syntaxify.regexpCMultiLineComment.source]],\n keywords: [['abstract', 'boolean', 'break', 'byte', 'case', 'catch', 'char',\n 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do',\n 'double', 'else', 'enum', 'export', 'extends', 'false', 'final',\n 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements',\n 'import', 'in', 'instanceof', 'int', 'interface', 'long', 'native',\n 'new', 'null', 'package', 'private', 'protected', 'public', 'return',\n 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw',\n 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void',\n 'volatile', 'while', 'with']\n ],\n literals: [\n [syntaxify.regexpSingleQuotedString.source],\n [syntaxify.regexpDoubleQuotedString.source],\n ["\s\sb\s\sd+(?:\s\s.\s\sd+(?:[eE][\s\s+-]\s\sd+)?)?\s\sb"] // Numbers\n ],\n delimiters: [["[\s\s{\s\s}]"],["[\s\s(\s\s)]"],["[\s\s[\s\s]]"]]\n}, \ncss: {\n multiLineComments: [[syntaxify.regexpCMultiLineComment.source]],\n keywords: [\n // Keywords appearing on the LHS of expressions\n ['ascent', 'azimuth', 'background-attachment', 'background-color',\n 'background-image', 'background-position', 'background-repeat',\n 'background', 'baseline', 'bbox', 'border-collapse', 'border-color',\n 'border-spacing', 'border-style', 'border-top', 'border-right',\n 'border-bottom', 'border-left', 'border-top-color',\n 'border-right-color', 'border-bottom-color', 'border-left-color',\n 'border-top-style', 'border-right-style', 'border-bottom-style',\n 'border-left-style', 'border-top-width', 'border-right-width',\n 'border-bottom-width', 'border-left-width', 'border-width', 'border',\n 'bottom', 'cap-height', 'caption-side', 'centerline', 'clear', 'clip',\n 'color', 'content', 'counter-increment', 'counter-reset', 'cue-after',\n 'cue-before', 'cue', 'cursor', 'definition-src', 'descent',\n 'direction', 'display', 'elevation', 'empty-cells', 'float',\n 'font-size-adjust', 'font-family', 'font-size', 'font-stretch',\n 'font-style', 'font-variant', 'font-weight', 'font', 'height', 'left',\n 'letter-spacing', 'line-height', 'list-style-image',\n 'list-style-position', 'list-style-type', 'list-style', 'margin-top',\n 'margin-right', 'margin-bottom', 'margin-left', 'margin',\n 'marker-offset', 'marks', 'mathline', 'max-height', 'max-width',\n 'min-height', 'min-width', 'orphans', 'outline-color',\n 'outline-style', 'outline-width', 'outline', 'overflow', 'padding-top',\n 'padding-right', 'padding-bottom', 'padding-left', 'padding', 'page',\n 'page-break-after', 'page-break-before', 'page-break-inside', 'pause',\n 'pause-after', 'pause-before', 'pitch', 'pitch-range', 'play-during',\n 'position', 'quotes', 'richness', 'right', 'size', 'slope', 'src',\n 'speak-header', 'speak-numeral', 'speak-punctuation', 'speak',\n 'speech-rate', 'stemh', 'stemv', 'stress', 'table-layout',\n 'text-align', 'text-decoration', 'text-indent', 'text-shadow',\n 'text-transform', 'unicode-bidi', 'unicode-range', 'units-per-em',\n 'vertical-align', 'visibility', 'voice-family', 'volume',\n 'white-space', 'widows', 'width', 'widths', 'word-spacing', 'x-height',\n 'z-index'],\n // Treat !important as a different kind of keyword\n ["important"]\n ],\n literals: [\n // Literals appearing on the RHS of expressions\n ['above', 'absolute', 'all', 'always', 'aqua', 'armenian', 'attr',\n 'aural', 'auto', 'avoid', 'baseline', 'behind', 'below',\n 'bidi-override', 'black', 'blink', 'block', 'blue', 'bold', 'bolder',\n 'both', 'bottom', 'braille', 'capitalize', 'caption', 'center',\n 'center-left', 'center-right', 'circle', 'close-quote', 'code',\n 'collapse', 'compact', 'condensed', 'continuous', 'counter',\n 'counters', 'crop', 'cross', 'crosshair', 'cursive', 'dashed',\n 'decimal', 'decimal-leading-zero', 'default', 'digits', 'disc',\n 'dotted', 'double', 'embed', 'embossed', 'e-resize', 'expanded',\n 'extra-condensed', 'extra-expanded', 'fantasy', 'far-left',\n 'far-right', 'fast', 'faster', 'fixed', 'format', 'fuchsia', 'gray',\n 'green', 'groove', 'handheld', 'hebrew', 'help', 'hidden', 'hide',\n 'high', 'higher', 'icon', 'inline-table', 'inline', 'inset', 'inside',\n 'invert', 'italic', 'justify', 'landscape', 'large', 'larger',\n 'left-side', 'left', 'leftwards', 'level', 'lighter', 'lime',\n 'line-through', 'list-item', 'local', 'loud', 'lower-alpha',\n 'lowercase', 'lower-greek', 'lower-latin', 'lower-roman', 'lower',\n 'low', 'ltr', 'marker', 'maroon', 'medium', 'message-box', 'middle',\n 'mix', 'move', 'narrower', 'navy', 'ne-resize', 'no-close-quote',\n 'none', 'no-open-quote', 'no-repeat', 'normal', 'nowrap', 'n-resize',\n 'nw-resize', 'oblique', 'olive', 'once', 'open-quote', 'outset',\n 'outside', 'overline', 'pointer', 'portrait', 'pre', 'print',\n 'projection', 'purple', 'red', 'relative', 'repeat', 'repeat-x',\n 'repeat-y', 'ridge', 'right', 'right-side', 'rightwards', 'rtl',\n 'run-in', 'screen', 'scroll', 'semi-condensed', 'semi-expanded',\n 'separate', 'se-resize', 'show', 'silent', 'silver', 'slower', 'slow',\n 'small', 'small-caps', 'small-caption', 'smaller', 'soft', 'solid',\n 'speech', 'spell-out', 'square', 's-resize', 'static', 'status-bar',\n 'sub', 'super', 'sw-resize', 'table-caption', 'table-cell',\n 'table-column', 'table-column-group', 'table-footer-group',\n 'table-header-group', 'table-row', 'table-row-group', 'teal',\n 'text-bottom', 'text-top', 'thick', 'thin', 'top', 'transparent',\n 'tty', 'tv', 'ultra-condensed', 'ultra-expanded', 'underline',\n 'upper-alpha', 'uppercase', 'upper-latin', 'upper-roman', 'url',\n 'visible', 'wait', 'white', 'wider', 'w-resize', 'x-fast', 'x-high',\n 'x-large', 'x-loud', 'x-low', 'x-slow', 'x-small', 'x-soft',\n 'xx-large', 'xx-small', 'yellow'],\n // Font literals\n ['[mM]ono(?:space)?', '[tT]ahoma', '[vV]erdana', '[aA]rial',\n '[hH]elvetica', '[sS]ans(?:-serif)?', '[sS]erif', '[Cc]ourier'],\n // Measurement literals\n ["\s\sb\s\sd+(?:\s\s.\s\sd+)?(?:em|pt|px|cm|in|pc|mm)\s\sb"],\n // Color literals\n ['(?:\s\s#[a-fA-F0-9]{6}\s\sb|\s\s#[a-fA-F0-9]{3}\s\sb|rgb\s\s(\s\ss*\s\sd+\s\ss*,\s\ss*\s\sd+\s\ss*,\s\ss*\s\sd+\s\ss*\s\s))']\n ],\n identifiers: [["\s\s.[a-zA-Z_]\s\sw*"],["\s\s#[a-zA-Z_]\s\sw*"]],\n delimiters: [["[\s\s{\s\s}]"]]\n}, \nxml: {\n multiLineComments: [\n ["<[^!>]*!--\s\ss*(?:(?:.|(?:\s\sr)?\s\sn)(?!--))*?(?:(?:.|(?:\s\sr)?\s\sn)(?=--))?\s\ss*--[^>]*?>"],\n ['<\s\s!\s\s[[\s\sw\s\ss]*?\s\s[(?:(?:.|(?:\s\sr)?\s\sn)(?!\s\s]\s\s]>))*?(?:(?:.|(?:\s\sr)?\s\sn)(?=\s\s]\s\s]>))?\s\s]\s\s]>']\n ],\n customFormatters: [{\n name: "tag",\n match: "<[/\s\s?]?[^>]*?>",\n handler: function(w) {\n var formatter = new Formatter(syntaxify.xmlTagFormatters);\n var wikifier = new Wikifier(w.matchText, formatter, w.highlightRegExp, w.tiddler);\n wikifier.subWikify(w.output, null);\n }\n }]\n}};\n\nconfig.formatterHelpers.customClassesHelper = function(w) {\n var lookaheadRegExp = (typeof(this.lookaheadRegExp) == "undefined")?(new RegExp(this.lookahead,"mg")):this.lookaheadRegExp;\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source);\n var language = (typeof(this.language) == "undefined")?lookaheadMatch[1]:this.language;\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n var isByLine = (typeof(this.byLine) == "undefined")?(lookaheadMatch[2] == "\sn"):this.byLine;\n var p = createTiddlyElement(w.output,isByLine ? "div" : "span",null,language);\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n if(typeof(syntaxify.formatters[language]) != "undefined") {\n var d = createTiddlyElement(w.output,isByLine?"div":"span",\n null,"syntaxify "+language);\n var formatter = new Formatter(syntaxify.formatters[language]);\n if(typeof(this.termRegExp) == "undefined") {\n var text = lookaheadMatch[1]; \n } else {\n this.termRegExp.lastIndex = w.nextMatch;\n var terminatorMatch = this.termRegExp.exec(w.source);\n var text = w.source.substr(w.nextMatch, terminatorMatch.index-w.nextMatch);\n }\n if(config.browser.isIE) text = text.replace(/\sn/g,"\sr"); \n if (isByLine) {\n var l = createTiddlyElement(d,"ol");\n var li = createTiddlyElement(l,"li");\n var wikifier = new Wikifier(text, formatter, w.highlightRegExp, w.tiddler);\n wikifier.subWikify(li, null);\n if(!l.childNodes[l.childNodes.length-1].hasChildNodes())\n l.removeChild(l.childNodes[l.childNodes.length-1]);\n } else {\n var wikifier = new Wikifier(text,formatter,w.highlightRegExp,w.tiddler);\n wikifier.subWikify(d, null);\n }\n if(typeof(this.termRegExp) != "undefined")\n w.nextMatch = terminatorMatch.index + terminatorMatch[0].length;\n else\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length; \n } else {\n if(isByLine)\n var e = createTiddlyElement(w.output,"code",null,null,text); \n else\n var e = createTiddlyElement(w.output,"pre",null,null,text); \n }\n }\n}\n\nsyntaxify.formatters = {};\n\nsyntaxify.addLanguages = function(languages) {\n for(lang in languages) {\n syntaxify.formatters[lang] = new Array();\n for(var i=0;i<syntaxify.commonFormatters.length;i++)\n syntaxify.formatters[lang].push(syntaxify.commonFormatters[i]);\n var addSpanClass = function(rule, spaces, wordbreak) {\n if(typeof(languages[lang][rule]) != "undefined") {\n for(var j=0;j<languages[lang][rule].length;j++) {\n syntaxify.formatters[lang].push({\n name: rule+((j==0)?"":j),\n match: wordbreak?("(?:\s\sb"+languages[lang][rule][j].join("\s\sb|\s\sb")+"\s\sb)")\n :("(?:"+languages[lang][rule][j].join("|")+")"),\n hasSpaces: spaces,\n handler: syntaxify.handleSpanClass\n });\n }\n }\n };\n addSpanClass("singleLineComments", true, false);\n addSpanClass("multiLineComments", true, false);\n addSpanClass("keywords", false, true);\n addSpanClass("literals", true, false);\n addSpanClass("delimiters", false, false);\n addSpanClass("identifiers", false, false);\n if(typeof(languages[lang].customFormatters) != "undefined") \n syntaxify.formatters[lang] = syntaxify.formatters[lang].concat(languages[lang].customFormatters);\n }\n}\n\nsyntaxify.addLanguages(syntaxify.languages);\n\n// Override the several built-in TiddlyWiki language-specific <pre> formatters\nfor(var i=0;i<config.formatters.length;i++) { \n if(config.formatters[i].name == "monospacedByLineForPlugin") { \n config.formatters[i].language = "javascript";\n config.formatters[i].byLine = true;\n config.formatters[i].handler = config.formatterHelpers.customClassesHelper; \n } \n if(config.formatters[i].name == "monospacedByLineForCSS") { \n config.formatters[i].language = "css";\n config.formatters[i].byLine = true;\n config.formatters[i].handler = config.formatterHelpers.customClassesHelper; \n } \n if(config.formatters[i].name == "monospacedByLineForTemplate") { \n config.formatters[i].language = "xml";\n config.formatters[i].byLine = true;\n config.formatters[i].handler = config.formatterHelpers.customClassesHelper; \n } \n if(config.formatters[i].name == "customClasses") {\n config.formatters[i].handler = config.formatterHelpers.customClassesHelper; \n if(typeof(config.formatters[i].termRegExp) == "undefined")\n config.formatters[i].termRegExp = new RegExp(config.formatters[i].terminator, "mg");\n }\n}\n\n// make syntaxify reliably accessible from dependent plugins even under IE.\nconfig.macros.syntaxify = syntaxify;\n//}}}\n
/***\n|Author|[[Conal Elliott|http://conal.net]]|\n|Date|2007-01-28|\n|Version|1.1|\n|LoadDependencies|SyntaxifyPlugin|\n|''Source:''|http://journal.conal.net/#%5B%5BSyntaxifyPlugin%3A%20Haskell%5D%5D|\n!Description\nAdd support for [[Haskell| http://haskell.org]] syntax highlighting, as an extension to SyntaxifyPlugin.\n!Use\n{{{\n{{haskell{\n<haskell code goes here>\n}}} \n}}}\nor <html><code>{{haskell{inline code}}}</code></html>.\n!Example\n{{haskell{\n-- Define the data types and conversion:\ntype Line = String\n\nsilly :: Line -> Line\nsilly src = src ++ toU " oho " ++ reverse src\n where\n toU = map toUpper\n}}}\nor {{haskell{if foo then "bar" else "baz"}}}.\n!History\n* Version 1.1\n** Smarter {{haskell{identifiers}}} pattern, to avoid false hits for expressions (especially in-line).\n** {{haskell{{- Multi-line comments -} }}} \n!To Do\n* Type coloring.\n!See Also\n* SyntaxifyPlugin\n* [[RewritePlugin: Haskell]] for a more convenient notation (especially with literate Haskell programming).\n!Code\n***/\n//{{{\nversion.extensions.syntaxifyHaskell =\n {major: 1, minor: 1, revision: 0, date: new Date(2007,1,28)};\n\nconfig.macros.syntaxify.addLanguages({\n haskell:\n { singleLineComments: [[new RegExp('-- .*$', "g").source]]\n , keywords: \n [ [ 'as', 'case', 'class', 'data', 'default'\n , 'deriving', 'do', 'else', 'forall', 'hiding', 'if'\n , 'import', 'in', 'infix', 'infixl', 'infixr'\n , 'instance', 'let', 'module', 'newtype', 'of'\n , 'qualified', 'then', 'type', 'where', '_'\n ]\n , ["\s\sb[A-Z][a-zA-Z0-9]*\s\sb"] \n ]\n , literals:\n [ ["'(?:\s\s\s\s.|[^\s\s\s\s'])'"] // char literals\n , [config.macros.syntaxify.regexpDoubleQuotedString.source]\n , ["\s\sb\s\sd+(?:\s\s.\s\sd+(?:[eE][\s\s+-]\s\sd+)?)?\s\sb"] // Numbers\n ]\n // def or decl. id in "id ... = ..." or "id :: ...". Ids can have tick marks.\n // The "..." must not contain symbols. (Not strictly true in Haskell, but too hard\n // to describe fully with regexps.)\n , identifiers: [["^[a-z][a-zA-Z0-9']*\s\sb'*(?=(?:[^=<>:+-]*=|\s\ss*::)[^=<>:+-])"]]\n , delimiters: [/*["[\s\s{\s\s}]"],*/["[\s\s(\s\s)]"],["[\s\s[\s\s]]"]]\n , multiLineComments: [["{-(?:.|\sn)*?-}"]]\n }\n});\n//}}}\n
a syntax highlighting plugin for TiddlyWiki
[[Plugin: Syntaxify]]
/***\nPlace your custom CSS here\n***/\n/*{{{*/\n\n.shell {\n font-family: monospace;\n font-size: 85%;\n}\n#output { \n white-space: pre; \n white-space: -moz-pre-wrap; \n} /* Preserve line breaks, but wrap too if browser supports it */\n#input { \n width: 100%; \n/* height: 1.4em; */\n border: none; \n padding: 0; \n overflow: auto; \n}\n.shell .input { \n font-family: mono; \n color: blue; \n font: inherit; \n margin-top: .5em;\n background: #E6E6FF; \n}\n.shell .normalOutput { \n font-family: mono; \n color: black; \n background: white; \n}\n.shell .print { color: brown; background: white; }\n.shell .error { color: red; background: white; }\n.shell .propList { color: green; background: white; }\n.shell .message { color: green; background: white; }\n.shell .tabcomplete { color: purple; background: white; }\n/*}}}*/\n
[[Plugin: Syntaxify]] syntax-highlights CSS, XML, and Javascript in your tiddlywiki, using the tiddlywiki Wikifier. Take a look at the tiddlers below. Then see [[Plugin: Syntaxify]] for the code to install. It can be easily extended for new languages by just specifying your favorite language's keywords, literals, etc. See [[Plugin: Syntaxify Haskell]] for an example (thanks to Conal Elliott).\n\n!CSS markup:\n# StyleSheetColors\n# StyleSheetLayout\n# StyleSheetPrint\n# StyleSheetSyntaxify\n{{css{\n#foo .bar { color: red; margin-left: 1em; }\n}}}\n!XML markup:\n# EditTemplate\n# PageTemplate\n# ViewTemplate\n{{xml{\n<tag foo="bar" />\n}}}\n!Javascript markup:\n# [[Plugin: Syntaxify]]\n{{javascript{\nvar mangle = function(x) { return x.replace("foo","bar"); };\n}}}