@toaq-oss/omni-mdx 0.1.1 → 0.1.2

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.
@@ -0,0 +1,56 @@
1
+ import React, { JSX } from 'react';
2
+
3
+ /**
4
+ * MDXServerRenderer.tsx
5
+ *
6
+ * React Server Component — renders an MDX AST on the server.
7
+ * No "use client" — safe for Next.js SSR, SSG, and ISR.
8
+ *
9
+ * Drop-in replacement for <MDXRemote source={...} components={MDX_COMPONENTS} />
10
+ *
11
+ * Usage in a Server Component (page.tsx):
12
+ *
13
+ * import { MDXServerRenderer, parseMdx } from '@toaq/omni-mdx/server';
14
+ * import { MDX_COMPONENTS } from './MDXComponents';
15
+ *
16
+ * export default async function Page() {
17
+ * const ast = await parseMdx(mdxString);
18
+ * return <MDXServerRenderer ast={ast} components={MDX_COMPONENTS} />;
19
+ * }
20
+ */
21
+
22
+ type AttrValueKind = {
23
+ kind: "text";
24
+ value: string;
25
+ } | {
26
+ kind: "expression";
27
+ value: string;
28
+ } | {
29
+ kind: "boolean";
30
+ } | {
31
+ kind: "ast";
32
+ value: AstNode[];
33
+ };
34
+ interface AstNode {
35
+ node_type: string;
36
+ content?: string;
37
+ self_closing?: boolean;
38
+ attributes?: Record<string, AttrValueKind>;
39
+ children?: AstNode[];
40
+ }
41
+ type MDXComponents = Record<string, React.ComponentType<any>>;
42
+ interface MDXServerRendererProps {
43
+ /** AST produced by parseMdx() — JSON-serialisable. */
44
+ ast: AstNode[];
45
+ /**
46
+ * Component registry. Keys are JSX tag names (e.g. "Note", "Details").
47
+ * Values are React components (Server or Client).
48
+ *
49
+ * Server Components render on the server (recommended for static content).
50
+ * Client Components receive "use client" and hydrate in the browser.
51
+ */
52
+ components?: MDXComponents;
53
+ }
54
+ declare function MDXServerRenderer({ ast, components, }: MDXServerRendererProps): JSX.Element;
55
+
56
+ export { type AstNode as A, type MDXComponents as M, type AttrValueKind as a, MDXServerRenderer as b };
package/dist/client.cjs CHANGED
@@ -95,7 +95,7 @@ async function loadKatex() {
95
95
  katexLoaded = true;
96
96
  return renderMathInElement;
97
97
  } catch {
98
- console.warn("[toaq/mdx-engine] KaTeX not available. Install: npm install katex");
98
+ console.warn("[toaq-oss/omni-mdx] KaTeX not available. Install: npm install katex");
99
99
  return null;
100
100
  }
101
101
  }
@@ -230,7 +230,7 @@ function renderNode(node, index, components) {
230
230
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Tag, { ...resolvedProps, children: renderedChildren }, key);
231
231
  }
232
232
  if (true) {
233
- console.warn(`[toaq/mdx-engine] Unknown component: <${node.node_type}>`);
233
+ console.warn(`[toaq-oss/omni-mdx] Unknown component: <${node.node_type}>`);
234
234
  }
