@immediately-run/sdk 0.29.0 → 0.30.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.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/safeContent/SafeContent.cjs +54 -0
- package/dist/safeContent/SafeContent.cjs.map +1 -0
- package/dist/safeContent/SafeContent.d.cts +13 -0
- package/dist/safeContent/SafeContent.d.ts +13 -0
- package/dist/safeContent/SafeContent.js +30 -0
- package/dist/safeContent/SafeContent.js.map +1 -0
- package/dist/safeContent/index.cjs +43 -0
- package/dist/safeContent/index.cjs.map +1 -0
- package/dist/safeContent/index.d.cts +6 -0
- package/dist/safeContent/index.d.ts +6 -0
- package/dist/safeContent/index.js +14 -0
- package/dist/safeContent/index.js.map +1 -0
- package/dist/safeContent/parseSafeMdast.cjs +69 -0
- package/dist/safeContent/parseSafeMdast.cjs.map +1 -0
- package/dist/safeContent/parseSafeMdast.d.cts +31 -0
- package/dist/safeContent/parseSafeMdast.d.ts +31 -0
- package/dist/safeContent/parseSafeMdast.js +35 -0
- package/dist/safeContent/parseSafeMdast.js.map +1 -0
- package/dist/safeContent/renderMdast.cjs +138 -0
- package/dist/safeContent/renderMdast.cjs.map +1 -0
- package/dist/safeContent/renderMdast.d.cts +27 -0
- package/dist/safeContent/renderMdast.d.ts +27 -0
- package/dist/safeContent/renderMdast.js +114 -0
- package/dist/safeContent/renderMdast.js.map +1 -0
- package/dist/safeContent/sanitizeUrl.cjs +39 -0
- package/dist/safeContent/sanitizeUrl.cjs.map +1 -0
- package/dist/safeContent/sanitizeUrl.d.cts +9 -0
- package/dist/safeContent/sanitizeUrl.d.ts +9 -0
- package/dist/safeContent/sanitizeUrl.js +15 -0
- package/dist/safeContent/sanitizeUrl.js.map +1 -0
- package/dist/safeContent/wikilink.cjs +63 -0
- package/dist/safeContent/wikilink.cjs.map +1 -0
- package/dist/safeContent/wikilink.d.cts +21 -0
- package/dist/safeContent/wikilink.d.ts +21 -0
- package/dist/safeContent/wikilink.js +38 -0
- package/dist/safeContent/wikilink.js.map +1 -0
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +9 -3
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ __reExport(index_exports, require("./ready"), module.exports);
|
|
|
49
49
|
__reExport(index_exports, require("./loading"), module.exports);
|
|
50
50
|
__reExport(index_exports, require("./protocolStream"), module.exports);
|
|
51
51
|
__reExport(index_exports, require("./sandboxTypes"), module.exports);
|
|
52
|
+
__reExport(index_exports, require("./safeContent"), module.exports);
|
|
52
53
|
// Annotate the CommonJS export names for ESM import in node:
|
|
53
54
|
0 && (module.exports = {
|
|
54
55
|
...require("./MDXProvider"),
|
|
@@ -84,6 +85,7 @@ __reExport(index_exports, require("./sandboxTypes"), module.exports);
|
|
|
84
85
|
...require("./ready"),
|
|
85
86
|
...require("./loading"),
|
|
86
87
|
...require("./protocolStream"),
|
|
87
|
-
...require("./sandboxTypes")
|
|
88
|
+
...require("./sandboxTypes"),
|
|
89
|
+
...require("./safeContent")
|
|
88
90
|
});
|
|
89
91
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './region';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oCALd;AAMA,0BAAc,gCANd;AAOA,0BAAc,oBAPd;AAQA,0BAAc,mBARd;AASA,0BAAc,oBATd;AAUA,0BAAc,4BAVd;AAWA,0BAAc,qBAXd;AAYA,0BAAc,yBAZd;AAaA,0BAAc,qBAbd;AAcA,0BAAc,qBAdd;AAeA,0BAAc,yBAfd;AAgBA,0BAAc,sBAhBd;AAiBA,0BAAc,kBAjBd;AAkBA,0BAAc,kBAlBd;AAmBA,0BAAc,uBAnBd;AAoBA,0BAAc,sBApBd;AAqBA,0BAAc,kBArBd;AAsBA,0BAAc,0BAtBd;AAuBA,0BAAc,kBAvBd;AAwBA,0BAAc,yBAxBd;AAyBA,0BAAc,iBAzBd;AA0BA,0BAAc,oBA1Bd;AA2BA,0BAAc,oBA3Bd;AA4BA,0BAAc,sBA5Bd;AA6BA,0BAAc,wBA7Bd;AA8BA,0BAAc,oBA9Bd;AA+BA,0BAAc,sBA/Bd;AAgCA,0BAAc,6BAhCd;AAiCA,0BAAc,2BAjCd;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './region';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oCALd;AAMA,0BAAc,gCANd;AAOA,0BAAc,oBAPd;AAQA,0BAAc,mBARd;AASA,0BAAc,oBATd;AAUA,0BAAc,4BAVd;AAWA,0BAAc,qBAXd;AAYA,0BAAc,yBAZd;AAaA,0BAAc,qBAbd;AAcA,0BAAc,qBAdd;AAeA,0BAAc,yBAfd;AAgBA,0BAAc,sBAhBd;AAiBA,0BAAc,kBAjBd;AAkBA,0BAAc,kBAlBd;AAmBA,0BAAc,uBAnBd;AAoBA,0BAAc,sBApBd;AAqBA,0BAAc,kBArBd;AAsBA,0BAAc,0BAtBd;AAuBA,0BAAc,kBAvBd;AAwBA,0BAAc,yBAxBd;AAyBA,0BAAc,iBAzBd;AA0BA,0BAAc,oBA1Bd;AA2BA,0BAAc,oBA3Bd;AA4BA,0BAAc,sBA5Bd;AA6BA,0BAAc,wBA7Bd;AA8BA,0BAAc,oBA9Bd;AA+BA,0BAAc,sBA/Bd;AAgCA,0BAAc,6BAhCd;AAiCA,0BAAc,2BAjCd;AAkCA,0BAAc,0BAlCd;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -32,6 +32,11 @@ export { ReadyState, __resetReady, __setReadyDeps, getReadyState, onReady, repor
|
|
|
32
32
|
export { LOADING_TIMINGS, LoadingRegion, Skeleton, SkeletonArchetype, SkeletonRow, Spinner } from './loading.cjs';
|
|
33
33
|
export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.cjs';
|
|
34
34
|
export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryEntry, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.cjs';
|
|
35
|
+
export { SafeContent, SafeContentProps } from './safeContent/SafeContent.cjs';
|
|
36
|
+
export { RenderMdastOptions, SafeContentComponents, renderMdast } from './safeContent/renderMdast.cjs';
|
|
37
|
+
export { SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './safeContent/parseSafeMdast.cjs';
|
|
38
|
+
export { sanitizeUrl } from './safeContent/sanitizeUrl.cjs';
|
|
39
|
+
export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './safeContent/wikilink.cjs';
|
|
35
40
|
export { Admonition, AdmonitionType } from './components/Admonition.cjs';
|
|
36
41
|
export { HeadingAnchor } from './components/HeadingAnchor.cjs';
|
|
37
42
|
export { ImmediatelyRunGlobal, getHostRuntime } from './hostRuntime.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export { ReadyState, __resetReady, __setReadyDeps, getReadyState, onReady, repor
|
|
|
32
32
|
export { LOADING_TIMINGS, LoadingRegion, Skeleton, SkeletonArchetype, SkeletonRow, Spinner } from './loading.js';
|
|
33
33
|
export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.js';
|
|
34
34
|
export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryEntry, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.js';
|
|
35
|
+
export { SafeContent, SafeContentProps } from './safeContent/SafeContent.js';
|
|
36
|
+
export { RenderMdastOptions, SafeContentComponents, renderMdast } from './safeContent/renderMdast.js';
|
|
37
|
+
export { SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './safeContent/parseSafeMdast.js';
|
|
38
|
+
export { sanitizeUrl } from './safeContent/sanitizeUrl.js';
|
|
39
|
+
export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './safeContent/wikilink.js';
|
|
35
40
|
export { Admonition, AdmonitionType } from './components/Admonition.js';
|
|
36
41
|
export { HeadingAnchor } from './components/HeadingAnchor.js';
|
|
37
42
|
export { ImmediatelyRunGlobal, getHostRuntime } from './hostRuntime.js';
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './region';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './region';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var SafeContent_exports = {};
|
|
20
|
+
__export(SafeContent_exports, {
|
|
21
|
+
SafeContent: () => SafeContent
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(SafeContent_exports);
|
|
24
|
+
var import_react = require("react");
|
|
25
|
+
var import_parseSafeMdast = require("./parseSafeMdast");
|
|
26
|
+
var import_renderMdast = require("./renderMdast");
|
|
27
|
+
function SafeContent({ source, fallback = null, ...options }) {
|
|
28
|
+
const [tree, setTree] = (0, import_react.useState)(null);
|
|
29
|
+
const runId = (0, import_react.useRef)(0);
|
|
30
|
+
(0, import_react.useEffect)(() => {
|
|
31
|
+
const id = ++runId.current;
|
|
32
|
+
setTree(null);
|
|
33
|
+
let cancelled = false;
|
|
34
|
+
(0, import_parseSafeMdast.parseSafeMdast)(source).then((parsed) => {
|
|
35
|
+
if (!cancelled && runId.current === id) setTree(parsed);
|
|
36
|
+
}).catch(() => {
|
|
37
|
+
if (!cancelled && runId.current === id) setTree(null);
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
cancelled = true;
|
|
41
|
+
};
|
|
42
|
+
}, [source]);
|
|
43
|
+
const rendered = (0, import_react.useMemo)(
|
|
44
|
+
() => tree ? (0, import_renderMdast.renderMdast)(tree, options) : null,
|
|
45
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
46
|
+
[tree, options.components, options.resolveWikiLink]
|
|
47
|
+
);
|
|
48
|
+
return tree ? rendered : fallback;
|
|
49
|
+
}
|
|
50
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
51
|
+
0 && (module.exports = {
|
|
52
|
+
SafeContent
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=SafeContent.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { parseSafeMdast } from './parseSafeMdast';\nimport { renderMdast, type RenderMdastOptions } from './renderMdast';\n\n// `<SafeContent>` — the host/SDK-owned safe renderer (TRUST_MODES_SPEC §5.1,\n// AGENT_AUTHORING §10). An interpreter app renders untrusted Markdown/MDX-syntax\n// content — a shared board's body, a multi-writer wiki entry — through THIS component\n// so **no author JavaScript ever executes** while `<Component/>` syntax still reaches\n// the app's own safe components. It is the mandatory terminal for the MDX-from-mount\n// gate: a shared board is a multi-writer (M3) source, and compiled/executable MDX\n// would run board-author code with the app's authority (the WHITEBOARD §8 blast\n// radius this gate bounds).\n//\n// The parse (no-acorn, ESM-only deps) is async, so this renders a small placeholder\n// until the tree is ready, then the pure synchronous `renderMdast`. Parsing is keyed\n// on the source string; a changed source re-parses, and a stale async result is\n// discarded (the ref guard) so a fast source swap can't paint the wrong content.\n\nexport interface SafeContentProps extends RenderMdastOptions {\n /** The untrusted Markdown/MDX-syntax source to render as data. */\n source: string;\n /** Rendered while the async parse is in flight (default: nothing). */\n fallback?: ReactNode;\n}\n\nexport function SafeContent({ source, fallback = null, ...options }: SafeContentProps): ReactNode {\n const [tree, setTree] = useState<Awaited<ReturnType<typeof parseSafeMdast>> | null>(null);\n const runId = useRef(0);\n\n useEffect(() => {\n const id = ++runId.current;\n setTree(null);\n let cancelled = false;\n parseSafeMdast(source)\n .then((parsed) => {\n // Discard a stale result (source changed / unmounted) so we never paint the\n // wrong tree — the render-as-data guarantee also needs the RIGHT data shown.\n if (!cancelled && runId.current === id) setTree(parsed);\n })\n .catch(() => {\n if (!cancelled && runId.current === id) setTree(null);\n });\n return () => {\n cancelled = true;\n };\n }, [source]);\n\n // `renderMdast` is pure; memoise on the tree + the option identities the caller\n // passes. (Callers should memoise `components`/`resolveWikiLink` themselves for a\n // stable identity; changing them re-renders, which is correct.)\n const rendered = useMemo(\n () => (tree ? renderMdast(tree, options) : null),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tree, options.components, options.resolveWikiLink],\n );\n\n return tree ? rendered : fallback;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqE;AACrE,4BAA+B;AAC/B,yBAAqD;AAuB9C,SAAS,YAAY,EAAE,QAAQ,WAAW,MAAM,GAAG,QAAQ,GAAgC;AAChG,QAAM,CAAC,MAAM,OAAO,QAAI,uBAA4D,IAAI;AACxF,QAAM,YAAQ,qBAAO,CAAC;AAEtB,8BAAU,MAAM;AACd,UAAM,KAAK,EAAE,MAAM;AACnB,YAAQ,IAAI;AACZ,QAAI,YAAY;AAChB,8CAAe,MAAM,EAClB,KAAK,CAAC,WAAW;AAGhB,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,MAAM;AAAA,IACxD,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,IAAI;AAAA,IACtD,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,eAAW;AAAA,IACf,MAAO,WAAO,gCAAY,MAAM,OAAO,IAAI;AAAA;AAAA,IAE3C,CAAC,MAAM,QAAQ,YAAY,QAAQ,eAAe;AAAA,EACpD;AAEA,SAAO,OAAO,WAAW;AAC3B;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { RenderMdastOptions } from './renderMdast.cjs';
|
|
3
|
+
import './parseSafeMdast.cjs';
|
|
4
|
+
|
|
5
|
+
interface SafeContentProps extends RenderMdastOptions {
|
|
6
|
+
/** The untrusted Markdown/MDX-syntax source to render as data. */
|
|
7
|
+
source: string;
|
|
8
|
+
/** Rendered while the async parse is in flight (default: nothing). */
|
|
9
|
+
fallback?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
declare function SafeContent({ source, fallback, ...options }: SafeContentProps): ReactNode;
|
|
12
|
+
|
|
13
|
+
export { SafeContent, type SafeContentProps };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { RenderMdastOptions } from './renderMdast.js';
|
|
3
|
+
import './parseSafeMdast.js';
|
|
4
|
+
|
|
5
|
+
interface SafeContentProps extends RenderMdastOptions {
|
|
6
|
+
/** The untrusted Markdown/MDX-syntax source to render as data. */
|
|
7
|
+
source: string;
|
|
8
|
+
/** Rendered while the async parse is in flight (default: nothing). */
|
|
9
|
+
fallback?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
declare function SafeContent({ source, fallback, ...options }: SafeContentProps): ReactNode;
|
|
12
|
+
|
|
13
|
+
export { SafeContent, type SafeContentProps };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { parseSafeMdast } from "./parseSafeMdast";
|
|
3
|
+
import { renderMdast } from "./renderMdast";
|
|
4
|
+
function SafeContent({ source, fallback = null, ...options }) {
|
|
5
|
+
const [tree, setTree] = useState(null);
|
|
6
|
+
const runId = useRef(0);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const id = ++runId.current;
|
|
9
|
+
setTree(null);
|
|
10
|
+
let cancelled = false;
|
|
11
|
+
parseSafeMdast(source).then((parsed) => {
|
|
12
|
+
if (!cancelled && runId.current === id) setTree(parsed);
|
|
13
|
+
}).catch(() => {
|
|
14
|
+
if (!cancelled && runId.current === id) setTree(null);
|
|
15
|
+
});
|
|
16
|
+
return () => {
|
|
17
|
+
cancelled = true;
|
|
18
|
+
};
|
|
19
|
+
}, [source]);
|
|
20
|
+
const rendered = useMemo(
|
|
21
|
+
() => tree ? renderMdast(tree, options) : null,
|
|
22
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
+
[tree, options.components, options.resolveWikiLink]
|
|
24
|
+
);
|
|
25
|
+
return tree ? rendered : fallback;
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
SafeContent
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=SafeContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/SafeContent.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { parseSafeMdast } from './parseSafeMdast';\nimport { renderMdast, type RenderMdastOptions } from './renderMdast';\n\n// `<SafeContent>` — the host/SDK-owned safe renderer (TRUST_MODES_SPEC §5.1,\n// AGENT_AUTHORING §10). An interpreter app renders untrusted Markdown/MDX-syntax\n// content — a shared board's body, a multi-writer wiki entry — through THIS component\n// so **no author JavaScript ever executes** while `<Component/>` syntax still reaches\n// the app's own safe components. It is the mandatory terminal for the MDX-from-mount\n// gate: a shared board is a multi-writer (M3) source, and compiled/executable MDX\n// would run board-author code with the app's authority (the WHITEBOARD §8 blast\n// radius this gate bounds).\n//\n// The parse (no-acorn, ESM-only deps) is async, so this renders a small placeholder\n// until the tree is ready, then the pure synchronous `renderMdast`. Parsing is keyed\n// on the source string; a changed source re-parses, and a stale async result is\n// discarded (the ref guard) so a fast source swap can't paint the wrong content.\n\nexport interface SafeContentProps extends RenderMdastOptions {\n /** The untrusted Markdown/MDX-syntax source to render as data. */\n source: string;\n /** Rendered while the async parse is in flight (default: nothing). */\n fallback?: ReactNode;\n}\n\nexport function SafeContent({ source, fallback = null, ...options }: SafeContentProps): ReactNode {\n const [tree, setTree] = useState<Awaited<ReturnType<typeof parseSafeMdast>> | null>(null);\n const runId = useRef(0);\n\n useEffect(() => {\n const id = ++runId.current;\n setTree(null);\n let cancelled = false;\n parseSafeMdast(source)\n .then((parsed) => {\n // Discard a stale result (source changed / unmounted) so we never paint the\n // wrong tree — the render-as-data guarantee also needs the RIGHT data shown.\n if (!cancelled && runId.current === id) setTree(parsed);\n })\n .catch(() => {\n if (!cancelled && runId.current === id) setTree(null);\n });\n return () => {\n cancelled = true;\n };\n }, [source]);\n\n // `renderMdast` is pure; memoise on the tree + the option identities the caller\n // passes. (Callers should memoise `components`/`resolveWikiLink` themselves for a\n // stable identity; changing them re-renders, which is correct.)\n const rendered = useMemo(\n () => (tree ? renderMdast(tree, options) : null),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [tree, options.components, options.resolveWikiLink],\n );\n\n return tree ? rendered : fallback;\n}\n"],"mappings":"AAAA,SAAS,WAAW,SAAS,QAAQ,gBAAgC;AACrE,SAAS,sBAAsB;AAC/B,SAAS,mBAA4C;AAuB9C,SAAS,YAAY,EAAE,QAAQ,WAAW,MAAM,GAAG,QAAQ,GAAgC;AAChG,QAAM,CAAC,MAAM,OAAO,IAAI,SAA4D,IAAI;AACxF,QAAM,QAAQ,OAAO,CAAC;AAEtB,YAAU,MAAM;AACd,UAAM,KAAK,EAAE,MAAM;AACnB,YAAQ,IAAI;AACZ,QAAI,YAAY;AAChB,mBAAe,MAAM,EAClB,KAAK,CAAC,WAAW;AAGhB,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,MAAM;AAAA,IACxD,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,aAAa,MAAM,YAAY,GAAI,SAAQ,IAAI;AAAA,IACtD,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,WAAW;AAAA,IACf,MAAO,OAAO,YAAY,MAAM,OAAO,IAAI;AAAA;AAAA,IAE3C,CAAC,MAAM,QAAQ,YAAY,QAAQ,eAAe;AAAA,EACpD;AAEA,SAAO,OAAO,WAAW;AAC3B;","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var safeContent_exports = {};
|
|
20
|
+
__export(safeContent_exports, {
|
|
21
|
+
SafeContent: () => import_SafeContent.SafeContent,
|
|
22
|
+
parseSafeMdast: () => import_parseSafeMdast.parseSafeMdast,
|
|
23
|
+
parseWikiInner: () => import_wikilink.parseWikiInner,
|
|
24
|
+
renderMdast: () => import_renderMdast.renderMdast,
|
|
25
|
+
sanitizeUrl: () => import_sanitizeUrl.sanitizeUrl,
|
|
26
|
+
splitWikiLinks: () => import_wikilink.splitWikiLinks
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(safeContent_exports);
|
|
29
|
+
var import_SafeContent = require("./SafeContent");
|
|
30
|
+
var import_renderMdast = require("./renderMdast");
|
|
31
|
+
var import_parseSafeMdast = require("./parseSafeMdast");
|
|
32
|
+
var import_sanitizeUrl = require("./sanitizeUrl");
|
|
33
|
+
var import_wikilink = require("./wikilink");
|
|
34
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
35
|
+
0 && (module.exports = {
|
|
36
|
+
SafeContent,
|
|
37
|
+
parseSafeMdast,
|
|
38
|
+
parseWikiInner,
|
|
39
|
+
renderMdast,
|
|
40
|
+
sanitizeUrl,
|
|
41
|
+
splitWikiLinks
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n\nexport { SafeContent } from './SafeContent';\nexport type { SafeContentProps } from './SafeContent';\nexport { renderMdast } from './renderMdast';\nexport type {\n RenderMdastOptions,\n SafeContentComponents,\n} from './renderMdast';\nexport { parseSafeMdast } from './parseSafeMdast';\nexport type { SafeMdastNode, SafeMdxAttribute } from './parseSafeMdast';\nexport { sanitizeUrl } from './sanitizeUrl';\nexport { splitWikiLinks, parseWikiInner } from './wikilink';\nexport type { WikiLinkToken, WikiPart } from './wikilink';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,yBAA4B;AAE5B,yBAA4B;AAK5B,4BAA+B;AAE/B,yBAA4B;AAC5B,sBAA+C;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SafeContent, SafeContentProps } from './SafeContent.cjs';
|
|
2
|
+
export { RenderMdastOptions, SafeContentComponents, renderMdast } from './renderMdast.cjs';
|
|
3
|
+
export { SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './parseSafeMdast.cjs';
|
|
4
|
+
export { sanitizeUrl } from './sanitizeUrl.cjs';
|
|
5
|
+
export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './wikilink.cjs';
|
|
6
|
+
import 'react';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SafeContent, SafeContentProps } from './SafeContent.js';
|
|
2
|
+
export { RenderMdastOptions, SafeContentComponents, renderMdast } from './renderMdast.js';
|
|
3
|
+
export { SafeMdastNode, SafeMdxAttribute, parseSafeMdast } from './parseSafeMdast.js';
|
|
4
|
+
export { sanitizeUrl } from './sanitizeUrl.js';
|
|
5
|
+
export { WikiLinkToken, WikiPart, parseWikiInner, splitWikiLinks } from './wikilink.js';
|
|
6
|
+
import 'react';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SafeContent } from "./SafeContent";
|
|
2
|
+
import { renderMdast } from "./renderMdast";
|
|
3
|
+
import { parseSafeMdast } from "./parseSafeMdast";
|
|
4
|
+
import { sanitizeUrl } from "./sanitizeUrl";
|
|
5
|
+
import { splitWikiLinks, parseWikiInner } from "./wikilink";
|
|
6
|
+
export {
|
|
7
|
+
SafeContent,
|
|
8
|
+
parseSafeMdast,
|
|
9
|
+
parseWikiInner,
|
|
10
|
+
renderMdast,
|
|
11
|
+
sanitizeUrl,
|
|
12
|
+
splitWikiLinks
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/index.ts"],"sourcesContent":["// Safe content rendering — non-executable MDX (TRUST_MODES_SPEC §5.1, AGENT_AUTHORING\n// §10). The host/SDK-owned renderer an INTERPRETER app uses to render untrusted\n// Markdown/MDX-syntax content as data, with **no evaluator anywhere in the pipeline**.\n// This is the mandatory terminal for the MDX-from-mount gate (§10 delta 1) — a shared\n// (multi-writer / M3) board or wiki entry MUST render through here, never compiled MDX.\n//\n// It is a **T2 tool, not a platform gate**: it stops content executing as code; it does\n// not certify anything to the host, and CO-4 data-fencing is still required for anything\n// that *reads* the content (the agent case).\n\nexport { SafeContent } from './SafeContent';\nexport type { SafeContentProps } from './SafeContent';\nexport { renderMdast } from './renderMdast';\nexport type {\n RenderMdastOptions,\n SafeContentComponents,\n} from './renderMdast';\nexport { parseSafeMdast } from './parseSafeMdast';\nexport type { SafeMdastNode, SafeMdxAttribute } from './parseSafeMdast';\nexport { sanitizeUrl } from './sanitizeUrl';\nexport { splitWikiLinks, parseWikiInner } from './wikilink';\nexport type { WikiLinkToken, WikiPart } from './wikilink';\n"],"mappings":"AAUA,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAK5B,SAAS,sBAAsB;AAE/B,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB,sBAAsB;","names":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var parseSafeMdast_exports = {};
|
|
30
|
+
__export(parseSafeMdast_exports, {
|
|
31
|
+
parseSafeMdast: () => parseSafeMdast
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(parseSafeMdast_exports);
|
|
34
|
+
let depsPromise = null;
|
|
35
|
+
function loadDeps() {
|
|
36
|
+
if (!depsPromise) {
|
|
37
|
+
depsPromise = Promise.all([
|
|
38
|
+
import("mdast-util-from-markdown"),
|
|
39
|
+
import("micromark-extension-mdx-jsx"),
|
|
40
|
+
import("mdast-util-mdx-jsx"),
|
|
41
|
+
import("micromark-extension-gfm"),
|
|
42
|
+
import("mdast-util-gfm")
|
|
43
|
+
]).then(
|
|
44
|
+
([fromMd, mdxJsxExt, mdxJsxMdast, gfmExt, gfmMdast]) => ({
|
|
45
|
+
fromMarkdown: fromMd.fromMarkdown,
|
|
46
|
+
mdxJsx: mdxJsxExt.mdxJsx,
|
|
47
|
+
mdxJsxFromMarkdown: mdxJsxMdast.mdxJsxFromMarkdown,
|
|
48
|
+
gfm: gfmExt.gfm,
|
|
49
|
+
gfmFromMarkdown: gfmMdast.gfmFromMarkdown
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return depsPromise;
|
|
54
|
+
}
|
|
55
|
+
async function parseSafeMdast(source) {
|
|
56
|
+
const { fromMarkdown, mdxJsx, mdxJsxFromMarkdown, gfm, gfmFromMarkdown } = await loadDeps();
|
|
57
|
+
return fromMarkdown(source, {
|
|
58
|
+
// `mdxJsx()` WITHOUT an acorn option → JSX tags + literal attrs; expressions are
|
|
59
|
+
// raw strings, never estree. The mdx *expression* extension is intentionally
|
|
60
|
+
// absent, so `{…}` in body text stays literal. GFM for tables/task-lists.
|
|
61
|
+
extensions: [mdxJsx(), gfm()],
|
|
62
|
+
mdastExtensions: [mdxJsxFromMarkdown(), gfmFromMarkdown()]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
66
|
+
0 && (module.exports = {
|
|
67
|
+
parseSafeMdast
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=parseSafeMdast.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/parseSafeMdast.ts"],"sourcesContent":["// The no-acorn parse pipeline for the safe content renderer (TRUST_MODES_SPEC §5.1,\n// empirically verified 2026-07-07 against `@mdx-js/mdx` v3 / `micromark-extension-\n// mdx-jsx`). This is the load-bearing half of the fail-safe: `<Component/>` syntax\n// parses to an element node with **literal** attributes, and every expression\n// (`n={1+1}`, `f={fetch(\"/x\")}`, `{...spread}`) is captured as an **inert raw string\n// with no estree** — because we pass **NO acorn option** to `micromark-extension-mdx-\n// jsx`. There is therefore no evaluator anywhere in the pipeline (fail-safe), unlike\n// `@mdx-js/mdx`'s `compile({format:'mdx'})` which always wires acorn.\n//\n// The §5.1 residual guarantees are also here: the expression micromark extension is\n// **not** enabled (body `{…}` stays literal text), and **no `rehype-raw`** / raw-HTML\n// passthrough exists — raw HTML blocks arrive as inert `html` mdast nodes the renderer\n// prints as text, never injected.\n//\n// `micromark`/`mdast` are ESM-only. They are loaded with a memoised dynamic `import()`\n// (the transpiler's `compile.ts` pattern) so this module sits in the package's CJS\n// build too — a CJS consumer that never renders untrusted content never `require()`s\n// an ESM-only package, and one that does gets it via Node's ESM-from-CJS import. The\n// dynamic load changes only *when* the deps resolve, never the produced tree.\n\n// A minimal structural mdast shape — we deliberately avoid a type dependency on the\n// ESM-only `mdast`/`unist` packages (which would break the CJS build's type surface).\nexport interface SafeMdastNode {\n type: string;\n value?: string;\n name?: string | null;\n url?: string;\n alt?: string | null;\n title?: string | null;\n depth?: number;\n ordered?: boolean;\n lang?: string | null;\n children?: SafeMdastNode[];\n attributes?: SafeMdxAttribute[];\n [key: string]: unknown;\n}\n\nexport interface SafeMdxAttribute {\n type: 'mdxJsxAttribute' | 'mdxJsxExpressionAttribute';\n name?: string;\n // A literal attribute carries a string; an expression attribute carries an\n // `mdxJsxAttributeValueExpression` object (a raw string, NO estree) or a string.\n value?: string | { type: string; value?: string } | null;\n}\n\ntype Deps = {\n fromMarkdown: (\n value: string,\n options: { extensions: unknown[]; mdastExtensions: unknown[] },\n ) => SafeMdastNode;\n mdxJsx: () => unknown;\n mdxJsxFromMarkdown: () => unknown;\n gfm: () => unknown;\n gfmFromMarkdown: () => unknown;\n};\n\nlet depsPromise: Promise<Deps> | null = null;\n\nfunction loadDeps(): Promise<Deps> {\n if (!depsPromise) {\n depsPromise = Promise.all([\n import('mdast-util-from-markdown'),\n import('micromark-extension-mdx-jsx'),\n import('mdast-util-mdx-jsx'),\n import('micromark-extension-gfm'),\n import('mdast-util-gfm'),\n ]).then(\n ([fromMd, mdxJsxExt, mdxJsxMdast, gfmExt, gfmMdast]) =>\n ({\n fromMarkdown: (fromMd as unknown as { fromMarkdown: Deps['fromMarkdown'] }).fromMarkdown,\n mdxJsx: (mdxJsxExt as unknown as { mdxJsx: Deps['mdxJsx'] }).mdxJsx,\n mdxJsxFromMarkdown: (mdxJsxMdast as unknown as { mdxJsxFromMarkdown: Deps['mdxJsxFromMarkdown'] })\n .mdxJsxFromMarkdown,\n gfm: (gfmExt as unknown as { gfm: Deps['gfm'] }).gfm,\n gfmFromMarkdown: (gfmMdast as unknown as { gfmFromMarkdown: Deps['gfmFromMarkdown'] }).gfmFromMarkdown,\n }) as Deps,\n );\n }\n return depsPromise;\n}\n\n/**\n * Parse untrusted Markdown/MDX-syntax source to an mdast tree with **no evaluator in\n * the pipeline**: JSX-as-data (no acorn), GFM on, the expression extension OFF, no\n * raw-HTML re-parse. The returned tree is safe to hand to `renderMdast` — expression\n * attributes are inert strings and raw HTML is inert `html` nodes.\n */\nexport async function parseSafeMdast(source: string): Promise<SafeMdastNode> {\n const { fromMarkdown, mdxJsx, mdxJsxFromMarkdown, gfm, gfmFromMarkdown } = await loadDeps();\n return fromMarkdown(source, {\n // `mdxJsx()` WITHOUT an acorn option → JSX tags + literal attrs; expressions are\n // raw strings, never estree. The mdx *expression* extension is intentionally\n // absent, so `{…}` in body text stays literal. GFM for tables/task-lists.\n extensions: [mdxJsx(), gfm()],\n mdastExtensions: [mdxJsxFromMarkdown(), gfmFromMarkdown()],\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDA,IAAI,cAAoC;AAExC,SAAS,WAA0B;AACjC,MAAI,CAAC,aAAa;AAChB,kBAAc,QAAQ,IAAI;AAAA,MACxB,OAAO,0BAA0B;AAAA,MACjC,OAAO,6BAA6B;AAAA,MACpC,OAAO,oBAAoB;AAAA,MAC3B,OAAO,yBAAyB;AAAA,MAChC,OAAO,gBAAgB;AAAA,IACzB,CAAC,EAAE;AAAA,MACD,CAAC,CAAC,QAAQ,WAAW,aAAa,QAAQ,QAAQ,OAC/C;AAAA,QACC,cAAe,OAA6D;AAAA,QAC5E,QAAS,UAAoD;AAAA,QAC7D,oBAAqB,YAClB;AAAA,QACH,KAAM,OAA2C;AAAA,QACjD,iBAAkB,SAAqE;AAAA,MACzF;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;AAQA,eAAsB,eAAe,QAAwC;AAC3E,QAAM,EAAE,cAAc,QAAQ,oBAAoB,KAAK,gBAAgB,IAAI,MAAM,SAAS;AAC1F,SAAO,aAAa,QAAQ;AAAA;AAAA;AAAA;AAAA,IAI1B,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,IAC5B,iBAAiB,CAAC,mBAAmB,GAAG,gBAAgB,CAAC;AAAA,EAC3D,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface SafeMdastNode {
|
|
2
|
+
type: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
name?: string | null;
|
|
5
|
+
url?: string;
|
|
6
|
+
alt?: string | null;
|
|
7
|
+
title?: string | null;
|
|
8
|
+
depth?: number;
|
|
9
|
+
ordered?: boolean;
|
|
10
|
+
lang?: string | null;
|
|
11
|
+
children?: SafeMdastNode[];
|
|
12
|
+
attributes?: SafeMdxAttribute[];
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface SafeMdxAttribute {
|
|
16
|
+
type: 'mdxJsxAttribute' | 'mdxJsxExpressionAttribute';
|
|
17
|
+
name?: string;
|
|
18
|
+
value?: string | {
|
|
19
|
+
type: string;
|
|
20
|
+
value?: string;
|
|
21
|
+
} | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse untrusted Markdown/MDX-syntax source to an mdast tree with **no evaluator in
|
|
25
|
+
* the pipeline**: JSX-as-data (no acorn), GFM on, the expression extension OFF, no
|
|
26
|
+
* raw-HTML re-parse. The returned tree is safe to hand to `renderMdast` — expression
|
|
27
|
+
* attributes are inert strings and raw HTML is inert `html` nodes.
|
|
28
|
+
*/
|
|
29
|
+
declare function parseSafeMdast(source: string): Promise<SafeMdastNode>;
|
|
30
|
+
|
|
31
|
+
export { type SafeMdastNode, type SafeMdxAttribute, parseSafeMdast };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface SafeMdastNode {
|
|
2
|
+
type: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
name?: string | null;
|
|
5
|
+
url?: string;
|
|
6
|
+
alt?: string | null;
|
|
7
|
+
title?: string | null;
|
|
8
|
+
depth?: number;
|
|
9
|
+
ordered?: boolean;
|
|
10
|
+
lang?: string | null;
|
|
11
|
+
children?: SafeMdastNode[];
|
|
12
|
+
attributes?: SafeMdxAttribute[];
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface SafeMdxAttribute {
|
|
16
|
+
type: 'mdxJsxAttribute' | 'mdxJsxExpressionAttribute';
|
|
17
|
+
name?: string;
|
|
18
|
+
value?: string | {
|
|
19
|
+
type: string;
|
|
20
|
+
value?: string;
|
|
21
|
+
} | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse untrusted Markdown/MDX-syntax source to an mdast tree with **no evaluator in
|
|
25
|
+
* the pipeline**: JSX-as-data (no acorn), GFM on, the expression extension OFF, no
|
|
26
|
+
* raw-HTML re-parse. The returned tree is safe to hand to `renderMdast` — expression
|
|
27
|
+
* attributes are inert strings and raw HTML is inert `html` nodes.
|
|
28
|
+
*/
|
|
29
|
+
declare function parseSafeMdast(source: string): Promise<SafeMdastNode>;
|
|
30
|
+
|
|
31
|
+
export { type SafeMdastNode, type SafeMdxAttribute, parseSafeMdast };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
let depsPromise = null;
|
|
2
|
+
function loadDeps() {
|
|
3
|
+
if (!depsPromise) {
|
|
4
|
+
depsPromise = Promise.all([
|
|
5
|
+
import("mdast-util-from-markdown"),
|
|
6
|
+
import("micromark-extension-mdx-jsx"),
|
|
7
|
+
import("mdast-util-mdx-jsx"),
|
|
8
|
+
import("micromark-extension-gfm"),
|
|
9
|
+
import("mdast-util-gfm")
|
|
10
|
+
]).then(
|
|
11
|
+
([fromMd, mdxJsxExt, mdxJsxMdast, gfmExt, gfmMdast]) => ({
|
|
12
|
+
fromMarkdown: fromMd.fromMarkdown,
|
|
13
|
+
mdxJsx: mdxJsxExt.mdxJsx,
|
|
14
|
+
mdxJsxFromMarkdown: mdxJsxMdast.mdxJsxFromMarkdown,
|
|
15
|
+
gfm: gfmExt.gfm,
|
|
16
|
+
gfmFromMarkdown: gfmMdast.gfmFromMarkdown
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return depsPromise;
|
|
21
|
+
}
|
|
22
|
+
async function parseSafeMdast(source) {
|
|
23
|
+
const { fromMarkdown, mdxJsx, mdxJsxFromMarkdown, gfm, gfmFromMarkdown } = await loadDeps();
|
|
24
|
+
return fromMarkdown(source, {
|
|
25
|
+
// `mdxJsx()` WITHOUT an acorn option → JSX tags + literal attrs; expressions are
|
|
26
|
+
// raw strings, never estree. The mdx *expression* extension is intentionally
|
|
27
|
+
// absent, so `{…}` in body text stays literal. GFM for tables/task-lists.
|
|
28
|
+
extensions: [mdxJsx(), gfm()],
|
|
29
|
+
mdastExtensions: [mdxJsxFromMarkdown(), gfmFromMarkdown()]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
parseSafeMdast
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=parseSafeMdast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/safeContent/parseSafeMdast.ts"],"sourcesContent":["// The no-acorn parse pipeline for the safe content renderer (TRUST_MODES_SPEC §5.1,\n// empirically verified 2026-07-07 against `@mdx-js/mdx` v3 / `micromark-extension-\n// mdx-jsx`). This is the load-bearing half of the fail-safe: `<Component/>` syntax\n// parses to an element node with **literal** attributes, and every expression\n// (`n={1+1}`, `f={fetch(\"/x\")}`, `{...spread}`) is captured as an **inert raw string\n// with no estree** — because we pass **NO acorn option** to `micromark-extension-mdx-\n// jsx`. There is therefore no evaluator anywhere in the pipeline (fail-safe), unlike\n// `@mdx-js/mdx`'s `compile({format:'mdx'})` which always wires acorn.\n//\n// The §5.1 residual guarantees are also here: the expression micromark extension is\n// **not** enabled (body `{…}` stays literal text), and **no `rehype-raw`** / raw-HTML\n// passthrough exists — raw HTML blocks arrive as inert `html` mdast nodes the renderer\n// prints as text, never injected.\n//\n// `micromark`/`mdast` are ESM-only. They are loaded with a memoised dynamic `import()`\n// (the transpiler's `compile.ts` pattern) so this module sits in the package's CJS\n// build too — a CJS consumer that never renders untrusted content never `require()`s\n// an ESM-only package, and one that does gets it via Node's ESM-from-CJS import. The\n// dynamic load changes only *when* the deps resolve, never the produced tree.\n\n// A minimal structural mdast shape — we deliberately avoid a type dependency on the\n// ESM-only `mdast`/`unist` packages (which would break the CJS build's type surface).\nexport interface SafeMdastNode {\n type: string;\n value?: string;\n name?: string | null;\n url?: string;\n alt?: string | null;\n title?: string | null;\n depth?: number;\n ordered?: boolean;\n lang?: string | null;\n children?: SafeMdastNode[];\n attributes?: SafeMdxAttribute[];\n [key: string]: unknown;\n}\n\nexport interface SafeMdxAttribute {\n type: 'mdxJsxAttribute' | 'mdxJsxExpressionAttribute';\n name?: string;\n // A literal attribute carries a string; an expression attribute carries an\n // `mdxJsxAttributeValueExpression` object (a raw string, NO estree) or a string.\n value?: string | { type: string; value?: string } | null;\n}\n\ntype Deps = {\n fromMarkdown: (\n value: string,\n options: { extensions: unknown[]; mdastExtensions: unknown[] },\n ) => SafeMdastNode;\n mdxJsx: () => unknown;\n mdxJsxFromMarkdown: () => unknown;\n gfm: () => unknown;\n gfmFromMarkdown: () => unknown;\n};\n\nlet depsPromise: Promise<Deps> | null = null;\n\nfunction loadDeps(): Promise<Deps> {\n if (!depsPromise) {\n depsPromise = Promise.all([\n import('mdast-util-from-markdown'),\n import('micromark-extension-mdx-jsx'),\n import('mdast-util-mdx-jsx'),\n import('micromark-extension-gfm'),\n import('mdast-util-gfm'),\n ]).then(\n ([fromMd, mdxJsxExt, mdxJsxMdast, gfmExt, gfmMdast]) =>\n ({\n fromMarkdown: (fromMd as unknown as { fromMarkdown: Deps['fromMarkdown'] }).fromMarkdown,\n mdxJsx: (mdxJsxExt as unknown as { mdxJsx: Deps['mdxJsx'] }).mdxJsx,\n mdxJsxFromMarkdown: (mdxJsxMdast as unknown as { mdxJsxFromMarkdown: Deps['mdxJsxFromMarkdown'] })\n .mdxJsxFromMarkdown,\n gfm: (gfmExt as unknown as { gfm: Deps['gfm'] }).gfm,\n gfmFromMarkdown: (gfmMdast as unknown as { gfmFromMarkdown: Deps['gfmFromMarkdown'] }).gfmFromMarkdown,\n }) as Deps,\n );\n }\n return depsPromise;\n}\n\n/**\n * Parse untrusted Markdown/MDX-syntax source to an mdast tree with **no evaluator in\n * the pipeline**: JSX-as-data (no acorn), GFM on, the expression extension OFF, no\n * raw-HTML re-parse. The returned tree is safe to hand to `renderMdast` — expression\n * attributes are inert strings and raw HTML is inert `html` nodes.\n */\nexport async function parseSafeMdast(source: string): Promise<SafeMdastNode> {\n const { fromMarkdown, mdxJsx, mdxJsxFromMarkdown, gfm, gfmFromMarkdown } = await loadDeps();\n return fromMarkdown(source, {\n // `mdxJsx()` WITHOUT an acorn option → JSX tags + literal attrs; expressions are\n // raw strings, never estree. The mdx *expression* extension is intentionally\n // absent, so `{…}` in body text stays literal. GFM for tables/task-lists.\n extensions: [mdxJsx(), gfm()],\n mdastExtensions: [mdxJsxFromMarkdown(), gfmFromMarkdown()],\n });\n}\n"],"mappings":"AAwDA,IAAI,cAAoC;AAExC,SAAS,WAA0B;AACjC,MAAI,CAAC,aAAa;AAChB,kBAAc,QAAQ,IAAI;AAAA,MACxB,OAAO,0BAA0B;AAAA,MACjC,OAAO,6BAA6B;AAAA,MACpC,OAAO,oBAAoB;AAAA,MAC3B,OAAO,yBAAyB;AAAA,MAChC,OAAO,gBAAgB;AAAA,IACzB,CAAC,EAAE;AAAA,MACD,CAAC,CAAC,QAAQ,WAAW,aAAa,QAAQ,QAAQ,OAC/C;AAAA,QACC,cAAe,OAA6D;AAAA,QAC5E,QAAS,UAAoD;AAAA,QAC7D,oBAAqB,YAClB;AAAA,QACH,KAAM,OAA2C;AAAA,QACjD,iBAAkB,SAAqE;AAAA,MACzF;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;AAQA,eAAsB,eAAe,QAAwC;AAC3E,QAAM,EAAE,cAAc,QAAQ,oBAAoB,KAAK,gBAAgB,IAAI,MAAM,SAAS;AAC1F,SAAO,aAAa,QAAQ;AAAA;AAAA;AAAA;AAAA,IAI1B,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,IAC5B,iBAAiB,CAAC,mBAAmB,GAAG,gBAAgB,CAAC;AAAA,EAC3D,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var renderMdast_exports = {};
|
|
20
|
+
__export(renderMdast_exports, {
|
|
21
|
+
renderMdast: () => renderMdast
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(renderMdast_exports);
|
|
24
|
+
var import_react = require("react");
|
|
25
|
+
var import_sanitizeUrl = require("./sanitizeUrl");
|
|
26
|
+
var import_wikilink = require("./wikilink");
|
|
27
|
+
function literalProps(attributes) {
|
|
28
|
+
const props = {};
|
|
29
|
+
for (const attr of attributes ?? []) {
|
|
30
|
+
if (attr.type !== "mdxJsxAttribute") continue;
|
|
31
|
+
if (typeof attr.name !== "string") continue;
|
|
32
|
+
if (typeof attr.value === "string") props[attr.name] = attr.value;
|
|
33
|
+
else if (attr.value === null || attr.value === void 0) props[attr.name] = "";
|
|
34
|
+
}
|
|
35
|
+
return props;
|
|
36
|
+
}
|
|
37
|
+
let keyCounter = 0;
|
|
38
|
+
const nextKey = () => `sc-${keyCounter++}`;
|
|
39
|
+
function renderWiki(token, resolve) {
|
|
40
|
+
const label = token.label ?? token.target;
|
|
41
|
+
const href = resolve?.(token.target);
|
|
42
|
+
const safe = href !== void 0 ? (0, import_sanitizeUrl.sanitizeUrl)(href) : void 0;
|
|
43
|
+
if (safe === void 0) return label;
|
|
44
|
+
return (0, import_react.createElement)("a", { href: safe, "data-wikilink": token.target, key: nextKey() }, label);
|
|
45
|
+
}
|
|
46
|
+
function renderText(value, opts) {
|
|
47
|
+
const parts = (0, import_wikilink.splitWikiLinks)(value);
|
|
48
|
+
if (!parts) return value;
|
|
49
|
+
return parts.map(
|
|
50
|
+
(p, i) => "text" in p ? (0, import_react.createElement)(import_react.Fragment, { key: `t${i}` }, p.text) : (0, import_react.createElement)(import_react.Fragment, { key: `w${i}` }, renderWiki(p.wiki, opts.resolveWikiLink))
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function renderChildren(node, opts) {
|
|
54
|
+
return (node.children ?? []).map((c, i) => renderNode(c, opts, i));
|
|
55
|
+
}
|
|
56
|
+
const HEADING_TAGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
57
|
+
function renderNode(node, opts, index = 0) {
|
|
58
|
+
const key = `n${index}`;
|
|
59
|
+
switch (node.type) {
|
|
60
|
+
case "root":
|
|
61
|
+
return (0, import_react.createElement)(import_react.Fragment, { key }, ...renderChildren(node, opts));
|
|
62
|
+
case "text":
|
|
63
|
+
return renderText(node.value ?? "", opts);
|
|
64
|
+
case "paragraph":
|
|
65
|
+
return (0, import_react.createElement)("p", { key }, ...renderChildren(node, opts));
|
|
66
|
+
case "heading": {
|
|
67
|
+
const tag = HEADING_TAGS[Math.min(Math.max((node.depth ?? 1) - 1, 0), 5)];
|
|
68
|
+
return (0, import_react.createElement)(tag, { key }, ...renderChildren(node, opts));
|
|
69
|
+
}
|
|
70
|
+
case "strong":
|
|
71
|
+
return (0, import_react.createElement)("strong", { key }, ...renderChildren(node, opts));
|
|
72
|
+
case "emphasis":
|
|
73
|
+
return (0, import_react.createElement)("em", { key }, ...renderChildren(node, opts));
|
|
74
|
+
case "delete":
|
|
75
|
+
return (0, import_react.createElement)("del", { key }, ...renderChildren(node, opts));
|
|
76
|
+
case "inlineCode":
|
|
77
|
+
return (0, import_react.createElement)("code", { key }, node.value ?? "");
|
|
78
|
+
case "code":
|
|
79
|
+
return (0, import_react.createElement)("pre", { key }, (0, import_react.createElement)("code", null, node.value ?? ""));
|
|
80
|
+
case "blockquote":
|
|
81
|
+
return (0, import_react.createElement)("blockquote", { key }, ...renderChildren(node, opts));
|
|
82
|
+
case "list":
|
|
83
|
+
return (0, import_react.createElement)(node.ordered ? "ol" : "ul", { key }, ...renderChildren(node, opts));
|
|
84
|
+
case "listItem":
|
|
85
|
+
return (0, import_react.createElement)("li", { key }, ...renderChildren(node, opts));
|
|
86
|
+
case "thematicBreak":
|
|
87
|
+
return (0, import_react.createElement)("hr", { key });
|
|
88
|
+
case "break":
|
|
89
|
+
return (0, import_react.createElement)("br", { key });
|
|
90
|
+
case "link": {
|
|
91
|
+
const href = (0, import_sanitizeUrl.sanitizeUrl)(node.url);
|
|
92
|
+
if (href === void 0) return (0, import_react.createElement)(import_react.Fragment, { key }, ...renderChildren(node, opts));
|
|
93
|
+
return (0, import_react.createElement)("a", { key, href, title: node.title ?? void 0 }, ...renderChildren(node, opts));
|
|
94
|
+
}
|
|
95
|
+
case "image": {
|
|
96
|
+
const src = (0, import_sanitizeUrl.sanitizeUrl)(node.url);
|
|
97
|
+
if (src === void 0) return node.alt ? (0, import_react.createElement)(import_react.Fragment, { key }, node.alt) : null;
|
|
98
|
+
return (0, import_react.createElement)("img", { key, src, alt: node.alt ?? "", title: node.title ?? void 0 });
|
|
99
|
+
}
|
|
100
|
+
// GFM tables.
|
|
101
|
+
case "table":
|
|
102
|
+
return (0, import_react.createElement)("table", { key }, (0, import_react.createElement)("tbody", null, ...renderChildren(node, opts)));
|
|
103
|
+
case "tableRow":
|
|
104
|
+
return (0, import_react.createElement)("tr", { key }, ...renderChildren(node, opts));
|
|
105
|
+
case "tableCell":
|
|
106
|
+
return (0, import_react.createElement)("td", { key }, ...renderChildren(node, opts));
|
|
107
|
+
// Raw HTML (`<script>`, `<div onclick>` at block level) → INERT TEXT. No
|
|
108
|
+
// `rehype-raw`, never `dangerouslySetInnerHTML`. The literal markup is shown, not run.
|
|
109
|
+
case "html":
|
|
110
|
+
return (0, import_react.createElement)(import_react.Fragment, { key }, node.value ?? "");
|
|
111
|
+
// JSX `<Component/>` syntax → registry lookup by NAME, literal props only.
|
|
112
|
+
case "mdxJsxFlowElement":
|
|
113
|
+
case "mdxJsxTextElement": {
|
|
114
|
+
const name = typeof node.name === "string" ? node.name : "";
|
|
115
|
+
const Component = name ? opts.components?.[name] : void 0;
|
|
116
|
+
const children = renderChildren(node, opts);
|
|
117
|
+
if (!Component) return (0, import_react.createElement)(import_react.Fragment, { key }, ...children);
|
|
118
|
+
return (0, import_react.createElement)(Component, { key, ...literalProps(node.attributes) }, ...children);
|
|
119
|
+
}
|
|
120
|
+
// Inert expression nodes (should not occur — expression extension is off — but be
|
|
121
|
+
// defensive if a tree from elsewhere carries them): render nothing.
|
|
122
|
+
case "mdxFlowExpression":
|
|
123
|
+
case "mdxTextExpression":
|
|
124
|
+
case "mdxjsEsm":
|
|
125
|
+
return null;
|
|
126
|
+
default:
|
|
127
|
+
return node.children ? (0, import_react.createElement)(import_react.Fragment, { key }, ...renderChildren(node, opts)) : null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function renderMdast(tree, options = {}) {
|
|
131
|
+
keyCounter = 0;
|
|
132
|
+
return renderNode(tree, options);
|
|
133
|
+
}
|
|
134
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
135
|
+
0 && (module.exports = {
|
|
136
|
+
renderMdast
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=renderMdast.cjs.map
|