UNPKG

imbroglio

Version:

a tool for making browser-based interactive fiction

248 lines (234 loc) 6.98 kB
// Generated by IcedCoffeeScript 1.8.0-d (function() { var $, assert, choiceChars, compile, error, hashchange, mkElem, mkText, newGame, prepare, quote, restore, stdlib, turn, _ref; choiceChars = 'abcdefghijklmnopqrstuvwxyz0123456789'; error = function(msg) { throw new Error(msg); }; assert = require('assert'); $ = require('jquery'); _ref = require('./compiler'), quote = _ref.quote, stdlib = _ref.stdlib, prepare = _ref.prepare; mkText = function(s) { return window.document.createTextNode(s); }; mkElem = function(tag, children, attrs) { var child, k, result, v, _i, _len; if (children == null) { children = []; } if (attrs == null) { attrs = {}; } result = window.document.createElement(tag); for (k in attrs) { v = attrs[k]; result.setAttribute(k, v); } for (_i = 0, _len = children.length; _i < _len; _i++) { child = children[_i]; if (child) { result.appendChild(child); } } return result; }; exports.compile = compile = function(src) { var firstPassage, passages, render; passages = {}; firstPassage = null; (function() { var lastPassage, m, re; re = /(?:^\s*\n?|\n\n)#\s*([^\n]*\S)\s*\n/g; lastPassage = null; while (m = re.exec(src)) { if (lastPassage) { lastPassage.endIndex = m.index; } lastPassage = { name: m[1], startIndex: re.lastIndex }; assert(!(lastPassage.name in passages), lastPassage.name); passages[lastPassage.name] = lastPassage; firstPassage || (firstPassage = lastPassage); } if (!lastPassage) { error('no passages found'); } lastPassage.endIndex = src.length; })(); (function() { var k, v, _fn; _fn = function() { v.src = src.substring(v.startIndex, v.endIndex); v.mungedSrc = v.src.replace(/\[\[([^\]]*)\]\]/g, function(outer, inner, index) { var m, offset, target, text; offset = index + v.startIndex; text = target = inner; if (m = /^(.*)->\s*([^<>]*[^\s<>])\s*$/.exec(inner)) { text = m[1]; target = m[2]; } else if (m = /^\s*([^<>]*[^\s<>])\s*<-(.*)$/.exec(inner)) { target = m[1]; text = m[2]; } if (!(target in passages)) { error("bad link target '" + target + "' at " + outer + ", passage " + k + ", offset " + offset); } return "#\{imbroglio.mkLink " + (quote(target)) + ", " + (quote(text)) + "}"; }); v.prepared = prepare(v.mungedSrc, { argNames: ['imbroglio'], thisVar: 'imbroglio.state', handleError: function(e) { console.log(e); if (e.error instanceof Error) { throw e.error; } else if (e.error) { return error(e.error); } else { return error(e); } } }); }; for (k in passages) { v = passages[k]; _fn(); } })(); render = function(passage, result) { var linkCount, links, mkLink, moves, state, stateJSON; if (result == null) { result = {}; } moves = result.moves || (result.moves = ''); links = {}; linkCount = 0; mkLink = function(target, text) { var choiceChar, el; if (linkCount >= choiceChars.length) { error("too many links, passage " + passage.name + ", target [" + target + "], text [" + text + "]"); } choiceChar = choiceChars[linkCount++]; el = mkElem('a', [mkText(text)], { "class": 'choice', href: "#!" + moves + choiceChar }); links[choiceChar] = { el: el, target: target }; return el; }; state = JSON.parse(result.stateJSON || '{}'); result.passageElem = passage.prepared(stdlib({ mkLink: mkLink, state: state })); stateJSON = result.stateJSON = JSON.stringify(state); result.choose = function(ch) { var link; if (!(link = links[ch])) { console.log("invalid move " + ch + " from passage " + passage.name); return null; } return render(passages[link.target], { moves: "" + moves + ch, chosenElem: link.el, stateJSON: stateJSON }); }; return result; }; return function() { return render(firstPassage); }; }; newGame = turn = null; restore = function(moves) { var $output, $p, ch, last, prevTurn, _i, _len, _ref1; if ((turn != null ? turn.moves : void 0) === moves) { return; } $('#loading').show(); $('.pane').hide(); $('#game').hide(); $output = $('#output'); if (!turn) { turn = newGame(); $output.empty(); $output.append(turn.passageElem); } else { last = function() { var children; children = $output.children(); if (children.length) { return $(children.get(children.length - 1)); } else { return children; } }; while (turn.moves !== moves.slice(0, turn.moves.length)) { last().remove(); turn = turn.prevTurn; } last().find('.chosen').removeClass('chosen'); } _ref1 = moves.slice(turn.moves.length); for (_i = 0, _len = _ref1.length; _i < _len; _i++) { ch = _ref1[_i]; prevTurn = turn; if (!(turn = turn.choose(ch))) { $('#404-pane').show(); $('#loading').hide(); return; } turn.prevTurn = prevTurn; $(turn.chosenElem).addClass('chosen'); $output.append(turn.passageElem); } $('#game').show(); $('#loading').hide(); $p = $(turn.passageElem); window.scrollTo(0, $p.offset().top); }; hashchange = function() { var hash, m, target; hash = window.location.hash.replace(/^#/, ''); if (m = /^!(.*)$/.exec(hash)) { return restore(m[1]); } turn = target = null; if (m = /^\/([a-z][a-z-]*)$/.exec(hash)) { target = $("#" + m[1] + "-pane"); } if (!(target != null ? target.length : void 0)) { target = $('#home'); } $('#game').hide(); $('#output').empty(); $('.pane').hide(); target.show(); $('#loading').hide(); window.scrollTo(0, 0); }; exports.start = function(src) { newGame = compile(src); return $(function() { (function() { var m, _ref1; m = /([^\/]+)$/.exec(((_ref1 = window.location) != null ? _ref1.pathname : void 0) || ''); if (m) { $('a[href="#"], a[href="#/"]').attr('href', m[1]); } })(); $(window).on('hashchange', function(e) { e.preventDefault(); hashchange(); return true; }); hashchange(); }); }; }).call(this);