{"_id":"@eit6609/storyteller","_rev":"11-457b13413b7317a30de5df6be0f11f2a","name":"@eit6609/storyteller","dist-tags":{"latest":"2.0.1"},"versions":{"1.0.0":{"name":"@eit6609/storyteller","version":"1.0.0","keywords":["epub","ebook","adventure","game","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.0","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"8c208b3b608c6860bd7cf876a58b7566a1fefacf","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.0.tgz","fileCount":135,"integrity":"sha512-1Pc53Mg5Xoi/WwobGUu0GOttIfmr2Q1losdicPl14vrzQu7iQHEamiYyie6liojdIJAVwvx7i8PEjZuCegXpCA==","signatures":[{"sig":"MEUCIQCuI7XT0zG8TqikIiplPrujl6bZ6AnI1wgbN7ubj0bxKgIgEFiK2q84/4txDGKatAETpFOA/WXjelIpqAs2xhIUEq8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1747559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelwCjCRA9TVsSAnZWagAAaj4P/2nvXHiP/pGdzJK2p8eP\nytLytZOzvRvc8DosL8JfnbQ7HzMuGlQon/5sTTYEsV+x4tThgYQxl/x3MJ1m\ndZ5TLD3XTeoi7Yz0+iF7x4ZHSu8Jghe8zoqPw3ZyYIqPWoUVZZy90ZUsN3Jr\n9HGxRf6DFBo1PdiF947KqY8tBkdhg+E4IeuQAdkgVcD2wpRMMpl/SMt+LtGl\n7AheWxW7RAhg/rwE/tBPw6uM6e7216S5/MlvaUJWIky8alCy0hmksm7MWVcF\nvY0/GMC+uGd5SuslRD0xPq5K/aiuMKFtUWMGRV2zVeQQjvxczo9z2QLfqPe5\nymumoe9Qh0F5/rlTov9OMhBdJ1z6rn9PeB2c8I7K1m3/MjoZKSySJc0VKecH\nsaPXJaroPYcSrgDhUrsEqJRfO22Fi9LdRDENXrXC1URAskiEHJfvaor+VB4e\nI8Ku11yO3PeC8vRvukU7Oj0IO5UR8or/A+y/ygpSbHJ8x5/ximcaQUyKj3hQ\nRkGmXpxGaN3aDFgLMlWhRI3Jgh6ZtR8TVb3adQFw6N/IxtnblIiBTfHWExUQ\n63k0mE912HT/JeRjKp7i6GQ1diW8AZmxxxAhRH0P5ql6yKXX+ooU9llfX1iS\nFbFwCDDVb7ygJ5V2RcGD7p+h3TyP/4p56mKxKWz133vy0BJBPmR3E1kDId1V\nC/ZH\r\n=hnuU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"50ca4d132591f66cd22bc827ccd4e2e3a1b155d9","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.0_1586954403357_0.23451402788241937","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"@eit6609/storyteller","version":"1.0.1","keywords":["epub","ebook","adventure","game","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.1","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"1fd51ec7113c4eae75f2d64caeb624dff1eaf711","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.1.tgz","fileCount":135,"integrity":"sha512-ECcLpw5jvrWbo4u9JS0OzYyxnPheBpXvmqCvK+eUWaFQ7V8JBbGlYwbSndLD75Y1q76/lzQyLCoosR0WkFVXFw==","signatures":[{"sig":"MEUCICFES/4xWWP4FaBmwy/dHLbLSH36mWsS1ExgV+hhpnRhAiEA9JI+v2IpzPG1Xa4ueBsJQyaMoCnhjkJDsZSX5+Y6PnY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1746563,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelwdQCRA9TVsSAnZWagAA/ycP+wU0HpEpdnpzr24PYkwX\nQrB1z2cBeIe0abVVdMfD5cljFSY60lcte622g5rr1mJGGhiyyw2KIJdTjk86\nrNWFDx0US/SHN5FuwwBMuoUwen/TNBqtBqoN/AJG80YiOBsjrYYmSr7wWM5N\nEaV9A6rSN9ed1NsvxjmaaM2aF/AezVbIYVlllDuC4AatBBjDmzdaCjQm+rdy\n904eozcHwHTyoeMoW9BMhjhNNjnrLdDkpecxQdeTiG7xXbWFknZIB13/ztt0\nV1ayBzfDX+p4Wf5/GVxw2MTjbtbQ9GAUQZddvysBAbcm6N7JITB2VnmRDyNz\nrxii0YsC7E+8Uydb5prsK/kjlVisUmbYX3ipQueH51PAZatCZhAkiCo2V1Jv\nWC3BpNyXSiksPp4cSIPaIxSGhEyxeQGiJi5iqBmzAKi5tHXxCkiZn9jQpsQ1\nYIRaGzaU7zmfYTAnrprih3FTE2IRIZ9TxY9PUy/Zf5TMMvZx56c19brOV5/Q\nMPA6x+x3jKqjMO2uYsYCy+CzuyRDP5gyKhh8yf7UfPvdSGl2sZK32IHwlIb7\nDXF4E2DUndxhm6Or9+6eQGPil8XyGjsgm8YtL5W7x+4W/ZOh6yWAhqlrFDoz\nb5bmy4wyqHXuSyRgfWpjpSeMM+5Ad3QYQRCE1nzdfpKtpCHqbhBadnbjQqLg\nD4mM\r\n=gsU6\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"da317ad9fcfdad0a289c5486a2eb2bc102c3a82f","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.1_1586956112238_0.23055515575466168","host":"s3://npm-registry-packages"}},"1.0.2":{"name":"@eit6609/storyteller","version":"1.0.2","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.2","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"eb1a63ce470c193e4098ba3b6e2abcba4cc6e48d","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.2.tgz","fileCount":1006,"integrity":"sha512-CJPpx6OMBTL22j83GwCW3k803sMoHUQ/HHPWwoEm06INo29UK6R6/osEay0ybOfoSfSV6pgEweIwtuR/21zJsA==","signatures":[{"sig":"MEUCIQCLpXso/dRIL4XtC1uZRo3IjGRBBt+qaXCl0g/2sswMAwIgCKljvVPC8McX17vJbhY8HZO8ghhE0se0WSs2ymJprsw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2558851,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelwoBCRA9TVsSAnZWagAABvcP/Rvfx2YwVdNhuSnR1sSp\nGxXCXyH8jIkRwsagTCyJYH10FBYoTzYcvJlDu6Thy4iaV/tKcmu3syurLR/u\nZvFp/WVChFa4EB2NNaY7/5YaFV88T5OcCWCBxBdfeIE6oR8etXZGqsvzFR94\nUH/gzImHcWChenv9MFdj2ZOuvDVBLd8dADJzKq9lGqEibcs1F9I8EHapufLd\nKaqIdUijpMZaUC+snLbvfuxaO/G21cKXoq+YnCenMLV+1a2Ok6dvbWf28vo4\nbbEvsW8uvqpQx1FSEbGx1dsfVXe4E7KXBxUAMPJoIx8wnoIrbEw0Ew92/rzf\nZslfmBBOyyMMkZ/ZPUJTr8TPlnSjNosmCaFAldeIgN2SoQdtAt8u/4pNqPIo\n8oc9LnCbP+4tpViFLu0T29HQiEAnSOKyrQDHeHFJpe7dNF1gollhWE1lgKMC\nsdIKVD8bBY4O7UlX/9zjZDJ2JH51/k2n8uSY59t965g+p1MYH12SAkaF0ZlP\nYUZCDdAFijDIZFkuP8laYpsj3/I6SZWVLTWNLDNZj+9oeqddtFEXaNwG3Cpr\nua9AAFkwuhDqFvu+DxHm4wVM0ed12cMopnstcx7Q9X6tJqGLOYqr3cWzXSRc\niZwDk5o0+A0XAwDgozpTQa3xYxnQH/8RUmxTaTtWfwi1LznQ25WsqcP8odVH\nS8vt\r\n=pdmw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"87b4e7bc0a3cce26f6dd37c84723e1484f614c6c","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.2_1586956800995_0.9834837997375732","host":"s3://npm-registry-packages"}},"1.0.3":{"name":"@eit6609/storyteller","version":"1.0.3","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.3","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"2f8b3646902f13b2e3202404134aa0bae0445d3c","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.3.tgz","fileCount":1000,"integrity":"sha512-fFUQ/PWWNYMuuAjwROEigzMuPve3cnQSkiG/nCsSNGMswloqcAQ3iCYXHZqXCNFxP322JcX6HjC3aPMAeg+Ecg==","signatures":[{"sig":"MEQCIEM8BnFQwdtJqPBVynbQRNJmdw45D+z4zUmlPbku83MIAiAOYr7G6x9aGMWMhjH2vhy3gZorKFyDPSVC0UpnzNATgQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1516948,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelwq3CRA9TVsSAnZWagAA8DIQAJ8pOji/+qUwRe8Sqpx+\n7MQWNInR6YAsmHuGzECCpP/eVsAudG3qh/ipWrYikPmX7tgamiGLpDqEfIzb\nxdXJqN5fBmwzNXwMXWfvkbNpZGU8aB+kHk9JqX8dDANvP/Ul14c81aYSFnKX\nOM7NnekUxtqw8nZZ5/cerr1K2Zav1tBH7NZIy3r3yz6MxYlHRyhjh5f9Yyao\nfnjsvTStxoipZkE9JfGymvQ4EInv+SRCueyEqvMTrlO8uLFpi12CsfuaN2jJ\npxgE/O4QJlVRT9OOXC+Sd8nu46dVTn3qTxRPoUoWcYmxQmS6N0BtHeKb+Hae\nTMVATrxmoRklVSzLJwclBPRYtOEKUha9KdX9FK2wSdCcWFyi/Cvd0DBvcRAF\nGUUORMalp0Cp+awF1IDh0OFgVuEOy2u/3FIoRw+vnO3fTd2OMihncwchFPDy\nKdYCZTEs8pTTU5nkbgY0QaDDVC+A8f8ilipXzesU/QH/7uJSfvwVgh6+JZ61\nsDz1PmSo1+f5adfpMc9L6foWBz3goDcVa8HuDSPk/GUYhhqsi4zcTgeDWtt9\nwZ0w+MPLAQ0owBeF1c0Y8efag6HPzQDC+08Xos9tbVefCbNuzm/Pkf3yJCmf\nY9Yw2YxuuWGhqgHJ6ekMgCcQc893YaVZj7bY0ih1YX86pS7c4H4rl7YhnKHa\nqAG1\r\n=24lH\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"e8c00e295149e06ae9a5278a0f67e4d9d9670c16","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.3_1586956982613_0.31440109439732233","host":"s3://npm-registry-packages"}},"1.0.4":{"name":"@eit6609/storyteller","version":"1.0.4","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.4","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"b8de751eec7affed04aebed2f7b6f099505f6501","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.4.tgz","fileCount":9,"integrity":"sha512-a3yntn8ieFv6OKqRamTFBMtIR7xnaRdyAEOdIIPjCT2fZWocSZI6GSpie4LAbnFPVbyUXvIH6XqzOCPI1/ZUjA==","signatures":[{"sig":"MEUCIAm0tcvZE6yeOZ1AUByhpRIrFFH4Xx+4KaEyKpvlJbfMAiEA/Q5IWvriUdR/04oQR9i9bL2fgYHzmhgOZ1yq4/Oyyfc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":29300,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelw1NCRA9TVsSAnZWagAAe6AP/12+SsZ0gZkE6clYeSeC\nH5spNcgdNhoV9x0AIyP29JMGD45Pa0bei/UfkRsdM8lGMTCjYHQ/2ESI4h1p\n2c8kmvXNp5cB5sGdV6R1kcpPFyx4Zv6TBM2QPQX64L03tKGXDk5vJ8i0xqod\na9qzCSJZ5JTp1OQLWbvqKu7AaSc4Lkt7ZR4QyKHEa5aPLXrGG2n7KXvBFDFl\n5yhCIBsAcaIRB7p3K6bvtsWE54FmEr5ZaKmtW8nMKUJdIHhUaVpk+l5yqJAc\nhzVoTjS/UX5s2o+ldJ+6UlTsNoBPjDs4OeiQ2lGOOC3TId+nJFqfFVZ5BmYu\nj3A8vd+RLhTvNuRZRijlHa2/mEmpxPskVlm1QNJN8KeNZsAIrroHZqDBbOZ+\nxf88Fzq6taYjMB9/QaHB199VNYxRPmttVvoXsKtk1YfxDi1MuANThJg9hkC9\nnYHU7wOyGso6/rI9YB/MMTQ+NeYBGi2L2Zths/tQYW0idQBOZ3qT/gGHuG2c\nu8Z/37lz5gm11zUy4stwewHl96TBuMNrPL2QvJXMrxNI8EEkjT9G/pVpXxTx\nG258iXx5MbC6H9wjCEgxclFUcfjZ/01QElpvKolQij45YNZ4Hp1T7RdNtN0E\nA3KHet6MHA/M7UK3okdpNC2vmNW9Y/U23qpULuE2JOlRUQz0IXgmkKTLx8cE\nwhpc\r\n=qlcl\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"095ccdbf92d4dc7ded52675fc5d7d9b5811392c3","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.4_1586957645419_0.7795205780819954","host":"s3://npm-registry-packages"}},"1.0.5":{"name":"@eit6609/storyteller","version":"1.0.5","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.5","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"2bd0c3019573525040c55548916ff217f08ef727","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.5.tgz","fileCount":10,"integrity":"sha512-JitIZoYXhqIWebPjW9/Dxbpw2Em5tMPpT9cfmMtteWiNs5WCWD0y5Q8/9gG9iVkRazaf1veuIugXd4v1e32idg==","signatures":[{"sig":"MEUCIQC8vnTYenjAURNHj1Vl3HbTvdoGQ/Aq7ISxQ/vLNhAyZAIgGyJEXDXmPw+qh1HpaVGn24WevoWTF+VbVEHF311HUko=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":29373,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelzCBCRA9TVsSAnZWagAABQEQAIwBX06fYNVuxtBCsApu\n+6fBErT+DNsrZ/MJWcflzvHVzDNNKZV1+6nnB1POKdCFCiEAi9rKKYT8YdDJ\nltnDjqTcnbHji64PgMR8rxJj3mN/FM/oO37S7aUjYSExSVBPzqTw4dk+Ex1y\nqb+5k58/gHb0TslK8n3Ma3iHjkcpu1d03oHvN/xig/rG5FcGY4EL6KJrp4d1\nrpRBVHjPQi5zn/Y0B6yOzWg/H/GlLgX71XqCDZcfynlXjq9h2tAZILivMbEV\nFlu6vCNpoNt93i2JnS/AwECiGbxX1OtCe04dGWH/DsAcI8ziD24G0O6303k0\nQFoFRf/eRMIekc8aPS45kyYfWVxlTlG4o8dBqRx456E739fkpJe0CEXY5i9B\naQMP0ZiGN7stjiPRa7ttMCBKnqIn8KWdBuu73ah9R0NyJE2mDCayjsRFP6a8\n6c/CXoDWt7AhcnXPzU1yXj9V0saYslRha2MUV6EuCOHgE8ufwrNN5Q73jMi+\nqmV9wWDxHuMqsfH1MrdYE+s2ojt6uQnP48WncOgThE9b7Z7tSGhHGcX98UuP\nUL8xkxEpDXI8fE1a5Uj1PX6z0c11R7Zz+uD6W/7bkwaRZFEdFqDHzSTyeCoW\nlFhATQ8Q93ZMn+IUSY+FOSom/UGoQpYqJwqqyhvBTzzTpi54n2vMk6nDDp/r\nAn1O\r\n=ibAW\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"629819ee151f7a8216ba8e2be589baaf388ea177","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.9.0","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.16.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.5_1586966657408_0.9639153952296811","host":"s3://npm-registry-packages"}},"1.0.6":{"name":"@eit6609/storyteller","version":"1.0.6","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.6","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"c3d91b7cf7d6143227ff499742797589c0a24435","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.6.tgz","fileCount":10,"integrity":"sha512-wy5oroF+trQ3SB/DVOiclRxGQ/WIhw5MAMfrMCvSJ3mfdC5eNI5Gj1+CzQj/+TxrVvQ4YPV2loeMww3rTRlBjA==","signatures":[{"sig":"MEQCIEVDBsqk090VxSpFLzy8jmx2XeTdQxnSb9JK5URbRn0iAiAgMlY+dZCEG4MXQAC3BlNLfQ8SJPhlUeXFn+Bp17TUUw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":30573,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6yLdCRA9TVsSAnZWagAAtvsQAKDnw4j5qnhjwZk24Jrg\nKS4blfMLkfsDTjDvkl2EcVBmgxDZazCYUTLObzzy3N2jD04jNLX3AyE1YZB0\nphYz9yzRsmn9+NINCP1LoW2jE8gXIETjj/YOG+8uWyfodFEGFvXTM3ks/VRd\nUp0vPGeC2amukLc3I3gV47jj67NxMdU7lR+b2AnpsUG92a6lK2GIRujcqhZ2\n021nSYnSGF8FpBtN4uc+YlaG7ywz6ODoz1NOianpettCPdhd3esQgJY0l4cS\nIqVTTsm9HwtBIWF2U9XcSSA/kY5I9I/Vv6F3hvFYrnquOTMlYOOX4MZuRdxQ\nPsu4oMsiBVX+cBc9ENJNHfEc17eWS0V/R8NMuCduiFtMqSJoCVMCglUlCkdp\nkKqLGrahVu/QtifVCv++iTHZ/7cgtSm5aaMFbuNfDtYnHVupEUFJYPzFP2CD\nsSyuQ0RK4eQft9dIXvQOCxKbqP4UyAALpAQJY5m4e9qFQSTnCvyvcd5kab6A\nlyMApWyBIKQDCszdcLeWe/Mx6/rWaWRqioGYX5ulrNPYPVjNuGei3VwTunqs\n0d/+iUJ+a3p3RgI8z8/mIwDXau1oXuLpIiAGvP2RdXK0lacCbMa74PETkGAo\n3gq1qUjh37C+QQFqKLdGPxs4prD31ie7q0HOPOiH6pH//J8kj5hbrvSd39Gb\nt+/c\r\n=4RRd\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"b4d9d1f719ebbad9395962287d0170b3a41a3d15","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.14.4","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"10.20.1","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.6_1592468189116_0.4680198953363557","host":"s3://npm-registry-packages"}},"1.0.7":{"name":"@eit6609/storyteller","version":"1.0.7","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@1.0.7","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"c227b8db38ee40fc7d8219b08f7ae3356684a3dc","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-1.0.7.tgz","fileCount":10,"integrity":"sha512-W5cTVh8a2XAV271cWPtSv1IA3uCl02n2wYJDC/o0fK99pRzLqVfNO7GFS0yqZuDBzhcxObfP1wvkoUSmyudh3w==","signatures":[{"sig":"MEQCIHwZfn66TKsdpFfGx7oogXiz96UWWF4VyTDYikVjtIzSAiBblt29OqLrKxwFgWOHMhVhFhcG249I+QZSDTkkHVWr1w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":31966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhLjw9CRA9TVsSAnZWagAAJV0QAJaxmTo4Ug3ck7UqBdMM\nTceBwMWrVLbWCi6FS4RjXIwfSQ+IA1vK11H+AZVyGLOMPBUR1naMamXyq+51\nG6b7qPAKzsKvK/jkWIThfCzAJlE32mTtl3e+a5Lar0ZBN745zKPc5vhUz4g3\nMa4epiLXwJ5+CrkJapphe+Jme42wgn3W0pLjZwumuVDTuvx3X0ohUSCG2e3h\nzYeVjGX660UVKLGWUSWwdCPUNWeM52H6tCgcn8wCAkp8bBgRGEuscBnTX1tO\nsDX94LQWzJ+GkBKPIu0ZKrBvteUCe5U2bYBX212LWsBdxSNMyL5hZEjz26WG\n3Z+cKTPSmtFV4AKABwRZSX85oy7+FTrh1STsH3AY5t/qpw4KD65Gh685aN5V\nxuu6L/ado14IRUPyiXvvtDAWm4KZglw4Gpj1L8/jPcctcvv70LSbAKXxuMAz\nIuqhQBCa7RMpKs0BUJA6FsJQEtyjBoZrQRhRzR7uQB2NsBNprh220vYbC0+3\n/xFTLEtyKQwHzAskvZ9YCzx/BmQa+r0gluxeIfkJ+FvYOdBb9eTrC1ycYpsD\n2X6Oho6xxh634qT8/hmJQ3tkWKRzt7cjnuxxMi8JxEOao7n0hUXWr5SW08eR\nYo6oay8/zu6vwqFppDuEfngtzi4Mvbjj915IrgqRnDh3X3o0PDHokQMRnkGh\nxzs3\r\n=R/yS\r\n-----END PGP SIGNATURE-----\r\n"},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"256fffafa2791d143b6ea6ae72d8ca557adb4a5b","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"7.18.1","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"14.16.0","dependencies":{"pug":"^2.0.4","lodash":"^4.17.10","marked":"^0.8.2","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.0.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_1.0.7_1630420028884_0.9987415372760742","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"@eit6609/storyteller","version":"2.0.0","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"license":"ISC","_id":"@eit6609/storyteller@2.0.0","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"homepage":"https://github.com/eit6609/storyteller#readme","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"dist":{"shasum":"40fde3fd6712a7903b4a18035fc7011523f9984a","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-2.0.0.tgz","fileCount":10,"integrity":"sha512-o/eOjRcqbGzJZqkIAR7VRnmRccz7cPV2gO4KUTWGgzEmFE6b+tf2J/54Ag4zwkvLrnbi6mkomUiQvZTO3dv8wg==","signatures":[{"sig":"MEUCIGAMJjL/BShxjFpuRQ4naMGh2dqo7NUuSlQbA/qr6z9RAiEAmEKkpYjb+HrSqsOPHNox6MuUAF9aEOQ7HUdHS1X7BdA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33796},"main":"src/generator.js","Author":"Dario Morandini","gitHead":"eff4a1382a7288d09f08b047c1489b6aa4f492e1","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"repository":{"url":"git+https://github.com/eit6609/storyteller.git","type":"git"},"_npmVersion":"6.14.18","description":"An interactive ebooks generator","directories":{},"_nodeVersion":"14.21.3","dependencies":{"ejs":"^3.1.8","pug":"^3.0.1","lodash":"^4.17.10","marked":"^4.0.10","@hapi/joi":"^16.1.7","@eit6609/epub-creator":"^1.1.0","@eit6609/markdown-templates":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^5.4.0","jasmine":"^2.5.2","istanbul":"^0.4.5","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","@eit6609/walker":"^1.0.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"_npmOperationalInternal":{"tmp":"tmp/storyteller_2.0.0_1771605546323_0.21565831817546832","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@eit6609/storyteller","version":"2.0.1","description":"An interactive ebooks generator","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"Author":"Dario Morandini","scripts":{"ci":"ENV=ci eslint src examples/**/code && ENV=ci istanbul cover --root src/ jasmine","cover":"ENV=test istanbul cover --root src/ jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.all.json","lint":"ENV=test eslint src examples/**/code","test":"ENV=test jasmine","test-integration":"ENV=test jasmine JASMINE_CONFIG_PATH=spec/support/jasmine.integration.json"},"repository":{"type":"git","url":"git+https://github.com/eit6609/storyteller.git"},"main":"src/generator.js","license":"ISC","devDependencies":{"@eit6609/walker":"^1.0.0","eslint":"^5.4.0","istanbul":"^0.4.5","jasmine":"^2.5.2","jasmine-core":"^2.5.2","jasmine-expect":"^3.6.0","jasmine-promises":"^0.4.1","jasmine-spec-reporter":"^3.2.0"},"dependencies":{"@eit6609/epub-creator":"^1.1.0","@eit6609/markdown-templates":"^1.0.0","@hapi/joi":"^16.1.7","ejs":"^3.1.8","lodash":"^4.17.10","marked":"^4.0.10","pug":"^3.0.1"},"gitHead":"78a5a52f4825ada29fa08384cf85ce3bd59562c7","bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"homepage":"https://github.com/eit6609/storyteller#readme","_id":"@eit6609/storyteller@2.0.1","_nodeVersion":"14.21.3","_npmVersion":"6.14.18","dist":{"integrity":"sha512-Fuecluo1V75fDN5N839ENOVATDffk4PepSIaG5y27s9W2llcakZHk5jEFpBCgkmrqlb/czrmaeY4/ByJfP7HhA==","shasum":"964fb7dac5b3ea5c38920828f24c91a6fcc71cd9","tarball":"https://registry.npmjs.org/@eit6609/storyteller/-/storyteller-2.0.1.tgz","fileCount":10,"unpackedSize":33870,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCPWL7dje8Z82qCzhxQTbbZMYuf3bJANJUGgLLzvU0w6wIgC0mfz4G4OFty8+8NkKHjOcGrzD2jsZt8Lw4F3oaJYQ4="}]},"_npmUser":{"name":"eit6609","email":"dario@morandini.org"},"directories":{},"maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/storyteller_2.0.1_1771607177699_0.5582965921953158"},"_hasShrinkwrap":false}},"time":{"created":"2020-04-15T12:40:03.289Z","modified":"2026-02-20T17:06:17.971Z","1.0.0":"2020-04-15T12:40:03.568Z","1.0.1":"2020-04-15T13:08:32.614Z","1.0.2":"2020-04-15T13:20:01.210Z","1.0.3":"2020-04-15T13:23:02.949Z","1.0.4":"2020-04-15T13:34:05.615Z","1.0.5":"2020-04-15T16:04:17.637Z","1.0.6":"2020-06-18T08:16:29.232Z","1.0.7":"2021-08-31T14:27:09.044Z","2.0.0":"2026-02-20T16:39:06.478Z","2.0.1":"2026-02-20T17:06:17.838Z"},"bugs":{"url":"https://github.com/eit6609/storyteller/issues"},"license":"ISC","homepage":"https://github.com/eit6609/storyteller#readme","keywords":["epub","ebook","adventure","game","text adventure","adventure games","if","interactive fiction","interactive ebook"],"repository":{"type":"git","url":"git+https://github.com/eit6609/storyteller.git"},"description":"An interactive ebooks generator","maintainers":[{"name":"eit6609","email":"dario@morandini.org"}],"readme":"# Storyteller, a generator of interactive ebooks\n\nStoryteller is a tool for the generation of game ebooks that, given\n\n* a set of XHTML templates representing the locations of the game\n* a class containing the data and implementing the actions of the game\n\ngenerates an ePUB containing all the possible situations of the game.\nThe player then plays the game by following the links.\n\nIt was inspired by [the Medusa compiler of Enrico Colombini](http://www.erix.it/medusa.html), which was used to create\nhis [Locusta Temporis](https://www.amazon.it/Locusta-Temporis-Enrico-Colombini-ebook/dp/B07DZ23VQP) interactive ebook.\n\nInstall it by running:\n\n    npm i @eit6609/storyteller\n\nAnd use it like this:\n\n```js\nconst Storyteller = require('@eit6609/storyteller');\n\nconst options = ...\nconst storyteller = new Storyteller(options)\nconst initialTemplateName = ...\nconst initialState = ...\nawait storyteller.generate(initialTemplateName, initialState);\n```\n\n## Why interactive ebooks?\n\nYou can find the details behind the idea in Colombini's\n[Interactive Fiction & ebooks: Designing puzzles for digital books](https://www.amazon.it/Interactive-Fiction-ebooks-Designing-italiano-ebook/dp/B07DZ3F71K), and an introduction in\n[the slides about Medusa from Lua workshop 2014](http://www.lua.org/wshop14/Colombini.pdf).\n\nWith an interactive ebook you don't need an engine to play the game, because the game has been pre-played by\nStoryteller. All you need is an ebook reader.\n\nSince there are ebook readers for every device you get the maximum portability.\n\nOf course there are some limitations in the design of the game:\n\n* the actions can be performed only by following links\n* you cannot use random generators or unlimited counters\n* you must avoid a combinatorial explosion\n\n[Interactive Fiction & ebooks](https://www.amazon.it/Interactive-Fiction-ebooks-Designing-italiano-ebook/dp/B07DZ3F71K)\ndeals thoroughly with these issues, however I give you some tips & tricks at the end of this document.\n\nThere are also some limits for the player:\n\n* the player must only follow the links and cannot navigate the book by freely turning the pages\n\nThis limitations notwithstanding, you can create amazing games.\n\nIf you try *Locusta Temporis* you won't believe your eyes. And it was created with Medusa, which is functionally\nequivalent to Storyteller.\n\nYou can find some example ePUBs in the [examples](#examples).\n\n## How does it work?\n\n### The state class\n\nThe logic of the game is implemented with a class that contains the state of the game and the methods to access and\nmanipulate the state.\n\nLet's see an example, that is included in the complete [examples](#examples):\n\n```js\nclass Hanoi {\n\n    static configure (config) {\n        Hanoi.config = config;\n    }\n\n    constructor () {\n        this.reset();\n    }\n\n    reset () {\n        this.pegs = [\n            new Peg(Hanoi.config.nDiscs),\n            new Peg(),\n            new Peg()\n        ];\n    }\n\n    getConfig () {\n        return Hanoi.config;\n    }\n\n    isFinished () {\n        return this.pegs[2].discs.length === Hanoi.config.nDiscs;\n    }\n\n    canMove (from, to) {\n        from = this.pegs[from];\n        to = this.pegs[to];\n        return from.discs.length > 0 && (to.discs.length === 0 || to.getTopDisc() > from.getTopDisc());\n    }\n\n    move (from, to) {\n        this.pegs[to].discs.push(this.pegs[from].discs.pop());\n    }\n\n}\n```\n\nIn this state class, the property `pegs` and the methods `getConfig()`, `canMove()` and `isFinished()` let you access\nthe state to display information and make decisions in the template.\n\nThe methods `reset()` and `move()` are modifiers, and will be used with the `goto()` function, explained later.\n\n### The templates\n\nThe pages of the ebook are generated by a set of XHTML templates, one for every location of the game.\n\nAfter many experiments with the most popular templating engines for Node.js, I have chosen:\n\n* [EJS](https://ejs.co)\n* [Pug](https://pugjs.org/api/getting-started.html)\n\nThere are many engines (the very popular [Handlebars](https://handlebarsjs.com) among others) but most\nof them make the call of methods on a class instance a nightmare.\n\nI have added **experimental** support for markdown templating by means of my\n[Markdown Templates](https://github.com/eit6609/markdown-templates) engine.\n\nLet's see an example of template:\n\n```pug\ndoctype 1.1\nhtml(xmlns='http://www.w3.org/1999/xhtml', xml:lang='en')\n    head\n        link(href=\"style-epub.css\", rel=\"stylesheet\", type=\"text/css\")\n        title The Tower of Hanoi\n    body\n        h3 The Tower of Hanoi\n        hr\n        p!= debug()\n        p.first The situation is:\n        ul\n            li Peg 1: #{state.pegs[0]}\n            li Peg 2: #{state.pegs[1]}\n            li Peg 3: #{state.pegs[2]}\n        if state.isFinished()\n            h1 YOU WIN!\n            br\n            p.first Want to #[a(href=goto((state) => state.reset())) play again]?\n        else\n            p.first Possible moves are:\n            ul\n                if state.canMove(0, 1)\n                    li #[a(href=goto((state) => state.move(0, 1))) 1 ==> 2]\n                if state.canMove(0, 2)\n                    li #[a(href=goto((state) => state.move(0, 2))) 1 ==> 3]\n                if state.canMove(1, 2)\n                    li #[a(href=goto((state) => state.move(1, 2))) 2 ==> 3]\n                if state.canMove(2, 1)\n                    li #[a(href=goto((state) => state.move(2, 1))) 3 ==> 2]\n                if state.canMove(2, 0)\n                    li #[a(href=goto((state) => state.move(2, 0))) 3 ==> 1]\n                if state.canMove(1, 0)\n                    li #[a(href=goto((state) => state.move(1, 0))) 2 ==> 1]\n            p.first Of course you can also #[a(href=goto((state) => state.reset())) restart the game].\n            p.first Or you may want to review the #[a(href=goto('start', (state) => state.reset())) instructions].\n        hr\n```\n\nAs you can see the accessors are used to display data:\n\n```pug\n            li Peg 1: #{state.pegs[0]}\n```\n\nand to make decisions:\n\n```pug\n                if state.canMove(0, 2)\n```\n\nThe modifiers are used in the links, with the `goto()` function, to perform actions:\n\n```pug\n                    li #[a(href=goto((state) => state.move(2, 0))) 3 ==> 1]\n\n            p.first Or you may want to review the #[a(href=goto('start', (state) => state.reset())) instructions].\n```\n\n### The generator\n\n#### Following the links\n\nStarting from a template and a state, the generator recursively follows all the links, generating all the possible\npages.\n\nThis is done with the `goto()` function, provided by the context of the template.\n\nYou can pass `goto()` a template name and/or a function (called *action*) that modifies the state. The action usually\njust calls a modifier method on the state.\n\nAs the action is optional, it is possible to change only the template (that is, the location) and keep the state as is.\n\nAs the template name is optional, it is possible to change only the state without changing the location.\n\n#### Generating the pages\n\nThe combination of a template and a state generates a page:\n\n    template + state = page\n\nTo keep track of the generated pages, every state instance is reduced to a *hash*, which is a human readable string that\nuniquely identifies the state instance.\nIt's a kind of compact JSON, that can deal also with the situations that are not handled by JSON, like circular\nreferences and the new data structures of ES6, Maps and Sets.\n\nA template name and a state hash uniquely identify a page:\n\n    template name + hash(state) = page key\n\nFor debug and learning purposes, you can use the `debug()` function inside a template to show the page key. Because the\nhash is human readable, it is a meaningful representation of the state. It can be very useful to understand why the\ntemplate engine has generated the page as it is.\n\n## API reference\n\n### The generator class\n\n#### `constructor(options?: object)`\n\nThese are the supported options:\n\n* `templatesDir`, string, required: the path of the directory containing the templates\n* `outputDir`, string, required: the path of the directory to use for the generated XHTML files. This directory is used\n  as input for the [ePUB creator](https://github.com/eit6609/epub-creator), so you can put in this directory any extra\n  file (images, stylesheets) that you need in the ePUB.\n* `metadata`, object, required, the options for the ePUB creator, with these properties:\n    * `title`, string, optional, default `Untitled`: the title of the ePUB\n    * `author`, string, optional, default no author: the author of the ePUB\n    * `language`, string, optional, default `en`: the language of the ePUB\n    * `description`, string, optional, default no description: the description of the ePUB\n    * `isbn`, string, optional, default no ISBN: the ISBN of the ePUB\n    * `tags`, array of string, optional, default no subjects: the subjects of the ePUB\n    * `cover`, string, optional, default no cover: a path relative to `outputDir` of an image that will become the cover\n      of the ePUB\n    * `filename`, string, required: the path of the generated ePUB\n* `templateEngine`, string, required, possible values: `ejs`, `pug`, `mt`: the template engine used to\n   generate the pages.\n* `debug`, boolean, optional, default `false`: if `true` the `debug()` function called in the templates will return the\n   page key, otherwise the empty string.\n* `contentBefore`, array, optional, default `[]`. Extra, static pages to insert into the generated ePUB before the\n   generated pages. The items of the array are objects with these properties:\n  * `fileName`, string, required. The path of the file relative to `outputDir`.\n  * `tocLabel`, string, optional. The label to use in the TOC. Leave it out if you don't want the page to be added to\n    the TOC.\n* `contentAfter`, array, optional, default `[]`. Extra, static pages to insert into the generated ePUB after the\n  generated pages. The items of the array are the same as `contentBefore`.\n\n#### `generate(initialTemplateName: string, initialState: object): promise`\n\nIt generates the ePUB given:\n\n* `initialTemplateName`:  the path of the initial template file, without the extension, relative to the `templatesDir`\n* `initialState`: the initial state instance\n\nIt returns a promise with no value.\n\n### The template context\n\nThese are the properties of the \"locals\" of the template engine.\n\n#### `state`\n\nIt is the current state instance, that can be used to call its accessors to display data and make decisions.\n\n#### `debug(): string`\n\nIf the `debug` option is `true`, this function returns the key of the current page, that is the template name and the\nstate hash, wrapped in a `<code>` element. Otherwise it returns the empty string. You can place its result wherever you\nlike in the templates to display the info, and then simply disable it by setting the `debug` option to `false` without\nmodifying the templates.\n\n#### `goto(templateName?: string, action?: function): string`\n\nThe purpose of this function is to ask the generator the URL of the page identified by the template name and the hash of\nthe state you get by applying the action to a copy of the current state.\nThe function returns the URL of the requested page, that can be used in the `href` of an `a` to create a link.\n\nThe parameters are:\n\n* `templateName`: the path of a template file, without the extension, relative to the `templatesDir`. It defaults to\nthe current template's name.\n* `action`: a function that receives a clone of the state as its only parameter and modifies it. It should return a falsy\nvalue unless it wants to replace the received state with a new one: in this case it should return the new state. This is\nhandy for complex games because it enables you to move through independent stages of the game. More about this later,\nin the *Tips & Tricks* section.\n\nWith this function you actually trigger the generation of the pages, because, if the requested page does not exist,\nthe generator creates an empty page and enqueues it for the build, that is the execution of the template with a clone\nof the state of the page. That execution could find and execute some `goto()` that could trigger the creation of new\npages, and so on.\n\n## Examples\n\nYou can generate the example ebooks by moving to the `code` folder and running the `main.js` script:\n\n    node main.js\n\nYou can change the debug options to `true` to see who (template + state) generated the pages.\n\nYou can inspect the generated XHTML files, they are in the `out` subdirectories.\n\nBut if you are lazy you can just download the generated ePUBs.\n\n### Goat, Cabbage & Wolf\n\nA classic puzzle!\n\nThere are three scripts:\n\n* `main-pug.js`, that uses the Pug (.pug) templates\n* `main-ejs.js`, that uses the EJS (.html) templates\n* `main-markdown.js`, that uses the experimental Markdown Templates (.md) templates\n\nThe generated ePUBs should be the same.\n\nYou can download the generated ePUBs here:\n\n* [pug](examples/goat-cabbage-wolf/code/goat-cabbage-wolf-pug.epub)\n* [ejs](examples/goat-cabbage-wolf/code/goat-cabbage-wolf-ejs.epub)\n* [markdown](examples/goat-cabbage-wolf/code/goat-cabbage-wolf-markdown.epub)\n\n### Desert Traversal\n\nA puzzle about managing scarce resources.\n\nYou can download the generated ePUB [here](examples/desert/code/desert.epub).\n\n### The Tower of Hanoi\n\nNot much of an adventure game, but I have loved this game when I learned about recursion and I think that it is a very\nneat example.\n\nYou can download the generated ePUB [here](examples/hanoi/code/hanoi.epub).\n\n## Tips & Tricks\n\n### Keep the state \"small\"\n\nThe golden rule to avoid combinatorial explosion is:\n\n> You must keep the state as empty as possible\n\nLet's see some examples.\n\n#### Be smart\n\nYou can implement a combination lock by using a simple boolean:\n\n* `true`: \"all digits right so far\"\n* `false`: \"at least one wrong digit\"\n\nThis way you won't need to handle the exponential number of cases.\n\nFor example, you can use this state:\n\n```js\nclass Safe {\n    constructor (combination) {\n        this.combination = combination;\n        this.ok = true;\n        this.index = 0;\n    }\n\n    choose (digit) {\n        this.ok = this.ok && String(digit) === this.combination.charAt(this.index);\n        this.index++;\n    }\n\n    isRight () {\n        return this.index === this.combination.length && this.ok;\n    }\n\n    isWrong () {\n        return this.index === this.combination.length && !this.ok;\n    }\n}\n```\n\nwith this template:\n\n```pug\ndoctype 1.1\nhtml(xmlns='http://www.w3.org/1999/xhtml', xml:lang='en')\n    head\n        link(href=\"style-epub.css\", rel=\"stylesheet\", type=\"text/css\")\n        title Open the Safe\n    body\n        h3 Open the Safe\n        hr\n        if state.isRight()\n            h1 YOU WIN!\n        else if state.isWrong()\n            h1 YOU LOSE!\n        else\n            p.first Choose digit ##{state.index + 1}:\n            ul\n                - for (let i = 0; i < state.combination.length; i++)\n                    li #[a(href=goto((s) => s.choose(i))) #{i}]\n        hr\n```\n\nThe generated pages will be only *n* (the correct combination) + *n* (all the possible wrong combinations), where *n* is\nthe length of the combination.\n\nWhy? Because what determines the number of pages are the possible values of the properties of the state, and they are\n2*n*:\n\n* 2 for `ok`\n* *n* for `index`\n\nFor the sake of precision, there are only 2*n* - 1 pages, because the state `{index=0,ok=false}` is not used.\n\n#### Consume objects\n\nAlmost every adventure game has a basket where the player can put the objects found around.\n\nHowever, keeping objects in the basket is very expensive, because you'll have 2 ^ *n* possible states if you need to\nkeep track of *n* objects.\n\nYou should prefer objects that get consumed, and drop them as soon as you can.\n\n#### Partition the game\n\nYou should partition the game in several independent stages, in order to reset the state when you finish one stage and\nenter another.\n\nYou should implement the different stages with different state classes, and then exploit the feature of the generator\nthat uses the new state returned by an action to make the transition from one stage to another.\n","readmeFilename":"README.md"}