@classic-homes/theme-docs 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/lib/components/CodeBlock.svelte +73 -0
  2. package/dist/lib/components/CodeBlock.svelte.d.ts +16 -0
  3. package/dist/lib/components/DocsCard.svelte +99 -0
  4. package/dist/lib/components/DocsCard.svelte.d.ts +11 -0
  5. package/dist/lib/components/DocsHub.svelte +83 -0
  6. package/dist/lib/components/DocsHub.svelte.d.ts +28 -0
  7. package/dist/lib/components/MarkdownPage.svelte +100 -0
  8. package/dist/lib/components/MarkdownPage.svelte.d.ts +33 -0
  9. package/dist/lib/components/MermaidDiagram.svelte +87 -0
  10. package/dist/lib/components/MermaidDiagram.svelte.d.ts +14 -0
  11. package/dist/lib/components/MermaidInit.svelte +100 -0
  12. package/dist/lib/components/MermaidInit.svelte.d.ts +9 -0
  13. package/dist/lib/components/TableOfContents.svelte +179 -0
  14. package/dist/lib/components/TableOfContents.svelte.d.ts +16 -0
  15. package/dist/lib/components/TocPanel.svelte +263 -0
  16. package/dist/lib/components/TocPanel.svelte.d.ts +20 -0
  17. package/dist/lib/highlighter/index.d.ts +15 -0
  18. package/dist/lib/highlighter/index.js +78 -0
  19. package/dist/lib/index.d.ts +29 -0
  20. package/dist/lib/index.js +31 -0
  21. package/dist/lib/parser/extensions.d.ts +75 -0
  22. package/dist/lib/parser/extensions.js +311 -0
  23. package/dist/lib/parser/index.d.ts +57 -0
  24. package/dist/lib/parser/index.js +150 -0
  25. package/dist/lib/styles/markdown.css +516 -0
  26. package/dist/lib/types/docs.d.ts +72 -0
  27. package/dist/lib/types/docs.js +4 -0
  28. package/dist/lib/types/frontmatter.d.ts +68 -0
  29. package/dist/lib/types/frontmatter.js +4 -0
  30. package/dist/lib/types/index.d.ts +5 -0
  31. package/dist/lib/types/index.js +4 -0
  32. package/dist/lib/utils.d.ts +6 -0
  33. package/dist/lib/utils.js +9 -0
  34. package/package.json +68 -0
