@artinstack/migrator 0.1.9 → 0.1.12
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-B3XS20r_.d.ts → bundle-CysqqLij.d.ts} +1 -1
- package/dist/chunk-J7EUSPEA.js +667 -0
- package/dist/chunk-J7EUSPEA.js.map +1 -0
- package/dist/{chunk-3YJFSTYR.js → chunk-MUFGDYGI.js} +2 -1
- package/dist/chunk-MUFGDYGI.js.map +1 -0
- package/dist/{chunk-KTQGOM45.js → chunk-PFUXPS7A.js} +1 -1
- package/dist/chunk-PFUXPS7A.js.map +1 -0
- package/dist/{chunk-FB3MMCHY.js → chunk-Q44KGFIH.js} +97 -531
- package/dist/chunk-Q44KGFIH.js.map +1 -0
- package/dist/chunk-QFJXNEXG.js +355 -0
- package/dist/chunk-QFJXNEXG.js.map +1 -0
- package/dist/{chunk-PPT5RIZ4.js → chunk-VRRYN6NS.js} +40 -236
- package/dist/chunk-VRRYN6NS.js.map +1 -0
- package/dist/{chunk-S4SUJT2D.js → chunk-WCAHVNWW.js} +98 -3
- package/dist/chunk-WCAHVNWW.js.map +1 -0
- package/dist/cli/index.js +12 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +9 -6
- package/dist/normalizer/index.d.ts +10 -4
- package/dist/normalizer/index.js +2 -2
- package/dist/sinks/index.d.ts +13 -3
- package/dist/sinks/index.js +5 -3
- package/dist/transformers/index.d.ts +1 -1
- package/dist/transformers/index.js +3 -2
- package/dist/{types-Ce4r6zqt.d.ts → types-CLNmloya.d.ts} +15 -1
- package/package.json +1 -1
- package/dist/chunk-3YJFSTYR.js.map +0 -1
- package/dist/chunk-BONZ3U3I.js +0 -124
- package/dist/chunk-BONZ3U3I.js.map +0 -1
- package/dist/chunk-FB3MMCHY.js.map +0 -1
- package/dist/chunk-KTQGOM45.js.map +0 -1
- package/dist/chunk-PPT5RIZ4.js.map +0 -1
- package/dist/chunk-S4SUJT2D.js.map +0 -1
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeVideoEmbedUrl
|
|
3
|
+
} from "./chunk-J7EUSPEA.js";
|
|
1
4
|
import {
|
|
2
5
|
isMigrationMediaRef,
|
|
3
6
|
parseMigrationMediaRef
|
|
@@ -131,6 +134,42 @@ function isPreservedEmbedIframe(tagName, attributes) {
|
|
|
131
134
|
const src = attributes?.src ?? "";
|
|
132
135
|
return EMBED_IFRAME_SRC.test(src);
|
|
133
136
|
}
|
|
137
|
+
function isBlockLinkedImageAnchor($, $el) {
|
|
138
|
+
if (tagNameOf($el) !== "a") return false;
|
|
139
|
+
const href = $el.attr("href")?.trim();
|
|
140
|
+
if (!href || href === "#") return false;
|
|
141
|
+
let tagChildCount = 0;
|
|
142
|
+
let onlyImg = false;
|
|
143
|
+
$el.contents().each((_, node) => {
|
|
144
|
+
if (node.type === "text") {
|
|
145
|
+
if (String("data" in node ? node.data : "").trim()) {
|
|
146
|
+
tagChildCount = -1;
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (node.type !== "tag") return;
|
|
151
|
+
tagChildCount += 1;
|
|
152
|
+
onlyImg = tagNameOf($(node)) === "img";
|
|
153
|
+
});
|
|
154
|
+
return tagChildCount === 1 && onlyImg;
|
|
155
|
+
}
|
|
156
|
+
function walkLinkedImageAnchor($, $el, options) {
|
|
157
|
+
const href = $el.attr("href").trim();
|
|
158
|
+
const $img = $el.children().first();
|
|
159
|
+
const meta = pickElementMeta($img);
|
|
160
|
+
const attributes = { ...meta.attributes ?? {}, href };
|
|
161
|
+
return applyElementMeta(
|
|
162
|
+
{
|
|
163
|
+
type: resolveComponentType("img", meta.classes, options),
|
|
164
|
+
tagName: "img",
|
|
165
|
+
void: true
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
attributes,
|
|
169
|
+
classes: meta.classes
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
134
173
|
function layoutAttributesForComponent(attributes) {
|
|
135
174
|
if (!attributes) return void 0;
|
|
136
175
|
const { [LAYOUT_DATA_ATTR]: _layout, ...rest } = attributes;
|
|
@@ -252,6 +291,9 @@ function walkNode($, $el, options) {
|
|
|
252
291
|
meta
|
|
253
292
|
);
|
|
254
293
|
}
|
|
294
|
+
if (tagName === "a" && isBlockLinkedImageAnchor($, $el)) {
|
|
295
|
+
return walkLinkedImageAnchor($, $el, options);
|
|
296
|
+
}
|
|
255
297
|
if (VOID_TAGS.has(tagName)) {
|
|
256
298
|
return applyElementMeta(
|
|
257
299
|
{
|
|
@@ -359,6 +401,45 @@ function serializeContentHtml($) {
|
|
|
359
401
|
// src/transformers/html-to-tiptap/index.ts
|
|
360
402
|
import * as cheerio2 from "cheerio";
|
|
361
403
|
|
|
404
|
+
// src/transformers/html-to-tiptap/video-embed.ts
|
|
405
|
+
var VIDEO_WIDGET = "video";
|
|
406
|
+
var VIDEO_IFRAME_SRC = /youtube\.com\/embed|youtube-nocookie\.com\/embed|youtu\.be|player\.vimeo\.com\/video/i;
|
|
407
|
+
function isVideoWidgetElement($el) {
|
|
408
|
+
return $el.attr("data-wp-widget")?.toLowerCase() === VIDEO_WIDGET;
|
|
409
|
+
}
|
|
410
|
+
function buildVideoEmbedNode(input) {
|
|
411
|
+
return {
|
|
412
|
+
type: "embed",
|
|
413
|
+
attrs: {
|
|
414
|
+
src: input.embedUrl,
|
|
415
|
+
provider: input.provider,
|
|
416
|
+
dataWpWidget: VIDEO_WIDGET,
|
|
417
|
+
dataEmbedUrl: input.embedUrl,
|
|
418
|
+
dataVideoProvider: input.provider
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function videoEmbedNodeFromWidget($el) {
|
|
423
|
+
const embedUrl = $el.attr("data-embed-url")?.trim();
|
|
424
|
+
if (!embedUrl) return null;
|
|
425
|
+
const provider = $el.attr("data-video-provider")?.trim() || "external";
|
|
426
|
+
return buildVideoEmbedNode({ embedUrl, provider });
|
|
427
|
+
}
|
|
428
|
+
function videoEmbedNodeFromIframe($el) {
|
|
429
|
+
const src = $el.attr("src")?.trim();
|
|
430
|
+
if (!src || !VIDEO_IFRAME_SRC.test(src)) return null;
|
|
431
|
+
const normalized = normalizeVideoEmbedUrl(src);
|
|
432
|
+
return buildVideoEmbedNode({
|
|
433
|
+
embedUrl: normalized?.embedUrl ?? src,
|
|
434
|
+
provider: normalized?.provider ?? "external"
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
function isPreservedVideoIframe($el, tagName) {
|
|
438
|
+
if (tagName !== "iframe") return false;
|
|
439
|
+
const src = $el.attr("src")?.trim() ?? "";
|
|
440
|
+
return VIDEO_IFRAME_SRC.test(src);
|
|
441
|
+
}
|
|
442
|
+
|
|
362
443
|
// src/transformers/html-to-tiptap/walk.ts
|
|
363
444
|
var SKIP_TAGS2 = /* @__PURE__ */ new Set(["script", "style", "noscript", "template"]);
|
|
364
445
|
var HEADING_TAGS = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
@@ -434,7 +515,7 @@ function hasBlockChild($, $el) {
|
|
|
434
515
|
if ($child.get(0)?.type === "text") return;
|
|
435
516
|
const childTag = tagNameOf2($child);
|
|
436
517
|
if (!childTag) return;
|
|
437
|
-
if (HEADING_TAGS.has(childTag) || childTag === "p" || childTag === "ul" || childTag === "ol" || childTag === "blockquote" || childTag === "pre" || childTag === "hr" || childTag === "img" || childTag === "table" || isLayoutMarker($child, { unwrapLayoutMarkers: true }) || UNWRAP_TAGS.has(childTag) && hasBlockChild($, $child)) {
|
|
518
|
+
if (HEADING_TAGS.has(childTag) || childTag === "p" || childTag === "ul" || childTag === "ol" || childTag === "blockquote" || childTag === "pre" || childTag === "hr" || childTag === "img" || childTag === "iframe" || childTag === "table" || isLayoutMarker($child, { unwrapLayoutMarkers: true }) || UNWRAP_TAGS.has(childTag) && hasBlockChild($, $child)) {
|
|
438
519
|
hasBlock = true;
|
|
439
520
|
}
|
|
440
521
|
});
|
|
@@ -549,6 +630,12 @@ function parseMixedBlockContent($, $el, options) {
|
|
|
549
630
|
if (image) blocks.push(image);
|
|
550
631
|
return;
|
|
551
632
|
}
|
|
633
|
+
if (tagName === "iframe" && isPreservedVideoIframe($child, tagName)) {
|
|
634
|
+
flushInline();
|
|
635
|
+
const embed = videoEmbedNodeFromIframe($child);
|
|
636
|
+
if (embed) blocks.push(embed);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
552
639
|
if (INLINE_TAGS2.has(tagName)) {
|
|
553
640
|
inlineBuffer.push(...parseInlineContent($, $child));
|
|
554
641
|
return;
|
|
@@ -566,7 +653,7 @@ function walkListItem($, $el, options) {
|
|
|
566
653
|
}
|
|
567
654
|
const normalized = [];
|
|
568
655
|
for (const block of blocks) {
|
|
569
|
-
if (block.type === "paragraph" || block.type === "image" || block.type === "blockquote" || block.type === "bulletList" || block.type === "orderedList") {
|
|
656
|
+
if (block.type === "paragraph" || block.type === "image" || block.type === "embed" || block.type === "blockquote" || block.type === "bulletList" || block.type === "orderedList") {
|
|
570
657
|
normalized.push(block);
|
|
571
658
|
continue;
|
|
572
659
|
}
|
|
@@ -587,6 +674,14 @@ function walkBlockNode($, $el, options) {
|
|
|
587
674
|
if (isLayoutMarker($el, options)) {
|
|
588
675
|
return walkBlockNodes($, $el, options);
|
|
589
676
|
}
|
|
677
|
+
if (isVideoWidgetElement($el)) {
|
|
678
|
+
const embed = videoEmbedNodeFromWidget($el);
|
|
679
|
+
return embed ? [embed] : [];
|
|
680
|
+
}
|
|
681
|
+
if (isPreservedVideoIframe($el, tagName)) {
|
|
682
|
+
const embed = videoEmbedNodeFromIframe($el);
|
|
683
|
+
return embed ? [embed] : [];
|
|
684
|
+
}
|
|
590
685
|
if (UNWRAP_TAGS.has(tagName)) {
|
|
591
686
|
if (hasBlockChild($, $el)) {
|
|
592
687
|
return walkBlockNodes($, $el, options);
|
|
@@ -961,4 +1056,4 @@ export {
|
|
|
961
1056
|
validateTiptapDoc,
|
|
962
1057
|
expandMigrationMediaRefs
|
|
963
1058
|
};
|
|
964
|
-
//# sourceMappingURL=chunk-
|
|
1059
|
+
//# sourceMappingURL=chunk-WCAHVNWW.js.map
|
|
@@ -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/video-embed.ts","../src/transformers/html-to-tiptap/walk.ts","../src/transformers/validate-snapshot.ts","../src/transformers/validate-tiptap-doc.ts","../src/transformers/expand-migration-media-refs.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\";\nconst WP_WIDGET_ATTR = \"data-wp-widget\";\nconst DEFAULT_WP_WIDGET_TYPE = \"wp-widget\";\nconst EMBED_IFRAME_TYPE = \"embed\";\n\nconst EMBED_IFRAME_SRC =\n /google\\.com\\/maps\\/embed|youtube\\.com\\/embed|youtube-nocookie\\.com\\/embed|player\\.vimeo\\.com\\/video/i;\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 resolveWidgetComponentType(options: HtmlToGrapesOptions): string {\n return options.widgetComponentType ?? DEFAULT_WP_WIDGET_TYPE;\n}\n\nfunction isWpWidgetMarker(attributes: Record<string, string> | undefined): boolean {\n return Boolean(attributes?.[WP_WIDGET_ATTR]);\n}\n\nfunction isPreservedEmbedIframe(\n tagName: string | undefined,\n attributes: Record<string, string> | undefined,\n): boolean {\n if (tagName !== \"iframe\") return false;\n const src = attributes?.src ?? \"\";\n return EMBED_IFRAME_SRC.test(src);\n}\n\n/** Block-level `<a href=\"…\"><img …></a>` (e.g. affiliation logos) → void image, not inline HTML text. */\nfunction isBlockLinkedImageAnchor($: CheerioAPI, $el: CheerioSelection): boolean {\n if (tagNameOf($el) !== \"a\") return false;\n const href = $el.attr(\"href\")?.trim();\n if (!href || href === \"#\") return false;\n\n let tagChildCount = 0;\n let onlyImg = false;\n $el.contents().each((_, node) => {\n if (node.type === \"text\") {\n if (String(\"data\" in node ? node.data : \"\").trim()) {\n tagChildCount = -1;\n }\n return;\n }\n if (node.type !== \"tag\") return;\n tagChildCount += 1;\n onlyImg = tagNameOf($(node)) === \"img\";\n });\n\n return tagChildCount === 1 && onlyImg;\n}\n\nfunction walkLinkedImageAnchor(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToGrapesOptions,\n): GrapesComponent {\n const href = $el.attr(\"href\")!.trim();\n const $img = $el.children().first();\n const meta = pickElementMeta($img);\n const attributes = { ...(meta.attributes ?? {}), href };\n\n return applyElementMeta(\n {\n type: resolveComponentType(\"img\", meta.classes, options),\n tagName: \"img\",\n void: true,\n },\n {\n attributes,\n classes: meta.classes,\n },\n );\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 // OSS-13 — atomic widget blocks (do not merge into preceding text / inline walks).\n if (isWpWidgetMarker(meta.attributes)) {\n return applyElementMeta(\n {\n type: resolveWidgetComponentType(options),\n tagName,\n },\n meta,\n );\n }\n\n if (isPreservedEmbedIframe(tagName, meta.attributes)) {\n return applyElementMeta(\n {\n type: EMBED_IFRAME_TYPE,\n tagName,\n void: true,\n },\n meta,\n );\n }\n\n if (tagName === \"a\" && isBlockLinkedImageAnchor($, $el)) {\n return walkLinkedImageAnchor($, $el, options);\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 } from \"cheerio\";\nimport type { AnyNode } from \"domhandler\";\n\nimport { normalizeVideoEmbedUrl } from \"../../parsers/wordpress/builders/flatten.js\";\nimport type { TiptapNode } from \"./types.js\";\n\ntype CheerioSelection = Cheerio<AnyNode>;\n\nconst VIDEO_WIDGET = \"video\";\n\nconst VIDEO_IFRAME_SRC =\n /youtube\\.com\\/embed|youtube-nocookie\\.com\\/embed|youtu\\.be|player\\.vimeo\\.com\\/video/i;\n\nexport function isVideoWidgetElement($el: CheerioSelection): boolean {\n return $el.attr(\"data-wp-widget\")?.toLowerCase() === VIDEO_WIDGET;\n}\n\nfunction buildVideoEmbedNode(input: {\n embedUrl: string;\n provider: string;\n}): TiptapNode {\n return {\n type: \"embed\",\n attrs: {\n src: input.embedUrl,\n provider: input.provider,\n dataWpWidget: VIDEO_WIDGET,\n dataEmbedUrl: input.embedUrl,\n dataVideoProvider: input.provider,\n },\n };\n}\n\nexport function videoEmbedNodeFromWidget($el: CheerioSelection): TiptapNode | null {\n const embedUrl = $el.attr(\"data-embed-url\")?.trim();\n if (!embedUrl) return null;\n\n const provider = $el.attr(\"data-video-provider\")?.trim() || \"external\";\n return buildVideoEmbedNode({ embedUrl, provider });\n}\n\nexport function videoEmbedNodeFromIframe($el: CheerioSelection): TiptapNode | null {\n const src = $el.attr(\"src\")?.trim();\n if (!src || !VIDEO_IFRAME_SRC.test(src)) return null;\n\n const normalized = normalizeVideoEmbedUrl(src);\n return buildVideoEmbedNode({\n embedUrl: normalized?.embedUrl ?? src,\n provider: normalized?.provider ?? \"external\",\n });\n}\n\nexport function isPreservedVideoIframe($el: CheerioSelection, tagName: string | undefined): boolean {\n if (tagName !== \"iframe\") return false;\n const src = $el.attr(\"src\")?.trim() ?? \"\";\n return VIDEO_IFRAME_SRC.test(src);\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { AnyNode, Element } from \"domhandler\";\n\nimport type { HtmlToTiptapOptions, TiptapDoc, TiptapMark, TiptapNode } from \"./types.js\";\nimport {\n isPreservedVideoIframe,\n isVideoWidgetElement,\n videoEmbedNodeFromIframe,\n videoEmbedNodeFromWidget,\n} from \"./video-embed.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 === \"iframe\" ||\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 (tagName === \"iframe\" && isPreservedVideoIframe($child, tagName)) {\n flushInline();\n const embed = videoEmbedNodeFromIframe($child);\n if (embed) blocks.push(embed);\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 === \"embed\" ||\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 (isVideoWidgetElement($el)) {\n const embed = videoEmbedNodeFromWidget($el);\n return embed ? [embed] : [];\n }\n\n if (isPreservedVideoIframe($el, tagName)) {\n const embed = videoEmbedNodeFromIframe($el);\n return embed ? [embed] : [];\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","import * as cheerio from \"cheerio\";\n\nimport { isMigrationMediaRef, parseMigrationMediaRef } from \"../lib/media-urls.js\";\n\nexport interface ExpandMigrationMediaRefsResult {\n html: 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 tryExpandRef(\n value: string,\n resolvePublicUrl: (sourceId: string) => string | undefined,\n unresolved: Set<string>,\n): string | undefined {\n if (!isMigrationMediaRef(value)) return undefined;\n const sourceId = parseMigrationMediaRef(value);\n if (!sourceId) {\n unresolved.add(value);\n return undefined;\n }\n const publicUrl = resolvePublicUrl(sourceId);\n if (!publicUrl) {\n unresolved.add(value);\n return undefined;\n }\n return publicUrl;\n}\n\nfunction expandBackgroundUrlsInStyle(\n style: string,\n resolvePublicUrl: (sourceId: string) => string | undefined,\n unresolved: Set<string>,\n): string {\n return style.replace(BACKGROUND_IMAGE_URL_PATTERN, (full, quote: string, rawUrl: string) => {\n const expanded = tryExpandRef(rawUrl.trim(), resolvePublicUrl, unresolved);\n if (!expanded) return full;\n\n const urlCall = quote ? `url(${quote}${expanded}${quote})` : `url(${expanded})`;\n return full.replace(/url\\s*\\(\\s*(['\"]?)([^'\")]+)\\1\\s*\\)/i, urlCall);\n });\n}\n\nfunction expandSrcset(\n srcset: string,\n resolvePublicUrl: (sourceId: string) => string | undefined,\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 expanded = tryExpandRef(urlPart ?? \"\", resolvePublicUrl, unresolved);\n if (!expanded) return entry;\n return descriptor ? `${expanded} ${descriptor}` : expanded;\n })\n .join(\", \");\n}\n\n/**\n * Expand OSS-14 `artinstack-migration://asset/…` refs to host CDN URLs.\n * Lookup (`migration_entities` → `publicUrl`) is host-supplied via `resolvePublicUrl`.\n */\nexport function expandMigrationMediaRefs(\n html: string,\n resolvePublicUrl: (sourceId: string) => string | undefined,\n): ExpandMigrationMediaRefsResult {\n if (!html.trim()) {\n return { html, unresolved: [] };\n }\n\n const $ = cheerio.load(html, { xml: false });\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) {\n const expanded = tryExpandRef(src, resolvePublicUrl, unresolved);\n if (expanded) img.attr(\"src\", expanded);\n }\n\n const srcset = img.attr(\"srcset\")?.trim();\n if (srcset) {\n img.attr(\"srcset\", expandSrcset(srcset, resolvePublicUrl, 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) return;\n const expanded = tryExpandRef(bgImage, resolvePublicUrl, unresolved);\n if (expanded) node.attr(\"data-bg-image\", expanded);\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 = expandBackgroundUrlsInStyle(style, resolvePublicUrl, unresolved);\n if (rewritten !== style) node.attr(\"style\", rewritten);\n });\n\n return {\n html: $.root().html() ?? html,\n unresolved: [...unresolved],\n };\n}\n"],"mappings":"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","names":["components","component","cheerio","SKIP_TAGS","INLINE_TAGS","tagNameOf","hasOnlyInlineContent","z","zodIssuesToValidationIssues","cheerio"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getAdapter
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-Q44KGFIH.js";
|
|
5
5
|
import {
|
|
6
6
|
analyzeConflicts,
|
|
7
7
|
buildMigrationReport,
|
|
@@ -12,15 +12,17 @@ import {
|
|
|
12
12
|
estimateStorage,
|
|
13
13
|
hasBlockingConflicts,
|
|
14
14
|
hasWarnings,
|
|
15
|
+
resolveAdapterImportSummary,
|
|
15
16
|
runDryRun,
|
|
16
17
|
runMigration,
|
|
17
18
|
staleUrlsFromEstimate,
|
|
18
19
|
writeFilesystemExport
|
|
19
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-VRRYN6NS.js";
|
|
20
21
|
import {
|
|
21
22
|
collectEntities
|
|
22
|
-
} from "../chunk-
|
|
23
|
-
import "../chunk-
|
|
23
|
+
} from "../chunk-PFUXPS7A.js";
|
|
24
|
+
import "../chunk-J7EUSPEA.js";
|
|
25
|
+
import "../chunk-QFJXNEXG.js";
|
|
24
26
|
import "../chunk-XRCF73DA.js";
|
|
25
27
|
import {
|
|
26
28
|
createWpContentGatewayRewrite
|
|
@@ -220,6 +222,7 @@ async function main() {
|
|
|
220
222
|
entities: adapter.enumerateEntities({ input })
|
|
221
223
|
});
|
|
222
224
|
const bundle2 = sink.bundle;
|
|
225
|
+
const wxrImportSummary2 = await resolveAdapterImportSummary(adapter, input);
|
|
223
226
|
const estimate2 = await estimateStorage({
|
|
224
227
|
assets: bundle2.media,
|
|
225
228
|
offline
|
|
@@ -227,7 +230,8 @@ async function main() {
|
|
|
227
230
|
const redirectMap2 = buildRedirectMap(bundle2);
|
|
228
231
|
const conflicts2 = analyzeConflicts(bundle2, {
|
|
229
232
|
staleAssetUrls: staleUrlsFromEstimate(estimate2),
|
|
230
|
-
redirectLoops: detectRedirectLoops(redirectMap2)
|
|
233
|
+
redirectLoops: detectRedirectLoops(redirectMap2),
|
|
234
|
+
wxrImportSummary: wxrImportSummary2
|
|
231
235
|
});
|
|
232
236
|
const report2 = buildMigrationReport({
|
|
233
237
|
platform,
|
|
@@ -248,13 +252,15 @@ async function main() {
|
|
|
248
252
|
process.exit(exitCode);
|
|
249
253
|
}
|
|
250
254
|
const bundle = await collectEntities(adapter.enumerateEntities({ input }));
|
|
255
|
+
const wxrImportSummary = await resolveAdapterImportSummary(adapter, input);
|
|
251
256
|
const estimate = await estimateStorage({
|
|
252
257
|
assets: bundle.media,
|
|
253
258
|
offline
|
|
254
259
|
});
|
|
255
260
|
const redirectMap = buildRedirectMap(bundle);
|
|
256
261
|
const conflicts = analyzeConflicts(bundle, {
|
|
257
|
-
staleAssetUrls: staleUrlsFromEstimate(estimate)
|
|
262
|
+
staleAssetUrls: staleUrlsFromEstimate(estimate),
|
|
263
|
+
wxrImportSummary
|
|
258
264
|
});
|
|
259
265
|
const report = buildMigrationReport({
|
|
260
266
|
platform,
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { writeFile } from \"node:fs/promises\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { getAdapter } from \"../parsers/index.js\";\nimport type { MigrationPlatform } from \"../normalizer/types.js\";\nimport {\n analyzeConflicts,\n buildMigrationReport,\n buildRedirectMap,\n bundleToCombinedJson,\n createFilesystemMigrationSink,\n detectRedirectLoops,\n hasBlockingConflicts,\n hasWarnings,\n runDryRun,\n runMigration,\n writeFilesystemExport,\n} from \"../sinks/index.js\";\nimport { collectEntities } from \"../normalizer/bundle.js\";\nimport { createWpContentGatewayRewrite } from \"../lib/media-urls.js\";\nimport { estimateStorage, staleUrlsFromEstimate } from \"../sinks/storage-estimate.js\";\n\nconst PLATFORMS: MigrationPlatform[] = [\"wordpress\", \"smugmug\", \"squarespace\", \"wix\"];\nconst SINKS = [\"filesystem\"] as const;\n\nfunction printUsage(): void {\n console.log(`artinstack-migrate — platform content migration CLI\n\nUsage:\n artinstack-migrate <platform> <export-file> [options]\n artinstack-migrate validate <platform> <export-file>\n\nPlatforms: ${PLATFORMS.join(\", \")}\n\nOptions:\n --out <dir> Write grouped JSON files to directory\n --sink <name> Run through MigrationSink (supported: ${SINKS.join(\", \")})\n --format json Write combined JSON to stdout\n --dry-run Parse and analyze without writing content files\n --report <dir> With --dry-run, write conflicts.json + migration-report.json\n --offline Skip network HEAD requests (4 MB fallback per asset)\n --urls <file> Wix W2: newline URL list or sitemap.xml for static page snapshots\n --rewrite-gateway <url> WordPress: API gateway base (requires --rewrite-public)\n --rewrite-public <url> WordPress: public origin for /wp-content/ asset paths\n\nExamples:\n artinstack-migrate wordpress export.xml --dry-run --report ./preview/\n artinstack-migrate wordpress export.xml --rewrite-gateway https://gateway.example/prod --rewrite-public https://www.example.com --dry-run --report ./preview/\n artinstack-migrate wix feed.xml --urls ./sitemap-urls.txt --dry-run\n artinstack-migrate wordpress export.xml --out ./output\n artinstack-migrate wordpress export.xml --sink filesystem --out ./output\n pnpm cli wordpress fixtures/wordpress/long-form-journal.xml --dry-run\n`);\n}\n\nfunction printDryRunStatus(exitCode: 0 | 1 | 2, reportDir?: string): void {\n const dest = reportDir ? ` Reports written to ${reportDir}.` : \"\";\n if (exitCode === 0) {\n console.error(`Dry run complete.${dest}`);\n } else if (exitCode === 2) {\n console.error(`Dry run complete with warnings (exit 2).${dest}`);\n } else {\n console.error(`Dry run found blocking conflicts (exit 1).${dest}`);\n }\n}\n\nfunction parseArgs(argv: string[]): {\n command: string | undefined;\n platform: MigrationPlatform | undefined;\n inputPath: string | undefined;\n urlsPath: string | undefined;\n outDir: string | undefined;\n reportDir: string | undefined;\n sinkName: string | undefined;\n dryRun: boolean;\n formatJson: boolean;\n offline: boolean;\n rewriteGateway: string | undefined;\n rewritePublic: string | undefined;\n} {\n const args = [...argv];\n let command: string | undefined;\n let platform: MigrationPlatform | undefined;\n let inputPath: string | undefined;\n let urlsPath: string | undefined;\n let outDir: string | undefined;\n let reportDir: string | undefined;\n let sinkName: string | undefined;\n let dryRun = false;\n let formatJson = false;\n let offline = false;\n let rewriteGateway: string | undefined;\n let rewritePublic: string | undefined;\n\n const first = args[0];\n if (first === \"validate\") {\n command = \"validate\";\n platform = args[1] as MigrationPlatform;\n inputPath = args[2];\n for (let i = 3; i < args.length; i++) {\n if (args[i] === \"--urls\" && args[i + 1]) urlsPath = args[++i];\n }\n } else if (first && PLATFORMS.includes(first as MigrationPlatform)) {\n command = \"migrate\";\n platform = first as MigrationPlatform;\n inputPath = args[1];\n for (let i = 2; i < args.length; i++) {\n const flag = args[i];\n if (flag === \"--dry-run\") dryRun = true;\n else if (flag === \"--format\" && args[i + 1] === \"json\") formatJson = true;\n else if (flag === \"--offline\") offline = true;\n else if (flag === \"--out\" && args[i + 1]) {\n outDir = args[++i];\n } else if (flag === \"--report\" && args[i + 1]) {\n reportDir = args[++i];\n } else if (flag === \"--sink\" && args[i + 1]) {\n sinkName = args[++i];\n } else if (flag === \"--urls\" && args[i + 1]) {\n urlsPath = args[++i];\n } else if (flag === \"--rewrite-gateway\" && args[i + 1]) {\n rewriteGateway = args[++i];\n } else if (flag === \"--rewrite-public\" && args[i + 1]) {\n rewritePublic = args[++i];\n }\n }\n } else {\n command = first;\n }\n\n return { command, platform, inputPath, urlsPath, outDir, reportDir, sinkName, dryRun, formatJson, offline, rewriteGateway, rewritePublic };\n}\n\nfunction buildAdapterInput(\n platform: MigrationPlatform,\n inputPath: string,\n urlsPath: string | undefined,\n rewriteGateway: string | undefined,\n rewritePublic: string | undefined,\n): unknown {\n if (rewriteGateway || rewritePublic) {\n if (platform !== \"wordpress\") {\n throw new Error(\"--rewrite-gateway and --rewrite-public are WordPress-only options\");\n }\n if (!rewriteGateway || !rewritePublic) {\n throw new Error(\"Both --rewrite-gateway and --rewrite-public are required together\");\n }\n }\n\n if (platform === \"wordpress\") {\n return {\n path: inputPath,\n ...(rewriteGateway && rewritePublic\n ? { originUrlRewrite: createWpContentGatewayRewrite(rewriteGateway, rewritePublic) }\n : {}),\n };\n }\n\n return {\n path: inputPath,\n ...(urlsPath ? { urlsFile: urlsPath } : {}),\n };\n}\n\nfunction migrationExitCode(hasBlockers: boolean, hasWarn: boolean): 0 | 1 | 2 {\n if (hasBlockers) return 1;\n if (hasWarn) return 2;\n return 0;\n}\n\nasync function main(): Promise<void> {\n const { command, platform, inputPath, urlsPath, outDir, reportDir, sinkName, dryRun, formatJson, offline, rewriteGateway, rewritePublic } =\n parseArgs(process.argv.slice(2));\n\n if (!command || command === \"--help\" || command === \"-h\") {\n printUsage();\n process.exit(0);\n }\n\n if (command === \"validate\") {\n if (!platform || !PLATFORMS.includes(platform) || !inputPath) {\n console.error(\"Usage: artinstack-migrate validate <platform> <export-file>\");\n process.exit(1);\n }\n const adapter = getAdapter(platform);\n const result = await adapter.validateInput({\n path: inputPath,\n ...(urlsPath ? { urlsFile: urlsPath } : {}),\n });\n console.log(JSON.stringify(result, null, 2));\n process.exit(result.ok ? 0 : 1);\n }\n\n if (command === \"migrate\") {\n if (!platform || !inputPath) {\n printUsage();\n process.exit(1);\n }\n\n if (sinkName && !SINKS.includes(sinkName as (typeof SINKS)[number])) {\n console.error(`Unknown sink: ${sinkName}. Supported: ${SINKS.join(\", \")}`);\n process.exit(1);\n }\n\n const adapter = getAdapter(platform);\n let input: unknown;\n try {\n input = buildAdapterInput(platform, inputPath, urlsPath, rewriteGateway, rewritePublic);\n } catch (error) {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n }\n\n if (dryRun) {\n const result = await runDryRun({\n adapter,\n input,\n platform,\n offlineStorageEstimate: offline,\n });\n\n if (reportDir) {\n await mkdir(reportDir, { recursive: true });\n await writeFile(\n join(reportDir, \"conflicts.json\"),\n `${JSON.stringify(result.conflicts, null, 2)}\\n`,\n );\n await writeFile(\n join(reportDir, \"migration-report.json\"),\n `${JSON.stringify(result.report, null, 2)}\\n`,\n );\n } else {\n console.log(JSON.stringify(result.report, null, 2));\n }\n\n printDryRunStatus(result.exitCode, reportDir);\n process.exit(result.exitCode);\n }\n\n const startedAt = new Date();\n\n if (sinkName === \"filesystem\") {\n if (!outDir) {\n console.error(\"Filesystem sink requires --out <dir>\");\n process.exit(1);\n }\n\n const sink = createFilesystemMigrationSink();\n const runResult = await runMigration({\n sink,\n platform,\n entities: adapter.enumerateEntities({ input }),\n });\n\n const bundle = sink.bundle;\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline,\n });\n const redirectMap = buildRedirectMap(bundle);\n const conflicts = analyzeConflicts(bundle, {\n staleAssetUrls: staleUrlsFromEstimate(estimate),\n redirectLoops: detectRedirectLoops(redirectMap),\n });\n const report = buildMigrationReport({\n platform,\n mode: \"sink\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n warnings:\n runResult.failed > 0\n ? [`${runResult.failed} entity write(s) failed during sink migration`]\n : [],\n });\n\n await sink.flush({ outDir, bundle, conflicts, report });\n console.error(`Wrote sink export to ${outDir}`);\n\n const exitCode = migrationExitCode(\n hasBlockingConflicts(conflicts) || runResult.failed > 0,\n hasWarnings(conflicts),\n );\n process.exit(exitCode);\n }\n\n const bundle = await collectEntities(adapter.enumerateEntities({ input }));\n\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline,\n });\n const redirectMap = buildRedirectMap(bundle);\n const conflicts = analyzeConflicts(bundle, {\n staleAssetUrls: staleUrlsFromEstimate(estimate),\n });\n\n const report = buildMigrationReport({\n platform,\n mode: \"export\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n });\n\n if (formatJson) {\n console.log(JSON.stringify({ ...bundleToCombinedJson(bundle), conflicts, report }, null, 2));\n process.exit(0);\n }\n\n if (!outDir) {\n console.error(\"Specify --out <dir>, --format json, --dry-run, or --sink filesystem --out <dir>\");\n process.exit(1);\n }\n\n await writeFilesystemExport({\n outDir,\n bundle,\n conflicts,\n report,\n });\n\n console.error(`Wrote export to ${outDir}`);\n process.exit(0);\n }\n\n console.error(`Unknown command: ${command}`);\n printUsage();\n process.exit(1);\n}\n\nmain().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n"],"mappings":"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","names":["bundle","estimate","redirectMap","conflicts","report"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { writeFile } from \"node:fs/promises\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { getAdapter } from \"../parsers/index.js\";\nimport type { MigrationPlatform } from \"../normalizer/types.js\";\nimport {\n analyzeConflicts,\n buildMigrationReport,\n buildRedirectMap,\n bundleToCombinedJson,\n createFilesystemMigrationSink,\n detectRedirectLoops,\n hasBlockingConflicts,\n hasWarnings,\n runDryRun,\n resolveAdapterImportSummary,\n runMigration,\n writeFilesystemExport,\n} from \"../sinks/index.js\";\nimport { collectEntities } from \"../normalizer/bundle.js\";\nimport { createWpContentGatewayRewrite } from \"../lib/media-urls.js\";\nimport { estimateStorage, staleUrlsFromEstimate } from \"../sinks/storage-estimate.js\";\n\nconst PLATFORMS: MigrationPlatform[] = [\"wordpress\", \"smugmug\", \"squarespace\", \"wix\"];\nconst SINKS = [\"filesystem\"] as const;\n\nfunction printUsage(): void {\n console.log(`artinstack-migrate — platform content migration CLI\n\nUsage:\n artinstack-migrate <platform> <export-file> [options]\n artinstack-migrate validate <platform> <export-file>\n\nPlatforms: ${PLATFORMS.join(\", \")}\n\nOptions:\n --out <dir> Write grouped JSON files to directory\n --sink <name> Run through MigrationSink (supported: ${SINKS.join(\", \")})\n --format json Write combined JSON to stdout\n --dry-run Parse and analyze without writing content files\n --report <dir> With --dry-run, write conflicts.json + migration-report.json\n --offline Skip network HEAD requests (4 MB fallback per asset)\n --urls <file> Wix W2: newline URL list or sitemap.xml for static page snapshots\n --rewrite-gateway <url> WordPress: API gateway base (requires --rewrite-public)\n --rewrite-public <url> WordPress: public origin for /wp-content/ asset paths\n\nExamples:\n artinstack-migrate wordpress export.xml --dry-run --report ./preview/\n artinstack-migrate wordpress export.xml --rewrite-gateway https://gateway.example/prod --rewrite-public https://www.example.com --dry-run --report ./preview/\n artinstack-migrate wix feed.xml --urls ./sitemap-urls.txt --dry-run\n artinstack-migrate wordpress export.xml --out ./output\n artinstack-migrate wordpress export.xml --sink filesystem --out ./output\n pnpm cli wordpress fixtures/wordpress/long-form-journal.xml --dry-run\n`);\n}\n\nfunction printDryRunStatus(exitCode: 0 | 1 | 2, reportDir?: string): void {\n const dest = reportDir ? ` Reports written to ${reportDir}.` : \"\";\n if (exitCode === 0) {\n console.error(`Dry run complete.${dest}`);\n } else if (exitCode === 2) {\n console.error(`Dry run complete with warnings (exit 2).${dest}`);\n } else {\n console.error(`Dry run found blocking conflicts (exit 1).${dest}`);\n }\n}\n\nfunction parseArgs(argv: string[]): {\n command: string | undefined;\n platform: MigrationPlatform | undefined;\n inputPath: string | undefined;\n urlsPath: string | undefined;\n outDir: string | undefined;\n reportDir: string | undefined;\n sinkName: string | undefined;\n dryRun: boolean;\n formatJson: boolean;\n offline: boolean;\n rewriteGateway: string | undefined;\n rewritePublic: string | undefined;\n} {\n const args = [...argv];\n let command: string | undefined;\n let platform: MigrationPlatform | undefined;\n let inputPath: string | undefined;\n let urlsPath: string | undefined;\n let outDir: string | undefined;\n let reportDir: string | undefined;\n let sinkName: string | undefined;\n let dryRun = false;\n let formatJson = false;\n let offline = false;\n let rewriteGateway: string | undefined;\n let rewritePublic: string | undefined;\n\n const first = args[0];\n if (first === \"validate\") {\n command = \"validate\";\n platform = args[1] as MigrationPlatform;\n inputPath = args[2];\n for (let i = 3; i < args.length; i++) {\n if (args[i] === \"--urls\" && args[i + 1]) urlsPath = args[++i];\n }\n } else if (first && PLATFORMS.includes(first as MigrationPlatform)) {\n command = \"migrate\";\n platform = first as MigrationPlatform;\n inputPath = args[1];\n for (let i = 2; i < args.length; i++) {\n const flag = args[i];\n if (flag === \"--dry-run\") dryRun = true;\n else if (flag === \"--format\" && args[i + 1] === \"json\") formatJson = true;\n else if (flag === \"--offline\") offline = true;\n else if (flag === \"--out\" && args[i + 1]) {\n outDir = args[++i];\n } else if (flag === \"--report\" && args[i + 1]) {\n reportDir = args[++i];\n } else if (flag === \"--sink\" && args[i + 1]) {\n sinkName = args[++i];\n } else if (flag === \"--urls\" && args[i + 1]) {\n urlsPath = args[++i];\n } else if (flag === \"--rewrite-gateway\" && args[i + 1]) {\n rewriteGateway = args[++i];\n } else if (flag === \"--rewrite-public\" && args[i + 1]) {\n rewritePublic = args[++i];\n }\n }\n } else {\n command = first;\n }\n\n return { command, platform, inputPath, urlsPath, outDir, reportDir, sinkName, dryRun, formatJson, offline, rewriteGateway, rewritePublic };\n}\n\nfunction buildAdapterInput(\n platform: MigrationPlatform,\n inputPath: string,\n urlsPath: string | undefined,\n rewriteGateway: string | undefined,\n rewritePublic: string | undefined,\n): unknown {\n if (rewriteGateway || rewritePublic) {\n if (platform !== \"wordpress\") {\n throw new Error(\"--rewrite-gateway and --rewrite-public are WordPress-only options\");\n }\n if (!rewriteGateway || !rewritePublic) {\n throw new Error(\"Both --rewrite-gateway and --rewrite-public are required together\");\n }\n }\n\n if (platform === \"wordpress\") {\n return {\n path: inputPath,\n ...(rewriteGateway && rewritePublic\n ? { originUrlRewrite: createWpContentGatewayRewrite(rewriteGateway, rewritePublic) }\n : {}),\n };\n }\n\n return {\n path: inputPath,\n ...(urlsPath ? { urlsFile: urlsPath } : {}),\n };\n}\n\nfunction migrationExitCode(hasBlockers: boolean, hasWarn: boolean): 0 | 1 | 2 {\n if (hasBlockers) return 1;\n if (hasWarn) return 2;\n return 0;\n}\n\nasync function main(): Promise<void> {\n const { command, platform, inputPath, urlsPath, outDir, reportDir, sinkName, dryRun, formatJson, offline, rewriteGateway, rewritePublic } =\n parseArgs(process.argv.slice(2));\n\n if (!command || command === \"--help\" || command === \"-h\") {\n printUsage();\n process.exit(0);\n }\n\n if (command === \"validate\") {\n if (!platform || !PLATFORMS.includes(platform) || !inputPath) {\n console.error(\"Usage: artinstack-migrate validate <platform> <export-file>\");\n process.exit(1);\n }\n const adapter = getAdapter(platform);\n const result = await adapter.validateInput({\n path: inputPath,\n ...(urlsPath ? { urlsFile: urlsPath } : {}),\n });\n console.log(JSON.stringify(result, null, 2));\n process.exit(result.ok ? 0 : 1);\n }\n\n if (command === \"migrate\") {\n if (!platform || !inputPath) {\n printUsage();\n process.exit(1);\n }\n\n if (sinkName && !SINKS.includes(sinkName as (typeof SINKS)[number])) {\n console.error(`Unknown sink: ${sinkName}. Supported: ${SINKS.join(\", \")}`);\n process.exit(1);\n }\n\n const adapter = getAdapter(platform);\n let input: unknown;\n try {\n input = buildAdapterInput(platform, inputPath, urlsPath, rewriteGateway, rewritePublic);\n } catch (error) {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n }\n\n if (dryRun) {\n const result = await runDryRun({\n adapter,\n input,\n platform,\n offlineStorageEstimate: offline,\n });\n\n if (reportDir) {\n await mkdir(reportDir, { recursive: true });\n await writeFile(\n join(reportDir, \"conflicts.json\"),\n `${JSON.stringify(result.conflicts, null, 2)}\\n`,\n );\n await writeFile(\n join(reportDir, \"migration-report.json\"),\n `${JSON.stringify(result.report, null, 2)}\\n`,\n );\n } else {\n console.log(JSON.stringify(result.report, null, 2));\n }\n\n printDryRunStatus(result.exitCode, reportDir);\n process.exit(result.exitCode);\n }\n\n const startedAt = new Date();\n\n if (sinkName === \"filesystem\") {\n if (!outDir) {\n console.error(\"Filesystem sink requires --out <dir>\");\n process.exit(1);\n }\n\n const sink = createFilesystemMigrationSink();\n const runResult = await runMigration({\n sink,\n platform,\n entities: adapter.enumerateEntities({ input }),\n });\n\n const bundle = sink.bundle;\n const wxrImportSummary = await resolveAdapterImportSummary(adapter, input);\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline,\n });\n const redirectMap = buildRedirectMap(bundle);\n const conflicts = analyzeConflicts(bundle, {\n staleAssetUrls: staleUrlsFromEstimate(estimate),\n redirectLoops: detectRedirectLoops(redirectMap),\n wxrImportSummary,\n });\n const report = buildMigrationReport({\n platform,\n mode: \"sink\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n warnings:\n runResult.failed > 0\n ? [`${runResult.failed} entity write(s) failed during sink migration`]\n : [],\n });\n\n await sink.flush({ outDir, bundle, conflicts, report });\n console.error(`Wrote sink export to ${outDir}`);\n\n const exitCode = migrationExitCode(\n hasBlockingConflicts(conflicts) || runResult.failed > 0,\n hasWarnings(conflicts),\n );\n process.exit(exitCode);\n }\n\n const bundle = await collectEntities(adapter.enumerateEntities({ input }));\n const wxrImportSummary = await resolveAdapterImportSummary(adapter, input);\n\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline,\n });\n const redirectMap = buildRedirectMap(bundle);\n const conflicts = analyzeConflicts(bundle, {\n staleAssetUrls: staleUrlsFromEstimate(estimate),\n wxrImportSummary,\n });\n\n const report = buildMigrationReport({\n platform,\n mode: \"export\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n });\n\n if (formatJson) {\n console.log(JSON.stringify({ ...bundleToCombinedJson(bundle), conflicts, report }, null, 2));\n process.exit(0);\n }\n\n if (!outDir) {\n console.error(\"Specify --out <dir>, --format json, --dry-run, or --sink filesystem --out <dir>\");\n process.exit(1);\n }\n\n await writeFilesystemExport({\n outDir,\n bundle,\n conflicts,\n report,\n });\n\n console.error(`Wrote export to ${outDir}`);\n process.exit(0);\n }\n\n console.error(`Unknown command: ${command}`);\n printUsage();\n process.exit(1);\n}\n\nmain().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n"],"mappings":"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","names":["bundle","wxrImportSummary","estimate","redirectMap","conflicts","report"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as MigrationAdapter, g as MigrationPlatform } from './types-
|
|
2
|
-
export { A as AdapterContext, E as EntityKey, h as EntityType, i as MigrationCursor, b as NormalizedAsset, j as NormalizedAssetExif, d as NormalizedCategory, f as NormalizedEntity, a as NormalizedPage, c as NormalizedPortfolio, N as NormalizedPost, e as NormalizedTag, P as PortfolioMediaLink, k as PublishStatus, S as SourceMetadata, V as ValidationIssue, l as ValidationResult, m as entityKey } from './types-
|
|
1
|
+
import { M as MigrationAdapter, g as MigrationPlatform } from './types-CLNmloya.js';
|
|
2
|
+
export { A as AdapterContext, E as EntityKey, h as EntityType, i as MigrationCursor, b as NormalizedAsset, j as NormalizedAssetExif, d as NormalizedCategory, f as NormalizedEntity, a as NormalizedPage, c as NormalizedPortfolio, N as NormalizedPost, e as NormalizedTag, P as PortfolioMediaLink, k as PublishStatus, S as SourceMetadata, V as ValidationIssue, l as ValidationResult, W as WxrImportSummary, m as entityKey } from './types-CLNmloya.js';
|
|
3
3
|
export { EntityState, MigrationCheckpoint, TrackedEntity, buildPortfolioMediaLinks, isTerminalState, normalizedAssetExifSchema, normalizedAssetSchema, normalizedCategorySchema, normalizedEntitySchema, normalizedPageSchema, normalizedPortfolioSchema, normalizedPostSchema, normalizedTagSchema, shouldProcessEntity, sourceMetadataSchema, validateNormalizedAsset, validateNormalizedCategory, validateNormalizedEntity, validateNormalizedPage, validateNormalizedPortfolio, validateNormalizedPost, validateNormalizedTag } from './normalizer/index.js';
|
|
4
|
-
export { B as BundleCounts, E as EntityBundle, b as bundleCounts, c as collectEntities, e as emptyBundle } from './bundle-
|
|
5
|
-
export { AssetDiscoverySummary, ConflictReport, DryRunOptions, DryRunResult, FALLBACK_ASSET_BYTES, FilesystemMigrationSink, MIGRATION_WRITE_STAGES, MigrationRedirect, MigrationReport, MigrationRunMode, MigrationRunOptions, MigrationRunResult, MigrationSink, MigrationWriteStage, StorageEstimate, UploadAssetInput, UploadAssetResult, WriteFilesystemOptions, analyzeConflicts, buildMigrationReport, buildRedirectMap, bundleToCombinedJson, createFilesystemMigrationSink, detectRedirectLoops, emptyConflictReport, estimateStorage, hasBlockingConflicts, hasWarnings, portfolioMediaMatchesBundle, runDryRun, runMigration, runMigrationFromBundle, staleUrlsFromEstimate, summarizeAssetDiscovery, writeFilesystemExport } from './sinks/index.js';
|
|
4
|
+
export { B as BundleCounts, E as EntityBundle, b as bundleCounts, c as collectEntities, e as emptyBundle } from './bundle-CysqqLij.js';
|
|
5
|
+
export { AssetDiscoverySummary, ConflictReport, DryRunOptions, DryRunResult, FALLBACK_ASSET_BYTES, FilesystemMigrationSink, MIGRATION_WRITE_STAGES, MigrationRedirect, MigrationReport, MigrationRunMode, MigrationRunOptions, MigrationRunResult, MigrationSink, MigrationWriteStage, StorageEstimate, UploadAssetInput, UploadAssetResult, WriteFilesystemOptions, analyzeConflicts, buildMigrationReport, buildRedirectMap, bundleToCombinedJson, createFilesystemMigrationSink, detectRedirectLoops, emptyConflictReport, estimateStorage, hasBlockingConflicts, hasWarnings, portfolioMediaMatchesBundle, resolveAdapterImportSummary, runDryRun, runMigration, runMigrationFromBundle, staleUrlsFromEstimate, summarizeAssetDiscovery, writeFilesystemExport } from './sinks/index.js';
|
|
6
6
|
export { R as RewriteInlineImageRef, a as RewriteInlineImagesOptions, b as RewriteInlineImagesResult, S as StampMigrationMediaRefsOptions, U as UploadedAssetRef, r as rewriteInlineImages, s as stampMigrationMediaRefs } from './rewrite-inline-images-BsgSquzV.js';
|
|
7
7
|
export { ExpandMigrationMediaRefsResult, GrapesComponent, GrapesProjectSnapshot, GrapesStyleRule, HtmlToGrapesOptions, HtmlToTiptapOptions, LayoutKind, LayoutTypeMap, TiptapDoc, TiptapMark, TiptapNode, ValidateGrapesProjectSnapshotOptions, ValidateTiptapDocOptions, cssToStyles, expandMigrationMediaRefs, grapesComponentSchema, grapesProjectSnapshotSchema, grapesStyleRuleSchema, htmlToGrapes, htmlToTiptap, tiptapDocSchema, tiptapMarkSchema, tiptapNodeSchema, validateGrapesProjectSnapshot, validateTiptapDoc } from './transformers/index.js';
|
|
8
8
|
export { C as CanonicalInlineAssetUrl, a as ContentAssetDiscovery, M as MIGRATION_MEDIA_REF_SCHEME, O as OriginUrlRewriteConfig, b as OriginUrlRewriteRule, c as buildContentMediaUrlIndex, d as buildMigrationMediaUrlIndex, e as canonicalizeInlineAssetUrl, f as createMigrationMediaRefReplaceWith, g as createWpContentGatewayRewrite, h as discoverContentAssetUrls, i as discoverContentAssets, j as discoverFeaturedAssetCandidateUrls, k as discoverRawImgSrcs, l as extractInlineImageSrcs, m as formatMigrationMediaRef, n as isLikelyImageUrl, o as isMigrationMediaRef, p as normalizeAssetUrl, q as parseMigrationMediaRef, r as resolveFeaturedContentAssetUrl, s as resolveMigrationMediaSourceId, t as rewriteOriginUrlsInText } from './media-urls-u49RCyPn.js';
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
squarespaceAdapter,
|
|
14
14
|
wixAdapter,
|
|
15
15
|
wordpressAdapter
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-Q44KGFIH.js";
|
|
17
17
|
import {
|
|
18
18
|
normalizedAssetExifSchema,
|
|
19
19
|
normalizedAssetSchema,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
validateNormalizedPortfolio,
|
|
32
32
|
validateNormalizedPost,
|
|
33
33
|
validateNormalizedTag
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-MUFGDYGI.js";
|
|
35
35
|
import {
|
|
36
36
|
FALLBACK_ASSET_BYTES,
|
|
37
37
|
FilesystemMigrationSink,
|
|
@@ -51,13 +51,14 @@ import {
|
|
|
51
51
|
hasWarnings,
|
|
52
52
|
mapJsonPrettyWire,
|
|
53
53
|
portfolioMediaMatchesBundle,
|
|
54
|
+
resolveAdapterImportSummary,
|
|
54
55
|
runDryRun,
|
|
55
56
|
runMigration,
|
|
56
57
|
runMigrationFromBundle,
|
|
57
58
|
staleUrlsFromEstimate,
|
|
58
59
|
summarizeAssetDiscovery,
|
|
59
60
|
writeFilesystemExport
|
|
60
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-VRRYN6NS.js";
|
|
61
62
|
import {
|
|
62
63
|
buildPortfolioMediaLinks,
|
|
63
64
|
bundleCounts,
|
|
@@ -66,7 +67,7 @@ import {
|
|
|
66
67
|
entityKey,
|
|
67
68
|
isTerminalState,
|
|
68
69
|
shouldProcessEntity
|
|
69
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-PFUXPS7A.js";
|
|
70
71
|
import {
|
|
71
72
|
cssToStyles,
|
|
72
73
|
expandMigrationMediaRefs,
|
|
@@ -80,11 +81,12 @@ import {
|
|
|
80
81
|
tiptapNodeSchema,
|
|
81
82
|
validateGrapesProjectSnapshot,
|
|
82
83
|
validateTiptapDoc
|
|
83
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-WCAHVNWW.js";
|
|
85
|
+
import "./chunk-J7EUSPEA.js";
|
|
84
86
|
import {
|
|
85
87
|
rewriteInlineImages,
|
|
86
88
|
stampMigrationMediaRefs
|
|
87
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-QFJXNEXG.js";
|
|
88
90
|
import "./chunk-EJTWYEAX.js";
|
|
89
91
|
import {
|
|
90
92
|
linkToPath,
|
|
@@ -176,6 +178,7 @@ export {
|
|
|
176
178
|
parseMigrationMediaRef,
|
|
177
179
|
portfolioMediaMatchesBundle,
|
|
178
180
|
readSmugMugCredentialsFromEnv,
|
|
181
|
+
resolveAdapterImportSummary,
|
|
179
182
|
resolveFeaturedContentAssetUrl,
|
|
180
183
|
resolveMigrationMediaSourceId,
|
|
181
184
|
rewriteInlineImages,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as MigrationCursor, E as EntityKey, P as PortfolioMediaLink, l as ValidationResult } from '../types-
|
|
2
|
-
export { A as AdapterContext, h as EntityType, M as MigrationAdapter, g as MigrationPlatform, b as NormalizedAsset, j as NormalizedAssetExif, d as NormalizedCategory, f as NormalizedEntity, a as NormalizedPage, c as NormalizedPortfolio, N as NormalizedPost, e as NormalizedTag, k as PublishStatus, S as SourceMetadata, V as ValidationIssue, m as entityKey } from '../types-
|
|
3
|
-
import { E as EntityBundle } from '../bundle-
|
|
4
|
-
export { B as BundleCounts, b as bundleCounts, c as collectEntities, e as emptyBundle } from '../bundle-
|
|
1
|
+
import { i as MigrationCursor, E as EntityKey, P as PortfolioMediaLink, l as ValidationResult } from '../types-CLNmloya.js';
|
|
2
|
+
export { A as AdapterContext, h as EntityType, M as MigrationAdapter, g as MigrationPlatform, b as NormalizedAsset, j as NormalizedAssetExif, d as NormalizedCategory, f as NormalizedEntity, a as NormalizedPage, c as NormalizedPortfolio, N as NormalizedPost, e as NormalizedTag, k as PublishStatus, S as SourceMetadata, V as ValidationIssue, W as WxrImportSummary, m as entityKey } from '../types-CLNmloya.js';
|
|
3
|
+
import { E as EntityBundle } from '../bundle-CysqqLij.js';
|
|
4
|
+
export { B as BundleCounts, b as bundleCounts, c as collectEntities, e as emptyBundle } from '../bundle-CysqqLij.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
/** Portable entity state for resume / idempotency (not Directus field names). */
|
|
@@ -148,6 +148,7 @@ declare const normalizedPageSchema: z.ZodObject<{
|
|
|
148
148
|
contentHtml: z.ZodString;
|
|
149
149
|
contentCss: z.ZodOptional<z.ZodString>;
|
|
150
150
|
isHomePage: z.ZodOptional<z.ZodBoolean>;
|
|
151
|
+
isPortfolioPage: z.ZodOptional<z.ZodBoolean>;
|
|
151
152
|
status: z.ZodEnum<["draft", "published", "archived"]>;
|
|
152
153
|
seoTitle: z.ZodOptional<z.ZodString>;
|
|
153
154
|
seoDescription: z.ZodOptional<z.ZodString>;
|
|
@@ -169,6 +170,7 @@ declare const normalizedPageSchema: z.ZodObject<{
|
|
|
169
170
|
seoDescription?: string | undefined;
|
|
170
171
|
contentCss?: string | undefined;
|
|
171
172
|
isHomePage?: boolean | undefined;
|
|
173
|
+
isPortfolioPage?: boolean | undefined;
|
|
172
174
|
}, {
|
|
173
175
|
type: "page";
|
|
174
176
|
status: "draft" | "published" | "archived";
|
|
@@ -187,6 +189,7 @@ declare const normalizedPageSchema: z.ZodObject<{
|
|
|
187
189
|
seoDescription?: string | undefined;
|
|
188
190
|
contentCss?: string | undefined;
|
|
189
191
|
isHomePage?: boolean | undefined;
|
|
192
|
+
isPortfolioPage?: boolean | undefined;
|
|
190
193
|
}>;
|
|
191
194
|
declare const normalizedAssetExifSchema: z.ZodObject<{
|
|
192
195
|
iso: z.ZodOptional<z.ZodNumber>;
|
|
@@ -557,6 +560,7 @@ declare const normalizedEntitySchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
|
|
|
557
560
|
contentHtml: z.ZodString;
|
|
558
561
|
contentCss: z.ZodOptional<z.ZodString>;
|
|
559
562
|
isHomePage: z.ZodOptional<z.ZodBoolean>;
|
|
563
|
+
isPortfolioPage: z.ZodOptional<z.ZodBoolean>;
|
|
560
564
|
status: z.ZodEnum<["draft", "published", "archived"]>;
|
|
561
565
|
seoTitle: z.ZodOptional<z.ZodString>;
|
|
562
566
|
seoDescription: z.ZodOptional<z.ZodString>;
|
|
@@ -578,6 +582,7 @@ declare const normalizedEntitySchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
|
|
|
578
582
|
seoDescription?: string | undefined;
|
|
579
583
|
contentCss?: string | undefined;
|
|
580
584
|
isHomePage?: boolean | undefined;
|
|
585
|
+
isPortfolioPage?: boolean | undefined;
|
|
581
586
|
}, {
|
|
582
587
|
type: "page";
|
|
583
588
|
status: "draft" | "published" | "archived";
|
|
@@ -596,6 +601,7 @@ declare const normalizedEntitySchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
|
|
|
596
601
|
seoDescription?: string | undefined;
|
|
597
602
|
contentCss?: string | undefined;
|
|
598
603
|
isHomePage?: boolean | undefined;
|
|
604
|
+
isPortfolioPage?: boolean | undefined;
|
|
599
605
|
}>, z.ZodObject<{
|
|
600
606
|
type: z.ZodLiteral<"asset">;
|
|
601
607
|
source: z.ZodObject<{
|
package/dist/normalizer/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
validateNormalizedPortfolio,
|
|
16
16
|
validateNormalizedPost,
|
|
17
17
|
validateNormalizedTag
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-MUFGDYGI.js";
|
|
19
19
|
import {
|
|
20
20
|
buildPortfolioMediaLinks,
|
|
21
21
|
bundleCounts,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
entityKey,
|
|
25
25
|
isTerminalState,
|
|
26
26
|
shouldProcessEntity
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-PFUXPS7A.js";
|
|
28
28
|
export {
|
|
29
29
|
buildPortfolioMediaLinks,
|
|
30
30
|
bundleCounts,
|