@andesine/converters 0.7.0 → 0.8.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 +7 -0
- package/dist/chunks/{adapter-BlLPQGXb.js → adapter-Dtv1L37e.js} +5 -4
- package/dist/chunks/{adapter-BlLPQGXb.js.map → adapter-Dtv1L37e.js.map} +1 -1
- package/dist/chunks/{core-CJ7Hlymb.js → core-DpOn10DI.js} +12 -2
- package/dist/chunks/core-DpOn10DI.js.map +1 -0
- package/dist/chunks/{decode-BJK_KI3W.js → decode-CmiiHK2G.js} +6 -3
- package/dist/chunks/decode-CmiiHK2G.js.map +1 -0
- package/dist/html.js +7 -4
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -2
- package/dist/markdoc.js +25 -9
- package/dist/markdoc.js.map +1 -1
- package/dist/markdown.js +2 -2
- package/dist/mdx.js +2 -2
- package/dist/text.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/core-CJ7Hlymb.js.map +0 -1
- package/dist/chunks/decode-BJK_KI3W.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
- Code blocks keep an optional `title`: a fence's `title="..."` meta in Markdown and MDX, a
|
|
6
|
+
`{% title="..." %}` annotation in Markdoc, and `data-title` on the `<pre>` in HTML. A titled
|
|
7
|
+
Markdown block without a language is written as `text`. `readCodeTitle` and `formatCodeMeta`
|
|
8
|
+
read and write the meta.
|
|
9
|
+
|
|
3
10
|
## 0.7.0
|
|
4
11
|
|
|
5
12
|
- Add the `properties: { as: "element", name }` mapping: each property becomes a self-closing
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as decodeMarkdown } from "./decode-
|
|
1
|
+
import { i as ConversionError, o as formatCodeMeta, u as textContent } from "./core-DpOn10DI.js";
|
|
2
|
+
import { t as decodeMarkdown } from "./decode-CmiiHK2G.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";
|
|
@@ -48,7 +48,8 @@ const encodeMarkdown = async (node, context) => {
|
|
|
48
48
|
case "horizontalRule": return { type: "thematicBreak" };
|
|
49
49
|
case "codeBlock": return {
|
|
50
50
|
type: "code",
|
|
51
|
-
lang: typeof attrs.language === "string" ? attrs.language : null,
|
|
51
|
+
lang: typeof attrs.language === "string" && attrs.language ? attrs.language : attrs.title ? "text" : null,
|
|
52
|
+
meta: formatCodeMeta(attrs.title),
|
|
52
53
|
value: textContent(node)
|
|
53
54
|
};
|
|
54
55
|
case "image": return {
|
|
@@ -174,4 +175,4 @@ const createMarkdownAdapter = (mdx) => {
|
|
|
174
175
|
//#endregion
|
|
175
176
|
export { createMarkdownAdapter as t };
|
|
176
177
|
|
|
177
|
-
//# sourceMappingURL=adapter-
|
|
178
|
+
//# sourceMappingURL=adapter-Dtv1L37e.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-BlLPQGXb.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, 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 lang: typeof attrs.language === \"string\" ? attrs.language : null,\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-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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"}
|
|
@@ -81,6 +81,16 @@ const element = (name, props, content, selfClosing = !content.length) => {
|
|
|
81
81
|
...content.length ? { content } : {}
|
|
82
82
|
};
|
|
83
83
|
};
|
|
84
|
+
/** A code fence's title from its meta, e.g. `title="install.sh"`. */
|
|
85
|
+
const readCodeTitle = (meta) => {
|
|
86
|
+
const match = meta?.match(/title=(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
87
|
+
return match?.[1] ?? match?.[2] ?? match?.[3];
|
|
88
|
+
};
|
|
89
|
+
/** A code fence's meta for its title, quoted to keep spaces. */
|
|
90
|
+
const formatCodeMeta = (title) => {
|
|
91
|
+
if (typeof title !== "string" || !title) return null;
|
|
92
|
+
return title.includes("\"") ? `title='${title}'` : `title="${title}"`;
|
|
93
|
+
};
|
|
84
94
|
//#endregion
|
|
85
95
|
//#region src/frontmatter.ts
|
|
86
96
|
const readFrontmatter = (source) => {
|
|
@@ -413,6 +423,6 @@ const mergeOptions = (defaults, options) => ({
|
|
|
413
423
|
}
|
|
414
424
|
});
|
|
415
425
|
//#endregion
|
|
416
|
-
export { element as a,
|
|
426
|
+
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 };
|
|
417
427
|
|
|
418
|
-
//# sourceMappingURL=core-
|
|
428
|
+
//# sourceMappingURL=core-DpOn10DI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as textNode, f as withMark, i as ConversionError, l as readCodeTitle } from "./core-DpOn10DI.js";
|
|
2
2
|
//#region src/markdown/decode.ts
|
|
3
3
|
const paragraphContent = (children) => {
|
|
4
4
|
const blocks = [];
|
|
@@ -58,7 +58,10 @@ const decodeMarkdown = async (node, context) => {
|
|
|
58
58
|
case "thematicBreak": return { type: "horizontalRule" };
|
|
59
59
|
case "code": return {
|
|
60
60
|
type: "codeBlock",
|
|
61
|
-
attrs: {
|
|
61
|
+
attrs: {
|
|
62
|
+
language: node.lang || null,
|
|
63
|
+
title: readCodeTitle(node.meta) ?? null
|
|
64
|
+
},
|
|
62
65
|
content: textNode(node.value)
|
|
63
66
|
};
|
|
64
67
|
case "inlineCode": return withMark(textNode(node.value), { type: "code" });
|
|
@@ -99,4 +102,4 @@ const decodeMarkdown = async (node, context) => {
|
|
|
99
102
|
//#endregion
|
|
100
103
|
export { paragraphContent as n, decodeMarkdown as t };
|
|
101
104
|
|
|
102
|
-
//# sourceMappingURL=decode-
|
|
105
|
+
//# sourceMappingURL=decode-CmiiHK2G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-CmiiHK2G.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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"}
|
package/dist/html.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, c as
|
|
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-DpOn10DI.js";
|
|
2
|
+
import { n as paragraphContent } from "./chunks/decode-CmiiHK2G.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
|
|
@@ -69,7 +69,7 @@ const htmlAdapter = {
|
|
|
69
69
|
case "codeBlock": return tag("pre", [tag("code", [{
|
|
70
70
|
type: "text",
|
|
71
71
|
value: textContent(node)
|
|
72
|
-
}], { dataLanguage: String(attrs.language || "") })]);
|
|
72
|
+
}], { dataLanguage: String(attrs.language || "") })], attrs.title ? { dataTitle: String(attrs.title) } : {});
|
|
73
73
|
case "image": {
|
|
74
74
|
const image = tag("img", [], {
|
|
75
75
|
src: safeURL(await context.imageURL(node), true),
|
|
@@ -108,7 +108,10 @@ const htmlAdapter = {
|
|
|
108
108
|
const code = node.children.find((child) => child.type === "element" && child.tagName === "code");
|
|
109
109
|
return {
|
|
110
110
|
type: "codeBlock",
|
|
111
|
-
attrs: {
|
|
111
|
+
attrs: {
|
|
112
|
+
language: (code?.type === "element" ? code.properties.dataLanguage || String(code.properties.className || "").match(/language-([\w+-]+)/)?.[1] : void 0) || null,
|
|
113
|
+
title: props.dataTitle ? String(props.dataTitle) : null
|
|
114
|
+
},
|
|
112
115
|
content: textNode(htmlText(node))
|
|
113
116
|
};
|
|
114
117
|
}
|
package/dist/html.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","names":[],"sources":["../src/html.ts"],"sourcesContent":["import { fromHtml } from \"hast-util-from-html\";\nimport { toHtml } from \"hast-util-to-html\";\nimport type { Element, ElementContent, Properties, Root, RootContent } from \"hast\";\nimport { createConverter } from \"./core\";\nimport { paragraphContent } from \"./markdown/decode\";\nimport { ConversionError, lookup, element, textContent, textNode, withMark } from \"./utils\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype HTMLNode = Root | RootContent;\ntype HTMLOptions = ConverterOptions<HTMLNode>;\n\nconst tag = (tagName: string, children: HTMLNode[] = [], properties: Properties = {}): Element => ({\n type: \"element\",\n tagName,\n properties,\n children: children as ElementContent[]\n});\nconst htmlText = (node: HTMLNode): string =>\n node.type === \"text\"\n ? node.value\n : \"children\" in node\n ? node.children.map(htmlText).join(\"\")\n : \"\";\nconst safeURL = (value: string, image = false): string => {\n const url = new URL(value, \"https://example.com\");\n const allowed = image ? [\"http:\", \"https:\"] : [\"http:\", \"https:\", \"mailto:\", \"tel:\"];\n\n if (!allowed.includes(url.protocol))\n throw new ConversionError(`Unsupported URL protocol: ${url.protocol}`);\n\n return value;\n};\nconst htmlMarks: Record<string, string> = {\n strong: \"bold\",\n b: \"bold\",\n em: \"italic\",\n i: \"italic\",\n s: \"strike\",\n del: \"strike\",\n code: \"code\",\n a: \"link\",\n sub: \"subscript\",\n sup: \"superscript\",\n mark: \"highlight\"\n};\n/** HTML adapter for createConverter(), including its parser and node/mark mappings. */\nconst htmlAdapter: FormatAdapter<HTMLNode> = {\n name: \"HTML\",\n type: (node) => (node.type === \"element\" ? node.tagName : node.type),\n elementName: (node) =>\n node.type === \"element\"\n ? String(node.properties.dataAndesineElement || node.tagName)\n : undefined,\n markName: (node) => (node.type === \"element\" ? lookup(htmlMarks, node.tagName) : undefined),\n root: (children) => ({ type: \"root\", children: children as RootContent[] }),\n parse: (source) => fromHtml(source, { fragment: true }),\n stringify: (tree) => toHtml(tree),\n async encode(node, context) {\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 tag(\"p\", children);\n case \"heading\":\n return tag(\n `h${Math.max(1, Math.min(6, Number(attrs.level || 1)))}`,\n children,\n context.anchor ? { id: context.anchor } : {}\n );\n case \"blockquote\":\n return tag(\"blockquote\", children);\n case \"bulletList\":\n return tag(\"ul\", children);\n case \"orderedList\":\n return tag(\"ol\", children, { start: Number(attrs.start || 1) });\n case \"taskList\":\n return tag(\"ul\", children, { dataType: \"taskList\" });\n case \"listItem\":\n return tag(\"li\", children);\n case \"taskItem\":\n return tag(\"li\", children, {\n dataType: \"taskItem\",\n dataChecked: Boolean(attrs.checked) ? \"true\" : \"false\"\n });\n case \"hardBreak\":\n return tag(\"br\");\n case \"horizontalRule\":\n return tag(\"hr\");\n case \"codeBlock\":\n return tag(\"pre\", [\n tag(\"code\", [{ type: \"text\", value: textContent(node) }], {\n dataLanguage: String(attrs.language || \"\")\n })\n ]);\n case \"image\": {\n const image = tag(\"img\", [], {\n src: safeURL(await context.imageURL(node), true),\n alt: String(attrs.alt || \"\")\n });\n\n return attrs.caption\n ? tag(\"figure\", [\n image,\n tag(\"figcaption\", [{ type: \"text\", value: String(attrs.caption) }])\n ])\n : image;\n }\n case \"table\":\n return tag(\"table\", [tag(\"tbody\", children)]);\n case \"tableRow\":\n return tag(\"tr\", children);\n case \"tableCell\":\n case \"tableHeader\":\n return tag(node.type === \"tableHeader\" ? \"th\" : \"td\", children, {\n colSpan: Number(attrs.colspan || 1),\n rowSpan: Number(attrs.rowspan || 1)\n });\n case \"element\":\n return tag(\"div\", children, {\n dataAndesineElement: String(attrs.name || \"Element\"),\n dataAndesineProps: JSON.stringify(attrs.props || {})\n });\n default:\n throw new ConversionError(`Unsupported HTML node: ${node.type}`, context.path);\n }\n },\n mark(mark, children, context) {\n const name = Object.entries(htmlMarks).find(([, type]) => type === mark.type)?.[0];\n\n if (!name) throw new ConversionError(`Unsupported HTML mark: ${mark.type}`, context.path);\n\n return tag(\n name,\n children,\n mark.type === \"link\" ? { href: safeURL(String(mark.attrs?.href || \"\")) } : {}\n );\n },\n async decode(node, context) {\n if (node.type === \"text\") return textNode(node.value.replace(/[ \\t\\r\\n\\f]+/g, \" \"));\n if (node.type !== \"root\" && node.type !== \"element\")\n throw new ConversionError(`Unsupported HTML syntax: ${node.type}`, context.path);\n\n const name = node.type === \"element\" ? node.tagName : \"root\";\n const props = node.type === \"element\" ? node.properties : {};\n\n if (name === \"pre\") {\n const code = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"code\"\n );\n const language =\n code?.type === \"element\"\n ? code.properties.dataLanguage ||\n String(code.properties.className || \"\").match(/language-([\\w+-]+)/)?.[1]\n : undefined;\n\n return {\n type: \"codeBlock\",\n attrs: { language: language || null },\n content: textNode(htmlText(node))\n };\n }\n if (name === \"img\")\n return context.image({\n url: safeURL(String(props.src || \"\"), true),\n alt: String(props.alt || \"\"),\n title: props.title ? String(props.title) : undefined\n });\n if (name === \"figure\") {\n const image = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"img\"\n );\n const caption = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"figcaption\"\n );\n\n if (!image || image.type !== \"element\")\n throw new ConversionError(\"HTML figures require an image\", context.path);\n\n return context.image({\n url: safeURL(String(image.properties.src || \"\"), true),\n alt: String(image.properties.alt || \"\"),\n title: caption ? htmlText(caption) : undefined\n });\n }\n const blockContainer = [\n \"root\",\n \"div\",\n \"section\",\n \"article\",\n \"main\",\n \"ul\",\n \"ol\",\n \"table\",\n \"thead\",\n \"tbody\",\n \"tfoot\",\n \"tr\",\n \"blockquote\"\n ].includes(name);\n const decoded = await context.children(node.children);\n const children = blockContainer\n ? decoded.filter((child, index) => {\n if (child.type !== \"text\" || /[^ \\t\\r\\n\\f]/.test(child.text || \"\")) return true;\n\n // Keep word separators inside inline runs, but omit indentation around blocks.\n return [decoded[index - 1], decoded[index + 1]].every(\n (sibling) => sibling && [\"text\", \"hardBreak\"].includes(sibling.type)\n );\n })\n : decoded;\n const mark = lookup(htmlMarks, name);\n\n if (props.dataAndesineElement) {\n return element(\n String(props.dataAndesineElement),\n JSON.parse(String(props.dataAndesineProps || \"{}\")),\n children\n );\n }\n if (mark)\n return withMark(children, {\n type: mark,\n ...(mark === \"link\" ? { attrs: { href: safeURL(String(props.href || \"\")) } } : {})\n });\n if (/^h[1-6]$/.test(name))\n return { type: \"heading\", attrs: { level: Number(name[1]) }, content: children };\n\n switch (name) {\n case \"root\":\n case \"div\":\n case \"section\":\n case \"article\":\n case \"main\":\n return paragraphContent(children);\n case \"thead\":\n case \"tbody\":\n case \"tfoot\":\n return children;\n case \"p\":\n return paragraphContent(children);\n case \"blockquote\":\n return { type: \"blockquote\", content: paragraphContent(children) };\n case \"ul\":\n case \"ol\":\n return {\n type:\n name === \"ol\"\n ? \"orderedList\"\n : props.dataType === \"taskList\"\n ? \"taskList\"\n : \"bulletList\",\n ...(name === \"ol\" ? { attrs: { start: Number(props.start || 1) } } : {}),\n content: children\n };\n case \"li\":\n return {\n type: props.dataType === \"taskItem\" ? \"taskItem\" : \"listItem\",\n ...(props.dataType === \"taskItem\"\n ? { attrs: { checked: props.dataChecked === \"true\" } }\n : {}),\n content: paragraphContent(children)\n };\n case \"br\":\n return { type: \"hardBreak\" };\n case \"hr\":\n return { type: \"horizontalRule\" };\n case \"table\":\n return { type: \"table\", content: children };\n case \"tr\":\n return { type: \"tableRow\", content: children };\n case \"th\":\n case \"td\":\n return {\n type: name === \"th\" ? \"tableHeader\" : \"tableCell\",\n attrs: { colspan: Number(props.colSpan || 1), rowspan: Number(props.rowSpan || 1) },\n content: paragraphContent(children)\n };\n default:\n throw new ConversionError(`Unsupported HTML element: ${name}`, context.path);\n }\n }\n};\n/**\n * Create a reusable async HTML 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 Andesine data attributes; frontmatter mappings are not supported.\n */\nconst createHTMLConverter = (options?: HTMLOptions) => createConverter(htmlAdapter, options);\nconst converter = createHTMLConverter();\n/**\n * Export ProseMirror JSON as HTML.\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 HTML. 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 toHTML = converter.encode;\n/**\n * Import HTML as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use Andesine data attributes; frontmatter mappings are not supported.\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 fromHTML = converter.decode;\n/**\n * Export ProseMirror JSON as a HTML 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 toHTML(), including unsupported frontmatter mappings.\n */\nconst toHTMLAST = converter.toAST;\n/**\n * Import a parsed HTML 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 fromHTML(), excluding string-parser errors.\n */\nconst fromHTMLAST = converter.fromAST;\n\nexport { createHTMLConverter, htmlAdapter, toHTML, fromHTML, toHTMLAST, fromHTMLAST };\nexport type { HTMLNode, HTMLOptions };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"html.js","names":[],"sources":["../src/html.ts"],"sourcesContent":["import { fromHtml } from \"hast-util-from-html\";\nimport { toHtml } from \"hast-util-to-html\";\nimport type { Element, ElementContent, Properties, Root, RootContent } from \"hast\";\nimport { createConverter } from \"./core\";\nimport { paragraphContent } from \"./markdown/decode\";\nimport { ConversionError, lookup, element, textContent, textNode, withMark } from \"./utils\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype HTMLNode = Root | RootContent;\ntype HTMLOptions = ConverterOptions<HTMLNode>;\n\nconst tag = (tagName: string, children: HTMLNode[] = [], properties: Properties = {}): Element => ({\n type: \"element\",\n tagName,\n properties,\n children: children as ElementContent[]\n});\nconst htmlText = (node: HTMLNode): string =>\n node.type === \"text\"\n ? node.value\n : \"children\" in node\n ? node.children.map(htmlText).join(\"\")\n : \"\";\nconst safeURL = (value: string, image = false): string => {\n const url = new URL(value, \"https://example.com\");\n const allowed = image ? [\"http:\", \"https:\"] : [\"http:\", \"https:\", \"mailto:\", \"tel:\"];\n\n if (!allowed.includes(url.protocol))\n throw new ConversionError(`Unsupported URL protocol: ${url.protocol}`);\n\n return value;\n};\nconst htmlMarks: Record<string, string> = {\n strong: \"bold\",\n b: \"bold\",\n em: \"italic\",\n i: \"italic\",\n s: \"strike\",\n del: \"strike\",\n code: \"code\",\n a: \"link\",\n sub: \"subscript\",\n sup: \"superscript\",\n mark: \"highlight\"\n};\n/** HTML adapter for createConverter(), including its parser and node/mark mappings. */\nconst htmlAdapter: FormatAdapter<HTMLNode> = {\n name: \"HTML\",\n type: (node) => (node.type === \"element\" ? node.tagName : node.type),\n elementName: (node) =>\n node.type === \"element\"\n ? String(node.properties.dataAndesineElement || node.tagName)\n : undefined,\n markName: (node) => (node.type === \"element\" ? lookup(htmlMarks, node.tagName) : undefined),\n root: (children) => ({ type: \"root\", children: children as RootContent[] }),\n parse: (source) => fromHtml(source, { fragment: true }),\n stringify: (tree) => toHtml(tree),\n async encode(node, context) {\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 tag(\"p\", children);\n case \"heading\":\n return tag(\n `h${Math.max(1, Math.min(6, Number(attrs.level || 1)))}`,\n children,\n context.anchor ? { id: context.anchor } : {}\n );\n case \"blockquote\":\n return tag(\"blockquote\", children);\n case \"bulletList\":\n return tag(\"ul\", children);\n case \"orderedList\":\n return tag(\"ol\", children, { start: Number(attrs.start || 1) });\n case \"taskList\":\n return tag(\"ul\", children, { dataType: \"taskList\" });\n case \"listItem\":\n return tag(\"li\", children);\n case \"taskItem\":\n return tag(\"li\", children, {\n dataType: \"taskItem\",\n dataChecked: Boolean(attrs.checked) ? \"true\" : \"false\"\n });\n case \"hardBreak\":\n return tag(\"br\");\n case \"horizontalRule\":\n return tag(\"hr\");\n case \"codeBlock\":\n return tag(\n \"pre\",\n [\n tag(\"code\", [{ type: \"text\", value: textContent(node) }], {\n dataLanguage: String(attrs.language || \"\")\n })\n ],\n attrs.title ? { dataTitle: String(attrs.title) } : {}\n );\n case \"image\": {\n const image = tag(\"img\", [], {\n src: safeURL(await context.imageURL(node), true),\n alt: String(attrs.alt || \"\")\n });\n\n return attrs.caption\n ? tag(\"figure\", [\n image,\n tag(\"figcaption\", [{ type: \"text\", value: String(attrs.caption) }])\n ])\n : image;\n }\n case \"table\":\n return tag(\"table\", [tag(\"tbody\", children)]);\n case \"tableRow\":\n return tag(\"tr\", children);\n case \"tableCell\":\n case \"tableHeader\":\n return tag(node.type === \"tableHeader\" ? \"th\" : \"td\", children, {\n colSpan: Number(attrs.colspan || 1),\n rowSpan: Number(attrs.rowspan || 1)\n });\n case \"element\":\n return tag(\"div\", children, {\n dataAndesineElement: String(attrs.name || \"Element\"),\n dataAndesineProps: JSON.stringify(attrs.props || {})\n });\n default:\n throw new ConversionError(`Unsupported HTML node: ${node.type}`, context.path);\n }\n },\n mark(mark, children, context) {\n const name = Object.entries(htmlMarks).find(([, type]) => type === mark.type)?.[0];\n\n if (!name) throw new ConversionError(`Unsupported HTML mark: ${mark.type}`, context.path);\n\n return tag(\n name,\n children,\n mark.type === \"link\" ? { href: safeURL(String(mark.attrs?.href || \"\")) } : {}\n );\n },\n async decode(node, context) {\n if (node.type === \"text\") return textNode(node.value.replace(/[ \\t\\r\\n\\f]+/g, \" \"));\n if (node.type !== \"root\" && node.type !== \"element\")\n throw new ConversionError(`Unsupported HTML syntax: ${node.type}`, context.path);\n\n const name = node.type === \"element\" ? node.tagName : \"root\";\n const props = node.type === \"element\" ? node.properties : {};\n\n if (name === \"pre\") {\n const code = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"code\"\n );\n const language =\n code?.type === \"element\"\n ? code.properties.dataLanguage ||\n String(code.properties.className || \"\").match(/language-([\\w+-]+)/)?.[1]\n : undefined;\n\n return {\n type: \"codeBlock\",\n attrs: {\n language: language || null,\n title: props.dataTitle ? String(props.dataTitle) : null\n },\n content: textNode(htmlText(node))\n };\n }\n if (name === \"img\")\n return context.image({\n url: safeURL(String(props.src || \"\"), true),\n alt: String(props.alt || \"\"),\n title: props.title ? String(props.title) : undefined\n });\n if (name === \"figure\") {\n const image = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"img\"\n );\n const caption = node.children.find(\n (child) => child.type === \"element\" && child.tagName === \"figcaption\"\n );\n\n if (!image || image.type !== \"element\")\n throw new ConversionError(\"HTML figures require an image\", context.path);\n\n return context.image({\n url: safeURL(String(image.properties.src || \"\"), true),\n alt: String(image.properties.alt || \"\"),\n title: caption ? htmlText(caption) : undefined\n });\n }\n const blockContainer = [\n \"root\",\n \"div\",\n \"section\",\n \"article\",\n \"main\",\n \"ul\",\n \"ol\",\n \"table\",\n \"thead\",\n \"tbody\",\n \"tfoot\",\n \"tr\",\n \"blockquote\"\n ].includes(name);\n const decoded = await context.children(node.children);\n const children = blockContainer\n ? decoded.filter((child, index) => {\n if (child.type !== \"text\" || /[^ \\t\\r\\n\\f]/.test(child.text || \"\")) return true;\n\n // Keep word separators inside inline runs, but omit indentation around blocks.\n return [decoded[index - 1], decoded[index + 1]].every(\n (sibling) => sibling && [\"text\", \"hardBreak\"].includes(sibling.type)\n );\n })\n : decoded;\n const mark = lookup(htmlMarks, name);\n\n if (props.dataAndesineElement) {\n return element(\n String(props.dataAndesineElement),\n JSON.parse(String(props.dataAndesineProps || \"{}\")),\n children\n );\n }\n if (mark)\n return withMark(children, {\n type: mark,\n ...(mark === \"link\" ? { attrs: { href: safeURL(String(props.href || \"\")) } } : {})\n });\n if (/^h[1-6]$/.test(name))\n return { type: \"heading\", attrs: { level: Number(name[1]) }, content: children };\n\n switch (name) {\n case \"root\":\n case \"div\":\n case \"section\":\n case \"article\":\n case \"main\":\n return paragraphContent(children);\n case \"thead\":\n case \"tbody\":\n case \"tfoot\":\n return children;\n case \"p\":\n return paragraphContent(children);\n case \"blockquote\":\n return { type: \"blockquote\", content: paragraphContent(children) };\n case \"ul\":\n case \"ol\":\n return {\n type:\n name === \"ol\"\n ? \"orderedList\"\n : props.dataType === \"taskList\"\n ? \"taskList\"\n : \"bulletList\",\n ...(name === \"ol\" ? { attrs: { start: Number(props.start || 1) } } : {}),\n content: children\n };\n case \"li\":\n return {\n type: props.dataType === \"taskItem\" ? \"taskItem\" : \"listItem\",\n ...(props.dataType === \"taskItem\"\n ? { attrs: { checked: props.dataChecked === \"true\" } }\n : {}),\n content: paragraphContent(children)\n };\n case \"br\":\n return { type: \"hardBreak\" };\n case \"hr\":\n return { type: \"horizontalRule\" };\n case \"table\":\n return { type: \"table\", content: children };\n case \"tr\":\n return { type: \"tableRow\", content: children };\n case \"th\":\n case \"td\":\n return {\n type: name === \"th\" ? \"tableHeader\" : \"tableCell\",\n attrs: { colspan: Number(props.colSpan || 1), rowspan: Number(props.rowSpan || 1) },\n content: paragraphContent(children)\n };\n default:\n throw new ConversionError(`Unsupported HTML element: ${name}`, context.path);\n }\n }\n};\n/**\n * Create a reusable async HTML 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 Andesine data attributes; frontmatter mappings are not supported.\n */\nconst createHTMLConverter = (options?: HTMLOptions) => createConverter(htmlAdapter, options);\nconst converter = createHTMLConverter();\n/**\n * Export ProseMirror JSON as HTML.\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 HTML. 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 toHTML = converter.encode;\n/**\n * Import HTML as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use Andesine data attributes; frontmatter mappings are not supported.\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 fromHTML = converter.decode;\n/**\n * Export ProseMirror JSON as a HTML 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 toHTML(), including unsupported frontmatter mappings.\n */\nconst toHTMLAST = converter.toAST;\n/**\n * Import a parsed HTML 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 fromHTML(), excluding string-parser errors.\n */\nconst fromHTMLAST = converter.fromAST;\n\nexport { createHTMLConverter, htmlAdapter, toHTML, fromHTML, toHTMLAST, fromHTMLAST };\nexport type { HTMLNode, HTMLOptions };\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,10 @@ declare const withMark: (nodes: ContentNode[], mark: ContentMark) => ContentNode
|
|
|
75
75
|
* @throws ConversionError for invalid names, property keys, or non-JSON property values.
|
|
76
76
|
*/
|
|
77
77
|
declare const element: (name: string, props: Record<string, unknown>, content: ContentNode[], selfClosing?: boolean) => ContentNode;
|
|
78
|
+
/** A code fence's title from its meta, e.g. `title="install.sh"`. */
|
|
79
|
+
declare const readCodeTitle: (meta?: string | null) => string | undefined;
|
|
80
|
+
/** A code fence's meta for its title, quoted to keep spaces. */
|
|
81
|
+
declare const formatCodeMeta: (title: unknown) => string | null;
|
|
78
82
|
//#endregion
|
|
79
83
|
//#region src/images.d.ts
|
|
80
84
|
interface ImageAsset {
|
|
@@ -111,5 +115,5 @@ declare const publishedContentOptions: (page: PublishedImageContent, options?: I
|
|
|
111
115
|
imageURL: (node: ContentNode) => Promise<string>;
|
|
112
116
|
};
|
|
113
117
|
//#endregion
|
|
114
|
-
export { type Awaitable, type ContentMark, type ContentNode, ConversionError, type ConvertedAST, type Converter, type ConverterOptions, type DecodeContext, type DecodeHandlers, type EncodeContext, type EncodeHandlers, type ExportConverter, type ExportConverterOptions, type ExportFormatAdapter, type FormatAdapter, type FragmentMapping, type HandlerResult, type HeadingAnchor, type ImageAsset, type ImageReference, type ImageURLOptions, type ImportConverter, type ImportConverterOptions, type ImportFormatAdapter, type PropertyMapping, type PublishedImageContent, createConverter, createExportConverter, createImageURLResolver, createImportConverter, element, getHeadingAnchors, publishedContentOptions, textContent, textNode, withMark };
|
|
118
|
+
export { type Awaitable, type ContentMark, type ContentNode, ConversionError, type ConvertedAST, type Converter, type ConverterOptions, type DecodeContext, type DecodeHandlers, type EncodeContext, type EncodeHandlers, type ExportConverter, type ExportConverterOptions, type ExportFormatAdapter, type FormatAdapter, type FragmentMapping, type HandlerResult, type HeadingAnchor, type ImageAsset, type ImageReference, type ImageURLOptions, type ImportConverter, type ImportConverterOptions, type ImportFormatAdapter, type PropertyMapping, type PublishedImageContent, createConverter, createExportConverter, createImageURLResolver, createImportConverter, element, formatCodeMeta, getHeadingAnchors, publishedContentOptions, readCodeTitle, textContent, textNode, withMark };
|
|
115
119
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getHeadingAnchors } from "./anchors.js";
|
|
2
|
-
import { a as element,
|
|
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-DpOn10DI.js";
|
|
3
3
|
//#region src/images.ts
|
|
4
4
|
/**
|
|
5
5
|
* Create an async imageURL callback from published asset references.
|
|
@@ -35,6 +35,6 @@ const createImageURLResolver = (assets, options = {}) => {
|
|
|
35
35
|
*/
|
|
36
36
|
const publishedContentOptions = (page, options) => ({ imageURL: createImageURLResolver(page.assets, options) });
|
|
37
37
|
//#endregion
|
|
38
|
-
export { ConversionError, createConverter, createExportConverter, createImageURLResolver, createImportConverter, element, getHeadingAnchors, publishedContentOptions, textContent, textNode, withMark };
|
|
38
|
+
export { ConversionError, createConverter, createExportConverter, createImageURLResolver, createImportConverter, element, formatCodeMeta, getHeadingAnchors, publishedContentOptions, readCodeTitle, textContent, textNode, withMark };
|
|
39
39
|
|
|
40
40
|
//# sourceMappingURL=index.js.map
|
package/dist/markdoc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, c as
|
|
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-DpOn10DI.js";
|
|
2
|
+
import { n as paragraphContent } from "./chunks/decode-CmiiHK2G.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";
|
|
@@ -80,11 +80,23 @@ const serializeMarkdoc = (tree) => {
|
|
|
80
80
|
type: "listItem",
|
|
81
81
|
children
|
|
82
82
|
}];
|
|
83
|
-
case "fence":
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
case "fence": {
|
|
84
|
+
const fence = new Markdoc.Ast.Node("fence", attrs);
|
|
85
|
+
if (!attrs.title) return [{
|
|
86
|
+
type: "code",
|
|
87
|
+
lang: String(attrs.language || ""),
|
|
88
|
+
value: String(attrs.content || "")
|
|
89
|
+
}];
|
|
90
|
+
fence.annotations = [{
|
|
91
|
+
type: "attribute",
|
|
92
|
+
name: "title",
|
|
93
|
+
value: String(attrs.title)
|
|
94
|
+
}];
|
|
95
|
+
return [{
|
|
96
|
+
type: "html",
|
|
97
|
+
value: Markdoc.format(fence).trim()
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
88
100
|
case "hardbreak": return [{ type: "break" }];
|
|
89
101
|
case "softbreak": return [{
|
|
90
102
|
type: "text",
|
|
@@ -165,7 +177,8 @@ const markdocAdapter = {
|
|
|
165
177
|
case "listItem": return new Markdoc.Ast.Node("item", {}, children);
|
|
166
178
|
case "codeBlock": return new Markdoc.Ast.Node("fence", {
|
|
167
179
|
language: attrs.language || "",
|
|
168
|
-
content: textContent(node)
|
|
180
|
+
content: textContent(node),
|
|
181
|
+
...attrs.title ? { title: attrs.title } : {}
|
|
169
182
|
});
|
|
170
183
|
case "hardBreak": return new Markdoc.Ast.Node("hardbreak");
|
|
171
184
|
case "horizontalRule": return new Markdoc.Ast.Node("hr");
|
|
@@ -235,7 +248,10 @@ const markdocAdapter = {
|
|
|
235
248
|
};
|
|
236
249
|
case "fence": return {
|
|
237
250
|
type: "codeBlock",
|
|
238
|
-
attrs: {
|
|
251
|
+
attrs: {
|
|
252
|
+
language: attrs.language || null,
|
|
253
|
+
title: attrs.title || null
|
|
254
|
+
},
|
|
239
255
|
content: textNode(String(attrs.content || "").replace(/\n$/, ""))
|
|
240
256
|
};
|
|
241
257
|
case "hardbreak": return { type: "hardBreak" };
|
package/dist/markdoc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdoc.js","names":[],"sources":["../src/markdoc/serialize.ts","../src/markdoc.ts"],"sourcesContent":["import Markdoc from \"@markdoc/markdoc\";\nimport { unified } from \"unified\";\nimport remarkStringify from \"remark-stringify\";\nimport remarkGFM from \"remark-gfm\";\nimport type {\n Root,\n RootContent,\n PhrasingContent,\n BlockContent,\n ListContent,\n TableContent,\n RowContent\n} from \"mdast\";\nimport { ConversionError } from \"../utils\";\nimport { normalizeMarkdown } from \"../markdown/normalize\";\nimport { markdownStringifyOptions } from \"../markdown/stringify\";\n\ntype MarkdocNode = InstanceType<typeof Markdoc.Ast.Node>;\ntype MarkdownNode = Root | RootContent;\n\n// Markdoc's formatter preserves source-like text. Use a Markdown serializer to\n// escape literal Markdown characters in newly created content.\nconst processor = unified()\n .use(remarkGFM)\n .use(remarkStringify, {\n ...markdownStringifyOptions,\n unsafe: [{ character: \"{\", after: \"%\" }]\n });\nconst serializeMarkdoc = (tree: MarkdocNode): string => {\n const convert = (node: MarkdocNode): MarkdownNode[] => {\n const attrs = node.attributes;\n const children = node.children.flatMap(convert);\n const inline = children as PhrasingContent[];\n\n switch (node.type) {\n case \"document\":\n return [{ type: \"root\", children: children as RootContent[] }];\n case \"inline\":\n case \"thead\":\n case \"tbody\":\n return children;\n case \"text\":\n return [{ type: \"text\", value: String(attrs.content || \"\") }];\n case \"paragraph\":\n return [{ type: \"paragraph\", children: inline }];\n case \"heading\":\n return [\n {\n type: \"heading\",\n depth: Number(attrs.level || 1) as 1 | 2 | 3 | 4 | 5 | 6,\n children: inline\n }\n ];\n case \"strong\":\n return [{ type: \"strong\", children: inline }];\n case \"em\":\n return [{ type: \"emphasis\", children: inline }];\n case \"s\":\n return [{ type: \"delete\", children: inline }];\n case \"code\":\n return [{ type: \"inlineCode\", value: String(attrs.content || \"\") }];\n case \"link\":\n return [{ type: \"link\", url: String(attrs.href || \"\"), children: inline }];\n case \"image\":\n return [\n {\n type: \"image\",\n url: String(attrs.src || \"\"),\n alt: String(attrs.alt || \"\"),\n title: attrs.title || null\n }\n ];\n case \"blockquote\":\n return [{ type: \"blockquote\", children: children as BlockContent[] }];\n case \"list\":\n return [\n {\n type: \"list\",\n ordered: Boolean(attrs.ordered),\n start: Number(attrs.start || 1),\n children: children as ListContent[]\n }\n ];\n case \"item\":\n return [{ type: \"listItem\", children: children as BlockContent[] }];\n case \"fence\":\n return [\n { type: \"code\", lang: String(attrs.language || \"\"), value: String(attrs.content || \"\") }\n ];\n case \"hardbreak\":\n return [{ type: \"break\" }];\n case \"softbreak\":\n return [{ type: \"text\", value: \"\\n\" }];\n case \"hr\":\n return [{ type: \"thematicBreak\" }];\n case \"table\":\n return [{ type: \"table\", children: children as TableContent[] }];\n case \"tr\":\n return [{ type: \"tableRow\", children: children as RowContent[] }];\n case \"td\":\n case \"th\":\n return [{ type: \"tableCell\", children: inline }];\n case \"tag\": {\n const opening = Markdoc.format(new Markdoc.Ast.Node(\"tag\", attrs, [], node.tag)).trim();\n const body = processor.stringify(\n normalizeMarkdown({ type: \"root\", children: children as RootContent[] })\n );\n const value = children.length\n ? `${opening.replace(/\\s*\\/%\\}$/, \" %}\")}\\n\\n${body}\\n{% /${node.tag} %}`\n : opening;\n\n return [{ type: \"html\", value }];\n }\n default:\n throw new ConversionError(`Unsupported Markdoc AST node: ${node.type}`);\n }\n };\n const nodes = convert(tree);\n const root: Root =\n nodes[0]?.type === \"root\" ? nodes[0] : { type: \"root\", children: nodes as RootContent[] };\n\n return processor.stringify(normalizeMarkdown(root));\n};\n\nexport { serializeMarkdoc };\n","import Markdoc from \"@markdoc/markdoc\";\nimport { serializeMarkdoc } from \"./markdoc/serialize\";\nimport { createConverter } from \"./core\";\nimport {\n ConversionError,\n lookup,\n element,\n isJSONValue,\n textContent,\n textNode,\n withMark\n} from \"./utils\";\nimport { paragraphContent } from \"./markdown/decode\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype MarkdocNode = InstanceType<typeof Markdoc.Ast.Node>;\ntype MarkdocOptions = ConverterOptions<MarkdocNode>;\n\nconst markTypes: Record<string, string> = {\n bold: \"strong\",\n italic: \"em\",\n strike: \"s\",\n code: \"code\",\n link: \"link\"\n};\n/** Markdoc adapter for createConverter(), including its parser and node/mark mappings. */\nconst markdocAdapter: FormatAdapter<MarkdocNode> = {\n name: \"Markdoc\",\n frontmatter: true,\n type: (node) => node.type,\n elementName: (node) => (node.type === \"tag\" ? node.tag : undefined),\n markName: (node) => Object.entries(markTypes).find(([, type]) => type === node.type)?.[0],\n root: (children) => new Markdoc.Ast.Node(\"document\", {}, children),\n parse: (source) => Markdoc.parse(source),\n stringify: serializeMarkdoc,\n async encode(node, context) {\n const attrs = node.attrs || {};\n const children = await context.children(node);\n const inline = () => [new Markdoc.Ast.Node(\"inline\", {}, children)];\n\n switch (node.type) {\n case \"text\":\n return new Markdoc.Ast.Node(\"text\", { content: node.text || \"\" });\n case \"paragraph\":\n return new Markdoc.Ast.Node(\"paragraph\", {}, inline());\n case \"heading\":\n return new Markdoc.Ast.Node(\n \"heading\",\n { level: Number(attrs.level || 1), ...(context.anchor ? { id: context.anchor } : {}) },\n inline()\n );\n case \"blockquote\":\n return new Markdoc.Ast.Node(\"blockquote\", {}, children);\n case \"bulletList\":\n case \"orderedList\":\n return new Markdoc.Ast.Node(\n \"list\",\n {\n ordered: node.type === \"orderedList\",\n start: attrs.start || 1,\n marker: node.type === \"orderedList\" ? \".\" : \"-\"\n },\n children\n );\n case \"listItem\":\n return new Markdoc.Ast.Node(\"item\", {}, children);\n case \"codeBlock\":\n return new Markdoc.Ast.Node(\"fence\", {\n language: attrs.language || \"\",\n content: textContent(node)\n });\n case \"hardBreak\":\n return new Markdoc.Ast.Node(\"hardbreak\");\n case \"horizontalRule\":\n return new Markdoc.Ast.Node(\"hr\");\n case \"image\":\n return new Markdoc.Ast.Node(\"paragraph\", {}, [\n new Markdoc.Ast.Node(\"inline\", {}, [\n new Markdoc.Ast.Node(\"image\", {\n src: await context.imageURL(node),\n alt: String(attrs.alt || \"\"),\n title: String(attrs.caption || \"\")\n })\n ])\n ]);\n case \"element\": {\n const props = (attrs.props || {}) as Record<string, unknown>;\n\n if (!isJSONValue(props))\n throw new ConversionError(\n \"Markdoc attributes must contain static JSON values\",\n context.path\n );\n\n return new Markdoc.Ast.Node(\"tag\", props, children, String(attrs.name || \"Element\"));\n }\n case \"table\":\n return new Markdoc.Ast.Node(\n \"table\",\n {},\n children.length\n ? [\n new Markdoc.Ast.Node(\"thead\", {}, children.slice(0, 1)),\n new Markdoc.Ast.Node(\"tbody\", {}, children.slice(1))\n ]\n : []\n );\n case \"tableRow\":\n return new Markdoc.Ast.Node(\"tr\", {}, children);\n case \"tableCell\":\n case \"tableHeader\": {\n if (\n Number(attrs.colspan || 1) !== 1 ||\n Number(attrs.rowspan || 1) !== 1 ||\n children.length > 1 ||\n children.some((child) => child.type !== \"paragraph\")\n ) {\n throw new ConversionError(\n \"Markdoc tables require single-paragraph cells without spans\",\n context.path\n );\n }\n return new Markdoc.Ast.Node(\n node.type === \"tableHeader\" ? \"th\" : \"td\",\n {},\n children.flatMap((child) => child.children)\n );\n }\n default:\n throw new ConversionError(`Unsupported Markdoc node: ${node.type}`, context.path);\n }\n },\n mark(mark, children, context) {\n const type = lookup(markTypes, mark.type);\n\n if (!type) throw new ConversionError(`Unsupported Markdoc mark: ${mark.type}`, context.path);\n if (mark.type === \"code\") {\n if (children.some((node) => node.type !== \"text\"))\n throw new ConversionError(\"Code marks must wrap plain text\", context.path);\n\n return new Markdoc.Ast.Node(\"code\", {\n content: children.map((node) => node.attributes.content).join(\"\")\n });\n }\n return new Markdoc.Ast.Node(\n type as MarkdocNode[\"type\"],\n mark.type === \"link\" ? { href: mark.attrs?.href || \"\" } : {},\n children\n );\n },\n async decode(node, context) {\n const attrs = node.attributes;\n\n if (node.errors.length)\n throw new ConversionError(`Invalid Markdoc: ${node.errors[0].message}`, context.path);\n if (!isJSONValue(attrs))\n throw new ConversionError(\n \"Dynamic Markdoc attributes require a custom handler\",\n context.path\n );\n\n const children = await context.children(node.children);\n const mark = Object.entries(markTypes).find(([, type]) => type === node.type)?.[0];\n\n if (mark === \"code\") return withMark(textNode(String(attrs.content || \"\")), { type: \"code\" });\n if (mark)\n return withMark(children, {\n type: mark,\n ...(mark === \"link\" ? { attrs: { href: attrs.href } } : {})\n });\n\n switch (node.type) {\n case \"document\":\n case \"inline\":\n case \"thead\":\n case \"tbody\":\n return children;\n case \"text\":\n return textNode(String(attrs.content || \"\"));\n case \"paragraph\":\n return paragraphContent(children);\n case \"heading\":\n return { type: \"heading\", attrs: { level: attrs.level || 1 }, content: children };\n case \"blockquote\":\n return { type: \"blockquote\", content: children };\n case \"list\":\n return {\n type: attrs.ordered ? \"orderedList\" : \"bulletList\",\n ...(attrs.ordered ? { attrs: { start: attrs.start || 1 } } : {}),\n content: children\n };\n case \"item\":\n return { type: \"listItem\", content: paragraphContent(children) };\n case \"fence\":\n return {\n type: \"codeBlock\",\n attrs: { language: attrs.language || null },\n content: textNode(String(attrs.content || \"\").replace(/\\n$/, \"\"))\n };\n case \"hardbreak\":\n return { type: \"hardBreak\" };\n case \"softbreak\":\n return textNode(\"\\n\");\n case \"hr\":\n return { type: \"horizontalRule\" };\n case \"image\":\n return context.image({\n url: String(attrs.src || \"\"),\n alt: String(attrs.alt || \"\"),\n title: attrs.title\n });\n case \"tag\":\n return element(\n node.tag || \"Element\",\n attrs,\n children.length ? paragraphContent(children) : []\n );\n case \"table\":\n return { type: \"table\", content: children };\n case \"tr\":\n return { type: \"tableRow\", content: children };\n case \"th\":\n case \"td\":\n return {\n type: node.type === \"th\" ? \"tableHeader\" : \"tableCell\",\n content: paragraphContent(children)\n };\n default:\n throw new ConversionError(`Unsupported Markdoc syntax: ${node.type}`, context.path);\n }\n }\n};\n/**\n * Create a reusable async Markdoc 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 Markdoc tags with static properties.\n */\nconst createMarkdocConverter = (options?: MarkdocOptions) =>\n createConverter(markdocAdapter, options);\nconst converter = createMarkdocConverter();\n/**\n * Export ProseMirror JSON as Markdoc.\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 Markdoc. 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 toMarkdoc = converter.encode;\n/**\n * Import Markdoc as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use Markdoc tags with static properties.\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 fromMarkdoc = converter.decode;\n/**\n * Export ProseMirror JSON as a Markdoc 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 toMarkdoc(), including unsupported frontmatter mappings.\n */\nconst toMarkdocAST = converter.toAST;\n/**\n * Import a parsed Markdoc 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 fromMarkdoc(), excluding string-parser errors.\n */\nconst fromMarkdocAST = converter.fromAST;\n\nexport {\n createMarkdocConverter,\n markdocAdapter,\n toMarkdoc,\n fromMarkdoc,\n toMarkdocAST,\n fromMarkdocAST\n};\nexport type { MarkdocNode, MarkdocOptions };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"markdoc.js","names":[],"sources":["../src/markdoc/serialize.ts","../src/markdoc.ts"],"sourcesContent":["import Markdoc from \"@markdoc/markdoc\";\nimport { unified } from \"unified\";\nimport remarkStringify from \"remark-stringify\";\nimport remarkGFM from \"remark-gfm\";\nimport type {\n Root,\n RootContent,\n PhrasingContent,\n BlockContent,\n ListContent,\n TableContent,\n RowContent\n} from \"mdast\";\nimport { ConversionError } from \"../utils\";\nimport { normalizeMarkdown } from \"../markdown/normalize\";\nimport { markdownStringifyOptions } from \"../markdown/stringify\";\n\ntype MarkdocNode = InstanceType<typeof Markdoc.Ast.Node>;\ntype MarkdownNode = Root | RootContent;\n\n// Markdoc's formatter preserves source-like text. Use a Markdown serializer to\n// escape literal Markdown characters in newly created content.\nconst processor = unified()\n .use(remarkGFM)\n .use(remarkStringify, {\n ...markdownStringifyOptions,\n unsafe: [{ character: \"{\", after: \"%\" }]\n });\nconst serializeMarkdoc = (tree: MarkdocNode): string => {\n const convert = (node: MarkdocNode): MarkdownNode[] => {\n const attrs = node.attributes;\n const children = node.children.flatMap(convert);\n const inline = children as PhrasingContent[];\n\n switch (node.type) {\n case \"document\":\n return [{ type: \"root\", children: children as RootContent[] }];\n case \"inline\":\n case \"thead\":\n case \"tbody\":\n return children;\n case \"text\":\n return [{ type: \"text\", value: String(attrs.content || \"\") }];\n case \"paragraph\":\n return [{ type: \"paragraph\", children: inline }];\n case \"heading\":\n return [\n {\n type: \"heading\",\n depth: Number(attrs.level || 1) as 1 | 2 | 3 | 4 | 5 | 6,\n children: inline\n }\n ];\n case \"strong\":\n return [{ type: \"strong\", children: inline }];\n case \"em\":\n return [{ type: \"emphasis\", children: inline }];\n case \"s\":\n return [{ type: \"delete\", children: inline }];\n case \"code\":\n return [{ type: \"inlineCode\", value: String(attrs.content || \"\") }];\n case \"link\":\n return [{ type: \"link\", url: String(attrs.href || \"\"), children: inline }];\n case \"image\":\n return [\n {\n type: \"image\",\n url: String(attrs.src || \"\"),\n alt: String(attrs.alt || \"\"),\n title: attrs.title || null\n }\n ];\n case \"blockquote\":\n return [{ type: \"blockquote\", children: children as BlockContent[] }];\n case \"list\":\n return [\n {\n type: \"list\",\n ordered: Boolean(attrs.ordered),\n start: Number(attrs.start || 1),\n children: children as ListContent[]\n }\n ];\n case \"item\":\n return [{ type: \"listItem\", children: children as BlockContent[] }];\n case \"fence\": {\n const fence = new Markdoc.Ast.Node(\"fence\", attrs);\n\n if (!attrs.title) {\n return [\n { type: \"code\", lang: String(attrs.language || \"\"), value: String(attrs.content || \"\") }\n ];\n }\n\n // Markdown escapes would break the title annotation's string, so Markdoc writes the fence.\n fence.annotations = [{ type: \"attribute\", name: \"title\", value: String(attrs.title) }];\n\n return [{ type: \"html\", value: Markdoc.format(fence).trim() }];\n }\n case \"hardbreak\":\n return [{ type: \"break\" }];\n case \"softbreak\":\n return [{ type: \"text\", value: \"\\n\" }];\n case \"hr\":\n return [{ type: \"thematicBreak\" }];\n case \"table\":\n return [{ type: \"table\", children: children as TableContent[] }];\n case \"tr\":\n return [{ type: \"tableRow\", children: children as RowContent[] }];\n case \"td\":\n case \"th\":\n return [{ type: \"tableCell\", children: inline }];\n case \"tag\": {\n const opening = Markdoc.format(new Markdoc.Ast.Node(\"tag\", attrs, [], node.tag)).trim();\n const body = processor.stringify(\n normalizeMarkdown({ type: \"root\", children: children as RootContent[] })\n );\n const value = children.length\n ? `${opening.replace(/\\s*\\/%\\}$/, \" %}\")}\\n\\n${body}\\n{% /${node.tag} %}`\n : opening;\n\n return [{ type: \"html\", value }];\n }\n default:\n throw new ConversionError(`Unsupported Markdoc AST node: ${node.type}`);\n }\n };\n const nodes = convert(tree);\n const root: Root =\n nodes[0]?.type === \"root\" ? nodes[0] : { type: \"root\", children: nodes as RootContent[] };\n\n return processor.stringify(normalizeMarkdown(root));\n};\n\nexport { serializeMarkdoc };\n","import Markdoc from \"@markdoc/markdoc\";\nimport { serializeMarkdoc } from \"./markdoc/serialize\";\nimport { createConverter } from \"./core\";\nimport {\n ConversionError,\n lookup,\n element,\n isJSONValue,\n textContent,\n textNode,\n withMark\n} from \"./utils\";\nimport { paragraphContent } from \"./markdown/decode\";\nimport type { ConverterOptions, FormatAdapter } from \"./types\";\n\ntype MarkdocNode = InstanceType<typeof Markdoc.Ast.Node>;\ntype MarkdocOptions = ConverterOptions<MarkdocNode>;\n\nconst markTypes: Record<string, string> = {\n bold: \"strong\",\n italic: \"em\",\n strike: \"s\",\n code: \"code\",\n link: \"link\"\n};\n/** Markdoc adapter for createConverter(), including its parser and node/mark mappings. */\nconst markdocAdapter: FormatAdapter<MarkdocNode> = {\n name: \"Markdoc\",\n frontmatter: true,\n type: (node) => node.type,\n elementName: (node) => (node.type === \"tag\" ? node.tag : undefined),\n markName: (node) => Object.entries(markTypes).find(([, type]) => type === node.type)?.[0],\n root: (children) => new Markdoc.Ast.Node(\"document\", {}, children),\n parse: (source) => Markdoc.parse(source),\n stringify: serializeMarkdoc,\n async encode(node, context) {\n const attrs = node.attrs || {};\n const children = await context.children(node);\n const inline = () => [new Markdoc.Ast.Node(\"inline\", {}, children)];\n\n switch (node.type) {\n case \"text\":\n return new Markdoc.Ast.Node(\"text\", { content: node.text || \"\" });\n case \"paragraph\":\n return new Markdoc.Ast.Node(\"paragraph\", {}, inline());\n case \"heading\":\n return new Markdoc.Ast.Node(\n \"heading\",\n { level: Number(attrs.level || 1), ...(context.anchor ? { id: context.anchor } : {}) },\n inline()\n );\n case \"blockquote\":\n return new Markdoc.Ast.Node(\"blockquote\", {}, children);\n case \"bulletList\":\n case \"orderedList\":\n return new Markdoc.Ast.Node(\n \"list\",\n {\n ordered: node.type === \"orderedList\",\n start: attrs.start || 1,\n marker: node.type === \"orderedList\" ? \".\" : \"-\"\n },\n children\n );\n case \"listItem\":\n return new Markdoc.Ast.Node(\"item\", {}, children);\n case \"codeBlock\":\n return new Markdoc.Ast.Node(\"fence\", {\n language: attrs.language || \"\",\n content: textContent(node),\n ...(attrs.title ? { title: attrs.title } : {})\n });\n case \"hardBreak\":\n return new Markdoc.Ast.Node(\"hardbreak\");\n case \"horizontalRule\":\n return new Markdoc.Ast.Node(\"hr\");\n case \"image\":\n return new Markdoc.Ast.Node(\"paragraph\", {}, [\n new Markdoc.Ast.Node(\"inline\", {}, [\n new Markdoc.Ast.Node(\"image\", {\n src: await context.imageURL(node),\n alt: String(attrs.alt || \"\"),\n title: String(attrs.caption || \"\")\n })\n ])\n ]);\n case \"element\": {\n const props = (attrs.props || {}) as Record<string, unknown>;\n\n if (!isJSONValue(props))\n throw new ConversionError(\n \"Markdoc attributes must contain static JSON values\",\n context.path\n );\n\n return new Markdoc.Ast.Node(\"tag\", props, children, String(attrs.name || \"Element\"));\n }\n case \"table\":\n return new Markdoc.Ast.Node(\n \"table\",\n {},\n children.length\n ? [\n new Markdoc.Ast.Node(\"thead\", {}, children.slice(0, 1)),\n new Markdoc.Ast.Node(\"tbody\", {}, children.slice(1))\n ]\n : []\n );\n case \"tableRow\":\n return new Markdoc.Ast.Node(\"tr\", {}, children);\n case \"tableCell\":\n case \"tableHeader\": {\n if (\n Number(attrs.colspan || 1) !== 1 ||\n Number(attrs.rowspan || 1) !== 1 ||\n children.length > 1 ||\n children.some((child) => child.type !== \"paragraph\")\n ) {\n throw new ConversionError(\n \"Markdoc tables require single-paragraph cells without spans\",\n context.path\n );\n }\n return new Markdoc.Ast.Node(\n node.type === \"tableHeader\" ? \"th\" : \"td\",\n {},\n children.flatMap((child) => child.children)\n );\n }\n default:\n throw new ConversionError(`Unsupported Markdoc node: ${node.type}`, context.path);\n }\n },\n mark(mark, children, context) {\n const type = lookup(markTypes, mark.type);\n\n if (!type) throw new ConversionError(`Unsupported Markdoc mark: ${mark.type}`, context.path);\n if (mark.type === \"code\") {\n if (children.some((node) => node.type !== \"text\"))\n throw new ConversionError(\"Code marks must wrap plain text\", context.path);\n\n return new Markdoc.Ast.Node(\"code\", {\n content: children.map((node) => node.attributes.content).join(\"\")\n });\n }\n return new Markdoc.Ast.Node(\n type as MarkdocNode[\"type\"],\n mark.type === \"link\" ? { href: mark.attrs?.href || \"\" } : {},\n children\n );\n },\n async decode(node, context) {\n const attrs = node.attributes;\n\n if (node.errors.length)\n throw new ConversionError(`Invalid Markdoc: ${node.errors[0].message}`, context.path);\n if (!isJSONValue(attrs))\n throw new ConversionError(\n \"Dynamic Markdoc attributes require a custom handler\",\n context.path\n );\n\n const children = await context.children(node.children);\n const mark = Object.entries(markTypes).find(([, type]) => type === node.type)?.[0];\n\n if (mark === \"code\") return withMark(textNode(String(attrs.content || \"\")), { type: \"code\" });\n if (mark)\n return withMark(children, {\n type: mark,\n ...(mark === \"link\" ? { attrs: { href: attrs.href } } : {})\n });\n\n switch (node.type) {\n case \"document\":\n case \"inline\":\n case \"thead\":\n case \"tbody\":\n return children;\n case \"text\":\n return textNode(String(attrs.content || \"\"));\n case \"paragraph\":\n return paragraphContent(children);\n case \"heading\":\n return { type: \"heading\", attrs: { level: attrs.level || 1 }, content: children };\n case \"blockquote\":\n return { type: \"blockquote\", content: children };\n case \"list\":\n return {\n type: attrs.ordered ? \"orderedList\" : \"bulletList\",\n ...(attrs.ordered ? { attrs: { start: attrs.start || 1 } } : {}),\n content: children\n };\n case \"item\":\n return { type: \"listItem\", content: paragraphContent(children) };\n case \"fence\":\n return {\n type: \"codeBlock\",\n attrs: { language: attrs.language || null, title: attrs.title || null },\n content: textNode(String(attrs.content || \"\").replace(/\\n$/, \"\"))\n };\n case \"hardbreak\":\n return { type: \"hardBreak\" };\n case \"softbreak\":\n return textNode(\"\\n\");\n case \"hr\":\n return { type: \"horizontalRule\" };\n case \"image\":\n return context.image({\n url: String(attrs.src || \"\"),\n alt: String(attrs.alt || \"\"),\n title: attrs.title\n });\n case \"tag\":\n return element(\n node.tag || \"Element\",\n attrs,\n children.length ? paragraphContent(children) : []\n );\n case \"table\":\n return { type: \"table\", content: children };\n case \"tr\":\n return { type: \"tableRow\", content: children };\n case \"th\":\n case \"td\":\n return {\n type: node.type === \"th\" ? \"tableHeader\" : \"tableCell\",\n content: paragraphContent(children)\n };\n default:\n throw new ConversionError(`Unsupported Markdoc syntax: ${node.type}`, context.path);\n }\n }\n};\n/**\n * Create a reusable async Markdoc 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 Markdoc tags with static properties.\n */\nconst createMarkdocConverter = (options?: MarkdocOptions) =>\n createConverter(markdocAdapter, options);\nconst converter = createMarkdocConverter();\n/**\n * Export ProseMirror JSON as Markdoc.\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 Markdoc. 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 toMarkdoc = converter.encode;\n/**\n * Import Markdoc as ProseMirror JSON without saving content or uploading assets.\n * @param source - Source text to parse. Custom elements use Markdoc tags with static properties.\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 fromMarkdoc = converter.decode;\n/**\n * Export ProseMirror JSON as a Markdoc 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 toMarkdoc(), including unsupported frontmatter mappings.\n */\nconst toMarkdocAST = converter.toAST;\n/**\n * Import a parsed Markdoc 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 fromMarkdoc(), excluding string-parser errors.\n */\nconst fromMarkdocAST = converter.fromAST;\n\nexport {\n createMarkdocConverter,\n markdocAdapter,\n toMarkdoc,\n fromMarkdoc,\n toMarkdocAST,\n fromMarkdocAST\n};\nexport type { MarkdocNode, MarkdocOptions };\n"],"mappings":"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"}
|
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-DpOn10DI.js";
|
|
2
|
+
import { t as createMarkdownAdapter } from "./chunks/adapter-Dtv1L37e.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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as element, i as ConversionError,
|
|
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-DpOn10DI.js";
|
|
2
|
+
import { t as createMarkdownAdapter } from "./chunks/adapter-Dtv1L37e.js";
|
|
3
3
|
import remarkMDX from "remark-mdx";
|
|
4
4
|
import { parseExpressionAt } from "acorn";
|
|
5
5
|
//#region src/static-expression.ts
|
package/dist/text.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as ConversionError, n as createExportConverter, u as textContent } from "./chunks/core-DpOn10DI.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-CJ7Hlymb.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\nexport { ConversionError, lookup, array, element, isJSONValue, textContent, textNode, withMark };\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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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decode-BJK_KI3W.js","names":[],"sources":["../../src/markdown/decode.ts"],"sourcesContent":["import type { Root, RootContent } from \"mdast\";\nimport { ConversionError, 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 },\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":";;AAMA,MAAM,oBAAoB,aAA2C;CACnE,MAAM,SAAwB,CAAC;CAC/B,IAAI,SAAwB,CAAC;CAE7B,KAAK,MAAM,SAAS,UAClB,IAAI,CAAC,QAAQ,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI,GAC3C,OAAO,KAAK,KAAK;MACZ;EACL,IAAI,OAAO,QAAQ,OAAO,KAAK;GAAE,MAAM;GAAa,SAAS;EAAO,CAAC;EACrE,SAAS,CAAC;EACV,OAAO,KAAK,KAAK;CACnB;CAEF,IAAI,OAAO,UAAU,CAAC,OAAO,QAAQ,OAAO,KAAK;EAAE,MAAM;EAAa,SAAS;CAAO,CAAC;CAEvF,OAAO;AACT;AACA,MAAM,iBAAiB,OACrB,MACA,YACgD;CAChD,MAAM,WAAW,cAAc,OAAO,MAAM,QAAQ,SAAS,KAAK,QAAQ,IAAI,CAAC;CAE/E,QAAQ,KAAK,MAAb;EACE,KAAK,QACH,OAAO;EACT,KAAK,QACH,OAAO,SAAS,KAAK,KAAK;EAC5B,KAAK,aACH,OAAO,iBAAiB,QAAQ;EAClC,KAAK,WACH,OAAO;GAAE,MAAM;GAAW,OAAO,EAAE,OAAO,KAAK,MAAM;GAAG,SAAS;EAAS;EAC5E,KAAK,cACH,OAAO;GAAE,MAAM;GAAc,SAAS;EAAS;EACjD,KAAK,QAAQ;GACX,MAAM,QAAQ,SAAS,MAAM,UAAU,MAAM,SAAS,UAAU;GAEhE,IAAI,KAAK,WAAW,OAClB,MAAM,IAAI,gBAAgB,+CAA+C,QAAQ,IAAI;GAEvF,OAAO;IACL,MAAM,KAAK,UAAU,gBAAgB,QAAQ,aAAa;IAC1D,GAAI,KAAK,UAAU,EAAE,OAAO,EAAE,OAAO,KAAK,SAAS,EAAE,EAAE,IAAI,CAAC;IAC5D,SAAS,QACL,SAAS,KAAK,WAAW;KACvB,GAAG;KACH,MAAM;KACN,OAAO;MAAE,SAAS;MAAO,GAAG,MAAM;KAAM;IAC1C,EAAE,IACF;GACN;EACF;EACA,KAAK,YACH,OAAO;GACL,MAAM,OAAO,KAAK,YAAY,YAAY,aAAa;GACvD,GAAI,OAAO,KAAK,YAAY,YAAY,EAAE,OAAO,EAAE,SAAS,KAAK,QAAQ,EAAE,IAAI,CAAC;GAChF,SAAS;EACX;EACF,KAAK,SACH,OAAO,EAAE,MAAM,YAAY;EAC7B,KAAK,iBACH,OAAO,EAAE,MAAM,iBAAiB;EAClC,KAAK,QACH,OAAO;GACL,MAAM;GACN,OAAO,EAAE,UAAU,KAAK,QAAQ,KAAK;GACrC,SAAS,SAAS,KAAK,KAAK;EAC9B;EACF,KAAK,cACH,OAAO,SAAS,SAAS,KAAK,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;EACxD,KAAK,UACH,OAAO,SAAS,UAAU,EAAE,MAAM,OAAO,CAAC;EAC5C,KAAK,YACH,OAAO,SAAS,UAAU,EAAE,MAAM,SAAS,CAAC;EAC9C,KAAK,UACH,OAAO,SAAS,UAAU,EAAE,MAAM,SAAS,CAAC;EAC9C,KAAK,QACH,OAAO,SAAS,UAAU;GAAE,MAAM;GAAQ,OAAO,EAAE,MAAM,KAAK,IAAI;EAAE,CAAC;EACvE,KAAK,SACH,OAAO,QAAQ,MAAM;GAAE,KAAK,KAAK;GAAK,KAAK,KAAK,OAAO;GAAI,OAAO,KAAK,SAAS,KAAA;EAAU,CAAC;EAC7F,KAAK,SACH,OAAO;GACL,MAAM;GACN,SAAS,SAAS,KAAK,KAAK,UAC1B,QACI,MACA;IAAE,GAAG;IAAK,SAAS,IAAI,SAAS,KAAK,UAAU;KAAE,GAAG;KAAM,MAAM;IAAc,EAAE;GAAE,CACxF;EACF;EACF,KAAK,YACH,OAAO;GAAE,MAAM;GAAY,SAAS;EAAS;EAC/C,KAAK,aACH,OAAO;GAAE,MAAM;GAAa,SAAS,iBAAiB,QAAQ;EAAE;EAClE,KAAK,cACH,OAAO;EACT,SACE,MAAM,IAAI,gBAAgB,gCAAgC,KAAK,QAAQ,QAAQ,IAAI;CACvF;AACF"}
|