@theseus.run/jsx-md 0.1.1 → 0.2.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/dist/index.js ADDED
@@ -0,0 +1,435 @@
1
+ import {
2
+ Fragment,
3
+ jsx,
4
+ jsxs
5
+ } from "./index-8tdwjkh9.js";
6
+ // src/escape.ts
7
+ var HTML_ATTR_MAP = {
8
+ "&": "&",
9
+ '"': """,
10
+ "<": "&lt;",
11
+ ">": "&gt;"
12
+ };
13
+ var HTML_ATTR_RE = /[&"<>]/g;
14
+ function escapeHtmlAttr(s) {
15
+ return s.replace(HTML_ATTR_RE, (c) => HTML_ATTR_MAP[c]);
16
+ }
17
+ var HTML_CONTENT_MAP = {
18
+ "&": "&amp;",
19
+ "<": "&lt;",
20
+ ">": "&gt;"
21
+ };
22
+ var HTML_CONTENT_RE = /[&<>]/g;
23
+ function escapeHtmlContent(s) {
24
+ return s.replace(HTML_CONTENT_RE, (c) => HTML_CONTENT_MAP[c]);
25
+ }
26
+ function encodeLinkUrl(url) {
27
+ return url.replace(/\(/g, "%28").replace(/\)/g, "%29");
28
+ }
29
+ function encodeLinkLabel(text) {
30
+ return text.replace(/[[\]]/g, (c) => encodeURIComponent(c));
31
+ }
32
+ var MARKDOWN_ESCAPE_RE = /[\\`*_[\]()#+\-.!|~<>]/g;
33
+ function escapeMarkdown(s) {
34
+ return s.replace(MARKDOWN_ESCAPE_RE, "\\$&");
35
+ }
36
+ function backtickFenceLength(content, minimum = 1) {
37
+ let maxRun = 0;
38
+ let currentRun = 0;
39
+ for (const ch of content) {
40
+ if (ch === "`") {
41
+ currentRun++;
42
+ if (currentRun > maxRun)
43
+ maxRun = currentRun;
44
+ } else {
45
+ currentRun = 0;
46
+ }
47
+ }
48
+ return Math.max(minimum, maxRun + 1);
49
+ }
50
+
51
+ // src/render.ts
52
+ function isVNodeElement(node) {
53
+ return typeof node === "object" && node !== null && !Array.isArray(node);
54
+ }
55
+ function render(node) {
56
+ if (node === null || node === undefined || node === false || node === true) {
57
+ return "";
58
+ }
59
+ if (typeof node === "string") {
60
+ return node;
61
+ }
62
+ if (typeof node === "number") {
63
+ return Number.isFinite(node) ? String(node) : "";
64
+ }
65
+ if (Array.isArray(node)) {
66
+ return node.map(render).join("");
67
+ }
68
+ if (!isVNodeElement(node)) {
69
+ if (typeof node === "function") {
70
+ throw new Error(`jsx-md: a function was passed as a VNode child. Did you forget to call it, or wrap it in JSX? ` + `Received: ${node.name || "anonymous function"}`);
71
+ }
72
+ return "";
73
+ }
74
+ const el = node;
75
+ if (el.type === Fragment) {
76
+ return render(el.props.children ?? null);
77
+ }
78
+ if (typeof el.type === "string") {
79
+ const tagName = el.type;
80
+ if (!/^[a-zA-Z][a-zA-Z0-9:._-]*$/.test(tagName)) {
81
+ throw new Error(`jsx-md: invalid XML tag name "${tagName}". Tag names must start with a letter and contain only letters, digits, ':', '.', '_', or '-'.`);
82
+ }
83
+ const { children, ...attrs } = el.props;
84
+ let attrStr = "";
85
+ for (const [k, v] of Object.entries(attrs)) {
86
+ if (v === undefined || v === null || v === false)
87
+ continue;
88
+ if (v === true) {
89
+ attrStr += ` ${k}`;
90
+ } else if (typeof v === "object") {
91
+ throw new Error(`jsx-md: attribute "${k}" received an object value. XML attributes must be strings. ` + `Use JSON.stringify() to convert: ${k}={JSON.stringify(v)}`);
92
+ } else {
93
+ attrStr += ` ${k}="${escapeHtmlAttr(String(v))}"`;
94
+ }
95
+ }
96
+ const inner = render(children ?? null);
97
+ if (inner.trimEnd() === "") {
98
+ return `<${tagName}${attrStr} />
99
+ `;
100
+ }
101
+ return `<${tagName}${attrStr}>
102
+ ${inner.trimEnd()}
103
+ </${tagName}>
104
+ `;
105
+ }
106
+ return render(el.type(el.props));
107
+ }
108
+ // src/context.ts
109
+ var stack = new Map;
110
+ function createContext(defaultValue) {
111
+ const _id = Symbol();
112
+ function Provider({ value, children }) {
113
+ let s = stack.get(_id);
114
+ if (!s) {
115
+ s = [];
116
+ stack.set(_id, s);
117
+ }
118
+ s.push(value);
119
+ try {
120
+ return render(children ?? null);
121
+ } finally {
122
+ s.pop();
123
+ if (s.length === 0)
124
+ stack.delete(_id);
125
+ }
126
+ }
127
+ return { _id, _default: defaultValue, Provider };
128
+ }
129
+ function useContext(ctx) {
130
+ const s = stack.get(ctx._id);
131
+ if (!s || s.length === 0) {
132
+ return ctx._default;
133
+ }
134
+ return s[s.length - 1];
135
+ }
136
+ function withContext(ctx, value, fn) {
137
+ let s = stack.get(ctx._id);
138
+ if (!s) {
139
+ s = [];
140
+ stack.set(ctx._id, s);
141
+ }
142
+ s.push(value);
143
+ try {
144
+ return fn();
145
+ } finally {
146
+ s.pop();
147
+ if (s.length === 0)
148
+ stack.delete(ctx._id);
149
+ }
150
+ }
151
+ // src/primitives.tsx
152
+ var DepthContext = createContext(0);
153
+ var OlCollectorContext = createContext(null);
154
+ var ColSpecContext = createContext(null);
155
+ function alignSeparator(align) {
156
+ if (align === "left")
157
+ return ":---";
158
+ if (align === "center")
159
+ return ":---:";
160
+ if (align === "right")
161
+ return "---:";
162
+ return "---";
163
+ }
164
+ function H1({ children }) {
165
+ return `# ${render(children).trim()}
166
+
167
+ `;
168
+ }
169
+ function H2({ children }) {
170
+ return `## ${render(children).trim()}
171
+
172
+ `;
173
+ }
174
+ function H3({ children }) {
175
+ return `### ${render(children).trim()}
176
+
177
+ `;
178
+ }
179
+ function H4({ children }) {
180
+ return `#### ${render(children).trim()}
181
+
182
+ `;
183
+ }
184
+ function H5({ children }) {
185
+ return `##### ${render(children).trim()}
186
+
187
+ `;
188
+ }
189
+ function H6({ children }) {
190
+ return `###### ${render(children).trim()}
191
+
192
+ `;
193
+ }
194
+ function P({ children }) {
195
+ return `${render(children)}
196
+
197
+ `;
198
+ }
199
+ function Hr(_ = {}) {
200
+ return `---
201
+
202
+ `;
203
+ }
204
+ function Codeblock({ lang = "", children, indent = 0 }) {
205
+ const prefix = " ".repeat(indent);
206
+ const content = render(children);
207
+ const fence = "`".repeat(backtickFenceLength(content, 3));
208
+ const rawLines = content.split(`
209
+ `);
210
+ while (rawLines.length > 0 && rawLines[rawLines.length - 1] === "") {
211
+ rawLines.pop();
212
+ }
213
+ const body = rawLines.map((line) => prefix + line).join(`
214
+ `);
215
+ return `${fence}${lang}
216
+ ${body}
217
+ ${fence}
218
+
219
+ `;
220
+ }
221
+ function Blockquote({ children }) {
222
+ const content = render(children).trimEnd();
223
+ const lines = content.split(`
224
+ `).map((line) => line === "" ? ">" : `> ${line}`).join(`
225
+ `);
226
+ return `${lines}
227
+
228
+ `;
229
+ }
230
+ function Ul({ children }) {
231
+ const depth = useContext(DepthContext);
232
+ const rendered = withContext(OlCollectorContext, null, () => withContext(DepthContext, depth + 1, () => render(children)));
233
+ return depth === 0 ? `${rendered}
234
+ ` : `
235
+ ${rendered}`;
236
+ }
237
+ function Ol({ children }) {
238
+ const depth = useContext(DepthContext);
239
+ const collector = { items: [] };
240
+ withContext(OlCollectorContext, collector, () => withContext(DepthContext, depth + 1, () => render(children)));
241
+ const indent = " ".repeat(depth);
242
+ const numbered = collector.items.map((item, i) => `${indent}${i + 1}. ${item}`).join("");
243
+ return depth === 0 ? `${numbered}
244
+ ` : `
245
+ ${numbered}`;
246
+ }
247
+ function Li({ children }) {
248
+ const depth = useContext(DepthContext);
249
+ const collector = useContext(OlCollectorContext);
250
+ const indent = " ".repeat(Math.max(0, depth - 1));
251
+ const inner = render(children).trimEnd();
252
+ if (collector) {
253
+ collector.items.push(`${inner}
254
+ `);
255
+ return "";
256
+ }
257
+ return `${indent}- ${inner}
258
+ `;
259
+ }
260
+ function Th({ children, align }) {
261
+ const spec = useContext(ColSpecContext);
262
+ if (spec)
263
+ spec.cols.push(align);
264
+ return ` ${render(children)} |`;
265
+ }
266
+ function Td({ children }) {
267
+ return ` ${render(children)} |`;
268
+ }
269
+ function Tr({ children }) {
270
+ return `|${render(children)}
271
+ `;
272
+ }
273
+ function Table({ children }) {
274
+ const spec = { cols: [] };
275
+ const rendered = withContext(ColSpecContext, spec, () => render(children));
276
+ const lines = rendered.split(`
277
+ `).filter((l) => l.trim().length > 0);
278
+ if (lines.length === 0) {
279
+ return "";
280
+ }
281
+ const separator = "| " + spec.cols.map(alignSeparator).join(" | ") + " |";
282
+ const headerLine = lines[0];
283
+ const bodyLines = lines.slice(1);
284
+ return [headerLine, separator, ...bodyLines].join(`
285
+ `) + `
286
+
287
+ `;
288
+ }
289
+ function Bold({ children }) {
290
+ const inner = render(children).replace(/\*\*/g, "\\*\\*");
291
+ return `**${inner}**`;
292
+ }
293
+ function Code({ children }) {
294
+ const inner = render(children);
295
+ const fence = "`".repeat(backtickFenceLength(inner));
296
+ return `${fence}${inner}${fence}`;
297
+ }
298
+ function Italic({ children }) {
299
+ return `*${render(children)}*`;
300
+ }
301
+ function Strikethrough({ children }) {
302
+ const inner = render(children).replace(/~~/g, "\\~\\~");
303
+ return `~~${inner}~~`;
304
+ }
305
+ function Br(_ = {}) {
306
+ return `
307
+ `;
308
+ }
309
+ function Sup({ children }) {
310
+ return `<sup>${render(children)}</sup>`;
311
+ }
312
+ function Sub({ children }) {
313
+ return `<sub>${render(children)}</sub>`;
314
+ }
315
+ function Kbd({ children }) {
316
+ return `<kbd>${render(children)}</kbd>`;
317
+ }
318
+ function Escape({ children }) {
319
+ return escapeMarkdown(render(children));
320
+ }
321
+ function Link({ href, children }) {
322
+ return `[${render(children)}](${encodeLinkUrl(href)})`;
323
+ }
324
+ function Img({ src, alt = "" }) {
325
+ return `![${encodeLinkLabel(alt)}](${encodeLinkUrl(src)})`;
326
+ }
327
+ function Md({ children }) {
328
+ return render(children);
329
+ }
330
+ function TaskList({ children }) {
331
+ const depth = useContext(DepthContext);
332
+ const rendered = withContext(DepthContext, depth + 1, () => render(children));
333
+ return depth === 0 ? `${rendered}
334
+ ` : `
335
+ ${rendered}`;
336
+ }
337
+ function Task({ children, done }) {
338
+ const depth = useContext(DepthContext);
339
+ const indent = " ".repeat(Math.max(0, depth - 1));
340
+ const prefix = done ? "[x]" : "[ ]";
341
+ const inner = render(children).trimEnd();
342
+ return `${indent}- ${prefix} ${inner}
343
+ `;
344
+ }
345
+ function Callout({
346
+ children,
347
+ type
348
+ }) {
349
+ const inner = render(children).trimEnd();
350
+ const lines = inner.split(`
351
+ `).map((line) => line === "" ? ">" : `> ${line}`).join(`
352
+ `);
353
+ return `> [!${type.toUpperCase()}]
354
+ ${lines}
355
+
356
+ `;
357
+ }
358
+ function HtmlComment({ children }) {
359
+ const inner = render(children).trimEnd();
360
+ if (!inner.trim()) {
361
+ return `<!-- -->
362
+ `;
363
+ }
364
+ const safe = inner.replace(/-->|--/g, (m) => m === "-->" ? "-- >" : "- -");
365
+ if (safe.includes(`
366
+ `)) {
367
+ return `<!--
368
+ ${safe}
369
+ -->
370
+ `;
371
+ }
372
+ return `<!-- ${safe} -->
373
+ `;
374
+ }
375
+ function Details({
376
+ children,
377
+ summary
378
+ }) {
379
+ const safeSummary = escapeHtmlContent(summary.replace(/\n/g, " "));
380
+ const body = render(children).trimEnd();
381
+ return `<details>
382
+ <summary>${safeSummary}</summary>
383
+
384
+ ${body}
385
+
386
+ </details>
387
+ `;
388
+ }
389
+ export {
390
+ withContext,
391
+ useContext,
392
+ render,
393
+ jsxs,
394
+ jsx,
395
+ escapeMarkdown,
396
+ createContext,
397
+ Ul,
398
+ Tr,
399
+ Th,
400
+ Td,
401
+ TaskList,
402
+ Task,
403
+ Table,
404
+ Sup,
405
+ Sub,
406
+ Strikethrough,
407
+ P,
408
+ Ol,
409
+ Md,
410
+ Link,
411
+ Li,
412
+ Kbd,
413
+ Italic,
414
+ Img,
415
+ HtmlComment,
416
+ Hr,
417
+ H6,
418
+ H5,
419
+ H4,
420
+ H3,
421
+ H2,
422
+ H1,
423
+ Fragment,
424
+ Escape,
425
+ Details,
426
+ Codeblock,
427
+ Code,
428
+ Callout,
429
+ Br,
430
+ Bold,
431
+ Blockquote
432
+ };
433
+
434
+ //# debugId=E837B16067996D6464756E2164756E21
435
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/escape.ts", "../src/render.ts", "../src/context.ts", "../src/primitives.tsx"],
4
+ "sourcesContent": [
5
+ "/**\n * Escapes `&`, `\"`, `<`, `>` — for use in XML/HTML attribute values.\n * Escapes for double-quoted HTML/XML attribute values. Single quotes are not\n * escaped — do not use this in single-quoted attribute contexts.\n *\n * Single-pass via a lookup map — avoids four sequential .replace() calls.\n */\nconst HTML_ATTR_MAP: Record<string, string> = {\n '&': '&amp;',\n '\"': '&quot;',\n '<': '&lt;',\n '>': '&gt;',\n};\nconst HTML_ATTR_RE = /[&\"<>]/g;\n\nexport function escapeHtmlAttr(s: string): string {\n return s.replace(HTML_ATTR_RE, (c) => HTML_ATTR_MAP[c]!);\n}\n\n/**\n * Escapes `&`, `<`, `>` — for use in HTML/XML text content (not attributes).\n *\n * Single-pass via a lookup map.\n */\nconst HTML_CONTENT_MAP: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n};\nconst HTML_CONTENT_RE = /[&<>]/g;\n\nexport function escapeHtmlContent(s: string): string {\n return s.replace(HTML_CONTENT_RE, (c) => HTML_CONTENT_MAP[c]!);\n}\n\n/**\n * Percent-encodes `(` and `)` in a URL to prevent premature link termination in\n * Markdown link syntax `[text](url)`.\n */\nexport function encodeLinkUrl(url: string): string {\n return url.replace(/\\(/g, '%28').replace(/\\)/g, '%29');\n}\n\n/**\n * Percent-encodes `[` and `]` in text used as Markdown link label (image alt).\n * Prevents premature bracket closure in `![alt](src)`.\n */\nexport function encodeLinkLabel(text: string): string {\n return text.replace(/[[\\]]/g, (c) => encodeURIComponent(c));\n}\n\n/**\n * Escapes all CommonMark ASCII punctuation metacharacters in a string so that\n * user-supplied content is treated as literal text by any markdown renderer.\n *\n * Useful when interpolating variable strings — filenames, user input, code\n * identifiers, etc. — into markdown prose where unintended formatting must be\n * suppressed:\n *\n * <P>File: <Escape>{untrustedFilename}</Escape></P>\n * <P>File: {escapeMarkdown(untrustedFilename)}</P>\n *\n * Escaped characters: \\ ` * _ [ ] ( ) # + - . ! | ~ < >\n * These cover all CommonMark inline and block trigger characters.\n * HTML entities (&amp; etc.) are intentionally not escaped here — use\n * escapeHtmlContent for HTML attribute / tag contexts.\n */\nconst MARKDOWN_ESCAPE_RE = /[\\\\`*_[\\]()#+\\-.!|~<>]/g;\n\nexport function escapeMarkdown(s: string): string {\n return s.replace(MARKDOWN_ESCAPE_RE, '\\\\$&');\n}\n\n/**\n * Returns the minimum backtick fence length needed to safely wrap `content`\n * as a CommonMark inline code span or fenced code block.\n *\n * CommonMark rule: the fence must be a run of N backticks where N is strictly\n * greater than the longest run of consecutive backticks in the content.\n * Minimum is 1 for inline code, 3 for fenced code blocks.\n */\nexport function backtickFenceLength(content: string, minimum: number = 1): number {\n let maxRun = 0;\n let currentRun = 0;\n for (const ch of content) {\n if (ch === '`') {\n currentRun++;\n if (currentRun > maxRun) maxRun = currentRun;\n } else {\n currentRun = 0;\n }\n }\n return Math.max(minimum, maxRun + 1);\n}\n",
6
+ "/**\n * render() — converts a VNode tree to a markdown string.\n *\n * This is the top-down evaluation pass. Components in the tree are called\n * here, not at JSX construction time. Children are passed as raw VNode values\n * to each component so they can wrap rendering in context (e.g. DepthContext).\n *\n * Fragment is a Symbol (imported from jsx-runtime.ts). When render() encounters\n * a VNodeElement whose type is the Fragment symbol, it renders children directly.\n * This keeps the dependency one-way (render.ts → jsx-runtime.ts) with no cycle.\n */\n\nimport { escapeHtmlAttr } from './escape.ts';\nimport { Fragment, type VNode, type VNodeElement } from './jsx-runtime.ts';\n\nfunction isVNodeElement(node: VNode): node is VNodeElement {\n return typeof node === 'object' && node !== null && !Array.isArray(node);\n}\n\nexport function render(node: VNode): string {\n if (node === null || node === undefined || node === false || node === true) {\n return '';\n }\n if (typeof node === 'string') {\n return node;\n }\n if (typeof node === 'number') {\n return Number.isFinite(node) ? String(node) : '';\n }\n if (Array.isArray(node)) {\n return node.map(render).join('');\n }\n // VNodeElement — dispatch on type\n if (!isVNodeElement(node)) {\n // From TypeScript's perspective this branch is unreachable: after the null/boolean/string/\n // number/Array guards above, the only remaining VNode member is VNodeElement, so `node`\n // is already narrowed to VNodeElement and `!isVNodeElement` is statically false.\n // The branch is kept as a runtime-only defensive net: if a caller bypasses TypeScript\n // (plain JS, `as any`, etc.) and passes a function as a child, we throw a diagnostic\n // error instead of silently returning ''. The double-cast (`as unknown as fn`) is\n // required precisely because TS knows this is unreachable.\n if (typeof node === 'function') {\n throw new Error(\n `jsx-md: a function was passed as a VNode child. Did you forget to call it, or wrap it in JSX? ` +\n `Received: ${(node as unknown as (...args: unknown[]) => unknown).name || 'anonymous function'}`,\n );\n }\n return '';\n }\n const el = node; // narrowed to VNodeElement\n\n // Fragment symbol — render children directly\n if (el.type === Fragment) {\n // props is Record<string, unknown> by design (props type varies per-component and cannot\n // be narrowed at the VNodeElement level). The `as VNode` cast is safe in practice: the\n // only source of props.children values is the JSX compiler and user JSX expressions,\n // both of which TypeScript has already validated as VNode at the call site.\n return render(el.props.children as VNode ?? null);\n }\n\n // String type → render as an XML block tag\n if (typeof el.type === 'string') {\n const tagName = el.type;\n if (!/^[a-zA-Z][a-zA-Z0-9:._-]*$/.test(tagName)) {\n throw new Error(\n `jsx-md: invalid XML tag name \"${tagName}\". Tag names must start with a letter and contain only letters, digits, ':', '.', '_', or '-'.`,\n );\n }\n const { children, ...attrs } = el.props;\n let attrStr = '';\n for (const [k, v] of Object.entries(attrs)) {\n if (v === undefined || v === null || v === false) continue;\n if (v === true) {\n attrStr += ` ${k}`;\n } else if (typeof v === 'object') {\n throw new Error(\n `jsx-md: attribute \"${k}\" received an object value. XML attributes must be strings. ` +\n `Use JSON.stringify() to convert: ${k}={JSON.stringify(v)}`,\n );\n } else {\n attrStr += ` ${k}=\"${escapeHtmlAttr(String(v))}\"`;\n }\n }\n // Same cast rationale as the Fragment branch above: props.children is unknown\n // at the VNodeElement level but is guaranteed VNode by the JSX type system.\n const inner = render(children as VNode ?? null);\n if (inner.trimEnd() === '') {\n return `<${tagName}${attrStr} />\\n`;\n }\n return `<${tagName}${attrStr}>\\n${inner.trimEnd()}\\n</${tagName}>\\n`;\n }\n\n // Function component — call with its props (children still as VNode),\n // then recurse in case the component returned a VNode.\n return render(el.type(el.props));\n}\n",
7
+ "/**\n * Synchronous context API for jsx-md — matches the React context shape.\n *\n * createContext(defaultValue) returns a Context object with a Provider\n * component. Wrap a render() call with <Ctx.Provider value={...}> and read\n * the value anywhere in the tree with useContext(Ctx).\n *\n * Uses a module-level stack map so values are available synchronously during\n * the render() traversal. Not safe for async or concurrent rendering.\n */\n\nimport { render } from './render.ts';\nimport type { VNode } from './jsx-runtime.ts';\n\nexport interface Context<T> {\n readonly _id: symbol;\n readonly _default: T;\n /**\n * JSX provider component — identical usage to React's Context.Provider.\n *\n * Return type is `string` (not `VNode`) because `render()` always returns `string`\n * and this is the honest, precise type. This means `Provider` is not directly\n * assignable to `Component<P>` without a cast, even though `string extends VNode`.\n *\n * React solves this by typing `Provider` as `ProviderExoticComponent` — a distinct\n * type with a `$$typeof: symbol` discriminant — rather than a plain function component.\n * That approach deliberately prevents `Provider` from being used as a generic\n * `Component` argument, and it returns `ReactNode` (broad) rather than a precise type.\n *\n * We keep `=> string` because: (a) no code in this codebase passes `Provider` as a\n * `Component`-typed value, (b) precision is more useful than assignability here,\n * and (c) the exotic-component indirection would be engineering for a non-problem.\n * If that higher-order pattern ever becomes necessary, change this to `=> VNode`.\n */\n readonly Provider: (props: { value: T; children?: VNode }) => string;\n}\n\n/**\n * Process-wide singleton. Not safe for concurrent render() calls in the same\n * process (e.g. simultaneous Bun HTTP requests). For agent prompt generation\n * this is almost always a non-issue — renders are sequential.\n */\nconst stack = new Map<symbol, unknown[]>();\n\nexport function createContext<T>(defaultValue: T): Context<T> {\n const _id = Symbol();\n\n function Provider({ value, children }: { value: T; children?: VNode }): string {\n let s = stack.get(_id);\n if (!s) {\n s = [];\n stack.set(_id, s);\n }\n s.push(value as unknown);\n try {\n return render(children ?? null);\n } finally {\n s.pop();\n if (s.length === 0) stack.delete(_id);\n }\n }\n\n return { _id, _default: defaultValue, Provider };\n}\n\nexport function useContext<T>(ctx: Context<T>): T {\n const s = stack.get(ctx._id);\n if (!s || s.length === 0) {\n return ctx._default;\n }\n return s[s.length - 1] as T;\n}\n\nexport function withContext<T>(ctx: Context<T>, value: T, fn: () => string): string {\n let s = stack.get(ctx._id);\n if (!s) {\n s = [];\n stack.set(ctx._id, s);\n }\n s.push(value);\n try {\n return fn();\n } finally {\n s.pop();\n if (s.length === 0) stack.delete(ctx._id);\n }\n}\n",
8
+ "/**\n * Markdown primitives as named TSX components.\n *\n * Components covering all markdown formatting needs:\n * Block: H1, H2, H3, H4, H5, H6, P, Hr, Codeblock, Blockquote\n * List: Ol, Ul, Li, TaskList, Task\n * Table: Table, Tr, Th, Td\n * Inline: Bold, Code, Italic, Strikethrough, Link, Img\n * Raw: Md\n * Other: Callout, HtmlComment, Details\n *\n * Each is a plain function (props) => string. No React. No DOM.\n *\n * Children are passed as VNode (unevaluated). Each component calls\n * render(children) to produce the final string. This enables context\n * propagation — Ul/Ol wrap render in a withContext(DepthContext, depth+1)\n * call so nested Li components can compute their indentation level.\n *\n * ---------------------------------------------------------------------------\n * AUTHORING RULES\n * ---------------------------------------------------------------------------\n *\n * 1. Prefer components over inline markdown strings.\n *\n * **text** → <Bold>text</Bold>\n * `text` → <Code>text</Code>\n * *text* → <Italic>text</Italic>\n * [label](url) → <Link href=\"url\">label</Link>\n *\n * 2. Bare JSX text for plain prose. {'...'} only when the string contains\n * a character JSX cannot represent as bare text:\n *\n * Requires {'...'}: backtick { } < > '\n * Bare text is fine: letters, spaces, digits, . , : ; ! ? — – - ( ) [ ] \" & * + = | / \\\n *\n * // WRONG — unnecessary wrapper\n * <Li><Bold>P1</Bold>{': Guard clauses over nesting.'}</Li>\n *\n * // CORRECT — bare text\n * <Li><Bold>P1</Bold>: Guard clauses over nesting.</Li>\n *\n * // CORRECT — must wrap, contains single quote\n * <Li><Bold>P1</Bold>{\": Dead code: delete, don't comment out.\"}</Li>\n *\n * // CORRECT — must wrap, contains backtick\n * <P>{'Format: `ROI≈X.X`'}</P>\n *\n * 3. Md is an escape hatch for genuinely undecomposable strings — typically\n * 4+ inline code spans mixed with bold and prose. Use sparingly.\n *\n * // Legitimate Md use — 6 code spans, decomposition adds noise\n * <Li><Md>{'**P0**: Type = `TKey`. Not `TFuncKey`, `string`, or `<Trans>`.'}</Md></Li>\n *\n * // Not legitimate — decompose instead\n * <Li><Md>{'**P1**: Guard clauses over nesting.'}</Md></Li>\n *\n * 4. Nested lists are fully supported via nested Ul or Ol inside Li children.\n * DepthContext tracks the nesting level and computes indentation automatically.\n *\n * <Ul>\n * <Li>top-level item\n * <Ul><Li>sub-item one</Li><Li>sub-item two</Li></Ul>\n * </Li>\n * </Ul>\n *\n * <Ol>\n * <Li>step one\n * <Ol><Li>sub-step a</Li><Li>sub-step b</Li></Ol>\n * </Li>\n * </Ol>\n */\n\n/* @jsxImportSource @theseus.run/jsx-md */\n\nimport type { VNode } from './jsx-runtime.ts';\nimport { render } from './render.ts';\nimport { createContext, useContext, withContext } from './context.ts';\nimport { escapeHtmlContent, encodeLinkUrl, encodeLinkLabel, backtickFenceLength, escapeMarkdown } from './escape.ts';\n\n// ---------------------------------------------------------------------------\n// DepthContext — tracks list nesting level for Li indentation\n// ---------------------------------------------------------------------------\n\n/** Tracks the current list nesting depth. 0 = outside any list. */\nconst DepthContext = createContext(0);\n\n// ---------------------------------------------------------------------------\n// OlCollectorContext — collects Li items for Ol numbering\n// ---------------------------------------------------------------------------\n\n/**\n * Mutable item-collector box passed through context during Ol rendering.\n * Li pushes its rendered content into collector.items (and returns '') when\n * an OlCollector is present; Ol reads the items after rendering to number them.\n * This eliminates the sentinel-character post-processing hack and allows Ol\n * to be nested at any depth, just like Ul.\n */\ntype OlCollector = { items: string[] };\nconst OlCollectorContext = createContext<OlCollector | null>(null);\n\n// ---------------------------------------------------------------------------\n// ColSpecContext — tracks Th alignment per column for Table separator row\n// ---------------------------------------------------------------------------\n\n/**\n * Alignment value for a GFM table column.\n * 'left' → `:---`, 'center' → `:---:`, 'right' → `---:`, undefined → `---`.\n */\nexport type ColAlign = 'left' | 'center' | 'right';\n\n/**\n * Mutable spec box passed through context during Table rendering.\n * Th pushes its alignment (or undefined) into spec.cols; Table reads the\n * array after the header row renders to build the GFM separator row.\n */\ntype ColSpec = { cols: Array<ColAlign | undefined> };\nconst ColSpecContext = createContext<ColSpec | null>(null);\n\nfunction alignSeparator(align: ColAlign | undefined): string {\n if (align === 'left') return ':---';\n if (align === 'center') return ':---:';\n if (align === 'right') return '---:';\n return '---';\n}\n\n// ---------------------------------------------------------------------------\n// Block elements — trailing \\n\\n\n// ---------------------------------------------------------------------------\n\ninterface BlockProps {\n children?: VNode;\n}\n\nexport function H1({ children }: BlockProps): string {\n return `# ${render(children).trim()}\\n\\n`;\n}\n\nexport function H2({ children }: BlockProps): string {\n return `## ${render(children).trim()}\\n\\n`;\n}\n\nexport function H3({ children }: BlockProps): string {\n return `### ${render(children).trim()}\\n\\n`;\n}\n\nexport function H4({ children }: BlockProps): string {\n return `#### ${render(children).trim()}\\n\\n`;\n}\n\nexport function H5({ children }: BlockProps): string {\n return `##### ${render(children).trim()}\\n\\n`;\n}\n\nexport function H6({ children }: BlockProps): string {\n return `###### ${render(children).trim()}\\n\\n`;\n}\n\nexport function P({ children }: BlockProps): string {\n return `${render(children)}\\n\\n`;\n}\n\nexport function Hr(_: { children?: never } = {}): string {\n return '---\\n\\n';\n}\n\ninterface CodeblockProps {\n lang?: string;\n children?: VNode;\n indent?: number;\n}\n\nexport function Codeblock({ lang = '', children, indent = 0 }: CodeblockProps): string {\n const prefix = ' '.repeat(indent);\n const content = render(children);\n const fence = '`'.repeat(backtickFenceLength(content, 3));\n const rawLines = content.split('\\n');\n // Drop trailing empty entries produced by a trailing \\n in content to prevent\n // a spurious indented blank line appearing before the closing fence.\n while (rawLines.length > 0 && rawLines[rawLines.length - 1] === '') {\n rawLines.pop();\n }\n const body = rawLines.map((line) => prefix + line).join('\\n');\n return `${fence}${lang}\\n${body}\\n${fence}\\n\\n`;\n}\n\n/**\n * Blockquote — prefixes every content line with `> `.\n * Trailing blank lines are stripped before prefixing so the output ends\n * cleanly with `\\n\\n` rather than `> \\n> \\n\\n`.\n * Empty lines within the content get a bare `>` (no trailing space) to\n * avoid invisible trailing whitespace in the rendered output.\n * Nested blockquotes compose naturally: the inner renders `> text\\n\\n`,\n * trimEnd strips the trailing newlines, then the outer prefixes each line\n * with `> `, producing `> > text`.\n */\nexport function Blockquote({ children }: BlockProps): string {\n const content = render(children).trimEnd();\n const lines = content.split('\\n').map((line) => (line === '' ? '>' : `> ${line}`)).join('\\n');\n return `${lines}\\n\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// List elements\n// ---------------------------------------------------------------------------\n\nexport function Ul({ children }: BlockProps): string {\n const depth = useContext(DepthContext);\n // Clear OlCollectorContext so Li items inside a Ul nested within Ol\n // render as \"- \" bullet items, not push to the outer Ol's collector.\n const rendered = withContext(OlCollectorContext, null, () =>\n withContext(DepthContext, depth + 1, () => render(children)),\n );\n // At depth 0 (outermost): trailing \\n to form a block.\n // At depth > 0 (nested): leading \\n so the sublist starts on its own line\n // when concatenated with the parent Li text.\n return depth === 0 ? `${rendered}\\n` : `\\n${rendered}`;\n}\n\n/**\n * Ordered list — auto-numbers Li children at the current depth level.\n *\n * Ul/Ol increment the depth before rendering children, so Li items know\n * their indentation. When an OlCollector is present in context, Li pushes\n * its content to collector.items and returns '' — Ol then numbers the\n * collected items. This pattern supports Ol at any nesting depth, including\n * Ol inside Ol, Ol inside Ul, etc.\n */\nexport function Ol({ children }: BlockProps): string {\n const depth = useContext(DepthContext);\n const collector: OlCollector = { items: [] };\n withContext(OlCollectorContext, collector, () =>\n withContext(DepthContext, depth + 1, () => render(children)),\n );\n const indent = ' '.repeat(depth);\n const numbered = collector.items\n .map((item, i) => `${indent}${i + 1}. ${item}`)\n .join('');\n return depth === 0 ? `${numbered}\\n` : `\\n${numbered}`;\n}\n\nexport function Li({ children }: BlockProps): string {\n const depth = useContext(DepthContext);\n const collector = useContext(OlCollectorContext);\n // depth is already incremented by the enclosing Ul/Ol, so depth 1 = top-level.\n // Math.max guard: safe when Li is used outside Ul/Ol (depth=0).\n const indent = ' '.repeat(Math.max(0, depth - 1));\n const inner = render(children).trimEnd();\n if (collector) {\n // Inside Ol: push content to collector; Ol will number items after rendering.\n collector.items.push(`${inner}\\n`);\n return '';\n }\n return `${indent}- ${inner}\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Table elements\n// ---------------------------------------------------------------------------\n\n/**\n * Th and Td are semantically identical in GFM — position determines header\n * styling, not cell type. Both return ` content |` (trailing pipe delimiter).\n * Tr prepends the leading `|` to form a complete row line.\n *\n * Th also increments the ColCountContext counter so Table knows how many\n * columns the header row has without parsing pipe characters.\n */\nexport function Th({ children, align }: { children?: VNode; align?: ColAlign }): string {\n const spec = useContext(ColSpecContext);\n if (spec) spec.cols.push(align);\n return ` ${render(children)} |`;\n}\n\nexport function Td({ children }: { children?: VNode }): string {\n return ` ${render(children)} |`;\n}\n\nexport function Tr({ children }: { children?: VNode }): string {\n return `|${render(children)}\\n`;\n}\n\n/**\n * Table — renders Tr children, then injects a GFM separator row after the\n * first row (the header). Column count is obtained from ColCountContext which\n * Th increments during rendering — correct even when cells contain '|'.\n */\nexport function Table({ children }: { children?: VNode }): string {\n const spec: ColSpec = { cols: [] };\n const rendered = withContext(ColSpecContext, spec, () => render(children));\n const lines = rendered.split('\\n').filter((l) => l.trim().length > 0);\n if (lines.length === 0) {\n return '';\n }\n const separator = '| ' + spec.cols.map(alignSeparator).join(' | ') + ' |';\n const headerLine = lines[0]!;\n const bodyLines = lines.slice(1);\n return [headerLine, separator, ...bodyLines].join('\\n') + '\\n\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Inline elements — no trailing whitespace\n// ---------------------------------------------------------------------------\n\ninterface InlineProps {\n children?: VNode;\n}\n\nexport function Bold({ children }: InlineProps): string {\n const inner = render(children).replace(/\\*\\*/g, '\\\\*\\\\*');\n return `**${inner}**`;\n}\n\nexport function Code({ children }: InlineProps): string {\n const inner = render(children);\n const fence = '`'.repeat(backtickFenceLength(inner));\n return `${fence}${inner}${fence}`;\n}\n\nexport function Italic({ children }: InlineProps): string {\n return `*${render(children)}*`;\n}\n\nexport function Strikethrough({ children }: InlineProps): string {\n const inner = render(children).replace(/~~/g, '\\\\~\\\\~');\n return `~~${inner}~~`;\n}\n\nexport function Br(_: { children?: never } = {}): string {\n return ' \\n';\n}\n\nexport function Sup({ children }: InlineProps): string {\n return `<sup>${render(children)}</sup>`;\n}\n\nexport function Sub({ children }: InlineProps): string {\n return `<sub>${render(children)}</sub>`;\n}\n\nexport function Kbd({ children }: InlineProps): string {\n return `<kbd>${render(children)}</kbd>`;\n}\n\nexport function Escape({ children }: InlineProps): string {\n return escapeMarkdown(render(children));\n}\n\ninterface LinkProps {\n href: string;\n children?: VNode;\n}\n\nexport function Link({ href, children }: LinkProps): string {\n return `[${render(children)}](${encodeLinkUrl(href)})`;\n}\n\ninterface ImgProps {\n src: string;\n alt?: string;\n}\n\nexport function Img({ src, alt = '' }: ImgProps): string {\n return `![${encodeLinkLabel(alt)}](${encodeLinkUrl(src)})`;\n}\n\n// ---------------------------------------------------------------------------\n// Raw passthrough — escape hatch only, see AUTHORING RULES above\n// ---------------------------------------------------------------------------\n\nexport function Md({ children }: BlockProps): string {\n return render(children);\n}\n\n// ---------------------------------------------------------------------------\n// TaskList + Task — GFM task list items\n// ---------------------------------------------------------------------------\n\nexport function TaskList({ children }: { children?: VNode }): string {\n const depth = useContext(DepthContext);\n const rendered = withContext(DepthContext, depth + 1, () => render(children));\n // Mirror Ul: at depth 0 trailing \\n, at depth > 0 leading \\n\n return depth === 0 ? `${rendered}\\n` : `\\n${rendered}`;\n}\n\nexport function Task({ children, done }: { children?: VNode; done?: boolean }): string {\n const depth = useContext(DepthContext);\n // Math.max guard matches Li's defensive pattern — safe when Task is used outside TaskList (depth=0)\n const indent = ' '.repeat(Math.max(0, depth - 1));\n const prefix = done ? '[x]' : '[ ]';\n const inner = render(children).trimEnd();\n return `${indent}- ${prefix} ${inner}\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Callout — GitHub-flavored alert blockquote\n// ---------------------------------------------------------------------------\n\nexport type CalloutType = 'note' | 'tip' | 'important' | 'warning' | 'caution';\n\nexport function Callout({\n children,\n type,\n}: {\n children?: VNode;\n type: CalloutType;\n}): string {\n const inner = render(children).trimEnd();\n const lines = inner.split('\\n').map((line) => (line === '' ? '>' : `> ${line}`)).join('\\n');\n return `> [!${type.toUpperCase()}]\\n${lines}\\n\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// HtmlComment — renders <!-- content --> (single-line or multi-line)\n// ---------------------------------------------------------------------------\n\nexport function HtmlComment({ children }: { children?: VNode }): string {\n const inner = render(children).trimEnd();\n // Use .trim() only for the empty-check: whitespace-only content → <!-- -->\n if (!inner.trim()) {\n return `<!-- -->\\n`;\n }\n // Sanitize in a single pass (left-to-right alternation):\n // '-->': closes comment prematurely → replace '>' with ' >' to break the sequence\n // '--': invalid per HTML spec → replace second '-' with ' -'\n const safe = inner.replace(/-->|--/g, (m) => (m === '-->' ? '-- >' : '- -'));\n if (safe.includes('\\n')) {\n return `<!--\\n${safe}\\n-->\\n`;\n }\n return `<!-- ${safe} -->\\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Details — GitHub collapsible section\n// ---------------------------------------------------------------------------\n\nexport function Details({\n children,\n summary,\n}: {\n children?: VNode;\n summary: string;\n}): string {\n // Newlines in summary break the <summary> element — collapse to spaces.\n const safeSummary = escapeHtmlContent(summary.replace(/\\n/g, ' '));\n // trimEnd() required: GitHub needs a blank line before </details> to render body as markdown.\n // The \\n\\n in the template provides that; trimEnd prevents double-blank-lines.\n const body = render(children).trimEnd();\n return `<details>\\n<summary>${safeSummary}</summary>\\n\\n${body}\\n\\n</details>\\n`;\n}\n"
9
+ ],
10
+ "mappings": ";;;;;;AAOA,IAAM,gBAAwC;AAAA,EAC5C,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AACA,IAAM,eAAe;AAEd,SAAS,cAAc,CAAC,GAAmB;AAAA,EAChD,OAAO,EAAE,QAAQ,cAAc,CAAC,MAAM,cAAc,EAAG;AAAA;AAQzD,IAAM,mBAA2C;AAAA,EAC/C,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AACA,IAAM,kBAAkB;AAEjB,SAAS,iBAAiB,CAAC,GAAmB;AAAA,EACnD,OAAO,EAAE,QAAQ,iBAAiB,CAAC,MAAM,iBAAiB,EAAG;AAAA;AAOxD,SAAS,aAAa,CAAC,KAAqB;AAAA,EACjD,OAAO,IAAI,QAAQ,OAAO,KAAK,EAAE,QAAQ,OAAO,KAAK;AAAA;AAOhD,SAAS,eAAe,CAAC,MAAsB;AAAA,EACpD,OAAO,KAAK,QAAQ,UAAU,CAAC,MAAM,mBAAmB,CAAC,CAAC;AAAA;AAmB5D,IAAM,qBAAqB;AAEpB,SAAS,cAAc,CAAC,GAAmB;AAAA,EAChD,OAAO,EAAE,QAAQ,oBAAoB,MAAM;AAAA;AAWtC,SAAS,mBAAmB,CAAC,SAAiB,UAAkB,GAAW;AAAA,EAChF,IAAI,SAAS;AAAA,EACb,IAAI,aAAa;AAAA,EACjB,WAAW,MAAM,SAAS;AAAA,IACxB,IAAI,OAAO,KAAK;AAAA,MACd;AAAA,MACA,IAAI,aAAa;AAAA,QAAQ,SAAS;AAAA,IACpC,EAAO;AAAA,MACL,aAAa;AAAA;AAAA,EAEjB;AAAA,EACA,OAAO,KAAK,IAAI,SAAS,SAAS,CAAC;AAAA;;;AC7ErC,SAAS,cAAc,CAAC,MAAmC;AAAA,EACzD,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI;AAAA;AAGlE,SAAS,MAAM,CAAC,MAAqB;AAAA,EAC1C,IAAI,SAAS,QAAQ,SAAS,aAAa,SAAS,SAAS,SAAS,MAAM;AAAA,IAC1E,OAAO;AAAA,EACT;AAAA,EACA,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EACA,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,IAAI,IAAI;AAAA,EAChD;AAAA,EACA,IAAI,MAAM,QAAQ,IAAI,GAAG;AAAA,IACvB,OAAO,KAAK,IAAI,MAAM,EAAE,KAAK,EAAE;AAAA,EACjC;AAAA,EAEA,IAAI,CAAC,eAAe,IAAI,GAAG;AAAA,IAQzB,IAAI,OAAO,SAAS,YAAY;AAAA,MAC9B,MAAM,IAAI,MACR,mGACE,aAAc,KAAoD,QAAQ,sBAC9E;AAAA,IACF;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACA,MAAM,KAAK;AAAA,EAGX,IAAI,GAAG,SAAS,UAAU;AAAA,IAKxB,OAAO,OAAO,GAAG,MAAM,YAAqB,IAAI;AAAA,EAClD;AAAA,EAGA,IAAI,OAAO,GAAG,SAAS,UAAU;AAAA,IAC/B,MAAM,UAAU,GAAG;AAAA,IACnB,IAAI,CAAC,6BAA6B,KAAK,OAAO,GAAG;AAAA,MAC/C,MAAM,IAAI,MACR,iCAAiC,uGACnC;AAAA,IACF;AAAA,IACA,QAAQ,aAAa,UAAU,GAAG;AAAA,IAClC,IAAI,UAAU;AAAA,IACd,YAAY,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG;AAAA,MAC1C,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM;AAAA,QAAO;AAAA,MAClD,IAAI,MAAM,MAAM;AAAA,QACd,WAAW,IAAI;AAAA,MACjB,EAAO,SAAI,OAAO,MAAM,UAAU;AAAA,QAChC,MAAM,IAAI,MACR,sBAAsB,kEACpB,oCAAoC,uBACxC;AAAA,MACF,EAAO;AAAA,QACL,WAAW,IAAI,MAAM,eAAe,OAAO,CAAC,CAAC;AAAA;AAAA,IAEjD;AAAA,IAGA,MAAM,QAAQ,OAAO,YAAqB,IAAI;AAAA,IAC9C,IAAI,MAAM,QAAQ,MAAM,IAAI;AAAA,MAC1B,OAAO,IAAI,UAAU;AAAA;AAAA,IACvB;AAAA,IACA,OAAO,IAAI,UAAU;AAAA,EAAa,MAAM,QAAQ;AAAA,IAAQ;AAAA;AAAA,EAC1D;AAAA,EAIA,OAAO,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;AAAA;;ACpDjC,IAAM,QAAQ,IAAI;AAEX,SAAS,aAAgB,CAAC,cAA6B;AAAA,EAC5D,MAAM,MAAM,OAAO;AAAA,EAEnB,SAAS,QAAQ,GAAG,OAAO,YAAoD;AAAA,IAC7E,IAAI,IAAI,MAAM,IAAI,GAAG;AAAA,IACrB,IAAI,CAAC,GAAG;AAAA,MACN,IAAI,CAAC;AAAA,MACL,MAAM,IAAI,KAAK,CAAC;AAAA,IAClB;AAAA,IACA,EAAE,KAAK,KAAgB;AAAA,IACvB,IAAI;AAAA,MACF,OAAO,OAAO,YAAY,IAAI;AAAA,cAC9B;AAAA,MACA,EAAE,IAAI;AAAA,MACN,IAAI,EAAE,WAAW;AAAA,QAAG,MAAM,OAAO,GAAG;AAAA;AAAA;AAAA,EAIxC,OAAO,EAAE,KAAK,UAAU,cAAc,SAAS;AAAA;AAG1C,SAAS,UAAa,CAAC,KAAoB;AAAA,EAChD,MAAM,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EAC3B,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;AAAA,IACxB,OAAO,IAAI;AAAA,EACb;AAAA,EACA,OAAO,EAAE,EAAE,SAAS;AAAA;AAGf,SAAS,WAAc,CAAC,KAAiB,OAAU,IAA0B;AAAA,EAClF,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EACzB,IAAI,CAAC,GAAG;AAAA,IACN,IAAI,CAAC;AAAA,IACL,MAAM,IAAI,IAAI,KAAK,CAAC;AAAA,EACtB;AAAA,EACA,EAAE,KAAK,KAAK;AAAA,EACZ,IAAI;AAAA,IACF,OAAO,GAAG;AAAA,YACV;AAAA,IACA,EAAE,IAAI;AAAA,IACN,IAAI,EAAE,WAAW;AAAA,MAAG,MAAM,OAAO,IAAI,GAAG;AAAA;AAAA;;ACA5C,IAAM,eAAe,cAAc,CAAC;AAcpC,IAAM,qBAAqB,cAAkC,IAAI;AAkBjE,IAAM,iBAAiB,cAA8B,IAAI;AAEzD,SAAS,cAAc,CAAC,OAAqC;AAAA,EAC3D,IAAI,UAAU;AAAA,IAAQ,OAAO;AAAA,EAC7B,IAAI,UAAU;AAAA,IAAU,OAAO;AAAA,EAC/B,IAAI,UAAU;AAAA,IAAS,OAAO;AAAA,EAC9B,OAAO;AAAA;AAWF,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,KAAK,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAG7B,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,MAAM,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAG9B,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,OAAO,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAG/B,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,QAAQ,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAGhC,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,SAAS,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAGjC,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,UAAU,OAAO,QAAQ,EAAE,KAAK;AAAA;AAAA;AAAA;AAGlC,SAAS,CAAC,GAAG,YAAgC;AAAA,EAClD,OAAO,GAAG,OAAO,QAAQ;AAAA;AAAA;AAAA;AAGpB,SAAS,EAAE,CAAC,IAA0B,CAAC,GAAW;AAAA,EACvD,OAAO;AAAA;AAAA;AAAA;AASF,SAAS,SAAS,GAAG,OAAO,IAAI,UAAU,SAAS,KAA6B;AAAA,EACrF,MAAM,SAAS,IAAI,OAAO,MAAM;AAAA,EAChC,MAAM,UAAU,OAAO,QAAQ;AAAA,EAC/B,MAAM,QAAQ,IAAI,OAAO,oBAAoB,SAAS,CAAC,CAAC;AAAA,EACxD,MAAM,WAAW,QAAQ,MAAM;AAAA,CAAI;AAAA,EAGnC,OAAO,SAAS,SAAS,KAAK,SAAS,SAAS,SAAS,OAAO,IAAI;AAAA,IAClE,SAAS,IAAI;AAAA,EACf;AAAA,EACA,MAAM,OAAO,SAAS,IAAI,CAAC,SAAS,SAAS,IAAI,EAAE,KAAK;AAAA,CAAI;AAAA,EAC5D,OAAO,GAAG,QAAQ;AAAA,EAAS;AAAA,EAAS;AAAA;AAAA;AAAA;AAa/B,SAAS,UAAU,GAAG,YAAgC;AAAA,EAC3D,MAAM,UAAU,OAAO,QAAQ,EAAE,QAAQ;AAAA,EACzC,MAAM,QAAQ,QAAQ,MAAM;AAAA,CAAI,EAAE,IAAI,CAAC,SAAU,SAAS,KAAK,MAAM,KAAK,MAAO,EAAE,KAAK;AAAA,CAAI;AAAA,EAC5F,OAAO,GAAG;AAAA;AAAA;AAAA;AAOL,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,MAAM,QAAQ,WAAW,YAAY;AAAA,EAGrC,MAAM,WAAW,YAAY,oBAAoB,MAAM,MACrD,YAAY,cAAc,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC,CAC7D;AAAA,EAIA,OAAO,UAAU,IAAI,GAAG;AAAA,IAAe;AAAA,EAAK;AAAA;AAYvC,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,MAAM,QAAQ,WAAW,YAAY;AAAA,EACrC,MAAM,YAAyB,EAAE,OAAO,CAAC,EAAE;AAAA,EAC3C,YAAY,oBAAoB,WAAW,MACzC,YAAY,cAAc,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC,CAC7D;AAAA,EACA,MAAM,SAAS,KAAK,OAAO,KAAK;AAAA,EAChC,MAAM,WAAW,UAAU,MACxB,IAAI,CAAC,MAAM,MAAM,GAAG,SAAS,IAAI,MAAM,MAAM,EAC7C,KAAK,EAAE;AAAA,EACV,OAAO,UAAU,IAAI,GAAG;AAAA,IAAe;AAAA,EAAK;AAAA;AAGvC,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,MAAM,QAAQ,WAAW,YAAY;AAAA,EACrC,MAAM,YAAY,WAAW,kBAAkB;AAAA,EAG/C,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AAAA,EACjD,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ;AAAA,EACvC,IAAI,WAAW;AAAA,IAEb,UAAU,MAAM,KAAK,GAAG;AAAA,CAAS;AAAA,IACjC,OAAO;AAAA,EACT;AAAA,EACA,OAAO,GAAG,WAAW;AAAA;AAAA;AAehB,SAAS,EAAE,GAAG,UAAU,SAAyD;AAAA,EACtF,MAAM,OAAO,WAAW,cAAc;AAAA,EACtC,IAAI;AAAA,IAAM,KAAK,KAAK,KAAK,KAAK;AAAA,EAC9B,OAAO,IAAI,OAAO,QAAQ;AAAA;AAGrB,SAAS,EAAE,GAAG,YAA0C;AAAA,EAC7D,OAAO,IAAI,OAAO,QAAQ;AAAA;AAGrB,SAAS,EAAE,GAAG,YAA0C;AAAA,EAC7D,OAAO,IAAI,OAAO,QAAQ;AAAA;AAAA;AAQrB,SAAS,KAAK,GAAG,YAA0C;AAAA,EAChE,MAAM,OAAgB,EAAE,MAAM,CAAC,EAAE;AAAA,EACjC,MAAM,WAAW,YAAY,gBAAgB,MAAM,MAAM,OAAO,QAAQ,CAAC;AAAA,EACzE,MAAM,QAAQ,SAAS,MAAM;AAAA,CAAI,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;AAAA,EACpE,IAAI,MAAM,WAAW,GAAG;AAAA,IACtB,OAAO;AAAA,EACT;AAAA,EACA,MAAM,YAAY,OAAO,KAAK,KAAK,IAAI,cAAc,EAAE,KAAK,KAAK,IAAI;AAAA,EACrE,MAAM,aAAa,MAAM;AAAA,EACzB,MAAM,YAAY,MAAM,MAAM,CAAC;AAAA,EAC/B,OAAO,CAAC,YAAY,WAAW,GAAG,SAAS,EAAE,KAAK;AAAA,CAAI,IAAI;AAAA;AAAA;AAAA;AAWrD,SAAS,IAAI,GAAG,YAAiC;AAAA,EACtD,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ,SAAS,QAAQ;AAAA,EACxD,OAAO,KAAK;AAAA;AAGP,SAAS,IAAI,GAAG,YAAiC;AAAA,EACtD,MAAM,QAAQ,OAAO,QAAQ;AAAA,EAC7B,MAAM,QAAQ,IAAI,OAAO,oBAAoB,KAAK,CAAC;AAAA,EACnD,OAAO,GAAG,QAAQ,QAAQ;AAAA;AAGrB,SAAS,MAAM,GAAG,YAAiC;AAAA,EACxD,OAAO,IAAI,OAAO,QAAQ;AAAA;AAGrB,SAAS,aAAa,GAAG,YAAiC;AAAA,EAC/D,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ,OAAO,QAAQ;AAAA,EACtD,OAAO,KAAK;AAAA;AAGP,SAAS,EAAE,CAAC,IAA0B,CAAC,GAAW;AAAA,EACvD,OAAO;AAAA;AAAA;AAGF,SAAS,GAAG,GAAG,YAAiC;AAAA,EACrD,OAAO,QAAQ,OAAO,QAAQ;AAAA;AAGzB,SAAS,GAAG,GAAG,YAAiC;AAAA,EACrD,OAAO,QAAQ,OAAO,QAAQ;AAAA;AAGzB,SAAS,GAAG,GAAG,YAAiC;AAAA,EACrD,OAAO,QAAQ,OAAO,QAAQ;AAAA;AAGzB,SAAS,MAAM,GAAG,YAAiC;AAAA,EACxD,OAAO,eAAe,OAAO,QAAQ,CAAC;AAAA;AAQjC,SAAS,IAAI,GAAG,MAAM,YAA+B;AAAA,EAC1D,OAAO,IAAI,OAAO,QAAQ,MAAM,cAAc,IAAI;AAAA;AAQ7C,SAAS,GAAG,GAAG,KAAK,MAAM,MAAwB;AAAA,EACvD,OAAO,KAAK,gBAAgB,GAAG,MAAM,cAAc,GAAG;AAAA;AAOjD,SAAS,EAAE,GAAG,YAAgC;AAAA,EACnD,OAAO,OAAO,QAAQ;AAAA;AAOjB,SAAS,QAAQ,GAAG,YAA0C;AAAA,EACnE,MAAM,QAAQ,WAAW,YAAY;AAAA,EACrC,MAAM,WAAW,YAAY,cAAc,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC;AAAA,EAE5E,OAAO,UAAU,IAAI,GAAG;AAAA,IAAe;AAAA,EAAK;AAAA;AAGvC,SAAS,IAAI,GAAG,UAAU,QAAsD;AAAA,EACrF,MAAM,QAAQ,WAAW,YAAY;AAAA,EAErC,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AAAA,EACjD,MAAM,SAAS,OAAO,QAAQ;AAAA,EAC9B,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ;AAAA,EACvC,OAAO,GAAG,WAAW,UAAU;AAAA;AAAA;AAS1B,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,GAIS;AAAA,EACT,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ;AAAA,EACvC,MAAM,QAAQ,MAAM,MAAM;AAAA,CAAI,EAAE,IAAI,CAAC,SAAU,SAAS,KAAK,MAAM,KAAK,MAAO,EAAE,KAAK;AAAA,CAAI;AAAA,EAC1F,OAAO,OAAO,KAAK,YAAY;AAAA,EAAO;AAAA;AAAA;AAAA;AAOjC,SAAS,WAAW,GAAG,YAA0C;AAAA,EACtE,MAAM,QAAQ,OAAO,QAAQ,EAAE,QAAQ;AAAA,EAEvC,IAAI,CAAC,MAAM,KAAK,GAAG;AAAA,IACjB,OAAO;AAAA;AAAA,EACT;AAAA,EAIA,MAAM,OAAO,MAAM,QAAQ,WAAW,CAAC,MAAO,MAAM,QAAQ,SAAS,KAAM;AAAA,EAC3E,IAAI,KAAK,SAAS;AAAA,CAAI,GAAG;AAAA,IACvB,OAAO;AAAA,EAAS;AAAA;AAAA;AAAA,EAClB;AAAA,EACA,OAAO,QAAQ;AAAA;AAAA;AAOV,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,GAIS;AAAA,EAET,MAAM,cAAc,kBAAkB,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAAA,EAGjE,MAAM,OAAO,OAAO,QAAQ,EAAE,QAAQ;AAAA,EACtC,OAAO;AAAA,WAAuB;AAAA;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;",
11
+ "debugId": "E837B16067996D6464756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,13 @@
1
+ import {
2
+ Fragment,
3
+ jsx,
4
+ jsxs
5
+ } from "./index-8tdwjkh9.js";
6
+ export {
7
+ jsxs,
8
+ jsx as jsxDEV,
9
+ Fragment
10
+ };
11
+
12
+ //# debugId=67B5BDB971EB74D764756E2164756E21
13
+ //# sourceMappingURL=jsx-dev-runtime.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "67B5BDB971EB74D764756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,13 @@
1
+ import {
2
+ Fragment,
3
+ jsx,
4
+ jsxs
5
+ } from "./index-8tdwjkh9.js";
6
+ export {
7
+ jsxs,
8
+ jsx,
9
+ Fragment
10
+ };
11
+
12
+ //# debugId=D254BD52363F289564756E2164756E21
13
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "D254BD52363F289564756E2164756E21",
8
+ "names": []
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theseus.run/jsx-md",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "JSX/TSX renderer for Markdown. Write agent prompts and LLM instructions as typed, composable components. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "author": "Roman Dubinin <romanonthego@gmail.com> (https://romanonthego.com)",
@@ -16,13 +16,17 @@
16
16
  "homepage": "https://theseus.run",
17
17
  "keywords": ["jsx", "tsx", "markdown", "llm", "agents", "prompts", "jsx-runtime"],
18
18
  "engines": {
19
- "bun": ">=1.0.0"
19
+ "bun": ">=1.0.0",
20
+ "node": ">=18.0.0"
20
21
  },
21
22
  "publishConfig": {
22
23
  "access": "public"
23
24
  },
24
25
  "scripts": {
25
- "test": "bun test"
26
+ "build": "bun build --target=node --sourcemap=linked --splitting --outdir=dist src/index.ts src/jsx-runtime.ts src/jsx-dev-runtime.ts",
27
+ "test": "bun test",
28
+ "test:dist": "node test/dist.mjs && bun test/dist.mjs",
29
+ "typecheck": "tsc"
26
30
  },
27
31
  "files": [
28
32
  "src/index.ts",
@@ -32,17 +36,29 @@
32
36
  "src/jsx-dev-runtime.ts",
33
37
  "src/context.ts",
34
38
  "src/escape.ts",
35
- "src/_render-registry.ts"
39
+ "dist"
36
40
  ],
37
41
  "sideEffects": false,
38
42
  "types": "./src/index.ts",
39
43
  "exports": {
40
- ".": "./src/index.ts",
41
- "./jsx-runtime": "./src/jsx-runtime.ts",
42
- "./jsx-dev-runtime": "./src/jsx-dev-runtime.ts"
44
+ ".": {
45
+ "bun": "./src/index.ts",
46
+ "types": "./src/index.ts",
47
+ "import": "./dist/index.js"
48
+ },
49
+ "./jsx-runtime": {
50
+ "bun": "./src/jsx-runtime.ts",
51
+ "types": "./src/jsx-runtime.ts",
52
+ "import": "./dist/jsx-runtime.js"
53
+ },
54
+ "./jsx-dev-runtime": {
55
+ "bun": "./src/jsx-dev-runtime.ts",
56
+ "types": "./src/jsx-dev-runtime.ts",
57
+ "import": "./dist/jsx-dev-runtime.js"
58
+ }
43
59
  },
44
60
  "devDependencies": {
45
- "@types/bun": "latest",
46
- "typescript": "^5"
61
+ "@types/bun": "1.3.10",
62
+ "typescript": "5.9.3"
47
63
  }
48
64
  }