@templatical/import-chamaileon 0.44.3 → 0.46.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.js +8 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_TEMPLATE_DEFAULTS, createButtonBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createTitleBlock, createVideoBlock, findOpenTagEnd, generateId } from "@templatical/types";
|
|
1
|
+
import { DEFAULT_TEMPLATE_DEFAULTS, canonicalFontStack, createButtonBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createTitleBlock, createVideoBlock, findOpenTagEnd, generateId } from "@templatical/types";
|
|
2
2
|
//#region src/normalize.ts
|
|
3
3
|
function isUnset(value) {
|
|
4
4
|
if (value === null || value === void 0) return true;
|
|
@@ -176,11 +176,10 @@ function parseLineStyle(value) {
|
|
|
176
176
|
color: border.color
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
|
-
/**
|
|
180
|
-
function
|
|
181
|
-
if (isUnset(value)
|
|
182
|
-
|
|
183
|
-
return family === "" ? void 0 : family;
|
|
179
|
+
/** The font stack to store, or `undefined` when `value` sets no font. */
|
|
180
|
+
function fontStack(value) {
|
|
181
|
+
if (isUnset(value)) return void 0;
|
|
182
|
+
return canonicalFontStack(value) || void 0;
|
|
184
183
|
}
|
|
185
184
|
//#endregion
|
|
186
185
|
//#region src/content-inference.ts
|
|
@@ -491,7 +490,7 @@ function convertTypedText(node, ctx) {
|
|
|
491
490
|
if (titleLevel !== void 0) {
|
|
492
491
|
const level = inferred.kind === "title" ? inferred.level : titleLevel;
|
|
493
492
|
const color = parseColor(styleValue(style, "color"));
|
|
494
|
-
const fontFamily =
|
|
493
|
+
const fontFamily = fontStack(styleValue(style, "fontFamily"));
|
|
495
494
|
return finish(createTitleBlock({
|
|
496
495
|
content: inferred.kind === "title" ? inferred.inner : stripTags(raw),
|
|
497
496
|
level,
|
|
@@ -513,7 +512,7 @@ function convertButton(node, ctx) {
|
|
|
513
512
|
const textColor = parseColor(styleValue(style, "color"));
|
|
514
513
|
const borderRadius = parsePx(styleValue(style, "borderRadius"));
|
|
515
514
|
const fontSize = parsePx(styleValue(style, "fontSize"));
|
|
516
|
-
const fontFamily =
|
|
515
|
+
const fontFamily = fontStack(styleValue(style, "fontFamily"));
|
|
517
516
|
const block = createButtonBlock({
|
|
518
517
|
text: stripTags(asString$1(attrs.text)),
|
|
519
518
|
url: asString$1(attrs.href) ?? "",
|
|
@@ -660,7 +659,7 @@ function typedTitleLevel(subType) {
|
|
|
660
659
|
function headingLooks(style, level, ctx) {
|
|
661
660
|
const nested = readNested(style[`h${level}`], ctx);
|
|
662
661
|
const color = parseColor(style[`h${level}Color`] ?? nested.color);
|
|
663
|
-
const fontFamily =
|
|
662
|
+
const fontFamily = fontStack(style[`h${level}FontFamily`] ?? nested.fontFamily);
|
|
664
663
|
return {
|
|
665
664
|
...color ? { color } : {},
|
|
666
665
|
...fontFamily ? { fontFamily } : {}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["asString","report","readVisibility","asString","readVisibility"],"sources":["../src/normalize.ts","../src/attribute-parser.ts","../src/content-inference.ts","../src/social-mapper.ts","../src/block-mapper.ts","../src/column-layout.ts","../src/section-builder.ts","../src/converter.ts"],"sourcesContent":["import type { ChamaileonNode, ChamaileonVariable } from \"./types\";\n\nexport function isUnset(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value !== \"string\") return false;\n const trimmed = value.trim();\n return (\n trimmed === \"\" ||\n trimmed === \"url()\" ||\n trimmed.toLowerCase() === \"transparent\"\n );\n}\n\nexport function camelKey(key: string): string {\n return key.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction isVariableObject(\n value: unknown,\n): value is { reference?: unknown; default?: unknown } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (\"reference\" in value || \"default\" in value)\n );\n}\n\nexport function unwrapValue(\n value: unknown,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): unknown {\n if (!isVariableObject(value)) return value;\n const resolved = !isUnset(value.default)\n ? value.default\n : (() => {\n const ref =\n typeof value.reference === \"string\" ? value.reference : undefined;\n if (!ref) return undefined;\n const found = variables.find((v) => v.name === ref);\n return found && !isUnset(found.value) ? found.value : undefined;\n })();\n if (stats && !isUnset(resolved)) stats.resolvedVariables += 1;\n return resolved;\n}\n\nfunction readMap(\n raw: Record<string, unknown> | undefined,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!raw) return out;\n for (const [key, value] of Object.entries(raw)) {\n const unwrapped = unwrapValue(value, variables, stats);\n if (isUnset(unwrapped)) continue;\n out[camelKey(key)] = unwrapped;\n }\n return out;\n}\n\nexport function readStyle(\n node: ChamaileonNode,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n return readMap(node.style, variables, stats);\n}\n\nexport function readAttrs(\n node: ChamaileonNode,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n return readMap(node.attrs, variables, stats);\n}\n\nexport function styleValue(\n style: Record<string, unknown>,\n key: string,\n): unknown {\n return style[camelKey(key)];\n}\n","import type { SpacingValue } from \"@templatical/types\";\nimport { isUnset, styleValue } from \"./normalize\";\n\n/**\n * Parse a px-like value into a rounded integer. Returns `undefined` when unset\n * or for units the block model cannot express (em, rem, %).\n *\n * Trims first, then matches with no surrounding `\\s*` so a failing match cannot\n * backtrack across trailing spaces.\n */\nexport function parsePx(value: unknown): number | undefined {\n if (isUnset(value)) return undefined;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? Math.round(value) : undefined;\n }\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n const match = /^(-?\\d+(?:\\.\\d+)?)(?:px)?$/.exec(trimmed);\n return match ? Math.round(parseFloat(match[1])) : undefined;\n}\n\nconst NAMED_COLORS: Record<string, string> = {\n black: \"#000000\",\n white: \"#ffffff\",\n red: \"#ff0000\",\n green: \"#008000\",\n blue: \"#0000ff\",\n yellow: \"#ffff00\",\n cyan: \"#00ffff\",\n magenta: \"#ff00ff\",\n gray: \"#808080\",\n grey: \"#808080\",\n silver: \"#c0c0c0\",\n maroon: \"#800000\",\n olive: \"#808000\",\n lime: \"#00ff00\",\n aqua: \"#00ffff\",\n teal: \"#008080\",\n navy: \"#000080\",\n fuchsia: \"#ff00ff\",\n purple: \"#800080\",\n orange: \"#ffa500\",\n pink: \"#ffc0cb\",\n};\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n const clamp = (n: number) => Math.max(0, Math.min(255, Math.round(n)));\n const hex = (n: number) => clamp(n).toString(16).padStart(2, \"0\");\n return `#${hex(r)}${hex(g)}${hex(b)}`;\n}\n\n/**\n * Normalize a colour to 6-digit lowercase hex.\n *\n * Returns `undefined` for unset inputs (including transparent) and for anything\n * unrecognised — optional colour fields stay omitted rather than empty string.\n */\nexport function parseColor(value: unknown): string | undefined {\n if (isUnset(value)) return undefined;\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim().toLowerCase();\n if (trimmed === \"transparent\" || trimmed === \"inherit\" || trimmed === \"none\")\n return undefined;\n if (/^#[0-9a-f]{6}$/.test(trimmed)) return trimmed;\n if (/^#[0-9a-f]{3}$/.test(trimmed)) {\n const [, r, g, b] = trimmed;\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n const rgb = trimmed.match(\n /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/,\n );\n if (rgb) return rgbToHex(+rgb[1], +rgb[2], +rgb[3]);\n return NAMED_COLORS[trimmed];\n}\n\n/** Read split padding sides from a normalized style map; missing sides are 0. */\nexport function parsePadding(style: Record<string, unknown>): SpacingValue {\n const side = (key: string) => parsePx(styleValue(style, key)) ?? 0;\n return {\n top: side(\"paddingTop\"),\n right: side(\"paddingRight\"),\n bottom: side(\"paddingBottom\"),\n left: side(\"paddingLeft\"),\n };\n}\n\n/** Narrow an alignment to the three the block model accepts. */\nexport function parseAlignment(\n value: unknown,\n fallback: \"left\" | \"center\" | \"right\",\n): \"left\" | \"center\" | \"right\" {\n if (typeof value !== \"string\") return fallback;\n const v = value.trim().toLowerCase();\n return v === \"left\" || v === \"center\" || v === \"right\" ? v : fallback;\n}\n\ntype CssBorder = {\n width: number;\n style: \"solid\" | \"dashed\" | \"dotted\";\n color: string;\n};\n\nfunction isSpace(ch: string): boolean {\n return ch === \" \" || ch === \"\\t\" || ch === \"\\n\" || ch === \"\\r\";\n}\n\nfunction skipSpaces(s: string, i: number): number {\n while (i < s.length && isSpace(s[i]!)) i++;\n return i;\n}\n\n/**\n * `\"2px solid #00a591\"` — width, style, colour.\n *\n * Linear: a regex whose last two tokens are \"spaces, then the rest of the\n * string\" is polynomial on a long run of spaces after the style word\n * (`js/polynomial-redos`). Every character here is visited at most once.\n */\nfunction parseCssBorder(value: unknown): CssBorder | undefined {\n if (isUnset(value) || typeof value !== \"string\") return undefined;\n const s = value.trim();\n let i = 0;\n const numStart = i;\n while (i < s.length && s[i]! >= \"0\" && s[i]! <= \"9\") i++;\n if (i < s.length && s[i] === \".\") {\n i++;\n while (i < s.length && s[i]! >= \"0\" && s[i]! <= \"9\") i++;\n }\n if (i === numStart) return undefined;\n const width = Math.round(parseFloat(s.slice(numStart, i)));\n if (s.slice(i, i + 2).toLowerCase() !== \"px\") return undefined;\n i += 2;\n i = skipSpaces(s, i);\n const styleStart = i;\n while (i < s.length && !isSpace(s[i]!)) i++;\n const styleWord = s.slice(styleStart, i).toLowerCase();\n if (\n styleWord !== \"solid\" &&\n styleWord !== \"dashed\" &&\n styleWord !== \"dotted\"\n ) {\n return undefined;\n }\n i = skipSpaces(s, i);\n if (i >= s.length) return undefined;\n const color = parseColor(s.slice(i));\n if (color === undefined || width === 0) return undefined;\n return { width, style: styleWord, color };\n}\n\n/** Parse a CSS border shorthand for outlined buttons / leaf borders. */\nexport function parseBorderShorthand(value: unknown): CssBorder | undefined {\n return parseCssBorder(value);\n}\n\n/** Parse a 2.0 divider `attrs.lineStyle` string into thickness/lineStyle/color. */\nexport function parseLineStyle(value: unknown):\n | {\n thickness: number;\n lineStyle: \"solid\" | \"dashed\" | \"dotted\";\n color: string;\n }\n | undefined {\n const border = parseCssBorder(value);\n if (!border) return undefined;\n return {\n thickness: border.width,\n lineStyle: border.style,\n color: border.color,\n };\n}\n\n/** Strip quotes and return the first family in a stack. */\nexport function firstFamily(value: unknown): string | undefined {\n if (isUnset(value) || typeof value !== \"string\") return undefined;\n const family = value\n .split(\",\")[0]\n .trim()\n .replace(/^['\"]|['\"]$/g, \"\");\n return family === \"\" ? undefined : family;\n}\n","import { findOpenTagEnd } from \"@templatical/types\";\nimport type { HeadingLevel } from \"@templatical/types\";\n\nexport type InferredText =\n | { kind: \"title\"; level: HeadingLevel; inner: string; clampedFrom?: number }\n | { kind: \"paragraph\"; html: string };\n\n/**\n * A single heading element wrapping the whole content, captured with its level\n * and inner markup. Anchored at both ends so a heading with a sibling does not\n * match — that case is a paragraph.\n */\nconst SOLE_HEADING = /^<h([1-6])(?:\\s[^>]*)?>([\\s\\S]*)<\\/h\\1>$/i;\n\nconst BLOCK_ROOT = /^<(p|h[1-6]|ul|ol|blockquote|div|table)\\b/i;\n\n/**\n * Resolve a Chamaileon `attrs.text` string to a Title or a Paragraph.\n *\n * Chamaileon has no menu or table construct for this arm, so this is a two-way\n * choice — the MJML importer needs four arms because `mj-text` is the output\n * of four different block renderers there. Paragraph is the terminal arm and\n * always reachable, so this function is total.\n */\nexport function inferTextBlock(content: string | undefined): InferredText {\n const trimmed = (content ?? \"\").trim();\n if (trimmed === \"\") return { kind: \"paragraph\", html: \"<p></p>\" };\n\n const heading = trimmed.match(SOLE_HEADING);\n if (heading) {\n const source = Number(heading[1]);\n const level = Math.min(source, 4) as HeadingLevel;\n return {\n kind: \"title\",\n level,\n inner: heading[2].trim(),\n ...(source > 4 ? { clampedFrom: source } : {}),\n };\n }\n\n return {\n kind: \"paragraph\",\n html: BLOCK_ROOT.test(trimmed) ? trimmed : `<p>${trimmed}</p>`,\n };\n}\n\nconst ENTITIES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n \""\": '\"',\n \"'\": \"'\",\n \"'\": \"'\",\n \" \": \" \",\n};\n\n/**\n * Remove every `<tag>` from `html`, keeping the text between them.\n *\n * A single-pass linear scan rather than `/<[^>]*>/g`: that regex is\n * polynomial over input with many `<` starts and no closing `>`, since\n * `[^>]*` backtracks at every one of them — `\"<\".repeat(n)` is quadratic in\n * `n`. `findOpenTagEnd` (from `@templatical/types`) resolves each `<` with a\n * bounded, quote-aware forward scan instead, so the walk stays O(n): every\n * character is visited at most once by `indexOf` and once by\n * `findOpenTagEnd`, because the cursor only moves forward and an\n * unterminated tag ends the walk rather than retrying from inside it. On\n * that unterminated case the remainder of the string — the dangling `<`\n * included — is emitted as-is, matching what `/<[^>]*>/g` does with\n * malformed markup: it can never complete a match without a `>`, so the\n * text is left untouched from that point on.\n */\nfunction removeTags(html: string): string {\n let out = \"\";\n let i = 0;\n while (i < html.length) {\n const open = html.indexOf(\"<\", i);\n if (open === -1) {\n out += html.substring(i);\n break;\n }\n out += html.substring(i, open);\n const tagEnd = findOpenTagEnd(html, open + 1);\n if (tagEnd === -1) {\n out += html.substring(open);\n break;\n }\n i = tagEnd + 1;\n }\n return out;\n}\n\n/**\n * The visible text of a markup fragment, for a button label — `ButtonBlock.text`\n * is a plain string, so the markup Chamaileon stores in `attrs.text` cannot\n * travel.\n */\nexport function stripTags(html: string | undefined): string {\n if (!html) return \"\";\n const text = removeTags(html);\n const decoded = text.replace(\n /&(?:amp|lt|gt|quot|#39|apos|nbsp);/g,\n (m) => ENTITIES[m] ?? m,\n );\n return decoded.replace(/\\s+/g, \" \").trim();\n}\n","import { createSocialIconsBlock, generateId } from \"@templatical/types\";\nimport type {\n BlockStyles,\n BlockVisibility,\n SocialIcon,\n SocialIconSize,\n SocialIconStyle,\n SocialPlatform,\n} from \"@templatical/types\";\nimport { parseAlignment, parsePadding, parsePx } from \"./attribute-parser\";\nimport type { Converted, MapContext } from \"./block-mapper\";\nimport { readAttrs, readStyle } from \"./normalize\";\nimport type {\n ChamaileonNode,\n ConversionStatus,\n ImportReportEntry,\n} from \"./types\";\n\n/**\n * Exhaustive over `SocialPlatform` on purpose: adding a member to that union\n * without adding it here is a compile error, so this cannot silently fall back\n * to \"website\" for a platform the block model gained.\n */\nconst KNOWN_PLATFORMS: Record<SocialPlatform, true> = {\n facebook: true,\n twitter: true,\n instagram: true,\n linkedin: true,\n youtube: true,\n tiktok: true,\n pinterest: true,\n email: true,\n whatsapp: true,\n telegram: true,\n discord: true,\n snapchat: true,\n reddit: true,\n github: true,\n dribbble: true,\n behance: true,\n website: true,\n};\n\nconst ICON_SIZES: Array<[number, SocialIconSize]> = [\n [24, \"small\"],\n [32, \"medium\"],\n [48, \"large\"],\n];\n\nconst KNOWN_STYLES = new Set<string>([\n \"solid\",\n \"outlined\",\n \"rounded\",\n \"square\",\n \"circle\",\n]);\n\nfunction normalizePlatform(raw: string): SocialPlatform | null {\n const cleaned = raw.trim().toLowerCase();\n if (!cleaned) return null;\n return cleaned in KNOWN_PLATFORMS ? (cleaned as SocialPlatform) : null;\n}\n\nfunction nearestSize(px: number): { size: SocialIconSize; exact: boolean } {\n let best = ICON_SIZES[1];\n let gap = Infinity;\n for (const candidate of ICON_SIZES) {\n const d = Math.abs(candidate[0] - px);\n if (d < gap) {\n gap = d;\n best = candidate;\n }\n }\n return { size: best[1], exact: gap === 0 };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asIconStyle(value: unknown): SocialIconStyle | undefined {\n if (typeof value !== \"string\") return undefined;\n const v = value.trim().toLowerCase();\n return KNOWN_STYLES.has(v) ? (v as SocialIconStyle) : undefined;\n}\n\n/**\n * Convert a Chamaileon `social` leaf into a `SocialIconsBlock`.\n *\n * `attrs.elements` is the source of truth for which icons render and in what\n * order. A row of images is not sniffed as social — only `type === \"social\"`.\n */\nexport function convertSocial(\n node: ChamaileonNode,\n ctx: MapContext,\n): Converted {\n const style = readStyle(node, ctx.variables, ctx.stats);\n const attrs = readAttrs(node, ctx.variables, ctx.stats);\n const rawElements = attrs.elements;\n const elements = Array.isArray(rawElements) ? rawElements : [];\n\n if (elements.length === 0) {\n return {\n block: null,\n entry: report(\"social\", null, \"skipped\", \"social has no elements\"),\n };\n }\n\n const notes: string[] = [];\n const icons: SocialIcon[] = [];\n\n for (const item of elements) {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n continue;\n }\n const el = item as Record<string, unknown>;\n const rawType = asString(el.type) ?? \"\";\n const platform = normalizePlatform(rawType);\n if (!platform) {\n notes.push(\n `Unrecognised social platform \"${rawType}\" mapped to \"website\".`,\n );\n }\n icons.push({\n id: generateId(),\n platform: platform ?? \"website\",\n url: asString(el.link) ?? \"\",\n });\n }\n\n if (icons.length === 0) {\n return {\n block: null,\n entry: report(\"social\", null, \"skipped\", \"social has no elements\"),\n };\n }\n\n let iconSize: SocialIconSize | undefined;\n const sizePx = parsePx(attrs.size);\n if (sizePx !== undefined) {\n const resolved = nearestSize(sizePx);\n iconSize = resolved.size;\n if (!resolved.exact) {\n notes.push(\n `Icon size ${attrs.size} is not one of 24/32/48px; resolved to \"${resolved.size}\".`,\n );\n }\n }\n\n const iconStyle = asIconStyle(attrs.color) ?? asIconStyle(attrs.iconSet);\n const spacing = parsePx(attrs.spacing);\n\n const block = createSocialIconsBlock({\n icons,\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...(iconSize ? { iconSize } : {}),\n ...(iconStyle ? { iconStyle } : {}),\n ...(spacing !== undefined ? { spacing } : {}),\n styles: { padding: parsePadding(style) } satisfies BlockStyles,\n });\n\n const visibility = readVisibility(attrs);\n if (visibility) block.visibility = visibility;\n\n return {\n block,\n entry: report(\n \"social\",\n \"social\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n ),\n };\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction report(\n sourceTag: string,\n templaticalBlockType: string | null,\n status: ConversionStatus,\n note?: string,\n): ImportReportEntry {\n return {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n}\n","import {\n createButtonBlock,\n createDividerBlock,\n createHtmlBlock,\n createImageBlock,\n createParagraphBlock,\n createTitleBlock,\n createVideoBlock,\n} from \"@templatical/types\";\nimport type {\n Block,\n BlockStyles,\n BlockVisibility,\n ButtonBlock,\n HeadingLevel,\n} from \"@templatical/types\";\nimport {\n firstFamily,\n parseAlignment,\n parseColor,\n parseLineStyle,\n parsePadding,\n parsePx,\n} from \"./attribute-parser\";\nimport { inferTextBlock, stripTags } from \"./content-inference\";\nimport {\n camelKey,\n isUnset,\n readAttrs,\n readStyle,\n styleValue,\n unwrapValue,\n} from \"./normalize\";\nimport { convertSocial } from \"./social-mapper\";\nimport type {\n ChamaileonNode,\n ChamaileonVariable,\n ConversionStatus,\n ImportReportEntry,\n} from \"./types\";\n\nexport interface MapContext {\n bodyWidth: number;\n columnWidth: number;\n variables: ChamaileonVariable[];\n warnings: string[];\n stats?: { resolvedVariables: number };\n}\n\nexport interface Converted {\n block: Block | null;\n entry: ImportReportEntry;\n}\n\nconst LOOP_TYPES = new Set([\n \"block-level-loop\",\n \"block-level-conditional\",\n \"loop\",\n \"conditional\",\n \"branch\",\n]);\n\nexport function isLoopType(type: string | undefined): boolean {\n return typeof type === \"string\" && LOOP_TYPES.has(type);\n}\n\nexport function readLoopExpression(\n node: ChamaileonNode,\n ctx: MapContext,\n): string | undefined {\n const value = readAttrs(node, ctx.variables, ctx.stats).expression;\n return typeof value === \"string\" ? value : undefined;\n}\n\nexport function skippedLoopEntry(\n type: string,\n expression: string | undefined,\n): ImportReportEntry {\n return {\n sourceTag: type,\n templaticalBlockType: null,\n status: \"skipped\",\n note: expression ? `${type} ${expression}` : type,\n };\n}\n\nexport function markLoopApproximated(\n entries: ImportReportEntry[],\n from: number,\n type: string,\n expression: string | undefined,\n): void {\n const extra = expression ? `${type} ${expression}` : type;\n for (let i = from; i < entries.length; i++) {\n const entry = entries[i];\n if (entry.status === \"converted\") {\n entry.status = \"approximated\";\n }\n entry.note = entry.note ? `${entry.note} ${extra}` : extra;\n }\n}\n\n/**\n * Convert one Chamaileon leaf into a Templatical block.\n *\n * Structure nodes (`fullwidth` / `box` / `multicolumn` / `column`)\n * html-fallback if they reach this function.\n */\nexport function convertLeaf(node: ChamaileonNode, ctx: MapContext): Converted {\n switch (node.type) {\n case \"text\":\n return convertText(node, ctx);\n case \"typed-text\":\n return convertTypedText(node, ctx);\n case \"button\":\n return convertButton(node, ctx);\n case \"image\":\n return convertImage(node, ctx, \"converted\");\n case \"dynamic-image\":\n return convertImage(\n node,\n ctx,\n \"approximated\",\n \"dynamic-image imported as an image block\",\n );\n case \"divider\":\n return convertDivider(node, ctx);\n case \"video\":\n return convertVideo(node, ctx);\n case \"code\":\n return convertCode(node, ctx);\n case \"social\":\n return convertSocial(node, ctx);\n default:\n return convertUnknown(node, ctx);\n }\n}\n\nfunction convertText(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const raw = asString(attrs.text);\n const inferred = inferTextBlock(raw);\n\n if (inferred.kind === \"paragraph\") {\n return finish(\n createParagraphBlock({\n content: inferred.html,\n ...paddingStyles(style),\n }),\n attrs,\n report(\"text\", \"paragraph\", \"converted\"),\n );\n }\n\n const heading = headingLooks(style, inferred.level, ctx);\n return finish(\n createTitleBlock({\n content: inferred.inner,\n level: inferred.level,\n textAlign: parseAlignment(\n alignFromMarkup(raw) ?? attrs.align ?? style.align,\n \"left\",\n ),\n ...heading,\n ...paddingStyles(style),\n }),\n attrs,\n inferred.clampedFrom\n ? report(\n \"text\",\n \"title\",\n \"approximated\",\n `Heading level h${inferred.clampedFrom} clamped to 4 — Templatical titles support h1-h4.`,\n )\n : report(\"text\", \"title\", \"converted\"),\n );\n}\n\nfunction convertTypedText(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const raw = asString(attrs.text);\n const inferred = inferTextBlock(raw);\n const subType = asString(style.subType)?.trim().toLowerCase() ?? \"paragraph\";\n const titleLevel = typedTitleLevel(subType);\n\n if (titleLevel !== undefined) {\n const level = inferred.kind === \"title\" ? inferred.level : titleLevel;\n const color = parseColor(styleValue(style, \"color\"));\n const fontFamily = firstFamily(styleValue(style, \"fontFamily\"));\n return finish(\n createTitleBlock({\n content: inferred.kind === \"title\" ? inferred.inner : stripTags(raw),\n level,\n textAlign: parseAlignment(\n style.align ?? attrs.align ?? alignFromMarkup(raw),\n \"left\",\n ),\n ...(color ? { color } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"typed-text\", \"title\", \"converted\"),\n );\n }\n\n const list = subType === \"list\";\n return finish(\n createParagraphBlock({\n content:\n inferred.kind === \"paragraph\"\n ? inferred.html\n : raw?.trim() || \"<p></p>\",\n ...paddingStyles(style),\n }),\n attrs,\n list\n ? report(\n \"typed-text\",\n \"paragraph\",\n \"approximated\",\n \"typed-text list imported as a paragraph\",\n )\n : report(\"typed-text\", \"paragraph\", \"converted\"),\n );\n}\n\nfunction convertButton(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const fill = parseColor(styleValue(style, \"backgroundColor\"));\n const textColor = parseColor(styleValue(style, \"color\"));\n const borderRadius = parsePx(styleValue(style, \"borderRadius\"));\n const fontSize = parsePx(styleValue(style, \"fontSize\"));\n const fontFamily = firstFamily(styleValue(style, \"fontFamily\"));\n\n const block: ButtonBlock = createButtonBlock({\n text: stripTags(asString(attrs.text)),\n url: asString(attrs.href) ?? \"\",\n ...(fill ? { backgroundColor: fill } : {}),\n ...(textColor ? { textColor } : {}),\n ...(borderRadius !== undefined ? { borderRadius } : {}),\n ...(fontSize !== undefined ? { fontSize } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...paddingStyles(style),\n });\n\n // createButtonBlock defaults fill to #333333; an unset Chamaileon\n // background is an outlined button, which has no Templatical equivalent.\n if (!fill) {\n block.backgroundColor = \"#ffffff\";\n }\n\n return finish(\n block,\n attrs,\n fill\n ? report(\"button\", \"button\", \"converted\")\n : report(\n \"button\",\n \"button\",\n \"approximated\",\n \"outlined button has no Templatical equivalent\",\n ),\n );\n}\n\nfunction convertImage(\n node: ChamaileonNode,\n ctx: MapContext,\n status: \"converted\" | \"approximated\",\n note?: string,\n): Converted {\n const { style, attrs } = readNode(node, ctx);\n const sourceTag = node.type ?? \"image\";\n const src = asString(attrs.src) ?? asString(styleValue(style, \"src\")) ?? \"\";\n const width = resolvedWidth(style, ctx.columnWidth);\n const linkUrl = asString(attrs.link);\n const borderRadius = parsePx(styleValue(style, \"borderRadius\"));\n\n return finish(\n createImageBlock({\n src,\n alt: asString(attrs.altText) ?? \"\",\n ...(width !== undefined ? { width } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...(linkUrl ? { linkUrl } : {}),\n ...(borderRadius && borderRadius > 0 ? { borderRadius } : {}),\n ...paddingStyles(style),\n }),\n attrs,\n report(sourceTag, \"image\", status, note),\n );\n}\n\nfunction convertDivider(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const fromLine = parseLineStyle(attrs.lineStyle);\n // 4.x `style.width` is line thickness, not DividerBlock.width.\n const thickness = fromLine?.thickness ?? parsePx(styleValue(style, \"width\"));\n const lineStyle = fromLine?.lineStyle ?? asLineStyle(style.type);\n const color = fromLine?.color ?? parseColor(styleValue(style, \"color\"));\n\n return finish(\n createDividerBlock({\n ...(thickness !== undefined ? { thickness } : {}),\n ...(lineStyle ? { lineStyle } : {}),\n ...(color ? { color } : {}),\n width: \"full\",\n ...paddingStyles(style),\n }),\n attrs,\n report(\"divider\", \"divider\", \"converted\"),\n );\n}\n\nfunction convertVideo(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const width = resolvedWidth(style, ctx.columnWidth);\n const alt = asString(attrs.altText);\n\n return finish(\n createVideoBlock({\n url: videoUrl(attrs),\n thumbnailUrl: asString(attrs.src) ?? \"\",\n ...(alt !== undefined ? { alt } : {}),\n ...(width !== undefined ? { width } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"video\", \"video\", \"converted\"),\n );\n}\n\nfunction videoUrl(attrs: Record<string, unknown>): string {\n const link = asString(attrs.link);\n if (link) return link;\n const videoId = asString(attrs.videoId);\n if (!videoId) return \"\";\n const provider = asString(attrs.videoProvider)?.trim().toLowerCase();\n if (provider === \"youtube\") {\n return `https://www.youtube.com/watch?v=${videoId}`;\n }\n if (provider === \"vimeo\") {\n return `https://vimeo.com/${videoId}`;\n }\n return \"\";\n}\n\nfunction convertCode(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n return finish(\n createHtmlBlock({\n content: firstSetContent(attrs.html, attrs.code, attrs.content),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"code\", \"html\", \"converted\"),\n );\n}\n\nfunction convertUnknown(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const sourceTag = node.type ?? \"unknown\";\n return finish(\n createHtmlBlock({\n content: JSON.stringify(node),\n ...paddingStyles(style),\n }),\n attrs,\n report(\n sourceTag,\n \"html\",\n \"html-fallback\",\n `${sourceTag} has no Templatical block equivalent; the original node is preserved as JSON.`,\n ),\n );\n}\n\nfunction readNode(\n node: ChamaileonNode,\n ctx: MapContext,\n): { style: Record<string, unknown>; attrs: Record<string, unknown> } {\n return {\n style: readStyle(node, ctx.variables, ctx.stats),\n attrs: readAttrs(node, ctx.variables, ctx.stats),\n };\n}\n\nfunction paddingStyles(style: Record<string, unknown>): {\n styles: BlockStyles;\n} {\n return { styles: { padding: parsePadding(style) } };\n}\n\nfunction finish(\n block: Block,\n attrs: Record<string, unknown>,\n entry: ImportReportEntry,\n): Converted {\n const visibility = readVisibility(attrs);\n if (visibility) block.visibility = visibility;\n return { block, entry };\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction report(\n sourceTag: string,\n templaticalBlockType: string,\n status: ConversionStatus,\n note?: string,\n): ImportReportEntry {\n return {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction firstSetContent(...values: unknown[]): string {\n for (const value of values) {\n if (isUnset(value)) continue;\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n }\n return \"\";\n}\n\nfunction resolvedWidth(\n style: Record<string, unknown>,\n columnWidth: number,\n): number | \"full\" | undefined {\n const px = parsePx(styleValue(style, \"width\"));\n if (px === undefined) return undefined;\n return px >= columnWidth ? \"full\" : px;\n}\n\nfunction asLineStyle(\n value: unknown,\n): \"solid\" | \"dashed\" | \"dotted\" | undefined {\n if (typeof value !== \"string\") return undefined;\n const v = value.trim().toLowerCase();\n return v === \"solid\" || v === \"dashed\" || v === \"dotted\" ? v : undefined;\n}\n\nfunction typedTitleLevel(subType: string): HeadingLevel | undefined {\n if (subType === \"title\" || subType === \"heading1\") return 1;\n if (subType === \"heading2\") return 2;\n if (subType === \"heading3\") return 3;\n return undefined;\n}\n\nfunction headingLooks(\n style: Record<string, unknown>,\n level: HeadingLevel,\n ctx: MapContext,\n): { color?: string; fontFamily?: string } {\n const nested = readNested(style[`h${level}`], ctx);\n const color = parseColor(style[`h${level}Color`] ?? nested.color);\n const fontFamily = firstFamily(\n style[`h${level}FontFamily`] ?? nested.fontFamily,\n );\n return {\n ...(color ? { color } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n };\n}\n\nfunction readNested(value: unknown, ctx: MapContext): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n const out: Record<string, unknown> = {};\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n const unwrapped = unwrapValue(raw, ctx.variables, ctx.stats);\n if (isUnset(unwrapped)) continue;\n out[camelKey(key)] = unwrapped;\n }\n return out;\n}\n\nfunction alignFromMarkup(html: string | undefined): string | undefined {\n if (!html) return undefined;\n const match = /text-align\\s*:\\s*(left|center|right)/i.exec(html);\n return match?.[1]?.toLowerCase();\n}\n","import type { ColumnLayout } from \"@templatical/types\";\n\nconst LAYOUT_SHAPES: Array<{ layout: ColumnLayout; percents: number[] }> = [\n { layout: \"1\", percents: [100] },\n { layout: \"2\", percents: [50, 50] },\n { layout: \"1-2\", percents: [33.33, 66.67] },\n { layout: \"2-1\", percents: [66.67, 33.33] },\n { layout: \"3\", percents: [33.33, 33.33, 33.34] },\n];\n\nconst WIDTH_TOLERANCE = 2;\n\nexport const COLUMN_COUNT: Record<ColumnLayout, number> = {\n \"1\": 1,\n \"2\": 2,\n \"3\": 3,\n \"2-1\": 2,\n \"1-2\": 2,\n};\n\nexport function columnPixels(\n layout: ColumnLayout,\n container: number,\n): number[] {\n switch (layout) {\n case \"2\":\n return [container / 2, container / 2];\n case \"3\":\n return [container / 3, container / 3, container / 3];\n case \"1-2\":\n return [container / 3, (container * 2) / 3];\n case \"2-1\":\n return [(container * 2) / 3, container / 3];\n default:\n return [container];\n }\n}\n\n/**\n * Resolve column widths to one of the five layouts `ColumnLayout` allows.\n *\n * `exact: false` means the caller reports `approximated` — Chamaileon permits\n * any column count at any width and this union permits five shapes, so this is\n * the importer's main irreducible loss.\n */\nexport function matchColumnLayout(percents: Array<number | null>): {\n layout: ColumnLayout;\n exact: boolean;\n} {\n const count = percents.length;\n if (count === 0) return { layout: \"1\", exact: true };\n\n // All-unset is \"distribute equally\", which is exactly what the n-column\n // layout means — not a missing value to approximate around.\n if (percents.every((p) => p === null)) {\n if (count === 1) return { layout: \"1\", exact: true };\n if (count === 2) return { layout: \"2\", exact: true };\n if (count === 3) return { layout: \"3\", exact: true };\n return { layout: \"3\", exact: false };\n }\n\n const known = percents.filter((p): p is number => p !== null);\n const unsetCount = count - known.length;\n const remainder =\n unsetCount === 0\n ? 0\n : Math.max(0, 100 - known.reduce((a, b) => a + b, 0)) / unsetCount;\n const resolved = percents.map((p) => p ?? remainder);\n\n const sameCount = LAYOUT_SHAPES.filter((s) => s.percents.length === count);\n\n for (const shape of sameCount) {\n if (\n shape.percents.every(\n (want, i) => Math.abs(want - resolved[i]) <= WIDTH_TOLERANCE,\n )\n ) {\n return { layout: shape.layout, exact: true };\n }\n }\n\n const candidates =\n sameCount.length > 0\n ? sameCount\n : LAYOUT_SHAPES.filter((s) => s.layout === \"3\");\n\n let best = candidates[0];\n let bestError = Infinity;\n for (const shape of candidates) {\n const error = shape.percents.reduce(\n (sum, want, i) => sum + Math.abs(want - (resolved[i] ?? 0)),\n 0,\n );\n if (error < bestError) {\n bestError = error;\n best = shape;\n }\n }\n\n return { layout: best.layout, exact: false };\n}\n\n/** Convert absolute px column widths to percents of `bodyWidth`. */\nexport function widthsToPercents(\n widthsPx: Array<number | undefined>,\n bodyWidth: number,\n): Array<number | null> {\n return widthsPx.map((w) => (w === undefined ? null : (w / bodyWidth) * 100));\n}\n","import { createSectionBlock } from \"@templatical/types\";\nimport type { Block, BlockVisibility, SpacingValue } from \"@templatical/types\";\nimport { parseColor, parsePadding, parsePx } from \"./attribute-parser\";\nimport {\n convertLeaf,\n isLoopType,\n markLoopApproximated,\n readLoopExpression,\n skippedLoopEntry,\n type MapContext,\n} from \"./block-mapper\";\nimport {\n COLUMN_COUNT,\n columnPixels,\n matchColumnLayout,\n widthsToPercents,\n} from \"./column-layout\";\nimport { readAttrs, readStyle, styleValue } from \"./normalize\";\nimport type { ChamaileonNode, ImportReportEntry } from \"./types\";\n\n/**\n * Build a `SectionBlock` from a Chamaileon `fullwidth`. Returns an array so\n * an empty fullwidth produces nothing.\n *\n * Boxes flatten into the parent. A nested `multicolumn` flattens into the\n * parent column — never a nested `type: \"section\"`.\n */\nexport function buildFullwidth(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n): Block[] {\n const style = readStyle(node, ctx.variables, ctx.stats);\n const attrs = readAttrs(node, ctx.variables, ctx.stats);\n const contentFill = parseColor(styleValue(style, \"contentBackgroundColor\"));\n const outerFill = parseColor(styleValue(style, \"backgroundColor\"));\n\n const original = node.children ?? [];\n const sole = original.length === 1 ? original[0] : undefined;\n const copySoleFill =\n sole?.type === \"box\" &&\n isPaintedBox(sole, ctx) &&\n contentFill === undefined;\n\n const flattened = flattenBoxes(\n original,\n ctx,\n entries,\n copySoleFill ? sole : undefined,\n );\n if (flattened.length === 0) return [];\n\n const mcIndex = flattened.findIndex((child) => child.type === \"multicolumn\");\n const reasons: string[] = [];\n\n const section = createSectionBlock();\n\n if (mcIndex === -1) {\n section.columns = \"1\";\n section.children = [\n convertColumnChildren(\n flattened,\n withColumnWidth(ctx, ctx.bodyWidth),\n entries,\n ),\n ];\n } else {\n const driving = flattened[mcIndex];\n const before = flattened.slice(0, mcIndex);\n const after = flattened.slice(mcIndex + 1);\n if (before.length > 0 || after.length > 0) {\n reasons.push(\n \"fullwidth mixes a multicolumn with sibling leaves; siblings were placed in column 0.\",\n );\n }\n\n const columns = (driving.children ?? []).filter(\n (child) => child.type === \"column\",\n );\n const widthsPx = columns.map((column) =>\n parsePx(styleValue(readStyle(column, ctx.variables, ctx.stats), \"width\")),\n );\n const { layout, exact } = matchColumnLayout(\n widthsToPercents(widthsPx, ctx.bodyWidth),\n );\n if (!exact) {\n reasons.push(\n `Column widths ${formatWidths(widthsPx)} have no exact Templatical layout; resolved to \"${layout}\".`,\n );\n }\n\n const stacking = asString(\n readAttrs(driving, ctx.variables, ctx.stats).stacking,\n );\n if (stacking === \"none\") {\n section.stackOnMobile = false;\n } else if (stacking !== undefined && stacking !== \"left-on-top\") {\n reasons.push(`unknown stacking \"${stacking}\" omitted`);\n }\n\n const slots = COLUMN_COUNT[layout];\n const pixels = columnPixels(layout, ctx.bodyWidth);\n const children: Block[][] = Array.from({ length: slots }, () => []);\n const slotCtx = (slot: number): MapContext =>\n withColumnWidth(ctx, Math.round(pixels[slot] ?? ctx.bodyWidth));\n\n children[0].push(...convertColumnChildren(before, slotCtx(0), entries));\n columns.forEach((column, index) => {\n const slot = Math.min(index, slots - 1);\n children[slot].push(\n ...convertColumnChildren(column.children ?? [], slotCtx(slot), entries),\n );\n });\n children[0].push(...convertColumnChildren(after, slotCtx(0), entries));\n\n section.columns = layout;\n section.children = children;\n }\n\n const soleFill = copySoleFill\n ? parseColor(\n styleValue(\n readStyle(sole, ctx.variables, ctx.stats),\n \"backgroundColor\",\n ),\n )\n : undefined;\n const fill = contentFill ?? soleFill;\n\n section.styles.padding = contentPadding(style);\n if (fill) section.styles.backgroundColor = fill;\n if (outerFill) section.wrapper = { backgroundColor: outerFill };\n\n const visibility = readVisibility(attrs);\n if (visibility) section.visibility = visibility;\n\n entries.push({\n sourceTag: \"fullwidth\",\n templaticalBlockType: \"section\",\n status: reasons.length > 0 ? \"approximated\" : \"converted\",\n ...(reasons.length > 0 ? { note: reasons.join(\" \") } : {}),\n });\n\n return [section];\n}\n\nfunction flattenBoxes(\n nodes: ChamaileonNode[],\n ctx: MapContext,\n entries: ImportReportEntry[],\n silent: ChamaileonNode | undefined,\n): ChamaileonNode[] {\n const out: ChamaileonNode[] = [];\n for (const child of nodes) {\n if (child.type === \"placeholder\") continue;\n if (child.type !== \"box\") {\n out.push(child);\n continue;\n }\n if (child !== silent && isPaintedBox(child, ctx)) {\n reportPaintedBox(child, ctx, entries);\n }\n out.push(...flattenBoxes(child.children ?? [], ctx, entries, undefined));\n }\n return out;\n}\n\nfunction convertColumnChildren(\n nodes: ChamaileonNode[],\n ctx: MapContext,\n entries: ImportReportEntry[],\n): Block[] {\n const blocks: Block[] = [];\n for (const child of nodes) {\n if (child.type === \"placeholder\") continue;\n if (child.type === \"box\") {\n if (isPaintedBox(child, ctx)) reportPaintedBox(child, ctx, entries);\n blocks.push(...convertColumnChildren(child.children ?? [], ctx, entries));\n continue;\n }\n if (child.type === \"multicolumn\") {\n const innerColumns = (child.children ?? []).filter(\n (column) => column.type === \"column\",\n );\n entries.push({\n sourceTag: \"multicolumn\",\n templaticalBlockType: null,\n status: \"approximated\",\n note: `nested multicolumn flattened (${innerColumns.length} columns)`,\n });\n for (const column of innerColumns) {\n blocks.push(\n ...convertColumnChildren(column.children ?? [], ctx, entries),\n );\n }\n continue;\n }\n if (child.type === \"column\") {\n blocks.push(...convertColumnChildren(child.children ?? [], ctx, entries));\n continue;\n }\n if (isLoopType(child.type)) {\n const type = child.type ?? \"loop\";\n const expression = readLoopExpression(child, ctx);\n const kids = child.children ?? [];\n if (kids.length === 0) {\n entries.push(skippedLoopEntry(type, expression));\n continue;\n }\n const from = entries.length;\n blocks.push(...convertColumnChildren(kids, ctx, entries));\n markLoopApproximated(entries, from, type, expression);\n continue;\n }\n const converted = convertLeaf(child, ctx);\n entries.push(converted.entry);\n if (converted.block) blocks.push(converted.block);\n }\n return blocks;\n}\n\nfunction isPaintedBox(node: ChamaileonNode, ctx: MapContext): boolean {\n const style = readStyle(node, ctx.variables, ctx.stats);\n if (parseColor(styleValue(style, \"backgroundColor\"))) return true;\n const padding = parsePadding(style);\n if (\n padding.top !== 0 ||\n padding.right !== 0 ||\n padding.bottom !== 0 ||\n padding.left !== 0\n ) {\n return true;\n }\n const radius = parsePx(styleValue(style, \"borderRadius\"));\n return radius !== undefined && radius > 0;\n}\n\nfunction reportPaintedBox(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n): void {\n const fill = parseColor(\n styleValue(readStyle(node, ctx.variables, ctx.stats), \"backgroundColor\"),\n );\n entries.push({\n sourceTag: \"box\",\n templaticalBlockType: null,\n status: \"approximated\",\n note: fill ? `box fill ${fill} dropped` : \"box padding/radius dropped\",\n });\n}\n\nfunction contentPadding(style: Record<string, unknown>): SpacingValue {\n return {\n top: parsePx(styleValue(style, \"contentPaddingTop\")) ?? 0,\n right: parsePx(styleValue(style, \"contentPaddingRight\")) ?? 0,\n bottom: parsePx(styleValue(style, \"contentPaddingBottom\")) ?? 0,\n left: parsePx(styleValue(style, \"contentPaddingLeft\")) ?? 0,\n };\n}\n\nfunction withColumnWidth(ctx: MapContext, columnWidth: number): MapContext {\n return { ...ctx, columnWidth };\n}\n\nfunction formatWidths(widthsPx: Array<number | undefined>): string {\n return widthsPx\n .map((width) => (width === undefined ? \"auto\" : `${width}px`))\n .join(\", \");\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n","import {\n createDefaultTemplateContent,\n DEFAULT_TEMPLATE_DEFAULTS,\n} from \"@templatical/types\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport { parseColor, parsePx } from \"./attribute-parser\";\nimport {\n convertLeaf,\n isLoopType,\n markLoopApproximated,\n readLoopExpression,\n skippedLoopEntry,\n type MapContext,\n} from \"./block-mapper\";\nimport { readStyle, styleValue } from \"./normalize\";\nimport { buildFullwidth } from \"./section-builder\";\nimport type {\n ChamaileonDocument,\n ChamaileonNode,\n ImportReportEntry,\n ImportResult,\n} from \"./types\";\n\nconst INVALID_MESSAGE =\n \"Invalid Chamaileon template: expected the document JSON object from getDocument().\";\nconst WRONG_BODY_MESSAGE =\n 'Invalid Chamaileon template: expected body.type to be \"body\".';\nconst EMPTY_WARNING =\n \"No convertible content was found in the Chamaileon document. Check that body.children holds at least one fullwidth.\";\n\n/**\n * `DEFAULT_TEMPLATE_DEFAULTS` is typed `Partial<TemplateSettings>` so a\n * consumer can override any subset, but its own literal always sets the six\n * required fields. Narrowing once here is what lets each fallback come out as\n * `number`/`string`/`boolean` rather than `| undefined`.\n */\nconst REQUIRED_DEFAULTS = DEFAULT_TEMPLATE_DEFAULTS as Required<\n Pick<\n TemplateSettings,\n | \"width\"\n | \"backgroundColor\"\n | \"textColor\"\n | \"linkUnderline\"\n | \"fontFamily\"\n | \"locale\"\n >\n>;\n\n/**\n * Convert a Chamaileon `getDocument()` tree into a Templatical template.\n *\n * The input is the document object itself — `{ body, variables?, … }` —\n * not `getEmailHtml()` markup and not an API envelope. That is documented\n * rather than sniffed: guessing between the persist JSON and compiled HTML\n * would send the HTML through the wrong package.\n *\n * @example\n * ```ts\n * const document = await editorInstance.methods.getDocument();\n * const { content, report } = convertChamaileonTemplate(document);\n * ```\n */\nexport function convertChamaileonTemplate(\n doc: ChamaileonDocument | string,\n): ImportResult {\n const root: unknown = typeof doc === \"string\" ? safeParse(doc) : doc;\n\n if (typeof root !== \"object\" || root === null || Array.isArray(root)) {\n throw new Error(INVALID_MESSAGE);\n }\n\n const document = root as ChamaileonDocument;\n const body = document.body;\n if (!body || body.type !== \"body\") {\n throw new Error(WRONG_BODY_MESSAGE);\n }\n\n const entries: ImportReportEntry[] = [];\n const warnings: string[] = [];\n const blocks: Block[] = [];\n const stats = { resolvedVariables: 0 };\n const variables = document.variables ?? [];\n\n const bodyStyle = readStyle(body, variables, stats);\n const width =\n parsePx(styleValue(bodyStyle, \"bodyWidth\")) ?? REQUIRED_DEFAULTS.width;\n const backgroundColor =\n parseColor(styleValue(bodyStyle, \"backgroundColor\")) ??\n REQUIRED_DEFAULTS.backgroundColor;\n\n const previewRaw =\n typeof document.previewText === \"string\" ? document.previewText.trim() : \"\";\n const subjectRaw =\n typeof document.subjectLine === \"string\" ? document.subjectLine.trim() : \"\";\n if (subjectRaw) {\n warnings.push(\n `Dropped subjectLine (\"${document.subjectLine}\") — Templatical templates have no subject-line field.`,\n );\n }\n\n const fontFiles = document.fontFiles;\n if (\n fontFiles &&\n typeof fontFiles === \"object\" &&\n !Array.isArray(fontFiles) &&\n Object.keys(fontFiles).length > 0\n ) {\n warnings.push(\n \"Dropped fontFiles — Templatical templates have no document-level font-file table.\",\n );\n }\n\n const ctx: MapContext = {\n bodyWidth: width,\n columnWidth: width,\n variables,\n warnings,\n stats,\n };\n\n for (const child of body.children ?? []) {\n convertBodyChild(child, ctx, entries, blocks);\n }\n\n if (stats.resolvedVariables > 0) {\n warnings.push(\n `Resolved ${stats.resolvedVariables} colour/image variables to their default values.`,\n );\n }\n\n if (blocks.length === 0) {\n warnings.push(EMPTY_WARNING);\n }\n\n const defaults = createDefaultTemplateContent();\n const content: TemplateContent = {\n ...defaults,\n blocks,\n settings: {\n ...defaults.settings,\n width,\n backgroundColor,\n ...(previewRaw ? { preheaderText: previewRaw } : {}),\n },\n };\n\n const summary = {\n total: entries.length,\n converted: entries.filter((e) => e.status === \"converted\").length,\n approximated: entries.filter((e) => e.status === \"approximated\").length,\n htmlFallback: entries.filter((e) => e.status === \"html-fallback\").length,\n skipped: entries.filter((e) => e.status === \"skipped\").length,\n };\n\n return { content, report: { entries, warnings, summary } };\n}\n\nfunction convertBodyChild(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n blocks: Block[],\n): void {\n if (node.type === \"fullwidth\") {\n blocks.push(...buildFullwidth(node, ctx, entries));\n return;\n }\n if (isLoopType(node.type)) {\n convertLoop(node, ctx, entries, blocks);\n return;\n }\n const converted = convertLeaf(node, ctx);\n entries.push(converted.entry);\n if (converted.block) blocks.push(converted.block);\n}\n\nfunction convertLoop(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n blocks: Block[],\n): void {\n const type = node.type ?? \"loop\";\n const expression = readLoopExpression(node, ctx);\n const children = node.children ?? [];\n if (children.length === 0) {\n entries.push(skippedLoopEntry(type, expression));\n return;\n }\n const from = entries.length;\n for (const child of children) {\n convertBodyChild(child, ctx, entries, blocks);\n }\n markLoopApproximated(entries, from, type, expression);\n}\n\nfunction safeParse(source: string): unknown {\n try {\n return JSON.parse(source);\n } catch {\n throw new Error(INVALID_MESSAGE);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["asString","report","readVisibility","asString","readVisibility"],"sources":["../src/normalize.ts","../src/attribute-parser.ts","../src/content-inference.ts","../src/social-mapper.ts","../src/block-mapper.ts","../src/column-layout.ts","../src/section-builder.ts","../src/converter.ts"],"sourcesContent":["import type { ChamaileonNode, ChamaileonVariable } from \"./types\";\n\nexport function isUnset(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value !== \"string\") return false;\n const trimmed = value.trim();\n return (\n trimmed === \"\" ||\n trimmed === \"url()\" ||\n trimmed.toLowerCase() === \"transparent\"\n );\n}\n\nexport function camelKey(key: string): string {\n return key.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction isVariableObject(\n value: unknown,\n): value is { reference?: unknown; default?: unknown } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (\"reference\" in value || \"default\" in value)\n );\n}\n\nexport function unwrapValue(\n value: unknown,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): unknown {\n if (!isVariableObject(value)) return value;\n const resolved = !isUnset(value.default)\n ? value.default\n : (() => {\n const ref =\n typeof value.reference === \"string\" ? value.reference : undefined;\n if (!ref) return undefined;\n const found = variables.find((v) => v.name === ref);\n return found && !isUnset(found.value) ? found.value : undefined;\n })();\n if (stats && !isUnset(resolved)) stats.resolvedVariables += 1;\n return resolved;\n}\n\nfunction readMap(\n raw: Record<string, unknown> | undefined,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!raw) return out;\n for (const [key, value] of Object.entries(raw)) {\n const unwrapped = unwrapValue(value, variables, stats);\n if (isUnset(unwrapped)) continue;\n out[camelKey(key)] = unwrapped;\n }\n return out;\n}\n\nexport function readStyle(\n node: ChamaileonNode,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n return readMap(node.style, variables, stats);\n}\n\nexport function readAttrs(\n node: ChamaileonNode,\n variables: ChamaileonVariable[],\n stats?: { resolvedVariables: number },\n): Record<string, unknown> {\n return readMap(node.attrs, variables, stats);\n}\n\nexport function styleValue(\n style: Record<string, unknown>,\n key: string,\n): unknown {\n return style[camelKey(key)];\n}\n","import { canonicalFontStack } from \"@templatical/types\";\nimport type { SpacingValue } from \"@templatical/types\";\nimport { isUnset, styleValue } from \"./normalize\";\n\n/**\n * Parse a px-like value into a rounded integer. Returns `undefined` when unset\n * or for units the block model cannot express (em, rem, %).\n *\n * Trims first, then matches with no surrounding `\\s*` so a failing match cannot\n * backtrack across trailing spaces.\n */\nexport function parsePx(value: unknown): number | undefined {\n if (isUnset(value)) return undefined;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? Math.round(value) : undefined;\n }\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n const match = /^(-?\\d+(?:\\.\\d+)?)(?:px)?$/.exec(trimmed);\n return match ? Math.round(parseFloat(match[1])) : undefined;\n}\n\nconst NAMED_COLORS: Record<string, string> = {\n black: \"#000000\",\n white: \"#ffffff\",\n red: \"#ff0000\",\n green: \"#008000\",\n blue: \"#0000ff\",\n yellow: \"#ffff00\",\n cyan: \"#00ffff\",\n magenta: \"#ff00ff\",\n gray: \"#808080\",\n grey: \"#808080\",\n silver: \"#c0c0c0\",\n maroon: \"#800000\",\n olive: \"#808000\",\n lime: \"#00ff00\",\n aqua: \"#00ffff\",\n teal: \"#008080\",\n navy: \"#000080\",\n fuchsia: \"#ff00ff\",\n purple: \"#800080\",\n orange: \"#ffa500\",\n pink: \"#ffc0cb\",\n};\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n const clamp = (n: number) => Math.max(0, Math.min(255, Math.round(n)));\n const hex = (n: number) => clamp(n).toString(16).padStart(2, \"0\");\n return `#${hex(r)}${hex(g)}${hex(b)}`;\n}\n\n/**\n * Normalize a colour to 6-digit lowercase hex.\n *\n * Returns `undefined` for unset inputs (including transparent) and for anything\n * unrecognised — optional colour fields stay omitted rather than empty string.\n */\nexport function parseColor(value: unknown): string | undefined {\n if (isUnset(value)) return undefined;\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim().toLowerCase();\n if (trimmed === \"transparent\" || trimmed === \"inherit\" || trimmed === \"none\")\n return undefined;\n if (/^#[0-9a-f]{6}$/.test(trimmed)) return trimmed;\n if (/^#[0-9a-f]{3}$/.test(trimmed)) {\n const [, r, g, b] = trimmed;\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n const rgb = trimmed.match(\n /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/,\n );\n if (rgb) return rgbToHex(+rgb[1], +rgb[2], +rgb[3]);\n return NAMED_COLORS[trimmed];\n}\n\n/** Read split padding sides from a normalized style map; missing sides are 0. */\nexport function parsePadding(style: Record<string, unknown>): SpacingValue {\n const side = (key: string) => parsePx(styleValue(style, key)) ?? 0;\n return {\n top: side(\"paddingTop\"),\n right: side(\"paddingRight\"),\n bottom: side(\"paddingBottom\"),\n left: side(\"paddingLeft\"),\n };\n}\n\n/** Narrow an alignment to the three the block model accepts. */\nexport function parseAlignment(\n value: unknown,\n fallback: \"left\" | \"center\" | \"right\",\n): \"left\" | \"center\" | \"right\" {\n if (typeof value !== \"string\") return fallback;\n const v = value.trim().toLowerCase();\n return v === \"left\" || v === \"center\" || v === \"right\" ? v : fallback;\n}\n\ntype CssBorder = {\n width: number;\n style: \"solid\" | \"dashed\" | \"dotted\";\n color: string;\n};\n\nfunction isSpace(ch: string): boolean {\n return ch === \" \" || ch === \"\\t\" || ch === \"\\n\" || ch === \"\\r\";\n}\n\nfunction skipSpaces(s: string, i: number): number {\n while (i < s.length && isSpace(s[i]!)) i++;\n return i;\n}\n\n/**\n * `\"2px solid #00a591\"` — width, style, colour.\n *\n * Linear: a regex whose last two tokens are \"spaces, then the rest of the\n * string\" is polynomial on a long run of spaces after the style word\n * (`js/polynomial-redos`). Every character here is visited at most once.\n */\nfunction parseCssBorder(value: unknown): CssBorder | undefined {\n if (isUnset(value) || typeof value !== \"string\") return undefined;\n const s = value.trim();\n let i = 0;\n const numStart = i;\n while (i < s.length && s[i]! >= \"0\" && s[i]! <= \"9\") i++;\n if (i < s.length && s[i] === \".\") {\n i++;\n while (i < s.length && s[i]! >= \"0\" && s[i]! <= \"9\") i++;\n }\n if (i === numStart) return undefined;\n const width = Math.round(parseFloat(s.slice(numStart, i)));\n if (s.slice(i, i + 2).toLowerCase() !== \"px\") return undefined;\n i += 2;\n i = skipSpaces(s, i);\n const styleStart = i;\n while (i < s.length && !isSpace(s[i]!)) i++;\n const styleWord = s.slice(styleStart, i).toLowerCase();\n if (\n styleWord !== \"solid\" &&\n styleWord !== \"dashed\" &&\n styleWord !== \"dotted\"\n ) {\n return undefined;\n }\n i = skipSpaces(s, i);\n if (i >= s.length) return undefined;\n const color = parseColor(s.slice(i));\n if (color === undefined || width === 0) return undefined;\n return { width, style: styleWord, color };\n}\n\n/** Parse a CSS border shorthand for outlined buttons / leaf borders. */\nexport function parseBorderShorthand(value: unknown): CssBorder | undefined {\n return parseCssBorder(value);\n}\n\n/** Parse a 2.0 divider `attrs.lineStyle` string into thickness/lineStyle/color. */\nexport function parseLineStyle(value: unknown):\n | {\n thickness: number;\n lineStyle: \"solid\" | \"dashed\" | \"dotted\";\n color: string;\n }\n | undefined {\n const border = parseCssBorder(value);\n if (!border) return undefined;\n return {\n thickness: border.width,\n lineStyle: border.style,\n color: border.color,\n };\n}\n\n/** The font stack to store, or `undefined` when `value` sets no font. */\nexport function fontStack(value: unknown): string | undefined {\n if (isUnset(value)) return undefined;\n return canonicalFontStack(value) || undefined;\n}\n","import { findOpenTagEnd } from \"@templatical/types\";\nimport type { HeadingLevel } from \"@templatical/types\";\n\nexport type InferredText =\n | { kind: \"title\"; level: HeadingLevel; inner: string; clampedFrom?: number }\n | { kind: \"paragraph\"; html: string };\n\n/**\n * A single heading element wrapping the whole content, captured with its level\n * and inner markup. Anchored at both ends so a heading with a sibling does not\n * match — that case is a paragraph.\n */\nconst SOLE_HEADING = /^<h([1-6])(?:\\s[^>]*)?>([\\s\\S]*)<\\/h\\1>$/i;\n\nconst BLOCK_ROOT = /^<(p|h[1-6]|ul|ol|blockquote|div|table)\\b/i;\n\n/**\n * Resolve a Chamaileon `attrs.text` string to a Title or a Paragraph.\n *\n * Chamaileon has no menu or table construct for this arm, so this is a two-way\n * choice — the MJML importer needs four arms because `mj-text` is the output\n * of four different block renderers there. Paragraph is the terminal arm and\n * always reachable, so this function is total.\n */\nexport function inferTextBlock(content: string | undefined): InferredText {\n const trimmed = (content ?? \"\").trim();\n if (trimmed === \"\") return { kind: \"paragraph\", html: \"<p></p>\" };\n\n const heading = trimmed.match(SOLE_HEADING);\n if (heading) {\n const source = Number(heading[1]);\n const level = Math.min(source, 4) as HeadingLevel;\n return {\n kind: \"title\",\n level,\n inner: heading[2].trim(),\n ...(source > 4 ? { clampedFrom: source } : {}),\n };\n }\n\n return {\n kind: \"paragraph\",\n html: BLOCK_ROOT.test(trimmed) ? trimmed : `<p>${trimmed}</p>`,\n };\n}\n\nconst ENTITIES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n \""\": '\"',\n \"'\": \"'\",\n \"'\": \"'\",\n \" \": \" \",\n};\n\n/**\n * Remove every `<tag>` from `html`, keeping the text between them.\n *\n * A single-pass linear scan rather than `/<[^>]*>/g`: that regex is\n * polynomial over input with many `<` starts and no closing `>`, since\n * `[^>]*` backtracks at every one of them — `\"<\".repeat(n)` is quadratic in\n * `n`. `findOpenTagEnd` (from `@templatical/types`) resolves each `<` with a\n * bounded, quote-aware forward scan instead, so the walk stays O(n): every\n * character is visited at most once by `indexOf` and once by\n * `findOpenTagEnd`, because the cursor only moves forward and an\n * unterminated tag ends the walk rather than retrying from inside it. On\n * that unterminated case the remainder of the string — the dangling `<`\n * included — is emitted as-is, matching what `/<[^>]*>/g` does with\n * malformed markup: it can never complete a match without a `>`, so the\n * text is left untouched from that point on.\n */\nfunction removeTags(html: string): string {\n let out = \"\";\n let i = 0;\n while (i < html.length) {\n const open = html.indexOf(\"<\", i);\n if (open === -1) {\n out += html.substring(i);\n break;\n }\n out += html.substring(i, open);\n const tagEnd = findOpenTagEnd(html, open + 1);\n if (tagEnd === -1) {\n out += html.substring(open);\n break;\n }\n i = tagEnd + 1;\n }\n return out;\n}\n\n/**\n * The visible text of a markup fragment, for a button label — `ButtonBlock.text`\n * is a plain string, so the markup Chamaileon stores in `attrs.text` cannot\n * travel.\n */\nexport function stripTags(html: string | undefined): string {\n if (!html) return \"\";\n const text = removeTags(html);\n const decoded = text.replace(\n /&(?:amp|lt|gt|quot|#39|apos|nbsp);/g,\n (m) => ENTITIES[m] ?? m,\n );\n return decoded.replace(/\\s+/g, \" \").trim();\n}\n","import { createSocialIconsBlock, generateId } from \"@templatical/types\";\nimport type {\n BlockStyles,\n BlockVisibility,\n SocialIcon,\n SocialIconSize,\n SocialIconStyle,\n SocialPlatform,\n} from \"@templatical/types\";\nimport { parseAlignment, parsePadding, parsePx } from \"./attribute-parser\";\nimport type { Converted, MapContext } from \"./block-mapper\";\nimport { readAttrs, readStyle } from \"./normalize\";\nimport type {\n ChamaileonNode,\n ConversionStatus,\n ImportReportEntry,\n} from \"./types\";\n\n/**\n * Exhaustive over `SocialPlatform` on purpose: adding a member to that union\n * without adding it here is a compile error, so this cannot silently fall back\n * to \"website\" for a platform the block model gained.\n */\nconst KNOWN_PLATFORMS: Record<SocialPlatform, true> = {\n facebook: true,\n twitter: true,\n instagram: true,\n linkedin: true,\n youtube: true,\n tiktok: true,\n pinterest: true,\n email: true,\n whatsapp: true,\n telegram: true,\n discord: true,\n snapchat: true,\n reddit: true,\n github: true,\n dribbble: true,\n behance: true,\n website: true,\n};\n\nconst ICON_SIZES: Array<[number, SocialIconSize]> = [\n [24, \"small\"],\n [32, \"medium\"],\n [48, \"large\"],\n];\n\nconst KNOWN_STYLES = new Set<string>([\n \"solid\",\n \"outlined\",\n \"rounded\",\n \"square\",\n \"circle\",\n]);\n\nfunction normalizePlatform(raw: string): SocialPlatform | null {\n const cleaned = raw.trim().toLowerCase();\n if (!cleaned) return null;\n return cleaned in KNOWN_PLATFORMS ? (cleaned as SocialPlatform) : null;\n}\n\nfunction nearestSize(px: number): { size: SocialIconSize; exact: boolean } {\n let best = ICON_SIZES[1];\n let gap = Infinity;\n for (const candidate of ICON_SIZES) {\n const d = Math.abs(candidate[0] - px);\n if (d < gap) {\n gap = d;\n best = candidate;\n }\n }\n return { size: best[1], exact: gap === 0 };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asIconStyle(value: unknown): SocialIconStyle | undefined {\n if (typeof value !== \"string\") return undefined;\n const v = value.trim().toLowerCase();\n return KNOWN_STYLES.has(v) ? (v as SocialIconStyle) : undefined;\n}\n\n/**\n * Convert a Chamaileon `social` leaf into a `SocialIconsBlock`.\n *\n * `attrs.elements` is the source of truth for which icons render and in what\n * order. A row of images is not sniffed as social — only `type === \"social\"`.\n */\nexport function convertSocial(\n node: ChamaileonNode,\n ctx: MapContext,\n): Converted {\n const style = readStyle(node, ctx.variables, ctx.stats);\n const attrs = readAttrs(node, ctx.variables, ctx.stats);\n const rawElements = attrs.elements;\n const elements = Array.isArray(rawElements) ? rawElements : [];\n\n if (elements.length === 0) {\n return {\n block: null,\n entry: report(\"social\", null, \"skipped\", \"social has no elements\"),\n };\n }\n\n const notes: string[] = [];\n const icons: SocialIcon[] = [];\n\n for (const item of elements) {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n continue;\n }\n const el = item as Record<string, unknown>;\n const rawType = asString(el.type) ?? \"\";\n const platform = normalizePlatform(rawType);\n if (!platform) {\n notes.push(\n `Unrecognised social platform \"${rawType}\" mapped to \"website\".`,\n );\n }\n icons.push({\n id: generateId(),\n platform: platform ?? \"website\",\n url: asString(el.link) ?? \"\",\n });\n }\n\n if (icons.length === 0) {\n return {\n block: null,\n entry: report(\"social\", null, \"skipped\", \"social has no elements\"),\n };\n }\n\n let iconSize: SocialIconSize | undefined;\n const sizePx = parsePx(attrs.size);\n if (sizePx !== undefined) {\n const resolved = nearestSize(sizePx);\n iconSize = resolved.size;\n if (!resolved.exact) {\n notes.push(\n `Icon size ${attrs.size} is not one of 24/32/48px; resolved to \"${resolved.size}\".`,\n );\n }\n }\n\n const iconStyle = asIconStyle(attrs.color) ?? asIconStyle(attrs.iconSet);\n const spacing = parsePx(attrs.spacing);\n\n const block = createSocialIconsBlock({\n icons,\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...(iconSize ? { iconSize } : {}),\n ...(iconStyle ? { iconStyle } : {}),\n ...(spacing !== undefined ? { spacing } : {}),\n styles: { padding: parsePadding(style) } satisfies BlockStyles,\n });\n\n const visibility = readVisibility(attrs);\n if (visibility) block.visibility = visibility;\n\n return {\n block,\n entry: report(\n \"social\",\n \"social\",\n notes.length > 0 ? \"approximated\" : \"converted\",\n notes.length > 0 ? notes.join(\" \") : undefined,\n ),\n };\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction report(\n sourceTag: string,\n templaticalBlockType: string | null,\n status: ConversionStatus,\n note?: string,\n): ImportReportEntry {\n return {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n}\n","import {\n createButtonBlock,\n createDividerBlock,\n createHtmlBlock,\n createImageBlock,\n createParagraphBlock,\n createTitleBlock,\n createVideoBlock,\n} from \"@templatical/types\";\nimport type {\n Block,\n BlockStyles,\n BlockVisibility,\n ButtonBlock,\n HeadingLevel,\n} from \"@templatical/types\";\nimport {\n fontStack,\n parseAlignment,\n parseColor,\n parseLineStyle,\n parsePadding,\n parsePx,\n} from \"./attribute-parser\";\nimport { inferTextBlock, stripTags } from \"./content-inference\";\nimport {\n camelKey,\n isUnset,\n readAttrs,\n readStyle,\n styleValue,\n unwrapValue,\n} from \"./normalize\";\nimport { convertSocial } from \"./social-mapper\";\nimport type {\n ChamaileonNode,\n ChamaileonVariable,\n ConversionStatus,\n ImportReportEntry,\n} from \"./types\";\n\nexport interface MapContext {\n bodyWidth: number;\n columnWidth: number;\n variables: ChamaileonVariable[];\n warnings: string[];\n stats?: { resolvedVariables: number };\n}\n\nexport interface Converted {\n block: Block | null;\n entry: ImportReportEntry;\n}\n\nconst LOOP_TYPES = new Set([\n \"block-level-loop\",\n \"block-level-conditional\",\n \"loop\",\n \"conditional\",\n \"branch\",\n]);\n\nexport function isLoopType(type: string | undefined): boolean {\n return typeof type === \"string\" && LOOP_TYPES.has(type);\n}\n\nexport function readLoopExpression(\n node: ChamaileonNode,\n ctx: MapContext,\n): string | undefined {\n const value = readAttrs(node, ctx.variables, ctx.stats).expression;\n return typeof value === \"string\" ? value : undefined;\n}\n\nexport function skippedLoopEntry(\n type: string,\n expression: string | undefined,\n): ImportReportEntry {\n return {\n sourceTag: type,\n templaticalBlockType: null,\n status: \"skipped\",\n note: expression ? `${type} ${expression}` : type,\n };\n}\n\nexport function markLoopApproximated(\n entries: ImportReportEntry[],\n from: number,\n type: string,\n expression: string | undefined,\n): void {\n const extra = expression ? `${type} ${expression}` : type;\n for (let i = from; i < entries.length; i++) {\n const entry = entries[i];\n if (entry.status === \"converted\") {\n entry.status = \"approximated\";\n }\n entry.note = entry.note ? `${entry.note} ${extra}` : extra;\n }\n}\n\n/**\n * Convert one Chamaileon leaf into a Templatical block.\n *\n * Structure nodes (`fullwidth` / `box` / `multicolumn` / `column`)\n * html-fallback if they reach this function.\n */\nexport function convertLeaf(node: ChamaileonNode, ctx: MapContext): Converted {\n switch (node.type) {\n case \"text\":\n return convertText(node, ctx);\n case \"typed-text\":\n return convertTypedText(node, ctx);\n case \"button\":\n return convertButton(node, ctx);\n case \"image\":\n return convertImage(node, ctx, \"converted\");\n case \"dynamic-image\":\n return convertImage(\n node,\n ctx,\n \"approximated\",\n \"dynamic-image imported as an image block\",\n );\n case \"divider\":\n return convertDivider(node, ctx);\n case \"video\":\n return convertVideo(node, ctx);\n case \"code\":\n return convertCode(node, ctx);\n case \"social\":\n return convertSocial(node, ctx);\n default:\n return convertUnknown(node, ctx);\n }\n}\n\nfunction convertText(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const raw = asString(attrs.text);\n const inferred = inferTextBlock(raw);\n\n if (inferred.kind === \"paragraph\") {\n return finish(\n createParagraphBlock({\n content: inferred.html,\n ...paddingStyles(style),\n }),\n attrs,\n report(\"text\", \"paragraph\", \"converted\"),\n );\n }\n\n const heading = headingLooks(style, inferred.level, ctx);\n return finish(\n createTitleBlock({\n content: inferred.inner,\n level: inferred.level,\n textAlign: parseAlignment(\n alignFromMarkup(raw) ?? attrs.align ?? style.align,\n \"left\",\n ),\n ...heading,\n ...paddingStyles(style),\n }),\n attrs,\n inferred.clampedFrom\n ? report(\n \"text\",\n \"title\",\n \"approximated\",\n `Heading level h${inferred.clampedFrom} clamped to 4 — Templatical titles support h1-h4.`,\n )\n : report(\"text\", \"title\", \"converted\"),\n );\n}\n\nfunction convertTypedText(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const raw = asString(attrs.text);\n const inferred = inferTextBlock(raw);\n const subType = asString(style.subType)?.trim().toLowerCase() ?? \"paragraph\";\n const titleLevel = typedTitleLevel(subType);\n\n if (titleLevel !== undefined) {\n const level = inferred.kind === \"title\" ? inferred.level : titleLevel;\n const color = parseColor(styleValue(style, \"color\"));\n const fontFamily = fontStack(styleValue(style, \"fontFamily\"));\n return finish(\n createTitleBlock({\n content: inferred.kind === \"title\" ? inferred.inner : stripTags(raw),\n level,\n textAlign: parseAlignment(\n style.align ?? attrs.align ?? alignFromMarkup(raw),\n \"left\",\n ),\n ...(color ? { color } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"typed-text\", \"title\", \"converted\"),\n );\n }\n\n const list = subType === \"list\";\n return finish(\n createParagraphBlock({\n content:\n inferred.kind === \"paragraph\"\n ? inferred.html\n : raw?.trim() || \"<p></p>\",\n ...paddingStyles(style),\n }),\n attrs,\n list\n ? report(\n \"typed-text\",\n \"paragraph\",\n \"approximated\",\n \"typed-text list imported as a paragraph\",\n )\n : report(\"typed-text\", \"paragraph\", \"converted\"),\n );\n}\n\nfunction convertButton(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const fill = parseColor(styleValue(style, \"backgroundColor\"));\n const textColor = parseColor(styleValue(style, \"color\"));\n const borderRadius = parsePx(styleValue(style, \"borderRadius\"));\n const fontSize = parsePx(styleValue(style, \"fontSize\"));\n const fontFamily = fontStack(styleValue(style, \"fontFamily\"));\n\n const block: ButtonBlock = createButtonBlock({\n text: stripTags(asString(attrs.text)),\n url: asString(attrs.href) ?? \"\",\n ...(fill ? { backgroundColor: fill } : {}),\n ...(textColor ? { textColor } : {}),\n ...(borderRadius !== undefined ? { borderRadius } : {}),\n ...(fontSize !== undefined ? { fontSize } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...paddingStyles(style),\n });\n\n // createButtonBlock defaults fill to #333333; an unset Chamaileon\n // background is an outlined button, which has no Templatical equivalent.\n if (!fill) {\n block.backgroundColor = \"#ffffff\";\n }\n\n return finish(\n block,\n attrs,\n fill\n ? report(\"button\", \"button\", \"converted\")\n : report(\n \"button\",\n \"button\",\n \"approximated\",\n \"outlined button has no Templatical equivalent\",\n ),\n );\n}\n\nfunction convertImage(\n node: ChamaileonNode,\n ctx: MapContext,\n status: \"converted\" | \"approximated\",\n note?: string,\n): Converted {\n const { style, attrs } = readNode(node, ctx);\n const sourceTag = node.type ?? \"image\";\n const src = asString(attrs.src) ?? asString(styleValue(style, \"src\")) ?? \"\";\n const width = resolvedWidth(style, ctx.columnWidth);\n const linkUrl = asString(attrs.link);\n const borderRadius = parsePx(styleValue(style, \"borderRadius\"));\n\n return finish(\n createImageBlock({\n src,\n alt: asString(attrs.altText) ?? \"\",\n ...(width !== undefined ? { width } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...(linkUrl ? { linkUrl } : {}),\n ...(borderRadius && borderRadius > 0 ? { borderRadius } : {}),\n ...paddingStyles(style),\n }),\n attrs,\n report(sourceTag, \"image\", status, note),\n );\n}\n\nfunction convertDivider(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const fromLine = parseLineStyle(attrs.lineStyle);\n // 4.x `style.width` is line thickness, not DividerBlock.width.\n const thickness = fromLine?.thickness ?? parsePx(styleValue(style, \"width\"));\n const lineStyle = fromLine?.lineStyle ?? asLineStyle(style.type);\n const color = fromLine?.color ?? parseColor(styleValue(style, \"color\"));\n\n return finish(\n createDividerBlock({\n ...(thickness !== undefined ? { thickness } : {}),\n ...(lineStyle ? { lineStyle } : {}),\n ...(color ? { color } : {}),\n width: \"full\",\n ...paddingStyles(style),\n }),\n attrs,\n report(\"divider\", \"divider\", \"converted\"),\n );\n}\n\nfunction convertVideo(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const width = resolvedWidth(style, ctx.columnWidth);\n const alt = asString(attrs.altText);\n\n return finish(\n createVideoBlock({\n url: videoUrl(attrs),\n thumbnailUrl: asString(attrs.src) ?? \"\",\n ...(alt !== undefined ? { alt } : {}),\n ...(width !== undefined ? { width } : {}),\n align: parseAlignment(attrs.align ?? style.align, \"center\"),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"video\", \"video\", \"converted\"),\n );\n}\n\nfunction videoUrl(attrs: Record<string, unknown>): string {\n const link = asString(attrs.link);\n if (link) return link;\n const videoId = asString(attrs.videoId);\n if (!videoId) return \"\";\n const provider = asString(attrs.videoProvider)?.trim().toLowerCase();\n if (provider === \"youtube\") {\n return `https://www.youtube.com/watch?v=${videoId}`;\n }\n if (provider === \"vimeo\") {\n return `https://vimeo.com/${videoId}`;\n }\n return \"\";\n}\n\nfunction convertCode(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n return finish(\n createHtmlBlock({\n content: firstSetContent(attrs.html, attrs.code, attrs.content),\n ...paddingStyles(style),\n }),\n attrs,\n report(\"code\", \"html\", \"converted\"),\n );\n}\n\nfunction convertUnknown(node: ChamaileonNode, ctx: MapContext): Converted {\n const { style, attrs } = readNode(node, ctx);\n const sourceTag = node.type ?? \"unknown\";\n return finish(\n createHtmlBlock({\n content: JSON.stringify(node),\n ...paddingStyles(style),\n }),\n attrs,\n report(\n sourceTag,\n \"html\",\n \"html-fallback\",\n `${sourceTag} has no Templatical block equivalent; the original node is preserved as JSON.`,\n ),\n );\n}\n\nfunction readNode(\n node: ChamaileonNode,\n ctx: MapContext,\n): { style: Record<string, unknown>; attrs: Record<string, unknown> } {\n return {\n style: readStyle(node, ctx.variables, ctx.stats),\n attrs: readAttrs(node, ctx.variables, ctx.stats),\n };\n}\n\nfunction paddingStyles(style: Record<string, unknown>): {\n styles: BlockStyles;\n} {\n return { styles: { padding: parsePadding(style) } };\n}\n\nfunction finish(\n block: Block,\n attrs: Record<string, unknown>,\n entry: ImportReportEntry,\n): Converted {\n const visibility = readVisibility(attrs);\n if (visibility) block.visibility = visibility;\n return { block, entry };\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction report(\n sourceTag: string,\n templaticalBlockType: string,\n status: ConversionStatus,\n note?: string,\n): ImportReportEntry {\n return {\n sourceTag,\n templaticalBlockType,\n status,\n ...(note ? { note } : {}),\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction firstSetContent(...values: unknown[]): string {\n for (const value of values) {\n if (isUnset(value)) continue;\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n }\n return \"\";\n}\n\nfunction resolvedWidth(\n style: Record<string, unknown>,\n columnWidth: number,\n): number | \"full\" | undefined {\n const px = parsePx(styleValue(style, \"width\"));\n if (px === undefined) return undefined;\n return px >= columnWidth ? \"full\" : px;\n}\n\nfunction asLineStyle(\n value: unknown,\n): \"solid\" | \"dashed\" | \"dotted\" | undefined {\n if (typeof value !== \"string\") return undefined;\n const v = value.trim().toLowerCase();\n return v === \"solid\" || v === \"dashed\" || v === \"dotted\" ? v : undefined;\n}\n\nfunction typedTitleLevel(subType: string): HeadingLevel | undefined {\n if (subType === \"title\" || subType === \"heading1\") return 1;\n if (subType === \"heading2\") return 2;\n if (subType === \"heading3\") return 3;\n return undefined;\n}\n\nfunction headingLooks(\n style: Record<string, unknown>,\n level: HeadingLevel,\n ctx: MapContext,\n): { color?: string; fontFamily?: string } {\n const nested = readNested(style[`h${level}`], ctx);\n const color = parseColor(style[`h${level}Color`] ?? nested.color);\n const fontFamily = fontStack(\n style[`h${level}FontFamily`] ?? nested.fontFamily,\n );\n return {\n ...(color ? { color } : {}),\n ...(fontFamily ? { fontFamily } : {}),\n };\n}\n\nfunction readNested(value: unknown, ctx: MapContext): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n const out: Record<string, unknown> = {};\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n const unwrapped = unwrapValue(raw, ctx.variables, ctx.stats);\n if (isUnset(unwrapped)) continue;\n out[camelKey(key)] = unwrapped;\n }\n return out;\n}\n\nfunction alignFromMarkup(html: string | undefined): string | undefined {\n if (!html) return undefined;\n const match = /text-align\\s*:\\s*(left|center|right)/i.exec(html);\n return match?.[1]?.toLowerCase();\n}\n","import type { ColumnLayout } from \"@templatical/types\";\n\nconst LAYOUT_SHAPES: Array<{ layout: ColumnLayout; percents: number[] }> = [\n { layout: \"1\", percents: [100] },\n { layout: \"2\", percents: [50, 50] },\n { layout: \"1-2\", percents: [33.33, 66.67] },\n { layout: \"2-1\", percents: [66.67, 33.33] },\n { layout: \"3\", percents: [33.33, 33.33, 33.34] },\n];\n\nconst WIDTH_TOLERANCE = 2;\n\nexport const COLUMN_COUNT: Record<ColumnLayout, number> = {\n \"1\": 1,\n \"2\": 2,\n \"3\": 3,\n \"2-1\": 2,\n \"1-2\": 2,\n};\n\nexport function columnPixels(\n layout: ColumnLayout,\n container: number,\n): number[] {\n switch (layout) {\n case \"2\":\n return [container / 2, container / 2];\n case \"3\":\n return [container / 3, container / 3, container / 3];\n case \"1-2\":\n return [container / 3, (container * 2) / 3];\n case \"2-1\":\n return [(container * 2) / 3, container / 3];\n default:\n return [container];\n }\n}\n\n/**\n * Resolve column widths to one of the five layouts `ColumnLayout` allows.\n *\n * `exact: false` means the caller reports `approximated` — Chamaileon permits\n * any column count at any width and this union permits five shapes, so this is\n * the importer's main irreducible loss.\n */\nexport function matchColumnLayout(percents: Array<number | null>): {\n layout: ColumnLayout;\n exact: boolean;\n} {\n const count = percents.length;\n if (count === 0) return { layout: \"1\", exact: true };\n\n // All-unset is \"distribute equally\", which is exactly what the n-column\n // layout means — not a missing value to approximate around.\n if (percents.every((p) => p === null)) {\n if (count === 1) return { layout: \"1\", exact: true };\n if (count === 2) return { layout: \"2\", exact: true };\n if (count === 3) return { layout: \"3\", exact: true };\n return { layout: \"3\", exact: false };\n }\n\n const known = percents.filter((p): p is number => p !== null);\n const unsetCount = count - known.length;\n const remainder =\n unsetCount === 0\n ? 0\n : Math.max(0, 100 - known.reduce((a, b) => a + b, 0)) / unsetCount;\n const resolved = percents.map((p) => p ?? remainder);\n\n const sameCount = LAYOUT_SHAPES.filter((s) => s.percents.length === count);\n\n for (const shape of sameCount) {\n if (\n shape.percents.every(\n (want, i) => Math.abs(want - resolved[i]) <= WIDTH_TOLERANCE,\n )\n ) {\n return { layout: shape.layout, exact: true };\n }\n }\n\n const candidates =\n sameCount.length > 0\n ? sameCount\n : LAYOUT_SHAPES.filter((s) => s.layout === \"3\");\n\n let best = candidates[0];\n let bestError = Infinity;\n for (const shape of candidates) {\n const error = shape.percents.reduce(\n (sum, want, i) => sum + Math.abs(want - (resolved[i] ?? 0)),\n 0,\n );\n if (error < bestError) {\n bestError = error;\n best = shape;\n }\n }\n\n return { layout: best.layout, exact: false };\n}\n\n/** Convert absolute px column widths to percents of `bodyWidth`. */\nexport function widthsToPercents(\n widthsPx: Array<number | undefined>,\n bodyWidth: number,\n): Array<number | null> {\n return widthsPx.map((w) => (w === undefined ? null : (w / bodyWidth) * 100));\n}\n","import { createSectionBlock } from \"@templatical/types\";\nimport type { Block, BlockVisibility, SpacingValue } from \"@templatical/types\";\nimport { parseColor, parsePadding, parsePx } from \"./attribute-parser\";\nimport {\n convertLeaf,\n isLoopType,\n markLoopApproximated,\n readLoopExpression,\n skippedLoopEntry,\n type MapContext,\n} from \"./block-mapper\";\nimport {\n COLUMN_COUNT,\n columnPixels,\n matchColumnLayout,\n widthsToPercents,\n} from \"./column-layout\";\nimport { readAttrs, readStyle, styleValue } from \"./normalize\";\nimport type { ChamaileonNode, ImportReportEntry } from \"./types\";\n\n/**\n * Build a `SectionBlock` from a Chamaileon `fullwidth`. Returns an array so\n * an empty fullwidth produces nothing.\n *\n * Boxes flatten into the parent. A nested `multicolumn` flattens into the\n * parent column — never a nested `type: \"section\"`.\n */\nexport function buildFullwidth(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n): Block[] {\n const style = readStyle(node, ctx.variables, ctx.stats);\n const attrs = readAttrs(node, ctx.variables, ctx.stats);\n const contentFill = parseColor(styleValue(style, \"contentBackgroundColor\"));\n const outerFill = parseColor(styleValue(style, \"backgroundColor\"));\n\n const original = node.children ?? [];\n const sole = original.length === 1 ? original[0] : undefined;\n const copySoleFill =\n sole?.type === \"box\" &&\n isPaintedBox(sole, ctx) &&\n contentFill === undefined;\n\n const flattened = flattenBoxes(\n original,\n ctx,\n entries,\n copySoleFill ? sole : undefined,\n );\n if (flattened.length === 0) return [];\n\n const mcIndex = flattened.findIndex((child) => child.type === \"multicolumn\");\n const reasons: string[] = [];\n\n const section = createSectionBlock();\n\n if (mcIndex === -1) {\n section.columns = \"1\";\n section.children = [\n convertColumnChildren(\n flattened,\n withColumnWidth(ctx, ctx.bodyWidth),\n entries,\n ),\n ];\n } else {\n const driving = flattened[mcIndex];\n const before = flattened.slice(0, mcIndex);\n const after = flattened.slice(mcIndex + 1);\n if (before.length > 0 || after.length > 0) {\n reasons.push(\n \"fullwidth mixes a multicolumn with sibling leaves; siblings were placed in column 0.\",\n );\n }\n\n const columns = (driving.children ?? []).filter(\n (child) => child.type === \"column\",\n );\n const widthsPx = columns.map((column) =>\n parsePx(styleValue(readStyle(column, ctx.variables, ctx.stats), \"width\")),\n );\n const { layout, exact } = matchColumnLayout(\n widthsToPercents(widthsPx, ctx.bodyWidth),\n );\n if (!exact) {\n reasons.push(\n `Column widths ${formatWidths(widthsPx)} have no exact Templatical layout; resolved to \"${layout}\".`,\n );\n }\n\n const stacking = asString(\n readAttrs(driving, ctx.variables, ctx.stats).stacking,\n );\n if (stacking === \"none\") {\n section.stackOnMobile = false;\n } else if (stacking !== undefined && stacking !== \"left-on-top\") {\n reasons.push(`unknown stacking \"${stacking}\" omitted`);\n }\n\n const slots = COLUMN_COUNT[layout];\n const pixels = columnPixels(layout, ctx.bodyWidth);\n const children: Block[][] = Array.from({ length: slots }, () => []);\n const slotCtx = (slot: number): MapContext =>\n withColumnWidth(ctx, Math.round(pixels[slot] ?? ctx.bodyWidth));\n\n children[0].push(...convertColumnChildren(before, slotCtx(0), entries));\n columns.forEach((column, index) => {\n const slot = Math.min(index, slots - 1);\n children[slot].push(\n ...convertColumnChildren(column.children ?? [], slotCtx(slot), entries),\n );\n });\n children[0].push(...convertColumnChildren(after, slotCtx(0), entries));\n\n section.columns = layout;\n section.children = children;\n }\n\n const soleFill = copySoleFill\n ? parseColor(\n styleValue(\n readStyle(sole, ctx.variables, ctx.stats),\n \"backgroundColor\",\n ),\n )\n : undefined;\n const fill = contentFill ?? soleFill;\n\n section.styles.padding = contentPadding(style);\n if (fill) section.styles.backgroundColor = fill;\n if (outerFill) section.wrapper = { backgroundColor: outerFill };\n\n const visibility = readVisibility(attrs);\n if (visibility) section.visibility = visibility;\n\n entries.push({\n sourceTag: \"fullwidth\",\n templaticalBlockType: \"section\",\n status: reasons.length > 0 ? \"approximated\" : \"converted\",\n ...(reasons.length > 0 ? { note: reasons.join(\" \") } : {}),\n });\n\n return [section];\n}\n\nfunction flattenBoxes(\n nodes: ChamaileonNode[],\n ctx: MapContext,\n entries: ImportReportEntry[],\n silent: ChamaileonNode | undefined,\n): ChamaileonNode[] {\n const out: ChamaileonNode[] = [];\n for (const child of nodes) {\n if (child.type === \"placeholder\") continue;\n if (child.type !== \"box\") {\n out.push(child);\n continue;\n }\n if (child !== silent && isPaintedBox(child, ctx)) {\n reportPaintedBox(child, ctx, entries);\n }\n out.push(...flattenBoxes(child.children ?? [], ctx, entries, undefined));\n }\n return out;\n}\n\nfunction convertColumnChildren(\n nodes: ChamaileonNode[],\n ctx: MapContext,\n entries: ImportReportEntry[],\n): Block[] {\n const blocks: Block[] = [];\n for (const child of nodes) {\n if (child.type === \"placeholder\") continue;\n if (child.type === \"box\") {\n if (isPaintedBox(child, ctx)) reportPaintedBox(child, ctx, entries);\n blocks.push(...convertColumnChildren(child.children ?? [], ctx, entries));\n continue;\n }\n if (child.type === \"multicolumn\") {\n const innerColumns = (child.children ?? []).filter(\n (column) => column.type === \"column\",\n );\n entries.push({\n sourceTag: \"multicolumn\",\n templaticalBlockType: null,\n status: \"approximated\",\n note: `nested multicolumn flattened (${innerColumns.length} columns)`,\n });\n for (const column of innerColumns) {\n blocks.push(\n ...convertColumnChildren(column.children ?? [], ctx, entries),\n );\n }\n continue;\n }\n if (child.type === \"column\") {\n blocks.push(...convertColumnChildren(child.children ?? [], ctx, entries));\n continue;\n }\n if (isLoopType(child.type)) {\n const type = child.type ?? \"loop\";\n const expression = readLoopExpression(child, ctx);\n const kids = child.children ?? [];\n if (kids.length === 0) {\n entries.push(skippedLoopEntry(type, expression));\n continue;\n }\n const from = entries.length;\n blocks.push(...convertColumnChildren(kids, ctx, entries));\n markLoopApproximated(entries, from, type, expression);\n continue;\n }\n const converted = convertLeaf(child, ctx);\n entries.push(converted.entry);\n if (converted.block) blocks.push(converted.block);\n }\n return blocks;\n}\n\nfunction isPaintedBox(node: ChamaileonNode, ctx: MapContext): boolean {\n const style = readStyle(node, ctx.variables, ctx.stats);\n if (parseColor(styleValue(style, \"backgroundColor\"))) return true;\n const padding = parsePadding(style);\n if (\n padding.top !== 0 ||\n padding.right !== 0 ||\n padding.bottom !== 0 ||\n padding.left !== 0\n ) {\n return true;\n }\n const radius = parsePx(styleValue(style, \"borderRadius\"));\n return radius !== undefined && radius > 0;\n}\n\nfunction reportPaintedBox(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n): void {\n const fill = parseColor(\n styleValue(readStyle(node, ctx.variables, ctx.stats), \"backgroundColor\"),\n );\n entries.push({\n sourceTag: \"box\",\n templaticalBlockType: null,\n status: \"approximated\",\n note: fill ? `box fill ${fill} dropped` : \"box padding/radius dropped\",\n });\n}\n\nfunction contentPadding(style: Record<string, unknown>): SpacingValue {\n return {\n top: parsePx(styleValue(style, \"contentPaddingTop\")) ?? 0,\n right: parsePx(styleValue(style, \"contentPaddingRight\")) ?? 0,\n bottom: parsePx(styleValue(style, \"contentPaddingBottom\")) ?? 0,\n left: parsePx(styleValue(style, \"contentPaddingLeft\")) ?? 0,\n };\n}\n\nfunction withColumnWidth(ctx: MapContext, columnWidth: number): MapContext {\n return { ...ctx, columnWidth };\n}\n\nfunction formatWidths(widthsPx: Array<number | undefined>): string {\n return widthsPx\n .map((width) => (width === undefined ? \"auto\" : `${width}px`))\n .join(\", \");\n}\n\nfunction readVisibility(\n attrs: Record<string, unknown>,\n): BlockVisibility | undefined {\n const hideOnMobile = attrs.hideOnMobile === true;\n const hideOnDesktop = attrs.hideOnDesktop === true;\n if (!hideOnMobile && !hideOnDesktop) return undefined;\n return { desktop: !hideOnDesktop, mobile: !hideOnMobile };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n","import {\n createDefaultTemplateContent,\n DEFAULT_TEMPLATE_DEFAULTS,\n} from \"@templatical/types\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport { parseColor, parsePx } from \"./attribute-parser\";\nimport {\n convertLeaf,\n isLoopType,\n markLoopApproximated,\n readLoopExpression,\n skippedLoopEntry,\n type MapContext,\n} from \"./block-mapper\";\nimport { readStyle, styleValue } from \"./normalize\";\nimport { buildFullwidth } from \"./section-builder\";\nimport type {\n ChamaileonDocument,\n ChamaileonNode,\n ImportReportEntry,\n ImportResult,\n} from \"./types\";\n\nconst INVALID_MESSAGE =\n \"Invalid Chamaileon template: expected the document JSON object from getDocument().\";\nconst WRONG_BODY_MESSAGE =\n 'Invalid Chamaileon template: expected body.type to be \"body\".';\nconst EMPTY_WARNING =\n \"No convertible content was found in the Chamaileon document. Check that body.children holds at least one fullwidth.\";\n\n/**\n * `DEFAULT_TEMPLATE_DEFAULTS` is typed `Partial<TemplateSettings>` so a\n * consumer can override any subset, but its own literal always sets the six\n * required fields. Narrowing once here is what lets each fallback come out as\n * `number`/`string`/`boolean` rather than `| undefined`.\n */\nconst REQUIRED_DEFAULTS = DEFAULT_TEMPLATE_DEFAULTS as Required<\n Pick<\n TemplateSettings,\n | \"width\"\n | \"backgroundColor\"\n | \"textColor\"\n | \"linkUnderline\"\n | \"fontFamily\"\n | \"locale\"\n >\n>;\n\n/**\n * Convert a Chamaileon `getDocument()` tree into a Templatical template.\n *\n * The input is the document object itself — `{ body, variables?, … }` —\n * not `getEmailHtml()` markup and not an API envelope. That is documented\n * rather than sniffed: guessing between the persist JSON and compiled HTML\n * would send the HTML through the wrong package.\n *\n * @example\n * ```ts\n * const document = await editorInstance.methods.getDocument();\n * const { content, report } = convertChamaileonTemplate(document);\n * ```\n */\nexport function convertChamaileonTemplate(\n doc: ChamaileonDocument | string,\n): ImportResult {\n const root: unknown = typeof doc === \"string\" ? safeParse(doc) : doc;\n\n if (typeof root !== \"object\" || root === null || Array.isArray(root)) {\n throw new Error(INVALID_MESSAGE);\n }\n\n const document = root as ChamaileonDocument;\n const body = document.body;\n if (!body || body.type !== \"body\") {\n throw new Error(WRONG_BODY_MESSAGE);\n }\n\n const entries: ImportReportEntry[] = [];\n const warnings: string[] = [];\n const blocks: Block[] = [];\n const stats = { resolvedVariables: 0 };\n const variables = document.variables ?? [];\n\n const bodyStyle = readStyle(body, variables, stats);\n const width =\n parsePx(styleValue(bodyStyle, \"bodyWidth\")) ?? REQUIRED_DEFAULTS.width;\n const backgroundColor =\n parseColor(styleValue(bodyStyle, \"backgroundColor\")) ??\n REQUIRED_DEFAULTS.backgroundColor;\n\n const previewRaw =\n typeof document.previewText === \"string\" ? document.previewText.trim() : \"\";\n const subjectRaw =\n typeof document.subjectLine === \"string\" ? document.subjectLine.trim() : \"\";\n if (subjectRaw) {\n warnings.push(\n `Dropped subjectLine (\"${document.subjectLine}\") — Templatical templates have no subject-line field.`,\n );\n }\n\n const fontFiles = document.fontFiles;\n if (\n fontFiles &&\n typeof fontFiles === \"object\" &&\n !Array.isArray(fontFiles) &&\n Object.keys(fontFiles).length > 0\n ) {\n warnings.push(\n \"Dropped fontFiles — Templatical templates have no document-level font-file table.\",\n );\n }\n\n const ctx: MapContext = {\n bodyWidth: width,\n columnWidth: width,\n variables,\n warnings,\n stats,\n };\n\n for (const child of body.children ?? []) {\n convertBodyChild(child, ctx, entries, blocks);\n }\n\n if (stats.resolvedVariables > 0) {\n warnings.push(\n `Resolved ${stats.resolvedVariables} colour/image variables to their default values.`,\n );\n }\n\n if (blocks.length === 0) {\n warnings.push(EMPTY_WARNING);\n }\n\n const defaults = createDefaultTemplateContent();\n const content: TemplateContent = {\n ...defaults,\n blocks,\n settings: {\n ...defaults.settings,\n width,\n backgroundColor,\n ...(previewRaw ? { preheaderText: previewRaw } : {}),\n },\n };\n\n const summary = {\n total: entries.length,\n converted: entries.filter((e) => e.status === \"converted\").length,\n approximated: entries.filter((e) => e.status === \"approximated\").length,\n htmlFallback: entries.filter((e) => e.status === \"html-fallback\").length,\n skipped: entries.filter((e) => e.status === \"skipped\").length,\n };\n\n return { content, report: { entries, warnings, summary } };\n}\n\nfunction convertBodyChild(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n blocks: Block[],\n): void {\n if (node.type === \"fullwidth\") {\n blocks.push(...buildFullwidth(node, ctx, entries));\n return;\n }\n if (isLoopType(node.type)) {\n convertLoop(node, ctx, entries, blocks);\n return;\n }\n const converted = convertLeaf(node, ctx);\n entries.push(converted.entry);\n if (converted.block) blocks.push(converted.block);\n}\n\nfunction convertLoop(\n node: ChamaileonNode,\n ctx: MapContext,\n entries: ImportReportEntry[],\n blocks: Block[],\n): void {\n const type = node.type ?? \"loop\";\n const expression = readLoopExpression(node, ctx);\n const children = node.children ?? [];\n if (children.length === 0) {\n entries.push(skippedLoopEntry(type, expression));\n return;\n }\n const from = entries.length;\n for (const child of children) {\n convertBodyChild(child, ctx, entries, blocks);\n }\n markLoopApproximated(entries, from, type, expression);\n}\n\nfunction safeParse(source: string): unknown {\n try {\n return JSON.parse(source);\n } catch {\n throw new Error(INVALID_MESSAGE);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@templatical/import-chamaileon",
|
|
3
3
|
"description": "Convert Chamaileon email templates to Templatical format",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.46.0",
|
|
5
5
|
"bugs": "https://github.com/templatical/sdk/issues",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@templatical/types": "0.
|
|
7
|
+
"@templatical/types": "0.46.0"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@types/node": "^25.9.9",
|