Commit Graph
705 Commits
Author SHA1 Message Date
Sidharth VinodandGitHub 7f08e5b970 Merge pull request #1987 from mermaid-js/sidv/examplesSelection
feat: add example picker dropdown to sample diagrams
2026-06-10 18:43:03 +00:00
Sidharth VinodandClaude Fable 5 a257f78d8e feat: add example picker dropdown to sample diagrams
Each diagram type in the Sample Diagrams panel is now a split button:
clicking the diagram name loads its default example, and a dropdown
arrow on the right (shown when a diagram has more than one example)
opens a popover listing all examples for that diagram.

- getSampleDiagrams now returns all examples per diagram with the
  default example first, instead of flattening to the default's code
- loadSampleDiagram analytics now include the chosen example title

https://claude.ai/code/session_015rUgHChBEkquLu77fMxmQ6

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:09:45 +05:30
Sidharth VinodandClaude Fable 5 c253054916 refactor: Make persisted() values raw state
The getter handed out a deep $state proxy, so in-place mutation of a
persisted array/record would update the UI while silently never being
written to localStorage. All consumers already replace .value wholesale;
$state.raw makes that the only semantics and drops the per-read proxy
overhead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:57:27 +05:30
Sidharth VinodandClaude Fable 5 d2f067a540 refactor: Route every input state mutation through one untracked gateway
The untrack()/persistAndProcess() pair was a per-function convention:
each update function had to remember both, a forgotten untrack would let
calling effects subscribe to input state (the bug fixed in 6a9a306e),
and a forgotten persistAndProcess would silently skip persistence and
re-validation. A single update(mutate) gateway now makes both structural,
and the scattered untrack calls (three of which were dead) are gone.

Also:
- Export inputState as Readonly<State> so writes outside the update
  functions are type errors instead of comment violations.
- Share the 'codeStore' key as a constant instead of two literals.
- Reuse validatedStateOf() in processState instead of duplicating the
  validated-state defaults.
- Use $state.raw for validatedCurrent: it is only ever replaced
  wholesale, so deep proxying every published state was pure overhead.

The new state.svelte.test.ts pins the invariants: update functions never
make a calling effect track input state, and every mutation persists.
Vitest needed resolve.conditions=['browser'] for those tests — it was
loading Svelte's server build, where $effect is a no-op.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:57:01 +05:30
Sidharth VinodandClaude Fable 5 59105628f4 fix: Treat a stored JSON null as a missing persisted value
readJSON returned any successfully parsed value, so a localStorage
entry holding the literal "null" came back as null instead of the
fallback — and a null inputState crashes module init on every load
until storage is cleared. The deleted MacFJA persist layer guarded
this with `null !== initialValue`; restore that behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:53:00 +05:30
Sidharth VinodandClaude Fable 5 144b4dc190 fix: Stop mobile editor from reverting keystrokes
currentText was $state, and the validated-state sync $effect both reads
and writes it. Every keystroke (which sets currentText in the CodeMirror
updateListener) therefore re-ran the effect while re-validation was
still in flight, dispatching a full-document replacement with the stale
validatedState text — visibly reverting the keystroke and resetting the
cursor until validation caught up.

The effect only needs to react to validatedState publishes, so make
currentText a plain variable, matching DesktopEditor.