235
235
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-missing-component": node.node_type, className: "mdx-missing-component", children: renderedChildren }, key);
236
236
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/MDXClientRenderer.tsx","../src/MDXErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * @toaq/mdx-engine/client\n *\n * Client-only entry point.\n * Use for live MDX editors, previews, or any fully client-side rendering.\n */\n\nexport { MDXClientRenderer } from \"./MDXClientRenderer\";\nexport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nexport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";","\"use client\";\n\n/**\n * MDXClientRenderer.tsx\n *\n * Client Component — handles KaTeX hydration and interactive components.\n *\n * You generally do NOT use this directly.\n * Use <MDXServerRenderer> in Server Components and only register Client\n * Components (wrapped in \"use client\") for interactive parts (charts, tabs, etc.).\n *\n * Use this component ONLY when:\n * 1. You are in a page/layout that is entirely client-side (no RSC)\n * 2. You need live re-rendering (e.g. a live MDX editor/preview)\n *\n * For the live editor use case, import from '@toaq/mdx-engine/client'.\n */\n\nimport React, { ReactNode, createContext, useContext, useEffect, useRef } from \"react\";\nimport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nimport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";\n\n// KaTeX loader (client-only, dynamic import)\n\nlet katexLoaded = false;\n\nasync function loadKatex() {\n if (katexLoaded || typeof window === \"undefined\") return;\n try {\n // Dynamically import KaTeX auto-render (avoids SSR issues)\n const [{ default: katex }, autoRenderMod] = await Promise.all([\n import(\"katex\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n import(\"katex/contrib/auto-render\") as any,\n ]);\n const renderMathInElement = autoRenderMod.default ?? autoRenderMod;\n katexLoaded = true;\n return renderMathInElement;\n } catch {\n console.warn(\"[toaq/mdx-engine] KaTeX not available. Install: npm install katex\");\n return null;\n }\n}\n\n// Attr resolver (client version handles expressions fully)\n\ntype AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\": return attr.value;\n case \"boolean\": return true;\n case \"expression\": {\n const raw = attr.value.trim();\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n case \"ast\":\n return <MDXClientContent ast={attr.value} components={components} />;\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"article\",\"aside\",\"b\",\"blockquote\",\"br\",\"caption\",\"cite\",\"code\",\n \"col\",\"colgroup\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\n \"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\n \"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\"p\",\"pre\",\"q\",\"s\",\"section\",\"small\",\"span\",\n \"strong\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"tr\",\n \"u\",\"ul\",\"var\",\n]);\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") return node.content ?? null;\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {node.children?.map((c, i) => renderNode(c, i, components))}\n </React.Fragment>\n );\n }\n\n // Math — rendered as semantic spans; KaTeX hydrates them via useEffect\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v as AttrValueKind, components);\n }\n }\n\n const renderedChildren = node.children?.length\n ? node.children.map((c, i) => renderNode(c, i, components))\n : (node.content ?? undefined);\n\n const Custom = components[node.node_type];\n if (Custom) {\n return (\n <MDXErrorBoundary key={key} componentName={node.node_type}>\n <Custom {...resolvedProps}>\n {renderedChildren}\n </Custom>\n </MDXErrorBoundary>\n );\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as any;\n return <Tag key={key} {...resolvedProps}>{renderedChildren}</Tag>;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(`[toaq/mdx-engine] Unknown component: <${node.node_type}>`);\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction MDXClientContent({\n ast,\n components,\n}: {\n ast: AstNode[];\n components: MDXComponents;\n}) {\n return <>{ast.map((node, i) => renderNode(node, i, components))}</>;\n}\n\ninterface MDXClientRendererProps {\n /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */\n ast: AstNode[];\n /** Component registry — same shape as MDX_COMPONENTS. */\n components?: MDXComponents;\n /** If true, activates KaTeX auto-render after mount. Default: true. */\n katex?: boolean;\n}\n\nexport function MDXClientRenderer({\n ast,\n components = {},\n katex = true,\n}: MDXClientRendererProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Hydrate math after mount\n useEffect(() => {\n if (!katex || !rootRef.current) return;\n loadKatex().then((renderMath) => {\n if (!renderMath || !rootRef.current) return;\n renderMath(rootRef.current, {\n delimiters: [\n { left: \"$$\", right: \"$$\", display: true },\n { left: \"$\", right: \"$\", display: false },\n ],\n });\n // Also handle data-math attributes directly\n rootRef.current.querySelectorAll<HTMLElement>(\"[data-math]\").forEach((el) => {\n const math = el.getAttribute(\"data-math\") ?? \"\";\n const display = el.classList.contains(\"math-display\");\n try {\n import(\"katex\").then(({ default: k }) => {\n el.innerHTML = k.renderToString(math, { displayMode: display, throwOnError: false });\n });\n } catch {}\n });\n });\n }, [ast, katex]);\n\n if (!ast || !Array.isArray(ast)) return null;\n\n return (\n <div ref={rootRef} className=\"omni-mdx-root\">\n <MDXClientContent ast={ast} components={components} />\n </div>\n );\n}","\"use client\";\nimport { Component, ErrorInfo, ReactNode } from 'react';\n\ninterface Props {\n children: ReactNode;\n /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */\n componentName?: string;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * A dedicated Error Boundary for MDX rendering.\n *\n * If a React component injected via MDX crashes (e.g., due to a data parsing error \n * inside a <Chart />), this boundary intercepts the error. This prevents the \n * entire React tree from unmounting and displays a clean fallback UI to \n * isolate the defective component.\n */\nexport class MDXErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * Updates the state when an error occurs to trigger the fallback UI rendering.\n */\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n /**\n * Intercepts the error and its contextual information.\n * This is the ideal place to hook into monitoring tools (like Sentry or Datadog) \n * for production environments.\n */\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\n `[MDXErrorBoundary] Error caught in component <${this.props.componentName || 'Unknown'}>:\\n`,\n error,\n errorInfo.componentStack\n );\n }\n \n render() {\n if (this.state.hasError) {\n // Fallback UI: A clean, isolated container that doesn't break the main layout\n return (\n <div style={{ padding: '1rem', border: '2px solid #ef4444', backgroundColor: '#fef2f2', borderRadius: '0.5rem', margin: '1rem 0' }}>\n <h3 style={{ color: '#b91c1c', fontWeight: 'bold', margin: 0 }}>\n Render Error : {this.props.componentName || 'Unknown Component'}\n </h3>\n <p style={{ color: '#dc2626', fontFamily: 'monospace', fontSize: '0.875rem' }}>\n {this.state.error?.message}\n </p>\n </div>\n );\n }\n return this.props.children;\n }\n}"],"mappings":"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","names":["import_react","import_jsx_runtime","React"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/MDXClientRenderer.tsx","../src/MDXErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * @toaq/omni-mdx/client\n *\n * Client-only entry point.\n * Use for live MDX editors, previews, or any fully client-side rendering.\n */\n\nexport { MDXClientRenderer } from \"./MDXClientRenderer\";\nexport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nexport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";","\"use client\";\n\n/**\n * MDXClientRenderer.tsx\n *\n * Client Component — handles KaTeX hydration and interactive components.\n *\n * You generally do NOT use this directly.\n * Use <MDXServerRenderer> in Server Components and only register Client\n * Components (wrapped in \"use client\") for interactive parts (charts, tabs, etc.).\n *\n * Use this component ONLY when:\n * 1. You are in a page/layout that is entirely client-side (no RSC)\n * 2. You need live re-rendering (e.g. a live MDX editor/preview)\n *\n * For the live editor use case, import from '@toaq/omni-mdx/client'.\n */\n\nimport React, { ReactNode, createContext, useContext, useEffect, useRef } from \"react\";\nimport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nimport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";\n\n// KaTeX loader (client-only, dynamic import)\n\nlet katexLoaded = false;\n\nasync function loadKatex() {\n if (katexLoaded || typeof window === \"undefined\") return;\n try {\n // Dynamically import KaTeX auto-render (avoids SSR issues)\n const [{ default: katex }, autoRenderMod] = await Promise.all([\n import(\"katex\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n import(\"katex/contrib/auto-render\") as any,\n ]);\n const renderMathInElement = autoRenderMod.default ?? autoRenderMod;\n katexLoaded = true;\n return renderMathInElement;\n } catch {\n console.warn(\"[toaq-oss/omni-mdx] KaTeX not available. Install: npm install katex\");\n return null;\n }\n}\n\n// Attr resolver (client version handles expressions fully)\n\ntype AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\": return attr.value;\n case \"boolean\": return true;\n case \"expression\": {\n const raw = attr.value.trim();\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n case \"ast\":\n return <MDXClientContent ast={attr.value} components={components} />;\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"article\",\"aside\",\"b\",\"blockquote\",\"br\",\"caption\",\"cite\",\"code\",\n \"col\",\"colgroup\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\n \"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\n \"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\"p\",\"pre\",\"q\",\"s\",\"section\",\"small\",\"span\",\n \"strong\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"tr\",\n \"u\",\"ul\",\"var\",\n]);\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") return node.content ?? null;\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {node.children?.map((c, i) => renderNode(c, i, components))}\n </React.Fragment>\n );\n }\n\n // Math — rendered as semantic spans; KaTeX hydrates them via useEffect\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v as AttrValueKind, components);\n }\n }\n\n const renderedChildren = node.children?.length\n ? node.children.map((c, i) => renderNode(c, i, components))\n : (node.content ?? undefined);\n\n const Custom = components[node.node_type];\n if (Custom) {\n return (\n <MDXErrorBoundary key={key} componentName={node.node_type}>\n <Custom {...resolvedProps}>\n {renderedChildren}\n </Custom>\n </MDXErrorBoundary>\n );\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as any;\n return <Tag key={key} {...resolvedProps}>{renderedChildren}</Tag>;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(`[toaq-oss/omni-mdx] Unknown component: <${node.node_type}>`);\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction MDXClientContent({\n ast,\n components,\n}: {\n ast: AstNode[];\n components: MDXComponents;\n}) {\n return <>{ast.map((node, i) => renderNode(node, i, components))}</>;\n}\n\ninterface MDXClientRendererProps {\n /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */\n ast: AstNode[];\n /** Component registry — same shape as MDX_COMPONENTS. */\n components?: MDXComponents;\n /** If true, activates KaTeX auto-render after mount. Default: true. */\n katex?: boolean;\n}\n\nexport function MDXClientRenderer({\n ast,\n components = {},\n katex = true,\n}: MDXClientRendererProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Hydrate math after mount\n useEffect(() => {\n if (!katex || !rootRef.current) return;\n loadKatex().then((renderMath) => {\n if (!renderMath || !rootRef.current) return;\n renderMath(rootRef.current, {\n delimiters: [\n { left: \"$$\", right: \"$$\", display: true },\n { left: \"$\", right: \"$\", display: false },\n ],\n });\n // Also handle data-math attributes directly\n rootRef.current.querySelectorAll<HTMLElement>(\"[data-math]\").forEach((el) => {\n const math = el.getAttribute(\"data-math\") ?? \"\";\n const display = el.classList.contains(\"math-display\");\n try {\n import(\"katex\").then(({ default: k }) => {\n el.innerHTML = k.renderToString(math, { displayMode: display, throwOnError: false });\n });\n } catch {}\n });\n });\n }, [ast, katex]);\n\n if (!ast || !Array.isArray(ast)) return null;\n\n return (\n <div ref={rootRef} className=\"omni-mdx-root\">\n <MDXClientContent ast={ast} components={components} />\n </div>\n );\n}","\"use client\";\nimport { Component, ErrorInfo, ReactNode } from 'react';\n\ninterface Props {\n children: ReactNode;\n /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */\n componentName?: string;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * A dedicated Error Boundary for MDX rendering.\n *\n * If a React component injected via MDX crashes (e.g., due to a data parsing error \n * inside a <Chart />), this boundary intercepts the error. This prevents the \n * entire React tree from unmounting and displays a clean fallback UI to \n * isolate the defective component.\n */\nexport class MDXErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * Updates the state when an error occurs to trigger the fallback UI rendering.\n */\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n /**\n * Intercepts the error and its contextual information.\n * This is the ideal place to hook into monitoring tools (like Sentry or Datadog) \n * for production environments.\n */\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\n `[MDXErrorBoundary] Error caught in component <${this.props.componentName || 'Unknown'}>:\\n`,\n error,\n errorInfo.componentStack\n );\n }\n \n render() {\n if (this.state.hasError) {\n // Fallback UI: A clean, isolated container that doesn't break the main layout\n return (\n <div style={{ padding: '1rem', border: '2px solid #ef4444', backgroundColor: '#fef2f2', borderRadius: '0.5rem', margin: '1rem 0' }}>\n <h3 style={{ color: '#b91c1c', fontWeight: 'bold', margin: 0 }}>\n Render Error : {this.props.componentName || 'Unknown Component'}\n </h3>\n <p style={{ color: '#dc2626', fontFamily: 'monospace', fontSize: '0.875rem' }}>\n {this.state.error?.message}\n </p>\n </div>\n );\n }\n return this.props.children;\n }\n}"],"mappings":"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","names":["import_react","import_jsx_runtime","React"]}
@@ -0,0 +1,86 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
3
+
4
+ /**
5
+ * MDXServerRenderer.tsx
6
+ *
7
+ * React Server Component — renders an MDX AST on the server.
8
+ * No "use client" — safe for Next.js SSR, SSG, and ISR.
9
+ *
10
+ * Drop-in replacement for <MDXRemote source={...} components={MDX_COMPONENTS} />
11
+ *
12
+ * Usage in a Server Component (page.tsx):
13
+ *
14
+ * import { MDXServerRenderer, parseMdx } from '@toaq/omni-mdx/server';
15
+ * import { MDX_COMPONENTS } from './MDXComponents';
16
+ *
17
+ * export default async function Page() {
18
+ * const ast = await parseMdx(mdxString);
19
+ * return <MDXServerRenderer ast={ast} components={MDX_COMPONENTS} />;
20
+ * }
21
+ */
22
+
23
+ type AttrValueKind = {
24
+ kind: "text";
25
+ value: string;
26
+ } | {
27
+ kind: "expression";
28
+ value: string;
29
+ } | {
30
+ kind: "boolean";
31
+ } | {
32
+ kind: "ast";
33
+ value: AstNode[];
34
+ };
35
+ interface AstNode {
36
+ node_type: string;
37
+ content?: string;
38
+ self_closing?: boolean;
39
+ attributes?: Record<string, AttrValueKind>;
40
+ children?: AstNode[];
41
+ }
42
+ type MDXComponents = Record<string, React.ComponentType<any>>;
43
+
44
+ interface MDXClientRendererProps {
45
+ /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */
46
+ ast: AstNode[];
47
+ /** Component registry — same shape as MDX_COMPONENTS. */
48
+ components?: MDXComponents;
49
+ /** If true, activates KaTeX auto-render after mount. Default: true. */
50
+ katex?: boolean;
51
+ }
52
+ declare function MDXClientRenderer({ ast, components, katex, }: MDXClientRendererProps): react_jsx_runtime.JSX.Element | null;
53
+
54
+ interface Props {
55
+ children: ReactNode;
56
+ /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */
57
+ componentName?: string;
58
+ }
59
+ interface State {
60
+ hasError: boolean;
61
+ error: Error | null;
62
+ }
63
+ /**
64
+ * A dedicated Error Boundary for MDX rendering.
65
+ *
66
+ * If a React component injected via MDX crashes (e.g., due to a data parsing error
67
+ * inside a <Chart />), this boundary intercepts the error. This prevents the
68
+ * entire React tree from unmounting and displays a clean fallback UI to
69
+ * isolate the defective component.
70
+ */
71
+ declare class MDXErrorBoundary extends Component<Props, State> {
72
+ constructor(props: Props);
73
+ /**
74
+ * Updates the state when an error occurs to trigger the fallback UI rendering.
75
+ */
76
+ static getDerivedStateFromError(error: Error): State;
77
+ /**
78
+ * Intercepts the error and its contextual information.
79
+ * This is the ideal place to hook into monitoring tools (like Sentry or Datadog)
80
+ * for production environments.
81
+ */
82
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
83
+ render(): string | number | boolean | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
84
+ }
85
+
86
+ export { type AstNode, MDXClientRenderer, type MDXComponents, MDXErrorBoundary };
@@ -0,0 +1,86 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
3
+
4
+ /**
5
+ * MDXServerRenderer.tsx
6
+ *
7
+ * React Server Component — renders an MDX AST on the server.
8
+ * No "use client" — safe for Next.js SSR, SSG, and ISR.
9
+ *
10
+ * Drop-in replacement for <MDXRemote source={...} components={MDX_COMPONENTS} />
11
+ *
12
+ * Usage in a Server Component (page.tsx):
13
+ *
14
+ * import { MDXServerRenderer, parseMdx } from '@toaq/omni-mdx/server';
15
+ * import { MDX_COMPONENTS } from './MDXComponents';
16
+ *
17
+ * export default async function Page() {
18
+ * const ast = await parseMdx(mdxString);
19
+ * return <MDXServerRenderer ast={ast} components={MDX_COMPONENTS} />;
20
+ * }
21
+ */
22
+
23
+ type AttrValueKind = {
24
+ kind: "text";
25
+ value: string;
26
+ } | {
27
+ kind: "expression";
28
+ value: string;
29
+ } | {
30
+ kind: "boolean";
31
+ } | {
32
+ kind: "ast";
33
+ value: AstNode[];
34
+ };
35
+ interface AstNode {
36
+ node_type: string;
37
+ content?: string;
38
+ self_closing?: boolean;
39
+ attributes?: Record<string, AttrValueKind>;
40
+ children?: AstNode[];
41
+ }
42
+ type MDXComponents = Record<string, React.ComponentType<any>>;
43
+
44
+ interface MDXClientRendererProps {
45
+ /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */
46
+ ast: AstNode[];
47
+ /** Component registry — same shape as MDX_COMPONENTS. */
48
+ components?: MDXComponents;
49
+ /** If true, activates KaTeX auto-render after mount. Default: true. */
50
+ katex?: boolean;
51
+ }
52
+ declare function MDXClientRenderer({ ast, components, katex, }: MDXClientRendererProps): react_jsx_runtime.JSX.Element | null;
53
+
54
+ interface Props {
55
+ children: ReactNode;
56
+ /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */
57
+ componentName?: string;
58
+ }
59
+ interface State {
60
+ hasError: boolean;
61
+ error: Error | null;
62
+ }
63
+ /**
64
+ * A dedicated Error Boundary for MDX rendering.
65
+ *
66
+ * If a React component injected via MDX crashes (e.g., due to a data parsing error
67
+ * inside a <Chart />), this boundary intercepts the error. This prevents the
68
+ * entire React tree from unmounting and displays a clean fallback UI to
69
+ * isolate the defective component.
70
+ */
71
+ declare class MDXErrorBoundary extends Component<Props, State> {
72
+ constructor(props: Props);
73
+ /**
74
+ * Updates the state when an error occurs to trigger the fallback UI rendering.
75
+ */
76
+ static getDerivedStateFromError(error: Error): State;
77
+ /**
78
+ * Intercepts the error and its contextual information.
79
+ * This is the ideal place to hook into monitoring tools (like Sentry or Datadog)
80
+ * for production environments.
81
+ */
82
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
83
+ render(): string | number | boolean | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
84
+ }
85
+
86
+ export { type AstNode, MDXClientRenderer, type MDXComponents, MDXErrorBoundary };
package/dist/client.js CHANGED
@@ -59,7 +59,7 @@ async function loadKatex() {
59
59
  katexLoaded = true;
60
60
  return renderMathInElement;
61
61
  } catch {
62
- console.warn("[toaq/mdx-engine] KaTeX not available. Install: npm install katex");
62
+ console.warn("[toaq-oss/omni-mdx] KaTeX not available. Install: npm install katex");
63
63
  return null;
64
64
  }
