Git Product home page Git Product logo

twine-specs's People

Contributors

klembot avatar tmedwards avatar videlais avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twine-specs's Issues

Twine 2 Story Formats

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:

  • name: (string) Optional. The name of the story format. (Omitting the name will lead to an Untitled Story Format.) Note that changing the name is not necessarily enough to get the Twine 2 UI to treat an edited story format as separate from the original format.
  • version: (string) Required, and semantic versioning (x.y.z, e.g., 1.2.1) is also required.
  • author: (string) Optional.
  • description: (string) Optional.
  • image: (string) Optional. The filename of an SVG image served from the same directory as the format.js file.
  • url: (string) Optional. The URL of the directory containing the format.js file.
  • license: (string) Optional.
  • proofing: (boolean) Optional (defaults to false). True if the story format is a "proofing" format; the distinction is relevant only in the Twine 2 UI.
  • source: (string) Required. An adequately escaped string containing the full HTML output of the story format, including the two placeholders {{STORY_NAME}} and {{STORY_DATA}}. (The placeholders are not themselves required.)

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.

Twine 2 HTML: Should `role` and `id` attributes be required for Story Stylesheet and Story JavaScript element encoding?

I introduced this problem four years ago, it looks like, but there is a difference between what the Twine 2 HTML specification states is a required attribute, type, and the example at the top of the document, which adds two more attributes for <style> and <script>.

The example, generated by Twine at the time and confirmed by me just now, shows role and id:

<tw-storydata>
  <style
    role="stylesheet"
    id="twine-user-stylesheet"
    type="text/twine-css">
  </style>
  <script
    role="script"
    id="twine-user-script"
    type="text/twine-javascript">
  </script>
</tw-storydata>

The Story JavaScript section only explicitly mentions the type attribute and value, text/twine-javascript. The same with Story Stylesheet and its type of text/twine-css.

Should (A) the spec explicitly include these attributes and values, since Twine generates them, or (B) some additional text be added to explain that tools may add other attributes as needed or wanted, but only type is explicitly needed?

[Twee] Extending the Twee format syntax.

There's been talk of extending the Twee format to allow for additional properties to be recorded—e.g. notably the story map coordinates in both Twine 1 & 2—since, at least, as far back as Twine 1.4 was still in development.

Let's discuss what extensions we'd like to see and, naturally, what syntax changes would be necessary to accommodate them.


  • Format name: Twee v3.
  • File extensions: .tw, .twee.
  • 100% compatibility with Twee v1 not required.
  • Retain the readability of Twee v1 as much as possible.
  • Encode the story and passage metadata as JSON. The story metadata should be pretty-printed—i.e., line-broken and indented. Passage metadata must be inline. Metadata decoding errors should be non-fatal warnings—i.e., discard the metadata and attempt to continue processing.
  • Story metadata attributes (current):
    • ifdb: (string, required) Maps to <tw-storydata ifid>.
    • format: (string, optional) Maps to <tw-storydata format>.
    • format-version: (string, optional) Maps to <tw-storydata format-version>.
    • start: (string, optional) Maps to <tw-passagedata name> of the node whose pid matches <tw-storydata startnode>.
    • tag-colors: (object of tag(string):color(string) pairs, optional) Indirectly maps to <tw-tag> nodes.
      • tag:color pairs: (string:string, optional) Maps to <tw-tag name>:<tw-tag color>.
    • zoom: (decimal, optional) Maps to <tw-storydata zoom>.
  • Passage metadata attributes (current):
    • position: (string, optional) Comma separated passage icon positional coordinates—e.g., 600,400.
    • size: (string, optional) Comma separated passage icon width and height—e.g., 100,200.
  • Passage header must be a single line and is composed of:
    • Double colon start token (::), which must start the line.
    • Name, which must directly follow the start token.
    • (optional) Inline tag block, which must directly follow the name.
    • (optional) Inline JSON metadata, which must directly follow either the tag block or, if the tag block is omitted, the name.
  • Compiler passages:
    • StoryTitle: The project's name. Maps to <tw-storydata name>.
    • Start: The default starting passage. May be overridden by the story metadata or compiler command.
    • StoryData: The story metadata passage. Must not be published to <tw-storydata>—i.e., the metadata should exist in one place.
  • Compiler tags:
    • script: Signifies that the passage contents are JavaScript code. Maps to the <script type="text/twine-javascript"> node.
    • stylesheet: Signifies that the passage content are CSS style rules. Maps to the <style type="text/twine-css"> node.
  • Within passage headers, passage and tag names must escape the optional tag and metadata block opening/closing metacharacters—i.e., [, ], {, }.
    • Encoding: The escapement mechanism is to prefix the escaped characters with a backslash—i.e., \. To avoid ambiguity, non-escape backslashes must also be escaped via the same mechanism—i.e., foo\bar yields foo\\bar.
    • Decoding: To make decoding more robust, any escaped character within a chunk of encoded text yields the character minus the backslash—e.g., \q yields q.
  • Author-use area.

