astro-mermaid 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # astro-mermaid
2
+
3
+ An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering.
4
+
5
+ ## Features
6
+
7
+ - 🎨 Automatic theme switching based on your site's theme
8
+ - 🚀 Client-side rendering for optimal performance
9
+ - 📝 Simple markdown syntax using code blocks
10
+ - ⚡ Vite optimization for fast development
11
+ - 🔧 Customizable mermaid configuration
12
+ - 🎯 TypeScript support
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install astro-mermaid mermaid
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Add the integration to your `astro.config.mjs`:
23
+
24
+ ```js
25
+ import { defineConfig } from 'astro/config';
26
+ import mermaid from 'astro-mermaid';
27
+
28
+ export default defineConfig({
29
+ integrations: [
30
+ mermaid()
31
+ ]
32
+ });
33
+ ```
34
+
35
+ Then use mermaid code blocks in your markdown files:
36
+
37
+ ````markdown
38
+ ```mermaid
39
+ graph TD
40
+ A[Start] --> B{Is it working?}
41
+ B -->|Yes| C[Great!]
42
+ B -->|No| D[Debug]
43
+ D --> A
44
+ ```
45
+ ````
46
+
47
+ ## Configuration
48
+
49
+ ```js
50
+ mermaid({
51
+ // Default theme: 'default', 'dark', 'forest', 'neutral', 'base'
52
+ theme: 'forest',
53
+
54
+ // Enable automatic theme switching based on data-theme attribute
55
+ autoTheme: true,
56
+
57
+ // Additional mermaid configuration
58
+ mermaidConfig: {
59
+ flowchart: {
60
+ curve: 'basis'
61
+ }
62
+ }
63
+ })
64
+ ```
65
+
66
+ ## Theme Switching
67
+
68
+ If `autoTheme` is enabled (default), the integration will automatically switch between themes based on your site's `data-theme` attribute:
69
+
70
+ - `data-theme="light"` → uses 'default' mermaid theme
71
+ - `data-theme="dark"` → uses 'dark' mermaid theme
72
+
73
+ ## Supported Diagrams
74
+
75
+ All mermaid diagram types are supported:
76
+
77
+ - Flowcharts
78
+ - Sequence diagrams
79
+ - Gantt charts
80
+ - Class diagrams
81
+ - State diagrams
82
+ - Entity Relationship diagrams
83
+ - User Journey diagrams
84
+ - Git graphs
85
+ - Pie charts
86
+ - Requirement diagrams
87
+ - C4 diagrams
88
+ - Mindmaps
89
+ - Timeline diagrams
90
+ - Quadrant charts
91
+ - And more!
92
+
93
+ ## License
94
+
95
+ MIT
@@ -0,0 +1,41 @@
1
+ import type { AstroIntegration } from 'astro';
2
+
3
+ export interface AstroMermaidOptions {
4
+ /**
5
+ * Default mermaid theme
6
+ * @default 'default'
7
+ */
8
+ theme?: 'default' | 'dark' | 'forest' | 'neutral' | 'base';
9
+
10
+ /**
11
+ * Enable automatic theme switching based on data-theme attribute
12
+ * @default true
13
+ */
14
+ autoTheme?: boolean;
15
+
16
+ /**
17
+ * Additional mermaid configuration options
18
+ * @see https://mermaid.js.org/config/setup/modules/mermaidAPI.html#mermaidapi-configuration-defaults
19
+ */
20
+ mermaidConfig?: Record<string, any>;
21
+ }
22
+
23
+ /**
24
+ * Astro integration for rendering Mermaid diagrams
25
+ *
26
+ * @example
27
+ * ```js
28
+ * import { defineConfig } from 'astro/config';
29
+ * import mermaid from 'astro-mermaid';
30
+ *
31
+ * export default defineConfig({
32
+ * integrations: [
33
+ * mermaid({
34
+ * theme: 'forest',
35
+ * autoTheme: true
36
+ * })
37
+ * ]
38
+ * });
39
+ * ```
40
+ */
41
+ export default function astroMermaid(options?: AstroMermaidOptions): AstroIntegration;
@@ -0,0 +1,255 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import path from 'node:path';
3
+
4
+ /**
5
+ * Rehype plugin to transform mermaid code blocks
6
+ * Converts ```mermaid code blocks to <pre class="mermaid">
7
+ */
8
+ function rehypeMermaidPlugin(options = {}) {
9
+ return async function transformer(tree, file) {
10
+ const { visit } = await import('unist-util-visit');
11
+ const { toString } = await import('mdast-util-to-string');
12
+
13
+ let mermaidCount = 0;
14
+
15
+ visit(tree, 'element', (node, index, parent) => {
16
+ // Look for <pre><code class="language-mermaid">
17
+ if (
18
+ node.tagName === 'pre' &&
19
+ node.children?.length === 1 &&
20
+ node.children[0].tagName === 'code'
21
+ ) {
22
+ const codeNode = node.children[0];
23
+ const className = codeNode.properties?.className;
24
+
25
+ if (Array.isArray(className) && className.includes('language-mermaid')) {
26
+ mermaidCount++;
27
+ // Get the mermaid diagram content
28
+ const diagramContent = toString(codeNode);
29
+
30
+ // Transform to <pre class="mermaid">
31
+ node.properties = {
32
+ ...node.properties,
33
+ className: ['mermaid']
34
+ };
35
+
36
+ node.children = [{
37
+ type: 'text',
38
+ value: diagramContent
39
+ }];
40
+
41
+ if (options.logger) {
42
+ options.logger.info(`Transformed mermaid block #${mermaidCount} in ${file.path || 'unknown file'}`);
43
+ }
44
+ }
45
+ }
46
+ });
47
+
48
+ if (mermaidCount > 0 && options.logger) {
49
+ options.logger.info(`Total mermaid blocks transformed: ${mermaidCount}`);
50
+ }
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Astro integration for rendering Mermaid diagrams
56
+ * Supports automatic theme switching and client-side rendering
57
+ *
58
+ * @param {Object} options - Configuration options
59
+ * @param {string} [options.theme='default'] - Default theme ('default', 'dark', 'forest', 'neutral')
60
+ * @param {boolean} [options.autoTheme=true] - Enable automatic theme switching based on data-theme attribute
61
+ * @param {Object} [options.mermaidConfig={}] - Additional mermaid configuration options
62
+ * @returns {import('astro').AstroIntegration}
63
+ */
64
+ export default function astroMermaid(options = {}) {
65
+ const {
66
+ theme = 'default',
67
+ autoTheme = true,
68
+ mermaidConfig = {}
69
+ } = options;
70
+
71
+ return {
72
+ name: 'astro-mermaid',
73
+ hooks: {
74
+ 'astro:config:setup': async ({ config, updateConfig, addWatchFile, injectScript, logger, command }) => {
75
+ logger.info('Setting up Mermaid integration');
76
+
77
+ // Log existing rehype plugins
78
+ logger.info('Existing rehype plugins:', config.markdown?.rehypePlugins?.length || 0);
79
+
80
+ // Update markdown config to use our rehype plugin
81
+ updateConfig({
82
+ markdown: {
83
+ rehypePlugins: [
84
+ ...(config.markdown?.rehypePlugins || []),
85
+ [rehypeMermaidPlugin, { logger }]
86
+ ]
87
+ },
88
+ vite: {
89
+ optimizeDeps: {
90
+ include: ['mermaid']
91
+ }
92
+ }
93
+ });
94
+
95
+ // Inject client-side mermaid script
96
+ const mermaidScriptContent = `
97
+ import mermaid from 'mermaid';
98
+
99
+ // Mermaid configuration
100
+ const defaultConfig = ${JSON.stringify({
101
+ startOnLoad: false,
102
+ theme: theme,
103
+ ...mermaidConfig
104
+ })};
105
+
106
+ // Theme mapping for auto-theme switching
107
+ const themeMap = {
108
+ 'light': 'default',
109
+ 'dark': 'dark'
110
+ };
111
+
112
+ // Initialize all mermaid diagrams
113
+ async function initMermaid() {
114
+ console.log('[astro-mermaid] Initializing mermaid diagrams...');
115
+ const diagrams = document.querySelectorAll('pre.mermaid');
116
+
117
+ console.log('[astro-mermaid] Found', diagrams.length, 'mermaid diagrams');
118
+
119
+ if (diagrams.length === 0) {
120
+ console.log('[astro-mermaid] No mermaid diagrams found. Looking for code blocks...');
121
+ const codeBlocks = document.querySelectorAll('pre code.language-mermaid');
122
+ console.log('[astro-mermaid] Found', codeBlocks.length, 'mermaid code blocks');
123
+ return;
124
+ }
125
+
126
+ // Get current theme
127
+ let currentTheme = defaultConfig.theme;
128
+
129
+ if (${autoTheme}) {
130
+ const dataTheme = document.documentElement.getAttribute('data-theme');
131
+ currentTheme = themeMap[dataTheme] || defaultConfig.theme;
132
+ console.log('[astro-mermaid] Using theme:', currentTheme);
133
+ }
134
+
135
+ // Configure mermaid
136
+ mermaid.initialize({
137
+ ...defaultConfig,
138
+ theme: currentTheme
139
+ });
140
+
141
+ // Render each diagram
142
+ for (const diagram of diagrams) {
143
+ // Skip if already processed
144
+ if (diagram.hasAttribute('data-processed')) continue;
145
+
146
+ // Store original content
147
+ if (!diagram.hasAttribute('data-diagram')) {
148
+ diagram.setAttribute('data-diagram', diagram.textContent || '');
149
+ }
150
+
151
+ const diagramDefinition = diagram.getAttribute('data-diagram') || '';
152
+ const id = 'mermaid-' + Math.random().toString(36).slice(2, 11);
153
+
154
+ console.log('[astro-mermaid] Rendering diagram:', id);
155
+
156
+ try {
157
+ const { svg } = await mermaid.render(id, diagramDefinition);
158
+ diagram.innerHTML = svg;
159
+ diagram.setAttribute('data-processed', 'true');
160
+ console.log('[astro-mermaid] Successfully rendered diagram:', id);
161
+ } catch (error) {
162
+ console.error('[astro-mermaid] Mermaid rendering error:', error);
163
+ diagram.innerHTML = '<div style="color: red;">Error rendering diagram</div>';
164
+ }
165
+ }
166
+ }
167
+
168
+ // Initialize on DOM ready
169
+ if (document.readyState === 'loading') {
170
+ document.addEventListener('DOMContentLoaded', initMermaid);
171
+ } else {
172
+ initMermaid();
173
+ }
174
+
175
+ // Re-render on theme change if auto-theme is enabled
176
+ if (${autoTheme}) {
177
+ const observer = new MutationObserver((mutations) => {
178
+ for (const mutation of mutations) {
179
+ if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
180
+ // Reset processed state and re-render
181
+ document.querySelectorAll('pre.mermaid[data-processed]').forEach(diagram => {
182
+ diagram.removeAttribute('data-processed');
183
+ });
184
+ initMermaid();
185
+ }
186
+ }
187
+ });
188
+
189
+ observer.observe(document.documentElement, {
190
+ attributes: true,
191
+ attributeFilter: ['data-theme']
192
+ });
193
+ }
194
+
195
+ // Handle view transitions (for Astro View Transitions API)
196
+ document.addEventListener('astro:after-swap', initMermaid);
197
+ `;
198
+
199
+ injectScript('page', mermaidScriptContent);
200
+
201
+ // Add CSS to the page
202
+ injectScript('page', `
203
+ // Add CSS for mermaid diagrams
204
+ const style = document.createElement('style');
205
+ style.textContent = \`
206
+ /* Hide diagrams until processed to prevent flash of unstyled content */
207
+ pre.mermaid:not([data-processed]) {
208
+ opacity: 0;
209
+ transition: opacity 0.3s ease-in-out;
210
+ }
211
+
212
+ /* Show processed diagrams */
213
+ pre.mermaid[data-processed] {
214
+ opacity: 1;
215
+ }
216
+
217
+ /* Center mermaid diagrams and add spacing */
218
+ pre.mermaid {
219
+ display: flex;
220
+ justify-content: center;
221
+ align-items: center;
222
+ margin: 2rem 0;
223
+ padding: 1rem;
224
+ background-color: transparent;
225
+ border: none;
226
+ overflow: auto;
227
+ }
228
+
229
+ /* Ensure responsive sizing for mermaid SVGs */
230
+ pre.mermaid svg {
231
+ max-width: 100%;
232
+ height: auto;
233
+ }
234
+
235
+ /* Optional: Add subtle background for better visibility */
236
+ @media (prefers-color-scheme: dark) {
237
+ pre.mermaid {
238
+ background-color: rgba(255, 255, 255, 0.02);
239
+ border-radius: 0.5rem;
240
+ }
241
+ }
242
+
243
+ @media (prefers-color-scheme: light) {
244
+ pre.mermaid {
245
+ background-color: rgba(0, 0, 0, 0.02);
246
+ border-radius: 0.5rem;
247
+ }
248
+ }
249
+ \`;
250
+ document.head.appendChild(style);
251
+ `);
252
+ }
253
+ }
254
+ };
255
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "astro-mermaid",
3
+ "version": "1.0.0",
4
+ "description": "An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering",
5
+ "type": "module",
6
+ "main": "./astro-mermaid-integration.js",
7
+ "types": "./astro-mermaid-integration.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./astro-mermaid-integration.js",
11
+ "types": "./astro-mermaid-integration.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "astro-mermaid-integration.js",
16
+ "astro-mermaid-integration.d.ts",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "astro",
21
+ "astro-integration",
22
+ "mermaid",
23
+ "diagrams",
24
+ "markdown",
25
+ "flowchart",
26
+ "gantt",
27
+ "sequence-diagram"
28
+ ],
29
+ "author": "Jose Sebastian",
30
+ "license": "MIT",
31
+ "peerDependencies": {
32
+ "astro": "^4.0.0 || ^5.0.0",
33
+ "mermaid": "^10.0.0 || ^11.0.0"
34
+ },
35
+ "dependencies": {
36
+ "mdast-util-to-string": "^4.0.0",
37
+ "unist-util-visit": "^5.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/hast": "^3.0.4",
41
+ "astro": "^5.0.0",
42
+ "mermaid": "^11.0.0",
43
+ "typescript": "^5.0.0"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/joesaby/astro-mermaid.git"
48
+ },
49
+ "homepage": "https://github.com/joesaby/astro-mermaid#readme",
50
+ "bugs": {
51
+ "url": "https://github.com/joesaby/astro-mermaid/issues"
52
+ }
53
+ }