12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071 |
- <!DOCTYPE html>
- <!--[if lte IE 8]><html class="lt-ie9"><![endif]-->
- <!--[if gt IE 8]><!--><html><!--<![endif]-->
- <head>
- <meta charset="utf-8">
- <title>Sugarcane</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <!--
- Made in Twee 1.4.3
- Built on 08 Dec 2014 at 17:56:03, -0500
- Sugarcane is based on:
- TiddlyWiki 1.2.39 by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
- Published under a BSD open source license
- Copyright (c) Osmosoft Limited 2005
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
- list of conditions and the following disclaimer in the documentation and/or other
- materials provided with the distribution.
- Neither the name of the Osmosoft Limited nor the names of its contributors may be
- used to endorse or promote products derived from this software without specific
- prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
- -->
- <script title="engine">
- (function(){
- /*
- **
- ** Basic utility functions
- **
- */
- function clone(a) {
- var constructor, b, proto;
- // Primitive types and functions are flat-out passed by value.
- if (!a || typeof a != "object") {
- return a;
- }
- constructor = a.constructor;
- if (constructor == Date || constructor == RegExp) {
- b = new constructor(a);
- }
- else if (constructor == Array) {
- b = [];
- }
- else if (a.nodeType && typeof a.cloneNode == "function") {
- b = a.cloneNode(true);
- }
- else {
- proto = (typeof Object.getPrototypeOf == "function" ? Object.getPrototypeOf(a) : a.__proto__);
- b = proto ? Object.create(proto) : {};
- }
- // This should work on both arrays and objects equally -
- // even copying expando properties foolishly added to arrays.
- for (var property in a) {
- if (Object.prototype.hasOwnProperty.call(a,property) && !isCyclic(a[property])) {
- if (typeof a[property] == "object") {
- try {
- b[property] = clone(a[property]);
- continue;
- }
- catch(e) {}
- }
- b[property] = a[property];
- }
- }
- return b;
- }
- function isCyclic(obj) {
- var properties = [];
- return (function recurse(obj) {
- var key, i, ownProps = [];
- if (obj && typeof obj == "object") {
- if (properties.indexOf(obj) > -1) {
- return true;
- }
- properties.push(obj);
- for (key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj,key) && recurse(obj[key])) {
- return true;
- }
- }
- }
- return false;
- }(obj));
- }
- function insertElement(a, d, f, c, e) {
- var b = document.createElement(d);
- if (f) {
- b.id = f
- }
- if (c) {
- b.className = c
- }
- if (e) {
- insertText(b, e)
- }
- if (a) {
- a.appendChild(b)
- }
- return b
- }
- function addClickHandler(el, fn) {
- if (el.addEventListener) {
- el.addEventListener('click', fn);
- } else if (el.attachEvent) {
- el.attachEvent('onclick', fn);
- }
- }
- function insertText(a, b) {
- return a.appendChild(document.createTextNode(b))
- }
- function removeChildren(a) {
- while (a.hasChildNodes()) {
- a.removeChild(a.firstChild)
- }
- }
- function findPassageParent(el) {
- while(el && el != document.body && !~el.className.indexOf("passage")) {
- el = el.parentNode;
- }
- return el == document.body ? null : el;
- }
- function setPageElement(c, b, a) {
- var place;
- if (place = (typeof c == "string" ? document.getElementById(c) : c)) {
- removeChildren(place);
- if (tale.has(b)) {
- new Wikifier(place, tale.get(b).processText())
- } else {
- new Wikifier(place, a)
- }
- }
- }
- var scrollWindowInterval;
- function scrollWindowTo(e, margin) {
- var d = window.scrollY ? window.scrollY : document.documentElement.scrollTop,
- m = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight,
- g = k(e),
- j = (d > g) ? -1 : 1,
- b = 0,
- c = Math.abs(d - g);
- scrollWindowInterval && window.clearInterval(scrollWindowInterval);
- if (c) {
- scrollWindowInterval = window.setInterval(h, 25);
- }
-
- function h() {
- b += 0.1;
- window.scrollTo(0, d + j * (c * Math.easeInOut(b)));
- if (b >= 1) {
- window.clearInterval(scrollWindowInterval)
- }
- }
- function k(o) {
- var p = a(o),
- h = o.offsetHeight,
- n = d + m;
- p = Math.min(Math.max(p + (margin || 0) * ( p < d ? -1 : 1), 0), n);
- if (p < d) {
- return p
- } else {
- if (p+h > n) {
- if (h < m) {
- return (p - (m - h) + 20)
- } else {
- return p
- }
- } else {
- return p
- }
- }
- }
- function a(l) {
- var m = 0;
- while (l.offsetParent) {
- m += l.offsetTop;
- l = l.offsetParent
- }
- return m
- }
- }
- // Returns an object containing the properties in neu which differ from old.
- function delta(old,neu) {
- var vars, ret = {};
- if (old && neu) {
- for (vars in neu) {
- if (neu[vars] !== old[vars]) {
- ret[vars] = neu[vars];
- }
- }
- }
- return ret;
- }
- // Convert various exotic objects into JSON-serialisable plain objects.
- function decompile(val) {
- var i, ret;
- if ((typeof val != "object" && typeof val != "function") || !val) {
- return val;
- }
- // Passage objects: store only their name
- else if (val instanceof Passage) {
- return { "[[Passage]]" : val.id };
- }
- else if (Array.isArray(val)) {
- ret = [];
- }
- else {
- ret = {};
- }
- // Deep-copy own properties
- for (i in val) {
- if (Object.prototype.hasOwnProperty.call(val,i) && !isCyclic(val[i])) {
- ret[i] = decompile(val[i]);
- }
- }
- // Functions: store the decompiled function body as a property
- // arbitrarily called "[[Call]]".
- if (typeof val == "function" || val instanceof RegExp) {
- try {
- // Check if it can be recompiled (i.e. isn't a bound or native)
- internalEval(val+"");
- ret["[[Call]]"] = val+"";
- } catch(e) {
- // Silently fail
- ret["[[Call]]"] = "function(){}"
- }
- }
- return ret;
- }
- // Reverses the effects of decompile()
- // Takes recently JSON.parse()d objects and makes them exotic again.
- function recompile(val) {
- var i, ret = val;
- if (val && typeof val == "object") {
- // Passages
- if (typeof val["[[Passage]]"] == "number") {
- return tale.get(val["[[Passage]]"]);
- }
- // Functions/RegExps
- if (typeof val["[[Call]]"] == "string") {
- try {
- ret = internalEval(val["[[Call]]"]);
- }
- catch(e){}
- }
- // Recursively recompile all properties
- // or, if a function/regexp, deep-copy them to the new function.
- for (i in val) {
- if (Object.prototype.hasOwnProperty.call(val,i)) {
- ret[i] = recompile(val[i]);
- }
- }
- }
- return ret;
- }
- function addStyle(b) {
- if (document.createStyleSheet) {
- document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd", " <style>" + b + "</style>")
- } else {
- var a = document.createElement("style");
- a.appendChild(document.createTextNode(b));
- document.getElementsByTagName("head")[0].appendChild(a)
- }
- }
- function alterCSS(text) {
- var temp = '', imgPassages = tale.lookup("tags", "Twine.image");
- // Remove comments
- text = text.replace(/\/\*(?:[^\*]|\*(?!\/))*\*\//g,'');
- // Replace :link
- text = text.replace(/:link/g,"[class*=Link]");
- // Replace :visited
- text = text.replace(/:visited/g,".visitedLink");
- // Hoist @import
- text = text.replace(/@import\s+(?:url\s*\(\s*['"]?|['"])[^"'\s]+(?:['"]?\s*\)|['"])\s*([\w\s\(\)\d\:,\-]*);/g, function(e) {
- temp += e; return '';
- });
- text = temp + text;
-
- // Add images
- return text.replace(new RegExp(Wikifier.imageFormatter.lookahead, "gim"), function(m,p1,p2,p3,src) {
- for (var i = 0; i < imgPassages.length; i++) {
- if (imgPassages[i].title == src) {
- src = imgPassages[i].text;
- break;
- }
- }
- return "url(" + src + ")"
- });
- }
- function setTransitionCSS(styleText) {
- styleText = alterCSS(styleText);
- var style = document.getElementById("transitionCSS");
- style.styleSheet ? (style.styleSheet.cssText = styleText) : (style.innerHTML = styleText);
- }
- function throwError(a, b, tooltip) {
- if (a) {
- var elem = insertElement(a, "span", null, "marked", b);
- tooltip && elem.setAttribute("title", tooltip);
- } else {
- alert("Regrettably, this " + tale.identity() + "'s code just ran into a problem:\n" + b + ".\n"+softErrorMessage);
- }
- }
- Math.easeInOut = function (a) {
- return (1 - ((Math.cos(a * Math.PI) + 1) / 2))
- };
- String.prototype.readMacroParams = function (keepquotes) {
- var exec, re = /(?:\s*)(?:(?:"([^"]*)")|(?:'([^']*)')|(?:\[\[((?:[^\]]|\](?!\]))*)\]\])|([^"'\s]\S*))/mg,
- params = [];
- do {
- var val;
- exec = re.exec(this);
- if (exec) {
- if (exec[1]) {
- val = exec[1];
- keepquotes && (val = '"' + val + '"');
- } else if (exec[2]) {
- val = exec[2];
- keepquotes && (val = "'" + val + "'");
- } else if (exec[3]) {
- val = exec[3];
- keepquotes && (val = '"' + val.replace('"','\\"') + '"');
- } else if (exec[4]) {
- val = exec[4];
- }
- val && params.push(val);
- }
- } while (exec);
- return params
- };
- String.prototype.readBracketedList = function () {
- var c, b = "\\[\\[([^\\]]+)\\]\\]",
- a = "[^\\s$]+",
- e = "(?:" + b + ")|(" + a + ")",
- d = new RegExp(e, "mg"),
- f = [];
- do {
- c = d.exec(this);
- if (c) {
- if (c[1]) {
- f.push(c[1])
- } else {
- if (c[2]) {
- f.push(c[2])
- }
- }
- }
- } while (c);
- return (f)
- };
- function rot13(s) {
- return s.replace(/[a-zA-Z]/g, function(c) {
- return String.fromCharCode((c<="Z" ? 90 : 122) >= (c=c.charCodeAt()+13) ? c : c-26);
- });
- }
- /*
- **
- ** Polyfills
- **
- */
- Object.create || (function() {
- var F = function(){};
- Object.create = function (o) {
- if (typeof o != 'object') throw TypeError();
- F.prototype = o;
- return new F();
- };
- })();
- String.prototype.trim || (String.prototype.trim = function () {
- return this.replace(/^\s\s*/, "").replace(/\s\s*$/, "")
- });
- Array.isArray || (Array.isArray = function(arg) {
- return Object.prototype.toString.call(arg) === '[object Array]';
- });
- Array.prototype.indexOf || (Array.prototype.indexOf = function (b, d) {
- d = (d == null) ? 0 : d;
- var a = this.length;
- for (var c = d; c < a; c++) {
- if (this[c] == b) {
- return c
- }
- }
- return -1
- });
- Array.prototype.forEach || (Array.prototype.forEach=function(fun){if(this==null){throw TypeError()}var t=Object(this);var len=+t.length;if(typeof fun!="function"){throw TypeError()}var thisArg=arguments.length>=2?arguments[1]:void 0;for(var i=0;i<len;i++){if(i in t){fun.call(thisArg,t[i],i,t)}}});
- /* btoa/atob polyfill by github.com/davidchambers */
- (function(){function t(t){this.message=t}var e=window,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t();o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t();for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})();
- /* Polyfill for fade transition */
- var hasTransition = 'transition' in document.documentElement.style || '-webkit-transition' in document.documentElement.style;
- function fade(f, c) {
- var h;
- var e = f.cloneNode(true);
- var g = (c.fade == "in") ? 1 : -1;
- f.parentNode.replaceChild(e, f);
- if (c.fade == "in") {
- h = 0;
- e.style.visibility = "visible"
- } else {
- h = 1
- }
- b(e, h);
- var a = window.setInterval(d, 25);
- function d() {
- h += 0.05 * g;
- b(e, Math.easeInOut(h));
- if (((g == 1) && (h >= 1)) || ((g == -1) && (h <= 0))) {
- f.style.visibility = (c.fade == "in") ? "visible" : "hidden";
- if (e.parentNode) {
- e.parentNode.replaceChild(f, e);
- }
- window.clearInterval(a);
- if (c.onComplete) {
- c.onComplete.call(f)
- }
- }
- }
- function b(k, j) {
- var l = Math.floor(j * 100);
- k.style.zoom = 1;
- k.style.filter = "alpha(opacity=" + l + ")";
- k.style.opacity = j
- }
- }
- /*
- **
- ** History object
- **
- */
- function History() {
- this.history = [{
- passage: null,
- variables: {}
- }]
- // Unique identifier for this game session
- this.id = new Date().getTime()+'';
- // URL of the bookmark link
- this.hash = '';
- }
- History.prototype.encodeHistory = function(b, noVars) {
- var ret = ".", vars, type, hist = this.history[b],
- d = this.history[b+1] ? delta(this.history[b+1].variables, hist.variables) : hist.variables;
-
- function vtob(val) {
- try {
- return window.btoa(unescape(encodeURIComponent(JSON.stringify(decompile(val)))));
- } catch(e) {
- return "0";
- }
- }
-
- if (!hist.passage || hist.passage.id == null) {
- return ""
- }
- ret += hist.passage.id.toString(36);
- if (noVars) {
- return ret;
- }
- for (vars in d) {
- type = typeof d[vars];
- if (type != "undefined") {
- ret += "$" + vtob(vars) + "," + vtob(d[vars]);
- }
- }
- for (vars in hist.linkVars) {
- type = typeof hist.linkVars[vars];
- if (type != "function" && type != "undefined") {
- ret += "[" + vtob(vars) + "," + vtob(hist.linkVars[vars]);
- }
- }
- return ret
- };
- History.decodeHistory = function(str, prev) {
- var name, splits, variable, c, d,
- ret = { variables: clone(prev.variables) || {} },
- match = /([a-z0-9]+)((?:\$[A-Za-z0-9\+\/=]+,[A-Za-z0-9\+\/=]+)*)((?:\[[A-Za-z0-9\+\/=]+,[A-Za-z0-9\+\/=]+)*)/g.exec(str);
-
- function btov(str) {
- try {
- return recompile(JSON.parse(decodeURIComponent(escape(window.atob(str)))));
- } catch(e) {
- return 0;
- }
- }
- if (match) {
- name = parseInt(match[1], 36);
- if (!tale.has(name)) {
- return false
- }
- if (match[2]) {
- ret.variables || (ret.variables = {});
- splits = match[2].split('$');
- for (c = 0; c < splits.length; c++) {
- variable = splits[c].split(",");
- d = btov(variable[0]);
- if (d) {
- ret.variables[d]=btov(variable[1]);
- }
- }
- }
- if (match[3]) {
- ret.linkVars || (ret.linkVars = {});
- splits = match[3].split('[');
- for (c = 0; c < splits.length; c++) {
- variable = splits[c].split(",");
- d = btov(variable[0]);
- if (d) {
- ret.linkVars[d]=btov(variable[1]);
- }
- }
- }
- ret.passage = tale.get(name);
- return ret;
- }
- };
- History.prototype.save = function() {
- var hist, b, a = "";
- for (b = this.history.length - 1; b >= 0; b--) {
- hist = this.history[b];
- if (!hist) {
- break;
- }
- a += this.encodeHistory(b);
- }
- return "#" + a
- };
- History.prototype.restore = function () {
- var a, b, c, vars;
- try {
- if (!window.location.hash || (window.location.hash == "#")) {
- if (testplay) {
- if (tale.has("StoryInit")) {
- new Wikifier(insertElement(null, "span"), tale.get("StoryInit").text);
- }
- this.display(testplay, null, 'quietly');
- return true
- }
- return false
- }
- if (window.location.hash.substr(0, 2) == '#!') {
- c = window.location.hash.substr(2).split('_').join(' ');
- this.display(c, null, 'quietly');
- return true
- }
- a = window.location.hash.replace("#", "").split(".");
- for (b = 0; b < a.length; b++) {
- vars = History.decodeHistory(a[b], vars || {});
- if (vars) {
- if (b == a.length - 1) {
- vars.variables = clone(this.history[0].variables);
- for (c in this.history[0].linkVars) {
- vars.variables[c] = clone(this.history[0].linkVars[c]);
- }
- this.history.unshift(vars);
- this.display(vars.passage.title, null, "back");
- }
- else {
- this.history.unshift(vars);
- }
- }
- }
- return true
- } catch (d) {
- return false
- }
- };
- History.prototype.saveVariables = function(c, el, callback) {
- if (typeof callback == "function") {
- callback.call(el);
- }
- this.history.unshift({
- passage: c,
- variables: clone(this.history[0].variables)
- });
- };
- var restart = History.prototype.restart = function () {
- if (typeof window.history.replaceState == "function") {
- (typeof this.pushState == "function") && this.pushState(true, window.location.href.replace(/#.*$/,''));
- window.location.reload()
- }
- else {
- window.location.hash = "";
- }
- };
- /*
- **
- ** Macros
- **
- */
- var version = {
- major: 4,
- minor: 3,
- revision: 0,
- date: new Date("2014"),
- extensions: {}
- };
- var testplay, tale, state, prerender = {}, postrender = {}, macros = window.macros = {};
- version.extensions.displayMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros.display = {
- // Used by parameter() and parameterValue()
- parameters: [],
- handler: function (place, macroName, params, parser) {
- var t, j, output, oldDisplayParams, name = parser.fullArgs();
-
- if (macroName != "display") {
- output = macroName;
- // Shorthand displays can have parameters
- params = parser.fullMatch().replace(/^\S*|>>$/g,'').readMacroParams(true);
- // The above line recreates params, with the quotes.
- try {
- for(j=0; j < params.length; j++) {
- params[j] = internalEval(Wikifier.parse(params[j]));
- }
- } catch (e) {
- throwError(place, parser.fullMatch() + " bad argument: " + params[j], parser.fullMatch());
- return
- }
- }
- else {
- try {
- output = internalEval(name);
- }
- catch(e) {
- }
- if (output == null) {
- // Last-ditch attempt
- if (tale.has(name)) {
- output = name;
- }
- }
- }
- if (!output) {
- throwError(place, '<<' + macroName + '>>: "' +name + "\" did not evaluate to a passage name", parser.fullMatch());
- } else if (!tale.has(output+"")) {
- throwError(place, '<<' + macroName + ">>: The \"" + output + "\" passage does not exist", parser.fullMatch());
- } else {
- oldDisplayParams = this.parameters;
- this.parameters = params;
- t = tale.get(output+"");
- if (t.tags.indexOf("script") > -1) {
- scriptEval(t);
- }
- else {
- new Wikifier(place, t.processText());
- }
- this.parameters = oldDisplayParams;
- }
- }
- };
- version.extensions.actionsMacro = {
- major: 1,
- minor: 2,
- revision: 0
- };
- macros.actions = {
- handler: function (a, f, g) {
- var v = state.history[0].variables, e = insertElement(a, "ul");
- if (!v["actions clicked"]) {
- v["actions clicked"] = {}
- }
- for (var b = 0; b < g.length; b++) {
- if (v["actions clicked"][g[b]]) {
- continue
- }
- var d = insertElement(e, "li");
- var c = Wikifier.createInternalLink(d, g[b], (function(link) {
- return function() { state.history[0].variables["actions clicked"][link] = true; }
- }(g[b])));
- insertText(c, g[b]);
- }
- }
- };
- version.extensions.printMacro = {
- major: 1,
- minor: 1,
- revision: 1
- };
- macros.print = {
- handler: function (place, macroName, params, parser) {
- var args = parser.fullArgs(macroName != "print"), output;
- try {
- // See comment within macros.display
- output = internalEval(args);
- if (output != null && (typeof output != "number" || !isNaN(output))) {
- new Wikifier(place, ''+output);
- }
- } catch (e) {
- throwError(place, "<<print>> bad expression: " + params.join(' '), parser.fullMatch());
- }
- }
- };
- version.extensions.setMacro = {
- major: 1,
- minor: 1,
- revision: 0
- };
- macros.set = {
- handler: function (a, b, c, parser) {
- macros.set.run(a, parser.fullArgs(), parser, c.join(' '))
- },
- run: function (a,expression, parser, original) {
- try {
- return internalEval(expression);
- } catch (e) {
- throwError(a, "bad expression: " + (original || expression), parser ? parser.fullMatch() : expression)
- }
- }
- };
- version.extensions.ifMacros = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros["if"] = {
- handler: function (place, macroName, params, parser) {
- var conditions = [],
- clauses = [],
- rawConds = [],
- srcOffset = parser.source.indexOf(">>", parser.matchStart) + 2,
- src = parser.source.slice(srcOffset),
- endPos = -1,
- rawCond = params.join(' '),
- currentCond = parser.fullArgs(),
- currentClause = "",
- t = 0,
- nesting = 0,
- i = 0;
-
- for (; i < src.length; i++) {
- if ((src.substr(i, 6) == "<<else") && !nesting) {
- rawConds.push(rawCond);
- conditions.push(currentCond.trim());
- clauses.push(currentClause);
- currentClause="";
- t = src.indexOf(">>",i+6);
- if(src.substr(i+6,4)==" if " || src.substr(i+6,3)=="if ") {
- rawCond = src.slice(i+9,t);
- currentCond = Wikifier.parse(rawCond);
- }
- else {
- rawCond = "";
- currentCond = "true";
- }
- i = t+2;
- }
- if (src.substr(i, 5) == "<<if ") {
- nesting++;
- }
- if (src.substr(i, 9) == "<<endif>>") {
- nesting--;
- if (nesting < 0) {
- endPos = srcOffset + i + 9;
- rawConds.push(rawCond);
- conditions.push(currentCond.trim());
- clauses.push(currentClause);
- break;
- }
- }
- currentClause += src.charAt(i);
- }
- if (endPos != -1) {
- parser.nextMatch = endPos;
- try {
- for(i=0;i<clauses.length;i++) {
- if (internalEval(conditions[i])) {
- new Wikifier(place, clauses[i]);
- break;
- }
- }
- } catch (e) {
- throwError(place, "<<" + (i ? "else " : "") + "if>> bad condition: " + rawConds[i], !i ? parser.fullMatch()
- : "<<else if " + rawConds[i] + ">>");
- }
- } else {
- throwError(place, "I can't find a matching <<endif>>", parser.fullMatch());
- }
- }
- };
- macros["else"] = macros.elseif = macros.endif = {
- handler: function () {}
- };
- version.extensions.rememberMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros.remember = {
- handler: function (place, macroName, params, parser) {
- var variable, value, re, match,
- statement = params.join(" ");
- macros.set.run(place, parser.fullArgs(), null, params.join(' '));
- if (!window.localStorage) {
- throwError(place, "<<remember>> can't be used "
- + (window.location.protocol == "file:" ? " by local HTML files " : "") + " in this browser.",parser.fullMatch());
- return;
- }
- re = new RegExp(Wikifier.textPrimitives.variable, "g");
- while (match = re.exec(statement)) {
- variable = match[1];
- value = state.history[0].variables[variable];
- try {
- value = JSON.stringify(value);
- } catch (e) {
- throwError(place, "can't <<remember>> the variable $" + variable + " (" + (typeof value) + ")", parser.fullMatch());
- return;
- }
- window.localStorage[this.prefix + variable] = value;
- }
- },
- init: function () {
- var i, variable, value;
- this.prefix = "Twine." + tale.defaultTitle + ".";
- for (i in window.localStorage) {
- if (i.indexOf(this.prefix) == 0) {
- variable = i.substr(this.prefix.length);
- value = window.localStorage[i];
- try {
- value = JSON.parse(value);
- state.history[0].variables[variable]=value;
- } catch (e) {
- }
- }
- }
- },
- expire: null,
- prefix: null
- };
- version.extensions.forgetMacro = {
- major: 1,
- minor: 0,
- revision: 0
- };
- macros.forget = {
- handler: function (place, macroName, params) {
- var re, match, variable,
- statement = params.join(" ");
- re = new RegExp(Wikifier.textPrimitives.variable, "g");
- while (match = re.exec(statement)) {
- variable = match[1] + ""
- delete state.history[0].variables[variable];
- delete window.localStorage[macros.remember.prefix + variable];
- }
- }
- };
-
- version.extensions.SilentlyMacro = {
- major: 1,
- minor: 1,
- revision: 0
- };
- macros.nobr = macros.silently = {
- handler: function (place, macroName, f, parser) {
- var i, h = insertElement(null, 'div'),
- k = parser.source.indexOf('>>', parser.matchStart) + 2,
- a = parser.source.slice(k),
- d = -1,
- c = '',
- l = 0;
- for (i = 0; i < a.length; i++) {
- if (a.substr(i, macroName.length+7) == '<<end' + macroName + '>>') {
- if (l == 0) {
- d = k + i + macroName.length+7;
- break;
- } else {
- l--;
- }
- } else if (a.substr(i, macroName.length+4) == '<<' + macroName + '>>') {
- l++;
- }
- if (macroName == "nobr" && a.charAt(i) == '\n') {
- c += "\u200c"; // Zero-width space
- }
- else {
- c += a.charAt(i);
- }
- }
- if (d != -1) {
- new Wikifier(macroName == "nobr" ? place : h, c);
- parser.nextMatch = d;
- } else {
- throwError(place, "can't find matching <<end" + macroName+">>", parser.fullMatch());
- }
- }
- };
- macros.endsilently = {
- handler: function () {}
- };
- version.extensions.choiceMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros.choice = {
- callback: function() {
- var i, other, passage = findPassageParent(this);
-
- if (passage) {
- other = passage.querySelectorAll(".choice");
- for (i = 0; i < other.length; i++) {
- other[i].outerHTML = "<span class=disabled>" + other[i].innerHTML + "</span>";
- }
- state.history[0].variables["choice clicked"][passage.id.replace(/\|[^\]]*$/,'')] = true;
- }
- },
- handler: function (A, C, D, parser) {
- var link, id, match,
- text = D[1] || D[0].split("|")[0],
- passage = findPassageParent(A);
- // Get ID of the "choice clicked" entry
- if (!passage) {
- throwError(A, "<<"+C+">> can't be used here.",parser.fullMatch());
- return;
- }
- id = (passage && passage.id.replace(/\|[^\]]*$/,''));
- if (id && (state.history[0].variables["choice clicked"] ||
- (state.history[0].variables["choice clicked"] = {}))[id]) {
- insertElement(A, "span", null, "disabled", text);
- }
- else {
- match = new RegExp(Wikifier.linkFormatter.lookahead).exec(parser.fullMatch());
-
- if (match) {
- link = Wikifier.linkFormatter.makeLink(A,match,this.callback);
- }
- else {
- link = Wikifier.linkFormatter.makeLink(A,[0,text,D[0]],this.callback);
- }
- link.className += " " + C;
- }
- }
- };
- version.extensions.backMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros.back = {
- labeltext: '« back',
- handler: function (a, b, e, parser) {
- var labelParam, c, el,
- labeltouse = this.labeltext,
- steps = 1,
- stepsParam = e.indexOf("steps"),
- stepsParam2 = "";
- // Steps parameter
- if(stepsParam > 0) {
- stepsParam2 = e[stepsParam - 1];
- if(stepsParam2[0] == '$') {
- try {
- stepsParam2 = internalEval(Wikifier.parse(stepsParam2));
- }
- catch(r) {
- throwError(a, parser.fullMatch() + " bad expression: " + r.message, parser.fullMatch())
- return;
- }
- }
- // Previously, trying to go back more steps than were present in the
- // history would silently revert to just 1 step.
- // Instead, let's just go back to the start.
- steps = +stepsParam2;
- if(steps >= state.history.length - 1) {
- steps = state.history.length - 2;
- }
- e.splice(stepsParam - 1, 2);
- }
- // Label parameter
- labelParam = e.indexOf("label");
- if(labelParam > -1) {
- if(!e[labelParam + 1]) {
- throwError(a, parser.fullMatch() + ": " + e[labelParam] + ' keyword needs an additional label parameter', parser.fullMatch());
- return;
- }
- labeltouse = e[labelParam + 1];
- e.splice(labelParam, 2);
- }
- // What's left is the passage name parameter
- if(stepsParam <= 0) {
- if(e[0]) {
- if(e[0].charAt(0) == '$') {
- try {
- e = internalEval(Wikifier.parse(e[0]));
- }
- catch(r) {
- throwError(a, parser.fullMatch() + " bad expression: " + r.message, parser.fullMatch())
- return;
- }
- }
- else {
- e = e[0];
- }
- if(!tale.has(e)) {
- throwError(a, "The \"" + e + "\" passage does not exist",parser.fullMatch());
- return;
- }
- for(c = 0; c < state.history.length; c++) {
- if(state.history[c].passage.title == e) {
- steps = c;
- break;
- }
- }
- }
- }
- el = document.createElement("a");
- el.className = b;
- addClickHandler(el, (function(b) { return function () {
- return macros.back.onclick(b == "back", steps, el)
- }}(b)));
- el.innerHTML = labeltouse;
- a.appendChild(el);
- }
- };
- version.extensions.returnMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros["return"] = {
- labeltext: '« return',
- handler: function(a,b,e) {
- macros.back.handler.call(this,a,b,e);
- }
- };
- version.extensions.textInputMacro = {
- major: 2,
- minor: 0,
- revision: 0
- };
- macros.checkbox = macros.radio = macros.textinput = {
- handler: function (A, C, D, parser) {
- var match,
- class_ = C.replace('input','Input'),
- q = A.querySelectorAll('input'),
- id = class_ + "|" + ((q && q.length) || 0);
- input = insertElement(null, 'input', id, class_);
-
- input.name=D[0];
- input.type=C.replace('input','');
- // IE 8 support - delay insertion until now
- A.appendChild(input);
-
- if (C == "textinput" && D[1]) {
- match = new RegExp(Wikifier.linkFormatter.lookahead).exec(parser.fullMatch());
-
- if (match) {
- Wikifier.linkFormatter.makeLink(A,match, macros.button.callback, 'button');
- }
- else {
- Wikifier.linkFormatter.makeLink(A,[0,(D[2] || D[1]),D[1]], macros.button.callback, 'button');
- }
- }
- else if ((C == "radio" || C == "checkbox") && D[1]) {
- input.value = D[1];
- insertElement(A, 'label','', '', D[1]).setAttribute('for',id);
- if (D[2]) {
- insertElement(A,'br');
- D.splice(1,1);
- macros[C].handler(A,C,D)
- }
- }
- }
- };
- version.extensions.buttonMacro = {
- major: 1,
- minor: 0,
- revision: 0
- };
- macros.button = {
- callback: function() {
- var el = findPassageParent(this);
- if (el) {
- var inputs = el.querySelectorAll("input");
- for (i = 0; i < inputs.length; i++) {
- if (inputs[i].type!="checkbox" && (inputs[i].type!="radio" || inputs[i].checked)) {
- macros.set.run(null, Wikifier.parse(inputs[i].name+' = "'+inputs[i].value.replace(/"/g,'\\"')+'"'));
- }
- else if (inputs[i].type=="checkbox" && inputs[i].checked) {
- macros.set.run(null, Wikifier.parse(
- inputs[i].name+' = [].concat('+inputs[i].name+' || []);'));
- macros.set.run(null, Wikifier.parse(
- inputs[i].name+'.push("'+inputs[i].value.replace(/"/g,'\\"')+'")'));
- }
- }
- }
- },
- handler: function (A, C, D, parser) {
- var link,
- match = new RegExp(Wikifier.linkFormatter.lookahead).exec(parser.fullMatch());
-
- if (match) {
- Wikifier.linkFormatter.makeLink(A, match, this.callback, 'button');
- }
- else {
- Wikifier.linkFormatter.makeLink(A,[0,D[1] || D[0], D[0]], this.callback, 'button');
- }
- }
- };
- /*
- **
- ** Passage object
- **
- */
- function Passage(c, b, a, ofunc) {
- var t;
- if (!this || this.constructor != Passage) {
- throw new ReferenceError("passage() must be in lowercase");
- }
- this.title = c;
- ofunc = typeof ofunc == 'function' && ofunc;
- if (b) {
- this.id = a;
- // Load tags
- this.tags = b.getAttribute("tags");
- if (typeof this.tags == "string") {
- if (ofunc) {
- this.tags = ofunc(this.tags);
- }
- this.tags = this.tags.readBracketedList();
- } else this.tags = [];
- // Load text
- t = b.firstChild ? b.firstChild.nodeValue : "";
- if (ofunc && !this.isImage()) {
- this.text = ofunc(Passage.unescapeLineBreaks(t));
- } else {
- this.text = Passage.unescapeLineBreaks(t);
- }
- // Preload linked images
- if (!this.isImage()) {
- this.preloadImages();
- }
- // Check for the .char selector, or the [data-char] selector
- // False positives aren't a big issue.
- if (/\.char\b|\[data\-char\b/.exec(this.text) && Wikifier.charSpanFormatter) {
- Wikifier.formatters.push(Wikifier.charSpanFormatter);
- delete Wikifier.charSpanFormatter;
- }
- } else {
- this.text = '@@This passage does not exist: ' + c + '@@';
- this.tags = [];
- }
- }
- Passage.prototype.isImage = function() {
- return !!~(this.tags.indexOf("Twine.image"));
- };
- Passage.prototype.preloadImages = function() {
- // Don't preload URLs containing '$' - suspect that they are variables.
- var u = "\\s*['\"]?([^\"'$]+\\.(jpe?g|a?png|gif|bmp|webp|svg))['\"]?\\s*",
- k = function(c, e) {
- var i,d;
- do {
- d = c.exec(this.text);
- if(d) {
- i = new Image();
- i.src = d[e];
- }
- } while (d);
- return k;
- };
- k.call(this, new RegExp(Wikifier.imageFormatter.lookahead.replace("[^\\[\\]\\|]+",u), "mg"), 4)
- .call(this, new RegExp("url\\s*\\(" + u + "\\)", "mig"), 1)
- .call(this, new RegExp("src\\s*=" + u, "mig"), 1);
- };
- Passage.unescapeLineBreaks = function (a) {
- if (a && typeof a == "string") {
- return a.replace(/\\n/mg, "\n").replace(/\\t/mg, "\t").replace(/\\s/mg, "\\").replace(/\\/mg, "\\").replace(/\r/mg, "")
- } else {
- return ""
- }
- };
- Passage.prototype.setTags = function(b) {
- var t = this.tags != null && this.tags.length ? this.tags.join(' ') : "";
- if (t) {
- b.setAttribute('data-tags', this.tags.join(' '));
- }
- document.body.setAttribute("data-tags", t);
- };
- Passage.prototype.processText = function() {
- var ret = this.text;
- if (~this.tags.indexOf("nobr")) {
- ret = ret.replace(/\n/g,"\u200c");
- }
- if (this.isImage()) {
- ret = "[img[" + ret + "]]"
- }
- return ret;
- };
- /*
- **
- ** Tale object
- **
- */
- function Tale() {
- var a,b,c,lines,i,kv,nsc,isImage,
- settings = this.storysettings = {
- lookup: function(a, dfault) {
- // The two runtime settings (undo and bookmark) default to true.
- if (!(a in this)) return dfault;
- return (this[a]+"") != "off";
- }
- },
- HTMLtitle = document.querySelector('title');
- tiddlerTitle = '';
- this.defaultTitle = (HTMLtitle && (HTMLtitle.textContent || HTMLtitle.innerText)) || "Untitled Story";
- this.passages = {};
- //Look for and load the StorySettings
- if (document.normalize) document.normalize();
- a = document.getElementById("storeArea").children;
- for (b = 0; b < a.length; b++) {
- c = a[b];
- if (c.getAttribute && c.getAttribute("tiddler") == 'StorySettings') {
- lines = new Passage('StorySettings', c, 0, null, null).text.split('\n');
- for (i in lines) {
- if (typeof lines[i] == "string" && lines[i].indexOf(':') > -1) {
- kv = lines[i].toLowerCase().split(':');
- kv[0] = kv[0].replace(/^\s+|\s+$/g, '');
- kv[1] = kv[1].replace(/^\s+|\s+$/g, '');
- if (kv[0] != "lookup") {
- settings[kv[0]] = kv[1];
- }
- }
- }
- }
- }
- //Load in the passages
- if (settings.obfuscate == 'rot13') {
- for (b = 0; b < a.length; b++) {
- c = a[b];
- if (c.getAttribute && (tiddlerTitle = c.getAttribute("tiddler"))) {
- isImage = (c.getAttribute("tags")+"").indexOf("Twine.image")>-1;
- if (tiddlerTitle != 'StorySettings' && !isImage)
- tiddlerTitle = rot13(tiddlerTitle);
- this.passages[tiddlerTitle] = new Passage(tiddlerTitle, c, b+1, !isImage && rot13);
- }
- }
- } else {
- for (b = 0; b < a.length; b++) {
- c = a[b];
- if (c.getAttribute && (tiddlerTitle = c.getAttribute("tiddler"))) {
- this.passages[tiddlerTitle] = new Passage(tiddlerTitle, c, b, null, null)
- }
- }
- }
- }
- Tale.prototype.has = function (a) {
- if (typeof a == "string") {
- return (this.passages[a] != null)
- } else {
- for (var i in this.passages) {
- if (this.passages[i].id == a) {
- return true
- }
- }
- return false
- }
- };
- Tale.prototype.get = function (a) {
- if (typeof a == "string") {
- return this.passages[a] || new Passage(a)
- } else {
- for (var i in this.passages) {
- if (this.passages[i].id == a) {
- return this.passages[i]
- }
- }
- }
- };
- Tale.prototype.lookup = function (h, g, a) {
- var d = [];
- for (var c in this.passages) {
- var f = this.passages[c];
- for (var b = 0; b < f[h].length; b++) {
- if (f[h][b] == g) {
- d.push(f)
- }
- }
- }
- if (!a) {
- a = "title"
- }
- d.sort(function (k, j) {
- if (k[a] == j[a]) {
- return (0)
- } else {
- return (k[a] < j[a]) ? -1 : +1
- }
- });
- return d
- };
- Tale.prototype.canUndo = function() {
- return this.storysettings.lookup('undo',true);
- };
- Tale.prototype.identity = function () {
- var meta = document.querySelector("meta[name='identity']"),
- identity = meta ? meta.getAttribute("content") : "story";
-
- return (Tale.prototype.identity = function() {
- return identity;
- })();
- };
- Tale.prototype.forEachStylesheet = function(tags, callback) {
- var passage, i;
- tags = tags || [];
-
- if (typeof callback != "function")
- return;
- for (passage in this.passages) {
- passage = tale.passages[passage];
- if (passage && ~passage.tags.indexOf("stylesheet")) {
- for (i = 0; i < tags.length; i++) {
- if (~passage.tags.indexOf(tags[i])) {
- callback(passage);
- break;
- }
- }
- }
- }
- };
- Tale.prototype.setPageElements = function() {
- var storyTitle;
-
- setPageElement("storyTitle", "StoryTitle", this.defaultTitle);
- storyTitle = document.getElementById("storyTitle");
- document.title = this.title = (storyTitle && (storyTitle.textContent || storyTitle.innerText)) || this.defaultTitle;
-
- setPageElement("storySubtitle", "StorySubtitle", "");
- if (tale.has("StoryAuthor")) {
- setPageElement("titleSeparator", null, "\n");
- setPageElement("storyAuthor", "StoryAuthor", "");
- }
- if (tale.has("StoryMenu")) {
- document.getElementById("storyMenu").setAttribute("style","");
- setPageElement("storyMenu", "StoryMenu", "");
- }
- };
- /*
- **
- ** Wikifier object
- **
- */
- function Wikifier(place, source) {
- this.source = source;
- this.output = place;
- this.nextMatch = 0;
- this.assembleFormatterMatches(Wikifier.formatters);
- this.subWikify(this.output);
- }
- Wikifier.textPrimitives = {
- upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
- lowerLetter: "[a-z\u00df-\u00ff_0-9\\-\u0151\u0171]",
- anyLetter: "[A-Za-z\u00c0-\u00de\u00df-\u00ff_0-9\\-\u0150\u0170\u0151\u0171]"
- }
- Wikifier.textPrimitives.variable = "\\$((?:"+Wikifier.textPrimitives.anyLetter.replace("\\-", "")+"*"+
- Wikifier.textPrimitives.anyLetter.replace("0-9\\-", "")+"+"+
- Wikifier.textPrimitives.anyLetter.replace("\\-", "")+"*)+)";
- Wikifier.textPrimitives.unquoted = "(?=(?:[^\"'\\\\]*(?:\\\\.|'(?:[^'\\\\]*\\\\.)*[^'\\\\]*'|\"(?:[^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^'\"]*$)";
- Wikifier.prototype.assembleFormatterMatches = function (formatters) {
- this.formatters = [];
- var pattern = [];
- for (var n = 0; n < formatters.length; n++) {
- pattern.push("(" + formatters[n].match + ")");
- this.formatters.push(formatters[n]);
- };
- this.formatterRegExp = new RegExp(pattern.join("|"), "mg");
- };
- Wikifier.prototype.subWikify = function (output, terminator) {
- // Temporarily replace the output pointer
- var terminatorMatch, formatterMatch, oldOutput = this.output;
- this.output = output;
- // Prepare the terminator RegExp
- var terminatorRegExp = terminator ? new RegExp("(" + terminator + ")", "mg") : null;
- do {
- // Prepare the RegExp match positions
- this.formatterRegExp.lastIndex = this.nextMatch;
- if (terminatorRegExp) terminatorRegExp.lastIndex = this.nextMatch;
- // Get the first matches
- formatterMatch = this.formatterRegExp.exec(this.source);
- terminatorMatch = terminatorRegExp ? terminatorRegExp.exec(this.source) : null;
- // Check for a terminator match
- if (terminatorMatch && (!formatterMatch || terminatorMatch.index <= formatterMatch.index)) {
- // Output any text before the match
- if (terminatorMatch.index > this.nextMatch) this.outputText(this.output, this.nextMatch, terminatorMatch.index);
- // Set the match parameters
- this.matchStart = terminatorMatch.index;
- this.matchLength = terminatorMatch[1].length;
- this.matchText = terminatorMatch[1];
- this.nextMatch = terminatorMatch.index + terminatorMatch[1].length;
- // Restore the output pointer and exit
- this.output = oldOutput;
- return;
- }
- // Check for a formatter match
- else if (formatterMatch) {
- // Output any text before the match
- if (formatterMatch.index > this.nextMatch) this.outputText(this.output, this.nextMatch, formatterMatch.index);
- // Set the match parameters
- this.matchStart = formatterMatch.index;
- this.matchLength = formatterMatch[0].length;
- this.matchText = formatterMatch[0];
- this.nextMatch = this.formatterRegExp.lastIndex;
- // Figure out which formatter matched
- var matchingFormatter = -1;
- for (var t = 1; t < formatterMatch.length; t++) {
- if (formatterMatch[t]) {
- matchingFormatter = t - 1;
- break;
- }
- }
- // Call the formatter
- if (matchingFormatter != -1) { this.formatters[matchingFormatter].handler(this); }
- }
- }
- while (terminatorMatch || formatterMatch);
- // Output any text after the last match
- if (this.nextMatch < this.source.length) {
- this.outputText(this.output, this.nextMatch, this.source.length);
- this.nextMatch = this.source.length;
- }
- // Restore the output pointer
- this.output = oldOutput;
- };
- Wikifier.prototype.outputText = function (place, startPos, endPos) {
- if (place) {
- insertText(place, this.source.substring(startPos, endPos));
- }
- };
- Wikifier.prototype.fullMatch = function() {
- return this.source.slice(this.matchStart, this.source.indexOf('>>', this.matchStart)+2);
- };
- Wikifier.prototype.fullArgs = function (includeName) {
- var source = this.source.replace(/\u200c/g," "),
- endPos = this.nextMatch-2,
- startPos = source.indexOf(includeName ? '<<' : ' ', this.matchStart);
- if (!~startPos || !~endPos || endPos <= startPos) {
- return "";
- }
- return Wikifier.parse(source.slice(startPos + (includeName ? 2 : 1), endPos).trim());
- };
- Wikifier.parse = function (input) {
- var m, re, b = input, found = [],
- g = Wikifier.textPrimitives.unquoted;
-
- function alter(from,to) {
- b = b.replace(new RegExp(from+g,"gim"),to);
- return alter;
- }
- // Extract all the variables, and set them to 0 if undefined.
- re = new RegExp(Wikifier.textPrimitives.variable+g,"gi");
- while (m = re.exec(input)) {
- if (!~found.indexOf(m[0])) {
- // This deliberately contains a 'null or undefined' check
- b = m[0]+" == null && ("+m[0]+" = 0);"+b;
- found.push(m[0]);
- }
- }
- alter(Wikifier.textPrimitives.variable, "state.history[0].variables.$1")
- // Old operators
- ("\\beq\\b", " == ")
- ("\\bneq\\b", " != ")
- ("\\bgt\\b", " > ")
- ("\\bgte\\b", " >= ")
- ("\\blt\\b", " < ")
- ("\\blte\\b", " <= ")
- ("\\band\\b", " && ")
- ("\\bor\\b", " || ")
- ("\\bnot\\b", " ! ")
- // New operators
- ("\\bis\\b", " == ")
- ("\\bto\\b", " = ");
- return b
- };
- Wikifier.formatHelpers = {
- charFormatHelper: function (a) {
- var b = insertElement(a.output, this.element);
- a.subWikify(b, this.terminator)
- },
- inlineCssHelper: function (w) {
- var s, v, lookaheadMatch, gotMatch,
- styles = [],
- lookahead = Wikifier.styleByCharFormatter.lookahead,
- lookaheadRegExp = new RegExp(lookahead, "mg"),
- hadStyle = false,
- unDash = function (str) {
- var s = str.split("-");
- if (s.length > 1) for (var t = 1; t < s.length; t++)
- s[t] = s[t].substr(0, 1).toUpperCase() + s[t].substr(1);
- return s.join("");
- };
-
- styles.className = "";
- do {
- lookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = lookaheadRegExp.exec(w.source);
- gotMatch = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
- if (gotMatch) {
- hadStyle = true;
- if (lookaheadMatch[5]) {
- styles.className += lookaheadMatch[5].replace(/\./g," ") + " ";
- } else if (lookaheadMatch[1]) {
- s = unDash(lookaheadMatch[1]);
- v = lookaheadMatch[2];
- } else {
- s = unDash(lookaheadMatch[3]);
- v = lookaheadMatch[4];
- }
- switch (s) {
- case "bgcolor":
- s = "backgroundColor";
- break;
- case "float":
- s = "cssFloat";
- break
- }
- styles.push({
- style: s,
- value: v
- });
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- } while (gotMatch);
- return styles;
- },
- monospacedByLineHelper: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead, "mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source);
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart) {
- insertElement(w.output, "pre", null, null, lookaheadMatch[1]);
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- }
- };
- Wikifier.formatters = [
- {
- name: "table",
- match: "^\\|(?:[^\\n]*)\\|(?:[fhc]?)$",
- lookahead: "^\\|([^\\n]*)\\|([fhc]?)$",
- rowTerminator: "\\|(?:[fhc]?)$\\n?",
- cellPattern: "(?:\\|([^\\n\\|]*)\\|)|(\\|[fhc]?$\\n?)",
- cellTerminator: "(?:\\x20*)\\|",
- rowTypes: {
- "c": "caption",
- "h": "thead",
- "": "tbody",
- "f": "tfoot"
- },
- handler: function (w) {
- var rowContainer, rowElement,lookaheadMatch, matched,
- table = insertElement(w.output, "table"),
- lookaheadRegExp = new RegExp(this.lookahead, "mg"),
- currRowType = null,
- nextRowType,
- prevColumns = [],
- rowCount = 0;
- w.nextMatch = w.matchStart;
- do {
- lookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = lookaheadRegExp.exec(w.source),
- matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
- if (matched) {
- nextRowType = lookaheadMatch[2];
- if (nextRowType != currRowType) rowContainer = insertElement(table, this.rowTypes[nextRowType]);
- currRowType = nextRowType;
- if (currRowType == "c") {
- if (rowCount == 0) rowContainer.setAttribute("align", "top");
- else rowContainer.setAttribute("align", "bottom");
- w.nextMatch = w.nextMatch + 1;
- w.subWikify(rowContainer, this.rowTerminator);
- } else {
- rowElement = insertElement(rowContainer, "tr");
- this.rowHandler(w, rowElement, prevColumns);
- }
- rowCount++;
- }
- } while (matched);
- },
- rowHandler: function (w, e, prevColumns) {
- var cellMatch, matched, col = 0,
- currColCount = 1,
- cellRegExp = new RegExp(this.cellPattern, "mg");
-
- do {
- cellRegExp.lastIndex = w.nextMatch;
- cellMatch = cellRegExp.exec(w.source);
- matched = cellMatch && cellMatch.index == w.nextMatch;
- if (matched) {
- if (cellMatch[1] == "~") {
- var last = prevColumns[col];
- if (last) {
- last.rowCount++;
- last.element.setAttribute("rowSpan", last.rowCount);
- last.element.setAttribute("rowspan", last.rowCount);
- last.element.valign = "center";
- }
- w.nextMatch = cellMatch.index + cellMatch[0].length - 1;
- } else if (cellMatch[1] == ">") {
- currColCount++;
- w.nextMatch = cellMatch.index + cellMatch[0].length - 1;
- } else if (cellMatch[2]) {
- w.nextMatch = cellMatch.index + cellMatch[0].length;
- break;
- } else {
- var spaceLeft = false,
- spaceRight = false,
- lastColCount, lastColElement, styles, cell, t;
- w.nextMatch++;
- styles = Wikifier.formatHelpers.inlineCssHelper(w);
- while (w.source.substr(w.nextMatch, 1) == " ") {
- spaceLeft = true;
- w.nextMatch++;
- }
- if (w.source.substr(w.nextMatch, 1) == "!") {
- cell = insertElement(e, "th");
- w.nextMatch++;
- } else cell = insertElement(e, "td");
- prevColumns[col] = {
- rowCount: 1,
- element: cell
- };
- lastColCount = 1;
- lastColElement = cell;
- if (currColCount > 1) {
- cell.setAttribute("colSpan", currColCount);
- cell.setAttribute("colspan", currColCount);
- currColCount = 1;
- }
- for (t = 0; t < styles.length; t++)
- cell.style[styles[t].style] = styles[t].value;
- w.subWikify(cell, this.cellTerminator);
- if (w.matchText.substr(w.matchText.length - 2, 1) == " ") spaceRight = true;
- if (spaceLeft && spaceRight) cell.align = "center";
- else if (spaceLeft) cell.align = "right";
- else if (spaceRight) cell.align = "left";
- w.nextMatch = w.nextMatch - 1;
- }
- col++;
- }
- } while (matched);
- }
- },
- {
- name: "rule",
- match: "^----$\\n?",
- handler: function (w) {
- insertElement(w.output, "hr");
- }
- },
- {
- name: "emdash",
- match: "--",
- becomes: String.fromCharCode(8212),
- handler: function (a) {
- insertElement(a.output, "span", null, "char", this.becomes).setAttribute("data-char","emdash");
- }
- },
- {
- name: "heading",
- match: "^!{1,5}",
- terminator: "\\n",
- handler: function (w) {
- var e = insertElement(w.output, "h" + w.matchLength);
- w.subWikify(e, this.terminator);
- }
- },
- {
- name: "monospacedByLine",
- match: "^\\{\\{\\{\\n",
- lookahead: "^\\{\\{\\{\\n((?:^[^\\n]*\\n)+?)(^\\}\\}\\}$\\n?)",
- handler: Wikifier.formatHelpers.monospacedByLineHelper
- },
- {
- name: "quoteByBlock",
- match: "^<<<\\n",
- terminator: "^<<<\\n",
- handler: function (w) {
- var e = insertElement(w.output, "blockquote");
- w.subWikify(e, this.terminator);
- }
- },
- {
- name: "list",
- match: "^(?:(?:\\*+)|(?:#+))",
- lookahead: "^(?:(\\*+)|(#+))",
- terminator: "\\n",
- handler: function (w) {
- var newType, newLevel, t, len, bulletType, lookaheadMatch, matched,
- lookaheadRegExp = new RegExp(this.lookahead, "mg"),
- placeStack = [w.output],
- currType = null,
- currLevel = 0;
-
- w.nextMatch = w.matchStart;
- do {
- lookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = lookaheadRegExp.exec(w.source);
- matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
- if (matched) {
- newLevel = lookaheadMatch[0].length;
- if (lookaheadMatch[1]) {
- bulletType = lookaheadMatch[1].slice(-1);
- newType = "ul";
- }
- else if (lookaheadMatch[2]) {
- newType = "ol";
- }
- w.nextMatch += newLevel;
- if (newLevel > currLevel) {
- for (t = currLevel; t < newLevel; t++) {
- placeStack.push(insertElement(placeStack[placeStack.length - 1], newType));
- }
- } else if (newLevel < currLevel) {
- for (t = currLevel; t > newLevel; t--)
- placeStack.pop();
- } else if (newLevel == currLevel && newType != currType) {
- placeStack.pop();
- placeStack.push(insertElement(placeStack[placeStack.length - 1], newType));
- }
- currLevel = newLevel;
- currType = newType;
- t = insertElement(placeStack[placeStack.length - 1], "li");
- // Currently unused
- if (bulletType && bulletType != "*") {
- t.setAttribute("data-bullet", bulletType);
- }
- w.subWikify(t, this.terminator);
- }
- } while (matched);
- }
- },
- (Wikifier.urlFormatter = {
- name: "urlLink",
- match: "(?:https?|mailto|javascript|ftp|data):[^\\s'\"]+(?:/|\\b)",
- handler: function (w) {
- var e = Wikifier.createExternalLink(w.output, w.matchText);
- w.outputText(e, w.matchStart, w.nextMatch);
- }
- }),
- (Wikifier.linkFormatter = {
- name: "prettyLink",
- match: "\\[\\[",
- lookahead: "\\[\\[([^\\|]*?)(?:\\|(.*?))?\\](?:\\[(.*?)\])?\\]",
- makeInternalOrExternal: function(out,title,callback,type) {
- if (title && !tale.has(title) && (title.match(Wikifier.urlFormatter.match,"g") || ~title.search(/[\.\\\/#]/)))
- return Wikifier.createExternalLink(out, title, callback, type);
- else
- return Wikifier.createInternalLink(out, title, callback, type);
- },
- // This base callback executes the code in a setter
- makeCallback: function(code,callback) {
- return function() {
- macros.set.run(null, Wikifier.parse(code), null, code);
- typeof callback == "function" && callback.call(this);
- }
- },
- makeLink: function(out, match, callback2, type) {
- var link, title, callback;
- if (match[3]) { // Code
- callback = this.makeCallback(match[3],callback2);
- }
- else {
- typeof callback2 == "function" && (callback = callback2);
- }
- title = Wikifier.parsePassageTitle(match[2] || match[1]);
- link = this.makeInternalOrExternal(out,title,callback, type);
- setPageElement(link, null, match[2] ? match[1] : title);
- return link;
- },
- handler: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead, "mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source)
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart) {
- this.makeLink(w.output, lookaheadMatch)
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- }
- }),
- (Wikifier.imageFormatter = {
- name: "image",
- match: "\\[(?:[<]{0,1})(?:[>]{0,1})[Ii][Mm][Gg]\\[",
- lookahead: "\\[([<]?)(>?)img\\[(?:([^\\|\\]]+)\\|)?([^\\[\\]\\|]+)\\](?:\\[([^\\]]*)\\]?)?(\\])",
- importedImage: function(img, passageName) {
- var imgPassages, imgname;
- // Try to parse it as a variable
- try {
- imgname = internalEval(Wikifier.parse(passageName));
- }
- catch(e) {
- }
- if (!imgname) {
- imgname = passageName;
- }
- // Base64 passage transclusion
- imgPassages = tale.lookup("tags", "Twine.image");
- for (j = 0; j < imgPassages.length; j++) {
- if (imgPassages[j].title == imgname) {
- img.src = imgPassages[j].text;
- break;
- }
- }
- },
- handler: function (w) {
- var e, img, j, lookaheadMatch,
- lookaheadRegExp = new RegExp(this.lookahead, "mig");
- lookaheadRegExp.lastIndex = w.matchStart;
- lookaheadMatch = lookaheadRegExp.exec(w.source);
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- e = w.output, title = Wikifier.parsePassageTitle(lookaheadMatch[5])
- if (title) {
- e = Wikifier.linkFormatter.makeInternalOrExternal(w.output, title);
- }
- img = insertElement(e, "img");
- if (lookaheadMatch[1]) img.align = "left";
- else if (lookaheadMatch[2]) img.align = "right";
- if (lookaheadMatch[3]) img.title = lookaheadMatch[3];
- // Setup the image if it's referencing an image passage.
- this.importedImage(img,lookaheadMatch[4]);
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- }
- }),
- {
- name: "macro",
- match: "<<",
- lookahead: /<<([^>\s]+)(?:\s*)((?:\\.|'(?:[^'\\]*\\.)*[^'\\]*'|"(?:[^"\\]*\\.)*[^"\\]*"|[^'"\\>]|>(?!>))*)>>/mg,
- handler: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead);
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source.replace(/\u200c/g,'\n'));
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
- var params = lookaheadMatch[2].readMacroParams();
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- var name = lookaheadMatch[1];
- try {
- var macro = macros[name];
- if (macro && typeof macro == "object" && macro.handler) {
- macro.handler(w.output, name, params, w);
- }
- // Variable?
- else if (name[0] == '$') {
- macros.print.handler(w.output, name, [name].concat(params), w);
- }
- // Passage
- else if (tale.has(name)) {
- macros.display.handler(w.output, name, [name].concat(params), w);
- }
- else throwError(w.output, 'No macro or passage called "' + name + '"', w.fullMatch());
- } catch (e) {
- throwError(w.output, 'Error executing macro ' + name + ': ' + e.toString(), w.fullMatch());
- }
- }
- }
- },
- {
- name: "html",
- match: "<html>",
- lookahead: "<html>((?:.|\\n)*?)</html>",
- handler: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead, "mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source)
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart) {
- var e = insertElement(w.output, "span");
- e.innerHTML = lookaheadMatch[1];
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- }
- },
- {
- name: "commentByBlock",
- match: "/%",
- lookahead: "/%((?:.|\\n)*?)%/",
- handler: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead, "mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source)
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart) w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- },
- {
- name: "boldByChar",
- match: "''",
- terminator: "''",
- element: "strong",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "strikeByChar",
- match: "==",
- terminator: "==",
- element: "strike",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "underlineByChar",
- match: "__",
- terminator: "__",
- element: "u",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "italicByChar",
- match: "//",
- terminator: "//",
- element: "em",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "subscriptByChar",
- match: "~~",
- terminator: "~~",
- element: "sub",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "superscriptByChar",
- match: "\\^\\^",
- terminator: "\\^\\^",
- element: "sup",
- handler: Wikifier.formatHelpers.charFormatHelper
- },
- {
- name: "monospacedByChar",
- match: "\\{\\{\\{",
- lookahead: "\\{\\{\\{((?:.|\\n)*?)\\}\\}\\}",
- handler: function (w) {
- var lookaheadRegExp = new RegExp(this.lookahead, "mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source)
- if (lookaheadMatch && lookaheadMatch.index == w.matchStart) {
- var e = insertElement(w.output, "code", null, null, lookaheadMatch[1]);
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- }
- },
- (Wikifier.styleByCharFormatter = {
- name: "styleByChar",
- match: "@@",
- terminator: "@@",
- lookahead: "(?:([^\\(@]+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:([^\\.:@]+):([^;\\|\\n]+);)|(?:\\.([^;\\|\\n]+);)",
- handler: function (w) {
- var e = insertElement(w.output, "span", null, null, null);
- var styles = Wikifier.formatHelpers.inlineCssHelper(w);
- if (styles.length == 0) {
- e.className = "marked";
- }
- else {
- for (var t = 0; t < styles.length; t++) {
- e.style[styles[t].style] = styles[t].value;
- }
- if (typeof styles.className == "string") {
- e.className = styles.className;
- }
- }
- w.subWikify(e, this.terminator);
- }
- }),
- {
- name: "lineBreak",
- match: "\\n",
- handler: function (w) {
- insertElement(w.output, "br");
- }
- },
- {
- name: "continuedLine",
- match: "\\\\\\s*?\\n",
- handler: function(a) {
- a.nextMatch = a.matchStart+2;
- }
- },
- {
- name: "htmlCharacterReference",
- match: "(?:(?:&#?[a-zA-Z0-9]{2,8};|.)(?:&#?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|&#?[a-zA-Z0-9]{2,8};)",
- handler: function(w)
- {
- var el = document.createElement("div");
- el.innerHTML = w.matchText;
- insertText(w.output, el.textContent);
- }
- },
- {
- name: "htmltag",
- match: "<(?:\\/?[\\w\\-]+|[\\w\\-]+(?:(?:\\s+[\\w\\-]+(?:\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)\\/?)>",
- tagname: "<(\\w+)",
- voids: ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"],
- tableElems: ["table","thead","tbody","tfoot","th","tr","td","colgroup","col","caption","figcaption"],
- cleanupTables: function (e) {
- var i, name, elems = [].slice.call(e.children);
- // Remove non-table child elements that aren't children of <td>s
- for (i = 0; i < elems.length; i++) {
- if (elems[i].tagName) {
- name = elems[i].tagName.toLowerCase();
- if (this.tableElems.indexOf(name)==-1) {
- elems[i].outerHTML = '';
- }
- else if (['col','caption','figcaption','td','th'].indexOf(name)==-1) {
- this.cleanupTables.call(this,elems[i]);
- }
- }
- }
- },
- handler: function (a) {
- var tmp, passage, setter, e, isvoid, isstyle, lookaheadRegExp, lookaheadMatch, lookahead,
- re = new RegExp(this.tagname).exec(a.matchText),
- tn = re && re[1] && re[1].toLowerCase();
- if(tn && tn != "html") {
- lookahead = "<\\/\\s*" + tn + "\\s*>";
- isvoid = (this.voids.indexOf(tn) != -1);
- isstyle = tn == "style" || tn == "script";
- lookaheadRegExp = new RegExp(lookahead, "mg");
- lookaheadRegExp.lastIndex = a.matchStart;
- lookaheadMatch = lookaheadRegExp.exec(a.source);
- if (lookaheadMatch || isvoid) {
- if (isstyle) {
- e = document.createElement(tn);
- e.type = "text/css"; // IE8 compatibility
- tmp = a.source.slice(a.nextMatch, lookaheadMatch.index);
- e.styleSheet ? (e.styleSheet.cssText = tmp) : (e.innerHTML = tmp);
- a.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- else {
- // Creating a loose <tr> element creates it wrapped inside a <tbody> element.
- e = document.createElement(a.output.tagName);
- e.innerHTML = a.matchText;
- while(e.firstChild) {
- e = e.firstChild;
- }
- if (!isvoid) {
- a.subWikify(e, lookahead);
- }
- }
- if (e.tagName.toLowerCase() == 'table') {
- this.cleanupTables.call(this,e);
- }
- // Special data-setter attribute
- if (setter = e.getAttribute("data-setter")) {
- setter = Wikifier.linkFormatter.makeCallback(setter);
- }
- // Special data-passage attribute
- if (passage = e.getAttribute("data-passage")) {
- if (tn != "img") {
- addClickHandler(e, Wikifier.linkFunction(Wikifier.parsePassageTitle(passage), e, setter));
- if (tn == "area" || tn == "a") {
- e.setAttribute("href", "javascript:;");
- }
- }
- else {
- Wikifier.imageFormatter.importedImage(e, passage);
- }
- }
- a.output.appendChild(e);
- } else {
- throwError(a.output,"HTML tag '"+tn+"' wasn't closed.", a.matchText);
- }
- }
- }
- }];
- // Optional - included if the ".char" selector appears anywhere in the story.
- Wikifier.charSpanFormatter = {
- name: "char",
- match: "[^\n]",
- handler: function (a) {
- // Line breaks do NOT get their own charspans
- insertElement(a.output, "span", null, "char", a.matchText).setAttribute("data-char", a.matchText == " " ? "space" :
- a.matchText == "\t" ? "tab" : a.matchText);
- }
- };
- Wikifier.parsePassageTitle = function(title) {
- if (title && !tale.has(title)) {
- try {
- title = (internalEval(this.parse(title)) || title)+"";
- }
- catch(e) {}
- }
- return title;
- };
- Wikifier.linkFunction = function(title, el, callback) {
- return function() {
- if (state.rewindTo) {
- var passage = findPassageParent(el);
- if (passage && passage.parentNode.lastChild != passage) {
- state.rewindTo(passage, true);
- }
- }
- if (title) {
- state.display(title, el, null, callback);
- }
- else if (typeof callback == "function") {
- callback();
- }
- };
- };
- Wikifier.createInternalLink = function (place, title, callback, type) {
- var tag = (type == "button" ? 'button' : 'a'),
- suffix = (type == "button" ? "Button" : "Link"),
- el = insertElement(place, tag);
- if (tale.has(title)) {
- el.className = 'internal'+suffix;
- if (visited(title)) el.className += ' visited'+suffix;
- }
- else el.className = 'broken'+suffix;
- addClickHandler(el, Wikifier.linkFunction(title, el, callback));
- if (place) place.appendChild(el);
- return el;
- };
- Wikifier.createExternalLink = function (place, url, callback, type) {
- var tag = (type == "button" ? 'button' : 'a'),
- el = insertElement(place, tag);
- el.href = url;
- el.className = "external"+(type == "button" ? "Button" : "Link");
- el.target = "_blank";
- if (typeof callback == "function") {
- addClickHandler(el,callback);
- }
-
- if (place) place.appendChild(el);
- return el;
- };
- // Functions usable solely by custom scripts
- // This includes restart(), above.
- function visited(e) {
- var ret = 0, i = 0;
- if (!state) {
- return 0;
- }
- e = e || state.history[0].passage.title;
- if (arguments.length > 1) {
- for (ret = state.history.length; i<arguments.length; i++) {
- ret = Math.min(ret, visited(arguments[i]));
- }
- }
- else for(; i<state.history.length && state.history[i].passage; i++) {
- if(e == state.history[i].passage.title) {
- ret++;
- }
- }
- return ret;
- }
- // Returns the number of times the player visited passages containing ALL
- // provided tags.
- // The tags can be several strings, or a single string with space-delimited tags.
- function visitedTag() {
- var i, j, sh, ret = 0, tags = Array.prototype.slice.call(arguments);
- if (tags.length == 1 && typeof tags[0] == "string") {
- tags = tags.split(" ");
- }
- if (!state) {
- return 0;
- }
- sh = state.history;
- for(i = 0; i<sh.length && sh[i].passage; i++) {
- for (j = 0; j < tags.length || void ret++; j++) {
- if(sh[i].passage.tags.indexOf(tags[j])==-1) {
- break;
- }
- }
- }
- return ret;
- }
- var visitedTags = visitedTag;
- function turns() {
- return state.history.length-1;
- }
- function passage() {
- return state.history[0].passage.title
- }
- function tags(e) {
- var ret = [], i = 0;
- if (!state) {
- return 0;
- }
- e = e || state.history[0].passage.title;
- if (arguments.length > 1) {
- for (i = arguments.length-1; i >= 1; i--) {
- ret = ret.concat(tags(arguments[i]));
- }
- }
- ret = ret.concat(tale.get(e).tags);
- return ret;
- }
- function previous() {
- if (state && state.history[1]) {
- for (var d = 1; d < state.history.length && state.history[d].passage; d++) {
- if (state.history[d].passage.title != state.history[0].passage.title) {
- return state.history[d].passage.title
- }
- }
- }
- return ""
- }
- // A random integer function
- // 1 argument: random int from 0 to a inclusive
- // 2 arguments: random int from a to b inclusive (order irrelevant)
- function random(a, b) {
- var from, to;
- if (!b) {
- from = 0;
- to = a;
- } else {
- from = Math.min(a, b);
- to = Math.max(a, b);
- }
- to += 1;
- return ~~((Math.random() * (to - from))) + from;
- }
- function either() {
- if (Array.isArray(arguments[0]) && arguments.length == 1) {
- return either.apply(this,arguments[0]);
- }
- return arguments[~~(Math.random()*arguments.length)];
- }
- function parameter(n) {
- n = n || 0;
- if (macros.display.parameters[n]) {
- return macros.display.parameters[n];
- }
- return 0
- }
- function bookmark() {
- return state.hash || "#";
- }
- /* Used to eval within Twine, but outside the context of a particular function */
- function internalEval(s) {
- // eval("{x:1,y:1}") fails miserably unless the obj. literal
- // is not the first expression in the line (hence, "0,").
- return eval("0,"+s);
- }
- /* Used to execute script passages */
- function scriptEval(s) {
- try {
- eval(s.text);
- } catch (e) {
- alert("There is a technical problem with this " + tale.identity() + " (" + s.title + ": " + e.message + ")."+softErrorMessage);
- }
- }
- /* Unload prompt */
- window.onbeforeunload = function() {
- if (tale && tale.storysettings.lookup("exitprompt",false) && state && state.history.length > 1) {
- return "You are about to end this " + tale.identity() + ".";
- }
- };
- /* Error reporting */
- var oldOnError = window.onerror || null,
- softErrorMessage = "You may be able to continue playing, but some parts may not work properly.";
- window.onerror = function (msg, a, b, c, error) {
- var s = (error && (".\n\n" + error.stack.replace(/\([^\)]+\)/g,'') + "\n\n")) || (" (" + msg + ").\n");
- alert("Sorry to interrupt, but this " + ((tale && tale.identity && tale.identity()) || "page") + "'s code has got itself in a mess" + s + softErrorMessage.slice(1));
- // Restore previous onerror
- window.onerror = oldOnError;
- if (typeof window.onerror == "function") {
- window.onerror(msg, a, b, c, error);
- }
- };
- /* Init function */
- var $;
- function main() {
- // Used by old custom scripts.
- // Cedes to jQuery if it exists.
- // Since jQuery is inserted after this script element,
- // wait until main() is called before doing this.
- $ = window.$ || function(a) {
- return (typeof a == "string" ? document.getElementById(a) : a);
- }
- var imgs, scripts, macro, style, i,
- styleText = "",
- passages = document.getElementById("passages");
-
- // Run checks after custom macros are installed
- function sanityCheck(thing) {
- var i, j, s = "NOTE: The " + thing,
- checks = { prerender: prerender, postrender: postrender, macros: macros };
- // Warn if prerender/postrender/macros aren't objects, and
- // prerender/postrender's own properties aren't functions.
- for (i in checks) {
- if (Object.prototype.hasOwnProperty.call(checks, i) && !sanityCheck[i]) {
- if (!checks[i] || typeof checks[i] != "object") {
- alert(s + " seems to have corrupted the " + i + " object."+softErrorMessage);
- sanityCheck[i] = true;
- continue;
- }
- if (i != "macros") {
- for (j in checks[i]) {
- if (Object.prototype.hasOwnProperty.call(checks[i], j)
- && typeof checks[i][j] != "function") {
- alert(s + " added a property '" + j + "' to " + i + ", "
- +"which is a "+typeof checks[i][j]+", not a function."+softErrorMessage);
- sanityCheck[i] = true;
- break;
- }
- }
- }
- }
- }
- }
-
- // Check for basic compatibility
- if (!window.JSON || !document.querySelector) {
- return (passages.innerHTML = "This " + tale.identity() + " requires a newer web browser. Sorry.");
- } else {
- passages.innerHTML = "";
- }
- // Initialise Tale
- tale = window.tale = new Tale();
-
- // Check for IE8 image compatibility
- if (~document.documentElement.className.indexOf("lt-ie9")) {
- imgs = tale.lookup("tags", "Twine.image");
- for (i = 0; i < imgs.length; i++) {
- if (imgs[i].text.length >= 32768) {
- alert("NOTE: This " + tale.identity() + "'s HTML file contains embedded images that may be too large for this browser to display."+softErrorMessage);
- break;
- }
- }
- }
- // Run all script passages
- scripts = tale.lookup("tags", "script");
- for (i = 0; i < scripts.length; i++) {
- scriptEval(scripts[i]);
- sanityCheck('script passage "'+scripts[i].title+'"');
- }
- // Need to create state now, since it's used by remember.init()
- state = window.state = new History();
- for (i in macros) {
- macro = macros[i];
- if (typeof macro.init == "function") {
- macro.init();
- sanityCheck('init() of the custom macro "'+i+'"');
- }
- }
- // Run all stylesheet passages
- style = document.getElementById("storyCSS");
- for (i in tale.passages) {
- i = tale.passages[i];
- if (i.tags.indexOf("stylesheet")==-1) {
- continue;
- }
- // No other tags?
- if (i.tags + "" == "stylesheet") {
- styleText += i.text;
- }
- else if (i.tags.length == 2 && i.tags.indexOf("transition") >-1) {
- setTransitionCSS(i.text);
- }
- }
- styleText = alterCSS(styleText);
- style.styleSheet ? (style.styleSheet.cssText = styleText) : (style.innerHTML = styleText);
-
- state.init();
- }
- setTimeout(function f() {
- var size, bar = document.getElementById("loadingbar"), store = document.getElementById("storeArea");
- if (!bar) {
- return;
- }
- if (store) {
- size = store.getAttribute("data-size");
- if (store.children.length <= size && !tale) {
- // +1 so that the bar can reach the end
- bar.style.width = ~~((store.children.length+1)/size*100)+"%";
- }
- else {
- bar.outerHTML = "";
- return;
- }
- }
- setTimeout(f,5);
- },5);
- /*
- **
- ** Sugarcane/Responsive specific code follows
- **
- */
- var hasPushState = !!window.history && (typeof window.history.pushState == "function") && (function(a) {
- // iOS Safari: setItem throws in private mode
- try {
- a.setItem("test", '1');
- a.removeItem("test");
- return true;
- } catch (e) {
- return false;
- }
- }(window.sessionStorage));
- Tale.prototype.canBookmark = function() {
- return this.canUndo() && !this.storysettings.lookup('hash') && (this.storysettings.lookup('bookmark',true) || !hasPushState);
- };
- History.prototype.init = function () {
- var a = this;
- if (!this.restore()) {
- if (tale.has("StoryInit")) {
- new Wikifier(insertElement(null, "span"), tale.get("StoryInit").text);
- }
- this.display("Start", null)
- }
- if (!hasPushState) {
- this.hash = window.location.hash;
- this.interval = window.setInterval(function () {
- a.watchHash()
- }, 250)
- }
- };
- hasPushState && (History.prototype.pushState = function(replace, uri) {
- window.history[replace ? "replaceState" : "pushState"]({ id: this.id, length: this.history.length }, document.title, uri);
- });
- History.prototype.display = function (title, source, type, callback) {
- var i, e, q, bookmark, hash, c = tale.get(title), p = document.getElementById("passages");
- if (c==null) {
- return;
- }
- if (type != "back") {
- this.saveVariables(c, source, callback);
- hash = (tale.storysettings.lookup('hash') && this.save()) || "";
- if (hasPushState && tale.canUndo()) {
- try {
- sessionStorage.setItem("Twine.History"+this.id, JSON.stringify(decompile(this.history)));
- this.pushState(this.history.length <= 2 && window.history.state == "", hash);
- } catch(e) {
- alert("Your browser couldn't save the state of the " + tale.identity() +".\n"+
- "You may continue playing, but it will no longer be possible to undo moves from here on in.");
- tale.storysettings.undo="off";
- }
- }
- }
- this.hash = hash || this.save();
- e = c.render();
- if (type != "quietly") {
- if (hasTransition) {
- for(i = 0; i < p.childNodes.length; i += 1) {
- q = p.childNodes[i];
- q.classList.add("transition-out");
- setTimeout((function(a) { return function () {
- if(a.parentNode) a.parentNode.removeChild(a);
- }}(q)), 1000);
- }
- e.classList.add("transition-in");
- setTimeout(function () { e.classList.remove("transition-in"); }, 1);
- e.style.visibility = "visible";
- p.appendChild(e);
- } else {
- removeChildren(p);
- p.appendChild(e);
- fade(e, {
- fade: "in"
- })
- }
- }
- else {
- p.appendChild(e);
- e.style.visibility = "visible"
- }
- tale.setPageElements();
- if (tale.canUndo()) {
- if (!hasPushState && type != "back") {
- window.location.hash = this.hash;
- } else if (tale.canBookmark()) {
- bookmark = document.getElementById("bookmark");
- bookmark && (bookmark.href = this.hash);
- }
- }
- window.scroll(0, 0)
- return e
- };
- History.prototype.watchHash = function () {
- if (window.location.hash != this.hash) {
- if (window.location.hash && (window.location.hash != "#")) {
- this.history = [{
- passage: null,
- variables: {}
- }];
- removeChildren(document.getElementById("passages"));
- if (!this.restore()) {
- alert("The passage you had previously visited could not be found.")
- }
- } else {
- window.location.reload()
- }
- this.hash = window.location.hash
- }
- };
- History.prototype.loadLinkVars = function() {
- for (var c in this.history[0].linkVars) {
- this.history[0].variables[c] = clone(this.history[0].linkVars[c]);
- }
- };
- Passage.prototype.render = function () {
- var b = insertElement(null, 'div', 'passage' + this.title, 'passage');
- b.style.visibility = 'hidden';
- this.setTags(b);
- this.setCSS();
- insertElement(b, 'div', '', 'header');
- var a = insertElement(b, 'div', '', 'body content');
- for (var i in prerender) {
- (typeof prerender[i] == "function") && prerender[i].call(this,a);
- }
- new Wikifier(a, this.processText());
- insertElement(b, 'div', '', 'footer');
- for (i in postrender) {
- (typeof postrender[i] == "function") && postrender[i].call(this,a);
- }
- return b;
- };
- Passage.prototype.excerpt = function () {
- var b = this.text.replace(/<<.*?>>/g, "");
- b = b.replace(/!.*?\n/g, "");
- b = b.replace(/[\[\]\/]/g, "");
- var a = b.split("\n");
- while (a.length && a[0].length == 0) a.shift();
- var c = '';
- if (a.length == 0 || a[0].length == 0) c = this.title;
- else c = a[0].substr(0, 30) + '...';
- return c;
- };
- Passage.transitionCache = "";
- Passage.prototype.setCSS = function() {
- var trans = false, text = "", tags = this.tags || [],
- c = document.getElementById('tagCSS'),
- c2 = document.getElementById('transitionCSS');
-
- if (c && c.getAttribute('data-tags') != tags.join(' ')) {
- tale.forEachStylesheet(tags, function(passage) {
- if (~passage.tags.indexOf("transition")) {
- if (!Passage.transitionCache && c2)
- Passage.transitionCache = c2.innerHTML;
- setTransitionCSS(passage.text);
- trans = true;
- }
- else text += alterCSS(passage.text);
- });
- if (!trans && Passage.transitionCache && c2) {
- setTransitionCSS(Passage.transitionCache);
- trans = false;
- Passage.transitionCache = "";
- }
- c.styleSheet ? (c.styleSheet.cssText = text) : (c.innerHTML = text);
- c.setAttribute('data-tags', tags.join(' '));
- }
- };
- var Interface = {
- init: function () {
- var snapback = document.getElementById("snapback"),
- restart = document.getElementById("restart"),
- bookmark = document.getElementById("bookmark");
- main();
- if (!tale) {
- return;
- }
- if (snapback) {
- if (!tale.lookup("tags", "bookmark").length) {
- snapback.parentNode.removeChild(snapback);
- } else addClickHandler(snapback, Interface.showSnapback);
- }
- if (bookmark && (!tale.canBookmark() || !hasPushState)) {
- bookmark.parentNode.removeChild(bookmark);
- }
- restart && addClickHandler(restart, Interface.restart);
- },
- restart: function () {
- if (confirm("Are you sure you want to restart this " + tale.identity() + "?")) {
- state.restart()
- }
- },
- showSnapback: function (a) {
- Interface.hideAllMenus();
- Interface.buildSnapback();
- Interface.showMenu(a, document.getElementById("snapbackMenu"))
- },
- buildSnapback: function () {
- var b, c = false,
- menuelem = document.getElementById("snapbackMenu");
- while (menuelem.hasChildNodes()) {
- menuelem.removeChild(menuelem.firstChild)
- }
- for(var a = state.history.length - 1; a >= 0; a--) {
- if(state.history[a].passage && state.history[a].passage.tags.indexOf("bookmark") != -1) {
- b = document.createElement("div");
- b.pos = a;
- addClickHandler(b, function () {
- return macros.back.onclick(true, this.pos);
- });
- b.innerHTML = state.history[a].passage.excerpt();
- menuelem.appendChild(b);
- c = true
- }
- }
- b = null
- if(!c) {
- b = document.createElement("div");
- b.innerHTML = "<i>No passages available</i>";
- document.getElementById("snapbackMenu").appendChild(b)
- }
- },
- hideAllMenus: function () {
- document.getElementById("snapbackMenu").style.display = "none"
- },
- showMenu: function (b, a) {
- if (!b) {
- b = window.event
- }
- var c = {
- x: 0,
- y: 0
- };
- if (b.pageX || b.pageY) {
- c.x = b.pageX;
- c.y = b.pageY
- } else {
- if (b.clientX || b.clientY) {
- c.x = b.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
- c.y = b.clientY + document.body.scrollTop + document.documentElement.scrollTop
- }
- }
- a.style.top = c.y + "px";
- a.style.left = c.x + "px";
- a.style.display = "block";
- addClickHandler(document, Interface.hideAllMenus);
- b.cancelBubble = true;
- if (b.stopPropagation) {
- b.stopPropagation()
- }
- }
- };
- window.onload = Interface.init;
- macros.back.onclick = function(back, steps) {
- var title;
- if (back) {
- if (tale.canUndo()) {
- window.history.go(-steps);
- return;
- }
- while(steps-- >= 0 && state.history.length>1) {
- title = state.history[0].passage.title;
- state.history.shift();
- }
- state.loadLinkVars();
- state.saveVariables(tale.get(title));
- state.display(title, null, "back");
- }
- else {
- state.display(state.history[steps].passage.title);
- }
- };
- window.onpopstate = function(e) {
- var title, hist, steps, i, s = e && e.state;
- if (s && s.id && s.length != null) {
- hist = recompile(JSON.parse(sessionStorage.getItem("Twine.History"+s.id)));
- if (hist) {
- steps = hist.length-s.length;
- }
- }
- if (steps != null) {
- state.history = hist;
- // Shift the position of history to match how far back we've gone
- while(steps-- >= 0 && state.history.length>1) {
- title = state.history[0].passage.title;
- state.history.shift();
- }
- state.loadLinkVars();
- state.saveVariables(tale.get(title));
- state.display(title, null, "back");
- }
- };
- testplay = "";
- }());
- </script>
- <script title="modules">
- </script>
- <style id="baseCSS">
- /* Sidebar */
- #sidebar {
- position: fixed;
- list-style: none;
- width: 12em;
- }
- #sidebar #title, #sidebar #credits {
- cursor: auto;
- }
- #sidebar #storySubtitle, #sidebar #storyMenu {
- display: block;
- }
- #sidebar hr {
- width: 5em;
- margin-left: 8em;
- height: 2px;
- color: #c0c0c0
- border: none;
- background: #c0c0c0;
- }
- .menu {
- position: absolute;
- display: none;
- z-index: 5;
- }
- /* Passages container */
- #passages {
- margin-left: 18.2em;
- position:relative;
- }
- /* Links */
- .passage a {
- color: #4d6ad8;
- }
- a.internalLink, a.externalLink, a.back, a.return, [data-passage], .menu div {
- cursor: pointer;
- }
- a.brokenLink {
- background-color: red;
- color: #000;
- }
- .marked {
- background-color: #f66;
- color: #000;
- }
- .marked[title] {
- cursor: help;
- }
- .passage li[data-bullet] {
- list-style-type: none;
- }
- .passage li[data-bullet]:before {
- content: attr(data-bullet);
- position: relative;
- left: -1em;
- }
- #storeArea {
- display: none;
- }
- #noscript {
- margin-left: 18.2em;
- font-size: 1.2em;
- font-weight: bold;
- }
- /* HTML4 compatibility */
- img {
- vertical-align:bottom;
- }
- @media screen and (max-width: 640px) {
- #sidebar {
- position: static;
- margin: 0 auto;
- padding: 0;
- }
- body #sidebar li {
- text-align: center;
- }
- #passages {
- min-height: 100vh;
- margin-left: 0em;
- }
- }
- #loadingbar {
- position:fixed;
- top:0;
- left:0;
- border-top: solid #4d6ad8 6px;
- transition: width 0.5s;
- }
- </style>
- <style id="defaultCSS">
- body {
- background-color: #000;
- color: #fff;
- font-family: Verdana,sans-serif;
- font-size: 62.5%;
- margin: 4em 15% 5% 5em;
- }
- #sidebar {
- left: 7.5em;
- margin: 0;
- padding: 0 1em 0 0;
- font: bold 1.1em Verdana,sans-serif;
- }
- #sidebar ul {
- padding: 0;
- }
- #sidebar li {
- color: #333;
- text-align: right;
- background-repeat: no-repeat;
- margin-bottom: 1em;
- line-height: 1.4em;
- list-style: none;
- }
- #sidebar li a {
- color: #333;
- text-decoration: none;
- }
- #sidebar li a:hover, #sidebar #title a:hover, #snapback:hover, #restart:hover {
- color: #fff;
- cursor: pointer;
- text-decoration: none;
- }
- #sidebar #title {
- font-size: 150%;
- }
- #sidebar #title, #sidebar #title:hover, #sidebar #title a {
- color: #999;
- }
- #sidebar #storySubtitle {
- font-size: 75%;
- }
- #storyAuthor {
- font-size: 50%;
- }
- #sidebar #storyMenu {
- line-height: 2.5em;
- margin-bottom: .5em;
- color: #999;
- cursor: auto;
- }
- #sidebar #credits {
- padding-top: 2em;
- font-weight: normal;
- font-size: 80%;
- }
- #sidebar #credits:hover {
- color: #333;
- }
- #sidebar #credits a {
- text-decoration: none;
- }
- #passages {
- border-left: 1px solid #333;
- padding-left: 1.5em;
- }
- .menu {
- background-color: #343434;
- color: #fff;
- opacity: .9;
- border: 1px solid #fff;
- text-align: left;
- font: 1.1em Verdana;
- line-height: 2em;
- }
- .menu div {
- padding: 0 .4em;
- }
- .menu div:hover {
- cursor: pointer;
- background-color: #fff;
- color: #343434;
- }
- .passage {
- font-size: 1.2em;
- line-height: 175%;
- margin-bottom: 2em;
- text-align: left;
- }
- .passage a {
- font-weight: bold;
- text-decoration: none;
- }
- .passage a:hover {
- color: #8ea6ff;
- text-decoration: underline;
- }
- .content > ul {
- padding-top: 1.3em;
- }
- .passage ul, .passage ol {
- margin-left: .5em;
- padding-left: 1.5em;
- }
- .passage li {
- margin-right: 6em;
- }
- .passage table {
- border-collapse: collapse;
- font-size: 100%;
- margin: .8em 1.0em;
- }
- .passage th,.passage td,.passage tr,.passage caption {
- padding: 3px;
- }
- .passage hr {
- height: 1px;
- }
- .passage center {
- max-width:50%;
- margin:auto;
- }
- .marked {
- margin-right: 12px;
- padding: 3px;
- }
- .disabled {
- font-weight: bold;
- color: #333;
- }
- @media screen and (max-width: 640px) {
- body {
- margin: 5%;
- }
- #sidebar {
- width:100%;
- margin: 0;
- border-bottom: 1px solid #333;
- }
- #passages {
- padding-top: 2em;
- border-left: 0;
- }
- }
- </style>
- <style id="transitionCSS">
- .transition-in {
- opacity:0;
- position:absolute;
- }
- .passage:not(.transition-out) {
- transition: 1s;
- -webkit-transition: 1s;
- }
- .transition-out {
- opacity:0 !important;
- position:absolute;
- }
- </style>
- <style id="storyCSS"></style>
- <style id="tagCSS"></style>
- </head>
- <body>
- <div id="loadingbar"></div>
- <ul id="sidebar">
- <li id="title" class="storyElement"><span id="storyTitle" class="storyElement"></span><span id="storySubtitle" class="storyElement"></span><span id="titleSeparator"></span><span id="storyAuthor" class="storyElement"></span></li>
- <li id="storyMenu" class="storyElement" style="display:none"></li>
- <li>---</li>
- <li><a href="javascript:;" id="restart">start over</a></li>
- </ul>
- <div id="snapbackMenu" class="menu"></div>
- <div id="passages">
- <noscript><div id="noscript">Please enable Javascript to play this story!</div></noscript>
- <style>
- #sidebar{display:none;}
- </style>
- </div>
- <div id="storeArea" data-size="18" hidden><div tiddler="deck of cards" tags="thing" twine-position="0,0"><<set $link = "[["+passage()+"]]">>\n//examining...//\n''a deck of cards'', dog-eared and held together with a rubber band that's about to snap\n\n<<if $loc is "edge of the cliff">>[[chuck it|goodbye][$inv.splice($inv.indexOf($link), 1)]]<<endif>>\n\n<<if previous() is "inv">>[[close|inv]] <<else>>[[take it|previous()][$inv.push($link); $pile.splice($pile.indexOf($link), 1);$new++]] or [[leave it|previous()]]<<endif>></div><div tiddler="lost keys" tags="thing" twine-position="0,0"><<set $link = "[["+passage()+"]]">>\n//examining...//\n''a set of lost keys'', worn and shiny\n\n<<if $loc is "edge of the cliff">>[[chuck it|goodbye][$inv.splice($inv.indexOf($link), 1); $trash.push($link)]]<<endif>>\n\n<<if previous() is "inv">>[[close|inv]] <<else>>[[take it|previous()][$inv.push($link); $pile.splice($pile.indexOf($link), 1);$new++]] or [[leave it|previous()]]<<endif>></div><div tiddler="crumpled bill" tags="thing" twine-position="0,0"><<set $link = "[["+passage()+"]]">>\n//examining...//\n''some crumpled bills'', that might be enough to get you a cup of coffee\n\n<<if $loc is "edge of the cliff">>[[chuck it|goodbye][$inv.splice($inv.indexOf($link), 1)]]<<endif>>\n\n<<if previous() is "inv">>[[close|inv]] <<else>>[[take it|previous()][$inv.push($link); $pile.splice($pile.indexOf($link), 1);$new++]] or [[leave it|previous()]]<<endif>></div><div tiddler="broken watch" tags="thing" twine-position="0,0"><<set $link = "[["+passage()+"]]">>\n//examining...//\n''a broken watch'', that doesn't really tell you anything\n\n<<if $loc is "edge of the cliff">>[[chuck it|goodbye][$inv.splice($inv.indexOf($link), 1)]]<<endif>>\n\n<<if previous() is "inv">>[[close|inv]] <<else>>[[take it|previous()][$inv.push($link); $pile.splice($pile.indexOf($link), 1);$new++]] or [[leave it|previous()]]<<endif>></div><div tiddler="fruit" tags="thing" twine-position="0,0"><<set $link = "[["+passage()+"]]">>\n<<if $fruit == 0>><<$inv.splice($inv.indexOf($link),1 )>><<endif>>\n//examining...//\n''<<if $fruit == 1>>a piece<<else>><<$fruit>> pieces<<endif>> of fruit'', from the tree that grows a little ways back from the cliff\n\n<<if $loc is "edge of the cliff">>[[chuck some|goodbye][$fruit--]]<<endif>>\n\n[[close|inv]]</div><div tiddler="StoryTitle" twine-position="0,0">a sandbox</div><div tiddler="StorySubtitle" twine-position="0,0">//--[[about]]//</div><div tiddler="StoryAuthor" twine-position="0,0">[[@modgethanc|http://twitter.com/modgethanc]]</div><div tiddler="StoryMenu" twine-position="0,0">[[inventory|inv]]<<if $new > 0>>(+<<$new>>)<<endif>>\n<<if not visited("under the tree")>><<else>>location: \n[[$loc]]<<endif>></div><div tiddler="StoryIncludes" twine-position="0,0">movement_test_items.tw</div><div tiddler="css" tags="stylesheet" twine-position="0,0">body, nav, #sidebar, #storyTitle, #storySubtitle {\n -webkit-touch-callout: none;\n -webkit-user-select: none;\n -khtml-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n cursor: default;\n}</div><div tiddler="about" twine-position="0,0">this is a sandbox for building a world model in twee. \n\nmain features are inventory, location tracking, object interactions.\n\nobjects have context-sensitive actions that depend on your location.\n\n[[close|previous()]]</div><div tiddler="inv" tags="container" twine-position="0,0"><<silently>>\n<<set $new = 0>>\n<<if ($fruit < 1) and ($inv.indexOf("[[fruit]]") != -1)>><<$inv.splice($inv.indexOf("[[fruit]]"),1 )>><<endif>>\n<<endsilently>>\n\n//inventory://\n<<if $inv.length == 0>>nothing.<<endif>>\s\n<<print $inv.join(", ")>>\n\n[[close|$loc]]</div><div tiddler="Start" tags="place" twine-position="0,0"><<nobr>>\n<<set $inv = []>>\n<<set $loc = passage()>>\n<<set $pile = ["[[deck of cards]]", "[[lost keys]]", "[[crumpled bill]]", "[[broken watch]]"]>>\n<<set $fruit = 0>>\n<<set $fruitRemaining = 8>>\n<<endnobr>>\nhey, you.\n\nlet's try something[[...|under the tree]]</div><div tiddler="under the tree" tags="place" twine-position="0,0"><<set $loc = passage()>>\n<<if $pile.length > 0>>under the fruit tree, there is a [[pile of objects]]. <<else>>it's neat and tidy under the fruit tree.<<endif>>\n\n<<if $fruitRemaining > 0>><<set $item = "[[fruit]]">>if you want, you can <<if $fruit == 0>>[[pick some fruit|passage()][$inv.push($item);$fruit++;$fruitRemaining--;$new++]].<<else>>[[pick some fruit|passage()][$fruit++;$fruitRemaining--;$new++]].<<endif>><<else>>the fruit tree is bare.<<endif>>\n\nthese sorts of things might prepare you to go to the [[edge of the cliff]].</div><div tiddler="pile of objects" tags="container" twine-position="0,0"><<if $pile.length > 0>> //examining...//\n\na pile of objects:\n<<set $item= "[[deck of cards]]">><<if $pile.indexOf($item) != -1>>* <<print $item>><<endif>>\s\n<<set $item= "[[lost keys]]">><<if $pile.indexOf($item) != -1>>* <<print $item>><<endif>>\s\n<<set $item= "[[crumpled bill]]">><<if $pile.indexOf($item) != -1>>* <<print $item>><<endif>>\s\n<<set $item= "[[broken watch]]">><<if $pile.indexOf($item) != -1>>* <<print $item>><<endif>>\s\n<<else>>//not much to do here...//<<endif>>\n[[close|$loc]]</div><div tiddler="edge of the cliff" tags="place" twine-position="0,0"><<set $trash = []>>\n<<set $loc = passage()>>\nthere's nothing of great interest at the edge of the cliff, so you might as well go back to standing [[under the tree]].\n\nif there's anything you want to throw away, though, this is a good place to [[do it|inv]].</div><div tiddler="goodbye" tags="messages" twine-position="0,0"><<if $inv.length > 1>>out into the abyss it goes. hope you weren't planning on getting it back.<<else>>with a quiet sigh of relief, you pitch the last thing you're holding into the abyss.<<endif>>\n\n<<if (previous() == "fruit") and ($fruit > 0)>>[[...|fruit]]<<else>>[[...|inv]]<<endif>></div></div></body></html>
|