iftechfoundation / twine-specs

Specs related to Twine
70 stars 5 forks source link

Twine 2 Story Formats #5

Closed mcdemarco closed 4 years ago

mcdemarco commented 5 years ago

Here's my first attempt at documenting story formats. It's a bit wordy.


Twine 2 Story Formats

Story formats are JavaScript files which are used by Twine 2 or other compiling tools to convert a set of passages and some accompanying metadata into an HTML file.

How they work

The tools create an HTML file by writing the story format's "source" into a new file, and replacing the appropriate placeholders in the source with the story's passages (including special passages) and metadata. The story passages and metadata are inserted into the final file within custom HTML tags (documented elsewhere).

Every story format includes code to extract the passage contents from these tags when the story "runs". Proofing and other utility formats often stop there, just reformatting the passage contents into the desired output, be it plain text for editing or some export format like Twee or JSON. For this reason proofing formats can be very short. For example, Paperthin, the proofing format built in to Twine 2, is under 1200 bytes, and only half of that is the CSS used to reformat the passages.

Playable story formats have additional code to parse the passage contents and display them as a story or game. The allowed passage content varies from story format to story format. For example, some story formats expect the story's text to be marked up using Markdown formatting, while others use wiki-style formatting. Playable story formats also include their own unique macro/scripting languages; to the extent that a story depends on scripting, it will need to be rewritten to use another story format's scripting language. The built-in Twine 2 playable story formats, Harlowe, Snowman, and SugarCube, differ significantly from one other. Proofing formats, on the other hand, are generally agnostic as to the intended playing format and can be used to proof stories written for most or all playable story formats.

Story format output is always HTML; formats whose intended output is not HTML (usually proofing formats that export to Twee or JSON) must use some workaround to extract the desired data type from that HTML.

Installation

Twine 2 story formats are generally hosted online, but they can also be loaded from the local filesystem into most Twine 2 versions. (See below for other compilers.) To add a story format to Twine 2, use its full URL, e.g., https://twinery.org/2/story-formats/snowman-1.3.0/format.js, or, for a local file, the file URI scheme, e.g., file:///Users/user/path/to/snowman-1.3.0/dist/format.js or file:///c:/path/to//snowman-1.3.0/dist/format.js. Spaces and other special characters should be escaped using percent encoding.

For compiling tools other than Twine 2, story formats are either built-into the tool or are loaded from the file system normally (without the need for file URIs).

Structure

In Twine 2 a story format is a single JavaScript file, usually called format.js.

The Wrapper

The story format JavaScript file consists of a single function call which takes the story format details as an argument (a JavaScript object):

window.storyFormat({
    "name": "Snowman",
    "version": "1.3.0",
    ...
});

While it is traditional to format the object as if it were JSON, this is not required.

The Keys

The following keys are found in most or all story formats:

TODO: Document what is enough to get the Twine 2 UI to treat an edited story format as separate from the original format (or file a bug for format overwriting in Twine 2). Also insert advice about escaping the source.

Twine 1 Story Formats

In Twine 1, story formats were always local, contained in a single HTML file (analogous to the source section of a Twine 2 story format) called header.html, with two wildcards "STORY", for the set of passages, and "STORY_SIZE", for the number of passages. The story format name was derived from the containing folder. License info and other supporting files could also be included in that folder.

The story formats built into Twine 1, Jonah, Responsive, and Sugarcane, were much more closely related to one another (and thus easier to switch between) than the major Twine 2 formats are. These story formats should no longer be used due to incompatibility with modern browsers. Instead, if Twine 1 must be used for some reason, a modern story format that also supports Twine 1 (most notably SugarCube) should be installed and used instead of the built-in formats.

videlais commented 5 years ago

Re: Installation

In some testing I've done, the online version of Twine 2 will not (as Chrome and Firefox prevent it) use the file:/// protocol to load story formats. The desktop version, however, will accept this.

(This could probably be fixed in the online version through loading the text file first and then attempting to execute a callback on it, but that is not how 2.3.3 handles it currently.)

Re: The Keys

It appears that Twine 2 will accept another story format of the same data as long as the version number does not match an existing story format of the same name and version. Changing to a minor version, for example Snowman with a version of "1.3.1", is considered different enough.

greyelf commented 5 years ago

re: Installation

You can use the file:// protocol if using the downloadable/local variation of the web-browser based release.

tapionx commented 5 years ago

@mcdemarco this documentation is really really useful, thanks a lot! I hope it gets included in the Twine official website soon.

videlais commented 5 years ago

New draft with some editing down of wording in first half and some very small technical editing for spacing in second half.

