@artinstack/migrator 0.1.12 → 0.1.13

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.
Files changed (32) hide show
  1. package/README.md +2 -1
  2. package/dist/{bundle-CysqqLij.d.ts → bundle-BgoXkWMy.d.ts} +1 -1
  3. package/dist/{chunk-MUFGDYGI.js → chunk-373TTCG7.js} +11 -1
  4. package/dist/chunk-373TTCG7.js.map +1 -0
  5. package/dist/{chunk-J7EUSPEA.js → chunk-4XZK55RW.js} +172 -2
  6. package/dist/chunk-4XZK55RW.js.map +1 -0
  7. package/dist/{chunk-Q44KGFIH.js → chunk-53VXTXGM.js} +74 -5
  8. package/dist/chunk-53VXTXGM.js.map +1 -0
  9. package/dist/{chunk-VRRYN6NS.js → chunk-5TRCJONX.js} +3 -3
  10. package/dist/{chunk-QFJXNEXG.js → chunk-HUSXCKPI.js} +4 -2
  11. package/dist/{chunk-QFJXNEXG.js.map → chunk-HUSXCKPI.js.map} +1 -1
  12. package/dist/{chunk-PFUXPS7A.js → chunk-PD5AZX3B.js} +1 -1
  13. package/dist/chunk-PD5AZX3B.js.map +1 -0
  14. package/dist/{chunk-WCAHVNWW.js → chunk-VQ5HKNYP.js} +13 -3
  15. package/dist/chunk-VQ5HKNYP.js.map +1 -0
  16. package/dist/cli/index.js +5 -5
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +7 -7
  19. package/dist/normalizer/index.d.ts +100 -4
  20. package/dist/normalizer/index.js +2 -2
  21. package/dist/sinks/index.d.ts +2 -2
  22. package/dist/sinks/index.js +3 -3
  23. package/dist/transformers/index.d.ts +1 -1
  24. package/dist/transformers/index.js +3 -3
  25. package/dist/{types-CLNmloya.d.ts → types-Bicgdp4Z.d.ts} +13 -1
  26. package/package.json +1 -1
  27. package/dist/chunk-J7EUSPEA.js.map +0 -1
  28. package/dist/chunk-MUFGDYGI.js.map +0 -1
  29. package/dist/chunk-PFUXPS7A.js.map +0 -1
  30. package/dist/chunk-Q44KGFIH.js.map +0 -1
  31. package/dist/chunk-WCAHVNWW.js.map +0 -1
  32. /package/dist/{chunk-VRRYN6NS.js.map → chunk-5TRCJONX.js.map} +0 -0
package/README.md CHANGED
@@ -158,9 +158,10 @@ pnpm dev # watch build
158
158
  | WordPress builder flattening + origin URL rewrite (pre-DTO) | Yes | Optional same config on adapter input |
159
159
  | Stamp `artinstack-migration://asset/…` refs in content HTML | Yes | No |
160
160
  | Expand refs → CDN URLs at persist | Exported helper | Call site + DB lookup |
161
+ | Page `layoutHints` (e.g. theme hero slider alias) | Yes — on `NormalizedPage` when meta references chrome outside body | Rebuild slider / hero at import |
161
162
  | CLI + filesystem JSON export | Yes | No |
162
163
  | `MigrationSink` interface | Yes | Implementation |
163
- | Dynamic shortcodes (`[portfolio]`, `[recent_posts]`), forms, sanitize | No | Yes |
164
+ | Map `data-wp-widget` stubs platform blocks; populate slider heroes from hints | No | Yes |
164
165
  | Jobs, worker, credentials, UI | No | Yes |
165
166
 
166
167
  ## License
@@ -1,4 +1,4 @@
1
- import { N as NormalizedPost, a as NormalizedPage, b as NormalizedAsset, c as NormalizedPortfolio, d as NormalizedCategory, e as NormalizedTag, f as NormalizedEntity } from './types-CLNmloya.js';
1
+ import { N as NormalizedPost, a as NormalizedPage, b as NormalizedAsset, c as NormalizedPortfolio, d as NormalizedCategory, e as NormalizedTag, f as NormalizedEntity } from './types-Bicgdp4Z.js';
2
2
 
