A twine like interactive fiction engine, written for my game The Library
Woven provides a clean syntax somewhat inspired by LaTeX, and a set of neat macros to help you make your story interactive.
That being said Woven is brand new, written by a single, somewhat inexperienced developer. There are going to be bugs.
To use the library engine you will need node JS, the yarn packagemanager and the typescript compiler.
- NodeJS can be installed installed from here, or installed via a package manager if you are on a linux/bsd.
- Yarn can be installed from here
- Install typescript with yarn
yarn global add typescript
- Clone the repo and run
yarn install
To compile the system run tsc
Note that you may have to add the yarn bin directory to your PATH
variable.
To compile a story from the command line run node cli.js <story file> <output html file>
Woven stories are made up of sections. Sections can be navigated to or included within other sections. When loaded, woven automatically attempts to display the section called main.
Sections are the basic building blocks of Woven stories.
\section(name[, anguments]) { text }
Sections can optionally take arguments which can then be used with \if
\else
and \print
to determine
how the text will be rendered. Note that section arguments are interpreted by javascript, meaning that strings
need to be enclosed with quotes. Note: only single quotes are supported, double quotes will break the system.
\section(main) {
Welcome to the main section
\nav(sectionTwo, 'amazing!') { Continue }
}
\section(sectionTwo, look) { You look \print(look) }
When the user presses continue, the program will output You look amazing!
\title(text)
Title sets the title of the story that will display in the browser's tab header.
Navigate to a new section I.E., replace what is currently on the screen.
\nav(sectionName[, arguments]) { link text }
Showing a section adds it to the currently visible text. There are two show macros. \show-reveal
which appends
the linked section below the link text, and \show-replace
which replaces the link text with the section.
\show-reveal(sectionName[, arguments]) { link text }
\show-replace(sectionName[, arguments]) { link text }
Set a variable. Variables in Woven are global by default meaning they are persistent throughout the story until the user
refreshes the page. Variables are interpreted by the page Javascript so text must be enclosed in quotes like so text
.
When a set macro is used within a \section
block, it will execute when that section is visited. If \set
is called
outside of a section it will be called when the story is loaded.
Note: Inside sections you can place \set
statements within \if
or \else
blocks. The variable will only be set if
the conditions of the if or else are met.
\set(variableName = value)
\set(name = 'Joey')
\set(count = 0)
\set(count = count + 1)
Output the contents of a variable
\print(variable)
Adds the content of a section into another.
\include(sectionName[, arguments])
Display an image
\image(url, height, width, alt)
The url can be a relative or absolute URL. Height and width can be specified as px
I.E., 200px
or other CSS units.
auto
may also be used I.E., \image(example.org/image, 200px, auto, alt text)
Display a block of text under a certain condition. Conditions are evaluated as Javascript, so
the ==
operator is used to check if values are equal. Text must be enclosed in single quotes.
You can set variables within if statements.
\if(condition) { text }
\set(doorUnlocked = true)
\if(doorUnlocked == true) { The door creeks open! \set(doorOpened = true) }
Display a block if a condition is not true. An else macro must follow a corresponding \if
macro.
\else { text }
The choices macro allows you to provide the user with a set of choices, only one of which may be selected.
\choices { \choice-reveal(section[, arguments) { Choice text } }
A choices block may contain any number \choice-reveal
, \choice-replace
and \choice-nav
macros. These
macros are nearly identical to\show-reveal
, \show-replace
and \nav
. The only difference is that when
a choice is clicked the other choices disappear.
\section(main) {
\choices {
\choice-reveal(win) { Pick heads }
\choice-replace(lose) { Pick tails }
\choice-nav(doNothing) { Do nothing }
}}
\section(win) { You win! }
\section(lose) { You lose! }
\section(doNothing { This option disappears when you pick heads or tails }
The \input
macro takes input from the player and assigns it to a variable.
\input(type, variable[, placeholder])
The input type parameter determines the input type. This can be any HTML5 input type; however, for most uses
text
or number
will probably be what you want to use. variable
determines the name of the variable the
output will be set to, and optionally placeholder determines text that will be shown as a placeholder when the
input box is empty.
Note: variable updates do not take effect on sections that are already visible. They only effect new sections as they are displayed.
\section(main) {
\input(text, textVariable, enter some text)
\nav(sectionTwo) { onwards }
}
\section(sectionTwo) { \print(testVariable) }
In this example, the text the user entered into the input box will be displayed when the click onwards and sectionTwo is displayed.
You can add custom styling to your stories with \style
.
\style { CSS code }
When used within a section, \style
will only change the CSS for as long as that section is visible. When used outside
a section, the CSS will be persistent throughout the story.
\style {
h1 { color: blue; }
}
This example will turn header text blue.
With \script
you can add custom JavaScript code to your stories. When used within a section, the code will run when the
section becomes visible. Using \script
outside of a section block will cause the code to be run when the game is loaded.
\script { JS code }
\script {
console.log('hell world!')
}
This example will cause hell world to be printed to the JavaScript console.
\title(Example Story)
\section(main) {
\h1 { Welcome to Woven! }
Woven is a \show-replace(coolSection) { cool } interactive fiction engine.
\nav(nextPage) { Turn the page }
}
\section(coolSection) {
cool, soft and rad
}
\section(nextPage) {
\h2 { Welcome to the second page }
Things feel a little different here
}