Skip to content

Twine 1.4.2#


Development program#

Fatal errors#

  • Now, building games in non-English locales should no longer get an encoding error caused by the built file's timestamp. Thanks to mth for assistance and Cab for the report.


  • The Story___ passages are no longer forbidden from being included via StoryIncludes.
  • The StoryIncludes passage is no longer broken on OS X.


  • Fixed buggy HTML importing for passages that have > symbols in their titles.
  • It is now possible to import from HTML files that use the SugarCube custom header.
  • Fixed imported images having the wrong MIME-type if their filename extensions were in all-caps (such as "tree.JPG").
  • Altered the MIME-type of imported fonts in ttf and otf format to "application/x-font-..." instead of "application/font-...". Also, unrecognised files are now "application/octet-stream". This shouldn't really change anything, but may improve browser support.

Story Map#

  • The position of passages created by right-clicking and selecting "New Passage Here" should be fixed.
  • Fixed passage names with full stops no longer failing to have incoming link arrows.
  • Selecting "New Passage" when a Start passage is missing no longer creates the "Start" passage, since it could be irritating for "partial .tws files" that are being used in a large StoryIncludes project.

Passage editor#

  • Passages with very long names no longer have the left half of their name scrolled out of the title text box when you initially edit them.
  • The passage editor now has a uniform tab width (set to 4 spaces).
  • Fixed a bug where HTML wouldn't be highlighted if its tag names or attribute names contained hyphens (e.g. <div data-tags="...">)

Game engine#


  • Built HTML files now have a UTF-8 byte-order mark. This should cause Dropbox to correctly transmit them with UTF-8 encoding instead of ASCII. Hooray!!
  • Fixed certain page elements (such as StoryTitle and StoryAuthor) not being drawn at the start of a test play build that begins at a non-Start passage.
  • Fixed the image preloader code, which didn't detect whitespace correctly, and thus prevented preloading images in HTML \<img> tags that had a space between "src" and "=".


  • You should now be able to put a ] character inside the link syntax (e.g. [[\<\<$obj[0].x>>|Passage name]]) and put a quoted ">>" inside the macro syntax (e.g. \<\<print "\<\<--cool-->>" >> ).
  • Shorthand \<\<display>>: variable default was causing $vars provided as arguments to mess up horridly. This should fix this.
  • Raw HTML entities (such as or \< or somesuch) are now correctly preserved, rather than being converted to their symbols during the build process.


  • Using Passage() instead of passage() in your code will no longer silently fail instead of producing an error message.
  • \<\<choice>>, \<\<button>> and \<\<textinput>> no longer incorrectly convert Twine operators in the text of the provided link to Javascript operators (e.g. \<\<choice [[not]]>> becoming \<\<choice [[!]]>>).
  • The undocumented clone() function has been updated to hopefully allow certain native objects to be cloned more effectively.
  • A number of macro error messages are a little clearer - displaying "$" instead of state.history[0].variables." when referring to the macro invocation.
  • Fixed a bug where certain objects were being passed by reference when used in a setter link - e.g. [[Link][$a = $obj]] caused $a and $obj to point to the same object, with changes to one altering the other.
  • Fixed a bug where object literals as shorthand \<\<display>> arguments wouldn't work at all.
  • Fixed a bug where multi-line string or object literals in \<\<set>> or \<\<print>> macros, etc., would not have Twine operators converted by Wikifier.parse() correctly.

