{"_id":"@a-morphous/recital-stage-ink","name":"@a-morphous/recital-stage-ink","dist-tags":{"latest":"1.5.0"},"versions":{"1.5.0":{"name":"@a-morphous/recital-stage-ink","version":"1.5.0","description":"Parses a recital *.stage file into an ink story.","main":"dist/stage-ink.js","module":"dist/stage-ink.module.js","author":{"name":"Amorphous"},"bin":{"stage-ink":"dist/cli.js"},"license":"MPL 2.0","dependencies":{"@a-morphous/recital":"^1.2.0","@a-morphous/recital-ext-common-commands":"^1.1.0","minimist":"^1.2.6","smartypants":"^0.1.6"},"devDependencies":{"@a-morphous/test":"^1.0.0","esbuild":"^0.14.32"},"scripts":{"build":"node build","test":"test test/*.js","dryRun":"pnpm publish --dry-run","pub":"pnpm publish --access public"},"_id":"@a-morphous/recital-stage-ink@1.5.0","_integrity":"sha512-cXosKrildah/yxxgBTwKYJuEShksYvrgtcZ2fDUCkOOuTBHdsTKuTrPsGcZcFsiwDAvrYkbrOUx1pild70129g==","_resolved":"/private/var/folders/pd/2r2pf8ln2cv61g2b_k9fr5nc0000gn/T/3117ef12ad91a13c802a90068a49a6f8/a-morphous-recital-stage-ink-1.5.0.tgz","_from":"file:a-morphous-recital-stage-ink-1.5.0.tgz","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-cXosKrildah/yxxgBTwKYJuEShksYvrgtcZ2fDUCkOOuTBHdsTKuTrPsGcZcFsiwDAvrYkbrOUx1pild70129g==","shasum":"558f527d749692746c14eec62827abb902a75409","tarball":"https://registry.npmjs.org/@a-morphous/recital-stage-ink/-/recital-stage-ink-1.5.0.tgz","fileCount":51,"unpackedSize":258601,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH18sIyT8ByDEVLptRT62gZgKW3iIUVT6FXuvSMNNVwmAiB1vzsd9rczoLDkZbQVmkWke3LyuvL42V3IUIazhflv7A=="}]},"_npmUser":{"name":"amorphous","email":"84998015+a-morphous@users.noreply.github.com"},"directories":{},"maintainers":[{"name":"amorphous","email":"84998015+a-morphous@users.noreply.github.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/recital-stage-ink_1.5.0_1728206594540_0.06005178162271929"},"_hasShrinkwrap":false}},"time":{"created":"2024-10-06T09:23:14.449Z","1.5.0":"2024-10-06T09:23:14.774Z","modified":"2024-10-06T09:23:15.128Z"},"maintainers":[{"name":"amorphous","email":"84998015+a-morphous@users.noreply.github.com"}],"description":"Parses a recital *.stage file into an ink story.","author":{"name":"Amorphous"},"license":"MPL 2.0","readme":"# Stage Export to Ink\n\nConverts a Recital `.stage` file into an [Ink file](https://www.inklestudios.com/ink/), which can then be consumed by any Ink parser to make interactive narratives.\n\n## Usage\n\n### CLI\n\n```\nstage-ink input-file.stage -o outputfile.ink\n\n\tOptions:\n\t\t-v - outputs version number\n\t\t-o - output file (otherwise goes to stdout)\n\t\t-s - adds stats metadata to the ink file\n```\n\n### In JS\n\n```js\nconst stageToInk = require('@a-morphous/recital-stage-ink')\n\nconst defaultOpts = {\n\tsceneToStartOn: 'name-of-scene',\n\taddStats: false,\n}\n\nreturn stageToInk(fs.readFileSync('input-file.stage', 'utf-8'), defaultOpts)\n```\n\n## Basic Syntax\n\n### Follows Recital when possible\n\nScenes are converted into `knots`, and Recital fragments into `stitches`.\n\nSpecific metadata are converted into tags, and the rest wrapped up into a JSON object as a `META` tag, which can be parsed later.\n\nMeta tag rules are:\n\n- top-level keys are listed in all-caps, followed by `:` and the value\n- any nested content is converted into JSON and fit on one line.\n- any newlines get broken up, and put onto another tag with the same key\n\nFor example, the meta\n```\n#: passage\n+++\ntitle=\"Title\"\nlist = [\"one\", \"two\", \"three\"]\ndescription=\"This is a line\nwith a newline\"\n[map]\ntest=\"foo\"\n+++\n```\n\nshould convert into\n\n```\n=== passage ===\n# TITLE: \"Title\"\n# LIST: [\"one\", \"two\", \"three\"]\n# DESCRIPTION: \"This is a line\n# DESCRIPTION: with a newline\"\n# MAP: { test: \"foo\" }\n```\n\nall JSON will be without any newlines. \n\nTo get the meta back, read the tags and use `JSON.parse()` on the values.\n\n### Choices\n\nChoices are created as **wikilinks**, with the double bracket `[[]]`, with the id of the scene or fragment after the displayed text linked with `->` (note that this is exactly how [Twine's Chapbook](https://klembot.github.io/chapbook/) does its links), e.g. `[[This is a link text->Scene Name]]`\n\nBy default, they are also prepended with a `> `, though you can omit them for top-level choices. (However, you cannot omit them if you want to have any modifiers onto your choice)\n\nThe `>` can have a character or more after it to modify the choice:\n\n`>!` Makes the choice 'loud', meaning that the choice displays again in the response (note that this is Ink's default)\n\n`>+` Sticky choices are not hidden when chosen (if we loop back to a previous knot)\n\n`>.` are fallback choices, and don't get displayed normally, only showing up if all other choices have been exhausted.\n\n`>!+` you can combine sticky and loud choices.\n\n### Diverts\n\n...are used totally normally, since they don't need to be converted to anything else.\n\nPut a `->` in normal text to produce a divert.\n\n#### Auto-slugifying diverts\n\nSince Recital is less strict about the titles of scenes than Ink is, all diverts are `slugified`, or turned into ink-compatible forms, when compiling. \n\nThis means that knots, stitches, and diverts are all:\n* Converted to lowercase\n* stripped of non alpha-numeric characters\n* spaces get turned into underscores\n\nThis also means that, functionally, `name_of_knot` and `name of knot` _will point to the same knot_.\n\nHowever, this also means that there are a few **gotchas**:\n\n### Diverting to different stitches\n\nInk's syntax for diverting to a stitch for a different knot is as follows:\n\n```\n-> knot.stitch\n```\n\n`.` symbols are not allowed as Ink titles, so the conversion process will get rid of the `.` if there are any in the knot or stitch title. However, since we need `.` characters to remain consistent in the divert itself, the auto-conversion in diverts will **not strip `.` characters**, unless they're at the end of the knot title. So this:\n\n```\n-> Title with. a period in it.\n#: Title with. a period in it.\n```\n\n...will fail, since the knot will slugify to `title_with_a_period_in_it`, and the divert will slugify to `title_with.a_period_in_it`.\n\n#### Diverts as variables\n\nInk allows you to store a divert in a variable, and then divert to that variable later to go to the knot or stitch specified.\n\nHowever, stage-ink's auto-slugify feature might cause the variable name to be changed in the divert, which will break the story.\n\nTo avoid this, you can **escape hatch** the slugifying process. Any string that begins with `$` will not be changed except for stripping out the leading `$` in a divert or knot or stitch title. So, to make sure that your variable diverts are untouched, you can do\n\n```\nVAR current_scene = ->name of scene\n-> $current_scene\n```\n\n### Weaves\n\nAKA nested content.\n\nWeaves are created when a choice doesn't have a divert in it, and instead has text afterwards. By default, `>` is considered the top-level weave.\n\nEvery level of weaves adds an extra bracket. `>` is the top-level, `>>` is the second level, and you can continue nesting them.\n\n**Gathers** are created via prepending the line with `<`. Nested gathers add more brackets, e.g. `<<`.\n\nTo nest weaves, ink has you create multiple `*` marks. Recital instead nests `>` and `<` symbols. A nested choice looks like `>> [[this is a nested choice]]`\n\n### Glue\n\nGlue at the end of a line can be written as normal; Ink uses `<>`:\n\n```\nThis is glued <>\nto the next line.\n```\n\nHowever, you can't use this form to write glue at the beginning of a line, since `<>` is also used to define fragments. In that case, you use `$<>` to denote it as glue:\n\n```\nThis is glued\n$<>\nlike so.\n```\n\n(You can use `$<>` in a line too, if you want. E.g. `This is glued $<>`.)\n\n### Tunnels\n\nTunnels are written as they are in Ink: with a divert that ends in `->`, and then in the tunnel, with a double divert that has no endpoint `->->`. \n\nThe parser expects the divert after a tunnel to be on its own line. It probably works if it isn't, but will skip other parsing of that line.\n\nTunnels are auto-slugified like other diverts.\n\n## Basic Example\n\nSee the `/test/data/kitchen-sink.stage` for up to date versions.\n\nRecital File:\n\n```\n#: title\n+++\nmeta=\"This is some metadata\"\ntitle=\"Title\"\n+++\n\nThis is a passage.\n\n> [[Choice]]\n\tThis is the aftermath of that.\n\n> [[Choice2]]\n\tThis is the syntax for weaves.\n\n>! This is the syntax for Weaves.\n\n< gather the choices. No matter what you choose you end up here.\n\n  >> [[Nested Choice 1]]\n  >> [[Nested Choice 2]]\n\n  << nested gather.\n\n> [[Another Choice->divert]]\n> [[Last Choice]]\n\tYou can use ink diverts normally, since they don't need to be converted.\n\t-> divert\n< This works, right?\nThis is a passage.\n>! [[Loud choices are displayed again in the answer.]]\n\tAftermath 1.\n\t\n>+ [[Sticky choices are not hidden when chosen.]]\n\tAftermath 2.\n\t\n>. [[Fallback choice with text.]]\n\n< Gather it all up.\n\n>!+ [[You can combine all of those. For nested, the extra symbols go after the `>`]]\n\t-> fragments start stitches\n\n<> fragments start stitches\n\nFinal content\nEND\n\n<> divert\n\nHmmm.\nEND\n```\n## Storylets\n\nInk doesn't natively support [storylets](https://emshort.blog/2019/11/29/storylets-you-want-them/), but this exporter will produce tags and metadata to help mark passages for storylets, for use in engines further down the line.\n\n### How are Storylets formatted?\n\n* A scene with a flag `storylet=true` in the TOML frontmatter.\n* All the fragments in that scene are the storylets.\n* `stage-ink` will also generate a 'hub' stitch, which contains a `$hub` command _that needs to be handled in the parser running this ink story_. Ink doesn't natively have storylet support, so all storylets when displayed in the Ink editor will immediately end the story, or move on beyond the whole storylet section. \n\nThe generated stitch looks a bit like \n```\n// the hub is autogenerated, and should not be created regularly\n= _hub\nChoices go here...this pulls from existing data or a special `choices` fragment to give content every time there are choices.\n\n// it creates a specific command that the engine will then use\n// to populate the choices\n$HUB\n\n// to make the compiler happy. This end should never be reached.\n->END\n```\n\nWhen converted to ink, a `STORYLET` tag will be added to the knot.\n\n### $hub\n\n_Note: this functionality is not within the parser, and must be implemented in the engine that consumes the output Ink file._\n\nThe `$hub` command contains one argument, which is the title of the knot that starts that storylet section.\n\nWhen the hub command is reached, the engine MUST:\n\n1. stop moving forward in the story\n2. iterate through all the stitches (storylets) in the knot\n3. display to the player the choices that link to the storylets whose **prerequisites** are met:\n\t* the values in the storylet's `prereqs` field all evaluate to 'true'\n\t* the storylet has not been visited before, OR has a `persistent` field.\n\nOnce a choice is clicked, the engine should divert to that storylet.\n\n### Metadata\n\n* `label`: what the choice is called, or the title of the storylet if `title` doesn't exist\n* `title`: internal title of the storylet. Can be used to list it outside of choices. Distinct from `label` only for logistical purposes and can be ignored.\n* `description`: longer form description. Can be multiple lines.\n* `persistent`: boolean. If true, a storylet can be visited multiple times, even after it's been seen.\n\n### Prereqs\n\nCreated as an array, as eval'd statements. All statements in the prerequisites _must_ evaluate to true in order for the storylet to run.\n\nStatements in prereqs key off of global variables in ink.\n\n```\n<> \n+++\nprereqs=[\n\t\"started === true\",\n\t\"keys > 3\"\n]\n+++\n\n```\n\nIn Javascript, this would check to make sure that the ink global variables started and keys are set properly. See https://github.com/y-lohse/inkjs#getting-and-setting-ink-variables for how to make sure we fetch the variables from ink.\n\nThose are saved in the ink as tags that are a part of the stitch. See https://github.com/inkle/ink/issues/249#issuecomment-271532488\n\n### Variables\n\nInspired by https://klembot.github.io/chapbook/guide/state/the-vars-section.html\nThese are variables that are set immediately before or after the storylet is finished.\n\n(Note that you can do this as commands inside of the storylet as well.)\n\n`enter` is used to set logic when a storylet is entered. Like with prereqs, these are all eval'd strings, and are processed in order.\n\n```\n<>\n+++\nenter=[\n\t\"keys = 1\"\n\t\"started = true\",\n\t\"keys += 1\",\n\t\"success = Math.random() > 0.5\",\n\t\"use_ink_function = ink!my_ink_function(arg1, arg2)\"\n]\n+++\n\nkeys is 2 throughout this section.\n\n```\n\nYou can in fact use Ink's `VAR` syntax to set variables as well, which will use Ink functions (rather than JS ones)\n","readmeFilename":"README.md"}