@echozedlabs/renderers 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eric Zimmerman (echozed)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @echozedlabs/renderers
2
+
3
+ Preview renderer registry for the [echozed markdown editor](https://github.com/echozulucode/markdown-editor): Markdown → HTML, Shiki syntax highlighting, and Mermaid / PlantUML diagrams, with per-renderer failure isolation and DOMPurify-sanitized output.
4
+
5
+ Most consumers should install [`@echozedlabs/react`](https://www.npmjs.com/package/@echozedlabs/react), which uses these renderers for preview mode. Use this package directly to render Markdown/diagrams outside the editor.
6
+
7
+ ## License
8
+
9
+ [MIT](https://github.com/echozulucode/markdown-editor/blob/main/LICENSE) © Eric Zimmerman (echozed)
@@ -0,0 +1,3 @@
1
+ export declare function escapeHtml(value: string): string;
2
+ export declare function escapeAttribute(value: string): string;
3
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
package/dist/escape.js ADDED
@@ -0,0 +1,12 @@
1
+ export function escapeHtml(value) {
2
+ return value
3
+ .replace(/&/g, '&')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;')
7
+ .replace(/'/g, '&#39;');
8
+ }
9
+ export function escapeAttribute(value) {
10
+ return escapeHtml(value).replace(/`/g, '&#96;');
11
+ }
12
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,11 @@
1
+ export { RendererRegistry, createDefaultRendererRegistry } from './registry';
2
+ export { parseMarkdownBlocks, renderMarkdownToHtml } from './markdown';
3
+ export { createMermaidRenderer } from './mermaid';
4
+ export { createPlantUmlRenderer, constrainDiagramSvgWidth } from './plantuml';
5
+ export { createShikiCodeRenderer } from './shiki';
6
+ export type { MermaidRendererOptions } from './mermaid';
7
+ export type { PlantUmlRendererOptions } from './plantuml';
8
+ export type { RenderMarkdownToHtmlResult } from './markdown';
9
+ export type { ShikiCodeRendererOptions } from './shiki';
10
+ export type { AsyncCodeRenderer, AsyncDiagramRenderer, BlockRenderer, CalloutBlock, CodeBlock, CodeRendererOptions, DiagramRendererOptions, HeadingBlock, ImageBlock, MarkdownBlock, ParagraphBlock, PlantUmlHostRenderer, RendererBlockKind, RendererContext, RendererDiagnostic, RendererRegistryOptions, RendererResult, SimpleBlock, TableBlock } from './types';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAClD,YAAY,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,sBAAsB,EACtB,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,WAAW,EACX,UAAU,EACX,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { RendererRegistry, createDefaultRendererRegistry } from './registry';
2
+ export { parseMarkdownBlocks, renderMarkdownToHtml } from './markdown';
3
+ export { createMermaidRenderer } from './mermaid';
4
+ export { createPlantUmlRenderer, constrainDiagramSvgWidth } from './plantuml';
5
+ export { createShikiCodeRenderer } from './shiki';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { RendererRegistry } from './registry';
2
+ import type { MarkdownBlock, RendererDiagnostic } from './types';
3
+ export interface RenderMarkdownOptions {
4
+ registry?: RendererRegistry;
5
+ signal?: AbortSignal;
6
+ }
7
+ export interface RenderMarkdownToHtmlResult {
8
+ html: string;
9
+ blocks: MarkdownBlock[];
10
+ diagnostics: RendererDiagnostic[];
11
+ }
12
+ export declare function renderMarkdownToHtml(markdown: string, options?: RenderMarkdownOptions): Promise<RenderMarkdownToHtmlResult>;
13
+ export declare function parseMarkdownBlocks(markdown: string): MarkdownBlock[];
14
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,KAAK,EAA2B,aAAa,EAAE,kBAAkB,EAAkB,MAAM,SAAS,CAAC;AAE1G,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,0BAA0B,CAAC,CAkBrC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAkIrE"}
@@ -0,0 +1,222 @@
1
+ import { createDefaultRendererRegistry } from './registry';
2
+ import { escapeHtml } from './escape';
3
+ export async function renderMarkdownToHtml(markdown, options = {}) {
4
+ const registry = options.registry ?? createDefaultRendererRegistry();
5
+ const frontmatter = parseFrontmatter(markdown);
6
+ const blocks = parseMarkdownBlocks(frontmatter?.body ?? markdown);
7
+ const results = [];
8
+ for (const block of blocks) {
9
+ results.push(await registry.renderBlock(block, { blockId: block.id, signal: options.signal }));
10
+ }
11
+ return {
12
+ html: [
13
+ frontmatter ? renderFrontmatterProperties(frontmatter.entries) : '',
14
+ ...results.map((result) => result.html)
15
+ ].filter(Boolean).join('\n'),
16
+ blocks,
17
+ diagnostics: results.flatMap((result) => result.diagnostics ?? [])
18
+ };
19
+ }
20
+ export function parseMarkdownBlocks(markdown) {
21
+ const lines = markdown.replace(/\r\n?/g, '\n').split('\n');
22
+ const blocks = [];
23
+ let index = 0;
24
+ while (index < lines.length) {
25
+ const line = lines[index];
26
+ if (line.trim() === '') {
27
+ index += 1;
28
+ continue;
29
+ }
30
+ const fence = line.match(/^```([\w-]+)?\s*$/);
31
+ if (fence) {
32
+ const language = fence[1]?.toLowerCase();
33
+ const start = index;
34
+ index += 1;
35
+ const sourceLines = [];
36
+ while (index < lines.length && !lines[index].startsWith('```')) {
37
+ sourceLines.push(lines[index]);
38
+ index += 1;
39
+ }
40
+ if (index < lines.length) {
41
+ index += 1;
42
+ }
43
+ const kind = language === 'mermaid' ? 'mermaid' : language === 'plantuml' || language === 'puml' ? 'plantuml' : 'code';
44
+ blocks.push({
45
+ id: blockId(blocks.length),
46
+ kind,
47
+ language,
48
+ source: sourceLines.join('\n'),
49
+ raw: lines.slice(start, index).join('\n')
50
+ });
51
+ continue;
52
+ }
53
+ const heading = line.match(/^(#{1,6})\s+(.+)$/);
54
+ if (heading) {
55
+ blocks.push({
56
+ id: blockId(blocks.length),
57
+ kind: 'heading',
58
+ depth: heading[1].length,
59
+ text: heading[2],
60
+ raw: line
61
+ });
62
+ index += 1;
63
+ continue;
64
+ }
65
+ const image = line.match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)$/);
66
+ if (image) {
67
+ blocks.push({
68
+ id: blockId(blocks.length),
69
+ kind: 'image',
70
+ alt: image[1],
71
+ url: image[2],
72
+ title: image[3],
73
+ raw: line
74
+ });
75
+ index += 1;
76
+ continue;
77
+ }
78
+ if (isCalloutStart(line)) {
79
+ const start = index;
80
+ const calloutLines = [];
81
+ while (index < lines.length && lines[index].startsWith('>')) {
82
+ calloutLines.push(lines[index]);
83
+ index += 1;
84
+ }
85
+ blocks.push(parseCallout(blocks.length, calloutLines, lines.slice(start, index).join('\n')));
86
+ continue;
87
+ }
88
+ if (isListLine(line)) {
89
+ const start = index;
90
+ const listLines = [];
91
+ while (index < lines.length && isListLine(lines[index])) {
92
+ listLines.push(lines[index]);
93
+ index += 1;
94
+ }
95
+ blocks.push(parseList(blocks.length, listLines, lines.slice(start, index).join('\n')));
96
+ continue;
97
+ }
98
+ if (isTableLine(line) && index + 1 < lines.length && isTableSeparator(lines[index + 1])) {
99
+ const start = index;
100
+ const tableLines = [];
101
+ while (index < lines.length && isTableLine(lines[index])) {
102
+ if (!isTableSeparator(lines[index])) {
103
+ tableLines.push(lines[index]);
104
+ }
105
+ index += 1;
106
+ }
107
+ blocks.push({
108
+ id: blockId(blocks.length),
109
+ kind: 'table',
110
+ rows: tableLines.map(parseTableRow),
111
+ raw: lines.slice(start, index).join('\n')
112
+ });
113
+ continue;
114
+ }
115
+ const paragraphLines = [];
116
+ const start = index;
117
+ while (index < lines.length && lines[index].trim() !== '') {
118
+ paragraphLines.push(lines[index]);
119
+ index += 1;
120
+ }
121
+ blocks.push({
122
+ id: blockId(blocks.length),
123
+ kind: 'paragraph',
124
+ text: paragraphLines.join('\n'),
125
+ raw: lines.slice(start, index).join('\n')
126
+ });
127
+ }
128
+ return blocks;
129
+ }
130
+ function parseList(index, lines, raw) {
131
+ const ordered = /^\s*\d+[.)]\s+/.test(lines[0]);
132
+ return {
133
+ id: blockId(index),
134
+ kind: 'list',
135
+ ordered,
136
+ items: lines.map((line) => {
137
+ const stripped = line.replace(/^\s*(?:[-*+]\s+|\d+[.)]\s+)/, '');
138
+ const task = stripped.match(/^\[([ xX])\]\s+(.*)$/);
139
+ if (!task) {
140
+ return { text: stripped };
141
+ }
142
+ return {
143
+ text: task[2],
144
+ checked: task[1].toLowerCase() === 'x'
145
+ };
146
+ }),
147
+ raw
148
+ };
149
+ }
150
+ function parseCallout(index, lines, raw) {
151
+ const first = lines[0].replace(/^>\s?/, '');
152
+ const match = first.match(/^\[!(\w+)\]\s*(.*)$/);
153
+ const body = lines.slice(1).map((line) => line.replace(/^>\s?/, '')).join('\n');
154
+ return {
155
+ id: blockId(index),
156
+ kind: 'callout',
157
+ calloutType: match?.[1] ?? 'note',
158
+ title: match?.[2] || undefined,
159
+ body,
160
+ raw
161
+ };
162
+ }
163
+ function blockId(index) {
164
+ return `block-${index + 1}`;
165
+ }
166
+ function isCalloutStart(line) {
167
+ return /^>\s?\[!\w+\]/.test(line);
168
+ }
169
+ function isListLine(line) {
170
+ return /^\s*(?:[-*+]\s+|\d+[.)]\s+)/.test(line);
171
+ }
172
+ function isTableLine(line) {
173
+ return /^\|.*\|$/.test(line.trim());
174
+ }
175
+ function isTableSeparator(line) {
176
+ return /^\|\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?$/.test(line.trim());
177
+ }
178
+ function parseTableRow(line) {
179
+ return line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
180
+ }
181
+ function parseFrontmatter(markdown) {
182
+ const normalized = markdown.replace(/\r\n?/g, '\n');
183
+ const lines = normalized.split('\n');
184
+ if (lines.length < 3 || lines[0].trim() !== '---') {
185
+ return null;
186
+ }
187
+ const closingIndex = lines.findIndex((line, index) => index > 0 && line.trim() === '---');
188
+ if (closingIndex < 0) {
189
+ return null;
190
+ }
191
+ return {
192
+ entries: lines.slice(1, closingIndex).map(parseFrontmatterProperty).filter(isFrontmatterProperty),
193
+ body: lines.slice(closingIndex + 1).join('\n')
194
+ };
195
+ }
196
+ function parseFrontmatterProperty(line) {
197
+ const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
198
+ if (!match) {
199
+ return null;
200
+ }
201
+ return {
202
+ key: match[1],
203
+ value: trimYamlScalar(match[2])
204
+ };
205
+ }
206
+ function trimYamlScalar(value) {
207
+ const trimmed = value.trim();
208
+ const quoted = trimmed.match(/^(['"])(.*)\1$/);
209
+ return quoted ? quoted[2] : trimmed;
210
+ }
211
+ function isFrontmatterProperty(entry) {
212
+ return entry !== null;
213
+ }
214
+ function renderFrontmatterProperties(entries) {
215
+ const rows = entries.length === 0
216
+ ? '<tr><td colspan="2">No properties</td></tr>'
217
+ : entries
218
+ .map((entry) => `<tr><th>${escapeHtml(entry.key)}</th><td>${escapeHtml(entry.value)}</td></tr>`)
219
+ .join('');
220
+ return `<section class="me-renderer-properties" aria-label="Markdown properties"><table class="me-renderer-properties-table"><tbody>${rows}</tbody></table></section>`;
221
+ }
222
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AsyncDiagramRenderer } from './types';
2
+ export interface MermaidRendererOptions {
3
+ timeoutMs?: number;
4
+ }
5
+ export declare function createMermaidRenderer(options?: MermaidRendererOptions): AsyncDiagramRenderer;
6
+ //# sourceMappingURL=mermaid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../src/mermaid.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAA8D,MAAM,SAAS,CAAC;AAEhH,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,oBAAoB,CAmChG"}
@@ -0,0 +1,67 @@
1
+ import { escapeAttribute, escapeHtml } from './escape';
2
+ let mermaidCounter = 0;
3
+ export function createMermaidRenderer(options = {}) {
4
+ const timeoutMs = options.timeoutMs ?? 3000;
5
+ return async ({ source, blockId, signal }) => {
6
+ if (signal?.aborted) {
7
+ return failure(source, blockId, 'renderer.mermaid.aborted', 'Mermaid rendering was aborted.');
8
+ }
9
+ try {
10
+ const mermaid = await import('mermaid');
11
+ const renderer = mermaid.default;
12
+ renderer.initialize({
13
+ startOnLoad: false,
14
+ securityLevel: 'strict',
15
+ theme: 'default',
16
+ // Render labels as SVG <text>, not HTML in <foreignObject>. The
17
+ // downstream HTML sanitizer (DOMPurify) categorically strips foreignObject
18
+ // HTML, which made diagram text disappear. Mermaid v11 only honors the
19
+ // TOP-LEVEL `htmlLabels` flag for flowcharts (the per-diagram
20
+ // `flowchart.htmlLabels` alone is NOT enough); set both.
21
+ htmlLabels: false,
22
+ flowchart: { htmlLabels: false }
23
+ });
24
+ const id = `me-mermaid-${blockId.replace(/[^a-zA-Z0-9_-]/g, '-')}-${++mermaidCounter}`;
25
+ const rendered = await withTimeout(renderer.render(id, source), timeoutMs);
26
+ return {
27
+ ok: true,
28
+ html: `<figure class="me-renderer-diagram me-renderer-mermaid" data-block-id="${escapeAttribute(blockId)}">${rendered.svg}</figure>`
29
+ };
30
+ }
31
+ catch (cause) {
32
+ return failure(source, blockId, 'renderer.mermaid.failed', 'Mermaid renderer failed; rendered source fallback.', cause);
33
+ }
34
+ };
35
+ }
36
+ async function withTimeout(promise, timeoutMs) {
37
+ let timeout;
38
+ try {
39
+ return await Promise.race([
40
+ promise,
41
+ new Promise((_, reject) => {
42
+ timeout = setTimeout(() => reject(new Error(`Mermaid render timed out after ${timeoutMs}ms.`)), timeoutMs);
43
+ })
44
+ ]);
45
+ }
46
+ finally {
47
+ if (timeout) {
48
+ clearTimeout(timeout);
49
+ }
50
+ }
51
+ }
52
+ function failure(source, blockId, code, message, cause) {
53
+ const error = {
54
+ severity: code.endsWith('.aborted') ? 'warning' : 'error',
55
+ code,
56
+ message,
57
+ blockId,
58
+ cause
59
+ };
60
+ return {
61
+ ok: false,
62
+ html: `<pre class="me-renderer-error" data-language="mermaid"><code>${escapeHtml(source)}</code></pre>`,
63
+ error,
64
+ diagnostics: [error]
65
+ };
66
+ }
67
+ //# sourceMappingURL=mermaid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../src/mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOvD,IAAI,cAAc,GAAG,CAAC,CAAC;AAEvB,MAAM,UAAU,qBAAqB,CAAC,UAAkC,EAAE;IACxE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAA0B,EAA2B,EAAE;QAC5F,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE,gCAAgC,CAAC,CAAC;QAChG,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YACjC,QAAQ,CAAC,UAAU,CAAC;gBAClB,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,QAAQ;gBACvB,KAAK,EAAE,SAAS;gBAChB,gEAAgE;gBAChE,2EAA2E;gBAC3E,uEAAuE;gBACvE,8DAA8D;gBAC9D,yDAAyD;gBACzD,UAAU,EAAE,KAAK;gBACjB,SAAS,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE;aACjC,CAAC,CAAC;YAEH,MAAM,EAAE,GAAG,cAAc,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC;YACvF,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;YAE3E,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,0EAA0E,eAAe,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,GAAG,WAAW;aACrI,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,oDAAoD,EAAE,KAAK,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW,CAAI,OAAmB,EAAE,SAAiB;IAClE,IAAI,OAAkD,CAAC;IAEvD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACxB,OAAO;YACP,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBAC/B,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,SAAS,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAC7G,CAAC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CACd,MAAc,EACd,OAAe,EACf,IAAY,EACZ,OAAe,EACf,KAAe;IAEf,MAAM,KAAK,GAAuB;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;QACzD,IAAI;QACJ,OAAO;QACP,OAAO;QACP,KAAK;KACN,CAAC;IAEF,OAAO;QACL,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,gEAAgE,UAAU,CAAC,MAAM,CAAC,eAAe;QACvG,KAAK;QACL,WAAW,EAAE,CAAC,KAAK,CAAC;KACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { AsyncDiagramRenderer, PlantUmlHostRenderer } from './types';
2
+ export interface PlantUmlRendererOptions {
3
+ renderPlantUml: PlantUmlHostRenderer['renderPlantUml'];
4
+ timeoutMs?: number;
5
+ }
6
+ export declare function createPlantUmlRenderer(options: PlantUmlRendererOptions): AsyncDiagramRenderer;
7
+ /**
8
+ * Give different-sized PlantUML diagrams sensible default sizing. A host SVG
9
+ * with only a `viewBox` (no width/height) is stretched by the browser to fill
10
+ * its container, so a small diagram renders huge on a wide screen. We cap such
11
+ * SVGs at their intrinsic viewBox width via `max-width: <W>px` — the diagram
12
+ * never upscales past its natural size yet still shrinks responsively on narrow
13
+ * screens (mirroring how Mermaid sizes its output). SVGs that already declare a
14
+ * width or a max-width, and non-SVG output (e.g. <img>), are left untouched.
15
+ */
16
+ export declare function constrainDiagramSvgWidth(html: string): string;
17
+ //# sourceMappingURL=plantuml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plantuml.d.ts","sourceRoot":"","sources":["../src/plantuml.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EAEpB,oBAAoB,EAGrB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,oBAAoB,CA0B7F;AAiCD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY7D"}
@@ -0,0 +1,92 @@
1
+ import { escapeHtml } from './escape';
2
+ export function createPlantUmlRenderer(options) {
3
+ const timeoutMs = options.timeoutMs ?? 5000;
4
+ return async ({ source, blockId, signal }) => {
5
+ if (signal?.aborted) {
6
+ return failure(source, blockId, 'renderer.plantuml.aborted', 'PlantUML rendering was aborted.');
7
+ }
8
+ try {
9
+ const result = await withTimeout(options.renderPlantUml(source, {
10
+ blockId,
11
+ signal
12
+ }), timeoutMs);
13
+ if (signal?.aborted) {
14
+ return failure(source, blockId, 'renderer.plantuml.aborted', 'PlantUML rendering was aborted.');
15
+ }
16
+ return normalizeHostResult(result);
17
+ }
18
+ catch (cause) {
19
+ return failure(source, blockId, 'renderer.plantuml.failed', 'PlantUML renderer failed; rendered source fallback.', cause);
20
+ }
21
+ };
22
+ }
23
+ async function withTimeout(promise, timeoutMs) {
24
+ let timeout;
25
+ try {
26
+ return await Promise.race([
27
+ promise,
28
+ new Promise((_, reject) => {
29
+ timeout = setTimeout(() => reject(new Error(`PlantUML render timed out after ${timeoutMs}ms.`)), timeoutMs);
30
+ })
31
+ ]);
32
+ }
33
+ finally {
34
+ if (timeout) {
35
+ clearTimeout(timeout);
36
+ }
37
+ }
38
+ }
39
+ function normalizeHostResult(result) {
40
+ if (isRendererResult(result)) {
41
+ return { ...result, html: constrainDiagramSvgWidth(result.html) };
42
+ }
43
+ return {
44
+ ok: true,
45
+ html: constrainDiagramSvgWidth(result.html),
46
+ diagnostics: result.diagnostics?.filter((diagnostic) => diagnostic.severity !== 'info')
47
+ };
48
+ }
49
+ /**
50
+ * Give different-sized PlantUML diagrams sensible default sizing. A host SVG
51
+ * with only a `viewBox` (no width/height) is stretched by the browser to fill
52
+ * its container, so a small diagram renders huge on a wide screen. We cap such
53
+ * SVGs at their intrinsic viewBox width via `max-width: <W>px` — the diagram
54
+ * never upscales past its natural size yet still shrinks responsively on narrow
55
+ * screens (mirroring how Mermaid sizes its output). SVGs that already declare a
56
+ * width or a max-width, and non-SVG output (e.g. <img>), are left untouched.
57
+ */
58
+ export function constrainDiagramSvgWidth(html) {
59
+ return html.replace(/<svg\b[^>]*>/gi, (tag) => {
60
+ if (/\swidth\s*=/.test(tag))
61
+ return tag;
62
+ if (/style\s*=\s*"[^"]*max-width/i.test(tag))
63
+ return tag;
64
+ const viewBox = tag.match(/viewBox\s*=\s*"\s*[-\d.]+\s+[-\d.]+\s+([\d.]+)\s+[\d.]+/i);
65
+ const width = viewBox ? Math.round(parseFloat(viewBox[1])) : NaN;
66
+ if (!Number.isFinite(width) || width <= 0)
67
+ return tag;
68
+ const declaration = `max-width:${width}px;`;
69
+ return /style\s*=\s*"/i.test(tag)
70
+ ? tag.replace(/style\s*=\s*"/i, `style="${declaration}`)
71
+ : tag.replace(/<svg\b/i, `<svg style="${declaration}"`);
72
+ });
73
+ }
74
+ function isRendererResult(result) {
75
+ return 'ok' in result;
76
+ }
77
+ function failure(source, blockId, code, message, cause) {
78
+ const error = {
79
+ severity: code.endsWith('.aborted') ? 'warning' : 'error',
80
+ code,
81
+ message,
82
+ blockId,
83
+ cause
84
+ };
85
+ return {
86
+ ok: false,
87
+ html: `<pre class="me-renderer-error" data-language="plantuml"><code>${escapeHtml(source)}</code></pre>`,
88
+ error,
89
+ diagnostics: [error]
90
+ };
91
+ }
92
+ //# sourceMappingURL=plantuml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plantuml.js","sourceRoot":"","sources":["../src/plantuml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAetC,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAA0B,EAA2B,EAAE;QAC5F,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,2BAA2B,EAAE,iCAAiC,CAAC,CAAC;QAClG,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE;gBAC7B,OAAO;gBACP,MAAM;aACP,CAAC,EACF,SAAS,CACV,CAAC;YAEF,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,2BAA2B,EAAE,iCAAiC,CAAC,CAAC;YAClG,CAAC;YAED,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE,qDAAqD,EAAE,KAAK,CAAC,CAAC;QAC5H,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW,CAAI,OAAmB,EAAE,SAAiB;IAClE,IAAI,OAAkD,CAAC;IAEvD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACxB,OAAO;YACP,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBAC/B,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,SAAS,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAC9G,CAAC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAyC;IACpE,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IACpE,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC;QAC3C,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,MAAM,CAEzE;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,EAAE;QAC5C,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;QACxC,IAAI,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;QACzD,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;QACtD,MAAM,WAAW,GAAG,aAAa,KAAK,KAAK,CAAC;QAC5C,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;YAC/B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,UAAU,WAAW,EAAE,CAAC;YACxD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,WAAW,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAyC;IACjE,OAAO,IAAI,IAAI,MAAM,CAAC;AACxB,CAAC;AAED,SAAS,OAAO,CACd,MAAc,EACd,OAAe,EACf,IAAY,EACZ,OAAe,EACf,KAAe;IAEf,MAAM,KAAK,GAAuB;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;QACzD,IAAI;QACJ,OAAO;QACP,OAAO;QACP,KAAK;KACN,CAAC;IAEF,OAAO;QACL,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,iEAAiE,UAAU,CAAC,MAAM,CAAC,eAAe;QACxG,KAAK;QACL,WAAW,EAAE,CAAC,KAAK,CAAC;KACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { BlockRenderer, MarkdownBlock, RendererContext, RendererRegistryOptions, RendererResult } from './types';
2
+ export declare class RendererRegistry {
3
+ private readonly renderers;
4
+ register<TBlock extends MarkdownBlock>(kind: TBlock['kind'], renderer: BlockRenderer<TBlock>): void;
5
+ renderBlock(block: MarkdownBlock, context?: Partial<RendererContext>): Promise<RendererResult>;
6
+ }
7
+ export declare function createDefaultRendererRegistry(options?: RendererRegistryOptions): RendererRegistry;
8
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,aAAa,EAEb,aAAa,EAEb,eAAe,EAEf,uBAAuB,EACvB,cAAc,EAQf,MAAM,SAAS,CAAC;AAEjB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+C;IAEzE,QAAQ,CAAC,MAAM,SAAS,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI;IAI7F,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;CAmBrG;AAED,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,uBAA4B,GAAG,gBAAgB,CA6CrG"}
@@ -0,0 +1,154 @@
1
+ import { escapeAttribute, escapeHtml } from './escape';
2
+ import { createPlantUmlRenderer } from './plantuml';
3
+ export class RendererRegistry {
4
+ renderers = new Map();
5
+ register(kind, renderer) {
6
+ this.renderers.set(kind, renderer);
7
+ }
8
+ async renderBlock(block, context) {
9
+ const renderer = this.renderers.get(block.kind) ?? fallbackUnsupportedRenderer;
10
+ const normalizedContext = {
11
+ blockId: context?.blockId ?? block.id,
12
+ signal: context?.signal
13
+ };
14
+ try {
15
+ return await renderer(block, normalizedContext);
16
+ }
17
+ catch (cause) {
18
+ return errorResult(block, {
19
+ severity: 'error',
20
+ code: 'renderer.threw',
21
+ message: `Renderer for "${block.kind}" failed.`,
22
+ blockId: normalizedContext.blockId,
23
+ cause
24
+ });
25
+ }
26
+ }
27
+ }
28
+ export function createDefaultRendererRegistry(options = {}) {
29
+ const registry = new RendererRegistry();
30
+ registry.register('paragraph', (block) => ok(`<p>${escapeHtml(block.text)}</p>`));
31
+ registry.register('heading', (block) => ok(`<h${block.depth}>${escapeHtml(block.text)}</h${block.depth}>`));
32
+ registry.register('list', (block) => ok(renderList(block)));
33
+ registry.register('blockquote', (block) => ok(`<blockquote>${escapeHtml(block.text)}</blockquote>`));
34
+ registry.register('html', (block) => ok(`<pre class="me-renderer-html">${escapeHtml(block.raw)}</pre>`));
35
+ registry.register('table', (block) => ok(renderTable(block.rows)));
36
+ registry.register('image', (block) => {
37
+ const title = block.title ? ` title="${escapeAttribute(block.title)}"` : '';
38
+ return ok(`<img src="${escapeAttribute(block.url)}" alt="${escapeAttribute(block.alt)}"${title}>`);
39
+ });
40
+ registry.register('callout', (block) => {
41
+ const title = block.title ? `<strong>${escapeHtml(block.title)}</strong>` : '';
42
+ return ok(`<aside class="me-renderer-callout me-renderer-callout-${escapeAttribute(block.calloutType.toLowerCase())}">${title}<p>${escapeHtml(block.body)}</p></aside>`);
43
+ });
44
+ registry.register('code', async (block, context) => {
45
+ if (!options.shiki) {
46
+ return renderPlainCode(block);
47
+ }
48
+ try {
49
+ return await options.shiki({
50
+ language: block.language,
51
+ source: block.source,
52
+ blockId: context.blockId,
53
+ signal: context.signal
54
+ });
55
+ }
56
+ catch (cause) {
57
+ return errorResult(block, {
58
+ severity: 'error',
59
+ code: 'renderer.code.failed',
60
+ message: 'Code highlighter failed; rendered plaintext fallback.',
61
+ blockId: context.blockId,
62
+ cause
63
+ });
64
+ }
65
+ });
66
+ registry.register('mermaid', createDiagramRenderer('mermaid', options.mermaid));
67
+ registry.register('plantuml', createDiagramRenderer('plantuml', normalizePlantUmlRenderer(options.plantUml)));
68
+ return registry;
69
+ }
70
+ function createDiagramRenderer(kind, renderer) {
71
+ return async (block, context) => {
72
+ if (!renderer) {
73
+ return errorResult(block, {
74
+ severity: 'warning',
75
+ code: `renderer.${kind}.missing`,
76
+ message: `${kind} renderer is not configured; rendered source fallback.`,
77
+ blockId: context.blockId
78
+ });
79
+ }
80
+ try {
81
+ return await renderer({
82
+ source: block.source,
83
+ blockId: context.blockId,
84
+ signal: context.signal
85
+ });
86
+ }
87
+ catch (cause) {
88
+ return errorResult(block, {
89
+ severity: 'error',
90
+ code: `renderer.${kind}.failed`,
91
+ message: `${kind} renderer failed; rendered source fallback.`,
92
+ blockId: context.blockId,
93
+ cause
94
+ });
95
+ }
96
+ };
97
+ }
98
+ function normalizePlantUmlRenderer(renderer) {
99
+ if (!renderer) {
100
+ return undefined;
101
+ }
102
+ if (typeof renderer === 'function') {
103
+ return renderer;
104
+ }
105
+ return createPlantUmlRenderer({
106
+ renderPlantUml: renderer.renderPlantUml.bind(renderer)
107
+ });
108
+ }
109
+ function renderPlainCode(block) {
110
+ const language = block.language ? ` data-language="${escapeAttribute(block.language)}"` : '';
111
+ return ok(`<pre class="me-renderer-code"${language}><code>${escapeHtml(block.source)}</code></pre>`);
112
+ }
113
+ function renderList(block) {
114
+ const tag = block.ordered ? 'ol' : 'ul';
115
+ const hasTasks = block.items.some((item) => item.checked !== undefined);
116
+ const className = hasTasks ? ' class="me-renderer-list me-renderer-task-list"' : ' class="me-renderer-list"';
117
+ const items = block.items
118
+ .map((item) => {
119
+ if (item.checked === undefined) {
120
+ return `<li>${escapeHtml(item.text)}</li>`;
121
+ }
122
+ const checked = item.checked ? ' checked' : '';
123
+ return `<li class="me-renderer-task-item"><input class="me-renderer-task-checkbox" type="checkbox" disabled${checked}> <span>${escapeHtml(item.text)}</span></li>`;
124
+ })
125
+ .join('');
126
+ return `<${tag}${className}>${items}</${tag}>`;
127
+ }
128
+ function renderTable(rows) {
129
+ const renderedRows = rows
130
+ .map((row) => `<tr>${row.map((cell) => `<td>${escapeHtml(cell.trim())}</td>`).join('')}</tr>`)
131
+ .join('');
132
+ return `<table><tbody>${renderedRows}</tbody></table>`;
133
+ }
134
+ function fallbackUnsupportedRenderer(block) {
135
+ return errorResult(block, {
136
+ severity: 'warning',
137
+ code: 'renderer.unsupported',
138
+ message: `No renderer registered for "${block.kind}".`,
139
+ blockId: block.id
140
+ });
141
+ }
142
+ function errorResult(block, error) {
143
+ const language = 'language' in block && block.language ? ` data-language="${escapeAttribute(block.language)}"` : '';
144
+ return {
145
+ ok: false,
146
+ html: `<pre class="me-renderer-error"${language}><code>${escapeHtml(block.raw)}</code></pre>`,
147
+ error,
148
+ diagnostics: [error]
149
+ };
150
+ }
151
+ function ok(html) {
152
+ return { ok: true, html };
153
+ }
154
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { AsyncCodeRenderer } from './types';
2
+ type ShikiLanguage = keyof typeof LANGUAGE_LOADERS;
3
+ type ShikiTheme = keyof typeof THEME_LOADERS;
4
+ export interface ShikiCodeRendererOptions {
5
+ theme?: ShikiTheme;
6
+ languages?: ShikiLanguage[];
7
+ fallbackLanguage?: 'text' | 'plaintext';
8
+ }
9
+ declare const LANGUAGE_LOADERS: {
10
+ bash: () => Promise<typeof import("shiki/dist/langs/bash.mjs")>;
11
+ css: () => Promise<typeof import("shiki/dist/langs/css.mjs")>;
12
+ html: () => Promise<typeof import("shiki/dist/langs/html.mjs")>;
13
+ javascript: () => Promise<typeof import("shiki/dist/langs/javascript.mjs")>;
14
+ json: () => Promise<typeof import("shiki/dist/langs/json.mjs")>;
15
+ jsx: () => Promise<typeof import("shiki/dist/langs/jsx.mjs")>;
16
+ markdown: () => Promise<typeof import("shiki/dist/langs/markdown.mjs")>;
17
+ python: () => Promise<typeof import("shiki/dist/langs/python.mjs")>;
18
+ shellscript: () => Promise<typeof import("shiki/dist/langs/shellscript.mjs")>;
19
+ sql: () => Promise<typeof import("shiki/dist/langs/sql.mjs")>;
20
+ tsx: () => Promise<typeof import("shiki/dist/langs/tsx.mjs")>;
21
+ typescript: () => Promise<typeof import("shiki/dist/langs/typescript.mjs")>;
22
+ yaml: () => Promise<typeof import("shiki/dist/langs/yaml.mjs")>;
23
+ };
24
+ declare const THEME_LOADERS: {
25
+ 'github-light': () => Promise<typeof import("shiki/dist/themes/github-light.mjs")>;
26
+ };
27
+ export declare function createShikiCodeRenderer(options?: ShikiCodeRendererOptions): AsyncCodeRenderer;
28
+ export {};
29
+ //# sourceMappingURL=shiki.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shiki.d.ts","sourceRoot":"","sources":["../src/shiki.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAA2D,MAAM,SAAS,CAAC;AAE1G,KAAK,aAAa,GAAG,MAAM,OAAO,gBAAgB,CAAC;AACnD,KAAK,UAAU,GAAG,MAAM,OAAO,aAAa,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CACzC;AAmBD,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;CAcrB,CAAC;AAEF,QAAA,MAAM,aAAa;;CAElB,CAAC;AAgBF,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,GAAG,iBAAiB,CAwDjG"}
package/dist/shiki.js ADDED
@@ -0,0 +1,150 @@
1
+ import { createHighlighterCore } from 'shiki/core';
2
+ import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
3
+ import { escapeAttribute, escapeHtml } from './escape';
4
+ const DEFAULT_THEME = 'github-light';
5
+ const DEFAULT_FALLBACK_LANGUAGE = 'text';
6
+ const DEFAULT_LANGUAGES = [
7
+ 'typescript',
8
+ 'javascript',
9
+ 'tsx',
10
+ 'jsx',
11
+ 'python',
12
+ 'bash',
13
+ 'json',
14
+ 'yaml',
15
+ 'markdown',
16
+ 'html',
17
+ 'css',
18
+ 'sql'
19
+ ];
20
+ const LANGUAGE_LOADERS = {
21
+ bash: () => import('shiki/langs/bash.mjs'),
22
+ css: () => import('shiki/langs/css.mjs'),
23
+ html: () => import('shiki/langs/html.mjs'),
24
+ javascript: () => import('shiki/langs/javascript.mjs'),
25
+ json: () => import('shiki/langs/json.mjs'),
26
+ jsx: () => import('shiki/langs/jsx.mjs'),
27
+ markdown: () => import('shiki/langs/markdown.mjs'),
28
+ python: () => import('shiki/langs/python.mjs'),
29
+ shellscript: () => import('shiki/langs/shellscript.mjs'),
30
+ sql: () => import('shiki/langs/sql.mjs'),
31
+ tsx: () => import('shiki/langs/tsx.mjs'),
32
+ typescript: () => import('shiki/langs/typescript.mjs'),
33
+ yaml: () => import('shiki/langs/yaml.mjs')
34
+ };
35
+ const THEME_LOADERS = {
36
+ 'github-light': () => import('shiki/themes/github-light.mjs')
37
+ };
38
+ const LANGUAGE_ALIASES = {
39
+ cjs: 'javascript',
40
+ js: 'javascript',
41
+ jsx: 'jsx',
42
+ md: 'markdown',
43
+ mjs: 'javascript',
44
+ py: 'python',
45
+ sh: 'bash',
46
+ shell: 'bash',
47
+ ts: 'typescript',
48
+ tsx: 'tsx',
49
+ yml: 'yaml'
50
+ };
51
+ export function createShikiCodeRenderer(options = {}) {
52
+ const theme = options.theme ?? DEFAULT_THEME;
53
+ const fallbackLanguage = options.fallbackLanguage ?? DEFAULT_FALLBACK_LANGUAGE;
54
+ const languages = [
55
+ ...new Set([...(options.languages ?? DEFAULT_LANGUAGES), 'shellscript'])
56
+ ];
57
+ let highlighterPromise;
58
+ return async ({ language, source, blockId }) => {
59
+ const requestedLanguage = language?.trim().toLowerCase();
60
+ const normalizedLanguage = normalizeLanguage(requestedLanguage);
61
+ const diagnostics = requestedLanguage && !normalizedLanguage ? fallbackDiagnostic(requestedLanguage, blockId, undefined) : undefined;
62
+ try {
63
+ const highlighter = await getHighlighter();
64
+ const html = highlighter.codeToHtml(source, {
65
+ lang: normalizedLanguage ?? fallbackLanguage,
66
+ theme
67
+ });
68
+ return ok(wrapHighlightedCode(html, requestedLanguage), diagnostics);
69
+ }
70
+ catch (cause) {
71
+ const highlighter = await getHighlighter();
72
+ try {
73
+ const html = highlighter.codeToHtml(source, {
74
+ lang: fallbackLanguage,
75
+ theme
76
+ });
77
+ return ok(wrapHighlightedCode(html, requestedLanguage), fallbackDiagnostic(requestedLanguage, blockId, cause));
78
+ }
79
+ catch (fallbackCause) {
80
+ return failure(source, requestedLanguage, blockId, fallbackCause);
81
+ }
82
+ }
83
+ };
84
+ function getHighlighter() {
85
+ highlighterPromise ??= createHighlighterCore({
86
+ themes: [THEME_LOADERS[theme]],
87
+ langs: languages.map((languageName) => LANGUAGE_LOADERS[languageName]),
88
+ langAlias: {
89
+ cjs: 'javascript',
90
+ js: 'javascript',
91
+ md: 'markdown',
92
+ mjs: 'javascript',
93
+ py: 'python',
94
+ sh: 'bash',
95
+ shell: 'bash',
96
+ ts: 'typescript',
97
+ yml: 'yaml'
98
+ },
99
+ engine: createJavaScriptRegexEngine()
100
+ });
101
+ return highlighterPromise;
102
+ }
103
+ }
104
+ function wrapHighlightedCode(html, requestedLanguage) {
105
+ const language = requestedLanguage ? ` data-language="${escapeAttribute(requestedLanguage)}"` : '';
106
+ return `<div class="me-renderer-code-highlight"${language}>${html}</div>`;
107
+ }
108
+ function fallbackDiagnostic(requestedLanguage, blockId, cause) {
109
+ if (!requestedLanguage) {
110
+ return undefined;
111
+ }
112
+ return [
113
+ {
114
+ severity: 'warning',
115
+ code: 'renderer.code.language.unsupported',
116
+ message: `Language "${requestedLanguage}" is not available to Shiki; rendered with plaintext highlighting.`,
117
+ blockId,
118
+ cause
119
+ }
120
+ ];
121
+ }
122
+ function normalizeLanguage(language) {
123
+ if (!language) {
124
+ return undefined;
125
+ }
126
+ if (language in LANGUAGE_LOADERS) {
127
+ return language;
128
+ }
129
+ return LANGUAGE_ALIASES[language];
130
+ }
131
+ function failure(source, requestedLanguage, blockId, cause) {
132
+ const language = requestedLanguage ? ` data-language="${escapeAttribute(requestedLanguage)}"` : '';
133
+ const error = {
134
+ severity: 'error',
135
+ code: 'renderer.code.shiki.failed',
136
+ message: 'Shiki highlighter failed; rendered plaintext fallback.',
137
+ blockId,
138
+ cause
139
+ };
140
+ return {
141
+ ok: false,
142
+ html: `<pre class="me-renderer-error"${language}><code>${escapeHtml(source)}</code></pre>`,
143
+ error,
144
+ diagnostics: [error]
145
+ };
146
+ }
147
+ function ok(html, diagnostics) {
148
+ return diagnostics?.length ? { ok: true, html, diagnostics } : { ok: true, html };
149
+ }
150
+ //# sourceMappingURL=shiki.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shiki.js","sourceRoot":"","sources":["../src/shiki.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import type { MarkdownDiagnostic, RenderResult as CoreRenderResult } from '@echozedlabs/core';
2
+ export type RendererBlockKind = 'paragraph' | 'heading' | 'list' | 'blockquote' | 'code' | 'table' | 'image' | 'callout' | 'mermaid' | 'plantuml' | 'html';
3
+ export interface RendererDiagnostic extends Omit<MarkdownDiagnostic, 'severity'> {
4
+ severity: 'error' | 'warning';
5
+ blockId?: string;
6
+ cause?: unknown;
7
+ }
8
+ export type RendererResult = {
9
+ ok: true;
10
+ html: CoreRenderResult['html'];
11
+ diagnostics?: RendererDiagnostic[];
12
+ } | {
13
+ ok: false;
14
+ html: CoreRenderResult['html'];
15
+ error: RendererDiagnostic;
16
+ diagnostics?: RendererDiagnostic[];
17
+ };
18
+ export interface RendererContext {
19
+ blockId: string;
20
+ signal?: AbortSignal;
21
+ }
22
+ export interface MarkdownBlockBase {
23
+ id: string;
24
+ kind: RendererBlockKind;
25
+ raw: string;
26
+ }
27
+ export interface ParagraphBlock extends MarkdownBlockBase {
28
+ kind: 'paragraph';
29
+ text: string;
30
+ }
31
+ export interface HeadingBlock extends MarkdownBlockBase {
32
+ kind: 'heading';
33
+ depth: 1 | 2 | 3 | 4 | 5 | 6;
34
+ text: string;
35
+ }
36
+ export interface CodeBlock extends MarkdownBlockBase {
37
+ kind: 'code' | 'mermaid' | 'plantuml';
38
+ language?: string;
39
+ source: string;
40
+ }
41
+ export interface TableBlock extends MarkdownBlockBase {
42
+ kind: 'table';
43
+ rows: string[][];
44
+ }
45
+ export interface ImageBlock extends MarkdownBlockBase {
46
+ kind: 'image';
47
+ alt: string;
48
+ url: string;
49
+ title?: string;
50
+ }
51
+ export interface CalloutBlock extends MarkdownBlockBase {
52
+ kind: 'callout';
53
+ calloutType: string;
54
+ title?: string;
55
+ body: string;
56
+ }
57
+ export interface ListItem {
58
+ text: string;
59
+ checked?: boolean;
60
+ }
61
+ export interface ListBlock extends MarkdownBlockBase {
62
+ kind: 'list';
63
+ ordered: boolean;
64
+ items: ListItem[];
65
+ }
66
+ export interface SimpleBlock extends MarkdownBlockBase {
67
+ kind: 'blockquote' | 'html';
68
+ text: string;
69
+ }
70
+ export type MarkdownBlock = ParagraphBlock | HeadingBlock | CodeBlock | TableBlock | ImageBlock | CalloutBlock | ListBlock | SimpleBlock;
71
+ export type BlockRenderer<TBlock extends MarkdownBlock = MarkdownBlock> = (block: TBlock, context: RendererContext) => RendererResult | Promise<RendererResult>;
72
+ export interface CodeRendererOptions {
73
+ language?: string;
74
+ source: string;
75
+ blockId: string;
76
+ signal?: AbortSignal;
77
+ }
78
+ export interface DiagramRendererOptions {
79
+ source: string;
80
+ blockId: string;
81
+ signal?: AbortSignal;
82
+ }
83
+ export type AsyncCodeRenderer = (options: CodeRendererOptions) => Promise<RendererResult>;
84
+ export type AsyncDiagramRenderer = (options: DiagramRendererOptions) => Promise<RendererResult>;
85
+ export interface PlantUmlHostRenderer {
86
+ renderPlantUml(source: string, options?: Record<string, unknown>): Promise<CoreRenderResult | RendererResult>;
87
+ }
88
+ export interface RendererRegistryOptions {
89
+ shiki?: AsyncCodeRenderer;
90
+ mermaid?: AsyncDiagramRenderer;
91
+ plantUml?: PlantUmlHostRenderer | AsyncDiagramRenderer;
92
+ }
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@echozedlabs/renderers",
3
+ "version": "0.1.0",
4
+ "description": "Preview renderers (Mermaid, Shiki syntax highlighting, and more) for the echozed markdown editor.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Eric Zimmerman (https://echozed.com)",
8
+ "homepage": "https://echozed.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/echozulucode/markdown-editor.git",
12
+ "directory": "packages/renderers"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/echozulucode/markdown-editor/issues"
16
+ },
17
+ "keywords": [
18
+ "markdown",
19
+ "mermaid",
20
+ "shiki",
21
+ "renderer",
22
+ "preview"
23
+ ],
24
+ "sideEffects": false,
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
31
+ }
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "dependencies": {
40
+ "mermaid": "^11.15.0",
41
+ "shiki": "^4.0.2",
42
+ "@echozedlabs/core": "0.1.0"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc -p tsconfig.json",
46
+ "typecheck": "tsc -p tsconfig.json --noEmit",
47
+ "test": "vitest run"
48
+ }
49
+ }