{"owner":"mermaid-js","repo":"mermaid-live-editor","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\n## Commands\n\nUses pnpm (install via `corepack enable pnpm`). Node >= 24 required.\n\n- `pnpm dev` — dev server on http://localhost:3000\n- `pnpm build` — production build (static site, output to `docs/`)\n- `pnpm check` — svelte-check type checking\n- `pnpm lint` / `pnpm lint:fix` — prettier + eslint\n- `pnpm test:unit` — vitest in watch mode; `pnpm vitest run` for a single pass\n- Single unit test: `pnpm vitest run src/lib/util/serde.test.ts` (or `-t \"test name\"`)\n- `pnpm test:e2e` — Playwright tests in `tests/`; auto-starts the dev server on port 3000 (reuses one already running). `pnpm test:e2e:ui` / `:debug` for interactive runs\n- `pnpm test` — unit + e2e\n\nGotchas:\n\n- If `.claude/worktrees/` contains repo copies, vitest picks up their test files too — scope with `pnpm vitest run --dir src`.\n- Local Playwright runs can be flaky under parallel workers; retry or use `--workers=1` before assuming a real failure.\n- CI runs lint, check, unit tests, and Playwright (against a production build) on PRs to master.\n\n## Architecture\n\nSvelteKit 2 + Svelte 5 (runes) SPA using `@sveltejs/adapter-static`. **`docs/` is build output** (GitHub Pages convention) — never edit it. Routes: `/` (redirects), `/edit` (main editor), `/view` (read-only viewer).\n\n### State flow (the core of the app)\n\n`src/lib/util/state.svelte.ts` is the single source of truth:\n\n- `inputState` — a `$state` rune holding `State` (code, mermaid config JSON, pan/zoom, etc.), initialized from localStorage key `codeStore`. **All writes must go through the exported update functions** (`updateCode`, `updateCodeStore`, `updateConfig`, `replaceInputState`, ...), which call `persistAndProcess()`: persist to localStorage → async re-validate via `mermaid.parse` → publish to `validatedState`. Reads inside update functions are wrapped in `untrack` so calling effects don't depend on the whole input state.\n- `validatedState` — read-only validated snapshot (adds `error`, `errorMarkers`, `serialized`, `diagramType`). Internal reads should use this, but it is never persisted or shared externally.\n- The serialized state is mirrored into the URL hash (debounced) — the URL **is** the sharing mechanism. `src/lib/util/serde.ts` encodes state as `pako:<base64 deflate>` (legacy plain-base64 supported). `mermaid.ink` PNG/SVG links, Kroki, and Mermaid Chart URLs are derived from it in `urls`.\n- App startup goes through `initHandler()` in `src/lib/util/util.ts`: migrations → load state from URL hash → optional gist/URL loading (`fileLoaders/`) → start URL-hash subscription → analytics.\n\n### Persistence\n\n`src/lib/util/persist.svelte.ts` provides `readJSON`/`writeJSON` and a `persisted()` localStorage-backed rune, shared by state, migrations (`migrations.svelte.ts`), promos, and History. History (`src/lib/components/History/historyState.svelte.ts`) auto-saves a timeline of diagrams for the whole session (`startAutoSave()` in the edit page).\n\n### Rendering\n\n`src/lib/util/mermaid.ts` wraps mermaid and registers the ELK and tidy-tree layout engines plus ZenUML at module load. `View.svelte` renders the diagram; `panZoom.ts` wraps svg-pan-zoom; \"rough\" hand-drawn mode uses svg2roughjs. Sample diagrams come from `@mermaid-js/examples`.\n\n### Editors\n\nTwo editor implementations behind `Editor.svelte`: Monaco for desktop (`DesktopEditor.svelte`; custom mermaid language, completions, and error markers in `monacoExtra.ts`) and CodeMirror for mobile (`MobileEditor.svelte`). Both edit either the diagram code or the mermaid config JSON depending on `editorMode`.\n\n### Security\n\nStates loaded from URLs pass through `sanitizeConfig` (state.svelte.ts), which detects unsafe mermaid config (XSS vectors, prototype pollution, `secure` keys) and asks the user before stripping it. Keep this in mind when touching anything that deserializes external state.\n\n### UI / styling\n\n- shadcn-svelte components live in `src/lib/components/ui/` (bits-ui based, registry config in `components.json`) — treat as vendored; several lint rules are disabled there.\n- Tailwind CSS 4 (via `@tailwindcss/vite`).\n- Icons via unplugin-icons: `import X from '~icons/material-symbols/...'`; custom icons load from `static/icons` under `~icons/custom/*`.\n- Path alias: `$/*` → `src/lib/*` (in addition to SvelteKit's `$lib`).\n\n### Environment / build quirks\n\n- Env vars use the `MERMAID_` prefix (`import.meta.env`), read in `src/lib/util/env.ts`. Defaults in `.env`; copy to `.env.local` for local overrides. These control renderer URL (mermaid.ink), Kroki, analytics, and Mermaid Chart integration.\n- HMR is deliberately disabled — every change triggers a full page reload (see `alwaysFullReload` in `vite.config.js`) because HMR corrupts app state.\n- `vite.config.js` pins monaco/mermaid/codemirror into named vendor chunks for long-term caching — keep that intact when touching build config.\n\n## Conventions\n\n- ESLint enforces alphabetically sorted object keys in `src/` for objects with 5+ keys (`sort-keys/sort-keys-fix`), plus typescript-eslint strict and unicorn rules.\n- Unit tests are colocated with source (`*.test.ts` in `src/`); vitest runs with jsdom and also supports in-source tests (`import.meta.vitest`). Playwright e2e specs live in `tests/` and use `data-testid` constants from `src/lib/constants.ts` (`TID`).\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\n## Commands\n\nUses pnpm (install via `corepack enable pnpm`). Node >= 24 required.\n\n- `pnpm dev` — dev server on http://localhost:3000\n- `pnpm build` — production build (static site, output to `docs/`)\n- `pnpm check` — svelte-check type checking\n- `pnpm lint` / `pnpm lint:fix` — prettier + eslint\n- `pnpm test:unit` — vitest in watch mode; `pnpm vitest run` for a single pass\n- Single unit test: `pnpm vitest run src/lib/util/serde.test.ts` (or `-t \"test name\"`)\n- `pnpm test:e2e` — Playwright tests in `tests/`; auto-starts the dev server on port 3000 (reuses one already running). `pnpm test:e2e:ui` / `:debug` for interactive runs\n- `pnpm test` — unit + e2e\n\nGotchas:\n\n- If `.claude/worktrees/` contains repo copies, vitest picks up their test files too — scope with `pnpm vitest run --dir src`.\n- Local Playwright runs can be flaky under parallel workers; retry or use `--workers=1` before assuming a real failure.\n- CI runs lint, check, unit tests, and Playwright (against a production build) on PRs to master.\n\n## Architecture\n\nSvelteKit 2 + Svelte 5 (runes) SPA using `@sveltejs/adapter-static`. **`docs/` is build output** (GitHub Pages convention) — never edit it. Routes: `/` (redirects), `/edit` (main editor), `/view` (read-only viewer).\n\n### State flow (the core of the app)\n\n`src/lib/util/state.svelte.ts` is the single source of truth:\n\n- `inputState` — a `$state` rune holding `State` (code, mermaid config JSON, pan/zoom, etc.), initialized from localStorage key `codeStore`. **All writes must go through the exported update functions** (`updateCode`, `updateCodeStore`, `updateConfig`, `replaceInputState`, ...), which call `persistAndProcess()`: persist to localStorage → async re-validate via `mermaid.parse` → publish to `validatedState`. Reads inside update functions are wrapped in `untrack` so calling effects don't depend on the whole input state.\n- `validatedState` — read-only validated snapshot (adds `error`, `errorMarkers`, `serialized`, `diagramType`). Internal reads should use this, but it is never persisted or shared externally.\n- The serialized state is mirrored into the URL hash (debounced) — the URL **is** the sharing mechanism. `src/lib/util/serde.ts` encodes state as `pako:<base64 deflate>` (legacy plain-base64 supported). `mermaid.ink` PNG/SVG links, Kroki, and Mermaid Chart URLs are derived from it in `urls`.\n- App startup goes through `initHandler()` in `src/lib/util/util.ts`: migrations → load state from URL hash → optional gist/URL loading (`fileLoaders/`) → start URL-hash subscription → analytics.\n\n### Persistence\n\n`src/lib/util/persist.svelte.ts` provides `readJSON`/`writeJSON` and a `persisted()` localStorage-backed rune, shared by state, migrations (`migrations.svelte.ts`), promos, and History. History (`src/lib/components/History/historyState.svelte.ts`) auto-saves a timeline of diagrams for the whole session (`startAutoSave()` in the edit page).\n\n### Rendering\n\n`src/lib/util/mermaid.ts` wraps mermaid and registers the ELK and tidy-tree layout engines plus ZenUML at module load. `View.svelte` renders the diagram; `panZoom.ts` wraps svg-pan-zoom; \"rough\" hand-drawn mode uses svg2roughjs. Sample diagrams come from `@mermaid-js/examples`.\n\n### Editors\n\nTwo editor implementations behind `Editor.svelte`: Monaco for desktop (`DesktopEditor.svelte`; custom mermaid language, completions, and error markers in `monacoExtra.ts`) and CodeMirror for mobile (`MobileEditor.svelte`). Both edit either the diagram code or the mermaid config JSON depending on `editorMode`.\n\n### Security\n\nStates loaded from URLs pass through `sanitizeConfig` (state.svelte.ts), which detects unsafe mermaid config (XSS vectors, prototype pollution, `secure` keys) and asks the user before stripping it. Keep this in mind when touching anything that deserializes external state.\n\n### UI / styling\n\n- shadcn-svelte components live in `src/lib/components/ui/` (bits-ui based, registry config in `components.json`) — treat as vendored; several lint rules are disabled there.\n- Tailwind CSS 4 (via `@tailwindcss/vite`).\n- Icons via unplugin-icons: `import X from '~icons/material-symbols/...'`; custom icons load from `static/icons` under `~icons/custom/*`.\n- Path alias: `$/*` → `src/lib/*` (in addition to SvelteKit's `$lib`).\n\n### Environment / build quirks\n\n- Env vars use the `MERMAID_` prefix (`import.meta.env`), read in `src/lib/util/env.ts`. Defaults in `.env`; copy to `.env.local` for local overrides. These control renderer URL (mermaid.ink), Kroki, analytics, and Mermaid Chart integration.\n- HMR is deliberately disabled — every change triggers a full page reload (see `alwaysFullReload` in `vite.config.js`) because HMR corrupts app state.\n- `vite.config.js` pins monaco/mermaid/codemirror into named vendor chunks for long-term caching — keep that intact when touching build config.\n\n## Conventions\n\n- ESLint enforces alphabetically sorted object keys in `src/` for objects with 5+ keys (`sort-keys/sort-keys-fix`), plus typescript-eslint strict and unicorn rules.\n- Unit tests are colocated with source (`*.test.ts` in `src/`); vitest runs with jsdom and also supports in-source tests (`import.meta.vitest`). Playwright e2e specs live in `tests/` and use `data-testid` constants from `src/lib/constants.ts` (`TID`).\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\n## Commands\n\nUses pnpm (install via `corepack enable pnpm`). Node >= 24 required.\n\n- `pnpm dev` — dev server on http://localhost:3000\n- `pnpm build` — production build (static site, output to `docs/`)\n- `pnpm check` — svelte-check type checking\n- `pnpm lint` / `pnpm lint:fix` — prettier + eslint\n- `pnpm test:unit` — vitest in watch mode; `pnpm vitest run` for a single pass\n- Single unit test: `pnpm vitest run src/lib/util/serde.test.ts` (or `-t \"test name\"`)\n- `pnpm test:e2e` — Playwright tests in `tests/`; auto-starts the dev server on port 3000 (reuses one already running). `pnpm test:e2e:ui` / `:debug` for interactive runs\n- `pnpm test` — unit + e2e\n\nGotchas:\n\n- If `.claude/worktrees/` contains repo copies, vitest picks up their test files too — scope with `pnpm vitest run --dir src`.\n- Local Playwright runs can be flaky under parallel workers; retry or use `--workers=1` before assuming a real failure.\n- CI runs lint, check, unit tests, and Playwright (against a production build) on PRs to master.\n\n## Architecture\n\nSvelteKit 2 + Svelte 5 (runes) SPA using `@sveltejs/adapter-static`. **`docs/` is build output** (GitHub Pages convention) — never edit it. Routes: `/` (redirects), `/edit` (main editor), `/view` (read-only viewer).\n\n### State flow (the core of the app)\n\n`src/lib/util/state.svelte.ts` is the single source of truth:\n\n- `inputState` — a `$state` rune holding `State` (code, mermaid config JSON, pan/zoom, etc.), initialized from localStorage key `codeStore`. **All writes must go through the exported update functions** (`updateCode`, `updateCodeStore`, `updateConfig`, `replaceInputState`, ...), which call `persistAndProcess()`: persist to localStorage → async re-validate via `mermaid.parse` → publish to `validatedState`. Reads inside update functions are wrapped in `untrack` so calling effects don't depend on the whole input state.\n- `validatedState` — read-only validated snapshot (adds `error`, `errorMarkers`, `serialized`, `diagramType`). Internal reads should use this, but it is never persisted or shared externally.\n- The serialized state is mirrored into the URL hash (debounced) — the URL **is** the sharing mechanism. `src/lib/util/serde.ts` encodes state as `pako:<base64 deflate>` (legacy plain-base64 supported). `mermaid.ink` PNG/SVG links, Kroki, and Mermaid Chart URLs are derived from it in `urls`.\n- App startup goes through `initHandler()` in `src/lib/util/util.ts`: migrations → load state from URL hash → optional gist/URL loading (`fileLoaders/`) → start URL-hash subscription → analytics.\n\n### Persistence\n\n`src/lib/util/persist.svelte.ts` provides `readJSON`/`writeJSON` and a `persisted()` localStorage-backed rune, shared by state, migrations (`migrations.svelte.ts`), promos, and History. History (`src/lib/components/History/historyState.svelte.ts`) auto-saves a timeline of diagrams for the whole session (`startAutoSave()` in the edit page).\n\n### Rendering\n\n`src/lib/util/mermaid.ts` wraps mermaid and registers the ELK and tidy-tree layout engines plus ZenUML at module load. `View.svelte` renders the diagram; `panZoom.ts` wraps svg-pan-zoom; \"rough\" hand-drawn mode uses svg2roughjs. Sample diagrams come from `@mermaid-js/examples`.\n\n### Editors\n\nTwo editor implementations behind `Editor.svelte`: Monaco for desktop (`DesktopEditor.svelte`; custom mermaid language, completions, and error markers in `monacoExtra.ts`) and CodeMirror for mobile (`MobileEditor.svelte`). Both edit either the diagram code or the mermaid config JSON depending on `editorMode`.\n\n### Security\n\nStates loaded from URLs pass through `sanitizeConfig` (state.svelte.ts), which detects unsafe mermaid config (XSS vectors, prototype pollution, `secure` keys) and asks the user before stripping it. Keep this in mind when touching anything that deserializes external state.\n\n### UI / styling\n\n- shadcn-svelte components live in `src/lib/components/ui/` (bits-ui based, registry config in `components.json`) — treat as vendored; several lint rules are disabled there.\n- Tailwind CSS 4 (via `@tailwindcss/vite`).\n- Icons via unplugin-icons: `import X from '~icons/material-symbols/...'`; custom icons load from `static/icons` under `~icons/custom/*`.\n- Path alias: `$/*` → `src/lib/*` (in addition to SvelteKit's `$lib`).\n\n### Environment / build quirks\n\n- Env vars use the `MERMAID_` prefix (`import.meta.env`), read in `src/lib/util/env.ts`. Defaults in `.env`; copy to `.env.local` for local overrides. These control renderer URL (mermaid.ink), Kroki, analytics, and Mermaid Chart integration.\n- HMR is deliberately disabled — every change triggers a full page reload (see `alwaysFullReload` in `vite.config.js`) because HMR corrupts app state.\n- `vite.config.js` pins monaco/mermaid/codemirror into named vendor chunks for long-term caching — keep that intact when touching build config.\n\n## Conventions\n\n- ESLint enforces alphabetically sorted object keys in `src/` for objects with 5+ keys (`sort-keys/sort-keys-fix`), plus typescript-eslint strict and unicorn rules.\n- Unit tests are colocated with source (`*.test.ts` in `src/`); vitest runs with jsdom and also supports in-source tests (`import.meta.vitest`). Playwright e2e specs live in `tests/` and use `data-testid` constants from `src/lib/constants.ts` (`TID`).\n","category":"root","tokens":1321}]}