NOTES: The above task list is not meant to be absolute. There are probably additional items that I'm not thinking of at the moment that should be on the list.

Twine 2 HTML Elements

Here's my first attempt at documenting HTML elements:


Twine 2 HTML

When writing to HTML, Twine 2 and other related tools like Twee compilers use specific elements when working with story data.

<tw-storydata>

All story data is stored within the nested elements of <tw-storydata>. Its properties define the metadata of a story.

  • name: (string) Required. The name of the story.
  • ifid: (string) Required. The IFID of the story.
  • format: (string) Optional. The story format used to create this story.
  • format-version: (string) Optional. The version of the story format used to create this story.
  • start: (string) Optional. The PID matching a <tw-passagedata> element whose content should be displayed first
  • tag-colors: (object of tag(string):color(string) pairs) Optional. Colors and associated tags
  • zoom: (decimal) Optional. The level of zoom

<tw-passagedata>

Each passage has its data stored in a <tw-passadata> element. Its properties describe its metadata.

  • pid: (number) Required. The Passage ID (PID)
  • name: (string) Required. The name of the passage
  • tags: (string) Optional. Any tags for the passage separated by a space.
  • position: (string) Optional. Comma-separated X and Y position of the upper-left of the passage when viewed within the Twin 2 editor
  • size: (string) Optional. Comma-separated width and height of the passage when viewed within the Twine 2 editor.

<script type="text/twine-javascript">

Any JavaScript saved as part of the story is kept within a single element with its type property set to text/twine-javascript. This will be executed upon story start.

<style type="text/twine-css">

Any CSS saved as part of the story is kept within a single element with its type property set to text/twine-css. This will be read and applied to the story upon start.

`ifdb` instead of `ifid`

In the StoryData part it says:

ifdb: (string) Required. Maps to <tw-storydata ifid>.

In the example, the property name is ifid. Seems likely ifdb is a typo.

Options=debug is missing

The options="debug" attr that's used to enable debug mode when using Test Play isn't specified here. h/t @webbedspace

Add it to twine-2-htmloutput-spec.md.

The intent is for the compiler to send options to the story, and no other options are currently in use.

twee-3: clashing passage headers and webkit pseudo-element selectors

As of now, spaces between components of the passage header are optional, as noted here:

NOTE: Each component after the start token may be preceded by one or more spaces for readability.

This brings up the following case:

:: Story Stylesheet [stylesheet]
body {
  color: red;
}
::-webkit-some-pseudo-element {
  /* this section is no longer read as a part of the stylesheet... This is new passage now. */
}

The above twee code fails to compile unless the ::-webkit-some-pseudo-element is prefixed by some other character (e.g. whitespace).

While this can be worked around by allowing an exception for the prefix ::-webkit-, making a space between the start token :: and the passage name mandatory would make things clearer and easier for writing tools.

Twee decompilers already do this, adding spaces between each of components, so, rather than having the spaces for readability, mandating them would potentially result in less ambiguous code.

[Twee] Twee Documentation

While we work (I hope) toward some sort of specification at some point, I am proposing creating documentation for Twee as it currently exists.

The following is a revised version of most current draft of the Twee entry in the Twine Cookbook and consists of information pulled from Tweego's documentation and off the Twine wiki.


Notation

