astro-mermaid 1.0.2 → 1.0.4
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 +44 -1
- package/astro-mermaid-integration.d.ts +26 -0
- package/astro-mermaid-integration.js +73 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,10 +85,53 @@ mermaid({
|
|
|
85
85
|
flowchart: {
|
|
86
86
|
curve: 'basis'
|
|
87
87
|
}
|
|
88
|
-
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// Register icon packs for use in diagrams
|
|
91
|
+
iconPacks: [
|
|
92
|
+
{
|
|
93
|
+
name: 'logos',
|
|
94
|
+
loader: () => fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then(res => res.json())
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'iconoir',
|
|
98
|
+
loader: () => fetch('https://unpkg.com/@iconify-json/iconoir@1/icons.json').then(res => res.json())
|
|
99
|
+
}
|
|
100
|
+
]
|
|
89
101
|
})
|
|
90
102
|
```
|
|
91
103
|
|
|
104
|
+
## Icon Packs
|
|
105
|
+
|
|
106
|
+
You can register icon packs to use custom icons in your diagrams. Icon packs are loaded from Iconify JSON sources:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
iconPacks: [
|
|
110
|
+
{
|
|
111
|
+
name: 'logos',
|
|
112
|
+
loader: () => fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then(res => res.json())
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then use icons in your diagrams:
|
|
118
|
+
|
|
119
|
+
````markdown
|
|
120
|
+
```mermaid
|
|
121
|
+
architecture-beta
|
|
122
|
+
group api(logos:aws-lambda)[API]
|
|
123
|
+
|
|
124
|
+
service db(logos:postgresql)[Database] in api
|
|
125
|
+
service disk1(logos:aws-s3)[Storage] in api
|
|
126
|
+
service disk2(logos:cloudflare)[CDN] in api
|
|
127
|
+
service server(logos:docker)[Server] in api
|
|
128
|
+
|
|
129
|
+
db:L -- R:server
|
|
130
|
+
disk1:T -- B:server
|
|
131
|
+
disk2:T -- B:db
|
|
132
|
+
```
|
|
133
|
+
````
|
|
134
|
+
|
|
92
135
|
## Theme Switching
|
|
93
136
|
|
|
94
137
|
If `autoTheme` is enabled (default), the integration will automatically switch between themes based on your site's `data-theme` attribute:
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { AstroIntegration } from 'astro';
|
|
2
2
|
|
|
3
|
+
export interface IconPack {
|
|
4
|
+
/**
|
|
5
|
+
* Name of the icon pack
|
|
6
|
+
*/
|
|
7
|
+
name: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Function that returns a promise resolving to the icon pack data
|
|
11
|
+
*/
|
|
12
|
+
loader: () => Promise<any>;
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
export interface AstroMermaidOptions {
|
|
4
16
|
/**
|
|
5
17
|
* Default mermaid theme
|
|
@@ -18,6 +30,20 @@ export interface AstroMermaidOptions {
|
|
|
18
30
|
* @see https://mermaid.js.org/config/setup/modules/mermaidAPI.html#mermaidapi-configuration-defaults
|
|
19
31
|
*/
|
|
20
32
|
mermaidConfig?: Record<string, any>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Icon packs to register with mermaid
|
|
36
|
+
* @example
|
|
37
|
+
* ```js
|
|
38
|
+
* iconPacks: [
|
|
39
|
+
* {
|
|
40
|
+
* name: 'logos',
|
|
41
|
+
* loader: () => fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then(res => res.json())
|
|
42
|
+
* }
|
|
43
|
+
* ]
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
iconPacks?: IconPack[];
|
|
21
47
|
}
|
|
22
48
|
|
|
23
49
|
/**
|
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Remark plugin to transform mermaid code blocks at the markdown level
|
|
6
|
+
*/
|
|
7
|
+
function remarkMermaidPlugin(options = {}) {
|
|
8
|
+
return async function transformer(tree, file) {
|
|
9
|
+
const { visit } = await import('unist-util-visit');
|
|
10
|
+
|
|
11
|
+
let mermaidCount = 0;
|
|
12
|
+
|
|
13
|
+
visit(tree, 'code', (node, index, parent) => {
|
|
14
|
+
if (node.lang === 'mermaid') {
|
|
15
|
+
mermaidCount++;
|
|
16
|
+
|
|
17
|
+
// Transform to html node with pre.mermaid
|
|
18
|
+
const htmlNode = {
|
|
19
|
+
type: 'html',
|
|
20
|
+
value: `<pre class="mermaid">${node.value}</pre>`
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Replace the code node with html node
|
|
24
|
+
if (parent && typeof index === 'number') {
|
|
25
|
+
parent.children[index] = htmlNode;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (options.logger) {
|
|
29
|
+
options.logger.info(`Remark transformed mermaid block #${mermaidCount} in ${file.path || 'unknown file'}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (mermaidCount > 0 && options.logger) {
|
|
35
|
+
options.logger.info(`Remark total mermaid blocks transformed: ${mermaidCount}`);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
4
40
|
/**
|
|
5
41
|
* Rehype plugin to transform mermaid code blocks
|
|
6
42
|
* Converts ```mermaid code blocks to <pre class="mermaid">
|
|
@@ -39,14 +75,14 @@ function rehypeMermaidPlugin(options = {}) {
|
|
|
39
75
|
}];
|
|
40
76
|
|
|
41
77
|
if (options.logger) {
|
|
42
|
-
options.logger.info(`
|
|
78
|
+
options.logger.info(`Rehype transformed mermaid block #${mermaidCount} in ${file.path || 'unknown file'}`);
|
|
43
79
|
}
|
|
44
80
|
}
|
|
45
81
|
}
|
|
46
82
|
});
|
|
47
83
|
|
|
48
84
|
if (mermaidCount > 0 && options.logger) {
|
|
49
|
-
options.logger.info(`
|
|
85
|
+
options.logger.info(`Rehype total mermaid blocks transformed: ${mermaidCount}`);
|
|
50
86
|
}
|
|
51
87
|
};
|
|
52
88
|
}
|
|
@@ -65,7 +101,8 @@ export default function astroMermaid(options = {}) {
|
|
|
65
101
|
const {
|
|
66
102
|
theme = 'default',
|
|
67
103
|
autoTheme = true,
|
|
68
|
-
mermaidConfig = {}
|
|
104
|
+
mermaidConfig = {},
|
|
105
|
+
iconPacks = []
|
|
69
106
|
} = options;
|
|
70
107
|
|
|
71
108
|
return {
|
|
@@ -77,9 +114,13 @@ export default function astroMermaid(options = {}) {
|
|
|
77
114
|
// Log existing rehype plugins
|
|
78
115
|
logger.info('Existing rehype plugins:', config.markdown?.rehypePlugins?.length || 0);
|
|
79
116
|
|
|
80
|
-
// Update markdown config to use
|
|
117
|
+
// Update markdown config to use both remark and rehype plugins
|
|
81
118
|
updateConfig({
|
|
82
119
|
markdown: {
|
|
120
|
+
remarkPlugins: [
|
|
121
|
+
...(config.markdown?.remarkPlugins || []),
|
|
122
|
+
[remarkMermaidPlugin, { logger }]
|
|
123
|
+
],
|
|
83
124
|
rehypePlugins: [
|
|
84
125
|
...(config.markdown?.rehypePlugins || []),
|
|
85
126
|
[rehypeMermaidPlugin, { logger }]
|
|
@@ -92,6 +133,12 @@ export default function astroMermaid(options = {}) {
|
|
|
92
133
|
}
|
|
93
134
|
});
|
|
94
135
|
|
|
136
|
+
// Serialize icon packs for client-side use
|
|
137
|
+
const iconPacksConfig = iconPacks.map(pack => ({
|
|
138
|
+
name: pack.name,
|
|
139
|
+
loader: pack.loader.toString()
|
|
140
|
+
}));
|
|
141
|
+
|
|
95
142
|
// Inject client-side mermaid script with conditional loading
|
|
96
143
|
const mermaidScriptContent = `
|
|
97
144
|
// Check if page has mermaid diagrams
|
|
@@ -104,7 +151,17 @@ if (hasMermaidDiagrams()) {
|
|
|
104
151
|
console.log('[astro-mermaid] Mermaid diagrams detected, loading mermaid.js...');
|
|
105
152
|
|
|
106
153
|
// Dynamically import mermaid only when needed
|
|
107
|
-
import('mermaid').then(({ default: mermaid }) => {
|
|
154
|
+
import('mermaid').then(async ({ default: mermaid }) => {
|
|
155
|
+
// Register icon packs if provided
|
|
156
|
+
const iconPacks = ${JSON.stringify(iconPacksConfig)};
|
|
157
|
+
if (iconPacks && iconPacks.length > 0) {
|
|
158
|
+
console.log('[astro-mermaid] Registering', iconPacks.length, 'icon packs');
|
|
159
|
+
const packs = iconPacks.map(pack => ({
|
|
160
|
+
name: pack.name,
|
|
161
|
+
loader: new Function('return ' + pack.loader)()
|
|
162
|
+
}));
|
|
163
|
+
await mermaid.registerIconPacks(packs);
|
|
164
|
+
}
|
|
108
165
|
// Mermaid configuration
|
|
109
166
|
const defaultConfig = ${JSON.stringify({
|
|
110
167
|
startOnLoad: false,
|
|
@@ -129,13 +186,16 @@ if (hasMermaidDiagrams()) {
|
|
|
129
186
|
return;
|
|
130
187
|
}
|
|
131
188
|
|
|
132
|
-
// Get current theme
|
|
189
|
+
// Get current theme from multiple sources
|
|
133
190
|
let currentTheme = defaultConfig.theme;
|
|
134
191
|
|
|
135
192
|
if (${autoTheme}) {
|
|
136
|
-
|
|
193
|
+
// Check both html and body for data-theme attribute
|
|
194
|
+
const htmlTheme = document.documentElement.getAttribute('data-theme');
|
|
195
|
+
const bodyTheme = document.body.getAttribute('data-theme');
|
|
196
|
+
const dataTheme = htmlTheme || bodyTheme;
|
|
137
197
|
currentTheme = themeMap[dataTheme] || defaultConfig.theme;
|
|
138
|
-
console.log('[astro-mermaid] Using theme:', currentTheme);
|
|
198
|
+
console.log('[astro-mermaid] Using theme:', currentTheme, 'from', htmlTheme ? 'html' : 'body');
|
|
139
199
|
}
|
|
140
200
|
|
|
141
201
|
// Configure mermaid with gitGraph support
|
|
@@ -204,10 +264,15 @@ if (hasMermaidDiagrams()) {
|
|
|
204
264
|
}
|
|
205
265
|
});
|
|
206
266
|
|
|
267
|
+
// Observe both html and body for data-theme changes
|
|
207
268
|
observer.observe(document.documentElement, {
|
|
208
269
|
attributes: true,
|
|
209
270
|
attributeFilter: ['data-theme']
|
|
210
271
|
});
|
|
272
|
+
observer.observe(document.body, {
|
|
273
|
+
attributes: true,
|
|
274
|
+
attributeFilter: ['data-theme']
|
|
275
|
+
});
|
|
211
276
|
}
|
|
212
277
|
|
|
213
278
|
// Handle view transitions (for Astro View Transitions API)
|
package/package.json
CHANGED