No unit test: the repo has no component-test harness, and CodeMirror
cannot mount under jsdom without one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:51:57 +05:30
Sidharth VinodandClaude Fable 5 6a9a306ed7 fix: Untrack input state reads inside state update functions
toggleDarkTheme runs inside the layout $effect; without untrack the
effect starts depending on inputState.mermaid and re-adds the default
theme whenever a loaded config replaces it (caught by the unsafe-config
scrub e2e test).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:44:16 +05:30
Sidharth VinodandClaude Fable 5 c9cfaa10e7 refactor: Replace vendored svelte-persistent-store with shared persisted rune
History now uses the shared persist.svelte helpers, the MacFJA store
copy is deleted, and the esserializer dependency it required is dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:37:53 +05:30
Sidharth VinodandClaude Fable 5 ed06c07c06 refactor: Migrate hidden promotions store to the persisted rune
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:36:58 +05:30
Sidharth VinodandClaude Fable 5 a49503a1f0 refactor: Migrate the migrations store to the persisted rune
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:35:41 +05:30
Sidharth VinodandClaude Fable 5 81aaafc085 refactor: Migrate loading state from svelte/store to runes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:35:00 +05:30
Sidharth VinodandClaude Fable 5 b3c8bd6c28 refactor: Migrate editor state from svelte/store to runes
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>
2026-06-10 00:34:07 +05:30
Sidharth VinodandClaude Fable 5 ca96ca8771 feat: Add shared runes-based localStorage persistence module
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:23:48 +05:30
Sidharth Vinod 49c5928202 fix: Resolve URLs in urlsStore 2026-06-09 19:32:08 +05:30
Sidharth VinodandClaude Opus 4.8 f25b3c82cd refactor: De-duplicate mode routing and drop dead getStateString
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>
2026-06-08 20:28:50 +05:30
Sidharth VinodandClaude Opus 4.8 2db9355b7b fix: Accept time:0 entries and precompute history entry URLs
Code-review follow-ups:
- validateEntry no longer rejects entries whose time is 0 (epoch); it now
  checks `typeof time === 'number'`, so restoring/uploading such entries
  works instead of silently dropping them.
- History.svelte serializes each entry's "open in new tab" URL once via a
  $derived list instead of calling serializeState (pako deflate) per row on
  every render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:22:40 +05:30
