@samva/markup 0.1.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.
Files changed (124) hide show
  1. package/AGENTS.md +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +41 -0
  4. package/dist/ast-DAhnAvQN.d.ts +120 -0
  5. package/dist/ast.d.ts +2 -0
  6. package/dist/ast.js +159 -0
  7. package/dist/ast.js.map +1 -0
  8. package/dist/candidate.d.ts +29 -0
  9. package/dist/candidate.js +88 -0
  10. package/dist/candidate.js.map +1 -0
  11. package/dist/checks-CW0nFj5n.js +58922 -0
  12. package/dist/checks-CW0nFj5n.js.map +1 -0
  13. package/dist/checks.d.ts +26 -0
  14. package/dist/checks.js +2 -0
  15. package/dist/classes.d.ts +27 -0
  16. package/dist/classes.js +184 -0
  17. package/dist/classes.js.map +1 -0
  18. package/dist/compile-sms.d.ts +28 -0
  19. package/dist/compile-sms.js +44 -0
  20. package/dist/compile-sms.js.map +1 -0
  21. package/dist/compile-whatsapp.d.ts +56 -0
  22. package/dist/compile-whatsapp.js +186 -0
  23. package/dist/compile-whatsapp.js.map +1 -0
  24. package/dist/compile.d.ts +93 -0
  25. package/dist/compile.js +938 -0
  26. package/dist/compile.js.map +1 -0
  27. package/dist/components.d.ts +289 -0
  28. package/dist/components.js +106 -0
  29. package/dist/components.js.map +1 -0
  30. package/dist/conditionals.d.ts +10 -0
  31. package/dist/conditionals.js +42 -0
  32. package/dist/conditionals.js.map +1 -0
  33. package/dist/diagnostics-oveE-laV.d.ts +79 -0
  34. package/dist/diagnostics.d.ts +2 -0
  35. package/dist/diagnostics.js +62 -0
  36. package/dist/diagnostics.js.map +1 -0
  37. package/dist/emit.d.ts +50 -0
  38. package/dist/emit.js +151 -0
  39. package/dist/emit.js.map +1 -0
  40. package/dist/footer.d.ts +66 -0
  41. package/dist/footer.js +90 -0
  42. package/dist/footer.js.map +1 -0
  43. package/dist/interpolate.d.ts +27 -0
  44. package/dist/interpolate.js +61 -0
  45. package/dist/interpolate.js.map +1 -0
  46. package/dist/jsx-dev-runtime.d.ts +10 -0
  47. package/dist/jsx-dev-runtime.js +7 -0
  48. package/dist/jsx-dev-runtime.js.map +1 -0
  49. package/dist/jsx-runtime-fSxcvlx4.d.ts +57 -0
  50. package/dist/jsx-runtime.d.ts +2 -0
  51. package/dist/jsx-runtime.js +102 -0
  52. package/dist/jsx-runtime.js.map +1 -0
  53. package/dist/lexer.d.ts +60 -0
  54. package/dist/lexer.js +269 -0
  55. package/dist/lexer.js.map +1 -0
  56. package/dist/model.d.ts +39 -0
  57. package/dist/model.js +90 -0
  58. package/dist/model.js.map +1 -0
  59. package/dist/ops.d.ts +208 -0
  60. package/dist/ops.js +546 -0
  61. package/dist/ops.js.map +1 -0
  62. package/dist/parser-yzjUOGhc.d.ts +387 -0
  63. package/dist/parser.d.ts +2 -0
  64. package/dist/parser.js +821 -0
  65. package/dist/parser.js.map +1 -0
  66. package/dist/predicate-DTtVtLK7.d.ts +49 -0
  67. package/dist/predicate.d.ts +2 -0
  68. package/dist/predicate.js +417 -0
  69. package/dist/predicate.js.map +1 -0
  70. package/dist/presets/category-mapping.d.ts +13 -0
  71. package/dist/presets/category-mapping.js +49 -0
  72. package/dist/presets/category-mapping.js.map +1 -0
  73. package/dist/presets/public-gallery.d.ts +490 -0
  74. package/dist/presets/public-gallery.js +563 -0
  75. package/dist/presets/public-gallery.js.map +1 -0
  76. package/dist/presets/public-handoff.d.ts +68 -0
  77. package/dist/presets/public-handoff.js +105 -0
  78. package/dist/presets/public-handoff.js.map +1 -0
  79. package/dist/presets/public-preview-artifacts.d.ts +41 -0
  80. package/dist/presets/public-preview-artifacts.js +109 -0
  81. package/dist/presets/public-preview-artifacts.js.map +1 -0
  82. package/dist/presets/public-preview.d.ts +1168 -0
  83. package/dist/presets/public-preview.js +1158 -0
  84. package/dist/presets/public-preview.js.map +1 -0
  85. package/dist/presets/sources.d.ts +7 -0
  86. package/dist/presets/sources.js +54 -0
  87. package/dist/presets/sources.js.map +1 -0
  88. package/dist/presets.d.ts +350 -0
  89. package/dist/presets.js +1251 -0
  90. package/dist/presets.js.map +1 -0
  91. package/dist/printer.d.ts +6 -0
  92. package/dist/printer.js +122 -0
  93. package/dist/printer.js.map +1 -0
  94. package/dist/registry.d.ts +42 -0
  95. package/dist/registry.js +646 -0
  96. package/dist/registry.js.map +1 -0
  97. package/dist/render-template.d.ts +42 -0
  98. package/dist/render-template.js +74 -0
  99. package/dist/render-template.js.map +1 -0
  100. package/dist/sms-segments-y4FpPilJ.d.ts +13 -0
  101. package/dist/sms-segments.d.ts +2 -0
  102. package/dist/sms-segments.js +46 -0
  103. package/dist/sms-segments.js.map +1 -0
  104. package/dist/theme-6ApjjiBo.d.ts +116 -0
  105. package/dist/theme-css.d.ts +24 -0
  106. package/dist/theme-css.js +509 -0
  107. package/dist/theme-css.js.map +1 -0
  108. package/dist/theme.d.ts +2 -0
  109. package/dist/theme.js +95 -0
  110. package/dist/theme.js.map +1 -0
  111. package/dist/tokens.d.ts +6 -0
  112. package/dist/tokens.js +417 -0
  113. package/dist/tokens.js.map +1 -0
  114. package/dist/variables-3NGLpNTB.d.ts +77 -0
  115. package/dist/variables.d.ts +2 -0
  116. package/dist/variables.js +141 -0
  117. package/dist/variables.js.map +1 -0
  118. package/dist/version-BITr58kk.js +96 -0
  119. package/dist/version-BITr58kk.js.map +1 -0
  120. package/generated/sml-agent-contract.json +917 -0
  121. package/generated/sml-email-agent-contract.json +790 -0
  122. package/generated/sml-email-language-reference.md +160 -0
  123. package/generated/sml-language-reference.md +220 -0
  124. package/package.json +203 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-whatsapp.js","names":[],"sources":["../src/compile-whatsapp.ts"],"sourcesContent":["import { Result } from \"effect\";\n\nimport type { ElementNode } from \"./ast\";\nimport { stringAttribute } from \"./ast\";\nimport type { InterpolationWidth } from \"./channel-text\";\nimport { channelTextVariants, flattenChannelText } from \"./channel-text\";\nimport type { Diagnostic } from \"./diagnostics\";\nimport { SmlCompileError } from \"./diagnostics\";\nimport { variableReferences } from \"./interpolate\";\nimport type { WHATSAPP_TAG_SPECS } from \"./parser\";\nimport { COMPILER_VERSION } from \"./version\";\n\n// The whatsapp compile backend: a <WhatsApp> document lowers 1:1 onto the\n// whatsapp_template_variants columns (name/language/category, header parts,\n// body/footer content, buttons jsonb, examples jsonb). Text slots carry\n// literal `{{vars}}` and `sml:` conditional markers like every other channel's\n// compiled content; provider registration payloads are the API layer's job.\n//\n// Meta constraints ride along as diagnostics, ported from @samva/document\n// channel-checks and the dashboard editor rather than re-derived from Meta's\n// docs: length limits (header/footer 60, body 1024, button text 25) are\n// warnings (the advisory posture channel-checks had); button count limits and\n// per-type attribute requirements are hard errors (the dashboard editor\n// blocked those outright).\n// @see https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/components/\n\ntype WhatsAppSpecs = typeof WHATSAPP_TAG_SPECS;\n\n/** Mirrors whatsappTemplateCategoryEnum, derived from the grammar's closed set. */\nexport type WhatsAppTemplateCategory =\n WhatsAppSpecs[\"WhatsApp\"][\"attributes\"][\"category\"][\"values\"][number];\n\n/** Header type as authored (`type` attribute; defaults to \"text\"). */\nexport type WhatsAppHeaderType = WhatsAppSpecs[\"Header\"][\"attributes\"][\"type\"][\"values\"][number];\n\nexport type WhatsAppHeaderMediaType = Exclude<WhatsAppHeaderType, \"text\">;\n\ntype WhatsAppButtonSourceType = WhatsAppSpecs[\"Button\"][\"attributes\"][\"type\"][\"values\"][number];\n\n/** Meta-wire button rows, stored as-is in the buttons jsonb column. */\nexport type WhatsAppButtonPayload =\n | { readonly type: \"QUICK_REPLY\"; readonly text: string }\n | { readonly type: \"URL\"; readonly text: string; readonly url: string }\n | { readonly type: \"PHONE_NUMBER\"; readonly text: string; readonly phone_number: string }\n | { readonly type: \"COPY_CODE\"; readonly example: string };\n\n/** Variable names referenced per slot — the raw material for Meta example payloads. */\nexport interface WhatsAppExamples {\n readonly header?: ReadonlyArray<string> | undefined;\n readonly body?: ReadonlyArray<string> | undefined;\n readonly footer?: ReadonlyArray<string> | undefined;\n readonly buttons?: ReadonlyArray<string> | undefined;\n}\n\nexport interface CompiledWhatsApp {\n readonly channel: \"whatsapp\";\n /** Authoring-intent metadata; the API layer defaults name from the template slug. */\n readonly name?: string | undefined;\n /** The API layer defaults language from the variant locale (\"en_US\"). */\n readonly language?: string | undefined;\n readonly category: WhatsAppTemplateCategory;\n readonly headerType?: WhatsAppHeaderType | undefined;\n readonly headerMediaType?: WhatsAppHeaderMediaType | undefined;\n readonly headerContent?: string | undefined;\n readonly bodyContent: string;\n readonly footerContent?: string | undefined;\n readonly buttons: ReadonlyArray<WhatsAppButtonPayload>;\n readonly examples: WhatsAppExamples;\n readonly warnings: ReadonlyArray<Diagnostic>;\n readonly compilerVersion: string;\n}\n\n// Meta message-template limits, ported from @samva/document channel-checks.\nconst WHATSAPP_BUTTON_LIMITS = {\n URL: 2,\n PHONE_NUMBER: 1,\n QUICK_REPLY: 10,\n total: 10,\n} as const;\n\nconst WHATSAPP_HEADER_MAX = 60;\nconst WHATSAPP_FOOTER_MAX = 60;\nconst WHATSAPP_BODY_MAX = 1024;\nconst WHATSAPP_BUTTON_TEXT_MAX = 25;\n\nconst POSITIONAL_PATTERN = /\\{\\{\\s*(\\d+)\\s*\\}\\}/;\nconst NAMED_PATTERN = /\\{\\{\\s*([A-Za-z_][\\w.]*)\\s*\\}\\}/;\n\nconst LITERAL: InterpolationWidth = \"literal\";\n\n/** Longest possible send-time rendering of a slot, with literal placeholders. */\nconst worstCaseLength = (node: ElementNode): number =>\n Math.max(0, ...channelTextVariants(node.children, LITERAL).map((variant) => variant.length));\n\nconst component = (root: ElementNode, tag: string): ElementNode | undefined =>\n root.children.find(\n (child): child is ElementNode => child.kind === \"element\" && child.tag === tag,\n );\n\nconst slotExamples = (texts: ReadonlyArray<string>): ReadonlyArray<string> | undefined => {\n const names = new Set<string>();\n for (const text of texts) {\n for (const name of variableReferences(text)) names.add(name);\n }\n return names.size === 0 ? undefined : [...names].sort();\n};\n\n/** Root is a parsed `<WhatsApp>` element; the grammar already validated its anatomy. */\nexport const compileWhatsAppRoot = (\n root: ElementNode,\n): Result.Result<CompiledWhatsApp, SmlCompileError> => {\n const errors: Array<Diagnostic> = [];\n const warnings: Array<Diagnostic> = [];\n\n const header = component(root, \"Header\");\n const body = component(root, \"Body\")!; // grammar: <Body> is required\n const footer = component(root, \"Footer\");\n const buttonsNode = component(root, \"Buttons\");\n\n const headerType =\n header === undefined\n ? undefined\n : ((stringAttribute(header, \"type\") ?? \"text\") as WhatsAppHeaderType);\n const headerContent = header === undefined ? undefined : flattenChannelText(header.children);\n const bodyContent = flattenChannelText(body.children);\n const footerContent = footer === undefined ? undefined : flattenChannelText(footer.children);\n\n // ── Length limits (ported advisory checks, now with spans) ────────────────\n if (\n header !== undefined &&\n headerType === \"text\" &&\n worstCaseLength(header) > WHATSAPP_HEADER_MAX\n ) {\n warnings.push({\n code: \"whatsapp-header-length\",\n message: `whatsapp header should stay under ${WHATSAPP_HEADER_MAX} characters`,\n span: header.span,\n });\n }\n if (worstCaseLength(body) > WHATSAPP_BODY_MAX) {\n warnings.push({\n code: \"whatsapp-body-length\",\n message: `whatsapp body should stay under ${WHATSAPP_BODY_MAX} characters`,\n span: body.span,\n });\n }\n if (footer !== undefined && worstCaseLength(footer) > WHATSAPP_FOOTER_MAX) {\n warnings.push({\n code: \"whatsapp-footer-length\",\n message: `whatsapp footer should stay under ${WHATSAPP_FOOTER_MAX} characters`,\n span: footer.span,\n });\n }\n\n // ── Buttons ────────────────────────────────────────────────────────────────\n const buttonElements =\n buttonsNode === undefined\n ? []\n : buttonsNode.children.filter(\n (child): child is ElementNode => child.kind === \"element\" && child.tag === \"Button\",\n );\n const buttons: Array<WhatsAppButtonPayload> = [];\n for (const button of buttonElements) {\n const type = stringAttribute(button, \"type\") as WhatsAppButtonSourceType;\n const text = flattenChannelText(button.children);\n const url = stringAttribute(button, \"url\");\n const phone = stringAttribute(button, \"phone\");\n\n if (url !== undefined && type !== \"url\") {\n errors.push({\n code: \"whatsapp-button-url\",\n message: `url is only valid on <Button type=\"url\"> — remove it or change the type`,\n span: button.span,\n });\n continue;\n }\n if (phone !== undefined && type !== \"phone\") {\n errors.push({\n code: \"whatsapp-button-phone\",\n message: `phone is only valid on <Button type=\"phone\"> — remove it or change the type`,\n span: button.span,\n });\n continue;\n }\n if (type !== \"copy-code\" && worstCaseLength(button) > WHATSAPP_BUTTON_TEXT_MAX) {\n warnings.push({\n code: \"whatsapp-button-text-length\",\n message: `whatsapp button text should stay under ${WHATSAPP_BUTTON_TEXT_MAX} characters`,\n span: button.span,\n });\n }\n switch (type) {\n case \"quick-reply\":\n buttons.push({ type: \"QUICK_REPLY\", text });\n break;\n case \"url\": {\n if (url === undefined) {\n errors.push({\n code: \"whatsapp-button-url\",\n message: `<Button type=\"url\"> requires a url attribute — add url=\"https://...\"`,\n span: button.span,\n });\n break;\n }\n buttons.push({ type: \"URL\", text, url });\n break;\n }\n case \"phone\": {\n if (phone === undefined) {\n errors.push({\n code: \"whatsapp-button-phone\",\n message: `<Button type=\"phone\"> requires a phone attribute — add phone=\"+15551234567\"`,\n span: button.span,\n });\n break;\n }\n buttons.push({ type: \"PHONE_NUMBER\", text, phone_number: phone });\n break;\n }\n case \"copy-code\":\n // The label is fixed by WhatsApp; the content is the code to copy.\n buttons.push({ type: \"COPY_CODE\", example: text });\n break;\n }\n }\n\n // Count limits (ported; the dashboard editor blocks these, so they are errors).\n const buttonsSpan = buttonsNode?.span ?? root.span;\n const countOf = (type: WhatsAppButtonPayload[\"type\"]): number =>\n buttons.filter((button) => button.type === type).length;\n if (countOf(\"URL\") > WHATSAPP_BUTTON_LIMITS.URL) {\n errors.push({\n code: \"whatsapp-button-limit\",\n message: `whatsapp allows at most ${WHATSAPP_BUTTON_LIMITS.URL} URL buttons`,\n span: buttonsSpan,\n });\n }\n if (countOf(\"PHONE_NUMBER\") > WHATSAPP_BUTTON_LIMITS.PHONE_NUMBER) {\n errors.push({\n code: \"whatsapp-button-limit\",\n message: `whatsapp allows at most ${WHATSAPP_BUTTON_LIMITS.PHONE_NUMBER} phone-number button`,\n span: buttonsSpan,\n });\n }\n if (countOf(\"QUICK_REPLY\") > WHATSAPP_BUTTON_LIMITS.QUICK_REPLY) {\n errors.push({\n code: \"whatsapp-button-limit\",\n message: `whatsapp allows at most ${WHATSAPP_BUTTON_LIMITS.QUICK_REPLY} quick-reply buttons`,\n span: buttonsSpan,\n });\n }\n if (buttonElements.length > WHATSAPP_BUTTON_LIMITS.total) {\n errors.push({\n code: \"whatsapp-button-limit\",\n message: `whatsapp allows at most ${WHATSAPP_BUTTON_LIMITS.total} buttons total`,\n span: buttonsSpan,\n });\n }\n\n // ── Placeholder style mixing (ported) ─────────────────────────────────────\n // Meta requires one placeholder style per template: positional {{1}} or\n // named {{var}}. Scan component text and dynamic button urls.\n const placeholderSources = [\n headerContent ?? \"\",\n bodyContent,\n footerContent ?? \"\",\n ...buttons.map((button) => (button.type === \"URL\" ? button.url : \"\")),\n ];\n const hasPositional = placeholderSources.some((source) => POSITIONAL_PATTERN.test(source));\n const hasNamed = placeholderSources.some((source) => NAMED_PATTERN.test(source));\n if (hasPositional && hasNamed) {\n warnings.push({\n code: \"whatsapp-mixed-placeholders\",\n message:\n \"whatsapp mixes positional {{1}} and named {{var}} placeholders; Meta requires one style\",\n span: root.span,\n });\n }\n\n if (errors.length > 0) {\n return Result.fail(new SmlCompileError({ diagnostics: errors }));\n }\n\n return Result.succeed({\n channel: \"whatsapp\",\n name: stringAttribute(root, \"name\"),\n language: stringAttribute(root, \"language\"),\n category: stringAttribute(root, \"category\") as WhatsAppTemplateCategory,\n headerType,\n headerMediaType:\n headerType === undefined || headerType === \"text\"\n ? undefined\n : (headerType satisfies WhatsAppHeaderMediaType),\n headerContent,\n bodyContent,\n footerContent,\n buttons,\n examples: {\n header: slotExamples([headerContent ?? \"\"]),\n body: slotExamples([bodyContent]),\n footer: slotExamples([footerContent ?? \"\"]),\n buttons: slotExamples(\n buttons.map((button) =>\n button.type === \"URL\"\n ? `${button.text} ${button.url}`\n : button.type === \"COPY_CODE\"\n ? button.example\n : button.text,\n ),\n ),\n },\n warnings,\n compilerVersion: COMPILER_VERSION,\n });\n};\n"],"mappings":";;;;;;AAyEA,MAAM,yBAAyB;CAC7B,KAAK;CACL,cAAc;CACd,aAAa;CACb,OAAO;AACT;AAEA,MAAM,sBAAsB;AAC5B,MAAM,sBAAsB;AAC5B,MAAM,oBAAoB;AAC1B,MAAM,2BAA2B;AAEjC,MAAM,qBAAqB;AAC3B,MAAM,gBAAgB;AAEtB,MAAM,UAA8B;;AAGpC,MAAM,mBAAmB,SACvB,KAAK,IAAI,GAAG,GAAG,oBAAoB,KAAK,UAAU,OAAO,CAAC,CAAC,KAAK,YAAY,QAAQ,MAAM,CAAC;AAE7F,MAAM,aAAa,MAAmB,QACpC,KAAK,SAAS,MACX,UAAgC,MAAM,SAAS,aAAa,MAAM,QAAQ,GAC7E;AAEF,MAAM,gBAAgB,UAAoE;CACxF,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,QAAQ,OACjB,KAAK,MAAM,QAAQ,mBAAmB,IAAI,GAAG,MAAM,IAAI,IAAI;CAE7D,OAAO,MAAM,SAAS,IAAI,KAAA,IAAY,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK;AACxD;;AAGA,MAAa,uBACX,SACqD;CACrD,MAAM,SAA4B,CAAC;CACnC,MAAM,WAA8B,CAAC;CAErC,MAAM,SAAS,UAAU,MAAM,QAAQ;CACvC,MAAM,OAAO,UAAU,MAAM,MAAM;CACnC,MAAM,SAAS,UAAU,MAAM,QAAQ;CACvC,MAAM,cAAc,UAAU,MAAM,SAAS;CAE7C,MAAM,aACJ,WAAW,KAAA,IACP,KAAA,IACE,gBAAgB,QAAQ,MAAM,KAAK;CAC3C,MAAM,gBAAgB,WAAW,KAAA,IAAY,KAAA,IAAY,mBAAmB,OAAO,QAAQ;CAC3F,MAAM,cAAc,mBAAmB,KAAK,QAAQ;CACpD,MAAM,gBAAgB,WAAW,KAAA,IAAY,KAAA,IAAY,mBAAmB,OAAO,QAAQ;CAG3F,IACE,WAAW,KAAA,KACX,eAAe,UACf,gBAAgB,MAAM,IAAI,qBAE1B,SAAS,KAAK;EACZ,MAAM;EACN,SAAS,qCAAqC,oBAAoB;EAClE,MAAM,OAAO;CACf,CAAC;CAEH,IAAI,gBAAgB,IAAI,IAAI,mBAC1B,SAAS,KAAK;EACZ,MAAM;EACN,SAAS,mCAAmC,kBAAkB;EAC9D,MAAM,KAAK;CACb,CAAC;CAEH,IAAI,WAAW,KAAA,KAAa,gBAAgB,MAAM,IAAI,qBACpD,SAAS,KAAK;EACZ,MAAM;EACN,SAAS,qCAAqC,oBAAoB;EAClE,MAAM,OAAO;CACf,CAAC;CAIH,MAAM,iBACJ,gBAAgB,KAAA,IACZ,CAAC,IACD,YAAY,SAAS,QAClB,UAAgC,MAAM,SAAS,aAAa,MAAM,QAAQ,QAC7E;CACN,MAAM,UAAwC,CAAC;CAC/C,KAAK,MAAM,UAAU,gBAAgB;EACnC,MAAM,OAAO,gBAAgB,QAAQ,MAAM;EAC3C,MAAM,OAAO,mBAAmB,OAAO,QAAQ;EAC/C,MAAM,MAAM,gBAAgB,QAAQ,KAAK;EACzC,MAAM,QAAQ,gBAAgB,QAAQ,OAAO;EAE7C,IAAI,QAAQ,KAAA,KAAa,SAAS,OAAO;GACvC,OAAO,KAAK;IACV,MAAM;IACN,SAAS;IACT,MAAM,OAAO;GACf,CAAC;GACD;EACF;EACA,IAAI,UAAU,KAAA,KAAa,SAAS,SAAS;GAC3C,OAAO,KAAK;IACV,MAAM;IACN,SAAS;IACT,MAAM,OAAO;GACf,CAAC;GACD;EACF;EACA,IAAI,SAAS,eAAe,gBAAgB,MAAM,IAAI,0BACpD,SAAS,KAAK;GACZ,MAAM;GACN,SAAS,0CAA0C,yBAAyB;GAC5E,MAAM,OAAO;EACf,CAAC;EAEH,QAAQ,MAAR;GACE,KAAK;IACH,QAAQ,KAAK;KAAE,MAAM;KAAe;IAAK,CAAC;IAC1C;GACF,KAAK;IACH,IAAI,QAAQ,KAAA,GAAW;KACrB,OAAO,KAAK;MACV,MAAM;MACN,SAAS;MACT,MAAM,OAAO;KACf,CAAC;KACD;IACF;IACA,QAAQ,KAAK;KAAE,MAAM;KAAO;KAAM;IAAI,CAAC;IACvC;GAEF,KAAK;IACH,IAAI,UAAU,KAAA,GAAW;KACvB,OAAO,KAAK;MACV,MAAM;MACN,SAAS;MACT,MAAM,OAAO;KACf,CAAC;KACD;IACF;IACA,QAAQ,KAAK;KAAE,MAAM;KAAgB;KAAM,cAAc;IAAM,CAAC;IAChE;GAEF,KAAK,aAEH,QAAQ,KAAK;IAAE,MAAM;IAAa,SAAS;GAAK,CAAC;EAErD;CACF;CAGA,MAAM,cAAc,aAAa,QAAQ,KAAK;CAC9C,MAAM,WAAW,SACf,QAAQ,QAAQ,WAAW,OAAO,SAAS,IAAI,CAAC,CAAC;CACnD,IAAI,QAAQ,KAAK,IAAI,uBAAuB,KAC1C,OAAO,KAAK;EACV,MAAM;EACN,SAAS,2BAA2B,uBAAuB,IAAI;EAC/D,MAAM;CACR,CAAC;CAEH,IAAI,QAAQ,cAAc,IAAI,uBAAuB,cACnD,OAAO,KAAK;EACV,MAAM;EACN,SAAS,2BAA2B,uBAAuB,aAAa;EACxE,MAAM;CACR,CAAC;CAEH,IAAI,QAAQ,aAAa,IAAI,uBAAuB,aAClD,OAAO,KAAK;EACV,MAAM;EACN,SAAS,2BAA2B,uBAAuB,YAAY;EACvE,MAAM;CACR,CAAC;CAEH,IAAI,eAAe,SAAS,uBAAuB,OACjD,OAAO,KAAK;EACV,MAAM;EACN,SAAS,2BAA2B,uBAAuB,MAAM;EACjE,MAAM;CACR,CAAC;CAMH,MAAM,qBAAqB;EACzB,iBAAiB;EACjB;EACA,iBAAiB;EACjB,GAAG,QAAQ,KAAK,WAAY,OAAO,SAAS,QAAQ,OAAO,MAAM,EAAG;CACtE;CACA,MAAM,gBAAgB,mBAAmB,MAAM,WAAW,mBAAmB,KAAK,MAAM,CAAC;CACzF,MAAM,WAAW,mBAAmB,MAAM,WAAW,cAAc,KAAK,MAAM,CAAC;CAC/E,IAAI,iBAAiB,UACnB,SAAS,KAAK;EACZ,MAAM;EACN,SACE;EACF,MAAM,KAAK;CACb,CAAC;CAGH,IAAI,OAAO,SAAS,GAClB,OAAO,OAAO,KAAK,IAAI,gBAAgB,EAAE,aAAa,OAAO,CAAC,CAAC;CAGjE,OAAO,OAAO,QAAQ;EACpB,SAAS;EACT,MAAM,gBAAgB,MAAM,MAAM;EAClC,UAAU,gBAAgB,MAAM,UAAU;EAC1C,UAAU,gBAAgB,MAAM,UAAU;EAC1C;EACA,iBACE,eAAe,KAAA,KAAa,eAAe,SACvC,KAAA,IACC;EACP;EACA;EACA;EACA;EACA,UAAU;GACR,QAAQ,aAAa,CAAC,iBAAiB,EAAE,CAAC;GAC1C,MAAM,aAAa,CAAC,WAAW,CAAC;GAChC,QAAQ,aAAa,CAAC,iBAAiB,EAAE,CAAC;GAC1C,SAAS,aACP,QAAQ,KAAK,WACX,OAAO,SAAS,QACZ,GAAG,OAAO,KAAK,GAAG,OAAO,QACzB,OAAO,SAAS,cACd,OAAO,UACP,OAAO,IACf,CACF;EACF;EACA;EACA,iBAAiB;CACnB,CAAC;AACH"}
