@andesine/converters 0.8.0 → 0.9.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/CHANGELOG.md +12 -0
- package/README.md +3 -2
- package/dist/anchors.d.ts +1 -1
- package/dist/chunks/{adapter-Dtv1L37e.js → adapter-BFwSkezI.js} +3 -3
- package/dist/chunks/{adapter-Dtv1L37e.js.map → adapter-BFwSkezI.js.map} +1 -1
- package/dist/chunks/{core-DpOn10DI.js → core-BR6Qs_Gz.js} +10 -1
- package/dist/chunks/core-BR6Qs_Gz.js.map +1 -0
- package/dist/chunks/{decode-CmiiHK2G.js → decode-DmUqH-b-.js} +2 -2
- package/dist/chunks/{decode-CmiiHK2G.js.map → decode-DmUqH-b-.js.map} +1 -1
- package/dist/chunks/{types-DoSWxQAZ.d.ts → types-DQUKLAU7.d.ts} +3 -3
- package/dist/html.d.ts +1 -1
- package/dist/html.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/markdoc.d.ts +1 -1
- package/dist/markdoc.js +2 -2
- package/dist/markdown.d.ts +1 -1
- package/dist/markdown.js +2 -2
- package/dist/mdx.d.ts +1 -1
- package/dist/mdx.js +26 -2
- package/dist/mdx.js.map +1 -1
- package/dist/text.d.ts +1 -1
- package/dist/text.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/core-DpOn10DI.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
- Images without an asset are placeholders. They export with an empty URL (`![alt]()` in
|
|
6
|
+
Markdown, MDX, and Markdoc; `src=""` in HTML), and an empty URL imports as an image without an
|
|
7
|
+
asset. Neither `imageURL` nor `imageAssetID` is called for them; before, both conversions threw.
|
|
8
|
+
|
|
9
|
+
## 0.8.1
|
|
10
|
+
|
|
11
|
+
- MDX elements that stand alone, with nothing but other elements and whitespace on their lines,
|
|
12
|
+
import as blocks, e.g. one-line `<Step title="...">...</Step>`s in `<Steps>`. Their content
|
|
13
|
+
becomes a paragraph. Elements between text still need a custom handler.
|
|
14
|
+
|
|
3
15
|
## 0.8.0
|
|
4
16
|
|
|
5
17
|
- Code blocks keep an optional `title`: a fence's `title="..."` meta in Markdown and MDX, a
|
package/README.md
CHANGED
|
@@ -359,8 +359,9 @@ node boundaries can change without changing displayed content.
|
|
|
359
359
|
|
|
360
360
|
MDX supports block components with static JSON-compatible properties. Expressions
|
|
361
361
|
inside property values may contain literal arrays/objects, but no calls, variable
|
|
362
|
-
references, spreads, imports, exports, or executable code.
|
|
363
|
-
|
|
362
|
+
references, spreads, imports, exports, or executable code. Elements that stand alone
|
|
363
|
+
on their lines, e.g. one-line `<Step>`s in `<Steps>`, import as blocks. JSX between
|
|
364
|
+
text and JSX fragments require custom handlers. Markdoc variables/functions also require custom
|
|
364
365
|
handlers. No source is evaluated during conversion.
|
|
365
366
|
|
|
366
367
|
Mixed bullet/task lists import as task lists with unchecked plain items. Ordered
|
package/dist/anchors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as ConversionError, o as formatCodeMeta, u as textContent } from "./core-
|
|
2
|
-
import { t as decodeMarkdown } from "./decode-
|
|
1
|
+
import { i as ConversionError, o as formatCodeMeta, u as textContent } from "./core-BR6Qs_Gz.js";
|
|
2
|
+
import { t as decodeMarkdown } from "./decode-DmUqH-b-.js";
|
|
3
3
|
import { n as normalizeMarkdown, t as markdownStringifyOptions } from "./stringify-DdPaV2y4.js";
|
|
4
4
|
import { unified } from "unified";
|
|
5
5
|
import remarkParse from "remark-parse";
|
|
@@ -175,4 +175,4 @@ const createMarkdownAdapter = (mdx) => {
|
|
|
175
175
|
//#endregion
|
|
176
176
|
export { createMarkdownAdapter as t };
|
|
177
177
|
|
|
178
|
-
//# sourceMappingURL=adapter-
|
|
178
|
+
//# sourceMappingURL=adapter-BFwSkezI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-Dtv1L37e.js","names":[],"sources":["../../src/markdown/encode.ts","../../src/markdown/adapter.ts"],"sourcesContent":["import type {\n RootContent,\n PhrasingContent,\n BlockContent,\n ListContent,\n TableContent,\n RowContent\n} from \"mdast\";\nimport { ConversionError, formatCodeMeta, textContent } from \"../utils\";\nimport type { ContentMark, ContentNode, EncodeContext } from \"../types\";\n\nconst encodeMarkdown = async (\n node: ContentNode,\n context: EncodeContext<RootContent>\n): Promise<RootContent> => {\n const attrs = node.attrs || {};\n const children = await context.children(node);\n\n switch (node.type) {\n case \"text\":\n return { type: \"text\", value: node.text || \"\" };\n case \"paragraph\":\n return { type: \"paragraph\", children: children as PhrasingContent[] };\n case \"heading\":\n return {\n type: \"heading\",\n ...(context.anchor ? { data: { hProperties: { id: context.anchor } } } : {}),\n depth: Number(attrs.level || 1) as 1 | 2 | 3 | 4 | 5 | 6,\n children: children as PhrasingContent[]\n };\n case \"blockquote\":\n return { type: \"blockquote\", children: children as BlockContent[] };\n case \"bulletList\":\n case \"orderedList\":\n case \"taskList\":\n return {\n type: \"list\",\n ordered: node.type === \"orderedList\",\n ...(node.type === \"orderedList\" ? { start: Number(attrs.start || 1) } : {}),\n spread: false,\n children: children as ListContent[]\n };\n case \"listItem\":\n case \"taskItem\":\n return {\n type: \"listItem\",\n ...(node.type === \"taskItem\" ? { checked: Boolean(attrs.checked) } : {}),\n spread: false,\n children: children as BlockContent[]\n };\n case \"hardBreak\":\n return { type: \"break\" };\n case \"horizontalRule\":\n return { type: \"thematicBreak\" };\n case \"codeBlock\":\n return {\n type: \"code\",\n // Fence meta needs a language, so a titled block without one is plain text.\n lang:\n typeof attrs.language === \"string\" && attrs.language\n ? attrs.language\n : attrs.title\n ? \"text\"\n : null,\n meta: formatCodeMeta(attrs.title),\n value: textContent(node)\n };\n case \"image\":\n return {\n type: \"image\",\n url: await context.imageURL(node),\n alt: String(attrs.alt || \"\"),\n title: attrs.caption ? String(attrs.caption) : null\n };\n case \"table\":\n return { type: \"table\", children: children as TableContent[] };\n case \"tableRow\":\n return { type: \"tableRow\", children: children as RowContent[] };\n case \"tableCell\":\n case \"tableHeader\": {\n if (\n Number(attrs.colspan || 1) !== 1 ||\n Number(attrs.rowspan || 1) !== 1 ||\n children.some((child) => child.type !== \"paragraph\") ||\n children.length > 1\n ) {\n throw new ConversionError(\n \"Markdown tables require single-paragraph cells without spans\",\n context.path\n );\n }\n return {\n type: \"tableCell\",\n children: children.flatMap((child) => (child.type === \"paragraph\" ? child.children : []))\n };\n }\n default:\n throw new ConversionError(`Unsupported Markdown node: ${node.type}`, context.path);\n }\n};\nconst encodeMarkdownMark = (\n mark: ContentMark,\n children: RootContent[],\n context: EncodeContext<RootContent>\n): RootContent => {\n const content = children as PhrasingContent[];\n\n switch (mark.type) {\n case \"bold\":\n return { type: \"strong\", children: content };\n case \"italic\":\n return { type: \"emphasis\", children: content };\n case \"strike\":\n return { type: \"delete\", children: content };\n case \"link\":\n return { type: \"link\", url: String(mark.attrs?.href || \"\"), title: null, children: content };\n case \"code\": {\n if (children.some((node) => node.type !== \"text\"))\n throw new ConversionError(\"Code marks must wrap plain text\", context.path);\n\n return {\n type: \"inlineCode\",\n value: children.map((node) => (node.type === \"text\" ? node.value : \"\")).join(\"\")\n };\n }\n default:\n throw new ConversionError(`Unsupported Markdown mark: ${mark.type}`, context.path);\n }\n};\n\nexport { encodeMarkdown, encodeMarkdownMark };\n","import { unified, type Plugin } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkStringify from \"remark-stringify\";\nimport remarkGFM from \"remark-gfm\";\nimport type { Definition, PhrasingContent, Root, RootContent } from \"mdast\";\nimport { encodeMarkdown, encodeMarkdownMark } from \"./encode\";\nimport { decodeMarkdown, type MarkdownNode } from \"./decode\";\nimport { normalizeMarkdown } from \"./normalize\";\nimport { markdownStringifyOptions } from \"./stringify\";\nimport { ConversionError } from \"../utils\";\nimport type { FormatAdapter } from \"../types\";\n\nconst createMarkdownAdapter = (mdx?: Plugin): FormatAdapter<MarkdownNode> => {\n const processor = unified()\n .use(remarkParse)\n .use(remarkGFM)\n .use(remarkStringify, markdownStringifyOptions);\n\n if (mdx) processor.use(mdx);\n\n const marks: Record<string, string> = {\n strong: \"bold\",\n emphasis: \"italic\",\n delete: \"strike\",\n inlineCode: \"code\",\n link: \"link\"\n };\n\n return {\n name: mdx ? \"MDX\" : \"Markdown\",\n frontmatter: true,\n type: (node) => node.type,\n markName: (node) => marks[node.type],\n root: (children) => ({\n type: \"root\",\n children: children.map((node) =>\n node.type === \"image\" ? { type: \"paragraph\", children: [node] } : node\n ) as RootContent[]\n }),\n parse(source) {\n const root = processor.parse(source);\n const definitions = new Map<string, Definition>();\n const collectDefinitions = (node: MarkdownNode): void => {\n if (node.type === \"definition\") {\n const identifier = node.identifier.toUpperCase();\n\n if (!definitions.has(identifier)) definitions.set(identifier, node);\n }\n\n if (\"children\" in node) node.children.forEach(collectDefinitions);\n };\n const resolve = (node: MarkdownNode): MarkdownNode => {\n if (node.type === \"linkReference\" || node.type === \"imageReference\") {\n const definition = definitions.get(node.identifier.toUpperCase());\n\n if (!definition)\n throw new ConversionError(`Missing Markdown definition: ${node.identifier}`);\n if (node.type === \"imageReference\")\n return { type: \"image\", url: definition.url, title: definition.title, alt: node.alt };\n\n return {\n type: \"link\",\n url: definition.url,\n title: definition.title,\n children: node.children.map(resolve) as PhrasingContent[]\n };\n }\n if (\"children\" in node)\n return { ...node, children: node.children.map(resolve) } as MarkdownNode;\n\n return node;\n };\n collectDefinitions(root);\n return resolve(root);\n },\n stringify: (root) => processor.stringify(normalizeMarkdown(root as Root)),\n encode: (node, context) =>\n encodeMarkdown(node, context as Parameters<typeof encodeMarkdown>[1]),\n mark: (mark, children, context) =>\n encodeMarkdownMark(\n mark,\n children as RootContent[],\n context as Parameters<typeof encodeMarkdownMark>[2]\n ),\n decode: decodeMarkdown\n };\n};\n\nexport { createMarkdownAdapter };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapter-BFwSkezI.js","names":[],"sources":["../../src/markdown/encode.ts","../../src/markdown/adapter.ts"],"sourcesContent":["import type {\n RootContent,\n PhrasingContent,\n BlockContent,\n ListContent,\n TableContent,\n RowContent\n} from \"mdast\";\nimport { ConversionError, formatCodeMeta, textContent } from \"../utils\";\nimport type { ContentMark, ContentNode, EncodeContext } from \"../types\";\n\nconst encodeMarkdown = async (\n node: ContentNode,\n context: EncodeContext<RootContent>\n): Promise<RootContent> => {\n const attrs = node.attrs || {};\n const children = await context.children(node);\n\n switch (node.type) {\n case \"text\":\n return { type: \"text\", value: node.text || \"\" };\n case \"paragraph\":\n return { type: \"paragraph\", children: children as PhrasingContent[] };\n case \"heading\":\n return {\n type: \"heading\",\n ...(context.anchor ? { data: { hProperties: { id: context.anchor } } } : {}),\n depth: Number(attrs.level || 1) as 1 | 2 | 3 | 4 | 5 | 6,\n children: children as PhrasingContent[]\n };\n case \"blockquote\":\n return { type: \"blockquote\", children: children as BlockContent[] };\n case \"bulletList\":\n case \"orderedList\":\n case \"taskList\":\n return {\n type: \"list\",\n ordered: node.type === \"orderedList\",\n ...(node.type === \"orderedList\" ? { start: Number(attrs.start || 1) } : {}),\n spread: false,\n children: children as ListContent[]\n };\n case \"listItem\":\n case \"taskItem\":\n return {\n type: \"listItem\",\n ...(node.type === \"taskItem\" ? { checked: Boolean(attrs.checked) } : {}),\n spread: false,\n children: children as BlockContent[]\n };\n case \"hardBreak\":\n return { type: \"break\" };\n case \"horizontalRule\":\n return { type: \"thematicBreak\" };\n case \"codeBlock\":\n return {\n type: \"code\",\n // Fence meta needs a language, so a titled block without one is plain text.\n lang:\n typeof attrs.language === \"string\" && attrs.language\n ? attrs.language\n : attrs.title\n ? \"text\"\n : null,\n meta: formatCodeMeta(attrs.title),\n value: textContent(node)\n };\n case \"image\":\n return {\n type: \"image\",\n url: await context.imageURL(node),\n alt: String(attrs.alt || \"\"),\n title: attrs.caption ? String(attrs.caption) : null\n };\n case \"table\":\n return { type: \"table\", children: children as TableContent[] };\n case \"tableRow\":\n return { type: \"tableRow\", children: children as RowContent[] };\n case \"tableCell\":\n case \"tableHeader\": {\n if (\n Number(attrs.colspan || 1) !== 1 ||\n Number(attrs.rowspan || 1) !== 1 ||\n children.some((child) => child.type !== \"paragraph\") ||\n children.length > 1\n ) {\n throw new ConversionError(\n \"Markdown tables require single-paragraph cells without spans\",\n context.path\n );\n }\n return {\n type: \"tableCell\",\n children: children.flatMap((child) => (child.type === \"paragraph\" ? child.children : []))\n };\n }\n default:\n throw new ConversionError(`Unsupported Markdown node: ${node.type}`, context.path);\n }\n};\nconst encodeMarkdownMark = (\n mark: ContentMark,\n children: RootContent[],\n context: EncodeContext<RootContent>\n): RootContent => {\n const content = children as PhrasingContent[];\n\n switch (mark.type) {\n case \"bold\":\n return { type: \"strong\", children: content };\n case \"italic\":\n return { type: \"emphasis\", children: content };\n case \"strike\":\n return { type: \"delete\", children: content };\n case \"link\":\n return { type: \"link\", url: String(mark.attrs?.href || \"\"), title: null, children: content };\n case \"code\": {\n if (children.some((node) => node.type !== \"text\"))\n throw new ConversionError(\"Code marks must wrap plain text\", context.path);\n\n return {\n type: \"inlineCode\",\n value: children.map((node) => (node.type === \"text\" ? node.value : \"\")).join(\"\")\n };\n }\n default:\n throw new ConversionError(`Unsupported Markdown mark: ${mark.type}`, context.path);\n }\n};\n\nexport { encodeMarkdown, encodeMarkdownMark };\n","import { unified, type Plugin } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkStringify from \"remark-stringify\";\nimport remarkGFM from \"remark-gfm\";\nimport type { Definition, PhrasingContent, Root, RootContent } from \"mdast\";\nimport { encodeMarkdown, encodeMarkdownMark } from \"./encode\";\nimport { decodeMarkdown, type MarkdownNode } from \"./decode\";\nimport { normalizeMarkdown } from \"./normalize\";\nimport { markdownStringifyOptions } from \"./stringify\";\nimport { ConversionError } from \"../utils\";\nimport type { FormatAdapter } from \"../types\";\n\nconst createMarkdownAdapter = (mdx?: Plugin): FormatAdapter<MarkdownNode> => {\n const processor = unified()\n .use(remarkParse)\n .use(remarkGFM)\n .use(remarkStringify, markdownStringifyOptions);\n\n if (mdx) processor.use(mdx);\n\n const marks: Record<string, string> = {\n strong: \"bold\",\n emphasis: \"italic\",\n delete: \"strike\",\n inlineCode: \"code\",\n link: \"link\"\n };\n\n return {\n name: mdx ? \"MDX\" : \"Markdown\",\n frontmatter: true,\n type: (node) => node.type,\n markName: (node) => marks[node.type],\n root: (children) => ({\n type: \"root\",\n children: children.map((node) =>\n node.type === \"image\" ? { type: \"paragraph\", children: [node] } : node\n ) as RootContent[]\n }),\n parse(source) {\n const root = processor.parse(source);\n const definitions = new Map<string, Definition>();\n const collectDefinitions = (node: MarkdownNode): void => {\n if (node.type === \"definition\") {\n const identifier = node.identifier.toUpperCase();\n\n if (!definitions.has(identifier)) definitions.set(identifier, node);\n }\n\n if (\"children\" in node) node.children.forEach(collectDefinitions);\n };\n const resolve = (node: MarkdownNode): MarkdownNode => {\n if (node.type === \"linkReference\" || node.type === \"imageReference\") {\n const definition = definitions.get(node.identifier.toUpperCase());\n\n if (!definition)\n throw new ConversionError(`Missing Markdown definition: ${node.identifier}`);\n if (node.type === \"imageReference\")\n return { type: \"image\", url: definition.url, title: definition.title, alt: node.alt };\n\n return {\n type: \"link\",\n url: definition.url,\n title: definition.title,\n children: node.children.map(resolve) as PhrasingContent[]\n };\n }\n if (\"children\" in node)\n return { ...node, children: node.children.map(resolve) } as MarkdownNode;\n\n return node;\n };\n collectDefinitions(root);\n return resolve(root);\n },\n stringify: (root) => processor.stringify(normalizeMarkdown(root as Root)),\n encode: (node, context) =>\n encodeMarkdown(node, context as Parameters<typeof encodeMarkdown>[1]),\n mark: (mark, children, context) =>\n encodeMarkdownMark(\n mark,\n children as RootContent[],\n context as Parameters<typeof encodeMarkdownMark>[2]\n ),\n decode: decodeMarkdown\n };\n};\n\nexport { createMarkdownAdapter };\n"],"mappings":"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"}
|
|
@@ -145,6 +145,7 @@ const createExportConverter = (adapter, defaults = {}) => {
|
|
|
145
145
|
return children;
|
|
146
146
|
},
|
|
147
147
|
imageURL: async (image) => {
|
|
148
|
+
if (!image.attrs?.assetID) return "";
|
|
148
149
|
const url = await settings.imageURL?.(image);
|
|
149
150
|
if (!url) throw new ConversionError("An imageURL callback must resolve the image asset", path);
|
|
150
151
|
return url;
|
|
@@ -252,6 +253,14 @@ const createImportConverter = (adapter, defaults = {}) => {
|
|
|
252
253
|
return output;
|
|
253
254
|
},
|
|
254
255
|
image: async (image) => {
|
|
256
|
+
if (!image.url) return {
|
|
257
|
+
type: "image",
|
|
258
|
+
attrs: {
|
|
259
|
+
assetID: null,
|
|
260
|
+
alt: image.alt,
|
|
261
|
+
caption: image.title || ""
|
|
262
|
+
}
|
|
263
|
+
};
|
|
255
264
|
const assetID = await settings.imageAssetID?.(image);
|
|
256
265
|
if (!assetID) throw new ConversionError("An imageAssetID callback must resolve the image URL", path);
|
|
257
266
|
return {
|
|
@@ -425,4 +434,4 @@ const mergeOptions = (defaults, options) => ({
|
|
|
425
434
|
//#endregion
|
|
426
435
|
export { element as a, lookup as c, textNode as d, withMark as f, ConversionError as i, readCodeTitle as l, createExportConverter as n, formatCodeMeta as o, createImportConverter as r, isJSONValue as s, createConverter as t, textContent as u };
|
|
427
436
|
|
|
428
|
-
//# sourceMappingURL=core-
|
|
437
|
+
//# sourceMappingURL=core-BR6Qs_Gz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-BR6Qs_Gz.js","names":[],"sources":["../../src/utils.ts","../../src/frontmatter.ts","../../src/core.ts"],"sourcesContent":["import type { ContentMark, ContentNode, HandlerResult } from \"./types\";\n\n/** A conversion failure, optionally located at a child-index path in the source tree. */\nclass ConversionError extends Error {\n /**\n * @param message - Description of the unsupported content or invalid mapping.\n * @param path - Child indexes appended to the message; defaults to the document root.\n */\n constructor(\n message: string,\n readonly path: readonly number[] = []\n ) {\n super(`${message}${path.length ? ` at content[${path.join(\"][\")}]` : \"\"}`);\n this.name = \"ConversionError\";\n }\n}\n\nconst lookup = <T>(record: Record<string, T> | undefined, name: string): T | undefined => {\n return record && Object.hasOwn(record, name) ? record[name] : undefined;\n};\nconst array = <T>(value: HandlerResult<T>): T[] =>\n value === null ? [] : Array.isArray(value) ? value : [value];\n/**\n * Concatenate a node's descendant text without changing the source.\n * @param node - ProseMirror node to read.\n * @returns Raw text with no added block separators, markup, or hard-break replacement.\n */\nconst textContent = (node: ContentNode): string =>\n node.text ?? (node.content || []).map(textContent).join(\"\");\n/**\n * Create text content suitable for a node handler.\n * @param text - Literal text to include.\n * @returns One text node, or an empty array for an empty string.\n */\nconst textNode = (text: string): ContentNode[] => (text ? [{ type: \"text\", text }] : []);\n/**\n * Append a mark to all descendant text nodes without modifying the input nodes.\n * @param nodes - Content to mark. Existing marks are retained, including duplicates.\n * @param mark - Mark to append to each text node.\n * @returns Mapped nodes; unchanged leaf nodes and existing marks may retain their references.\n */\nconst withMark = (nodes: ContentNode[], mark: ContentMark): ContentNode[] =>\n nodes.map((node) => {\n if (node.type === \"text\") return { ...node, marks: [...(node.marks || []), mark] };\n\n return node.content ? { ...node, content: withMark(node.content, mark) } : node;\n });\nconst isJSONValue = (value: unknown): boolean => {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (Array.isArray(value)) return value.every(isJSONValue);\n if (typeof value !== \"object\" || Object.getPrototypeOf(value) !== Object.prototype) return false;\n\n return Object.values(value).every(isJSONValue);\n};\n/**\n * Create an Andesine element node with static JSON properties and a source representation.\n * @param name - Element name, starting with a letter and containing letters, digits, _, ., or -.\n * @param props - Static JSON properties with valid attribute names; executable expressions are rejected.\n * @param content - Child nodes. The supplied content array is retained.\n * @param selfClosing - Whether the source uses a self-closing tag; defaults to true for empty content.\n * @returns A ProseMirror element node for use in import handlers.\n * @throws ConversionError for invalid names, property keys, or non-JSON property values.\n */\nconst element = (\n name: string,\n props: Record<string, unknown>,\n content: ContentNode[],\n selfClosing = !content.length\n): ContentNode => {\n if (!/^[A-Za-z][\\w.-]*$/.test(name) || !isJSONValue(props)) {\n throw new ConversionError(\"Elements require a valid name and static JSON properties\");\n }\n const attributes = Object.entries(props)\n .map(([key, value]) => {\n if (!/^[A-Za-z][\\w-]*$/.test(key))\n throw new ConversionError(`Invalid element property: ${key}`);\n\n return typeof value === \"string\"\n ? ` ${key}=${JSON.stringify(value)}`\n : ` ${key}={${JSON.stringify(value)}}`;\n })\n .join(\"\");\n\n return {\n type: \"element\",\n attrs: { name, props, selfClosing, source: `<${name}${attributes}${selfClosing ? \" /\" : \"\"}>` },\n ...(content.length ? { content } : {})\n };\n};\n\n/** A code fence's title from its meta, e.g. `title=\"install.sh\"`. */\nconst readCodeTitle = (meta?: string | null): string | undefined => {\n const match = meta?.match(/title=(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/);\n\n return match?.[1] ?? match?.[2] ?? match?.[3];\n};\n/** A code fence's meta for its title, quoted to keep spaces. */\nconst formatCodeMeta = (title: unknown): string | null => {\n if (typeof title !== \"string\" || !title) return null;\n\n return title.includes('\"') ? `title='${title}'` : `title=\"${title}\"`;\n};\n\nexport {\n ConversionError,\n lookup,\n array,\n element,\n formatCodeMeta,\n isJSONValue,\n readCodeTitle,\n textContent,\n textNode,\n withMark\n};\n","import { parseDocument, stringify } from \"yaml\";\nimport { ConversionError, isJSONValue } from \"./utils\";\n\nconst readFrontmatter = (\n source: string\n): { source: string; frontmatter: Record<string, unknown> } => {\n const match = /^(?:\\uFEFF)?---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/.exec(source);\n\n if (!match) return { source, frontmatter: {} };\n\n const document = parseDocument(match[1], { schema: \"core\", uniqueKeys: true });\n\n if (document.errors.length)\n throw new ConversionError(`Invalid frontmatter: ${document.errors[0].message}`);\n\n const value: unknown = document.toJS({ maxAliasCount: 100 });\n\n if (!value || Array.isArray(value) || typeof value !== \"object\" || !isJSONValue(value)) {\n throw new ConversionError(\"Frontmatter must contain an object with static JSON values\");\n }\n return { source: source.slice(match[0].length), frontmatter: value as Record<string, unknown> };\n};\nconst writeFrontmatter = (frontmatter: Record<string, unknown>, source: string): string => {\n return Object.keys(frontmatter).length\n ? `---\\n${stringify(frontmatter)}---\\n\\n${source}`\n : source;\n};\n\nexport { readFrontmatter, writeFrontmatter };\n","import { getHeadingAnchors } from \"./anchors\";\nimport { readFrontmatter, writeFrontmatter } from \"./frontmatter\";\nimport { array, ConversionError, lookup, textContent, textNode } from \"./utils\";\nimport type {\n ContentNode,\n ConvertedAST,\n Converter,\n ConverterOptions,\n DecodeContext,\n EncodeContext,\n ExportConverter,\n ExportConverterOptions,\n ExportFormatAdapter,\n ImportConverter,\n ImportConverterOptions,\n ImportFormatAdapter,\n FormatAdapter\n} from \"./types\";\n\n/**\n * Build an async export-only converter using the shared content mappings.\n *\n * @param adapter - Root builder, serializer, and export node/mark handlers. No import stubs are needed.\n * @param defaults - Reusable options. Per-call handler maps and named fragment mappings merge by key.\n * @returns Only encode() and toAST(), both async. Handlers and image callbacks may be async.\n * Import methods are absent at runtime and in TypeScript. No content is saved.\n * Unsupported nodes and marks are handled by the adapter, usually by throwing ConversionError.\n * Defaults render titles as H1s, unwrap fragments, and omit properties. Removed boundaries and\n * omitted data cannot be recovered on import; choose explicit mappings when preservation matters.\n */\nconst createExportConverter = <T>(\n adapter: ExportFormatAdapter<T>,\n defaults: ExportConverterOptions<T> = {}\n): ExportConverter<T> => {\n const toAST = async (\n document: ContentNode,\n options: ExportConverterOptions<T> = {}\n ): Promise<ConvertedAST<T>> => {\n const settings = mergeOptions(defaults, options);\n const anchors = new Map(\n getHeadingAnchors(document).map((heading) => [heading.path.join(\".\"), heading.anchor])\n );\n const frontmatter: Record<string, unknown> = Object.create(null);\n const encode = async (node: ContentNode, path: readonly number[]): Promise<T[]> => {\n // Code handlers consume plain text, so code must be the innermost mark.\n const marks = [...(node.marks || [])].sort(\n (first, second) => Number(first.type === \"code\") - Number(second.type === \"code\")\n );\n const context: EncodeContext<T> = {\n anchor: node.type === \"heading\" ? anchors.get(path.join(\".\")) : undefined,\n options: settings,\n path,\n encode: (child) => encode(child, path),\n children: async (parent) => {\n const children: T[] = [];\n\n for (const [index, child] of (parent.content || []).entries())\n children.push(...(await encode(child, [...path, index])));\n return children;\n },\n imageURL: async (image) => {\n if (!image.attrs?.assetID) return \"\";\n\n const url = await settings.imageURL?.(image);\n\n if (!url)\n throw new ConversionError(\"An imageURL callback must resolve the image asset\", path);\n return url;\n }\n };\n const handlers = settings.encode;\n const elementName = node.type === \"element\" ? String(node.attrs?.name || \"\") : undefined;\n const handler = elementName\n ? (lookup(handlers?.elements, elementName) ??\n lookup(handlers?.elements, \"*\") ??\n lookup(handlers?.nodes, \"element\") ??\n lookup(handlers?.nodes, \"*\"))\n : (lookup(handlers?.nodes, node.type) ?? lookup(handlers?.nodes, \"*\"));\n let result: T[];\n\n if (handler) {\n result = array(await handler(node, context));\n } else if (node.type === \"doc\") {\n result = await context.children(node);\n } else if (node.type === \"title\") {\n const title = settings.title ?? \"heading\";\n\n if (title === \"omit\") return [];\n if (typeof title === \"object\") {\n setMetadata(frontmatter, title.key || \"title\", textContent(node));\n return [];\n }\n result = array(\n await adapter.encode({ ...node, type: \"heading\", attrs: { level: 1 } }, context)\n );\n } else if (node.type === \"property\") {\n const mapping = settings.properties ?? \"omit\";\n const name = String(node.attrs?.label || \"Property\");\n const type = String(node.attrs?.type || \"text\");\n const value = node.attrs?.value ?? \"\";\n const normalized = type === \"number\" ? (value === \"\" ? null : Number(value)) : value;\n\n if (mapping === \"omit\") return [];\n\n if (mapping.as === \"frontmatter\") {\n setMetadata(frontmatter, name, normalized);\n return [];\n }\n result = await context.encode({\n type: \"element\",\n attrs: {\n name: mapping.name,\n // The type is written only when import can't infer it from the value.\n props: {\n name,\n ...(getPropertyType(normalized) !== type && { type }),\n value: normalized\n },\n selfClosing: true\n }\n });\n } else if (node.type === \"fragment\") {\n const name = String(node.attrs?.name || \"Content\");\n const mapping =\n lookup(settings.fragments?.named, name) ?? settings.fragments?.default ?? \"unwrap\";\n\n if (mapping === \"omit\") return [];\n if (mapping === \"unwrap\") return context.children(node);\n\n result = await context.encode({\n type: \"element\",\n attrs: { name: mapping.name, props: { name }, selfClosing: false },\n content: node.content\n });\n } else {\n result = array(await adapter.encode(node, context));\n }\n if (!result.length) return result;\n\n for (const mark of marks.reverse()) {\n const handler = lookup(handlers?.marks, mark.type) ?? lookup(handlers?.marks, \"*\");\n\n result = array(\n await (handler ? handler(mark, result, context) : adapter.mark(mark, result, context))\n );\n }\n return result;\n };\n const children = await encode(document, []);\n\n if (!adapter.frontmatter && Object.keys(frontmatter).length)\n throw new ConversionError(`${adapter.name} does not support frontmatter`);\n\n return { tree: adapter.root(children), frontmatter };\n };\n\n return {\n toAST,\n async encode(document: ContentNode, options?: ExportConverterOptions<T>): Promise<string> {\n const result = await toAST(document, options);\n\n return writeFrontmatter(result.frontmatter, await adapter.stringify(result.tree));\n }\n };\n};\n\n/**\n * Build an async import-only converter using the shared content mappings.\n *\n * @param adapter - Parser, decode handler, and node-type lookup. No export stubs are needed.\n * @param defaults - Reusable import mappings and handlers, merged by key with per-call overrides.\n * @returns Only decode() and fromAST(), both async. Parsers, handlers, and image callbacks may\n * be async. Export methods are absent at runtime and in TypeScript. No content is saved.\n * Imports create an entry with a title by default; document: \"fragment\" retains headings as body\n * content. Unsupported input is handled by the adapter; parser and handler errors pass through.\n */\nconst createImportConverter = <T>(\n adapter: ImportFormatAdapter<T>,\n defaults: ImportConverterOptions<T> = {}\n): ImportConverter<T> => {\n const fromAST = async (\n input: ConvertedAST<T>,\n options: ImportConverterOptions<T> = {}\n ): Promise<ContentNode> => {\n const settings = mergeOptions(defaults, options);\n const decode = async (node: T, path: readonly number[]): Promise<ContentNode[]> => {\n const context: DecodeContext<T> = {\n options: settings,\n path,\n decode: (child) => decode(child, path),\n children: async (children) => {\n const output: ContentNode[] = [];\n\n for (const [index, child] of children.entries())\n output.push(...(await decode(child, [...path, index])));\n return output;\n },\n image: async (image) => {\n if (!image.url) {\n return {\n type: \"image\",\n attrs: { assetID: null, alt: image.alt, caption: image.title || \"\" }\n };\n }\n\n const assetID = await settings.imageAssetID?.(image);\n\n if (!assetID)\n throw new ConversionError(\"An imageAssetID callback must resolve the image URL\", path);\n return { type: \"image\", attrs: { assetID, alt: image.alt, caption: image.title || \"\" } };\n }\n };\n const handlers = settings.decode;\n const type = adapter.type(node);\n const name = adapter.elementName?.(node);\n const mark = adapter.markName?.(node);\n const handler =\n (name\n ? (lookup(handlers?.elements, name) ?? lookup(handlers?.elements, \"*\"))\n : undefined) ??\n (mark ? (lookup(handlers?.marks, mark) ?? lookup(handlers?.marks, \"*\")) : undefined) ??\n lookup(handlers?.nodes, type) ??\n lookup(handlers?.nodes, \"*\");\n const result = array(\n await (handler ? handler(node, context) : adapter.decode(node, context))\n );\n\n return result.flatMap((content) => {\n if (content.type !== \"element\") return [content];\n\n const props = content.attrs?.props as Record<string, unknown> | undefined;\n const propertyMapping =\n typeof settings.properties === \"object\" && settings.properties.as === \"element\"\n ? settings.properties\n : undefined;\n\n if (propertyMapping?.name === content.attrs?.name) {\n if (typeof props?.name !== \"string\") {\n throw new ConversionError(\"Property elements require a name\", path);\n }\n\n return [createProperty(props.name, props.value, props.type)];\n }\n\n const fragmentName = typeof props?.name === \"string\" ? props.name : undefined;\n const mapping = fragmentName\n ? (lookup(settings.fragments?.named, fragmentName) ?? settings.fragments?.default)\n : undefined;\n\n if (mapping && typeof mapping === \"object\" && mapping.name === content.attrs?.name) {\n return [\n {\n type: \"fragment\",\n attrs: { name: fragmentName },\n content: content.content || [{ type: \"paragraph\" }]\n }\n ];\n }\n return [content];\n });\n };\n const content = await decode(input.tree, []);\n const title = settings.title ?? \"heading\";\n const titleKey = typeof title === \"object\" ? title.key || \"title\" : undefined;\n const properties: ContentNode[] = [];\n let titleText = \"\";\n\n if (titleKey && input.frontmatter[titleKey] !== undefined)\n titleText = String(input.frontmatter[titleKey]);\n if (\n title === \"heading\" &&\n settings.document !== \"fragment\" &&\n content[0]?.type === \"heading\" &&\n content[0].attrs?.level === 1\n ) {\n titleText = textContent(content.shift()!);\n }\n if (settings.properties && settings.properties !== \"omit\") {\n for (const [label, value] of Object.entries(input.frontmatter)) {\n if (label === titleKey) continue;\n\n properties.push(createProperty(label, value));\n }\n }\n const body: ContentNode[] = settings.targetFragment\n ? [\n {\n type: \"fragment\",\n attrs: { name: settings.targetFragment },\n content: content.length ? content : [{ type: \"paragraph\" }]\n }\n ]\n : content;\n\n return {\n type: \"doc\",\n content: [\n ...(settings.document === \"fragment\"\n ? []\n : [{ type: \"title\", content: textNode(titleText) }]),\n ...properties,\n ...(body.length ? body : [{ type: \"paragraph\" }])\n ]\n };\n };\n\n return {\n fromAST,\n async decode(source: string, options?: ImportConverterOptions<T>): Promise<ContentNode> {\n const input = adapter.frontmatter ? readFrontmatter(source) : { source, frontmatter: {} };\n\n return fromAST(\n { tree: await adapter.parse(input.source), frontmatter: input.frontmatter },\n options\n );\n }\n };\n};\n\n/**\n * Build an async converter for a custom format that supports both import and export.\n *\n * @param adapter - Full adapter with parser, serializer, and mappings for both directions.\n * @param defaults - Shared defaults and direction-specific handlers. Per-call maps merge by key.\n * @returns encode(), toAST(), decode(), and fromAST(), composed from the one-way factories.\n * Each method accepts options for its own direction. No content is saved or uploaded.\n * Defaults render titles as H1s, unwrap fragments, and omit properties. Removed boundaries and\n * omitted data cannot be recovered on import; choose explicit mappings when preservation matters.\n */\nconst createConverter = <T>(\n adapter: FormatAdapter<T>,\n defaults: ConverterOptions<T> = {}\n): Converter<T> => ({\n ...createExportConverter(adapter, defaults),\n ...createImportConverter(adapter, defaults)\n});\nconst PROPERTY_TYPES = [\"text\", \"number\", \"checkbox\", \"date\", \"url\", \"select\", \"multi-select\"];\nconst getPropertyType = (value: unknown): string => {\n const stringArray = Array.isArray(value) && value.every((item) => typeof item === \"string\");\n\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"boolean\") return \"checkbox\";\n if (stringArray) return \"multi-select\";\n\n return \"text\";\n};\nconst createProperty = (label: string, value: unknown, type?: unknown): ContentNode => {\n const propertyType = type === undefined ? getPropertyType(value) : type;\n const textValue = ![\"number\", \"checkbox\", \"multi-select\"].includes(String(propertyType));\n const supportedType = typeof propertyType === \"string\" && PROPERTY_TYPES.includes(propertyType);\n const unsupportedValue =\n textValue && value !== null && value !== undefined && typeof value !== \"string\";\n\n if (!supportedType) {\n throw new ConversionError(`Property ${label} has an unsupported type: ${String(type)}`);\n }\n\n if (unsupportedValue) throw new ConversionError(`Property ${label} cannot represent this value`);\n\n return { type: \"property\", attrs: { label, type: propertyType, value: value ?? \"\" } };\n};\nconst setMetadata = (metadata: Record<string, unknown>, key: string, value: unknown): void => {\n if (Object.hasOwn(metadata, key))\n throw new ConversionError(`Duplicate frontmatter field: ${key}`);\n\n metadata[key] = value;\n};\nconst mergeOptions = <T>(\n defaults: ConverterOptions<T>,\n options: ConverterOptions<T>\n): ConverterOptions<T> => ({\n ...defaults,\n ...options,\n fragments: {\n ...defaults.fragments,\n ...options.fragments,\n named: { ...defaults.fragments?.named, ...options.fragments?.named }\n },\n encode: {\n nodes: { ...defaults.encode?.nodes, ...options.encode?.nodes },\n marks: { ...defaults.encode?.marks, ...options.encode?.marks },\n elements: { ...defaults.encode?.elements, ...options.encode?.elements }\n },\n decode: {\n nodes: { ...defaults.decode?.nodes, ...options.decode?.nodes },\n marks: { ...defaults.decode?.marks, ...options.decode?.marks },\n elements: { ...defaults.decode?.elements, ...options.decode?.elements }\n }\n});\n\nexport { createConverter, createExportConverter, createImportConverter };\n"],"mappings":";;;;AAGA,IAAM,kBAAN,cAA8B,MAAM;CAOvB;;;;;CAFX,YACE,SACA,OAAmC,CAAC,GACpC;EACA,MAAM,GAAG,UAAU,KAAK,SAAS,eAAe,KAAK,KAAK,IAAI,EAAE,KAAK,IAAI;EAFhE,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;AAEA,MAAM,UAAa,QAAuC,SAAgC;CACxF,OAAO,UAAU,OAAO,OAAO,QAAQ,IAAI,IAAI,OAAO,QAAQ,KAAA;AAChE;AACA,MAAM,SAAY,UAChB,UAAU,OAAO,CAAC,IAAI,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;;;;;;AAM7D,MAAM,eAAe,SACnB,KAAK,SAAS,KAAK,WAAW,CAAC,EAAA,CAAG,IAAI,WAAW,CAAC,CAAC,KAAK,EAAE;;;;;;AAM5D,MAAM,YAAY,SAAiC,OAAO,CAAC;CAAE,MAAM;CAAQ;AAAK,CAAC,IAAI,CAAC;;;;;;;AAOtF,MAAM,YAAY,OAAsB,SACtC,MAAM,KAAK,SAAS;CAClB,IAAI,KAAK,SAAS,QAAQ,OAAO;EAAE,GAAG;EAAM,OAAO,CAAC,GAAI,KAAK,SAAS,CAAC,GAAI,IAAI;CAAE;CAEjF,OAAO,KAAK,UAAU;EAAE,GAAG;EAAM,SAAS,SAAS,KAAK,SAAS,IAAI;CAAE,IAAI;AAC7E,CAAC;AACH,MAAM,eAAe,UAA4B;CAC/C,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW,OAAO;CACtF,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,SAAS,KAAK;CAC3D,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,MAAM,WAAW;CACxD,IAAI,OAAO,UAAU,YAAY,OAAO,eAAe,KAAK,MAAM,OAAO,WAAW,OAAO;CAE3F,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,MAAM,WAAW;AAC/C;;;;;;;;;;AAUA,MAAM,WACJ,MACA,OACA,SACA,cAAc,CAAC,QAAQ,WACP;CAChB,IAAI,CAAC,oBAAoB,KAAK,IAAI,KAAK,CAAC,YAAY,KAAK,GACvD,MAAM,IAAI,gBAAgB,0DAA0D;CAatF,OAAO;EACL,MAAM;EACN,OAAO;GAAE;GAAM;GAAO;GAAa,QAAQ,IAAI,OAb9B,OAAO,QAAQ,KAAK,CAAC,CACrC,KAAK,CAAC,KAAK,WAAW;IACrB,IAAI,CAAC,mBAAmB,KAAK,GAAG,GAC9B,MAAM,IAAI,gBAAgB,6BAA6B,KAAK;IAE9D,OAAO,OAAO,UAAU,WACpB,IAAI,IAAI,GAAG,KAAK,UAAU,KAAK,MAC/B,IAAI,IAAI,IAAI,KAAK,UAAU,KAAK,EAAE;GACxC,CAAC,CAAC,CACD,KAAK,EAIyD,IAAI,cAAc,OAAO,GAAG;EAAG;EAC9F,GAAI,QAAQ,SAAS,EAAE,QAAQ,IAAI,CAAC;CACtC;AACF;;AAGA,MAAM,iBAAiB,SAA6C;CAClE,MAAM,QAAQ,MAAM,MAAM,qCAAqC;CAE/D,OAAO,QAAQ,MAAM,QAAQ,MAAM,QAAQ;AAC7C;;AAEA,MAAM,kBAAkB,UAAkC;CACxD,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,OAAO;CAEhD,OAAO,MAAM,SAAS,IAAG,IAAI,UAAU,MAAM,KAAK,UAAU,MAAM;AACpE;;;ACnGA,MAAM,mBACJ,WAC6D;CAC7D,MAAM,QAAQ,oDAAoD,KAAK,MAAM;CAE7E,IAAI,CAAC,OAAO,OAAO;EAAE;EAAQ,aAAa,CAAC;CAAE;CAE7C,MAAM,WAAW,cAAc,MAAM,IAAI;EAAE,QAAQ;EAAQ,YAAY;CAAK,CAAC;CAE7E,IAAI,SAAS,OAAO,QAClB,MAAM,IAAI,gBAAgB,wBAAwB,SAAS,OAAO,EAAE,CAAC,SAAS;CAEhF,MAAM,QAAiB,SAAS,KAAK,EAAE,eAAe,IAAI,CAAC;CAE3D,IAAI,CAAC,SAAS,MAAM,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,YAAY,KAAK,GACnF,MAAM,IAAI,gBAAgB,4DAA4D;CAExF,OAAO;EAAE,QAAQ,OAAO,MAAM,MAAM,EAAE,CAAC,MAAM;EAAG,aAAa;CAAiC;AAChG;AACA,MAAM,oBAAoB,aAAsC,WAA2B;CACzF,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,SAC5B,QAAQ,UAAU,WAAW,EAAE,SAAS,WACxC;AACN;;;;;;;;;;;;;;ACIA,MAAM,yBACJ,SACA,WAAsC,CAAC,MAChB;CACvB,MAAM,QAAQ,OACZ,UACA,UAAqC,CAAC,MACT;EAC7B,MAAM,WAAW,aAAa,UAAU,OAAO;EAC/C,MAAM,UAAU,IAAI,IAClB,kBAAkB,QAAQ,CAAC,CAAC,KAAK,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG,GAAG,QAAQ,MAAM,CAAC,CACvF;EACA,MAAM,cAAuC,OAAO,OAAO,IAAI;EAC/D,MAAM,SAAS,OAAO,MAAmB,SAA0C;GAEjF,MAAM,QAAQ,CAAC,GAAI,KAAK,SAAS,CAAC,CAAE,CAAC,CAAC,MACnC,OAAO,WAAW,OAAO,MAAM,SAAS,MAAM,IAAI,OAAO,OAAO,SAAS,MAAM,CAClF;GACA,MAAM,UAA4B;IAChC,QAAQ,KAAK,SAAS,YAAY,QAAQ,IAAI,KAAK,KAAK,GAAG,CAAC,IAAI,KAAA;IAChE,SAAS;IACT;IACA,SAAS,UAAU,OAAO,OAAO,IAAI;IACrC,UAAU,OAAO,WAAW;KAC1B,MAAM,WAAgB,CAAC;KAEvB,KAAK,MAAM,CAAC,OAAO,WAAW,OAAO,WAAW,CAAC,EAAA,CAAG,QAAQ,GAC1D,SAAS,KAAK,GAAI,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,CAAE;KAC1D,OAAO;IACT;IACA,UAAU,OAAO,UAAU;KACzB,IAAI,CAAC,MAAM,OAAO,SAAS,OAAO;KAElC,MAAM,MAAM,MAAM,SAAS,WAAW,KAAK;KAE3C,IAAI,CAAC,KACH,MAAM,IAAI,gBAAgB,qDAAqD,IAAI;KACrF,OAAO;IACT;GACF;GACA,MAAM,WAAW,SAAS;GAC1B,MAAM,cAAc,KAAK,SAAS,YAAY,OAAO,KAAK,OAAO,QAAQ,EAAE,IAAI,KAAA;GAC/E,MAAM,UAAU,cACX,OAAO,UAAU,UAAU,WAAW,KACvC,OAAO,UAAU,UAAU,GAAG,KAC9B,OAAO,UAAU,OAAO,SAAS,KACjC,OAAO,UAAU,OAAO,GAAG,IAC1B,OAAO,UAAU,OAAO,KAAK,IAAI,KAAK,OAAO,UAAU,OAAO,GAAG;GACtE,IAAI;GAEJ,IAAI,SACF,SAAS,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC;QACtC,IAAI,KAAK,SAAS,OACvB,SAAS,MAAM,QAAQ,SAAS,IAAI;QAC/B,IAAI,KAAK,SAAS,SAAS;IAChC,MAAM,QAAQ,SAAS,SAAS;IAEhC,IAAI,UAAU,QAAQ,OAAO,CAAC;IAC9B,IAAI,OAAO,UAAU,UAAU;KAC7B,YAAY,aAAa,MAAM,OAAO,SAAS,YAAY,IAAI,CAAC;KAChE,OAAO,CAAC;IACV;IACA,SAAS,MACP,MAAM,QAAQ,OAAO;KAAE,GAAG;KAAM,MAAM;KAAW,OAAO,EAAE,OAAO,EAAE;IAAE,GAAG,OAAO,CACjF;GACF,OAAO,IAAI,KAAK,SAAS,YAAY;IACnC,MAAM,UAAU,SAAS,cAAc;IACvC,MAAM,OAAO,OAAO,KAAK,OAAO,SAAS,UAAU;IACnD,MAAM,OAAO,OAAO,KAAK,OAAO,QAAQ,MAAM;IAC9C,MAAM,QAAQ,KAAK,OAAO,SAAS;IACnC,MAAM,aAAa,SAAS,WAAY,UAAU,KAAK,OAAO,OAAO,KAAK,IAAK;IAE/E,IAAI,YAAY,QAAQ,OAAO,CAAC;IAEhC,IAAI,QAAQ,OAAO,eAAe;KAChC,YAAY,aAAa,MAAM,UAAU;KACzC,OAAO,CAAC;IACV;IACA,SAAS,MAAM,QAAQ,OAAO;KAC5B,MAAM;KACN,OAAO;MACL,MAAM,QAAQ;MAEd,OAAO;OACL;OACA,GAAI,gBAAgB,UAAU,MAAM,QAAQ,EAAE,KAAK;OACnD,OAAO;MACT;MACA,aAAa;KACf;IACF,CAAC;GACH,OAAO,IAAI,KAAK,SAAS,YAAY;IACnC,MAAM,OAAO,OAAO,KAAK,OAAO,QAAQ,SAAS;IACjD,MAAM,UACJ,OAAO,SAAS,WAAW,OAAO,IAAI,KAAK,SAAS,WAAW,WAAW;IAE5E,IAAI,YAAY,QAAQ,OAAO,CAAC;IAChC,IAAI,YAAY,UAAU,OAAO,QAAQ,SAAS,IAAI;IAEtD,SAAS,MAAM,QAAQ,OAAO;KAC5B,MAAM;KACN,OAAO;MAAE,MAAM,QAAQ;MAAM,OAAO,EAAE,KAAK;MAAG,aAAa;KAAM;KACjE,SAAS,KAAK;IAChB,CAAC;GACH,OACE,SAAS,MAAM,MAAM,QAAQ,OAAO,MAAM,OAAO,CAAC;GAEpD,IAAI,CAAC,OAAO,QAAQ,OAAO;GAE3B,KAAK,MAAM,QAAQ,MAAM,QAAQ,GAAG;IAClC,MAAM,UAAU,OAAO,UAAU,OAAO,KAAK,IAAI,KAAK,OAAO,UAAU,OAAO,GAAG;IAEjF,SAAS,MACP,OAAO,UAAU,QAAQ,MAAM,QAAQ,OAAO,IAAI,QAAQ,KAAK,MAAM,QAAQ,OAAO,EACtF;GACF;GACA,OAAO;EACT;EACA,MAAM,WAAW,MAAM,OAAO,UAAU,CAAC,CAAC;EAE1C,IAAI,CAAC,QAAQ,eAAe,OAAO,KAAK,WAAW,CAAC,CAAC,QACnD,MAAM,IAAI,gBAAgB,GAAG,QAAQ,KAAK,8BAA8B;EAE1E,OAAO;GAAE,MAAM,QAAQ,KAAK,QAAQ;GAAG;EAAY;CACrD;CAEA,OAAO;EACL;EACA,MAAM,OAAO,UAAuB,SAAsD;GACxF,MAAM,SAAS,MAAM,MAAM,UAAU,OAAO;GAE5C,OAAO,iBAAiB,OAAO,aAAa,MAAM,QAAQ,UAAU,OAAO,IAAI,CAAC;EAClF;CACF;AACF;;;;;;;;;;;AAYA,MAAM,yBACJ,SACA,WAAsC,CAAC,MAChB;CACvB,MAAM,UAAU,OACd,OACA,UAAqC,CAAC,MACb;EACzB,MAAM,WAAW,aAAa,UAAU,OAAO;EAC/C,MAAM,SAAS,OAAO,MAAS,SAAoD;GACjF,MAAM,UAA4B;IAChC,SAAS;IACT;IACA,SAAS,UAAU,OAAO,OAAO,IAAI;IACrC,UAAU,OAAO,aAAa;KAC5B,MAAM,SAAwB,CAAC;KAE/B,KAAK,MAAM,CAAC,OAAO,UAAU,SAAS,QAAQ,GAC5C,OAAO,KAAK,GAAI,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,CAAE;KACxD,OAAO;IACT;IACA,OAAO,OAAO,UAAU;KACtB,IAAI,CAAC,MAAM,KACT,OAAO;MACL,MAAM;MACN,OAAO;OAAE,SAAS;OAAM,KAAK,MAAM;OAAK,SAAS,MAAM,SAAS;MAAG;KACrE;KAGF,MAAM,UAAU,MAAM,SAAS,eAAe,KAAK;KAEnD,IAAI,CAAC,SACH,MAAM,IAAI,gBAAgB,uDAAuD,IAAI;KACvF,OAAO;MAAE,MAAM;MAAS,OAAO;OAAE;OAAS,KAAK,MAAM;OAAK,SAAS,MAAM,SAAS;MAAG;KAAE;IACzF;GACF;GACA,MAAM,WAAW,SAAS;GAC1B,MAAM,OAAO,QAAQ,KAAK,IAAI;GAC9B,MAAM,OAAO,QAAQ,cAAc,IAAI;GACvC,MAAM,OAAO,QAAQ,WAAW,IAAI;GACpC,MAAM,WACH,OACI,OAAO,UAAU,UAAU,IAAI,KAAK,OAAO,UAAU,UAAU,GAAG,IACnE,KAAA,OACH,OAAQ,OAAO,UAAU,OAAO,IAAI,KAAK,OAAO,UAAU,OAAO,GAAG,IAAK,KAAA,MAC1E,OAAO,UAAU,OAAO,IAAI,KAC5B,OAAO,UAAU,OAAO,GAAG;GAK7B,OAJe,MACb,OAAO,UAAU,QAAQ,MAAM,OAAO,IAAI,QAAQ,OAAO,MAAM,OAAO,EAG5D,CAAC,CAAC,SAAS,YAAY;IACjC,IAAI,QAAQ,SAAS,WAAW,OAAO,CAAC,OAAO;IAE/C,MAAM,QAAQ,QAAQ,OAAO;IAM7B,KAJE,OAAO,SAAS,eAAe,YAAY,SAAS,WAAW,OAAO,YAClE,SAAS,aACT,KAAA,EAAA,EAEe,SAAS,QAAQ,OAAO,MAAM;KACjD,IAAI,OAAO,OAAO,SAAS,UACzB,MAAM,IAAI,gBAAgB,oCAAoC,IAAI;KAGpE,OAAO,CAAC,eAAe,MAAM,MAAM,MAAM,OAAO,MAAM,IAAI,CAAC;IAC7D;IAEA,MAAM,eAAe,OAAO,OAAO,SAAS,WAAW,MAAM,OAAO,KAAA;IACpE,MAAM,UAAU,eACX,OAAO,SAAS,WAAW,OAAO,YAAY,KAAK,SAAS,WAAW,UACxE,KAAA;IAEJ,IAAI,WAAW,OAAO,YAAY,YAAY,QAAQ,SAAS,QAAQ,OAAO,MAC5E,OAAO,CACL;KACE,MAAM;KACN,OAAO,EAAE,MAAM,aAAa;KAC5B,SAAS,QAAQ,WAAW,CAAC,EAAE,MAAM,YAAY,CAAC;IACpD,CACF;IAEF,OAAO,CAAC,OAAO;GACjB,CAAC;EACH;EACA,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM,CAAC,CAAC;EAC3C,MAAM,QAAQ,SAAS,SAAS;EAChC,MAAM,WAAW,OAAO,UAAU,WAAW,MAAM,OAAO,UAAU,KAAA;EACpE,MAAM,aAA4B,CAAC;EACnC,IAAI,YAAY;EAEhB,IAAI,YAAY,MAAM,YAAY,cAAc,KAAA,GAC9C,YAAY,OAAO,MAAM,YAAY,SAAS;EAChD,IACE,UAAU,aACV,SAAS,aAAa,cACtB,QAAQ,EAAE,EAAE,SAAS,aACrB,QAAQ,EAAE,CAAC,OAAO,UAAU,GAE5B,YAAY,YAAY,QAAQ,MAAM,CAAE;EAE1C,IAAI,SAAS,cAAc,SAAS,eAAe,QACjD,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,MAAM,WAAW,GAAG;GAC9D,IAAI,UAAU,UAAU;GAExB,WAAW,KAAK,eAAe,OAAO,KAAK,CAAC;EAC9C;EAEF,MAAM,OAAsB,SAAS,iBACjC,CACE;GACE,MAAM;GACN,OAAO,EAAE,MAAM,SAAS,eAAe;GACvC,SAAS,QAAQ,SAAS,UAAU,CAAC,EAAE,MAAM,YAAY,CAAC;EAC5D,CACF,IACA;EAEJ,OAAO;GACL,MAAM;GACN,SAAS;IACP,GAAI,SAAS,aAAa,aACtB,CAAC,IACD,CAAC;KAAE,MAAM;KAAS,SAAS,SAAS,SAAS;IAAE,CAAC;IACpD,GAAG;IACH,GAAI,KAAK,SAAS,OAAO,CAAC,EAAE,MAAM,YAAY,CAAC;GACjD;EACF;CACF;CAEA,OAAO;EACL;EACA,MAAM,OAAO,QAAgB,SAA2D;GACtF,MAAM,QAAQ,QAAQ,cAAc,gBAAgB,MAAM,IAAI;IAAE;IAAQ,aAAa,CAAC;GAAE;GAExF,OAAO,QACL;IAAE,MAAM,MAAM,QAAQ,MAAM,MAAM,MAAM;IAAG,aAAa,MAAM;GAAY,GAC1E,OACF;EACF;CACF;AACF;;;;;;;;;;;AAYA,MAAM,mBACJ,SACA,WAAgC,CAAC,OACf;CAClB,GAAG,sBAAsB,SAAS,QAAQ;CAC1C,GAAG,sBAAsB,SAAS,QAAQ;AAC5C;AACA,MAAM,iBAAiB;CAAC;CAAQ;CAAU;CAAY;CAAQ;CAAO;CAAU;AAAc;AAC7F,MAAM,mBAAmB,UAA2B;CAClD,MAAM,cAAc,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,SAAS,OAAO,SAAS,QAAQ;CAE1F,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,IAAI,aAAa,OAAO;CAExB,OAAO;AACT;AACA,MAAM,kBAAkB,OAAe,OAAgB,SAAgC;CACrF,MAAM,eAAe,SAAS,KAAA,IAAY,gBAAgB,KAAK,IAAI;CACnE,MAAM,YAAY,CAAC;EAAC;EAAU;EAAY;CAAc,CAAC,CAAC,SAAS,OAAO,YAAY,CAAC;CACvF,MAAM,gBAAgB,OAAO,iBAAiB,YAAY,eAAe,SAAS,YAAY;CAC9F,MAAM,mBACJ,aAAa,UAAU,QAAQ,UAAU,KAAA,KAAa,OAAO,UAAU;CAEzE,IAAI,CAAC,eACH,MAAM,IAAI,gBAAgB,YAAY,MAAM,4BAA4B,OAAO,IAAI,GAAG;CAGxF,IAAI,kBAAkB,MAAM,IAAI,gBAAgB,YAAY,MAAM,6BAA6B;CAE/F,OAAO;EAAE,MAAM;EAAY,OAAO;GAAE;GAAO,MAAM;GAAc,OAAO,SAAS;EAAG;CAAE;AACtF;AACA,MAAM,eAAe,UAAmC,KAAa,UAAyB;CAC5F,IAAI,OAAO,OAAO,UAAU,GAAG,GAC7B,MAAM,IAAI,gBAAgB,gCAAgC,KAAK;CAEjE,SAAS,OAAO;AAClB;AACA,MAAM,gBACJ,UACA,aACyB;CACzB,GAAG;CACH,GAAG;CACH,WAAW;EACT,GAAG,SAAS;EACZ,GAAG,QAAQ;EACX,OAAO;GAAE,GAAG,SAAS,WAAW;GAAO,GAAG,QAAQ,WAAW;EAAM;CACrE;CACA,QAAQ;EACN,OAAO;GAAE,GAAG,SAAS,QAAQ;GAAO,GAAG,QAAQ,QAAQ;EAAM;EAC7D,OAAO;GAAE,GAAG,SAAS,QAAQ;GAAO,GAAG,QAAQ,QAAQ;EAAM;EAC7D,UAAU;GAAE,GAAG,SAAS,QAAQ;GAAU,GAAG,QAAQ,QAAQ;EAAS;CACxE;CACA,QAAQ;EACN,OAAO;GAAE,GAAG,SAAS,QAAQ;GAAO,GAAG,QAAQ,QAAQ;EAAM;EAC7D,OAAO;GAAE,GAAG,SAAS,QAAQ;GAAO,GAAG,QAAQ,QAAQ;EAAM;EAC7D,UAAU;GAAE,GAAG,SAAS,QAAQ;GAAU,GAAG,QAAQ,QAAQ;EAAS;CACxE;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as textNode, f as withMark, i as ConversionError, l as readCodeTitle } from "./core-
|
|
1
|
+
import { d as textNode, f as withMark, i as ConversionError, l as readCodeTitle } from "./core-BR6Qs_Gz.js";
|
|
2
2
|
//#region src/markdown/decode.ts
|
|
3
3
|
const paragraphContent = (children) => {
|
|
4
4
|
const blocks = [];
|
|
@@ -102,4 +102,4 @@ const decodeMarkdown = async (node, context) => {
|
|
|
102
102
|
//#endregion
|
|
103
103
|
export { paragraphContent as n, decodeMarkdown as t };
|
|
104
104
|
|
|
105
|
-
//# sourceMappingURL=decode-
|
|
105
|
+
//# sourceMappingURL=decode-DmUqH-b-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode-
|
|
1
|
+
{"version":3,"file":"decode-DmUqH-b-.js","names":[],"sources":["../../src/markdown/decode.ts"],"sourcesContent":["import type { Root, RootContent } from \"mdast\";\nimport { ConversionError, readCodeTitle, textNode, withMark } from \"../utils\";\nimport type { ContentNode, DecodeContext } from \"../types\";\n\ntype MarkdownNode = Root | RootContent;\n\nconst paragraphContent = (children: ContentNode[]): ContentNode[] => {\n const blocks: ContentNode[] = [];\n let inline: ContentNode[] = [];\n\n for (const child of children) {\n if ([\"text\", \"hardBreak\"].includes(child.type)) {\n inline.push(child);\n } else {\n if (inline.length) blocks.push({ type: \"paragraph\", content: inline });\n inline = [];\n blocks.push(child);\n }\n }\n if (inline.length || !blocks.length) blocks.push({ type: \"paragraph\", content: inline });\n\n return blocks;\n};\nconst decodeMarkdown = async (\n node: MarkdownNode,\n context: DecodeContext<MarkdownNode>\n): Promise<ContentNode | ContentNode[] | null> => {\n const children = \"children\" in node ? await context.children(node.children) : [];\n\n switch (node.type) {\n case \"root\":\n return children;\n case \"text\":\n return textNode(node.value);\n case \"paragraph\":\n return paragraphContent(children);\n case \"heading\":\n return { type: \"heading\", attrs: { level: node.depth }, content: children };\n case \"blockquote\":\n return { type: \"blockquote\", content: children };\n case \"list\": {\n const tasks = children.some((child) => child.type === \"taskItem\");\n\n if (node.ordered && tasks)\n throw new ConversionError(\"Ordered task lists require a custom handler\", context.path);\n\n return {\n type: node.ordered ? \"orderedList\" : tasks ? \"taskList\" : \"bulletList\",\n ...(node.ordered ? { attrs: { start: node.start || 1 } } : {}),\n content: tasks\n ? children.map((child) => ({\n ...child,\n type: \"taskItem\",\n attrs: { checked: false, ...child.attrs }\n }))\n : children\n };\n }\n case \"listItem\":\n return {\n type: typeof node.checked === \"boolean\" ? \"taskItem\" : \"listItem\",\n ...(typeof node.checked === \"boolean\" ? { attrs: { checked: node.checked } } : {}),\n content: children\n };\n case \"break\":\n return { type: \"hardBreak\" };\n case \"thematicBreak\":\n return { type: \"horizontalRule\" };\n case \"code\":\n return {\n type: \"codeBlock\",\n attrs: { language: node.lang || null, title: readCodeTitle(node.meta) ?? null },\n content: textNode(node.value)\n };\n case \"inlineCode\":\n return withMark(textNode(node.value), { type: \"code\" });\n case \"strong\":\n return withMark(children, { type: \"bold\" });\n case \"emphasis\":\n return withMark(children, { type: \"italic\" });\n case \"delete\":\n return withMark(children, { type: \"strike\" });\n case \"link\":\n return withMark(children, { type: \"link\", attrs: { href: node.url } });\n case \"image\":\n return context.image({ url: node.url, alt: node.alt || \"\", title: node.title || undefined });\n case \"table\":\n return {\n type: \"table\",\n content: children.map((row, index) =>\n index\n ? row\n : { ...row, content: row.content?.map((cell) => ({ ...cell, type: \"tableHeader\" })) }\n )\n };\n case \"tableRow\":\n return { type: \"tableRow\", content: children };\n case \"tableCell\":\n return { type: \"tableCell\", content: paragraphContent(children) };\n case \"definition\":\n return null;\n default:\n throw new ConversionError(`Unsupported Markdown syntax: ${node.type}`, context.path);\n }\n};\n\nexport { decodeMarkdown, paragraphContent };\nexport type { MarkdownNode };\n"],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ interface EncodeContext<T> {
|
|
|
26
26
|
encode(node: ContentNode): Promise<T[]>;
|
|
27
27
|
/** Encode child nodes in order, updating their paths and awaiting async handlers. */
|
|
28
28
|
children(node: ContentNode): Promise<T[]>;
|
|
29
|
-
/** Resolve an image through imageURL;
|
|
29
|
+
/** Resolve an image through imageURL; placeholders without an asset get an empty URL. */
|
|
30
30
|
imageURL(node: ContentNode): Promise<string>;
|
|
31
31
|
}
|
|
32
32
|
interface DecodeContext<T> {
|
|
@@ -38,7 +38,7 @@ interface DecodeContext<T> {
|
|
|
38
38
|
decode(node: T): Promise<ContentNode[]>;
|
|
39
39
|
/** Decode child nodes in order, updating their paths and awaiting async handlers. */
|
|
40
40
|
children(nodes: readonly T[]): Promise<ContentNode[]>;
|
|
41
|
-
/** Resolve a URL through imageAssetID and create an image node;
|
|
41
|
+
/** Resolve a URL through imageAssetID and create an image node; an empty URL is a placeholder. */
|
|
42
42
|
image(reference: ImageReference): Promise<ContentNode>;
|
|
43
43
|
}
|
|
44
44
|
interface EncodeHandlers<T> {
|
|
@@ -190,4 +190,4 @@ type PropertyMapping = {
|
|
|
190
190
|
};
|
|
191
191
|
//#endregion
|
|
192
192
|
export { ImageReference as _, Converter as a, ImportFormatAdapter as b, DecodeHandlers as c, ExportConverter as d, ExportConverterOptions as f, HandlerResult as g, FragmentMapping as h, ConvertedAST as i, EncodeContext as l, FormatAdapter as m, ContentMark as n, ConverterOptions as o, ExportFormatAdapter as p, ContentNode as r, DecodeContext as s, Awaitable as t, EncodeHandlers as u, ImportConverter as v, PropertyMapping as x, ImportConverterOptions as y };
|
|
193
|
-
//# sourceMappingURL=types-
|
|
193
|
+
//# sourceMappingURL=types-DQUKLAU7.d.ts.map
|
package/dist/html.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-
|
|
1
|
+
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
import { Root, RootContent } from "hast";
|
|
3
3
|
//#region src/html.d.ts
|
|
4
4
|
type HTMLNode = Root | RootContent;
|
package/dist/html.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, c as lookup, d as textNode, f as withMark, i as ConversionError, t as createConverter, u as textContent } from "./chunks/core-
|
|
2
|
-
import { n as paragraphContent } from "./chunks/decode-
|
|
1
|
+
import { a as element, c as lookup, d as textNode, f as withMark, i as ConversionError, t as createConverter, u as textContent } from "./chunks/core-BR6Qs_Gz.js";
|
|
2
|
+
import { n as paragraphContent } from "./chunks/decode-DmUqH-b-.js";
|
|
3
3
|
import { fromHtml } from "hast-util-from-html";
|
|
4
4
|
import { toHtml } from "hast-util-to-html";
|
|
5
5
|
//#region src/html.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as ImageReference, a as Converter, b as ImportFormatAdapter, c as DecodeHandlers, d as ExportConverter, f as ExportConverterOptions, g as HandlerResult, h as FragmentMapping, i as ConvertedAST, l as EncodeContext, m as FormatAdapter, n as ContentMark, o as ConverterOptions, p as ExportFormatAdapter, r as ContentNode, s as DecodeContext, t as Awaitable, u as EncodeHandlers, v as ImportConverter, x as PropertyMapping, y as ImportConverterOptions } from "./chunks/types-
|
|
1
|
+
import { _ as ImageReference, a as Converter, b as ImportFormatAdapter, c as DecodeHandlers, d as ExportConverter, f as ExportConverterOptions, g as HandlerResult, h as FragmentMapping, i as ConvertedAST, l as EncodeContext, m as FormatAdapter, n as ContentMark, o as ConverterOptions, p as ExportFormatAdapter, r as ContentNode, s as DecodeContext, t as Awaitable, u as EncodeHandlers, v as ImportConverter, x as PropertyMapping, y as ImportConverterOptions } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
import { HeadingAnchor, getHeadingAnchors } from "./anchors.js";
|
|
3
3
|
//#region src/core.d.ts
|
|
4
4
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getHeadingAnchors } from "./anchors.js";
|
|
2
|
-
import { a as element, d as textNode, f as withMark, i as ConversionError, l as readCodeTitle, n as createExportConverter, o as formatCodeMeta, r as createImportConverter, t as createConverter, u as textContent } from "./chunks/core-
|
|
2
|
+
import { a as element, d as textNode, f as withMark, i as ConversionError, l as readCodeTitle, n as createExportConverter, o as formatCodeMeta, r as createImportConverter, t as createConverter, u as textContent } from "./chunks/core-BR6Qs_Gz.js";
|
|
3
3
|
//#region src/images.ts
|
|
4
4
|
/**
|
|
5
5
|
* Create an async imageURL callback from published asset references.
|
package/dist/markdoc.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-
|
|
1
|
+
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
import Markdoc from "@markdoc/markdoc";
|
|
3
3
|
//#region src/markdoc.d.ts
|
|
4
4
|
type MarkdocNode = InstanceType<typeof Markdoc.Ast.Node>;
|
package/dist/markdoc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, c as lookup, d as textNode, f as withMark, i as ConversionError, s as isJSONValue, t as createConverter, u as textContent } from "./chunks/core-
|
|
2
|
-
import { n as paragraphContent } from "./chunks/decode-
|
|
1
|
+
import { a as element, c as lookup, d as textNode, f as withMark, i as ConversionError, s as isJSONValue, t as createConverter, u as textContent } from "./chunks/core-BR6Qs_Gz.js";
|
|
2
|
+
import { n as paragraphContent } from "./chunks/decode-DmUqH-b-.js";
|
|
3
3
|
import { n as normalizeMarkdown, t as markdownStringifyOptions } from "./chunks/stringify-DdPaV2y4.js";
|
|
4
4
|
import { unified } from "unified";
|
|
5
5
|
import remarkStringify from "remark-stringify";
|
package/dist/markdown.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-
|
|
1
|
+
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
import { t as MarkdownNode } from "./chunks/decode-BLP2Olia.js";
|
|
3
3
|
//#region src/markdown.d.ts
|
|
4
4
|
type MarkdownOptions = ConverterOptions<MarkdownNode>;
|
package/dist/markdown.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createConverter } from "./chunks/core-
|
|
2
|
-
import { t as createMarkdownAdapter } from "./chunks/adapter-
|
|
1
|
+
import { t as createConverter } from "./chunks/core-BR6Qs_Gz.js";
|
|
2
|
+
import { t as createMarkdownAdapter } from "./chunks/adapter-BFwSkezI.js";
|
|
3
3
|
//#region src/markdown.ts
|
|
4
4
|
/** Markdown/GFM adapter for createConverter(), including its parser and node/mark mappings. */
|
|
5
5
|
const markdownAdapter = createMarkdownAdapter();
|
package/dist/mdx.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-
|
|
1
|
+
import { a as Converter, f as ExportConverterOptions, i as ConvertedAST, m as FormatAdapter, o as ConverterOptions, r as ContentNode, y as ImportConverterOptions } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
import { t as MarkdownNode } from "./chunks/decode-BLP2Olia.js";
|
|
3
3
|
import { MdxJsxFlowElement } from "mdast-util-mdx-jsx";
|
|
4
4
|
//#region src/mdx.d.ts
|
package/dist/mdx.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, i as ConversionError, s as isJSONValue, t as createConverter } from "./chunks/core-
|
|
2
|
-
import { t as createMarkdownAdapter } from "./chunks/adapter-
|
|
1
|
+
import { a as element, i as ConversionError, s as isJSONValue, t as createConverter } from "./chunks/core-BR6Qs_Gz.js";
|
|
2
|
+
import { t as createMarkdownAdapter } from "./chunks/adapter-BFwSkezI.js";
|
|
3
3
|
import remarkMDX from "remark-mdx";
|
|
4
4
|
import { parseExpressionAt } from "acorn";
|
|
5
5
|
//#region src/static-expression.ts
|
|
@@ -28,6 +28,26 @@ const staticExpression = (source) => {
|
|
|
28
28
|
//#endregion
|
|
29
29
|
//#region src/mdx.ts
|
|
30
30
|
const markdown = createMarkdownAdapter(remarkMDX);
|
|
31
|
+
const isBlank = (node) => node.type === "text" && !node.value.trim();
|
|
32
|
+
/**
|
|
33
|
+
* A paragraph of elements only, e.g. one-line `<Step>`s in `<Steps>`: the parser reads them as
|
|
34
|
+
* text, but nothing is around them, so they are blocks. Elements between text stay unsupported.
|
|
35
|
+
*/
|
|
36
|
+
const isElementParagraph = (node) => {
|
|
37
|
+
return node.type === "paragraph" && node.children.some((child) => child.type === "mdxJsxTextElement") && node.children.every((child) => child.type === "mdxJsxTextElement" || isBlank(child));
|
|
38
|
+
};
|
|
39
|
+
/** The block form of a one-line element: its content becomes a paragraph. */
|
|
40
|
+
const toFlowElement = (node) => {
|
|
41
|
+
const children = node.children.filter((child) => !isBlank(child));
|
|
42
|
+
return {
|
|
43
|
+
...node,
|
|
44
|
+
type: "mdxJsxFlowElement",
|
|
45
|
+
children: children.length ? [{
|
|
46
|
+
type: "paragraph",
|
|
47
|
+
children
|
|
48
|
+
}] : []
|
|
49
|
+
};
|
|
50
|
+
};
|
|
31
51
|
/** MDX adapter for createConverter(), including its parser and node/mark mappings. */
|
|
32
52
|
const mdxAdapter = {
|
|
33
53
|
...markdown,
|
|
@@ -54,6 +74,10 @@ const mdxAdapter = {
|
|
|
54
74
|
};
|
|
55
75
|
},
|
|
56
76
|
async decode(node, context) {
|
|
77
|
+
if (isElementParagraph(node)) {
|
|
78
|
+
const elements = node.children.filter((child) => child.type === "mdxJsxTextElement");
|
|
79
|
+
return context.children(elements.map(toFlowElement));
|
|
80
|
+
}
|
|
57
81
|
if (node.type !== "mdxJsxFlowElement") return markdown.decode(node, context);
|
|
58
82
|
if (!node.name) throw new ConversionError("MDX fragments require a custom handler", context.path);
|
|
59
83
|
const props = Object.create(null);
|
package/dist/mdx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdx.js","names":[],"sources":["../src/static-expression.ts","../src/mdx.ts"],"sourcesContent":["import { parseExpressionAt } from \"acorn\";\nimport { ConversionError } from \"./utils\";\n\ninterface Expression {\n type: string;\n end: number;\n value?: unknown;\n name?: string;\n regex?: unknown;\n bigint?: unknown;\n elements?: Array<Expression | null>;\n properties?: Expression[];\n key?: Expression;\n computed?: boolean;\n method?: boolean;\n shorthand?: boolean;\n kind?: string;\n operator?: string;\n argument?: Expression;\n}\n\nconst staticExpression = (source: string): unknown => {\n const expression = parseExpressionAt(source, 0, { ecmaVersion: \"latest\" }) as Expression;\n const read = (node: Expression): unknown => {\n if (node.type === \"Literal\" && !node.regex && !node.bigint) return node.value;\n if (node.type === \"ArrayExpression\")\n return node.elements!.map((item) => {\n if (!item) throw new ConversionError(\"Array holes are not static JSON values\");\n\n return read(item);\n });\n if (node.type === \"ObjectExpression\")\n return Object.fromEntries(\n node.properties!.map((property) => {\n if (\n property.type !== \"Property\" ||\n property.computed ||\n property.method ||\n property.shorthand ||\n property.kind !== \"init\"\n ) {\n throw new ConversionError(\"Only static object properties are supported\");\n }\n const key = property.key!;\n\n return [\n key.type === \"Identifier\" ? key.name : String(key.value),\n read(property.value as Expression)\n ];\n })\n );\n if (node.type === \"UnaryExpression\" && [\"-\", \"+\"].includes(node.operator || \"\")) {\n const value = read(node.argument!);\n\n if (typeof value === \"number\") return node.operator === \"-\" ? -value : value;\n }\n throw new ConversionError(`Unsupported dynamic expression: ${node.type}`);\n };\n\n if (source.slice(expression.end).trim())\n throw new ConversionError(\"Unexpected content after static expression\");\n\n return read(expression);\n};\n\nexport { staticExpression };\n","import remarkMDX from \"remark-mdx\";\nimport type { MdxJsxFlowElement } from \"mdast-util-mdx-jsx\";\nimport { createConverter } from \"./core\";\nimport { createMarkdownAdapter } from \"./markdown/adapter\";\nimport { element, isJSONValue, ConversionError } from \"./utils\";\nimport { staticExpression } from \"./static-expression\";\nimport type { MarkdownNode } from \"./markdown/decode\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype MDXNode = MarkdownNode | MdxJsxFlowElement;\ntype MDXOptions = ConverterOptions<MDXNode>;\n\nconst markdown = createMarkdownAdapter(remarkMDX);\n/** MDX adapter for createConverter(), including its parser and node/mark mappings. */\nconst mdxAdapter: FormatAdapter<MDXNode> = {\n ...markdown,\n elementName: (node) =>\n node.type === \"mdxJsxFlowElement\" || node.type === \"mdxJsxTextElement\"\n ? node.name || undefined\n : undefined,\n async encode(node, context) {\n if (node.type !== \"element\") return markdown.encode(node, context);\n\n const name = String(node.attrs?.name || \"Element\");\n const props = (node.attrs?.props || {}) as Record<string, unknown>;\n const children = await context.children(node);\n\n if (!isJSONValue(props))\n throw new ConversionError(\"MDX element properties must be static JSON values\", context.path);\n\n // Validate names and build a source form using the same static element rules.\n element(name, props, []);\n return {\n type: \"mdxJsxFlowElement\",\n name,\n attributes: Object.entries(props).map(([name, value]) => ({\n type: \"mdxJsxAttribute\",\n name,\n value:\n typeof value === \"string\"\n ? value\n : { type: \"mdxJsxAttributeValueExpression\", value: JSON.stringify(value) }\n })),\n children\n } as Extract<MarkdownNode, { type: \"mdxJsxFlowElement\" }>;\n },\n async decode(node, context) {\n if (node.type !== \"mdxJsxFlowElement\") return markdown.decode(node, context);\n if (!node.name)\n throw new ConversionError(\"MDX fragments require a custom handler\", context.path);\n\n const props: Record<string, unknown> = Object.create(null);\n\n for (const attribute of node.attributes) {\n if (attribute.type !== \"mdxJsxAttribute\")\n throw new ConversionError(\"MDX spread attributes require a custom handler\", context.path);\n\n props[attribute.name] =\n attribute.value === null || attribute.value === undefined\n ? true\n : typeof attribute.value === \"string\"\n ? attribute.value\n : staticExpression(attribute.value.value);\n }\n return element(node.name, { ...props }, await context.children(node.children));\n }\n};\n/**\n * Create a reusable async MDX converter with application-specific defaults.\n * @param options - Default mappings and handlers; per-call maps merge by key and callbacks may be async.\n * @returns String and AST import/export methods. Defaults use an H1 title, unwrap fragments, and omit properties.\n * Custom elements use static JSON properties; executable expressions require custom handlers.\n */\nconst createMDXConverter = (options?: MDXOptions) => createConverter(mdxAdapter, options);\nconst converter = createMDXConverter();\n/**\n * Export ProseMirror JSON as MDX.\n * @param document - Entry or fragment document. Fragment wrappers are removed by default.\n * @param options - Title/property/fragment mappings and async handlers; imageURL resolves images.\n * @returns Serialized MDX. Omitted metadata and unwrapped fragment boundaries are not recoverable.\n * @throws ConversionError for unsupported content, unresolved images, or invalid mappings; handler errors pass through.\n */\nconst toMDX = converter.encode;\n/**\n * Import MDX as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use static JSON properties; executable expressions require custom handlers.\n * @param options - Import mappings and async handlers. imageAssetID must resolve image URLs.\n * @returns An entry document; use document: \"fragment\" to omit the title and retain the first H1 as body content.\n * @throws ConversionError for unsupported content/mappings; parser and handler errors pass through.\n */\nconst fromMDX = converter.decode;\n/**\n * Export ProseMirror JSON as a MDX AST with separate frontmatter.\n * @param document - Source entry or fragment document.\n * @param options - Export mappings and async handlers, including imageURL for images.\n * @returns The format tree and metadata without string serialization.\n * @throws The same conversion errors as toMDX(), including unsupported frontmatter mappings.\n */\nconst toMDXAST = converter.toAST;\n/**\n * Import a parsed MDX AST and its frontmatter as ProseMirror JSON.\n * @param input - Tree and frontmatter object; use an empty object when metadata is absent.\n * @param options - Import mappings and async handlers, including imageAssetID for images.\n * @returns An entry document by default, or a fragment document when requested.\n * @throws The same conversion errors as fromMDX(), excluding string-parser errors.\n */\nconst fromMDXAST = converter.fromAST;\n\nexport { createMDXConverter, mdxAdapter, toMDX, fromMDX, toMDXAST, fromMDXAST };\nexport type { MDXOptions, MDXNode };\n"],"mappings":";;;;;AAqBA,MAAM,oBAAoB,WAA4B;CACpD,MAAM,aAAa,kBAAkB,QAAQ,GAAG,EAAE,aAAa,SAAS,CAAC;CACzE,MAAM,QAAQ,SAA8B;EAC1C,IAAI,KAAK,SAAS,aAAa,CAAC,KAAK,SAAS,CAAC,KAAK,QAAQ,OAAO,KAAK;EACxE,IAAI,KAAK,SAAS,mBAChB,OAAO,KAAK,SAAU,KAAK,SAAS;GAClC,IAAI,CAAC,MAAM,MAAM,IAAI,gBAAgB,wCAAwC;GAE7E,OAAO,KAAK,IAAI;EAClB,CAAC;EACH,IAAI,KAAK,SAAS,oBAChB,OAAO,OAAO,YACZ,KAAK,WAAY,KAAK,aAAa;GACjC,IACE,SAAS,SAAS,cAClB,SAAS,YACT,SAAS,UACT,SAAS,aACT,SAAS,SAAS,QAElB,MAAM,IAAI,gBAAgB,6CAA6C;GAEzE,MAAM,MAAM,SAAS;GAErB,OAAO,CACL,IAAI,SAAS,eAAe,IAAI,OAAO,OAAO,IAAI,KAAK,GACvD,KAAK,SAAS,KAAmB,CACnC;EACF,CAAC,CACH;EACF,IAAI,KAAK,SAAS,qBAAqB,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,KAAK,YAAY,EAAE,GAAG;GAC/E,MAAM,QAAQ,KAAK,KAAK,QAAS;GAEjC,IAAI,OAAO,UAAU,UAAU,OAAO,KAAK,aAAa,MAAM,CAAC,QAAQ;EACzE;EACA,MAAM,IAAI,gBAAgB,mCAAmC,KAAK,MAAM;CAC1E;CAEA,IAAI,OAAO,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,GACpC,MAAM,IAAI,gBAAgB,4CAA4C;CAExE,OAAO,KAAK,UAAU;AACxB;;;ACnDA,MAAM,WAAW,sBAAsB,SAAS;;AAEhD,MAAM,aAAqC;CACzC,GAAG;CACH,cAAc,SACZ,KAAK,SAAS,uBAAuB,KAAK,SAAS,sBAC/C,KAAK,QAAQ,KAAA,IACb,KAAA;CACN,MAAM,OAAO,MAAM,SAAS;EAC1B,IAAI,KAAK,SAAS,WAAW,OAAO,SAAS,OAAO,MAAM,OAAO;EAEjE,MAAM,OAAO,OAAO,KAAK,OAAO,QAAQ,SAAS;EACjD,MAAM,QAAS,KAAK,OAAO,SAAS,CAAC;EACrC,MAAM,WAAW,MAAM,QAAQ,SAAS,IAAI;EAE5C,IAAI,CAAC,YAAY,KAAK,GACpB,MAAM,IAAI,gBAAgB,qDAAqD,QAAQ,IAAI;EAG7F,QAAQ,MAAM,OAAO,CAAC,CAAC;EACvB,OAAO;GACL,MAAM;GACN;GACA,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY;IACxD,MAAM;IACN;IACA,OACE,OAAO,UAAU,WACb,QACA;KAAE,MAAM;KAAkC,OAAO,KAAK,UAAU,KAAK;IAAE;GAC/E,EAAE;GACF;EACF;CACF;CACA,MAAM,OAAO,MAAM,SAAS;EAC1B,IAAI,KAAK,SAAS,qBAAqB,OAAO,SAAS,OAAO,MAAM,OAAO;EAC3E,IAAI,CAAC,KAAK,MACR,MAAM,IAAI,gBAAgB,0CAA0C,QAAQ,IAAI;EAElF,MAAM,QAAiC,OAAO,OAAO,IAAI;EAEzD,KAAK,MAAM,aAAa,KAAK,YAAY;GACvC,IAAI,UAAU,SAAS,mBACrB,MAAM,IAAI,gBAAgB,kDAAkD,QAAQ,IAAI;GAE1F,MAAM,UAAU,QACd,UAAU,UAAU,QAAQ,UAAU,UAAU,KAAA,IAC5C,OACA,OAAO,UAAU,UAAU,WACzB,UAAU,QACV,iBAAiB,UAAU,MAAM,KAAK;EAChD;EACA,OAAO,QAAQ,KAAK,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,QAAQ,SAAS,KAAK,QAAQ,CAAC;CAC/E;AACF;;;;;;;AAOA,MAAM,sBAAsB,YAAyB,gBAAgB,YAAY,OAAO;AACxF,MAAM,YAAY,mBAAmB;;;;;;;;AAQrC,MAAM,QAAQ,UAAU;;;;;;;;AAQxB,MAAM,UAAU,UAAU;;;;;;;;AAQ1B,MAAM,WAAW,UAAU;;;;;;;;AAQ3B,MAAM,aAAa,UAAU"}
|
|
1
|
+
{"version":3,"file":"mdx.js","names":[],"sources":["../src/static-expression.ts","../src/mdx.ts"],"sourcesContent":["import { parseExpressionAt } from \"acorn\";\nimport { ConversionError } from \"./utils\";\n\ninterface Expression {\n type: string;\n end: number;\n value?: unknown;\n name?: string;\n regex?: unknown;\n bigint?: unknown;\n elements?: Array<Expression | null>;\n properties?: Expression[];\n key?: Expression;\n computed?: boolean;\n method?: boolean;\n shorthand?: boolean;\n kind?: string;\n operator?: string;\n argument?: Expression;\n}\n\nconst staticExpression = (source: string): unknown => {\n const expression = parseExpressionAt(source, 0, { ecmaVersion: \"latest\" }) as Expression;\n const read = (node: Expression): unknown => {\n if (node.type === \"Literal\" && !node.regex && !node.bigint) return node.value;\n if (node.type === \"ArrayExpression\")\n return node.elements!.map((item) => {\n if (!item) throw new ConversionError(\"Array holes are not static JSON values\");\n\n return read(item);\n });\n if (node.type === \"ObjectExpression\")\n return Object.fromEntries(\n node.properties!.map((property) => {\n if (\n property.type !== \"Property\" ||\n property.computed ||\n property.method ||\n property.shorthand ||\n property.kind !== \"init\"\n ) {\n throw new ConversionError(\"Only static object properties are supported\");\n }\n const key = property.key!;\n\n return [\n key.type === \"Identifier\" ? key.name : String(key.value),\n read(property.value as Expression)\n ];\n })\n );\n if (node.type === \"UnaryExpression\" && [\"-\", \"+\"].includes(node.operator || \"\")) {\n const value = read(node.argument!);\n\n if (typeof value === \"number\") return node.operator === \"-\" ? -value : value;\n }\n throw new ConversionError(`Unsupported dynamic expression: ${node.type}`);\n };\n\n if (source.slice(expression.end).trim())\n throw new ConversionError(\"Unexpected content after static expression\");\n\n return read(expression);\n};\n\nexport { staticExpression };\n","import remarkMDX from \"remark-mdx\";\nimport type { MdxJsxFlowElement } from \"mdast-util-mdx-jsx\";\nimport { createConverter } from \"./core\";\nimport { createMarkdownAdapter } from \"./markdown/adapter\";\nimport { element, isJSONValue, ConversionError } from \"./utils\";\nimport { staticExpression } from \"./static-expression\";\nimport type { MarkdownNode } from \"./markdown/decode\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype MDXNode = MarkdownNode | MdxJsxFlowElement;\ntype MDXOptions = ConverterOptions<MDXNode>;\ntype Paragraph = Extract<MarkdownNode, { type: \"paragraph\" }>;\ntype PhrasingNode = Paragraph[\"children\"][number];\ntype TextElement = Extract<PhrasingNode, { type: \"mdxJsxTextElement\" }>;\n\nconst markdown = createMarkdownAdapter(remarkMDX);\nconst isBlank = (node: PhrasingNode) => node.type === \"text\" && !node.value.trim();\n/**\n * A paragraph of elements only, e.g. one-line `<Step>`s in `<Steps>`: the parser reads them as\n * text, but nothing is around them, so they are blocks. Elements between text stay unsupported.\n */\nconst isElementParagraph = (node: MDXNode): node is Paragraph => {\n return (\n node.type === \"paragraph\" &&\n node.children.some((child) => child.type === \"mdxJsxTextElement\") &&\n node.children.every((child) => child.type === \"mdxJsxTextElement\" || isBlank(child))\n );\n};\n/** The block form of a one-line element: its content becomes a paragraph. */\nconst toFlowElement = (node: TextElement): MdxJsxFlowElement => {\n const children = node.children.filter((child) => !isBlank(child));\n\n return {\n ...node,\n type: \"mdxJsxFlowElement\",\n children: children.length ? [{ type: \"paragraph\", children }] : []\n };\n};\n/** MDX adapter for createConverter(), including its parser and node/mark mappings. */\nconst mdxAdapter: FormatAdapter<MDXNode> = {\n ...markdown,\n elementName: (node) =>\n node.type === \"mdxJsxFlowElement\" || node.type === \"mdxJsxTextElement\"\n ? node.name || undefined\n : undefined,\n async encode(node, context) {\n if (node.type !== \"element\") return markdown.encode(node, context);\n\n const name = String(node.attrs?.name || \"Element\");\n const props = (node.attrs?.props || {}) as Record<string, unknown>;\n const children = await context.children(node);\n\n if (!isJSONValue(props))\n throw new ConversionError(\"MDX element properties must be static JSON values\", context.path);\n\n // Validate names and build a source form using the same static element rules.\n element(name, props, []);\n return {\n type: \"mdxJsxFlowElement\",\n name,\n attributes: Object.entries(props).map(([name, value]) => ({\n type: \"mdxJsxAttribute\",\n name,\n value:\n typeof value === \"string\"\n ? value\n : { type: \"mdxJsxAttributeValueExpression\", value: JSON.stringify(value) }\n })),\n children\n } as Extract<MarkdownNode, { type: \"mdxJsxFlowElement\" }>;\n },\n async decode(node, context) {\n if (isElementParagraph(node)) {\n const elements = node.children.filter((child) => child.type === \"mdxJsxTextElement\");\n\n return context.children(elements.map(toFlowElement));\n }\n\n if (node.type !== \"mdxJsxFlowElement\") return markdown.decode(node, context);\n if (!node.name)\n throw new ConversionError(\"MDX fragments require a custom handler\", context.path);\n\n const props: Record<string, unknown> = Object.create(null);\n\n for (const attribute of node.attributes) {\n if (attribute.type !== \"mdxJsxAttribute\")\n throw new ConversionError(\"MDX spread attributes require a custom handler\", context.path);\n\n props[attribute.name] =\n attribute.value === null || attribute.value === undefined\n ? true\n : typeof attribute.value === \"string\"\n ? attribute.value\n : staticExpression(attribute.value.value);\n }\n return element(node.name, { ...props }, await context.children(node.children));\n }\n};\n/**\n * Create a reusable async MDX converter with application-specific defaults.\n * @param options - Default mappings and handlers; per-call maps merge by key and callbacks may be async.\n * @returns String and AST import/export methods. Defaults use an H1 title, unwrap fragments, and omit properties.\n * Custom elements use static JSON properties; executable expressions require custom handlers.\n */\nconst createMDXConverter = (options?: MDXOptions) => createConverter(mdxAdapter, options);\nconst converter = createMDXConverter();\n/**\n * Export ProseMirror JSON as MDX.\n * @param document - Entry or fragment document. Fragment wrappers are removed by default.\n * @param options - Title/property/fragment mappings and async handlers; imageURL resolves images.\n * @returns Serialized MDX. Omitted metadata and unwrapped fragment boundaries are not recoverable.\n * @throws ConversionError for unsupported content, unresolved images, or invalid mappings; handler errors pass through.\n */\nconst toMDX = converter.encode;\n/**\n * Import MDX as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use static JSON properties; executable expressions require custom handlers.\n * @param options - Import mappings and async handlers. imageAssetID must resolve image URLs.\n * @returns An entry document; use document: \"fragment\" to omit the title and retain the first H1 as body content.\n * @throws ConversionError for unsupported content/mappings; parser and handler errors pass through.\n */\nconst fromMDX = converter.decode;\n/**\n * Export ProseMirror JSON as a MDX AST with separate frontmatter.\n * @param document - Source entry or fragment document.\n * @param options - Export mappings and async handlers, including imageURL for images.\n * @returns The format tree and metadata without string serialization.\n * @throws The same conversion errors as toMDX(), including unsupported frontmatter mappings.\n */\nconst toMDXAST = converter.toAST;\n/**\n * Import a parsed MDX AST and its frontmatter as ProseMirror JSON.\n * @param input - Tree and frontmatter object; use an empty object when metadata is absent.\n * @param options - Import mappings and async handlers, including imageAssetID for images.\n * @returns An entry document by default, or a fragment document when requested.\n * @throws The same conversion errors as fromMDX(), excluding string-parser errors.\n */\nconst fromMDXAST = converter.fromAST;\n\nexport { createMDXConverter, mdxAdapter, toMDX, fromMDX, toMDXAST, fromMDXAST };\nexport type { MDXOptions, MDXNode };\n"],"mappings":"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"}
|
package/dist/text.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as ExportConverter, f as ExportConverterOptions, i as ConvertedAST, p as ExportFormatAdapter, r as ContentNode } from "./chunks/types-
|
|
1
|
+
import { d as ExportConverter, f as ExportConverterOptions, i as ConvertedAST, p as ExportFormatAdapter, r as ContentNode } from "./chunks/types-DQUKLAU7.js";
|
|
2
2
|
//#region src/text.d.ts
|
|
3
3
|
interface TextNode {
|
|
4
4
|
type: "text" | "root";
|
package/dist/text.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as ConversionError, n as createExportConverter, u as textContent } from "./chunks/core-
|
|
1
|
+
import { i as ConversionError, n as createExportConverter, u as textContent } from "./chunks/core-BR6Qs_Gz.js";
|
|
2
2
|
//#region src/text.ts
|
|
3
3
|
const getText = (node) => node.value ?? (node.children || []).map(getText).join("");
|
|
4
4
|
/** Export-only plain-text adapter. Formatting is discarded; import methods are not provided. */
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core-DpOn10DI.js","names":[],"sources":["../../src/utils.ts","../../src/frontmatter.ts","../../src/core.ts"],"sourcesContent":["import type { ContentMark, ContentNode, HandlerResult } from \"./types\";\n\n/** A conversion failure, optionally located at a child-index path in the source tree. */\nclass ConversionError extends Error {\n /**\n * @param message - Description of the unsupported content or invalid mapping.\n * @param path - Child indexes appended to the message; defaults to the document root.\n */\n constructor(\n message: string,\n readonly path: readonly number[] = []\n ) {\n super(`${message}${path.length ? ` at content[${path.join(\"][\")}]` : \"\"}`);\n this.name = \"ConversionError\";\n }\n}\n\nconst lookup = <T>(record: Record<string, T> | undefined, name: string): T | undefined => {\n return record && Object.hasOwn(record, name) ? record[name] : undefined;\n};\nconst array = <T>(value: HandlerResult<T>): T[] =>\n value === null ? [] : Array.isArray(value) ? value : [value];\n/**\n * Concatenate a node's descendant text without changing the source.\n * @param node - ProseMirror node to read.\n * @returns Raw text with no added block separators, markup, or hard-break replacement.\n */\nconst textContent = (node: ContentNode): string =>\n node.text ?? (node.content || []).map(textContent).join(\"\");\n/**\n * Create text content suitable for a node handler.\n * @param text - Literal text to include.\n * @returns One text node, or an empty array for an empty string.\n */\nconst textNode = (text: string): ContentNode[] => (text ? [{ type: \"text\", text }] : []);\n/**\n * Append a mark to all descendant text nodes without modifying the input nodes.\n * @param nodes - Content to mark. Existing marks are retained, including duplicates.\n * @param mark - Mark to append to each text node.\n * @returns Mapped nodes; unchanged leaf nodes and existing marks may retain their references.\n */\nconst withMark = (nodes: ContentNode[], mark: ContentMark): ContentNode[] =>\n nodes.map((node) => {\n if (node.type === \"text\") return { ...node, marks: [...(node.marks || []), mark] };\n\n return node.content ? { ...node, content: withMark(node.content, mark) } : node;\n });\nconst isJSONValue = (value: unknown): boolean => {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (Array.isArray(value)) return value.every(isJSONValue);\n if (typeof value !== \"object\" || Object.getPrototypeOf(value) !== Object.prototype) return false;\n\n return Object.values(value).every(isJSONValue);\n};\n/**\n * Create an Andesine element node with static JSON properties and a source representation.\n * @param name - Element name, starting with a letter and containing letters, digits, _, ., or -.\n * @param props - Static JSON properties with valid attribute names; executable expressions are rejected.\n * @param content - Child nodes. The supplied content array is retained.\n * @param selfClosing - Whether the source uses a self-closing tag; defaults to true for empty content.\n * @returns A ProseMirror element node for use in import handlers.\n * @throws ConversionError for invalid names, property keys, or non-JSON property values.\n */\nconst element = (\n name: string,\n props: Record<string, unknown>,\n content: ContentNode[],\n selfClosing = !content.length\n): ContentNode => {\n if (!/^[A-Za-z][\\w.-]*$/.test(name) || !isJSONValue(props)) {\n throw new ConversionError(\"Elements require a valid name and static JSON properties\");\n }\n const attributes = Object.entries(props)\n .map(([key, value]) => {\n if (!/^[A-Za-z][\\w-]*$/.test(key))\n throw new ConversionError(`Invalid element property: ${key}`);\n\n return typeof value === \"string\"\n ? ` ${key}=${JSON.stringify(value)}`\n : ` ${key}={${JSON.stringify(value)}}`;\n })\n .join(\"\");\n\n return {\n type: \"element\",\n attrs: { name, props, selfClosing, source: `<${name}${attributes}${selfClosing ? \" /\" : \"\"}>` },\n ...(content.length ? { content } : {})\n };\n};\n\n/** A code fence's title from its meta, e.g. `title=\"install.sh\"`. */\nconst readCodeTitle = (meta?: string | null): string | undefined => {\n const match = meta?.match(/title=(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/);\n\n return match?.[1] ?? match?.[2] ?? match?.[3];\n};\n/** A code fence's meta for its title, quoted to keep spaces. */\nconst formatCodeMeta = (title: unknown): string | null => {\n if (typeof title !== \"string\" || !title) return null;\n\n return title.includes('\"') ? `title='${title}'` : `title=\"${title}\"`;\n};\n\nexport {\n ConversionError,\n lookup,\n array,\n element,\n formatCodeMeta,\n isJSONValue,\n readCodeTitle,\n textContent,\n textNode,\n withMark\n};\n","import { parseDocument, stringify } from \"yaml\";\nimport { ConversionError, isJSONValue } from \"./utils\";\n\nconst readFrontmatter = (\n source: string\n): { source: string; frontmatter: Record<string, unknown> } => {\n const match = /^(?:\\uFEFF)?---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/.exec(source);\n\n if (!match) return { source, frontmatter: {} };\n\n const document = parseDocument(match[1], { schema: \"core\", uniqueKeys: true });\n\n if (document.errors.length)\n throw new ConversionError(`Invalid frontmatter: ${document.errors[0].message}`);\n\n const value: unknown = document.toJS({ maxAliasCount: 100 });\n\n if (!value || Array.isArray(value) || typeof value !== \"object\" || !isJSONValue(value)) {\n throw new ConversionError(\"Frontmatter must contain an object with static JSON values\");\n }\n return { source: source.slice(match[0].length), frontmatter: value as Record<string, unknown> };\n};\nconst writeFrontmatter = (frontmatter: Record<string, unknown>, source: string): string => {\n return Object.keys(frontmatter).length\n ? `---\\n${stringify(frontmatter)}---\\n\\n${source}`\n : source;\n};\n\nexport { readFrontmatter, writeFrontmatter };\n","import { getHeadingAnchors } from \"./anchors\";\nimport { readFrontmatter, writeFrontmatter } from \"./frontmatter\";\nimport { array, ConversionError, lookup, textContent, textNode } from \"./utils\";\nimport type {\n ContentNode,\n ConvertedAST,\n Converter,\n ConverterOptions,\n DecodeContext,\n EncodeContext,\n ExportConverter,\n ExportConverterOptions,\n ExportFormatAdapter,\n ImportConverter,\n ImportConverterOptions,\n ImportFormatAdapter,\n FormatAdapter\n} from \"./types\";\n\n/**\n * Build an async export-only converter using the shared content mappings.\n *\n * @param adapter - Root builder, serializer, and export node/mark handlers. No import stubs are needed.\n * @param defaults - Reusable options. Per-call handler maps and named fragment mappings merge by key.\n * @returns Only encode() and toAST(), both async. Handlers and image callbacks may be async.\n * Import methods are absent at runtime and in TypeScript. No content is saved.\n * Unsupported nodes and marks are handled by the adapter, usually by throwing ConversionError.\n * Defaults render titles as H1s, unwrap fragments, and omit properties. Removed boundaries and\n * omitted data cannot be recovered on import; choose explicit mappings when preservation matters.\n */\nconst createExportConverter = <T>(\n adapter: ExportFormatAdapter<T>,\n defaults: ExportConverterOptions<T> = {}\n): ExportConverter<T> => {\n const toAST = async (\n document: ContentNode,\n options: ExportConverterOptions<T> = {}\n ): Promise<ConvertedAST<T>> => {\n const settings = mergeOptions(defaults, options);\n const anchors = new Map(\n getHeadingAnchors(document).map((heading) => [heading.path.join(\".\"), heading.anchor])\n );\n const frontmatter: Record<string, unknown> = Object.create(null);\n const encode = async (node: ContentNode, path: readonly number[]): Promise<T[]> => {\n // Code handlers consume plain text, so code must be the innermost mark.\n const marks = [...(node.marks || [])].sort(\n (first, second) => Number(first.type === \"code\") - Number(second.type === \"code\")\n );\n const context: EncodeContext<T> = {\n anchor: node.type === \"heading\" ? anchors.get(path.join(\".\")) : undefined,\n options: settings,\n path,\n encode: (child) => encode(child, path),\n children: async (parent) => {\n const children: T[] = [];\n\n for (const [index, child] of (parent.content || []).entries())\n children.push(...(await encode(child, [...path, index])));\n return children;\n },\n imageURL: async (image) => {\n const url = await settings.imageURL?.(image);\n\n if (!url)\n throw new ConversionError(\"An imageURL callback must resolve the image asset\", path);\n return url;\n }\n };\n const handlers = settings.encode;\n const elementName = node.type === \"element\" ? String(node.attrs?.name || \"\") : undefined;\n const handler = elementName\n ? (lookup(handlers?.elements, elementName) ??\n lookup(handlers?.elements, \"*\") ??\n lookup(handlers?.nodes, \"element\") ??\n lookup(handlers?.nodes, \"*\"))\n : (lookup(handlers?.nodes, node.type) ?? lookup(handlers?.nodes, \"*\"));\n let result: T[];\n\n if (handler) {\n result = array(await handler(node, context));\n } else if (node.type === \"doc\") {\n result = await context.children(node);\n } else if (node.type === \"title\") {\n const title = settings.title ?? \"heading\";\n\n if (title === \"omit\") return [];\n if (typeof title === \"object\") {\n setMetadata(frontmatter, title.key || \"title\", textContent(node));\n return [];\n }\n result = array(\n await adapter.encode({ ...node, type: \"heading\", attrs: { level: 1 } }, context)\n );\n } else if (node.type === \"property\") {\n const mapping = settings.properties ?? \"omit\";\n const name = String(node.attrs?.label || \"Property\");\n const type = String(node.attrs?.type || \"text\");\n const value = node.attrs?.value ?? \"\";\n const normalized = type === \"number\" ? (value === \"\" ? null : Number(value)) : value;\n\n if (mapping === \"omit\") return [];\n\n if (mapping.as === \"frontmatter\") {\n setMetadata(frontmatter, name, normalized);\n return [];\n }\n result = await context.encode({\n type: \"element\",\n attrs: {\n name: mapping.name,\n // The type is written only when import can't infer it from the value.\n props: {\n name,\n ...(getPropertyType(normalized) !== type && { type }),\n value: normalized\n },\n selfClosing: true\n }\n });\n } else if (node.type === \"fragment\") {\n const name = String(node.attrs?.name || \"Content\");\n const mapping =\n lookup(settings.fragments?.named, name) ?? settings.fragments?.default ?? \"unwrap\";\n\n if (mapping === \"omit\") return [];\n if (mapping === \"unwrap\") return context.children(node);\n\n result = await context.encode({\n type: \"element\",\n attrs: { name: mapping.name, props: { name }, selfClosing: false },\n content: node.content\n });\n } else {\n result = array(await adapter.encode(node, context));\n }\n if (!result.length) return result;\n\n for (const mark of marks.reverse()) {\n const handler = lookup(handlers?.marks, mark.type) ?? lookup(handlers?.marks, \"*\");\n\n result = array(\n await (handler ? handler(mark, result, context) : adapter.mark(mark, result, context))\n );\n }\n return result;\n };\n const children = await encode(document, []);\n\n if (!adapter.frontmatter && Object.keys(frontmatter).length)\n throw new ConversionError(`${adapter.name} does not support frontmatter`);\n\n return { tree: adapter.root(children), frontmatter };\n };\n\n return {\n toAST,\n async encode(document: ContentNode, options?: ExportConverterOptions<T>): Promise<string> {\n const result = await toAST(document, options);\n\n return writeFrontmatter(result.frontmatter, await adapter.stringify(result.tree));\n }\n };\n};\n\n/**\n * Build an async import-only converter using the shared content mappings.\n *\n * @param adapter - Parser, decode handler, and node-type lookup. No export stubs are needed.\n * @param defaults - Reusable import mappings and handlers, merged by key with per-call overrides.\n * @returns Only decode() and fromAST(), both async. Parsers, handlers, and image callbacks may\n * be async. Export methods are absent at runtime and in TypeScript. No content is saved.\n * Imports create an entry with a title by default; document: \"fragment\" retains headings as body\n * content. Unsupported input is handled by the adapter; parser and handler errors pass through.\n */\nconst createImportConverter = <T>(\n adapter: ImportFormatAdapter<T>,\n defaults: ImportConverterOptions<T> = {}\n): ImportConverter<T> => {\n const fromAST = async (\n input: ConvertedAST<T>,\n options: ImportConverterOptions<T> = {}\n ): Promise<ContentNode> => {\n const settings = mergeOptions(defaults, options);\n const decode = async (node: T, path: readonly number[]): Promise<ContentNode[]> => {\n const context: DecodeContext<T> = {\n options: settings,\n path,\n decode: (child) => decode(child, path),\n children: async (children) => {\n const output: ContentNode[] = [];\n\n for (const [index, child] of children.entries())\n output.push(...(await decode(child, [...path, index])));\n return output;\n },\n image: async (image) => {\n const assetID = await settings.imageAssetID?.(image);\n\n if (!assetID)\n throw new ConversionError(\"An imageAssetID callback must resolve the image URL\", path);\n return { type: \"image\", attrs: { assetID, alt: image.alt, caption: image.title || \"\" } };\n }\n };\n const handlers = settings.decode;\n const type = adapter.type(node);\n const name = adapter.elementName?.(node);\n const mark = adapter.markName?.(node);\n const handler =\n (name\n ? (lookup(handlers?.elements, name) ?? lookup(handlers?.elements, \"*\"))\n : undefined) ??\n (mark ? (lookup(handlers?.marks, mark) ?? lookup(handlers?.marks, \"*\")) : undefined) ??\n lookup(handlers?.nodes, type) ??\n lookup(handlers?.nodes, \"*\");\n const result = array(\n await (handler ? handler(node, context) : adapter.decode(node, context))\n );\n\n return result.flatMap((content) => {\n if (content.type !== \"element\") return [content];\n\n const props = content.attrs?.props as Record<string, unknown> | undefined;\n const propertyMapping =\n typeof settings.properties === \"object\" && settings.properties.as === \"element\"\n ? settings.properties\n : undefined;\n\n if (propertyMapping?.name === content.attrs?.name) {\n if (typeof props?.name !== \"string\") {\n throw new ConversionError(\"Property elements require a name\", path);\n }\n\n return [createProperty(props.name, props.value, props.type)];\n }\n\n const fragmentName = typeof props?.name === \"string\" ? props.name : undefined;\n const mapping = fragmentName\n ? (lookup(settings.fragments?.named, fragmentName) ?? settings.fragments?.default)\n : undefined;\n\n if (mapping && typeof mapping === \"object\" && mapping.name === content.attrs?.name) {\n return [\n {\n type: \"fragment\",\n attrs: { name: fragmentName },\n content: content.content || [{ type: \"paragraph\" }]\n }\n ];\n }\n return [content];\n });\n };\n const content = await decode(input.tree, []);\n const title = settings.title ?? \"heading\";\n const titleKey = typeof title === \"object\" ? title.key || \"title\" : undefined;\n const properties: ContentNode[] = [];\n let titleText = \"\";\n\n if (titleKey && input.frontmatter[titleKey] !== undefined)\n titleText = String(input.frontmatter[titleKey]);\n if (\n title === \"heading\" &&\n settings.document !== \"fragment\" &&\n content[0]?.type === \"heading\" &&\n content[0].attrs?.level === 1\n ) {\n titleText = textContent(content.shift()!);\n }\n if (settings.properties && settings.properties !== \"omit\") {\n for (const [label, value] of Object.entries(input.frontmatter)) {\n if (label === titleKey) continue;\n\n properties.push(createProperty(label, value));\n }\n }\n const body: ContentNode[] = settings.targetFragment\n ? [\n {\n type: \"fragment\",\n attrs: { name: settings.targetFragment },\n content: content.length ? content : [{ type: \"paragraph\" }]\n }\n ]\n : content;\n\n return {\n type: \"doc\",\n content: [\n ...(settings.document === \"fragment\"\n ? []\n : [{ type: \"title\", content: textNode(titleText) }]),\n ...properties,\n ...(body.length ? body : [{ type: \"paragraph\" }])\n ]\n };\n };\n\n return {\n fromAST,\n async decode(source: string, options?: ImportConverterOptions<T>): Promise<ContentNode> {\n const input = adapter.frontmatter ? readFrontmatter(source) : { source, frontmatter: {} };\n\n return fromAST(\n { tree: await adapter.parse(input.source), frontmatter: input.frontmatter },\n options\n );\n }\n };\n};\n\n/**\n * Build an async converter for a custom format that supports both import and export.\n *\n * @param adapter - Full adapter with parser, serializer, and mappings for both directions.\n * @param defaults - Shared defaults and direction-specific handlers. Per-call maps merge by key.\n * @returns encode(), toAST(), decode(), and fromAST(), composed from the one-way factories.\n * Each method accepts options for its own direction. No content is saved or uploaded.\n * Defaults render titles as H1s, unwrap fragments, and omit properties. Removed boundaries and\n * omitted data cannot be recovered on import; choose explicit mappings when preservation matters.\n */\nconst createConverter = <T>(\n adapter: FormatAdapter<T>,\n defaults: ConverterOptions<T> = {}\n): Converter<T> => ({\n ...createExportConverter(adapter, defaults),\n ...createImportConverter(adapter, defaults)\n});\nconst PROPERTY_TYPES = [\"text\", \"number\", \"checkbox\", \"date\", \"url\", \"select\", \"multi-select\"];\nconst getPropertyType = (value: unknown): string => {\n const stringArray = Array.isArray(value) && value.every((item) => typeof item === \"string\");\n\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"boolean\") return \"checkbox\";\n if (stringArray) return \"multi-select\";\n\n return \"text\";\n};\nconst createProperty = (label: string, value: unknown, type?: unknown): ContentNode => {\n const propertyType = type === undefined ? getPropertyType(value) : type;\n const textValue = ![\"number\", \"checkbox\", \"multi-select\"].includes(String(propertyType));\n const supportedType = typeof propertyType === \"string\" && PROPERTY_TYPES.includes(propertyType);\n const unsupportedValue =\n textValue && value !== null && value !== undefined && typeof value !== \"string\";\n\n if (!supportedType) {\n throw new ConversionError(`Property ${label} has an unsupported type: ${String(type)}`);\n }\n\n if (unsupportedValue) throw new ConversionError(`Property ${label} cannot represent this value`);\n\n return { type: \"property\", attrs: { label, type: propertyType, value: value ?? \"\" } };\n};\nconst setMetadata = (metadata: Record<string, unknown>, key: string, value: unknown): void => {\n if (Object.hasOwn(metadata, key))\n throw new ConversionError(`Duplicate frontmatter field: ${key}`);\n\n metadata[key] = value;\n};\nconst mergeOptions = <T>(\n defaults: ConverterOptions<T>,\n options: ConverterOptions<T>\n): ConverterOptions<T> => ({\n ...defaults,\n ...options,\n fragments: {\n ...defaults.fragments,\n ...options.fragments,\n named: { ...defaults.fragments?.named, ...options.fragments?.named }\n },\n encode: {\n nodes: { ...defaults.encode?.nodes, ...options.encode?.nodes },\n marks: { ...defaults.encode?.marks, ...options.encode?.marks },\n elements: { ...defaults.encode?.elements, ...options.encode?.elements }\n },\n decode: {\n nodes: { ...defaults.decode?.nodes, ...options.decode?.nodes },\n marks: { ...defaults.decode?.marks, ...options.decode?.marks },\n elements: { ...defaults.decode?.elements, ...options.decode?.elements }\n }\n});\n\nexport { createConverter, createExportConverter, createImportConverter };\n"],"mappings":"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"}
|