astro-mermaid 1.0.1 → 1.0.3
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 +113 -3
- package/astro-mermaid-integration.d.ts +26 -0
- package/astro-mermaid-integration.js +183 -106
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# astro-mermaid
|
|
2
2
|
|
|
3
|
-
An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering.
|
|
3
|
+
An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering. This follows the mermaid integration in [cloudflare-docs](https://github.com/cloudflare/cloudflare-docs)
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -10,6 +10,11 @@ An Astro integration for rendering Mermaid diagrams with automatic theme switchi
|
|
|
10
10
|
- ⚡ Vite optimization for fast development
|
|
11
11
|
- 🔧 Customizable mermaid configuration
|
|
12
12
|
- 🎯 TypeScript support
|
|
13
|
+
- 🔒 Privacy-focused with no external server dependencies
|
|
14
|
+
- 🌐 Offline-capable rendering
|
|
15
|
+
- ⚡ Zero network latency for diagram generation
|
|
16
|
+
- 📦 Conditional loading - mermaid.js only loads on pages with diagrams
|
|
17
|
+
- 🎭 Smooth loading animations to prevent layout shifts
|
|
13
18
|
|
|
14
19
|
## Installation
|
|
15
20
|
|
|
@@ -27,7 +32,28 @@ import mermaid from 'astro-mermaid';
|
|
|
27
32
|
|
|
28
33
|
export default defineConfig({
|
|
29
34
|
integrations: [
|
|
30
|
-
mermaid(
|
|
35
|
+
mermaid({
|
|
36
|
+
theme: 'forest'
|
|
37
|
+
})
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Important: Integration Order
|
|
43
|
+
|
|
44
|
+
When using with Starlight or other integrations that process markdown, make sure to place the mermaid integration **before** them:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { defineConfig } from 'astro/config';
|
|
48
|
+
import starlight from '@astrojs/starlight';
|
|
49
|
+
import mermaid from 'astro-mermaid';
|
|
50
|
+
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
integrations: [
|
|
53
|
+
mermaid(), // Must come BEFORE starlight
|
|
54
|
+
starlight({
|
|
55
|
+
title: 'My Docs'
|
|
56
|
+
})
|
|
31
57
|
]
|
|
32
58
|
});
|
|
33
59
|
```
|
|
@@ -59,10 +85,53 @@ mermaid({
|
|
|
59
85
|
flowchart: {
|
|
60
86
|
curve: 'basis'
|
|
61
87
|
}
|
|
62
|
-
}
|
|
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
|
+
]
|
|
63
101
|
})
|
|
64
102
|
```
|
|
65
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
|
+
|
|
66
135
|
## Theme Switching
|
|
67
136
|
|
|
68
137
|
If `autoTheme` is enabled (default), the integration will automatically switch between themes based on your site's `data-theme` attribute:
|
|
@@ -70,6 +139,39 @@ If `autoTheme` is enabled (default), the integration will automatically switch b
|
|
|
70
139
|
- `data-theme="light"` → uses 'default' mermaid theme
|
|
71
140
|
- `data-theme="dark"` → uses 'dark' mermaid theme
|
|
72
141
|
|
|
142
|
+
## Client-Side Rendering & Security
|
|
143
|
+
|
|
144
|
+
### 🔒 Privacy & Security Benefits
|
|
145
|
+
|
|
146
|
+
This integration uses **100% client-side rendering** with zero external dependencies at runtime:
|
|
147
|
+
|
|
148
|
+
- **No Data Transmission**: Your diagram content never leaves your browser
|
|
149
|
+
- **No External Servers**: No calls to mermaid.live or any external services
|
|
150
|
+
- **Offline Capable**: Works completely offline after initial page load
|
|
151
|
+
- **Zero Network Latency**: Instant diagram rendering without network delays
|
|
152
|
+
- **Corporate Firewall Friendly**: No external domains need to be whitelisted
|
|
153
|
+
|
|
154
|
+
### ⚡ How It Works
|
|
155
|
+
|
|
156
|
+
1. **Build Time**: Mermaid code blocks are transformed to `<pre class="mermaid">` elements
|
|
157
|
+
2. **Runtime**: The bundled Mermaid JavaScript library renders diagrams locally
|
|
158
|
+
3. **Output**: Pure SVG generated entirely in your browser
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
// All rendering happens locally - no network calls
|
|
162
|
+
import mermaid from 'mermaid';
|
|
163
|
+
const { svg } = await mermaid.render(id, diagramDefinition);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 🛡️ Enterprise & Compliance
|
|
167
|
+
|
|
168
|
+
Perfect for:
|
|
169
|
+
- Corporate environments with strict security policies
|
|
170
|
+
- GDPR/privacy-compliant applications
|
|
171
|
+
- Air-gapped or restricted network environments
|
|
172
|
+
- Applications requiring data sovereignty
|
|
173
|
+
- High-security environments where external requests are prohibited
|
|
174
|
+
|
|
73
175
|
## Supported Diagrams
|
|
74
176
|
|
|
75
177
|
All mermaid diagram types are supported:
|
|
@@ -90,6 +192,14 @@ All mermaid diagram types are supported:
|
|
|
90
192
|
- Quadrant charts
|
|
91
193
|
- And more!
|
|
92
194
|
|
|
195
|
+
## Demo
|
|
196
|
+
|
|
197
|
+
Check out the [live demo](https://starlight-mermaid-demo.netlify.app/) built with Starlight.
|
|
198
|
+
|
|
199
|
+
## Contributing
|
|
200
|
+
|
|
201
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
202
|
+
|
|
93
203
|
## License
|
|
94
204
|
|
|
95
205
|
MIT
|
|
@@ -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
|
/**
|
|
@@ -65,7 +65,8 @@ export default function astroMermaid(options = {}) {
|
|
|
65
65
|
const {
|
|
66
66
|
theme = 'default',
|
|
67
67
|
autoTheme = true,
|
|
68
|
-
mermaidConfig = {}
|
|
68
|
+
mermaidConfig = {},
|
|
69
|
+
iconPacks = []
|
|
69
70
|
} = options;
|
|
70
71
|
|
|
71
72
|
return {
|
|
@@ -92,129 +93,163 @@ export default function astroMermaid(options = {}) {
|
|
|
92
93
|
}
|
|
93
94
|
});
|
|
94
95
|
|
|
95
|
-
//
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const defaultConfig = ${JSON.stringify({
|
|
101
|
-
startOnLoad: false,
|
|
102
|
-
theme: theme,
|
|
103
|
-
...mermaidConfig
|
|
104
|
-
})};
|
|
96
|
+
// Serialize icon packs for client-side use
|
|
97
|
+
const iconPacksConfig = iconPacks.map(pack => ({
|
|
98
|
+
name: pack.name,
|
|
99
|
+
loader: pack.loader.toString()
|
|
100
|
+
}));
|
|
105
101
|
|
|
106
|
-
//
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
// Inject client-side mermaid script with conditional loading
|
|
103
|
+
const mermaidScriptContent = `
|
|
104
|
+
// Check if page has mermaid diagrams
|
|
105
|
+
const hasMermaidDiagrams = () => {
|
|
106
|
+
return document.querySelectorAll('pre.mermaid').length > 0;
|
|
110
107
|
};
|
|
111
108
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
console.log('[astro-mermaid]
|
|
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
|
-
});
|
|
109
|
+
// Only proceed if there are mermaid diagrams on the page
|
|
110
|
+
if (hasMermaidDiagrams()) {
|
|
111
|
+
console.log('[astro-mermaid] Mermaid diagrams detected, loading mermaid.js...');
|
|
140
112
|
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
113
|
+
// Dynamically import mermaid only when needed
|
|
114
|
+
import('mermaid').then(async ({ default: mermaid }) => {
|
|
115
|
+
// Register icon packs if provided
|
|
116
|
+
const iconPacks = ${JSON.stringify(iconPacksConfig)};
|
|
117
|
+
if (iconPacks && iconPacks.length > 0) {
|
|
118
|
+
console.log('[astro-mermaid] Registering', iconPacks.length, 'icon packs');
|
|
119
|
+
const packs = iconPacks.map(pack => ({
|
|
120
|
+
name: pack.name,
|
|
121
|
+
loader: new Function('return ' + pack.loader)()
|
|
122
|
+
}));
|
|
123
|
+
await mermaid.registerIconPacks(packs);
|
|
149
124
|
}
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
125
|
+
// Mermaid configuration
|
|
126
|
+
const defaultConfig = ${JSON.stringify({
|
|
127
|
+
startOnLoad: false,
|
|
128
|
+
theme: theme,
|
|
129
|
+
...mermaidConfig
|
|
130
|
+
})};
|
|
131
|
+
|
|
132
|
+
// Theme mapping for auto-theme switching
|
|
133
|
+
const themeMap = {
|
|
134
|
+
'light': 'default',
|
|
135
|
+
'dark': 'dark'
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Initialize all mermaid diagrams
|
|
139
|
+
async function initMermaid() {
|
|
140
|
+
console.log('[astro-mermaid] Initializing mermaid diagrams...');
|
|
141
|
+
const diagrams = document.querySelectorAll('pre.mermaid');
|
|
142
|
+
|
|
143
|
+
console.log('[astro-mermaid] Found', diagrams.length, 'mermaid diagrams');
|
|
144
|
+
|
|
145
|
+
if (diagrams.length === 0) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Get current theme
|
|
150
|
+
let currentTheme = defaultConfig.theme;
|
|
151
|
+
|
|
152
|
+
if (${autoTheme}) {
|
|
153
|
+
const dataTheme = document.documentElement.getAttribute('data-theme');
|
|
154
|
+
currentTheme = themeMap[dataTheme] || defaultConfig.theme;
|
|
155
|
+
console.log('[astro-mermaid] Using theme:', currentTheme);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Configure mermaid with gitGraph support
|
|
159
|
+
mermaid.initialize({
|
|
160
|
+
...defaultConfig,
|
|
161
|
+
theme: currentTheme,
|
|
162
|
+
gitGraph: {
|
|
163
|
+
mainBranchName: 'main',
|
|
164
|
+
showCommitLabel: true,
|
|
165
|
+
showBranches: true,
|
|
166
|
+
rotateCommitLabel: true
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Render each diagram
|
|
171
|
+
for (const diagram of diagrams) {
|
|
172
|
+
// Skip if already processed
|
|
173
|
+
if (diagram.hasAttribute('data-processed')) continue;
|
|
174
|
+
|
|
175
|
+
// Store original content
|
|
176
|
+
if (!diagram.hasAttribute('data-diagram')) {
|
|
177
|
+
diagram.setAttribute('data-diagram', diagram.textContent || '');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const diagramDefinition = diagram.getAttribute('data-diagram') || '';
|
|
181
|
+
const id = 'mermaid-' + Math.random().toString(36).slice(2, 11);
|
|
182
|
+
|
|
183
|
+
console.log('[astro-mermaid] Rendering diagram:', id);
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
// Clear any existing error state
|
|
187
|
+
const existingGraph = document.getElementById(id);
|
|
188
|
+
if (existingGraph) {
|
|
189
|
+
existingGraph.remove();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const { svg } = await mermaid.render(id, diagramDefinition);
|
|
193
|
+
diagram.innerHTML = svg;
|
|
194
|
+
diagram.setAttribute('data-processed', 'true');
|
|
195
|
+
console.log('[astro-mermaid] Successfully rendered diagram:', id);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error('[astro-mermaid] Mermaid rendering error for diagram:', id, error);
|
|
198
|
+
diagram.innerHTML = \`<div style="color: red; padding: 1rem; border: 1px solid red; border-radius: 0.5rem;">
|
|
199
|
+
<strong>Error rendering diagram:</strong><br/>
|
|
200
|
+
\${error.message || 'Unknown error'}
|
|
201
|
+
</div>\`;
|
|
202
|
+
diagram.setAttribute('data-processed', 'true');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
164
205
|
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
206
|
|
|
168
|
-
// Initialize
|
|
169
|
-
|
|
170
|
-
document.addEventListener('DOMContentLoaded', initMermaid);
|
|
171
|
-
} else {
|
|
172
|
-
initMermaid();
|
|
173
|
-
}
|
|
207
|
+
// Initialize immediately since DOM is ready
|
|
208
|
+
initMermaid();
|
|
174
209
|
|
|
175
|
-
// Re-render on theme change if auto-theme is enabled
|
|
176
|
-
if (${autoTheme}) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
210
|
+
// Re-render on theme change if auto-theme is enabled
|
|
211
|
+
if (${autoTheme}) {
|
|
212
|
+
const observer = new MutationObserver((mutations) => {
|
|
213
|
+
for (const mutation of mutations) {
|
|
214
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
|
|
215
|
+
// Reset processed state and re-render
|
|
216
|
+
document.querySelectorAll('pre.mermaid[data-processed]').forEach(diagram => {
|
|
217
|
+
diagram.removeAttribute('data-processed');
|
|
218
|
+
});
|
|
219
|
+
initMermaid();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
observer.observe(document.documentElement, {
|
|
225
|
+
attributes: true,
|
|
226
|
+
attributeFilter: ['data-theme']
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Handle view transitions (for Astro View Transitions API)
|
|
231
|
+
document.addEventListener('astro:after-swap', () => {
|
|
232
|
+
// Check again if new page has diagrams
|
|
233
|
+
if (hasMermaidDiagrams()) {
|
|
184
234
|
initMermaid();
|
|
185
235
|
}
|
|
186
|
-
}
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
observer.observe(document.documentElement, {
|
|
190
|
-
attributes: true,
|
|
191
|
-
attributeFilter: ['data-theme']
|
|
236
|
+
});
|
|
237
|
+
}).catch(error => {
|
|
238
|
+
console.error('[astro-mermaid] Failed to load mermaid:', error);
|
|
192
239
|
});
|
|
240
|
+
} else {
|
|
241
|
+
console.log('[astro-mermaid] No mermaid diagrams found on this page, skipping mermaid.js load');
|
|
193
242
|
}
|
|
194
|
-
|
|
195
|
-
// Handle view transitions (for Astro View Transitions API)
|
|
196
|
-
document.addEventListener('astro:after-swap', initMermaid);
|
|
197
243
|
`;
|
|
198
244
|
|
|
199
245
|
injectScript('page', mermaidScriptContent);
|
|
200
246
|
|
|
201
|
-
// Add CSS to the page
|
|
247
|
+
// Add CSS to the page with layout shift prevention
|
|
202
248
|
injectScript('page', `
|
|
203
249
|
// Add CSS for mermaid diagrams
|
|
204
250
|
const style = document.createElement('style');
|
|
205
251
|
style.textContent = \`
|
|
206
|
-
/*
|
|
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 */
|
|
252
|
+
/* Prevent layout shifts by setting minimum height */
|
|
218
253
|
pre.mermaid {
|
|
219
254
|
display: flex;
|
|
220
255
|
justify-content: center;
|
|
@@ -224,6 +259,37 @@ document.addEventListener('astro:after-swap', initMermaid);
|
|
|
224
259
|
background-color: transparent;
|
|
225
260
|
border: none;
|
|
226
261
|
overflow: auto;
|
|
262
|
+
min-height: 200px; /* Prevent layout shift */
|
|
263
|
+
position: relative;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* Loading state with skeleton loader */
|
|
267
|
+
pre.mermaid:not([data-processed]) {
|
|
268
|
+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
|
269
|
+
background-size: 200% 100%;
|
|
270
|
+
animation: shimmer 1.5s infinite;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Dark mode skeleton loader */
|
|
274
|
+
[data-theme="dark"] pre.mermaid:not([data-processed]) {
|
|
275
|
+
background: linear-gradient(90deg, #2a2a2a 25%, #3a3a3a 50%, #2a2a2a 75%);
|
|
276
|
+
background-size: 200% 100%;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@keyframes shimmer {
|
|
280
|
+
0% {
|
|
281
|
+
background-position: -200% 0;
|
|
282
|
+
}
|
|
283
|
+
100% {
|
|
284
|
+
background-position: 200% 0;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Show processed diagrams with smooth transition */
|
|
289
|
+
pre.mermaid[data-processed] {
|
|
290
|
+
animation: none;
|
|
291
|
+
background: transparent;
|
|
292
|
+
min-height: auto; /* Allow natural height after render */
|
|
227
293
|
}
|
|
228
294
|
|
|
229
295
|
/* Ensure responsive sizing for mermaid SVGs */
|
|
@@ -234,18 +300,29 @@ document.addEventListener('astro:after-swap', initMermaid);
|
|
|
234
300
|
|
|
235
301
|
/* Optional: Add subtle background for better visibility */
|
|
236
302
|
@media (prefers-color-scheme: dark) {
|
|
237
|
-
pre.mermaid {
|
|
303
|
+
pre.mermaid[data-processed] {
|
|
238
304
|
background-color: rgba(255, 255, 255, 0.02);
|
|
239
305
|
border-radius: 0.5rem;
|
|
240
306
|
}
|
|
241
307
|
}
|
|
242
308
|
|
|
243
309
|
@media (prefers-color-scheme: light) {
|
|
244
|
-
pre.mermaid {
|
|
310
|
+
pre.mermaid[data-processed] {
|
|
245
311
|
background-color: rgba(0, 0, 0, 0.02);
|
|
246
312
|
border-radius: 0.5rem;
|
|
247
313
|
}
|
|
248
314
|
}
|
|
315
|
+
|
|
316
|
+
/* Respect user's color scheme preference */
|
|
317
|
+
[data-theme="dark"] pre.mermaid[data-processed] {
|
|
318
|
+
background-color: rgba(255, 255, 255, 0.02);
|
|
319
|
+
border-radius: 0.5rem;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
[data-theme="light"] pre.mermaid[data-processed] {
|
|
323
|
+
background-color: rgba(0, 0, 0, 0.02);
|
|
324
|
+
border-radius: 0.5rem;
|
|
325
|
+
}
|
|
249
326
|
\`;
|
|
250
327
|
document.head.appendChild(style);
|
|
251
328
|
`);
|
package/package.json
CHANGED