Sidharth VinodandClaude Opus 4.8 8dd9cb49a0 feat: Add "open in new tab" link to history entries
Each history entry now has a third action: a real anchor (rendered via
the Button's href, target="_blank") linking to the editor with that
entry's serialized state. Being a normal link, users can also copy it or
open it in a new tab via the context menu.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:03:31 +05:30
Sidharth VinodandClaude Opus 4.8 64e8822e32 fix: Make svelte-check pass and resolve TS6/Svelte 5.56 type errors
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>
2026-06-08 19:53:25 +05:30
Sidharth VinodandClaude Opus 4.8 e6333e9d7f refactor: Convert history state to Svelte 5 runes + add svelte-check
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>
2026-06-08 19:28:38 +05:30
Sidharth VinodandClaude Opus 4.8 3628acec02 fix: Rewrite Timeline/Saved history state and UI handling
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>
2026-06-08 19:27:23 +05:30
Sidharth VinodandCursor 1f0812496e fix: prevent state feedback loop when updating Monaco via executeEdits
Guard programmatic editor updates so sample diagrams and URL loads do not re-trigger onUpdate, which caused infinite state/URL churn and failing e2e tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 18:40:07 +05:30
Sidharth Vinod c62ebf6d09 fix: #1753 Undo in Monaco 2026-06-08 18:14:56 +05:30
Sidharth VinodandCursor c25675d418 chore: update all dependencies to latest versions
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>
2026-06-08 17:47:38 +05:30
Sidharth VinodandCursor 55d9bd043f refactor: Inline editor chooser modal content
Remove the separate testB component now that the A/B test is over.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 15:49:44 +05:30
Sidharth VinodandCursor adf3ddf015 feat: Ship editor chooser testB and use live_2026 UTM campaign
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>
2026-05-29 15:45:04 +05:30
Sidharth VinodandGitHub 1bd6355ea8 Merge pull request #1938 from mermaid-js/sidv/editorChooserExperiments
feat(MC-4486): Add variations to editor picker
2026-04-23 14:32:44 +05:30
Sidharth Vinod b446c37315 chore: Add enhanced edit button 2026-04-23 13:31:19 +05:30
Sidharth Vinod 031477cda9 fix: Update tagline and layout 2026-04-23 13:05:45 +05:30
Sidharth Vinod a9becf5509 fix: copy 2026-04-22 22:37:01 +05:30
Sidharth Vinod 79c4b3bf55 chore: Add noopener 2026-04-22 21:04:00 +05:30
Sidharth Vinod a61a69e477 fix: Show picker on netlify 2026-04-22 18:58:31 +05:30
Sidharth Vinod 1daac45c87 feat(MC-4486): Add variations to editor picker 2026-04-22 18:52:02 +05:30
Alois KlinkandGitHub 4925de94a9 Merge commit from fork
fix: improve sanitization of mermaid config
2026-04-10 21:35:24 +09:00
Alois Klink 46a7a533ab fix: copy mermaid config sanitization check
Copy the XSS prevention check from the `sanitize` function in mermaid
upstream's `config.ts` file.

See: https://github.com/mermaid-js/mermaid/blob/9745f325cb9e1967640f0e85da193a2f820634f1/packages/mermaid/src/config.ts#L178-L183
2026-04-02 19:00:54 +09:00
Alois Klink 67aacdebe4 fix: sanitize config for __ keys
According to upstream, this is supposed to be fore prototype pollution
prevention.

See: https://github.com/mermaid-js/mermaid/blob/9745f325cb9e1967640f0e85da193a2f820634f1/packages/mermaid/src/config.ts#L169-L174
2026-04-02 19:00:54 +09:00
Alois Klink 7e9cdfca73 fix: sanitize all secure keys in config
Check and remove all the secure keys in the site Mermaid Config,
not just `securityLevel`. Unfortunately, the logic of Mermaid's
`sanitize` function in `config.ts` is a bit convoluted. For instance,
the `secure` config restricts keys deeply in the object.

See: https://github.com/mermaid-js/mermaid/blob/9745f325cb9e1967640f0e85da193a2f820634f1/packages/mermaid/src/config.ts#L155-L190
2026-04-02 19:00:54 +09:00
Alois Klink 48b9560e8e fix: sanitize config loaded from gist/config URL
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
2026-04-02 18:59:09 +09:00
Sidharth Vinod 62699769d5 fix: Use {} instead of undefined 2026-04-01 22:19:02 +05:30
Sidharth Vinod 5608dc5661 feat: Add visual editor button 2026-04-01 21:50:18 +05:30
Sidharth VinodandGitHub 29e92a9702 Merge pull request #1917 from mermaid-js/sidv/fixBasePath
fix(#1914): Resolve base path
2026-04-01 15:13:59 +00:00
Sidharth Vinod 0e0da3b1e9 chore: Reduce Error debounce interval 2026-04-01 20:43:15 +05:30
Sidharth Vinod d273e1d722 fix: Asset links 2026-03-30 21:30:13 +05:30
Sidharth Vinod c799dff042 fix(#1914): Resolve redirectURL considering base path 2026-03-30 21:24:33 +05:30
Alois Klink ae7ad1b93e refactor: move config sanitization into function
Moves the code that prompts the user to remove unsafe MermaidConfig
settings into it's own function, so that it can be reused.
2026-03-30 17:06:32 +09:00
Sidharth Vinod c675dc02e9 fix: Avoid double popups 2026-03-25 17:03:04 +09:00
Sidharth Vinod ab760f35fa feat: Retain search query in URL to get insights into traffic flow 2026-03-18 22:05:07 +09:00
Sidharth Vinod d7db71e38a chore: Add new mermaid home button 2026-03-16 23:29:49 +09:00
Sidharth Vinod b466e8430e feat: Show mermaid.live privacy policy only on mermaid.live
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.
2026-03-16 23:29:13 +09:00
Sidharth Vinod 15cdb7b64a chore: Show editor picker once to existing users as well 2026-03-12 13:35:42 +09:00
Sidharth Vinod 340911f271 chore: Remove panZoom event 2026-03-05 23:28:34 +05:30