3
3
  interface EntityBundle {
4
4
  posts: NormalizedPost[];
@@ -26,6 +26,15 @@ var normalizedPostSchema = z.object({
26
26
  seoTitle: z.string().optional(),
27
27
  seoDescription: z.string().optional()
28
28
  });
29
+ var pageHeroSliderHintSchema = z.object({
30
+ plugin: z.enum(["revslider", "masterslider"]),
31
+ alias: z.string().min(1),
32
+ slidertitle: z.string().optional(),
33
+ source: z.enum(["meta-shortcode", "meta-slider-field", "tatsu-json"]).optional()
34
+ });
35
+ var pageLayoutHintsSchema = z.object({
36
+ heroSlider: pageHeroSliderHintSchema.optional()
37
+ });
29
38
  var normalizedPageSchema = z.object({
30
39
  type: z.literal("page"),
31
40
  source: sourceMetadataSchema,
@@ -36,6 +45,7 @@ var normalizedPageSchema = z.object({
36
45
  contentCss: z.string().optional(),
37
46
  isHomePage: z.boolean().optional(),
38
47
  isPortfolioPage: z.boolean().optional(),
48
+ layoutHints: pageLayoutHintsSchema.optional(),
39
49
  status: publishStatusSchema,
40
50
  seoTitle: z.string().optional(),
41
51
  seoDescription: z.string().optional()
@@ -145,4 +155,4 @@ export {
145
155
  validateNormalizedTag,
146
156
  validateNormalizedEntity
147
157
  };
148
- //# sourceMappingURL=chunk-MUFGDYGI.js.map
158
+ //# sourceMappingURL=chunk-373TTCG7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/normalizer/validate.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport type { ValidationIssue, ValidationResult } from \"./types.js\";\n\nconst migrationPlatformSchema = z.enum([\"wordpress\", \"smugmug\", \"squarespace\", \"wix\"]);\nconst publishStatusSchema = z.enum([\"draft\", \"published\", \"archived\"]);\n\nexport const sourceMetadataSchema = z.object({\n platform: migrationPlatformSchema,\n id: z.string().min(1),\n url: z.string().optional(),\n path: z.string().optional(),\n exportedAt: z.string().optional(),\n});\n\nexport const normalizedPostSchema = z.object({\n type: z.literal(\"post\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n title: z.string().min(1),\n slug: z.string().min(1),\n excerpt: z.string().optional(),\n contentHtml: z.string(),\n publishedAt: z.string().optional(),\n status: publishStatusSchema,\n categorySlugs: z.array(z.string().min(1)).optional(),\n tagSlugs: z.array(z.string().min(1)).optional(),\n sourceFeaturedMediaId: z.string().optional(),\n featuredAssetSourceId: z.string().optional(),\n seoTitle: z.string().optional(),\n seoDescription: z.string().optional(),\n});\n\nconst pageHeroSliderHintSchema = z.object({\n plugin: z.enum([\"revslider\", \"masterslider\"]),\n alias: z.string().min(1),\n slidertitle: z.string().optional(),\n source: z.enum([\"meta-shortcode\", \"meta-slider-field\", \"tatsu-json\"]).optional(),\n});\n\nconst pageLayoutHintsSchema = z.object({\n heroSlider: pageHeroSliderHintSchema.optional(),\n});\n\nexport const normalizedPageSchema = z.object({\n type: z.literal(\"page\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n title: z.string().min(1),\n slug: z.string().min(1),\n contentHtml: z.string(),\n contentCss: z.string().optional(),\n isHomePage: z.boolean().optional(),\n isPortfolioPage: z.boolean().optional(),\n layoutHints: pageLayoutHintsSchema.optional(),\n status: publishStatusSchema,\n seoTitle: z.string().optional(),\n seoDescription: z.string().optional(),\n});\n\nexport const normalizedAssetExifSchema = z.object({\n iso: z.number().optional(),\n aperture: z.number().optional(),\n shutter: z.string().optional(),\n focalLength: z.number().optional(),\n});\n\nexport const normalizedAssetSchema = z.object({\n type: z.literal(\"asset\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n sourceUrl: z.string().min(1),\n filename: z.string().min(1),\n mimeType: z.string().optional(),\n caption: z.string().optional(),\n altText: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n exif: normalizedAssetExifSchema.optional(),\n portfolioSourceId: z.string().optional(),\n sort: z.number().optional(),\n});\n\nexport const normalizedPortfolioSchema = z.object({\n type: z.literal(\"portfolio\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n title: z.string().min(1),\n slug: z.string().min(1),\n description: z.string().optional(),\n parentSourceId: z.string().optional(),\n});\n\nexport const normalizedCategorySchema = z.object({\n type: z.literal(\"category\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n name: z.string().min(1),\n slug: z.string().min(1),\n});\n\nexport const normalizedTagSchema = z.object({\n type: z.literal(\"tag\"),\n source: sourceMetadataSchema,\n sourceId: z.string().min(1),\n name: z.string().min(1),\n slug: z.string().min(1),\n});\n\nexport const normalizedEntitySchema = z.discriminatedUnion(\"type\", [\n normalizedPostSchema,\n normalizedPageSchema,\n normalizedAssetSchema,\n normalizedPortfolioSchema,\n normalizedCategorySchema,\n normalizedTagSchema,\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 parseToValidationResult(schema: z.ZodTypeAny, value: unknown): ValidationResult {\n const result = schema.safeParse(value);\n if (result.success) {\n return { ok: true, issues: [] };\n }\n return { ok: false, issues: zodIssuesToValidationIssues(result.error.issues) };\n}\n\n/** Opt-in structural check for a normalized post DTO (no cross-entity FK validation). */\nexport function validateNormalizedPost(post: unknown): ValidationResult {\n return parseToValidationResult(normalizedPostSchema, post);\n}\n\n/** Opt-in structural check for a normalized page DTO (no cross-entity FK validation). */\nexport function validateNormalizedPage(page: unknown): ValidationResult {\n return parseToValidationResult(normalizedPageSchema, page);\n}\n\n/** Opt-in structural check for a normalized asset DTO. */\nexport function validateNormalizedAsset(asset: unknown): ValidationResult {\n return parseToValidationResult(normalizedAssetSchema, asset);\n}\n\n/** Opt-in structural check for a normalized portfolio DTO. */\nexport function validateNormalizedPortfolio(portfolio: unknown): ValidationResult {\n return parseToValidationResult(normalizedPortfolioSchema, portfolio);\n}\n\n/** Opt-in structural check for a normalized category DTO. */\nexport function validateNormalizedCategory(category: unknown): ValidationResult {\n return parseToValidationResult(normalizedCategorySchema, category);\n}\n\n/** Opt-in structural check for a normalized tag DTO. */\nexport function validateNormalizedTag(tag: unknown): ValidationResult {\n return parseToValidationResult(normalizedTagSchema, tag);\n}\n\n/** Opt-in structural check for any normalized entity discriminated by `type`. */\nexport function validateNormalizedEntity(entity: unknown): ValidationResult {\n return parseToValidationResult(normalizedEntitySchema, entity);\n}\n"],"mappings":"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","names":[]}
@@ -2,7 +2,7 @@ import {
2
2
  WORDPRESS_BUILDER_REGISTRY,
3
3
  WORDPRESS_WIDGET_REGISTRY,
4
4
  WP_WIDGET_PLACEHOLDER
5
- } from "./chunk-QFJXNEXG.js";
5
+ } from "./chunk-HUSXCKPI.js";
6
6
  import {
7
7
  normalizeAssetUrl
8
8
  } from "./chunk-S4GMDRGX.js";
@@ -295,6 +295,43 @@ function extractBareOrQuotedParam(params, name) {
295
295
  const match = pattern.exec(params);
296
296
  return match?.[1]?.trim() || void 0;
297
297
  }
298
+ function parseSliderShortcodeMarkup(markup) {
299
+ const trimmed = markup.trim();
300
+ if (!trimmed) return void 0;
301
+ const revMatch = trimmed.match(/\[rev_slider\b([^\]]*)\]/i);
302
+ if (revMatch) {
303
+ const params = revMatch[1] ?? "";
304
+ const alias = extractBareOrQuotedParam(params, "alias");
305
+ if (alias) {
306
+ return {
307
+ plugin: "revslider",
308
+ alias,
309
+ slidertitle: extractBareOrQuotedParam(params, "slidertitle")
310
+ };
311
+ }
312
+ }
313
+ const masterMatch = trimmed.match(/\[masterslider\b([^\]]*)\]/i);
314
+ if (masterMatch) {
315
+ const params = masterMatch[1] ?? "";
316
+ const alias = extractBareOrQuotedParam(params, "alias");
317
+ if (alias) return { plugin: "masterslider", alias };
318
+ }
319
+ return void 0;
320
+ }
321
+ function parseSliderMetaValue(value) {
322
+ const trimmed = value.trim();
323
+ if (!trimmed || trimmed.toLowerCase() === "none") return void 0;
324
+ const lower = trimmed.toLowerCase();
325
+ if (lower.startsWith("revslider_")) {
326
+ const alias = trimmed.slice("revslider_".length).trim();
327
+ if (alias) return { plugin: "revslider", alias };
328
+ }
329
+ if (lower.startsWith("masterslider_")) {
330
+ const alias = trimmed.slice("masterslider_".length).trim();
331
+ if (alias) return { plugin: "masterslider", alias };
332
+ }
333
+ return void 0;
334
+ }
298
335
  function emitWidgetStub(widget, attrs, tag = "div") {
299
336
  const parts = [`data-wp-widget="${escapeLayoutAttr(widget)}"`];
300
337
  for (const [key, value] of Object.entries(attrs)) {
@@ -513,6 +550,135 @@ function inferBlogListingLayout(params) {
513
550
  }
514
551
  return "grid";
515
552
  }
553
+ function decodeBasicHtmlEntities(text) {
554
+ return text.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
555
+ }
556
+ function stripHtmlTags(html) {
557
+ return html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
558
+ }
559
+ function extractTestimonialQuoteFromInner(inner) {
560
+ const trimmed = inner.trim();
561
+ if (!trimmed) return void 0;
562
+ const paragraphMatch = trimmed.match(/<p[^>]*>([\s\S]*?)<\/p>/i);
563
+ if (paragraphMatch?.[1]) {
564
+ const quote = decodeBasicHtmlEntities(stripHtmlTags(paragraphMatch[1])).trim();
565
+ return quote || void 0;
566
+ }
567
+ const blockquoteMatch = trimmed.match(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/i);
568
+ if (blockquoteMatch?.[1]) {
569
+ const quote = decodeBasicHtmlEntities(stripHtmlTags(blockquoteMatch[1])).trim();
570
+ return quote || void 0;
571
+ }
572
+ const plain = decodeBasicHtmlEntities(stripHtmlTags(trimmed)).trim();
573
+ return plain || void 0;
574
+ }
575
+ function parseTestimonialItemAttrs(params, inner) {
576
+ const author = extractBareOrQuotedParam(params, "author") ?? extractBareOrQuotedParam(params, "name");
577
+ const role = extractBareOrQuotedParam(params, "author_role") ?? extractBareOrQuotedParam(params, "role") ?? extractBareOrQuotedParam(params, "title");
578
+ const image = extractBareOrQuotedParam(params, "author_image") ?? extractBareOrQuotedParam(params, "image") ?? extractBareOrQuotedParam(params, "avatar");
579
+ const quote = extractBareOrQuotedParam(params, "quote") ?? extractBareOrQuotedParam(params, "content") ?? extractTestimonialQuoteFromInner(inner);
580
+ const rating = extractBareOrQuotedParam(params, "rating") ?? extractBareOrQuotedParam(params, "stars");
581
+ if (!author && !quote) return null;
582
+ return {
583
+ "data-wp-testimonial-author": author,
584
+ "data-wp-testimonial-role": role,
585
+ "data-wp-testimonial-image": image,
586
+ "data-wp-testimonial-quote": quote,
587
+ ...rating ? { "data-wp-testimonial-rating": rating } : {}
588
+ };
589
+ }
590
+ function emitTestimonialItemStub(attrs) {
591
+ const parts = [];
592
+ for (const [key, value] of Object.entries(attrs)) {
593
+ if (value) parts.push(`${key}="${escapeLayoutAttr(value)}"`);
594
+ }
595
+ return `<div ${parts.join(" ")}>${WP_WIDGET_PLACEHOLDER}</div>`;
596
+ }
597
+ function emitTestimonialsWidgetStub(sectionAttrs, items) {
598
+ const sectionParts = ['data-wp-widget="testimonials"'];
599
+ for (const [key, value] of Object.entries(sectionAttrs)) {
600
+ if (value) sectionParts.push(`${key}="${escapeLayoutAttr(value)}"`);
601
+ }
602
+ const children = items.map((item) => emitTestimonialItemStub(item)).join("");
603
+ return `<section ${sectionParts.join(" ")}>${children}</section>`;
604
+ }
605
+ function inferTestimonialColumns(wrapperParams, itemCount) {
606
+ const explicit = normalizeShortcodeCount(extractBareOrQuotedParam(wrapperParams, "columns")) ?? normalizeShortcodeCount(extractBareOrQuotedParam(wrapperParams, "col"));
607
+ if (explicit) return explicit;
608
+ if (itemCount <= 1) return "1";
609
+ if (itemCount === 2) return "2";
610
+ if (itemCount >= 4) return "4";
611
+ return "3";
612
+ }
613
+ function collectTestimonialItemsFromInner(inner, itemTag) {
614
+ const escaped = escapeRegExp(itemTag);
615
+ const pattern = new RegExp(
616
+ `\\[${escaped}\\b([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escaped}\\b[^\\]]*\\]`,
617
+ "gi"
618
+ );
619
+ const items = [];
620
+ inner.replace(pattern, (_, params, itemInner) => {
621
+ const item = parseTestimonialItemAttrs(params, itemInner);
622
+ if (item) items.push(item);
623
+ return "";
624
+ });
625
+ return items;
626
+ }
627
+ function flattenTestimonialsShortcodes(content, widgetRegistry) {
628
+ const itemTag = widgetRegistry.testimonialItemTag;
629
+ let html = content;
630
+ for (const wrapperTag of widgetRegistry.testimonialsWrapperTags) {
631
+ const escaped = escapeRegExp(wrapperTag);
632
+ const pattern = new RegExp(
633
+ `\\[${escaped}\\b([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escaped}\\b[^\\]]*\\]`,
634
+ "gi"
635
+ );
636
+ html = html.replace(pattern, (fullMatch, wrapperParams, inner) => {
637
+ const items = collectTestimonialItemsFromInner(inner, itemTag);
638
+ if (items.length === 0) return fullMatch;
639
+ return emitTestimonialsWidgetStub(
640
+ {
641
+ "data-wp-testimonial-columns": inferTestimonialColumns(wrapperParams, items.length),
642
+ "data-wp-testimonial-show-stars": items.some((item) => item["data-wp-testimonial-rating"]) ? "true" : "false"
643
+ },
644
+ items
645
+ );
646
+ });
647
+ }
648
+ const itemPattern = new RegExp(
649
+ `\\[${escapeRegExp(itemTag)}\\b([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escapeRegExp(itemTag)}\\b[^\\]]*\\]`,
650
+ "gi"
651
+ );
652
+ return html.replace(itemPattern, (fullMatch, params, inner) => {
653
+ const item = parseTestimonialItemAttrs(params, inner);
654
+ if (!item) return fullMatch;
655
+ return emitTestimonialsWidgetStub(
656
+ {
657
+ "data-wp-testimonial-columns": "1",
658
+ "data-wp-testimonial-show-stars": item["data-wp-testimonial-rating"] ? "true" : "false"
659
+ },
660
+ [item]
661
+ );
662
+ });
663
+ }
664
+ function flattenSliderShortcodes(content, widgetRegistry) {
665
+ let html = content;
666
+ for (const tag of widgetRegistry.sliderShortcodeTags) {
667
+ const escaped = escapeRegExp(tag);
668
+ const plugin = tag.toLowerCase() === "masterslider" ? "masterslider" : "revslider";
669
+ const pattern = new RegExp(`\\[${escaped}\\b([^\\]]*)\\](?:\\s*\\[\\/${escaped}\\b[^\\]]*\\])?`, "gi");
670
+ html = html.replace(pattern, (_, params) => {
671
+ const alias = extractBareOrQuotedParam(params, "alias");
672
+ const slidertitle = extractBareOrQuotedParam(params, "slidertitle");
673
+ return emitWidgetStub("slider", {
674
+ "data-wp-slider-plugin": plugin,
675
+ ...alias ? { "data-wp-slider-alias": alias } : {},
676
+ ...slidertitle ? { "data-wp-slider-title": slidertitle } : {}
677
+ });
678
+ });
679
+ }
680
+ return html;
681
+ }
516
682
  function flattenBlogListingShortcodes(content, widgetRegistry) {
517
683
  let html = content;
518
684
  for (const tag of widgetRegistry.blogShortcodeTags) {
@@ -611,7 +777,9 @@ function flattenWordPressWidgets(content, widgetRegistry = WORDPRESS_WIDGET_REGI
611
777
  html = flattenGalleryShortcodes(html, widgetRegistry);
612
778
  html = flattenIdBasedGalleryShortcodes(html, widgetRegistry);
613
779
  html = flattenPortfolioShortcodes(html, widgetRegistry);
780
+ html = flattenSliderShortcodes(html, widgetRegistry);
614
781
  html = flattenBlogListingShortcodes(html, widgetRegistry);
782
+ html = flattenTestimonialsShortcodes(html, widgetRegistry);
615
783
  html = flattenMapShortcodes(html, widgetRegistry);
616
784
  html = flattenContactFormShortcodes(html, widgetRegistry);
617
785
  html = flattenVideoShortcodes(html, widgetRegistry);
@@ -661,7 +829,9 @@ function flattenWordPressBuilders(content, options = {}) {
661
829
  }
662
830
 
663
831
  export {
832
+ parseSliderShortcodeMarkup,
833
+ parseSliderMetaValue,
664
834
  normalizeVideoEmbedUrl,
665
835
  flattenWordPressBuilders
666
836
  };
667
- //# sourceMappingURL=chunk-J7EUSPEA.js.map
837
+ //# sourceMappingURL=chunk-4XZK55RW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parsers/wordpress/builders/flatten.ts"],"sourcesContent":["import { normalizeAssetUrl } from \"../../../lib/media-urls.js\";\nimport type {\n BuilderIconImageRule,\n BuilderPlaceholderRule,\n BuilderTextRule,\n BuilderThemeConfig,\n BuilderUrlRule,\n BuilderWrapperRule,\n FractionalLayoutMap,\n ExtendedPrefixedLayoutMap,\n PrefixedLayoutMap,\n StructuralLayoutMap,\n TextHtmlTag,\n BuilderHtmlTag,\n} from \"./registry.js\";\nimport {\n WORDPRESS_BUILDER_REGISTRY,\n WORDPRESS_WIDGET_REGISTRY,\n WP_WIDGET_PLACEHOLDER,\n type WordPressWidgetRegistry,\n} from \"./registry.js\";\n\nexport interface FlattenWordPressBuildersOptions {\n registry?: BuilderThemeConfig[];\n widgetRegistry?: WordPressWidgetRegistry;\n}\n\nexport interface FlattenWordPressBuildersResult {\n html: string;\n detectedThemes: string[];\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/** Read a quoted shortcode attribute value (supports multiline). */\nexport function extractQuotedParam(params: string, name: string): string | undefined {\n const pattern = new RegExp(`\\\\b${escapeRegExp(name)}\\\\s*=\\\\s*`, \"i\");\n const match = pattern.exec(params);\n if (!match) return undefined;\n\n let index = match.index + match[0].length;\n while (index < params.length && /\\s/.test(params[index]!)) index += 1;\n\n if (params.slice(index, index + 6) === \"&quot;\") {\n index += 6;\n let value = \"\";\n while (index < params.length) {\n if (params.slice(index, index + 6) === \"&quot;\") break;\n value += params[index]!;\n index += 1;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n }\n\n const quote = params[index];\n if (quote !== '\"' && quote !== \"'\") return undefined;\n index += 1;\n\n let value = \"\";\n while (index < params.length) {\n const char = params[index]!;\n if (char === \"\\\\\" && index + 1 < params.length) {\n value += params[index + 1];\n index += 2;\n continue;\n }\n if (char === quote) break;\n value += char;\n index += 1;\n }\n\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction escapeLayoutAttr(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\");\n}\n\n/** Parse `width=\"1/2\"` / `columns=\"1/3+1/3+1/3\"` style strings → percentage or column count. */\nexport function parseFractionWidth(fraction: string | undefined): string | undefined {\n if (!fraction?.trim()) return undefined;\n const trimmed = fraction.trim();\n const match = trimmed.match(/^(\\d+)\\s*\\/\\s*(\\d+)$/);\n if (!match) return undefined;\n const numerator = Number(match[1]);\n const denominator = Number(match[2]);\n if (!Number.isFinite(numerator) || !Number.isFinite(denominator) || denominator <= 0) {\n return undefined;\n }\n const percent = (numerator / denominator) * 100;\n const rounded = Math.round(percent * 100) / 100;\n return `${rounded % 1 === 0 ? rounded.toFixed(0) : rounded}%`;\n}\n\n/** Parse row `layout=\"1/2+1/2\"` style strings → column count. */\nexport function parseRowLayoutCols(layout: string | undefined): number | undefined {\n if (!layout?.trim()) return undefined;\n const parts = layout.split(\"+\").map((part) => part.trim()).filter(Boolean);\n return parts.length > 1 ? parts.length : undefined;\n}\n\nfunction openSectionDiv(params: string, bgParamName?: string): string {\n const attrs = ['data-layout=\"section\"'];\n const bgImage = extractQuotedParam(params, bgParamName ?? \"bg_image\");\n if (bgImage?.startsWith(\"http\")) {\n attrs.push(`data-bg-image=\"${escapeLayoutAttr(bgImage)}\"`);\n }\n return `<div ${attrs.join(\" \")}>`;\n}\n\nfunction openRowDiv(params: string, colsParamName?: string): string {\n const attrs = ['data-layout=\"row\"'];\n const cols = parseRowLayoutCols(extractQuotedParam(params, colsParamName ?? \"layout\"));\n if (cols) attrs.push(`data-cols=\"${cols}\"`);\n return `<div ${attrs.join(\" \")}>`;\n}\n\nfunction openColumnDiv(params: string, widthParamName?: string): string {\n const attrs = ['data-layout=\"column\"'];\n const width = parseFractionWidth(extractQuotedParam(params, widthParamName ?? \"width\"));\n if (width) attrs.push(`data-col-width=\"${width}\"`);\n return `<div ${attrs.join(\" \")}>`;\n}\n\nfunction applyPrefixedLayoutMap(content: string, map: PrefixedLayoutMap): string {\n let html = content;\n html = html.replace(map.sectionRegex, (_, params: string) => openSectionDiv(params, map.bgParamName));\n html = html.replace(map.sectionCloseRegex, \"</div>\");\n html = html.replace(map.rowRegex, (_, params: string) => openRowDiv(params, map.colsParamName));\n html = html.replace(map.rowCloseRegex, \"</div>\");\n html = html.replace(map.columnRegex, '<div data-layout=\"column\">');\n html = html.replace(map.columnCloseRegex, \"</div>\");\n return html;\n}\n\nfunction applyFractionalLayoutMap(content: string, map: FractionalLayoutMap): string {\n let html = content;\n html = html.replace(map.sectionRegex, (_, params: string) => openSectionDiv(params, map.bgParamName));\n html = html.replace(map.sectionCloseRegex, \"</div>\");\n html = html.replace(map.rowRegex, (_, params: string) => openRowDiv(params));\n html = html.replace(map.rowCloseRegex, \"</div>\");\n\n for (let index = 0; index < map.columnTokens.length; index += 1) {\n const token = map.columnTokens[index]!;\n const width = map.columnWidths[token];\n const openRegex = map.columnOpenRegexes[index]!;\n const closeRegex = map.columnCloseRegexes[index]!;\n html = html.replace(openRegex, () => {\n const attrs = ['data-layout=\"column\"'];\n if (width) attrs.push(`data-col-width=\"${width}\"`);\n return `<div ${attrs.join(\" \")}>`;\n });\n html = html.replace(closeRegex, \"</div>\");\n }\n return html;\n}\n\nfunction applyExtendedPrefixedLayoutMap(content: string, map: ExtendedPrefixedLayoutMap): string {\n let html = content;\n const levels = [...map.levels].sort((left, right) => {\n const leftMax = Math.max(...left.tokens.map((token) => token.length));\n const rightMax = Math.max(...right.tokens.map((token) => token.length));\n return rightMax - leftMax;\n });\n\n for (const level of levels) {\n const tokens = [...level.tokens].sort((left, right) => right.length - left.length);\n for (const token of tokens) {\n const openRegex = new RegExp(`\\\\[${escapeRegExp(token)}\\\\b([^\\\\]]*)\\\\]`, \"gi\");\n const closeRegex = new RegExp(`\\\\[\\\\/${escapeRegExp(token)}\\\\b[^\\\\]]*\\\\]`, \"gi\");\n\n html = html.replace(openRegex, (_, params: string) => {\n switch (level.role) {\n case \"section\":\n return openSectionDiv(params, level.bgParamName);\n case \"row\":\n return openRowDiv(params, level.colsParamName);\n case \"column\":\n return openColumnDiv(params, level.widthParamName);\n }\n });\n html = html.replace(closeRegex, \"</div>\");\n }\n }\n\n return html;\n}\n\n/** Map builder layout shortcodes → editor-neutral `data-layout` HTML. */\nexport function applyStructuralLayoutMap(content: string, map: StructuralLayoutMap): string {\n switch (map.kind) {\n case \"prefixed\":\n return applyPrefixedLayoutMap(content, map);\n case \"fractional\":\n return applyFractionalLayoutMap(content, map);\n case \"extended-prefixed\":\n return applyExtendedPrefixedLayoutMap(content, map);\n }\n}\n\nfunction collectLayoutMaps(theme: BuilderThemeConfig): StructuralLayoutMap[] {\n const maps: StructuralLayoutMap[] = [];\n if (theme.layoutMap) maps.push(theme.layoutMap);\n if (theme.layoutMaps?.length) maps.push(...theme.layoutMaps);\n return maps;\n}\n\nfunction extractShortcodeParam(params: string, names: string[]): string | undefined {\n for (const name of names) {\n const value = extractQuotedParam(params, name);\n if (value) return value;\n }\n return undefined;\n}\n\nfunction escapeHtmlText(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction textToHtml(text: string, tag: TextHtmlTag): string {\n const paragraphs = text.split(/\\n{2,}/).map((part) => part.trim()).filter(Boolean);\n if (paragraphs.length === 0) return \"\";\n\n return paragraphs\n .map((paragraph) => {\n const inner = escapeHtmlText(paragraph).replace(/\\n/g, \"<br />\");\n return `<${tag}>${inner}</${tag}>`;\n })\n .join(\"\\n\");\n}\n\nfunction emitHtmlTag(tag: BuilderHtmlTag, url: string): string {\n const normalized = normalizeAssetUrl(url) ?? url;\n const escaped = normalized\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\");\n\n switch (tag) {\n case \"img\":\n return `<img src=\"${escaped}\" alt=\"\" />`;\n case \"video\":\n return `<video src=\"${escaped}\" controls></video>`;\n case \"iframe\":\n return `<iframe src=\"${escaped}\" loading=\"lazy\"></iframe>`;\n }\n}\n\nfunction convertUrlRule(content: string, rule: BuilderUrlRule): string {\n const prefix = escapeRegExp(rule.shortcodePrefix);\n const pattern = new RegExp(\n `\\\\[${prefix}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${prefix}\\\\b[^\\\\]]*\\\\])?`,\n \"gi\",\n );\n\n return content.replace(pattern, (block, params: string) => {\n const url = extractShortcodeParam(params, rule.urlParams);\n if (!url) return block;\n return emitHtmlTag(rule.tag, url);\n });\n}\n\nfunction convertTextRule(content: string, rule: BuilderTextRule): string {\n const prefix = escapeRegExp(rule.shortcodePrefix);\n const pattern = new RegExp(\n `\\\\[${prefix}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${prefix}\\\\b[^\\\\]]*\\\\])?`,\n \"gis\",\n );\n\n return content.replace(pattern, (block, params: string) => {\n const parts: string[] = [];\n for (const field of rule.fields) {\n const text = extractQuotedParam(params, field.param);\n if (!text) continue;\n const html = textToHtml(text, field.tag);\n if (html) parts.push(html);\n }\n return parts.length > 0 ? parts.join(\"\\n\") : block;\n });\n}\n\nfunction convertWrapperRule(content: string, rule: BuilderWrapperRule): string {\n const prefix = escapeRegExp(rule.shortcodePrefix);\n const pattern = new RegExp(\n `\\\\[${prefix}\\\\b([^\\\\]]*)\\\\]([\\\\s\\\\S]*?)\\\\[\\\\/${prefix}\\\\b[^\\\\]]*\\\\]`,\n \"gi\",\n );\n\n return content.replace(pattern, (_, params: string, inner: string) => {\n const parts: string[] = [];\n if (rule.urlParams?.length) {\n const url = extractShortcodeParam(params, rule.urlParams);\n if (url) parts.push(emitHtmlTag(\"img\", url));\n }\n parts.push(inner.trim());\n return parts.filter(Boolean).join(\"\\n\");\n });\n}\n\nfunction isPlaceholderImageUrl(url: string): boolean {\n return /placehold\\.it|placeholder\\.com|via\\.placeholder/i.test(url);\n}\n\nfunction convertIconImageRule(content: string, rule: BuilderIconImageRule): string {\n const prefix = escapeRegExp(rule.shortcodePrefix);\n const pattern = new RegExp(\n `\\\\[${prefix}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${prefix}\\\\b[^\\\\]]*\\\\])?`,\n \"gi\",\n );\n\n return content.replace(pattern, (_, params: string) => {\n const iconImage =\n extractQuotedParam(params, rule.imageParam) ?? extractQuotedParam(params, \"image\");\n if (!iconImage?.startsWith(\"http\") || isPlaceholderImageUrl(iconImage)) {\n return \"\";\n }\n const img = emitHtmlTag(\"img\", iconImage);\n if (rule.hrefParam) {\n const href = extractQuotedParam(params, rule.hrefParam);\n if (href?.startsWith(\"http\")) {\n const escapedHref = href\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\");\n return `<a href=\"${escapedHref}\">${img}</a>`;\n }\n }\n return img;\n });\n}\n\nfunction convertPlaceholderRule(content: string, rule: BuilderPlaceholderRule): string {\n const prefix = escapeRegExp(rule.shortcodePrefix);\n const pattern = new RegExp(\n `\\\\[${prefix}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${prefix}\\\\b[^\\\\]]*\\\\])?`,\n \"gi\",\n );\n return content.replace(pattern, rule.html);\n}\n\nfunction stripScaffoldingPrefix(content: string, prefix: string): string {\n const escaped = escapeRegExp(prefix);\n const opener = new RegExp(`\\\\[${escaped}[a-z0-9_-]*[^\\\\]]*\\\\]`, \"gi\");\n const closer = new RegExp(`\\\\[\\\\/${escaped}[a-z0-9_-]*[^\\\\]]*\\\\]`, \"gi\");\n return content.replace(opener, \"\").replace(closer, \"\");\n}\n\nfunction stripLegacyTokens(content: string, tokens: string[]): string {\n let result = content;\n for (const token of tokens) {\n const escaped = escapeRegExp(token);\n const opener = new RegExp(`\\\\[${escaped}\\\\b[^\\\\]]*\\\\]`, \"gi\");\n const closer = new RegExp(`\\\\[\\\\/${escaped}\\\\b[^\\\\]]*\\\\]`, \"gi\");\n result = result.replace(opener, \"\").replace(closer, \"\");\n }\n return result;\n}\n\nfunction detectThemes(content: string, registry: BuilderThemeConfig[]): BuilderThemeConfig[] {\n return registry.filter((theme) => theme.detect.test(content));\n}\n\nfunction extractBareOrQuotedParam(params: string, name: string): string | undefined {\n const quoted = extractQuotedParam(params, name);\n if (quoted) return quoted;\n const pattern = new RegExp(`\\\\b${escapeRegExp(name)}\\\\s*=\\\\s*([^\\\\s\"'\\\\]]+)`, \"i\");\n const match = pattern.exec(params);\n return match?.[1]?.trim() || undefined;\n}\n\nexport type SliderPluginId = \"revslider\" | \"masterslider\";\n\nexport interface ParsedSliderReference {\n plugin: SliderPluginId;\n alias: string;\n slidertitle?: string;\n}\n\n/** Parse `[rev_slider …]` / `[masterslider …]` markup (OSS-27 meta + in-body stubs). */\nexport function parseSliderShortcodeMarkup(markup: string): ParsedSliderReference | undefined {\n const trimmed = markup.trim();\n if (!trimmed) return undefined;\n\n const revMatch = trimmed.match(/\\[rev_slider\\b([^\\]]*)\\]/i);\n if (revMatch) {\n const params = revMatch[1] ?? \"\";\n const alias = extractBareOrQuotedParam(params, \"alias\");\n if (alias) {\n return {\n plugin: \"revslider\",\n alias,\n slidertitle: extractBareOrQuotedParam(params, \"slidertitle\"),\n };\n }\n }\n\n const masterMatch = trimmed.match(/\\[masterslider\\b([^\\]]*)\\]/i);\n if (masterMatch) {\n const params = masterMatch[1] ?? \"\";\n const alias = extractBareOrQuotedParam(params, \"alias\");\n if (alias) return { plugin: \"masterslider\", alias };\n }\n\n return undefined;\n}\n\n/** Parse Oshine `_slider` meta (`revslider_alias`, `masterslider_alias`, or `none`). */\nexport function parseSliderMetaValue(value: string): ParsedSliderReference | undefined {\n const trimmed = value.trim();\n if (!trimmed || trimmed.toLowerCase() === \"none\") return undefined;\n\n const lower = trimmed.toLowerCase();\n if (lower.startsWith(\"revslider_\")) {\n const alias = trimmed.slice(\"revslider_\".length).trim();\n if (alias) return { plugin: \"revslider\", alias };\n }\n if (lower.startsWith(\"masterslider_\")) {\n const alias = trimmed.slice(\"masterslider_\".length).trim();\n if (alias) return { plugin: \"masterslider\", alias };\n }\n\n return undefined;\n}\n\nfunction emitWidgetStub(\n widget: string,\n attrs: Record<string, string | undefined>,\n tag: \"div\" | \"section\" = \"div\",\n): string {\n const parts = [`data-wp-widget=\"${escapeLayoutAttr(widget)}\"`];\n for (const [key, value] of Object.entries(attrs)) {\n if (value) parts.push(`${key}=\"${escapeLayoutAttr(value)}\"`);\n }\n return `<${tag} ${parts.join(\" \")}>${WP_WIDGET_PLACEHOLDER}</${tag}>`;\n}\n\n/** Normalize YouTube/Vimeo share URLs to canonical embed URLs. */\nexport function normalizeVideoEmbedUrl(\n raw: string,\n): { provider: \"youtube\" | \"vimeo\" | \"external\"; embedUrl: string } | undefined {\n const trimmed = raw.trim();\n if (!trimmed || trimmed.startsWith(\"data:\")) return undefined;\n\n try {\n const url = new URL(trimmed.startsWith(\"//\") ? `https:${trimmed}` : trimmed);\n const host = url.hostname.replace(/^www\\./, \"\").replace(/^m\\./, \"\");\n\n if (host === \"youtu.be\") {\n const id = url.pathname.split(\"/\").filter(Boolean)[0];\n if (id) {\n return { provider: \"youtube\", embedUrl: `https://www.youtube-nocookie.com/embed/${id}` };\n }\n }\n\n if (host === \"youtube.com\" || host === \"youtube-nocookie.com\") {\n const embedMatch = url.pathname.match(/\\/embed\\/([^/?#]+)/);\n if (embedMatch?.[1]) {\n const start = url.searchParams.get(\"start\");\n const suffix = start ? `?start=${start}` : \"\";\n return {\n provider: \"youtube\",\n embedUrl: `https://www.youtube-nocookie.com/embed/${embedMatch[1]}${suffix}`,\n };\n }\n const videoId = url.searchParams.get(\"v\");\n if (videoId) {\n const t = url.searchParams.get(\"t\") ?? url.searchParams.get(\"start\");\n const startSeconds = t?.endsWith(\"s\") ? t.slice(0, -1) : t;\n const suffix = startSeconds ? `?start=${startSeconds}` : \"\";\n return {\n provider: \"youtube\",\n embedUrl: `https://www.youtube-nocookie.com/embed/${videoId}${suffix}`,\n };\n }\n }\n\n if (host === \"vimeo.com\") {\n const segments = url.pathname.split(\"/\").filter(Boolean);\n const id = segments[segments.length - 1];\n if (id && /^\\d+$/.test(id)) {\n return { provider: \"vimeo\", embedUrl: `https://player.vimeo.com/video/${id}` };\n }\n }\n\n if (host === \"player.vimeo.com\") {\n const match = url.pathname.match(/\\/video\\/(\\d+)/);\n if (match?.[1]) {\n return { provider: \"vimeo\", embedUrl: `https://player.vimeo.com/video/${match[1]}` };\n }\n }\n } catch {\n return undefined;\n }\n\n return undefined;\n}\n\nfunction emitVideoWidgetFromParams(params: string, inner: string): string {\n const url =\n extractShortcodeParam(params, [\"url\", \"src\", \"video\", \"link\", \"youtube_url\", \"vimeo_url\"]) ??\n inner.trim().match(/^https?:\\/\\/\\S+/)?.[0];\n\n if (!url) {\n return emitWidgetStub(\"video\", { \"data-video-provider\": \"external\" });\n }\n\n const normalized = normalizeVideoEmbedUrl(url);\n if (normalized) {\n return emitWidgetStub(\"video\", {\n \"data-video-provider\": normalized.provider,\n \"data-embed-url\": normalized.embedUrl,\n });\n }\n\n if (/\\.(mp4|webm|ogg)(\\?|#|$)/i.test(url)) {\n return emitHtmlTag(\"video\", url);\n }\n\n return emitWidgetStub(\"video\", {\n \"data-video-provider\": \"external\",\n \"data-embed-url\": url,\n });\n}\n\n/** Build a Google Maps iframe embed URL from map shortcode params. */\nexport function buildGoogleMapsEmbedUrlFromMapParams(params: string): {\n embedUrl?: string;\n lat?: string;\n lng?: string;\n query?: string;\n} {\n const direct = extractShortcodeParam(params, [\n \"embed_url\",\n \"url\",\n \"src\",\n \"map_url\",\n \"iframe_url\",\n \"embed\",\n ]);\n if (direct && /google\\.com\\/maps|maps\\.google\\.com/i.test(direct)) {\n return { embedUrl: direct.trim() };\n }\n\n const lat =\n extractBareOrQuotedParam(params, \"lat\") ??\n extractBareOrQuotedParam(params, \"latitude\") ??\n extractBareOrQuotedParam(params, \"map_lat\");\n const lng =\n extractBareOrQuotedParam(params, \"lng\") ??\n extractBareOrQuotedParam(params, \"longitude\") ??\n extractBareOrQuotedParam(params, \"map_lng\");\n const address =\n extractBareOrQuotedParam(params, \"address\") ??\n extractBareOrQuotedParam(params, \"map_address\") ??\n extractBareOrQuotedParam(params, \"location\") ??\n extractBareOrQuotedParam(params, \"map_location\") ??\n extractBareOrQuotedParam(params, \"q\");\n\n if (lat && lng) {\n const zoom = extractBareOrQuotedParam(params, \"zoom\") ?? \"14\";\n return {\n embedUrl: `https://maps.google.com/maps?q=${encodeURIComponent(`${lat},${lng}`)}&z=${zoom}&output=embed`,\n lat,\n lng,\n };\n }\n\n if (address) {\n return {\n embedUrl: `https://maps.google.com/maps?q=${encodeURIComponent(address)}&output=embed`,\n query: address,\n };\n }\n\n return {};\n}\n\nfunction flattenMapShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n let html = content;\n for (const prefix of widgetRegistry.mapShortcodePrefixes) {\n const pattern = new RegExp(\n `\\\\[${escapeRegExp(prefix)}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${escapeRegExp(prefix)}\\\\b[^\\\\]]*\\\\])?`,\n \"gi\",\n );\n html = html.replace(pattern, (_, params: string) => {\n const resolved = buildGoogleMapsEmbedUrlFromMapParams(params);\n return emitWidgetStub(\"map\", {\n ...(resolved.embedUrl ? { \"data-embed-url\": resolved.embedUrl } : {}),\n ...(resolved.lat ? { \"data-wp-map-lat\": resolved.lat } : {}),\n ...(resolved.lng ? { \"data-wp-map-lng\": resolved.lng } : {}),\n ...(resolved.query ? { \"data-wp-map-query\": resolved.query } : {}),\n });\n });\n }\n return html;\n}\n\nfunction flattenContactFormShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n let html = content;\n for (const rule of widgetRegistry.contactFormRules) {\n const pattern = new RegExp(\n `\\\\[${escapeRegExp(rule.tag)}\\\\b([^\\\\]]*)\\\\]\\\\s*(?:\\\\[\\\\/${escapeRegExp(rule.tag)}\\\\b[^\\\\]]*\\\\])?`,\n \"gi\",\n );\n html = html.replace(pattern, (_, params: string) => {\n const id = extractBareOrQuotedParam(params, rule.idParam);\n return emitWidgetStub(\n \"contact-form\",\n {\n \"data-wp-form-source\": rule.source,\n ...(id ? { \"data-wp-form-id\": id } : {}),\n },\n \"section\",\n );\n });\n }\n return html;\n}\n\nfunction emitInlineGalleryFromIds(idList: string[]): string {\n const images = idList\n .map((id) => `<img data-wp-attachment-id=\"${escapeLayoutAttr(id)}\" alt=\"\" />`)\n .join(\"\");\n return `<figure data-wp-inline-gallery>${images}</figure>`;\n}\n\nfunction parseGalleryAttachmentIds(params: string): string[] | undefined {\n const ids = extractBareOrQuotedParam(params, \"ids\");\n const idList = ids\n ?.split(\",\")\n .map((part) => part.trim())\n .filter((part) => /^\\d+$/.test(part));\n return idList?.length ? idList : undefined;\n}\n\nfunction flattenIdGalleryShortcode(content: string, tag: string): string {\n const escaped = escapeRegExp(tag);\n const pattern = new RegExp(`\\\\[${escaped}\\\\b([^\\\\]]*)\\\\](?:\\\\s*\\\\[\\\\/${escaped}\\\\])?`, \"gi\");\n return content.replace(pattern, (fullMatch, params: string) => {\n const idList = parseGalleryAttachmentIds(params);\n if (idList?.length) {\n return emitInlineGalleryFromIds(idList);\n }\n return fullMatch;\n });\n}\n\nfunction flattenGalleryShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n const tag = escapeRegExp(widgetRegistry.galleryShortcode);\n const pattern = new RegExp(`\\\\[${tag}\\\\b([^\\\\]]*)\\\\](?:\\\\s*\\\\[\\\\/${tag}\\\\])?`, \"gi\");\n return content.replace(pattern, (_, params: string) => {\n const idList = parseGalleryAttachmentIds(params);\n\n if (idList?.length) {\n return emitInlineGalleryFromIds(idList);\n }\n\n const category = extractBareOrQuotedParam(params, \"category\") ?? extractBareOrQuotedParam(params, \"type\");\n return emitWidgetStub(\"portfolio\", {\n \"data-wp-gallery-dynamic\": \"1\",\n ...(category ? { \"data-wp-portfolio-category\": category } : {}),\n });\n });\n}\n\nfunction flattenIdBasedGalleryShortcodes(\n content: string,\n widgetRegistry: WordPressWidgetRegistry,\n): string {\n let html = content;\n for (const tag of widgetRegistry.idGalleryShortcodes) {\n html = flattenIdGalleryShortcode(html, tag);\n }\n return html;\n}\n\nconst SHORTCODE_WORD_COUNTS: Record<string, string> = {\n one: \"1\",\n two: \"2\",\n three: \"3\",\n four: \"4\",\n five: \"5\",\n six: \"6\",\n seven: \"7\",\n eight: \"8\",\n nine: \"9\",\n ten: \"10\",\n};\n\nfunction normalizeShortcodeCount(raw: string | undefined): string | undefined {\n if (!raw?.trim()) return undefined;\n const trimmed = raw.trim().toLowerCase();\n if (/^\\d+$/.test(trimmed)) return trimmed;\n return SHORTCODE_WORD_COUNTS[trimmed];\n}\n\nfunction inferBlogListingLayout(params: string): string {\n const raw =\n extractBareOrQuotedParam(params, \"builderLayout\") ??\n extractBareOrQuotedParam(params, \"layout\") ??\n extractBareOrQuotedParam(params, \"style\");\n if (!raw) return \"grid\";\n const normalized = raw.trim().toLowerCase();\n if (normalized === \"list\" || normalized === \"grid\" || normalized === \"featured\" || normalized === \"sidebar\") {\n return normalized;\n }\n return \"grid\";\n}\n\nfunction decodeBasicHtmlEntities(text: string): string {\n return text\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&amp;/g, \"&\");\n}\n\nfunction stripHtmlTags(html: string): string {\n return html.replace(/<[^>]+>/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\nfunction extractTestimonialQuoteFromInner(inner: string): string | undefined {\n const trimmed = inner.trim();\n if (!trimmed) return undefined;\n\n const paragraphMatch = trimmed.match(/<p[^>]*>([\\s\\S]*?)<\\/p>/i);\n if (paragraphMatch?.[1]) {\n const quote = decodeBasicHtmlEntities(stripHtmlTags(paragraphMatch[1])).trim();\n return quote || undefined;\n }\n\n const blockquoteMatch = trimmed.match(/<blockquote[^>]*>([\\s\\S]*?)<\\/blockquote>/i);\n if (blockquoteMatch?.[1]) {\n const quote = decodeBasicHtmlEntities(stripHtmlTags(blockquoteMatch[1])).trim();\n return quote || undefined;\n }\n\n const plain = decodeBasicHtmlEntities(stripHtmlTags(trimmed)).trim();\n return plain || undefined;\n}\n\nfunction parseTestimonialItemAttrs(\n params: string,\n inner: string,\n): Record<string, string | undefined> | null {\n const author =\n extractBareOrQuotedParam(params, \"author\") ??\n extractBareOrQuotedParam(params, \"name\");\n const role =\n extractBareOrQuotedParam(params, \"author_role\") ??\n extractBareOrQuotedParam(params, \"role\") ??\n extractBareOrQuotedParam(params, \"title\");\n const image =\n extractBareOrQuotedParam(params, \"author_image\") ??\n extractBareOrQuotedParam(params, \"image\") ??\n extractBareOrQuotedParam(params, \"avatar\");\n const quote =\n extractBareOrQuotedParam(params, \"quote\") ??\n extractBareOrQuotedParam(params, \"content\") ??\n extractTestimonialQuoteFromInner(inner);\n const rating =\n extractBareOrQuotedParam(params, \"rating\") ??\n extractBareOrQuotedParam(params, \"stars\");\n\n if (!author && !quote) return null;\n\n return {\n \"data-wp-testimonial-author\": author,\n \"data-wp-testimonial-role\": role,\n \"data-wp-testimonial-image\": image,\n \"data-wp-testimonial-quote\": quote,\n ...(rating ? { \"data-wp-testimonial-rating\": rating } : {}),\n };\n}\n\nfunction emitTestimonialItemStub(attrs: Record<string, string | undefined>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(attrs)) {\n if (value) parts.push(`${key}=\"${escapeLayoutAttr(value)}\"`);\n }\n return `<div ${parts.join(\" \")}>${WP_WIDGET_PLACEHOLDER}</div>`;\n}\n\nfunction emitTestimonialsWidgetStub(\n sectionAttrs: Record<string, string | undefined>,\n items: Array<Record<string, string | undefined>>,\n): string {\n const sectionParts = ['data-wp-widget=\"testimonials\"'];\n for (const [key, value] of Object.entries(sectionAttrs)) {\n if (value) sectionParts.push(`${key}=\"${escapeLayoutAttr(value)}\"`);\n }\n const children = items.map((item) => emitTestimonialItemStub(item)).join(\"\");\n return `<section ${sectionParts.join(\" \")}>${children}</section>`;\n}\n\nfunction inferTestimonialColumns(\n wrapperParams: string,\n itemCount: number,\n): string {\n const explicit =\n normalizeShortcodeCount(extractBareOrQuotedParam(wrapperParams, \"columns\")) ??\n normalizeShortcodeCount(extractBareOrQuotedParam(wrapperParams, \"col\"));\n if (explicit) return explicit;\n if (itemCount <= 1) return \"1\";\n if (itemCount === 2) return \"2\";\n if (itemCount >= 4) return \"4\";\n return \"3\";\n}\n\nfunction collectTestimonialItemsFromInner(\n inner: string,\n itemTag: string,\n): Array<Record<string, string | undefined>> {\n const escaped = escapeRegExp(itemTag);\n const pattern = new RegExp(\n `\\\\[${escaped}\\\\b([^\\\\]]*)\\\\]([\\\\s\\\\S]*?)\\\\[\\\\/${escaped}\\\\b[^\\\\]]*\\\\]`,\n \"gi\",\n );\n const items: Array<Record<string, string | undefined>> = [];\n inner.replace(pattern, (_, params: string, itemInner: string) => {\n const item = parseTestimonialItemAttrs(params, itemInner);\n if (item) items.push(item);\n return \"\";\n });\n return items;\n}\n\nfunction flattenTestimonialsShortcodes(\n content: string,\n widgetRegistry: WordPressWidgetRegistry,\n): string {\n const itemTag = widgetRegistry.testimonialItemTag;\n let html = content;\n\n for (const wrapperTag of widgetRegistry.testimonialsWrapperTags) {\n const escaped = escapeRegExp(wrapperTag);\n const pattern = new RegExp(\n `\\\\[${escaped}\\\\b([^\\\\]]*)\\\\]([\\\\s\\\\S]*?)\\\\[\\\\/${escaped}\\\\b[^\\\\]]*\\\\]`,\n \"gi\",\n );\n html = html.replace(pattern, (fullMatch, wrapperParams: string, inner: string) => {\n const items = collectTestimonialItemsFromInner(inner, itemTag);\n if (items.length === 0) return fullMatch;\n\n return emitTestimonialsWidgetStub(\n {\n \"data-wp-testimonial-columns\": inferTestimonialColumns(wrapperParams, items.length),\n \"data-wp-testimonial-show-stars\": items.some((item) => item[\"data-wp-testimonial-rating\"])\n ? \"true\"\n : \"false\",\n },\n items,\n );\n });\n }\n\n const itemPattern = new RegExp(\n `\\\\[${escapeRegExp(itemTag)}\\\\b([^\\\\]]*)\\\\]([\\\\s\\\\S]*?)\\\\[\\\\/${escapeRegExp(itemTag)}\\\\b[^\\\\]]*\\\\]`,\n \"gi\",\n );\n return html.replace(itemPattern, (fullMatch, params: string, inner: string) => {\n const item = parseTestimonialItemAttrs(params, inner);\n if (!item) return fullMatch;\n return emitTestimonialsWidgetStub(\n {\n \"data-wp-testimonial-columns\": \"1\",\n \"data-wp-testimonial-show-stars\": item[\"data-wp-testimonial-rating\"] ? \"true\" : \"false\",\n },\n [item],\n );\n });\n}\n\nfunction flattenSliderShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n let html = content;\n for (const tag of widgetRegistry.sliderShortcodeTags) {\n const escaped = escapeRegExp(tag);\n const plugin: SliderPluginId = tag.toLowerCase() === \"masterslider\" ? \"masterslider\" : \"revslider\";\n const pattern = new RegExp(`\\\\[${escaped}\\\\b([^\\\\]]*)\\\\](?:\\\\s*\\\\[\\\\/${escaped}\\\\b[^\\\\]]*\\\\])?`, \"gi\");\n html = html.replace(pattern, (_, params: string) => {\n const alias = extractBareOrQuotedParam(params, \"alias\");\n const slidertitle = extractBareOrQuotedParam(params, \"slidertitle\");\n return emitWidgetStub(\"slider\", {\n \"data-wp-slider-plugin\": plugin,\n ...(alias ? { \"data-wp-slider-alias\": alias } : {}),\n ...(slidertitle ? { \"data-wp-slider-title\": slidertitle } : {}),\n });\n });\n }\n return html;\n}\n\nfunction flattenBlogListingShortcodes(\n content: string,\n widgetRegistry: WordPressWidgetRegistry,\n): string {\n let html = content;\n for (const tag of widgetRegistry.blogShortcodeTags) {\n const escaped = escapeRegExp(tag);\n const pattern = new RegExp(`\\\\[${escaped}\\\\b([^\\\\]]*)\\\\](?:\\\\s*\\\\[\\\\/${escaped}\\\\])?`, \"gi\");\n html = html.replace(pattern, (_, params: string) => {\n const limit =\n normalizeShortcodeCount(extractBareOrQuotedParam(params, \"number_of_posts\")) ??\n normalizeShortcodeCount(extractBareOrQuotedParam(params, \"count\")) ??\n normalizeShortcodeCount(extractBareOrQuotedParam(params, \"posts_per_page\")) ??\n normalizeShortcodeCount(extractBareOrQuotedParam(params, \"number\"));\n const filterBy = extractBareOrQuotedParam(params, \"filter_by\")?.toLowerCase();\n const categories = extractBareOrQuotedParam(params, \"categories\");\n const tags = extractBareOrQuotedParam(params, \"tags\");\n const col = extractBareOrQuotedParam(params, \"col\");\n\n return emitWidgetStub(\n \"blog-listing\",\n {\n \"data-wp-blog-layout\": inferBlogListingLayout(params),\n ...(limit ? { \"data-wp-blog-limit\": limit } : {}),\n ...(col ? { \"data-wp-blog-columns\": col } : {}),\n ...(filterBy === \"category\" && categories ? { \"data-wp-blog-category\": categories } : {}),\n ...(filterBy === \"tag\" && tags ? { \"data-wp-blog-tags\": tags } : {}),\n },\n \"section\",\n );\n });\n }\n return html;\n}\n\nfunction flattenPortfolioShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n const tag = escapeRegExp(widgetRegistry.portfolioShortcode);\n const pattern = new RegExp(`\\\\[${tag}\\\\b([^\\\\]]*)\\\\](?:\\\\s*\\\\[\\\\/${tag}\\\\])?`, \"gi\");\n return content.replace(pattern, (_, params: string) => {\n const category = extractBareOrQuotedParam(params, \"category\");\n const slug = extractBareOrQuotedParam(params, \"slug\");\n return emitWidgetStub(\"portfolio\", {\n ...(category ? { \"data-wp-portfolio-category\": category } : {}),\n ...(slug ? { \"data-wp-portfolio-slug\": slug } : {}),\n });\n });\n}\n\nfunction flattenVideoShortcodes(content: string, widgetRegistry: WordPressWidgetRegistry): string {\n let html = content;\n for (const prefix of widgetRegistry.videoShortcodePrefixes) {\n const wrapped = new RegExp(\n `\\\\[${escapeRegExp(prefix)}\\\\b([^\\\\]]*)\\\\]([\\\\s\\\\S]*?)\\\\[\\\\/${escapeRegExp(prefix)}\\\\b[^\\\\]]*\\\\]`,\n \"gi\",\n );\n html = html.replace(wrapped, (_, params: string, inner: string) =>\n emitVideoWidgetFromParams(params, inner),\n );\n\n const selfClosing = new RegExp(\n `\\\\[${escapeRegExp(prefix)}\\\\b([^\\\\]]*)\\\\]`,\n \"gi\",\n );\n html = html.replace(selfClosing, (_, params: string) => emitVideoWidgetFromParams(params, \"\"));\n }\n return html;\n}\n\n/** Detect embedded HTML contact forms (e.g. Tatsu `[tatsu_code]` with `<form>`). */\nexport function looksLikeContactFormHtml(formHtml: string): boolean {\n if (!/<form\\b/i.test(formHtml)) return false;\n\n const lower = formHtml.toLowerCase();\n if (/searchform|wp-login-form|loginform|lostpasswordform/i.test(lower)) return false;\n if (/type\\s*=\\s*[\"']search[\"']/i.test(formHtml)) return false;\n if (/newsletter|subscribe/i.test(lower) && !/<textarea\\b/i.test(formHtml)) return false;\n\n const hasEmailField =\n /type\\s*=\\s*[\"']email[\"']/i.test(formHtml) ||\n /name\\s*=\\s*[\"'][^\"']*email/i.test(formHtml) ||\n /class\\s*=\\s*[\"'][^\"']*email/i.test(formHtml);\n const hasMessageField =\n /<textarea\\b/i.test(formHtml) ||\n /name\\s*=\\s*[\"'][^\"']*(message|comment|body|enquiry|inquiry)/i.test(formHtml);\n const hasContactHint =\n /contact|serverless-contact|get-in-touch|request-quote|quote-request/i.test(lower);\n\n if (hasEmailField && hasMessageField) return true;\n if (hasContactHint && hasEmailField) return true;\n if (hasContactHint && hasMessageField) return true;\n\n return false;\n}\n\nfunction stripContactFormHelperScripts(html: string): string {\n return html.replace(\n /<script\\b[^>]*\\bsrc\\s*=\\s*[\"'][^\"']*(?:recaptcha|contact_form|contact-form)[^\"']*[\"'][^>]*>\\s*<\\/script>\\s*/gi,\n \"\",\n );\n}\n\nfunction flattenCustomHtmlContactForms(content: string): string {\n let html = content.replace(/<form\\b[^>]*>[\\s\\S]*?<\\/form>/gi, (formHtml) => {\n if (!looksLikeContactFormHtml(formHtml)) return formHtml;\n\n const formId =\n formHtml.match(/\\bid\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1]?.trim() ||\n formHtml.match(/\\bname\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1]?.trim();\n\n return emitWidgetStub(\n \"contact-form\",\n {\n \"data-wp-form-source\": \"custom-html\",\n ...(formId ? { \"data-wp-form-id\": formId } : {}),\n },\n \"section\",\n );\n });\n\n html = stripContactFormHelperScripts(html);\n return html;\n}\n\n/** Cross-builder widget + video stubs (before scaffolding strip). */\nfunction flattenWordPressWidgets(\n content: string,\n widgetRegistry: WordPressWidgetRegistry = WORDPRESS_WIDGET_REGISTRY,\n): string {\n let html = content;\n html = flattenGalleryShortcodes(html, widgetRegistry);\n html = flattenIdBasedGalleryShortcodes(html, widgetRegistry);\n html = flattenPortfolioShortcodes(html, widgetRegistry);\n html = flattenSliderShortcodes(html, widgetRegistry);\n html = flattenBlogListingShortcodes(html, widgetRegistry);\n html = flattenTestimonialsShortcodes(html, widgetRegistry);\n html = flattenMapShortcodes(html, widgetRegistry);\n html = flattenContactFormShortcodes(html, widgetRegistry);\n html = flattenVideoShortcodes(html, widgetRegistry);\n html = flattenCustomHtmlContactForms(html);\n return html;\n}\n\n/**\n * Pre-DTO WordPress builder flattening — Bucket 1 (asset/text shortcodes → HTML) then\n * Bucket 2 (layout scaffolding stripped). Decoupled from sink-time rewriteInlineImages.\n */\nexport function flattenWordPressBuilders(\n content: string,\n options: FlattenWordPressBuildersOptions = {},\n): FlattenWordPressBuildersResult {\n if (!content.trim()) {\n return { html: content, detectedThemes: [] };\n }\n\n const registry = options.registry ?? WORDPRESS_BUILDER_REGISTRY;\n const themes = detectThemes(content, registry);\n\n const widgetRegistry = options.widgetRegistry ?? WORDPRESS_WIDGET_REGISTRY;\n // Widget stubs before scaffolding strips (e.g. blox_gmap, tatsu_video, portfolio).\n let html = flattenWordPressWidgets(content, widgetRegistry);\n for (const theme of themes) {\n for (const rule of theme.wrapperRules ?? []) {\n html = convertWrapperRule(html, rule);\n }\n for (const rule of theme.textRules ?? []) {\n html = convertTextRule(html, rule);\n }\n for (const rule of theme.urlRules ?? []) {\n html = convertUrlRule(html, rule);\n }\n for (const rule of theme.placeholderRules ?? []) {\n html = convertPlaceholderRule(html, rule);\n }\n for (const rule of theme.iconImageRules ?? []) {\n html = convertIconImageRule(html, rule);\n }\n for (const layoutMap of collectLayoutMaps(theme)) {\n html = applyStructuralLayoutMap(html, layoutMap);\n }\n for (const prefix of theme.scaffoldingPrefixes ?? []) {\n html = stripScaffoldingPrefix(html, prefix);\n }\n if (theme.legacyScaffoldingTokens?.length) {\n html = stripLegacyTokens(html, theme.legacyScaffoldingTokens);\n }\n }\n\n // Catch widget shortcodes revealed after wrapper unwrap (e.g. blox_gmap inside tatsu_text_with_shortcodes).\n html = flattenWordPressWidgets(html, widgetRegistry);\n\n html = html.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n\n return {\n html,\n detectedThemes: themes.map((theme) => theme.id),\n };\n}\n"],"mappings":"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","names":["value","trimmed"]}
@@ -3,13 +3,15 @@ import {
3
3
  enumerateSquarespaceEntities,
4
4
  summarizeSquarespaceExport,
5
5
  validateSquarespaceExportFile
6
- } from "./chunk-VRRYN6NS.js";
6
+ } from "./chunk-5TRCJONX.js";
7
7
  import {
8
- flattenWordPressBuilders
9
- } from "./chunk-J7EUSPEA.js";
8
+ flattenWordPressBuilders,
9
+ parseSliderMetaValue,
10
+ parseSliderShortcodeMarkup
11
+ } from "./chunk-4XZK55RW.js";
10
12
  import {
11
13
  stampMigrationMediaRefs
12
- } from "./chunk-QFJXNEXG.js";
14
+ } from "./chunk-HUSXCKPI.js";
13
15
  import {
14
16
  linkToPath,
15
17
  sanitizeSlug
@@ -168,6 +170,71 @@ function inferPortfolioListingPage(item, options) {
168
170
  const hasPortfolioListingWidget = /data-wp-widget=["']portfolio["']/i.test(options.contentHtml);
169
171
  return hasPortfolioListingWidget && PORTFOLIO_LISTING_PAGE_SLUGS.has(options.slug.toLowerCase());
170
172
  }
173
+ function toHeroSliderHint(parsed, source) {
174
+ return {
175
+ plugin: parsed.plugin,
176
+ alias: parsed.alias,
177
+ slidertitle: parsed.slidertitle,
178
+ source
179
+ };
180
+ }
181
+ function findSliderInTatsuTree(node) {
182
+ if (!node) return void 0;
183
+ if (Array.isArray(node)) {
184
+ for (const child of node) {
185
+ const found = findSliderInTatsuTree(child);
186
+ if (found) return found;
187
+ }
188
+ return void 0;
189
+ }
190
+ if (typeof node !== "object") return void 0;
191
+ const obj = node;
192
+ const name = typeof obj.name === "string" ? obj.name : "";
193
+ if (name === "tatsu_rev_slider") {
194
+ const atts = obj.atts;
195
+ const alias = typeof atts?.rev_slider_alias === "string" ? atts.rev_slider_alias.trim() : "";
196
+ if (alias) {
197
+ return toHeroSliderHint({ plugin: "revslider", alias }, "tatsu-json");
198
+ }
199
+ }
200
+ if (name === "masterslider" || name === "tatsu_masterslider") {
201
+ const atts = obj.atts;
202
+ const alias = typeof atts?.alias === "string" ? atts.alias.trim() : "";
203
+ if (alias) {
204
+ return toHeroSliderHint({ plugin: "masterslider", alias }, "tatsu-json");
205
+ }
206
+ }
207
+ if (obj.inner) return findSliderInTatsuTree(obj.inner);
208
+ return void 0;
209
+ }
210
+ function inferHeroSliderLayoutHint(item) {
211
+ const shortcodeMeta = getPostMeta(item, "be_themes_hero_section_slider_shortcode");
212
+ if (shortcodeMeta) {
213
+ const parsed = parseSliderShortcodeMarkup(shortcodeMeta);
214
+ if (parsed) {
215
+ return { heroSlider: toHeroSliderHint(parsed, "meta-shortcode") };
216
+ }
217
+ }
218
+ const sliderMeta = getPostMeta(item, "_slider");
219
+ if (sliderMeta) {
220
+ const parsed = parseSliderMetaValue(sliderMeta);
221
+ if (parsed) {
222
+ return { heroSlider: toHeroSliderHint(parsed, "meta-slider-field") };
223
+ }
224
+ }
225
+ const heroSection = (getPostMeta(item, "be_themes_hero_section") ?? "").trim().toLowerCase();
226
+ if (heroSection === "slider") {
227
+ const tatsuContent = getPostMeta(item, "_tatsu_page_content");
228
+ if (tatsuContent) {
229
+ try {
230
+ const heroSlider = findSliderInTatsuTree(JSON.parse(tatsuContent));
231
+ if (heroSlider) return { heroSlider };
232
+ } catch {
233
+ }
234
+ }
235
+ }
236
+ return void 0;
237
+ }
171
238
  function parseItems(xml) {
172
239
  const parser = new XMLParser({
173
240
  ignoreAttributes: false,
@@ -425,6 +492,7 @@ async function* enumerateWxrEntities(options) {
425
492
  slug,
426
493
  contentHtml
427
494
  });
495
+ const layoutHints = inferHeroSliderLayoutHint(item);
428
496
  const pageSourceId = isPortfolioCpt ? portfolioCptSourceId(id) : id;
429
497
  const page = {
430
498
  type: "page",
@@ -435,6 +503,7 @@ async function* enumerateWxrEntities(options) {
435
503
  contentHtml,
436
504
  isHomePage: isHomePage || void 0,
437
505
  isPortfolioPage: isPortfolioPage || void 0,
506
+ layoutHints: layoutHints ?? void 0,
438
507
  status: mapPublishStatus(textValue(item.status))
439
508
  };
440
509
  yield page;
@@ -2494,4 +2563,4 @@ export {
2494
2563
  wixAdapter,
2495
2564
  getAdapter
2496
2565
  };
2497
- //# sourceMappingURL=chunk-Q44KGFIH.js.map
2566
+ //# sourceMappingURL=chunk-53VXTXGM.js.map