History/Back Button#

  • Game history: Added a test for iOS Safari's private browsing mode, which does not disable sessionStorage but does reduce its quota to 0
  • making it hard to tell if it's actually usable. This causes the "couldn't save the state" alert to not pop up if you're playing in private mode.
  • The story state serialisation functions have been rewritten to allow basic Javascript functions stored in Twine variables to be decompiled and stored. Previously, using the Sugarcane back button or a bookmark would cause function variables to lose their value. (Of course, this relies on function decompilation, so bound functions and native functions' serialisation will silently fail. And, when recompiling them, their original scope is lost.)


  • Added Array.prototype.forEach(), Object.create() and Array.isArray() polyfills to the engine, allowing IE 8-compliant scripts to use them.
  • The engine now records the previous value of window.onerror, and restores it once the message has been displayed once.

New features#

Development program#


  • Added StoryInit, a special passage in which to put Twine macros that you want to run before every play - including Test Plays of specific passages. This is generally a more ideal place to put your initial \<\<set>> macros instead of the Start passage. Thanks to T. M. Edwards for pioneering this feature.

Error checking#

  • Added a very basic passage code error-checking system. When closing a passage, Twine will now report a few possible errors: not matching an \<\<if>> macro with an \<\<endif>>, using "=" instead of "is" in the \<\<if>> macro, misspelling "http://" in a link, and putting HTML \<script> tags in a script passage. (Less obvious errors can only be identified by your browser's Javascript engine, and will, as usual, only be identified at runtime.)
  • Also, when closing a passage, Twine will now offer to create new passages for each red link in the passage text. This potentially saves you having to create them yourself.
  • Also, when closing a passage, Twine will now offer to import all images, linked from URLs, into the story, and update the [img] references to match. Importing images is recommended because it saves you the bother of hosting the image files, keeps the story from breaking if your image hosting site is down, and allows you to host the HTML file on sites such as, which only allow single HTML files to be uploaded.
  • All of the above checks and helpers can be run from the "Verify All Passages" menu item in the Build menu, or the "Verify Passage" item in the passage editor's Passage menu.


  • Twine now tries to keep track of passages that aren't present in the file, but are included via the StoryIncludes feature (henceforth, "included passages"). Links to included passages are now mauve, and passages that link to included passages now have a mauve marker drawn on them in the Story Map.

Story Metadata#

  • Added a "metadata" option to the Story Menu, which lets you edit some data that is included in the final HTML file.
  • The "identity" specifies a noun to use for game interface dialog boxes (the restart confirmation, the error dialog, etc.) If left blank, then "game" will be used.
  • The "description" provides text to use for a HTML <meta> description element, which is often used by search engines etc. to provide a summary of the page. I've noticed that often Google will, at a loss to find the game content, display odd bits of the storeArea div as a page description in its search results, which is most definitely not a good look. Maybe this will fix things.


Story Formats#

  • Custom story formats can now supply a Python file, "", which lets various parts of the Twine development program be customised to match the features of the story format. See the base class, which your file should subclass, for details.

Game engine#


  • You can now use the inline syntax as a shorthand for the <span class="..."> HTML tag.
  • @@.robot;This is a robot-class span@@ is equivalent to <span class="robot">This is a robot-class span</span>.
  • You can also use it alongside style attributes: @@.robot;text-decoration:underline;This is a robot-class span with an underline@@
  • One bothersome fact about Twine up to now is that there's no real "bridge" between the basic Twine link's functionality and raw HTML. There was no convenient way to make a raw <a> link trigger a passage change. So, I've added a "data-passage" HTML attribute that you can put on HTML <a>, <img>, <map> and <area> tags.
  • <a data-passage="Distant woods">Some text</a> is equivalent to %%[[Some text|Distant woods]]%%, but allows you to add extra HTML attributes to the link, like "style".
  • <img data-passage="Trees"> is equivalent to %%[img[Trees]]%% - thus, you can now refer to imported images in HTML. (If you wish to make an image that links to a passage, put the <img> inside an <a> element.)
  • <area data-passage="Trapdoor" coords="..."> is how you can make an image map area link to a passage.
  • You can also attach data-passage to any other kind of tag to make it serve as a link, too: <span data-passage="Secret link">This looks like ordinary text</span>.
  • To simulate setter-links, you can also add a "data-setter" property, too. <span data-passage="Cellar" data-setter="$teeth += 2">Collect teeth</span>. Note that it does nothing without a data-passage attribute as well.
  • It should now be possible to supply variables to the image syntax, as an image passage name or URL - for instance, [img[$pictureName]].
  • Removed the quote-by-line [[syntax]], on the basis that a good number of people don't really want indenting that often, and would rather have greater-than signs as bullet points. The rest can rely on the indented block syntax (%%<<<%%) or HTML <blockquote> tags.

Generated HTML#

  • Passage links no longer have ID attributes that reveal the name of the passage they go to, allowing anyone to "cheat" by right clicking them and selecting "Inspect Element". This has been the case for every previous version of Twine, but not anymore!
  • Jonah: rewind links now have the class "toolbar-rewind" instead of "toolbar-rewind to here".

Default CSS#

  • Mobile Sugarcane layout: I've added a somewhat rudimentary media query to Sugarcane that converts the sidebar to a vertical header, using a minimum of alterations, when viewed on a 640px-width