@@ -0,0 +1,93 @@
1
+ import { a as SmlCompileError, o as SmlParseError, t as Diagnostic } from "./diagnostics-oveE-laV.js";
2
+ import { C as SmlDocument } from "./ast-DAhnAvQN.js";
3
+ import { a as ThemeLayers, s as TokenTable } from "./theme-6ApjjiBo.js";
4
+ import { Declaration } from "./registry.js";
5
+ import { CompiledSms } from "./compile-sms.js";
6
+ import { CompiledWhatsApp } from "./compile-whatsapp.js";
7
+ import { Result } from "effect";
8
+ //#region src/version.d.ts
9
+ declare const COMPILER_VERSION = "0.1.0";
10
+ //#endregion
11
+ //#region src/compile.d.ts
12
+ type CompileBase = "outlook-safe" | "modern";
13
+ /** Email-only knobs; sms/whatsapp compile ignores both (no theming, no bases). */
14
+ interface CompileOptions {
15
+ readonly base?: CompileBase | undefined;
16
+ readonly theme?: (Omit<ThemeLayers, "base"> & {
17
+ readonly base?: TokenTable | undefined;
18
+ }) | undefined;
19
+ /** Omit editor DOM instrumentation from exported/sent HTML artifacts. */
20
+ readonly stripInstrumentation?: boolean | undefined;
21
+ }
22
+ interface CompiledEmail {
23
+ readonly channel: "email";
24
+ readonly html: string;
25
+ /** Plain-text alternative ({{vars}} verbatim, envelope metadata skipped). */
26
+ readonly text: string;
27
+ /** Authored <Subject> text with interpolation tokens preserved; null when absent. */
28
+ readonly subjectText: string | null;
29
+ readonly warnings: ReadonlyArray<Diagnostic>;
30
+ readonly base: CompileBase;
31
+ readonly compilerVersion: string;
32
+ }
33
+ /**
34
+ * The compile result, discriminated on `channel` — which the root tag
35
+ * declares. email → HTML + plain-text artifacts; sms → body + segment math;
36
+ * whatsapp → whatsapp_template_variants column shapes.
37
+ */
38
+ type CompiledTemplate = CompiledEmail | CompiledSms | CompiledWhatsApp;
39
+ interface HtmlElement {
40
+ readonly kind: "element";
41
+ readonly tag: string;
42
+ /** Ordered; serialized before style. */
43
+ readonly attrs: ReadonlyArray<readonly [string, string]>;
44
+ /** Serialized as style="" in order — CSS last-wins handles overrides. */
45
+ readonly style: ReadonlyArray<Declaration>;
46
+ readonly children: ReadonlyArray<HtmlNode>;
47
+ readonly void?: boolean | undefined;
48
+ }
49
+ type HtmlTextNode = {
50
+ readonly kind: "text";
51
+ readonly value: string;
52
+ };
53
+ type HtmlRawNode = {
54
+ readonly kind: "raw";
55
+ readonly html: string;
56
+ };
57
+ /** Children spliced into the parent's block flow — <If> lowers to one. */
58
+ interface HtmlFragment {
59
+ readonly kind: "fragment";
60
+ readonly children: ReadonlyArray<HtmlNode>;
61
+ }
62
+ type HtmlNode = HtmlElement | HtmlTextNode | HtmlRawNode | HtmlFragment;
63
+ interface CompileHeadStyleAsset {
64
+ readonly kind: "style";
65
+ readonly css: string;
66
+ /** Serialized style asset as emitted in <head>. */
67
+ readonly html: string;
68
+ /** True for the Outlook-hidden webfont style block. */
69
+ readonly outlookHidden: boolean;
70
+ }
71
+ interface CompileHeadAssets {
72
+ readonly styles: ReadonlyArray<CompileHeadStyleAsset>;
73
+ readonly links: ReadonlyArray<HtmlElement>;
74
+ }
75
+ type HtmlNodeIdMap = Readonly<Record<string, ReadonlyArray<HtmlElement>>>;
76
+ interface CompiledEmailArtifact extends CompiledEmail {
77
+ /** Resolved primary document width in pixels. */
78
+ readonly width: number;
79
+ readonly tree: HtmlElement;
80
+ readonly doctype: string;
81
+ readonly headAssets: CompileHeadAssets;
82
+ readonly nodeIdMap: HtmlNodeIdMap;
83
+ }
84
+ type CompiledTemplateArtifact = CompiledEmailArtifact | CompiledSms | CompiledWhatsApp;
85
+ declare const serializeHtmlNode: (node: HtmlNode) => string;
86
+ /** Compile a parsed document; the root tag routes to its channel backend. */
87
+ declare const compileSml: (document: SmlDocument, options?: CompileOptions) => Result.Result<CompiledTemplate, SmlCompileError>;
88
+ declare const compileSmlArtifact: (document: SmlDocument, options?: CompileOptions) => Result.Result<CompiledTemplateArtifact, SmlCompileError>;
89
+ declare const compileSource: (source: string, options?: CompileOptions) => Result.Result<CompiledTemplate, SmlParseError | SmlCompileError>;
90
+ declare const compileSourceArtifact: (source: string, options?: CompileOptions) => Result.Result<CompiledTemplateArtifact, SmlParseError | SmlCompileError>;
91
+ //#endregion
92
+ export { COMPILER_VERSION, CompileBase, CompileHeadAssets, CompileHeadStyleAsset, CompileOptions, CompiledEmail, CompiledEmailArtifact, CompiledTemplate, CompiledTemplateArtifact, HtmlElement, HtmlFragment, HtmlNode, HtmlNodeIdMap, HtmlRawNode, HtmlTextNode, compileSml, compileSmlArtifact, compileSource, compileSourceArtifact, serializeHtmlNode };
93
+ //# sourceMappingURL=compile.d.ts.map