@artinstack/migrator 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle-uAAHehbv.d.ts +23 -0
- package/dist/chunk-CIOYDRY5.js +851 -0
- package/dist/chunk-CIOYDRY5.js.map +1 -0
- package/dist/chunk-EXYXTAZM.js +91 -0
- package/dist/chunk-EXYXTAZM.js.map +1 -0
- package/dist/{chunk-XKWWXKP3.js → chunk-IPYHS5R2.js} +157 -87
- package/dist/chunk-IPYHS5R2.js.map +1 -0
- package/dist/{chunk-Q6M5JEL3.js → chunk-XQVKA54A.js} +150 -6
- package/dist/chunk-XQVKA54A.js.map +1 -0
- package/dist/chunk-XYP3VYDH.js +159 -0
- package/dist/chunk-XYP3VYDH.js.map +1 -0
- package/dist/cli/index.js +4 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +8 -87
- package/dist/index.js +29 -353
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +14 -4
- package/dist/lib/index.js +7 -3
- package/dist/normalizer/index.d.ts +4 -2
- package/dist/rewrite-inline-images-DPoxyzVC.d.ts +21 -0
- package/dist/sinks/index.d.ts +262 -3
- package/dist/sinks/index.js +5 -3
- 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-2PNSVE5Y.js +0 -67
- package/dist/chunk-2PNSVE5Y.js.map +0 -1
- package/dist/chunk-Q6M5JEL3.js.map +0 -1
- package/dist/chunk-XKWWXKP3.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,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeAssetUrl
|
|
3
|
+
} from "./chunk-XYP3VYDH.js";
|
|
4
|
+
|
|
5
|
+
// src/transformers/rewrite-inline-images.ts
|
|
6
|
+
import * as cheerio from "cheerio";
|
|
7
|
+
var BACKGROUND_IMAGE_URL_PATTERN = /background(?:-image)?\s*:[^;]*?url\s*\(\s*(['"]?)([^'")]+)\1\s*\)/gi;
|
|
8
|
+
function tryRewriteUrl(src, options, uploadedBySourceId, referencedSources, unresolved) {
|
|
9
|
+
const normalized = normalizeAssetUrl(src);
|
|
10
|
+
if (!normalized) return void 0;
|
|
11
|
+
referencedSources.add(normalized);
|
|
12
|
+
const ref = options.resolveAsset(normalized);
|
|
13
|
+
if (!ref?.sourceAssetId) {
|
|
14
|
+
unresolved.add(normalized);
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
const uploaded = uploadedBySourceId.get(ref.sourceAssetId);
|
|
18
|
+
if (!uploaded) {
|
|
19
|
+
unresolved.add(normalized);
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
return options.replaceWith(ref, uploaded);
|
|
23
|
+
}
|
|
24
|
+
function rewriteBackgroundUrlsInStyle(style, options, uploadedBySourceId, referencedSources, unresolved) {
|
|
25
|
+
return style.replace(BACKGROUND_IMAGE_URL_PATTERN, (full, quote, rawUrl) => {
|
|
26
|
+
const replaced = tryRewriteUrl(rawUrl.trim(), options, uploadedBySourceId, referencedSources, unresolved);
|
|
27
|
+
if (!replaced) return full;
|
|
28
|
+
const urlCall = quote ? `url(${quote}${replaced}${quote})` : `url(${replaced})`;
|
|
29
|
+
return full.replace(/url\s*\(\s*(['"]?)([^'")]+)\1\s*\)/i, urlCall);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved) {
|
|
33
|
+
return srcset.split(",").map((entry) => {
|
|
34
|
+
const trimmed = entry.trim();
|
|
35
|
+
if (!trimmed) return entry;
|
|
36
|
+
const [urlPart, descriptor] = trimmed.split(/\s+/, 2);
|
|
37
|
+
const replaced = tryRewriteUrl(urlPart ?? "", options, uploadedBySourceId, referencedSources, unresolved);
|
|
38
|
+
if (!replaced) return entry;
|
|
39
|
+
return descriptor ? `${replaced} ${descriptor}` : replaced;
|
|
40
|
+
}).join(", ");
|
|
41
|
+
}
|
|
42
|
+
function rewriteInlineImages(html, options, uploadedBySourceId) {
|
|
43
|
+
if (!html.trim()) {
|
|
44
|
+
return { html, referencedSources: [], unresolved: [] };
|
|
45
|
+
}
|
|
46
|
+
const $ = cheerio.load(html, { xml: false });
|
|
47
|
+
const referencedSources = /* @__PURE__ */ new Set();
|
|
48
|
+
const unresolved = /* @__PURE__ */ new Set();
|
|
49
|
+
$("img").each((_, element) => {
|
|
50
|
+
const img = $(element);
|
|
51
|
+
const src = img.attr("src")?.trim();
|
|
52
|
+
if (src && !src.startsWith("data:")) {
|
|
53
|
+
const replaced = tryRewriteUrl(src, options, uploadedBySourceId, referencedSources, unresolved);
|
|
54
|
+
if (replaced) img.attr("src", replaced);
|
|
55
|
+
}
|
|
56
|
+
const srcset = img.attr("srcset")?.trim();
|
|
57
|
+
if (srcset) {
|
|
58
|
+
img.attr("srcset", rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
$("[data-bg-image]").each((_, element) => {
|
|
62
|
+
const node = $(element);
|
|
63
|
+
const bgImage = node.attr("data-bg-image")?.trim();
|
|
64
|
+
if (!bgImage || bgImage.startsWith("data:")) return;
|
|
65
|
+
const replaced = tryRewriteUrl(bgImage, options, uploadedBySourceId, referencedSources, unresolved);
|
|
66
|
+
if (replaced) node.attr("data-bg-image", replaced);
|
|
67
|
+
});
|
|
68
|
+
$("[style]").each((_, element) => {
|
|
69
|
+
const node = $(element);
|
|
70
|
+
const style = node.attr("style");
|
|
71
|
+
if (!style?.includes("background")) return;
|
|
72
|
+
const rewritten = rewriteBackgroundUrlsInStyle(
|
|
73
|
+
style,
|
|
74
|
+
options,
|
|
75
|
+
uploadedBySourceId,
|
|
76
|
+
referencedSources,
|
|
77
|
+
unresolved
|
|
78
|
+
);
|
|
79
|
+
if (rewritten !== style) node.attr("style", rewritten);
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
html: $.root().html() ?? html,
|
|
83
|
+
referencedSources: [...referencedSources],
|
|
84
|
+
unresolved: [...unresolved]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
rewriteInlineImages
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=chunk-EXYXTAZM.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\n/** Inline CSS `background` / `background-image: url(…)` (quoted or bare). */\nconst BACKGROUND_IMAGE_URL_PATTERN =\n /background(?:-image)?\\s*:[^;]*?url\\s*\\(\\s*(['\"]?)([^'\")]+)\\1\\s*\\)/gi;\n\nfunction tryRewriteUrl(\n src: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n referencedSources: Set<string>,\n unresolved: Set<string>,\n): string | undefined {\n const normalized = normalizeAssetUrl(src);\n if (!normalized) return undefined;\n\n referencedSources.add(normalized);\n const ref = options.resolveAsset(normalized);\n if (!ref?.sourceAssetId) {\n unresolved.add(normalized);\n return undefined;\n }\n\n const uploaded = uploadedBySourceId.get(ref.sourceAssetId);\n if (!uploaded) {\n unresolved.add(normalized);\n return undefined;\n }\n\n return options.replaceWith(ref, uploaded);\n}\n\nfunction rewriteBackgroundUrlsInStyle(\n style: string,\n options: RewriteInlineImagesOptions,\n uploadedBySourceId: Map<string, UploadedAssetRef>,\n referencedSources: Set<string>,\n unresolved: Set<string>,\n): string {\n return style.replace(BACKGROUND_IMAGE_URL_PATTERN, (full, quote: string, rawUrl: string) => {\n const replaced = tryRewriteUrl(rawUrl.trim(), options, uploadedBySourceId, referencedSources, unresolved);\n if (!replaced) return full;\n\n const urlCall = quote\n ? `url(${quote}${replaced}${quote})`\n : `url(${replaced})`;\n return full.replace(/url\\s*\\(\\s*(['\"]?)([^'\")]+)\\1\\s*\\)/i, urlCall);\n });\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 replaced = tryRewriteUrl(urlPart ?? \"\", options, uploadedBySourceId, referencedSources, unresolved);\n if (!replaced) return entry;\n return descriptor ? `${replaced} ${descriptor}` : replaced;\n })\n .join(\", \");\n}\n\n/** Rewrite `<img src>` / `srcset`, `data-bg-image`, and inline CSS backgrounds using uploaded asset targets. */\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 replaced = tryRewriteUrl(src, options, uploadedBySourceId, referencedSources, unresolved);\n if (replaced) img.attr(\"src\", replaced);\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 $(\"[data-bg-image]\").each((_, element) => {\n const node = $(element);\n const bgImage = node.attr(\"data-bg-image\")?.trim();\n if (!bgImage || bgImage.startsWith(\"data:\")) return;\n const replaced = tryRewriteUrl(bgImage, options, uploadedBySourceId, referencedSources, unresolved);\n if (replaced) node.attr(\"data-bg-image\", replaced);\n });\n\n $(\"[style]\").each((_, element) => {\n const node = $(element);\n const style = node.attr(\"style\");\n if (!style?.includes(\"background\")) return;\n const rewritten = rewriteBackgroundUrlsInStyle(\n style,\n options,\n uploadedBySourceId,\n referencedSources,\n unresolved,\n );\n if (rewritten !== style) node.attr(\"style\", rewritten);\n });\n\n return {\n html: $.root().html() ?? html,\n referencedSources: [...referencedSources],\n unresolved: [...unresolved],\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,11 +6,14 @@ import {
|
|
|
6
6
|
entityKey,
|
|
7
7
|
shouldProcessEntity
|
|
8
8
|
} from "./chunk-HI7JHWZU.js";
|
|
9
|
+
import {
|
|
10
|
+
rewriteInlineImages
|
|
11
|
+
} from "./chunk-EXYXTAZM.js";
|
|
9
12
|
import {
|
|
10
13
|
discoverContentAssetUrls,
|
|
11
14
|
discoverRawImgSrcs,
|
|
12
15
|
normalizeAssetUrl
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XYP3VYDH.js";
|
|
14
17
|
|
|
15
18
|
// src/sinks/types.ts
|
|
16
19
|
var MIGRATION_WRITE_STAGES = [
|
|
@@ -25,71 +28,8 @@ var MIGRATION_WRITE_STAGES = [
|
|
|
25
28
|
// src/sinks/run-migration.ts
|
|
26
29
|
import { Readable } from "stream";
|
|
27
30
|
|
|
28
|
-
// src/transformers/rewrite-inline-images.ts
|
|
29
|
-
import * as cheerio from "cheerio";
|
|
30
|
-
function rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved) {
|
|
31
|
-
return srcset.split(",").map((entry) => {
|
|
32
|
-
const trimmed = entry.trim();
|
|
33
|
-
if (!trimmed) return entry;
|
|
34
|
-
const [urlPart, descriptor] = trimmed.split(/\s+/, 2);
|
|
35
|
-
const normalized = normalizeAssetUrl(urlPart ?? "");
|
|
36
|
-
if (!normalized) return entry;
|
|
37
|
-
referencedSources.add(normalized);
|
|
38
|
-
const ref = options.resolveAsset(normalized);
|
|
39
|
-
if (!ref?.sourceAssetId) {
|
|
40
|
-
unresolved.add(normalized);
|
|
41
|
-
return entry;
|
|
42
|
-
}
|
|
43
|
-
const uploaded = uploadedBySourceId.get(ref.sourceAssetId);
|
|
44
|
-
if (!uploaded) {
|
|
45
|
-
unresolved.add(normalized);
|
|
46
|
-
return entry;
|
|
47
|
-
}
|
|
48
|
-
const replaced = options.replaceWith(ref, uploaded);
|
|
49
|
-
return descriptor ? `${replaced} ${descriptor}` : replaced;
|
|
50
|
-
}).join(", ");
|
|
51
|
-
}
|
|
52
|
-
function rewriteInlineImages(html, options, uploadedBySourceId) {
|
|
53
|
-
if (!html.trim()) {
|
|
54
|
-
return { html, referencedSources: [], unresolved: [] };
|
|
55
|
-
}
|
|
56
|
-
const $ = cheerio.load(html, { xml: false });
|
|
57
|
-
const referencedSources = /* @__PURE__ */ new Set();
|
|
58
|
-
const unresolved = /* @__PURE__ */ new Set();
|
|
59
|
-
$("img").each((_, element) => {
|
|
60
|
-
const img = $(element);
|
|
61
|
-
const src = img.attr("src")?.trim();
|
|
62
|
-
if (src && !src.startsWith("data:")) {
|
|
63
|
-
const normalized = normalizeAssetUrl(src);
|
|
64
|
-
if (normalized) {
|
|
65
|
-
referencedSources.add(normalized);
|
|
66
|
-
const ref = options.resolveAsset(normalized);
|
|
67
|
-
if (!ref?.sourceAssetId) {
|
|
68
|
-
unresolved.add(normalized);
|
|
69
|
-
} else {
|
|
70
|
-
const uploaded = uploadedBySourceId.get(ref.sourceAssetId);
|
|
71
|
-
if (!uploaded) {
|
|
72
|
-
unresolved.add(normalized);
|
|
73
|
-
} else {
|
|
74
|
-
img.attr("src", options.replaceWith(ref, uploaded));
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const srcset = img.attr("srcset")?.trim();
|
|
80
|
-
if (srcset) {
|
|
81
|
-
img.attr("srcset", rewriteSrcset(srcset, options, uploadedBySourceId, referencedSources, unresolved));
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
return {
|
|
85
|
-
html: $.root().html() ?? html,
|
|
86
|
-
referencedSources: [...referencedSources],
|
|
87
|
-
unresolved: [...unresolved]
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
31
|
// src/sinks/conflicts.ts
|
|
92
|
-
import * as
|
|
32
|
+
import * as cheerio2 from "cheerio";
|
|
93
33
|
|
|
94
34
|
// src/parsers/squarespace/parse-export.ts
|
|
95
35
|
import { readFile } from "fs/promises";
|
|
@@ -115,7 +55,7 @@ function linkToPath(link) {
|
|
|
115
55
|
}
|
|
116
56
|
|
|
117
57
|
// src/parsers/squarespace/collect.ts
|
|
118
|
-
import * as
|
|
58
|
+
import * as cheerio from "cheerio";
|
|
119
59
|
import { z } from "zod";
|
|
120
60
|
var SQUARESPACE_JSON_FORMAT = "json-pretty";
|
|
121
61
|
var squarespaceClientOptionsSchema = z.object({
|
|
@@ -168,7 +108,7 @@ function inferBlockTypeFromClassName(className) {
|
|
|
168
108
|
}
|
|
169
109
|
function extractBlocksFromBodyHtml(html) {
|
|
170
110
|
if (!html.trim()) return [];
|
|
171
|
-
const $ =
|
|
111
|
+
const $ = cheerio.load(html, { xml: false });
|
|
172
112
|
const blocks = [];
|
|
173
113
|
$(".sqs-block").each((_, element) => {
|
|
174
114
|
const el = $(element);
|
|
@@ -964,6 +904,63 @@ function findUnsupportedBlockMarkers(html) {
|
|
|
964
904
|
}
|
|
965
905
|
|
|
966
906
|
// src/parsers/wordpress/builders/registry.ts
|
|
907
|
+
function layoutEscapeRegExp(value) {
|
|
908
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
909
|
+
}
|
|
910
|
+
function shortcodeOpenRegex(token) {
|
|
911
|
+
return new RegExp(`\\[${layoutEscapeRegExp(token)}\\b([^\\]]*)\\]`, "gi");
|
|
912
|
+
}
|
|
913
|
+
function shortcodeCloseRegex(token) {
|
|
914
|
+
return new RegExp(`\\[\\/${layoutEscapeRegExp(token)}\\b[^\\]]*\\]`, "gi");
|
|
915
|
+
}
|
|
916
|
+
var FRACTIONAL_COLUMN_WIDTHS = {
|
|
917
|
+
one_col: "100%",
|
|
918
|
+
one_half: "50%",
|
|
919
|
+
one_third: "33.33%",
|
|
920
|
+
two_third: "66.67%",
|
|
921
|
+
two_thirds: "66.67%",
|
|
922
|
+
one_fourth: "25%",
|
|
923
|
+
three_fourth: "75%",
|
|
924
|
+
three_fourths: "75%"
|
|
925
|
+
};
|
|
926
|
+
function parseFractionalColumnWidth(token) {
|
|
927
|
+
return FRACTIONAL_COLUMN_WIDTHS[token];
|
|
928
|
+
}
|
|
929
|
+
function prefixedLayoutMap(config) {
|
|
930
|
+
return {
|
|
931
|
+
kind: "prefixed",
|
|
932
|
+
sectionRegex: shortcodeOpenRegex(config.section),
|
|
933
|
+
sectionCloseRegex: shortcodeCloseRegex(config.section),
|
|
934
|
+
rowRegex: shortcodeOpenRegex(config.row),
|
|
935
|
+
rowCloseRegex: shortcodeCloseRegex(config.row),
|
|
936
|
+
columnRegex: shortcodeOpenRegex(config.column),
|
|
937
|
+
columnCloseRegex: shortcodeCloseRegex(config.column),
|
|
938
|
+
bgParamName: config.bgParamName,
|
|
939
|
+
colsParamName: config.colsParamName
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function extendedPrefixedLayoutMap(levels) {
|
|
943
|
+
return { kind: "extended-prefixed", levels };
|
|
944
|
+
}
|
|
945
|
+
function fractionalLayoutMap(config) {
|
|
946
|
+
const columnWidths = {};
|
|
947
|
+
for (const token of config.columns) {
|
|
948
|
+
const width = parseFractionalColumnWidth(token);
|
|
949
|
+
if (width) columnWidths[token] = width;
|
|
950
|
+
}
|
|
951
|
+
return {
|
|
952
|
+
kind: "fractional",
|
|
953
|
+
sectionRegex: shortcodeOpenRegex(config.section),
|
|
954
|
+
sectionCloseRegex: shortcodeCloseRegex(config.section),
|
|
955
|
+
rowRegex: shortcodeOpenRegex(config.row),
|
|
956
|
+
rowCloseRegex: shortcodeCloseRegex(config.row),
|
|
957
|
+
columnTokens: config.columns,
|
|
958
|
+
columnOpenRegexes: config.columns.map(shortcodeOpenRegex),
|
|
959
|
+
columnCloseRegexes: config.columns.map(shortcodeCloseRegex),
|
|
960
|
+
columnWidths,
|
|
961
|
+
bgParamName: config.bgParamName
|
|
962
|
+
};
|
|
963
|
+
}
|
|
967
964
|
var UNRESOLVABLE_SHORTCODE_PREFIXES = [
|
|
968
965
|
"portfolio",
|
|
969
966
|
"recent_posts",
|
|
@@ -975,18 +972,73 @@ var WORDPRESS_BUILDER_REGISTRY = [
|
|
|
975
972
|
{
|
|
976
973
|
id: "tatsu",
|
|
977
974
|
detect: /\[(?:\/)?tatsu_/i,
|
|
975
|
+
layoutMap: prefixedLayoutMap({
|
|
976
|
+
section: "tatsu_section",
|
|
977
|
+
row: "tatsu_row",
|
|
978
|
+
column: "tatsu_column",
|
|
979
|
+
bgParamName: "bg_image",
|
|
980
|
+
colsParamName: "layout"
|
|
981
|
+
}),
|
|
982
|
+
wrapperRules: [
|
|
983
|
+
{ shortcodePrefix: "tatsu_text" },
|
|
984
|
+
{ shortcodePrefix: "tatsu_inline_text" },
|
|
985
|
+
{ shortcodePrefix: "tatsu_text_with_shortcodes" }
|
|
986
|
+
],
|
|
978
987
|
urlRules: [
|
|
979
988
|
{ shortcodePrefix: "tatsu_image", urlParams: ["image", "url", "src"], tag: "img" },
|
|
989
|
+
{ shortcodePrefix: "tatsu_single_image", urlParams: ["image", "url", "src"], tag: "img" },
|
|
980
990
|
{ shortcodePrefix: "tatsu_video", urlParams: ["video", "src", "url"], tag: "video" }
|
|
981
991
|
],
|
|
992
|
+
iconImageRules: [
|
|
993
|
+
{ shortcodePrefix: "tatsu_icon", imageParam: "icon_image", hrefParam: "href" }
|
|
994
|
+
],
|
|
982
995
|
scaffoldingPrefixes: ["tatsu_"]
|
|
983
996
|
},
|
|
984
997
|
{
|
|
985
998
|
id: "divi",
|
|
986
999
|
detect: /\[(?:\/)?et_pb_/i,
|
|
1000
|
+
layoutMap: prefixedLayoutMap({
|
|
1001
|
+
section: "et_pb_section",
|
|
1002
|
+
row: "et_pb_row",
|
|
1003
|
+
column: "et_pb_column",
|
|
1004
|
+
bgParamName: "background_image"
|
|
1005
|
+
}),
|
|
987
1006
|
urlRules: [{ shortcodePrefix: "et_pb_image", urlParams: ["src", "url"], tag: "img" }],
|
|
988
1007
|
scaffoldingPrefixes: ["et_pb_"]
|
|
989
1008
|
},
|
|
1009
|
+
{
|
|
1010
|
+
id: "wpbakery",
|
|
1011
|
+
detect: /\[(?:\/)?vc_/i,
|
|
1012
|
+
layoutMap: extendedPrefixedLayoutMap([
|
|
1013
|
+
{ role: "section", tokens: ["vc_section"], bgParamName: "bg_image" },
|
|
1014
|
+
{ role: "row", tokens: ["vc_row"], colsParamName: "layout" },
|
|
1015
|
+
{ role: "column", tokens: ["vc_column_inner", "vc_column"], widthParamName: "width" }
|
|
1016
|
+
]),
|
|
1017
|
+
urlRules: [
|
|
1018
|
+
{ shortcodePrefix: "vc_single_image", urlParams: ["image", "src", "url"], tag: "img" }
|
|
1019
|
+
],
|
|
1020
|
+
scaffoldingPrefixes: ["vc_"]
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
id: "fusion",
|
|
1024
|
+
detect: /\[(?:\/)?fusion_/i,
|
|
1025
|
+
layoutMap: prefixedLayoutMap({
|
|
1026
|
+
section: "fusion_builder_container",
|
|
1027
|
+
row: "fusion_builder_row",
|
|
1028
|
+
column: "fusion_builder_column",
|
|
1029
|
+
bgParamName: "background_image"
|
|
1030
|
+
}),
|
|
1031
|
+
scaffoldingPrefixes: ["fusion_"]
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
id: "beaver",
|
|
1035
|
+
detect: /\[(?:\/)?fl_(?:row|col|builder)/i,
|
|
1036
|
+
layoutMap: extendedPrefixedLayoutMap([
|
|
1037
|
+
{ role: "row", tokens: ["fl_row"] },
|
|
1038
|
+
{ role: "column", tokens: ["fl_col"] }
|
|
1039
|
+
]),
|
|
1040
|
+
scaffoldingPrefixes: ["fl_"]
|
|
1041
|
+
},
|
|
990
1042
|
{
|
|
991
1043
|
id: "elementor",
|
|
992
1044
|
detect: /\[(?:\/)?elementor[-_]/i,
|
|
@@ -997,7 +1049,33 @@ var WORDPRESS_BUILDER_REGISTRY = [
|
|
|
997
1049
|
},
|
|
998
1050
|
{
|
|
999
1051
|
id: "oshine",
|
|
1000
|
-
detect: /\[(?:special_sub_title|special_heading5|blox_\w+|grid_content|grids|testimonial\b|portfolio\b|recent_posts\b|animate_icon\w*|section\b|row\b|one_col|text\b)/i,
|
|
1052
|
+
detect: /\[(?:special_sub_title|special_heading5|blox_\w+|grid_content|grids|testimonial\b|portfolio\b|recent_posts\b|animate_icon\w*|section\b|row\b|one_col|one_third|one_half|one_fourth|two_third|three_fourth|text\b)/i,
|
|
1053
|
+
layoutMap: fractionalLayoutMap({
|
|
1054
|
+
section: "section",
|
|
1055
|
+
row: "row",
|
|
1056
|
+
columns: [
|
|
1057
|
+
"one_col",
|
|
1058
|
+
"one_third",
|
|
1059
|
+
"two_third",
|
|
1060
|
+
"two_thirds",
|
|
1061
|
+
"one_half",
|
|
1062
|
+
"one_fourth",
|
|
1063
|
+
"three_fourth",
|
|
1064
|
+
"three_fourths"
|
|
1065
|
+
],
|
|
1066
|
+
bgParamName: "bg_image"
|
|
1067
|
+
}),
|
|
1068
|
+
layoutMaps: [
|
|
1069
|
+
extendedPrefixedLayoutMap([
|
|
1070
|
+
{ role: "section", tokens: ["blox_row"], bgParamName: "bg_image" },
|
|
1071
|
+
{ role: "row", tokens: ["blox_row_inner"], colsParamName: "columns" },
|
|
1072
|
+
{
|
|
1073
|
+
role: "column",
|
|
1074
|
+
tokens: ["blox_column_inner", "blox_column"],
|
|
1075
|
+
widthParamName: "width"
|
|
1076
|
+
}
|
|
1077
|
+
])
|
|
1078
|
+
],
|
|
1001
1079
|
textRules: [
|
|
1002
1080
|
{
|
|
1003
1081
|
shortcodePrefix: "special_sub_title",
|
|
@@ -1013,7 +1091,11 @@ var WORDPRESS_BUILDER_REGISTRY = [
|
|
|
1013
1091
|
],
|
|
1014
1092
|
wrapperRules: [
|
|
1015
1093
|
{ shortcodePrefix: "grid_content" },
|
|
1016
|
-
{ shortcodePrefix: "testimonial", urlParams: ["author_image"] }
|
|
1094
|
+
{ shortcodePrefix: "testimonial", urlParams: ["author_image"] },
|
|
1095
|
+
{ shortcodePrefix: "blox_text" }
|
|
1096
|
+
],
|
|
1097
|
+
urlRules: [
|
|
1098
|
+
{ shortcodePrefix: "blox_image", urlParams: ["image", "img", "src", "url"], tag: "img" }
|
|
1017
1099
|
],
|
|
1018
1100
|
placeholderRules: [
|
|
1019
1101
|
{
|
|
@@ -1022,21 +1104,7 @@ var WORDPRESS_BUILDER_REGISTRY = [
|
|
|
1022
1104
|
}
|
|
1023
1105
|
],
|
|
1024
1106
|
scaffoldingPrefixes: ["blox_", "animate_icon"],
|
|
1025
|
-
legacyScaffoldingTokens: [
|
|
1026
|
-
"section",
|
|
1027
|
-
"row",
|
|
1028
|
-
"one_col",
|
|
1029
|
-
"one_third",
|
|
1030
|
-
"one_fourth",
|
|
1031
|
-
"one_half",
|
|
1032
|
-
"two_third",
|
|
1033
|
-
"three_fourth",
|
|
1034
|
-
"text",
|
|
1035
|
-
"icon",
|
|
1036
|
-
"linebreak",
|
|
1037
|
-
"grids",
|
|
1038
|
-
"testimonials"
|
|
1039
|
-
]
|
|
1107
|
+
legacyScaffoldingTokens: ["text", "icon", "linebreak", "grids", "testimonials"]
|
|
1040
1108
|
}
|
|
1041
1109
|
];
|
|
1042
1110
|
|
|
@@ -1102,7 +1170,7 @@ function analyzeHtml(html) {
|
|
|
1102
1170
|
issues.push("script_tag_present");
|
|
1103
1171
|
}
|
|
1104
1172
|
try {
|
|
1105
|
-
const $ =
|
|
1173
|
+
const $ = cheerio2.load(html, { xml: false });
|
|
1106
1174
|
$("p").each((_, el) => {
|
|
1107
1175
|
const inner = $(el).html() ?? "";
|
|
1108
1176
|
if (inner.includes("<p")) {
|
|
@@ -1259,6 +1327,9 @@ async function runMigrationFromBundle(bundle, options) {
|
|
|
1259
1327
|
}
|
|
1260
1328
|
const existingTargetId = await sink.findExisting?.(key);
|
|
1261
1329
|
if (existingTargetId) {
|
|
1330
|
+
if (stage === "assets" && key.entityType === "asset") {
|
|
1331
|
+
uploadedAssets.set(key.sourceId, { targetId: existingTargetId });
|
|
1332
|
+
}
|
|
1262
1333
|
skipped += 1;
|
|
1263
1334
|
onEntityProcessed?.(key, "skipped");
|
|
1264
1335
|
return;
|
|
@@ -1611,7 +1682,6 @@ async function runDryRun(options) {
|
|
|
1611
1682
|
|
|
1612
1683
|
export {
|
|
1613
1684
|
MIGRATION_WRITE_STAGES,
|
|
1614
|
-
rewriteInlineImages,
|
|
1615
1685
|
sanitizeSlug,
|
|
1616
1686
|
linkToPath,
|
|
1617
1687
|
SQUARESPACE_JSON_FORMAT,
|
|
@@ -1641,4 +1711,4 @@ export {
|
|
|
1641
1711
|
staleUrlsFromEstimate,
|
|
1642
1712
|
runDryRun
|
|
1643
1713
|
};
|
|
1644
|
-
//# sourceMappingURL=chunk-
|
|
1714
|
+
//# sourceMappingURL=chunk-IPYHS5R2.js.map
|