File: twine2storyformats.md.txt


Twine 2 Story Formats

Story formats are JavaScript files used by Twine 2 or other compiling tools to convert story and passage data into an HTML file browsers can read.

Introduction

Twine 2 and other tools create an HTML file by writing the story format's "source" into a new file through replacing the appropriate placeholders in the source with the story's passages and metadata using custom HTML elements (see Twine 2 HTML).

Playable Story Formats

Every story format includes code to extract the passage data from these elements when the story "runs." For example, some story formats allow a story to include Markdown while others might use wiki-style formatting. Playable story formats can also include their own unique macro and scripting functionality. The built-in Twine 2 playable story formats (Harlowe, Snowman, and SugarCube) differ significantly from one other in this way. They each understand their own programming "language."

Proofing Story Formats

Proofing and other utility formats are often much simpler. Instead of interpreting the contents of passages, these story formats reformat or analyze the HTML data. Tools to produce Twee or JSON output from Twine 2 HTML are part of this story format category, converting HTML into formats or presentation layouts.

Installation

Twine 2 story formats are generally hosted online, but they can also be loaded from the local filesystem into most desktop Twine 2 versions.

Adding Story Formats

To add a story format to Twine 2, use its full URL, e.g., https://twinery.org/2/story-formats/snowman-1.3.0/format.js, or, for a local file, the file URI scheme, e.g., file:///Users/user/path/to/snowman-1.3.0/dist/format.js or file:///c:/path/to//snowman-1.3.0/dist/format.js. Spaces and other special characters should be escaped using percent encoding.

For compiling tools other than Twine 2, story formats are either built-into the tool or are loaded from the file system normally (without the need for file URIs).

Structure

In Twine 2 a story format is a single JavaScript file, usually called format.js.

Wrapper

The story format JavaScript file consists of a single function call which takes the story format details as an argument (a JavaScript object):

window.storyFormat({
    "name": "Snowman",
    "version": "1.3.0",
    ...
});

While it is traditional to format the object as if it were JSON, this is not required.

Keys

The following keys are found in most or all story formats:

Story Format Versions

A new story format is considered different from other, loaded story formats if (A) the name is not the same as any currently installed or (B) if the semantic versioning is not the same as one with the same name currently installed.

Twine 2 does not allow installed story formats of the same version and name to be overwritten.

Twine 1 Story Formats

In Twine 1, story formats were always local, contained in a single HTML file (analogous to the source section of a Twine 2 story format) called header.html, with two wildcards "STORY", for the set of passages, and "STORY_SIZE", for the number of passages. The story format name was derived from the containing folder. License info and other supporting files could also be included in that same folder.

The story formats built into Twine 1, Jonah, Responsive, and Sugarcane, were much more closely related to one another (and thus easier to switch between) than the major Twine 2 formats are. These story formats should no longer be used due to incompatibility with modern browsers. Instead, if Twine 1 must be used for some reason, a modern story format that also supports Twine 1 (most notably SugarCube) should be installed and used instead of the built-in formats.

tmedwards commented 5 years ago

While it is traditional to format the object as if it were JSON, this is not required.

Strictly speaking, story formats were always supposed to be JSON-P, with the parameter to the function being an unstringified JSON chunk. It is, unfortunately, not because the value of the optional setup property was allowed to be a naked function due to confusion.

I think there's merit, as I've said before, in requiring the chunk to actually be JSON. It would be trivial to grandfather Harlowe's use of a naked function value, so that's no impediment. This is CK's (paging @klembot ) ball to run with or not, but there's no good reason to use an object literal and at least one good one, interoperability, to require JSON.

In Twine 1, story formats were always local, contained in a single HTML file (analogous to the source section of a Twine 2 story format) called header.html, with two wildcards "STORY", for the set of passages, and "STORY_SIZE", for the number of passages.

Actually, that's only true for Twine 1 ≥v1.4. Previous versions used two files—a header and a footer file, though the latter was optional—and did not use replacement targets. The bundled formats were also somewhat different and Responsive was not included.

I'm unsure the pedantry is necessary within the document, however, so maybe just nixing the "always" would stop my inner OCD from triggering.

These story formats should no longer be used due to incompatibility with modern browsers.

And bugs, can't forget those.

mcdemarco commented 5 years ago

Notes from a meeting:

mcdemarco commented 5 years ago

I've incorporated all the comments (I hope) as well as many of Dan's changes and checked it in marked as a draft. You can read it from the front page. Any restoration of my wordiness is not a rejection of Dan's shortening per se, but I did think a couple of points were lost in the edits that needed making.