The notation is written as a series of three parts for the header of each passage:

  • Sigil: Two colons (":") followed by a space
  • Passage Name: The name of the passage
  • Tags: Optional tags

The content of a passage continues until the next header of a passage is found or the input ends with at least a single empty line between passage headers.

Example Twee Notation:

:: Snoopy [dog peanuts]
Snoopy is a dog in the comic Peanuts.

:: Charlie Brown [person peanuts]
Charlie Brown is a person in the comic Peanuts

Special Passage Names

Some compilers understand and process certain keywords differently. The following is a common set of reserved passage names.

Start

The first passage.

:: Start
A beginning!

StoryTitle

The title of the story.

:: StoryTitle
A Named Story

StorySubtitle

The subtitle of the story.

:: StorySubtitle
The subtitle of this story

StoryAuthor

The author of the story.

:: StoryAuthor
John Smith

StoryMenu

In Twine 1.4.2, the StoryMenu passage coresponds to the menu that hovers in the upper-right corner of the page in the Jonah story format, or on the left side of the page in the Sugarcane story format.

:: StoryMenu
Content of the story menu!

StorySettings

Used to specify certain options and settings.

Twine 1.4.2 Settings:

  • Undo: enables the player to "undo moves." In Sugarcane, this means being able to use the Back button in the browser. In Jonah, this means being able to use the “Rewind to here” link, and being able to click links in previous passages.

  • Bookmark: enables the player to use the “Bookmark” link in Sugarcane and Jonah. On by default.

  • Hash updates: this causes the current passage's bookmark URL to be automatically placed in the player's browser address bar whenever they change passages. This is off by default because the URLs can become very long and ugly quickly.

  • Prompt before closing: If the player tries to reload or close the page, the browser will prompt for confirmation. This is useful for long games - it would be unfortunate if the player lost a lot of progress due to an idle key-press.

  • Don't use default CSS: This removes most of the CSS used by the story format, allowing CSS programmers to write their own stylesheet redesigns more easily. Off by default - but including the text “blank stylesheet” in a stylesheet will set it on automatically.

  • ROT13: obfuscates the story's HTML source to dissuade people from spoiling themselves by reading it. Off by default.

  • jQuery: include the library or not

  • Modernizr: include the the library or not

:: StorySettings
undo:on
bookmark:on
hash:on
exitprompt:on
blankcss:on
obfuscate:rot13
jquery:on
modernizr:on

StoryIncludes

Includes, "imports", other local or remote files during the HTML compilation process. In Twine 1.4.2, both Twine Story (.tws) and Twine Source (.twee) files can be used.

:: StoryIncludes
localfile.tws

UserStylesheet

Although not an official keyword in most compilers, stories converted into Twee, or those without an existing passage tagged with "stylesheet", will sometimes be given a passage with the name "UserStylesheet". In most cases, this will also have the tag "stylesheet".

In Twine 2, this passage is the equivalent of Story Stylesheet.

:: UserStylesheet[stylesheet]

UserScript

Although not an official keyword in most compilers, stories converted into Twee, or those without an existing passage tagged with "script", will sometimes be given a passage with the name "UserScript". In most cases, this will also have the tag "script".

In Twine 2, this passage is the equivalent of Story JavaScript.

:: UserStylesheet[stylesheet]

Special Tag Names

Most Twee compilers understand two common tag names, stylesheet and script. These are usually loaded and run from passages tagged with them in alphabetical order.

Stylesheet

Any additional or overriding CSS rules for the story.

:: UserStylesheet[stylesheet]

Script:

Any additional or overriding JavaScript code for the story.

:: UserScript[script]

Twee 3: Unique Passage Names

While Twine 2 actively prevents passages from having the exact same name, the Twee 3 Specification does not mention it.

I propose adding "unique" to the line for passage name under the Passage Header section. Something like the following:

Required passage name. This must be unique in the story.

Twee 3 spec: leading and trailing space in passage names

Looking over the spec, something that isn't mentioned is how to handle leading or trailing space in a passage name. I know it's not best practice to put either in a passage name, but people do (came up in discussion here) and I think the spec as it's currently written would cause that whitespace to be lost, and links to potentially break as a result.

Wondering if this is worth documenting in the spec or if there is a recommended workaround.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.