@templatical/import-stripo 0.51.1 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ConversionStatus, ImportReport, ImportReportEntry, ImportResult, ImportResult as ImportResult$1 } from "@templatical/import-html";
2
- //#region src/converter.d.ts
3
2
  interface ConvertStripoOptions {
4
3
  /** Sibling CSS from plugin `getTemplateData()`. Applied inside each HTML fragment. */
5
4
  css?: string;
@@ -14,8 +13,6 @@ interface ConvertStripoOptions {
14
13
  * Pass `options.css` when converting plugin storage (`getTemplateData().css`).
15
14
  */
16
15
  export declare function convertStripoTemplate(html: string, options?: ConvertStripoOptions): ImportResult$1;
17
- //#endregion
18
- //#region src/detect.d.ts
19
16
  type StripoKind = "editor" | "compiled";
20
17
  /**
21
18
  * Which Stripo HTML surface this is, or null if it is not Stripo markup.
@@ -27,6 +24,5 @@ type StripoKind = "editor" | "compiled";
27
24
  */
28
25
  export declare function detectStripoKind(html: string): StripoKind | null;
29
26
  export declare function isStripoHtml(html: string): boolean;
30
- //#endregion
31
27
  export type { ConversionStatus, ConvertStripoOptions, ImportReport, ImportReportEntry, ImportResult, StripoKind };
32
28
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { load } from "cheerio";
2
2
  import { convertHtmlTemplate } from "@templatical/import-html";
3
3
  import { createButtonBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createMenuBlock, createSectionBlock, createSocialIconsBlock, createSpacerBlock, generateId } from "@templatical/types";
4
- //#region src/classes.ts
4
+ // src/classes.ts
5
5
  function classTokens($el) {
6
6
  return ($el.attr("class") ?? "").trim().split(/\s+/).filter(Boolean);
7
7
  }
@@ -37,8 +37,7 @@ function topLevelWithToken($, token, $root) {
37
37
  function isHidden($el) {
38
38
  return hasToken($el, "es-hidden") || hasToken($el, "esd-hidden");
39
39
  }
40
- //#endregion
41
- //#region src/css.ts
40
+ // src/css.ts
42
41
  const ZERO$3 = {
43
42
  top: 0,
44
43
  right: 0,
@@ -758,8 +757,7 @@ function withoutBandOverImage(paint, hasImage) {
758
757
  notes: [`The band colour ${paint.wrapperColor} was dropped: Outlook desktop paints a wrapper colour over the section's background image.`]
759
758
  };
760
759
  }
761
- //#endregion
762
- //#region src/fragment.ts
760
+ // src/fragment.ts
763
761
  /** Paint after `createSectionBlock` so `styles` keeps its required padding. */
764
762
  function withBackground(section, backgroundColor) {
765
763
  if (backgroundColor) section.styles.backgroundColor = backgroundColor;
@@ -852,8 +850,7 @@ function bandImage($stripe, $cell, boxWidth) {
852
850
  source: $stripe[0]
853
851
  } : null;
854
852
  }
855
- //#endregion
856
- //#region src/platform.ts
853
+ // src/platform.ts
857
854
  const NAMED = {
858
855
  facebook: "facebook",
859
856
  fb: "facebook",
@@ -898,8 +895,7 @@ function normalizePlatform(name, src, alt) {
898
895
  }
899
896
  return "website";
900
897
  }
901
- //#endregion
902
- //#region src/labelled.ts
898
+ // src/labelled.ts
903
899
  const ZERO$2 = {
904
900
  top: 0,
905
901
  right: 0,
@@ -1115,8 +1111,7 @@ function socialFrom($el, $, sourceTag, ctx) {
1115
1111
  function labelledInnerBlocks($el, $, ctx) {
1116
1112
  return blocksFromHtml($.html($el) ?? "", ctx);
1117
1113
  }
1118
- //#endregion
1119
- //#region src/compiled.ts
1114
+ // src/compiled.ts
1120
1115
  const ZERO$1 = {
1121
1116
  top: 0,
1122
1117
  right: 0,
@@ -1479,8 +1474,7 @@ function convertCompiled(html, ctx) {
1479
1474
  for (const $stripe of stripes) out.push(...sectionsFromStripe($stripe, $, ctx));
1480
1475
  return out;
1481
1476
  }
1482
- //#endregion
1483
- //#region src/detect.ts
1477
+ // src/detect.ts
1484
1478
  const EDITOR_TOKENS = /* @__PURE__ */ new Set([
1485
1479
  "esd-stripe",
1486
1480
  "esd-structure",
@@ -1563,8 +1557,7 @@ function detectStripoKind(html) {
1563
1557
  function isStripoHtml(html) {
1564
1558
  return detectStripoKind(html) !== null;
1565
1559
  }
1566
- //#endregion
1567
- //#region src/editor.ts
1560
+ // src/editor.ts
1568
1561
  const ZERO = {
1569
1562
  top: 0,
1570
1563
  right: 0,
@@ -1721,8 +1714,7 @@ function convertEditor(html, ctx) {
1721
1714
  }), paint.backgroundColor);
1722
1715
  });
1723
1716
  }
1724
- //#endregion
1725
- //#region src/converter.ts
1717
+ // src/converter.ts
1726
1718
  function injectCss(html, css) {
1727
1719
  if (!css || css.trim().length === 0) return html;
1728
1720
  const $ = load(html);
@@ -1819,7 +1811,6 @@ function convertStripoTemplate(html, options) {
1819
1811
  report: summarize(ctx)
1820
1812
  };
1821
1813
  }
1822
- //#endregion
1823
1814
  export { convertStripoTemplate, detectStripoKind, isStripoHtml };
1824
1815
 
1825
1816
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ZERO","ZERO","ZERO","BODY_SELECTOR","bandColor"],"sources":["../src/classes.ts","../src/css.ts","../src/fragment.ts","../src/platform.ts","../src/labelled.ts","../src/compiled.ts","../src/detect.ts","../src/editor.ts","../src/converter.ts"],"sourcesContent":["import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\n\nexport function classTokens($el: Cheerio<Element>): string[] {\n return ($el.attr(\"class\") ?? \"\").trim().split(/\\s+/).filter(Boolean);\n}\n\nexport function hasToken($el: Cheerio<Element>, token: string): boolean {\n return classTokens($el).includes(token);\n}\n\nexport function hasAnyToken(\n $el: Cheerio<Element>,\n tokens: readonly string[],\n): boolean {\n const set = new Set(classTokens($el));\n return tokens.some((t) => set.has(t));\n}\n\nexport function tokenStartingWith(\n $el: Cheerio<Element>,\n prefix: string,\n): string | undefined {\n return classTokens($el).find((t) => t.startsWith(prefix));\n}\n\n/** Elements carrying `token` that are not nested in another such element. */\nexport function topLevelWithToken(\n $: CheerioAPI,\n token: string,\n $root?: Cheerio<Element>,\n): Cheerio<Element>[] {\n const selector = `[class~=\"${token}\"]`;\n const $found = $root ? $root.find(selector) : $(selector);\n const out: Cheerio<Element>[] = [];\n $found.each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n const nested = $el.parents(selector);\n if ($root && $root.length) {\n const outside = nested.filter((_, p) => {\n const $p = $(p) as Cheerio<Element>;\n return $p.closest($root).length === 0 && !$p.is($root);\n });\n if (nested.length - outside.length > 0) return;\n } else if (nested.length > 0) {\n return;\n }\n out.push($el);\n });\n return out;\n}\n\nexport function isHidden($el: Cheerio<Element>): boolean {\n return hasToken($el, \"es-hidden\") || hasToken($el, \"esd-hidden\");\n}\n","/**\n * Tiny CSS readers for paint, padding and divider width.\n * Hex (3/6), a bare bgcolor hex, and rgb()/rgba() (alpha dropped).\n * \"transparent\" is unset. A present padding longhand of 0 beats the shorthand.\n */\n\nimport type {\n BackgroundImage,\n BackgroundPositionX,\n BackgroundPositionY,\n BackgroundSize,\n DividerBlock,\n SpacingValue,\n} from \"@templatical/types\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/** Column shares of the body width. The third column takes the rounding remainder. */\nconst COLUMN_SHARES = {\n \"1\": [100],\n \"2\": [50, 50],\n \"3\": [33.33, 33.33, 33.34],\n} as const;\n\nconst DIVIDER_WIDTH = /^(-?\\d+(?:\\.\\d+)?)\\s*(%|px)?$/i;\n\nconst SIDE_LETTER: Record<string, keyof SpacingValue> = {\n t: \"top\",\n r: \"right\",\n b: \"bottom\",\n l: \"left\",\n};\n\n/**\n * A `style` attribute as a key/value map. A semicolon inside quotes or\n * parentheses — `url(\"a;b\")`, `url(data:image/png;base64,…)` — belongs to\n * its value.\n */\nexport function parseStyleAttribute(\n styleAttr: string | undefined,\n): Record<string, string> {\n const result: Record<string, string> = {};\n if (!styleAttr) return result;\n for (const decl of splitTopLevel(styleAttr, \";\")) {\n const idx = decl.indexOf(\":\");\n if (idx === -1) continue;\n const key = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (key && value) result[key] = value;\n }\n return result;\n}\n\n/**\n * Split `value` at each `separator` that sits outside quotes and parentheses.\n * A value whose quote or parenthesis never closes is split at every\n * `separator` instead, so a malformed declaration costs only itself and the\n * ones after it still read.\n */\nfunction splitTopLevel(value: string, separator: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let quote = \"\";\n let start = 0;\n for (let i = 0; i < value.length; i++) {\n const char = value[i];\n if (quote) {\n if (char === quote) quote = \"\";\n continue;\n }\n if (char === '\"' || char === \"'\") quote = char;\n else if (char === \"(\") depth++;\n else if (char === \")\") depth = Math.max(0, depth - 1);\n else if (char === separator && depth === 0) {\n parts.push(value.slice(start, i));\n start = i + 1;\n }\n }\n if (quote || depth > 0) return value.split(separator);\n parts.push(value.slice(start));\n return parts;\n}\n\nfunction channelHex(value: number): string {\n const clamped = Math.max(0, Math.min(255, Math.round(value)));\n return clamped.toString(16).padStart(2, \"0\");\n}\n\nexport function parseColor(value: string | undefined): string {\n if (!value) return \"\";\n const trimmed = value.trim().toLowerCase();\n if (trimmed === \"transparent\" || trimmed === \"inherit\" || trimmed === \"none\")\n return \"\";\n const hex = trimmed.startsWith(\"#\")\n ? trimmed\n : /^[0-9a-f]{3}$|^[0-9a-f]{6}$/.test(trimmed)\n ? `#${trimmed}`\n : \"\";\n if (/^#[0-9a-f]{6}$/.test(hex)) return hex;\n if (/^#[0-9a-f]{3}$/.test(hex)) {\n return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;\n }\n const rgb = trimmed.match(\n /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/,\n );\n if (rgb) {\n return `#${channelHex(Number(rgb[1]))}${channelHex(Number(rgb[2]))}${channelHex(Number(rgb[3]))}`;\n }\n return \"\";\n}\n\nexport function parsePxValue(value: string | undefined): number {\n if (!value) return 0;\n const match = value.trim().match(/^(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s*$/);\n return match ? Math.round(parseFloat(match[1])) : 0;\n}\n\n/** Inline `background-color` / `background` wins over the `bgcolor` attribute. */\nexport function colorFromPaint(\n styleAttr: string | undefined,\n bgcolor?: string,\n): string {\n const styles = parseStyleAttribute(styleAttr);\n const fromShorthand = styles.background\n ? parseColor(styles.background.trim().split(/\\s+/)[0])\n : \"\";\n return (\n parseColor(styles[\"background-color\"]) ||\n fromShorthand ||\n parseColor(bgcolor) ||\n \"\"\n );\n}\n\nexport function parsePaddingShorthand(value: string | undefined): SpacingValue {\n if (!value) return { ...ZERO };\n const values = value\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .map((part) => parsePxValue(part));\n if (values.length === 0) return { ...ZERO };\n if (values.length === 1) {\n return {\n top: values[0],\n right: values[0],\n bottom: values[0],\n left: values[0],\n };\n }\n if (values.length === 2) {\n return {\n top: values[0],\n right: values[1],\n bottom: values[0],\n left: values[1],\n };\n }\n if (values.length === 3) {\n return {\n top: values[0],\n right: values[1],\n bottom: values[2],\n left: values[1],\n };\n }\n return {\n top: values[0],\n right: values[1],\n bottom: values[2],\n left: values[3],\n };\n}\n\n/**\n * Longhand wins when it is present, including an explicit 0.\n * A missing longhand falls back to the shorthand, then 0.\n */\nexport function readPadding(styles: Record<string, string>): SpacingValue {\n const shorthand =\n styles.padding !== undefined ? parsePaddingShorthand(styles.padding) : ZERO;\n const side = (name: keyof SpacingValue): number => {\n const key = `padding-${name}`;\n if (styles[key] !== undefined) return parsePxValue(styles[key]);\n return shorthand[name];\n };\n return {\n top: side(\"top\"),\n right: side(\"right\"),\n bottom: side(\"bottom\"),\n left: side(\"left\"),\n };\n}\n\n/** `es-p20` sets every side; `es-p10t` / `r` / `b` / `l` then override one side. */\nexport function paddingFromClasses(\n classAttr: string | undefined,\n): SpacingValue {\n const pad: SpacingValue = { ...ZERO };\n const tokens = (classAttr ?? \"\").split(/\\s+/).filter(Boolean);\n for (const token of tokens) {\n const all = /^es-p(\\d+)$/.exec(token);\n if (!all) continue;\n const n = Number(all[1]);\n pad.top = n;\n pad.right = n;\n pad.bottom = n;\n pad.left = n;\n }\n for (const token of tokens) {\n const side = /^es-p(\\d+)([trbl])$/.exec(token);\n if (!side) continue;\n pad[SIDE_LETTER[side[2]]] = Number(side[1]);\n }\n return pad;\n}\n\n/**\n * Class padding first, then inline padding per side.\n * A shorthand replaces every side; a longhand replaces only that side.\n */\nexport function readBoxPadding(\n classAttr: string | undefined,\n styleAttr: string | undefined,\n): SpacingValue {\n const base = paddingFromClasses(classAttr);\n const styles = parseStyleAttribute(styleAttr);\n const hasShorthand = styles.padding !== undefined;\n const shorthand = hasShorthand ? parsePaddingShorthand(styles.padding) : base;\n const side = (name: keyof SpacingValue): number => {\n const key = `padding-${name}`;\n if (styles[key] !== undefined) return parsePxValue(styles[key]);\n if (hasShorthand) return shorthand[name];\n return base[name];\n };\n return {\n top: side(\"top\"),\n right: side(\"right\"),\n bottom: side(\"bottom\"),\n left: side(\"left\"),\n };\n}\n\nexport interface SectionPaint {\n backgroundColor: string;\n wrapperColor?: string;\n notes: string[];\n}\n\n/**\n * Body fill paints the section. A band that is neither the page nor the body\n * becomes the section wrapper. A transparent body leaves the band on the section.\n */\nexport function resolveSectionPaint(\n pageBackground: string,\n band: string,\n body: string,\n): SectionPaint {\n const page = pageBackground || \"#ffffff\";\n if (body) {\n if (band && band !== page && band !== body) {\n return {\n backgroundColor: body,\n wrapperColor: band,\n notes: [\"The band colour was imported as a section wrapper.\"],\n };\n }\n return { backgroundColor: body, notes: [] };\n }\n return { backgroundColor: band, notes: [] };\n}\n\n/** `es-*-body` width in px, or 600 when the document does not state one. */\nexport function emailBodyWidth(\n widthAttr: string | undefined,\n styleAttr: string | undefined,\n): number {\n const raw = (widthAttr || parseStyleAttribute(styleAttr).width || \"\").trim();\n const n = parsePxValue(raw);\n return n > 0 ? n : 600;\n}\n\n/**\n * Room each column has for a line, before the line's own side padding.\n * The share is of the body width; the first column then loses the section's\n * left padding and the last loses the right. One column loses both.\n * A room that is not positive is unknown — the caller keeps the stated px.\n */\nexport function columnRooms(\n bodyWidth: number,\n layout: \"1\" | \"2\" | \"3\",\n padding: SpacingValue,\n slotCount: number,\n): Array<number | undefined> {\n const shares = COLUMN_SHARES[layout];\n const count = layout === \"1\" ? 1 : slotCount;\n const width = bodyWidth > 0 ? bodyWidth : 600;\n return Array.from({ length: count }, (_, index) => {\n const span = layout === \"1\" ? width : (width * shares[index]) / 100;\n const left = layout === \"1\" || index === 0 ? padding.left : 0;\n const right = layout === \"1\" || index === count - 1 ? padding.right : 0;\n const room = span - left - right;\n return room > 0 ? room : undefined;\n });\n}\n\n/**\n * No width, `auto` and `100%` span the column. Another percentage stays a\n * share, clamped to 0–100 and rounded to two decimals. A px width stays px\n * until it reaches `room` less the divider's own side padding.\n */\nexport function readDividerWidth(\n raw: string,\n room: number | undefined,\n ownLeft: number,\n ownRight: number,\n notes: string[],\n): DividerBlock[\"width\"] {\n const trimmed = raw.trim();\n if (\n trimmed === \"\" ||\n trimmed.toLowerCase() === \"auto\" ||\n trimmed === \"100%\"\n ) {\n return \"full\";\n }\n const match = trimmed.match(DIVIDER_WIDTH);\n if (!match) {\n notes.push(\n `Divider width \"${trimmed}\" could not be read; imported as full width.`,\n );\n return \"full\";\n }\n const value = parseFloat(match[1]);\n if ((match[2] ?? \"\").toLowerCase() === \"%\") {\n const percent = Math.min(100, Math.max(0, value));\n if (percent !== value) {\n notes.push(`Divider width ${trimmed} was clamped to ${percent}%.`);\n }\n const share = Math.round((percent + Number.EPSILON) * 100) / 100;\n return share === 100 ? \"full\" : `${share}%`;\n }\n const px = Math.max(0, Math.round(value));\n if (value < 0) notes.push(`Divider width ${trimmed} was clamped to 0px.`);\n if (room === undefined || room <= 0) return px;\n return px >= room - ownLeft - ownRight ? \"full\" : px;\n}\n\nconst BORDER_STYLES = new Set([\n \"none\",\n \"hidden\",\n \"dotted\",\n \"dashed\",\n \"solid\",\n \"double\",\n \"groove\",\n \"ridge\",\n \"inset\",\n \"outset\",\n]);\n\nexport interface ParsedBorder {\n width: number;\n style: string;\n color: string;\n}\n\n/** A `border-bottom` / `border-top` shorthand. Color is empty when absent. */\nexport function parseBorderShorthand(value: string | undefined): ParsedBorder {\n const parsed: ParsedBorder = { width: 0, style: \"solid\", color: \"\" };\n if (!value) return parsed;\n for (const token of value.trim().split(/\\s+/)) {\n const lower = token.toLowerCase();\n if (BORDER_STYLES.has(lower)) {\n parsed.style = lower;\n } else if (/^-?\\d+(?:\\.\\d+)?(?:px)?$/i.test(lower)) {\n parsed.width = parsePxValue(lower);\n } else {\n const color = parseColor(lower);\n if (color) parsed.color = color;\n }\n }\n return parsed;\n}\n\nexport function visibleLineBorder(\n styles: Record<string, string>,\n): ParsedBorder | null {\n for (const key of [\"border-bottom\", \"border-top\"]) {\n if (styles[key] === undefined) continue;\n const parsed = parseBorderShorthand(styles[key]);\n if (\n parsed.width > 0 &&\n parsed.style !== \"none\" &&\n parsed.style !== \"hidden\"\n ) {\n return parsed;\n }\n }\n return null;\n}\n\n/** A background image read from the source, with a note for each value that had no exact keyword. */\nexport interface ReadBackgroundImage {\n image: BackgroundImage;\n notes: string[];\n}\n\nconst X_GRID = [\"left\", \"center\", \"right\"] as const;\nconst Y_GRID = [\"top\", \"center\", \"bottom\"] as const;\nconst PERCENT = /^(-?(?:\\d+(?:\\.\\d+)?|\\.\\d+))%$/;\nconst LENGTH = /^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)[a-z]*$/;\n\n/**\n * `background-size` as a keyword. A size with a side at 100%, or a px width\n * spanning the box, fills it as `cover` does; any other length or percentage\n * draws the image at a size of its own, which `auto` is closest to.\n */\nfunction backgroundSizeKeyword(\n raw: string,\n boxWidth: number | undefined,\n): { size: BackgroundSize; exact: boolean } {\n const parts = raw.toLowerCase().split(/\\s+/);\n const [first] = parts;\n if (parts.length === 1 && (first === \"cover\" || first === \"contain\")) {\n return { size: first, exact: true };\n }\n if (parts.every((part) => part === \"auto\")) {\n return { size: \"auto\", exact: true };\n }\n const px = /^(\\d+(?:\\.\\d+)?|\\.\\d+)px$/.exec(first);\n const fills =\n parts.includes(\"100%\") ||\n (px !== null && boxWidth !== undefined && Number(px[1]) >= boxWidth);\n return { size: fills ? \"cover\" : \"auto\", exact: false };\n}\n\n/**\n * `background-position` split into x and y the way MJML and CSS read it: a\n * lone `top` / `bottom` names y and centres x, any other lone value is x\n * with y centred, and a pair is x then y unless it leads with `top` /\n * `bottom` (or with `center` before `left` / `right`). Three- and four-value\n * edge offsets keep their edge keywords only.\n */\nfunction splitBackgroundPosition(raw: string): {\n x: string;\n y: string;\n exact: boolean;\n} {\n const parts = raw.toLowerCase().split(/\\s+/);\n if (parts.length === 1) {\n const [only] = parts;\n return only === \"top\" || only === \"bottom\"\n ? { x: \"center\", y: only, exact: true }\n : { x: only, y: \"center\", exact: true };\n }\n if (parts.length === 2) {\n const [a, b] = parts;\n const yFirst =\n a === \"top\" ||\n a === \"bottom\" ||\n (a === \"center\" && (b === \"left\" || b === \"right\"));\n return yFirst ? { x: b, y: a, exact: true } : { x: a, y: b, exact: true };\n }\n return {\n x: parts.find((part) => part === \"left\" || part === \"right\") ?? \"center\",\n y: parts.find((part) => part === \"top\" || part === \"bottom\") ?? \"center\",\n exact: false,\n };\n}\n\n/**\n * One axis as a grid point: its keyword; the point nearest a percentage,\n * ties going to the centre; or the start edge for a length, which is an\n * offset from it. `null` when the token is unreadable.\n */\nfunction backgroundAxisPoint<T extends string>(\n token: string,\n grid: readonly [T, T, T],\n): { point: T; exact: boolean } | null {\n const keyword = grid.find((point) => point === token);\n if (keyword) return { point: keyword, exact: true };\n const percent = PERCENT.exec(token);\n if (percent) {\n const n = Number(percent[1]);\n return {\n point: n < 25 ? grid[0] : n > 75 ? grid[2] : grid[1],\n exact: n === 0 || n === 50 || n === 100,\n };\n }\n if (LENGTH.test(token)) {\n return { point: grid[0], exact: parseFloat(token) === 0 };\n }\n return null;\n}\n\n/**\n * `background-repeat`: unrepeated only when every axis is `no-repeat`.\n * Anything but plain `repeat` tiles too, inexactly.\n */\nfunction backgroundRepeatFlag(raw: string): {\n repeat: boolean;\n exact: boolean;\n} {\n const parts = raw.toLowerCase().split(/\\s+/);\n if (parts.every((part) => part === \"no-repeat\")) {\n return { repeat: false, exact: true };\n }\n return { repeat: true, exact: parts.every((part) => part === \"repeat\") };\n}\n\n/** CSS's initial values: what a browser paints for a longhand the source leaves out. */\nconst CSS_BACKGROUND_DEFAULTS = {\n size: \"auto\",\n x: \"left\",\n y: \"top\",\n repeat: true,\n} as const;\n\nconst IMAGE_FUNCTION = /^(?:url|[a-z-]*gradient|image-set)\\(/;\nconst REPEAT_TOKENS = new Set([\n \"repeat\",\n \"no-repeat\",\n \"repeat-x\",\n \"repeat-y\",\n \"round\",\n \"space\",\n]);\nconst POSITION_TOKENS = new Set([\"left\", \"right\", \"top\", \"bottom\", \"center\"]);\nconst NON_COLOR_TOKENS = new Set([\n \"none\",\n \"scroll\",\n \"fixed\",\n \"local\",\n \"border-box\",\n \"padding-box\",\n \"content-box\",\n \"text\",\n \"cover\",\n \"contain\",\n \"auto\",\n]);\nconst MEASURE = /^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:%|[a-z]+)?$/i;\n\n/**\n * The URL inside the first CSS `url(…)`, unquoted and trimmed; \"\" when there\n * is none or it is malformed. A forward scan rather than a regex, so a long\n * run of unclosed `url(` can't make it backtrack.\n */\nfunction cssUrl(value: string | undefined): string {\n const text = value ?? \"\";\n const start = text.search(/url\\(/i);\n if (start === -1) return \"\";\n let i = start + 4;\n while (i < text.length && /\\s/.test(text[i])) i++;\n const quote = text[i];\n if (quote === '\"' || quote === \"'\") {\n const close = text.indexOf(quote, i + 1);\n if (close === -1) return \"\";\n let j = close + 1;\n while (j < text.length && /\\s/.test(text[j])) j++;\n return text[j] === \")\" ? text.slice(i + 1, close).trim() : \"\";\n }\n const close = text.indexOf(\")\", i);\n if (close === -1) return \"\";\n const inner = text.slice(i, close);\n return /[\"']/.test(inner) ? \"\" : inner.trim();\n}\n\n/**\n * Whitespace-separated tokens, keeping a function's arguments together and\n * making the `/` between position and size a token of its own.\n */\nfunction cssTokens(value: string): string[] {\n const tokens: string[] = [];\n let depth = 0;\n let quote = \"\";\n let current = \"\";\n const push = (): void => {\n if (current) tokens.push(current);\n current = \"\";\n };\n for (const char of value) {\n if (quote) {\n current += char;\n if (char === quote) quote = \"\";\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === \"(\") depth++;\n if (char === \")\") depth = Math.max(0, depth - 1);\n if (depth === 0 && /\\s/.test(char)) {\n push();\n continue;\n }\n if (depth === 0 && char === \"/\") {\n push();\n tokens.push(\"/\");\n continue;\n }\n current += char;\n }\n push();\n return tokens;\n}\n\nfunction isColorToken(token: string): boolean {\n const lower = token.toLowerCase();\n if (lower === \"/\" || IMAGE_FUNCTION.test(lower)) return false;\n return (\n !REPEAT_TOKENS.has(lower) &&\n !POSITION_TOKENS.has(lower) &&\n !NON_COLOR_TOKENS.has(lower) &&\n !MEASURE.test(lower)\n );\n}\n\nexport interface BackgroundShorthand {\n /** The colour token as written; \"\" when there is none. */\n color: string;\n url: string;\n size: string;\n position: string;\n repeat: string;\n layers: number;\n}\n\n/**\n * The parts of a `background` shorthand. The colour comes from the last\n * layer, the only one CSS lets carry it; the image and its size, position\n * and repeat come from the first layer with a `url()`.\n */\nexport function parseBackgroundShorthand(value: string): BackgroundShorthand {\n const layers = splitTopLevel(value, \",\")\n .map((layer) => layer.trim())\n .filter(Boolean);\n const last = cssTokens(layers[layers.length - 1] ?? \"\");\n const color = last.find(isColorToken) ?? \"\";\n const imageLayer = layers.find((layer) => cssUrl(layer) !== \"\");\n if (!imageLayer) {\n return {\n color,\n url: \"\",\n size: \"\",\n position: \"\",\n repeat: \"\",\n layers: layers.length,\n };\n }\n\n const tokens = cssTokens(imageLayer);\n const slash = tokens.indexOf(\"/\");\n const before = slash === -1 ? tokens : tokens.slice(0, slash);\n const after = slash === -1 ? [] : tokens.slice(slash + 1);\n const size: string[] = [];\n for (const token of after) {\n const lower = token.toLowerCase();\n const isSize =\n lower === \"cover\" ||\n lower === \"contain\" ||\n lower === \"auto\" ||\n MEASURE.test(lower);\n if (size.length === 2 || !isSize) break;\n size.push(token);\n }\n const rest = [...before, ...after.slice(size.length)];\n return {\n color,\n url: cssUrl(imageLayer),\n size: size.join(\" \"),\n position: before\n .filter(\n (token) =>\n POSITION_TOKENS.has(token.toLowerCase()) || MEASURE.test(token),\n )\n .join(\" \"),\n repeat: rest\n .filter((token) => REPEAT_TOKENS.has(token.toLowerCase()))\n .join(\" \"),\n layers: layers.length,\n };\n}\n\n/**\n * A background image from a URL and its longhands. A longhand left out takes\n * CSS's initial value; a value with no exact keyword takes the nearest one\n * and adds a note naming it. `null` for a blank URL.\n */\nfunction buildBackgroundImage(\n url: string,\n longhands: {\n size?: string;\n position?: string;\n positionX?: string;\n positionY?: string;\n repeat?: string;\n },\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const trimmedUrl = url.trim();\n if (!trimmedUrl) return null;\n\n const notes: string[] = [];\n const lossy = (name: string, raw: string, shown: string): void => {\n notes.push(\n `${label} ${name} \"${raw}\" has no exact Templatical equivalent; imported as \"${shown}\".`,\n );\n };\n\n let size: BackgroundSize = CSS_BACKGROUND_DEFAULTS.size;\n const rawSize = longhands.size?.trim();\n if (rawSize) {\n const parsed = backgroundSizeKeyword(rawSize, boxWidth);\n size = parsed.size;\n if (!parsed.exact) lossy(\"background-size\", rawSize, size);\n }\n\n let x: BackgroundPositionX = CSS_BACKGROUND_DEFAULTS.x;\n let y: BackgroundPositionY = CSS_BACKGROUND_DEFAULTS.y;\n let lossyX = false;\n let lossyY = false;\n const rawPosition = longhands.position?.trim();\n if (rawPosition) {\n const split = splitBackgroundPosition(rawPosition);\n const readX = backgroundAxisPoint(split.x, X_GRID);\n const readY = backgroundAxisPoint(split.y, Y_GRID);\n x = readX?.point ?? x;\n y = readY?.point ?? y;\n lossyX = !split.exact || !readX?.exact;\n lossyY = !split.exact || !readY?.exact;\n }\n // A readable `-x` / `-y` replaces its axis, and with it whatever the\n // position lost there; the position's note then names what was imported.\n const rawX = longhands.positionX?.trim();\n const overrideX = rawX\n ? backgroundAxisPoint(rawX.toLowerCase(), X_GRID)\n : null;\n if (overrideX) {\n x = overrideX.point;\n lossyX = false;\n }\n const rawY = longhands.positionY?.trim();\n const overrideY = rawY\n ? backgroundAxisPoint(rawY.toLowerCase(), Y_GRID)\n : null;\n if (overrideY) {\n y = overrideY.point;\n lossyY = false;\n }\n if (rawPosition && (lossyX || lossyY)) {\n lossy(\"background-position\", rawPosition, `${x} ${y}`);\n }\n if (rawX && !overrideX?.exact) lossy(\"background-position-x\", rawX, x);\n if (rawY && !overrideY?.exact) lossy(\"background-position-y\", rawY, y);\n\n let repeat: boolean = CSS_BACKGROUND_DEFAULTS.repeat;\n const rawRepeat = longhands.repeat?.trim();\n if (rawRepeat) {\n const parsed = backgroundRepeatFlag(rawRepeat);\n repeat = parsed.repeat;\n if (!parsed.exact) {\n lossy(\"background-repeat\", rawRepeat, repeat ? \"repeat\" : \"no-repeat\");\n }\n }\n\n return {\n image: { url: trimmedUrl, size, position: { x, y }, repeat },\n notes,\n };\n}\n\n/**\n * A background image from CSS declarations: `background-image`, else the\n * `background` shorthand's image, with the size, position and repeat\n * longhands winning over the shorthand's. A style map keeps no declaration\n * order, so a longhand is taken to follow the shorthand, as it usually does.\n * Of several layers the first image is kept, and a note says so. `null`\n * when the declarations paint no image.\n */\nexport function readCssBackground(\n styles: Record<string, string>,\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const shorthand =\n styles.background !== undefined\n ? parseBackgroundShorthand(styles.background)\n : null;\n const imageLayers =\n styles[\"background-image\"] !== undefined\n ? splitTopLevel(styles[\"background-image\"], \",\").map((layer) =>\n layer.trim(),\n )\n : null;\n const index = imageLayers\n ? imageLayers.findIndex((layer) => cssUrl(layer) !== \"\")\n : -1;\n const url = imageLayers\n ? index === -1\n ? \"\"\n : cssUrl(imageLayers[index])\n : (shorthand?.url ?? \"\");\n if (!url) return null;\n\n const layer = (value: string | undefined): string | undefined => {\n if (value === undefined) return undefined;\n const parts = splitTopLevel(value, \",\").map((part) => part.trim());\n return parts[Math.max(index, 0)] ?? parts[0];\n };\n const read = buildBackgroundImage(\n url,\n {\n size: layer(styles[\"background-size\"]) ?? shorthand?.size,\n position: layer(styles[\"background-position\"]) ?? shorthand?.position,\n positionX: styles[\"background-position-x\"],\n positionY: styles[\"background-position-y\"],\n repeat: layer(styles[\"background-repeat\"]) ?? shorthand?.repeat,\n },\n label,\n boxWidth,\n );\n const layers = imageLayers?.length ?? shorthand?.layers ?? 1;\n if (read && layers > 1) {\n read.notes.unshift(\n `${label} background has ${layers} layers; only the image \"${url}\" was imported.`,\n );\n }\n return read;\n}\n\n/**\n * The image an element paints: its inline CSS background, else its legacy\n * `background` attribute. A `background-image` or `background` declaration\n * overrides the attribute; a `background-color` doesn't. The image twin of\n * `colorFromPaint`.\n */\nexport function imageFromPaint(\n styleAttr: string | undefined,\n backgroundAttr: string | undefined,\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const styles = parseStyleAttribute(styleAttr);\n if (\n styles[\"background-image\"] !== undefined ||\n styles.background !== undefined\n ) {\n return readCssBackground(styles, label, boxWidth);\n }\n return buildBackgroundImage(backgroundAttr ?? \"\", {}, label, boxWidth);\n}\n\n/** An image an element paints, and that element, which identifies the image when it spans several sections. */\nexport interface ImageLayer {\n read: ReadBackgroundImage;\n source: object;\n}\n\n/** Every image that can reach one section. */\nexport interface SectionImageLayers {\n /** The structure (row) cell's own image. */\n structure: ImageLayer | null;\n /** The `es-*-body` image: the content area behind every structure in the stripe. */\n body: ImageLayer | null;\n /** The stripe's image: the full-width band. */\n band: ImageLayer | null;\n /** Each container's image, in column order. */\n columns: Array<ReadBackgroundImage | null>;\n /** Whether the body paints a colour, which hides the band in the content area. */\n bodyPainted: boolean;\n}\n\nexport interface SectionImage {\n image: BackgroundImage | undefined;\n notes: string[];\n /** The element the image came from when other sections can share it; `null` for a container's. */\n source: object | null;\n}\n\nfunction sameImage(a: BackgroundImage, b: BackgroundImage): boolean {\n return (\n a.url === b.url &&\n a.size === b.size &&\n a.repeat === b.repeat &&\n a.position.x === b.position.x &&\n a.position.y === b.position.y\n );\n}\n\nfunction droppedColumnsNote(columns: number[]): string {\n return columns.length === 1\n ? `The background image on column ${columns[0]} was dropped. A Templatical section has one background image.`\n : `Background images on columns ${columns.join(\", \")} were dropped. A Templatical section has one background image.`;\n}\n\n/**\n * The image a section paints, nearest first: the structure's own, then the\n * body's, then the containers', moved up when there is one or all share the\n * same image, then the stripe's while the body leaves it showing. An image\n * that showed in the section but can't be kept is named in a note. A body\n * image beneath the structure's own is covered in this section, so it isn't\n * named; it still paints the stripe's other sections. The image is a copy,\n * so sections that share a source don't share an object.\n */\nexport function resolveSectionImage(layers: SectionImageLayers): SectionImage {\n const notes: string[] = [];\n let picked: { read: ReadBackgroundImage; source: object | null } | null =\n layers.structure ?? layers.body;\n\n const withImage = layers.columns.flatMap((read, index) =>\n read ? [index + 1] : [],\n );\n const first = layers.columns[0] ?? null;\n const shared =\n first !== null &&\n layers.columns.every(\n (read) => read !== null && sameImage(read.image, first.image),\n );\n if (withImage.length > 0) {\n if (!picked && shared) picked = { read: first, source: null };\n else notes.push(droppedColumnsNote(withImage));\n }\n\n if (layers.band) {\n if (!picked && !layers.bodyPainted) {\n picked = layers.band;\n notes.push(\n \"The stripe's background image spans the full width in Stripo; the section paints it at the content width.\",\n );\n } else {\n notes.push(\n \"The stripe's background image outside the content width was dropped.\",\n );\n }\n }\n\n if (!picked) return { image: undefined, notes, source: null };\n return {\n image: {\n ...picked.read.image,\n position: { ...picked.read.image.position },\n },\n notes: [...picked.read.notes, ...notes],\n source: picked.source,\n };\n}\n\n/**\n * The paint, minus a band colour that would become the section's wrapper\n * colour, when the section has a background image. The wrapper has no\n * padding, so the colour shows nowhere except Outlook desktop, which paints\n * it over the section's image.\n */\nexport function withoutBandOverImage(\n paint: SectionPaint,\n hasImage: boolean,\n): SectionPaint {\n if (!hasImage || !paint.wrapperColor) return paint;\n return {\n backgroundColor: paint.backgroundColor,\n notes: [\n `The band colour ${paint.wrapperColor} was dropped: Outlook desktop paints a wrapper colour over the section's background image.`,\n ],\n };\n}\n","import type { Cheerio } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReportEntry } from \"@templatical/import-html\";\nimport type { Block, SectionBlock } from \"@templatical/types\";\nimport {\n imageFromPaint,\n type ImageLayer,\n type ReadBackgroundImage,\n} from \"./css\";\n\nexport interface ConvertCtx {\n entries: ImportReportEntry[];\n warnings: string[];\n /** Caller's plugin CSS. Applied inside each HTML fragment, never raw. */\n css?: string;\n /** `es-wrapper` colour, or `#ffffff` when the document has none. */\n pageBackground?: string;\n /**\n * The report entries of the sections that took each shared image, keyed by\n * the element that paints it (a body, stripe or structure cell).\n */\n imageSpans?: Map<object, ImportReportEntry[]>;\n}\n\n/** Paint after `createSectionBlock` so `styles` keeps its required padding. */\nexport function withBackground(\n section: SectionBlock,\n backgroundColor: string,\n): SectionBlock {\n if (backgroundColor) section.styles.backgroundColor = backgroundColor;\n return section;\n}\n\nexport function flattenBlocks(blocks: Block[]): Block[] {\n const out: Block[] = [];\n for (const b of blocks) {\n if (b.type === \"section\") {\n for (const col of b.children ?? []) out.push(...flattenBlocks(col));\n } else {\n out.push(b);\n }\n }\n return out;\n}\n\nfunction fragmentDocument(inner: string, css?: string): string {\n const safe = css ? css.replace(/<\\/style/gi, \"<\\\\/style\") : \"\";\n const head = safe ? `<head><style>${safe}</style></head>` : \"\";\n return `<!DOCTYPE html><html>${head}<body>${inner}</body></html>`;\n}\n\n/** The start of the HTML importer's page-image warning. */\nconst PAGE_IMAGE_WARNING = \"The email background image \";\n\n/**\n * Run the generic HTML importer on a subtree and keep its blocks.\n * Section entries belong to the row the HTML importer invented; Stripo's own\n * section entries are recorded by the caller. A fragment's `<body>` is\n * synthetic, so the page-image warning the HTML importer raises for a `body`\n * background in the caller's CSS is dropped; Stripo reports the page image\n * once, from `es-wrapper`.\n */\nexport function blocksFromHtml(inner: string, ctx: ConvertCtx): Block[] {\n const result = convertHtmlTemplate(fragmentDocument(inner, ctx.css));\n for (const entry of result.report.entries) {\n if (entry.templaticalBlockType === \"section\") continue;\n ctx.entries.push(entry);\n }\n ctx.warnings.push(\n ...result.report.warnings.filter(\n (warning) => !warning.startsWith(PAGE_IMAGE_WARNING),\n ),\n );\n return flattenBlocks(result.content.blocks);\n}\n\nexport function pushEntry(\n ctx: ConvertCtx,\n sourceTag: string,\n templaticalBlockType: string | null,\n status: ImportReportEntry[\"status\"],\n note?: string,\n): ImportReportEntry {\n const entry: ImportReportEntry = {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n ctx.entries.push(entry);\n return entry;\n}\n\n/** Record that a section's entry took the image `source` paints. */\nexport function recordImageSpan(\n ctx: ConvertCtx,\n source: object | null,\n entry: ImportReportEntry,\n): void {\n if (!source) return;\n ctx.imageSpans ??= new Map();\n const spanned = ctx.imageSpans.get(source) ?? [];\n spanned.push(entry);\n ctx.imageSpans.set(source, spanned);\n}\n\n/** Note on each entry whose section shares its image with another section. */\nexport function noteImageSpans(ctx: ConvertCtx): void {\n for (const spanned of ctx.imageSpans?.values() ?? []) {\n if (spanned.length < 2) continue;\n const note = `A background image behind ${spanned.length} sections was applied to each of them — Templatical has no multi-section band.`;\n for (const entry of spanned) {\n entry.status = \"approximated\";\n entry.note = entry.note ? `${entry.note} ${note}` : note;\n }\n }\n}\n\n/** The image an element paints: its inline CSS background, else its `background` attribute. */\nexport function imageOf(\n $el: Cheerio<Element>,\n label: string,\n boxWidth: number,\n): ReadBackgroundImage | null {\n return imageFromPaint(\n $el.attr(\"style\"),\n $el.attr(\"background\"),\n label,\n boxWidth,\n );\n}\n\n/** An element's image with that element as its source; `null` when there is no element or it paints none. */\nexport function imageLayer(\n $el: Cheerio<Element> | null,\n label: string,\n boxWidth: number,\n): ImageLayer | null {\n if (!$el) return null;\n const read = imageOf($el, label, boxWidth);\n return read ? { read, source: $el[0] } : null;\n}\n\n/**\n * The stripe's image: on the stripe, else on `$cell`, the cell Stripo paints\n * instead of a table stripe, as the band colour is read. A `td` / `th` stripe\n * is its own paint. The stripe names the image either way, since it is the\n * element that spans the sections.\n */\nexport function bandImage(\n $stripe: Cheerio<Element>,\n $cell: Cheerio<Element>,\n boxWidth: number,\n): ImageLayer | null {\n const own = imageLayer($stripe, \"Stripe\", boxWidth);\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return null;\n const cell = $cell.length > 0 ? imageOf($cell, \"Stripe\", boxWidth) : null;\n return cell ? { read: cell, source: $stripe[0] } : null;\n}\n","import type { SocialPlatform } from \"@templatical/types\";\n\nconst NAMED: Record<string, SocialPlatform> = {\n facebook: \"facebook\",\n fb: \"facebook\",\n twitter: \"twitter\",\n x: \"twitter\",\n instagram: \"instagram\",\n inst: \"instagram\",\n linkedin: \"linkedin\",\n youtube: \"youtube\",\n yt: \"youtube\",\n tiktok: \"tiktok\",\n pinterest: \"pinterest\",\n email: \"email\",\n mail: \"email\",\n whatsapp: \"whatsapp\",\n telegram: \"telegram\",\n discord: \"discord\",\n snapchat: \"snapchat\",\n reddit: \"reddit\",\n github: \"github\",\n dribbble: \"dribbble\",\n behance: \"behance\",\n};\n\nfunction peel(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/\\.(png|jpe?g|gif|svg|webp)$/i, \"\")\n .replace(/[^a-z0-9]+/g, \" \")\n .trim();\n}\n\n/**\n * Map a Stripo icon's title, alt, or src stem onto a SocialPlatform.\n * Unknown names become `website` — same floor as the MJML importer.\n */\nexport function normalizePlatform(\n name?: string,\n src?: string,\n alt?: string,\n): SocialPlatform {\n for (const candidate of [name, alt, src]) {\n if (!candidate) continue;\n const words = peel(candidate).split(/\\s+/);\n for (const w of words) {\n if (NAMED[w]) return NAMED[w];\n }\n const stem = peel(candidate.split(\"/\").pop() ?? \"\");\n for (const w of stem.split(/\\s+/)) {\n if (NAMED[w]) return NAMED[w];\n }\n }\n return \"website\";\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport {\n createButtonBlock,\n createDividerBlock,\n createMenuBlock,\n createSocialIconsBlock,\n createSpacerBlock,\n generateId,\n} from \"@templatical/types\";\nimport type {\n Block,\n DividerBlock,\n MenuItemData,\n SocialIcon,\n SpacingValue,\n} from \"@templatical/types\";\nimport { hasAnyToken, hasToken, isHidden } from \"./classes\";\nimport {\n colorFromPaint,\n parseColor,\n parsePxValue,\n parseStyleAttribute,\n readDividerWidth,\n readPadding,\n visibleLineBorder,\n type ParsedBorder,\n} from \"./css\";\nimport { blocksFromHtml, pushEntry, type ConvertCtx } from \"./fragment\";\nimport { normalizePlatform } from \"./platform\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/** Tables whose padding is the section's padding. A divider must not copy it. */\nconst STRUCTURE_TABLES = [\n \"es-header-body\",\n \"es-content-body\",\n \"es-footer-body\",\n \"es-header\",\n \"es-content\",\n \"es-footer\",\n] as const;\n\nconst MAPPED_LINE_STYLES = new Set([\n \"double\",\n \"groove\",\n \"ridge\",\n \"inset\",\n \"outset\",\n]);\n\nfunction firstAnchor($el: Cheerio<Element>): Cheerio<Element> {\n const $self = $el.is(\"a\") ? $el : $el.find(\"a\").first();\n return $self as Cheerio<Element>;\n}\n\nexport function buttonFrom(\n $el: Cheerio<Element>,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block {\n const $a = firstAnchor($el);\n const text = ($a.text() ?? \"\").trim() || \"Shop Now\";\n const url = $a.attr(\"href\") ?? \"#\";\n const target = $a.attr(\"target\");\n const own = parseStyleAttribute($a.attr(\"style\"));\n const parent = parseStyleAttribute($a.parent().attr(\"style\"));\n const backgroundColor =\n colorFromPaint($a.attr(\"style\")) ||\n colorFromPaint($a.parent().attr(\"style\"));\n const textColor = parseColor(own.color) || parseColor(parent.color);\n const borderRadius =\n parsePxValue(own[\"border-radius\"]) || parsePxValue(parent[\"border-radius\"]);\n pushEntry(ctx, sourceTag, \"button\", \"converted\");\n return createButtonBlock({\n text,\n url,\n ...(target === \"_blank\" ? { openInNewTab: true } : {}),\n ...(backgroundColor ? { backgroundColor } : {}),\n ...(textColor ? { textColor } : {}),\n ...(borderRadius > 0 ? { borderRadius } : {}),\n });\n}\n\nfunction declaresPadding($el: Cheerio<Element>): boolean {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n return (\n styles.padding !== undefined ||\n styles[\"padding-top\"] !== undefined ||\n styles[\"padding-right\"] !== undefined ||\n styles[\"padding-bottom\"] !== undefined ||\n styles[\"padding-left\"] !== undefined\n );\n}\n\n/**\n * The structure cell's padding becomes the section's padding. Reading it again\n * as the divider's own padding shortens the line twice.\n */\nfunction isStructureCell($cell: Cheerio<Element>): boolean {\n if (!$cell.is(\"td\") && !$cell.is(\"th\")) return false;\n if (hasToken($cell, \"esd-structure\")) return true;\n let $table = $cell.parent().parent();\n if ($table.is(\"tbody\") || $table.is(\"thead\") || $table.is(\"tfoot\")) {\n $table = $table.parent();\n }\n return $table.is(\"table\") && hasAnyToken($table, STRUCTURE_TABLES);\n}\n\nfunction spacerElement($root: Cheerio<Element>): Cheerio<Element> {\n if (hasToken($root, \"es-spacer\")) return $root;\n const $inner = $root.find(\"[class~='es-spacer']\").first();\n return ($inner.length ? $inner : $root) as Cheerio<Element>;\n}\n\nfunction lineBorder(\n $root: Cheerio<Element>,\n $spacer: Cheerio<Element>,\n $: CheerioAPI,\n): ParsedBorder | null {\n const own = visibleLineBorder(parseStyleAttribute($root.attr(\"style\")));\n if (own) return own;\n const onSpacer = visibleLineBorder(\n parseStyleAttribute($spacer.attr(\"style\")),\n );\n if (onSpacer) return onSpacer;\n let found: ParsedBorder | null = null;\n $spacer.find(\"td, th\").each((_, cell) => {\n if (found) return;\n found = visibleLineBorder(parseStyleAttribute($(cell).attr(\"style\")));\n });\n return found;\n}\n\nfunction dividerPadding(\n $root: Cheerio<Element>,\n $spacer: Cheerio<Element>,\n): SpacingValue {\n if (declaresPadding($root)) {\n return readPadding(parseStyleAttribute($root.attr(\"style\")));\n }\n if ($spacer[0] !== $root[0] && declaresPadding($spacer)) {\n return readPadding(parseStyleAttribute($spacer.attr(\"style\")));\n }\n const $parent = $spacer.parent();\n if (\n ($parent.is(\"td\") || $parent.is(\"th\")) &&\n !isStructureCell($parent as Cheerio<Element>)\n ) {\n return readPadding(parseStyleAttribute($parent.attr(\"style\")));\n }\n return { ...ZERO };\n}\n\n/**\n * No align and no margin is unset. A partial Stripo line with neither sits on\n * the left; the caller supplies that default.\n */\nfunction specifiedAlign(\n $el: Cheerio<Element>,\n): \"left\" | \"center\" | \"right\" | undefined {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n const alignAttr = ($el.attr(\"align\") ?? \"\").trim().toLowerCase();\n const alignKnown =\n alignAttr === \"left\" || alignAttr === \"center\" || alignAttr === \"right\";\n const hasMargin =\n styles.margin !== undefined ||\n styles[\"margin-left\"] !== undefined ||\n styles[\"margin-right\"] !== undefined;\n if (!alignKnown && !hasMargin) return undefined;\n\n let left = \"auto\";\n let right = \"auto\";\n if (alignAttr === \"left\") left = \"0\";\n if (alignAttr === \"right\") right = \"0\";\n\n const margin = (styles.margin ?? \"\").trim().split(/\\s+/).filter(Boolean);\n if (margin.length > 0) {\n right = margin[1] ?? margin[0];\n left = margin.length === 4 ? margin[3] : right;\n }\n if (styles[\"margin-left\"] !== undefined) left = styles[\"margin-left\"];\n if (styles[\"margin-right\"] !== undefined) right = styles[\"margin-right\"];\n\n const isAuto = (value: string) => value.trim().toLowerCase() === \"auto\";\n if (isAuto(left) && isAuto(right)) return \"center\";\n return isAuto(left) ? \"right\" : \"left\";\n}\n\nfunction placementOf(\n $spacer: Cheerio<Element>,\n $root: Cheerio<Element>,\n): \"left\" | \"center\" | \"right\" {\n const own = specifiedAlign($spacer);\n if (own) return own;\n for (const $candidate of [$spacer.parent(), $root.parent()]) {\n if (!$candidate.is(\"td\") && !$candidate.is(\"th\")) continue;\n const fromCell = specifiedAlign($candidate as Cheerio<Element>);\n if (fromCell) return fromCell;\n }\n return \"left\";\n}\n\nfunction spacerHeight($el: Cheerio<Element>): number {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n const fromStyle = parsePxValue(styles.height);\n if (fromStyle > 0) return fromStyle;\n const fromAttr = parsePxValue($el.attr(\"height\"));\n if (fromAttr > 0) return fromAttr;\n const pad = readPadding(styles);\n const vertical = pad.top + pad.bottom;\n return vertical > 0 ? vertical : 24;\n}\n\nfunction dividerBlock(\n border: ParsedBorder,\n padding: SpacingValue,\n width: DividerBlock[\"width\"],\n): Block {\n const lineStyle =\n border.style === \"dashed\" || border.style === \"dotted\"\n ? border.style\n : \"solid\";\n return createDividerBlock({\n lineStyle,\n color: border.color || \"#e5e7eb\",\n thickness: border.width,\n width,\n styles: { padding },\n });\n}\n\n/**\n * A bordered spacer is a divider. `room` is the column width the line can\n * span, after the section padding that column owns.\n */\nexport function spacerFrom(\n $el: Cheerio<Element>,\n sourceTag: string,\n ctx: ConvertCtx,\n $: CheerioAPI,\n room?: number,\n): Block {\n const $spacer = spacerElement($el);\n const border = lineBorder($el, $spacer, $);\n if (!border) {\n const height = spacerHeight($spacer);\n pushEntry(ctx, sourceTag, \"spacer\", \"converted\");\n return createSpacerBlock({ height });\n }\n\n const padding = dividerPadding($el, $spacer);\n const styles = parseStyleAttribute($spacer.attr(\"style\"));\n const raw = (styles.width ?? $spacer.attr(\"width\") ?? \"\").trim();\n const notes: string[] = [];\n const width = readDividerWidth(raw, room, padding.left, padding.right, notes);\n if (MAPPED_LINE_STYLES.has(border.style)) {\n notes.push(`Divider border style \"${border.style}\" was imported as solid.`);\n }\n if (width !== \"full\") {\n const align = placementOf($spacer, $el);\n if (align !== \"center\") {\n notes.push(\n `The source aligns this divider ${align}; Templatical centres every divider.`,\n );\n }\n }\n pushEntry(\n ctx,\n sourceTag,\n \"divider\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n return dividerBlock(border, padding, width);\n}\n\nfunction menuItems($table: Cheerio<Element>, $: CheerioAPI): MenuItemData[] {\n const items: MenuItemData[] = [];\n $table.find(\"td\").each((_, td) => {\n const $td = $(td) as Cheerio<Element>;\n if (isHidden($td)) return;\n const $a = $td.find(\"a\").first();\n if (!$a.length) return;\n const text = ($a.text() ?? \"\").trim();\n if (!text) return;\n items.push({\n id: generateId(),\n text,\n url: $a.attr(\"href\") ?? \"#\",\n openInNewTab: $a.attr(\"target\") === \"_blank\",\n bold: false,\n underline: false,\n });\n });\n return items;\n}\n\n/**\n * A compiled/editor `table.es-menu` / `esd-block-menu` is a MenuBlock only\n * when one row holds two or more item cells. A single 100% cell is a stacked\n * step (Password reset) and must fall through.\n */\nexport function menuFrom(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block | null {\n const $table = $el.is(\"table\") ? $el : $el.find(\"table\").first();\n const $row = $table.find(\"tr\").first();\n const itemCells = $row\n .children(\"td\")\n .toArray()\n .filter((td) => !isHidden($(td) as Cheerio<Element>));\n if (itemCells.length < 2) return null;\n const items = menuItems($table, $);\n if (items.length < 2) return null;\n pushEntry(ctx, sourceTag, \"menu\", \"converted\");\n return createMenuBlock({ items });\n}\n\nexport function socialFrom(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block {\n const icons: SocialIcon[] = [];\n $el.find(\"a\").each((_, a) => {\n const $a = $(a) as Cheerio<Element>;\n const $img = $a.find(\"img\").first();\n const url = $a.attr(\"href\") ?? \"#\";\n const platform = normalizePlatform(\n $img.attr(\"title\"),\n $img.attr(\"src\"),\n $img.attr(\"alt\"),\n );\n icons.push({ id: generateId(), platform, url });\n });\n pushEntry(ctx, sourceTag, \"social\", \"converted\");\n return createSocialIconsBlock({ icons });\n}\n\nexport function labelledInnerBlocks(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block[] {\n return blocksFromHtml($.html($el) ?? \"\", ctx);\n}\n","import { load, type Cheerio, type CheerioAPI } from \"cheerio\";\nimport type { AnyNode, Element } from \"domhandler\";\nimport { createSectionBlock } from \"@templatical/types\";\nimport type { Block, ColumnLayout, SpacingValue } from \"@templatical/types\";\nimport { hasAnyToken, hasToken, isHidden } from \"./classes\";\nimport {\n colorFromPaint,\n columnRooms,\n emailBodyWidth,\n readBoxPadding,\n resolveSectionImage,\n resolveSectionPaint,\n withoutBandOverImage,\n type ImageLayer,\n type ReadBackgroundImage,\n type SectionPaint,\n} from \"./css\";\nimport {\n bandImage,\n blocksFromHtml,\n imageLayer,\n imageOf,\n pushEntry,\n recordImageSpan,\n withBackground,\n type ConvertCtx,\n} from \"./fragment\";\nimport { buttonFrom, menuFrom, socialFrom, spacerFrom } from \"./labelled\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\nconst COLUMN_TOKENS = [\"es-left\", \"es-right\"] as const;\nconst STRIPE_TOKENS = [\"es-header\", \"es-content\", \"es-footer\"] as const;\nconst BODY_SELECTOR =\n \"[class~='es-header-body'], [class~='es-content-body'], [class~='es-footer-body']\";\n\nconst BETWEEN_NOTE = \"Content between columns was placed after them.\";\nconst SEAM_NOTE = \"This row's padding was split across more than one section.\";\n\ntype WidgetKind = \"menu\" | \"social\" | \"button\" | \"spacer\";\n\ntype Piece =\n { kind: \"flow\"; nodes: AnyNode[] } | { kind: \"column\"; el: Element };\n\nfunction paintOf($el: Cheerio<Element>): string {\n return colorFromPaint($el.attr(\"style\"), $el.attr(\"bgcolor\"));\n}\n\nfunction stripeToken($el: Cheerio<Element>): string | undefined {\n return STRIPE_TOKENS.find((token) => hasToken($el, token));\n}\n\nfunction topStripes($: CheerioAPI): Cheerio<Element>[] {\n const out: Cheerio<Element>[] = [];\n $(\"[class]\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n if (!stripeToken($el)) return;\n const nested = $el\n .parents()\n .toArray()\n .some((parent) =>\n hasAnyToken($(parent) as Cheerio<Element>, STRIPE_TOKENS),\n );\n if (nested) return;\n out.push($el);\n });\n return out;\n}\n\nfunction directRows(\n $table: Cheerio<Element>,\n $: CheerioAPI,\n): Cheerio<Element>[] {\n const $direct = $table.children(\"tr\");\n const $nested = $table.children(\"tbody, thead, tfoot\").children(\"tr\");\n const $rows = $direct.length > 0 ? $direct : $nested;\n return $rows.toArray().map((node) => $(node) as Cheerio<Element>);\n}\n\nfunction directCell($table: Cheerio<Element>): Cheerio<Element> {\n const $direct = $table.children(\"tr\").children(\"td, th\");\n const $nested = $table\n .children(\"tbody, thead, tfoot\")\n .children(\"tr\")\n .children(\"td, th\");\n return ($direct.length > 0 ? $direct : $nested).first() as Cheerio<Element>;\n}\n\n/** Paint on the stripe table, else on its cell. A `td` stripe is its own paint. */\nfunction bandColor($stripe: Cheerio<Element>): string {\n const own = paintOf($stripe);\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return \"\";\n const $cell = directCell($stripe);\n return $cell.length > 0 ? paintOf($cell) : \"\";\n}\n\n/** A column's image: on its `es-left` / `es-right` table, else on that table's cell. */\nfunction columnImage(\n $column: Cheerio<Element>,\n boxWidth: number,\n): ReadBackgroundImage | null {\n const own = imageOf($column, \"Column\", boxWidth);\n if (own) return own;\n const $cell = directCell($column);\n return $cell.length > 0 ? imageOf($cell, \"Column\", boxWidth) : null;\n}\n\ninterface StripeImages {\n body: ImageLayer | null;\n band: ImageLayer | null;\n bodyPainted: boolean;\n}\n\nfunction hasPadding(padding: SpacingValue): boolean {\n return (\n padding.top !== 0 ||\n padding.right !== 0 ||\n padding.bottom !== 0 ||\n padding.left !== 0\n );\n}\n\nfunction splitPadding(\n padding: SpacingValue,\n count: number,\n index: number,\n): SpacingValue {\n if (count <= 1) return { ...padding };\n return {\n top: index === 0 ? padding.top : 0,\n right: padding.right,\n bottom: index === count - 1 ? padding.bottom : 0,\n left: padding.left,\n };\n}\n\nfunction isColumn($el: Cheerio<Element>): boolean {\n return $el.is(\"table\") && hasAnyToken($el, COLUMN_TOKENS);\n}\n\nfunction containsColumn($el: Cheerio<Element>, $: CheerioAPI): boolean {\n const stop = $el[0];\n let found = false;\n $el.find(\"table\").each((_, node) => {\n if (found) return;\n const $n = $(node) as Cheerio<Element>;\n if (!hasAnyToken($n, COLUMN_TOKENS)) return;\n let $parent = $n.parent();\n while ($parent.length > 0 && $parent[0] !== stop) {\n if (hasAnyToken($parent as Cheerio<Element>, COLUMN_TOKENS)) return;\n $parent = $parent.parent();\n }\n found = true;\n });\n return found;\n}\n\n/**\n * Columns in one cell are one section. Flow before them, between them and\n * after them becomes its own one-column section, in that order.\n */\nfunction collectPieces($root: Cheerio<Element>, $: CheerioAPI): Piece[] {\n const pieces: Piece[] = [];\n const walk = ($parent: Cheerio<Element>) => {\n const flow: AnyNode[] = [];\n const flush = () => {\n if (flow.length === 0) return;\n pieces.push({ kind: \"flow\", nodes: flow.splice(0, flow.length) });\n };\n for (const node of $parent.contents().toArray()) {\n if (node.type === \"text\") {\n if (node.data.trim()) flow.push(node);\n continue;\n }\n if (node.type !== \"tag\") continue;\n const $el = $(node) as Cheerio<Element>;\n if (isHidden($el)) continue;\n if (isColumn($el)) {\n flush();\n pieces.push({ kind: \"column\", el: node });\n continue;\n }\n if (containsColumn($el, $)) {\n flush();\n walk($el);\n continue;\n }\n flow.push(node);\n }\n flush();\n };\n walk($root);\n return pieces;\n}\n\nfunction widgetKind($el: Cheerio<Element>): WidgetKind | null {\n if (hasToken($el, \"es-menu\")) {\n if (!$el.is(\"table\") && $el.find(\"table\").length > 0) return null;\n return \"menu\";\n }\n if (hasToken($el, \"es-social\")) return \"social\";\n if (hasToken($el, \"es-button\")) {\n if ($el.is(\"a\") || $el.find(\"a\").length > 0) return \"button\";\n return null;\n }\n if (hasToken($el, \"es-spacer\")) return \"spacer\";\n return null;\n}\n\nfunction containsWidget($el: Cheerio<Element>, $: CheerioAPI): boolean {\n let found = false;\n $el.find(\"[class]\").each((_, node) => {\n if (found) return;\n if (widgetKind($(node) as Cheerio<Element>)) found = true;\n });\n return found;\n}\n\nfunction widgetBlocks(\n $el: Cheerio<Element>,\n kind: WidgetKind,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room: number | undefined,\n): Block[] {\n if (kind === \"button\") return [buttonFrom($el, \"es-button\", ctx)];\n if (kind === \"spacer\") return [spacerFrom($el, \"es-spacer\", ctx, $, room)];\n if (kind === \"social\") return [socialFrom($el, $, \"es-social\", ctx)];\n const menu = menuFrom($el, $, \"es-menu\", ctx);\n if (menu) return [menu];\n return blocksFromHtml($.html($el) ?? \"\", ctx);\n}\n\n/** Widgets stay where they sit. A run of everything else goes through HTML import. */\nfunction convertRegion(\n nodes: AnyNode[],\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const out: Block[] = [];\n let pending = \"\";\n const flush = () => {\n if (!pending.trim()) {\n pending = \"\";\n return;\n }\n out.push(...blocksFromHtml(pending, ctx));\n pending = \"\";\n };\n const visit = (node: AnyNode) => {\n if (node.type === \"text\") {\n if (node.data.trim()) pending += node.data;\n return;\n }\n if (node.type !== \"tag\") return;\n const $el = $(node) as Cheerio<Element>;\n if ($el.is(\"head, style, script\")) return;\n if (isHidden($el)) return;\n const kind = widgetKind($el);\n if (kind) {\n flush();\n out.push(...widgetBlocks($el, kind, $, ctx, room));\n return;\n }\n if (containsWidget($el, $)) {\n for (const child of $el.contents().toArray()) visit(child);\n return;\n }\n pending += $.html(node) ?? \"\";\n };\n for (const node of nodes) visit(node);\n flush();\n return out;\n}\n\nfunction regionFromElement(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n return convertRegion($el.contents().toArray(), $, ctx, room);\n}\n\nfunction hasBlocks(children: Block[][]): boolean {\n return children.some((column) => column.length > 0);\n}\n\nfunction columnChildren(\n cols: Element[],\n $: CheerioAPI,\n ctx: ConvertCtx,\n bodyWidth: number,\n padding: SpacingValue,\n): { children: Block[][]; layout: ColumnLayout; flattenNote?: string } | null {\n const count = cols.length;\n const layout: ColumnLayout = count >= 3 ? \"3\" : count === 2 ? \"2\" : \"1\";\n const used = count >= 4 ? 3 : layout === \"1\" ? 1 : count;\n const rooms = columnRooms(\n bodyWidth,\n count >= 4 ? \"3\" : layout,\n padding,\n used,\n );\n let children: Block[][];\n if (count >= 4) {\n const rest: Block[] = [];\n for (const el of cols.slice(2)) {\n rest.push(\n ...regionFromElement($(el) as Cheerio<Element>, $, ctx, rooms[2]),\n );\n }\n children = [\n regionFromElement($(cols[0]) as Cheerio<Element>, $, ctx, rooms[0]),\n regionFromElement($(cols[1]) as Cheerio<Element>, $, ctx, rooms[1]),\n rest,\n ];\n } else {\n children = cols.map((el, index) =>\n regionFromElement($(el) as Cheerio<Element>, $, ctx, rooms[index]),\n );\n }\n if (!hasBlocks(children)) return null;\n if (count < 4) return { children, layout: count >= 3 ? \"3\" : layout };\n const flattenNote = `Row with ${count} columns was flattened; extra columns merged into the third slot. Templatical supports up to 3 columns per section.`;\n ctx.warnings.push(flattenNote);\n return { children, layout: \"3\", flattenNote };\n}\n\nfunction flowNodes(pieces: Piece[]): AnyNode[] {\n return pieces.flatMap((piece) => (piece.kind === \"flow\" ? piece.nodes : []));\n}\n\nfunction groupsFromPieces(\n pieces: Piece[],\n): Array<{ mode: \"flow\" | \"columns\"; pieces: Piece[]; extra?: string }> {\n const columns = pieces.filter((piece) => piece.kind === \"column\");\n if (columns.length === 0) {\n return pieces.length > 0 ? [{ mode: \"flow\", pieces }] : [];\n }\n let first = -1;\n let last = -1;\n pieces.forEach((piece, index) => {\n if (piece.kind !== \"column\") return;\n if (first === -1) first = index;\n last = index;\n });\n const groups: Array<{\n mode: \"flow\" | \"columns\";\n pieces: Piece[];\n extra?: string;\n }> = [];\n const leading = pieces.slice(0, first);\n if (leading.length > 0) groups.push({ mode: \"flow\", pieces: leading });\n groups.push({ mode: \"columns\", pieces: columns });\n const between = pieces\n .slice(first + 1, last)\n .filter((piece) => piece.kind === \"flow\");\n if (between.length > 0) {\n groups.push({ mode: \"flow\", pieces: between, extra: BETWEEN_NOTE });\n }\n const trailing = pieces.slice(last + 1);\n if (trailing.length > 0) groups.push({ mode: \"flow\", pieces: trailing });\n return groups;\n}\n\nfunction sectionsFromRow(\n $row: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n token: string,\n paint: SectionPaint,\n images: StripeImages,\n bodyWidth: number,\n): Block[] {\n if (isHidden($row)) return [];\n const pieces: Piece[] = [];\n let padding = { ...ZERO };\n let sawCell = false;\n let $structure: Cheerio<Element> | null = null;\n $row.children(\"td, th\").each((_, cell) => {\n const $cell = $(cell) as Cheerio<Element>;\n if (isHidden($cell)) return;\n if (!sawCell) {\n padding = readBoxPadding($cell.attr(\"class\"), $cell.attr(\"style\"));\n sawCell = true;\n $structure = $cell;\n }\n pieces.push(...collectPieces($cell, $));\n });\n if (!sawCell || pieces.length === 0) return [];\n\n const rendered: Array<{\n children: Block[][];\n layout: ColumnLayout;\n extra?: string;\n columnImages: Array<ReadBackgroundImage | null>;\n }> = [];\n for (const group of groupsFromPieces(pieces)) {\n if (group.mode === \"columns\") {\n const cols = group.pieces.flatMap((piece) =>\n piece.kind === \"column\" ? [piece.el] : [],\n );\n const built = columnChildren(cols, $, ctx, bodyWidth, padding);\n if (!built) continue;\n rendered.push({\n children: built.children,\n layout: built.layout,\n extra: built.flattenNote,\n columnImages: cols.map((el) =>\n columnImage($(el) as Cheerio<Element>, bodyWidth),\n ),\n });\n continue;\n }\n const blocks = convertRegion(\n flowNodes(group.pieces),\n $,\n ctx,\n columnRooms(bodyWidth, \"1\", padding, 1)[0],\n );\n if (blocks.length === 0) continue;\n rendered.push({\n children: [blocks],\n layout: \"1\",\n extra: group.extra,\n columnImages: [],\n });\n }\n if (rendered.length === 0) return [];\n\n const seam =\n rendered.length > 1 && hasPadding(padding) ? SEAM_NOTE : undefined;\n const structure = imageLayer($structure, \"Section\", bodyWidth);\n return rendered.map((group, index) => {\n const image = resolveSectionImage({\n structure,\n body: images.body,\n band: images.band,\n columns: group.columnImages,\n bodyPainted: images.bodyPainted,\n });\n const groupPaint = withoutBandOverImage(paint, image.image !== undefined);\n const notes = [\n ...groupPaint.notes,\n group.extra,\n ...image.notes,\n seam,\n ].filter((note): note is string => Boolean(note));\n const entry = pushEntry(\n ctx,\n token,\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n recordImageSpan(ctx, image.source, entry);\n const section = createSectionBlock({\n columns: group.layout,\n children: group.children,\n styles: { padding: splitPadding(padding, rendered.length, index) },\n ...(groupPaint.wrapperColor\n ? { wrapper: { backgroundColor: groupPaint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, groupPaint.backgroundColor);\n });\n}\n\nfunction sectionsFromStripe(\n $stripe: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block[] {\n if (isHidden($stripe)) return [];\n const token = stripeToken($stripe) ?? \"es-content\";\n const $body = $stripe.find(BODY_SELECTOR).first() as Cheerio<Element>;\n const rows = $body.length > 0 ? directRows($body, $) : directRows($stripe, $);\n const $width = $body.length > 0 ? $body : $stripe;\n const bodyWidth = emailBodyWidth($width.attr(\"width\"), $width.attr(\"style\"));\n const paint = resolveSectionPaint(\n ctx.pageBackground ?? \"#ffffff\",\n bandColor($stripe),\n $body.length > 0 ? paintOf($body) : \"\",\n );\n const images: StripeImages = {\n body: imageLayer($body, \"Section\", bodyWidth),\n band: bandImage($stripe, directCell($stripe), bodyWidth),\n bodyPainted: $body.length > 0 && paintOf($body) !== \"\",\n };\n const out: Block[] = [];\n for (const $row of rows) {\n out.push(...sectionsFromRow($row, $, ctx, token, paint, images, bodyWidth));\n }\n return out;\n}\n\nexport function convertCompiled(html: string, ctx: ConvertCtx): Block[] {\n const $ = load(html);\n const stripes = topStripes($);\n if (stripes.length === 0) {\n return convertRegion($.root().contents().toArray(), $, ctx);\n }\n const out: Block[] = [];\n for (const $stripe of stripes)\n out.push(...sectionsFromStripe($stripe, $, ctx));\n return out;\n}\n","const EDITOR_TOKENS = new Set([\n \"esd-stripe\",\n \"esd-structure\",\n \"esd-container-frame\",\n]);\n\nconst COMPILED_TOKENS = new Set([\n \"es-wrapper\",\n \"es-content-body\",\n \"es-header-body\",\n]);\n\nexport type StripoKind = \"editor\" | \"compiled\";\n\nfunction isTagNameEnd(ch: string | undefined): boolean {\n return ch === undefined || !/[A-Za-z0-9_]/.test(ch);\n}\n\n/**\n * Drop every `tag` element, including a closer with extra attributes or\n * whitespace (`</style >`, `</script foo>`). Linear `indexOf` — a regex\n * here fails `js/bad-tag-filter` or `js/polynomial-redos`, and Cheerio\n * rewrites a bare `<td>` fragment and would drop the attributes we need.\n */\nfunction withoutElements(html: string, tag: string): string {\n const open = `<${tag}`;\n const close = `</${tag}`;\n const lower = html.toLowerCase();\n let out = \"\";\n let pos = 0;\n while (pos < html.length) {\n const start = lower.indexOf(open, pos);\n if (start === -1) {\n out += html.slice(pos);\n break;\n }\n if (!isTagNameEnd(lower[start + open.length])) {\n out += html.slice(pos, start + open.length);\n pos = start + open.length;\n continue;\n }\n out += html.slice(pos, start);\n const gt = html.indexOf(\">\", start);\n if (gt === -1) break;\n const closeAt = lower.indexOf(close, gt + 1);\n if (closeAt === -1) break;\n const closeGt = html.indexOf(\">\", closeAt);\n if (closeGt === -1) break;\n out += \" \";\n pos = closeGt + 1;\n }\n return out;\n}\n\n/**\n * Class tokens from attributes only. Stylesheets and scripts are dropped\n * first so a compiled leftover `.esd-block-html table` rule cannot trip\n * editor detection.\n */\nfunction markupClassTokens(html: string): string[] {\n const stripped = withoutElements(withoutElements(html, \"style\"), \"script\");\n const tokens: string[] = [];\n const re = /\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/gi;\n let m: RegExpExecArray | null;\n while ((m = re.exec(stripped))) {\n tokens.push(...m[2].trim().split(/\\s+/).filter(Boolean));\n }\n return tokens;\n}\n\nfunction isEditorToken(token: string): boolean {\n return EDITOR_TOKENS.has(token) || token.startsWith(\"esd-block-\");\n}\n\n/**\n * Which Stripo HTML surface this is, or null if it is not Stripo markup.\n *\n * Editor-source (`getTemplateData`) carries `esd-*` on elements. Compiled\n * export carries `es-wrapper` / `es-*-body` and never `esd-*` on a class\n * attribute. A CSS-only leftover (`.esd-block-html` in a stylesheet) is not\n * a discriminator — stylesheets are stripped before the check.\n */\nexport function detectStripoKind(html: string): StripoKind | null {\n if (typeof html !== \"string\" || html.trim().length === 0) return null;\n const tokens = markupClassTokens(html);\n if (tokens.some(isEditorToken)) return \"editor\";\n if (tokens.some((t) => COMPILED_TOKENS.has(t))) return \"compiled\";\n return null;\n}\n\nexport function isStripoHtml(html: string): boolean {\n return detectStripoKind(html) !== null;\n}\n","import { load, type Cheerio, type CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport { createHtmlBlock, createSectionBlock } from \"@templatical/types\";\nimport type { Block, SpacingValue } from \"@templatical/types\";\nimport { isHidden, tokenStartingWith, topLevelWithToken } from \"./classes\";\nimport {\n colorFromPaint,\n columnRooms,\n emailBodyWidth,\n readBoxPadding,\n resolveSectionImage,\n resolveSectionPaint,\n withoutBandOverImage,\n type SectionPaint,\n} from \"./css\";\nimport {\n bandImage,\n imageLayer,\n imageOf,\n pushEntry,\n recordImageSpan,\n withBackground,\n type ConvertCtx,\n} from \"./fragment\";\nimport {\n buttonFrom,\n labelledInnerBlocks,\n menuFrom,\n socialFrom,\n spacerFrom,\n} from \"./labelled\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\nconst BODY_SELECTOR =\n \"[class~='es-header-body'], [class~='es-content-body'], [class~='es-footer-body']\";\n\nfunction columnLayout(\n count: number,\n ctx: ConvertCtx,\n): { layout: \"1\" | \"2\" | \"3\"; flattenNote?: string } {\n if (count <= 1) return { layout: \"1\" };\n if (count === 2) return { layout: \"2\" };\n if (count === 3) return { layout: \"3\" };\n const flattenNote = `Row with ${count} columns was flattened to a single column. Templatical supports up to 3 columns per section.`;\n ctx.warnings.push(flattenNote);\n return { layout: \"1\", flattenNote };\n}\n\nfunction esdBlockKind($el: Cheerio<Element>): string | undefined {\n const token = tokenStartingWith($el, \"esd-block-\");\n return token ? token.slice(\"esd-block-\".length) : undefined;\n}\n\nfunction convertEsdBlock(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const kind = esdBlockKind($el);\n if (!kind) return labelledInnerBlocks($el, $, ctx);\n if (kind === \"button\") return [buttonFrom($el, \"esd-block-button\", ctx)];\n if (kind === \"spacer\")\n return [spacerFrom($el, \"esd-block-spacer\", ctx, $, room)];\n if (kind === \"social\") return [socialFrom($el, $, \"esd-block-social\", ctx)];\n if (kind === \"menu\") {\n const menu = menuFrom($el, $, \"esd-block-menu\", ctx);\n if (menu) return [menu];\n return labelledInnerBlocks($el, $, ctx);\n }\n if (kind === \"html\") {\n pushEntry(\n ctx,\n \"esd-block-html\",\n \"html\",\n \"html-fallback\",\n \"HTML block preserved as HTML.\",\n );\n return [createHtmlBlock({ content: ($el.html() ?? \"\").trim() })];\n }\n // image / text / anything else: generic HTML mapping of the inner markup\n pushEntry(\n ctx,\n `esd-block-${kind}`,\n kind === \"image\" ? \"image\" : \"paragraph\",\n \"converted\",\n );\n return labelledInnerBlocks($el, $, ctx);\n}\n\nfunction blocksInContainer(\n $frame: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const out: Block[] = [];\n const seen = new Set<Element>();\n $frame.find(\"[class]\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n if (!tokenStartingWith($el, \"esd-block-\")) return;\n const nested = $el\n .parents()\n .toArray()\n .some((p) => tokenStartingWith($(p) as Cheerio<Element>, \"esd-block-\"));\n if (nested) return;\n if (seen.has(node)) return;\n seen.add(node);\n out.push(...convertEsdBlock($el, $, ctx, room));\n });\n if (out.length === 0) return labelledInnerBlocks($frame, $, ctx);\n return out;\n}\n\nfunction enclosing(\n $el: Cheerio<Element>,\n selector: string,\n): Cheerio<Element> | null {\n if ($el.is(selector)) return $el;\n const $parent = $el.parents(selector).first();\n return $parent.length > 0 ? ($parent as Cheerio<Element>) : null;\n}\n\n/** A table stripe's first cell, which Stripo paints instead of the table. */\nfunction bandCell($stripe: Cheerio<Element>): Cheerio<Element> {\n const $direct = $stripe.children(\"tr\").children(\"td, th\");\n const $nested = $stripe\n .children(\"tbody, thead\")\n .children(\"tr\")\n .children(\"td, th\");\n return ($direct.length > 0 ? $direct : $nested).first() as Cheerio<Element>;\n}\n\nfunction bandColor($stripe: Cheerio<Element>): string {\n const own = colorFromPaint($stripe.attr(\"style\"), $stripe.attr(\"bgcolor\"));\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return \"\";\n const $cell = bandCell($stripe);\n return $cell.length > 0\n ? colorFromPaint($cell.attr(\"style\"), $cell.attr(\"bgcolor\"))\n : \"\";\n}\n\nfunction paintFor($el: Cheerio<Element>, ctx: ConvertCtx): SectionPaint {\n const $stripe = enclosing($el, \"[class~='esd-stripe']\");\n const $body = enclosing($el, BODY_SELECTOR);\n return resolveSectionPaint(\n ctx.pageBackground ?? \"#ffffff\",\n $stripe ? bandColor($stripe) : \"\",\n $body ? colorFromPaint($body.attr(\"style\"), $body.attr(\"bgcolor\")) : \"\",\n );\n}\n\nfunction sectionFromStructure(\n $structure: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block {\n const frames = $structure\n .find(\"[class~='esd-container-frame']\")\n .toArray()\n .map((n) => $(n) as Cheerio<Element>)\n .filter(($el) => {\n if (isHidden($el)) return false;\n return (\n $el.parents(\"[class~='esd-container-frame']\").filter((_, p) => {\n return $(p).closest($structure).length > 0;\n }).length === 0\n );\n });\n\n const frameCount = frames.length;\n const { layout, flattenNote } = columnLayout(\n frameCount === 0 ? 1 : frameCount,\n ctx,\n );\n const padding = readBoxPadding(\n $structure.attr(\"class\"),\n $structure.attr(\"style\"),\n );\n const $body = enclosing($structure, BODY_SELECTOR);\n const bodyWidth = emailBodyWidth($body?.attr(\"width\"), $body?.attr(\"style\"));\n const rooms = columnRooms(\n bodyWidth,\n layout,\n padding,\n layout === \"1\" ? 1 : Math.min(frameCount, 3),\n );\n let children: Block[][];\n if (layout === \"1\") {\n const merged: Block[] = [];\n const room = rooms[0];\n if (frames.length === 0) {\n merged.push(...blocksInContainer($structure, $, ctx, room));\n } else {\n for (const $f of frames)\n merged.push(...blocksInContainer($f, $, ctx, room));\n }\n children = [merged];\n } else {\n children = frames.map(($f, index) =>\n blocksInContainer($f, $, ctx, rooms[index]),\n );\n }\n const $stripe = enclosing($structure, \"[class~='esd-stripe']\");\n const image = resolveSectionImage({\n structure: imageLayer($structure, \"Section\", bodyWidth),\n body: imageLayer($body, \"Section\", bodyWidth),\n band: $stripe ? bandImage($stripe, bandCell($stripe), bodyWidth) : null,\n columns: frames.map(($f) => imageOf($f, \"Column\", bodyWidth)),\n bodyPainted: $body\n ? colorFromPaint($body.attr(\"style\"), $body.attr(\"bgcolor\")) !== \"\"\n : false,\n });\n const paint = withoutBandOverImage(\n paintFor($structure, ctx),\n image.image !== undefined,\n );\n const notes = [...paint.notes, flattenNote, ...image.notes].filter(\n (note): note is string => Boolean(note),\n );\n if (notes.length > 0) {\n const entry = pushEntry(\n ctx,\n \"esd-structure\",\n \"section\",\n \"approximated\",\n notes.join(\" \"),\n );\n recordImageSpan(ctx, image.source, entry);\n } else if (frameCount <= 3) {\n const entry = pushEntry(ctx, \"esd-structure\", \"section\", \"converted\");\n recordImageSpan(ctx, image.source, entry);\n }\n const section = createSectionBlock({\n columns: layout,\n children,\n styles: { padding },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, paint.backgroundColor);\n}\n\nexport function convertEditor(html: string, ctx: ConvertCtx): Block[] {\n const $ = load(html);\n const structures = topLevelWithToken($, \"esd-structure\");\n if (structures.length > 0) {\n return structures.map(($s) => sectionFromStructure($s, $, ctx));\n }\n const stripes = topLevelWithToken($, \"esd-stripe\");\n if (stripes.length === 0) {\n return labelledInnerBlocks($.root() as unknown as Cheerio<Element>, $, ctx);\n }\n return stripes.map(($stripe) => {\n const inner = $stripe.find(\"[class~='esd-structure']\");\n if (inner.length > 0) {\n return sectionFromStructure(inner.first() as Cheerio<Element>, $, ctx);\n }\n const image = resolveSectionImage({\n structure: null,\n body: null,\n band: bandImage($stripe, bandCell($stripe), 600),\n columns: [],\n bodyPainted: false,\n });\n const paint = withoutBandOverImage(\n paintFor($stripe, ctx),\n image.image !== undefined,\n );\n const notes = [...paint.notes, ...image.notes].filter(\n (note): note is string => Boolean(note),\n );\n const entry = pushEntry(\n ctx,\n \"esd-stripe\",\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n recordImageSpan(ctx, image.source, entry);\n const section = createSectionBlock({\n columns: \"1\",\n children: [\n blocksInContainer($stripe, $, ctx, columnRooms(600, \"1\", ZERO, 1)[0]),\n ],\n styles: { padding: { ...ZERO } },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, paint.backgroundColor);\n });\n}\n","import { load, type CheerioAPI } from \"cheerio\";\nimport { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReport, ImportResult } from \"@templatical/import-html\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport { convertCompiled } from \"./compiled\";\nimport { colorFromPaint, imageFromPaint } from \"./css\";\nimport { detectStripoKind } from \"./detect\";\nimport { convertEditor } from \"./editor\";\nimport { noteImageSpans, type ConvertCtx } from \"./fragment\";\n\nexport interface ConvertStripoOptions {\n /** Sibling CSS from plugin `getTemplateData()`. Applied inside each HTML fragment. */\n css?: string;\n}\n\nfunction injectCss(html: string, css?: string): string {\n if (!css || css.trim().length === 0) return html;\n const $ = load(html);\n if ($(\"head\").length === 0) {\n $(\"html\").prepend(\"<head></head>\");\n }\n // Style elements serialize as HTML rawtext, so a literal `</style` in the\n // CSS would close the element and the rest would parse as markup — which\n // can flip editor/compiled detection. Neutralize the closer; then set a\n // text node rather than interpolating into an HTML string.\n const safe = css.replace(/<\\/style/gi, \"<\\\\/style\");\n const $style = $(\"<style></style>\").attr(\"data-stripo-css\", \"1\").text(safe);\n $(\"head\").append($style);\n return $.html() ?? html;\n}\n\n/** First painted `es-wrapper-color` / `es-wrapper`, or white when neither is set. */\nfunction pageBackground($: CheerioAPI): string {\n const nodes = $(\n \"[class~='es-wrapper-color'], [class~='es-wrapper']\",\n ).toArray();\n for (const node of nodes) {\n const $el = $(node);\n const color = colorFromPaint($el.attr(\"style\"), $el.attr(\"bgcolor\"));\n if (color) return color;\n }\n return \"#ffffff\";\n}\n\n/** The page's background image, which has no Templatical equivalent: the first `es-wrapper-color` / `es-wrapper` that paints one. */\nfunction pageImageWarning($: CheerioAPI): string | null {\n const nodes = $(\n \"[class~='es-wrapper-color'], [class~='es-wrapper']\",\n ).toArray();\n for (const node of nodes) {\n const $el = $(node);\n const read = imageFromPaint(\n $el.attr(\"style\"),\n $el.attr(\"background\"),\n \"Page\",\n undefined,\n );\n if (read) {\n return `The email background image \"${read.image.url}\" was dropped; Templatical has no email-level background image.`;\n }\n }\n return null;\n}\n\nfunction summarize(ctx: ConvertCtx): ImportReport {\n const summary = {\n total: ctx.entries.length,\n converted: 0,\n approximated: 0,\n htmlFallback: 0,\n skipped: 0,\n };\n for (const e of ctx.entries) {\n if (e.status === \"converted\") summary.converted++;\n else if (e.status === \"approximated\") summary.approximated++;\n else if (e.status === \"html-fallback\") summary.htmlFallback++;\n else if (e.status === \"skipped\") summary.skipped++;\n }\n return { entries: ctx.entries, warnings: ctx.warnings, summary };\n}\n\n/**\n * Convert a Stripo template to Templatical content.\n *\n * Auto-detects the surface from class attributes:\n * - `esd-*` on elements → plugin/editor `getTemplateData` HTML\n * - `es-wrapper` / `es-*-body` without `esd-*` → compiled File→HTML export\n *\n * Pass `options.css` when converting plugin storage (`getTemplateData().css`).\n */\nexport function convertStripoTemplate(\n html: string,\n options?: ConvertStripoOptions,\n): ImportResult {\n if (typeof html !== \"string\") {\n throw new Error(\n \"Invalid Stripo template: expected a string. Pass the HTML source as a string.\",\n );\n }\n if (html.trim().length === 0) {\n throw new Error(\n \"Invalid Stripo template: input is empty. Pass the HTML source of a Stripo email.\",\n );\n }\n\n const prepared = injectCss(html, options?.css);\n const kind = detectStripoKind(prepared);\n const fallback = convertHtmlTemplate(prepared);\n\n if (!kind) {\n return {\n content: fallback.content,\n report: {\n ...fallback.report,\n warnings: [\n \"No Stripo class attributes found; converted as generic HTML.\",\n ...fallback.report.warnings,\n ],\n },\n };\n }\n\n const ctx: ConvertCtx = {\n entries: [],\n warnings: [],\n css: options?.css,\n };\n const $page = load(prepared);\n const pageBg = pageBackground($page);\n const pageImage = pageImageWarning($page);\n if (pageImage) ctx.warnings.push(pageImage);\n ctx.pageBackground = pageBg;\n const blocks =\n kind === \"editor\"\n ? convertEditor(prepared, ctx)\n : convertCompiled(prepared, ctx);\n noteImageSpans(ctx);\n\n // After `fallback.content`: its settings carry the HTML importer's white\n // page, which would hide the wrapper colour.\n const defaults = createDefaultTemplateContent();\n return {\n content: {\n ...defaults,\n ...fallback.content,\n blocks,\n settings: {\n ...defaults.settings,\n ...fallback.content.settings,\n backgroundColor: pageBg,\n },\n },\n report: summarize(ctx),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["ZERO","ZERO","ZERO","BODY_SELECTOR","bandColor"],"sources":["../src/classes.ts","../src/css.ts","../src/fragment.ts","../src/platform.ts","../src/labelled.ts","../src/compiled.ts","../src/detect.ts","../src/editor.ts","../src/converter.ts"],"sourcesContent":["import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\n\nexport function classTokens($el: Cheerio<Element>): string[] {\n return ($el.attr(\"class\") ?? \"\").trim().split(/\\s+/).filter(Boolean);\n}\n\nexport function hasToken($el: Cheerio<Element>, token: string): boolean {\n return classTokens($el).includes(token);\n}\n\nexport function hasAnyToken(\n $el: Cheerio<Element>,\n tokens: readonly string[],\n): boolean {\n const set = new Set(classTokens($el));\n return tokens.some((t) => set.has(t));\n}\n\nexport function tokenStartingWith(\n $el: Cheerio<Element>,\n prefix: string,\n): string | undefined {\n return classTokens($el).find((t) => t.startsWith(prefix));\n}\n\n/** Elements carrying `token` that are not nested in another such element. */\nexport function topLevelWithToken(\n $: CheerioAPI,\n token: string,\n $root?: Cheerio<Element>,\n): Cheerio<Element>[] {\n const selector = `[class~=\"${token}\"]`;\n const $found = $root ? $root.find(selector) : $(selector);\n const out: Cheerio<Element>[] = [];\n $found.each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n const nested = $el.parents(selector);\n if ($root && $root.length) {\n const outside = nested.filter((_, p) => {\n const $p = $(p) as Cheerio<Element>;\n return $p.closest($root).length === 0 && !$p.is($root);\n });\n if (nested.length - outside.length > 0) return;\n } else if (nested.length > 0) {\n return;\n }\n out.push($el);\n });\n return out;\n}\n\nexport function isHidden($el: Cheerio<Element>): boolean {\n return hasToken($el, \"es-hidden\") || hasToken($el, \"esd-hidden\");\n}\n","/**\n * Tiny CSS readers for paint, padding and divider width.\n * Hex (3/6), a bare bgcolor hex, and rgb()/rgba() (alpha dropped).\n * \"transparent\" is unset. A present padding longhand of 0 beats the shorthand.\n */\n\nimport type {\n BackgroundImage,\n BackgroundPositionX,\n BackgroundPositionY,\n BackgroundSize,\n DividerBlock,\n SpacingValue,\n} from \"@templatical/types\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/** Column shares of the body width. The third column takes the rounding remainder. */\nconst COLUMN_SHARES = {\n \"1\": [100],\n \"2\": [50, 50],\n \"3\": [33.33, 33.33, 33.34],\n} as const;\n\nconst DIVIDER_WIDTH = /^(-?\\d+(?:\\.\\d+)?)\\s*(%|px)?$/i;\n\nconst SIDE_LETTER: Record<string, keyof SpacingValue> = {\n t: \"top\",\n r: \"right\",\n b: \"bottom\",\n l: \"left\",\n};\n\n/**\n * A `style` attribute as a key/value map. A semicolon inside quotes or\n * parentheses — `url(\"a;b\")`, `url(data:image/png;base64,…)` — belongs to\n * its value.\n */\nexport function parseStyleAttribute(\n styleAttr: string | undefined,\n): Record<string, string> {\n const result: Record<string, string> = {};\n if (!styleAttr) return result;\n for (const decl of splitTopLevel(styleAttr, \";\")) {\n const idx = decl.indexOf(\":\");\n if (idx === -1) continue;\n const key = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (key && value) result[key] = value;\n }\n return result;\n}\n\n/**\n * Split `value` at each `separator` that sits outside quotes and parentheses.\n * A value whose quote or parenthesis never closes is split at every\n * `separator` instead, so a malformed declaration costs only itself and the\n * ones after it still read.\n */\nfunction splitTopLevel(value: string, separator: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let quote = \"\";\n let start = 0;\n for (let i = 0; i < value.length; i++) {\n const char = value[i];\n if (quote) {\n if (char === quote) quote = \"\";\n continue;\n }\n if (char === '\"' || char === \"'\") quote = char;\n else if (char === \"(\") depth++;\n else if (char === \")\") depth = Math.max(0, depth - 1);\n else if (char === separator && depth === 0) {\n parts.push(value.slice(start, i));\n start = i + 1;\n }\n }\n if (quote || depth > 0) return value.split(separator);\n parts.push(value.slice(start));\n return parts;\n}\n\nfunction channelHex(value: number): string {\n const clamped = Math.max(0, Math.min(255, Math.round(value)));\n return clamped.toString(16).padStart(2, \"0\");\n}\n\nexport function parseColor(value: string | undefined): string {\n if (!value) return \"\";\n const trimmed = value.trim().toLowerCase();\n if (trimmed === \"transparent\" || trimmed === \"inherit\" || trimmed === \"none\")\n return \"\";\n const hex = trimmed.startsWith(\"#\")\n ? trimmed\n : /^[0-9a-f]{3}$|^[0-9a-f]{6}$/.test(trimmed)\n ? `#${trimmed}`\n : \"\";\n if (/^#[0-9a-f]{6}$/.test(hex)) return hex;\n if (/^#[0-9a-f]{3}$/.test(hex)) {\n return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;\n }\n const rgb = trimmed.match(\n /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/,\n );\n if (rgb) {\n return `#${channelHex(Number(rgb[1]))}${channelHex(Number(rgb[2]))}${channelHex(Number(rgb[3]))}`;\n }\n return \"\";\n}\n\nexport function parsePxValue(value: string | undefined): number {\n if (!value) return 0;\n const match = value.trim().match(/^(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s*$/);\n return match ? Math.round(parseFloat(match[1])) : 0;\n}\n\n/** Inline `background-color` / `background` wins over the `bgcolor` attribute. */\nexport function colorFromPaint(\n styleAttr: string | undefined,\n bgcolor?: string,\n): string {\n const styles = parseStyleAttribute(styleAttr);\n const fromShorthand = styles.background\n ? parseColor(styles.background.trim().split(/\\s+/)[0])\n : \"\";\n return (\n parseColor(styles[\"background-color\"]) ||\n fromShorthand ||\n parseColor(bgcolor) ||\n \"\"\n );\n}\n\nexport function parsePaddingShorthand(value: string | undefined): SpacingValue {\n if (!value) return { ...ZERO };\n const values = value\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .map((part) => parsePxValue(part));\n if (values.length === 0) return { ...ZERO };\n if (values.length === 1) {\n return {\n top: values[0],\n right: values[0],\n bottom: values[0],\n left: values[0],\n };\n }\n if (values.length === 2) {\n return {\n top: values[0],\n right: values[1],\n bottom: values[0],\n left: values[1],\n };\n }\n if (values.length === 3) {\n return {\n top: values[0],\n right: values[1],\n bottom: values[2],\n left: values[1],\n };\n }\n return {\n top: values[0],\n right: values[1],\n bottom: values[2],\n left: values[3],\n };\n}\n\n/**\n * Longhand wins when it is present, including an explicit 0.\n * A missing longhand falls back to the shorthand, then 0.\n */\nexport function readPadding(styles: Record<string, string>): SpacingValue {\n const shorthand =\n styles.padding !== undefined ? parsePaddingShorthand(styles.padding) : ZERO;\n const side = (name: keyof SpacingValue): number => {\n const key = `padding-${name}`;\n if (styles[key] !== undefined) return parsePxValue(styles[key]);\n return shorthand[name];\n };\n return {\n top: side(\"top\"),\n right: side(\"right\"),\n bottom: side(\"bottom\"),\n left: side(\"left\"),\n };\n}\n\n/** `es-p20` sets every side; `es-p10t` / `r` / `b` / `l` then override one side. */\nexport function paddingFromClasses(\n classAttr: string | undefined,\n): SpacingValue {\n const pad: SpacingValue = { ...ZERO };\n const tokens = (classAttr ?? \"\").split(/\\s+/).filter(Boolean);\n for (const token of tokens) {\n const all = /^es-p(\\d+)$/.exec(token);\n if (!all) continue;\n const n = Number(all[1]);\n pad.top = n;\n pad.right = n;\n pad.bottom = n;\n pad.left = n;\n }\n for (const token of tokens) {\n const side = /^es-p(\\d+)([trbl])$/.exec(token);\n if (!side) continue;\n pad[SIDE_LETTER[side[2]]] = Number(side[1]);\n }\n return pad;\n}\n\n/**\n * Class padding first, then inline padding per side.\n * A shorthand replaces every side; a longhand replaces only that side.\n */\nexport function readBoxPadding(\n classAttr: string | undefined,\n styleAttr: string | undefined,\n): SpacingValue {\n const base = paddingFromClasses(classAttr);\n const styles = parseStyleAttribute(styleAttr);\n const hasShorthand = styles.padding !== undefined;\n const shorthand = hasShorthand ? parsePaddingShorthand(styles.padding) : base;\n const side = (name: keyof SpacingValue): number => {\n const key = `padding-${name}`;\n if (styles[key] !== undefined) return parsePxValue(styles[key]);\n if (hasShorthand) return shorthand[name];\n return base[name];\n };\n return {\n top: side(\"top\"),\n right: side(\"right\"),\n bottom: side(\"bottom\"),\n left: side(\"left\"),\n };\n}\n\nexport interface SectionPaint {\n backgroundColor: string;\n wrapperColor?: string;\n notes: string[];\n}\n\n/**\n * Body fill paints the section. A band that is neither the page nor the body\n * becomes the section wrapper. A transparent body leaves the band on the section.\n */\nexport function resolveSectionPaint(\n pageBackground: string,\n band: string,\n body: string,\n): SectionPaint {\n const page = pageBackground || \"#ffffff\";\n if (body) {\n if (band && band !== page && band !== body) {\n return {\n backgroundColor: body,\n wrapperColor: band,\n notes: [\"The band colour was imported as a section wrapper.\"],\n };\n }\n return { backgroundColor: body, notes: [] };\n }\n return { backgroundColor: band, notes: [] };\n}\n\n/** `es-*-body` width in px, or 600 when the document does not state one. */\nexport function emailBodyWidth(\n widthAttr: string | undefined,\n styleAttr: string | undefined,\n): number {\n const raw = (widthAttr || parseStyleAttribute(styleAttr).width || \"\").trim();\n const n = parsePxValue(raw);\n return n > 0 ? n : 600;\n}\n\n/**\n * Room each column has for a line, before the line's own side padding.\n * The share is of the body width; the first column then loses the section's\n * left padding and the last loses the right. One column loses both.\n * A room that is not positive is unknown — the caller keeps the stated px.\n */\nexport function columnRooms(\n bodyWidth: number,\n layout: \"1\" | \"2\" | \"3\",\n padding: SpacingValue,\n slotCount: number,\n): Array<number | undefined> {\n const shares = COLUMN_SHARES[layout];\n const count = layout === \"1\" ? 1 : slotCount;\n const width = bodyWidth > 0 ? bodyWidth : 600;\n return Array.from({ length: count }, (_, index) => {\n const span = layout === \"1\" ? width : (width * shares[index]) / 100;\n const left = layout === \"1\" || index === 0 ? padding.left : 0;\n const right = layout === \"1\" || index === count - 1 ? padding.right : 0;\n const room = span - left - right;\n return room > 0 ? room : undefined;\n });\n}\n\n/**\n * No width, `auto` and `100%` span the column. Another percentage stays a\n * share, clamped to 0–100 and rounded to two decimals. A px width stays px\n * until it reaches `room` less the divider's own side padding.\n */\nexport function readDividerWidth(\n raw: string,\n room: number | undefined,\n ownLeft: number,\n ownRight: number,\n notes: string[],\n): DividerBlock[\"width\"] {\n const trimmed = raw.trim();\n if (\n trimmed === \"\" ||\n trimmed.toLowerCase() === \"auto\" ||\n trimmed === \"100%\"\n ) {\n return \"full\";\n }\n const match = trimmed.match(DIVIDER_WIDTH);\n if (!match) {\n notes.push(\n `Divider width \"${trimmed}\" could not be read; imported as full width.`,\n );\n return \"full\";\n }\n const value = parseFloat(match[1]);\n if ((match[2] ?? \"\").toLowerCase() === \"%\") {\n const percent = Math.min(100, Math.max(0, value));\n if (percent !== value) {\n notes.push(`Divider width ${trimmed} was clamped to ${percent}%.`);\n }\n const share = Math.round((percent + Number.EPSILON) * 100) / 100;\n return share === 100 ? \"full\" : `${share}%`;\n }\n const px = Math.max(0, Math.round(value));\n if (value < 0) notes.push(`Divider width ${trimmed} was clamped to 0px.`);\n if (room === undefined || room <= 0) return px;\n return px >= room - ownLeft - ownRight ? \"full\" : px;\n}\n\nconst BORDER_STYLES = new Set([\n \"none\",\n \"hidden\",\n \"dotted\",\n \"dashed\",\n \"solid\",\n \"double\",\n \"groove\",\n \"ridge\",\n \"inset\",\n \"outset\",\n]);\n\nexport interface ParsedBorder {\n width: number;\n style: string;\n color: string;\n}\n\n/** A `border-bottom` / `border-top` shorthand. Color is empty when absent. */\nexport function parseBorderShorthand(value: string | undefined): ParsedBorder {\n const parsed: ParsedBorder = { width: 0, style: \"solid\", color: \"\" };\n if (!value) return parsed;\n for (const token of value.trim().split(/\\s+/)) {\n const lower = token.toLowerCase();\n if (BORDER_STYLES.has(lower)) {\n parsed.style = lower;\n } else if (/^-?\\d+(?:\\.\\d+)?(?:px)?$/i.test(lower)) {\n parsed.width = parsePxValue(lower);\n } else {\n const color = parseColor(lower);\n if (color) parsed.color = color;\n }\n }\n return parsed;\n}\n\nexport function visibleLineBorder(\n styles: Record<string, string>,\n): ParsedBorder | null {\n for (const key of [\"border-bottom\", \"border-top\"]) {\n if (styles[key] === undefined) continue;\n const parsed = parseBorderShorthand(styles[key]);\n if (\n parsed.width > 0 &&\n parsed.style !== \"none\" &&\n parsed.style !== \"hidden\"\n ) {\n return parsed;\n }\n }\n return null;\n}\n\n/** A background image read from the source, with a note for each value that had no exact keyword. */\nexport interface ReadBackgroundImage {\n image: BackgroundImage;\n notes: string[];\n}\n\nconst X_GRID = [\"left\", \"center\", \"right\"] as const;\nconst Y_GRID = [\"top\", \"center\", \"bottom\"] as const;\nconst PERCENT = /^(-?(?:\\d+(?:\\.\\d+)?|\\.\\d+))%$/;\nconst LENGTH = /^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)[a-z]*$/;\n\n/**\n * `background-size` as a keyword. A size with a side at 100%, or a px width\n * spanning the box, fills it as `cover` does; any other length or percentage\n * draws the image at a size of its own, which `auto` is closest to.\n */\nfunction backgroundSizeKeyword(\n raw: string,\n boxWidth: number | undefined,\n): { size: BackgroundSize; exact: boolean } {\n const parts = raw.toLowerCase().split(/\\s+/);\n const [first] = parts;\n if (parts.length === 1 && (first === \"cover\" || first === \"contain\")) {\n return { size: first, exact: true };\n }\n if (parts.every((part) => part === \"auto\")) {\n return { size: \"auto\", exact: true };\n }\n const px = /^(\\d+(?:\\.\\d+)?|\\.\\d+)px$/.exec(first);\n const fills =\n parts.includes(\"100%\") ||\n (px !== null && boxWidth !== undefined && Number(px[1]) >= boxWidth);\n return { size: fills ? \"cover\" : \"auto\", exact: false };\n}\n\n/**\n * `background-position` split into x and y the way MJML and CSS read it: a\n * lone `top` / `bottom` names y and centres x, any other lone value is x\n * with y centred, and a pair is x then y unless it leads with `top` /\n * `bottom` (or with `center` before `left` / `right`). Three- and four-value\n * edge offsets keep their edge keywords only.\n */\nfunction splitBackgroundPosition(raw: string): {\n x: string;\n y: string;\n exact: boolean;\n} {\n const parts = raw.toLowerCase().split(/\\s+/);\n if (parts.length === 1) {\n const [only] = parts;\n return only === \"top\" || only === \"bottom\"\n ? { x: \"center\", y: only, exact: true }\n : { x: only, y: \"center\", exact: true };\n }\n if (parts.length === 2) {\n const [a, b] = parts;\n const yFirst =\n a === \"top\" ||\n a === \"bottom\" ||\n (a === \"center\" && (b === \"left\" || b === \"right\"));\n return yFirst ? { x: b, y: a, exact: true } : { x: a, y: b, exact: true };\n }\n return {\n x: parts.find((part) => part === \"left\" || part === \"right\") ?? \"center\",\n y: parts.find((part) => part === \"top\" || part === \"bottom\") ?? \"center\",\n exact: false,\n };\n}\n\n/**\n * One axis as a grid point: its keyword; the point nearest a percentage,\n * ties going to the centre; or the start edge for a length, which is an\n * offset from it. `null` when the token is unreadable.\n */\nfunction backgroundAxisPoint<T extends string>(\n token: string,\n grid: readonly [T, T, T],\n): { point: T; exact: boolean } | null {\n const keyword = grid.find((point) => point === token);\n if (keyword) return { point: keyword, exact: true };\n const percent = PERCENT.exec(token);\n if (percent) {\n const n = Number(percent[1]);\n return {\n point: n < 25 ? grid[0] : n > 75 ? grid[2] : grid[1],\n exact: n === 0 || n === 50 || n === 100,\n };\n }\n if (LENGTH.test(token)) {\n return { point: grid[0], exact: parseFloat(token) === 0 };\n }\n return null;\n}\n\n/**\n * `background-repeat`: unrepeated only when every axis is `no-repeat`.\n * Anything but plain `repeat` tiles too, inexactly.\n */\nfunction backgroundRepeatFlag(raw: string): {\n repeat: boolean;\n exact: boolean;\n} {\n const parts = raw.toLowerCase().split(/\\s+/);\n if (parts.every((part) => part === \"no-repeat\")) {\n return { repeat: false, exact: true };\n }\n return { repeat: true, exact: parts.every((part) => part === \"repeat\") };\n}\n\n/** CSS's initial values: what a browser paints for a longhand the source leaves out. */\nconst CSS_BACKGROUND_DEFAULTS = {\n size: \"auto\",\n x: \"left\",\n y: \"top\",\n repeat: true,\n} as const;\n\nconst IMAGE_FUNCTION = /^(?:url|[a-z-]*gradient|image-set)\\(/;\nconst REPEAT_TOKENS = new Set([\n \"repeat\",\n \"no-repeat\",\n \"repeat-x\",\n \"repeat-y\",\n \"round\",\n \"space\",\n]);\nconst POSITION_TOKENS = new Set([\"left\", \"right\", \"top\", \"bottom\", \"center\"]);\nconst NON_COLOR_TOKENS = new Set([\n \"none\",\n \"scroll\",\n \"fixed\",\n \"local\",\n \"border-box\",\n \"padding-box\",\n \"content-box\",\n \"text\",\n \"cover\",\n \"contain\",\n \"auto\",\n]);\nconst MEASURE = /^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:%|[a-z]+)?$/i;\n\n/**\n * The URL inside the first CSS `url(…)`, unquoted and trimmed; \"\" when there\n * is none or it is malformed. A forward scan rather than a regex, so a long\n * run of unclosed `url(` can't make it backtrack.\n */\nfunction cssUrl(value: string | undefined): string {\n const text = value ?? \"\";\n const start = text.search(/url\\(/i);\n if (start === -1) return \"\";\n let i = start + 4;\n while (i < text.length && /\\s/.test(text[i])) i++;\n const quote = text[i];\n if (quote === '\"' || quote === \"'\") {\n const close = text.indexOf(quote, i + 1);\n if (close === -1) return \"\";\n let j = close + 1;\n while (j < text.length && /\\s/.test(text[j])) j++;\n return text[j] === \")\" ? text.slice(i + 1, close).trim() : \"\";\n }\n const close = text.indexOf(\")\", i);\n if (close === -1) return \"\";\n const inner = text.slice(i, close);\n return /[\"']/.test(inner) ? \"\" : inner.trim();\n}\n\n/**\n * Whitespace-separated tokens, keeping a function's arguments together and\n * making the `/` between position and size a token of its own.\n */\nfunction cssTokens(value: string): string[] {\n const tokens: string[] = [];\n let depth = 0;\n let quote = \"\";\n let current = \"\";\n const push = (): void => {\n if (current) tokens.push(current);\n current = \"\";\n };\n for (const char of value) {\n if (quote) {\n current += char;\n if (char === quote) quote = \"\";\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === \"(\") depth++;\n if (char === \")\") depth = Math.max(0, depth - 1);\n if (depth === 0 && /\\s/.test(char)) {\n push();\n continue;\n }\n if (depth === 0 && char === \"/\") {\n push();\n tokens.push(\"/\");\n continue;\n }\n current += char;\n }\n push();\n return tokens;\n}\n\nfunction isColorToken(token: string): boolean {\n const lower = token.toLowerCase();\n if (lower === \"/\" || IMAGE_FUNCTION.test(lower)) return false;\n return (\n !REPEAT_TOKENS.has(lower) &&\n !POSITION_TOKENS.has(lower) &&\n !NON_COLOR_TOKENS.has(lower) &&\n !MEASURE.test(lower)\n );\n}\n\nexport interface BackgroundShorthand {\n /** The colour token as written; \"\" when there is none. */\n color: string;\n url: string;\n size: string;\n position: string;\n repeat: string;\n layers: number;\n}\n\n/**\n * The parts of a `background` shorthand. The colour comes from the last\n * layer, the only one CSS lets carry it; the image and its size, position\n * and repeat come from the first layer with a `url()`.\n */\nexport function parseBackgroundShorthand(value: string): BackgroundShorthand {\n const layers = splitTopLevel(value, \",\")\n .map((layer) => layer.trim())\n .filter(Boolean);\n const last = cssTokens(layers[layers.length - 1] ?? \"\");\n const color = last.find(isColorToken) ?? \"\";\n const imageLayer = layers.find((layer) => cssUrl(layer) !== \"\");\n if (!imageLayer) {\n return {\n color,\n url: \"\",\n size: \"\",\n position: \"\",\n repeat: \"\",\n layers: layers.length,\n };\n }\n\n const tokens = cssTokens(imageLayer);\n const slash = tokens.indexOf(\"/\");\n const before = slash === -1 ? tokens : tokens.slice(0, slash);\n const after = slash === -1 ? [] : tokens.slice(slash + 1);\n const size: string[] = [];\n for (const token of after) {\n const lower = token.toLowerCase();\n const isSize =\n lower === \"cover\" ||\n lower === \"contain\" ||\n lower === \"auto\" ||\n MEASURE.test(lower);\n if (size.length === 2 || !isSize) break;\n size.push(token);\n }\n const rest = [...before, ...after.slice(size.length)];\n return {\n color,\n url: cssUrl(imageLayer),\n size: size.join(\" \"),\n position: before\n .filter(\n (token) =>\n POSITION_TOKENS.has(token.toLowerCase()) || MEASURE.test(token),\n )\n .join(\" \"),\n repeat: rest\n .filter((token) => REPEAT_TOKENS.has(token.toLowerCase()))\n .join(\" \"),\n layers: layers.length,\n };\n}\n\n/**\n * A background image from a URL and its longhands. A longhand left out takes\n * CSS's initial value; a value with no exact keyword takes the nearest one\n * and adds a note naming it. `null` for a blank URL.\n */\nfunction buildBackgroundImage(\n url: string,\n longhands: {\n size?: string;\n position?: string;\n positionX?: string;\n positionY?: string;\n repeat?: string;\n },\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const trimmedUrl = url.trim();\n if (!trimmedUrl) return null;\n\n const notes: string[] = [];\n const lossy = (name: string, raw: string, shown: string): void => {\n notes.push(\n `${label} ${name} \"${raw}\" has no exact Templatical equivalent; imported as \"${shown}\".`,\n );\n };\n\n let size: BackgroundSize = CSS_BACKGROUND_DEFAULTS.size;\n const rawSize = longhands.size?.trim();\n if (rawSize) {\n const parsed = backgroundSizeKeyword(rawSize, boxWidth);\n size = parsed.size;\n if (!parsed.exact) lossy(\"background-size\", rawSize, size);\n }\n\n let x: BackgroundPositionX = CSS_BACKGROUND_DEFAULTS.x;\n let y: BackgroundPositionY = CSS_BACKGROUND_DEFAULTS.y;\n let lossyX = false;\n let lossyY = false;\n const rawPosition = longhands.position?.trim();\n if (rawPosition) {\n const split = splitBackgroundPosition(rawPosition);\n const readX = backgroundAxisPoint(split.x, X_GRID);\n const readY = backgroundAxisPoint(split.y, Y_GRID);\n x = readX?.point ?? x;\n y = readY?.point ?? y;\n lossyX = !split.exact || !readX?.exact;\n lossyY = !split.exact || !readY?.exact;\n }\n // A readable `-x` / `-y` replaces its axis, and with it whatever the\n // position lost there; the position's note then names what was imported.\n const rawX = longhands.positionX?.trim();\n const overrideX = rawX\n ? backgroundAxisPoint(rawX.toLowerCase(), X_GRID)\n : null;\n if (overrideX) {\n x = overrideX.point;\n lossyX = false;\n }\n const rawY = longhands.positionY?.trim();\n const overrideY = rawY\n ? backgroundAxisPoint(rawY.toLowerCase(), Y_GRID)\n : null;\n if (overrideY) {\n y = overrideY.point;\n lossyY = false;\n }\n if (rawPosition && (lossyX || lossyY)) {\n lossy(\"background-position\", rawPosition, `${x} ${y}`);\n }\n if (rawX && !overrideX?.exact) lossy(\"background-position-x\", rawX, x);\n if (rawY && !overrideY?.exact) lossy(\"background-position-y\", rawY, y);\n\n let repeat: boolean = CSS_BACKGROUND_DEFAULTS.repeat;\n const rawRepeat = longhands.repeat?.trim();\n if (rawRepeat) {\n const parsed = backgroundRepeatFlag(rawRepeat);\n repeat = parsed.repeat;\n if (!parsed.exact) {\n lossy(\"background-repeat\", rawRepeat, repeat ? \"repeat\" : \"no-repeat\");\n }\n }\n\n return {\n image: { url: trimmedUrl, size, position: { x, y }, repeat },\n notes,\n };\n}\n\n/**\n * A background image from CSS declarations: `background-image`, else the\n * `background` shorthand's image, with the size, position and repeat\n * longhands winning over the shorthand's. A style map keeps no declaration\n * order, so a longhand is taken to follow the shorthand, as it usually does.\n * Of several layers the first image is kept, and a note says so. `null`\n * when the declarations paint no image.\n */\nexport function readCssBackground(\n styles: Record<string, string>,\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const shorthand =\n styles.background !== undefined\n ? parseBackgroundShorthand(styles.background)\n : null;\n const imageLayers =\n styles[\"background-image\"] !== undefined\n ? splitTopLevel(styles[\"background-image\"], \",\").map((layer) =>\n layer.trim(),\n )\n : null;\n const index = imageLayers\n ? imageLayers.findIndex((layer) => cssUrl(layer) !== \"\")\n : -1;\n const url = imageLayers\n ? index === -1\n ? \"\"\n : cssUrl(imageLayers[index])\n : (shorthand?.url ?? \"\");\n if (!url) return null;\n\n const layer = (value: string | undefined): string | undefined => {\n if (value === undefined) return undefined;\n const parts = splitTopLevel(value, \",\").map((part) => part.trim());\n return parts[Math.max(index, 0)] ?? parts[0];\n };\n const read = buildBackgroundImage(\n url,\n {\n size: layer(styles[\"background-size\"]) ?? shorthand?.size,\n position: layer(styles[\"background-position\"]) ?? shorthand?.position,\n positionX: styles[\"background-position-x\"],\n positionY: styles[\"background-position-y\"],\n repeat: layer(styles[\"background-repeat\"]) ?? shorthand?.repeat,\n },\n label,\n boxWidth,\n );\n const layers = imageLayers?.length ?? shorthand?.layers ?? 1;\n if (read && layers > 1) {\n read.notes.unshift(\n `${label} background has ${layers} layers; only the image \"${url}\" was imported.`,\n );\n }\n return read;\n}\n\n/**\n * The image an element paints: its inline CSS background, else its legacy\n * `background` attribute. A `background-image` or `background` declaration\n * overrides the attribute; a `background-color` doesn't. The image twin of\n * `colorFromPaint`.\n */\nexport function imageFromPaint(\n styleAttr: string | undefined,\n backgroundAttr: string | undefined,\n label: string,\n boxWidth: number | undefined,\n): ReadBackgroundImage | null {\n const styles = parseStyleAttribute(styleAttr);\n if (\n styles[\"background-image\"] !== undefined ||\n styles.background !== undefined\n ) {\n return readCssBackground(styles, label, boxWidth);\n }\n return buildBackgroundImage(backgroundAttr ?? \"\", {}, label, boxWidth);\n}\n\n/** An image an element paints, and that element, which identifies the image when it spans several sections. */\nexport interface ImageLayer {\n read: ReadBackgroundImage;\n source: object;\n}\n\n/** Every image that can reach one section. */\nexport interface SectionImageLayers {\n /** The structure (row) cell's own image. */\n structure: ImageLayer | null;\n /** The `es-*-body` image: the content area behind every structure in the stripe. */\n body: ImageLayer | null;\n /** The stripe's image: the full-width band. */\n band: ImageLayer | null;\n /** Each container's image, in column order. */\n columns: Array<ReadBackgroundImage | null>;\n /** Whether the body paints a colour, which hides the band in the content area. */\n bodyPainted: boolean;\n}\n\nexport interface SectionImage {\n image: BackgroundImage | undefined;\n notes: string[];\n /** The element the image came from when other sections can share it; `null` for a container's. */\n source: object | null;\n}\n\nfunction sameImage(a: BackgroundImage, b: BackgroundImage): boolean {\n return (\n a.url === b.url &&\n a.size === b.size &&\n a.repeat === b.repeat &&\n a.position.x === b.position.x &&\n a.position.y === b.position.y\n );\n}\n\nfunction droppedColumnsNote(columns: number[]): string {\n return columns.length === 1\n ? `The background image on column ${columns[0]} was dropped. A Templatical section has one background image.`\n : `Background images on columns ${columns.join(\", \")} were dropped. A Templatical section has one background image.`;\n}\n\n/**\n * The image a section paints, nearest first: the structure's own, then the\n * body's, then the containers', moved up when there is one or all share the\n * same image, then the stripe's while the body leaves it showing. An image\n * that showed in the section but can't be kept is named in a note. A body\n * image beneath the structure's own is covered in this section, so it isn't\n * named; it still paints the stripe's other sections. The image is a copy,\n * so sections that share a source don't share an object.\n */\nexport function resolveSectionImage(layers: SectionImageLayers): SectionImage {\n const notes: string[] = [];\n let picked: { read: ReadBackgroundImage; source: object | null } | null =\n layers.structure ?? layers.body;\n\n const withImage = layers.columns.flatMap((read, index) =>\n read ? [index + 1] : [],\n );\n const first = layers.columns[0] ?? null;\n const shared =\n first !== null &&\n layers.columns.every(\n (read) => read !== null && sameImage(read.image, first.image),\n );\n if (withImage.length > 0) {\n if (!picked && shared) picked = { read: first, source: null };\n else notes.push(droppedColumnsNote(withImage));\n }\n\n if (layers.band) {\n if (!picked && !layers.bodyPainted) {\n picked = layers.band;\n notes.push(\n \"The stripe's background image spans the full width in Stripo; the section paints it at the content width.\",\n );\n } else {\n notes.push(\n \"The stripe's background image outside the content width was dropped.\",\n );\n }\n }\n\n if (!picked) return { image: undefined, notes, source: null };\n return {\n image: {\n ...picked.read.image,\n position: { ...picked.read.image.position },\n },\n notes: [...picked.read.notes, ...notes],\n source: picked.source,\n };\n}\n\n/**\n * The paint, minus a band colour that would become the section's wrapper\n * colour, when the section has a background image. The wrapper has no\n * padding, so the colour shows nowhere except Outlook desktop, which paints\n * it over the section's image.\n */\nexport function withoutBandOverImage(\n paint: SectionPaint,\n hasImage: boolean,\n): SectionPaint {\n if (!hasImage || !paint.wrapperColor) return paint;\n return {\n backgroundColor: paint.backgroundColor,\n notes: [\n `The band colour ${paint.wrapperColor} was dropped: Outlook desktop paints a wrapper colour over the section's background image.`,\n ],\n };\n}\n","import type { Cheerio } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReportEntry } from \"@templatical/import-html\";\nimport type { Block, SectionBlock } from \"@templatical/types\";\nimport {\n imageFromPaint,\n type ImageLayer,\n type ReadBackgroundImage,\n} from \"./css\";\n\nexport interface ConvertCtx {\n entries: ImportReportEntry[];\n warnings: string[];\n /** Caller's plugin CSS. Applied inside each HTML fragment, never raw. */\n css?: string;\n /** `es-wrapper` colour, or `#ffffff` when the document has none. */\n pageBackground?: string;\n /**\n * The report entries of the sections that took each shared image, keyed by\n * the element that paints it (a body, stripe or structure cell).\n */\n imageSpans?: Map<object, ImportReportEntry[]>;\n}\n\n/** Paint after `createSectionBlock` so `styles` keeps its required padding. */\nexport function withBackground(\n section: SectionBlock,\n backgroundColor: string,\n): SectionBlock {\n if (backgroundColor) section.styles.backgroundColor = backgroundColor;\n return section;\n}\n\nexport function flattenBlocks(blocks: Block[]): Block[] {\n const out: Block[] = [];\n for (const b of blocks) {\n if (b.type === \"section\") {\n for (const col of b.children ?? []) out.push(...flattenBlocks(col));\n } else {\n out.push(b);\n }\n }\n return out;\n}\n\nfunction fragmentDocument(inner: string, css?: string): string {\n const safe = css ? css.replace(/<\\/style/gi, \"<\\\\/style\") : \"\";\n const head = safe ? `<head><style>${safe}</style></head>` : \"\";\n return `<!DOCTYPE html><html>${head}<body>${inner}</body></html>`;\n}\n\n/** The start of the HTML importer's page-image warning. */\nconst PAGE_IMAGE_WARNING = \"The email background image \";\n\n/**\n * Run the generic HTML importer on a subtree and keep its blocks.\n * Section entries belong to the row the HTML importer invented; Stripo's own\n * section entries are recorded by the caller. A fragment's `<body>` is\n * synthetic, so the page-image warning the HTML importer raises for a `body`\n * background in the caller's CSS is dropped; Stripo reports the page image\n * once, from `es-wrapper`.\n */\nexport function blocksFromHtml(inner: string, ctx: ConvertCtx): Block[] {\n const result = convertHtmlTemplate(fragmentDocument(inner, ctx.css));\n for (const entry of result.report.entries) {\n if (entry.templaticalBlockType === \"section\") continue;\n ctx.entries.push(entry);\n }\n ctx.warnings.push(\n ...result.report.warnings.filter(\n (warning) => !warning.startsWith(PAGE_IMAGE_WARNING),\n ),\n );\n return flattenBlocks(result.content.blocks);\n}\n\nexport function pushEntry(\n ctx: ConvertCtx,\n sourceTag: string,\n templaticalBlockType: string | null,\n status: ImportReportEntry[\"status\"],\n note?: string,\n): ImportReportEntry {\n const entry: ImportReportEntry = {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n ctx.entries.push(entry);\n return entry;\n}\n\n/** Record that a section's entry took the image `source` paints. */\nexport function recordImageSpan(\n ctx: ConvertCtx,\n source: object | null,\n entry: ImportReportEntry,\n): void {\n if (!source) return;\n ctx.imageSpans ??= new Map();\n const spanned = ctx.imageSpans.get(source) ?? [];\n spanned.push(entry);\n ctx.imageSpans.set(source, spanned);\n}\n\n/** Note on each entry whose section shares its image with another section. */\nexport function noteImageSpans(ctx: ConvertCtx): void {\n for (const spanned of ctx.imageSpans?.values() ?? []) {\n if (spanned.length < 2) continue;\n const note = `A background image behind ${spanned.length} sections was applied to each of them — Templatical has no multi-section band.`;\n for (const entry of spanned) {\n entry.status = \"approximated\";\n entry.note = entry.note ? `${entry.note} ${note}` : note;\n }\n }\n}\n\n/** The image an element paints: its inline CSS background, else its `background` attribute. */\nexport function imageOf(\n $el: Cheerio<Element>,\n label: string,\n boxWidth: number,\n): ReadBackgroundImage | null {\n return imageFromPaint(\n $el.attr(\"style\"),\n $el.attr(\"background\"),\n label,\n boxWidth,\n );\n}\n\n/** An element's image with that element as its source; `null` when there is no element or it paints none. */\nexport function imageLayer(\n $el: Cheerio<Element> | null,\n label: string,\n boxWidth: number,\n): ImageLayer | null {\n if (!$el) return null;\n const read = imageOf($el, label, boxWidth);\n return read ? { read, source: $el[0] } : null;\n}\n\n/**\n * The stripe's image: on the stripe, else on `$cell`, the cell Stripo paints\n * instead of a table stripe, as the band colour is read. A `td` / `th` stripe\n * is its own paint. The stripe names the image either way, since it is the\n * element that spans the sections.\n */\nexport function bandImage(\n $stripe: Cheerio<Element>,\n $cell: Cheerio<Element>,\n boxWidth: number,\n): ImageLayer | null {\n const own = imageLayer($stripe, \"Stripe\", boxWidth);\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return null;\n const cell = $cell.length > 0 ? imageOf($cell, \"Stripe\", boxWidth) : null;\n return cell ? { read: cell, source: $stripe[0] } : null;\n}\n","import type { SocialPlatform } from \"@templatical/types\";\n\nconst NAMED: Record<string, SocialPlatform> = {\n facebook: \"facebook\",\n fb: \"facebook\",\n twitter: \"twitter\",\n x: \"twitter\",\n instagram: \"instagram\",\n inst: \"instagram\",\n linkedin: \"linkedin\",\n youtube: \"youtube\",\n yt: \"youtube\",\n tiktok: \"tiktok\",\n pinterest: \"pinterest\",\n email: \"email\",\n mail: \"email\",\n whatsapp: \"whatsapp\",\n telegram: \"telegram\",\n discord: \"discord\",\n snapchat: \"snapchat\",\n reddit: \"reddit\",\n github: \"github\",\n dribbble: \"dribbble\",\n behance: \"behance\",\n};\n\nfunction peel(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/\\.(png|jpe?g|gif|svg|webp)$/i, \"\")\n .replace(/[^a-z0-9]+/g, \" \")\n .trim();\n}\n\n/**\n * Map a Stripo icon's title, alt, or src stem onto a SocialPlatform.\n * Unknown names become `website` — same floor as the MJML importer.\n */\nexport function normalizePlatform(\n name?: string,\n src?: string,\n alt?: string,\n): SocialPlatform {\n for (const candidate of [name, alt, src]) {\n if (!candidate) continue;\n const words = peel(candidate).split(/\\s+/);\n for (const w of words) {\n if (NAMED[w]) return NAMED[w];\n }\n const stem = peel(candidate.split(\"/\").pop() ?? \"\");\n for (const w of stem.split(/\\s+/)) {\n if (NAMED[w]) return NAMED[w];\n }\n }\n return \"website\";\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport {\n createButtonBlock,\n createDividerBlock,\n createMenuBlock,\n createSocialIconsBlock,\n createSpacerBlock,\n generateId,\n} from \"@templatical/types\";\nimport type {\n Block,\n DividerBlock,\n MenuItemData,\n SocialIcon,\n SpacingValue,\n} from \"@templatical/types\";\nimport { hasAnyToken, hasToken, isHidden } from \"./classes\";\nimport {\n colorFromPaint,\n parseColor,\n parsePxValue,\n parseStyleAttribute,\n readDividerWidth,\n readPadding,\n visibleLineBorder,\n type ParsedBorder,\n} from \"./css\";\nimport { blocksFromHtml, pushEntry, type ConvertCtx } from \"./fragment\";\nimport { normalizePlatform } from \"./platform\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/** Tables whose padding is the section's padding. A divider must not copy it. */\nconst STRUCTURE_TABLES = [\n \"es-header-body\",\n \"es-content-body\",\n \"es-footer-body\",\n \"es-header\",\n \"es-content\",\n \"es-footer\",\n] as const;\n\nconst MAPPED_LINE_STYLES = new Set([\n \"double\",\n \"groove\",\n \"ridge\",\n \"inset\",\n \"outset\",\n]);\n\nfunction firstAnchor($el: Cheerio<Element>): Cheerio<Element> {\n const $self = $el.is(\"a\") ? $el : $el.find(\"a\").first();\n return $self as Cheerio<Element>;\n}\n\nexport function buttonFrom(\n $el: Cheerio<Element>,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block {\n const $a = firstAnchor($el);\n const text = ($a.text() ?? \"\").trim() || \"Shop Now\";\n const url = $a.attr(\"href\") ?? \"#\";\n const target = $a.attr(\"target\");\n const own = parseStyleAttribute($a.attr(\"style\"));\n const parent = parseStyleAttribute($a.parent().attr(\"style\"));\n const backgroundColor =\n colorFromPaint($a.attr(\"style\")) ||\n colorFromPaint($a.parent().attr(\"style\"));\n const textColor = parseColor(own.color) || parseColor(parent.color);\n const borderRadius =\n parsePxValue(own[\"border-radius\"]) || parsePxValue(parent[\"border-radius\"]);\n pushEntry(ctx, sourceTag, \"button\", \"converted\");\n return createButtonBlock({\n text,\n url,\n ...(target === \"_blank\" ? { openInNewTab: true } : {}),\n ...(backgroundColor ? { backgroundColor } : {}),\n ...(textColor ? { textColor } : {}),\n ...(borderRadius > 0 ? { borderRadius } : {}),\n });\n}\n\nfunction declaresPadding($el: Cheerio<Element>): boolean {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n return (\n styles.padding !== undefined ||\n styles[\"padding-top\"] !== undefined ||\n styles[\"padding-right\"] !== undefined ||\n styles[\"padding-bottom\"] !== undefined ||\n styles[\"padding-left\"] !== undefined\n );\n}\n\n/**\n * The structure cell's padding becomes the section's padding. Reading it again\n * as the divider's own padding shortens the line twice.\n */\nfunction isStructureCell($cell: Cheerio<Element>): boolean {\n if (!$cell.is(\"td\") && !$cell.is(\"th\")) return false;\n if (hasToken($cell, \"esd-structure\")) return true;\n let $table = $cell.parent().parent();\n if ($table.is(\"tbody\") || $table.is(\"thead\") || $table.is(\"tfoot\")) {\n $table = $table.parent();\n }\n return $table.is(\"table\") && hasAnyToken($table, STRUCTURE_TABLES);\n}\n\nfunction spacerElement($root: Cheerio<Element>): Cheerio<Element> {\n if (hasToken($root, \"es-spacer\")) return $root;\n const $inner = $root.find(\"[class~='es-spacer']\").first();\n return ($inner.length ? $inner : $root) as Cheerio<Element>;\n}\n\nfunction lineBorder(\n $root: Cheerio<Element>,\n $spacer: Cheerio<Element>,\n $: CheerioAPI,\n): ParsedBorder | null {\n const own = visibleLineBorder(parseStyleAttribute($root.attr(\"style\")));\n if (own) return own;\n const onSpacer = visibleLineBorder(\n parseStyleAttribute($spacer.attr(\"style\")),\n );\n if (onSpacer) return onSpacer;\n let found: ParsedBorder | null = null;\n $spacer.find(\"td, th\").each((_, cell) => {\n if (found) return;\n found = visibleLineBorder(parseStyleAttribute($(cell).attr(\"style\")));\n });\n return found;\n}\n\nfunction dividerPadding(\n $root: Cheerio<Element>,\n $spacer: Cheerio<Element>,\n): SpacingValue {\n if (declaresPadding($root)) {\n return readPadding(parseStyleAttribute($root.attr(\"style\")));\n }\n if ($spacer[0] !== $root[0] && declaresPadding($spacer)) {\n return readPadding(parseStyleAttribute($spacer.attr(\"style\")));\n }\n const $parent = $spacer.parent();\n if (\n ($parent.is(\"td\") || $parent.is(\"th\")) &&\n !isStructureCell($parent as Cheerio<Element>)\n ) {\n return readPadding(parseStyleAttribute($parent.attr(\"style\")));\n }\n return { ...ZERO };\n}\n\n/**\n * No align and no margin is unset. A partial Stripo line with neither sits on\n * the left; the caller supplies that default.\n */\nfunction specifiedAlign(\n $el: Cheerio<Element>,\n): \"left\" | \"center\" | \"right\" | undefined {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n const alignAttr = ($el.attr(\"align\") ?? \"\").trim().toLowerCase();\n const alignKnown =\n alignAttr === \"left\" || alignAttr === \"center\" || alignAttr === \"right\";\n const hasMargin =\n styles.margin !== undefined ||\n styles[\"margin-left\"] !== undefined ||\n styles[\"margin-right\"] !== undefined;\n if (!alignKnown && !hasMargin) return undefined;\n\n let left = \"auto\";\n let right = \"auto\";\n if (alignAttr === \"left\") left = \"0\";\n if (alignAttr === \"right\") right = \"0\";\n\n const margin = (styles.margin ?? \"\").trim().split(/\\s+/).filter(Boolean);\n if (margin.length > 0) {\n right = margin[1] ?? margin[0];\n left = margin.length === 4 ? margin[3] : right;\n }\n if (styles[\"margin-left\"] !== undefined) left = styles[\"margin-left\"];\n if (styles[\"margin-right\"] !== undefined) right = styles[\"margin-right\"];\n\n const isAuto = (value: string) => value.trim().toLowerCase() === \"auto\";\n if (isAuto(left) && isAuto(right)) return \"center\";\n return isAuto(left) ? \"right\" : \"left\";\n}\n\nfunction placementOf(\n $spacer: Cheerio<Element>,\n $root: Cheerio<Element>,\n): \"left\" | \"center\" | \"right\" {\n const own = specifiedAlign($spacer);\n if (own) return own;\n for (const $candidate of [$spacer.parent(), $root.parent()]) {\n if (!$candidate.is(\"td\") && !$candidate.is(\"th\")) continue;\n const fromCell = specifiedAlign($candidate as Cheerio<Element>);\n if (fromCell) return fromCell;\n }\n return \"left\";\n}\n\nfunction spacerHeight($el: Cheerio<Element>): number {\n const styles = parseStyleAttribute($el.attr(\"style\"));\n const fromStyle = parsePxValue(styles.height);\n if (fromStyle > 0) return fromStyle;\n const fromAttr = parsePxValue($el.attr(\"height\"));\n if (fromAttr > 0) return fromAttr;\n const pad = readPadding(styles);\n const vertical = pad.top + pad.bottom;\n return vertical > 0 ? vertical : 24;\n}\n\nfunction dividerBlock(\n border: ParsedBorder,\n padding: SpacingValue,\n width: DividerBlock[\"width\"],\n): Block {\n const lineStyle =\n border.style === \"dashed\" || border.style === \"dotted\"\n ? border.style\n : \"solid\";\n return createDividerBlock({\n lineStyle,\n color: border.color || \"#e5e7eb\",\n thickness: border.width,\n width,\n styles: { padding },\n });\n}\n\n/**\n * A bordered spacer is a divider. `room` is the column width the line can\n * span, after the section padding that column owns.\n */\nexport function spacerFrom(\n $el: Cheerio<Element>,\n sourceTag: string,\n ctx: ConvertCtx,\n $: CheerioAPI,\n room?: number,\n): Block {\n const $spacer = spacerElement($el);\n const border = lineBorder($el, $spacer, $);\n if (!border) {\n const height = spacerHeight($spacer);\n pushEntry(ctx, sourceTag, \"spacer\", \"converted\");\n return createSpacerBlock({ height });\n }\n\n const padding = dividerPadding($el, $spacer);\n const styles = parseStyleAttribute($spacer.attr(\"style\"));\n const raw = (styles.width ?? $spacer.attr(\"width\") ?? \"\").trim();\n const notes: string[] = [];\n const width = readDividerWidth(raw, room, padding.left, padding.right, notes);\n if (MAPPED_LINE_STYLES.has(border.style)) {\n notes.push(`Divider border style \"${border.style}\" was imported as solid.`);\n }\n if (width !== \"full\") {\n const align = placementOf($spacer, $el);\n if (align !== \"center\") {\n notes.push(\n `The source aligns this divider ${align}; Templatical centres every divider.`,\n );\n }\n }\n pushEntry(\n ctx,\n sourceTag,\n \"divider\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n return dividerBlock(border, padding, width);\n}\n\nfunction menuItems($table: Cheerio<Element>, $: CheerioAPI): MenuItemData[] {\n const items: MenuItemData[] = [];\n $table.find(\"td\").each((_, td) => {\n const $td = $(td) as Cheerio<Element>;\n if (isHidden($td)) return;\n const $a = $td.find(\"a\").first();\n if (!$a.length) return;\n const text = ($a.text() ?? \"\").trim();\n if (!text) return;\n items.push({\n id: generateId(),\n text,\n url: $a.attr(\"href\") ?? \"#\",\n openInNewTab: $a.attr(\"target\") === \"_blank\",\n bold: false,\n underline: false,\n });\n });\n return items;\n}\n\n/**\n * A compiled/editor `table.es-menu` / `esd-block-menu` is a MenuBlock only\n * when one row holds two or more item cells. A single 100% cell is a stacked\n * step (Password reset) and must fall through.\n */\nexport function menuFrom(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block | null {\n const $table = $el.is(\"table\") ? $el : $el.find(\"table\").first();\n const $row = $table.find(\"tr\").first();\n const itemCells = $row\n .children(\"td\")\n .toArray()\n .filter((td) => !isHidden($(td) as Cheerio<Element>));\n if (itemCells.length < 2) return null;\n const items = menuItems($table, $);\n if (items.length < 2) return null;\n pushEntry(ctx, sourceTag, \"menu\", \"converted\");\n return createMenuBlock({ items });\n}\n\nexport function socialFrom(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block {\n const icons: SocialIcon[] = [];\n $el.find(\"a\").each((_, a) => {\n const $a = $(a) as Cheerio<Element>;\n const $img = $a.find(\"img\").first();\n const url = $a.attr(\"href\") ?? \"#\";\n const platform = normalizePlatform(\n $img.attr(\"title\"),\n $img.attr(\"src\"),\n $img.attr(\"alt\"),\n );\n icons.push({ id: generateId(), platform, url });\n });\n pushEntry(ctx, sourceTag, \"social\", \"converted\");\n return createSocialIconsBlock({ icons });\n}\n\nexport function labelledInnerBlocks(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block[] {\n return blocksFromHtml($.html($el) ?? \"\", ctx);\n}\n","import { load, type Cheerio, type CheerioAPI } from \"cheerio\";\nimport type { AnyNode, Element } from \"domhandler\";\nimport { createSectionBlock } from \"@templatical/types\";\nimport type { Block, ColumnLayout, SpacingValue } from \"@templatical/types\";\nimport { hasAnyToken, hasToken, isHidden } from \"./classes\";\nimport {\n colorFromPaint,\n columnRooms,\n emailBodyWidth,\n readBoxPadding,\n resolveSectionImage,\n resolveSectionPaint,\n withoutBandOverImage,\n type ImageLayer,\n type ReadBackgroundImage,\n type SectionPaint,\n} from \"./css\";\nimport {\n bandImage,\n blocksFromHtml,\n imageLayer,\n imageOf,\n pushEntry,\n recordImageSpan,\n withBackground,\n type ConvertCtx,\n} from \"./fragment\";\nimport { buttonFrom, menuFrom, socialFrom, spacerFrom } from \"./labelled\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\nconst COLUMN_TOKENS = [\"es-left\", \"es-right\"] as const;\nconst STRIPE_TOKENS = [\"es-header\", \"es-content\", \"es-footer\"] as const;\nconst BODY_SELECTOR =\n \"[class~='es-header-body'], [class~='es-content-body'], [class~='es-footer-body']\";\n\nconst BETWEEN_NOTE = \"Content between columns was placed after them.\";\nconst SEAM_NOTE = \"This row's padding was split across more than one section.\";\n\ntype WidgetKind = \"menu\" | \"social\" | \"button\" | \"spacer\";\n\ntype Piece =\n { kind: \"flow\"; nodes: AnyNode[] } | { kind: \"column\"; el: Element };\n\nfunction paintOf($el: Cheerio<Element>): string {\n return colorFromPaint($el.attr(\"style\"), $el.attr(\"bgcolor\"));\n}\n\nfunction stripeToken($el: Cheerio<Element>): string | undefined {\n return STRIPE_TOKENS.find((token) => hasToken($el, token));\n}\n\nfunction topStripes($: CheerioAPI): Cheerio<Element>[] {\n const out: Cheerio<Element>[] = [];\n $(\"[class]\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n if (!stripeToken($el)) return;\n const nested = $el\n .parents()\n .toArray()\n .some((parent) =>\n hasAnyToken($(parent) as Cheerio<Element>, STRIPE_TOKENS),\n );\n if (nested) return;\n out.push($el);\n });\n return out;\n}\n\nfunction directRows(\n $table: Cheerio<Element>,\n $: CheerioAPI,\n): Cheerio<Element>[] {\n const $direct = $table.children(\"tr\");\n const $nested = $table.children(\"tbody, thead, tfoot\").children(\"tr\");\n const $rows = $direct.length > 0 ? $direct : $nested;\n return $rows.toArray().map((node) => $(node) as Cheerio<Element>);\n}\n\nfunction directCell($table: Cheerio<Element>): Cheerio<Element> {\n const $direct = $table.children(\"tr\").children(\"td, th\");\n const $nested = $table\n .children(\"tbody, thead, tfoot\")\n .children(\"tr\")\n .children(\"td, th\");\n return ($direct.length > 0 ? $direct : $nested).first() as Cheerio<Element>;\n}\n\n/** Paint on the stripe table, else on its cell. A `td` stripe is its own paint. */\nfunction bandColor($stripe: Cheerio<Element>): string {\n const own = paintOf($stripe);\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return \"\";\n const $cell = directCell($stripe);\n return $cell.length > 0 ? paintOf($cell) : \"\";\n}\n\n/** A column's image: on its `es-left` / `es-right` table, else on that table's cell. */\nfunction columnImage(\n $column: Cheerio<Element>,\n boxWidth: number,\n): ReadBackgroundImage | null {\n const own = imageOf($column, \"Column\", boxWidth);\n if (own) return own;\n const $cell = directCell($column);\n return $cell.length > 0 ? imageOf($cell, \"Column\", boxWidth) : null;\n}\n\ninterface StripeImages {\n body: ImageLayer | null;\n band: ImageLayer | null;\n bodyPainted: boolean;\n}\n\nfunction hasPadding(padding: SpacingValue): boolean {\n return (\n padding.top !== 0 ||\n padding.right !== 0 ||\n padding.bottom !== 0 ||\n padding.left !== 0\n );\n}\n\nfunction splitPadding(\n padding: SpacingValue,\n count: number,\n index: number,\n): SpacingValue {\n if (count <= 1) return { ...padding };\n return {\n top: index === 0 ? padding.top : 0,\n right: padding.right,\n bottom: index === count - 1 ? padding.bottom : 0,\n left: padding.left,\n };\n}\n\nfunction isColumn($el: Cheerio<Element>): boolean {\n return $el.is(\"table\") && hasAnyToken($el, COLUMN_TOKENS);\n}\n\nfunction containsColumn($el: Cheerio<Element>, $: CheerioAPI): boolean {\n const stop = $el[0];\n let found = false;\n $el.find(\"table\").each((_, node) => {\n if (found) return;\n const $n = $(node) as Cheerio<Element>;\n if (!hasAnyToken($n, COLUMN_TOKENS)) return;\n let $parent = $n.parent();\n while ($parent.length > 0 && $parent[0] !== stop) {\n if (hasAnyToken($parent as Cheerio<Element>, COLUMN_TOKENS)) return;\n $parent = $parent.parent();\n }\n found = true;\n });\n return found;\n}\n\n/**\n * Columns in one cell are one section. Flow before them, between them and\n * after them becomes its own one-column section, in that order.\n */\nfunction collectPieces($root: Cheerio<Element>, $: CheerioAPI): Piece[] {\n const pieces: Piece[] = [];\n const walk = ($parent: Cheerio<Element>) => {\n const flow: AnyNode[] = [];\n const flush = () => {\n if (flow.length === 0) return;\n pieces.push({ kind: \"flow\", nodes: flow.splice(0, flow.length) });\n };\n for (const node of $parent.contents().toArray()) {\n if (node.type === \"text\") {\n if (node.data.trim()) flow.push(node);\n continue;\n }\n if (node.type !== \"tag\") continue;\n const $el = $(node) as Cheerio<Element>;\n if (isHidden($el)) continue;\n if (isColumn($el)) {\n flush();\n pieces.push({ kind: \"column\", el: node });\n continue;\n }\n if (containsColumn($el, $)) {\n flush();\n walk($el);\n continue;\n }\n flow.push(node);\n }\n flush();\n };\n walk($root);\n return pieces;\n}\n\nfunction widgetKind($el: Cheerio<Element>): WidgetKind | null {\n if (hasToken($el, \"es-menu\")) {\n if (!$el.is(\"table\") && $el.find(\"table\").length > 0) return null;\n return \"menu\";\n }\n if (hasToken($el, \"es-social\")) return \"social\";\n if (hasToken($el, \"es-button\")) {\n if ($el.is(\"a\") || $el.find(\"a\").length > 0) return \"button\";\n return null;\n }\n if (hasToken($el, \"es-spacer\")) return \"spacer\";\n return null;\n}\n\nfunction containsWidget($el: Cheerio<Element>, $: CheerioAPI): boolean {\n let found = false;\n $el.find(\"[class]\").each((_, node) => {\n if (found) return;\n if (widgetKind($(node) as Cheerio<Element>)) found = true;\n });\n return found;\n}\n\nfunction widgetBlocks(\n $el: Cheerio<Element>,\n kind: WidgetKind,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room: number | undefined,\n): Block[] {\n if (kind === \"button\") return [buttonFrom($el, \"es-button\", ctx)];\n if (kind === \"spacer\") return [spacerFrom($el, \"es-spacer\", ctx, $, room)];\n if (kind === \"social\") return [socialFrom($el, $, \"es-social\", ctx)];\n const menu = menuFrom($el, $, \"es-menu\", ctx);\n if (menu) return [menu];\n return blocksFromHtml($.html($el) ?? \"\", ctx);\n}\n\n/** Widgets stay where they sit. A run of everything else goes through HTML import. */\nfunction convertRegion(\n nodes: AnyNode[],\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const out: Block[] = [];\n let pending = \"\";\n const flush = () => {\n if (!pending.trim()) {\n pending = \"\";\n return;\n }\n out.push(...blocksFromHtml(pending, ctx));\n pending = \"\";\n };\n const visit = (node: AnyNode) => {\n if (node.type === \"text\") {\n if (node.data.trim()) pending += node.data;\n return;\n }\n if (node.type !== \"tag\") return;\n const $el = $(node) as Cheerio<Element>;\n if ($el.is(\"head, style, script\")) return;\n if (isHidden($el)) return;\n const kind = widgetKind($el);\n if (kind) {\n flush();\n out.push(...widgetBlocks($el, kind, $, ctx, room));\n return;\n }\n if (containsWidget($el, $)) {\n for (const child of $el.contents().toArray()) visit(child);\n return;\n }\n pending += $.html(node) ?? \"\";\n };\n for (const node of nodes) visit(node);\n flush();\n return out;\n}\n\nfunction regionFromElement(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n return convertRegion($el.contents().toArray(), $, ctx, room);\n}\n\nfunction hasBlocks(children: Block[][]): boolean {\n return children.some((column) => column.length > 0);\n}\n\nfunction columnChildren(\n cols: Element[],\n $: CheerioAPI,\n ctx: ConvertCtx,\n bodyWidth: number,\n padding: SpacingValue,\n): { children: Block[][]; layout: ColumnLayout; flattenNote?: string } | null {\n const count = cols.length;\n const layout: ColumnLayout = count >= 3 ? \"3\" : count === 2 ? \"2\" : \"1\";\n const used = count >= 4 ? 3 : layout === \"1\" ? 1 : count;\n const rooms = columnRooms(\n bodyWidth,\n count >= 4 ? \"3\" : layout,\n padding,\n used,\n );\n let children: Block[][];\n if (count >= 4) {\n const rest: Block[] = [];\n for (const el of cols.slice(2)) {\n rest.push(\n ...regionFromElement($(el) as Cheerio<Element>, $, ctx, rooms[2]),\n );\n }\n children = [\n regionFromElement($(cols[0]) as Cheerio<Element>, $, ctx, rooms[0]),\n regionFromElement($(cols[1]) as Cheerio<Element>, $, ctx, rooms[1]),\n rest,\n ];\n } else {\n children = cols.map((el, index) =>\n regionFromElement($(el) as Cheerio<Element>, $, ctx, rooms[index]),\n );\n }\n if (!hasBlocks(children)) return null;\n if (count < 4) return { children, layout: count >= 3 ? \"3\" : layout };\n const flattenNote = `Row with ${count} columns was flattened; extra columns merged into the third slot. Templatical supports up to 3 columns per section.`;\n ctx.warnings.push(flattenNote);\n return { children, layout: \"3\", flattenNote };\n}\n\nfunction flowNodes(pieces: Piece[]): AnyNode[] {\n return pieces.flatMap((piece) => (piece.kind === \"flow\" ? piece.nodes : []));\n}\n\nfunction groupsFromPieces(\n pieces: Piece[],\n): Array<{ mode: \"flow\" | \"columns\"; pieces: Piece[]; extra?: string }> {\n const columns = pieces.filter((piece) => piece.kind === \"column\");\n if (columns.length === 0) {\n return pieces.length > 0 ? [{ mode: \"flow\", pieces }] : [];\n }\n let first = -1;\n let last = -1;\n pieces.forEach((piece, index) => {\n if (piece.kind !== \"column\") return;\n if (first === -1) first = index;\n last = index;\n });\n const groups: Array<{\n mode: \"flow\" | \"columns\";\n pieces: Piece[];\n extra?: string;\n }> = [];\n const leading = pieces.slice(0, first);\n if (leading.length > 0) groups.push({ mode: \"flow\", pieces: leading });\n groups.push({ mode: \"columns\", pieces: columns });\n const between = pieces\n .slice(first + 1, last)\n .filter((piece) => piece.kind === \"flow\");\n if (between.length > 0) {\n groups.push({ mode: \"flow\", pieces: between, extra: BETWEEN_NOTE });\n }\n const trailing = pieces.slice(last + 1);\n if (trailing.length > 0) groups.push({ mode: \"flow\", pieces: trailing });\n return groups;\n}\n\nfunction sectionsFromRow(\n $row: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n token: string,\n paint: SectionPaint,\n images: StripeImages,\n bodyWidth: number,\n): Block[] {\n if (isHidden($row)) return [];\n const pieces: Piece[] = [];\n let padding = { ...ZERO };\n let sawCell = false;\n let $structure: Cheerio<Element> | null = null;\n $row.children(\"td, th\").each((_, cell) => {\n const $cell = $(cell) as Cheerio<Element>;\n if (isHidden($cell)) return;\n if (!sawCell) {\n padding = readBoxPadding($cell.attr(\"class\"), $cell.attr(\"style\"));\n sawCell = true;\n $structure = $cell;\n }\n pieces.push(...collectPieces($cell, $));\n });\n if (!sawCell || pieces.length === 0) return [];\n\n const rendered: Array<{\n children: Block[][];\n layout: ColumnLayout;\n extra?: string;\n columnImages: Array<ReadBackgroundImage | null>;\n }> = [];\n for (const group of groupsFromPieces(pieces)) {\n if (group.mode === \"columns\") {\n const cols = group.pieces.flatMap((piece) =>\n piece.kind === \"column\" ? [piece.el] : [],\n );\n const built = columnChildren(cols, $, ctx, bodyWidth, padding);\n if (!built) continue;\n rendered.push({\n children: built.children,\n layout: built.layout,\n extra: built.flattenNote,\n columnImages: cols.map((el) =>\n columnImage($(el) as Cheerio<Element>, bodyWidth),\n ),\n });\n continue;\n }\n const blocks = convertRegion(\n flowNodes(group.pieces),\n $,\n ctx,\n columnRooms(bodyWidth, \"1\", padding, 1)[0],\n );\n if (blocks.length === 0) continue;\n rendered.push({\n children: [blocks],\n layout: \"1\",\n extra: group.extra,\n columnImages: [],\n });\n }\n if (rendered.length === 0) return [];\n\n const seam =\n rendered.length > 1 && hasPadding(padding) ? SEAM_NOTE : undefined;\n const structure = imageLayer($structure, \"Section\", bodyWidth);\n return rendered.map((group, index) => {\n const image = resolveSectionImage({\n structure,\n body: images.body,\n band: images.band,\n columns: group.columnImages,\n bodyPainted: images.bodyPainted,\n });\n const groupPaint = withoutBandOverImage(paint, image.image !== undefined);\n const notes = [\n ...groupPaint.notes,\n group.extra,\n ...image.notes,\n seam,\n ].filter((note): note is string => Boolean(note));\n const entry = pushEntry(\n ctx,\n token,\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n recordImageSpan(ctx, image.source, entry);\n const section = createSectionBlock({\n columns: group.layout,\n children: group.children,\n styles: { padding: splitPadding(padding, rendered.length, index) },\n ...(groupPaint.wrapperColor\n ? { wrapper: { backgroundColor: groupPaint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, groupPaint.backgroundColor);\n });\n}\n\nfunction sectionsFromStripe(\n $stripe: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block[] {\n if (isHidden($stripe)) return [];\n const token = stripeToken($stripe) ?? \"es-content\";\n const $body = $stripe.find(BODY_SELECTOR).first() as Cheerio<Element>;\n const rows = $body.length > 0 ? directRows($body, $) : directRows($stripe, $);\n const $width = $body.length > 0 ? $body : $stripe;\n const bodyWidth = emailBodyWidth($width.attr(\"width\"), $width.attr(\"style\"));\n const paint = resolveSectionPaint(\n ctx.pageBackground ?? \"#ffffff\",\n bandColor($stripe),\n $body.length > 0 ? paintOf($body) : \"\",\n );\n const images: StripeImages = {\n body: imageLayer($body, \"Section\", bodyWidth),\n band: bandImage($stripe, directCell($stripe), bodyWidth),\n bodyPainted: $body.length > 0 && paintOf($body) !== \"\",\n };\n const out: Block[] = [];\n for (const $row of rows) {\n out.push(...sectionsFromRow($row, $, ctx, token, paint, images, bodyWidth));\n }\n return out;\n}\n\nexport function convertCompiled(html: string, ctx: ConvertCtx): Block[] {\n const $ = load(html);\n const stripes = topStripes($);\n if (stripes.length === 0) {\n return convertRegion($.root().contents().toArray(), $, ctx);\n }\n const out: Block[] = [];\n for (const $stripe of stripes)\n out.push(...sectionsFromStripe($stripe, $, ctx));\n return out;\n}\n","const EDITOR_TOKENS = new Set([\n \"esd-stripe\",\n \"esd-structure\",\n \"esd-container-frame\",\n]);\n\nconst COMPILED_TOKENS = new Set([\n \"es-wrapper\",\n \"es-content-body\",\n \"es-header-body\",\n]);\n\nexport type StripoKind = \"editor\" | \"compiled\";\n\nfunction isTagNameEnd(ch: string | undefined): boolean {\n return ch === undefined || !/[A-Za-z0-9_]/.test(ch);\n}\n\n/**\n * Drop every `tag` element, including a closer with extra attributes or\n * whitespace (`</style >`, `</script foo>`). Linear `indexOf` — a regex\n * here fails `js/bad-tag-filter` or `js/polynomial-redos`, and Cheerio\n * rewrites a bare `<td>` fragment and would drop the attributes we need.\n */\nfunction withoutElements(html: string, tag: string): string {\n const open = `<${tag}`;\n const close = `</${tag}`;\n const lower = html.toLowerCase();\n let out = \"\";\n let pos = 0;\n while (pos < html.length) {\n const start = lower.indexOf(open, pos);\n if (start === -1) {\n out += html.slice(pos);\n break;\n }\n if (!isTagNameEnd(lower[start + open.length])) {\n out += html.slice(pos, start + open.length);\n pos = start + open.length;\n continue;\n }\n out += html.slice(pos, start);\n const gt = html.indexOf(\">\", start);\n if (gt === -1) break;\n const closeAt = lower.indexOf(close, gt + 1);\n if (closeAt === -1) break;\n const closeGt = html.indexOf(\">\", closeAt);\n if (closeGt === -1) break;\n out += \" \";\n pos = closeGt + 1;\n }\n return out;\n}\n\n/**\n * Class tokens from attributes only. Stylesheets and scripts are dropped\n * first so a compiled leftover `.esd-block-html table` rule cannot trip\n * editor detection.\n */\nfunction markupClassTokens(html: string): string[] {\n const stripped = withoutElements(withoutElements(html, \"style\"), \"script\");\n const tokens: string[] = [];\n const re = /\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/gi;\n let m: RegExpExecArray | null;\n while ((m = re.exec(stripped))) {\n tokens.push(...m[2].trim().split(/\\s+/).filter(Boolean));\n }\n return tokens;\n}\n\nfunction isEditorToken(token: string): boolean {\n return EDITOR_TOKENS.has(token) || token.startsWith(\"esd-block-\");\n}\n\n/**\n * Which Stripo HTML surface this is, or null if it is not Stripo markup.\n *\n * Editor-source (`getTemplateData`) carries `esd-*` on elements. Compiled\n * export carries `es-wrapper` / `es-*-body` and never `esd-*` on a class\n * attribute. A CSS-only leftover (`.esd-block-html` in a stylesheet) is not\n * a discriminator — stylesheets are stripped before the check.\n */\nexport function detectStripoKind(html: string): StripoKind | null {\n if (typeof html !== \"string\" || html.trim().length === 0) return null;\n const tokens = markupClassTokens(html);\n if (tokens.some(isEditorToken)) return \"editor\";\n if (tokens.some((t) => COMPILED_TOKENS.has(t))) return \"compiled\";\n return null;\n}\n\nexport function isStripoHtml(html: string): boolean {\n return detectStripoKind(html) !== null;\n}\n","import { load, type Cheerio, type CheerioAPI } from \"cheerio\";\nimport type { Element } from \"domhandler\";\nimport { createHtmlBlock, createSectionBlock } from \"@templatical/types\";\nimport type { Block, SpacingValue } from \"@templatical/types\";\nimport { isHidden, tokenStartingWith, topLevelWithToken } from \"./classes\";\nimport {\n colorFromPaint,\n columnRooms,\n emailBodyWidth,\n readBoxPadding,\n resolveSectionImage,\n resolveSectionPaint,\n withoutBandOverImage,\n type SectionPaint,\n} from \"./css\";\nimport {\n bandImage,\n imageLayer,\n imageOf,\n pushEntry,\n recordImageSpan,\n withBackground,\n type ConvertCtx,\n} from \"./fragment\";\nimport {\n buttonFrom,\n labelledInnerBlocks,\n menuFrom,\n socialFrom,\n spacerFrom,\n} from \"./labelled\";\n\nconst ZERO: SpacingValue = { top: 0, right: 0, bottom: 0, left: 0 };\nconst BODY_SELECTOR =\n \"[class~='es-header-body'], [class~='es-content-body'], [class~='es-footer-body']\";\n\nfunction columnLayout(\n count: number,\n ctx: ConvertCtx,\n): { layout: \"1\" | \"2\" | \"3\"; flattenNote?: string } {\n if (count <= 1) return { layout: \"1\" };\n if (count === 2) return { layout: \"2\" };\n if (count === 3) return { layout: \"3\" };\n const flattenNote = `Row with ${count} columns was flattened to a single column. Templatical supports up to 3 columns per section.`;\n ctx.warnings.push(flattenNote);\n return { layout: \"1\", flattenNote };\n}\n\nfunction esdBlockKind($el: Cheerio<Element>): string | undefined {\n const token = tokenStartingWith($el, \"esd-block-\");\n return token ? token.slice(\"esd-block-\".length) : undefined;\n}\n\nfunction convertEsdBlock(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const kind = esdBlockKind($el);\n if (!kind) return labelledInnerBlocks($el, $, ctx);\n if (kind === \"button\") return [buttonFrom($el, \"esd-block-button\", ctx)];\n if (kind === \"spacer\")\n return [spacerFrom($el, \"esd-block-spacer\", ctx, $, room)];\n if (kind === \"social\") return [socialFrom($el, $, \"esd-block-social\", ctx)];\n if (kind === \"menu\") {\n const menu = menuFrom($el, $, \"esd-block-menu\", ctx);\n if (menu) return [menu];\n return labelledInnerBlocks($el, $, ctx);\n }\n if (kind === \"html\") {\n pushEntry(\n ctx,\n \"esd-block-html\",\n \"html\",\n \"html-fallback\",\n \"HTML block preserved as HTML.\",\n );\n return [createHtmlBlock({ content: ($el.html() ?? \"\").trim() })];\n }\n // image / text / anything else: generic HTML mapping of the inner markup\n pushEntry(\n ctx,\n `esd-block-${kind}`,\n kind === \"image\" ? \"image\" : \"paragraph\",\n \"converted\",\n );\n return labelledInnerBlocks($el, $, ctx);\n}\n\nfunction blocksInContainer(\n $frame: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n room?: number,\n): Block[] {\n const out: Block[] = [];\n const seen = new Set<Element>();\n $frame.find(\"[class]\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n if (!tokenStartingWith($el, \"esd-block-\")) return;\n const nested = $el\n .parents()\n .toArray()\n .some((p) => tokenStartingWith($(p) as Cheerio<Element>, \"esd-block-\"));\n if (nested) return;\n if (seen.has(node)) return;\n seen.add(node);\n out.push(...convertEsdBlock($el, $, ctx, room));\n });\n if (out.length === 0) return labelledInnerBlocks($frame, $, ctx);\n return out;\n}\n\nfunction enclosing(\n $el: Cheerio<Element>,\n selector: string,\n): Cheerio<Element> | null {\n if ($el.is(selector)) return $el;\n const $parent = $el.parents(selector).first();\n return $parent.length > 0 ? ($parent as Cheerio<Element>) : null;\n}\n\n/** A table stripe's first cell, which Stripo paints instead of the table. */\nfunction bandCell($stripe: Cheerio<Element>): Cheerio<Element> {\n const $direct = $stripe.children(\"tr\").children(\"td, th\");\n const $nested = $stripe\n .children(\"tbody, thead\")\n .children(\"tr\")\n .children(\"td, th\");\n return ($direct.length > 0 ? $direct : $nested).first() as Cheerio<Element>;\n}\n\nfunction bandColor($stripe: Cheerio<Element>): string {\n const own = colorFromPaint($stripe.attr(\"style\"), $stripe.attr(\"bgcolor\"));\n if (own) return own;\n if ($stripe.is(\"td\") || $stripe.is(\"th\")) return \"\";\n const $cell = bandCell($stripe);\n return $cell.length > 0\n ? colorFromPaint($cell.attr(\"style\"), $cell.attr(\"bgcolor\"))\n : \"\";\n}\n\nfunction paintFor($el: Cheerio<Element>, ctx: ConvertCtx): SectionPaint {\n const $stripe = enclosing($el, \"[class~='esd-stripe']\");\n const $body = enclosing($el, BODY_SELECTOR);\n return resolveSectionPaint(\n ctx.pageBackground ?? \"#ffffff\",\n $stripe ? bandColor($stripe) : \"\",\n $body ? colorFromPaint($body.attr(\"style\"), $body.attr(\"bgcolor\")) : \"\",\n );\n}\n\nfunction sectionFromStructure(\n $structure: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block {\n const frames = $structure\n .find(\"[class~='esd-container-frame']\")\n .toArray()\n .map((n) => $(n) as Cheerio<Element>)\n .filter(($el) => {\n if (isHidden($el)) return false;\n return (\n $el.parents(\"[class~='esd-container-frame']\").filter((_, p) => {\n return $(p).closest($structure).length > 0;\n }).length === 0\n );\n });\n\n const frameCount = frames.length;\n const { layout, flattenNote } = columnLayout(\n frameCount === 0 ? 1 : frameCount,\n ctx,\n );\n const padding = readBoxPadding(\n $structure.attr(\"class\"),\n $structure.attr(\"style\"),\n );\n const $body = enclosing($structure, BODY_SELECTOR);\n const bodyWidth = emailBodyWidth($body?.attr(\"width\"), $body?.attr(\"style\"));\n const rooms = columnRooms(\n bodyWidth,\n layout,\n padding,\n layout === \"1\" ? 1 : Math.min(frameCount, 3),\n );\n let children: Block[][];\n if (layout === \"1\") {\n const merged: Block[] = [];\n const room = rooms[0];\n if (frames.length === 0) {\n merged.push(...blocksInContainer($structure, $, ctx, room));\n } else {\n for (const $f of frames)\n merged.push(...blocksInContainer($f, $, ctx, room));\n }\n children = [merged];\n } else {\n children = frames.map(($f, index) =>\n blocksInContainer($f, $, ctx, rooms[index]),\n );\n }\n const $stripe = enclosing($structure, \"[class~='esd-stripe']\");\n const image = resolveSectionImage({\n structure: imageLayer($structure, \"Section\", bodyWidth),\n body: imageLayer($body, \"Section\", bodyWidth),\n band: $stripe ? bandImage($stripe, bandCell($stripe), bodyWidth) : null,\n columns: frames.map(($f) => imageOf($f, \"Column\", bodyWidth)),\n bodyPainted: $body\n ? colorFromPaint($body.attr(\"style\"), $body.attr(\"bgcolor\")) !== \"\"\n : false,\n });\n const paint = withoutBandOverImage(\n paintFor($structure, ctx),\n image.image !== undefined,\n );\n const notes = [...paint.notes, flattenNote, ...image.notes].filter(\n (note): note is string => Boolean(note),\n );\n if (notes.length > 0) {\n const entry = pushEntry(\n ctx,\n \"esd-structure\",\n \"section\",\n \"approximated\",\n notes.join(\" \"),\n );\n recordImageSpan(ctx, image.source, entry);\n } else if (frameCount <= 3) {\n const entry = pushEntry(ctx, \"esd-structure\", \"section\", \"converted\");\n recordImageSpan(ctx, image.source, entry);\n }\n const section = createSectionBlock({\n columns: layout,\n children,\n styles: { padding },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, paint.backgroundColor);\n}\n\nexport function convertEditor(html: string, ctx: ConvertCtx): Block[] {\n const $ = load(html);\n const structures = topLevelWithToken($, \"esd-structure\");\n if (structures.length > 0) {\n return structures.map(($s) => sectionFromStructure($s, $, ctx));\n }\n const stripes = topLevelWithToken($, \"esd-stripe\");\n if (stripes.length === 0) {\n return labelledInnerBlocks($.root() as unknown as Cheerio<Element>, $, ctx);\n }\n return stripes.map(($stripe) => {\n const inner = $stripe.find(\"[class~='esd-structure']\");\n if (inner.length > 0) {\n return sectionFromStructure(inner.first() as Cheerio<Element>, $, ctx);\n }\n const image = resolveSectionImage({\n structure: null,\n body: null,\n band: bandImage($stripe, bandCell($stripe), 600),\n columns: [],\n bodyPainted: false,\n });\n const paint = withoutBandOverImage(\n paintFor($stripe, ctx),\n image.image !== undefined,\n );\n const notes = [...paint.notes, ...image.notes].filter(\n (note): note is string => Boolean(note),\n );\n const entry = pushEntry(\n ctx,\n \"esd-stripe\",\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n recordImageSpan(ctx, image.source, entry);\n const section = createSectionBlock({\n columns: \"1\",\n children: [\n blocksInContainer($stripe, $, ctx, columnRooms(600, \"1\", ZERO, 1)[0]),\n ],\n styles: { padding: { ...ZERO } },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\n ...(image.image ? { backgroundImage: image.image } : {}),\n });\n return withBackground(section, paint.backgroundColor);\n });\n}\n","import { load, type CheerioAPI } from \"cheerio\";\nimport { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReport, ImportResult } from \"@templatical/import-html\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport { convertCompiled } from \"./compiled\";\nimport { colorFromPaint, imageFromPaint } from \"./css\";\nimport { detectStripoKind } from \"./detect\";\nimport { convertEditor } from \"./editor\";\nimport { noteImageSpans, type ConvertCtx } from \"./fragment\";\n\nexport interface ConvertStripoOptions {\n /** Sibling CSS from plugin `getTemplateData()`. Applied inside each HTML fragment. */\n css?: string;\n}\n\nfunction injectCss(html: string, css?: string): string {\n if (!css || css.trim().length === 0) return html;\n const $ = load(html);\n if ($(\"head\").length === 0) {\n $(\"html\").prepend(\"<head></head>\");\n }\n // Style elements serialize as HTML rawtext, so a literal `</style` in the\n // CSS would close the element and the rest would parse as markup — which\n // can flip editor/compiled detection. Neutralize the closer; then set a\n // text node rather than interpolating into an HTML string.\n const safe = css.replace(/<\\/style/gi, \"<\\\\/style\");\n const $style = $(\"<style></style>\").attr(\"data-stripo-css\", \"1\").text(safe);\n $(\"head\").append($style);\n return $.html() ?? html;\n}\n\n/** First painted `es-wrapper-color` / `es-wrapper`, or white when neither is set. */\nfunction pageBackground($: CheerioAPI): string {\n const nodes = $(\n \"[class~='es-wrapper-color'], [class~='es-wrapper']\",\n ).toArray();\n for (const node of nodes) {\n const $el = $(node);\n const color = colorFromPaint($el.attr(\"style\"), $el.attr(\"bgcolor\"));\n if (color) return color;\n }\n return \"#ffffff\";\n}\n\n/** The page's background image, which has no Templatical equivalent: the first `es-wrapper-color` / `es-wrapper` that paints one. */\nfunction pageImageWarning($: CheerioAPI): string | null {\n const nodes = $(\n \"[class~='es-wrapper-color'], [class~='es-wrapper']\",\n ).toArray();\n for (const node of nodes) {\n const $el = $(node);\n const read = imageFromPaint(\n $el.attr(\"style\"),\n $el.attr(\"background\"),\n \"Page\",\n undefined,\n );\n if (read) {\n return `The email background image \"${read.image.url}\" was dropped; Templatical has no email-level background image.`;\n }\n }\n return null;\n}\n\nfunction summarize(ctx: ConvertCtx): ImportReport {\n const summary = {\n total: ctx.entries.length,\n converted: 0,\n approximated: 0,\n htmlFallback: 0,\n skipped: 0,\n };\n for (const e of ctx.entries) {\n if (e.status === \"converted\") summary.converted++;\n else if (e.status === \"approximated\") summary.approximated++;\n else if (e.status === \"html-fallback\") summary.htmlFallback++;\n else if (e.status === \"skipped\") summary.skipped++;\n }\n return { entries: ctx.entries, warnings: ctx.warnings, summary };\n}\n\n/**\n * Convert a Stripo template to Templatical content.\n *\n * Auto-detects the surface from class attributes:\n * - `esd-*` on elements → plugin/editor `getTemplateData` HTML\n * - `es-wrapper` / `es-*-body` without `esd-*` → compiled File→HTML export\n *\n * Pass `options.css` when converting plugin storage (`getTemplateData().css`).\n */\nexport function convertStripoTemplate(\n html: string,\n options?: ConvertStripoOptions,\n): ImportResult {\n if (typeof html !== \"string\") {\n throw new Error(\n \"Invalid Stripo template: expected a string. Pass the HTML source as a string.\",\n );\n }\n if (html.trim().length === 0) {\n throw new Error(\n \"Invalid Stripo template: input is empty. Pass the HTML source of a Stripo email.\",\n );\n }\n\n const prepared = injectCss(html, options?.css);\n const kind = detectStripoKind(prepared);\n const fallback = convertHtmlTemplate(prepared);\n\n if (!kind) {\n return {\n content: fallback.content,\n report: {\n ...fallback.report,\n warnings: [\n \"No Stripo class attributes found; converted as generic HTML.\",\n ...fallback.report.warnings,\n ],\n },\n };\n }\n\n const ctx: ConvertCtx = {\n entries: [],\n warnings: [],\n css: options?.css,\n };\n const $page = load(prepared);\n const pageBg = pageBackground($page);\n const pageImage = pageImageWarning($page);\n if (pageImage) ctx.warnings.push(pageImage);\n ctx.pageBackground = pageBg;\n const blocks =\n kind === \"editor\"\n ? convertEditor(prepared, ctx)\n : convertCompiled(prepared, ctx);\n noteImageSpans(ctx);\n\n // After `fallback.content`: its settings carry the HTML importer's white\n // page, which would hide the wrapper colour.\n const defaults = createDefaultTemplateContent();\n return {\n content: {\n ...defaults,\n ...fallback.content,\n blocks,\n settings: {\n ...defaults.settings,\n ...fallback.content.settings,\n backgroundColor: pageBg,\n },\n },\n report: summarize(ctx),\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@templatical/import-stripo",
3
3
  "description": "Convert Stripo email templates to Templatical format",
4
- "version": "0.51.1",
4
+ "version": "0.52.0",
5
5
  "bugs": "https://github.com/templatical/sdk/issues",
6
6
  "dependencies": {
7
- "@templatical/import-html": "0.51.1",
8
- "@templatical/types": "0.51.1",
7
+ "@templatical/import-html": "0.52.0",
8
+ "@templatical/types": "0.52.0",
9
9
  "cheerio": "^1.2.0",
10
10
  "domhandler": "^6.0.1"
11
11
  },
12
12
  "devDependencies": {
13
- "@types/node": "^25.9.9",
13
+ "@types/node": "^26.6.5",
14
14
  "typescript": "^6.0.3",
15
15
  "vitest": "^5.0.5"
16
16
  },