yarn-spinner-runner-ts
v0.1.5-c
Published
TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter [NPM package](https://www.npmjs.com/package/yarn-spinner-runner-ts)
Downloads
207
Maintainers
Readme
yarn-spinner-runner-ts
TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter.
- Github repository for more information.
- NPM package
References
- Old JS parser:
bondage.js(Yarn 2.x) — GitHub - Official compiler (C#): YarnSpinner.Compiler — GitHub
- Existing dialogue runner API: YarnBound — GitHub
Features
- ✅ Full Yarn Spinner 3.x syntax support
- ✅ Parser for
.yarnfiles → AST - ✅ Compiler: AST → Intermediate Representation (IR)
- ✅ Runtime with
YarnRunnerclass - ✅ React hook:
useYarnRunner() - ✅ React components:
<DialogueView />,<DialogueScene />,<DialogueExample /> - ✅ Typing animation with configurable speeds, cursor styles, and auto-advance controls
- ✅ Markup parsing with HTML formatting tags and CSS-ready spans
- ✅ Expression evaluator for conditions
- ✅ Command system with built-in handlers (
<<set>>,<<declare>>, etc.) - ✅ Scene system with backgrounds and actor images (with configurable portrait cross-fades)
- ✅ Custom CSS styling via
&css{}attributes - ✅ Built-in functions (
visited,random,min,max, etc.) - ✅ Support for:
- Lines with speakers
- Options with indented bodies
- Inline option conditions via
[if expression] <<if>>/<<elseif>>/<<else>>/<<endif>>blocks<<once>>...<<endonce>>blocks<<jump NodeName>>commands<<detour NodeName>>commands- Variables and expressions
- Enums (
<<enum>>blocks) - Smart variables (
<<declare $var = expr>>) - Node groups with
when:conditions - Tags and metadata on nodes, lines, and options
- Custom commands
Installation
npm install
npm run buildQuick Start
Basic Usage
import { parseYarn, compile, YarnRunner } from "yarn-spinner-runner-ts";
const yarnText = `
title: Start
---
Narrator: Hello!
-> Option 1
Narrator: You chose option 1.
-> Option 2
Narrator: You chose option 2.
===
`;
const ast = parseYarn(yarnText);
const program = compile(ast);
const runner = new YarnRunner(program, {
startAt: "Start",
variables: { score: 10 },
functions: {
add: (a: number, b: number) => a + b,
},
handleCommand: (cmd, parsed) => {
console.log("Command:", cmd);
},
onStoryEnd: ({ variables, storyEnd }) => {
console.log("Story ended!", storyEnd);
console.log("Final variables:", variables);
},
});
// Get current result
console.log(runner.currentResult); // TextResult, OptionsResult, or CommandResult
// Advance dialogue
runner.advance(); // Continue text
runner.advance(0); // Choose option 0Variables passed from your host app can be provided as
scoreor$score; the runner normalizes keys so either style works.
Inline conditional options
You can add a per-option condition by appending [if expression] to the option text. The expression is evaluated when the option list is emitted; options whose expression evaluates to false are dropped before the runner shows them.
title: Hub
---
<<declare $hasBadge = false>>
-> Ask about the badge [if $hasBadge]
Narrator: You flash the badge.
-> Offer a bribe
Narrator: You slide some eddies across the table.
===Once some branch executes <<set $hasBadge = true>>, the badge option automatically appears alongside the other entries, without extra <<if>> blocks.
Arithmetic assignments
<<set>> accepts both to and = aliases and evaluates the expression on the right-hand side, so you can modify variables inline—operator precedence and parentheses all work the same way they do in Yarn Spinner:
<<set $reputation = $reputation - 25 >>
<<set $score = ($score + 10) / 2>>
Narrator: Current street cred: {$reputation}, score: {$score}React Usage
import { parseYarn, compile, useYarnRunner, DialogueView } from "yarn-spinner-runner-ts";
import { parseScenes } from "yarn-spinner-runner-ts";
import type { SceneCollection } from "yarn-spinner-runner-ts";
function MyDialogue() {
const [program] = useState(() => {
const ast = parseYarn(yarnText);
return compile(ast);
});
const [scenes] = useState<SceneCollection>(() => {
return parseScenes(sceneYamlText);
});
const { result, advance } = useYarnRunner(program, {
startAt: "Start",
variables: { score: 10 },
});
return (
<DialogueView
result={result}
onAdvance={advance}
scenes={scenes}
/>
);
}Full Example Component
import { DialogueExample } from "yarn-spinner-runner-ts";
function App() {
return <DialogueExample />;
}Typing Animation
Set enableTypingAnimation on DialogueView to enable the TypingText component for typewriter-style delivery. Tweak props like typingSpeed, showTypingCursor, cursorCharacter, autoAdvanceAfterTyping, autoAdvanceDelay, and pauseBeforeAdvance to fine-tune behaviour, and see Typing Animation (React) for details.
Browser Demo
Run the interactive browser demo:
npm run demoThis starts a Vite dev server with a live Yarn script editor and dialogue system.
API Reference
Parser
parseYarn(text: string): YarnDocument— Parse Yarn script text into AST
Compiler
compile(doc: YarnDocument, opts?: CompileOptions): IRProgram— Compile AST to IR
Runtime
YarnRunner(program: IRProgram, options: RunnerOptions)— Dialogue runner classcurrentResult: RuntimeResult | null— Current dialogue stateadvance(optionIndex?: number): void— Advance dialoguegetVariable(name: string): unknown— Get variable valuesetVariable(name: string, value: unknown): void— Set variable valuegetVariables(): Readonly<Record<string, unknown>>— Get all variablesonStoryEnd?: (payload: { variables: Readonly<Record<string, unknown>>; storyEnd: true }) => void— Handler called when story reaches its end, providing final variable state
React Components
useYarnRunner(program: IRProgram, options: RunnerOptions)— React hook- Returns:
{ result: RuntimeResult | null, advance: (optionIndex?: number) => void, runner: YarnRunner }
- Returns:
<DialogueView result={...} onAdvance={...} scenes={...} />— Ready-to-use dialogue component<DialogueScene sceneName={...} speaker={...} scenes={...} actorTransitionDuration={...} /> — Scene background, actor display, and portrait transitions— Scene background and actor display<DialogueExample />— Full example with editor
Scene System
parseScenes(input: string | Record<string, unknown>): SceneCollection— Parse YAML scene configurationSceneCollection— Type for scene configurationSceneConfig— Type for individual scene configActorConfig— Type for actor configuration
See Scene and Actor Setup Guide for detailed documentation.
Expression Evaluator
ExpressionEvaluator(variables, functions, enums?)— Safe expression evaluator- Supports:
===,!==,<,>,<=,>=,&&,||,! - Operator aliases:
eq/is,neq,gt,lt,lte,gte,and,or,not,xor - Function calls:
functionName(arg1, arg2) - Variables, numbers, strings, booleans
- Enum support with shorthand (
MyEnum.Case)
- Supports:
Commands
CommandHandler— Command handler registry- Built-in:
<<set variable = value>>,<<declare $var = expr>> - Register custom handlers:
handler.register("mycommand", (args) => { ... })
- Built-in:
parseCommand(content: string): ParsedCommand— Parse command string
Built-in Functions
The runtime includes these built-in functions:
visited(nodeName)— Check if a node was visitedvisited_count(nodeName)— Get visit count for a noderandom()— Random float 0-1random_range(min, max)— Random integer in rangedice(sides)— Roll a diemin(a, b),max(a, b)— Min/max valuesround(n),round_places(n, places)— Roundingfloor(n),ceil(n)— Floor/ceilinginc(n),dec(n)— Increment/decrementdecimal(n)— Convert to decimalint(n)— Convert to integerstring(n),number(n),bool(n)— Type conversions
Example Yarn Script
title: Start
tags: #introduction #tutorial
---
Narrator: Welcome!
<<set score = 10>>
<<if score >= 10>>
Narrator: High score!
<<else>>
Narrator: Low score.
<<endif>>
<<declare $randomName = random_range(1, 3) == 1 ? "Alice" : "Bob">>
Narrator: Your name is {$randomName}.
-> Ask about features
Player: What can this do?
Narrator: Lots of things!
-> Ask about commands
Player: Tell me about commands.
Narrator: Commands modify state.
<<once>>
Narrator: This only shows once!
<<endonce>>
<<jump NextNode>>
===
title: NextNode
scene: scene1
---
Narrator: You've arrived at the next scene!
===CSS Styling
You can apply custom CSS styles to nodes and options using the &css{} attribute:
title: StyledNode
&css{background-color: #ff0000; color: white;}
---
Narrator: This node has a red background.
-> Option 1 &css{background-color: blue;}
Narrator: You chose the blue option.
===Styles are merged with default styles, with custom styles taking precedence.
See CSS Attribute Documentation for details.
Scene Configuration
Configure scenes and actors using YAML:
scenes:
scene1:
background: https://example.com/background1.jpg
actors:
special_npc:
image: https://example.com/special-npc.png
actors:
Narrator: https://example.com/narrator.png
Player: https://example.com/player.pngUse scenes in Yarn nodes:
title: MyNode
scene: scene1
---
Narrator: This scene uses scene1's background and actors.
===See Scene and Actor Setup Guide for complete documentation.
Project Structure
yarn-spinner/
├── src/
│ ├── model/ # AST types
│ ├── parse/ # Lexer and parser
│ ├── compile/ # Compiler (AST → IR)
│ ├── runtime/ # Runtime execution
│ ├── scene/ # Scene system
│ ├── react/ # React components
│ └── tests/ # Test files
├── examples/
│ ├── yarn/ # Example Yarn scripts
│ ├── browser/ # Browser demo (Vite)
│ └── scenes/ # Scene configuration examples
├── docs/ # Documentation
└── dist/ # Compiled outputDevelopment
npm run build # Build TypeScript
npm run dev # Watch mode
npm run lint # Run ESLint
npm test # Run tests
npm run demo # Start browser demo
npm run demo:build # Build browser demoTesting
Tests are located in src/tests/ and cover:
- Basic dialogue flow
- Options and branching
- Variables and flow control
- Commands (
<<set>>,<<declare>>, etc.) <<once>>blocks<<jump>>and<<detour>>- Full featured Yarn scripts
Run tests:
npm testDocumentation
Additional documentation is available in the docs/ folder:
- Lines, Nodes, and Options
- Options
- Jumps
- Detour
- Logic and Variables
- Flow Control
- Once Blocks
- Smart Variables
- Enums
- Commands
- Functions
- Node Groups
- Tags and Metadata
- CSS Attribute
- Typing Animation (React)
- Markup (Yarn Spinner)
- Actor Image Transitions
- Scene and Actor Setup
License
MIT
