Document markup and improve choice tags

This commit is contained in:
2026-05-17 15:52:41 +02:00
parent c2fb27b6b8
commit 2c54498ee2
52 changed files with 3485 additions and 377 deletions
+63
View File
@@ -26,6 +26,10 @@ The production client must tolerate TTS being unavailable. The safe default TTS
- Done: placeholder game API for new/load/save/running state.
- Done: sound effect and music folders, sound effect playback, music playback, and music ducking during TTS.
- Done: image markup is parsed, persisted in history, restored from save/history, and rendered as line-snapped page blocks.
- Done: Ink engine integration with source compilation, engine config, metadata handoff, choice-mode turns, one-list choice UI, and keyboard choice letters.
- Done: localized UI strings, game metadata language handoff for typography/hyphenation/TTS language, and German dialogue guillemet normalization.
- Done: localized popup queue for intended endings, unrecoverable errors, achievements, and tutorial/player alerts.
- Done: credits dialog and third-party license display.
- Partial: save-game API restores story state and Ink state, but the broader save/storage model still needs hardening for all engines.
- Pending: deeper automated tests for layout, playback timing, TTS provider switching, and media cue timing.
@@ -74,6 +78,7 @@ The loader is deliberately the conductor, not the orchestra. Module-specific con
- `options-ui-module.js`: options modal, persisted controls, provider status displays.
- `ui-controller-module.js`: top-bar commands, global input behavior, game API control wiring.
- `ui-display-handler-module.js`: book page display, startup prompt, unified live/history rendering, line-coordinate scrolling, image placement, and media block dispatch.
- `choice-display-module.js`: choice-mode rendering, keyboard-letter assignment, click/keyboard choice dispatch, and future choice-template hook.
- `ui-input-handler-module.js`: command entry, history, fast-forward key handling.
- `socket-client-module.js`: socket connection and game API request wrapper.
- `game-loop-module.js`: high-level client/game flow.
@@ -192,6 +197,16 @@ Canonical structural and media tags use Ink-style `#` syntax:
- YAML and Zork narrative output use the same leading `#...` syntax, parsed by the server into `StoryTag` objects before the client sees them.
- The browser protocol is structured `TurnResult` objects with structured tags and render blocks, not raw story markup.
Tag syntax:
```text
#key
#key[value]
#key[value](options)
```
The current parser accepts the bracket/parentheses form above and colon value tags such as `#key:x` or `#action:movement`.
Markdown emphasis:
```text
@@ -256,6 +271,47 @@ File names resolve relative to `public/music/`. Modes:
For chapter openings, authors can place `#music[file](..., lead=N)` after `#chapter[...]` and before the first prose paragraph. The heading is rendered/spoken first, then music starts and plays alone for the lead duration, then the dropcapped paragraph continues. Music and image pauses are playback gates only; they must not stop the queue from preparing upcoming TTS in the background.
Sound effect options:
```text
#sfx[church-bells.ogg](max=8 fade fade-duration=2)
#sfx[steam-whistle.ogg](fade-after=4 fade-duration=1.5)
```
Supported SFX options are `max=`, `duration=`, `max-duration=`, `limit=`, `stop-after=`, `fade-after=`, bare seconds such as `4s`, `mode=fade`, `mode=stop`, `fade`, `stop`, `cut`, and `fade-duration=`/`fade-time=`.
Choice tags:
```ink
* [Open the compartment door]
# letter[o]
# action[examine]
```
`#letter[x]`, `# letter[x]`, or `#key:x` reserves keyboard letter `X` for that choice. Explicit letters are assigned first; remaining visible choices receive `A` through `Z` in screen order, skipping reserved letters. The current UI supports up to 26 visible choices and renders them in one list. `#action[name]` or `#action:name` is stored as the choice category and reserved for later template routing.
Future choice-template metadata should keep the same bracket tag syntax if implemented:
```text
#action[movement]
#optional
#gated[noble]
#sort[last]
```
The older standalone `MARKUP_GUIDELINES.md` draft proposed colon tags, digit keys, grouping, shuffling, and parser-style reserved shortcuts. The active implementation deliberately does not use that syntax yet. Any future expansion should first extend the shared tag parser and `TurnResult.choices` contract so Ink, YAML, and Z-code all still emit the same structured choice objects.
Game-state and popup tags:
```text
#score[You reached the quiet ending.]
#error[The story ended unexpectedly.]
#achievement[First Steps]
#alert[Try examining objects before using them.]
```
`#score[...]` marks an intended ending and is surfaced as `gameState.endState.type = intended` when the turn ends. `#error[...]` marks an unrecoverable ending and is surfaced as `gameState.endState.type = error`. The Ink engine emits a synthetic `#error[...]` when it runs out of content without an explicit `#score[...]`/`#error[...]`. `#achievement[...]` and `#alert[...]` show queued localized popups while play continues.
## TTS And Playback Specification
The playback system must keep text animation and audio synchronized.
@@ -345,6 +401,7 @@ Current placeholder behavior:
- `loadGame(slot)` requires a placeholder save and then starts the demo game like `newGame()`.
- Saves do not persist across reloads yet.
- `isGameRunning()` returns true after a game starts and until the session ends.
- Turn results use `inputMode: 'end'` when no more input is accepted. End turns may include `gameState.endState` and/or `#score[...]`/`#error[...]` tags to distinguish intended endings from unrecoverable errors.
UI requirements before a game starts:
@@ -415,6 +472,11 @@ Longer-term goal:
- [x] Added command input focus and global typing behavior.
- [x] Added command mirroring through the server path for UI testing.
- [x] Added fast-forward for animation and TTS fade/stop.
- [x] Added Ink source compilation and Ink engine server.
- [x] Added choice-mode UI and keyboard letter assignment from `#letter[x]` and `#key:x`.
- [x] Added localized ending, error, achievement, and alert popups from tag-channel events.
- [x] Added credits/license dialog.
- [x] Added line-addressed history scrolling model and moved the NOTE.md scrolling specification here.
### In Progress
@@ -422,6 +484,7 @@ Longer-term goal:
- [ ] Tighten automated checks around top-bar/options state initialization after reload.
- [ ] Improve automated visual regression coverage for page scaling, dropcap line-height alignment, and paragraph indentation.
- [ ] Improve automated audio tests for music ducking, sound effect timing, and fast-forward fadeout.
- [ ] Polish custom scrollbar dragging so the thumb moves freely during drag and commits the scroll target only on release.
### Pending