@k11k/better-blocks-astro-renderer 0.2.0 → 0.3.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 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. [License](#license)
37
+ 10. [Support this project](#support-this-project)
38
+ 11. [License](#license)
35
39
 
36
40
  ---
37
41
 
@@ -110,22 +114,31 @@ 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
+
113
125
  ## Supported Blocks
114
126
 
115
- | Block | Default element | Source |
116
- | ------------------------------- | ------------------- | --------------------------- |
117
- | `paragraph` | `<p>` | Strapi core |
118
- | `heading` (1&ndash;6) | `<h1>`&ndash;`<h6>` | Strapi core |
119
- | `list` (ordered/unordered/todo) | `<ol>` / `<ul>` | Strapi core + Better Blocks |
120
- | `list-item` | `<li>` | Strapi core |
121
- | `link` | `<a>` | Strapi core |
122
- | `quote` | `<blockquote>` | Strapi core |
123
- | `code` | `<pre><code>` | Strapi core |
124
- | `image` | `<figure><img>` | Strapi core |
125
- | `horizontal-line` | `<hr>` | Better Blocks |
126
- | `table` | `<table>` | Better Blocks |
127
- | `media-embed` | `<iframe>` (16:9) | Better Blocks |
128
- | `math` (inline/block) | `<span>` / `<div>` | Better Blocks |
127
+ | Block | Default element | Source |
128
+ | ------------------------------- | -------------------- | --------------------------- |
129
+ | `paragraph` | `<p>` | Strapi core |
130
+ | `heading` (1&ndash;6) | `<h1>`&ndash;`<h6>` | Strapi core |
131
+ | `list` (ordered/unordered/todo) | `<ol>` / `<ul>` | Strapi core + Better Blocks |
132
+ | `list-item` | `<li>` | Strapi core |
133
+ | `link` | `<a>` | Strapi core |
134
+ | `quote` | `<blockquote>` | Strapi core |
135
+ | `code` | `<pre><code>` | Strapi core |
136
+ | `image` | `<figure><img>` | Strapi core |
137
+ | `horizontal-line` | `<hr>` | Better Blocks |
138
+ | `table` | `<table>` | Better Blocks |
139
+ | `media-embed` | `<iframe>` (16:9) | Better Blocks |
140
+ | `math` (inline/block) | `<span>` / `<div>` | Better Blocks |
141
+ | `diagram` (mermaid) | `<div>` (inline SVG) | Better Blocks |
129
142
 
130
143
  ### Block properties
131
144
 
@@ -145,6 +158,8 @@ import 'katex/dist/katex.min.css';
145
158
  | `originalUrl` | media-embed | Original user-provided URL |
146
159
  | `format` | math | `inline` (`<span>`) or `block` (`<div>`) |
147
160
  | `value` | math | LaTeX source rendered with KaTeX |
161
+ | `format` | diagram | `mermaid` (the only supported diagram format) |
162
+ | `value` | diagram | Mermaid source, pre-rendered to SVG on the server |
148
163
 
149
164
  ## Supported Modifiers
150
165
 
@@ -217,6 +232,7 @@ The props each custom block component receives:
217
232
  | `table` / `table-row` / `table-cell` / `table-header-cell` | children via `<slot />` |
218
233
  | `media-embed` | `{ url; originalUrl? }` (no slot) |
219
234
  | `math` | `{ formula; inline }` (no slot) — bring your own math engine |
235
+ | `diagram` | `{ code; format }` (no slot) — bring your own diagram engine |
220
236
 
221
237
  ### Custom modifier renderers
222
238
 
@@ -267,6 +283,7 @@ import type {
267
283
  TableHeaderCellNode,
268
284
  MediaEmbedNode,
269
285
  MathNode,
286
+ DiagramNode,
270
287
  TextAlign,
271
288
  CustomBlocksConfig,
272
289
  CustomModifiersConfig,
@@ -327,6 +344,16 @@ yarn lint # Check formatting
327
344
  - [@k11k/better-blocks-react-renderer](https://github.com/k11k-labs/better-blocks-react-renderer) &mdash; React renderer with the same Better Blocks support
328
345
  - [@k11k/strapi-plugin-better-blocks](https://github.com/k11k-labs/strapi-plugin-better-blocks) &mdash; Strapi plugin that extends the Blocks editor with colors, tables, to-do lists, media embeds, and more
329
346
 
347
+ ## Support this project
348
+
349
+ 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:
350
+
351
+ <a href="https://buymeacoffee.com/k11k">
352
+ <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" />
353
+ </a>
354
+
355
+ Every coffee goes toward fixing bugs, reviewing PRs, writing docs, and shipping the features you ask for. Thank you! &#9749;
356
+
330
357
  ## License
331
358
 
332
359
  [MIT License](LICENSE) &copy; [k11k-labs](https://github.com/k11k-labs)
package/index.ts CHANGED
@@ -21,6 +21,7 @@ export type {
21
21
  TableHeaderCellNode,
22
22
  MediaEmbedNode,
23
23
  MathNode,
24
+ DiagramNode,
24
25
  TextAlign,
25
26
  StyleValue,
26
27
  CustomBlocksConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k11k/better-blocks-astro-renderer",
3
- "version": "0.2.0",
3
+ "version": "0.3.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,7 @@ 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';
7
8
  import { getBlockStyle, getPlainText } from './utils';
8
9
 
9
10
  interface Props {
@@ -154,3 +155,5 @@ const EmbedComp = blocks?.['media-embed'] as any;
154
155
  }
155
156
 
156
157
  {block.type === 'math' && <Math node={block} blocks={blocks} />}
158
+
159
+ {block.type === 'diagram' && <Diagram node={block} blocks={blocks} />}
@@ -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,13 @@ 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
+
131
138
  export type BlockNode =
132
139
  | ParagraphNode
133
140
  | HeadingNode
@@ -138,7 +145,8 @@ export type BlockNode =
138
145
  | HorizontalLineNode
139
146
  | TableNode
140
147
  | MediaEmbedNode
141
- | MathNode;
148
+ | MathNode
149
+ | DiagramNode;
142
150
 
143
151
  export type BlocksContent = BlockNode[];
144
152
 
@@ -176,6 +184,7 @@ export type AstroComponentFactory = (...args: any[]) => any;
176
184
  * - `table` / `table-row` / `table-cell` / `table-header-cell` — children via `<slot />`
177
185
  * - `media-embed` — `{ url: string; originalUrl?: string }`
178
186
  * - `math` — `{ formula: string; inline: boolean }`
187
+ * - `diagram` — `{ code: string; format: 'mermaid' }`
179
188
  */
180
189
  export type CustomBlocksConfig = Partial<{
181
190
  paragraph: AstroComponentFactory;
@@ -193,6 +202,7 @@ export type CustomBlocksConfig = Partial<{
193
202
  'table-header-cell': AstroComponentFactory;
194
203
  'media-embed': AstroComponentFactory;
195
204
  math: AstroComponentFactory;
205
+ diagram: AstroComponentFactory;
196
206
  }>;
197
207
 
198
208
  /**