Boundless is a React-based Story Format for Twine Its built upon the Unified ecosystem.
Boundless supports GitHub Flavored Markdown and a few additional features.
Passage links are defined using the [[
and ]]
syntax. Boundless supports the
following link formats:
Syntax | Example |
---|---|
[[link target]] |
[[store]] |
[[link text->link target]] |
[[go to the store->store]] |
[[link target<-link text]] |
[[store<-go to the store]] |
[[link text|link target]] |
[[go to the store|store]] |
Boundless supports Remark's implementation of Markdown directives
(via remark-directive
), which are used to add HTML elements not
normally supported by Markdown.
Container directives start with :::tag
and end with :::
, both of which must appear
on their own separate line.
:::section
This is a section.
:::
You can also add attributes to the container directive by adding
{key="value"}
after the tag name.
:::section{style="color: red"}
Here is some content
:::
Will produce:
<section style="color: red">
Here is some content
</section>
Any attributes that starts with a .
will be added to the
container's class list.
:::section{.red .bold}
Here is some content
:::
Will produce:
<section class="red bold">
Here is some content
</section>
You can also use state values in attributes (see the :state[key]
Directive for more
information). For example:
:::script
App.set({test: "Hello World!"})
:::
:::section{data-state=":state[test]"}
Here is some content
:::
Will produce:
<section data-state="Hello World!">
Here is some content
</section>
You can also use state values as class names:
:::script
App.set({test: "red"})
:::
:::section{.bold .:state[test]}
Here is some content
:::
Will produce:
<section class="bold red">
Here is some content
</section>
The :::script
container directive is used to add JavaScript to the passage.
The code is executed as soon as the passage loads (see "Global API" below for
information on how to access application variables).
:::script
console.log("Hello, world!")
:::
The :::if[condition]
container directive is used to conditionally render content. The
content inside the directive will only be rendered if the condition is true
.
Using a single word as the condition will check if the variable exists in the Global App
state. Therefore, the following two examples are equivalent:
:::if[key]
This will be rendered assuming the `key` exists in the application state and is truthy.
:::
Is equivalent to:
:::if[useApp.getState()['key']]
This will be rendered assuming the `key` exists in the application state and is truthy.
:::
You can also negate the condition by prefixing it with !
.
:::if[!key]
This will be rendered assuming the `key` does not exist in the application state or is
falsy.
:::
Is equivalent to:
:::if[!useApp.getState()['key']]
This will be rendered assuming the `key` does not exist in the application state or is
falsy.
:::
The :::html
container directive is used to render raw HTML content.
This is useful for very complex content.
:::html
<div>
This is some <strong>HTML</strong> content.
<ul>
<li>It can be as complex as you want.</li>
<li>It can even contain <a href="https://google.com">links</a>.</li>
</ul>
</div>
:::
The :state[key]
directive also works in :::html
directives.
:::script
App.set({test: "Hello World!"})
:::
:::html
<div>
This is some <strong>HTML</strong> content.
<p>Here is a state variable: :state[test]</p>
</div>
:::
The ::include[passageName]
directive is used to include other passages in the
current passage. For example, let's say you have two passages: welcome
and store
.
Here is the contents of welcome
:
Welcome to the store!
Here is the contents of store
:
::include[welcome]
These are the items in the store:
- content
- content
...
Will produce:
Welcome to the store!
These are the items in the store:
- content
- content
...
The :state[key]
directive is used to access the value of a state variable.
:::script
App.set({test: "Hello World!"})
:::
This is the value of the `test` variable: :state[test]
Will produce:
This is the value of the `test` variable: Hello World!
Boundless exposes two global objects: App
and Story
. These are accessible
from Story's JavaScript.
Used to access/manipulate application data.
Returns the value of the specified key in the application state. If no key is specified, the entire application state is returned.
App.get('key') // => value
App.get() // => { key: value }
Sets the value of the specified key in the application state. If no value is specified and the key is an object, the new state is merged with the existing state.
App.set('key', 'value') // => { key: 'value' }
App.set({ key: 'value2', key2: 'value2' }) // => { key: 'value2', key2: 'value2' }
Used to access/manipulate story data such as what passage is currently being displayed.