Simplify the `DocDialog` component by removing hardcoded property
tables and syntax blocks. Instead, rely on the raw markdown body
provided in the `DocEntry` to render documentation content. This
shifts the responsibility of formatting (syntax, props, etc.) from
the component to the individual markdown files, allowing for more
flexible and detailed documentation.
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.
- Remove unused `MessageTypeDef` imports in `ComposePanel` and
`DynamicForm`
- Remove unused `schema` memo in `DynamicForm`
- Update `FieldInput` label class to use `shrink-0` instead of
`flex-shrink-0`
- Exclude test files from `tsconfig.cli.json`
- 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.
Add `rebuildReactivityFromStore` to synchronize local reactivity
state with the hydrated variable store. This ensures tag activations
are correctly tracked following a reducer replay.
Also remove the unused `invalidateCompletions` function.
Remove the mutable `streamFallback` global state and instead pass the
`VariableStore` as an explicit argument to `getCombined` and related
functions. This ensures correctness by avoiding reliance on mutable
module state during reactivity calculations.
Introduce a distinction between base values (set via `/set` or
declarations) and active modifiers (applied via tags). This ensures
tag transitions and numeric modifiers are calculated correctly during
cascades.
- Refactor `VariableView` to use a flat list with hover popups for
declarations and active modifiers.
- Update `command-dispatcher` to use `getCombined` for accurate
value lookups and `setBase` for variable updates.
- Update `var-reactivity` to manage `baseValues`, `activeMods`, and
`sourceActivations` separately.
- Export new utility functions for accessing combined values,
modifiers, and declaration expressions.
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.
Implement `computeInitialValues` to calculate the starting state of
declared variables and seed them into the journal stream store during
the completions initialization process.
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.
Replaces the specialized `stat` system with a more general-purpose
variable system. This includes:
- Renaming `ReactiveStatManager` to `ReactiveVariableManager`
- Changing template syntax from `${key}` to `{{$key}}`
- Replacing `StatsView` with `VariableView` to show declared, plain,
and tag-typed variables
- Updating command `/stat` to `/set`
- Refactoring the reactivity engine to support variable declarations
and tag modifiers via `csv role=declare` blocks
Add support for `role=declare` blocks in markdown to allow for
dynamic variable declarations and tag-based modifiers.
- Implement `declare-parser` to parse CSV-formatted declaration blocks.
- Implement `var-reactivity` to manage dependency graphs, topological
sorting, and cascading updates when variables change.
- Implement `variable-expression` to evaluate arithmetic, dice rolls,
and math functions within expressions.
Introduce a shared `dispatchError` signal in the command dispatcher
to unify error reporting across different components. This allows
`CommandLinkManager` to surface errors through the `JournalInput`
UI, ensuring that errors from `:cmd[]` directive clicks are visible
to the user.
Move command parsing and dispatching logic from `CommandLinkManager`
and `JournalInput` into a new `command-dispatcher.ts` module. This
unifies how commands are handled whether they are typed manually or
triggered via `:cmd[]` directive clicks.
- Simplify `dispatchCommand` by removing role-based logic and ensuring
commands are prefixed with a slash.
- Change `:cmd[]` directive output from a `span` to an `a` tag.
- Update `.cmd-link` styles to improve link appearance and prevent
text selection.
Replace the previous mechanism of intercepting specific command-prefixed
anchor tags with a dedicated `:cmd[]` markdown directive.
- Implement `cmdDirective` for `marked-directive` support.
- Update `CommandLinkManager` to listen for clicks on `[data-cmd]` spans
instead of parsing `href` attributes.
- Add CSS styles for the new `.cmd-link` class.
Implement a component that uses event delegation to intercept clicks
on markdown links starting with command prefixes (e.g., >roll, >spark).
It dispatches these as journal stream messages based on the user's
role (Observer, Player, or GM).
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.
Convert div elements to anchor tags in FileTree and HeadingNode to
enable native browser features like middle-click to open in new tabs.
The implementation preserves SPA navigation for left-clicks while
ensuring search parameters are preserved in the href.
Persist name and role to localStorage and URL parameters when
received via patch to ensure synchronization. Broadcast full state
upon successful connection.
Move MQTT connection and message log management to a Shared Worker
using Comlink. This allows multiple browser tabs to share a single
connection and synchronized state.
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.
Update `createSession` to return the session ID, allowing the UI to
automatically set the active session and trigger a server hydration
immediately after creation. This ensures the UI reflects the new
session state without a manual refresh.
Change the proxy path from `/journal` to `/.ttrpg` and ensure the
MQTT broker URL points to localhost:3000 during development to
match the CLI server configuration.
Remove the webpack-based file indexing strategy in favor of a proxy
approach. The dev server now proxies content requests to a local CLI
server, simplifying the data loading logic and removing webpack-specific
types and loaders.
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 binary from ttrpg-tools/ttrpg to tttk
- Update UI titles in App.tsx and index.html
- Add Node.js engine requirement to package.json
- Update SheetView to use full-width SVG and auto-height for better
scaling
- Center template nodes in SheetView to maintain text alignment
- Enable overflow-y-auto in SheetView to support long sheets
- Persist selected sheet ID in URL search parameters in StatsView
Update the stat sheet parser to scan <tspan> elements within <text>
nodes. This allows for individual binding of template patterns to
specific tspans, preserving their position attributes.
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.
Introduces a scoping mechanism for statistics, allowing properties
to be defined as either "player" (prefixed with player name) or
"global".
- Adds `scope` property to StatDef
- Implements key resolution to handle bare keys vs full keys
- Updates `canModifyStat` to enforce player-specific permissions
- Enhances `makeStatLookup` to resolve scoped references in formulas
- Adds documentation for the new stat system
Refactor journal input command parsing into a dedicated module and
add a `CompletionsDropdown` component to provide real-time suggestions
for commands (/roll, /spark, /link, /stat) and their arguments.
Introduces a comprehensive stat management system including:
- `/stat` command support (set, del, roll)
- `StatsView` component for displaying grouped stat tables
- Formula evaluation for derived stats (supporting arithmetic and
functions)
- Stat definition parsing from YAML blocks
- Permission checking for stat modification based on roles
Pass the file's base path through the markdown parsing pipeline to
allow the icon directive to resolve relative asset paths correctly
using an absolute fallback chain.
Refactor icon rendering to use a custom `marked-directive` instead of
a global icon prefix. This allows icons to use a CSS-based fallback
chain (searching up to 10 directory levels for an `assets/` folder),
making icon paths more robust and removing the need to pass path
prefixes through the component tree.
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.
Update file-index.ts documentation and implementation to specify
that webpackContext loading is restricted to development mode.
This ensures the code block is tree-shaken during production builds.
Remove the `md-token` and `md-token-viewer` components along with their
associated 3D generation and image tracing utilities. Update
documentation and project metadata to reflect these changes and rename
the project title to "Tabletop Tools".
Switch from fixed positioning to a flexbox-based layout for the
main application structure. This introduces a `ScrollContainerCtx` to
provide access to the main scrollable element, allowing child
components like `FileTree` and `RevealManager` to perform accurate
scrolling and positioning relative to the container instead of the
window.
refactor: set JournalPanel height to full
Refactor `CreateSessionDialog` to be controlled by its parent instead
of using an internal `open` prop. Lift the state up to `JournalPanel`
and pass the creation callback through `JournalHeader` to
`SessionDropdown`.
Add a suite of dialogs and header components to manage journal
sessions, including:
- ConnectDialog for joining sessions with name and role selection
- CreateSessionDialog for starting new sessions
- InviteDialog for generating and copying player invite links
- SessionDropdown for switching between sessions (GM only)
- JournalHeader for displaying connection status and user info
- 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
Introduce a new documentation set for Journal server functionality,
including a dropdown selector in the DocDialog to switch between
"directives" and "journal" documentation modes.
- 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
Introduce `useNavigateWithParams` to ensure that existing URL search
parameters are maintained when navigating between pages. This is
applied to the Article component, FileTree, and journal links to
prevent losing state (like session or player info) during client-side
navigation.
Also intercepts markdown anchor links in the Article component to use
client-side navigation.
Migrate GM action button injection from imperative DOM manipulation to
a reactive Solid component (`RevealManager`) using `Portal`. This
improves cleanup reliability and ensures buttons are proper Solid
components rather than raw HTML strings injected into the DOM.
Also adds URI encoding for link paths and simplifies the reveal
store logic.
Decouple the reveal logic from the `Article` component by introducing
a `RevealManager` component and an `ArticleDomCtx`. This allows the
reveal logic to reactively manage DOM injections and classes without
polluting the `Article` component's props or lifecycle.
Additionally, implements a robust `cleanupInjections` mechanism to
ensure that injected buttons and styling artifacts are properly removed
during navigation, role changes, or disconnections.
Update the spark button injection to use `data-spark` slugs on
`md-table` elements instead of manual table parsing. This improves
reliability by leveraging the slug generated during markdown
rendering.
Introduces the ability for GMs to inject spark roll buttons into
tables that match existing spark completions.
- Replaces `linkPrefill` with a more flexible `actionPrefill` system
to support multiple command types (e.g., `/link`, `/spark`).
- Implements `injectSparkButtons` to identify spark tables in the
DOM and insert action buttons.
- Updates `JournalInput` to handle structured prefill actions.
Replace the heuristic-based slug parsing with a more robust
combined-slug lookup to correctly handle page names containing
hyphens. Added `scanSparkTables` to provide better error messages
when a table is not found.
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.
Move localStorage and URL parameter management from `journalStream`
to a dedicated `persistence` store. Relocate DOM reveal and heading
injection logic to a new `reveal` store to improve separation of
concerns.
Rewrite `addRevealedClasses` to use a two-pass approach that correctly
cascades revealed status from child headings to parent headings. This
ensures that if a sub-heading is revealed, its parent headings are
also treated as revealed, maintaining proper visibility hierarchy.