@templatical/import-stripo 0.42.1 → 0.43.1

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["columnLayout"],"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 that compiled Stripo HTML already inlines.\n * Hex (3/6) and a bare bgcolor hex; \"transparent\" is unset.\n */\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 styleAttr.split(\";\")) {\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\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 : trimmed;\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 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","import { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReportEntry } from \"@templatical/import-html\";\nimport type { Block, SectionBlock } from \"@templatical/types\";\n\nexport interface ConvertCtx {\n entries: ImportReportEntry[];\n warnings: string[];\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\n/** Run the generic HTML importer on a subtree and keep its blocks, not its sections. */\nexport function blocksFromHtml(inner: string, ctx: ConvertCtx): Block[] {\n const wrapped = `<!DOCTYPE html><html><body>${inner}</body></html>`;\n const result = convertHtmlTemplate(wrapped);\n ctx.entries.push(...result.report.entries);\n ctx.warnings.push(...result.report.warnings);\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): void {\n ctx.entries.push({\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n });\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 createMenuBlock,\n createSocialIconsBlock,\n createSpacerBlock,\n generateId,\n} from \"@templatical/types\";\nimport type { Block, MenuItemData, SocialIcon } from \"@templatical/types\";\nimport { isHidden } from \"./classes\";\nimport {\n colorFromPaint,\n parseColor,\n parsePxValue,\n parseStyleAttribute,\n} from \"./css\";\nimport { blocksFromHtml, pushEntry, type ConvertCtx } from \"./fragment\";\nimport { normalizePlatform } from \"./platform\";\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\nexport function spacerFrom(\n $el: Cheerio<Element>,\n sourceTag: string,\n ctx: ConvertCtx,\n): Block {\n const style = $el.attr(\"style\") ?? \"\";\n const h = /(?:^|;)\\s*height\\s*:\\s*(\\d+)px/i.exec(style);\n const attrH = $el.attr(\"height\");\n const height = h ? Number(h[1]) : attrH ? Number(attrH) : 24;\n pushEntry(ctx, sourceTag, \"spacer\", \"converted\");\n return createSpacerBlock({\n height: Number.isFinite(height) && height > 0 ? height : 24,\n });\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 { Element } from \"domhandler\";\nimport { createSectionBlock } from \"@templatical/types\";\nimport type { Block, ColumnLayout } from \"@templatical/types\";\nimport { hasAnyToken, hasToken, isHidden } from \"./classes\";\nimport { colorFromPaint } from \"./css\";\nimport {\n blocksFromHtml,\n pushEntry,\n withBackground,\n type ConvertCtx,\n} from \"./fragment\";\nimport { buttonFrom, menuFrom, socialFrom, spacerFrom } from \"./labelled\";\n\nfunction paintOf($el: Cheerio<Element>): string {\n return colorFromPaint($el.attr(\"style\"), $el.attr(\"bgcolor\"));\n}\n\n/**\n * The 600px band (`es-*-body`) carries the fill; the outer stripe is often\n * `transparent`. Style wins over `bgcolor` (a white bgcolor with a mint\n * `background-color` is the compiled password-reset shape).\n */\nfunction stripeFill($stripe: Cheerio<Element>): string {\n const $body = $stripe\n .find(\n \"[class~='es-header-body'], [class~='es-content-body'], [class~='es-footer-body']\",\n )\n .first();\n if ($body.length) {\n const fromBody = paintOf($body as Cheerio<Element>);\n if (fromBody) return fromBody;\n }\n return paintOf($stripe);\n}\n\nconst STRIPE_TOKENS = [\"es-header\", \"es-content\", \"es-footer\"] as const;\n\nfunction stripeToken($el: Cheerio<Element>): string | undefined {\n return STRIPE_TOKENS.find((t) => hasToken($el, t));\n}\n\nfunction topStripes($: CheerioAPI): Cheerio<Element>[] {\n const out: Cheerio<Element>[] = [];\n $(\"[class]\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n const token = stripeToken($el);\n if (!token) return;\n const nested = $el\n .parents()\n .toArray()\n .some((p) => hasAnyToken($(p) as Cheerio<Element>, STRIPE_TOKENS));\n if (nested) return;\n out.push($el);\n });\n return out;\n}\n\nfunction floatedColumns(\n $stripe: Cheerio<Element>,\n $: CheerioAPI,\n): Cheerio<Element>[] {\n const out: Cheerio<Element>[] = [];\n $stripe.find(\"[class~='es-left'], [class~='es-right']\").each((_, node) => {\n const $el = $(node) as Cheerio<Element>;\n if (isHidden($el)) return;\n const nested = $el\n .parents(\"[class~='es-left'], [class~='es-right']\")\n .filter((_, p) => {\n return $stripe.find(p).length > 0 || $(p).closest($stripe).length > 0;\n });\n if (nested.length > 0) return;\n const inOtherStripe = $el\n .parents()\n .toArray()\n .some((p) => {\n if (p === $stripe[0]) return false;\n return hasAnyToken($(p) as Cheerio<Element>, STRIPE_TOKENS);\n });\n if (inOtherStripe) return;\n out.push($el);\n });\n return out;\n}\n\nfunction columnLayout(\n count: number,\n ctx: ConvertCtx,\n sourceTag: string,\n): {\n layout: ColumnLayout;\n flattenExtra: boolean;\n} {\n if (count <= 1) return { layout: \"1\", flattenExtra: false };\n if (count === 2) return { layout: \"2\", flattenExtra: false };\n if (count === 3) return { layout: \"3\", flattenExtra: false };\n pushEntry(\n ctx,\n sourceTag,\n \"section\",\n \"approximated\",\n `Row with ${count} columns was flattened; extra columns merged into the third slot. Templatical supports up to 3 columns per section.`,\n );\n ctx.warnings.push(\n `Row with ${count} columns was flattened; extra columns merged into the third slot. Templatical supports up to 3 columns per section.`,\n );\n return { layout: \"3\", flattenExtra: true };\n}\n\nfunction convertSubtree(\n $el: Cheerio<Element>,\n $: CheerioAPI,\n ctx: ConvertCtx,\n): Block[] {\n const $clone = $el.clone();\n const replacements: Block[][] = [];\n\n const take = ($node: Cheerio<Element>, block: Block | null) => {\n if (!block) return;\n const marker = `stripo-keep-${replacements.length}`;\n replacements.push([block]);\n $node.replaceWith(`<div data-stripo-keep=\"${marker}\"></div>`);\n };\n\n $clone.find(\"table.es-menu, [class~='es-menu']\").each((_, node) => {\n const $n = $(node) as Cheerio<Element>;\n if (!$n.is(\"table\") && $n.find(\"table\").length) return;\n const menu = menuFrom($n, $, \"es-menu\", ctx);\n take($n, menu);\n });\n $clone.find(\"[class~='es-social']\").each((_, node) => {\n const $n = $(node) as Cheerio<Element>;\n take($n, socialFrom($n, $, \"es-social\", ctx));\n });\n $clone.find(\"a.es-button, [class~='es-button']\").each((_, node) => {\n const $n = $(node) as Cheerio<Element>;\n if (!$n.is(\"a\") && $n.find(\"a\").length === 0) return;\n take($n, buttonFrom($n, \"es-button\", ctx));\n });\n $clone.find(\"[class~='es-spacer']\").each((_, node) => {\n const $n = $(node) as Cheerio<Element>;\n take($n, spacerFrom($n, \"es-spacer\", ctx));\n });\n\n const html = $.html($clone) ?? \"\";\n const generic = blocksFromHtml(html, ctx);\n const out: Block[] = [];\n const used = new Set<number>();\n const walk = (blocks: Block[]) => {\n for (const b of blocks) {\n if (\n b.type === \"html\" &&\n /data-stripo-keep=\"stripo-keep-(\\d+)\"/.test(b.content)\n ) {\n const m = /data-stripo-keep=\"stripo-keep-(\\d+)\"/.exec(b.content);\n const i = m ? Number(m[1]) : -1;\n if (i >= 0 && replacements[i] && !used.has(i)) {\n used.add(i);\n out.push(...replacements[i]);\n continue;\n }\n }\n if (b.type === \"paragraph\" && /stripo-keep-/.test(b.content ?? \"\")) {\n const m = /stripo-keep-(\\d+)/.exec(b.content);\n const i = m ? Number(m[1]) : -1;\n if (i >= 0 && replacements[i] && !used.has(i)) {\n used.add(i);\n out.push(...replacements[i]);\n continue;\n }\n }\n out.push(b);\n }\n };\n walk(generic);\n for (let i = 0; i < replacements.length; i++) {\n if (!used.has(i)) out.push(...replacements[i]);\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 convertSubtree($.root() as unknown as Cheerio<Element>, $, ctx);\n }\n return stripes.map(($stripe) => {\n const token = stripeToken($stripe) ?? \"es-content\";\n const cols = floatedColumns($stripe, $);\n const { layout, flattenExtra } = columnLayout(cols.length || 1, ctx, token);\n let children: Block[][];\n if (cols.length <= 1) {\n children = [convertSubtree($stripe, $, ctx)];\n } else if (flattenExtra) {\n const slots = cols.slice(0, 2).map(($c) => convertSubtree($c, $, ctx));\n const rest: Block[] = [];\n for (const $c of cols.slice(2)) rest.push(...convertSubtree($c, $, ctx));\n slots.push(rest);\n children = slots;\n } else {\n children = cols.map(($c) => convertSubtree($c, $, ctx));\n }\n if (!flattenExtra) pushEntry(ctx, token, \"section\", \"converted\");\n return withBackground(\n createSectionBlock({ columns: layout, children }),\n stripeFill($stripe),\n );\n });\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, ColumnLayout } from \"@templatical/types\";\nimport { isHidden, tokenStartingWith, topLevelWithToken } from \"./classes\";\nimport { colorFromPaint } from \"./css\";\nimport { pushEntry, withBackground, type ConvertCtx } from \"./fragment\";\nimport {\n buttonFrom,\n labelledInnerBlocks,\n menuFrom,\n socialFrom,\n spacerFrom,\n} from \"./labelled\";\n\nfunction columnLayout(count: number, ctx: ConvertCtx): ColumnLayout {\n if (count <= 1) return \"1\";\n if (count === 2) return \"2\";\n if (count === 3) return \"3\";\n pushEntry(\n ctx,\n \"esd-structure\",\n \"section\",\n \"approximated\",\n `Row with ${count} columns was flattened to a single column. Templatical supports up to 3 columns per section.`,\n );\n ctx.warnings.push(\n `Row with ${count} columns was flattened to a single column. Templatical supports up to 3 columns per section.`,\n );\n return \"1\";\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): 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\") return [spacerFrom($el, \"esd-block-spacer\", ctx)];\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): 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));\n });\n if (out.length === 0) return labelledInnerBlocks($frame, $, ctx);\n return out;\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 count = frames.length || 1;\n const layout = columnLayout(count, ctx);\n let children: Block[][];\n if (layout === \"1\") {\n const merged: Block[] = [];\n if (frames.length === 0)\n merged.push(...blocksInContainer($structure, $, ctx));\n else for (const $f of frames) merged.push(...blocksInContainer($f, $, ctx));\n children = [merged];\n } else {\n children = frames.map(($f) => blocksInContainer($f, $, ctx));\n }\n if (layout !== \"1\" || frames.length <= 3) {\n pushEntry(ctx, \"esd-structure\", \"section\", \"converted\");\n }\n return withBackground(\n createSectionBlock({ columns: layout, children }),\n colorFromPaint($structure.attr(\"style\"), $structure.attr(\"bgcolor\")),\n );\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 pushEntry(ctx, \"esd-stripe\", \"section\", \"converted\");\n return withBackground(\n createSectionBlock({\n columns: \"1\",\n children: [blocksInContainer($stripe, $, ctx)],\n }),\n colorFromPaint($stripe.attr(\"style\"), $stripe.attr(\"bgcolor\")),\n );\n });\n}\n","import { load } 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 { detectStripoKind } from \"./detect\";\nimport { convertEditor } from \"./editor\";\nimport type { ConvertCtx } from \"./fragment\";\n\nexport interface ConvertStripoOptions {\n /** Sibling CSS from plugin `getTemplateData()`. Ignored on compiled exports. */\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\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 = { entries: [], warnings: [] };\n const blocks =\n kind === \"editor\"\n ? convertEditor(prepared, ctx)\n : convertCompiled(prepared, ctx);\n\n return {\n content: {\n ...createDefaultTemplateContent(),\n ...fallback.content,\n blocks,\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","IMAGE_NOTE","bandColor","imageNote"],"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 { DividerBlock, SpacingValue } 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\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 styleAttr.split(\";\")) {\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\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 hasBackgroundImage(styleAttr: string | undefined): boolean {\n if (!styleAttr) return false;\n const styles = parseStyleAttribute(styleAttr);\n return (\n /url\\s*\\(/i.test(styles[\"background-image\"] ?? \"\") ||\n /url\\s*\\(/i.test(styles.background ?? \"\")\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","import { convertHtmlTemplate } from \"@templatical/import-html\";\nimport type { ImportReportEntry } from \"@templatical/import-html\";\nimport type { Block, SectionBlock } from \"@templatical/types\";\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\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/**\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.\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(...result.report.warnings);\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): void {\n ctx.entries.push({\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n });\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 hasBackgroundImage,\n readBoxPadding,\n resolveSectionPaint,\n type SectionPaint,\n} from \"./css\";\nimport {\n blocksFromHtml,\n pushEntry,\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.\";\nconst IMAGE_NOTE = \"A background image was not imported.\";\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\nfunction imageNote(...styles: Array<string | undefined>): string | undefined {\n return styles.some((style) => hasBackgroundImage(style))\n ? IMAGE_NOTE\n : undefined;\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 image: string | undefined,\n bodyWidth: number,\n): Block[] {\n if (isHidden($row)) return [];\n const pieces: Piece[] = [];\n let padding = { ...ZERO };\n let sawCell = false;\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 }\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 }> = [];\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 });\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({ children: [blocks], layout: \"1\", extra: group.extra });\n }\n if (rendered.length === 0) return [];\n\n const seam =\n rendered.length > 1 && hasPadding(padding) ? SEAM_NOTE : undefined;\n return rendered.map((group, index) => {\n const notes = [...paint.notes, group.extra, image, seam].filter(\n (note): note is string => Boolean(note),\n );\n pushEntry(\n ctx,\n token,\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\n const section = createSectionBlock({\n columns: group.layout,\n children: group.children,\n styles: { padding: splitPadding(padding, rendered.length, index) },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\n });\n return withBackground(section, paint.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 paint = resolveSectionPaint(\n ctx.pageBackground ?? \"#ffffff\",\n bandColor($stripe),\n $body.length > 0 ? paintOf($body) : \"\",\n );\n const image = imageNote(\n $stripe.attr(\"style\"),\n directCell($stripe).attr(\"style\"),\n $body.attr(\"style\"),\n );\n const $width = $body.length > 0 ? $body : $stripe;\n const bodyWidth = emailBodyWidth($width.attr(\"width\"), $width.attr(\"style\"));\n const out: Block[] = [];\n for (const $row of rows) {\n out.push(...sectionsFromRow($row, $, ctx, token, paint, image, 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 hasBackgroundImage,\n readBoxPadding,\n resolveSectionPaint,\n type SectionPaint,\n} from \"./css\";\nimport { pushEntry, withBackground, type ConvertCtx } 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']\";\nconst IMAGE_NOTE = \"A background image was not imported.\";\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\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 $direct = $stripe.children(\"tr\").children(\"td, th\");\n const $nested = $stripe\n .children(\"tbody, thead\")\n .children(\"tr\")\n .children(\"td, th\");\n const $cell = (\n $direct.length > 0 ? $direct : $nested\n ).first() as Cheerio<Element>;\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 imageNote(...styles: Array<string | undefined>): string | undefined {\n return styles.some((style) => hasBackgroundImage(style))\n ? IMAGE_NOTE\n : undefined;\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 paint = paintFor($structure, ctx);\n const $stripe = enclosing($structure, \"[class~='esd-stripe']\");\n const notes = [\n ...paint.notes,\n flattenNote,\n imageNote($stripe?.attr(\"style\"), $body?.attr(\"style\")),\n ].filter((note): note is string => Boolean(note));\n if (notes.length > 0) {\n pushEntry(ctx, \"esd-structure\", \"section\", \"approximated\", notes.join(\" \"));\n } else if (frameCount <= 3) {\n pushEntry(ctx, \"esd-structure\", \"section\", \"converted\");\n }\n const section = createSectionBlock({\n columns: layout,\n children,\n styles: { padding },\n ...(paint.wrapperColor\n ? { wrapper: { backgroundColor: paint.wrapperColor } }\n : {}),\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 paint = paintFor($stripe, ctx);\n const notes = [...paint.notes, imageNote($stripe.attr(\"style\"))].filter(\n (note): note is string => Boolean(note),\n );\n pushEntry(\n ctx,\n \"esd-stripe\",\n \"section\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n );\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 });\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 } from \"./css\";\nimport { detectStripoKind } from \"./detect\";\nimport { convertEditor } from \"./editor\";\nimport 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\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 pageBg = pageBackground(load(prepared));\n ctx.pageBackground = pageBg;\n const blocks =\n kind === \"editor\"\n ? convertEditor(prepared, ctx)\n : convertCompiled(prepared, 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,11 +1,11 @@
1
1
  {
2
2
  "name": "@templatical/import-stripo",
3
3
  "description": "Convert Stripo email templates to Templatical format",
4
- "version": "0.42.1",
4
+ "version": "0.43.1",
5
5
  "bugs": "https://github.com/templatical/sdk/issues",
6
6
  "dependencies": {
7
- "@templatical/import-html": "0.42.1",
8
- "@templatical/types": "0.42.1",
7
+ "@templatical/import-html": "0.43.1",
8
+ "@templatical/types": "0.43.1",
9
9
  "cheerio": "^1.2.0",
10
10
  "domhandler": "^6.0.1"
11
11
  },