Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
/***\n|Name|BreadcrumbsPlugin|\n|Author|Eric Shulman|\n|Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|\n|Documentation|http://www.TiddlyTools.com/#BreadcrumbsPluginInfo|\n|Version|2.1.5|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|plugin|\n|Description|list/jump to tiddlers viewed during this session plus "back" button/macro|\nThis plugin provides a list of links to all tiddlers opened during the session, creating a "trail of breadcrumbs" from one tiddler to the next, allowing you to quickly navigate to any previously viewed tiddler, or select 'home' to reset the display to the initial set of tiddlers that were open at the start of the session (i.e., when the document was loaded into the browser).\n!Documentation\n<<<\nsee [[BreadcrumbsPluginInfo]]\n<<<\n!!!Configuration\n<<<\n<<option chkCreateDefaultBreadcrumbs>> automatically create breadcrumbs display (if needed)\n<<option chkShowBreadcrumbs>> show/hide breadcrumbs display\n<<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler\n<<option chkBreadcrumbsHideHomeLink>> omit 'Home' link from breadcrumbs display\n<<option chkBreadcrumbsSave>> prompt to save breadcrumbs when 'Home' link is pressed\n<<option chkShowStartupBreadcrumbs>> show breadcrumbs for 'startup' tiddlers\n<<option chkBreadcrumbsReverse>> show breadcrumbs in reverse order (most recent first)\n<<option chkBreadcrumbsLimit>> limit breadcrumbs display to {{twochar{<<option txtBreadcrumbsLimit>>}}} items\n<<option chkBreadcrumbsLimitOpenTiddlers>> limit open tiddlers to {{twochar{<<option txtBreadcrumbsLimitOpenTiddlers>>}}} items\n\n<<<\n!!!Revisions\n<<<\n2012.06.10 2.1.5 refactored default options to eliminate global variable and use init() handling\n| Please see [[BreadcrumbsPluginInfo]] for previous revision details |\n2006.02.01 1.0.0 initial release\n<<<\n!!!Code\n***/\n//{{{\nversion.extensions.BreadcrumbsPlugin = { major: 2, minor: 1, revision: 5, date: new Date(2012,6,10) };\nconfig.macros.breadcrumbs = {\n crumbs: [], // the list of current breadcrumbs\n askMsg: "Save current breadcrumbs before clearing?\sn"\n +"Press OK to save, or CANCEL to continue without saving.",\n saveMsg: 'Enter the name of a tiddler in which to save the current breadcrumbs',\n saveTitle: 'SavedBreadcrumbs',\n options: {\n chkShowBreadcrumbs: true,\n chkReorderBreadcrumbs: true,\n chkCreateDefaultBreadcrumbs: true,\n chkShowStartupBreadcrumbs: false,\n chkBreadcrumbsReverse: false,\n chkBreadcrumbsLimit: false,\n txtBreadcrumbsLimit: 5,\n chkBreadcrumbsLimitOpenTiddlers:false,\n txtBreadcrumbsLimitOpenTiddlers:5,\n chkBreadcrumbsHideHomeLink: false,\n chkBreadcrumbsSave: false,\n txtBreadcrumbsHomeSeparator: ' | ',\n txtBreadcrumbsCrumbSeparator: ' > '\n },\n init: function() {\n merge(config.options,this.options,true);\n },\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var area=createTiddlyElement(place,"span",null,"breadCrumbs",null);\n area.setAttribute("homeSep",params[0]||config.options.txtBreadcrumbsHomeSeparator);\n area.setAttribute("crumbSep",params[1]||config.options.txtBreadcrumbsCrumbSeparator);\n this.render(area);\n },\n add: function (title) {\n var thisCrumb = title;\n var ind = this.crumbs.indexOf(thisCrumb);\n if(ind === -1)\n this.crumbs.push(thisCrumb);\n else if (config.options.chkReorderBreadcrumbs)\n this.crumbs.push(this.crumbs.splice(ind,1)[0]); // reorder crumbs\n else\n this.crumbs=this.crumbs.slice(0,ind+1); // trim crumbs\n if (config.options.chkBreadcrumbsLimitOpenTiddlers)\n this.limitOpenTiddlers();\n this.refresh();\n return false;\n },\n getAreas: function() {\n var crumbAreas=[];\n // find all DIVs with classname=="breadCrumbs"\n var all=document.getElementsByTagName("*");\n for (var i=0; i<all.length; i++)\n try{ if (hasClass(all[i],"breadCrumbs")) crumbAreas.push(all[i]); } catch(e) {;}\n // or, find single DIV w/fixed ID (backward compatibility)\n var byID=document.getElementById("breadCrumbs")\n if (byID && !hasClass(byID,"breadCrumbs")) crumbAreas.push(byID);\n if (!crumbAreas.length && config.options.chkCreateDefaultBreadcrumbs) {\n // no crumbs display... create one\n var defaultArea = createTiddlyElement(null,"span",null,"breadCrumbs",null);\n defaultArea.style.display= "none";\n var targetArea= document.getElementById("tiddlerDisplay");\n targetArea.parentNode.insertBefore(defaultArea,targetArea);\n crumbAreas.push(defaultArea);\n }\n return crumbAreas;\n },\n refresh: function() {\n var crumbAreas=this.getAreas();\n for (var i=0; i<crumbAreas.length; i++) {\n crumbAreas[i].style.display = config.options.chkShowBreadcrumbs?"inline":"none";\n removeChildren(crumbAreas[i]);\n this.render(crumbAreas[i]);\n }\n },\n render: function(here) {\n var co=config.options; var out=""\n if (!co.chkBreadcrumbsHideHomeLink) {\n createTiddlyButton(here,"Home",null,this.home,"tiddlyLink tiddlyLinkExisting");\n out+=here.getAttribute("homeSep")||config.options.txtBreadcrumbsHomeSeparator;\n }\n for (c=0; c<this.crumbs.length; c++) // remove non-existing tiddlers from crumbs\n if (!store.tiddlerExists(this.crumbs[c]) && !store.isShadowTiddler(this.crumbs[c]))\n this.crumbs.splice(c,1);\n var count=this.crumbs.length;\n if (co.chkBreadcrumbsLimit && co.txtBreadcrumbsLimit<count) count=co.txtBreadcrumbsLimit;\n var list=[];\n for (c=this.crumbs.length-count; c<this.crumbs.length; c++) list.push('[['+this.crumbs[c]+']]');\n if (co.chkBreadcrumbsReverse) list.reverse();\n out+=list.join(here.getAttribute("crumbSep")||config.options.txtBreadcrumbsCrumbSeparator);\n wikify(out,here);\n },\n home: function() {\n var cmb=config.macros.breadcrumbs;\n if (config.options.chkBreadcrumbsSave && confirm(cmb.askMsg)) cmb.saveCrumbs();\n story.closeAllTiddlers(); restart();\n cmb.crumbs = []; var crumbAreas=cmb.getAreas();\n for (var i=0; i<crumbAreas.length; i++) crumbAreas[i].style.display = "none";\n return false;\n },\n saveCrumbs: function() {\n var tid=prompt(this.saveMsg,this.saveTitle); if (!tid||!tid.length) return; // cancelled by user\n var t=store.getTiddler(tid);\n if(t && !confirm(config.messages.overwriteWarning.format([tid]))) return;\n var who=config.options.txtUserName;\n var when=new Date();\n var text='[['+this.crumbs.join(']]\sn[[')+']]';\n var tags=t?t.tags:[]; tags.pushUnique('story');\n var fields=t?t.fields:{};\n store.saveTiddler(tid,tid,text,who,when,tags,fields);\n story.displayTiddler(null,tid);\n story.refreshTiddler(tid,null,true);\n displayMessage(tid+' has been '+(t?'updated':'created'));\n },\n limitOpenTiddlers: function() {\n var limit=config.options.txtBreadcrumbsLimitOpenTiddlers; if (limit<1) limit=1;\n for (c=this.crumbs.length-1; c>=0; c--) {\n var tid=this.crumbs[c];\n var elem=story.getTiddler(tid);\n if (elem) { // tiddler is displayed\n if (limit <=0) { // display limit has been reached\n if (elem.getAttribute("dirty")=="true") { // tiddler is being edited\n var msg= "'"+tid+"' is currently being edited.\sn\sn"\n +"Press OK to save and close this tiddler\sn"\n +"or press Cancel to leave it opened";\n if (confirm(msg)) {\n story.saveTiddler(tid);\n story.closeTiddler(tid);\n }\n }\n else story.closeTiddler(this.crumbs[c]);\n }\n limit--;\n }\n }\n }\n};\n//}}}\n// // PreviousTiddler ('back') command and macro\n//{{{\nconfig.commands.previousTiddler = {\n text: 'back',\n tooltip: 'view the previous tiddler',\n handler: function(event,src,title) {\n var crumbs=config.macros.breadcrumbs.crumbs;\n if (crumbs.length<2) config.macros.breadcrumbs.home();\n else story.displayTiddler(story.findContainingTiddler(src),crumbs[crumbs.length-2]);\n return false;\n }\n};\nconfig.macros.previousTiddler= {\n label: 'back',\n prompt: 'view the previous tiddler',\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var label=params.shift(); if (!label) label=this.label;\n var prompt=params.shift(); if (!prompt) prompt=this.prompt;\n createTiddlyButton(place,label,prompt,function(ev){\n return config.commands.previousTiddler.handler(ev,this)\n });\n }\n}\n//}}}\n// // HIJACKS\n//{{{\n// update crumbs when a tiddler is displayed\nif (Story.prototype.breadCrumbs_coreDisplayTiddler==undefined)\n Story.prototype.breadCrumbs_coreDisplayTiddler=Story.prototype.displayTiddler;\nStory.prototype.displayTiddler = function(srcElement,tiddler) {\n var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;\n this.breadCrumbs_coreDisplayTiddler.apply(this,arguments);\n if (!startingUp || config.options.chkShowStartupBreadcrumbs)\n config.macros.breadcrumbs.add(title);\n}\n\n// update crumbs when a tiddler is deleted\nif (TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler==undefined)\n TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler=TiddlyWiki.prototype.removeTiddler;\nTiddlyWiki.prototype.removeTiddler= function() {\n this.breadCrumbs_coreRemoveTiddler.apply(this,arguments);\n config.macros.breadcrumbs.refresh();\n}\n//}}}
!CSS\nCSS, which stands for Cascading Style Sheets, is a stylesheet language used to describe the presentation and styling of a document written in HTML or XML.\nIt was invented by Håkon Wium Lie and Bert Bos in 1996 as a way to separate the structure and content of a webpage from its visual appearance.\n\nCSS provides a set of rules that define how elements within a webpage should be displayed. These rules can be applied to specific HTML elements or groups of elements, allowing for consistent and efficient styling across multiple pages. CSS works in a cascading manner, meaning that multiple styles can be applied to an element, and the most specific rule takes precedence.\nCSS rules consist of a selector and a declaration block. The selector targets the HTML element(s) to which the styles should be applied, while the declaration block contains one or more property-value pairs. For example, the CSS rule "h1 { color: blue; }" targets all elements and sets their color to blue.\n\nCSS offers a wide range of properties to control various aspects of the webpage's appearance, including font styles, colors, margins, padding, borders, backgrounds, and positioning. It also allows for the creation of responsive designs that adapt to different screen sizes and devices.\nWith CSS, developers can create reusable styles by defining classes and IDs, which can be applied to multiple elements throughout the webpage. This helps maintain consistency and simplifies the process of updating styles across the site.\n\nOver the years, CSS has evolved to include more advanced features and capabilities. CSS3, the latest version of CSS, introduced new properties like gradients, animations, transitions, and flexible box layouts, providing even more flexibility and creativity for web designers.\nCSS plays a crucial role in web development, allowing designers and developers to separate the structure and content of a webpage from its visual presentation. This separation improves maintainability, flexibility, and accessibility, making it easier to update and modify the design of a website without affecting its underlying structure.
!Primary colors are modified\nBackground: #FFFFFF\nForeground: #000000\nPrimaryPale: #789FD6\nPrimaryLight: #2c5bbf\nPrimaryMid: #003599\nPrimaryDark: #00007A\nSecondaryPale: #FFFFCC\nSecondaryLight: #FFEE88\nSecondaryMid: #d2b341\nSecondaryDark: #884411\nTertiaryPale: #EEEEEE\nTertiaryLight: #D6D6D6\nTertiaryMid: #878787\nTertiaryDark: #474747\nPureSuccessPale: #81ee9b\nPureSuccessLight: #2fd055\nPureSuccessMid: #00801c\nPureSuccessDark: #015b04\nPureWarningPale: #ffc367\nPureWarningLight: #ffa242\nPureWarningMid: #db730a\nPureWarningDark: #a84c00\nPureSecondaryMid: #1790b5\nPureSecondaryDark: #02617e\nPureErrorPale: #f09898\nPureErrorLight: #ee5353\nPureErrorMid: #e01717\nPureErrorDark: #930606\nError: #ff0000
[[Welcome]]
!HTML\nHTML, which stands for HyperText Markup Language, was invented by Tim Berners-Lee in 1989 while he was working at CERN (European Organization for Nuclear Research).\nBerners-Lee, often referred to as the inventor of the World Wide Web, developed HTML as a markup language to structure and link documents on the web. The first version of HTML, known as HTML 1.0, was released in 1991 and provided basic elements for structuring web pages.\n\nSince its inception, HTML has undergone several revisions and updates. HTML 2.0 was released in 1995, followed by HTML 3.2 in 1997, HTML 4.01 in 1999, and XHTML 1.0 in 2000.\nThese versions introduced new features, improved functionality, and stricter syntax rules.\n\nHTML5, the current and fifth major version of HTML, was first published as a working draft in 2008 and reached its official recommendation status in October 2014.\nHTML5 introduced many new elements, attributes, and APIs that significantly enhanced the capabilities of web development. It introduced multimedia support, native video and audio elements, canvas for drawing graphics, improved form controls, and better support for mobile devices.\n\nSince its inception, HTML has played a crucial role in the development of the World Wide Web, serving as the foundation for creating and structuring web pages. It has become the standard markup language used by web developers worldwide and continues to evolve with new features and standards to meet the demands of modern web development.\n
<<tiddler HideTiddlerTitle>><<tiddler HideTiddlerSubtitle>><<tiddler HideTiddlerToolbar>><<tiddler HideTiddlerTags>>
/%\n|Name|HideTiddlerSubtitle|\n|Source|http://www.TiddlyTools.com/#HideTiddlerSubtitle|\n|Version|0.0.0|\n|Author|Eric Shulman - ELS Design Studios|\n|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|~CoreVersion|2.1|\n|Type|script|\n|Requires|InlineJavascriptPlugin|\n|Overrides||\n|Description|hide a tiddler's subtitle (dates/created by) display|\n\nUsage: <<tiddler HideTiddlerSubtitle>>\n\n%/<script>\n var t=story.findContainingTiddler(place);\n if (!t || t.id=="tiddlerHideTiddlerSubtitle") return;\n var nodes=t.getElementsByTagName("*");\n for (var i=0; i<nodes.length; i++)\n if (hasClass(nodes[i],"subtitle"))\n nodes[i].style.display="none";\n</script>
/%\n!info\n|Name|HideTiddlerTags|\n|Source|http://www.TiddlyTools.com/#HideTiddlerTags|\n|Version|2.0.1|\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|transclusion|\n|Description|hide a tiddler's 'tagged' and 'tagging' displays (if any)|\nUsage:\n<<<\n{{{\n<<tiddler HideTiddlerTags>>\n<<tiddler HideTiddlerTags with: TiddlerTitle>>\n}}}\n<<<\n!end\n!show\n<<tiddler {{\n var title="$1";\n if (title=='$'+'1') {\n var here=story.findContainingTiddler(place);\n if (here) title=here.getAttribute('tiddler');\n }\n var t=story.getTiddler(title); if (t) {\n var e=t.getElementsByTagName('*');\n for (var i=0; i<e.length; i++)\n if (hasClass(e[i],'tagging')||hasClass(e[i],'tagged'))\n e[i].style.display='none';\n }\n'';}}>>\n!end\n%/<<tiddler {{\n var src='HideTiddlerTags';\n src+(tiddler&&tiddler.title==src?'##info':'##show');}}\nwith: [[$1]]>>
/%\n!info\n|Name|HideTiddlerTitle|\n|Source|http://www.TiddlyTools.com/#HideTiddlerTitle|\n|Version|2.0.1|\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|transclusion|\n|Description|hide a tiddler's title and subtitle (date and author)|\nUsage:\n<<<\n{{{\n<<tiddler HideTiddlerTitle>>\n<<tiddler HideTiddlerTitle with: TiddlerTitle>>\n}}}\n<<<\n!end\n!show\n<<tiddler {{\n var title="$1";\n if (title=='$'+'1')\n title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';\n var t=story.getTiddler(title); if (t) {\n var e=t.getElementsByTagName('*');\n for (var i=0; i<e.length; i++)\n if (hasClass(e[i],'title')||hasClass(e[i],'subtitle')) e[i].style.display='none';\n }\n'';}}>>\n!end\n%/<<tiddler {{\n var src='HideTiddlerTitle';\n src+(tiddler&&tiddler.title==src?'##info':'##show');}}\nwith: [[$1]]>>
/%\n!info\n|Name|HideTiddlerToolbar|\n|Source|http://www.TiddlyTools.com/#HideTiddlerToolbar|\n|Version|2.0.2|\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|transclusion|\n|Description|hide a tiddler's toolbar (menu commands)|\nUsage:\n<<<\n{{{\n<<tiddler HideTiddlerToolbar>>\n<<tiddler HideTiddlerToolbar with: TiddlerTitle>>\n}}}\n<<<\n!end\n\n!show\n<<tiddler {{\n var title="$1";\n if (title=='$'+'1')\n title=(story.findContainingTiddler(place)||place).getAttribute('tiddler')||'';\n var t=story.getTiddler(title); if (t) {\n var e=t.getElementsByTagName('*');\n for (var i=0; i<e.length; i++)\n if (hasClass(e[i],'toolbar')) e[i].style.display='none';\n }\n'';}}>>\n!end\n%/<<tiddler {{\n var src='HideTiddlerToolbar';\n src+(tiddler&&tiddler.title==src?'##info':'##show');\n}} with [[$1]]>>
/***\n|Name|InlineJavascriptPlugin|\n|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|\n|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|\n|Version|1.9.6|\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|plugin|\n|Description|Insert Javascript executable code directly into your tiddler content.|\n''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!Documentation\n>see [[InlineJavascriptPluginInfo]]\n!!!Revisions\n<<<\n2010.12.15 1.9.6 allow (but ignore) type="..." syntax\n|please see [[InlineJavascriptPluginInfo]] for additional revision details|\n2005.11.08 1.0.0 initial release\n<<<\n!!!Code\n***/\n//{{{\nversion.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 6, date: new Date(2010,12,15)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: type=\s\s\s"[^\s\s\s"]*\s\s\s")?(?: src=\s\s\s"([^\s\s\s"]*)\s\s\s")?(?: label=\s\s\s"([^\s\s\s"]*)\s\s\s")?(?: title=\s\s\s"([^\s\s\s"]*)\s\s\s")?(?: key=\s\s\s"([^\s\s\s"]*)\s\s\s")?( show)?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\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 src=lookaheadMatch[1];\n var label=lookaheadMatch[2];\n var tip=lookaheadMatch[3];\n var key=lookaheadMatch[4];\n var show=lookaheadMatch[5];\n var code=lookaheadMatch[6];\n if (src) { // external script library\n var script = document.createElement("script"); script.src = src;\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (code) { // inline code\n if (show) // display source in tiddler\n wikify("{{{\sn"+lookaheadMatch[0]+"\sn}}}\sn",w.output);\n if (label) { // create 'onclick' command link\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));\n var fixup=code.replace(/document.write\ss*\s(/gi,'place.bufferedHTML+=(');\n link.code="function _out(place,tiddler){"+fixup+"\sn};_out(this,this.tiddler);"\n link.tiddler=w.tiddler;\n link.onclick=function(){\n this.bufferedHTML="";\n try{ var r=eval(this.code);\n if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)\n var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);\n if(this.bufferedHTML.length)\n s.innerHTML=this.bufferedHTML;\n if((typeof(r)==="string")&&r.length) {\n wikify(r,s,null,this.tiddler);\n return false;\n } else return r!==undefined?r:false;\n } catch(e){alert(e.description||e.toString());return false;}\n };\n link.setAttribute("title",tip||"");\n var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';\n URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\sn/g,' ')));\n URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';\n link.setAttribute("href",URIcode);\n link.style.cursor="pointer";\n if (key) link.accessKey=key.substr(0,1); // single character only\n }\n else { // run script immediately\n var fixup=code.replace(/document.write\ss*\s(/gi,'place.innerHTML+=(');\n var c="function _out(place,tiddler){"+fixup+"\sn};_out(w.output,w.tiddler);";\n try { var out=eval(c); }\n 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// // Backward-compatibility for TW2.1.x and earlier\n//{{{\nif (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {\n if(limit > 0) text = text.substr(0,limit);\n var wikifier = new Wikifier(text,formatter,null,tiddler);\n return wikifier.wikifyPlain();\n}\n//}}}\n\n// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()\n//{{{\nif (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }\n//}}}
!JavaScript\nJavaScript was invented in 1995 by Brendan Eich while he was working at Netscape Communications Corporation.\nInitially called "Mocha," the language was later renamed to "LiveScript" and finally to "JavaScript" to align with the popularity of Java at that time.\n\nJavaScript was developed as a scripting language for enhancing the interactivity and functionality of web pages. It quickly gained popularity and became one of the fundamental technologies used in web development. Today, JavaScript is widely used both on the client-side (in web browsers) and server-side (with technologies like Node.js) to create dynamic and interactive web applications.\n\nIt has evolved significantly over the years, with the introduction of new features and standards such as ES6 (ECMAScript 2015) and subsequent versions.\nJavaScript can manipulate and modify HTML and CSS, handle user events like button clicks, and make HTTP requests to fetch data from servers. It supports object-oriented programming and has a wide range of built-in functions and libraries. It is easy to learn and has a large and active community, making it a powerful tool for building modern web applications.\n\nJavaScript's versatility and ubiquity have made it an essential part of web development, enabling developers to create interactive user interfaces, handle data, perform animations, and communicate with servers.
!License\nThe licenses for plugins can be found in the plugins, the [[TiddlyWikiClassic]] license is included in the [[TiddlyWikiClassic]] source.\n\n!The code by Okido is licensed with:\nThe MIT License (MIT)\n\nCopyright (c) 2019 - 2025 Okido\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[[Welcome]]\n[[nwSaver-Plugin.js]]\n[[]]\n[[systemConfig|systemConfig-Tiddlers]]\n[[License]]\n[[]]\n[[TiddlyWikiClassic]]\n[[NW.js]]\n{{center{\n<script>\n wikify(`<html><div style="height: 16px"></div> ${config.macros.qbroker_logo.svg("blue", "36px", "36px", false)}</html>`, place)\n</script>}}}\n
![[NW.js]]\n[[NW.js]], formerly known as <nowiki>Node-Webkit</nowiki>, is an open-source framework that allows developers to build desktop applications using web technologies such as [[HTML]], [[CSS]], and JavaScript. It was created by Roger Wang and released by Intel in 2011. [[NW.js]] provides a unique combination of web technologies and native <nowiki>APIs</nowiki>, enabling developers to create cross-platform applications that can run on Windows, macOS, and Linux.\n\n[[NW.js]] achieves this by combining the Chromium rendering engine, which powers Google Chrome, with the Node.js runtime environment. This combination allows developers to access both web <nowiki>APIs</nowiki> and Node.js <nowiki>APIs</nowiki>, making it possible to build desktop applications with features like file system access, network communication, and system-level operations.\n\nWith [[NW.js]], developers can use their existing web development skills and tools to create desktop applications, eliminating the need to learn platform-specific languages or frameworks. They can leverage their knowledge of [[HTML]], [[CSS]], and [[JavaScript]] to create user interfaces, handle events, and apply styling. Additionally, [[NW.js]] supports popular web frameworks and libraries, such as Angular, React, and Vue.js, allowing developers to use their preferred tools for building desktop applications.\n\n[[NW.js]] also provides access to native <nowiki>APIs</nowiki> through JavaScript bindings, allowing developers to interact with the underlying operating system. This enables tasks like reading and writing files, accessing hardware devices, displaying system notifications, and more.\n\nFurthermore, [[NW.js]] offers extensive support for packaging and distributing applications. It provides tools to bundle the application's code, assets, and dependencies into an executable file or installer, making it easy to distribute the application to end-users.\n\nThe versatility of [[NW.js]] has made it popular among developers who want to create cross-platform desktop applications quickly and efficiently. It allows them to leverage their web development skills, reuse existing code, and target multiple platforms with a single codebase. [[NW.js]] has been used to build a wide range of applications, including productivity tools, media players, code editors, and more.\n\nIn summary, [[NW.js]] is a framework that enables developers to build desktop applications using web technologies. It combines the Chromium rendering engine and the Node.js runtime environment, providing access to web and native <nowiki>APIs</nowiki>. With [[NW.js]], developers can create cross-platform applications, package them for distribution, and leverage their existing web development skills.
/***\n|Title |Okido-Logo-Plugin.js |\n|Description |This plugin holds the Okido logo in 4 colors |\n|Documentation | |\n|Version |0.0.3 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |Okido-Logo-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |24-05-2025 - 21:11, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin provides the Okido logo in 4 different colors, default blue, TiddlyWikiClassic blue, green and red.\n<<qbroker_logo default 24px 24px true>><<qbroker_logo blue 24px 24px true>><<qbroker_logo green 24px 24px true>><<qbroker_logo red 24px 24px true>>\n<<<\n!!!Usage\n<<<\nBy macro call: <nowiki><<qbroker_logo blue 24px 24px true>></nowiki><<qbroker_logo blue 36px 36px true>>\nUse with the [[InlineJavascriptPlugin]] with script tags: \n{{{\n<script> wikify(config.macros.qbroker_logo.svg("red", "36px", "36px", true), place) </script>\n}}}\n<script> wikify(config.macros.qbroker_logo.svg("red", "36px", "36px", true), place) </script>\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n22-11-2024 0.0.2 Change logo name to default, red, green and blue\n09-09-2024 0.0.1 First implementation of the new svg logo's for Okido applications.\n<<<\n!!!License\n<<<\n!!License for the third party library code\nLICENSE: <nowiki>CC0</nowiki> License\nSource: Vectors and icons by https://www.svgrepo.com\nDate: 09-09-2024\n\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2025 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 24-05-2025 */\n"object"!=typeof config.macros.qbroker_logo?config.macros.qbroker_logo={}:config.macros.qbroker_logo,config.macros.qbroker_logo={init:function(){console.log("START INIT: Okido-Logo-Plugin.js")},handler:function(c,o,l,i,e,t){wikify(config.macros.qbroker_logo.svg(l[0],l[1],l[2],l[3]),c)},svg:function(c="default",o="800px",l="800px",i=!1){let e={default:{height:l,width:o,fillcolor:"#CEE8FA",linecolor:"#2D527C"},blue:{height:l,width:o,fillcolor:"#CEE8FA",linecolor:"#0035AC"},green:{height:l,width:o,fillcolor:"#8CEAAE",linecolor:"#00801C"},red:{height:l,width:o,fillcolor:"#FFAEBC",linecolor:"#d3072a"}},t=`<?xml version="1.0" encoding="iso-8859-1"?>\sx3c!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --\sx3e\sx3c!-- Modified by BK to work well with TiddlyWikiClassic, 09-09-2024 --\sx3e<svg height="${e[c].height}" width="${e[c].width}" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.999 511.999" xml:space="preserve"><path style="fill:${e[c].fillcolor};" d="M79.81,168.497c0-43.656,35.391-79.048,79.048-79.048c6.245,0,12.311,0.746,18.138,2.115\stc0.952-42.83,35.944-77.264,79.003-77.264v338.322h-97.14c-43.656,0-79.048-35.391-79.048-79.048\stc0-20.173,7.568-38.571,20.006-52.538C87.379,207.068,79.81,188.67,79.81,168.497z"/><path style="fill:${e[c].linecolor};" d="M446.486,168.497c0-51.473-41.876-93.348-93.348-93.348c-1.849,0-3.701,0.056-5.553,0.167 c-3.586-18.397-12.638-35.284-26.288-48.659C303.761,9.474,280.58,0.009,256.024,0.001c-0.009,0-0.017-0.001-0.026-0.001\stc-24.566,0-47.756,9.467-65.3,26.657c-13.649,13.375-22.701,30.263-26.288,48.66c-1.852-0.112-3.704-0.167-5.553-0.167 c-51.473,0-93.348,41.876-93.348,93.348c0,18.856,5.687,37.123,16.199,52.538c-10.512,15.415-16.199,33.682-16.199,52.538\stc0,51.473,41.876,93.348,93.348,93.348h49.376v130.778c0,7.898,6.402,14.3,14.3,14.3h66.928c7.898,0,14.3-6.402,14.3-14.3v-86.095 c0-7.898-6.402-14.3-14.3-14.3c-7.898,0-14.3,6.402-14.3,14.3v71.795h-38.328V366.921h19.163c6.458,0,9.65-3.728,10.102-4.18\stc0.003-0.003,0.007-0.006,0.01-0.009c0.003-0.003,0.004-0.004,0.007-0.007l89.415-89.414c5.584-5.584,5.584-14.639,0-20.224\stc-5.584-5.583-14.637-5.583-20.225,0l-65.009,65.009V30.24c28.198,6.486,49.74,31.652,50.406,61.64 c0.096,4.311,2.132,8.348,5.541,10.988c3.409,2.641,7.826,3.601,12.026,2.615c4.905-1.153,9.907-1.736,14.868-1.736\stc35.701,0,64.747,29.046,64.747,64.748c0,15.882-5.819,31.164-16.385,43.029c-4.826,5.421-4.826,13.599,0,19.02 c10.566,11.865,16.385,27.146,16.385,43.029c0,35.703-29.046,64.748-64.748,64.748h-19.206c-7.898,0-14.3,6.402-14.3,14.3 s6.402,14.3,14.3,14.3h19.206c51.473,0,93.348-41.876,93.348-93.348c0-18.856-5.689-37.124-16.199-52.538 C440.799,205.621,446.486,187.353,446.486,168.497z M158.859,338.322c-3.348,0-6.635-0.255-9.847-0.748\stc-31.045-4.758-54.901-31.646-54.901-64.001c0-12.904,3.841-25.411,10.95-36.013c1.64-2.447,3.455-4.792,5.435-7.016 c4.826-5.421,4.826-13.599,0-19.02c-10.566-11.865-16.385-27.147-16.385-43.029c0-35.701,29.046-64.748,64.748-64.748\stc1.836,0,3.678,0.107,5.518,0.266c3.132,0.27,6.261,0.745,9.349,1.47c4.2,0.985,8.616,0.024,12.026-2.615 c3.409-2.64,5.445-6.677,5.541-10.988c0.023-1.021,0.074-2.036,0.144-3.044c0.023-0.329,0.059-0.654,0.086-0.981\stc0.059-0.681,0.122-1.361,0.2-2.036c0.044-0.38,0.099-0.758,0.15-1.137c0.084-0.621,0.176-1.238,0.277-1.853 c0.064-0.389,0.133-0.776,0.204-1.163c0.113-0.609,0.236-1.214,0.366-1.818c0.08-0.372,0.159-0.744,0.246-1.113 c0.15-0.639,0.315-1.273,0.483-1.905c0.086-0.322,0.166-0.645,0.256-0.965c0.24-0.844,0.498-1.682,0.771-2.511 c0.033-0.099,0.06-0.199,0.093-0.297c0.309-0.924,0.642-1.838,0.991-2.743c0.113-0.293,0.237-0.581,0.355-0.872 c0.246-0.612,0.496-1.221,0.761-1.823c0.152-0.343,0.31-0.684,0.466-1.025c0.25-0.545,0.506-1.088,0.772-1.624 c0.173-0.349,0.349-0.695,0.528-1.041c0.272-0.526,0.552-1.047,0.838-1.564c0.184-0.335,0.369-0.671,0.561-1.002\stc0.31-0.539,0.632-1.07,0.957-1.599c0.18-0.293,0.356-0.591,0.541-0.882c0.419-0.658,0.852-1.306,1.293-1.948\stc0.104-0.15,0.202-0.306,0.306-0.456c0.548-0.782,1.113-1.549,1.692-2.305c0.184-0.242,0.379-0.475,0.568-0.714 c0.406-0.515,0.817-1.028,1.238-1.532c0.24-0.286,0.486-0.565,0.731-0.847c0.388-0.448,0.779-0.891,1.178-1.326 c0.263-0.287,0.531-0.571,0.798-0.854c0.402-0.423,0.809-0.839,1.221-1.251c0.272-0.272,0.545-0.543,0.822-0.811 c0.438-0.422,0.884-0.835,1.334-1.246c0.262-0.239,0.519-0.48,0.784-0.714c0.553-0.489,1.118-0.965,1.689-1.436 c0.17-0.14,0.335-0.286,0.506-0.425c0.741-0.599,1.497-1.183,2.264-1.749c0.225-0.166,0.455-0.322,0.681-0.485 c0.555-0.399,1.113-0.795,1.68-1.177c0.297-0.2,0.601-0.393,0.901-0.588c0.51-0.332,1.025-0.659,1.546-0.977\stc0.323-0.197,0.651-0.39,0.978-0.583c0.515-0.302,1.035-0.598,1.559-0.885c0.33-0.182,0.661-0.363,0.994-0.539 c0.552-0.292,1.111-0.572,1.673-0.848c0.309-0.152,0.615-0.307,0.925-0.455c0.682-0.322,1.371-0.628,2.065-0.925 c0.197-0.084,0.39-0.176,0.588-0.259c0.899-0.376,1.81-0.732,2.73-1.068c0.204-0.074,0.412-0.14,0.618-0.213\stc0.715-0.253,1.434-0.499,2.161-0.726c0.319-0.1,0.642-0.192,0.964-0.287c0.623-0.186,1.248-0.365,1.879-0.531 c0.353-0.093,0.709-0.182,1.064-0.269c0.309-0.076,0.622-0.143,0.932-0.214v287.858l-65.009-65.009\stc-5.584-5.584-14.639-5.583-20.224,0c-5.584,5.584-5.584,14.639,0,20.225l65.011,65.009H158.859z"/></svg>`;return i?`<html>${t}</html>`:t}};\n/* JavaScript CODE ENDS HERE */\n//}}}
<!--{{{-->\n<div class='header' role='banner' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='mainMenu' role='navigation' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' role='navigation' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' role='complementary' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea' role='main'>\n<div id='messageArea' class='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>\n<!--}}}-->
<!--{{{-->\n<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='ThemeBroker##SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea' class='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>\n<!--}}}-->
<<sidebarsvgbutton>><<search>>
/*{{{*/\n/* This is an auto-generated tiddler with the CSS to position the tablist correct under the buttons */\n/* Last updated 13-08-2023 */\n\n#sidebarTabs {\n margin-top: 202px;\n}\n/*}}}*/
<<sidebarsvgbutton>><<search>>
/***\n|Name|SinglePageModePlugin|\n|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|\n|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|\n|Version|2.9.7|\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|plugin|\n|Description|Show tiddlers one at a time with automatic permalink, or always open tiddlers at top/bottom of page.|\nThis plugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one tiddler displayed at a time.\n!Documentation\n>see [[SinglePageModePluginInfo]]\n!!!Configuration\n<<<\n<<option chkSinglePageMode>> Display one tiddler at a time\n><<option chkSinglePagePermalink>> Automatically permalink current tiddler\n><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded\n><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited\n<<option chkTopOfPageMode>> Open tiddlers at the top of the page\n<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page\n<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)\n\nNotes:\n* The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}.\n* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.\n* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.\n<<<\n!!!Revisions\n<<<\n2010.11.30 2.9.7 use story.getTiddler()\n2008.10.17 2.9.6 changed chkSinglePageAutoScroll default to false\n| Please see [[SinglePageModePluginInfo]] for previous revision details |\n2005.08.15 1.0.0 Initial Release. Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts.\n<<<\n!!!Code\n***/\n//{{{\nversion.extensions.SinglePageModePlugin= {major: 2, minor: 9, revision: 7, date: new Date(2010,11,30)};\n//}}}\n//{{{\nconfig.paramifiers.SPM = { onstart: function(v) {\n config.options.chkSinglePageMode=eval(v);\n if (config.options.chkSinglePageMode && config.options.chkSinglePagePermalink && !config.browser.isSafari) {\n config.lastURL = window.location.hash;\n if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);\n }\n} };\n//}}}\n//{{{\nif (config.options.chkSinglePageMode==undefined)\n config.options.chkSinglePageMode=false;\nif (config.options.chkSinglePagePermalink==undefined)\n config.options.chkSinglePagePermalink=true;\nif (config.options.chkSinglePageKeepFoldedTiddlers==undefined)\n config.options.chkSinglePageKeepFoldedTiddlers=false;\nif (config.options.chkSinglePageKeepEditedTiddlers==undefined)\n config.options.chkSinglePageKeepEditedTiddlers=false;\nif (config.options.chkTopOfPageMode==undefined)\n config.options.chkTopOfPageMode=false;\nif (config.options.chkBottomOfPageMode==undefined)\n config.options.chkBottomOfPageMode=false;\nif (config.options.chkSinglePageAutoScroll==undefined)\n config.options.chkSinglePageAutoScroll=false;\n//}}}\n//{{{\nconfig.SPMTimer = 0;\nconfig.lastURL = window.location.hash;\nfunction checkLastURL()\n{\n if (!config.options.chkSinglePageMode)\n { window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }\n if (config.lastURL == window.location.hash) return; // no change in hash\n var tids=decodeURIComponent(window.location.hash.substr(1)).readBracketedList();\n if (tids.length==1) // permalink (single tiddler in URL)\n story.displayTiddler(null,tids[0]);\n else { // restore permaview or default view\n config.lastURL = window.location.hash;\n if (!tids.length) tids=store.getTiddlerText("DefaultTiddlers").readBracketedList();\n story.closeAllTiddlers();\n story.displayTiddlers(null,tids);\n }\n}\n\n\nif (Story.prototype.SPM_coreDisplayTiddler==undefined)\n Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;\nStory.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)\n{\n var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;\n var tiddlerElem=story.getTiddler(title); // ==null unless tiddler is already displayed\n var opt=config.options;\n var single=opt.chkSinglePageMode && !startingUp;\n var top=opt.chkTopOfPageMode && !startingUp;\n var bottom=opt.chkBottomOfPageMode && !startingUp;\n if (single) {\n story.forEachTiddler(function(tid,elem) {\n // skip current tiddler and, optionally, tiddlers that are folded.\n if ( tid==title\n || (opt.chkSinglePageKeepFoldedTiddlers && elem.getAttribute("folded")=="true"))\n return;\n // if a tiddler is being edited, ask before closing\n if (elem.getAttribute("dirty")=="true") {\n if (opt.chkSinglePageKeepEditedTiddlers) return;\n // if tiddler to be displayed is already shown, then leave active tiddler editor as is\n // (occurs when switching between view and edit modes)\n if (tiddlerElem) return;\n // otherwise, ask for permission\n var msg="'"+tid+"' is currently being edited.\sn\sn";\n msg+="Press OK to save and close this tiddler\snor press Cancel to leave it opened";\n if (!confirm(msg)) return; else story.saveTiddler(tid);\n }\n story.closeTiddler(tid);\n });\n }\n else if (top)\n arguments[0]=null;\n else if (bottom)\n arguments[0]="bottom";\n if (single && opt.chkSinglePagePermalink && !config.browser.isSafari) {\n window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));\n config.lastURL = window.location.hash;\n document.title = wikifyPlain("SiteTitle") + " - " + title;\n if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);\n }\n if (tiddlerElem && tiddlerElem.getAttribute("dirty")=="true") { // editing... move tiddler without re-rendering\n var isTopTiddler=(tiddlerElem.previousSibling==null);\n if (!isTopTiddler && (single || top))\n tiddlerElem.parentNode.insertBefore(tiddlerElem,tiddlerElem.parentNode.firstChild);\n else if (bottom)\n tiddlerElem.parentNode.insertBefore(tiddlerElem,null);\n else this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler\n } else\n this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler\n var tiddlerElem=story.getTiddler(title);\n if (tiddlerElem&&opt.chkSinglePageAutoScroll) {\n // scroll to top of page or top of tiddler\n var isTopTiddler=(tiddlerElem.previousSibling==null);\n var yPos=isTopTiddler?0:ensureVisible(tiddlerElem);\n // if animating, defer scroll until after animation completes\n var delay=opt.chkAnimate?config.animDuration+10:0;\n setTimeout("window.scrollTo(0,"+yPos+")",delay);\n }\n}\n\nif (Story.prototype.SPM_coreDisplayTiddlers==undefined)\n Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;\nStory.prototype.displayTiddlers = function() {\n // suspend single/top/bottom modes when showing multiple tiddlers\n var opt=config.options;\n var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;\n var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;\n var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;\n this.SPM_coreDisplayTiddlers.apply(this,arguments);\n opt.chkBottomOfPageMode=saveBPM;\n opt.chkTopOfPageMode=saveTPM;\n opt.chkSinglePageMode=saveSPM;\n}\n//}}}
nwSaver
[[StyleSheetShortcuts]]\n[[StyleSheet-nwSaver]]\n[[StyleSheet-Local]]
[[SideBarTab-Correction]]
\n----\n----\n{{preblue{\n/* <nowiki>CSS code minified with Uglify-CSS - Last updated: 15 October 2025</nowiki> */\n/* <nowiki>Pure-CSS provides the CSS for TiddlyWikiClassic, grids, buttons, forms etc. v3.0.0</nowiki> */\n}}}\n{{preblue{\nSoftware License Agreement (BSD License)\n========================================\n\nCopyright 2013 Yahoo! Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n\n * Neither the name of the Yahoo! Inc. nor the\n names of its contributors may be used to endorse or promote products\n derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\nNormalize.css License\n=====================\n\nCopyright (c) Nicolas Gallagher and Jonathan Neal\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the "Software"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n}}}\n/*{{{*/\n/*!\nPure v3.0.0\nCopyright 2013 Yahoo!\nLicensed under the BSD License.\nhttps://github.com/pure-css/pure/blob/master/LICENSE\n*//*!\nnormalize.css v | MIT License | https://necolas.github.io/normalize.css/\nCopyright (c) Nicolas Gallagher and Jonathan Neal\n*//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none !important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{display:flex;flex-flow:row wrap;align-content:flex-start}.pure-u{display:inline-block;vertical-align:top}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}\n.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;user-select:none;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:0;background-image:none;opacity:.4;cursor:not-allowed;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}\n.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:0}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}\n.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}\n.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}\n.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\s25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\s25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent;cursor:default}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}\n/*}}}*/\n----\n----\n{{preblue{\n/* <nowiki>CSS code minified with Uglify-CSS - Last updated: 22 March 2025</nowiki> */\n/* <nowiki>This CSS modifies the standard TiddlyWikiClassic CSS to make a nice pixel correct blue theme for use in NW.js</nowiki> */\n}}}\n{{preblue{\nMIT License\n\nCopyright (c) 2025 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n}}}\n/*{{{*/\n.viewer .tabContents{width:99%;background:#fff;color:black;border-top-left-radius:4px;border-top-right-radius:4px}.viewer tabSelected{background:#fff}.viewer .tab{border-top-left-radius:2px;border-top-right-radius:2px;font-size:14px;padding:2px 4px 2px 4px;line-height:1.0}.viewer .tab:hover{background:[[ColorPalette::TertiaryDark]]}.tab{border-top-left-radius:2px;border-top-right-radius:2px;font-size:12px;padding:2px 4px 0 4px}.tab:hover{background:[[ColorPalette::TertiaryDark]]}#sidebarTabs .tabContents{border-top-left-radius:4px;border-top-right-radius:4px}.tabset{padding:.5em 0 0 0}th[role=columnheader]:not(.no-sort){cursor:pointer}th[role=columnheader]:not(.no-sort):after{content:'';float:right;margin-top:7px;border-width:0 4px 4px;border-style:solid;border-color:#404040 transparent;visibility:hidden;opacity:0;-ms-user-select:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}th[aria-sort=ascending]:not(.no-sort):after{border-bottom:0;border-width:4px 4px 0}th[aria-sort]:not(.no-sort):after{visibility:visible;opacity:.4}th[role=columnheader]:not(.no-sort):hover:after{visibility:visible;opacity:1}h1,h2,h3,h4,h5,h6{color:[[ColorPalette::PrimaryDark]]}hr{border:0;border-top:solid 1px;color:[[ColorPalette::TertiaryMid]];width:100%;margin:4px 0 3px 0}.viewer hr{border:0;border-top:solid 1px;color:[[ColorPalette::TertiaryMid]];width:100%;margin:4px 0 3px 0}.tiddler{padding:8px 8px 8px 8px;background-color:[[ColorPalette::Background]];border:1px solid;border-color:[[ColorPalette::TertiaryLight]]}.tagging,.tagged{border:1px solid #bbb;background-color:#eee;border-radius:2px}.selected .tagging,.selected .tagged{border:1px solid #ccc;background-color:#dedede;border-radius:2px}.prered,.pregreen,.preblue,.preyellow,.viewer pre{white-space:pre-wrap;white-space:-moz-pre-wrap !important;font-family:monospace;font-size:100%;word-wrap:break-word;margin-top:10px;margin-bottom:10px;margin-left:0;margin-right:0;-webkit-border-radius:5px;-khtml-border-radius:5px;-moz-border-radius:5px !important;padding:.5em;overflow:auto}.viewer pre{border:1px solid #c3c306}.preyellow{border:1px solid #c3c306;background:#ffc}.prered{border:1px solid #f62108;background:#fbd9d9}.pregreen{border:1px solid green;background:#e4ffe4}.preblue{border:1px solid #080bf6;background:#d3dff9}.title{color:[[ColorPalette::PrimaryMid]];font-size:16pt}.selected .title{color:[[ColorPalette::PrimaryDark]]}.subtitle{font-size:12pt}.viewer ul{margin-top:0}.viewer ol{margin-top:0}\n#mainMenu{position:fixed;float:left;width:9%;padding:0 0 10px 2px;margin-top:32px;overflow:hidden}#mainMenu br{display:none}#mainMenu .tiddlyLink{background-color:[[ColorPalette::PrimaryMid]];border-radius:2px;font-family:inherit;font-size:11pt;color:[[ColorPalette::Background]];width:100%;margin-left:0;margin-right:0;margin-bottom:1px;padding-left:3px;padding-right:0;padding-top:2px;padding-bottom:2px;display:-webkit-box;text-align:left;box-sizing:border-box}#mainMenu a:hover{background-color:[[ColorPalette::PrimaryDark]];font-weight:bold}a{color:[[ColorPalette::PrimaryDark]]}.pure-form input[type="text"],.pure-form input[type="password"],.pure-form input[type="email"],.pure-form input[type="url"],.pure-form input[type="date"],.pure-form input[type="month"],.pure-form input[type="time"],.pure-form input[type="datetime"],.pure-form input[type="datetime-local"],.pure-form input[type="week"],.pure-form input[type="number"],.pure-form input[type="search"],.pure-form input[type="tel"],.pure-form input[type="color"]{margin-top:2px;padding:.3em;height:2.25em}.pure-form select{margin-top:2px;padding:.3em;height:2.25em}.pure-form textarea{margin-top:2px;padding:.3em;height:2.25em}.pure-form input[type="checkbox"],.pure-form input[type="radio"]{vertical-align:middle}.pure-form legend{padding:.2em 0}.pure-form label{margin-top:5px}h1,h2,h3,h4,h5,h6{font-weight:bold;text-decoration:none;border-bottom:1px solid [[ColorPalette::TertiaryLight]]}h1,h2,h3{padding-bottom:0;margin-top:8px;margin-bottom:2px}h4,h5,h6{margin-top:1rem}h1{font-size:16px}h2{font-size:14px}h3{font-size:12px}h4{font-size:10px}h5{font-size:8px}h6{font-size:6px}#displayArea{margin:0;background:#eee;padding:32px 11.6% 100% 9.2%}body{font-size:12pt;background-color:[[ColorPalette::TertiaryPale]]}.button-gray,.button-warning,.button-primary,.button-secondary,.button-success,.button-error{color:white;border-radius:4px;text-shadow:0 1px 1px rgba(0,0,0,0.2)}.button-success{background:[[ColorPalette::PureSuccessMid]]}.button-success:hover{background:[[ColorPalette::PureSuccessDark]]}.button-gray{background:[[ColorPalette::TertiaryMid]]}.button-gray:hover{background:[[ColorPalette::TertiaryDark]]}.button-warning{background:[[ColorPalette::PureWarningMid]]}\n.button-warning:hover{background:[[ColorPalette::PureWarningDark]]}.button-primary{background:[[ColorPalette::PrimaryMid]]}.button-primary:hover{background:[[ColorPalette::PrimaryDark]]}.button-secondary{background:[[ColorPalette::PureSecondaryMid]]}.button-secondary:hover{background:[[ColorPalette::PureSecondaryDark]]}.button-error{background:[[ColorPalette::PureErrorMid]]}.button-error:hover{background:[[ColorPalette::PureErrorDark]]}.pure-button{margin:1px 1px 1px 1px;padding:.5em .3em .5em .3em}#sidebarOptions .button{background-color:[[ColorPalette::PrimaryMid]];border-radius:2px;font-family:inherit;font-size:11pt;padding:5px 2px 5px 2px;color:[[ColorPalette::Background]];width:100%;margin-left:0;margin-right:0;margin-bottom:1px;padding-left:3px;padding-right:0;padding-top:2px;padding-bottom:2px;display:-webkit-box;text-align:left;box-sizing:border-box;line-height:2em}#sidebarOptions .orangebutton{background-color:#df7514}#sidebarOptions .redbutton{background-color:#e01717}#sidebarOptions .greenbutton{background-color:#1cb841}#sidebarOptions a:hover{background-color:[[ColorPalette::PrimaryDark]];font-weight:bold}input,textarea{outline:0}#sidebar{position:absolute;right:3px;font-size:.9em;background:#eee;border:0 solid #eee;width:11.2%;margin-top:0}#sidebar a{border:0}#sidebarOptions{position:fixed;margin-top:22px;padding-top:8px;background:#eee;width:inherit;text-align:left;display:block;z-index:99}#sidebarOptions input{border:1px solid #aaa;border-radius:3px;width:-webkit-fill-available;width:100%;// -webkit-fill-available;height:2em;margin-left:0;marging-top:0;margin-right:0;margin-bottom:.4em;padding-top:0}#sidebarTabs{margin-top:26em}#sidebarTabs li:not(:last-child){margin-bottom:.1em}#sidebarTabs ul:not(:last-child){margin-bottom:.2em}#sidebarTabs .tabContents{width:inherit;overflow:hidden;padding:.3em}\n/*}}}*/\n----\n----\n{{preblue{\n/* <nowiki>CSS code minified with Uglify-CSS - Last updated: 20 October 2024</nowiki> */\n/* <nowiki>Toastify-CSS provides the CSS for the TiddlyWikiClassic toastify-Plugin.js</nowiki> */\n}}}\n{{preblue{\nMIT License\n\nCopyright (c) 2018 apvarun\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n}}}\n/*{{{*/\n/*!\n * Toastify js 1.12.0\n * https://github.com/apvarun/toastify-js\n * @license MIT licensed\n *\n * Copyright (C) 2018 Varun A P\n */.toastify{padding:12px 20px;color:#fff;display:inline-block;box-shadow:0 3px 6px -1px rgba(0,0,0,0.12),0 10px 36px -4px rgba(77,96,232,0.3);background:-webkit-linear-gradient(315deg,#73a5ff,#5477f5);background:linear-gradient(135deg,#73a5ff,#5477f5);position:fixed;opacity:0;transition:all .4s cubic-bezier(0.215,0.61,0.355,1);border-radius:2px;cursor:pointer;text-decoration:none;max-width:calc(50% - 20px);z-index:2147483647}.toastify.on{opacity:1}.toast-close{background:transparent;border:0;color:white;cursor:pointer;font-family:inherit;font-size:1em;opacity:.4;padding:0 5px}.toastify-right{right:15px}.toastify-left{left:15px}.toastify-top{top:-150px}.toastify-bottom{bottom:-150px}.toastify-rounded{border-radius:25px}.toastify-avatar{width:1.5em;height:1.5em;margin:-7px 5px;border-radius:2px}.toastify-center{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content;max-width:-moz-fit-content}@media only screen and (max-width:360px){.toastify-right,.toastify-left{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content}}\n/*}}}*/
/***\n|Name|StyleSheetAdjustments|\n|Source|http://www.TiddlyTools.com/#StyleSheetAdjustments|\n|Version||\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|CSS|\n|Description|adjust TiddlyWiki default shadow stylesheets definitions|\n***/\n\n[[StyleSheetPlugins]] /* include adjustments to plugin-supplied definitions */\n[[StyleSheetShortcuts]] /* include formatting "shortcut" definitions */\n[[Jash.css]] /* Javascript Shell (jash) Styles */\n\n/***\nThese 'style tweaks' can be easily included in other stylesheet tiddler so they can share a baseline look-and-feel that can then be customized to create a wide variety of 'flavors'.\n/***\n!body /%==================================================%/\nIE needs explicit "position:static" declaration (fixes 'partial background display bug')\n***/\n/*{{{*/\nbody { font-family: Verdana,Arial,Helvetica; position:static; }\n/*}}}*/\n\n/***\n!backstage /%==================================================%/\nfix for bug #347/#349, wherein backstageCloak covers backstagePanel whenever fixed elements are present\n***/\n/*{{{*/\n#backstageCloak { z-index:49; }\n#backstagePanel { margin:0em 0.5em 0em 0.5em; }\n#backstageButton a:hover\n {background-color:transparent !important;}\n\n/*}}}*/\n\n/***\n!common colors /%==================================================%/\n***/\n/*{{{*/\n/* these seem to have been omitted from the core defaults for link styles */\na { color:#014; }\na:hover { color:#def; }\n/*}}}*/\n\n/***\n!HTML forms /%==================================================%/\n***/\n/*{{{*/\n/* eliminate whitespace before/after form controls */\nform { margin:0;padding:0; }\n/*}}}*/\n\n/***\n!basic styling /%==================================================%/\n***/\n/*{{{*/\n/* reduce whitespace before/after horizontal rule */\nhr { margin:2px 0 1px 0;padding:0; }\n/*}}}*/\n\n/***\n!header and titles /%==================================================%/\nIE needs explicit "position:static" declaration (fixes 'background display hides text bug')\n***/\n/*{{{*/\n.header\n { background:transparent; padding:.2em 1em; position:static; margin-bottom:.5em; }\n.headerShadow, .headerForeground\n { padding:.5em; }\n.header a, .header .button, .header .tiddlyLinkExisting, .header .tiddlyLinkNonExisting\n { font-weight: normal; }\n.header .externalLink,\n.siteSubtitle a, .siteSubtitle .button, .siteSubtitle .tiddlyLinkExisting, .siteSubtitle .tiddlyLinkNonExisting\n { text-decoration:none; }\n.header table\n { border-collapse: collapse !important; }\n\n/*}}}*/\n\n/***\n!displayArea /%==================================================%/\n***/\n/*{{{*/\n#displayArea\n { margin:0em 17em 0em 11em; }\n/*}}}*/\n\n\n/***\n!popups /%==================================================%/\nwhite-space:nowrap prevents items from wrapping if popup is near right edge of window\nz-index:1000 makes sure popup is above EVERYTHING else\n***/\n/*{{{*/\n.popup\n { white-space: nowrap; z-index:1000; color: #000; background: #ffe; border: 1px solid #000;\n -moz-border-radius-topright: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px;\n -webkit-border-top-right-radius: 5px; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; }\n.popup a, .popup .button, .popup .tiddlyLinkExisting, .popup .tiddlyLinkNonExisting\n { font-weight: normal; font-style: normal; }\n.popup hr\n { color: #000; background: #ddd; border: 0; }\n.popup li.disabled\n { color: #999; }\n.popup li a, .popup li a:visited\n { color: #300; padding:1px; }\n.popup li a:hover\n { background: #006; color: #fff !important;}\n/*}}}*/\n\n/***\n!messageArea /%==================================================%/\n***/\n/*{{{*/\n#messageArea\n { font-size:90%; -moz-border-radius:1em;-webkit-border-radius:1em; background:#eee; }\n/*}}}*/\n\n/***\n!main menu (left sidebar) /%==================================================%/\n***/\n/*{{{*/\n#mainMenu\n { z-index:1; width:9em; text-align:left; margin:0; margin-left:1.5em; padding:0; clear:both; }\n*[id="mainMenu"] /* moz browsers only */\n { width:auto !important; }\n/*}}}*/\n\n/***\n!sidebar (right sidebar) /%==================================================%/\n***/\n/*{{{*/\n#sidebar\n { width:18em; margin-right:1em; clear:both; }\n#sidebarTabs .tab\n { font-size:90%; -moz-border-radius-topleft:.5em; -moz-border-radius-topright:.5em;\n -webkit-border-top-left-radius:.5em; -webkit-border-top-right-radius:.5em; }\n#sidebarTabs .tabContents\n { background:transparent; border:1px solid #999; padding:.5em; height:auto; overflow:auto; width:92.5%; }\n#sidebarTabs .tabContents .tabContents\n { background:transparent; border:1px solid #999; padding:.5em; height:auto; }\n#sidebarOptions input[type="text"]\n { font-size:8pt; }\n}\n*/\n/*}}}*/\n\n/***\n!tabs /%==================================================%/\n***/\n/*{{{*/\n.tabset\n { padding: 0.2em 0 0 0; }\n.tab\n { padding:0 1px 0 1px; }\n.viewer .tab\n { padding:0 .5em 0 .5em; }\n.tabSelected\n { border: 1px solid; border-bottom: 0px !important; margin-bottom:-2px !important;\n -moz-border-radius-topleft:.5em; -moz-border-radius-topright:.5em;\n -webkit-border-top-left-radius:.5em; -webkit-border-top-right-radius:.5em;}\n.tabUnselected\n { border: 1px solid #999; border-bottom:0px;\n -moz-border-radius-topleft:.5em; -moz-border-radius-topright:.5em;\n -webkit-border-top-left-radius:.5em; -webkit-border-top-right-radius:.5em;}\n.tabContents\n { border: 1px solid; -moz-border-radius:1em;-webkit-border-radius:1em; padding: 1em; }\n/*}}}*/\n\n/***\n!tiddler display elements /%==================================================%/\n***/\n/*{{{*/\n.tiddler { padding: 0 1em 1em 1em; }\n.annotation {\n border: 1px solid;\n -moz-border-radius:.5em;\n -webkit-border-radius:.5em;\n margin: .5em 0;\n padding: .2em .5em;\n font-size:90%;\n}\n.button, .button:hover, .button:active,\n.viewer .button, .viewer .button:hover, .viewer .button:active\n { background:transparent; border:0; }\n.toolbar\n { float:right; display:inline; padding-bottom:0; visibility:hidden; }\n.selected .toolbar\n { visibility:visible; }\n.toolbar .floatingPanel\n { visibility:visible !important; } /* make sure floating panels from toolbars don't disappear on mouseout */\n.toolbar .button, .toolbar a\n { border:1px solid transparent; background:transparent; margin:0px 1px; padding:0px .2em; -moz-border-radius:.5em;-webkit-border-radius:.5em; }\n.toolbar\n {color:[[ColorPalette::TertiaryLight]];}\n.toolbar a\n {color:[[ColorPalette::TertiaryLight]];}\n.selected .toolbar\n {color:[[ColorPalette::Foreground]];}\n.selected .toolbar, .selected .toolbar .button, .selected .toolbar a\n { color:#006; }\n.toolbar .button:hover, .toolbar a:hover\n { border:1px solid #69c !important; background:#006 !important; color:#fff !important; }\n.shadow .tagging, .shadow .tagged\n { display:none; }\n.tagging, .tagged\n { background-color: #ccc; border: 1px solid; }\n.selected .tagging, .selected .tagged\n { background-color:#eee; border: 1px solid #999; }\n.tagging, .tagged\n { -moz-border-radius:1em;-webkit-border-radius:1em; }\n.subtitle\n { font-size:90%; }\n.shadow input, .shadow textarea, .shadow button, .shadow checkbox, .shadow radio, .shadow select\n { font-size:90%; }\n.shadow input, .shadow textarea, .shadow button, .shadow checkbox, .shadow radio, .shadow select\n { font-size:90%; }\n.editor input\n { font-size: 8pt;}\n.editor textarea\n { font-size: 8pt; font-family:monospace; }\n.editor select\n { font-size: 8pt; border:1px solid; }\n.title\n { font-size: 12pt; line-height:120%; }\n.viewer\n { font-size: 9pt; padding: 0.7em; text-align:justify; }\n.viewer pre, .viewer code, .viewer blockquote\n { font-size:8pt; text-align:left; }\n.viewer pre\n { background:#ffe; border:1px solid; }\n.viewer table, .viewer table tr, .viewer table td\n { border:1px solid; }\n.viewer hr {\n margin: 1px; padding:1px;\n border:0;\n border-top: solid 1px #666;\n color: #666;\n}\n.viewer blockquote {\n line-height: 1.5em;\n padding-left: 1em;\n margin-left: 1em;\n border-left: 1px dotted;\n}\n/*}}}*/\n
/***\n|Name|StyleSheetShortcuts|\n|Source|http://www.TiddlyTools.com/#StyleSheetShortcuts|\n|Version||\n|Author|Eric Shulman|\n|License|http://www.TiddlyTools.com/#LegalStatements|\n|~CoreVersion|2.1|\n|Type|CSS|\n|Description|'convenience' classes for common formatting, alignment, boxes, tables, etc.|\n\nThese 'style tweaks' can be easily included in other stylesheet tiddler so they can share a baseline look-and-feel that can then be customized to create a wide variety of 'flavors'.\n26-05-2017 .stretch changed to from 99% to 100%\n***/\n/*{{{*/\n\n/* text alignments */\n.left\n { display:block;text-align:left; }\n.center\n { display:block;text-align:center; }\n.center table\n { margin:auto !important; }\n.right\n { display:block;text-align:right; }\n.justify\n { display:block;text-align:justify; }\n.indent\n { display:block;margin:0;padding:0;border:0;margin-left:2em; }\n.floatleft\n { float:left; }\n.floatright\n { float:right; }\n.valignTop, .valignTop table, .valignTop tbody, .valignTop th, .valignTop tr, .valignTop td\n { vertical-align:top; }\n.valignBottom, .valignBottom table, .valignBottom tbody, .valignBottom th, .valignBottom tr, .valignBottom td\n { vertical-align:bottom; }\n.clear\n { clear:both; }\n.wrap\n { white-space:normal; }\n.nowrap\n { white-space:nowrap; }\n.hidden\n { display:none; }\n.show\n { display:inline !important; }\n.span\n { display:span; }\n.block\n { display:block; }\n.relative\n { position:relative; }\n.absolute\n { position:absolute; }\n\n/* font sizes */\n.big\n { font-size:14pt;line-height:120% }\n.medium\n { font-size:12pt;line-height:120% }\n.normal\n { font-size:9pt;line-height:120% }\n.small\n { font-size:8pt;line-height:120% }\n.fine\n { font-size:7pt;line-height:120% }\n.tiny\n { font-size:6pt;line-height:120% }\n.larger\n { font-size:120%; }\n.smaller\n { font-size:80%; }\n\n/* font styles */\n.bold\n { font-weight:bold; }\n.italic\n { font-style:italic; }\n.underline\n { text-decoration:underline; }\n\n/* plain list items (no bullets or indent) */\n.nobullets li { list-style-type: none; margin-left:-2em; }\n\n/* vertical tabsets - courtesy of Tobias Beer */\n.vTabs .tabset {float:left;display:block;padding:0px;margin-top:.5em;min-width:20%;}\n.vTabs .tabset .tab {display:block;text-align:right;padding:2px 3px 2px 7px; margin:0 1px 1px 0;}\n.vTabs .tabContents {margin-left:20%;max-width:80%;padding:5px;}\n.vTabs .tabContents .tabContents {border:none; background:transparent;}\n\n/* multi-column tiddler content (not supported in Internet Explorer) */\n.twocolumns { display:block;\n -moz-column-count:2; -moz-column-gap:1em; -moz-column-width:50%; /* FireFox */\n -webkit-column-count:2; -webkit-column-gap:1em; -webkit-column-width:50%; /* Safari */\n column-count:2; column-gap:1em; column-width:50%; /* Opera */\n}\n.threecolumns { display:block;\n -moz-column-count:3; -moz-column-gap:1em; -moz-column-width:33%; /* FireFox */\n -webkit-column-count:3; -webkit-column-gap:1em; -webkit-column-width:33%; /* Safari */\n column-count:3; column-gap:1em; column-width:33%; /* Opera */\n}\n.fourcolumns { display:block;\n -moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%; /* FireFox */\n -webkit-column-count:4; -webkit-column-gap:1em; -webkit-column-width:25%; /* Safari */\n column-count:4; column-gap:1em; column-width:25%; /* Opera */\n}\n\n/* page breaks */\n.breakbefore { page-break-before:always; }\n.breakafter { page-break-before:always; }\n\n/* show/hide browser-specific content for InternetExplorer vs. non-IE ("moz") browsers */\n*[class="ieOnly"]\n { display:none; } /* hide in moz (uses CSS selector) */\n* html .mozOnly, *:first-child+html .mozOnly\n { display: none; } /* hide in IE (uses IE6/IE7 CSS hacks) */\n\n/* borderless tables */\n.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody\n { border:0 !important; margin:0 !important; padding:0 !important; }\n.widetable, .widetable table\n { width:100%; }\n\n/* thumbnail images (fixed-sized scaled images) */\n.thumbnail img { height:5em !important; }\n\n/* stretchable images (auto-size to fit tiddler) */\n.stretch img { width:95%; }\n\n/* grouped content */\n.outline\n { display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; }\n.menubox\n { display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#fff; color:#000; }\n.menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting\n { color:#009 !important; }\n.groupbox\n { display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#ffe; color:#000; }\n.groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting\n { color:#009 !important; }\n.groupbox code\n { color:#333 !important; }\n.borderleft\n { margin:0;padding:0;border:0;margin-left:1em; border-left:1px dotted; padding-left:.5em; }\n.borderright\n { margin:0;padding:0;border:0;margin-right:1em; border-right:1px dotted; padding-right:.5em; }\n.borderbottom\n { margin:0;padding:1px 0;border:0;border-bottom:1px dotted; margin-bottom:1px; padding-bottom:1px; }\n.bordertop\n { margin:0;padding:0;border:0;border-top:1px dotted; margin-top:1px; padding-top:1px; }\n\n/* scrolled content */\n.scrollbars { overflow:auto; }\n.height10em { height:10em; }\n.height15em { height:15em; }\n.height20em { height:20em; }\n.height25em { height:25em; }\n.height30em { height:30em; }\n.height35em { height:35em; }\n.height40em { height:40em; }\n\n/* compact form */\n.smallform\n { white-space:nowrap; }\n.smallform input, .smallform textarea, .smallform button, .smallform checkbox, .smallform radio, .smallform select\n { font-size:8pt; }\n\n/* stretchable edit fields and textareas (auto-size to fit tiddler) */\n/* used to be 99%, changed 26-05-2017 */\n.stretch input { width: 100%; }\n.stretch textarea { width: 100%; }\n\n/* compact input fields (limited to a few characters for entering percentages and other small values) */\n.onechar input { width:1em; }\n.twochar input { width:2em; }\n.threechar input { width:3em; }\n.fourchar input { width:4em; }\n.fivechar input { width:5em; }\n\n/* text colors */\n.white { color:#fff !important }\n.gray { color:#999 !important }\n.black { color:#000 !important }\n.red { color:#f66 !important }\n.green { color:#0c0 !important }\n.blue { color:#99f !important }\n\n/* rollover highlighting */\n.mouseover\n {color:[[ColorPalette::TertiaryLight]] !important;}\n.mouseover a\n {color:[[ColorPalette::TertiaryLight]] !important;}\n.selected .mouseover\n {color:[[ColorPalette::Foreground]] !important;}\n.selected .mouseover .button, .selected .mouseover a\n {color:[[ColorPalette::PrimaryDark]] !important;}\n\n/* rollover zoom text */\n.zoomover\n { font-size:80% !important; }\n.selected .zoomover\n { font-size:100% !important; }\n\n/* [[ColorPalette]] text colors */\n.Background { color:[[ColorPalette::Background]]; }\n.Foreground { color:[[ColorPalette::Foreground]]; }\n.PrimaryPale { color:[[ColorPalette::PrimaryPale]]; }\n.PrimaryLight { color:[[ColorPalette::PrimaryLight]]; }\n.PrimaryMid { color:[[ColorPalette::PrimaryMid]]; }\n.PrimaryDark { color:[[ColorPalette::PrimaryDark]]; }\n.SecondaryPale { color:[[ColorPalette::SecondaryPale]]; }\n.SecondaryLight { color:[[ColorPalette::SecondaryLight]];}\n.SecondaryMid { color:[[ColorPalette::SecondaryMid]]; }\n.SecondaryDark { color:[[ColorPalette::SecondaryDark]]; }\n.TertiaryPale { color:[[ColorPalette::TertiaryPale]]; }\n.TertiaryLight { color:[[ColorPalette::TertiaryLight]]; }\n.TertiaryMid { color:[[ColorPalette::TertiaryMid]]; }\n.TertiaryDark { color:[[ColorPalette::TertiaryDark]]; }\n.Error { color:[[ColorPalette::Error]]; }\n\n/* [[ColorPalette]] background colors */\n.BGBackground { background-color:[[ColorPalette::Background]]; }\n.BGForeground { background-color:[[ColorPalette::Foreground]]; }\n.BGPrimaryPale { background-color:[[ColorPalette::PrimaryPale]]; }\n.BGPrimaryLight { background-color:[[ColorPalette::PrimaryLight]]; }\n.BGPrimaryMid { background-color:[[ColorPalette::PrimaryMid]]; }\n.BGPrimaryDark { background-color:[[ColorPalette::PrimaryDark]]; }\n.BGSecondaryPale { background-color:[[ColorPalette::SecondaryPale]]; }\n.BGSecondaryLight { background-color:[[ColorPalette::SecondaryLight]]; }\n.BGSecondaryMid { background-color:[[ColorPalette::SecondaryMid]]; }\n.BGSecondaryDark { background-color:[[ColorPalette::SecondaryDark]]; }\n.BGTertiaryPale { background-color:[[ColorPalette::TertiaryPale]]; }\n.BGTertiaryLight { background-color:[[ColorPalette::TertiaryLight]]; }\n.BGTertiaryMid { background-color:[[ColorPalette::TertiaryMid]]; }\n.BGTertiaryDark { background-color:[[ColorPalette::TertiaryDark]]; }\n.BGError { background-color:[[ColorPalette::Error]]; }\n/*}}}*/
/*{{{*/\n/* Make sure that TiddlyWikiClassic always starts in edit mode */\n/* Last updated 15-04-2023 */\nchkHttpReadOnly: false;\n/*}}}*/
TiddlyWikiClassic
/***\n|Name |ThemeBroker |\n|Description |The basic style theme |\n|Author |Okido |\n|Version |2.2 |\n|Date |18-10-2022 |\n|~ViewTemplate |##ViewTemplate|\n|~PageTemplate |##PageTemplate|\n|~EditTemplate |##EditTemplate|\n|~StyleSheet |##StyleSheet|\n|~MainMenu |MainMenu |\n|~SideBarOptions |##SideBarOptions |\n|~SideBarTid |SideBarTid |\n|~ToolbarCommands |ToolbarCommands |\n***/\n!SideBarOptions\n<<tiddler SideBarTid>>\n\n!StyleSheet\n[[StyleSheet-Custom]]\n!ViewTemplate\n<!--{{{-->\n<div class='toolbar'>\n <span macro='toolbar [[ToolbarCommands::ViewToolbar]]'></span>\n</div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'>\n <span macro='view modifier'></span>\n <span macro='view created date'> - Created: </span>\n <span macro='view modified date'> - Modified: </span> \n</div>\n<!-- <div class='tagged' macro='tags'></div> -->\n<div class='viewer pure-form' macro='view text wikified'></div>\n<div macro="nwappstyle"></div>\n<!--}}}-->\n!PageTemplate\n[[PageTemplateModified]]\n!EditTemplate\n<!--{{{-->\n<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'><b>Title</b></div>\n<div class='editor' macro='edit tags' ><b>Tags</b></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span></div>\n<div id='acehidetweditor' class='editor' macro='edit text'></div>\n<div id='aceViewer' contenteditable='true' spellcheck='true'></div>\n<!--}}}-->
!TiddlyWiki\nTiddlyWiki is the name used till 2023, now it is refered to as TiddlyWikiClassic.\nThe successor of TiddlyWikiClassic is called <nowiki>TiddlyWiki 5</nowiki> or <nowiki>TW5</nowiki>.
!TiddlyWikiClassic\nTiddlyWikiClassic is the original version of [[TiddlyWiki]], an open-source wiki software. It is a self-contained single [[HTML]] file that can be downloaded and run offline in a web browser or in the [[NW.js]] framework. TiddlyWikiClassic is known for its simplicity, reliability, and ease of use.\n\nAt its core, TiddlyWikiClassic utilizes a concept called "tiddlers" to store individual pieces of content.\nA tiddler can be a note, an article, a task, a script, a macro, or any other unit of information. These tiddlers can be easily linked and organized to create a flexible and interconnected web of knowledge.\n\nTiddlyWikiClassic offers a rich text editor that allows users to format their content using various styles, fonts, and colors. It also supports features like bullet points, numbered lists, tables, and images, making it a versatile tool for creating and editing content.\nWith TiddlyWikiClassic, users can tag their tiddlers to categorize and organize them. This helps in quickly finding relevant information using the advanced search capabilities provided by the software. Users can search for specific tags, keywords, or phrases, making it easy to navigate and retrieve information from their personal knowledge base.\n\nOne of the significant advantages of TiddlyWikiClassic is its ability to be customized. Users can extend its functionality by installing plugins and themes. Plugins allow users to add additional features and functionality to their [[TiddlyWiki]], while themes enable them to change the appearance and layout of their wiki. This customization capability makes TiddlyWikiClassic highly adaptable to different use cases and user preferences.\n\nTiddlyWikiClassic excels in personal note-taking, project management, and collaborative knowledge sharing. It can be used by individuals to organize their thoughts, ideas, and research in a single, accessible location. It is also an excellent tool for managing tasks, keeping track of to-do lists, and setting reminders. Furthermore, TiddlyWikiClassic supports collaboration, allowing multiple users to work on a shared wiki, making it suitable for team projects and knowledge sharing within organizations.\n\nWhile newer versions of TiddlyWiki have been developed, TiddlyWikiClassic remains popular among users who appreciate its simplicity, reliability, and straightforward implementation. It continues to be a valuable tool for those seeking a self-contained, offline-capable wiki software.\n\nTiddlyWikiClassic is build with the programming languages JavaScript, [[HTML]] and [[CSS]].\n\nThe original [[TiddlyWikiClassic]] can be found [[here|https://classic.tiddlywiki.com/]].
<!--{{{-->\n<div class='toolbar' role='navigation' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>\n<div class='title' macro='view title'></div>\n<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>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div macro="nwappstyle"></div>\n<div class='tagClear'></div>\n<!--}}}-->\n
!Introduction\nThe [[nwSaver-Plugin.js]] provides a saver for [[TiddlyWikiClassic]] that is running in a [[NW.js]] environment.\nBesides saving the plugin also provides basic I/O functions.\nThe list of available functions is listed in the [[plugin info|nwSaver-Plugin.js]].\nWhen running in a browser the default [[TiddlyWikiClassic]] saving functionality is used.\n!Browser use\nThis [[TiddlyWikiClassic]] can be opened in a browser too.\nThe buttons to minimize, maximize and close-window do not work in a browser, these buttons are specific for running [[TiddlyWikiClassic]] in a [[NW.js]] environment.\nThe [[stylesheets|StyleSheet-Custom]] in this [[TiddlyWikiClassic]] are optimized for usage in a [[NW.js]] environment.\n!Is there more?\nYes, there is the [[ace-Plugin.js|https://qbroker.github.io/ace-Plugin.js/]] for easy [[JavaScript]] editing.\nOther work can be found [[here|https://github.com/qbroker]].\nThe original [[TiddlyWikiClassic]] can be found [[here|https://classic.tiddlywiki.com/]].
/***\n|''Name:''|YourSearchPlugin-Fork by Okido |\n|''Version:''|2.2.1 (2023-06-03)|\n|''Summary:''|Search your TiddlyWiki with advanced search features such as result lists, tiddler preview, result ranking, search filters, combined searches and many more.|\n|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|\n|''Twitter:''|[[@abego|https://twitter.com/#!/abego]]|\n|''GitHub:''|https://github.com/abego/YourSearchPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''License:''|[[BSD open source license|http://www.abego-software.de/legal/apl-v10.html]]|\n!About YourSearch\nYourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!\n\nFor more information see [[Help|YourSearch Help]].\n!Compatibility\nThis plugin requires TiddlyWiki 2.1.\nCheck the [[archive|http://tiddlywiki.abego-software.de/archive]] for ~YourSearchPlugins supporting older versions of TiddlyWiki.\n!Revision history\n* v2.2.2 (2025-05-14) by Okido\n** Added an id to to the search box, this helps when autofill is used.\n* v2.2.1 (2023-06-03) Forked by Okido\n** Hide the search button and added the HTML placeholder Search, this is a visual only improvement\n** Improved the centering of the results box, in Chromium the box is landing on the far left, now it is in the center\n* v2.2.0 (2023-05-06)\n** Several features, fixes and changes by Yakov Litvin. Thanks for contributing.\n*** feat: make shadows be formatted as code in TWC 2.9.x and others\n*** feat: increase z-index of .yourSearchResult not to interfere with CodeMirror and others\n*** fix: don't overwrite Array.prototype.forEach when present\n*** refactor: countStrings - omit unreachable return\n*** refactor: use yourSearchResultItemsID instead of repeasting the value\n*** codestyle: make indetation and blocks in myMacroSearchHandler and myStorySearch consistent with other code\n*** codestyle: apply eslint's space-before-blocks, block-spacing, semi-spacing, object-curly-spacing\n*** codestyle: apply eslint's no-trailing-spaces, comma-spacing, space-infix-ops, key-spacing\n* v2.1.6 (2012-04-19)\n** Fix issue with IE8. Thanks to Roger Gallion for reporting and providing the fix. (For details see: https://github.com/abego/YourSearchPlugin/issues/1)\n** remove warnings\n* v2.1.5 (2010-02-16)\n** Fix problems with CSS and search textfield. Thanks to Guido Glatzel for reporting.\n* v2.1.4 (2009-09-04)\n** Fix "this command is not supported" error under IE 8. Thanks to rouilj for reporting. (For details see: http://groups.google.com/group/TiddlyWiki/browse_thread/thread/cffee3254381e478)\n* v2.1.3 (2008-04-16)\n** Fix problem with Firefox3. Thanks to Andreas Hoefler for reporting.\n* v2.1.2 (2008-03-17)\n** Bug: on IE (6.0) the first letter is dropped from the search string. Thanks to Kashgarinn and Nick Padfield for reporting.\n* v2.1.1 (2007-03-11)\n** Extend "New tiddler" feature: Ctrl-Return invokes the "new tiddler" feature (create tiddler based on search text)\n** Extend "New tiddler" feature: tiddler's text and tags may also be specified (see abego.parseNewTiddlerCommandLine)\n** Support searching for URLs (like http://www.example.com)\n** Provided extended public API (abego.YourSearch.getFoundTiddlers/getQuery/onShowResult)\n** Clear MessageBox when search field gets focus (so the box no longer hides the search field)\n** Reset search result when TiddlyWiki is changed\n** Fix function abego.BoolExp\n* v2.1.0 (2006-10-12)\n** Release version with TiddlyWiki 2.1 support\n*** Support (Extended) Field search\n*** Support parenthesis in Boolean Search\n*** Support direct regular expression input\n*** Support JavaScript Expressions for filtering\n*** "new tiddler" feature (create tiddler based on search text)\n* v2.0.2 (2006-02-13)\n** Bugfix for Firefox 1.5.0.1 related to the "Show prefix" checkbox. Thanks to Ted Pavlic for reporting and to BramChen for fixing.\n** Internal\n*** Make "JSLint" conform\n* v2.0.1 (2006-02-05)\n** Support "Exact Word Match" (use '=' to prefix word)\n** Support default filter settings (when no filter flags are given in search term)\n** Rework on the "less than 3 chars search text" feature (thanks to EricShulman)\n** Better support SinglePageMode when doing "Open all tiddlers" (thanks to EricShulman)\n** Support Firefox 1.5.0.1\n** Bug: Fixed a hilite bug in "classic search mode" (thanks to EricShulman)\n* v2.0.0 (2006-01-16)\n** Add User Interface\n* v1.0.1 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.0 (2005-12-28)\n** initial version\n!Source Code\n***/\n//{{{\n//============================================================================\n//============================================================================\n// YourSearchPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the Plugin is only installed once.\n//\nif (!version.extensions.YourSearchPlugin) {\n\nversion.extensions.YourSearchPlugin = {\n major: 2, minor: 2, revision: 1,\n source: "http://tiddlywiki.abego-software.de/#YourSearchPlugin",\n licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",\n copyright: "Copyright (c) abego Software GmbH, 2005-2023 (www.abego-software.de)"\n};\n\nif (!window.abego) window.abego = {};\n\n// define the Array forEach when not yet defined (e.g. by Mozilla)\nif (!Array.forEach && !Array.prototype.forEach) {\n Array.forEach = function(obj, callback, thisObj) {\n for (var i = 0, len = obj.length; i < len; i++)\n callback.call(thisObj, obj[i], i, obj);\n };\n Array.prototype.forEach = function(callback, thisObj) {\n for (var i = 0, len = this.length; i < len; i++)\n callback.call(thisObj, this[i], i, this);\n };\n}\n\nabego.toInt = function(s, defaultValue) {\n if (!s) return defaultValue;\n var n = parseInt(s);\n return (n == NaN) ? defaultValue : n;\n};\n\nabego.createEllipsis = function(place) {\n var e = createTiddlyElement(place, "span");\n e.innerHTML = "…";\n};\n\n//#concept Object\n//\nabego.shallowCopy = function(object) {\n if (!object)\n return object;\n var result = {};\n for (var n in object)\n result[n] = object[n];\n return result;\n};\n\n// Returns a shallow copy of the options, or a new, empty object if options is null/undefined.\n//\n// @param options [may be null/undefined]\n//\n//#concept Object, Options\n//#import abego.shallowCopy\n//\nabego.copyOptions = function(options) {\n return !options ? {} : abego.shallowCopy(options);\n};\n\n//#import abego.define-namespace\n// returns the number of occurances of s in the text\nabego.countStrings = function(text, s) {\n var n = 0;\n if (!s) return n;\n\n var lastIndex = 0;\n while (true) {\n var i = text.indexOf(s, lastIndex);\n if (i < 0) return n;\n n++;\n lastIndex = i + s.length;\n }\n};\n\n// Returns the content of the first "braced" text {...}\n// Also takes care of nested braces\n//\n// Returns undefined when no braced text is found or it is not properly nested\n//\n// @param [optional] when defined and a braced text is found lastIndexRef.lastIndex will contain the index of the char following the (final) closing brace on return.\n//\nabego.getBracedText = function(text, offset, lastIndexRef) {\n if (!offset) offset = 0;\n var re = /\s{([^\s}]*)\s}/gm;\n re.lastIndex = offset;\n var m = re.exec(text);\n if (m) {\n // The matching stopped at the first closing brace.\n // But if the matched text contains opening braces\n // this is not the final closing brace.\n // Handle this case specially, find the "corresponding" closing brace\n var s = m[1];\n var nExtraOpenBrace = abego.countStrings(s, "{");\n\n if (!nExtraOpenBrace) {\n if (lastIndexRef)\n lastIndexRef.lastIndex = re.lastIndex;\n // simple case: no nested braces\n return s;\n }\n\n // special case: "nested braces"\n var len = text.length;\n for (var i = re.lastIndex; i < len && nExtraOpenBrace; i++) {\n var c = text.charAt(i);\n if (c == "{")\n nExtraOpenBrace++;\n else if (c == "}")\n nExtraOpenBrace--;\n }\n if (!nExtraOpenBrace) {\n // found the corresponding "}".\n if (lastIndexRef)\n lastIndexRef.lastIndex = i - 1;\n return text.substring(m.index + 1, i - 1);\n }\n }\n\n // no return means: return undefined;\n};\n\n// Returns an array with those items from the array that pass the given test\n//\n// @param test an one-arg boolean function that returns true when the item should be added.\n// @param testObj [optional] the receiver for the test function (global if undefined or null)\n// @param result [optional] an array. When define the selected items are added to this array, otherwise a new array is used.\n//\n//#import Array.prototype.forEach\n//\nabego.select = function(array, test, testObj, result) {\n if (!result) result = [];\n array.forEach(function(t) {\n if (test.call(testObj, t))\n result.push(t);\n });\n return result;\n};\n\n// A portable way to "consume an event"\n//\n// (Uses "stopPropagation" and "preventDefault", but will also "cancelBubble",\n// even though this is a "non-standard method" , just in case).\n//\nabego.consumeEvent = function(e) {\n if (e.stopPropagation) e.stopPropagation();\n if (e.preventDefault) e.preventDefault();\n e.cancelBubble = true;\n e.returnValue = true;\n};\n\n// Class abego.TiddlerFilterTerm =================================================================\n//\n// Used to check if a tiddler contains a given text.\n//\n// A list of fields (standard and/or extended) may be specified to restrict the search to certain fields.\n//\n// When no explicit fields are given the fields defined by defaultFields are checked, plus all extended\n// fields (when options.withExtendedFields is true).\n//\n// @param options [may be null/undefined]\n// options.fields @seeParam abego.MultiFieldRegExpTester.fields\n// options.withExtendedFields @seeParam abego.MultiFieldRegExpTester.withExtendedFields\n// options.caseSensitive [Default: false]\n// options.fullWordMatch [Default: false]\n// options.textIsRegExp [Default: false] when true the given text is already a regExp\n//\n//#import abego.MultiFieldRegExpTester\n//\nabego.TiddlerFilterTerm = function(text, options) {\n if (!options) options = {};\n\n var reText = text;\n if (!options.textIsRegExp) {\n reText = text.escapeRegExp();\n if (options.fullWordMatch)\n reText = "\s\sb" + reText + "\s\sb";\n }\n var regExp = new RegExp(reText, "m" + (options.caseSensitive ? "" : "i"));\n\n this.tester = new abego.MultiFieldRegExpTester(regExp, options.fields, options.withExtendedFields);\n};\n\nabego.TiddlerFilterTerm.prototype.test = function(tiddler) {\n return this.tester.test(tiddler);\n};\n\n// Recognize a string like\n// "Some Title. Some content text #Tag1 #Tag2 Tag3"\n// with the tags and the text being optional.\n// Also the period at the end of the title is optional when no content text is specified)\n//\n// Returns the result in an object with properties "title" and "params",\n// with "params" following the parseParams format, containing the "tag" and "text" arguments.\n//\nabego.parseNewTiddlerCommandLine = function(s) {\n var m = /(.*?)\s.(?:\ss+|$)([^#]*)(#.*)?/.exec(s);\n if (!m) m = /([^#]*)()(#.*)?/.exec(s);\n if (m) {\n var r;\n if (m[3]) {\n var s2 = m[3].replace(/#/g, "");\n r = s2.parseParams("tag");\n } else\n r = [[]];\n\n // add the text parameter\n var text = m[2] ? m[2].trim() : "";\n r.push({ name: "text", value: text });\n r[0].text = [text];\n\n return { title: m[1].trim(), params: r };\n } else\n return { title: s.trim(), params: [[]] };\n};\n// options.defaultFields [@seeOptionDefault abego.TiddlerFilterTerm.fields] fields to check when no fields are explicitly specified in queryText.\n// options.withExtendedFields [@seeOptionDefault abego.TiddlerFilterTerm.withExtendedFields] when true and no fields are explicitly specified in queryText also the extended fields are considered (in addition to the ones in defaultFields).\n// @seeOptions abego.TiddlerFilterTerm (-fields -fullWordMatch -withExtendedFields)\n//\n//#import abego.getBracedText\n//#import abego.copyOptions\n//#import abego.TiddlerFilterTerm\n//\nabego.parseTiddlerFilterTerm = function(queryText, offset, options) {\n\n // group 1: {...} (JavaScript expression)\n // group 2: '=' (full word match (optional))\n // group 3: [!%#] (field selection short cuts)\n // group 4: fieldName ':'\n // group 5: String literal "..."\n // group 6: RegExp literal /.../\n // group 7: scheme '://' nonSpaceChars\n // group 8: word\n var re = /\ss*(?:(?:\s{([^\s}]*)\s})|(?:(=)|([#%!])|(?:(\sw+)\ss*\s:(?!\s/\s/))|(?:(?:("(?:(?:\s\s")|[^"])+")|(?:\s/((?:(?:\s\s\s/)|[^\s/])+)\s/)|(\sw+\s:\s/\s/[^\ss]+)|([^\ss\s)\s-\s"]+)))))/mg; // " <- The syntax highlighting of my editors gets confused without this quote\n var shortCuts = { '!': 'title', '%': 'text', '#': 'tags' };\n\n var fieldNames = {};\n var fullWordMatch = false;\n re.lastIndex = offset;\n while (true) {\n var i = re.lastIndex;\n var m = re.exec(queryText);\n if (!m || m.index != i)\n throw "Word or String literal expected";\n if (m[1]) {\n var lastIndexRef = {};\n var code = abego.getBracedText(queryText, 0, lastIndexRef);\n if (!code)\n throw "Invalid {...} syntax";\n var f = Function("tiddler", "return (" + code + ");");\n return {\n func: f,\n lastIndex: lastIndexRef.lastIndex,\n markRE: null\n };\n }\n if (m[2])\n fullWordMatch = true;\n else if (m[3])\n fieldNames[shortCuts[m[3]]] = 1;\n else if (m[4])\n fieldNames[m[4]] = 1;\n else {\n var textIsRegExp = m[6];\n var text = m[5] ? window.eval(m[5]) : m[6] ? m[6] : m[7] ? m[7] : m[8];\n\n options = abego.copyOptions(options);\n options.fullWordMatch = fullWordMatch;\n options.textIsRegExp = textIsRegExp;\n\n var fields = [];\n for (var n in fieldNames)\n fields.push(n);\n if (fields.length == 0) {\n options.fields = options.defaultFields;\n } else {\n options.fields = fields;\n options.withExtendedFields = false;\n }\n var term = new abego.TiddlerFilterTerm(text, options);\n var markREText = textIsRegExp ? text : text.escapeRegExp();\n if (markREText && fullWordMatch)\n markREText = "\s\sb" + markREText + "\s\sb";\n return {\n func: function(tiddler) { return term.test(tiddler) },\n lastIndex: re.lastIndex,\n markRE: markREText ? "(?:" + markREText + ")" : null\n };\n }\n }\n};\n\n// Class abego.BoolExp =================================================================\n//\n// Allows the execution/evaluation of a boolean expression, according to this syntax:\n//\n// boolExpression : unaryExpression (("AND"|"OR"|"&&"|"||")? unaryExpression)*\n// ;\n//\n// unaryExpression : ("not"|"-")? primaryExpression\n// ;\n//\n// primaryExpression : "(" boolExpression ")"\n// | Term\n// ;\n//\n// For flexibility the Term syntax is defined by a separate parse function.\n//\n// Notice that there is no precedence between "AND" and "OR" operators, i.e. they are evaluated from left to right.\n//\n// To evaluate the expression in a given context use code like this:\n//\n// var be = new abego.BoolExp(s, termParseFunc);\n// var result = be.exec(context);\n//\n// @param s the text defining the expression\n// @param parseTermFunc a Function(text,offset,options) that parses the text starting at offset for a "Term" and returns an object with properties {func: Function(context), lastIndex: ...}. func is the function to be used to evaluate the term in the given context.\n// @param options [may be null/undefined] (is also passed to the parseTermFunc)\n// options.defaultOperationIs_OR [Default: false] When true the concatenation of unaryExpressions (without an operator) is interpreted as an "OR", otherwise as an "AND".\n// options.caseSensitive [default: false]\n//\nabego.BoolExp = function(s, parseTermFunc, options) {\n this.s = s;\n var defaultOperationIs_OR = options && options.defaultOperationIs_OR;\n\n var reCloseParenthesis = /\ss*\s)/g; // match )\n var reAndOr = /\ss*(?:(and|\s&\s&)|(or|\s|\s|))/gi; // group 1: AND, group 2: OR\n\n var reNot_Parenthesis = /\ss*(\s-|not)?(\ss*\s()?/gi;\n\n var parseBoolExpression; //#Pre-declare function name to avoid problem with "shrinkSafe"\n\n var parseUnaryExpression = function(offset) {\n reNot_Parenthesis.lastIndex = offset;\n var m = reNot_Parenthesis.exec(s);\n var negate = false;\n var result = null;\n if (m && m.index == offset) {\n offset += m[0].length;\n negate = m[1];\n if (m[2]) {\n // case: (...)\n var e = parseBoolExpression(offset);\n reCloseParenthesis.lastIndex = e.lastIndex;\n if (!reCloseParenthesis.exec(s)) throw "Missing ')'";\n result = { func: e.func, lastIndex: reCloseParenthesis.lastIndex, markRE: e.markRE };\n }\n }\n if (!result) result = parseTermFunc(s, offset, options);\n\n if (negate) {\n result.func = (function(f) { return function(context) { return !f(context) } })(result.func);\n // don't mark patterns that are negated\n // (This is essential since the marking may also be used to calculate "ranks". If we\n // would also count the negated matches (i.e. that should not exist) the rank may get too high)\n result.markRE = null;\n }\n return result;\n };\n\n parseBoolExpression = function(offset) {\n var result = parseUnaryExpression(offset);\n while (true) {\n var l = result.lastIndex;\n reAndOr.lastIndex = l;\n var m = reAndOr.exec(s);\n var isOrCase;\n var nextExp;\n if (m && m.index == l) {\n isOrCase = !m[1];\n nextExp = parseUnaryExpression(reAndOr.lastIndex);\n } else {\n // no "AND" or "OR" found.\n // Maybe it is a concatenations of parseUnaryExpression without operators\n try {\n nextExp = parseUnaryExpression(l);\n } catch (e) {\n // no unary expression follows. We are done\n return result;\n }\n isOrCase = defaultOperationIs_OR;\n }\n result.func = (function(func1, func2, isOrCase) {\n return isOrCase\n ? function(context) { return func1(context) || func2(context) }\n : function(context) { return func1(context) && func2(context) };\n })(result.func, nextExp.func, isOrCase);\n result.lastIndex = nextExp.lastIndex;\n if (!result.markRE)\n result.markRE = nextExp.markRE;\n else if (nextExp.markRE)\n result.markRE = result.markRE + "|" + nextExp.markRE;\n }\n };\n\n var expr = parseBoolExpression(0);\n this.evalFunc = expr.func;\n if (expr.markRE) this.markRegExp = new RegExp(expr.markRE, options.caseSensitive ? "mg" : "img");\n};\n\nabego.BoolExp.prototype.exec = function() {\n return this.evalFunc.apply(this, arguments);\n};\n\nabego.BoolExp.prototype.getMarkRegExp = function() {\n return this.markRegExp;\n};\n\nabego.BoolExp.prototype.toString = function() {\n return this.s;\n};\n\n// Class abego.MultiFieldRegExpTester ==================================================================\n//\n// @param fields [optional; Default: ["title","text","tags"]] array of names of fields to be considered\n// @param withExtendedFields [optional; Default: false] when true also extended fields are considered (in addition to the ones given in 'fields')\n//\nabego.MultiFieldRegExpTester = function(re, fields, withExtendedFields) {\n this.re = re;\n this.fields = fields ? fields : ["title", "text", "tags"];\n this.withExtendedFields = withExtendedFields;\n};\n\n// Returns the name of the first field found that value succeeds the given test,\n// or null when no such field is found\n//\nabego.MultiFieldRegExpTester.prototype.test = function(tiddler) {\n var re = this.re;\n // Check the fields explicitly specified\n for (var i = 0; i < this.fields.length; i++) {\n var s = store.getValue(tiddler, this.fields[i]);\n if (typeof s == "string" && re.test(s))\n return this.fields[i];\n }\n // Check the extended fields (if required)\n if (this.withExtendedFields) return store.forEachField(\n tiddler,\n function(tiddler, fieldName, value) {\n return typeof value == "string" && re.test(value) ? fieldName : null;\n }, true);\n\n return null;\n};\n\n// Class abego.TiddlerQuery ==================================================================\n//\n//#import abego.select\n//#import abego.MultiFieldRegExpTester\n//\nabego.TiddlerQuery = function(queryText, caseSensitive, useRegExp, defaultFields, withExtendedFields) {\n if (useRegExp) {\n this.regExp = new RegExp(queryText, caseSensitive ? "mg" : "img");\n this.tester = new abego.MultiFieldRegExpTester(this.regExp, defaultFields, withExtendedFields);\n } else {\n this.expr = new abego.BoolExp(\n queryText,\n abego.parseTiddlerFilterTerm, {\n defaultFields: defaultFields,\n caseSensitive: caseSensitive,\n withExtendedFields: withExtendedFields\n });\n }\n\n this.getQueryText = function() {\n return queryText;\n };\n this.getUseRegExp = function() {\n return useRegExp;\n };\n this.getCaseSensitive = function() {\n return caseSensitive;\n };\n this.getDefaultFields = function() {\n return defaultFields;\n };\n this.getWithExtendedFields = function() {\n return withExtendedFields;\n };\n};\n\n// Returns true iff the query includes the given tiddler\n//\n// @param tiddler [may be null/undefined]\n//\nabego.TiddlerQuery.prototype.test = function(tiddler) {\n if (!tiddler) return false;\n if (this.regExp) {\n return this.tester.test(tiddler);\n }\n return this.expr.exec(tiddler);\n};\n\n// Returns an array with those tiddlers from the tiddlers array that match the query.\n//\nabego.TiddlerQuery.prototype.filter = function(tiddlers) {\n return abego.select(tiddlers, this.test, this);\n};\n\nabego.TiddlerQuery.prototype.getMarkRegExp = function() {\n if (this.regExp) {\n // Only use the regExp for marking when it does not match the empty string.\n return "".search(this.regExp) >= 0 ? null : this.regExp;\n }\n return this.expr.getMarkRegExp();\n};\n\nabego.TiddlerQuery.prototype.toString = function() {\n return (this.regExp ? this.regExp : this.expr).toString();\n};\n\n// Class abego.PageWiseRenderer ================================================\n//\n// Subclass or instance must implement getItemsPerPage function;\n// They should also implement onPageChanged and refresh the container of the\n// PageWiseRenderer on that event.\n//\n//#import abego.toInt\n//\nabego.PageWiseRenderer = function() {\n this.firstIndexOnPage = 0; // The index of the first item of the lastResults list displayed on the search result page\n};\n\nmerge(abego.PageWiseRenderer.prototype, {\n setItems: function(items) {\n this.items = items;\n this.setFirstIndexOnPage(0);\n },\n\n // Maximum number of pages listed in the navigation bar (before or after the current page)\n //\n getMaxPagesInNavigation: function() {\n return 10;\n },\n\n getItemsCount: function(items) {\n return this.items ? this.items.length : 0;\n },\n\n getCurrentPageIndex: function() {\n return Math.floor(this.firstIndexOnPage / this.getItemsPerPage());\n },\n\n getLastPageIndex: function() {\n return Math.floor((this.getItemsCount() - 1) / this.getItemsPerPage());\n },\n\n setFirstIndexOnPage: function(index) {\n this.firstIndexOnPage = Math.min(Math.max(0, index), this.getItemsCount() - 1);\n },\n\n getFirstIndexOnPage: function() {\n // Ensure that the firstIndexOnPage is really a page start.\n // This may have become violated when getItemsPerPage has changed,\n // (e.g. when switching between previewText and simple mode.)\n this.firstIndexOnPage = Math.floor(this.firstIndexOnPage / this.getItemsPerPage()) * this.getItemsPerPage();\n\n return this.firstIndexOnPage;\n },\n\n getLastIndexOnPage: function() {\n return Math.min(this.getFirstIndexOnPage() + this.getItemsPerPage() - 1, this.getItemsCount() - 1);\n },\n\n onPageChanged: function(pageIndex, oldPageIndex) {\n },\n\n renderPage: function(itemRenderer) {\n if (itemRenderer.beginRendering)\n itemRenderer.beginRendering(this);\n try {\n // When there are items found add them to the result page (pagewise)\n if (this.getItemsCount()) {\n // Add the items of the current page\n var lastIndex = this.getLastIndexOnPage();\n var iInPage = -1;\n for (var i = this.getFirstIndexOnPage(); i <= lastIndex; i++) {\n iInPage++;\n\n itemRenderer.render(this, this.items[i], i, iInPage);\n }\n }\n } finally {\n if (itemRenderer.endRendering)\n itemRenderer.endRendering(this);\n }\n },\n\n addPageNavigation: function(place) {\n if (!this.getItemsCount()) return;\n\n var self = this;\n var onNaviButtonClick = function(e) {\n if (!e) e = window.event;\n\n abego.consumeEvent(e);\n\n var pageIndex = abego.toInt(this.getAttribute("page"), 0);\n var oldPageIndex = self.getCurrentPageIndex();\n if (pageIndex == oldPageIndex)\n return;\n var index = pageIndex * self.getItemsPerPage();\n self.setFirstIndexOnPage(index);\n self.onPageChanged(pageIndex, oldPageIndex);\n };\n\n var button;\n var currentPageIndex = this.getCurrentPageIndex();\n var lastPageIndex = this.getLastPageIndex();\n if (currentPageIndex > 0) {\n button = createTiddlyButton(place, "Previous", "Go to previous page (Shortcut: Alt-'<')", onNaviButtonClick, "prev");\n button.setAttribute("page", (currentPageIndex - 1).toString());\n button.setAttribute("accessKey", "<");\n }\n\n for (var i = -this.getMaxPagesInNavigation(); i < this.getMaxPagesInNavigation(); i++) {\n var pageIndex = currentPageIndex + i;\n if (pageIndex < 0) continue;\n if (pageIndex > lastPageIndex) break;\n\n var pageNo = (i + currentPageIndex + 1).toString();\n var buttonClass = pageIndex == currentPageIndex ? "currentPage" : "otherPage";\n button = createTiddlyButton(place, pageNo, "Go to page %0".format([pageNo]), onNaviButtonClick, buttonClass);\n button.setAttribute("page", (pageIndex).toString());\n }\n\n if (currentPageIndex < lastPageIndex) {\n button = createTiddlyButton(place, "Next", "Go to next page (Shortcut: Alt-'>')", onNaviButtonClick, "next");\n button.setAttribute("page", (currentPageIndex + 1).toString());\n button.setAttribute("accessKey", ">");\n }\n }\n});\n\n// Class abego.LimitedTextRenderer ===========================================================\n//\n// Renders a given text, ensuring that a given limit of number of characters\n// is not exceeded.\n//\n// A "markRegExp" may be specified. Substring matching this regular expression\n// ("matched strings") are rendered with the class "marked".\n//\n// if the given text is longer than the limit the matched strings are preferred\n// to be included in the rendered text (with some leading and trailing "context text").\n//\n// Example:\n// var renderer = new abego.LimitedTextRenderer();\n//\n// var place = ... // a DOM element that should contain the rendered (limited) text\n// var s = "This is another 'Hello World' example, as saying 'Hello' is always nice. So let's say it again: >Hello!<";\n// var maxLen = 50;\n// var markRE = /hello/gi;\n// renderer.render(place,s,maxLen,markRE);\n//\n//#import abego.createEllipsis\n//\nabego.LimitedTextRenderer = function() {\n var minMatchWithContextSize = 40;\n var maxMovementForWordCorrection = 4; // When a "match" context starts or end on a word the context borders may be changed to at most this amount to include or exclude the word.\n\n\n //----------------------------------------------------------------------------\n //\n // Ranges\n //\n // Objects with a "start" and "end" property (not a specific class).\n //\n // In a corresponding "Ranges array" these objects are sorted by their start\n // and no Range object intersects/touches any other in the array.\n //\n //----------------------------------------------------------------------------\n\n // Adds the Range [startIndex,endIndex[ to the ranges, ensuring that the Ranges\n // in the array are sorted by their start and no Range object\n // intersects/touches any other in the array (i.e. possibly the new Range is\n // "merged" with existing ranges)\n //\n // @param ranges array of Range objects\n //\n var addRange = function(ranges, startIndex, endIndex) {\n var n = ranges.length;\n\n // When there are no ranges in ranges, just add it.\n if (n == 0) {\n ranges.push({ start: startIndex, end: endIndex });\n return;\n }\n\n var i = 0;\n for (; i < n; i++) {\n var range = ranges[i];\n\n // find the first range that intersects or "touches" [startIndex, endIndex[\n if (range.start <= endIndex && startIndex <= range.end) {\n // Found.\n\n var r;\n // find the first range behind the new range that does not interfere\n var rIndex = i + 1;\n for (; rIndex < n; rIndex++) {\n r = ranges[rIndex];\n if (r.start > endIndex || startIndex > range.end) {\n break;\n }\n }\n\n // Replace the ranges i to rIndex-1 with the union of the new range with these ranges.\n var unionStart = startIndex;\n var unionEnd = endIndex;\n for (var j = i; j < rIndex; j++) {\n r = ranges[j];\n unionStart = Math.min(unionStart, r.start);\n unionEnd = Math.max(unionEnd, r.end);\n }\n ranges.splice(i, rIndex - i, { start: unionStart, end: unionEnd });\n return;\n }\n\n // if we found a range R that is right of the new range there is no\n // intersection and we can insert the new range before R.\n if (range.start > endIndex) {\n break;\n }\n }\n\n // When we are here the new range does not interfere with any range in ranges and\n // i is the index of the first range right to it (or ranges.length, when the new range\n // becomes the right most range).\n\n ranges.splice(i, 0, { start: startIndex, end: endIndex });\n };\n\n // Returns the total size of all Ranges in ranges\n //\n var getTotalRangesSize = function(ranges) {\n var totalRangeSize = 0;\n for (var i = 0; i < ranges.length; i++) {\n var range = ranges[i];\n totalRangeSize += range.end - range.start;\n }\n return totalRangeSize;\n };\n\n //----------------------------------------------------------------------------\n\n\n var isWordChar = function(c) {\n return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c == "_";\n };\n\n // Returns the bounds of the word in s around offset as a {start: , end:} object.\n //\n // Returns null when the char at offset is not a word char.\n //\n var getWordBounds = function(s, offset) {\n // Handle the "offset is not in word" case\n if (!isWordChar(s[offset])) return null;\n\n for (var i = offset - 1; i >= 0 && isWordChar(s[i]); i--)\n { /*empty*/ }\n\n var startIndex = i + 1;\n var n = s.length;\n for (i = offset + 1; i < n && isWordChar(s[i]); i++)\n { /*empty*/ }\n\n return { start: startIndex, end: i };\n };\n\n var moveToWordBorder = function(s, offset, isStartOffset) {\n var wordBounds;\n if (isStartOffset) {\n wordBounds = getWordBounds(s, offset);\n } else {\n if (offset <= 0) return offset;\n wordBounds = getWordBounds(s, offset - 1);\n }\n if (!wordBounds) return offset;\n\n if (isStartOffset) {\n if (wordBounds.start >= offset - maxMovementForWordCorrection) return wordBounds.start;\n if (wordBounds.end <= offset + maxMovementForWordCorrection) return wordBounds.end;\n } else {\n if (wordBounds.end <= offset + maxMovementForWordCorrection) return wordBounds.end;\n if (wordBounds.start >= offset - maxMovementForWordCorrection) return wordBounds.start;\n }\n return offset;\n };\n\n\n\n // Splits s into a sequence of "matched" and "unmatched" substrings, using the\n // matchRegExp to do the matching.\n //\n // Returns an array of objects with a "text" property containing the substring text.\n // Substrings that are "matches" also contain a boolean "isMatch" property set to true.\n //\n // @param matchRegExp [may be null] when null no matching is performed and the returned\n // array just contains one item with s as its text\n //\n var getTextAndMatchArray = function(s, matchRegExp) {\n var result = [];\n if (matchRegExp) {\n var startIndex = 0;\n do {\n matchRegExp.lastIndex = startIndex;\n var match = matchRegExp.exec(s);\n if (match) {\n if (startIndex < match.index) {\n var t = s.substring(startIndex, match.index);\n result.push({ text: t });\n }\n result.push({ text: match[0], isMatch: true });\n startIndex = match.index + match[0].length;\n } else {\n result.push({ text: s.substr(startIndex) });\n break;\n }\n } while (true);\n } else {\n result.push({ text: s });\n }\n return result;\n };\n\n\n\n var getMatchedTextCount = function(textAndMatches) {\n var result = 0;\n for (var i = 0; i < textAndMatches.length; i++) {\n if (textAndMatches[i].isMatch) {\n result++;\n }\n }\n return result;\n };\n\n\n\n var getContextRangeAround = function(s, startIndex, endIndex, matchCount, maxLen) {\n // Partition the available space into equal sized areas for each match and one\n // for the text start.\n // But the size should not go below a certain limit\n var size = Math.max(Math.floor(maxLen / (matchCount + 1)), minMatchWithContextSize);\n\n // Substract the size of the range to get the size of the context.\n var contextSize = Math.max(size - (endIndex - startIndex), 0);\n // Two thirds of the context should be before the match, one third after.\n var contextEnd = Math.min(Math.floor(endIndex + contextSize / 3), s.length);\n var contextStart = Math.max(contextEnd - size, 0);\n\n // If the contextStart/End is inside a word and the end of the word is\n // close move the pointers accordingly to make the text more readable.\n contextStart = moveToWordBorder(s, contextStart, true);\n contextEnd = moveToWordBorder(s, contextEnd, false);\n\n return { start: contextStart, end: contextEnd };\n };\n\n // Get all ranges around matched substrings with their contexts\n //\n var getMatchedTextWithContextRanges = function(textAndMatches, s, maxLen) {\n var ranges = [];\n var matchCount = getMatchedTextCount(textAndMatches);\n var pos = 0;\n for (var i = 0; i < textAndMatches.length; i++) {\n var t = textAndMatches[i];\n var text = t.text;\n if (t.isMatch) {\n var range = getContextRangeAround(s, pos, pos + text.length, matchCount, maxLen);\n addRange(ranges, range.start, range.end);\n }\n pos += text.length;\n }\n return ranges;\n };\n\n var fillUpRanges = function(s, ranges, maxLen) {\n var remainingLen = maxLen - getTotalRangesSize(ranges);\n while (remainingLen > 0) {\n if (ranges.length == 0) {\n // No matches added yet. Make one large range.\n addRange(ranges, 0, moveToWordBorder(s, maxLen, false));\n return;\n } else {\n var range = ranges[0];\n var startIndex;\n var maxEndIndex;\n if (range.start == 0) {\n // The first range already starts at the beginning of the string.\n\n // When there is a second range fill to the next range start or to the maxLen.\n startIndex = range.end;\n if (ranges.length > 1) {\n maxEndIndex = ranges[1].start;\n } else {\n // Only one range. Add a range after that with the complete remaining len\n // (corrected to "beautify" the output)\n addRange(ranges, startIndex, moveToWordBorder(s, startIndex + remainingLen, false));\n return;\n }\n } else {\n // There is unused space between the start of the text and the first range.\n startIndex = 0;\n maxEndIndex = range.start;\n }\n var endIndex = Math.min(maxEndIndex, startIndex + remainingLen);\n addRange(ranges, startIndex, endIndex);\n remainingLen -= (endIndex - startIndex);\n }\n }\n };\n\n\n // Write the given ranges of s, using textAndMatches for marking portions of the text.\n //\n var writeRanges = function(place, s, textAndMatches, ranges, maxLen) {\n if (ranges.length == 0) return;\n\n // Processes the text between startIndex and endIndex of the textAndMatches\n // "writes" them (as DOM elements) at the given place, possibly as "marked" text.\n //\n // When endIndex is not the end of the full text an ellisis is appended.\n //\n var writeTextAndMatchRange = function(place, s, textAndMatches, startIndex, endIndex) {\n var t;\n var text;\n\n // find the first text item to write\n var pos = 0;\n var i = 0;\n var offset = 0;\n for (;i < textAndMatches.length; i++) {\n t = textAndMatches[i];\n text = t.text;\n if (startIndex < pos + text.length) {\n offset = startIndex - pos;\n break;\n }\n pos += text.length;\n }\n\n var remainingLen = endIndex - startIndex;\n for (; i < textAndMatches.length && remainingLen > 0; i++) {\n t = textAndMatches[i];\n text = t.text.substr(offset);\n offset = 0;\n if (text.length > remainingLen) text = text.substr(0, remainingLen);\n\n if (t.isMatch) {\n createTiddlyElement(place, "span", null, "marked", text);\n } else {\n createTiddlyText(place, text);\n }\n remainingLen -= text.length;\n }\n\n if (endIndex < s.length) {\n abego.createEllipsis(place);\n }\n };\n\n // When the first range is not at the start of the text write an ellipsis("...")\n // (Ellipses between ranges are written in the writeTextAndMatchRange method)\n if (ranges[0].start > 0) abego.createEllipsis(place);\n\n var remainingLen = maxLen;\n for (var i = 0; i < ranges.length && remainingLen > 0; i++) {\n var range = ranges[i];\n var len = Math.min(range.end - range.start, remainingLen);\n writeTextAndMatchRange(place, s, textAndMatches, range.start, range.start + len);\n remainingLen -= len;\n }\n };\n\n this.render = function(place, s, maxLen, markRegExp) {\n if (s.length < maxLen) maxLen = s.length;\n\n var textAndMatches = getTextAndMatchArray(s, markRegExp);\n\n var ranges = getMatchedTextWithContextRanges(textAndMatches, s, maxLen);\n\n // When the maxLen is not yet reached add more ranges\n // starting from the beginning until either maxLen or\n // the end of the string is reached.\n fillUpRanges(s, ranges, maxLen);\n\n writeRanges(place, s, textAndMatches, ranges, maxLen);\n };\n};\n\n\n\n(function() {\n\nfunction alertAndThrow(msg) {\n alert(msg);\n throw msg;\n};\n\nif (version.major < 2 || (version.major == 2 && version.minor < 1))\n alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.1 or newer.\sn\snCheck the archive for YourSearch plugins\snsupporting older versions of TiddlyWiki.\sn\snArchive: http://tiddlywiki.abego-software.de/archive");\n\nabego.YourSearch = {};\n\n//----------------------------------------------------------------------------\n// The Search Core\n//----------------------------------------------------------------------------\n\n// Model Variables\nvar lastResults = undefined; // Array of tiddlers that matched the last search\nvar lastQuery = undefined; // The last Search query (TiddlerQuery)\n\nvar setLastResults = function(array) {\n lastResults = array;\n};\n\nvar getLastResults = function() {\n return lastResults ? lastResults : [];\n};\n\nvar getLastResultsCount = function() {\n return lastResults ? lastResults.length : 0;\n};\n\n// Standard Ranking Weights\nvar matchInTitleWeight = 4;\nvar precisionInTitleWeight = 10;\nvar matchInTagsWeight = 2;\n\nvar getMatchCount = function(s, re) {\n var m = s.match(re);\n return m ? m.length : 0;\n};\n\nvar standardRankFunction = function(tiddler, query) {\n // Count the matches in the title and the tags\n var markRE = query.getMarkRegExp();\n if (!markRE) return 1;\n\n var matchesInTitle = tiddler.title.match(markRE);\n var nMatchesInTitle = matchesInTitle ? matchesInTitle.length : 0;\n var nMatchesInTags = getMatchCount(tiddler.getTags(), markRE);\n\n // Calculate the "precision" of the matches in the title as the ratio of\n // the length of the matches to the total length of the title.\n var lengthOfMatchesInTitle = matchesInTitle ? matchesInTitle.join("").length : 0;\n var precisionInTitle = tiddler.title.length > 0 ? lengthOfMatchesInTitle / tiddler.title.length : 0;\n\n // calculate a weighted score\n var rank = nMatchesInTitle * matchInTitleWeight\n + nMatchesInTags * matchInTagsWeight\n + precisionInTitle * precisionInTitleWeight\n + 1;\n\n return rank;\n};\n\n// @return Tiddler[]\n//\nvar findMatches = function(store, searchText, caseSensitive, useRegExp, sortField, excludeTag) {\n lastQuery = null;\n\n var candidates = store.reverseLookup("tags", excludeTag, false);\n try {\n var defaultFields = [];\n if (config.options.chkSearchInTitle) defaultFields.push("title");\n if (config.options.chkSearchInText) defaultFields.push("text");\n if (config.options.chkSearchInTags) defaultFields.push("tags");\n lastQuery = new abego.TiddlerQuery(\n searchText, caseSensitive, useRegExp, defaultFields, config.options.chkSearchExtendedFields);\n } catch (e) {\n // when an invalid query is given no tiddlers are matched\n return [];\n }\n\n var results = lastQuery.filter(candidates);\n\n // Rank the results\n var rankFunction = abego.YourSearch.getRankFunction();\n for (var i = 0; i < results.length; i++) {\n var tiddler = results[i];\n var rank = rankFunction(tiddler, lastQuery);\n // Add the rank information to the tiddler.\n // This is used during the sorting, but it may also\n // be used in the result, e.g. to display some "relevance"\n // information in the result\n tiddler.searchRank = rank;\n }\n\n // sort the result, taking care of the rank and the sortField\n if(!sortField) sortField = "title";\n\n var sortFunction = function (a, b) {\n var searchRankDiff = a.searchRank - b.searchRank;\n if (searchRankDiff == 0) {\n if (a[sortField] == b[sortField]) {\n return(0);\n } else {\n return (a[sortField] < b[sortField]) ? -1 : +1;\n }\n } else {\n return (searchRankDiff > 0) ? -1 : +1;\n }\n };\n results.sort(sortFunction);\n return results;\n};\n\n//----------------------------------------------------------------------------\n// The Search UI (Result page)\n//----------------------------------------------------------------------------\n\n\n// Visual appearance of the result page\nvar maxCharsInTitle = 80;\nvar maxCharsInTags = 50;\nvar maxCharsInText = 250;\nvar maxCharsInField = 50;\n\nvar itemsPerPageDefault = 25; // Default maximum number of items on one search result page\nvar itemsPerPageWithPreviewDefault = 10; // Default maximum number of items on one search result page when PreviewText is on\n\n// DOM IDs\nvar yourSearchResultID = "yourSearchResult";\nvar yourSearchResultItemsID = "yourSearchResultItems";\n\nvar lastSearchText = null; // The last search text, as passed to findMatches\n\nvar resultElement = null; // The (popup) DOM element containing the search result [may be null]\nvar searchInputField = null; // The "search" input field\nvar searchButton = null; // The "search" button\nvar lastNewTiddlerButton = null;\n\nvar initStylesheet = function() {\n if (version.extensions.YourSearchPlugin.styleSheetInited)\n return;\n\n version.extensions.YourSearchPlugin.styleSheetInited = true;\n setStylesheet(store.getTiddlerText("YourSearchStyleSheet"), "yourSearch");\n};\n\nvar isResultOpen = function() {\n return resultElement != null && resultElement.parentNode == document.body;\n};\n\nvar closeResult = function() {\n if (isResultOpen()) {\n document.body.removeChild(resultElement);\n }\n};\n\n// Closes the Search Result window and displays the tiddler\n// defined by the "tiddlyLink" attribute of this element\n//\nvar closeResultAndDisplayTiddler = function(e) {\n closeResult();\n\n var title = this.getAttribute("tiddlyLink");\n if(title) {\n var withHilite = this.getAttribute("withHilite");\n var oldHighlightHack = highlightHack;\n if (withHilite && withHilite == "true" && lastQuery) {\n highlightHack = lastQuery.getMarkRegExp();\n }\n story.displayTiddler(this, title);\n highlightHack = oldHighlightHack;\n }\n return(false);\n};\n\n// Adjusts the resultElement's size and position, relative to the search input field.\n//\nvar adjustResultPositionAndSize = function() {\n if (!searchInputField) return;\n\n var root = searchInputField;\n\n // Position the result below the root and resize it if necessary.\n var rootLeft = findPosX(root);\n var rootTop = findPosY(root);\n var rootHeight = root.offsetHeight;\n var popupLeft = rootLeft;\n var popupTop = rootTop + rootHeight;\n\n // Make sure the result is not wider than the window\n var winWidth = findWindowWidth();\n// console.log("rootLeft", rootLeft, "rootTop", rootTop)\n// console.log("winWidth", winWidth)\n// console.log("resultElement", resultElement.offsetWidth)\n \n if (winWidth < resultElement.offsetWidth) {\n resultElement.style.width = (winWidth - 100) + "px";\n winWidth = findWindowWidth(); // Not sure why this is needed, Okido 03-06-2023\n }\n\n // Ensure that the left and right of the result are not\n // clipped by the window. Move it to the left or right, if necessary.\n var popupWidth = resultElement.offsetWidth;\n \n // Calculate for the center position, Okido 03-06-2023\n popupLeft = (winWidth - popupWidth) / 2\n \n if(popupLeft + popupWidth > winWidth)\n popupLeft = winWidth - popupWidth - 30;\n if (popupLeft < 0) popupLeft = 0;\n\n // Do the actual moving\n resultElement.style.left = popupLeft + "px";\n resultElement.style.top = popupTop + "px";\n resultElement.style.display = "block";\n};\n\nvar scrollVisible = function() {\n // Scroll the window to make the result page (and the search Input field) visible.\n if (resultElement) window.scrollTo(0, ensureVisible(resultElement));\n if (searchInputField) window.scrollTo(0, ensureVisible(searchInputField));\n};\n\n// Makes sure the result page has a good size and position and visible\n// (may scroll the window)\n//\nvar ensureResultIsDisplayedNicely = function() {\n adjustResultPositionAndSize();\n scrollVisible();\n};\n\n\n\nvar indexInPage = undefined; // The index (in the current page) of the tiddler currently rendered.\nvar currentTiddler = undefined; // While rendering the page the tiddler that is currently rendered.\n\nvar pager = new abego.PageWiseRenderer();\n\nvar MyItemRenderer = function(parent) {\n // Load the template how to display the items that represent a found tiddler\n this.itemHtml = store.getTiddlerText("YourSearchItemTemplate");\n if (!this.itemHtml) alertAndThrow("YourSearchItemTemplate not found");\n\n // Locate the node that shall contain the list of found tiddlers\n this.place = document.getElementById(yourSearchResultItemsID);\n if(!this.place)\n this.place = createTiddlyElement(parent, "div", yourSearchResultItemsID);\n};\n\nmerge(MyItemRenderer.prototype, {\n render: function(pager, object, index, indexOnPage) {\n // Define global variables, referenced by macros during applyHtmlMacros\n indexInPage = indexOnPage;\n currentTiddler = object;\n\n var item = createTiddlyElement(this.place, "div", null, "yourSearchItem");\n item.innerHTML = this.itemHtml;\n applyHtmlMacros(item, null);\n refreshElements(item, null);\n },\n\n endRendering: function(pager) {\n // The currentTiddler must only be defined while rendering the found tiddlers\n currentTiddler = null;\n }\n});\n\n// Refreshes the content of the result with the current search result\n// of the selected page.\n//\n// Assumes that the result is already open.\n//\nvar refreshResult = function() {\n if (!resultElement || !searchInputField) return;\n\n // Load the template for the YourSearchResult\n var html = store.getTiddlerText("YourSearchResultTemplate");\n if (!html) html = "<b>Tiddler YourSearchResultTemplate not found</b>";\n resultElement.innerHTML = html;\n\n // Expand the template macros etc.\n applyHtmlMacros(resultElement, null);\n refreshElements(resultElement, null);\n\n var itemRenderer = new MyItemRenderer(resultElement);\n pager.renderPage(itemRenderer);\n\n ensureResultIsDisplayedNicely();\n};\n\npager.getItemsPerPage = function() {\n var n = (config.options.chkPreviewText)\n ? abego.toInt(config.options.txtItemsPerPageWithPreview, itemsPerPageWithPreviewDefault)\n : abego.toInt(config.options.txtItemsPerPage, itemsPerPageDefault);\n return (n > 0) ? n : 1;\n};\n\npager.onPageChanged = function() {\n refreshResult();\n};\n\nvar reopenResultIfApplicable = function() {\n if (searchInputField == null || !config.options.chkUseYourSearch) return;\n\n if ((searchInputField.value == lastSearchText) && lastSearchText && !isResultOpen()) {\n // For speedup we check re-use the previously created resultElement, if possible.\n if (resultElement && (resultElement.parentNode != document.body)) {\n document.body.appendChild(resultElement);\n ensureResultIsDisplayedNicely();\n } else {\n abego.YourSearch.onShowResult(true);\n }\n }\n};\n\n\nvar invalidateResult = function() {\n closeResult();\n resultElement = null;\n lastSearchText = null;\n};\n\n\n\n//-------------------------------------------------------------------------\n// Close the search result page when the user clicks on the document\n// (and not into the searchInputField, on the search button or in the result)\n// or presses the ESC key\n\n// Returns true if e is either self or a descendant (child, grandchild,...) of self.\n//\n// @param self DOM:Element\n// @param e DOM:Element or null\n//\nvar isDescendantOrSelf = function(self, e) {\n while (e != null) {\n if (self == e) return true;\n e = e.parentNode;\n }\n return false;\n};\n\nvar onDocumentClick = function(e) {\n if (e.target == searchInputField) return;\n if (e.target == searchButton) return;\n if (resultElement && isDescendantOrSelf(resultElement, e.target)) return;\n\n closeResult();\n};\n\nvar onDocumentKeyup = function(e) {\n // Close the search result page when the user presses "ESC"\n if (e.keyCode == 27) closeResult();\n};\naddEvent(document, "click", onDocumentClick);\naddEvent(document, "keyup", onDocumentKeyup);\n\n\n// Our Search Macro Hijack Function ==========================================\n\n// Helper\nvar myStorySearch = function(text, useCaseSensitive, useRegExp) {\n lastSearchText = text;\n setLastResults(findMatches(store, text, useCaseSensitive, useRegExp, "title", "excludeSearch"));\n\n abego.YourSearch.onShowResult();\n};\n\n\nvar myMacroSearchHandler = function(place, macroName, params, wikifier, paramString, tiddler) {\n initStylesheet();\n\n lastSearchText = "";\n var searchTimeout = null;\n var doSearch = function(txt) {\n if (config.options.chkUseYourSearch)\n myStorySearch(txt.value, config.options.chkCaseSensitiveSearch, config.options.chkRegExpSearch);\n else\n story.search(txt.value, config.options.chkCaseSensitiveSearch, config.options.chkRegExpSearch);\n lastSearchText = txt.value;\n };\n var clickHandler = function(e) {\n doSearch(searchInputField);\n return false;\n };\n var keyHandler = function(e)\n {\n if (!e) e = window.event;\n searchInputField = this;\n switch(e.keyCode) {\n case 13:\n if (e.ctrlKey && lastNewTiddlerButton && isResultOpen())\n lastNewTiddlerButton.onclick.apply(lastNewTiddlerButton, [e]);\n else\n doSearch(this);\n break;\n case 27:\n // When the result is open, close it,\n // otherwise clear the content of the input field\n if (isResultOpen()) {\n closeResult();\n } else {\n this.value = "";\n clearMessage();\n }\n break;\n }\n if (String.fromCharCode(e.keyCode) == this.accessKey || e.altKey) {\n reopenResultIfApplicable();\n }\n\n if(this.value.length < 3 && searchTimeout) clearTimeout(searchTimeout);\n if(this.value.length > 2) {\n if (this.value != lastSearchText) {\n if (!config.options.chkUseYourSearch || config.options.chkSearchAsYouType) {\n if(searchTimeout)\n clearTimeout(searchTimeout);\n var txt = this;\n searchTimeout = setTimeout(function() { doSearch(txt) }, 500);\n }\n } else {\n if(searchTimeout) clearTimeout(searchTimeout);\n }\n };\n if (this.value.length == 0) {\n closeResult();\n }\n };\n\n\n var focusHandler = function(e) {\n this.select();\n clearMessage();\n reopenResultIfApplicable();\n };\n\n\n var args = paramString.parseParams("list", null, true);\n // either create the button to the left or the right of the text.\n var buttonAtRight = getFlag(args, "buttonAtRight");\n var sizeTextbox = getParam(args, "sizeTextbox", this.sizeTextbox);\n\n var txt = createTiddlyElement(null, "input", "search_box", "txtOptionInput searchField", null);\n if(params[0]) txt.value = params[0];\n txt.onkeyup = keyHandler;\n txt.onfocus = focusHandler;\n txt.setAttribute("size", sizeTextbox);\n txt.setAttribute("accessKey", this.accessKey);\n txt.setAttribute("autocomplete", "off");\n if(config.browser.isSafari) {\n txt.setAttribute("type", "search");\n txt.setAttribute("results", "5");\n }\n else if (!config.browser.isIE)\n txt.setAttribute("type", "text");\n\n var btn = createTiddlyButton(null, this.label, this.prompt, clickHandler);\n if (place) {\n if (!buttonAtRight) place.appendChild(btn);\n place.appendChild(txt);\n if (buttonAtRight) place.appendChild(btn);\n }\n\n searchInputField = txt;\n searchButton = btn;\n \n // Hide the button and add a placeholder in the searchbox, changed 03-06-2023 by Okido \n jQuery("a[title = \s"Search this TiddlyWiki\s"]").css({"display": "none"});\n jQuery(".searchField").attr({"placeholder": "Search"});\n \n \n \n};\n\n//----------------------------------------------------------------------------\n// Support for Macros\n//----------------------------------------------------------------------------\n\nvar openAllFoundTiddlers = function() {\n closeResult();\n var results = getLastResults();\n var n = results.length;\n if (n) {\n var titles = [];\n for(var i = 0; i < n; i++)\n titles.push(results[i].title);\n story.displayTiddlers(null, titles);\n }\n};\n\nvar createOptionWithRefresh = function(place, optionParams, wikifier, tiddler) {\n invokeMacro(place, "option", optionParams, wikifier, tiddler);\n // The option macro appended the component at the end of the place.\n var elem = place.lastChild;\n var oldOnClick = elem.onclick;\n elem.onclick = function(e) {\n var result = oldOnClick.apply(this, arguments);\n refreshResult();\n return result;\n };\n return elem;\n};\n\nvar removeTextDecoration = function(s) {\n var removeThis = ["''", "{{{", "}}}", "//", "<<<", "/***", "***/"];\n var reText = "";\n for (var i = 0; i < removeThis.length; i++) {\n if (i != 0) reText += "|";\n reText += "(" + removeThis[i].escapeRegExp() + ")";\n }\n return s.replace(new RegExp(reText, "mg"), "").trim();\n};\n\n\n\n// Returns the "shortcut number" of the currentTiddler.\n// I.e. When the user presses Alt-n the given tiddler is opened/display.\n//\n// @return 0-9 or -1 when no number is defined\n//\nvar getShortCutNumber = function() {\n var i = indexInPage;\n return (i >= 0 && i <= 9)\n ? (i < 9 ? (i + 1) : 0)\n : -1;\n};\n\nvar limitedTextRenderer = new abego.LimitedTextRenderer();\nvar renderLimitedText = function(place, s, maxLen) {\n limitedTextRenderer.render(place, s, maxLen, lastQuery.getMarkRegExp());\n};\n\n// When any tiddler are changed reset the result.\n//\nvar oldTiddlyWikiSaveTiddler = TiddlyWiki.prototype.saveTiddler;\nTiddlyWiki.prototype.saveTiddler = function(title, newTitle, newBody, modifier, modified, tags, fields) {\n oldTiddlyWikiSaveTiddler.apply(this, arguments);\n invalidateResult();\n};\nvar oldTiddlyWikiRemoveTiddler = TiddlyWiki.prototype.removeTiddler;\nTiddlyWiki.prototype.removeTiddler = function(title) {\n oldTiddlyWikiRemoveTiddler.apply(this, arguments);\n invalidateResult();\n};\n\n//----------------------------------------------------------------------------\n// Macros\n//----------------------------------------------------------------------------\n\n// ====Macro yourSearch ================================================\n\nconfig.macros.yourSearch = {\n // Standard Properties\n label: "yourSearch",\n prompt: "Gives access to the current/last YourSearch result",\n\n handler: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (params.length == 0) return;\n\n var name = params[0];\n var func = config.macros.yourSearch.funcs[name];\n if (func) func(place, macroName, params, wikifier, paramString, tiddler);\n },\n\n tests: {\n "true": function() { return true },\n "false": function() { return false },\n "found": function() { return getLastResultsCount() > 0 },\n "previewText": function() { return config.options.chkPreviewText }\n },\n\n funcs: {\n itemRange: function(place) {\n if (getLastResultsCount()) {\n var lastIndex = pager.getLastIndexOnPage();\n var s = "%0 - %1".format([pager.getFirstIndexOnPage() + 1, lastIndex + 1]);\n createTiddlyText(place, s);\n }\n },\n\n count: function(place) {\n createTiddlyText(place, getLastResultsCount().toString());\n },\n\n query: function(place) {\n if (lastQuery) {\n createTiddlyText(place, lastQuery.toString());\n }\n },\n\n version: function(place) {\n var t = "YourSearch %0.%1.%2".format(\n [version.extensions.YourSearchPlugin.major,\n version.extensions.YourSearchPlugin.minor,\n version.extensions.YourSearchPlugin.revision]);\n var e = createTiddlyElement(place, "a");\n e.setAttribute("href", "http://tiddlywiki.abego-software.de/#YourSearchPlugin");\n e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">' + t + '<font>';\n },\n\n copyright: function(place) {\n var e = createTiddlyElement(place, "a");\n e.setAttribute("href", "http://www.abego-software.de");\n e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">© 2005-2008 <b><font color="red">abego</font></b> Software<font>';\n },\n\n newTiddlerButton: function(place) {\n if (lastQuery) {\n var r = abego.parseNewTiddlerCommandLine(lastQuery.getQueryText());\n var btn = config.macros.newTiddler.createNewTiddlerButton(place, r.title, r.params, "new tiddler", "Create a new tiddler based on search text. (Shortcut: Ctrl-Enter; Separators: '.', '#')", null, "text");\n // Close the result before the new tiddler is created.\n var oldOnClick = btn.onclick;\n btn.onclick = function() {\n closeResult();\n oldOnClick.apply(this, arguments);\n };\n lastNewTiddlerButton = btn;\n }\n },\n\n linkButton: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (params < 2) return;\n\n var tiddlyLink = params[1];\n var text = params < 3 ? tiddlyLink : params[2];\n var tooltip = params < 4 ? text : params[3];\n var accessKey = params < 5 ? null : params[4];\n\n var btn = createTiddlyButton(place, text, tooltip, closeResultAndDisplayTiddler, null, null, accessKey);\n btn.setAttribute("tiddlyLink", tiddlyLink);\n },\n\n closeButton: function(place, macroName, params, wikifier, paramString, tiddler) {\n createTiddlyButton(place, "close", "Close the Search Results (Shortcut: ESC)", closeResult);\n },\n\n openAllButton: function(place, macroName, params, wikifier, paramString, tiddler) {\n var n = getLastResultsCount();\n if (n == 0) return;\n\n var title = n == 1 ? "open tiddler" : "open all %0 tiddlers".format([n]);\n var button = createTiddlyButton(place, title, "Open all found tiddlers (Shortcut: Alt-O)", openAllFoundTiddlers);\n button.setAttribute("accessKey", "O");\n },\n\n naviBar: function(place, macroName, params, wikifier, paramString, tiddler) {\n pager.addPageNavigation(place);\n },\n\n "if": function(place, macroName, params, wikifier, paramString, tiddler) {\n if (params.length < 2) return;\n\n var testName = params[1];\n var negate = (testName == "not");\n if (negate) {\n if (params.length < 3) return;\n testName = params[2];\n }\n\n var test = config.macros.yourSearch.tests[testName];\n var showIt = false;\n try {\n if (test) {\n showIt = test(place, macroName, params, wikifier, paramString, tiddler) != negate;\n } else {\n // When no predefined test is specified try to evaluate it as a JavaScript expression.\n showIt = (!eval(testName)) == negate;\n }\n } catch (ex) {\n }\n\n if (!showIt) {\n place.style.display = "none";\n }\n },\n\n chkPreviewText: function(place, macroName, params, wikifier, paramString, tiddler) {\n var elem = createOptionWithRefresh(place, "chkPreviewText", wikifier, tiddler);\n elem.setAttribute("accessKey", "P");\n elem.title = "Show text preview of found tiddlers (Shortcut: Alt-P)";\n return elem;\n }\n }\n};\n\n\n// ====Macro foundTiddler ================================================\n\nconfig.macros.foundTiddler = {\n // Standard Properties\n label: "foundTiddler",\n prompt: "Provides information on the tiddler currently processed on the YourSearch result page",\n\n handler: function(place, macroName, params, wikifier, paramString, tiddler) {\n var name = params[0];\n var func = config.macros.foundTiddler.funcs[name];\n if (func) func(place, macroName, params, wikifier, paramString, tiddler);\n },\n\n funcs: {\n title: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (!currentTiddler) return;\n\n var shortcutNumber = getShortCutNumber();\n var tooltip = shortcutNumber >= 0\n ? "Open tiddler (Shortcut: Alt-%0)".format([shortcutNumber.toString()])\n : "Open tiddler";\n\n var btn = createTiddlyButton(place, null, tooltip, closeResultAndDisplayTiddler, null);\n btn.setAttribute("tiddlyLink", currentTiddler.title);\n btn.setAttribute("withHilite", "true");\n\n renderLimitedText(btn, currentTiddler.title, maxCharsInTitle);\n\n if (shortcutNumber >= 0) {\n btn.setAttribute("accessKey", shortcutNumber.toString());\n }\n },\n\n tags: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (!currentTiddler) return;\n\n renderLimitedText(place, currentTiddler.getTags(), maxCharsInTags);\n },\n\n text: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (!currentTiddler) return;\n\n renderLimitedText(place, removeTextDecoration(currentTiddler.text), maxCharsInText);\n },\n\n field: function(place, macroName, params, wikifier, paramString, tiddler) {\n if (!currentTiddler) return;\n var name = params[1];\n var len = params.length > 2 ? abego.toInt(params[2], maxCharsInField) : maxCharsInField;\n var v = store.getValue(currentTiddler, name);\n if (v)\n renderLimitedText(place, removeTextDecoration(v), len);\n },\n\n // Renders the "shortcut number" of the current tiddler, to indicate to the user\n // what number to "Alt-press" to open the tiddler.\n //\n number: function(place, macroName, params, wikifier, paramString, tiddler) {\n var numberToDisplay = getShortCutNumber();\n if (numberToDisplay >= 0) {\n var text = "%0)".format([numberToDisplay.toString()]);\n createTiddlyElement(place, "span", null, "shortcutNumber", text);\n }\n }\n }\n};\n\n\n//----------------------------------------------------------------------------\n// Configuration Stuff\n//----------------------------------------------------------------------------\n\nvar opts = {\n chkUseYourSearch: true,\n chkPreviewText: true,\n chkSearchAsYouType: true,\n chkSearchInTitle: true,\n chkSearchInText: true,\n chkSearchInTags: true,\n chkSearchExtendedFields: true,\n txtItemsPerPage: itemsPerPageDefault,\n txtItemsPerPageWithPreview: itemsPerPageWithPreviewDefault\n};\nfor (var n in opts)\n if (config.options[n] == undefined) config.options[n] = opts[n];\n\n\n\n\n//----------------------------------------------------------------------------\n// Shadow Tiddlers\n//----------------------------------------------------------------------------\n\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// ";\n\nconfig.shadowTiddlers["YourSearch Help"] =\n"!Field Search\snWith the Field Search you can restrict your search to certain fields of a tiddler, e.g" +\n" only search the tags or only the titles. The general form is //fieldname//'':''//textToSearch// (e." +\n"g. {{{title:intro}}}). In addition one-character shortcuts are also supported for the standard field" +\n"s {{{title}}}, {{{text}}} and {{{tags}}}:\sn|!What you want|!What you type|!Example|\sn|Search ''titles " +\n"only''|start word with ''!''|{{{!jonny}}} (shortcut for {{{title:jonny}}})|\sn|Search ''contents/text " +\n"only''|start word with ''%''|{{{%football}}} (shortcut for {{{text:football}}})|\sn|Search ''tags only" +\n"''|start word with ''#''|{{{#Plugin}}} (shortcut for {{{tags:Plugin}}})|\sn\snUsing this feature you may" +\n" also search the extended fields (\s"Metadata\s") introduced with TiddlyWiki 2.1, e.g. use {{{priority:1" +\n"}}} to find all tiddlers with the priority field set to \s"1\s".\sn\snYou may search a word in more than one" +\n" field. E.g. {{{!#Plugin}}} (or {{{title:tags:Plugin}}} in the \s"long form\s") finds tiddlers containin" +\n"g \s"Plugin\s" either in the title or in the tags (but does not look for \s"Plugin\s" in the text). \sn\sn!Boole" +\n"an Search\snThe Boolean Search is useful when searching for multiple words.\sn|!What you want|!What you " +\n"type|!Example|\sn|''All words'' must exist|List of words|{{{jonny jeremy}}} (or {{{jonny and jeremy}}}" +\n")|\sn|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\sn|A word ''must " +\n"not exist''|Start word with ''-''|{{{-jonny}}} (or {{{not jonny}}})|\sn\sn''Note:'' When you specify two" +\n" words, separated with a space, YourSearch finds all tiddlers that contain both words, but not neces" +\n"sarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need" +\n" to put the words into quotes. I.e. you type: {{{\s"john brown\s"}}}.\sn\snUsing parenthesis you may change " +\n"the default \s"left to right\s" evaluation of the boolean search. E.g. {{{not (jonny or jeremy)}}} finds" +\n" all tiddlers that contain neither \s"jonny\s" nor \s"jeremy. In contrast to this {{{not jonny or jeremy}}" +\n"} (i.e. without parenthesis) finds all tiddlers that either don't contain \s"jonny\s" or that contain \s"j" +\n"eremy\s".\sn\sn!'Exact Word' Search\snBy default a search result all matches that 'contain' the searched tex" +\n"t. E.g. if you search for {{{Task}}} you will get all tiddlers containing 'Task', but also '~Complet" +\n"edTask', '~TaskForce' etc.\sn\snIf you only want to get the tiddlers that contain 'exactly the word' you" +\n" need to prefix it with a '='. E.g. typing '=Task' will find the tiddlers that contain the word 'Tas" +\n"k', ignoring words that just contain 'Task' as a substring.\sn\sn!~CaseSensitiveSearch and ~RegExpSearch" +\n"\snThe standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearc" +\n"h. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\sn\snIn addition you m" +\n"ay do a \s"regular expression\s" search even with the ''~RegExpSearch'' set to false by directly enterin" +\n"g the regular expression into the search field, framed with {{{/.../}}}. \sn\snExample: {{{/m[ae][iy]er/" +\n"}}} will find all tiddlers that contain either \s"maier\s", \s"mayer\s", \s"meier\s" or \s"meyer\s".\sn\sn!~JavaScript E" +\n"xpression Filtering\snIf you are familiar with JavaScript programming and know some TiddlyWiki interna" +\n"ls you may also use JavaScript expression for the search. Just enter a JavaScript boolean expression" +\n" into the search field, framed with {{{ { ... } }}}. In the code refer to the variable tiddler and e" +\n"valuate to {{{true}}} when the given tiddler should be included in the result. \sn\snExample: {{{ { tidd" +\n"ler.modified > new Date(\s"Jul 4, 2005\s")} }}} returns all tiddler modified after July 4th, 2005.\sn\sn!Com" +\n"bined Search\snYou are free to combine the various search options. \sn\sn''Examples''\sn|!What you type|!Res" +\n"ult|\sn|{{{!jonny !jeremy -%football}}}|all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its tit" +\n"les, but no {{{football}}} in content.|\sn|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact wor" +\n"d). Tags named '~CompletedTask', '~TaskForce' etc. are not considered.|\sn\sn!Access Keys\snYou are encour" +\n"aged to use the access keys (also called \s"shortcut\s" keys) for the most frequently used operations. F" +\n"or quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\sn\sn|" +\n"!Key|!Operation|\sn|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search in" +\n"put field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the pr" +\n"evious search result. This way you can quickly display multiple tiddlers using \s"Press {{{Alt-F}}}. S" +\n"elect tiddler.\s" sequences.|\sn|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Resul" +\n"t]] is already closed and the cursor is in the search input field the field's content is cleared so " +\n"you start a new query.|\sn|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second e" +\n"tc. tiddler from the result list.|\sn|{{{Alt-O}}}|Opens all found tiddlers.|\sn|{{{Alt-P}}}|Toggles the " +\n"'Preview Text' mode.|\sn|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[Your" +\n"Search Result]].|\sn|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the " +\n"{{{Return}}} key actually starts the search (as does pressing the 'search' button).|\sn\sn//If some of t" +\n"hese shortcuts don't work for you check your browser if you have other extensions installed that alr" +\n"eady \s"use\s" these shortcuts.//";\n\nconfig.shadowTiddlers["YourSearch Options"] =\n"|>|!YourSearch Options|\sn|>|<<option chkUseYourSearch>> Use 'Your Search'|\sn|!|<<option chkPreviewText" +\n">> Show Text Preview|\sn|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required" +\n" to start search)|\sn|!|Default Search Filter:<<option chkSearchInTitle>>Title ('!') <<option chk" +\n"SearchInText>>Text ('%') <<option chkSearchInTags>>Tags ('#') <<option chkSearchExtendedFiel" +\n"ds>>Extended Fields<html><br><font size=\s"-2\s">The fields of a tiddlers that are searched when you don" +\n"'t explicitly specify a filter in the search text <br>(Explictly specify fields using one or more '!" +\n"', '%', '#' or 'fieldname:' prefix before the word/text to find).</font></html>|\sn|!|Number of items " +\n"on search result page: <<option txtItemsPerPage>>|\sn|!|Number of items on search result page with pre" +\n"view text: <<option txtItemsPerPageWithPreview>>|\sn";\n\nconfig.shadowTiddlers["YourSearchStyleSheet"] =\n"/***\sn!~YourSearchResult Stylesheet\sn***/\sn/*{{{*/\sn.yourSearchResult {\sn\stz-index: 10;\sn\stposition: absolute;\sn\stwidth: 800" +\n"px;\sn\sn\stpadding: 0.2em;\sn\stlist-style: none;\sn\stmargin: 0;\sn\sn\stbackground: #ffd;\sn\stborder: 1px solid DarkGra" +\n"y;\sn}\sn\sn/*}}}*/\sn/***\sn!!Summary Section\sn***/\sn/*{{{*/\sn.yourSearchResult .summary {\sn\stborder-bottom-width:" +\n" thin;\sn\stborder-bottom-style: solid;\sn\stborder-bottom-color: #999999;\sn\stpadding-bottom: 4px;\sn}\sn\sn.yourSea" +\n"rchRange, .yourSearchCount, .yourSearchQuery {\sn\stfont-weight: bold;\sn}\sn\sn.yourSearchResult .summary ." +\n"button {\sn\stfont-size: 10px;\sn\sn\stpadding-left: 0.3em;\sn\stpadding-right: 0.3em;\sn}\sn\sn.yourSearchResult .summa" +\n"ry .chkBoxLabel {\sn\stfont-size: 10px;\sn\sn\stpadding-right: 0.3em;\sn}\sn\sn/*}}}*/\sn/***\sn!!Items Area\sn***/\sn/*{{{*" +\n"/\sn.yourSearchResult .marked {\sn\stbackground: none;\sn\stfont-weight: bold;\sn}\sn\sn.yourSearchItem {\sn\stmargin-to" +\n"p: 2px;\sn}\sn\sn.yourSearchNumber {\sn\stcolor: #808080;\sn}\sn\sn\sn.yourSearchTags {\sn\stcolor: #008000;\sn}\sn\sn.yourSearc" +\n"hText {\sn\stcolor: #808080;\sn\stmargin-bottom: 6px;\sn}\sn\sn/*}}}*/\sn/***\sn!!Footer\sn***/\sn/*{{{*/\sn.yourSearchFoote" +\n"r {\sn\stmargin-top: 8px;\sn\stborder-top-width: thin;\sn\stborder-top-style: solid;\sn\stborder-top-color: #999999;" +\n"\sn}\sn\sn.yourSearchFooter a:hover{\sn\stbackground: none;\sn\stcolor: none;\sn}\sn/*}}}*/\sn/***\sn!!Navigation Bar\sn***/" +\n"\sn/*{{{*/\sn.yourSearchNaviBar a {\sn\stfont-size: 16px;\sn\stmargin-left: 4px;\sn\stmargin-right: 4px;\sn\stcolor: bla" +\n"ck;\sn\sttext-decoration: underline;\sn}\sn\sn.yourSearchNaviBar a:hover {\sn\stbackground-color: none;\sn}\sn\sn.yourSe" +\n"archNaviBar .prev {\sn\stfont-weight: bold;\sn\stcolor: blue;\sn}\sn\sn.yourSearchNaviBar .currentPage {\sn\stcolor: #" +\n"FF0000;\sn\stfont-weight: bold;\sn\sttext-decoration: none;\sn}\sn\sn.yourSearchNaviBar .next {\sn\stfont-weight: bold" +\n";\sn\stcolor: blue;\sn}\sn/*}}}*/\sn";\n\nconfig.shadowTiddlers["YourSearchResultTemplate"] =\n"<!--{{{-->\sn<span macro=\s"yourSearch if found\s">\sn<!-- The Summary Header ============================" +\n"================ -->\sn<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s">" +\n"<tbody>\sn <tr>\sn\st<td align=\s"left\s">\sn\st\stYourSearch Result <span class=\s"yourSearchRange\s" macro=\s"yourSearc" +\n"h itemRange\s"></span>\sn\st\st of <span class=\s"yourSearchCount\s" macro=\s"yourSearch count\s"></span>\sn" +\n"\st\stfor <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>\sn\st</td>\sn\st<td class=\s"yourSea" +\n"rchButtons\s" align=\s"right\s">\sn\st\st<span macro=\s"yourSearch chkPreviewText\s"></span><span class=\s"chkBoxLabel" +\n"\s">preview text</span>\sn\st\st<span macro=\s"yourSearch newTiddlerButton\s"></span>\sn\st\st<span macro=\s"yourSearch openAllButton\s"></span>\sn\st\st<span macro=\s"yourSearch lin" +\n"kButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn\st\st<span macro=\s"yourSearch linkB" +\n"utton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn\st\st<span macro=\s"yourSearch clo" +\n"seButton\s"></span>\sn\st</td>\sn </tr>\sn</tbody></table>\sn\sn<!-- The List of Found Tiddlers =================" +\n"=========================== -->\sn<div id=\s"" + yourSearchResultItemsID + "\s" itemsPerPage=\s"25\s" itemsPerPageWithPr" +\n"eview=\s"10\s"></div>\sn\sn<!-- The Footer (with the Navigation) ===========================================" +\n"= -->\sn<table class=\s"yourSearchFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody" +\n">\sn <tr>\sn\st<td align=\s"left\s">\sn\st\stResult page: <span class=\s"yourSearchNaviBar\s" macro=\s"yourSearch naviBar" +\n"\s"></span>\sn\st</td>\sn\st<td align=\s"right\s"><span macro=\s"yourSearch version\s"></span>, <span macro=\s"yourSearc" +\n"h copyright\s"></span>\sn\st</td>\sn </tr>\sn</tbody></table>\sn<!-- end of the 'tiddlers found' case =========" +\n"================================== -->\sn</span>\sn\sn\sn<!-- The \s"No tiddlers found\s" case =================" +\n"========================== -->\sn<span macro=\s"yourSearch if not found\s">\sn<table class=\s"summary\s" border=" +\n"\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn <tr>\sn\st<td align=\s"left\s">\sn\st\stYourSearch Resu" +\n"lt: No tiddlers found for <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>.\sn\st</td>\sn\st<t" +\n"d class=\s"yourSearchButtons\s" align=\s"right\s">\sn\st\st<span macro=\s"yourSearch newTiddlerButton\s"></span>\sn\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options'" +\n" options 'Configure YourSearch'\s"></span>\sn\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help" +\n" 'Get help how to use YourSearch'\s"></span>\sn\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn\st</td>\sn <" +\n"/tr>\sn</tbody></table>\sn</span>\sn<!--}}}-->";\n\nconfig.shadowTiddlers["YourSearchItemTemplate"] =\n"<!--{{{-->\sn<span class='yourSearchNumber' macro='foundTiddler number'></span>\sn<span class='yourSea" +\n"rchTitle' macro='foundTiddler title'/></span> - \sn<span class='yourSearchTags' macro='found" +\n"Tiddler field tags 50'/></span>\sn<span macro=\s"yourSearch if previewText\s"><div class='yourSearchText' macro='fo" +\n"undTiddler field text 250'/></div></span>\sn<!--}}}-->";\n\nconfig.shadowTiddlers["YourSearch"] = "<<tiddler [[YourSearch Help]]>>";\n\nconfig.shadowTiddlers["YourSearch Result"] = "The popup-like window displaying the result of a YourSearch query.";\n\n//----------------------------------------------------------------------------\n// Install YourSearch\n//----------------------------------------------------------------------------\n\n// Overwrite the TiddlyWiki search handler and verify after a while\n// that nobody else has overwritten it.\nconfig.macros.search.handler = myMacroSearchHandler;\n\nvar checkForOtherHijacker = function() {\n // Check that still our search handler is installed\n if (config.macros.search.handler != myMacroSearchHandler) {\n alert(\n"Message from YourSearchPlugin:\sn\sn\snAnother plugin has disabled the 'Your Search' features.\sn\sn\snYou may " +\n"disable the other plugin or change the load order of \snthe plugins (by changing the names of the tidd" +\n"lers)\snto enable the 'Your Search' features.");\n }\n};\n\nsetTimeout(checkForOtherHijacker, 5000);\n\n// === Public API =================================\n\nabego.YourSearch.getStandardRankFunction = function() {\n return standardRankFunction;\n};\n\nabego.YourSearch.getRankFunction = function() {\n return abego.YourSearch.getStandardRankFunction();\n};\n\nabego.YourSearch.getCurrentTiddler = function() {\n return currentTiddler;\n};\n\nabego.YourSearch.closeResult = function() {\n closeResult();\n};\n\n// Returns an array of tiddlers that matched the last search\nabego.YourSearch.getFoundTiddlers = function() {\n return lastResults;\n};\n\n// The last Search query (TiddlerQuery), or null\nabego.YourSearch.getQuery = function() {\n return lastQuery;\n};\n\nabego.YourSearch.onShowResult = function(useOldResult) {\n highlightHack = lastQuery ? lastQuery.getMarkRegExp() : null;\n if (!useOldResult)\n pager.setItems(getLastResults());\n if (!resultElement) {\n resultElement = createTiddlyElement(document.body, "div", yourSearchResultID, "yourSearchResult");\n } else if (resultElement.parentNode != document.body) {\n document.body.appendChild(resultElement);\n }\n refreshResult();\n highlightHack = null;\n};\n\n})();\n} // of "install only once"\n// Used Globals (for JSLint) ==============\n\n// ... JavaScript Core\n/*global alert,clearTimeout,confirm */\n// ... TiddlyWiki Core\n/*global Tiddler, applyHtmlMacros, clearMessage, createTiddlyElement, createTiddlyButton, createTiddlyText, ensureVisible ,findPosX, highlightHack, findPosY,findWindowWidth, invokeMacro, saveChanges, refreshElements, story */\n//}}}\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005-2023 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n\n
/***\n|Name |displayMessageToast-Plugin.js |\n|Version |0.0.7 |\n|Version library | |\n|Description | |\n|Source |displayMessageToast-Source |\n|Documentation | |\n|Author |Okido |\n|Original author | |\n|License |See below under license |\n|Core version | |\n|Plugin type |systemConfig |\n|Status | |\n|Build date - time |12-09-2023 - 16:28, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin hijacks displayMessage().\nIf there are no settings defined for the [[displayMessageToast-Plugin.js]] the original displayMessage() is invoked.\n<<<\n!!!Usage\n<<<\nSettings:\n{{{\ndisplayMessage( "string", "link" or undefined, { "use": true, "color": "", "duration": "5000" } )\n\n "string", message to display,\n "link", if a link is required put it here else undefined\n "use": true, switch to use displayMessage-Plugin.js\n "color": "", set the color to use\n "duration": "5000", the time the message is displayed\n}}}\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2023 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 12-09-2023 */\nfunction displayMessage(r="",e,o){const t=r=>store.getTiddlerSlice("ColorPalette",r);!0===(o={use:!1,color:"yellow",text:""===r?"TiddlyWikiClassic Toastify is awesome!":r,link:void 0===e?"":e,duration:"4000",...o}).use?function(r){const e={gray:{light:t("TertiaryMid"),darken:t("TertiaryDark")},orange:{light:t("PureWarningMid"),darken:t("PureWarningDark")},blue:{light:t("PrimaryMid"),darken:t("PrimaryDark")},green:{light:t("PureSuccessMid"),darken:t("PureSuccessDark")},red:{light:t("PureErrorMid"),darken:t("PureErrorDark")},yellow:{light:t("SecondaryLight"),darken:t("SecondaryMid")}};let o=""===r.color?e.gray.light:!0===e.hasOwnProperty(r.color)?e[r.color].light:e.gray.light,a=""===r.color?e.gray.darken:!0===e.hasOwnProperty(r.color)?e[r.color].darken:e.gray.darken;Toastify({text:r.text+r.link,gravity:"bottom",position:"right",close:!1,newWindow:!1,duration:parseInt(r.duration),style:{background:o,"border-radius":"4px","border-left":`solid 16px ${a}`,"margin-left":"20px",color:"yellow"===r.color?"black":"white"}}).showToast()}(o):function(r,e){let o=getMessageDiv();if(!o)return void alert(r);e?createTiddlyElement(o,"a",null,null,r,{href:e,target:"_blank"}):o.appendChild(document.createTextNode(r))}(r,e)}\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |nwAppStyle-Plugin.js |\n|Description |The plugin provides an application look and feel when<br>running [[TiddlyWikiClassic]] in a [[NW.js]] environment |\n|Documentation | |\n|Version |1.3.3 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |nwAppStyle-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |15-10-2025 - 10:48, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin provides an application look and feel to [[TiddlyWikiClassic|http://www.tiddlywiki.com]] when running in a [[NW.js]] environment.\nThe [[TiddlyWikiClassic]] background area elements are hidden or removed and height is set to 0px.\nThe plugin works also in a modern browsers but the buttons for minimize, maximize and close window have no functionalty.\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\nAdd the following code to ViewTemplate, to ensure that the buttons are added.\n{{{\n<div macro="nwappstyle"></div>\n}}}\nRemove following code from PageTemplate.\n{{{\n<div class='header' role='banner' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n}}}\n<<<\n!!!Revisions\n<<<\n2025.10.15 1.3.4 CSS color adjustments\n2025.05.24 1.3.3 Removed some console.log() warnings that have no meaning anymore\n2025.01.11 1.3.0 Renamed the plugin, NW.js related plugins start with the prefix "nw", added estimated versions to the plugin information\n2023.12.10 1.2.9 Version information is now displayed using the native TWC function\n2023.08.13 1.2.8 Removed obsolete CSS for color switching when the wiki is for development\n2023.07.24 1.2.7 Fixed a CSS difference between [[NW.js]] and browsers and solved a conflict with [[SinglePageModePlugin]] \n2023.05.29 1.2.6 Fixed maximize button toggle failure \n2022.10.31 1.2.5 Optimized the code and moved all CSS to a dedicated CSS tiddler\n2022.01.29 1.2.4 Added warning text that the 3 window buttons do not work in a modern browser\n2021.11.13 1.2.3 Removed the browser limitation, the theme can be used in a modern browser too\n2020.10.17 1.2.1 Window buttons require a min size\n2019.12.25 1.2.0 Removed some obsolete code\n2019.10.27 1.1.1 Fixed some more positioning issue's, jQuery 3.4.1+ calculates width and height more accurate\n2019.10.01 1.1.0 Fixed some more positioning issue's\n2019.09.24 1.0.3 Fixed some more positioning issue's after refreshAll is done\n2019.09.22 1.0.2 The container for the buttons has a fixed position, the center of the container makes the window draggable\n2019.09.15 1.0.1 Re-written the code and minified as plugin\n<<<\n!!!License\n<<<\n!!License for the third party library code\nFont Awesome Free License\n-------------------------\n\nFont Awesome Free is free, open source, and GPL friendly. You can use it for\ncommercial projects, open source projects, or really almost whatever you want.\nFull Font Awesome Free license: https://fontawesome.com/license/free.\n\n<nowiki>#</nowiki> Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)\nIn the Font Awesome Free download, the CC BY 4.0 license applies to all icons\npackaged as SVG and JS file types.\n\n<nowiki>#</nowiki> Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL)\nIn the Font Awesome Free download, the SIL OFL license applies to all icons\npackaged as web and desktop font files.\n\n<nowiki>#</nowiki> Code: MIT License (https://opensource.org/licenses/MIT)\nIn the Font Awesome Free download, the MIT license applies to all non-font and\nnon-icon files.\n\n<nowiki>#</nowiki> Attribution\nAttribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font\nAwesome Free files already contain embedded comments with sufficient\nattribution, so you shouldn't need to do anything additional when using these\nfiles normally.\n\nWe've kept attribution comments terse, so we ask that you do not actively work\nto remove them from files, especially code. They're a great way for folks to\nlearn about Font Awesome.\n\n<nowiki>#</nowiki> Brand Icons\nAll brand icons are trademarks of their respective owners. The use of these\ntrademarks does not indicate endorsement of the trademark holder by Font\nAwesome, nor vice versa. **Please do not use brand logos for any purpose except\nto represent the company, product, or service to which they refer.**\n\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2025 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 15-10-2025 */\n"object"!=typeof config.macros.nwappstyle?config.macros.nwappstyle={}:config.macros.nwappstyle,config.macros.nwappstyle.init=function(){console.log("START INIT: nwAppStyle-Plugin.js");store.tiddlerExists("nwTWcAppStyle-Plugin.js")&&"<nowiki>coreBroker</nowiki>"!==store.getTiddlerText("SiteTitle")&&store.saveTiddler("nwTWcAppStyle-Plugin.js","nwAppStyle-Plugin.js");const e="zzz-config-development-TWC";!store.tiddlerExists(e)&&store.saveTiddler(e,e,"/*{{{*/\sn/* Set to true for development TWC, the window will turn dark red, last updated 22-03-2025 */\snconfig.options.chkDevelopmentTWC = false\sn/*}}}*/",config.options.txtUserName,new Date,"systemConfig",{});let n=store.getTiddler("ThemeBroker");n.text=n.text.replace("nwtwcappstyle","nwappstyle")},config.macros.nwappstyle.handler=function(){const e="windowheader",n="object"==typeof nw,t=!0===n?require("nw.gui").Window.get():"";setStylesheet(store.getTiddlerText("nwAppStyleStyleSheet"),"NWAppStyle"),!0===config.options.chkDevelopmentTWC&&setStylesheet(store.getTiddlerText("nwAppStyleStyleSheetDEV"),"nwAppStyleDEV");const i=["svgminimizebutton","svgmaximizebutton","svgclosebutton"],o=store.getTiddlerText("SiteTitle"),d=formatVersion(version);if(jQuery("#backstageCloak").css({height:"0px"}),jQuery("#backstageButton").css({height:"0px","pointer-events":"none"}),jQuery("#backstageArea").css({height:"0px"}),jQuery("#backstage").css({height:"0px"}),"none"!==jQuery(".header").css("display")&&jQuery(".header").css({display:"none"}),0===jQuery(`#${e}`).length){const r=`<svg class=${i[0]} viewBox='0 0 512 512'><title>Minimize the window</title><path d='M480 480H32c-17.7 0-32-14.3-32-32s14.3-32 32-32h448c17.7 0 32 14.3 32 32s-14.3 32-32 32z'/></svg>`,a=`<svg class=${i[1]} viewBox='0 0 512 512'><title>Toggle the window size</title><path d='M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm0 394c0 3.3-2.7 6-6 6H54c-3.3 0-6-2.7-6-6V192h416v234z'/></svg>`,s=`<svg class=${i[2]} viewBox='0 0 512 512'><title>Close the window</title><path d='M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm0 394c0 3.3-2.7 6-6 6H54c-3.3 0-6-2.7-6-6V86c0-3.3 2.7-6 6-6h404c3.3 0 6 2.7 6 6v340zM356.5 194.6L295.1 256l61.4 61.4c4.6 4.6 4.6 12.1 0 16.8l-22.3 22.3c-4.6 4.6-12.1 4.6-16.8 0L256 295.1l-61.4 61.4c-4.6 4.6-12.1 4.6-16.8 0l-22.3-22.3c-4.6-4.6-4.6-12.1 0-16.8l61.4-61.4-61.4-61.4c-4.6-4.6-4.6-12.1 0-16.8l22.3-22.3c4.6-4.6 12.1-4.6 16.8 0l61.4 61.4 61.4-61.4c4.6-4.6 12.1-4.6 16.8 0l22.3 22.3c4.7 4.6 4.7 12.1 0 16.8z'/></svg>`;jQuery("body").prepend(`<div id="${e}"></div>`),jQuery(`#${e}`).append("<div id='header_left'></div>").append(`<div id='header_center'>${o} v${d}</div>`).append("<div id='header_right'></div>"),jQuery("#header_right").append(r).append(a).append(s);const l=e=>displayMessage(`The ${e} button is only active in a NW.js environment!`,void 0,{use:!0,color:"yellow",duration:"6000"});n&&(jQuery(`.${i[0]}`).on("click",()=>t.minimize()),jQuery(`.${i[1]}`).on("click",()=>t.toggleFullscreen()),jQuery(`.${i[2]}`).on("click",()=>window.close()),jQuery("#header_center").on("mousedown",()=>l("mousedown"))),n||(jQuery(`.${i[0]}`).on("click",()=>l("minimize")),jQuery(`.${i[1]}`).on("click",()=>l("maximize")),jQuery(`.${i[2]}`).on("click",()=>l("close")))}},config.shadowTiddlers.nwAppStyleStyleSheet="/*{{{*/\sn/* The CSS for the nwAppStyle-Plugin.js */\sn/* Last updated 23-02-2025 */\sn\sn /* Add a small 1px margin to the body, this looks better */ \sn body {\sn margin-left: 0px;\sn padding-left: 1px;\sn border-left: 1px solid #D6D6D6;\sn border-top: 1px solid #D6D6D6;\sn border-right: 1px solid #D6D6D6;\sn border-bottom: 0px;\sn border-radius: 4px;\sn min-height: 100%;\sn z-index: 99;\sn }\sn \sn /* Hide the backstage area */\sn #backstageArea { padding: 0em; }\sn \sn /* Remove the header, this includes the backstage, it conflicts with the button position */\sn .header { display: none }\sn \sn /* CSS for the div that holds the buttons */\sn #windowheader {\sn display: flex;\sn flex-direction: row;\sn flex-wrap: nowrap;\sn justify-content: space-between;\sn background-color: #003599;\sn width: 100%;\sn border-bottom: 1px solid #D6D6D6;\sn border-top: 1px solid #D6D6D6;\sn margin: -1px 0px 4px 0px;\sn padding: 1px;\sn position: fixed;\sn z-index: 200;\sn }\sn \sn /* Left CSS */\sn #header_left {\sn width: 10%;\sn display: flex;\sn flex-direction: row;\sn flex-wrap: nowrap;\sn justify-content: flex-start;\sn padding: 2px 6px 2px 0px;\sn height: 1.0rem;\sn -webkit-app-region: no-drag;\sn \sn }\sn \sn /* Center CSS */\sn #header_center {\sn width: 80%;\sn text-align: center;\sn color: #FFFFFF;\sn font-weight: normal;\sn font-size: 12px;\sn padding: 3px 0px 2px 0px;\sn }\sn \sn /* Right CSS */\sn #header_right {\sn width: 10%;\sn display: flex;\sn flex-direction: row;\sn flex-wrap: nowrap;\sn justify-content: flex-end;\sn padding: 2px 6px 2px 0px;\sn height: 1.0rem;\sn -webkit-app-region: no-drag;\sn }\sn \sn /* Give the svg buttons their color, hover function that changes the colour */\sn .svgclosebutton, .svgmaximizebutton, .svgminimizebutton, .svginfobutton { width: 3%; fill: #ddd; margin: 0px 2px 0px 2px; min-width: 16px }\sn .svgclosebutton:hover, .svgmaximizebutton:hover, .svgminimizebutton:hover { fill: red }\sn \sn /* classname: windowheader */\sn /* In order to drag the window we need to define the dragging area */\sn #windowheader { -webkit-app-region: drag }\sn \sn /* The button area should not be dragable, draggable is not clickable */\sn .messageArea { -webkit-app-region: no-drag }\sn .siteSubtitle { -webkit-app-region: no-drag }\sn/*}}}*/",config.shadowTiddlers.nwAppStyleStyleSheetDEV="\sn/*{{{*/\sn/* This CSS tiddler makes the window header and MainMenu darkread */\sn/* Last updated 13-08-2023 */\sn\sn#windowheader {\sn background-color: darkred;\sn}\sn\sn#mainMenu .tiddlyLink {\sn background-color: darkred;\sn}\sn\sn#mainMenu a:hover {\sn background-color: #620101; \sn}\sn/*}}}*/";\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |nwPrint-Plugin.js |\n|Description | |\n|Documentation | |\n|Version |1.0.2 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |nwPrint-Source |\n|Author |Okido |\n|Original author | |\n|License | |\n|Core version | |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |03-10-2023 - 19:19, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\n\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n2019.09.22 Changed the text Print to Print screen\n2019.04.10 Plugin written, settings are hardcoded for the time being\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2023 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 03-10-2023 */\n"object"!=typeof config.macros.nwprint?config.macros.nwprint={}:config.macros.nwprint,config.macros.nwprint.handler=function(n,i,r,o,t,c){createTiddlyButton(n,"Print screen","Print the screen",this.onclick)},config.macros.nwprint.onclick=function(){nw.Window.get().print({headerFooterEnabled:!1,marginsType:3,marginsCustom:{marginBottom:1,marginLeft:30,marginRight:30,marginTop:5},shouldPrintBackgrounds:!0,autoprint:!1})};\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |nwReload-Plugin.js |\n|Description |Reload this TiddlyWiki |\n|Documentation | |\n|Version |0.0.5 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |nwReload-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |10-11-2024 - 14:12, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin provides a button to reload TiddlyWikiClassic.\n{{{\n<<nwreload>>\n}}}\n<<nwreload>>\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n2024.11.10 Updated the handler to default format\n2023.07.29 Rebuild with latest [[pluginBuilder-Plugin.js]] format\n2022.10.12 setDirty to false to prevent the alert box from popping up\n2022.09.18 Added message box\n2019.10.19 First build of the plugin, reload [[TiddlyWikiClassic]] in [[NW.js]]\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2024 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 10-11-2024 */\n"object"!=typeof config.macros.nwreload?config.macros.nwreload={}:config.macros.nwreload,config.macros.nwreload.handler=function(o,e,n,c,i,t){createTiddlyButton(o,"Reload","Reload this TiddlyWiki",this.onclick,"pure-form pure-button button-success pure-u-3-24 center",null,null,{})},config.macros.nwreload.onclick=function(){displayMessage("Reload application",void 0,{use:!0,color:"red",duration:"3000"}),store.setDirty(!1),setTimeout((function(){document.location.reload(!0)}),1500)};\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |nwSaveReload-Plugin.js |\n|Description |Save and reload this TiddlyWiki |\n|Documentation | |\n|Version |0.0.5 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |nwSaveReload-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |10-11-2024 - 14:12, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin provides a button to save and reload TiddlyWikiClassic.\n{{{\n<<saveandreload>>\n}}}\n<<saveandreload>>\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n2024.11.10 Updated handler code\n2023.07.29 Rebuild with latest [[pluginBuilder-Plugin.js]] format\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2024 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 10-11-2024 */\n"object"!=typeof config.macros.saveandreload?config.macros.saveandreload={}:config.macros.saveandreload,config.macros.saveandreload.handler=function(o,e,a,n,c,i){createTiddlyButton(o,"Save & Reload","Save and reload this TiddlyWiki",this.onclick,"pure-form pure-button button-success pure-u-3-24 center",null,null,{})},config.macros.saveandreload.onclick=function(){config.macros.nwsaver.onclick(),displayMessage("Reload application",void 0,{use:!0,color:"red",duration:"3000"}),store.setDirty(!1),setTimeout((function(){document.location.reload(!0)}),2e3)};\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |nwSaver-Plugin.js |\n|Description |This is a saver plugin for [[TiddlyWikiClassic]] running with [[NW.js]] |\n|Documentation | |\n|Version |2.2.14 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |nwSaver-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |08-11-2025 - 10:40, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThe [[nwSaver-Plugin.js]] provides a saver for [[TiddlyWikiClassic]] that is running in a [[NW.js]] environment.\nBesides saving the plugin also provides some basic I/O functions.\nWhen running in a browser the default [[TiddlyWikiClassic]] saver is used.\n<<<\n!!!Usage\n<<<\n!Available functions in this plugin\nconfig.macros.nwsaver.direntries(folderPath) >> returns an object with the key/value for folder path and the entries in an array, in Posix style "/"\nconfig.macros.nwsaver.direntriesattr(folderPath, "posix") >> returns an object with the file and folder attributes, default is Posix style with "/", alternative is Windows with "\s\s", invoked with "win32"\nconfig.macros.nwsaver.direntriesattrfilter(folderPath, "dir" || "file" || "") >> filter by dir, file or no filter\nconfig.macros.nwsaver.load(fullPath) >> load a file from disk, returns the content\nconfig.macros.nwsaver.loadAsync(fullPath) >> load a file from disk async, returns the content or false\nconfig.macros.nwsaver.save(fullPath, content, message = true or false) >> save a file to disk, existing files are overwritten\nconfig.macros.nwsaver.saveAsync(fullPath, content, message = true or false) >> save a file to disk async, existing files are overwritten\nconfig.macros.nwsaver.copy(fullPathSource, fullPathTarget) >> copies a file\nconfig.macros.nwsaver.delete(fullPath) >> delete a file or folder\nconfig.macros.nwsaver.openfile(fullPath) >> open a file with the default application, starts from the commandline\nconfig.macros.nwsaver.exist(fullPath) >> check if the file/folder exist\nconfig.macros.nwsaver.rename(fullPathSource, fullPathTarget) >> rename a file\nconfig.macros.nwsaver.normalizepath(fullPath) >> normalize a path following os rules, Posix "/" and Windows "\s\s" \nconfig.macros.nwsaver.mkdir(fullPath) >> create a path, replacement for config.macros.nwsaver.createpath(fullPath)\n<<<\n!!!Configuration\n<<<\nPut following code in [[SideBarOptions]] <nowiki><<nwsaver>></nowiki><<nwsaver>>.\nThe default backup pattern for [[TiddlyWikiClassic]] is the filename + a date part: -YYYY.html, -MMM.html, -ddd.html and -latest.html.\nFor a different backup pattern create a system tiddler with the title [[zzzz-config]] and tag it with systemConfig.\nPut the following code in the system tiddlers:\n{{{\n // Possible settings for nwSaver backup pattern\n // [ ["YYYY"], ["MMM"], ["ddd"], ["d0DD"], ["m0mm"], ["latest",0], ["h0hh"], ["m0mm"], ["s0ss"] ];\n config.options.nwSaver = [ ["YYYY"], ["MMM"], ["ddd"], ["d0DD"], ["m0mm"], ["latest",0] ]; \n}}}\nTo assure that the [[TiddlyWikiClassic]] is loaded in edit mode all the time add following code to SystemSettings:\n{{{\nchkHttpReadOnly: false;\n}}}\n<<<\n!!!Revisions\n<<<\n08.11.2025 2.2.14 Optimized all functions, changed the internal save and load functions for TWC to async\n17.07.2025 2.2.12 Optimized code and proper returns in case of errors\n18.03.2025 2.2.11 Fixed a problem with the return value of ...direntriesattr(folderPath, "win32"), now it correctly returns with "\s\s"\n22.12.2023 2.2.10 Removed some console.log() messages\n04.11.2023 2.2.9 Fix a load and save bug when there are spaces in the path\n28.10.2023 2.2.8 Change this reference for button onclick handlers \n10.09.2023 2.2.7 Added message if file save is successful\n25.06.2023 2.2.6 Changed the build process to the latest pluginBuilder format\n22.04.2023 2.2.5 Renamed all variations of TiddlyWiki... to [[TiddlyWikiClassic]]\n06.10.2022 2.2.4 Fix bug, function normalize does not exist when the native saver macro is used\n27.08.2022 2.2.2 Paths are now build with path.resolve to ensure proper paths on Windows\n20.08.2022 2.2.0 To open files from windows command line "&" needs to be escaped to "^&", this is added\n12.12.2021 2.1.0 Path separators are by default Posix "/" style, optional is Windows "\s\s" style, use "win32" to invoke this \n13.11.2021 2.0.9 Fixed a problem with special characters in path and filenames that give a normalization error\n07.08.2021 2.0.8 Added path normalization to all functions, to prevent problems on windows systems\n16.07.2021 2.0.7 Checked possible several spaces issue in windows filenames, files can not be opened with the default application, no problems found\n28.05.2021 2.0.6 Fixed spaces problem on windows, no limit anymore for number of spaces in a path \n23.05.2021 2.0.5 Fixed some typos\n16.05.2021 2.0.4 Fixed opening of paths with more than two spaces once more\n04.05.2021 2.0.3 Fixed opening of paths with spaces\n26.04.2021 2.0.2 Added folder deletion to the delete function, folders must be empty\n27.10.2020 2.0.1 Added a two functions, check if a file/folder exist and rename\n29.08.2020 2.0.0 Renamed functions and added filter options for folders, the old function names can still be used\n16.07.2020 1.2.8 Changed windows path regex to <nowiki>path.win32.normalize(nw.__filename)</nowiki>\n29.06.2020 1.2.7 If tiddler.text starts with \sn it is eaten up during saving, escapeLineBreaks() is required, set config.options.chkUsePreForStorage to false\n26.06.2020 1.2.6 Added "createpath" as an I/O function\n26.05.2020 1.2.5 Fixed "openfile" with default aplication, spaces are handled different on the Linux and Windows command line\n17.05.2020 1.2.4 Fixed saving issue when there are spaces %20 in the filename, use process.platform to detect the platform, name changed to nwSaver-Plugin.js\n10.05.2020 1.2.3 Added a function to open a file with the default application \n05.05.2020 1.2.2 Fixed the texts used for error warnings\n05.04.2020 1.2.1 Modified and created bug removed, mtime and ctime are properly mapped now\n28.03.2020 1.2.0 Renamed function names, added functions to copy and delete files\n10.03.2020 1.1.8 Added decodeURI, special characters need special encoding\n08.03.2020 1.1.7 Added basic I/O functions\n16.02.2020 1.1.6 Removed save function encapsulation, the saver can be used by other functions too\n03.01.2020 1.1.5 Fixed the first load view/edit mode problem \n10.11.2019 1.1.4 Made some minor changes and added remarks to the source\n19.10.2019 1.1.3 Added tags to make distribution with the [[LoadTiddlersPlugin]] easy\n15.09.2019 1.1.2 Minified the plugin code includding the TiddlyWikiClassic macro code\n16.06.2019 1.1.1 Made backup sequence definable in systemConfig tiddler\n13.06.2019 1.1.0 Moved the code in the external nwTWcSaver.js into this plugin\n17.04.2019 1.0.6 Added win path coding in nwTWcSaver.js\n02.04.2019 1.0.5 Removed hard coded paths for <nowiki>WinXX</nowiki>\n10.03.2019 1.0.4 Updated documentation and fixed date format\n25.02.2019 1.0.3 Removed moment.js dependency\n22.02.2019 1.0.2 Added win32 path fix\n21.02.2019 1.0.1 Merged all files to nwTWcSaver.js\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2025 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nBackup logic based on the code from [[LessBackupsPlugin]] by Simon Baird, http://mptw.tiddlyspot.com/#TheBSDLicense.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 08-11-2025 */\n"use strict";config.options.chkUsePreForStorage=!1,"object"==typeof nw?("object"!=typeof config.macros.nwsaver?config.macros.nwsaver={}:config.macros.nwsaver,config.macros.nwsaver={init:function(){this.os=process.platform},os:"linux",fs:require("fs"),path:require("path"),exec:require("child_process").exec,pathresolve:function(e){return this.path.resolve(nw.__dirname,this.normalizepath(e))},commandline:function(){return{darwin:"open",win32:"start"}[this.os]||"xdg-open"},openfile:function(e){let t=this.pathresolve(e);const s=this.fs.existsSync(t);s?("win32"===this.os?t=t.replace(/(\ss+)/g,e=>`"${e}"`).replace(/&/g,"^&"):"linux"===this.os&&(t=`"${t}"`),this.exec(`${this.commandline()} ${t}`)):this.error("openfile",`${t} not found`)},handler:function(e,t,s,i,r,n){createTiddlyButton(e,"Save","Save your TiddlyWikiClassic with the development code",this.onclick,"button saveChangesButton")},onclick:async function(){const e=!1,t=config.macros.nwsaver,s=new Date,i=config.options.nwsaver||[["YYYY"],["MMM"],["ddd"],["latest",0]];try{const r=t.normalizepath(nw.__filename),n=t.normalizepath(getBackupPath(r));e;const o=await t.loadAsync(r),a=locateStoreArea(o),c=updateOriginal(o,a,r);await t.saveAsync(r,c,!1);const h=i.map(([e])=>n.replace(/(\s.)([0-9]+\s.[0-9]+)(\s.html)$/,`$1${s.formatString(e).toLowerCase()}$3`));for(const e of h)await t.saveAsync(e,c,!1);displayMessage(`File and backups saved @ ${s.formatString("0hh:0mm")}`,void 0,{use:!0,color:"green",duration:"3000"})}catch(e){t.error("onclick handler",e),displayMessage(`File and backups saving failed @ ${s.formatString("0hh:0mm")}`,void 0,{use:!0,color:"red",duration:"3000"})}},save:function(e,t,s=!0){const i=this.pathresolve(e),r=this.path.dirname(i);try{this.fs.existsSync(r)||this.fs.mkdirSync(r,{recursive:!0}),this.fs.writeFile(i,t,e=>{e?displayMessage(e,void 0,{use:!0,color:"red",duration:"5000"}):s&&displayMessage(`File ${i} saved`,void 0,{use:!0,color:"green",duration:"5000"})})}catch(e){this.error("save",e)}},saveAsync:async function(e,t,s=!0){const i=this.pathresolve(e),r=this.path.dirname(i);try{return await this.fs.promises.mkdir(r,{recursive:!0}),await this.fs.promises.writeFile(i,t),s&&displayMessage(`File ${i} saved`,void 0,{use:!0,color:"green",duration:"5000"}),!0}catch(e){displayMessage(e.message||e,void 0,{use:!0,color:"red",duration:"5000"}),this.error("saveAsync",e)}},direntriesattrfilter:function(e,t=""){const s=this.direntriesattr(e);return"dir"===t?s.filter(e=>e.isdir):"file"===t?s.filter(e=>e.isfile):s},direntriesattr:function(e,t="posix"){const s=!1,i=e=>this.fs.lstatSync(e),{direntries:r,dirpath:n}=this.direntries(e);try{const e=decodeURI(encodeURI(this.path.posix.normalize(n))),s="posix"===t?this.path.posix.normalize:this.path.win32.normalize;return r.map(r=>{const o=decodeURI(encodeURI(this.path.posix.normalize(n+r))),a="posix"===t?o:s(o),c="posix"===t?e:s(e),h=i(o);return{filename:r,dirpath:c,fullpath:a,accessed:h.atime,modified:h.mtime,created:h.ctime,isfile:h.isFile(),isdir:h.isDirectory(),extension:this.path.parse(r).ext}})}catch(e){this.error("direntriesattr",e)}},direntries:function(e){try{const t=this.path.posix.normalize(e),s=this.pathresolve(e);return{dirpath:decodeURI(encodeURI(t)),direntries:this.fs.readdirSync(s)}}catch(e){this.error("direntries",e)}},rename:function(e,t){const s=this.pathresolve(e),i=this.pathresolve(t);try{return!(!this.fs.existsSync(s)||this.fs.existsSync(i))&&(this.fs.renameSync(s,i),!0)}catch(e){this.error("rename",e)}},delete:function(e){const t=this.pathresolve(e);try{const e=this.fs.existsSync(t)?this.fs.lstatSync(t):null;if(!e)return!1;if(e.isFile())this.fs.unlinkSync(t);else{if(!e.isDirectory())return!1;this.fs.rmdirSync(t,{recursive:!0})}return displayMessage(`Deleted ${t}`,void 0,{use:!0,color:"yellow",duration:"5000"}),!0}catch(e){this.error("delete",e)}},load:function(e){const t=this.pathresolve(e);try{return!!this.fs.existsSync(t)&&this.fs.readFileSync(t,{encoding:"utf8"})}catch(e){this.error("load",e)}},loadAsync:async function(e){const t=this.pathresolve(e);try{await this.fs.promises.access(t);return await this.fs.promises.readFile(t,{encoding:"utf8"})}catch(e){return this.error("loadAsync",e),!1}},copy:function(e,t){const s=this.pathresolve(e),i=this.pathresolve(t);try{return!(!this.fs.existsSync(s)||this.fs.existsSync(i))&&(this.fs.copyFileSync(s,i),!0)}catch(e){this.error("copy",e)}},mkdir:function(e){const t=this.pathresolve(e);try{return!this.fs.existsSync(t)&&(this.fs.mkdirSync(t,{recursive:!0}),!0)}catch(e){this.error("mkdir",e)}},exist:function(e){try{return this.fs.existsSync(this.pathresolve(e))}catch(e){this.error("exist",e)}},error:function(e,t){alert(`An error occurred in function "${e}" of the nwSaver-Plugin.js\snError message:\sn${JSON.stringify(t,null,"\st")}`)},normalizepath:function(e){return"linux"===this.os?decodeURI(encodeURI(this.path.posix.normalize(e))):decodeURI(encodeURI(this.path.win32.normalize(e)))}}):(console.log("We are in a browser!!!"),"object"!=typeof config.macros.nwsaver?config.macros.nwsaver={}:config.macros.nwsaver,config.macros.nwsaver={handler:function(e,t,s,i,r,n){createTiddlyButton(e,"Save-DEV","Save your TiddlyWikiClassic with the development code",this.onclick,"button saveChangesButton")},onclick:function(){return saveChanges(),!1}});\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |sideBarSVGButton-Plugin.js |\n|Description |Fill the buttons in the sideBar with SVG's |\n|Documentation | |\n|Version |0.0.31 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |sideBarSVGButton-Source |\n|Author |Okido |\n|Original author | |\n|License | |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |03-11-2024 - 11:09, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThe buttons are styled with CSS and ColorPalette.\n\n|Setting |Function |Object name |h\n|save |Save |save_outline |\n|nwsaverdev |Save in the development environment |save_outline |\n|saveandreload |Save and Reload |save_outline + refresh_outline |\n|reload |Reload |refresh_outline |\n|closetiddlers |Close tiddler |close_circle_outline |\n|print |Print screen |print_outline |\n|newtiddler |New tiddler |document_outline |\n|newjs |New tiddler filled with a JavaScript template |logo_javascript |\n|options |Options |options_outline |\n|refresh |Refresh references to files and folders on drive with [[hiveBroker-Plugin.js]] |sync_outline |\n|autolinker |Refresh references to files and folders on drive with [[autoLinker-Plugin.js]] |reload-outline |\n|newaction |New action tiddler with [[actionBroker-Plugin.js]] |pencil_outline |\n|promotenew2open |Change action status from new to open with [[actionBroker-Plugin.js]] |pencil_outline + reader_outline |\n|promoteclosure2ready |Change actions status from closure to ready with [[actionBroker-Plugin.js]] |reader_outline + archive_outline |\n<<<\n!!!Usage\n<<<\n{{{\n<<sidebarsvgbutton>>\n}}}\n<<<\n!!!Configuration\n<<<\nButton order and extra buttons can be set in [[z-sideBarSVGButton-Definition]].\n<<<\n!!!Revisions\n<<<\n<<<\n!!!License\n<<<\n!!License for the third party library code\nThe MIT License (MIT)\n\nCopyright (c) 2015-present Ionic (http://ionic.io/)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2024 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 03-11-2024 */\nconst debug=!1;"object"!=typeof config.macros.sidebarsvgbutton&&(config.macros.sidebarsvgbutton={}),config.macros.sidebarsvgbutton.data={save:{css:"button-success",info:"Save TiddlyWikiClassic",id:"buttonsave",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M380.93,57.37A32,32,0,0,0,358.3,48H94.22A46.21,46.21,0,0,0,48,94.22V417.78A46.21,46.21,0,0,0,94.22,464H417.78A46.36,46.36,0,0,0,464,417.78V153.7a32,32,0,0,0-9.37-22.63ZM256,416a64,64,0,1,1,64-64A63.92,63.92,0,0,1,256,416Zm48-224H112a16,16,0,0,1-16-16V112a16,16,0,0,1,16-16H304a16,16,0,0,1,16,16v64A16,16,0,0,1,304,192Z" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},nwsaverdev:{css:"button-error",info:"Save TiddlyWikiClassic with the nwSaverDevelopment-Plugin",id:"buttonnwsaverdev",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M380.93,57.37A32,32,0,0,0,358.3,48H94.22A46.21,46.21,0,0,0,48,94.22V417.78A46.21,46.21,0,0,0,94.22,464H417.78A46.36,46.36,0,0,0,464,417.78V153.7a32,32,0,0,0-9.37-22.63ZM256,416a64,64,0,1,1,64-64A63.92,63.92,0,0,1,256,416Zm48-224H112a16,16,0,0,1-16-16V112a16,16,0,0,1,16-16H304a16,16,0,0,1,16,16v64A16,16,0,0,1,304,192Z" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},saveandreload:{css:"button-primary",info:"Save and reload TiddlyWikiClassic",id:"buttonsavereload",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M380.93,57.37A32,32,0,0,0,358.3,48H94.22A46.21,46.21,0,0,0,48,94.22V417.78A46.21,46.21,0,0,0,94.22,464H417.78A46.36,46.36,0,0,0,464,417.78V153.7a32,32,0,0,0-9.37-22.63ZM256,416a64,64,0,1,1,64-64A63.92,63.92,0,0,1,256,416Zm48-224H112a16,16,0,0,1-16-16V112a16,16,0,0,1,16-16H304a16,16,0,0,1,16,16v64A16,16,0,0,1,304,192Z" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>\sn <svg class="buttonsvg" viewBox="0 0 512 512"><path d="M320,146s24.36-12-64-12A160,160,0,1,0,416,294" style="fill:none;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/><polyline points="256 58 336 138 256 218" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},reload:{css:"button-warning",info:"Reload TiddlyWikiClassic",id:"buttonreload",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M320,146s24.36-12-64-12A160,160,0,1,0,416,294" style="fill:none;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/><polyline points="256 58 336 138 256 218" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},closetiddlers:{css:"button-primary",info:"Close all tiddlers",id:"buttonclose",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M448,256c0-106-86-192-192-192S64,150,64,256s86,192,192,192S448,362,448,256Z" style="fill:none;stroke-miterlimit:10;stroke-width:32px"/><line x1="320" y1="320" x2="192" y2="192" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="192" y1="320" x2="320" y2="192" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},print:{css:"button-primary",info:"Print screen",id:"buttonprint",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M384,368h24a40.12,40.12,0,0,0,40-40V168a40.12,40.12,0,0,0-40-40H104a40.12,40.12,0,0,0-40,40V328a40.12,40.12,0,0,0,40,40h24" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><rect x="128" y="240" width="256" height="208" rx="24.32" ry="24.32" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M384,128V104a40.12,40.12,0,0,0-40-40H168a40.12,40.12,0,0,0-40,40v24" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><circle cx="392" cy="184" r="24"/></svg>'},newtiddler:{css:"button-primary",info:"New tiddler",id:"buttonnewtiddler",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M416,221.25V416a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V96a48,48,0,0,1,48-48h98.75a32,32,0,0,1,22.62,9.37L406.63,198.63A32,32,0,0,1,416,221.25Z" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M256,56V176a32,32,0,0,0,32,32H408" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="288" x2="336" y2="288" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="368" x2="336" y2="368" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},options:{css:"button-primary",info:"Options",id:"buttonoptions",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><line x1="368" y1="128" x2="448" y2="128" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="64" y1="128" x2="304" y2="128" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="368" y1="384" x2="448" y2="384" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="64" y1="384" x2="304" y2="384" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="208" y1="256" x2="448" y2="256" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="64" y1="256" x2="144" y2="256" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><circle cx="336" cy="128" r="32" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><circle cx="176" cy="256" r="32" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><circle cx="336" cy="384" r="32" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},warning:{css:"button-error",info:"This button is incorrect defined",id:"buttonwarning",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M85.57,446.25H426.43a32,32,0,0,0,28.17-47.17L284.18,82.58c-12.09-22.44-44.27-22.44-56.36,0L57.4,399.08A32,32,0,0,0,85.57,446.25Z" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><path d="M250.26,195.39l5.74,122,5.73-121.95a5.74,5.74,0,0,0-5.79-6h0A5.74,5.74,0,0,0,250.26,195.39Z" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><path d="M256,397.25a20,20,0,1,1,20-20A20,20,0,0,1,256,397.25Z"/></svg>'},newjs:{css:"button-primary",info:"New JavaScript template",id:"buttonnewjs",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M32,32V480H480V32ZM272,380c0,43.61-25.76,64.87-63.05,64.87-33.68,0-53.23-17.44-63.15-38.49h0l34.28-20.75c6.61,11.73,11.63,21.65,26.06,21.65,12,0,21.86-5.41,21.86-26.46V240h44Zm99.35,63.87c-39.09,0-64.35-17.64-76.68-42h0L329,382c9,14.74,20.75,24.56,41.5,24.56,17.44,0,27.57-7.72,27.57-19.75,0-14.43-10.43-19.54-29.68-28l-10.52-4.52c-30.38-12.92-50.52-29.16-50.52-63.45,0-31.57,24.05-54.63,61.64-54.63,26.77,0,46,8.32,59.85,32.68L396,290c-7.22-12.93-15-18-27.06-18-12.33,0-20.15,7.82-20.15,18,0,12.63,7.82,17.74,25.86,25.56l10.52,4.51c35.79,15.34,55.94,31,55.94,66.16C441.12,424.13,411.35,443.87,371.35,443.87Z"/></svg>'},refresh:{css:"button-primary",info:"Refresh references to external files/folders on drive with hiveBroker-Plugin.js",id:"buttonrefresh",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M434.67,285.59v-29.8C434.67,157.06,354.43,77,255.47,77a179,179,0,0,0-140.14,67.36m-38.53,82v29.8C76.8,355,157,435,256,435a180.45,180.45,0,0,0,140-66.92" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><polyline points="32 256 76 212 122 256" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><polyline points="480 256 436 300 390 256" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},autolinker:{css:"button-primary",info:"Refresh references to external files/folders on drive with autolinker-Plugin.js",id:"buttonautolinker",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M400,148l-21.12-24.57A191.43,191.43,0,0,0,240,64C134,64,48,150,48,256s86,192,192,192A192.09,192.09,0,0,0,421.07,320" style="fill:none;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/><path d="M464,97.42V208a16,16,0,0,1-16,16H337.42c-14.26,0-21.4-17.23-11.32-27.31L436.69,86.1C446.77,76,464,83.16,464,97.42Z"/></svg>'},newaction:{css:"button-warning",info:"New action",id:"buttonnewaction",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M416,221.25V416a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V96a48,48,0,0,1,48-48h98.75a32,32,0,0,1,22.62,9.37L406.63,198.63A32,32,0,0,1,416,221.25Z" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M256,56V176a32,32,0,0,0,32,32H408" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},promotenew2open:{css:"button-primary",info:"Promote actions with status new to open",id:"buttonpromotenew2open",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M416,221.25V416a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V96a48,48,0,0,1,48-48h98.75a32,32,0,0,1,22.62,9.37L406.63,198.63A32,32,0,0,1,416,221.25Z" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M256,56V176a32,32,0,0,0,32,32H408" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>\sn \sn <svg class="buttonsvg" viewBox="0 0 512 512"><path d="M416,221.25V416a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V96a48,48,0,0,1,48-48h98.75a32,32,0,0,1,22.62,9.37L406.63,198.63A32,32,0,0,1,416,221.25Z" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M256,56V176a32,32,0,0,0,32,32H408" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="288" x2="336" y2="288" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="368" x2="336" y2="368" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},promoteclosure2ready:{css:"button-success",info:"Promote actions with status closure to ready",id:"buttonpromoteclosure2ready",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M416,221.25V416a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V96a48,48,0,0,1,48-48h98.75a32,32,0,0,1,22.62,9.37L406.63,198.63A32,32,0,0,1,416,221.25Z" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><path d="M256,56V176a32,32,0,0,0,32,32H408" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="288" x2="336" y2="288" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="368" x2="336" y2="368" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>\sn <svg class="buttonsvg" viewBox="0 0 512 512"><path d="M80,152V408a40.12,40.12,0,0,0,40,40H392a40.12,40.12,0,0,0,40-40V152" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><rect x="48" y="64" width="416" height="80" rx="28" ry="28" style="fill:none;stroke-linejoin:round;stroke-width:32px"/><polyline points="320 304 256 368 192 304" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="256" y1="345.89" x2="256" y2="224" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'},newrth:{css:"button-primary",info:"New RTH risk record",id:"buttonnewrth",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path style="fill:none;stroke-miterlimit:10;stroke-width:32px" d="M366.05,146a46.7,46.7,0,0,1-2.42-63.42,3.87,3.87,0,0,0-.22-5.26L319.28,33.14a3.89,3.89,0,0,0-5.5,0l-70.34,70.34a23.62,23.62,0,0,0-5.71,9.24h0a23.66,23.66,0,0,1-14.95,15h0a23.7,23.7,0,0,0-9.25,5.71L33.14,313.78a3.89,3.89,0,0,0,0,5.5l44.13,44.13a3.87,3.87,0,0,0,5.26.22,46.69,46.69,0,0,1,65.84,65.84,3.87,3.87,0,0,0,.22,5.26l44.13,44.13a3.89,3.89,0,0,0,5.5,0l180.4-180.39a23.7,23.7,0,0,0,5.71-9.25h0a23.66,23.66,0,0,1,14.95-15h0a23.62,23.62,0,0,0,9.24-5.71l70.34-70.34a3.89,3.89,0,0,0,0-5.5l-44.13-44.13a3.87,3.87,0,0,0-5.26-.22A46.7,46.7,0,0,1,366.05,146Z"/><line style="fill:none;stroke-miterlimit:10;stroke-width:32px;stroke-linecap:round" x1="250.5" y1="140.44" x2="233.99" y2="123.93"/><line style="fill:none;stroke-miterlimit:10;stroke-width:32px;stroke-linecap:round" x1="294.52" y1="184.46" x2="283.51" y2="173.46"/><line style="fill:none;stroke-miterlimit:10;stroke-width:32px;stroke-linecap:round" x1="338.54" y1="228.49" x2="327.54" y2="217.48"/><line style="fill=none;stroke-miterlimit:10;stroke-width:32px;stroke-linecap:round" x1="388.07" y1="278.01" x2="371.56" y2="261.5"/></svg>'},newinstrument:{css:"button-primary",info:"New instrument record",id:"buttonnewinstrument",svgcode:'<svg class="buttonsvg" viewBox="0 0 512 512"><path d="M384,80H128c-26,0-43,14-48,40L48,272V384a48.14,48.14,0,0,0,48,48H416a48.14,48.14,0,0,0,48-48V272L432,120C427,93,409,80,384,80Z" style="fill:none;stroke:#FFF;stroke-linejoin:round;stroke-width:32px"/><line x1="48" y1="272" x2="192" y2="272" style="fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="320" y1="272" x2="464" y2="272" style="fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><path d="M192,272a64,64,0,0,0,128,0" style="fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="144" y1="144" x2="368" y2="144" style="fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="128" y1="208" x2="384" y2="208" style="fill:none;stroke:#FFF;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>'}},config.macros.sidebarsvgbutton.handler=function(e,o,n,t,i,s){const r=Object.keys(config.macros.sidebarsvgbutton.data);let l=void 0===config.macros.sidebarsvgbutton.buttonorder?[["save","saveandreload","reload"],["closetiddlers","print","newtiddler"],["newjs","options"]]:config.macros.sidebarsvgbutton.buttonorder;l=l.map((e=>e.map((e=>r.includes(e)?e:"warning"))));for(let o=0;o<l.length;o++){let n=createTiddlyElement(e,"div","id","flexrow");for(let e=0;e<l[o].length;e++){let t=l[o][e],i=config.macros.sidebarsvgbutton.data[t].svgcode,s=config.macros.sidebarsvgbutton.data[t].info,r=config.macros.sidebarsvgbutton.data[t].css,a=config.macros.sidebarsvgbutton.data[t].id;createTiddlyButton(n,"","",this.onclick,`pure-button pure-button-hover ${r} pure-u-1`,`${a}`,null,{name:a}),jQuery(`#${a}`).html(i),jQuery(`#${a}`).attr({title:s})}}jQuery("#sidebarOptions a").css({margin:"1px"}),jQuery(".buttonsvg").css({width:"24px",height:"24px",fill:"#FFF",stroke:"#EEEEEE",padding:"6px 0px 1px 0px","pointer-events":"none"}),jQuery(".flexrow").css({display:"grid","row-gap":"2px","column-gap":"2px","grid-template-columns":"33% 33% 32%","justify-content":"space-between","max-width":"320px"})},config.macros.sidebarsvgbutton.onclick=function(e){let o=e.target.getAttribute("name");switch(!0){case"buttonsave"===o:config.macros.nwsaver.onclick();break;case"buttonsavereload"===o:config.macros.saveandreload.onclick();break;case"buttonreload"===o:config.macros.nwreload.onclick();break;case"buttonclose"===o:config.macros.closeAll.onClick();break;case"buttonprint"===o:config.macros.nwprint.onclick();break;case"buttonnewtiddler"===o:story.displayTiddler(this,"newTitle",DEFAULT_EDIT_TEMPLATE,!1,null,null),story.focusTiddler("newTitle",focus);break;case"buttonnewjs"===o:const e="NewScript";story.displayTiddler(this,e,DEFAULT_EDIT_TEMPLATE,!1,null,null),story.getTiddlerField(e,"text").value=store.getTiddlerText("JS-Script-Template"),story.focusTiddler(e,focus);break;case"buttonoptions"===o:const n="AdvancedOptions";story.closeAllTiddlers(),story.displayTiddler("top",n);break;case"buttonwarning"===o:displayMessage("This button is not correct defined!",void 0,{use:!0,color:"red",duration:"5000"});break;case"buttonnwsaverdev"===o:config.macros.nwsaverdev.onclick();break;case"buttonrefresh"===o&&"function"==typeof config.macros.recordprocessing.onclick:case"buttonrefresh"===o&&"function"==typeof config.macros.recordprocessing.onclick:config.macros.recordprocessing.onclick();break;case"buttonautolinker"===o&&"function"==typeof config.macros.autolinker.onclick:config.macros.autolinker.onclick();break;case"buttonnewaction"===o&&"function"==typeof config.macros.record_creator.onclick:config.macros.record_creator.onclick();break;case"buttonpromotenew2open"===o&&"function"==typeof config.macros.makenew2openbutton.onclick:config.macros.makenew2openbutton.onclick();break;case"buttonpromoteclosure2ready"===o&&"function"==typeof config.macros.makeclosure2readybutton.onclick:config.macros.makeclosure2readybutton.onclick();break;case"buttonnewinstrument"===o&&"function"==typeof config.macros.newinstrument.onclick:config.macros.newinstrument.onclick();break;case"buttonnewrth"===o&&"function"==typeof config.macros.newrth.onclick:config.macros.newrth.onclick();break;default:displayMessage("No proper button definition is found!",void 0,{use:!0,color:"red",duration:"5000"})}};\n/* JavaScript CODE ENDS HERE */\n//}}}
!systemConfig tiddlers\n<<list filter [tag[systemConfig]]>>
/***\n|Title |toastify-Plugin.js |\n|Description |Provides toast messages for display messages |\n|Documentation | |\n|Version |0.0.1 |\n|Version library |1.12.0 |\n|Plugin type |library |\n|Source |toastify.js |\n|Author |Okido |\n|Original author | |\n|License | |\n|Core version | |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |30-09-2023 - 17:54, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\n\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n\n<<<\n!!!License\n<<<\n!!License for the third party library code\nMIT License\n\nCopyright (c) 2018 apvarun\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2023 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 30-09-2023 */\n/*!\n * Toastify js 1.12.0\n * https://github.com/apvarun/toastify-js\n * @license MIT licensed\n *\n * Copyright (C) 2018 Varun A P\n */\n!function(t,o){"object"==typeof module&&module.exports?module.exports=o():t.Toastify=o()}(this,(function(t){var o=function(t){return new o.lib.init(t)};function i(t,o){return o.offset[t]?isNaN(o.offset[t])?o.offset[t]:o.offset[t]+"px":"0px"}function s(t,o){return!(!t||"string"!=typeof o)&&!!(t.className&&t.className.trim().split(/\ss+/gi).indexOf(o)>-1)}return o.defaults={oldestFirst:!0,text:"Toastify is awesome!",node:void 0,duration:3e3,selector:void 0,callback:function(){},destination:void 0,newWindow:!1,close:!1,gravity:"toastify-top",positionLeft:!1,position:"",backgroundColor:"",avatar:"",className:"",stopOnFocus:!0,onClick:function(){},offset:{x:0,y:0},escapeMarkup:!0,ariaLive:"polite",style:{background:""}},o.lib=o.prototype={toastify:"1.12.0",constructor:o,init:function(t){return t||(t={}),this.options={},this.toastElement=null,this.options.text=t.text||o.defaults.text,this.options.node=t.node||o.defaults.node,this.options.duration=0===t.duration?0:t.duration||o.defaults.duration,this.options.selector=t.selector||o.defaults.selector,this.options.callback=t.callback||o.defaults.callback,this.options.destination=t.destination||o.defaults.destination,this.options.newWindow=t.newWindow||o.defaults.newWindow,this.options.close=t.close||o.defaults.close,this.options.gravity="bottom"===t.gravity?"toastify-bottom":o.defaults.gravity,this.options.positionLeft=t.positionLeft||o.defaults.positionLeft,this.options.position=t.position||o.defaults.position,this.options.backgroundColor=t.backgroundColor||o.defaults.backgroundColor,this.options.avatar=t.avatar||o.defaults.avatar,this.options.className=t.className||o.defaults.className,this.options.stopOnFocus=void 0===t.stopOnFocus?o.defaults.stopOnFocus:t.stopOnFocus,this.options.onClick=t.onClick||o.defaults.onClick,this.options.offset=t.offset||o.defaults.offset,this.options.escapeMarkup=void 0!==t.escapeMarkup?t.escapeMarkup:o.defaults.escapeMarkup,this.options.ariaLive=t.ariaLive||o.defaults.ariaLive,this.options.style=t.style||o.defaults.style,t.backgroundColor&&(this.options.style.background=t.backgroundColor),this},buildToast:function(){if(!this.options)throw"Toastify is not initialized";var t=document.createElement("div");for(var o in t.className="toastify on "+this.options.className,this.options.position?t.className+=" toastify-"+this.options.position:!0===this.options.positionLeft?(t.className+=" toastify-left",console.warn("Property `positionLeft` will be depreciated in further versions. Please use `position` instead.")):t.className+=" toastify-right",t.className+=" "+this.options.gravity,this.options.backgroundColor&&console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.'),this.options.style)t.style[o]=this.options.style[o];if(this.options.ariaLive&&t.setAttribute("aria-live",this.options.ariaLive),this.options.node&&this.options.node.nodeType===Node.ELEMENT_NODE)t.appendChild(this.options.node);else if(this.options.escapeMarkup?t.innerText=this.options.text:t.innerHTML=this.options.text,""!==this.options.avatar){var s=document.createElement("img");s.src=this.options.avatar,s.className="toastify-avatar","left"==this.options.position||!0===this.options.positionLeft?t.appendChild(s):t.insertAdjacentElement("afterbegin",s)}if(!0===this.options.close){var e=document.createElement("button");e.type="button",e.setAttribute("aria-label","Close"),e.className="toast-close",e.innerHTML="✖",e.addEventListener("click",function(t){t.stopPropagation(),this.removeElement(this.toastElement),window.clearTimeout(this.toastElement.timeOutValue)}.bind(this));var n=window.innerWidth>0?window.innerWidth:screen.width;("left"==this.options.position||!0===this.options.positionLeft)&&n>360?t.insertAdjacentElement("afterbegin",e):t.appendChild(e)}if(this.options.stopOnFocus&&this.options.duration>0){var a=this;t.addEventListener("mouseover",(function(o){window.clearTimeout(t.timeOutValue)})),t.addEventListener("mouseleave",(function(){t.timeOutValue=window.setTimeout((function(){a.removeElement(t)}),a.options.duration)}))}if(void 0!==this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),!0===this.options.newWindow?window.open(this.options.destination,"_blank"):window.location=this.options.destination}.bind(this)),"function"==typeof this.options.onClick&&void 0===this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),this.options.onClick()}.bind(this)),"object"==typeof this.options.offset){var l=i("x",this.options),r=i("y",this.options),p="left"==this.options.position?l:"-"+l,d="toastify-top"==this.options.gravity?r:"-"+r;t.style.transform="translate("+p+","+d+")"}return t},showToast:function(){var t;if(this.toastElement=this.buildToast(),!(t="string"==typeof this.options.selector?document.getElementById(this.options.selector):this.options.selector instanceof HTMLElement||"undefined"!=typeof ShadowRoot&&this.options.selector instanceof ShadowRoot?this.options.selector:document.body))throw"Root element is not defined";var i=o.defaults.oldestFirst?t.firstChild:t.lastChild;return t.insertBefore(this.toastElement,i),o.reposition(),this.options.duration>0&&(this.toastElement.timeOutValue=window.setTimeout(function(){this.removeElement(this.toastElement)}.bind(this),this.options.duration)),this},hideToast:function(){this.toastElement.timeOutValue&&clearTimeout(this.toastElement.timeOutValue),this.removeElement(this.toastElement)},removeElement:function(t){t.className=t.className.replace(" on",""),window.setTimeout(function(){this.options.node&&this.options.node.parentNode&&this.options.node.parentNode.removeChild(this.options.node),t.parentNode&&t.parentNode.removeChild(t),this.options.callback.call(t),o.reposition()}.bind(this),400)}},o.reposition=function(){for(var t,o={top:15,bottom:15},i={top:15,bottom:15},e={top:15,bottom:15},n=document.getElementsByClassName("toastify"),a=0;a<n.length;a++){t=!0===s(n[a],"toastify-top")?"toastify-top":"toastify-bottom";var l=n[a].offsetHeight;t=t.substr(9,t.length-1);(window.innerWidth>0?window.innerWidth:screen.width)<=360?(n[a].style[t]=e[t]+"px",e[t]+=l+15):!0===s(n[a],"toastify-left")?(n[a].style[t]=o[t]+"px",o[t]+=l+15):(n[a].style[t]=i[t]+"px",i[t]+=l+15)}return this},o.lib.init.prototype=o.lib,o}));\n/* JavaScript CODE ENDS HERE */\n//}}}
/***\n|Title |welcomeTWC-Plugin.js |\n|Description |Show the version information after startup |\n|Documentation | |\n|Version |0.0.4 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |welcomeTWC-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |25-05-2025 - 10:37, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\nThis plugin shows a message after all plugins are loaded.\nThe message shows the version numbers of [[TiddlyWikiClassic]], [[NW.js]], [[Node]] and [[jQuery]].\n<<<\n!!!Usage\n<<<\n{{{\nThe code is started 500ms after all plugins are loaded, it uses the macro call init().\n}}}\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n11-09-2023 Updated code to [[TWC]] style and use init() to start the code after all plugins are loaded.\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2025 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Minified with Terser.js - 25-05-2025 */\n"object"!=typeof config.macros.welcomeTWC?config.macros.welcomeTWC={}:config.macros.welcomeTWC,config.macros.welcomeTWC={init:function(){console.log("START INIT: welcomeTWC-Plugin.js"),this.handler()},handler:function(o,e,i,n,s,r){const c="object"==typeof nw,l=c?`NW.js version: ${process.versions.nw}\snNode.js version: ${process.versions.node}`:"",a=`TiddlyWikiClassic core version: ${formatVersion(version)}\snjQuery version: ${jQuery.fn.jquery}\sn${l}`;setTimeout((function(){c?displayMessage("TiddlyWikiClassic is running in a NW.js environment",void 0,{use:!0,color:"green",duration:"5000"}):displayMessage("TiddlyWikiClassic is running in a browser,\snnot all functionality is available !!!",void 0,{use:!0,color:"red",duration:"8000"}),displayMessage(a,void 0,{use:!0,color:"yellow",duration:"7000"})}),500)}};\n/* JavaScript CODE ENDS HERE */\n//}}}
//{{{\n/* Definition for sideBarSVGbutton-Plugin.js, last updated 27-05-2023 */\n\ntypeof config.macros.sidebarsvgbutton !== "object" ? config.macros.sidebarsvgbutton = {} : "" \nconfig.macros.sidebarsvgbutton.buttonorder = [ ["save", "saveandreload", "reload"],\n ["closetiddlers", "print", "newtiddler"],\n ["options"]\n ]\n//}}}
/***\n|Title |zzz-config |\n|Description |Modify systemConfig settings at startup |\n|Documentation | |\n|Version |1.0.0 |\n|Version library | |\n|Plugin type |systemConfig |\n|Source |systemConfig-Plugin-Source |\n|Author |Okido |\n|Original author | |\n|License |See the license section |\n|Core version |≥2.9.4 |\n|Browser |A modern browser supporting ES6 or [[NW.js]] |\n|Status |EXPERIMENTAL - SUBJECT TO CHANGE |\n|Build date - time |25-12-2024 - 12:18, build with [[pluginBuilder-Plugin.js]] |\n\n!!!Documentation\n<<<\n\n<<<\n!!!Usage\n<<<\n\n<<<\n!!!Configuration\n<<<\n\n<<<\n!!!Revisions\n<<<\n\n<<<\n!!!License\n<<<\n!!License for the TiddlyWikiClassic plugin code\nMIT License\n\nCopyright (c) 2024 Okido\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n<<<\n!!!Code\n***/\n//{{{\n/* JavaScript CODE STARTS HERE */\n/* Settings for the SinglePageModePlugin */\n/* SinglePageMode is activated when set to true */\nconfig.options.chkSinglePageMode = true;\nconfig.options.chkSinglePagePermalink = false;\nconfig.options.chkSinglePageAutoScroll = true;\n//}}}\n//{{{\n/* Settings for TiddlyWikiClassic */\nconfig.options.chkShowQuickEdit = true;\nconfig.options.chkDisplayInstrumentation = false;\nconfig.options.chkAnimate = false;\nconfig.options.chkShowRightSidebar = true;\nconfig.options.chkBreadcrumbsLimit = true;\nconfig.options.txtBreadcrumbsLimit = 10;\nconfig.options.txtBackupFolder = "backup";\nconfig.options.txtUserName = "Okido";\nconfig.options.txtMaxEditRows = 140;\nconfig.options.txtTheme = "ThemeBroker";\nconfig.macros.edit.cancelMsg = "";\nconfig.macros.edit.saveMsg = "";\nconfig.options.txtToggleRightSideBarLabelShow = "◄";\nconfig.options.txtToggleRightSideBarLabelHide = "►";\nconfig.views.editor.tagPrompt = " ";\n/* JavaScript CODE ENDS HERE */\n//}}}
/*{{{*/\n/* Set to true for development TWC, the window will turn dark red, last updated 22-03-2025 */\nconfig.options.chkDevelopmentTWC = false\n/*}}}*/