@bengo.codes/pan-saga (0.1.0)
Installation
@bengo.codes:registry=npm install @bengo.codes/pan-saga@0.1.0"@bengo.codes/pan-saga": "0.1.0"About this package
pan-saga
<pan-saga> reads screenplay-style saga scripts and streams them as JSON activity objects — characters speaking, narrator descriptions, cinematic effects. Drop it in any HTML page, point it at a .saga file or write one inline, and iterate the results.
Usage
Inline source (slot)
<pan-saga>
<script slot="src" type="text/saga">
# Int. Bengo Apt.
@ Bengo
> if you omit the hyphen it'll redirect you to
<hello-world
! this is a comment — it is ignored
^ fade to black
</script>
</pan-saga>
Remote source (attribute)
<pan-saga src="https://example.com/story.saga"></pan-saga>
If src is provided but the fetch fails, <pan-saga> falls back to the inline slot="src" script tag if one is present.
Saga format sigils
| Sigil | Meaning | Emitted activity |
|---|---|---|
# … |
Scene heading / location | (sets location context) |
@ … |
Character name | (sets speaker context) |
& … |
Character mood/modifier | (sets mood context, silent) |
> … |
Dialogue | CreateActivity |
^ … |
Cinematic effect | EffectActivity |
< tagname |
Embedded HTML element (attrs follow) | NarrateActivity |
! … |
Comment | (ignored) |
| plain text | Narrator description | NarrateActivity |
Attribute lines for <tagname elements look like key: value or key: (boolean attribute). A blank line ends the attribute block.
Activity shapes
// dialogue
{
"type": "Create",
"actor": { "name": "Bengo" },
"object": { "type": "Note", "content": "if you omit the hyphen it'll redirect you to" },
"location": "Int. Bengo Apt."
}
// narrator text or embedded HTML element
{
"type": "Narrate",
"actor": { "type": "Narrator" },
"content": "<hello-world>"
}
// cinematic effect
{
"type": "Effect",
"content": "fade to black"
}
Element API
Implemented in src/pan-saga.ts as PanSaga extends LitElement. The package has no side effects — you register the element yourself when your app is ready.
HTML attributes
| Attribute | Type | Description |
|---|---|---|
src |
string |
URL to fetch saga text from. Falls back to inline slot content on fetch failure. |
Slots
| Slot | Description |
|---|---|
<script slot="src" type="text/saga"> |
Inline saga source text. Used as primary source if no src attribute, or as fallback if the remote fetch fails. |
JavaScript / TypeScript
import { PanSaga } from "pan-saga";
// Registration is the caller's responsibility — the library has no side effects:
customElements.define("pan-saga", PanSaga);
PanSaga#activities: AsyncIterable<Activity>
Lazy async iterable of parsed Activity objects. Begins resolving once the element is connected to the DOM and the saga source is ready. Defined in src/types.ts.
const el = document.querySelector("pan-saga") as PanSaga;
for await (const activity of el.activities) {
console.log(activity); // CreateActivity | NarrateActivity | EffectActivity
}
The parser itself is a standalone export — usable without the element:
import { parseSaga } from "pan-saga/parser";
for await (const activity of parseSaga(sagaText)) {
console.log(activity);
}
The parser is a streaming async generator — it emits one activity at a time and never buffers the full file. For streaming directly from a fetch response body, see SagaTransformStream in DEVELOPMENT.md.
CLI
Pipe saga text in, get NDJSON activity objects out:
printf '@ Alice\n> Hello world\n^ fade to black' | pan-saga | jq .
npx pan-saga --help # usage + sigil reference
Requires Node 22+.
Quick start
npm run dev # dev server → http://localhost:5173
npm run build # production bundle
npm test # browser tests via vitest + Storybook
See DEVELOPMENT.md for full setup instructions, module layout, tool notes, Storybook details, and how to add tests.
Releases
Versioning is managed with Changesets. See DEVELOPMENT.md for the release workflow.
Dependencies
Dependencies
| ID | Version |
|---|---|
| @lit-labs/scoped-registry-mixin | ^1.0.4 |
| @webcomponents/scoped-custom-element-registry | ^0.0.10 |
| lit | ^3.2.0 |
Development dependencies
| ID | Version |
|---|---|
| @11ty/eleventy | ^3.1.2 |
| @changesets/cli | ^2.29.8 |
| @storybook/addon-docs | ^10.2.13 |
| @storybook/addon-vitest | ^10.2.13 |
| @storybook/web-components-vite | ^10.2.13 |
| @types/node | ^25.3.2 |
| @vitest/browser | ^4.0.18 |
| @vitest/browser-playwright | ^4.0.18 |
| @vitest/runner | ^3.0.0 |
| playwright | ^1.50.0 |
| storybook | ^10.2.13 |
| typedoc | ^0.28.17 |
| typedoc-plugin-markdown | ^4.10.0 |
| typescript | ^5.7.0 |
| vite | ^6.1.0 |
| vitest | ^4.0.18 |