@artinstack/migrator 0.1.3 → 0.1.5
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/README.md +11 -0
- package/dist/bundle-uAAHehbv.d.ts +23 -0
- package/dist/chunk-CIOYDRY5.js +851 -0
- package/dist/chunk-CIOYDRY5.js.map +1 -0
- package/dist/chunk-S7TRWILI.js +71 -0
- package/dist/chunk-S7TRWILI.js.map +1 -0
- package/dist/{chunk-QEXTXHFG.js → chunk-XUBCG3IA.js} +221 -41
- package/dist/{chunk-QEXTXHFG.js.map → chunk-XUBCG3IA.js.map} +1 -1
- package/dist/{chunk-HH7666MQ.js → chunk-YLFVYPB3.js} +207 -75
- package/dist/chunk-YLFVYPB3.js.map +1 -0
- package/dist/cli/index.js +42 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +8 -87
- package/dist/index.js +23 -351
- package/dist/index.js.map +1 -1
- package/dist/normalizer/index.d.ts +4 -2
- package/dist/rewrite-inline-images-BckVKPbh.d.ts +21 -0
- package/dist/sinks/index.d.ts +262 -3
- package/dist/sinks/index.js +4 -2
- package/dist/transformers/index.d.ts +157 -0
- package/dist/transformers/index.js +32 -0
- package/dist/transformers/index.js.map +1 -0
- package/dist/{bundle-DfM_jKbq.d.ts → types-DWOP8Dcy.d.ts} +1 -21
- package/package.json +5 -1
- package/dist/chunk-HH7666MQ.js.map +0 -1
- package/dist/index-D88mjcF5.d.ts +0 -279
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/transformers/html-to-grapes/index.ts","../src/transformers/css-to-styles/index.ts","../src/transformers/html-to-grapes/walk.ts","../src/transformers/html-to-tiptap/index.ts","../src/transformers/html-to-tiptap/walk.ts","../src/transformers/validate-snapshot.ts","../src/transformers/validate-tiptap-doc.ts"],"sourcesContent":["import * as cheerio from \"cheerio\";\n\nimport { cssToStyles } from \"../css-to-styles/index.js\";\nimport type { GrapesProjectSnapshot, HtmlToGrapesOptions } from \"./types.js\";\nimport { walkHtmlToComponents } from \"./walk.js\";\n\nexport type {\n GrapesComponent,\n GrapesProjectSnapshot,\n GrapesStyleRule,\n HtmlToGrapesOptions,\n LayoutKind,\n LayoutTypeMap,\n} from \"./types.js\";\n\n/** Cheerio HTML walk → Grapes `content` + root `styles`. */\nexport function htmlToGrapes(html: string, options: HtmlToGrapesOptions = {}): GrapesProjectSnapshot {\n const trimmed = html.trim();\n if (!trimmed) {\n return { content: [], styles: [] };\n }\n\n const $ = cheerio.load(trimmed, { xml: false });\n const styleBlocks: string[] = [];\n\n $(\"style\").each((_, element) => {\n styleBlocks.push($(element).html() ?? \"\");\n $(element).remove();\n });\n\n const contentCss = styleBlocks.join(\"\\n\").trim();\n const styles = cssToStyles(contentCss);\n const content = walkHtmlToComponents($, options);\n const contentHtml = serializeContentHtml($);\n\n return {\n content,\n styles,\n ...(contentHtml ? { contentHtml } : {}),\n ...(contentCss ? { contentCss } : {}),\n };\n}\n\nfunction serializeContentHtml($: cheerio.CheerioAPI): string | undefined {\n const body = $(\"body\");\n if (body.length) {\n const html = body.html()?.trim();\n return html || undefined;\n }\n\n const rootHtml = $.root().html()?.trim();\n return rootHtml || undefined;\n}\n","import type { GrapesStyleRule } from \"../html-to-grapes/types.js\";\n\nfunction stripCssComments(css: string): string {\n return css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n}\n\nfunction parseDeclarations(block: string): Record<string, string> {\n const style: Record<string, string> = {};\n for (const declaration of block.split(\";\")) {\n const trimmed = declaration.trim();\n if (!trimmed) continue;\n const separator = trimmed.indexOf(\":\");\n if (separator === -1) continue;\n const property = trimmed.slice(0, separator).trim();\n const value = trimmed.slice(separator + 1).trim();\n if (!property || !value) continue;\n style[property] = value;\n }\n return style;\n}\n\n/** Parse `<style>` blocks and class rules into Grapes root `styles[]`. */\nexport function cssToStyles(css: string): GrapesStyleRule[] {\n const cleaned = stripCssComments(css);\n const rules: GrapesStyleRule[] = [];\n const rulePattern = /([^{]+)\\{([^}]*)\\}/g;\n\n for (const match of cleaned.matchAll(rulePattern)) {\n const selectorText = match[1]?.trim() ?? \"\";\n const declarationBlock = match[2] ?? \"\";\n if (!selectorText || selectorText.startsWith(\"@\")) continue;\n\n const style = parseDeclarations(declarationBlock);\n if (Object.keys(style).length === 0) continue;\n\n const selectors = selectorText\n .split(\",\")\n .map((selector) => selector.trim())\n .filter(Boolean);\n\n if (selectors.length === 0) continue;\n rules.push({ selectors, style });\n }\n\n return rules;\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { AnyNode } from \"domhandler\";\n\nimport type { GrapesComponent, HtmlToGrapesOptions, LayoutKind } from \"./types.js\";\n\ntype CheerioSelection = Cheerio<AnyNode>;\n\nconst INLINE_TAGS = new Set([\n \"a\",\n \"abbr\",\n \"b\",\n \"br\",\n \"cite\",\n \"code\",\n \"del\",\n \"em\",\n \"i\",\n \"img\",\n \"ins\",\n \"mark\",\n \"q\",\n \"s\",\n \"small\",\n \"span\",\n \"strong\",\n \"sub\",\n \"sup\",\n \"u\",\n \"wbr\",\n]);\n\nconst VOID_TAGS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\nconst TEXT_CONTAINER_TAGS = new Set([\n \"blockquote\",\n \"figcaption\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"label\",\n \"li\",\n \"p\",\n \"pre\",\n \"td\",\n \"th\",\n]);\n\nconst SKIP_TAGS = new Set([\"script\", \"style\", \"noscript\", \"template\"]);\n\nconst DEFAULT_TYPES: Record<string, string> = {\n a: \"link\",\n img: \"image\",\n};\n\nconst LAYOUT_DATA_ATTR = \"data-layout\";\n\nconst DEFAULT_LAYOUT_TYPE_MAP: Record<LayoutKind, string> = {\n section: \"section\",\n row: \"row\",\n column: \"column\",\n};\n\nfunction parseLayoutKind(attributes: Record<string, string> | undefined): LayoutKind | undefined {\n const value = attributes?.[LAYOUT_DATA_ATTR];\n if (value === \"section\" || value === \"row\" || value === \"column\") return value;\n return undefined;\n}\n\nfunction resolveLayoutComponentType(kind: LayoutKind, options: HtmlToGrapesOptions): string {\n return options.layoutTypeMap?.[kind] ?? DEFAULT_LAYOUT_TYPE_MAP[kind];\n}\n\nfunction layoutAttributesForComponent(\n attributes: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n if (!attributes) return undefined;\n const { [LAYOUT_DATA_ATTR]: _layout, ...rest } = attributes;\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\nfunction tagNameOf($el: CheerioSelection): string | undefined {\n const raw = $el.prop(\"tagName\");\n return typeof raw === \"string\" ? raw.toLowerCase() : undefined;\n}\n\nfunction applyElementMeta(\n component: GrapesComponent,\n meta: Pick<GrapesComponent, \"attributes\" | \"classes\">,\n): GrapesComponent {\n if (meta.attributes) component.attributes = meta.attributes;\n if (meta.classes) component.classes = meta.classes;\n return component;\n}\n\nfunction pickElementMeta($el: CheerioSelection): Pick<GrapesComponent, \"attributes\" | \"classes\"> {\n const attributes: Record<string, string> = {};\n const classes: string[] = [];\n\n if (typeof $el.attr() === \"object\") {\n for (const [key, value] of Object.entries($el.attr() ?? {})) {\n if (key === \"class\") {\n classes.push(...value.split(/\\s+/).filter(Boolean));\n continue;\n }\n attributes[key] = value;\n }\n }\n\n return {\n attributes: Object.keys(attributes).length > 0 ? attributes : undefined,\n classes: classes.length > 0 ? classes : undefined,\n };\n}\n\nfunction resolveComponentType(\n tagName: string,\n classes: string[] | undefined,\n options: HtmlToGrapesOptions,\n fallback = \"default\",\n): string {\n if (options.componentMap && classes) {\n for (const className of classes) {\n const mapped = options.componentMap[className];\n if (mapped) return mapped;\n }\n }\n const tagMapped = options.tagMap?.[tagName];\n if (tagMapped) return tagMapped;\n return DEFAULT_TYPES[tagName] ?? fallback;\n}\n\nfunction hasOnlyInlineContent($: CheerioAPI, $el: CheerioSelection): boolean {\n let inlineOnly = true;\n\n $el.contents().each((_, node) => {\n if (!inlineOnly) return;\n const $child = $(node);\n if ($child.get(0)?.type === \"text\") return;\n const childTag = tagNameOf($child);\n if (!childTag || !INLINE_TAGS.has(childTag)) {\n inlineOnly = false;\n return;\n }\n if (!hasOnlyInlineContent($, $child)) {\n inlineOnly = false;\n }\n });\n\n return inlineOnly;\n}\n\nfunction walkChildren(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToGrapesOptions,\n): GrapesComponent[] {\n const components: GrapesComponent[] = [];\n\n $el.contents().each((_, node) => {\n const walked = walkNode($, $(node), options);\n if (!walked) return;\n if (Array.isArray(walked)) {\n components.push(...walked);\n } else {\n components.push(walked);\n }\n });\n\n return components;\n}\n\nfunction walkNode(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToGrapesOptions,\n): GrapesComponent | GrapesComponent[] | null {\n const node = $el.get(0);\n if (!node) return null;\n\n if (node.type === \"text\") {\n const text = \"data\" in node ? String(node.data ?? \"\") : \"\";\n if (!text.trim()) return null;\n return { type: \"textnode\", content: text };\n }\n\n if (node.type !== \"tag\") return null;\n\n const tagName = tagNameOf($el);\n if (!tagName || SKIP_TAGS.has(tagName)) return null;\n\n const meta = pickElementMeta($el);\n\n const layoutKind = parseLayoutKind(meta.attributes);\n if (layoutKind) {\n const components = walkChildren($, $el, options);\n const component = applyElementMeta(\n {\n type: resolveLayoutComponentType(layoutKind, options),\n tagName,\n },\n {\n attributes: layoutAttributesForComponent(meta.attributes),\n classes: meta.classes,\n },\n );\n if (components.length > 0) {\n component.components = components;\n }\n return component;\n }\n\n if (VOID_TAGS.has(tagName)) {\n return applyElementMeta(\n {\n type: resolveComponentType(tagName, meta.classes, options),\n tagName,\n void: true,\n },\n meta,\n );\n }\n\n if (TEXT_CONTAINER_TAGS.has(tagName) && hasOnlyInlineContent($, $el)) {\n return applyElementMeta(\n {\n type: resolveComponentType(tagName, meta.classes, options, \"text\"),\n tagName,\n content: $el.html() ?? \"\",\n },\n meta,\n );\n }\n\n if (INLINE_TAGS.has(tagName)) {\n return applyElementMeta(\n {\n type: \"text\",\n content: $.html($el) ?? \"\",\n },\n meta,\n );\n }\n\n const components = walkChildren($, $el, options);\n const component = applyElementMeta(\n {\n type: resolveComponentType(tagName, meta.classes, options),\n tagName,\n },\n meta,\n );\n\n if (components.length > 0) {\n component.components = components;\n }\n\n return component;\n}\n\nfunction appendWalked(\n content: GrapesComponent[],\n walked: GrapesComponent | GrapesComponent[] | null,\n): void {\n if (!walked) return;\n if (Array.isArray(walked)) {\n content.push(...walked);\n return;\n }\n content.push(walked);\n}\n\nfunction walkNodes(\n $: CheerioAPI,\n $nodes: CheerioSelection,\n content: GrapesComponent[],\n options: HtmlToGrapesOptions,\n): void {\n $nodes.each((_, node) => {\n appendWalked(content, walkNode($, $(node), options));\n });\n}\n\nexport function walkHtmlToComponents(\n $: CheerioAPI,\n options: HtmlToGrapesOptions = {},\n): GrapesComponent[] {\n const content: GrapesComponent[] = [];\n const body = $(\"body\");\n\n if (body.length) {\n walkNodes($, body.contents(), content, options);\n return content;\n }\n\n const children = $.root().children();\n if (children.length) {\n walkNodes($, children, content, options);\n } else {\n walkNodes($, $.root().contents(), content, options);\n }\n\n return content;\n}\n","import * as cheerio from \"cheerio\";\n\nimport type { HtmlToTiptapOptions, TiptapDoc } from \"./types.js\";\nimport { prepareHtmlForTiptap, walkHtmlToTiptapDoc } from \"./walk.js\";\n\nexport type { HtmlToTiptapOptions, TiptapDoc, TiptapMark, TiptapNode } from \"./types.js\";\n\n/** Cheerio HTML walk → Tiptap / ProseMirror `doc` JSON for blog `content_json`. */\nexport function htmlToTiptap(html: string, options: HtmlToTiptapOptions = {}): TiptapDoc {\n const trimmed = html.trim();\n if (!trimmed) {\n return { type: \"doc\", content: [{ type: \"paragraph\" }] };\n }\n\n const $ = cheerio.load(trimmed, { xml: false });\n prepareHtmlForTiptap($);\n return walkHtmlToTiptapDoc($, options);\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { AnyNode, Element } from \"domhandler\";\n\nimport type { HtmlToTiptapOptions, TiptapDoc, TiptapMark, TiptapNode } from \"./types.js\";\n\ntype CheerioSelection = Cheerio<AnyNode>;\n\nconst SKIP_TAGS = new Set([\"script\", \"style\", \"noscript\", \"template\"]);\nconst HEADING_TAGS = new Set([\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"]);\nconst UNWRAP_TAGS = new Set([\n \"article\",\n \"aside\",\n \"div\",\n \"figure\",\n \"footer\",\n \"header\",\n \"main\",\n \"nav\",\n \"section\",\n \"span\",\n]);\n\nconst INLINE_TAGS = new Set([\n \"a\",\n \"abbr\",\n \"b\",\n \"br\",\n \"cite\",\n \"code\",\n \"del\",\n \"em\",\n \"i\",\n \"ins\",\n \"mark\",\n \"q\",\n \"s\",\n \"small\",\n \"strong\",\n \"sub\",\n \"sup\",\n \"u\",\n \"wbr\",\n]);\n\nconst LAYOUT_ATTR = \"data-layout\";\n\nfunction tagNameOf($el: CheerioSelection): string | undefined {\n const raw = $el.prop(\"tagName\");\n return typeof raw === \"string\" ? raw.toLowerCase() : undefined;\n}\n\nfunction headingLevel(tagName: string): number {\n const level = Number.parseInt(tagName.slice(1), 10);\n return Number.isFinite(level) ? level : 1;\n}\n\nfunction isLayoutMarker($el: CheerioSelection, options: HtmlToTiptapOptions): boolean {\n if (options.unwrapLayoutMarkers === false) return false;\n return $el.attr(LAYOUT_ATTR) !== undefined;\n}\n\nfunction hasOnlyInlineContent($: CheerioAPI, $el: CheerioSelection): boolean {\n let inlineOnly = true;\n\n $el.contents().each((_, node) => {\n if (!inlineOnly) return;\n const $child = $(node);\n if ($child.get(0)?.type === \"text\") return;\n const childTag = tagNameOf($child);\n if (!childTag || childTag === \"br\" || childTag === \"img\") return;\n if (!INLINE_TAGS.has(childTag)) {\n inlineOnly = false;\n return;\n }\n if (!hasOnlyInlineContent($, $child)) {\n inlineOnly = false;\n }\n });\n\n return inlineOnly;\n}\n\nfunction hasBlockChild($: CheerioAPI, $el: CheerioSelection): boolean {\n let hasBlock = false;\n $el.contents().each((_, node) => {\n if (hasBlock) return;\n const $child = $(node);\n if ($child.get(0)?.type === \"text\") return;\n const childTag = tagNameOf($child);\n if (!childTag) return;\n if (\n HEADING_TAGS.has(childTag) ||\n childTag === \"p\" ||\n childTag === \"ul\" ||\n childTag === \"ol\" ||\n childTag === \"blockquote\" ||\n childTag === \"pre\" ||\n childTag === \"hr\" ||\n childTag === \"img\" ||\n childTag === \"table\" ||\n isLayoutMarker($child, { unwrapLayoutMarkers: true }) ||\n (UNWRAP_TAGS.has(childTag) && hasBlockChild($, $child))\n ) {\n hasBlock = true;\n }\n });\n return hasBlock;\n}\n\nfunction textNode(text: string, marks: TiptapMark[] = []): TiptapNode {\n const node: TiptapNode = { type: \"text\", text };\n if (marks.length > 0) node.marks = marks;\n return node;\n}\n\nfunction paragraph(content: TiptapNode[]): TiptapNode {\n return content.length > 0 ? { type: \"paragraph\", content } : { type: \"paragraph\" };\n}\n\nfunction appendMarks(existing: TiptapMark[], added: TiptapMark): TiptapMark[] {\n if (existing.some((mark) => mark.type === added.type)) return existing;\n return [...existing, added];\n}\n\nfunction marksForTag(tagName: string, $el: CheerioSelection): TiptapMark[] {\n switch (tagName) {\n case \"strong\":\n case \"b\":\n return [{ type: \"bold\" }];\n case \"em\":\n case \"i\":\n return [{ type: \"italic\" }];\n case \"s\":\n case \"del\":\n case \"strike\":\n return [{ type: \"strike\" }];\n case \"u\":\n return [{ type: \"underline\" }];\n case \"code\":\n return [{ type: \"code\" }];\n case \"a\": {\n const href = $el.attr(\"href\");\n if (!href) return [];\n const attrs: Record<string, string> = { href };\n const target = $el.attr(\"target\");\n if (target) attrs.target = target;\n const rel = $el.attr(\"rel\");\n if (rel) attrs.rel = rel;\n return [{ type: \"link\", attrs }];\n }\n default:\n return [];\n }\n}\n\nfunction imageNode($el: CheerioSelection): TiptapNode | null {\n const src = $el.attr(\"src\");\n if (!src) return null;\n const attrs: Record<string, unknown> = { src };\n const alt = $el.attr(\"alt\");\n if (alt !== undefined) attrs.alt = alt;\n const title = $el.attr(\"title\");\n if (title) attrs.title = title;\n return { type: \"image\", attrs };\n}\n\nfunction parseInlineContent(\n $: CheerioAPI,\n $el: CheerioSelection,\n marks: TiptapMark[] = [],\n): TiptapNode[] {\n const rootTag = tagNameOf($el);\n if (rootTag && INLINE_TAGS.has(rootTag) && rootTag !== \"br\") {\n marks = marksForTag(rootTag, $el).reduce((acc, mark) => appendMarks(acc, mark), marks);\n }\n\n const nodes: TiptapNode[] = [];\n\n $el.contents().each((_, node) => {\n if (node.type === \"text\") {\n const text = String(node.data ?? \"\");\n if (text) nodes.push(textNode(text, marks));\n return;\n }\n\n if (node.type !== \"tag\") return;\n\n const $child = $(node);\n const tagName = tagNameOf($child);\n if (!tagName || SKIP_TAGS.has(tagName)) return;\n\n if (tagName === \"br\") {\n nodes.push({ type: \"hardBreak\" });\n return;\n }\n\n if (tagName === \"img\") {\n return;\n }\n\n const childMarks = marksForTag(tagName, $child);\n const combinedMarks = childMarks.reduce((acc, mark) => appendMarks(acc, mark), [...marks]);\n nodes.push(...parseInlineContent($, $child, combinedMarks));\n });\n\n return nodes;\n}\n\n/** Parse a block container that holds inline content (p, heading, etc.). Splits on nested block/img. */\nfunction parseMixedBlockContent(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToTiptapOptions,\n): TiptapNode[] {\n const blocks: TiptapNode[] = [];\n let inlineBuffer: TiptapNode[] = [];\n\n function flushInline(): void {\n if (inlineBuffer.length === 0) return;\n blocks.push(paragraph(inlineBuffer));\n inlineBuffer = [];\n }\n\n $el.contents().each((_, node) => {\n if (node.type === \"text\") {\n const text = String(node.data ?? \"\");\n if (text) inlineBuffer.push(textNode(text));\n return;\n }\n\n if (node.type !== \"tag\") return;\n\n const $child = $(node);\n const tagName = tagNameOf($child);\n if (!tagName || SKIP_TAGS.has(tagName)) return;\n\n if (tagName === \"br\") {\n inlineBuffer.push({ type: \"hardBreak\" });\n return;\n }\n\n if (tagName === \"img\") {\n flushInline();\n const image = imageNode($child);\n if (image) blocks.push(image);\n return;\n }\n\n if (INLINE_TAGS.has(tagName)) {\n inlineBuffer.push(...parseInlineContent($, $child));\n return;\n }\n\n flushInline();\n blocks.push(...walkBlockNodes($, $child, options));\n });\n\n flushInline();\n return blocks;\n}\n\nfunction walkListItem($: CheerioAPI, $el: CheerioSelection, options: HtmlToTiptapOptions): TiptapNode {\n const blocks = walkBlockNodes($, $el, options);\n if (blocks.length === 0) {\n return { type: \"listItem\", content: [{ type: \"paragraph\" }] };\n }\n\n const normalized: TiptapNode[] = [];\n for (const block of blocks) {\n if (\n block.type === \"paragraph\" ||\n block.type === \"image\" ||\n block.type === \"blockquote\" ||\n block.type === \"bulletList\" ||\n block.type === \"orderedList\"\n ) {\n normalized.push(block);\n continue;\n }\n normalized.push(paragraph(block.content ?? []));\n }\n\n return { type: \"listItem\", content: normalized };\n}\n\nfunction walkBlockNode(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToTiptapOptions,\n): TiptapNode[] {\n const node = $el.get(0);\n if (!node) return [];\n\n if (node.type === \"text\") {\n const text = String(node.data ?? \"\").trim();\n return text ? [paragraph([textNode(text)])] : [];\n }\n\n if (node.type !== \"tag\") return [];\n\n const tagName = tagNameOf($el);\n if (!tagName || SKIP_TAGS.has(tagName)) return [];\n\n if (isLayoutMarker($el, options)) {\n return walkBlockNodes($, $el, options);\n }\n\n if (UNWRAP_TAGS.has(tagName)) {\n if (hasBlockChild($, $el)) {\n return walkBlockNodes($, $el, options);\n }\n if (hasOnlyInlineContent($, $el)) {\n const inline = parseInlineContent($, $el);\n return inline.length > 0 ? [paragraph(inline)] : [];\n }\n return walkBlockNodes($, $el, options);\n }\n\n if (HEADING_TAGS.has(tagName)) {\n const content = parseInlineContent($, $el);\n if (content.length === 0) return [];\n return [{ type: \"heading\", attrs: { level: headingLevel(tagName) }, content }];\n }\n\n if (tagName === \"p\") {\n return parseMixedBlockContent($, $el, options);\n }\n\n if (tagName === \"ul\") {\n const items: TiptapNode[] = [];\n $el.children(\"li\").each((_, li) => {\n items.push(walkListItem($, $(li), options));\n });\n return items.length > 0 ? [{ type: \"bulletList\", content: items }] : [];\n }\n\n if (tagName === \"ol\") {\n const items: TiptapNode[] = [];\n $el.children(\"li\").each((_, li) => {\n items.push(walkListItem($, $(li), options));\n });\n return items.length > 0 ? [{ type: \"orderedList\", content: items }] : [];\n }\n\n if (tagName === \"li\") {\n return [walkListItem($, $el, options)];\n }\n\n if (tagName === \"blockquote\") {\n const blocks = walkBlockNodes($, $el, options);\n if (blocks.length === 0) return [];\n return [{ type: \"blockquote\", content: blocks }];\n }\n\n if (tagName === \"pre\") {\n const code = $el.find(\"code\").first();\n const text = (code.length ? code.text() : $el.text()).replace(/\\n$/, \"\");\n if (!text) return [];\n return [{ type: \"codeBlock\", content: [textNode(text)] }];\n }\n\n if (tagName === \"hr\") {\n return [{ type: \"horizontalRule\" }];\n }\n\n if (tagName === \"img\") {\n const image = imageNode($el);\n return image ? [image] : [];\n }\n\n if (tagName === \"table\") {\n const rows: string[] = [];\n $el.find(\"tr\").each((_, tr) => {\n const cells: string[] = [];\n $(tr)\n .find(\"th, td\")\n .each((__, cell) => {\n const text = $(cell).text().trim();\n if (text) cells.push(text);\n });\n if (cells.length > 0) rows.push(cells.join(\" | \"));\n });\n return rows.map((row) => paragraph([textNode(row)]));\n }\n\n return walkBlockNodes($, $el, options);\n}\n\nfunction walkBlockNodes(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToTiptapOptions,\n): TiptapNode[] {\n const blocks: TiptapNode[] = [];\n\n $el.contents().each((_, node) => {\n blocks.push(...walkBlockNode($, $(node), options));\n });\n\n return blocks;\n}\n\nfunction normalizeDocContent(content: TiptapNode[]): TiptapNode[] {\n const normalized: TiptapNode[] = [];\n\n for (const block of content) {\n if (block.type === \"paragraph\" && (!block.content || block.content.length === 0)) {\n continue;\n }\n normalized.push(block);\n }\n\n return normalized;\n}\n\nexport function walkHtmlToTiptapDoc(\n $: CheerioAPI,\n options: HtmlToTiptapOptions = {},\n): TiptapDoc {\n const resolved: HtmlToTiptapOptions = {\n unwrapLayoutMarkers: options.unwrapLayoutMarkers ?? true,\n };\n\n let content: TiptapNode[] = [];\n const body = $(\"body\");\n\n if (body.length) {\n content = walkBlockNodes($, body, resolved);\n } else {\n const children = $.root().children();\n if (children.length) {\n content = walkBlockNodes($, children, resolved);\n } else {\n content = walkBlockNodes($, $.root(), resolved);\n }\n }\n\n content = normalizeDocContent(content);\n if (content.length === 0) {\n content = [{ type: \"paragraph\" }];\n }\n\n return { type: \"doc\", content };\n}\n\n/** Strip layout/style noise before walking (mutates loaded DOM). */\nexport function prepareHtmlForTiptap($: CheerioAPI): void {\n $(\"style, script, noscript, template\").remove();\n}\n\nexport function isElementNode(node: AnyNode): node is Element {\n return node.type === \"tag\";\n}\n","import { z } from \"zod\";\n\nimport type { ValidationIssue, ValidationResult } from \"../normalizer/types.js\";\nimport type { GrapesComponent, GrapesProjectSnapshot } from \"./html-to-grapes/types.js\";\n\nexport const grapesStyleRuleSchema = z.object({\n selectors: z.array(z.string().min(1)).min(1),\n style: z.record(z.string(), z.string()),\n});\n\nexport const grapesComponentSchema: z.ZodType<GrapesComponent> = z.lazy(() =>\n z.object({\n type: z.string().min(1),\n tagName: z.string().optional(),\n attributes: z.record(z.string(), z.string()).optional(),\n classes: z.array(z.string()).optional(),\n components: z.array(grapesComponentSchema).optional(),\n content: z.string().optional(),\n void: z.boolean().optional(),\n }),\n);\n\nexport const grapesProjectSnapshotSchema = z.object({\n content: z.array(grapesComponentSchema),\n styles: z.array(grapesStyleRuleSchema),\n contentHtml: z.string().optional(),\n contentCss: z.string().optional(),\n});\n\nexport interface ValidateGrapesProjectSnapshotOptions {\n /** When set, every component `type` in the tree must be in this allowlist. */\n allowedComponentTypes?: string[];\n}\n\nfunction zodIssuesToValidationIssues(issues: z.ZodIssue[]): ValidationIssue[] {\n return issues.map((issue) => ({\n code: issue.code,\n message: issue.message,\n path: issue.path.length > 0 ? issue.path.join(\".\") : undefined,\n }));\n}\n\nfunction collectComponentTypes(components: GrapesComponent[]): string[] {\n const types: string[] = [];\n for (const component of components) {\n types.push(component.type);\n if (component.components?.length) {\n types.push(...collectComponentTypes(component.components));\n }\n }\n return types;\n}\n\nfunction validateAllowedComponentTypes(\n snapshot: GrapesProjectSnapshot,\n allowedComponentTypes: string[],\n): ValidationIssue[] {\n const allowlist = new Set(allowedComponentTypes);\n const issues: ValidationIssue[] = [];\n\n for (const componentType of collectComponentTypes(snapshot.content)) {\n if (!allowlist.has(componentType)) {\n issues.push({\n code: \"invalid_component_type\",\n message: `Component type \"${componentType}\" is not in allowedComponentTypes`,\n path: \"content\",\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Opt-in structural check for a Grapes project snapshot (not a full Grapes editor project file).\n * Does not validate host-specific component registries unless `allowedComponentTypes` is passed.\n */\nexport function validateGrapesProjectSnapshot(\n snapshot: unknown,\n options: ValidateGrapesProjectSnapshotOptions = {},\n): ValidationResult {\n const result = grapesProjectSnapshotSchema.safeParse(snapshot);\n if (!result.success) {\n return { ok: false, issues: zodIssuesToValidationIssues(result.error.issues) };\n }\n\n if (options.allowedComponentTypes?.length) {\n const typeIssues = validateAllowedComponentTypes(result.data, options.allowedComponentTypes);\n if (typeIssues.length > 0) {\n return { ok: false, issues: typeIssues };\n }\n }\n\n return { ok: true, issues: [] };\n}\n","import { z } from \"zod\";\n\nimport type { ValidationIssue, ValidationResult } from \"../normalizer/types.js\";\nimport type { TiptapDoc, TiptapNode } from \"./html-to-tiptap/types.js\";\n\nexport const tiptapMarkSchema = z.object({\n type: z.string().min(1),\n attrs: z.record(z.string(), z.string()).optional(),\n});\n\nexport const tiptapNodeSchema: z.ZodType<TiptapNode> = z.lazy(() =>\n z.union([\n z.object({\n type: z.literal(\"text\"),\n text: z.string(),\n marks: z.array(tiptapMarkSchema).optional(),\n }),\n z.object({\n type: z.string().min(1),\n attrs: z.record(z.unknown()).optional(),\n content: z.array(tiptapNodeSchema).optional(),\n marks: z.array(tiptapMarkSchema).optional(),\n }),\n ]),\n);\n\nexport const tiptapDocSchema = z.object({\n type: z.literal(\"doc\"),\n content: z.array(tiptapNodeSchema),\n});\n\nexport interface ValidateTiptapDocOptions {\n /** When set, every node `type` in the tree must be in this allowlist. */\n allowedNodeTypes?: string[];\n /** When set, every mark `type` must be in this allowlist. */\n allowedMarkTypes?: string[];\n}\n\nfunction zodIssuesToValidationIssues(issues: z.ZodIssue[]): ValidationIssue[] {\n return issues.map((issue) => ({\n code: issue.code,\n message: issue.message,\n path: issue.path.length > 0 ? issue.path.join(\".\") : undefined,\n }));\n}\n\nfunction collectNodeTypes(nodes: TiptapNode[]): string[] {\n const types: string[] = [];\n for (const node of nodes) {\n types.push(node.type);\n if (node.content?.length) {\n types.push(...collectNodeTypes(node.content));\n }\n }\n return types;\n}\n\nfunction collectMarkTypes(nodes: TiptapNode[]): string[] {\n const types: string[] = [];\n for (const node of nodes) {\n if (node.marks?.length) {\n types.push(...node.marks.map((mark) => mark.type));\n }\n if (node.content?.length) {\n types.push(...collectMarkTypes(node.content));\n }\n }\n return types;\n}\n\nfunction validateAllowedTypes(\n doc: TiptapDoc,\n allowedNodeTypes: string[] | undefined,\n allowedMarkTypes: string[] | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n\n if (allowedNodeTypes) {\n const allowlist = new Set(allowedNodeTypes);\n for (const nodeType of collectNodeTypes(doc.content)) {\n if (!allowlist.has(nodeType)) {\n issues.push({\n code: \"invalid_node_type\",\n message: `Node type \"${nodeType}\" is not in allowedNodeTypes`,\n path: \"content\",\n });\n }\n }\n }\n\n if (allowedMarkTypes) {\n const allowlist = new Set(allowedMarkTypes);\n for (const markType of collectMarkTypes(doc.content)) {\n if (!allowlist.has(markType)) {\n issues.push({\n code: \"invalid_mark_type\",\n message: `Mark type \"${markType}\" is not in allowedMarkTypes`,\n path: \"content\",\n });\n }\n }\n }\n\n return issues;\n}\n\n/** Opt-in structural check for a Tiptap / ProseMirror document. */\nexport function validateTiptapDoc(\n doc: unknown,\n options: ValidateTiptapDocOptions = {},\n): ValidationResult {\n const parsed = tiptapDocSchema.safeParse(doc);\n if (!parsed.success) {\n return { ok: false, issues: zodIssuesToValidationIssues(parsed.error.issues) };\n }\n\n const typeIssues = validateAllowedTypes(\n parsed.data,\n options.allowedNodeTypes,\n options.allowedMarkTypes,\n );\n if (typeIssues.length > 0) {\n return { ok: false, issues: typeIssues };\n }\n\n return { ok: true, issues: [] };\n}\n"],"mappings":"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","names":["components","component","cheerio","SKIP_TAGS","INLINE_TAGS","tagNameOf","hasOnlyInlineContent","z","zodIssuesToValidationIssues"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeAssetUrl
|
|
3
|
+
} from "./chunk-2PNSVE5Y.js";
|
|
4
|
+
|
|
5
|
+
// src/transformers/rewrite-inline-images.ts
|
|
6
|
+
import * as cheerio from "cheerio";
|
|
7
|
+
function rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved) {
|
|
8
|
+
return srcset.split(",").map((entry) => {
|
|
9
|
+
const trimmed = entry.trim();
|
|
10
|
+
if (!trimmed) return entry;
|
|
11
|
+
const [urlPart, descriptor] = trimmed.split(/\s+/, 2);
|
|
12
|
+
const normalized = normalizeAssetUrl(urlPart ?? "");
|
|
13
|
+
if (!normalized) return entry;
|
|
14
|
+
referencedSources.add(normalized);
|
|
15
|
+
const ref = options.resolveAsset(normalized);
|
|
16
|
+
if (!ref?.sourceAssetId) {
|
|
17
|
+
unresolved.add(normalized);
|
|
18
|
+
return entry;
|
|
19
|
+
}
|
|
20
|
+
const uploaded = uploadedBySourceId.get(ref.sourceAssetId);
|
|
21
|
+
if (!uploaded) {
|
|
22
|
+
unresolved.add(normalized);
|
|
23
|
+
return entry;
|
|
24
|
+
}
|
|
25
|
+
const replaced = options.replaceWith(ref, uploaded);
|
|
26
|
+
return descriptor ? `${replaced} ${descriptor}` : replaced;
|
|
27
|
+
}).join(", ");
|
|
28
|
+
}
|
|
29
|
+
function rewriteInlineImages(html, options, uploadedBySourceId) {
|
|
30
|
+
if (!html.trim()) {
|
|
31
|
+
return { html, referencedSources: [], unresolved: [] };
|
|
32
|
+
}
|
|
33
|
+
const $ = cheerio.load(html, { xml: false });
|
|
34
|
+
const referencedSources = /* @__PURE__ */ new Set();
|
|
35
|
+
const unresolved = /* @__PURE__ */ new Set();
|
|
36
|
+
$("img").each((_, element) => {
|
|
37
|
+
const img = $(element);
|
|
38
|
+
const src = img.attr("src")?.trim();
|
|
39
|
+
if (src && !src.startsWith("data:")) {
|
|
40
|
+
const normalized = normalizeAssetUrl(src);
|
|
41
|
+
if (normalized) {
|
|
42
|
+
referencedSources.add(normalized);
|
|
43
|
+
const ref = options.resolveAsset(normalized);
|
|
44
|
+
if (!ref?.sourceAssetId) {
|
|
45
|
+
unresolved.add(normalized);
|
|
46
|
+
} else {
|
|
47
|
+
const uploaded = uploadedBySourceId.get(ref.sourceAssetId);
|
|
48
|
+
if (!uploaded) {
|
|
49
|
+
unresolved.add(normalized);
|
|
50
|
+
} else {
|
|
51
|
+
img.attr("src", options.replaceWith(ref, uploaded));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const srcset = img.attr("srcset")?.trim();
|
|
57
|
+
if (srcset) {
|
|
58
|
+
img.attr("srcset", rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
html: $.root().html() ?? html,
|
|
63
|
+
referencedSources: [...referencedSources],
|
|
64
|
+
unresolved: [...unresolved]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
rewriteInlineImages
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=chunk-S7TRWILI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/transformers/rewrite-inline-images.ts"],"sourcesContent":["import * as cheerio from \"cheerio\";\n\nimport { normalizeAssetUrl } from \"../lib/content-asset-urls.js\";\n\nexport interface RewriteInlineImageRef {\n originalSrc: string;\n sourceAssetId?: string;\n}\n\nexport interface UploadedAssetRef {\n targetId: string;\n publicUrl?: string;\n}\n\nexport interface RewriteInlineImagesOptions {\n resolveAsset: (src: string) => RewriteInlineImageRef | undefined;\n replaceWith: (ref: RewriteInlineImageRef, uploaded: UploadedAssetRef) => string;\n}\n\nexport interface RewriteInlineImagesResult {\n html: string;\n referencedSources: string[];\n unresolved: string[];\n}\n\nfunction rewriteSrcset(\n srcset: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n referencedSources: Set<string>,\n unresolved: Set<string>,\n): string {\n return srcset\n .split(\",\")\n .map((entry) => {\n const trimmed = entry.trim();\n if (!trimmed) return entry;\n const [urlPart, descriptor] = trimmed.split(/\\s+/, 2);\n const normalized = normalizeAssetUrl(urlPart ?? \"\");\n if (!normalized) return entry;\n referencedSources.add(normalized);\n const ref = options.resolveAsset(normalized);\n if (!ref?.sourceAssetId) {\n unresolved.add(normalized);\n return entry;\n }\n const uploaded = uploadedBySourceId.get(ref.sourceAssetId);\n if (!uploaded) {\n unresolved.add(normalized);\n return entry;\n }\n const replaced = options.replaceWith(ref, uploaded);\n return descriptor ? `${replaced} ${descriptor}` : replaced;\n })\n .join(\", \");\n}\n\n/** Rewrite `<img src>` / `srcset` using uploaded asset targets supplied by the host sink. */\nexport function rewriteInlineImages(\n html: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n): RewriteInlineImagesResult {\n if (!html.trim()) {\n return { html, referencedSources: [], unresolved: [] };\n }\n\n const $ = cheerio.load(html, { xml: false });\n const referencedSources = new Set<string>();\n const unresolved = new Set<string>();\n\n $(\"img\").each((_, element) => {\n const img = $(element);\n const src = img.attr(\"src\")?.trim();\n if (src && !src.startsWith(\"data:\")) {\n const normalized = normalizeAssetUrl(src);\n if (normalized) {\n referencedSources.add(normalized);\n const ref = options.resolveAsset(normalized);\n if (!ref?.sourceAssetId) {\n unresolved.add(normalized);\n } else {\n const uploaded = uploadedBySourceId.get(ref.sourceAssetId);\n if (!uploaded) {\n unresolved.add(normalized);\n } else {\n img.attr(\"src\", options.replaceWith(ref, uploaded));\n }\n }\n }\n }\n\n const srcset = img.attr(\"srcset\")?.trim();\n if (srcset) {\n img.attr(\"srcset\", rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved));\n }\n });\n\n return {\n html: $.root().html() ?? html,\n referencedSources: [...referencedSources],\n unresolved: [...unresolved],\n };\n}\n"],"mappings":";;;;;AAAA,YAAY,aAAa;AAyBzB,SAAS,cACP,QACA,SACA,oBACA,mBACA,YACQ;AACR,SAAO,OACJ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU;AACd,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,CAAC,SAAS,UAAU,IAAI,QAAQ,MAAM,OAAO,CAAC;AACpD,UAAM,aAAa,kBAAkB,WAAW,EAAE;AAClD,QAAI,CAAC,WAAY,QAAO;AACxB,sBAAkB,IAAI,UAAU;AAChC,UAAM,MAAM,QAAQ,aAAa,UAAU;AAC3C,QAAI,CAAC,KAAK,eAAe;AACvB,iBAAW,IAAI,UAAU;AACzB,aAAO;AAAA,IACT;AACA,UAAM,WAAW,mBAAmB,IAAI,IAAI,aAAa;AACzD,QAAI,CAAC,UAAU;AACb,iBAAW,IAAI,UAAU;AACzB,aAAO;AAAA,IACT;AACA,UAAM,WAAW,QAAQ,YAAY,KAAK,QAAQ;AAClD,WAAO,aAAa,GAAG,QAAQ,IAAI,UAAU,KAAK;AAAA,EACpD,CAAC,EACA,KAAK,IAAI;AACd;AAGO,SAAS,oBACd,MACA,SACA,oBAC2B;AAC3B,MAAI,CAAC,KAAK,KAAK,GAAG;AAChB,WAAO,EAAE,MAAM,mBAAmB,CAAC,GAAG,YAAY,CAAC,EAAE;AAAA,EACvD;AAEA,QAAM,IAAY,aAAK,MAAM,EAAE,KAAK,MAAM,CAAC;AAC3C,QAAM,oBAAoB,oBAAI,IAAY;AAC1C,QAAM,aAAa,oBAAI,IAAY;AAEnC,IAAE,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY;AAC5B,UAAM,MAAM,EAAE,OAAO;AACrB,UAAM,MAAM,IAAI,KAAK,KAAK,GAAG,KAAK;AAClC,QAAI,OAAO,CAAC,IAAI,WAAW,OAAO,GAAG;AACnC,YAAM,aAAa,kBAAkB,GAAG;AACxC,UAAI,YAAY;AACd,0BAAkB,IAAI,UAAU;AAChC,cAAM,MAAM,QAAQ,aAAa,UAAU;AAC3C,YAAI,CAAC,KAAK,eAAe;AACvB,qBAAW,IAAI,UAAU;AAAA,QAC3B,OAAO;AACL,gBAAM,WAAW,mBAAmB,IAAI,IAAI,aAAa;AACzD,cAAI,CAAC,UAAU;AACb,uBAAW,IAAI,UAAU;AAAA,UAC3B,OAAO;AACL,gBAAI,KAAK,OAAO,QAAQ,YAAY,KAAK,QAAQ,CAAC;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,IAAI,KAAK,QAAQ,GAAG,KAAK;AACxC,QAAI,QAAQ;AACV,UAAI,KAAK,UAAU,cAAc,QAAQ,SAAS,oBAAoB,mBAAmB,UAAU,CAAC;AAAA,IACtG;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK;AAAA,IACzB,mBAAmB,CAAC,GAAG,iBAAiB;AAAA,IACxC,YAAY,CAAC,GAAG,UAAU;AAAA,EAC5B;AACF;","names":[]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SquarespaceCollectionClient,
|
|
3
|
+
WORDPRESS_BUILDER_REGISTRY,
|
|
3
4
|
enumerateSquarespaceEntities,
|
|
4
5
|
linkToPath,
|
|
5
6
|
sanitizeSlug,
|
|
6
7
|
summarizeSquarespaceExport,
|
|
7
8
|
validateSquarespaceExportFile
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YLFVYPB3.js";
|
|
9
10
|
import {
|
|
10
11
|
discoverContentAssetUrls,
|
|
11
12
|
normalizeAssetUrl
|
|
@@ -43,45 +44,112 @@ import { readFile } from "fs/promises";
|
|
|
43
44
|
import { basename } from "path";
|
|
44
45
|
import { XMLParser } from "fast-xml-parser";
|
|
45
46
|
|
|
46
|
-
// src/parsers/wordpress/builders/registry.ts
|
|
47
|
-
var WORDPRESS_BUILDER_REGISTRY = [
|
|
48
|
-
{
|
|
49
|
-
id: "tatsu",
|
|
50
|
-
detect: /\[(?:\/)?tatsu_/i,
|
|
51
|
-
contentRules: [
|
|
52
|
-
{ shortcodePrefix: "tatsu_image", urlParams: ["image", "url", "src"], tag: "img" },
|
|
53
|
-
{ shortcodePrefix: "tatsu_video", urlParams: ["video", "src", "url"], tag: "video" }
|
|
54
|
-
],
|
|
55
|
-
scaffoldingPrefix: "tatsu_"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: "divi",
|
|
59
|
-
detect: /\[(?:\/)?et_pb_/i,
|
|
60
|
-
contentRules: [{ shortcodePrefix: "et_pb_image", urlParams: ["src", "url"], tag: "img" }],
|
|
61
|
-
scaffoldingPrefix: "et_pb_"
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
id: "elementor",
|
|
65
|
-
detect: /\[(?:\/)?elementor[-_]/i,
|
|
66
|
-
contentRules: [
|
|
67
|
-
{ shortcodePrefix: "elementor-widget", urlParams: ["url", "src", "image"], tag: "img" }
|
|
68
|
-
],
|
|
69
|
-
scaffoldingPrefix: "elementor_"
|
|
70
|
-
}
|
|
71
|
-
];
|
|
72
|
-
|
|
73
47
|
// src/parsers/wordpress/builders/flatten.ts
|
|
74
48
|
function escapeRegExp(value) {
|
|
75
49
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
76
50
|
}
|
|
51
|
+
function extractQuotedParam(params, name) {
|
|
52
|
+
const pattern = new RegExp(`\\b${escapeRegExp(name)}\\s*=\\s*`, "i");
|
|
53
|
+
const match = pattern.exec(params);
|
|
54
|
+
if (!match) return void 0;
|
|
55
|
+
let index = match.index + match[0].length;
|
|
56
|
+
while (index < params.length && /\s/.test(params[index])) index += 1;
|
|
57
|
+
const quote = params[index];
|
|
58
|
+
if (quote !== '"' && quote !== "'") return void 0;
|
|
59
|
+
index += 1;
|
|
60
|
+
let value = "";
|
|
61
|
+
while (index < params.length) {
|
|
62
|
+
const char = params[index];
|
|
63
|
+
if (char === "\\" && index + 1 < params.length) {
|
|
64
|
+
value += params[index + 1];
|
|
65
|
+
index += 2;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (char === quote) break;
|
|
69
|
+
value += char;
|
|
70
|
+
index += 1;
|
|
71
|
+
}
|
|
72
|
+
const trimmed = value.trim();
|
|
73
|
+
return trimmed || void 0;
|
|
74
|
+
}
|
|
75
|
+
function escapeLayoutAttr(value) {
|
|
76
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
77
|
+
}
|
|
78
|
+
function parseRowLayoutCols(layout) {
|
|
79
|
+
if (!layout?.trim()) return void 0;
|
|
80
|
+
const parts = layout.split("+").map((part) => part.trim()).filter(Boolean);
|
|
81
|
+
return parts.length > 1 ? parts.length : void 0;
|
|
82
|
+
}
|
|
83
|
+
function openSectionDiv(params, bgParamName) {
|
|
84
|
+
const attrs = ['data-layout="section"'];
|
|
85
|
+
const bgImage = extractQuotedParam(params, bgParamName ?? "bg_image");
|
|
86
|
+
if (bgImage?.startsWith("http")) {
|
|
87
|
+
attrs.push(`data-bg-image="${escapeLayoutAttr(bgImage)}"`);
|
|
88
|
+
}
|
|
89
|
+
return `<div ${attrs.join(" ")}>`;
|
|
90
|
+
}
|
|
91
|
+
function openRowDiv(params, colsParamName) {
|
|
92
|
+
const attrs = ['data-layout="row"'];
|
|
93
|
+
const cols = parseRowLayoutCols(extractQuotedParam(params, colsParamName ?? "layout"));
|
|
94
|
+
if (cols) attrs.push(`data-cols="${cols}"`);
|
|
95
|
+
return `<div ${attrs.join(" ")}>`;
|
|
96
|
+
}
|
|
97
|
+
function applyPrefixedLayoutMap(content, map) {
|
|
98
|
+
let html = content;
|
|
99
|
+
html = html.replace(map.sectionRegex, (_, params) => openSectionDiv(params, map.bgParamName));
|
|
100
|
+
html = html.replace(map.sectionCloseRegex, "</div>");
|
|
101
|
+
html = html.replace(map.rowRegex, (_, params) => openRowDiv(params, map.colsParamName));
|
|
102
|
+
html = html.replace(map.rowCloseRegex, "</div>");
|
|
103
|
+
html = html.replace(map.columnRegex, '<div data-layout="column">');
|
|
104
|
+
html = html.replace(map.columnCloseRegex, "</div>");
|
|
105
|
+
return html;
|
|
106
|
+
}
|
|
107
|
+
function applyFractionalLayoutMap(content, map) {
|
|
108
|
+
let html = content;
|
|
109
|
+
html = html.replace(map.sectionRegex, (_, params) => openSectionDiv(params, map.bgParamName));
|
|
110
|
+
html = html.replace(map.sectionCloseRegex, "</div>");
|
|
111
|
+
html = html.replace(map.rowRegex, (_, params) => openRowDiv(params));
|
|
112
|
+
html = html.replace(map.rowCloseRegex, "</div>");
|
|
113
|
+
for (let index = 0; index < map.columnTokens.length; index += 1) {
|
|
114
|
+
const token = map.columnTokens[index];
|
|
115
|
+
const width = map.columnWidths[token];
|
|
116
|
+
const openRegex = map.columnOpenRegexes[index];
|
|
117
|
+
const closeRegex = map.columnCloseRegexes[index];
|
|
118
|
+
html = html.replace(openRegex, () => {
|
|
119
|
+
const attrs = ['data-layout="column"'];
|
|
120
|
+
if (width) attrs.push(`data-col-width="${width}"`);
|
|
121
|
+
return `<div ${attrs.join(" ")}>`;
|
|
122
|
+
});
|
|
123
|
+
html = html.replace(closeRegex, "</div>");
|
|
124
|
+
}
|
|
125
|
+
return html;
|
|
126
|
+
}
|
|
127
|
+
function applyStructuralLayoutMap(content, map) {
|
|
128
|
+
switch (map.kind) {
|
|
129
|
+
case "prefixed":
|
|
130
|
+
return applyPrefixedLayoutMap(content, map);
|
|
131
|
+
case "fractional":
|
|
132
|
+
return applyFractionalLayoutMap(content, map);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
77
135
|
function extractShortcodeParam(params, names) {
|
|
78
136
|
for (const name of names) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
if (match?.[1]?.trim()) return match[1].trim();
|
|
137
|
+
const value = extractQuotedParam(params, name);
|
|
138
|
+
if (value) return value;
|
|
82
139
|
}
|
|
83
140
|
return void 0;
|
|
84
141
|
}
|
|
142
|
+
function escapeHtmlText(text) {
|
|
143
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
144
|
+
}
|
|
145
|
+
function textToHtml(text, tag) {
|
|
146
|
+
const paragraphs = text.split(/\n{2,}/).map((part) => part.trim()).filter(Boolean);
|
|
147
|
+
if (paragraphs.length === 0) return "";
|
|
148
|
+
return paragraphs.map((paragraph) => {
|
|
149
|
+
const inner = escapeHtmlText(paragraph).replace(/\n/g, "<br />");
|
|
150
|
+
return `<${tag}>${inner}</${tag}>`;
|
|
151
|
+
}).join("\n");
|
|
152
|
+
}
|
|
85
153
|
function emitHtmlTag(tag, url) {
|
|
86
154
|
const normalized = normalizeAssetUrl(url) ?? url;
|
|
87
155
|
const escaped = normalized.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
@@ -94,10 +162,10 @@ function emitHtmlTag(tag, url) {
|
|
|
94
162
|
return `<iframe src="${escaped}" loading="lazy"></iframe>`;
|
|
95
163
|
}
|
|
96
164
|
}
|
|
97
|
-
function
|
|
165
|
+
function convertUrlRule(content, rule) {
|
|
98
166
|
const prefix = escapeRegExp(rule.shortcodePrefix);
|
|
99
167
|
const pattern = new RegExp(
|
|
100
|
-
`\\[${prefix}([^\\]]*)\\]\\s*(?:\\[\\/${prefix}[^\\]]*\\])?`,
|
|
168
|
+
`\\[${prefix}\\b([^\\]]*)\\]\\s*(?:\\[\\/${prefix}\\b[^\\]]*\\])?`,
|
|
101
169
|
"gi"
|
|
102
170
|
);
|
|
103
171
|
return content.replace(pattern, (block, params) => {
|
|
@@ -106,12 +174,85 @@ function convertContentBlocker(content, rule) {
|
|
|
106
174
|
return emitHtmlTag(rule.tag, url);
|
|
107
175
|
});
|
|
108
176
|
}
|
|
109
|
-
function
|
|
177
|
+
function convertTextRule(content, rule) {
|
|
178
|
+
const prefix = escapeRegExp(rule.shortcodePrefix);
|
|
179
|
+
const pattern = new RegExp(
|
|
180
|
+
`\\[${prefix}\\b([^\\]]*)\\]\\s*(?:\\[\\/${prefix}\\b[^\\]]*\\])?`,
|
|
181
|
+
"gis"
|
|
182
|
+
);
|
|
183
|
+
return content.replace(pattern, (block, params) => {
|
|
184
|
+
const parts = [];
|
|
185
|
+
for (const field of rule.fields) {
|
|
186
|
+
const text = extractQuotedParam(params, field.param);
|
|
187
|
+
if (!text) continue;
|
|
188
|
+
const html = textToHtml(text, field.tag);
|
|
189
|
+
if (html) parts.push(html);
|
|
190
|
+
}
|
|
191
|
+
return parts.length > 0 ? parts.join("\n") : block;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function convertWrapperRule(content, rule) {
|
|
195
|
+
const prefix = escapeRegExp(rule.shortcodePrefix);
|
|
196
|
+
const pattern = new RegExp(
|
|
197
|
+
`\\[${prefix}\\b([^\\]]*)\\]([\\s\\S]*?)\\[\\/${prefix}\\b[^\\]]*\\]`,
|
|
198
|
+
"gi"
|
|
199
|
+
);
|
|
200
|
+
return content.replace(pattern, (_, params, inner) => {
|
|
201
|
+
const parts = [];
|
|
202
|
+
if (rule.urlParams?.length) {
|
|
203
|
+
const url = extractShortcodeParam(params, rule.urlParams);
|
|
204
|
+
if (url) parts.push(emitHtmlTag("img", url));
|
|
205
|
+
}
|
|
206
|
+
parts.push(inner.trim());
|
|
207
|
+
return parts.filter(Boolean).join("\n");
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
function convertIconImageRule(content, rule) {
|
|
211
|
+
const prefix = escapeRegExp(rule.shortcodePrefix);
|
|
212
|
+
const pattern = new RegExp(
|
|
213
|
+
`\\[${prefix}\\b([^\\]]*)\\]\\s*(?:\\[\\/${prefix}\\b[^\\]]*\\])?`,
|
|
214
|
+
"gi"
|
|
215
|
+
);
|
|
216
|
+
return content.replace(pattern, (_, params) => {
|
|
217
|
+
const iconImage = extractQuotedParam(params, rule.imageParam);
|
|
218
|
+
if (!iconImage?.startsWith("http") || iconImage.includes("placehold")) {
|
|
219
|
+
return "";
|
|
220
|
+
}
|
|
221
|
+
const img = emitHtmlTag("img", iconImage);
|
|
222
|
+
if (rule.hrefParam) {
|
|
223
|
+
const href = extractQuotedParam(params, rule.hrefParam);
|
|
224
|
+
if (href?.startsWith("http")) {
|
|
225
|
+
const escapedHref = href.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
226
|
+
return `<a href="${escapedHref}">${img}</a>`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return img;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function convertPlaceholderRule(content, rule) {
|
|
233
|
+
const prefix = escapeRegExp(rule.shortcodePrefix);
|
|
234
|
+
const pattern = new RegExp(
|
|
235
|
+
`\\[${prefix}\\b([^\\]]*)\\]\\s*(?:\\[\\/${prefix}\\b[^\\]]*\\])?`,
|
|
236
|
+
"gi"
|
|
237
|
+
);
|
|
238
|
+
return content.replace(pattern, rule.html);
|
|
239
|
+
}
|
|
240
|
+
function stripScaffoldingPrefix(content, prefix) {
|
|
110
241
|
const escaped = escapeRegExp(prefix);
|
|
111
242
|
const opener = new RegExp(`\\[${escaped}[a-z0-9_-]*[^\\]]*\\]`, "gi");
|
|
112
243
|
const closer = new RegExp(`\\[\\/${escaped}[a-z0-9_-]*[^\\]]*\\]`, "gi");
|
|
113
244
|
return content.replace(opener, "").replace(closer, "");
|
|
114
245
|
}
|
|
246
|
+
function stripLegacyTokens(content, tokens) {
|
|
247
|
+
let result = content;
|
|
248
|
+
for (const token of tokens) {
|
|
249
|
+
const escaped = escapeRegExp(token);
|
|
250
|
+
const opener = new RegExp(`\\[${escaped}\\b[^\\]]*\\]`, "gi");
|
|
251
|
+
const closer = new RegExp(`\\[\\/${escaped}\\b[^\\]]*\\]`, "gi");
|
|
252
|
+
result = result.replace(opener, "").replace(closer, "");
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
115
256
|
function detectThemes(content, registry) {
|
|
116
257
|
return registry.filter((theme) => theme.detect.test(content));
|
|
117
258
|
}
|
|
@@ -126,10 +267,30 @@ function flattenWordPressBuilders(content, options = {}) {
|
|
|
126
267
|
}
|
|
127
268
|
let html = content;
|
|
128
269
|
for (const theme of themes) {
|
|
129
|
-
for (const rule of theme.
|
|
130
|
-
html =
|
|
270
|
+
for (const rule of theme.wrapperRules ?? []) {
|
|
271
|
+
html = convertWrapperRule(html, rule);
|
|
272
|
+
}
|
|
273
|
+
for (const rule of theme.textRules ?? []) {
|
|
274
|
+
html = convertTextRule(html, rule);
|
|
275
|
+
}
|
|
276
|
+
for (const rule of theme.urlRules ?? []) {
|
|
277
|
+
html = convertUrlRule(html, rule);
|
|
278
|
+
}
|
|
279
|
+
for (const rule of theme.placeholderRules ?? []) {
|
|
280
|
+
html = convertPlaceholderRule(html, rule);
|
|
281
|
+
}
|
|
282
|
+
for (const rule of theme.iconImageRules ?? []) {
|
|
283
|
+
html = convertIconImageRule(html, rule);
|
|
284
|
+
}
|
|
285
|
+
if (theme.layoutMap) {
|
|
286
|
+
html = applyStructuralLayoutMap(html, theme.layoutMap);
|
|
287
|
+
}
|
|
288
|
+
for (const prefix of theme.scaffoldingPrefixes ?? []) {
|
|
289
|
+
html = stripScaffoldingPrefix(html, prefix);
|
|
290
|
+
}
|
|
291
|
+
if (theme.legacyScaffoldingTokens?.length) {
|
|
292
|
+
html = stripLegacyTokens(html, theme.legacyScaffoldingTokens);
|
|
131
293
|
}
|
|
132
|
-
html = stripScaffolding(html, theme.scaffoldingPrefix);
|
|
133
294
|
}
|
|
134
295
|
html = html.replace(/\n{3,}/g, "\n\n").trim();
|
|
135
296
|
return {
|
|
@@ -140,6 +301,14 @@ function flattenWordPressBuilders(content, options = {}) {
|
|
|
140
301
|
|
|
141
302
|
// src/parsers/wordpress/parse-wxr.ts
|
|
142
303
|
var PLATFORM = "wordpress";
|
|
304
|
+
var WOOCOMMERCE_STUB_PAGE_SLUGS = /* @__PURE__ */ new Set(["cart", "checkout", "my-account"]);
|
|
305
|
+
var WOOCOMMERCE_STUB_SHORTCODE = /^\[woocommerce_(?:cart|checkout|my_account)\]\s*$/i;
|
|
306
|
+
function isWooCommerceStubPage(slug, contentHtml) {
|
|
307
|
+
if (WOOCOMMERCE_STUB_PAGE_SLUGS.has(slug)) return true;
|
|
308
|
+
const trimmed = contentHtml.trim();
|
|
309
|
+
if (!trimmed) return false;
|
|
310
|
+
return WOOCOMMERCE_STUB_SHORTCODE.test(trimmed);
|
|
311
|
+
}
|
|
143
312
|
function asArray(value) {
|
|
144
313
|
if (value === void 0) return [];
|
|
145
314
|
return Array.isArray(value) ? value : [value];
|
|
@@ -316,6 +485,11 @@ function resolveFeaturedAssetSourceId(thumbnailId, attachmentIndex, contentHtml)
|
|
|
316
485
|
const firstInline = discoverContentAssetUrls(contentHtml)[0];
|
|
317
486
|
return firstInline ? `url:${firstInline}` : void 0;
|
|
318
487
|
}
|
|
488
|
+
function maybeRewriteUrl(url, config) {
|
|
489
|
+
if (!url) return void 0;
|
|
490
|
+
if (!config) return url;
|
|
491
|
+
return rewriteOriginUrlsInText(url, config);
|
|
492
|
+
}
|
|
319
493
|
async function* enumerateWxrEntities(options) {
|
|
320
494
|
const xml = await readFile(options.filePath, "utf8");
|
|
321
495
|
const items = parseItems(xml);
|
|
@@ -346,9 +520,12 @@ async function* enumerateWxrEntities(options) {
|
|
|
346
520
|
const postType = textValue(item.post_type);
|
|
347
521
|
if (postType !== "post" && postType !== "page") continue;
|
|
348
522
|
const id = textValue(item.post_id);
|
|
349
|
-
const link = textValue(item.link);
|
|
523
|
+
const link = maybeRewriteUrl(textValue(item.link), options.originUrlRewrite);
|
|
350
524
|
const slug = sanitizeSlug(textValue(item.post_name) || textValue(item.title) || id);
|
|
351
525
|
const contentHtml = preprocessContent(getContentEncoded(item), options);
|
|
526
|
+
if (postType === "page" && options.skipWooCommerceStubPages !== false && isWooCommerceStubPage(slug, contentHtml)) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
352
529
|
for (const asset of collectInlineAssets(
|
|
353
530
|
contentHtml,
|
|
354
531
|
attachmentIndex,
|
|
@@ -446,10 +623,13 @@ function resolveWxrOptions(input) {
|
|
|
446
623
|
return {
|
|
447
624
|
filePath: String(obj.path),
|
|
448
625
|
originUrlRewrite: obj.originUrlRewrite,
|
|
449
|
-
flattenBuilders: obj.flattenBuilders
|
|
626
|
+
flattenBuilders: obj.flattenBuilders,
|
|
627
|
+
skipWooCommerceStubPages: obj.skipWooCommerceStubPages
|
|
450
628
|
};
|
|
451
629
|
}
|
|
452
|
-
throw new Error(
|
|
630
|
+
throw new Error(
|
|
631
|
+
"WordPress adapter requires input path (string or { path, originUrlRewrite?, flattenBuilders?, skipWooCommerceStubPages? })"
|
|
632
|
+
);
|
|
453
633
|
}
|
|
454
634
|
var wordpressAdapter = {
|
|
455
635
|
platform: "wordpress",
|
|
@@ -2441,4 +2621,4 @@ export {
|
|
|
2441
2621
|
wixAdapter,
|
|
2442
2622
|
getAdapter
|
|
2443
2623
|
};
|
|
2444
|
-
//# sourceMappingURL=chunk-
|
|
2624
|
+
//# sourceMappingURL=chunk-XUBCG3IA.js.map
|