Replace the writable+derived store pipeline in state.ts with a
state.svelte.ts module: a deep $state inputState mutated only through
the exported update functions, each of which persists the snapshot and
re-validates it asynchronously into validatedState.current (with
urls.current derived from it). Store subscriptions in components become
$effect blocks, and the rough/grid toggles use function bindings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code-review cleanup:
- Collapse the two mode switches (the historyState.entries getter and
activeSlot) into a single slotFor(mode) helper; entries now reads
`slotFor(mode)?.value ?? loader`.
- Remove the now-unused getStateString export from state.ts (its only
consumer was rewritten off it in this PR).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adding the `svelte-check` CI gate surfaced pre-existing type errors and
warnings under develop's TypeScript 6 / Svelte 5.56 bump. Fixes them so
`pnpm check` reports 0 errors / 0 warnings:
- Add `lang="ts"` to Share/Privacy (and a script to PrivacyPolicyLink) so
importers get real declarations instead of implicit `any`.
- Replace the deprecated `monaco.languages.json` with the new top-level
`monaco.json` namespace (proper API, no casts).
- Navbar: use `resolve('/', {})` instead of the deprecated `base`.
- Type the promo `component` as `Component<{ closeBanner: Snippet }>` and
MainMenu's `renderer` as `Snippet<[Omit<MenuItem, 'renderer'>]>`.
- Index-by-string casts in state.ts / Preset / DiagramDocumentationButton.
- Make Actions' clipboard handler accept an optional event.
- toggle-group: expose variant/size via getters to fix the
state_referenced_locally warning.
- Make the History e2e save/delete cases change state via a sample
diagram (deterministic) instead of editor typing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrate the Timeline/Saved history state module to idiomatic Svelte 5
runes and wire up type-checking.
- Rename history.ts -> historyState.svelte.ts and replace the Svelte
stores with $state-backed reactive values, removing the get() calls
(the only remaining one reads the external inputStateStore). A small
localStorage-backed `persisted()` helper keeps the same keys, so user
data is preserved. Consumers read via the reactive `historyState`
getter object instead of store auto-subscriptions.
- The gist loader now replaces the in-memory revisions in one call
(setLoaderEntries) instead of appending, so loading a new gist no
longer accumulates stale revisions.
- Add svelte-check: new `check` script, a "Type check" step in the
unit-tests CI workflow, and skipLibCheck so the check passes on the
dependency .d.ts files. svelte-check reports 0 errors / 0 warnings.
- Add accessible labels to the History toggle and the per-item
Restore/Delete buttons (a11y + testability).
- Unskip tests/history.spec.ts and rewrite it against the new UI:
load-from-localStorage + restore, tab-highlight follows the mode,
save/dedupe, auto-vs-manual isolation, and delete/clear. All pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The auto (Timeline) and manual (Saved) history handling had several bugs.
This rewrites the state module into a small, tested source-of-truth API and
turns History.svelte into a thin view.
Bugs fixed:
- Auto-saves no longer leak into the Saved list. addEntry now writes only to
the store for its own type (previously every entry was also pushed to the
manual store).
- Dedup is keyed on code + config via stateKey() instead of the whole input
state, so volatile/view-only fields (renderCount, updateDiagram, pan/zoom)
no longer cause spurious saves or hide real edits.
- The active-tab highlight tracks the history mode. History binds
activeTabID={$historyModeStore} and Tabs derives the highlight reactively
instead of mutating its prop once, which had frozen it on the first tab.
- Auto-save runs for the whole edit session via startAutoSave() in +page,
with proper cleanup. Previously the interval lived in History.svelte, only
ran while the panel was open, and was never cleared (leaking a new interval
on every open).
- restoreEntries() routes each uploaded entry to the store matching its own
type instead of dumping everything into one store by the first entry's type.
The persisted localStorage keys (autoHistoryStore, manualHistoryStore,
autoHistoryMode) are unchanged, so existing user data is preserved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump the full dependency tree (Vite 8, Vitest 4, ESLint 10, Svelte 5.56,
mode-watcher 1.x, etc.) and adapt code for breaking API changes. Upgrade
Playwright CI image to v1.60 for Node 24 compatibility.
Co-authored-by: Cursor <cursoragent@cursor.com>
End the A/B test by always showing the testB modal, remove unused variant
components and assignment logic, and route CTA links with utm_campaign=live_2026.
Co-authored-by: Cursor <cursoragent@cursor.com>
Currently, the `config` in the codeState in the hash is sanitized for
unsafe values, however the `?config` URL parameter or configs loaded
from a GitHub Gist are not.
Reported-by: Chai Cheng Xun @QiaoNPC
As the OSS project only controls the mermaid.live domain, we're adding an env variable to let anyone who is self hosting live editor to set their own privacy policy, or to hide the button if they want to.