@@ -0,0 +1,73 @@
1
+ <script lang="ts">
2
+ /**
3
+ * CodeBlock - Standalone syntax-highlighted code block
4
+ *
5
+ * For use outside of markdown content when you need
6
+ * to display code with highlighting directly.
7
+ */
8
+ import { onMount } from 'svelte';
9
+ import { cn } from '../utils.js';
10
+ import { escapeHtml } from '../highlighter/index.js';
11
+
12
+ interface Props {
13
+ /** Code to highlight */
14
+ code: string;
15
+ /** Language for syntax highlighting */
16
+ language?: string;
17
+ /** Shiki theme */
18
+ theme?: string;
19
+ /** Custom class */
20
+ class?: string;
21
+ /** Optional filename to display */
22
+ filename?: string;
23
+ [key: string]: unknown;
24
+ }
25
+
26
+ let {
27
+ code,
28
+ language = 'text',
29
+ theme = 'github-dark',
30
+ class: className,
31
+ filename,
32
+ ...restProps
33
+ }: Props = $props();
34
+
35
+ let highlighted = $state('');
36
+ let loading = $state(true);
37
+
38
+ onMount(async () => {
39
+ try {
40
+ const { highlightCode } = await import('../highlighter/index.js');
41
+ highlighted = await highlightCode(code, language, { theme });
42
+ loading = false;
43
+ } catch (err) {
44
+ // Log warning for debugging - falling back to plain code
45
+ console.warn(
46
+ '[docs] Failed to highlight code block, showing plain code:',
47
+ err instanceof Error ? err.message : err
48
+ );
49
+ highlighted = `<pre class="shiki bg-muted rounded-lg p-4 overflow-x-auto"><code>${escapeHtml(code)}</code></pre>`;
50
+ loading = false;
51
+ }
52
+ });
53
+ </script>
54
+
55
+ <div class={cn('code-block-wrapper', className)} {...restProps}>
56
+ {#if filename}
57
+ <div
58
+ class="code-block-filename bg-muted/50 px-4 py-2 text-sm text-muted-foreground border-b border-border rounded-t-lg font-mono"
59
+ >
60
+ {filename}
61
+ </div>
62
+ {/if}
63
+
64
+ {#if loading}
65
+ <div class="code-block-loading">
66
+ <pre class="bg-muted rounded-lg p-4 overflow-x-auto"><code class="text-sm font-mono"
67
+ >{code}</code
68
+ ></pre>
69
+ </div>
70
+ {:else}
71
+ {@html highlighted}
72
+ {/if}
73
+ </div>
@@ -0,0 +1,16 @@
1
+ interface Props {
2
+ /** Code to highlight */
3
+ code: string;
4
+ /** Language for syntax highlighting */
5
+ language?: string;
6
+ /** Shiki theme */
7
+ theme?: string;
8
+ /** Custom class */
9
+ class?: string;
10
+ /** Optional filename to display */
11
+ filename?: string;
12
+ [key: string]: unknown;
13
+ }
14
+ declare const CodeBlock: import("svelte").Component<Props, {}, "">;
15
+ type CodeBlock = ReturnType<typeof CodeBlock>;
16
+ export default CodeBlock;
@@ -0,0 +1,99 @@
1
+ <script lang="ts">
2
+ /**
3
+ * DocsCard - Individual documentation card for DocsHub
4
+ *
5
+ * Displays a single documentation item with title, description,
6
+ * optional icon, and optional badge.
7
+ */
8
+ import { cn } from '../utils.js';
9
+ import { tv } from 'tailwind-variants';
10
+ import type { DocsItem } from '../types/docs.js';
11
+
12
+ const docsCardVariants = tv({
13
+ base: 'group relative flex flex-col rounded-lg border border-border bg-card p-6 transition-all hover:border-primary hover:shadow-md',
14
+ });
15
+
16
+ interface Props {
17
+ /** Documentation item to display */
18
+ item: DocsItem;
19
+ /** Custom class */
20
+ class?: string;
21
+ [key: string]: unknown;
22
+ }
23
+
24
+ let { item, class: className, ...restProps }: Props = $props();
25
+ </script>
26
+
27
+ <a
28
+ href={item.href}
29
+ class={cn(docsCardVariants(), className)}
30
+ target={item.external ? '_blank' : undefined}
31
+ rel={item.external ? 'noopener noreferrer' : undefined}
32
+ aria-label={item.external ? `${item.title} (opens in new tab)` : undefined}
33
+ {...restProps}
34
+ >
35
+ {#if item.badge}
36
+ <span
37
+ class="absolute -top-2 -right-2 rounded-full px-2 py-0.5 text-xs font-medium {item.badge ===
38
+ 'new'
39
+ ? 'bg-primary text-primary-foreground'
40
+ : item.badge === 'updated'
41
+ ? 'bg-blue-600 text-white'
42
+ : item.badge === 'deprecated'
43
+ ? 'bg-destructive text-destructive-foreground'
44
+ : 'bg-muted text-foreground'}"
45
+ >
46
+ {item.badge}
47
+ </span>
48
+ {/if}
49
+
50
+ <div class="flex items-start gap-4">
51
+ {#if item.icon}
52
+ <div
53
+ class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary"
54
+ >
55
+ <span class="text-lg">{item.icon}</span>
56
+ </div>
57
+ {/if}
58
+
59
+ <div class="flex-1 min-w-0">
60
+ <h3
61
+ class="font-semibold text-foreground group-hover:text-primary transition-colors flex items-center gap-2"
62
+ >
63
+ {item.title}
64
+ {#if item.external}
65
+ <svg
66
+ class="h-4 w-4 text-muted-foreground"
67
+ fill="none"
68
+ stroke="currentColor"
69
+ viewBox="0 0 24 24"
70
+ aria-hidden="true"
71
+ >
72
+ <path
73
+ stroke-linecap="round"
74
+ stroke-linejoin="round"
75
+ stroke-width="2"
76
+ d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
77
+ />
78
+ </svg>
79
+ {/if}
80
+ </h3>
81
+
82
+ {#if item.description}
83
+ <p class="mt-1 text-sm text-muted-foreground line-clamp-2">
84
+ {item.description}
85
+ </p>
86
+ {/if}
87
+
88
+ {#if item.tags && item.tags.length > 0}
89
+ <div class="mt-3 flex flex-wrap gap-1">
90
+ {#each item.tags as tag}
91
+ <span class="rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground">
92
+ {tag}
93
+ </span>
94
+ {/each}
95
+ </div>
96
+ {/if}
97
+ </div>
98
+ </div>
99
+ </a>
@@ -0,0 +1,11 @@
1
+ import type { DocsItem } from '../types/docs.js';
2
+ interface Props {
3
+ /** Documentation item to display */
4
+ item: DocsItem;
5
+ /** Custom class */
6
+ class?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ declare const DocsCard: import("svelte").Component<Props, {}, "">;
10
+ type DocsCard = ReturnType<typeof DocsCard>;
11
+ export default DocsCard;
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ /**
3
+ * DocsHub - Documentation navigation and index component
4
+ *
5
+ * Features:
6
+ * - Card-based layout for documentation entries
7
+ * - Category/section grouping
8
+ * - Responsive grid layout
9
+ */
10
+ import type { Snippet } from 'svelte';
11
+ import { cn } from '../utils.js';
12
+ import { tv, type VariantProps } from 'tailwind-variants';
13
+ import DocsCard from './DocsCard.svelte';
14
+ import type { DocsHubConfig, DocsSection, DocsItem } from '../types/docs.js';
15
+
16
+ const docsHubVariants = tv({
17
+ slots: {
18
+ container: '',
19
+ sectionContainer: 'mb-8',
20
+ sectionTitle: 'text-2xl font-bold text-foreground mb-2',
21
+ sectionDescription: 'text-muted-foreground mb-6',
22
+ grid: 'grid gap-4',
23
+ },
24
+ variants: {
25
+ columns: {
26
+ 1: { grid: 'grid-cols-1' },
27
+ 2: { grid: 'grid-cols-1 md:grid-cols-2' },
28
+ 3: { grid: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3' },
29
+ 4: { grid: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4' },
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ columns: 3,
34
+ },
35
+ });
36
+
37
+ type DocsHubVariants = VariantProps<typeof docsHubVariants>;
38
+
39
+ interface Props {
40
+ /** Documentation configuration */
41
+ config: DocsHubConfig;
42
+ /** Number of columns in the grid */
43
+ columns?: DocsHubVariants['columns'];
44
+ /** Custom class for the container */
45
+ class?: string;
46
+ /** Optional custom card renderer */
47
+ card?: Snippet<[{ item: DocsItem; section: DocsSection }]>;
48
+ /** Optional header slot */
49
+ header?: Snippet;
50
+ [key: string]: unknown;
51
+ }
52
+
53
+ let { config, columns = 3, class: className, card, header, ...restProps }: Props = $props();
54
+
55
+ const styles = $derived(docsHubVariants({ columns }));
56
+ </script>
57
+
58
+ <div class={cn(styles.container(), className)} {...restProps}>
59
+ {#if header}
60
+ {@render header()}
61
+ {/if}
62
+
63
+ {#each config.sections as section}
64
+ <div class={styles.sectionContainer()}>
65
+ {#if section.title}
66
+ <h2 class={styles.sectionTitle()}>{section.title}</h2>
67
+ {/if}
68
+ {#if section.description}
69
+ <p class={styles.sectionDescription()}>{section.description}</p>
70
+ {/if}
71
+
72
+ <div class={styles.grid()}>
73
+ {#each section.items as item}
74
+ {#if card}
75
+ {@render card({ item, section })}
76
+ {:else}
77
+ <DocsCard {item} />
78
+ {/if}
79
+ {/each}
80
+ </div>
81
+ </div>
82
+ {/each}
83
+ </div>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * DocsHub - Documentation navigation and index component
3
+ *
4
+ * Features:
5
+ * - Card-based layout for documentation entries
6
+ * - Category/section grouping
7
+ * - Responsive grid layout
8
+ */
9
+ import type { Snippet } from 'svelte';
10
+ import type { DocsHubConfig, DocsSection, DocsItem } from '../types/docs.js';
11
+ declare const DocsHub: import("svelte").Component<{
12
+ [key: string]: unknown;
13
+ /** Documentation configuration */
14
+ config: DocsHubConfig;
15
+ /** Number of columns in the grid */
16
+ columns?: 1 | 2 | 3 | 4 | undefined;
17
+ /** Custom class for the container */
18
+ class?: string;
19
+ /** Optional custom card renderer */
20
+ card?: Snippet<[{
21
+ item: DocsItem;
22
+ section: DocsSection;
23
+ }]>;
24
+ /** Optional header slot */
25
+ header?: Snippet;
26
+ }, {}, "">;
27
+ type DocsHub = ReturnType<typeof DocsHub>;
28
+ export default DocsHub;
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ /**
3
+ * MarkdownPage - Core markdown renderer with frontmatter and syntax highlighting
4
+ *
5
+ * Features:
6
+ * - YAML frontmatter parsing with gray-matter
7
+ * - Shiki syntax highlighting for code blocks
8
+ * - Loading and error states
9
+ * - Configurable styling
10
+ * - Optional Table of Contents generation
11
+ */
12
+ import type { Snippet } from 'svelte';
13
+ import { cn } from '../utils.js';
14
+ import type { FrontmatterData } from '../types/index.js';
15
+
16
+ interface Props {
17
+ /** Raw markdown content (with optional frontmatter) */
18
+ content: string;
19
+ /** Custom class for the content container */
20
+ class?: string;
21
+ /** Custom header snippet (receives frontmatter data) */
22
+ header?: Snippet<[FrontmatterData | null]>;
23
+ /** Custom error display snippet */
24
+ errorSlot?: Snippet<[string]>;
25
+ /** Shiki theme to use */
26
+ theme?: 'github-dark' | 'github-light' | 'one-dark-pro' | string;
27
+ /** Callback when content is parsed */
28
+ onParsed?: (data: { frontmatter: FrontmatterData | null; html: string }) => void;
29
+ [key: string]: unknown;
30
+ }
31
+
32
+ let {
33
+ content,
34
+ class: className,
35
+ header,
36
+ errorSlot,
37
+ theme = 'github-dark',
38
+ onParsed,
39
+ ...restProps
40
+ }: Props = $props();
41
+
42
+ let htmlContent = $state('');
43
+ let frontmatter = $state<FrontmatterData | null>(null);
44
+ let loading = $state(true);
45
+ let error = $state('');
46
+
47
+ // Use $effect to react to content changes (enables proper navigation)
48
+ $effect(() => {
49
+ // Track content as a dependency
50
+ const currentContent = content;
51
+
52
+ // Reset state for new content
53
+ loading = true;
54
+ error = '';
55
+
56
+ (async () => {
57
+ try {
58
+ const { parseMarkdown } = await import('../parser/index.js');
59
+ const result = await parseMarkdown(currentContent, { theme });
60
+
61
+ frontmatter = result.frontmatter;
62
+ htmlContent = result.html;
63
+ loading = false;
64
+
65
+ onParsed?.({ frontmatter, html: htmlContent });
66
+ } catch (err: unknown) {
67
+ error = err instanceof Error ? err.message : 'Failed to parse markdown';
68
+ loading = false;
69
+ }
70
+ })();
71
+ });
72
+ </script>
73
+
74
+ {#if header && frontmatter}
75
+ {@render header(frontmatter)}
76
+ {/if}
77
+
78
+ {#if error}
79
+ {#if errorSlot}
80
+ {@render errorSlot(error)}
81
+ {:else}
82
+ <div class="rounded-lg border border-destructive bg-destructive/10 p-4 text-destructive">
83
+ {error}
84
+ </div>
85
+ {/if}
86
+ {/if}
87
+
88
+ {#if loading}
89
+ <div class="flex items-center justify-center py-12">
90
+ <div
91
+ class="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent"
92
+ ></div>
93
+ </div>
94
+ {/if}
95
+
96
+ {#if !loading && !error}
97
+ <div class={cn('markdown-content', className)} {...restProps}>
98
+ {@html htmlContent}
99
+ </div>
100
+ {/if}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * MarkdownPage - Core markdown renderer with frontmatter and syntax highlighting
3
+ *
4
+ * Features:
5
+ * - YAML frontmatter parsing with gray-matter
6
+ * - Shiki syntax highlighting for code blocks
7
+ * - Loading and error states
8
+ * - Configurable styling
9
+ * - Optional Table of Contents generation
10
+ */
11
+ import type { Snippet } from 'svelte';
12
+ import type { FrontmatterData } from '../types/index.js';
13
+ interface Props {
14
+ /** Raw markdown content (with optional frontmatter) */
15
+ content: string;
16
+ /** Custom class for the content container */
17
+ class?: string;
18
+ /** Custom header snippet (receives frontmatter data) */
19
+ header?: Snippet<[FrontmatterData | null]>;
20
+ /** Custom error display snippet */
21
+ errorSlot?: Snippet<[string]>;
22
+ /** Shiki theme to use */
23
+ theme?: 'github-dark' | 'github-light' | 'one-dark-pro' | string;
24
+ /** Callback when content is parsed */
25
+ onParsed?: (data: {
26
+ frontmatter: FrontmatterData | null;
27
+ html: string;
28
+ }) => void;
29
+ [key: string]: unknown;
30
+ }
31
+ declare const MarkdownPage: import("svelte").Component<Props, {}, "">;
32
+ type MarkdownPage = ReturnType<typeof MarkdownPage>;
33
+ export default MarkdownPage;
@@ -0,0 +1,87 @@
1
+ <script lang="ts">
2
+ /**
3
+ * MermaidDiagram - Client-side Mermaid diagram renderer
4
+ *
5
+ * Renders Mermaid diagrams from code. Can be used standalone or
6
+ * automatically initialized on markdown-rendered mermaid blocks.
7
+ *
8
+ * Requires mermaid to be installed in the consuming application:
9
+ * npm install mermaid
10
+ */
11
+ import { onMount } from 'svelte';
12
+ import { cn } from '../utils.js';
13
+
14
+ interface Props {
15
+ /** Mermaid diagram code */
16
+ code: string;
17
+ /** Custom class */
18
+ class?: string;
19
+ /** Unique ID for the diagram (auto-generated if not provided) */
20
+ id?: string;
21
+ /** Mermaid theme (default: 'default') */
22
+ theme?: 'default' | 'dark' | 'forest' | 'neutral';
23
+ [key: string]: unknown;
24
+ }
25
+
26
+ let {
27
+ code,
28
+ class: className,
29
+ id = `mermaid-${Math.random().toString(36).slice(2, 9)}`,
30
+ theme = 'default',
31
+ ...restProps
32
+ }: Props = $props();
33
+
34
+ let containerRef = $state<HTMLDivElement | null>(null);
35
+ let rendered = $state(false);
36
+ let error = $state<string | null>(null);
37
+
38
+ onMount(async () => {
39
+ if (!containerRef) return;
40
+
41
+ try {
42
+ // Dynamically import mermaid to avoid SSR issues
43
+ const mermaid = await import('mermaid');
44
+
45
+ // Initialize mermaid with theme
46
+ mermaid.default.initialize({
47
+ startOnLoad: false,
48
+ theme: theme,
49
+ securityLevel: 'strict',
50
+ });
51
+
52
+ // Render the diagram
53
+ const { svg } = await mermaid.default.render(id, code);
54
+ containerRef.innerHTML = svg;
55
+ rendered = true;
56
+ } catch (err) {
57
+ console.warn(
58
+ '[docs] Failed to render Mermaid diagram:',
59
+ err instanceof Error ? err.message : err
60
+ );
61
+ error = err instanceof Error ? err.message : 'Failed to render diagram';
62
+ }
63
+ });
64
+ </script>
65
+
66
+ <div
67
+ bind:this={containerRef}
68
+ class={cn(
69
+ 'mermaid-container',
70
+ !rendered && !error && 'mermaid-loading',
71
+ error && 'mermaid-error',
72
+ className
73
+ )}
74
+ {...restProps}
75
+ >
76
+ {#if !rendered && !error}
77
+ <!-- Show code as fallback while loading -->
78
+ <pre class="mermaid-fallback"><code>{code}</code></pre>
79
+ {/if}
80
+ {#if error}
81
+ <div class="mermaid-error-message">
82
+ <p class="mermaid-error-title">Failed to render diagram</p>
83
+ <pre class="mermaid-error-code"><code>{code}</code></pre>
84
+ <p class="mermaid-error-details">{error}</p>
85
+ </div>
86
+ {/if}
87
+ </div>
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ /** Mermaid diagram code */
3
+ code: string;
4
+ /** Custom class */
5
+ class?: string;
6
+ /** Unique ID for the diagram (auto-generated if not provided) */
7
+ id?: string;
8
+ /** Mermaid theme (default: 'default') */
9
+ theme?: 'default' | 'dark' | 'forest' | 'neutral';
10
+ [key: string]: unknown;
11
+ }
12
+ declare const MermaidDiagram: import("svelte").Component<Props, {}, "">;
13
+ type MermaidDiagram = ReturnType<typeof MermaidDiagram>;
14
+ export default MermaidDiagram;
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ /**
3
+ * MermaidInit - Auto-initialize all Mermaid diagrams on the page
4
+ *
5
+ * Place this component once in your layout or page to automatically
6
+ * render all mermaid diagrams from markdown content.
7
+ *
8
+ * Requires mermaid to be installed in the consuming application:
9
+ * npm install mermaid
10
+ */
11
+ import { onMount } from 'svelte';
12
+
13
+ interface Props {
14
+ /** Mermaid theme (default: 'default') */
15
+ theme?: 'default' | 'dark' | 'forest' | 'neutral';
16
+ /** Whether to watch for new diagrams via MutationObserver */
17
+ watch?: boolean;
18
+ }
19
+
20
+ let { theme = 'default', watch = false }: Props = $props();
21
+
22
+ let initialized = $state(false);
23
+
24
+ async function renderDiagrams() {
25
+ try {
26
+ const mermaid = await import('mermaid');
27
+
28
+ // Initialize mermaid
29
+ mermaid.default.initialize({
30
+ startOnLoad: false,
31
+ theme: theme,
32
+ securityLevel: 'strict',
33
+ });
34
+
35
+ // Find all mermaid diagram placeholders
36
+ const diagrams = document.querySelectorAll('.mermaid-diagram[data-mermaid]');
37
+
38
+ for (const diagram of diagrams) {
39
+ const code = diagram.getAttribute('data-mermaid');
40
+ if (!code || diagram.classList.contains('mermaid-rendered')) continue;
41
+
42
+ try {
43
+ const id = `mermaid-${Math.random().toString(36).slice(2, 9)}`;
44
+ const { svg } = await mermaid.default.render(id, code);
45
+
46
+ // Replace the placeholder with the rendered SVG
47
+ diagram.innerHTML = svg;
48
+ diagram.classList.add('mermaid-rendered');
49
+ diagram.removeAttribute('data-mermaid');
50
+ } catch (err) {
51
+ console.warn(
52
+ '[docs] Failed to render Mermaid diagram:',
53
+ err instanceof Error ? err.message : err
54
+ );
55
+ diagram.classList.add('mermaid-error');
56
+ }
57
+ }
58
+
59
+ initialized = true;
60
+ } catch (err) {
61
+ // Mermaid not installed - that's okay, diagrams will show as code
62
+ console.warn('[docs] Mermaid library not available. Install with: npm install mermaid');
63
+ }
64
+ }
65
+
66
+ onMount(() => {
67
+ renderDiagrams();
68
+
69
+ if (watch) {
70
+ // Watch for new diagrams being added to the DOM
71
+ const observer = new MutationObserver((mutations) => {
72
+ for (const mutation of mutations) {
73
+ if (mutation.type === 'childList') {
74
+ const hasNewDiagrams = Array.from(mutation.addedNodes).some(
75
+ (node) =>
76
+ node instanceof HTMLElement &&
77
+ (node.classList?.contains('mermaid-diagram') ||
78
+ node.querySelector?.('.mermaid-diagram[data-mermaid]'))
79
+ );
80
+ if (hasNewDiagrams) {
81
+ renderDiagrams();
82
+ }
83
+ }
84
+ }
85
+ });
86
+
87
+ observer.observe(document.body, {
88
+ childList: true,
89
+ subtree: true,
90
+ });
91
+
92
+ return () => observer.disconnect();
93
+ }
94
+ });
95
+ </script>
96
+
97
+ <!-- This component has no visual output, it just initializes mermaid -->
98
+ {#if !initialized}
99
+ <!-- Hidden slot for loading state if needed -->
100
+ {/if}
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ /** Mermaid theme (default: 'default') */
3
+ theme?: 'default' | 'dark' | 'forest' | 'neutral';
4
+ /** Whether to watch for new diagrams via MutationObserver */
5
+ watch?: boolean;
6
+ }
7
+ declare const MermaidInit: import("svelte").Component<Props, {}, "">;
8
+ type MermaidInit = ReturnType<typeof MermaidInit>;
9
+ export default MermaidInit;