65
65
  }
@@ -194,7 +194,7 @@ function renderNode(node, index, components) {
194
194
  return /* @__PURE__ */ jsx2(Tag, { ...resolvedProps, children: renderedChildren }, key);
195
195
  }
196
196
  if (true) {
197
- console.warn(`[toaq/mdx-engine] Unknown component: <${node.node_type}>`);
197
+ console.warn(`[toaq-oss/omni-mdx] Unknown component: <${node.node_type}>`);
198
198
  }
199
199
  return /* @__PURE__ */ jsx2("div", { "data-missing-component": node.node_type, className: "mdx-missing-component", children: renderedChildren }, key);
200
200
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MDXClientRenderer.tsx","../src/MDXErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * MDXClientRenderer.tsx\n *\n * Client Component — handles KaTeX hydration and interactive components.\n *\n * You generally do NOT use this directly.\n * Use <MDXServerRenderer> in Server Components and only register Client\n * Components (wrapped in \"use client\") for interactive parts (charts, tabs, etc.).\n *\n * Use this component ONLY when:\n * 1. You are in a page/layout that is entirely client-side (no RSC)\n * 2. You need live re-rendering (e.g. a live MDX editor/preview)\n *\n * For the live editor use case, import from '@toaq/mdx-engine/client'.\n */\n\nimport React, { ReactNode, createContext, useContext, useEffect, useRef } from \"react\";\nimport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nimport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";\n\n// KaTeX loader (client-only, dynamic import)\n\nlet katexLoaded = false;\n\nasync function loadKatex() {\n if (katexLoaded || typeof window === \"undefined\") return;\n try {\n // Dynamically import KaTeX auto-render (avoids SSR issues)\n const [{ default: katex }, autoRenderMod] = await Promise.all([\n import(\"katex\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n import(\"katex/contrib/auto-render\") as any,\n ]);\n const renderMathInElement = autoRenderMod.default ?? autoRenderMod;\n katexLoaded = true;\n return renderMathInElement;\n } catch {\n console.warn(\"[toaq/mdx-engine] KaTeX not available. Install: npm install katex\");\n return null;\n }\n}\n\n// Attr resolver (client version handles expressions fully)\n\ntype AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\": return attr.value;\n case \"boolean\": return true;\n case \"expression\": {\n const raw = attr.value.trim();\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n case \"ast\":\n return <MDXClientContent ast={attr.value} components={components} />;\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"article\",\"aside\",\"b\",\"blockquote\",\"br\",\"caption\",\"cite\",\"code\",\n \"col\",\"colgroup\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\n \"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\n \"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\"p\",\"pre\",\"q\",\"s\",\"section\",\"small\",\"span\",\n \"strong\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"tr\",\n \"u\",\"ul\",\"var\",\n]);\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") return node.content ?? null;\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {node.children?.map((c, i) => renderNode(c, i, components))}\n </React.Fragment>\n );\n }\n\n // Math — rendered as semantic spans; KaTeX hydrates them via useEffect\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v as AttrValueKind, components);\n }\n }\n\n const renderedChildren = node.children?.length\n ? node.children.map((c, i) => renderNode(c, i, components))\n : (node.content ?? undefined);\n\n const Custom = components[node.node_type];\n if (Custom) {\n return (\n <MDXErrorBoundary key={key} componentName={node.node_type}>\n <Custom {...resolvedProps}>\n {renderedChildren}\n </Custom>\n </MDXErrorBoundary>\n );\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as any;\n return <Tag key={key} {...resolvedProps}>{renderedChildren}</Tag>;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(`[toaq/mdx-engine] Unknown component: <${node.node_type}>`);\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction MDXClientContent({\n ast,\n components,\n}: {\n ast: AstNode[];\n components: MDXComponents;\n}) {\n return <>{ast.map((node, i) => renderNode(node, i, components))}</>;\n}\n\ninterface MDXClientRendererProps {\n /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */\n ast: AstNode[];\n /** Component registry — same shape as MDX_COMPONENTS. */\n components?: MDXComponents;\n /** If true, activates KaTeX auto-render after mount. Default: true. */\n katex?: boolean;\n}\n\nexport function MDXClientRenderer({\n ast,\n components = {},\n katex = true,\n}: MDXClientRendererProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Hydrate math after mount\n useEffect(() => {\n if (!katex || !rootRef.current) return;\n loadKatex().then((renderMath) => {\n if (!renderMath || !rootRef.current) return;\n renderMath(rootRef.current, {\n delimiters: [\n { left: \"$$\", right: \"$$\", display: true },\n { left: \"$\", right: \"$\", display: false },\n ],\n });\n // Also handle data-math attributes directly\n rootRef.current.querySelectorAll<HTMLElement>(\"[data-math]\").forEach((el) => {\n const math = el.getAttribute(\"data-math\") ?? \"\";\n const display = el.classList.contains(\"math-display\");\n try {\n import(\"katex\").then(({ default: k }) => {\n el.innerHTML = k.renderToString(math, { displayMode: display, throwOnError: false });\n });\n } catch {}\n });\n });\n }, [ast, katex]);\n\n if (!ast || !Array.isArray(ast)) return null;\n\n return (\n <div ref={rootRef} className=\"omni-mdx-root\">\n <MDXClientContent ast={ast} components={components} />\n </div>\n );\n}","\"use client\";\nimport { Component, ErrorInfo, ReactNode } from 'react';\n\ninterface Props {\n children: ReactNode;\n /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */\n componentName?: string;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * A dedicated Error Boundary for MDX rendering.\n *\n * If a React component injected via MDX crashes (e.g., due to a data parsing error \n * inside a <Chart />), this boundary intercepts the error. This prevents the \n * entire React tree from unmounting and displays a clean fallback UI to \n * isolate the defective component.\n */\nexport class MDXErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * Updates the state when an error occurs to trigger the fallback UI rendering.\n */\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n /**\n * Intercepts the error and its contextual information.\n * This is the ideal place to hook into monitoring tools (like Sentry or Datadog) \n * for production environments.\n */\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\n `[MDXErrorBoundary] Error caught in component <${this.props.componentName || 'Unknown'}>:\\n`,\n error,\n errorInfo.componentStack\n );\n }\n \n render() {\n if (this.state.hasError) {\n // Fallback UI: A clean, isolated container that doesn't break the main layout\n return (\n <div style={{ padding: '1rem', border: '2px solid #ef4444', backgroundColor: '#fef2f2', borderRadius: '0.5rem', margin: '1rem 0' }}>\n <h3 style={{ color: '#b91c1c', fontWeight: 'bold', margin: 0 }}>\n Render Error : {this.props.componentName || 'Unknown Component'}\n </h3>\n <p style={{ color: '#dc2626', fontFamily: 'monospace', fontSize: '0.875rem' }}>\n {this.state.error?.message}\n </p>\n </div>\n );\n }\n return this.props.children;\n }\n}"],"mappings":"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","names":["jsx"]}
1
+ {"version":3,"sources":["../src/MDXClientRenderer.tsx","../src/MDXErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * MDXClientRenderer.tsx\n *\n * Client Component — handles KaTeX hydration and interactive components.\n *\n * You generally do NOT use this directly.\n * Use <MDXServerRenderer> in Server Components and only register Client\n * Components (wrapped in \"use client\") for interactive parts (charts, tabs, etc.).\n *\n * Use this component ONLY when:\n * 1. You are in a page/layout that is entirely client-side (no RSC)\n * 2. You need live re-rendering (e.g. a live MDX editor/preview)\n *\n * For the live editor use case, import from '@toaq/omni-mdx/client'.\n */\n\nimport React, { ReactNode, createContext, useContext, useEffect, useRef } from \"react\";\nimport { MDXErrorBoundary } from \"./MDXErrorBoundary\";\nimport type { AstNode, MDXComponents } from \"./MDXServerRenderer\";\n\n// KaTeX loader (client-only, dynamic import)\n\nlet katexLoaded = false;\n\nasync function loadKatex() {\n if (katexLoaded || typeof window === \"undefined\") return;\n try {\n // Dynamically import KaTeX auto-render (avoids SSR issues)\n const [{ default: katex }, autoRenderMod] = await Promise.all([\n import(\"katex\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n import(\"katex/contrib/auto-render\") as any,\n ]);\n const renderMathInElement = autoRenderMod.default ?? autoRenderMod;\n katexLoaded = true;\n return renderMathInElement;\n } catch {\n console.warn(\"[toaq-oss/omni-mdx] KaTeX not available. Install: npm install katex\");\n return null;\n }\n}\n\n// Attr resolver (client version handles expressions fully)\n\ntype AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\": return attr.value;\n case \"boolean\": return true;\n case \"expression\": {\n const raw = attr.value.trim();\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n case \"ast\":\n return <MDXClientContent ast={attr.value} components={components} />;\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"article\",\"aside\",\"b\",\"blockquote\",\"br\",\"caption\",\"cite\",\"code\",\n \"col\",\"colgroup\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\n \"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\n \"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\"p\",\"pre\",\"q\",\"s\",\"section\",\"small\",\"span\",\n \"strong\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"tr\",\n \"u\",\"ul\",\"var\",\n]);\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") return node.content ?? null;\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {node.children?.map((c, i) => renderNode(c, i, components))}\n </React.Fragment>\n );\n }\n\n // Math — rendered as semantic spans; KaTeX hydrates them via useEffect\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v as AttrValueKind, components);\n }\n }\n\n const renderedChildren = node.children?.length\n ? node.children.map((c, i) => renderNode(c, i, components))\n : (node.content ?? undefined);\n\n const Custom = components[node.node_type];\n if (Custom) {\n return (\n <MDXErrorBoundary key={key} componentName={node.node_type}>\n <Custom {...resolvedProps}>\n {renderedChildren}\n </Custom>\n </MDXErrorBoundary>\n );\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as any;\n return <Tag key={key} {...resolvedProps}>{renderedChildren}</Tag>;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(`[toaq-oss/omni-mdx] Unknown component: <${node.node_type}>`);\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction MDXClientContent({\n ast,\n components,\n}: {\n ast: AstNode[];\n components: MDXComponents;\n}) {\n return <>{ast.map((node, i) => renderNode(node, i, components))}</>;\n}\n\ninterface MDXClientRendererProps {\n /** AST from parseMdx() — must be JSON-serialisable (pass via Server Component). */\n ast: AstNode[];\n /** Component registry — same shape as MDX_COMPONENTS. */\n components?: MDXComponents;\n /** If true, activates KaTeX auto-render after mount. Default: true. */\n katex?: boolean;\n}\n\nexport function MDXClientRenderer({\n ast,\n components = {},\n katex = true,\n}: MDXClientRendererProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Hydrate math after mount\n useEffect(() => {\n if (!katex || !rootRef.current) return;\n loadKatex().then((renderMath) => {\n if (!renderMath || !rootRef.current) return;\n renderMath(rootRef.current, {\n delimiters: [\n { left: \"$$\", right: \"$$\", display: true },\n { left: \"$\", right: \"$\", display: false },\n ],\n });\n // Also handle data-math attributes directly\n rootRef.current.querySelectorAll<HTMLElement>(\"[data-math]\").forEach((el) => {\n const math = el.getAttribute(\"data-math\") ?? \"\";\n const display = el.classList.contains(\"math-display\");\n try {\n import(\"katex\").then(({ default: k }) => {\n el.innerHTML = k.renderToString(math, { displayMode: display, throwOnError: false });\n });\n } catch {}\n });\n });\n }, [ast, katex]);\n\n if (!ast || !Array.isArray(ast)) return null;\n\n return (\n <div ref={rootRef} className=\"omni-mdx-root\">\n <MDXClientContent ast={ast} components={components} />\n </div>\n );\n}","\"use client\";\nimport { Component, ErrorInfo, ReactNode } from 'react';\n\ninterface Props {\n children: ReactNode;\n /** The name of the MDX component being rendered (e.g., 'Chart', 'SplitLayout') */\n componentName?: string;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * A dedicated Error Boundary for MDX rendering.\n *\n * If a React component injected via MDX crashes (e.g., due to a data parsing error \n * inside a <Chart />), this boundary intercepts the error. This prevents the \n * entire React tree from unmounting and displays a clean fallback UI to \n * isolate the defective component.\n */\nexport class MDXErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * Updates the state when an error occurs to trigger the fallback UI rendering.\n */\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n /**\n * Intercepts the error and its contextual information.\n * This is the ideal place to hook into monitoring tools (like Sentry or Datadog) \n * for production environments.\n */\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\n `[MDXErrorBoundary] Error caught in component <${this.props.componentName || 'Unknown'}>:\\n`,\n error,\n errorInfo.componentStack\n );\n }\n \n render() {\n if (this.state.hasError) {\n // Fallback UI: A clean, isolated container that doesn't break the main layout\n return (\n <div style={{ padding: '1rem', border: '2px solid #ef4444', backgroundColor: '#fef2f2', borderRadius: '0.5rem', margin: '1rem 0' }}>\n <h3 style={{ color: '#b91c1c', fontWeight: 'bold', margin: 0 }}>\n Render Error : {this.props.componentName || 'Unknown Component'}\n </h3>\n <p style={{ color: '#dc2626', fontFamily: 'monospace', fontSize: '0.875rem' }}>\n {this.state.error?.message}\n </p>\n </div>\n );\n }\n return this.props.children;\n }\n}"],"mappings":"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","names":["jsx"]}
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ export { A as AstNode, a as AttrValueKind, M as MDXComponents } from './MDXServerRenderer-BYhg7yHp.js';
3
+
4
+ /**
5
+ * Parses a stringified JSX property value into its native JavaScript type.
6
+ *
7
+ * Useful in custom components that receive props from the MDX AST —
8
+ * especially for expression attributes like `data={[1, 2, 3]}` or `config={{ a: 1 }}`.
9
+ *
10
+ * @param propValue - Raw property value from the Rust AST (may be a string representation)
11
+ * @returns Parsed JS value — object, array, boolean, number, or original string as fallback
12
+ */
13
+ declare const parseProps: (propValue: any) => any;
14
+
15
+ /**
16
+ * @toaq/omni-mdx
17
+ *
18
+ * Safe entry point — types only; no server/native/wasm imports.
19
+ * To parse and render, use:
20
+ * import { parseMdx, MDXServerRenderer } from '@toaq/omni-mdx/server'
21
+ * import { MDXClientRenderer } from '@toaq/omni-mdx/client'
22
+ */
23
+
24
+ declare const MDX_COMPONENTS: Record<string, React.ComponentType<any>>;
25
+
26
+ export { MDX_COMPONENTS, parseProps };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/parserHelpers.ts","../src/index.ts"],"sourcesContent":["/**\n * Parses a stringified JSX property value into its native JavaScript type.\n *\n * Useful in custom components that receive props from the MDX AST —\n * especially for expression attributes like `data={[1, 2, 3]}` or `config={{ a: 1 }}`.\n *\n * @param propValue - Raw property value from the Rust AST (may be a string representation)\n * @returns Parsed JS value — object, array, boolean, number, or original string as fallback\n */\nexport const parseProps = (propValue: any): any => {\n if (typeof propValue !== \"string\") return propValue;\n \n const cleanVal = propValue.trim();\n \n // Primitives\n if (cleanVal === \"true\") return true;\n if (cleanVal === \"false\") return false;\n if (cleanVal !== \"\" && !isNaN(Number(cleanVal))) return Number(cleanVal);\n \n // Unwrap double JSX braces: {{ a: 1 }} → { a: 1 }\n let val = cleanVal;\n if (val.startsWith(\"{\") && val.endsWith(\"}\")) {\n const inner = val.slice(1, -1).trim();\n if (\n (inner.startsWith(\"[\") && inner.endsWith(\"]\")) ||\n (inner.startsWith(\"{\") && inner.endsWith(\"}\"))\n ) {\n val = inner;\n }\n }\n \n // Evaluate arrays and objects (relaxed JS syntax, not strict JSON)\n if (\n (val.startsWith(\"[\") && val.endsWith(\"]\")) ||\n (val.startsWith(\"{\") && val.endsWith(\"}\"))\n ) {\n try {\n return new Function(`return ${val}`)();\n } catch {\n return propValue;\n }\n }\n \n return propValue;\n};\n ","/**\n * @toaq/mdx-engine\n *\n * Safe entry point — types only; no server/native/wasm imports.\n * To parse and render, use:\n * import { parseMdx, MDXServerRenderer } from '@toaq/mdx-engine/server'\n * import { MDXClientRenderer } from '@toaq/mdx-engine/client'\n */\n\nimport React from \"react\";\n\n// Types only (no runtime imports)\nexport type { AstNode, AttrValueKind, MDXComponents } from \"./MDXServerRenderer\";\n\n// Component registry (empty by default; to be expanded)\nexport const MDX_COMPONENTS: Record<string, React.ComponentType<any>> = {};\n\n// Utility for parsing props in custom components\nexport { parseProps } from \"./utils/parserHelpers\";"],"mappings":";AASO,IAAM,aAAa,CAAC,cAAwB;AACjD,MAAI,OAAO,cAAc,SAAU,QAAO;AAE1C,QAAM,WAAW,UAAU,KAAK;AAGhC,MAAI,aAAa,OAAS,QAAO;AACjC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,aAAa,MAAM,CAAC,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO,OAAO,QAAQ;AAGvE,MAAI,MAAM;AACV,MAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC5C,UAAM,QAAQ,IAAI,MAAM,GAAG,EAAE,EAAE,KAAK;AACpC,QACG,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC5C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAGA,MACG,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KACvC,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GACxC;AACA,QAAI;AACF,aAAO,IAAI,SAAS,UAAU,GAAG,EAAE,EAAE;AAAA,IACvC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AC7BO,IAAM,iBAA2D,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/utils/parserHelpers.ts","../src/index.ts"],"sourcesContent":["/**\n * Parses a stringified JSX property value into its native JavaScript type.\n *\n * Useful in custom components that receive props from the MDX AST —\n * especially for expression attributes like `data={[1, 2, 3]}` or `config={{ a: 1 }}`.\n *\n * @param propValue - Raw property value from the Rust AST (may be a string representation)\n * @returns Parsed JS value — object, array, boolean, number, or original string as fallback\n */\nexport const parseProps = (propValue: any): any => {\n if (typeof propValue !== \"string\") return propValue;\n \n const cleanVal = propValue.trim();\n \n // Primitives\n if (cleanVal === \"true\") return true;\n if (cleanVal === \"false\") return false;\n if (cleanVal !== \"\" && !isNaN(Number(cleanVal))) return Number(cleanVal);\n \n // Unwrap double JSX braces: {{ a: 1 }} → { a: 1 }\n let val = cleanVal;\n if (val.startsWith(\"{\") && val.endsWith(\"}\")) {\n const inner = val.slice(1, -1).trim();\n if (\n (inner.startsWith(\"[\") && inner.endsWith(\"]\")) ||\n (inner.startsWith(\"{\") && inner.endsWith(\"}\"))\n ) {\n val = inner;\n }\n }\n \n // Evaluate arrays and objects (relaxed JS syntax, not strict JSON)\n if (\n (val.startsWith(\"[\") && val.endsWith(\"]\")) ||\n (val.startsWith(\"{\") && val.endsWith(\"}\"))\n ) {\n try {\n return new Function(`return ${val}`)();\n } catch {\n return propValue;\n }\n }\n \n return propValue;\n};\n ","/**\n * @toaq/omni-mdx\n *\n * Safe entry point — types only; no server/native/wasm imports.\n * To parse and render, use:\n * import { parseMdx, MDXServerRenderer } from '@toaq/omni-mdx/server'\n * import { MDXClientRenderer } from '@toaq/omni-mdx/client'\n */\n\nimport React from \"react\";\n\n// Types only (no runtime imports)\nexport type { AstNode, AttrValueKind, MDXComponents } from \"./MDXServerRenderer\";\n\n// Component registry (empty by default; to be expanded)\nexport const MDX_COMPONENTS: Record<string, React.ComponentType<any>> = {};\n\n// Utility for parsing props in custom components\nexport { parseProps } from \"./utils/parserHelpers\";"],"mappings":";AASO,IAAM,aAAa,CAAC,cAAwB;AACjD,MAAI,OAAO,cAAc,SAAU,QAAO;AAE1C,QAAM,WAAW,UAAU,KAAK;AAGhC,MAAI,aAAa,OAAS,QAAO;AACjC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,aAAa,MAAM,CAAC,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO,OAAO,QAAQ;AAGvE,MAAI,MAAM;AACV,MAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC5C,UAAM,QAAQ,IAAI,MAAM,GAAG,EAAE,EAAE,KAAK;AACpC,QACG,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC5C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAGA,MACG,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KACvC,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GACxC;AACA,QAAI;AACF,aAAO,IAAI,SAAS,UAAU,GAAG,EAAE,EAAE;AAAA,IACvC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AC7BO,IAAM,iBAA2D,CAAC;","names":[]}
@@ -0,0 +1,12 @@
1
+ import { A as AstNode } from './MDXServerRenderer-BYhg7yHp.js';
2
+ export { a as AttrValueKind, M as MDXComponents, b as MDXServerRenderer } from './MDXServerRenderer-BYhg7yHp.js';
3
+ import 'react';
4
+
5
+ declare function parseMdx(mdx: string): Promise<AstNode[]>;
6
+ declare function parseMdxSync(mdx: string): AstNode[];
7
+ declare class MDXParseError extends Error {
8
+ readonly source: string;
9
+ constructor(message: string, source: string);
10
+ }
11
+
12
+ export { AstNode, MDXParseError, parseMdx, parseMdxSync };
package/dist/server.js CHANGED
@@ -8,10 +8,10 @@ var _parse = null;
8
8
  async function getParser() {
9
9
  if (_parse) return _parse;
10
10
  const platformPackages = [
11
- "@toaq-oss/mdx-engine-darwin-arm64",
12
- "@toaq-oss/mdx-engine-darwin-x64",
13
- "@toaq-oss/mdx-engine-linux-x64-gnu",
14
- "@toaq-oss/mdx-engine-win32-x64-msvc"
11
+ "@toaq-oss/omni-mdx-darwin-arm64",
12
+ "@toaq-oss/omni-mdx-darwin-x64",
13
+ "@toaq-oss/omni-mdx-linux-x64-gnu",
14
+ "@toaq-oss/omni-mdx-win32-x64-msvc"
15
15
  ];
16
16
  for (const pkg of platformPackages) {
17
17
  try {
@@ -43,19 +43,12 @@ async function getParser() {
43
43
  } catch {
44
44
  }
45
45
  throw new Error(
46
- `[toaq-oss/mdx-engine] Native parser not found for this platform.
46
+ `[toaq-oss/omni-mdx] Native parser not found for this platform.
47
47
  Tried npm packages: ${platformPackages.join(", ")}
48
- Tried local native/ directory \u2014 no matching .node file found
49
-
50
- \u279C Build the native addon:
51
- cd core-parser
52
- napi build --platform --release --features node --no-js
53
- cp toaq-parser-core.*.node ../packages/mdx-next/native/
54
-
55
- \u279C Or install the prebuilt package (once published):
56
- npm install @toaq-oss/mdx-engine-darwin-arm64 # Mac M1/M2
57
- npm install @toaq-oss/mdx-engine-linux-x64-gnu # Linux/Vercel
58
- npm install @toaq-oss/mdx-engine-win32-x64-msvc # Windows
48
+ \u279C Install the prebuilt package (once published):
49
+ npm install @toaq-oss/omni-mdx-darwin-arm64 # Mac M1/M2
50
+ npm install @toaq-oss/omni-mdx-linux-x64-gnu # Linux/Vercel
51
+ npm install @toaq-oss/omni-mdx-win32-x64-msvc # Windows
59
52
  `
60
53
  );
61
54
  }
@@ -70,11 +63,11 @@ async function parseMdx(mdx) {
70
63
  try {
71
64
  return JSON.parse(json);
72
65
  } catch {
73
- throw new Error("[toaq-oss/mdx-engine] Parser returned invalid JSON.");
66
+ throw new Error("[toaq-oss/omni-mdx] Parser returned invalid JSON.");
74
67
  }
75
68
  }
76
69
  function parseMdxSync(mdx) {
77
- if (!_parse) throw new Error("[toaq-oss/mdx-engine] parseMdxSync() called before init.");
70
+ if (!_parse) throw new Error("[toaq-oss/omni-mdx] parseMdxSync() called before init.");
78
71
  try {
79
72
  return JSON.parse(_parse(mdx));
80
73
  } catch (err) {
@@ -243,7 +236,7 @@ function renderNode(node, index, components) {
243
236
  return /* @__PURE__ */ jsx(Custom, { ...resolvedProps, children: renderedChildren }, key);
244
237
  } catch (err) {
245
238
  if (process.env.NODE_ENV === "development") {
246
- console.error(`[toaq/mdx-engine] Server render failed for <${node.node_type}>:`, err);
239
+ console.error(`[toaq-oss/omni-mdx] Server render failed for <${node.node_type}>:`, err);
247
240
  }
248
241
  return /* @__PURE__ */ jsxs(
249
242
  "div",
@@ -288,7 +281,7 @@ function renderNode(node, index, components) {
288
281
  }
289
282
  if (process.env.NODE_ENV === "development") {
290
283
  console.warn(
291
- `[toaq/mdx-engine] Unknown component: <${node.node_type}>. Register it via MDX_COMPONENTS or add it to your components prop.`
284
+ `[toaq-oss/omni-mdx]Unknown component: <${node.node_type}>. Register it via MDX_COMPONENTS or add it to your components prop.`
292
285
  );
293
286
  }
294
287
  return /* @__PURE__ */ jsx("div", { "data-missing-component": node.node_type, className: "mdx-missing-component", children: renderedChildren }, key);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parse.server.ts","../src/MDXServerRenderer.tsx"],"sourcesContent":["import type { AstNode } from \"./MDXServerRenderer\";\nimport { createRequire } from \"module\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, resolve } from \"path\";\n\ndeclare const __non_webpack_require__: NodeRequire | undefined;\n\nconst _require = createRequire(import.meta.url);\nconst nativeRequire: NodeRequire =\n typeof __non_webpack_require__ !== \"undefined\"\n ? __non_webpack_require__\n : _require;\n\nlet _parse: ((mdx: string) => string) | null = null;\n\nasync function getParser(): Promise<(mdx: string) => string> {\n if (_parse) return _parse;\n\n // ── 1. Sous-packages npm (prod, optionalDependencies) ─────────────────────\n const platformPackages = [\n \"@toaq-oss/mdx-engine-darwin-arm64\",\n \"@toaq-oss/mdx-engine-darwin-x64\",\n \"@toaq-oss/mdx-engine-linux-x64-gnu\",\n \"@toaq-oss/mdx-engine-win32-x64-msvc\",\n ];\n\n for (const pkg of platformPackages) {\n try {\n const native = nativeRequire(pkg);\n if (typeof native.parse === \"function\") {\n _parse = native.parse;\n return _parse!;\n }\n } catch { /* non installé sur cette plateforme */ }\n }\n\n // ── 2. Fallback local — native/ dans le package (dev / monorepo) ──────────\n try {\n const __dir = dirname(fileURLToPath(import.meta.url));\n const nativeDir = resolve(__dir, \"../native\");\n const fs = nativeRequire(\"fs\") as typeof import(\"fs\");\n\n if (fs.existsSync(nativeDir)) {\n const files = fs.readdirSync(nativeDir).filter((f: string) => f.endsWith(\".node\"));\n const platform = process.platform ?? \"\";\n const arch = process.arch ?? \"\";\n const match = files.find((f: string) => f.includes(platform) && f.includes(arch))\n ?? files[0];\n\n if (match) {\n const native = nativeRequire(resolve(nativeDir, match));\n if (typeof native.parse === \"function\") {\n _parse = native.parse;\n return _parse!;\n }\n }\n }\n } catch { /* native/ absent */ }\n\n throw new Error(\n `[toaq-oss/mdx-engine] Native parser not found for this platform.\\n` +\n ` Tried npm packages: ${platformPackages.join(\", \")}\\n` +\n ` Tried local native/ directory — no matching .node file found\\n\\n` +\n ` ➜ Build the native addon:\\n` +\n ` cd core-parser\\n` +\n ` napi build --platform --release --features node --no-js\\n` +\n ` cp toaq-parser-core.*.node ../packages/mdx-next/native/\\n\\n` +\n ` ➜ Or install the prebuilt package (once published):\\n` +\n ` npm install @toaq-oss/mdx-engine-darwin-arm64 # Mac M1/M2\\n` +\n ` npm install @toaq-oss/mdx-engine-linux-x64-gnu # Linux/Vercel\\n` +\n ` npm install @toaq-oss/mdx-engine-win32-x64-msvc # Windows\\n`\n );\n}\n\nexport async function parseMdx(mdx: string): Promise<AstNode[]> {\n const parse = await getParser();\n let json: string;\n try {\n json = parse(mdx);\n } catch (err: any) {\n throw new MDXParseError(err?.message ?? String(err), mdx);\n }\n try {\n return JSON.parse(json) as AstNode[];\n } catch {\n throw new Error(\"[toaq-oss/mdx-engine] Parser returned invalid JSON.\");\n }\n}\n\nexport function parseMdxSync(mdx: string): AstNode[] {\n if (!_parse) throw new Error(\"[toaq-oss/mdx-engine] parseMdxSync() called before init.\");\n try {\n return JSON.parse(_parse(mdx)) as AstNode[];\n } catch (err: any) {\n throw new MDXParseError(err?.message ?? String(err), mdx);\n }\n}\n\nexport class MDXParseError extends Error {\n readonly source: string;\n constructor(message: string, source: string) {\n super(`MDX parse error: ${message}`);\n this.name = \"MDXParseError\";\n this.source = source;\n }\n}","/**\n * MDXServerRenderer.tsx\n *\n * React Server Component — renders an MDX AST on the server.\n * No \"use client\" — safe for Next.js SSR, SSG, and ISR.\n *\n * Drop-in replacement for <MDXRemote source={...} components={MDX_COMPONENTS} />\n *\n * Usage in a Server Component (page.tsx):\n *\n * import { MDXServerRenderer, parseMdx } from '@toaq/mdx-engine/server';\n * import { MDX_COMPONENTS } from '@toaq/mdx-engine';\n *\n * export default async function Page() {\n * const ast = await parseMdx(mdxString);\n * return <MDXServerRenderer ast={ast} components={MDX_COMPONENTS} />;\n * }\n */\n\nimport React, { ReactNode, JSX } from \"react\";\n\n// AST types (mirror Rust output exactly)\n\nexport type AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nexport interface AstNode {\n node_type: string;\n content?: string;\n self_closing?: boolean;\n attributes?: Record<string, AttrValueKind>;\n children?: AstNode[];\n}\n\nexport type MDXComponents = Record<string, React.ComponentType<any>>;\n\n/**\n * Converts a raw AttrValueKind from the Rust AST into a React-usable prop value.\n * text → string\n * expression → attempt JSON/JS parse, fallback to string\n * boolean → true\n * ast → <MDXServerRenderer ast={...} components={...} />\n */\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\":\n return attr.value;\n\n case \"boolean\":\n return true;\n\n case \"expression\": {\n const raw = attr.value.trim();\n // Try JSON first (safe), then JS expression as last resort\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n\n case \"ast\":\n return (\n <MDXServerRenderer\n ast={attr.value}\n components={components}\n />\n );\n\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"address\",\"article\",\"aside\",\"b\",\"bdi\",\"bdo\",\"blockquote\",\"br\",\n \"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"data\",\"dd\",\"del\",\"details\",\"dfn\",\n \"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\n \"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\n \"p\",\"pre\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"section\",\"small\",\"span\",\"strong\",\n \"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"time\",\"tr\",\n \"u\",\"ul\",\"var\",\"wbr\",\n]);\n\nfunction extractText(node: AstNode): string {\n if (node.node_type === \"text\") return node.content ?? \"\";\n if (node.content) return node.content;\n return (node.children ?? []).map(extractText).join(\"\");\n}\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") {\n return node.content ?? null;\n }\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {renderChildren(node, components)}\n </React.Fragment>\n );\n }\n\n // Math — rendered server-side as semantic HTML\n // KaTeX processing happens via rehype-katex on the HTML output,\n // or the client component wraps these with react-katex if needed.\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n // Resolve props from AST attributes\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v, components);\n }\n }\n\n const renderedChildren = node.children && node.children.length > 0\n ? renderChildren(node, components)\n : (node.content ?? undefined);\n\n // Custom registered component\n const Custom = components[node.node_type];\n if (Custom) {\n try {\n return (\n <Custom key={key} {...resolvedProps}>\n {renderedChildren}\n </Custom>\n );\n } catch (err) {\n if (process.env.NODE_ENV === \"development\") {\n console.error(`[toaq/mdx-engine] Server render failed for <${node.node_type}>:`, err);\n }\n return (\n <div\n key={key}\n className=\"mdx-component-error\"\n data-component={node.node_type}\n style={{ padding: \"1rem\", border: \"2px solid #ef4444\", borderRadius: \"0.5rem\", margin: \"1rem 0\", background: \"#fef2f2\" }}\n >\n <strong style={{ color: \"#b91c1c\" }}>Render error: &lt;{node.node_type}&gt;</strong>\n {process.env.NODE_ENV === \"development\" && (\n <pre style={{ color: \"#dc2626\", fontSize: \"0.875rem\", marginTop: \"0.5rem\" }}>\n {String(err)}\n </pre>\n )}\n </div>\n );\n }\n }\n\n if (node.node_type === \"table\") {\n const firstChild = node.children?.[0];\n const hasThead = firstChild?.node_type === \"thead\";\n const theadNode = hasThead ? firstChild : null;\n const bodyRows = hasThead ? node.children!.slice(1) : node.children ?? [];\n\n const theadEl = theadNode ? (\n <thead key=\"thead\">\n <tr>\n {theadNode.children?.map((cell, i) =>\n renderNode({ ...cell, node_type: \"th\" }, i, components)\n )}\n </tr>\n </thead>\n ) : null;\n\n const tbodyEl = bodyRows.length > 0 ? (\n <tbody key=\"tbody\">\n {bodyRows.map((row, i) => renderNode(row, i, components))}\n </tbody>\n ) : null;\n\n return <table key={key} {...resolvedProps}>{theadEl}{tbodyEl}</table>;\n }\n\n if (node.node_type === \"pre\") {\n const rawText = extractText(node);\n return <pre key={key} {...resolvedProps}><code>{rawText}</code></pre>;\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as keyof JSX.IntrinsicElements;\n return (\n <Tag key={key} {...resolvedProps}>\n {renderedChildren}\n </Tag>\n );\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(\n `[toaq/mdx-engine] Unknown component: <${node.node_type}>. ` +\n `Register it via MDX_COMPONENTS or add it to your components prop.`\n );\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction renderChildren(node: AstNode, components: MDXComponents): ReactNode[] {\n if (!node.children?.length) return [];\n return node.children.map((child, i) => renderNode(child, i, components));\n}\n\ninterface MDXServerRendererProps {\n /** AST produced by parseMdx() — JSON-serialisable. */\n ast: AstNode[];\n /**\n * Component registry. Keys are JSX tag names (e.g. \"Note\", \"Details\").\n * Values are React components (Server or Client).\n *\n * Server Components render on the server (recommended for static content).\n * Client Components receive \"use client\" and hydrate in the browser.\n */\n components?: MDXComponents;\n}\n\nexport function MDXServerRenderer({\n ast,\n components = {},\n}: MDXServerRendererProps): JSX.Element {\n if (!ast || !Array.isArray(ast)) {\n return <></>;\n }\n\n return (\n <div className=\"omni-mdx-root\">\n {ast.map((node, i) => renderNode(node, i, components))}\n </div>\n );\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/parse.server.ts","../src/MDXServerRenderer.tsx"],"sourcesContent":["import type { AstNode } from \"./MDXServerRenderer\";\nimport { createRequire } from \"module\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, resolve } from \"path\";\n\ndeclare const __non_webpack_require__: NodeRequire | undefined;\n\nconst _require = createRequire(import.meta.url);\nconst nativeRequire: NodeRequire =\n typeof __non_webpack_require__ !== \"undefined\"\n ? __non_webpack_require__\n : _require;\n\nlet _parse: ((mdx: string) => string) | null = null;\n\nasync function getParser(): Promise<(mdx: string) => string> {\n if (_parse) return _parse;\n\n const platformPackages = [\n \"@toaq-oss/omni-mdx-darwin-arm64\",\n \"@toaq-oss/omni-mdx-darwin-x64\",\n \"@toaq-oss/omni-mdx-linux-x64-gnu\",\n \"@toaq-oss/omni-mdx-win32-x64-msvc\",\n ];\n\n for (const pkg of platformPackages) {\n try {\n const native = nativeRequire(pkg);\n if (typeof native.parse === \"function\") {\n _parse = native.parse;\n return _parse!;\n }\n } catch { /* not installed on this platform */ }\n }\n\n // Fallback local\n try {\n const __dir = dirname(fileURLToPath(import.meta.url));\n const nativeDir = resolve(__dir, \"../native\");\n const fs = nativeRequire(\"fs\") as typeof import(\"fs\");\n\n if (fs.existsSync(nativeDir)) {\n const files = fs.readdirSync(nativeDir).filter((f: string) => f.endsWith(\".node\"));\n const platform = process.platform ?? \"\";\n const arch = process.arch ?? \"\";\n const match = files.find((f: string) => f.includes(platform) && f.includes(arch))\n ?? files[0];\n\n if (match) {\n const native = nativeRequire(resolve(nativeDir, match));\n if (typeof native.parse === \"function\") {\n _parse = native.parse;\n return _parse!;\n }\n }\n }\n } catch { /* native/ absent */ }\n\n throw new Error(\n `[toaq-oss/omni-mdx] Native parser not found for this platform.\\n` +\n ` Tried npm packages: ${platformPackages.join(\", \")}\\n` +\n ` ➜ Install the prebuilt package (once published):\\n` +\n ` npm install @toaq-oss/omni-mdx-darwin-arm64 # Mac M1/M2\\n` +\n ` npm install @toaq-oss/omni-mdx-linux-x64-gnu # Linux/Vercel\\n` +\n ` npm install @toaq-oss/omni-mdx-win32-x64-msvc # Windows\\n`\n );\n}\n\nexport async function parseMdx(mdx: string): Promise<AstNode[]> {\n const parse = await getParser();\n let json: string;\n try {\n json = parse(mdx);\n } catch (err: any) {\n throw new MDXParseError(err?.message ?? String(err), mdx);\n }\n try {\n return JSON.parse(json) as AstNode[];\n } catch {\n throw new Error(\"[toaq-oss/omni-mdx] Parser returned invalid JSON.\");\n }\n}\n\nexport function parseMdxSync(mdx: string): AstNode[] {\n if (!_parse) throw new Error(\"[toaq-oss/omni-mdx] parseMdxSync() called before init.\");\n try {\n return JSON.parse(_parse(mdx)) as AstNode[];\n } catch (err: any) {\n throw new MDXParseError(err?.message ?? String(err), mdx);\n }\n}\n\nexport class MDXParseError extends Error {\n readonly source: string;\n constructor(message: string, source: string) {\n super(`MDX parse error: ${message}`);\n this.name = \"MDXParseError\";\n this.source = source;\n }\n}","/**\n * MDXServerRenderer.tsx\n *\n * React Server Component — renders an MDX AST on the server.\n * No \"use client\" — safe for Next.js SSR, SSG, and ISR.\n *\n * Drop-in replacement for <MDXRemote source={...} components={MDX_COMPONENTS} />\n *\n * Usage in a Server Component (page.tsx):\n *\n * import { MDXServerRenderer, parseMdx } from '@toaq/omni-mdx/server';\n * import { MDX_COMPONENTS } from './MDXComponents';\n *\n * export default async function Page() {\n * const ast = await parseMdx(mdxString);\n * return <MDXServerRenderer ast={ast} components={MDX_COMPONENTS} />;\n * }\n */\n\nimport React, { ReactNode, JSX } from \"react\";\n\n// AST types (mirror Rust output exactly)\n\nexport type AttrValueKind =\n | { kind: \"text\"; value: string }\n | { kind: \"expression\"; value: string }\n | { kind: \"boolean\" }\n | { kind: \"ast\"; value: AstNode[] };\n\nexport interface AstNode {\n node_type: string;\n content?: string;\n self_closing?: boolean;\n attributes?: Record<string, AttrValueKind>;\n children?: AstNode[];\n}\n\nexport type MDXComponents = Record<string, React.ComponentType<any>>;\n\n/**\n * Converts a raw AttrValueKind from the Rust AST into a React-usable prop value.\n * text → string\n * expression → attempt JSON/JS parse, fallback to string\n * boolean → true\n * ast → <MDXServerRenderer ast={...} components={...} />\n */\nfunction resolveAttr(\n attr: AttrValueKind,\n components: MDXComponents,\n): React.ReactNode | string | boolean {\n switch (attr.kind) {\n case \"text\":\n return attr.value;\n\n case \"boolean\":\n return true;\n\n case \"expression\": {\n const raw = attr.value.trim();\n // Try JSON first (safe), then JS expression as last resort\n try { return JSON.parse(raw); } catch {}\n try { return new Function(`return (${raw})`)(); } catch {}\n return raw;\n }\n\n case \"ast\":\n return (\n <MDXServerRenderer\n ast={attr.value}\n components={components}\n />\n );\n\n default:\n return undefined;\n }\n}\n\nconst HTML_TAGS = new Set([\n \"a\",\"abbr\",\"address\",\"article\",\"aside\",\"b\",\"bdi\",\"bdo\",\"blockquote\",\"br\",\n \"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"data\",\"dd\",\"del\",\"details\",\"dfn\",\n \"div\",\"dl\",\"dt\",\"em\",\"figcaption\",\"figure\",\"footer\",\"h1\",\"h2\",\"h3\",\"h4\",\n \"h5\",\"h6\",\"header\",\"hr\",\"i\",\"img\",\"ins\",\"kbd\",\"li\",\"main\",\"mark\",\"nav\",\"ol\",\n \"p\",\"pre\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"section\",\"small\",\"span\",\"strong\",\n \"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"tfoot\",\"th\",\"thead\",\"time\",\"tr\",\n \"u\",\"ul\",\"var\",\"wbr\",\n]);\n\nfunction extractText(node: AstNode): string {\n if (node.node_type === \"text\") return node.content ?? \"\";\n if (node.content) return node.content;\n return (node.children ?? []).map(extractText).join(\"\");\n}\n\nfunction renderNode(\n node: AstNode,\n index: number,\n components: MDXComponents,\n): ReactNode {\n const key = `${node.node_type}-${index}`;\n\n if (node.node_type === \"text\") {\n return node.content ?? null;\n }\n\n if (node.node_type === \"fragment\") {\n return (\n <React.Fragment key={key}>\n {renderChildren(node, components)}\n </React.Fragment>\n );\n }\n\n // Math — rendered server-side as semantic HTML\n // KaTeX processing happens via rehype-katex on the HTML output,\n // or the client component wraps these with react-katex if needed.\n if (node.node_type === \"InlineMath\") {\n return (\n <span\n key={key}\n className=\"math math-inline\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n if (node.node_type === \"BlockMath\") {\n return (\n <div\n key={key}\n className=\"math math-display\"\n data-math={node.content ?? \"\"}\n suppressHydrationWarning\n />\n );\n }\n\n // Resolve props from AST attributes\n const resolvedProps: Record<string, any> = {};\n if (node.attributes) {\n for (const [k, v] of Object.entries(node.attributes)) {\n resolvedProps[k] = resolveAttr(v, components);\n }\n }\n\n const renderedChildren = node.children && node.children.length > 0\n ? renderChildren(node, components)\n : (node.content ?? undefined);\n\n // Custom registered component\n const Custom = components[node.node_type];\n if (Custom) {\n try {\n return (\n <Custom key={key} {...resolvedProps}>\n {renderedChildren}\n </Custom>\n );\n } catch (err) {\n if (process.env.NODE_ENV === \"development\") {\n console.error(`[toaq-oss/omni-mdx] Server render failed for <${node.node_type}>:`, err);\n }\n return (\n <div\n key={key}\n className=\"mdx-component-error\"\n data-component={node.node_type}\n style={{ padding: \"1rem\", border: \"2px solid #ef4444\", borderRadius: \"0.5rem\", margin: \"1rem 0\", background: \"#fef2f2\" }}\n >\n <strong style={{ color: \"#b91c1c\" }}>Render error: &lt;{node.node_type}&gt;</strong>\n {process.env.NODE_ENV === \"development\" && (\n <pre style={{ color: \"#dc2626\", fontSize: \"0.875rem\", marginTop: \"0.5rem\" }}>\n {String(err)}\n </pre>\n )}\n </div>\n );\n }\n }\n\n if (node.node_type === \"table\") {\n const firstChild = node.children?.[0];\n const hasThead = firstChild?.node_type === \"thead\";\n const theadNode = hasThead ? firstChild : null;\n const bodyRows = hasThead ? node.children!.slice(1) : node.children ?? [];\n\n const theadEl = theadNode ? (\n <thead key=\"thead\">\n <tr>\n {theadNode.children?.map((cell, i) =>\n renderNode({ ...cell, node_type: \"th\" }, i, components)\n )}\n </tr>\n </thead>\n ) : null;\n\n const tbodyEl = bodyRows.length > 0 ? (\n <tbody key=\"tbody\">\n {bodyRows.map((row, i) => renderNode(row, i, components))}\n </tbody>\n ) : null;\n\n return <table key={key} {...resolvedProps}>{theadEl}{tbodyEl}</table>;\n }\n\n if (node.node_type === \"pre\") {\n const rawText = extractText(node);\n return <pre key={key} {...resolvedProps}><code>{rawText}</code></pre>;\n }\n\n if (HTML_TAGS.has(node.node_type)) {\n const Tag = node.node_type as keyof JSX.IntrinsicElements;\n return (\n <Tag key={key} {...resolvedProps}>\n {renderedChildren}\n </Tag>\n );\n }\n\n if (process.env.NODE_ENV === \"development\") {\n console.warn(\n `[toaq-oss/omni-mdx]Unknown component: <${node.node_type}>. ` +\n `Register it via MDX_COMPONENTS or add it to your components prop.`\n );\n }\n return (\n <div key={key} data-missing-component={node.node_type} className=\"mdx-missing-component\">\n {renderedChildren}\n </div>\n );\n}\n\nfunction renderChildren(node: AstNode, components: MDXComponents): ReactNode[] {\n if (!node.children?.length) return [];\n return node.children.map((child, i) => renderNode(child, i, components));\n}\n\ninterface MDXServerRendererProps {\n /** AST produced by parseMdx() — JSON-serialisable. */\n ast: AstNode[];\n /**\n * Component registry. Keys are JSX tag names (e.g. \"Note\", \"Details\").\n * Values are React components (Server or Client).\n *\n * Server Components render on the server (recommended for static content).\n * Client Components receive \"use client\" and hydrate in the browser.\n */\n components?: MDXComponents;\n}\n\nexport function MDXServerRenderer({\n ast,\n components = {},\n}: MDXServerRendererProps): JSX.Element {\n if (!ast || !Array.isArray(ast)) {\n return <></>;\n }\n\n return (\n <div className=\"omni-mdx-root\">\n {ast.map((node, i) => renderNode(node, i, components))}\n </div>\n );\n}"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,61 +1,61 @@
1
- {
2
- "name": "@toaq-oss/omni-mdx",
3
- "version": "0.1.1",
4
- "description": "MDX parser + renderer for Next.js \u2014 Rust core, RSC-compatible",
5
- "license": "MIT",
6
- "type": "module",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/TOAQ-oss/omni-mdx-core"
10
- },
11
- "exports": {
12
- ".": {
13
- "import": "./dist/index.js",
14
- "require": "./dist/index.cjs"
15
- },
16
- "./server": {
17
- "import": "./dist/server.js"
18
- },
19
- "./client": {
20
- "import": "./dist/client.js",
21
- "require": "./dist/client.cjs"
22
- },
23
- "./wasm": {
24
- "import": "./wasm/mdx_parser.js",
25
- "require": "./wasm/mdx_parser.js"
26
- }
27
- },
28
- "main": "./dist/index.cjs",
29
- "module": "./dist/index.js",
30
- "types": "./dist/index.d.ts",
31
- "files": [
32
- "dist",
33
- "wasm"
34
- ],
35
- "scripts": {
36
- "build": "tsup",
37
- "typecheck": "tsc --noEmit"
38
- },
39
- "optionalDependencies": {
40
- "@toaq-oss/omni-mdx-darwin-arm64": "0.1.0",
41
- "@toaq-oss/omni-mdx-darwin-x64": "0.1.0",
42
- "@toaq-oss/omni-mdx-linux-x64-gnu": "0.1.0",
43
- "@toaq-oss/omni-mdx-win32-x64-msvc": "0.1.0"
44
- },
45
- "peerDependencies": {
46
- "katex": ">=0.16.0",
47
- "react": ">=18.0.0"
48
- },
49
- "peerDependenciesMeta": {
50
- "katex": {
51
- "optional": true
52
- }
53
- },
54
- "devDependencies": {
55
- "@types/katex": "^0.16.0",
56
- "@types/node": "^25.5.0",
57
- "@types/react": "^18.0.0",
58
- "tsup": "^8.0.0",
59
- "typescript": "^5.0.0"
60
- }
1
+ {
2
+ "name": "@toaq-oss/omni-mdx",
3
+ "version": "0.1.2",
4
+ "description": "MDX parser + renderer for Next.js \u2014 Rust core, RSC-compatible",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/TOAQ-oss/omni-mdx-core"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ },
16
+ "./server": {
17
+ "import": "./dist/server.js"
18
+ },
19
+ "./client": {
20
+ "import": "./dist/client.js",
21
+ "require": "./dist/client.cjs"
22
+ },
23
+ "./wasm": {
24
+ "import": "./wasm/mdx_parser.js",
25
+ "require": "./wasm/mdx_parser.js"
26
+ }
27
+ },
28
+ "main": "./dist/index.cjs",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "files": [
32
+ "dist",
33
+ "wasm"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "typecheck": "tsc --noEmit"
38
+ },
39
+ "optionalDependencies": {
40
+ "@toaq-oss/omni-mdx-darwin-arm64": "0.1.1",
41
+ "@toaq-oss/omni-mdx-darwin-x64": "0.1.1",
42
+ "@toaq-oss/omni-mdx-linux-x64-gnu": "0.1.1",
43
+ "@toaq-oss/omni-mdx-win32-x64-msvc": "0.1.1"
44
+ },
45
+ "peerDependencies": {
46
+ "katex": ">=0.16.0",
47
+ "react": ">=18.0.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "katex": {
51
+ "optional": true
52
+ }
53
+ },
54
+ "devDependencies": {
55
+ "@types/katex": "^0.16.0",
56
+ "@types/node": "^25.5.0",
57
+ "@types/react": "^18.0.0",
58
+ "tsup": "^8.0.0",
59
+ "typescript": "^5.0.0"
60
+ }
61
61
  }
Binary file