Add D002 (malformed attribute blocks), R004 (skipped declare rows), and V001-V005 (CSV data files). CSV checks run once per referenced file and also cover inline spark-table bodies.
Generate docs/reference.md from the known.ts catalog via npm run gen:reference, and add drift guards asserting the catalog matches the customElement call sites and the committed reference.
Statically validate a directory of tttk documents and report structured diagnostics with file/line positions, exit codes, and --json output. Checks cover code-block roles, unresolved content references, tag blocks, element names, links, anchors, and assets. Runs over the same content registry as the app.
- deriveLinks strips fenced code blocks so markdown examples don't
produce phantom link completions
- Add resolveContentEntry returning body + path + inline flag;
scanDocDirectives uses it instead of re-deriving resolution, and
parseDirectiveAttrs is replaced by the shared parseBlockAttrs
- Fix relative file refs with ./ prefix never resolving through
resolveContent (pathIndex lookup joined the ./ verbatim)
- Drop resolveBlockAs and the as= attribute; scanDoc now switches
directly on role and warns on unknown roles instead of silently
stripping
- md-table derives data-spark from its loaded CSV via
parseSparkTableCsv; delete injectSparkDirectives and the second
registry pass so pathIndex is exactly scanDoc output
- Align spark-table dice header regex with isSparkTableHeader
- Split loadCSV into parseCSVString (content) and loadCSVFromPath
(path); drop isCSV/looksLikeCsv heuristics
- Delete coerceSparkTables and markedTable label-header magic;
plain markdown tables now render as plain tables
- Add explicit markdown role=spark-table fence syntax that converts
pipe tables to CSV at scan time, with dice-header validation
- Map ESM-only github-slugger and csv-parse browser build to CJS in
jest config; add content-registry tests
Drop legacy yaml/tag info string; tag blocks now require
```yaml role=tag. Add fence-line tag=/id= attributes that
override YAML body values, and move parseBlockAttrs to
src/markdown/block-attrs.ts so scanner and render extensions
share one parser.
Export isSparkTableHeader from content-registry and use it in both CLI
and frontend table parsing. Add resolveContentRef to resolve content
references consistently. Write processed registry content back to the
file index so browser mode renders identically to CLI mode.
Extract buildRegistryFromIndex and normalizePathKey from the CLI serve
command and the browser completions module into the shared
content-registry module. This ensures both paths produce identical
pathIndex/docContent, including the spark-injection pass that was
previously only applied in the CLI.
Add a browser-safe ContentRegistry owning path and inline content
stores, then derive completions from it. Remove the old block-processor,
directive-scanner, and link-source modules in favor of scanDoc,
deriveCompletions, and injectSparkDirectives, and register an inline
resolver for the frontend file index.
Introduce a `threshold` column to tag modifiers in CSV declarations,
allowing modifiers to activate only when a tag's count meets a minimum
requirement.
Implement support for "tagmap" variables (e.g., `#warrior:1;#druid:2`)
which allow for complex, multi-tag state tracking. These variables
can receive specialized tagmap modifications rather than simple
numeric additions.
Consolidate the `/spark` command into `/roll` to simplify the CLI.
The `/roll` command now handles both dice notation and spark table
slugs.
- Update `parseInput` to treat `/roll` arguments as a generic string.
- Update `dispatchCommand` to check for spark table matches before
evaluating dice notation or variable expressions.
- Update command completions to show both dice and spark table
suggestions under `/roll`.
- Update documentation and UI placeholders to reflect the change.
- Replace `scanDeclareBlocks` with `parseDeclareCsv` in block processor
- Add error handling for declare block parsing
- Optimize `ReactiveVariableManager` by pre-computing variable keys
- Store template text and keys in data attributes for faster updates
- Adjust `VariableView` popup width via CSS class
- Add comprehensive tests for variable system, including parsing,
expression evaluation, and reactivity.
- Add `moduleNameMapper` to `jest.config.js` to resolve `.js` imports
to `.ts` source files.
- Add a mock for `csv-parse/browser/esm/sync` to support Node-based
testing.
Introduce `scanDeclareBlocks` in `declare-parser.ts` to provide a
single source of truth for parsing `role=declare` blocks. This
replaces redundant scanning logic in both the CLI and the journal
completions.
Also remove unused `dice.ts` and `spark-scanner.ts` files.
Replace manual CSV splitting with `csv-parse` to allow for
order-agnostic columns and better handling of quoted values.
The `tag` column is now optional.
Replace the old stat-parser logic with a new declare-parser to handle
variable declarations and tag modifiers. This includes moving the
declare-parser logic to a shared location in cli/completions to avoid
duplication between the CLI and the journal component.
Introduce ReactiveStatManager to allow dynamic stat replacement within
rendered markdown content. This component scans the article DOM for
`${key}` patterns and reactively updates them based on the journal
stream.
As part of this change, the SVG-based StatSheet system is removed in
favor of this more flexible text-based approach.
Introduces a `remix` option that allows each data column in a spark
table to be rolled independently. This is enabled via a `remix=true`
attribute in the directive's extra attributes.
Also refactors spark table scanning by moving markdown parsing logic
from the frontend to a new CLI-side `spark-scanner.ts` utility,
improving separation of concerns.
Switch the spark table resolution logic to use the direct path to the
backing CSV file rather than attempting to parse the containing
markdown file. This simplifies the lookup process and improves
reliability.
Also refactor `SparkTableMeta` to store rows as objects keyed by
header instead of raw string arrays.
Relocate spark table logic from the block processor to a dedicated
directive scanner. This allows spark tables to be treated as
`:md-table` directives and ensures they are processed in a second pass
after the content index is fully populated.
- Update package name and CLI binary to 'tttk'
- Revise documentation to reflect new name
- Add default serve behavior when no subcommand is given
- Add directory existence check in serve command
- Refactor inline comments to Chinese
Introduces the ability to discover and render `*.sheet.svg` files.
These files can contain `<text>` elements with `${key}` templates
that reactively update based on the current journal stats.
- Add `StatSheet` type and CLI scanning logic
- Implement `SheetView` for rendering SVGs with live bindings
- Add `parseSheet` utility to extract template patterns from SVG
- Update file indexer to include `.svg` files
Allows passing an optional label to `parseStatModifiers` to override
the default ID-based label. This enables more descriptive names in
the UI and improves how modifier labels are derived in the journal
view.
Introduces a new `stat-modifiers` CSV role that simplifies the
creation of template stats and their associated modifier stats.
A single CSV block now automatically generates:
- A template stat definition.
- Multiple modifier stat definitions (prefixed with the template ID).
- The corresponding template table.
This reduces the need for manual YAML definitions for every
modifier associated with a template.
Introduce a centralized `block-processor` and `block-scanner` to
handle markdown fenced code blocks. This replaces the previous
`inline-blocks.ts` and individual completion sources with a unified
approach that handles block stripping, directive replacement, and
metadata extraction (stats, templates, and spark tables) in a single
pass.
Introduces a new `template` stat type that allows for table-based
lookups via CSV blocks in markdown files. When a template stat is
rolled, it uses a dice expression defined in the template to select
an entry, applies a label, and automatically updates associated
modifier stats using relative values.
Move YAML and CSV stat parsing logic from CLI and journal components
into a new shared `stat-parser.ts` module to enable reuse between
the CLI scanner and the client-side frontend.
Update the inline block parser to support arbitrary key-value pairs.
If an `as` attribute is provided, the block is replaced with a
directive (e.g., `:directive[path]{attrs}`) instead of being
stripped. If no `as` attribute is present, the block is removed.
Additionally, filenames are now automatically generated using a
content hash if the `file` attribute is missing.
- Publish the existing session manifest via the broker on startup
- Automatically focus the new session input field when it is shown
- Prevent event propagation when clicking to create a new session
- Add logic to detect the best LAN IPv4 address for easier network
access
- Display both localhost and LAN access URLs in the CLI
- Remove file path from journal input autocomplete labels
Implement "spark tables" functionality, which allows users to roll
dice against markdown tables to retrieve specific values.
- Add `sparkTablesSource` to scan markdown files for tables starting
with a dice notation (e.g., d6, d20).
- Implement `/spark` command in the journal to resolve and roll
spark tables.
- Add a new message type `spark` with a dedicated UI component to
render the results.
- Update completions API to include spark table metadata.
Refactor the completions system to support both CLI mode (via
`/__COMPLETIONS.json`) and a client-side fallback scan for dev mode.
- Implement client-side scanning of the file index for dice and headings
- Add `ensureCompletions` to allow components to await data readiness
- Update `JournalInput` to handle "no results" states in the dropdown
- Improve keyboard navigation (Tab to accept, Enter to select)
- Update dice regex to support `:md-dice[...]` syntax
Implement a new completions system that scans markdown files for
dice notation and headings. The server now exposes a
`/__COMPLETIONS.json`
endpoint and automatically recomputes the completion index when
files are added, updated, or deleted.
Remove the `websocket-stream` dependency in favor of
`createWebSocketStream`
from the `ws` package. This simplifies the MQTT broker setup in the
journal server and removes unnecessary transitive dependencies.
Also improve the JournalPanel UI with smoother transitions and better
visibility handling.
Integrate `websocket-stream` to handle MQTT broker upgrades in the
CLI and add granular connection status tracking to the UI.
- Add `websocket-stream` dependency
- Update CLI to use `websocket-stream` for socket upgrades
- Enhance `journalStream` store with `connectionStatus` and
`connectionError` states
- Add visual connection status indicators to `App` and `JournalPanel`
Refactor the journal server to run over WebSockets on the existing
HTTP server instead of a separate MQTT TCP port. This removes the need
for a separate port configuration and simplifies the connection flow
by auto-connecting to the current host.
- Remove `--mqtt-port` CLI option
- Attach Aedes broker to the HTTP server via WebSocket upgrade
- Update UI to remove manual broker URL and player name inputs
- Add "Content Source" access from the sidebar
- Update JournalPanel to auto-connect to the local server
Implement a journal server that uses an Aedes MQTT broker to
persist stream messages to JSONL files and manage session metadata
via a manifest.
- Add `aedes`, `mqtt`, and `zod` dependencies
- Implement `createJournalServer` in `src/cli/journal.ts`
- Integrate journal server into the `serve` command
- Add `--mqtt-port` option to the CLI
- Add session lifecycle management (create, update, delete) via
retained MQTT topics