@k11k/better-blocks-astro-renderer 0.2.0 → 0.4.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 +68 -15
- package/index.ts +3 -0
- package/package.json +4 -1
- package/src/Block.astro +6 -0
- package/src/Callout.astro +135 -0
- package/src/Diagram.astro +40 -0
- package/src/types.ts +23 -1
package/README.md
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
<a href="https://github.com/k11k-labs/better-blocks-astro-renderer/blob/main/LICENSE">
|
|
13
13
|
<img alt="license" src="https://img.shields.io/npm/l/@k11k/better-blocks-astro-renderer.svg" />
|
|
14
14
|
</a>
|
|
15
|
+
<a href="https://buymeacoffee.com/k11k">
|
|
16
|
+
<img alt="Buy Me a Coffee" src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-FFDD00?logo=buymeacoffee&logoColor=black" />
|
|
17
|
+
</a>
|
|
15
18
|
</p>
|
|
16
19
|
|
|
17
20
|
<p align="center">
|
|
@@ -31,7 +34,8 @@
|
|
|
31
34
|
7. [Custom Renderers](#custom-renderers)
|
|
32
35
|
8. [TypeScript](#typescript)
|
|
33
36
|
9. [Contributing](#contributing)
|
|
34
|
-
10. [
|
|
37
|
+
10. [Support this project](#support-this-project)
|
|
38
|
+
11. [License](#license)
|
|
35
39
|
|
|
36
40
|
---
|
|
37
41
|
|
|
@@ -110,22 +114,57 @@ import 'katex/dist/katex.min.css';
|
|
|
110
114
|
|
|
111
115
|
`katex` ships as a dependency of this package, so the stylesheet resolves without a separate install. If KaTeX fails to parse a formula, the renderer falls back to the raw LaTeX source instead of crashing.
|
|
112
116
|
|
|
117
|
+
### Diagrams (Mermaid)
|
|
118
|
+
|
|
119
|
+
[Mermaid](https://mermaid.js.org/) diagram blocks (`{ type: 'diagram', format: 'mermaid' }`) are **pre-rendered to inline SVG on the server** using [`beautiful-mermaid`](https://www.npmjs.com/package/beautiful-mermaid) — a pure-Node renderer that needs **no headless browser** (no Puppeteer, no Chromium download). Like math, rendering happens during SSR and static builds with **zero client-side JavaScript** and no hydration step.
|
|
120
|
+
|
|
121
|
+
Supported diagram types — **flowchart, sequence, state, class, ER, and xychart** — render to a `<div class="mermaid-diagram">` wrapping the generated SVG. Diagram types `beautiful-mermaid` does not implement yet (gantt, pie, mindmap, gitGraph, …) and any source that fails to parse fall back gracefully to the raw definition in a `<pre class="mermaid-source">`, so content is never lost.
|
|
122
|
+
|
|
123
|
+
`beautiful-mermaid` ships as a dependency of this package, so no extra install or stylesheet is required.
|
|
124
|
+
|
|
125
|
+
### Callouts (Admonitions)
|
|
126
|
+
|
|
127
|
+
Block-level `callout` nodes render GitHub-style alerts in five variants — `note`, `tip`, `important`, `warning`, and `caution`. Each renders as an `<aside role="note">` with a colored left border, a title row (icon + label), and the nested block children (paragraphs, lists, links, etc.). If a `title` is set on the node it is used; otherwise the localized variant label is shown.
|
|
128
|
+
|
|
129
|
+
Colors come from a small **scoped `<style>`** that ships with the component (still zero client-side JavaScript), and the default palette **adapts to dark mode automatically** via `@media (prefers-color-scheme: dark)`. The accent for each variant is driven by a `--bb-callout-accent` custom property on the `.bb-callout-{variant}` element, so you can retheme colors from your own CSS without replacing the markup:
|
|
130
|
+
|
|
131
|
+
```css
|
|
132
|
+
/* Recolor a single variant, or override per color scheme */
|
|
133
|
+
.bb-callout-note {
|
|
134
|
+
--bb-callout-accent: #2563eb;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
To replace the markup entirely, override the `callout` block. It receives `variant` and `title`; the nested children arrive via `<slot />`:
|
|
139
|
+
|
|
140
|
+
```astro
|
|
141
|
+
---
|
|
142
|
+
import { BlocksRenderer } from '@k11k/better-blocks-astro-renderer';
|
|
143
|
+
import MyCallout from '../components/MyCallout.astro';
|
|
144
|
+
const { blocks } = Astro.props;
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
<BlocksRenderer content={blocks} blocks={{ callout: MyCallout }} />
|
|
148
|
+
```
|
|
149
|
+
|
|
113
150
|
## Supported Blocks
|
|
114
151
|
|
|
115
|
-
| Block | Default element
|
|
116
|
-
| ------------------------------- |
|
|
117
|
-
| `paragraph` | `<p>`
|
|
118
|
-
| `heading` (1–6) | `<h1>`–`<h6>`
|
|
119
|
-
| `list` (ordered/unordered/todo) | `<ol>` / `<ul>`
|
|
120
|
-
| `list-item` | `<li>`
|
|
121
|
-
| `link` | `<a>`
|
|
122
|
-
| `quote` | `<blockquote>`
|
|
123
|
-
| `code` | `<pre><code>`
|
|
124
|
-
| `image` | `<figure><img>`
|
|
125
|
-
| `horizontal-line` | `<hr>`
|
|
126
|
-
| `table` | `<table>`
|
|
127
|
-
| `media-embed` | `<iframe>` (16:9)
|
|
128
|
-
| `math` (inline/block) | `<span>` / `<div>`
|
|
152
|
+
| Block | Default element | Source |
|
|
153
|
+
| ------------------------------- | -------------------- | --------------------------- |
|
|
154
|
+
| `paragraph` | `<p>` | Strapi core |
|
|
155
|
+
| `heading` (1–6) | `<h1>`–`<h6>` | Strapi core |
|
|
156
|
+
| `list` (ordered/unordered/todo) | `<ol>` / `<ul>` | Strapi core + Better Blocks |
|
|
157
|
+
| `list-item` | `<li>` | Strapi core |
|
|
158
|
+
| `link` | `<a>` | Strapi core |
|
|
159
|
+
| `quote` | `<blockquote>` | Strapi core |
|
|
160
|
+
| `code` | `<pre><code>` | Strapi core |
|
|
161
|
+
| `image` | `<figure><img>` | Strapi core |
|
|
162
|
+
| `horizontal-line` | `<hr>` | Better Blocks |
|
|
163
|
+
| `table` | `<table>` | Better Blocks |
|
|
164
|
+
| `media-embed` | `<iframe>` (16:9) | Better Blocks |
|
|
165
|
+
| `math` (inline/block) | `<span>` / `<div>` | Better Blocks |
|
|
166
|
+
| `diagram` (mermaid) | `<div>` (inline SVG) | Better Blocks |
|
|
167
|
+
| `callout` (admonition) | `<aside>` | Better Blocks |
|
|
129
168
|
|
|
130
169
|
### Block properties
|
|
131
170
|
|
|
@@ -145,6 +184,8 @@ import 'katex/dist/katex.min.css';
|
|
|
145
184
|
| `originalUrl` | media-embed | Original user-provided URL |
|
|
146
185
|
| `format` | math | `inline` (`<span>`) or `block` (`<div>`) |
|
|
147
186
|
| `value` | math | LaTeX source rendered with KaTeX |
|
|
187
|
+
| `format` | diagram | `mermaid` (the only supported diagram format) |
|
|
188
|
+
| `value` | diagram | Mermaid source, pre-rendered to SVG on the server |
|
|
148
189
|
|
|
149
190
|
## Supported Modifiers
|
|
150
191
|
|
|
@@ -217,6 +258,7 @@ The props each custom block component receives:
|
|
|
217
258
|
| `table` / `table-row` / `table-cell` / `table-header-cell` | children via `<slot />` |
|
|
218
259
|
| `media-embed` | `{ url; originalUrl? }` (no slot) |
|
|
219
260
|
| `math` | `{ formula; inline }` (no slot) — bring your own math engine |
|
|
261
|
+
| `diagram` | `{ code; format }` (no slot) — bring your own diagram engine |
|
|
220
262
|
|
|
221
263
|
### Custom modifier renderers
|
|
222
264
|
|
|
@@ -267,6 +309,7 @@ import type {
|
|
|
267
309
|
TableHeaderCellNode,
|
|
268
310
|
MediaEmbedNode,
|
|
269
311
|
MathNode,
|
|
312
|
+
DiagramNode,
|
|
270
313
|
TextAlign,
|
|
271
314
|
CustomBlocksConfig,
|
|
272
315
|
CustomModifiersConfig,
|
|
@@ -327,6 +370,16 @@ yarn lint # Check formatting
|
|
|
327
370
|
- [@k11k/better-blocks-react-renderer](https://github.com/k11k-labs/better-blocks-react-renderer) — React renderer with the same Better Blocks support
|
|
328
371
|
- [@k11k/strapi-plugin-better-blocks](https://github.com/k11k-labs/strapi-plugin-better-blocks) — Strapi plugin that extends the Blocks editor with colors, tables, to-do lists, media embeds, and more
|
|
329
372
|
|
|
373
|
+
## Support this project
|
|
374
|
+
|
|
375
|
+
This package is built and maintained in my free time, and it's free for everyone. If it has saved you time on a project, you can help keep it caffeinated and actively developed:
|
|
376
|
+
|
|
377
|
+
<a href="https://buymeacoffee.com/k11k">
|
|
378
|
+
<img alt="Buy Me a Coffee" src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-FFDD00?logo=buymeacoffee&logoColor=black&style=for-the-badge" />
|
|
379
|
+
</a>
|
|
380
|
+
|
|
381
|
+
Every coffee goes toward fixing bugs, reviewing PRs, writing docs, and shipping the features you ask for. Thank you! ☕
|
|
382
|
+
|
|
330
383
|
## License
|
|
331
384
|
|
|
332
385
|
[MIT License](LICENSE) © [k11k-labs](https://github.com/k11k-labs)
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k11k/better-blocks-astro-renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Astro renderer for Strapi v5 Blocks content with full Better Blocks plugin support — colors, tables, to-do lists, media embeds, alignment, and more. Native Astro components, zero client-side JavaScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.ts",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"*.{js,jsx,ts,tsx,astro,json,md,yml,yaml,css}": "prettier --write"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"beautiful-mermaid": "^1.1.3",
|
|
33
34
|
"katex": "^0.16.11"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
@@ -65,6 +66,8 @@
|
|
|
65
66
|
"katex",
|
|
66
67
|
"latex",
|
|
67
68
|
"math",
|
|
69
|
+
"mermaid",
|
|
70
|
+
"diagram",
|
|
68
71
|
"cms",
|
|
69
72
|
"headless-cms"
|
|
70
73
|
],
|
package/src/Block.astro
CHANGED
|
@@ -4,6 +4,8 @@ import Inline from './Inline.astro';
|
|
|
4
4
|
import List from './List.astro';
|
|
5
5
|
import Table from './Table.astro';
|
|
6
6
|
import Math from './Math.astro';
|
|
7
|
+
import Diagram from './Diagram.astro';
|
|
8
|
+
import Callout from './Callout.astro';
|
|
7
9
|
import { getBlockStyle, getPlainText } from './utils';
|
|
8
10
|
|
|
9
11
|
interface Props {
|
|
@@ -154,3 +156,7 @@ const EmbedComp = blocks?.['media-embed'] as any;
|
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
{block.type === 'math' && <Math node={block} blocks={blocks} />}
|
|
159
|
+
|
|
160
|
+
{block.type === 'diagram' && <Diagram node={block} blocks={blocks} />}
|
|
161
|
+
|
|
162
|
+
{block.type === 'callout' && <Callout node={block} blocks={blocks} modifiers={modifiers} />}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type {
|
|
3
|
+
CalloutNode,
|
|
4
|
+
CalloutVariant,
|
|
5
|
+
CustomBlocksConfig,
|
|
6
|
+
CustomModifiersConfig,
|
|
7
|
+
} from './types';
|
|
8
|
+
import Block from './Block.astro';
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
node: CalloutNode;
|
|
12
|
+
blocks?: CustomBlocksConfig;
|
|
13
|
+
modifiers?: CustomModifiersConfig;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { node, blocks, modifiers } = Astro.props;
|
|
17
|
+
|
|
18
|
+
// GitHub-style alert metadata: default label and octicon path. Accent colors
|
|
19
|
+
// live in the scoped <style> below so they can adapt to dark mode.
|
|
20
|
+
const VARIANTS: Record<CalloutVariant, { label: string; icon: string }> = {
|
|
21
|
+
note: {
|
|
22
|
+
label: 'Note',
|
|
23
|
+
icon: 'M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z',
|
|
24
|
+
},
|
|
25
|
+
tip: {
|
|
26
|
+
label: 'Tip',
|
|
27
|
+
icon: 'M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z',
|
|
28
|
+
},
|
|
29
|
+
important: {
|
|
30
|
+
label: 'Important',
|
|
31
|
+
icon: 'M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z',
|
|
32
|
+
},
|
|
33
|
+
warning: {
|
|
34
|
+
label: 'Warning',
|
|
35
|
+
icon: 'M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z',
|
|
36
|
+
},
|
|
37
|
+
caution: {
|
|
38
|
+
label: 'Caution',
|
|
39
|
+
icon: 'M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .39.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.39.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const variant: CalloutVariant = VARIANTS[node.variant] ? node.variant : 'note';
|
|
44
|
+
const meta = VARIANTS[variant];
|
|
45
|
+
const title = node.title?.trim() ? node.title : meta.label;
|
|
46
|
+
const CalloutComp = blocks?.callout as any;
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
{
|
|
50
|
+
CalloutComp ? (
|
|
51
|
+
<CalloutComp variant={variant} title={node.title}>
|
|
52
|
+
{node.children.map((child) => (
|
|
53
|
+
<Block block={child} blocks={blocks} modifiers={modifiers} />
|
|
54
|
+
))}
|
|
55
|
+
</CalloutComp>
|
|
56
|
+
) : (
|
|
57
|
+
<aside class={`bb-callout bb-callout-${variant}`} role="note">
|
|
58
|
+
<p class="bb-callout-title">
|
|
59
|
+
<svg class="bb-callout-icon" viewBox="0 0 16 16" aria-hidden="true">
|
|
60
|
+
<path d={meta.icon} />
|
|
61
|
+
</svg>
|
|
62
|
+
{title}
|
|
63
|
+
</p>
|
|
64
|
+
<div class="bb-callout-body">
|
|
65
|
+
{node.children.map((child) => (
|
|
66
|
+
<Block block={child} blocks={blocks} modifiers={modifiers} />
|
|
67
|
+
))}
|
|
68
|
+
</div>
|
|
69
|
+
</aside>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
<style>
|
|
74
|
+
.bb-callout {
|
|
75
|
+
border-left: 0.25rem solid var(--bb-callout-accent, #0969da);
|
|
76
|
+
padding: 0.5rem 1rem;
|
|
77
|
+
margin: 1rem 0;
|
|
78
|
+
}
|
|
79
|
+
.bb-callout-title {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
gap: 0.5rem;
|
|
83
|
+
margin: 0 0 0.25rem;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
color: var(--bb-callout-accent, #0969da);
|
|
86
|
+
}
|
|
87
|
+
.bb-callout-icon {
|
|
88
|
+
width: 16px;
|
|
89
|
+
height: 16px;
|
|
90
|
+
flex: none;
|
|
91
|
+
fill: currentColor;
|
|
92
|
+
}
|
|
93
|
+
.bb-callout-body > :first-child {
|
|
94
|
+
margin-top: 0;
|
|
95
|
+
}
|
|
96
|
+
.bb-callout-body > :last-child {
|
|
97
|
+
margin-bottom: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Light-mode accents (GitHub palette) */
|
|
101
|
+
.bb-callout-note {
|
|
102
|
+
--bb-callout-accent: #0969da;
|
|
103
|
+
}
|
|
104
|
+
.bb-callout-tip {
|
|
105
|
+
--bb-callout-accent: #1a7f37;
|
|
106
|
+
}
|
|
107
|
+
.bb-callout-important {
|
|
108
|
+
--bb-callout-accent: #8250df;
|
|
109
|
+
}
|
|
110
|
+
.bb-callout-warning {
|
|
111
|
+
--bb-callout-accent: #9a6700;
|
|
112
|
+
}
|
|
113
|
+
.bb-callout-caution {
|
|
114
|
+
--bb-callout-accent: #cf222e;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Dark-mode accents adapt automatically */
|
|
118
|
+
@media (prefers-color-scheme: dark) {
|
|
119
|
+
.bb-callout-note {
|
|
120
|
+
--bb-callout-accent: #4493f8;
|
|
121
|
+
}
|
|
122
|
+
.bb-callout-tip {
|
|
123
|
+
--bb-callout-accent: #3fb950;
|
|
124
|
+
}
|
|
125
|
+
.bb-callout-important {
|
|
126
|
+
--bb-callout-accent: #ab7df8;
|
|
127
|
+
}
|
|
128
|
+
.bb-callout-warning {
|
|
129
|
+
--bb-callout-accent: #d29922;
|
|
130
|
+
}
|
|
131
|
+
.bb-callout-caution {
|
|
132
|
+
--bb-callout-accent: #f85149;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { renderMermaidSVG } from 'beautiful-mermaid';
|
|
3
|
+
import type { CustomBlocksConfig, DiagramNode } from './types';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
node: DiagramNode;
|
|
7
|
+
blocks?: CustomBlocksConfig;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { node, blocks } = Astro.props;
|
|
11
|
+
|
|
12
|
+
const source = node.value ?? '';
|
|
13
|
+
const format = node.format ?? 'mermaid';
|
|
14
|
+
const DiagramComp = blocks?.diagram;
|
|
15
|
+
|
|
16
|
+
// beautiful-mermaid renders Mermaid to an SVG string synchronously on the
|
|
17
|
+
// server — no browser, no client-side hydration. It throws on empty or invalid
|
|
18
|
+
// input and on unsupported diagram types (gantt, pie, mindmap, gitGraph, …); in
|
|
19
|
+
// that case we fall back to the raw source in a <pre> so content is never lost.
|
|
20
|
+
let svg: string | null = null;
|
|
21
|
+
if (!DiagramComp && source) {
|
|
22
|
+
try {
|
|
23
|
+
const out = renderMermaidSVG(source);
|
|
24
|
+
svg = typeof out === 'string' && out.includes('<svg') ? out : null;
|
|
25
|
+
} catch {
|
|
26
|
+
svg = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const Custom = DiagramComp as any;
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
Custom ? (
|
|
34
|
+
<Custom code={source} format={format} />
|
|
35
|
+
) : svg !== null ? (
|
|
36
|
+
<div class="mermaid-diagram" set:html={svg} />
|
|
37
|
+
) : (
|
|
38
|
+
<pre class="mermaid-source">{source}</pre>
|
|
39
|
+
)
|
|
40
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -128,6 +128,22 @@ export type MediaEmbedNode = {
|
|
|
128
128
|
children: [{ type: 'text'; text: '' }];
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
+
export type DiagramNode = {
|
|
132
|
+
type: 'diagram';
|
|
133
|
+
format: 'mermaid';
|
|
134
|
+
value: string;
|
|
135
|
+
children: [{ type: 'text'; text: '' }];
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export type CalloutVariant = 'note' | 'tip' | 'important' | 'warning' | 'caution';
|
|
139
|
+
|
|
140
|
+
export type CalloutNode = {
|
|
141
|
+
type: 'callout';
|
|
142
|
+
variant: CalloutVariant;
|
|
143
|
+
title?: string;
|
|
144
|
+
children: BlockNode[];
|
|
145
|
+
};
|
|
146
|
+
|
|
131
147
|
export type BlockNode =
|
|
132
148
|
| ParagraphNode
|
|
133
149
|
| HeadingNode
|
|
@@ -138,7 +154,9 @@ export type BlockNode =
|
|
|
138
154
|
| HorizontalLineNode
|
|
139
155
|
| TableNode
|
|
140
156
|
| MediaEmbedNode
|
|
141
|
-
| MathNode
|
|
157
|
+
| MathNode
|
|
158
|
+
| DiagramNode
|
|
159
|
+
| CalloutNode;
|
|
142
160
|
|
|
143
161
|
export type BlocksContent = BlockNode[];
|
|
144
162
|
|
|
@@ -176,6 +194,8 @@ export type AstroComponentFactory = (...args: any[]) => any;
|
|
|
176
194
|
* - `table` / `table-row` / `table-cell` / `table-header-cell` — children via `<slot />`
|
|
177
195
|
* - `media-embed` — `{ url: string; originalUrl?: string }`
|
|
178
196
|
* - `math` — `{ formula: string; inline: boolean }`
|
|
197
|
+
* - `diagram` — `{ code: string; format: 'mermaid' }`
|
|
198
|
+
* - `callout` — `{ variant: CalloutVariant; title?: string }` (children via `<slot />`)
|
|
179
199
|
*/
|
|
180
200
|
export type CustomBlocksConfig = Partial<{
|
|
181
201
|
paragraph: AstroComponentFactory;
|
|
@@ -193,6 +213,8 @@ export type CustomBlocksConfig = Partial<{
|
|
|
193
213
|
'table-header-cell': AstroComponentFactory;
|
|
194
214
|
'media-embed': AstroComponentFactory;
|
|
195
215
|
math: AstroComponentFactory;
|
|
216
|
+
diagram: AstroComponentFactory;
|
|
217
|
+
callout: AstroComponentFactory;
|
|
196
218
|
}>;
|
|
197
219
|
|
|
198
220
|
/**
|