@lyads/visual-editor 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +8 -0
  4. package/README.md +135 -2
  5. package/THIRD_PARTY_NOTICES.md +21259 -0
  6. package/dist/application/block-placement.d.ts +30 -0
  7. package/dist/application/block-session.d.ts +135 -0
  8. package/dist/application/content-service.d.ts +73 -0
  9. package/dist/application/document-commands.d.ts +51 -0
  10. package/dist/application/document-metadata.d.ts +30 -0
  11. package/dist/application/document-presentation.d.ts +35 -0
  12. package/dist/application/email-insertion.d.ts +76 -0
  13. package/dist/application/host.d.ts +36 -0
  14. package/dist/application/image-link.d.ts +36 -0
  15. package/dist/application/section-layout.d.ts +25 -0
  16. package/dist/application/session.d.ts +128 -0
  17. package/dist/assets/browser-worker-D56tNvnb.js +1014 -0
  18. package/dist/assets/browser-worker-D56tNvnb.js.map +1 -0
  19. package/dist/block-controller-RjYGvOcn.js +2468 -0
  20. package/dist/block-controller-RjYGvOcn.js.map +1 -0
  21. package/dist/block-factory-C5oHi4Fm.js +5397 -0
  22. package/dist/block-factory-C5oHi4Fm.js.map +1 -0
  23. package/dist/blocks/block-checks.d.ts +34 -0
  24. package/dist/blocks/block-inspector.d.ts +55 -0
  25. package/dist/blocks/block-output.d.ts +28 -0
  26. package/dist/blocks/block-type.d.ts +124 -0
  27. package/dist/blocks/content-guard.d.ts +52 -0
  28. package/dist/blocks/conversion.d.ts +22 -0
  29. package/dist/blocks/definitions.d.ts +43 -0
  30. package/dist/blocks/device-styles.d.ts +31 -0
  31. package/dist/blocks/email-generator.d.ts +22 -0
  32. package/dist/blocks/email-preview.d.ts +23 -0
  33. package/dist/blocks/email-renderer.d.ts +20 -0
  34. package/dist/blocks/fields.d.ts +34 -0
  35. package/dist/blocks/page-generator.d.ts +16 -0
  36. package/dist/blocks/render-context.d.ts +58 -0
  37. package/dist/blocks/styles.d.ts +54 -0
  38. package/dist/blocks/types/embed.d.ts +40 -0
  39. package/dist/blocks/types/layout.d.ts +41 -0
  40. package/dist/blocks/types/media.d.ts +53 -0
  41. package/dist/blocks/types/structure.d.ts +44 -0
  42. package/dist/blocks/types/text.d.ts +88 -0
  43. package/dist/blocks/values.d.ts +64 -0
  44. package/dist/browser.js +69 -0
  45. package/dist/browser.js.map +1 -0
  46. package/dist/canvas-runtime/action-bar.d.ts +19 -0
  47. package/dist/canvas-runtime/auto-scroll.d.ts +10 -0
  48. package/dist/canvas-runtime/block-drag.d.ts +29 -0
  49. package/dist/canvas-runtime/bridge.d.ts +6 -0
  50. package/dist/canvas-runtime/context.d.ts +53 -0
  51. package/dist/canvas-runtime/document-sync.d.ts +21 -0
  52. package/dist/canvas-runtime/drop-targets.d.ts +34 -0
  53. package/dist/canvas-runtime/embed-markers.d.ts +15 -0
  54. package/dist/canvas-runtime/file-guard.d.ts +12 -0
  55. package/dist/canvas-runtime/image-tools.d.ts +31 -0
  56. package/dist/canvas-runtime/keyboard.d.ts +18 -0
  57. package/dist/canvas-runtime/main.d.ts +1 -0
  58. package/dist/canvas-runtime/messages.d.ts +26 -0
  59. package/dist/canvas-runtime/morph.d.ts +21 -0
  60. package/dist/canvas-runtime/navigation.d.ts +29 -0
  61. package/dist/canvas-runtime/overlay.d.ts +15 -0
  62. package/dist/canvas-runtime/pointer-intents.d.ts +14 -0
  63. package/dist/canvas-runtime/selection-layer.d.ts +16 -0
  64. package/dist/canvas-runtime/shared/shortcuts.d.ts +27 -0
  65. package/dist/canvas-runtime/text-editor.d.ts +55 -0
  66. package/dist/canvas-runtime/text-session.d.ts +39 -0
  67. package/dist/canvas-runtime/variable-marks.d.ts +20 -0
  68. package/dist/canvas-runtime/viewport.d.ts +10 -0
  69. package/dist/codecs/css.d.ts +74 -0
  70. package/dist/codecs/html.d.ts +81 -0
  71. package/dist/compilation/browser-compiler.d.ts +14 -0
  72. package/dist/compilation/browser-worker.d.ts +1 -0
  73. package/dist/compilation/compile-lanes.d.ts +18 -0
  74. package/dist/compilation/generated-mjml.d.ts +25 -0
  75. package/dist/compilation/guard.d.ts +40 -0
  76. package/dist/compilation/node-compiler.d.ts +17 -0
  77. package/dist/compilation/node-worker.d.ts +1 -0
  78. package/dist/composition/block-factory.d.ts +84 -0
  79. package/dist/composition/browser.d.ts +48 -0
  80. package/dist/composition/factory.d.ts +48 -0
  81. package/dist/composition/server.d.ts +43 -0
  82. package/dist/core/any-document.d.ts +16 -0
  83. package/dist/core/block-document.d.ts +215 -0
  84. package/dist/core/budget.d.ts +32 -0
  85. package/dist/core/canvas-contract.d.ts +29 -0
  86. package/dist/core/canvas-layout.d.ts +66 -0
  87. package/dist/core/catalog.d.ts +35 -0
  88. package/dist/core/document-presentation.d.ts +21 -0
  89. package/dist/core/document.d.ts +99 -0
  90. package/dist/core/history.d.ts +26 -0
  91. package/dist/core/html-content-model.d.ts +32 -0
  92. package/dist/core/html-escape.d.ts +2 -0
  93. package/dist/core/rich-text-format.d.ts +14 -0
  94. package/dist/core/rich-text-markup.d.ts +28 -0
  95. package/dist/core/section-layout.d.ts +83 -0
  96. package/dist/generated-mjml-CtzE-f3v.js +1235 -0
  97. package/dist/generated-mjml-CtzE-f3v.js.map +1 -0
  98. package/dist/identity-CJHb6l9N.js +13759 -0
  99. package/dist/identity-CJHb6l9N.js.map +1 -0
  100. package/dist/renderers/canvas-bridge.d.ts +75 -0
  101. package/dist/renderers/canvas-icons.d.ts +1 -0
  102. package/dist/renderers/canvas-runtime.generated.d.ts +3 -0
  103. package/dist/renderers/element-source.d.ts +13 -0
  104. package/dist/renderers/email-renderer.d.ts +14 -0
  105. package/dist/renderers/marked-preview.d.ts +34 -0
  106. package/dist/renderers/markup-tree.d.ts +36 -0
  107. package/dist/renderers/page-renderer.d.ts +15 -0
  108. package/dist/renderers/preview-document.d.ts +39 -0
  109. package/dist/renderers/preview-frame.d.ts +102 -0
  110. package/dist/renderers/section-scaffold.d.ts +16 -0
  111. package/dist/renderers/selection-preview.d.ts +47 -0
  112. package/dist/rich-text/command-executor.d.ts +26 -0
  113. package/dist/rich-text/commands.d.ts +36 -0
  114. package/dist/rich-text/document-builder.d.ts +52 -0
  115. package/dist/rich-text/formatting.d.ts +17 -0
  116. package/dist/rich-text/projection-export.d.ts +17 -0
  117. package/dist/rich-text/projection-rules.d.ts +13 -0
  118. package/dist/rich-text/schema.d.ts +50 -0
  119. package/dist/rich-text/whitespace.d.ts +7 -0
  120. package/dist/security/bounded-parser.d.ts +18 -0
  121. package/dist/security/conditional-comment.d.ts +30 -0
  122. package/dist/security/content-inventory.d.ts +78 -0
  123. package/dist/security/email-sanitizer.d.ts +36 -0
  124. package/dist/security/identity.d.ts +6 -0
  125. package/dist/security/markup-rules.d.ts +31 -0
  126. package/dist/security/policy.d.ts +61 -0
  127. package/dist/security/preview-message.d.ts +317 -0
  128. package/dist/security/rich-text-projection.d.ts +19 -0
  129. package/dist/security/sha256.d.ts +6 -0
  130. package/dist/security/source-markup.d.ts +53 -0
  131. package/dist/security/text-presentation.d.ts +19 -0
  132. package/dist/security/url-policy.d.ts +23 -0
  133. package/dist/server-worker.js +17 -0
  134. package/dist/server-worker.js.map +1 -0
  135. package/dist/server.js +79 -0
  136. package/dist/server.js.map +1 -0
  137. package/dist/templates/blank-email.d.ts +6 -0
  138. package/dist/templates/blocks/catalog.d.ts +31 -0
  139. package/dist/templates/catalog.d.ts +31 -0
  140. package/dist/visual-editor.css +2 -0
  141. package/dist/vue/block-controller.d.ts +106 -0
  142. package/dist/vue/block-workbench.d.ts +70 -0
  143. package/dist/vue/canvas/canvas-theme.d.ts +8 -0
  144. package/dist/vue/canvas/file-drop.d.ts +38 -0
  145. package/dist/vue/canvas/frame-window.d.ts +26 -0
  146. package/dist/vue/canvas/inline-text.d.ts +98 -0
  147. package/dist/vue/canvas/palette-drag.d.ts +55 -0
  148. package/dist/vue/canvas/piece-requests.d.ts +48 -0
  149. package/dist/vue/canvas/strip-reserve.d.ts +14 -0
  150. package/dist/vue/canvas-content-label.d.ts +5 -0
  151. package/dist/vue/components/BlockVisualEditor.vue.d.ts +44 -0
  152. package/dist/vue/components/CanvasSurface.vue.d.ts +11 -0
  153. package/dist/vue/components/CodeEditor.vue.d.ts +22 -0
  154. package/dist/vue/components/EditorBlockMenus.vue.d.ts +3 -0
  155. package/dist/vue/components/EditorBlockPalette.vue.d.ts +3 -0
  156. package/dist/vue/components/EditorDiagnostics.vue.d.ts +3 -0
  157. package/dist/vue/components/EditorDialogs.vue.d.ts +16 -0
  158. package/dist/vue/components/EditorDocumentMetadata.vue.d.ts +3 -0
  159. package/dist/vue/components/EditorDocumentStyles.vue.d.ts +15 -0
  160. package/dist/vue/components/EditorImageSizeControls.vue.d.ts +23 -0
  161. package/dist/vue/components/EditorLayoutControls.vue.d.ts +16 -0
  162. package/dist/vue/components/EditorLeftPanel.vue.d.ts +3 -0
  163. package/dist/vue/components/EditorNoticeIndicator.vue.d.ts +3 -0
  164. package/dist/vue/components/EditorPreview.vue.d.ts +8 -0
  165. package/dist/vue/components/EditorProperties.vue.d.ts +14 -0
  166. package/dist/vue/components/EditorRichTextControls.vue.d.ts +25 -0
  167. package/dist/vue/components/EditorSelectionPath.vue.d.ts +11 -0
  168. package/dist/vue/components/EditorShortcutHelp.vue.d.ts +3 -0
  169. package/dist/vue/components/EditorSourcePane.vue.d.ts +3 -0
  170. package/dist/vue/components/EditorStructureTree.vue.d.ts +3 -0
  171. package/dist/vue/components/EditorTemplateGallery.vue.d.ts +15 -0
  172. package/dist/vue/components/EditorTopBar.vue.d.ts +33 -0
  173. package/dist/vue/components/RichTextEditor.vue.d.ts +47 -0
  174. package/dist/vue/components/SelectionPreviewFrame.vue.d.ts +212 -0
  175. package/dist/vue/components/VisualEditor.vue.d.ts +53 -0
  176. package/dist/vue/components/blocks/BlockCanvas.vue.d.ts +15 -0
  177. package/dist/vue/components/blocks/BlockFieldControl.vue.d.ts +39 -0
  178. package/dist/vue/components/blocks/BlockGlobalStyles.vue.d.ts +3 -0
  179. package/dist/vue/components/blocks/BlockPalette.vue.d.ts +6 -0
  180. package/dist/vue/components/blocks/BlockProperties.vue.d.ts +5 -0
  181. package/dist/vue/components/blocks/BlockReview.vue.d.ts +5 -0
  182. package/dist/vue/components/properties/EditorPropertyAdvanced.vue.d.ts +8 -0
  183. package/dist/vue/components/properties/EditorPropertyContent.vue.d.ts +13 -0
  184. package/dist/vue/components/properties/EditorPropertyStyle.vue.d.ts +8 -0
  185. package/dist/vue/components/ui/EditorAnchoredMenu.vue.d.ts +36 -0
  186. package/dist/vue/components/ui/EditorBadge.vue.d.ts +18 -0
  187. package/dist/vue/components/ui/EditorButton.vue.d.ts +28 -0
  188. package/dist/vue/components/ui/EditorCheckbox.vue.d.ts +13 -0
  189. package/dist/vue/components/ui/EditorColorInput.vue.d.ts +27 -0
  190. package/dist/vue/components/ui/EditorConfirmDialog.vue.d.ts +35 -0
  191. package/dist/vue/components/ui/EditorContextMenu.vue.d.ts +27 -0
  192. package/dist/vue/components/ui/EditorContextPopover.vue.d.ts +33 -0
  193. package/dist/vue/components/ui/EditorEmpty.vue.d.ts +8 -0
  194. package/dist/vue/components/ui/EditorField.vue.d.ts +24 -0
  195. package/dist/vue/components/ui/EditorGroup.vue.d.ts +16 -0
  196. package/dist/vue/components/ui/EditorIcon.vue.d.ts +6 -0
  197. package/dist/vue/components/ui/EditorIconButton.vue.d.ts +19 -0
  198. package/dist/vue/components/ui/EditorInput.vue.d.ts +41 -0
  199. package/dist/vue/components/ui/EditorKeys.vue.d.ts +6 -0
  200. package/dist/vue/components/ui/EditorMeasurement.vue.d.ts +34 -0
  201. package/dist/vue/components/ui/EditorMenu.vue.d.ts +56 -0
  202. package/dist/vue/components/ui/EditorNotice.vue.d.ts +30 -0
  203. package/dist/vue/components/ui/EditorPropertyGroup.vue.d.ts +22 -0
  204. package/dist/vue/components/ui/EditorRecoveryDialog.vue.d.ts +23 -0
  205. package/dist/vue/components/ui/EditorScrollArea.vue.d.ts +13 -0
  206. package/dist/vue/components/ui/EditorSelect.vue.d.ts +25 -0
  207. package/dist/vue/components/ui/EditorSeparator.vue.d.ts +8 -0
  208. package/dist/vue/components/ui/EditorSidePanel.vue.d.ts +26 -0
  209. package/dist/vue/components/ui/EditorSwitch.vue.d.ts +12 -0
  210. package/dist/vue/components/ui/EditorTabs.vue.d.ts +28 -0
  211. package/dist/vue/components/ui/EditorTemplatePreview.vue.d.ts +9 -0
  212. package/dist/vue/components/ui/EditorTextToolbar.vue.d.ts +16 -0
  213. package/dist/vue/components/ui/EditorTree.vue.d.ts +37 -0
  214. package/dist/vue/components/ui/EditorUiProvider.vue.d.ts +13 -0
  215. package/dist/vue/components/ui/EditorVariablePicker.vue.d.ts +20 -0
  216. package/dist/vue/components/ui/color-style-value.d.ts +9 -0
  217. package/dist/vue/components/ui/composition-dismissal.d.ts +1 -0
  218. package/dist/vue/components/ui/editor-dialog-focus.d.ts +6 -0
  219. package/dist/vue/components/ui/numeric-style-value.d.ts +15 -0
  220. package/dist/vue/controller.d.ts +115 -0
  221. package/dist/vue/font-options.d.ts +6 -0
  222. package/dist/vue/icon-data.d.ts +233 -0
  223. package/dist/vue/icons.d.ts +5 -0
  224. package/dist/vue/locale.d.ts +7 -0
  225. package/dist/vue/outline.d.ts +26 -0
  226. package/dist/vue/projection-key.d.ts +7 -0
  227. package/dist/vue/properties/selection-properties.d.ts +40 -0
  228. package/dist/vue/properties/style-fields.d.ts +30 -0
  229. package/dist/vue/public.d.ts +14 -0
  230. package/dist/vue/recovery.d.ts +30 -0
  231. package/dist/vue/responsive-panel.d.ts +1 -0
  232. package/dist/vue/rich-text-commands.d.ts +29 -0
  233. package/dist/vue/services/block-command-definitions.d.ts +14 -0
  234. package/dist/vue/services/block-commands.d.ts +114 -0
  235. package/dist/vue/services/block-menu.d.ts +12 -0
  236. package/dist/vue/services/block-palette.d.ts +21 -0
  237. package/dist/vue/services/block-presentation.d.ts +16 -0
  238. package/dist/vue/services/diagnostic-groups.d.ts +25 -0
  239. package/dist/vue/services/image-requests.d.ts +80 -0
  240. package/dist/vue/services/live-change.d.ts +26 -0
  241. package/dist/vue/services/property-commands.d.ts +28 -0
  242. package/dist/vue/services/saved-blocks.d.ts +32 -0
  243. package/dist/vue/services/selection-path.d.ts +20 -0
  244. package/dist/vue/services/shortcuts.d.ts +39 -0
  245. package/dist/vue/services/structure-tree.d.ts +38 -0
  246. package/dist/vue/services/template-application.d.ts +33 -0
  247. package/dist/vue/services/tree-drag.d.ts +28 -0
  248. package/dist/vue/session/blocks.d.ts +44 -0
  249. package/dist/vue/session/guard.d.ts +13 -0
  250. package/dist/vue/session/structure.d.ts +36 -0
  251. package/dist/vue/session/text.d.ts +23 -0
  252. package/dist/vue/session/transfer.d.ts +23 -0
  253. package/dist/vue/theme.d.ts +20 -0
  254. package/dist/vue/variables.d.ts +21 -0
  255. package/dist/vue/workbench.d.ts +100 -0
  256. package/dist/vue.js +71418 -0
  257. package/dist/vue.js.map +1 -0
  258. package/package.json +125 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-factory-C5oHi4Fm.js","names":["v.pipe","v.string","v.regex","v.union","v.maxLength","v.number","v.finite","v.boolean","v.lazy","v.strictObject","v.picklist","v.record","v.exactOptional","v.array","v.literal","v.minLength","v.integer","v.minValue","v.maxValue","v.safeParse","id","kind","titleKey","descriptionKey","document","translations","id","kind","titleKey","descriptionKey","document","translations","id","kind","titleKey","descriptionKey","document","translations","id","kind","titleKey","descriptionKey","document","translations","emailBlank","emailNewsletter","emailWelcome","pageMaterial","pageEvent","integer","pipe","DocumentBudget","boolean","minLength","string$1","regex","minValue","number","literal","maxLength","exactOptional","maxValue","array","safeParse","record","strictObject","parse","defaultTreeAdapter","BlockCatalog","lazy","finite","parseFragment","NS","Tokenizer","union","CssDocumentCodec","UrlPolicy","SecureIdentifier","serialize","DocumentValidationError","DocumentBudgetError","EditorDocument","picklist","SectionLayoutPolicy","isReservedAttribute","SECTION_LAYOUT_LIMITS","CanvasLayout","DocumentPresentationService","ContentService","RICH_TEXT_ORIGIN_ATTRIBUTE","RICH_TEXT_REMOVED_ATTRIBUTE","RichTextFormatPolicy","stripReservedAttributes","EDIT_NODE_ATTRIBUTE","EditorController","markupChildren","documentParts","escapeHtml","sha256Base64","CompileLanes","RichTextProjection","BlockEditorController","SelectionPreviewRenderer","NODE_ATTRIBUTE","HtmlDocumentCodec","COMPILE_LIMITS","ContentPolicy","GeneratedMjml","PREHEADER_STYLE","TITLE_LIMIT","PREHEADER_LIMIT","DocumentMetadataService","content","identifiers","preheader","document","value","nodes","node","head","children","title","body","siblings","existing","first","direct","child","previous","code","character","tag","found","DocumentHistory","maxEntries","maxBytes","#maxEntries","#maxBytes","#position","#entries","#sizes","sum","size","bytes","INLINE_TAGS","MODE_TAGS","RichTextMarkup","mode","tags","stack","allowed","check","name","CONDITIONAL_PREFIX","CONDITIONAL_SUFFIX","GHOST_CLOSE","TABLE_CONTEXT","ROW_GROUPS","SECTION_HOSTS","PRESENTATION_TABLE","EmailInsertionPlanner","id","hidden","visible","preheaders","index","candidate","rest","wrapper","units","sections","shapes","section","known","shape","conditional","chain","parent","roots","inCell","columns","block","unit","requested","anchorIndex","anchor","owner","rows","column","rowHost","target","position","row","cell","image","table","place","before","after","next","shellRow","shellCell","last","requestedParent","requestedIndex","redirect","wrappers","length","bridge","opening","depth","kind","current","markup","elements","trailing","nested","EMAIL_IMAGE_STYLE","PAGE_IMAGE_STYLE","DocumentMutationService","catalog","style","imported","item","violation","removed","importedNodes","paragraph","reconciled","property","reference","parentId","asset","attrs","data","plan","source","styles","type","original","copies","clearIdentities","finalLength","documentNodes","documentCss","originals","collect","identities","collectIdentities","owners","decorationRules","ambiguousDecoration","stylesheets","collectStylesheets","css","used","equivalent","restore","origin","split","attribute","decoration","change","clone","opener","SectionLayoutService","scaffold","context","projection","settings","patch","reason","ids","extraCss","retained","old","generated","shell","columnMap","shellMap","transplant","values","key","host","total","weight","attempt","replacement","MjmlEmailRenderer","codec","policy","compiler","mjml","MjmlSectionScaffold","renderer","geometry","root","inner","rootDeclarations","innerDeclarations","padding","start","end","valid","token","fixedValues","attr","inspected","ImageLinkService","urls","location","imageId","href","options","freshId","targetId","branch","pieces","originalUsed","retain","rel","path","anchors","exclusiveBranch","offset","shared","parents","HostIntegration","adapters","controller","job","result","expectedRevision","EditorSession","services","admitted","#document","#diagnostics","#readOnly","#revision","#persistedRevision","#savedDocumentRevision","#source","#draft","#mode","#selection","#pendingRichText","#editGeneration","#listeners","listener","input","diagnostics","initialHtml","html","draft","service","initial","#disposed","error","codes","#saving","revision","persisted","merged","diagnostic","entry","action","direction","history","clearRichText","#emitting","#emitQueued","failed","state","PageRenderer","ACTIVE_META","PREVIEW_POLICY","HtmlDocumentAssembler","imageOrigins","#imageOrigins","url","loopback","preview","csp","directive","fragment","safe","PreviewDocument","assembler","BLANK_EMAIL_HTML","EMAIL_STYLE","EMAIL_BLOCK_STYLE","EMAIL_SECTION_BLOCKS","EMAIL_FOOTER","PAGE_CSS","BLOCK_CSS","DEFINITIONS","TemplateCatalog","emailRenderer","entryKind","definition","InitialDocumentError","EditorFactory","compilerFactory","structure","templates","session","BLOCK_NODE_TYPES","BLOCK_DEVICES","BLOCK_DOCUMENT_LIMITS","BLOCK_ID_PATTERN","KEY_PATTERN","LANGUAGE_TAG_PATTERN","keySchema","propValueSchema","styleValueSchema","BlockSchema","GlobalStylesSchema","BlockDocumentSchema","BlockDocumentError","BlockDocument","#data","#rules","rules","parsed","#bytes","#index","blocks","moving","destination","copy","nextId","device","changed","normalized","present","keys","group","meta","#opened","list","opened","groups","sets","accepted","seen","frame","count","limits","mobile","props","parseAnyDocument","version","BlockEditorSession","#savedRevision","#history","#text","applied","all","choice","stale","text","store","#saveAbort","abort","#saveSequence","output","saved","BlockPlacementService","located","leaving","placement","neighbour","outer","container","visit","besides","placements","HTML_LIMITS","CACHE_SIZE","PAGE_FORBIDDEN_TAGS","EMAIL_FORBIDDEN_TAGS","CLASS_ATTRIBUTE","GENERATED_PREFIX","writesGeneratedClass","scannedTo","match","GOOGLE_FONTS_CSS","GOOGLE_FONTS_FILES","BlockContentGuard","#urls","#css","#policy","#codec","#projection","purpose","projected","settled","forbidden","inventory","#markup","dropLinks","lines","flat","holder","line","scope","#cache","compute","oldest","keyCharacters","blockClass","previewClass","HIDE_DESKTOP_CLASS","HIDE_MOBILE_CLASS","mobileClass","visibilityClasses","BaseContext","renderChildren","own","field","reverse","EmailRenderContext","fragments","columnWidth","pairs","extra","cellClass","classes","PageRenderContext","mobileRules","base","selectorSuffix","declarations","FONT_STACKS","COLOR","LENGTH","BOX_PART","RATIO","URL_LENGTH","TEXT_LENGTH","ValueRules","spec","parts","part","max","color","pixels","fontWeights","fontFamily","GLOBAL_STYLE_GROUPS","GlobalStyleSpec","#keys","StyleResolver","ALIGN_OPTIONS","BLOCK_PADDING","DEVICE_KEYS","TEXT_MOBILE_EMAIL","fields","inherits","option","COLUMN_CONTENT","columnWeight","SectionBlock","ColumnBlock","FADED","cssValue","mapped","BlockDeviceStyles","breakpoint","rule","properties","selectors","suffix","self","selector","small","large","desktop","phone","inline","usage","shown","hide","EMAIL_BREAKPOINT","SMALL_SCREEN","BlockMjmlGenerator","registry","run","#devices","widths","weights","attributes","styleVariable","letter","v","BASE_CSS","MOBILE_CSS","BlockPageGenerator","variables","kinds","TextBlock","HEADING_LEVELS","HeadingBlock","level","FooterBlock","string","EMPTY_IMAGE_HEIGHT","EMPTY_IMAGE_COLOR","ImageBlock","ButtonBlock","DividerBlock","SpacerBlock","FormBlock","HtmlBlock","defaultBlockTypes","MEASURE_TOKEN","BlockDefinitionRegistry","#values","types","#types","#fields","budget","page","EDITABLE","EmailPreviewMarker","prefix","marked","tree","element","kept","queue","BlockEmailRenderer","generator","marker","identity","BlockOutputRenderer","emails","pages","previewEmails","regions","BlockInspector","responsive","model","resolver","effective","BlockConversionError","BlockToHtmlConversion","email","TEMPLATES","\"title\"","\"meta\"","\"lang\"","\"styles\"","\"blocks\"","\"id\"","\"type\"","\"props\"","\"children\"","\"text\"","\"en\"","\"s1t1\"","\"es\"","\"padding\"","\"fontSize\"","\"color\"","\"level\"","\"href\"","\"background\"","\"s1h1\"","\"s1t2\"","\"s1h2\"","\"s1t3\"","\"s1b1\"","\"s2f1\"","\"s2h1\"","\"s2t1\"","\"s2h2\"","\"s2t2\"","\"s3f1\"","\"align\"","\"s3h1\"","\"s4f1\"","\"button\"","\"heading\"","\"weight\"","\"s3f2\"","TEMPLATE_LANGUAGES","templateLanguage","language","BlockTemplateCatalog","template","documentId","translated","texts","lang","translations","blockId","BlockEditorFactory","toolkit","piece","lanes","conversion","templateId"],"sources":["../src/application/document-metadata.ts","../src/core/history.ts","../src/core/rich-text-markup.ts","../src/application/email-insertion.ts","../src/application/document-commands.ts","../src/application/section-layout.ts","../src/renderers/email-renderer.ts","../src/renderers/section-scaffold.ts","../src/application/image-link.ts","../src/application/host.ts","../src/application/session.ts","../src/renderers/page-renderer.ts","../src/renderers/preview-document.ts","../src/templates/blank-email.ts","../src/templates/catalog.ts","../src/composition/factory.ts","../src/core/block-document.ts","../src/core/any-document.ts","../src/application/block-session.ts","../src/application/block-placement.ts","../src/blocks/content-guard.ts","../src/blocks/render-context.ts","../src/blocks/values.ts","../src/blocks/styles.ts","../src/blocks/fields.ts","../src/blocks/types/layout.ts","../src/blocks/device-styles.ts","../src/blocks/email-generator.ts","../src/blocks/page-generator.ts","../src/blocks/types/text.ts","../src/blocks/types/media.ts","../src/blocks/types/structure.ts","../src/blocks/types/embed.ts","../src/blocks/definitions.ts","../src/blocks/email-preview.ts","../src/blocks/email-renderer.ts","../src/blocks/block-output.ts","../src/blocks/block-inspector.ts","../src/blocks/conversion.ts","../src/templates/blocks/email-blank.json","../src/templates/blocks/email-newsletter.json","../src/templates/blocks/email-welcome.json","../src/templates/blocks/page-event.json","../src/templates/blocks/page-material.json","../src/templates/blocks/catalog.ts","../src/composition/block-factory.ts"],"sourcesContent":["import type { DocumentNode, EditorDocumentData } from '../core/document';\nimport { EditorDocument } from '../core/document';\nimport { ContentService } from './content-service';\nimport type { MutableNode } from './email-insertion';\n\nexport interface DocumentMetadata {\n readonly title: string;\n /** Hidden preview text of an e-mail; undefined for a page, empty when there is none. */\n readonly preheader: string | undefined;\n}\n\nexport interface MetadataIdentityPort {\n next(): string;\n}\n\n/** What MJML itself writes for `mj-preview`: hidden from the message, read by the inbox. */\nconst PREHEADER_STYLE =\n 'display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;';\nconst TITLE_LIMIT = 1_000;\nconst PREHEADER_LIMIT = 500;\n\n/**\n * Title and preheader are part of what a recipient receives, so they are document content\n * edited by commands like any other, never sample text left behind by a template.\n */\nexport class DocumentMetadataService {\n constructor(\n private readonly content: ContentService,\n private readonly identifiers: MetadataIdentityPort,\n ) {}\n\n read(document: EditorDocumentData): DocumentMetadata {\n const preheader = document.kind === 'email' ? this.preheaderNode(document.nodes) : undefined;\n return {\n title: document.title,\n preheader: document.kind === 'email' ? (preheader ? this.text(preheader) : '') : undefined,\n };\n }\n\n title(document: EditorDocumentData, value: string): EditorDocument {\n if (typeof value !== 'string' || value.length > TITLE_LIMIT || this.control(value))\n throw new Error('Invalid document title');\n const nodes = document.nodes.map((node) => this.copy(node));\n const head = this.findTag(nodes, 'head');\n if (head) {\n const children = (head.children ??= []);\n let title = children.find((node) => node.tag === 'title');\n if (!title) {\n title = { id: this.identifiers.next(), type: 'element', tag: 'title' };\n children.push(title);\n }\n title.children = value ? [{ id: this.identifiers.next(), type: 'text', value }] : [];\n }\n return this.next(document, nodes, value);\n }\n\n preheader(document: EditorDocumentData, value: string): EditorDocument {\n if (\n document.kind !== 'email' ||\n typeof value !== 'string' ||\n value.length > PREHEADER_LIMIT ||\n this.control(value)\n )\n throw new Error('Invalid preheader');\n const nodes = document.nodes.map((node) => this.copy(node));\n const body = this.findTag(nodes, 'body');\n const siblings = body ? (body.children ??= []) : nodes;\n const existing = this.preheaderNode(siblings, true);\n if (existing) {\n if (value) existing.children = [{ id: this.identifiers.next(), type: 'text', value }];\n else siblings.splice(siblings.indexOf(existing), 1);\n } else if (value) {\n const first = siblings.findIndex((node) => node.type !== 'doctype');\n siblings.splice(first < 0 ? siblings.length : first, 0, {\n id: this.identifiers.next(),\n type: 'element',\n tag: 'div',\n attrs: { style: PREHEADER_STYLE },\n children: [{ id: this.identifiers.next(), type: 'text', value }],\n });\n }\n return this.next(document, nodes, document.title);\n }\n\n /** The first content of the body when it is a hidden block which only holds text. */\n private preheaderNode(nodes: MutableNode[], direct: true): MutableNode | undefined;\n private preheaderNode(nodes: readonly DocumentNode[]): DocumentNode | undefined;\n private preheaderNode(nodes: readonly DocumentNode[], direct = false): DocumentNode | undefined {\n const siblings = direct ? nodes : (this.findTag(nodes, 'body')?.children ?? nodes);\n const first = siblings.find(\n (node) => node.type === 'element' || (node.type === 'text' && !!node.value?.trim()),\n );\n if (\n first?.type !== 'element' ||\n first.tag !== 'div' ||\n (first.children ?? []).some((child) => child.type !== 'text')\n )\n return undefined;\n try {\n return this.content.inlineDeclarations(first.attrs?.style ?? '').display === 'none'\n ? first\n : undefined;\n } catch {\n return undefined;\n }\n }\n\n private next(\n previous: EditorDocumentData,\n nodes: readonly DocumentNode[],\n title: string,\n ): EditorDocument {\n return this.content.document({ ...previous, title, nodes, revision: previous.revision + 1 });\n }\n\n private text(node: DocumentNode): string {\n return (node.children ?? []).map((child) => child.value ?? '').join('');\n }\n\n private control(value: string): boolean {\n return [...value].some((character) => {\n const code = character.charCodeAt(0);\n return code < 32 || code === 127;\n });\n }\n\n private findTag(nodes: MutableNode[], tag: string): MutableNode | undefined;\n private findTag(nodes: readonly DocumentNode[], tag: string): DocumentNode | undefined;\n private findTag(nodes: readonly DocumentNode[], tag: string): DocumentNode | undefined {\n for (const node of nodes) {\n if (node.tag === tag) return node;\n const found = this.findTag(node.children ?? [], tag);\n if (found) return found;\n }\n return undefined;\n }\n\n private copy(node: DocumentNode): MutableNode {\n return {\n id: node.id,\n type: node.type,\n ...(node.tag !== undefined ? { tag: node.tag } : {}),\n ...(node.value !== undefined ? { value: node.value } : {}),\n ...(node.attrs ? { attrs: { ...node.attrs } } : {}),\n ...(node.children ? { children: node.children.map((child) => this.copy(child)) } : {}),\n ...(node.metadata ? { metadata: { ...node.metadata } } : {}),\n };\n }\n}\n","import type { EditorDocument } from './document';\n\n/** What a history keeps: an immutable, validated document which knows its serialized size. */\nexport interface HistoryEntry {\n serializedBytes(): number;\n}\n\n/**\n * One history per editing session. A new branch discards only the redo branch. The HTML\n * document (schema 1) and the block piece (schema 2) use the same history.\n */\nexport class DocumentHistory<T extends HistoryEntry = EditorDocument> {\n readonly #maxEntries: number;\n readonly #maxBytes: number;\n #entries: T[] = [];\n #sizes: number[] = [];\n #position = -1;\n\n /**\n * A document inside the import limits can serialize to about 30 MB of JSON, and its history\n * has to hold it at least twice.\n */\n constructor(maxEntries = 100, maxBytes = 64 * 1024 * 1024) {\n if (!Number.isInteger(maxEntries) || maxEntries < 2 || maxEntries > 1_000)\n throw new RangeError('INVALID_HISTORY_LIMIT');\n if (!Number.isSafeInteger(maxBytes) || maxBytes < 1_024 || maxBytes > 128 * 1024 * 1024)\n throw new RangeError('INVALID_HISTORY_BUDGET');\n this.#maxEntries = maxEntries;\n this.#maxBytes = maxBytes;\n }\n\n get canUndo(): boolean {\n return this.#position > 0;\n }\n get canRedo(): boolean {\n return this.#position >= 0 && this.#position < this.#entries.length - 1;\n }\n get size(): number {\n return this.#entries.length;\n }\n get retainedBytes(): number {\n return this.#sizes.reduce((sum, size) => sum + size, 0);\n }\n\n push(document: T): void {\n const bytes = document.serializedBytes();\n if (bytes > this.#maxBytes) throw new RangeError('HISTORY_SNAPSHOT_TOO_LARGE');\n this.#entries = this.#entries.slice(0, this.#position + 1);\n this.#sizes = this.#sizes.slice(0, this.#position + 1);\n // The aggregate is immutable and was validated when it was built: it is kept as it is.\n this.#entries.push(document);\n this.#sizes.push(bytes);\n while (this.#entries.length > this.#maxEntries || this.retainedBytes > this.#maxBytes) {\n this.#entries.shift();\n this.#sizes.shift();\n }\n this.#position = this.#entries.length - 1;\n }\n\n current(): T | undefined {\n return this.#entries[this.#position];\n }\n\n undo(): T | undefined {\n if (!this.canUndo) return undefined;\n this.#position--;\n return this.current();\n }\n\n redo(): T | undefined {\n if (!this.canRedo) return undefined;\n this.#position++;\n return this.current();\n }\n\n reset(document?: T): void {\n this.#entries = [];\n this.#sizes = [];\n this.#position = -1;\n if (document) this.push(document);\n }\n}\n","import type { DocumentNode } from './document';\n\n/**\n * `block`: paragraphs, lists, headings and quotes (the HTML document and the text and footer\n * blocks). `inline`: one line of formatted text with links (heading block). `button`: formatted\n * text without links, since the button is the link.\n */\nexport type RichTextMode = 'block' | 'inline' | 'button';\n\nconst INLINE_TAGS = ['span', 'strong', 'b', 'em', 'i', 'u', 's', 'br', 'sup', 'sub', 'code'];\nconst MODE_TAGS: Readonly<Record<RichTextMode, ReadonlySet<string>>> = Object.freeze({\n button: new Set(INLINE_TAGS),\n inline: new Set([...INLINE_TAGS, 'a']),\n block: new Set([\n ...INLINE_TAGS,\n 'a',\n 'p',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'blockquote',\n 'pre',\n 'hr',\n ]),\n});\n\nexport type RichTextMarkupViolation = 'tag' | 'attribute' | 'style' | 'node';\n\nexport interface RichTextMarkupCheck {\n /** Attributes the caller adds to every element, e.g. the origin marks of schema 1. */\n readonly extraAttributes?: readonly string[];\n /** Whether a `style` attribute holds only the declarations a rich text may carry. */\n style(value: string): boolean;\n /** A further rule for one element; false makes the tree invalid. */\n element?(node: DocumentNode): boolean;\n}\n\n/**\n * The single rule of the markup a rich-text projection may hold once it is imported: which\n * elements each mode accepts and which attributes each element keeps. The in-place editing of\n * the HTML document (schema 1) and the texts of the block pieces (schema 2) both apply it.\n */\nexport class RichTextMarkup {\n tags(mode: RichTextMode): ReadonlySet<string> {\n return MODE_TAGS[mode];\n }\n\n /** The attributes an element of the projection keeps besides `style`. */\n semanticAttributes(tag: string): readonly string[] {\n return tag === 'a' ? ['href', 'target', 'rel', 'title'] : tag === 'ol' ? ['start'] : [];\n }\n\n /** The first rule the tree breaks, or undefined when all of it follows the mode. */\n violation(\n nodes: readonly DocumentNode[],\n mode: RichTextMode,\n check: RichTextMarkupCheck,\n ): RichTextMarkupViolation | undefined {\n const tags = this.tags(mode);\n const stack = [...nodes];\n while (stack.length) {\n const node = stack.pop();\n if (!node) break;\n if (node.type === 'text') continue;\n if (node.type !== 'element' || !tags.has(node.tag ?? '')) return 'tag';\n const allowed = [\n 'style',\n ...(check.extraAttributes ?? []),\n ...this.semanticAttributes(node.tag ?? ''),\n ];\n for (const [name, value] of Object.entries(node.attrs ?? {})) {\n if (!allowed.includes(name)) return 'attribute';\n if (name === 'style' && !check.style(value)) return 'style';\n }\n if (check.element && !check.element(node)) return 'node';\n stack.push(...(node.children ?? []));\n }\n return undefined;\n }\n}\n","import type { DocumentNode } from '../core/document';\n\nexport interface MutableNode {\n id: string;\n type: DocumentNode['type'];\n tag?: string;\n value?: string;\n attrs?: Record<string, string>;\n children?: MutableNode[];\n metadata?: NonNullable<DocumentNode['metadata']>;\n}\n\n/** The unit a generated e-mail block is meant to be inserted as. */\nexport type EmailInsertionUnit = 'content' | 'section';\n\ninterface TreeNode<T> extends Omit<DocumentNode, 'children'> {\n readonly children?: readonly T[];\n}\n\ninterface EmailColumn<T> {\n /** Presentation table owned by the column; its body holds one row per content element. */\n readonly table: T;\n readonly body: T;\n readonly rows: readonly T[];\n}\n\nexport interface CompiledEmailBlock {\n /** False for plain snippets, which keep the generic insertion rules. */\n readonly compiled: boolean;\n /** Section-level sequence: sections and their Outlook conditional comments. */\n readonly units: readonly DocumentNode[];\n /** Undefined when a compiled section has a shape this planner does not know. */\n readonly columns: readonly EmailColumn<DocumentNode>[] | undefined;\n}\n\nexport interface EmailInsertionPlan {\n readonly parent: MutableNode | undefined;\n readonly target: MutableNode[];\n readonly index: number;\n readonly nodes: readonly DocumentNode[];\n}\n\ntype ConditionalKind = 'open' | 'close' | 'bridge' | 'inline' | 'other';\n\nconst CONDITIONAL_PREFIX = '[if mso | IE]>';\nconst CONDITIONAL_SUFFIX = '<![endif]';\nconst GHOST_CLOSE = '</td></tr></table>';\nconst TABLE_CONTEXT = new Set(['table', 'tbody', 'thead', 'tfoot', 'tr', 'td', 'th']);\nconst ROW_GROUPS = new Set(['tbody', 'thead', 'tfoot']);\n/** Parents which take section-level flow content; anything else passes it to an ancestor. */\nconst SECTION_HOSTS = new Set([\n 'body',\n 'td',\n 'th',\n 'div',\n 'section',\n 'article',\n 'main',\n 'header',\n 'footer',\n 'figure',\n 'details',\n]);\nconst PRESENTATION_TABLE: Readonly<Record<string, string>> = Object.freeze({\n border: '0',\n cellpadding: '0',\n cellspacing: '0',\n role: 'presentation',\n width: '100%',\n});\n\n/**\n * Chooses what a generated e-mail block contributes to a destination. Inside a column or\n * cell only content rows travel; at section level the section goes with its balanced pair of\n * Outlook comments. The preheader, the title and the article wrapper of the compiled block\n * never enter the document. Anything that cannot be placed safely is refused.\n */\nexport class EmailInsertionPlanner {\n constructor(\n private readonly id: () => string,\n private readonly hidden: (style: string) => boolean,\n ) {}\n\n block(body: readonly DocumentNode[]): CompiledEmailBlock {\n const visible = body.filter((node) => !this.blank(node));\n const preheaders = visible.filter((node, index) =>\n visible.slice(0, index + 1).every((candidate) => this.preheader(candidate)),\n );\n const rest = visible.slice(preheaders.length);\n const wrapper = rest.length === 1 && rest[0] && this.wrapper(rest[0]) ? rest[0] : undefined;\n const units = this.trim(\n wrapper ? (wrapper.children ?? []) : body.filter((node) => !preheaders.includes(node)),\n );\n const sections = units.filter((node) => node.type === 'element');\n const shapes = sections.map((section) => this.columns<DocumentNode>(section));\n const known = sections.length > 0 && shapes.every((shape) => shape !== undefined);\n const conditional = units.some((node) =>\n ['open', 'close', 'bridge'].includes(this.conditional(node) ?? ''),\n );\n return {\n compiled: !!wrapper || conditional || known,\n units,\n columns: known ? shapes.flatMap((shape) => shape ?? []) : undefined,\n };\n }\n\n place(\n roots: MutableNode[],\n parent: MutableNode | undefined,\n index: number | undefined,\n block: CompiledEmailBlock,\n requested?: EmailInsertionUnit,\n ): EmailInsertionPlan {\n const chain = parent ? this.chain(roots, parent.id) : [];\n if (parent && !chain.length) throw new Error('Missing parent');\n const inCell = chain.some((node) => TABLE_CONTEXT.has(node.tag ?? ''));\n const columns = block.columns;\n const unit = requested ?? (columns?.length === 1 ? 'content' : 'section');\n if (!inCell) return this.sectionLevel(roots, parent, index, block.units, true);\n if (!columns || unit === 'section') {\n // A whole section cannot live inside a cell: it follows the enclosing layout unit.\n let anchorIndex = chain.findIndex((node) => this.layoutUnit(node));\n if (anchorIndex < 0) throw new Error('Unsupported e-mail block destination');\n // A wrapper such as <center> takes no section: the block follows it in a real host.\n while (anchorIndex > 0 && !SECTION_HOSTS.has(chain[anchorIndex - 1]?.tag ?? ''))\n anchorIndex--;\n const anchor = chain[anchorIndex];\n if (!anchor) throw new Error('Unsupported e-mail block destination');\n const owner = chain[anchorIndex - 1];\n const siblings = owner ? (owner.children ??= []) : roots;\n return this.sectionLevel(roots, owner, siblings.indexOf(anchor) + 1, block.units, false);\n }\n if (!parent) throw new Error('Missing parent');\n const rows = columns.flatMap((column) => column.rows);\n const rowHost = this.rowHost(chain, parent);\n if (rowHost) return { ...rowHost, nodes: rows };\n const target = (parent.children ??= []);\n const position = this.position(index, target.length);\n if (ROW_GROUPS.has(parent.tag ?? '')) return { parent, target, index: position, nodes: rows };\n if (parent.tag === 'tr')\n return {\n parent,\n target,\n index: position,\n nodes: rows.flatMap((row) =>\n (row.children ?? []).filter((cell) => cell.type === 'element'),\n ),\n };\n if (parent.tag === 'table')\n return {\n parent,\n target,\n index: position,\n nodes: [{ id: this.id(), type: 'element', tag: 'tbody', children: rows }],\n };\n this.assertFlowDestination(parent);\n return { parent, target, index: position, nodes: columns.map((column) => column.table) };\n }\n\n /** A new image is born inside the content unit generated image blocks use. */\n placeImage(\n roots: MutableNode[],\n parent: MutableNode | undefined,\n index: number | undefined,\n image: MutableNode,\n ): EmailInsertionPlan {\n const chain = parent ? this.chain(roots, parent.id) : [];\n if (parent && !chain.length) throw new Error('Missing parent');\n const cell: MutableNode = {\n id: this.id(),\n type: 'element',\n tag: 'td',\n attrs: { align: 'center', style: 'padding:10px 25px' },\n children: [image],\n };\n const row: MutableNode = { id: this.id(), type: 'element', tag: 'tr', children: [cell] };\n const table = (): MutableNode => ({\n id: this.id(),\n type: 'element',\n tag: 'table',\n attrs: { ...PRESENTATION_TABLE },\n children: [{ id: this.id(), type: 'element', tag: 'tbody', children: [row] }],\n });\n if (parent && chain.some((node) => TABLE_CONTEXT.has(node.tag ?? ''))) {\n const rowHost = this.rowHost(chain, parent);\n if (rowHost) return { ...rowHost, nodes: [row] };\n const target = (parent.children ??= []);\n const position = this.position(index, target.length);\n if (ROW_GROUPS.has(parent.tag ?? ''))\n return { parent, target, index: position, nodes: [row] };\n if (parent.tag === 'tr') return { parent, target, index: position, nodes: [cell] };\n if (parent.tag === 'table')\n return {\n parent,\n target,\n index: position,\n nodes: [{ id: this.id(), type: 'element', tag: 'tbody', children: [row] }],\n };\n this.assertFlowDestination(parent);\n return { parent, target, index: position, nodes: [table()] };\n }\n const place = this.sectionLevel(roots, parent, index, [], true);\n // Prefer a column of the neighbouring section, so the image keeps the message width.\n const before = place.target\n .slice(0, place.index)\n .reverse()\n .find((node) => node.type === 'element');\n const after = place.target.slice(place.index).find((node) => node.type === 'element');\n const previous = before ? this.columns<MutableNode>(before)?.at(-1) : undefined;\n if (previous) {\n const target = (previous.body.children ??= []);\n return { parent: previous.body, target, index: target.length, nodes: [row] };\n }\n const next = after ? this.columns<MutableNode>(after)?.[0] : undefined;\n if (next)\n return { parent: next.body, target: (next.body.children ??= []), index: 0, nodes: [row] };\n return { ...place, nodes: [table()] };\n }\n\n /**\n * Where content rows go when the destination is part of a recognized section: after the\n * selected row of a column, or at the end of the last column when the section shell (its\n * row or the cell which holds the columns) was selected. A cell beside the selected row,\n * or flow content between the Outlook ghost cells, would break the column layout.\n */\n private rowHost(\n chain: readonly MutableNode[],\n parent: MutableNode,\n ): Omit<EmailInsertionPlan, 'nodes'> | undefined {\n if (parent.tag !== 'tr' && parent.tag !== 'td') return undefined;\n for (const section of chain) {\n const columns = this.columns<MutableNode>(section);\n if (!columns) continue;\n const column = columns.find((candidate) => candidate.rows.includes(parent));\n if (column) {\n const target = (column.body.children ??= []);\n return { parent: column.body, target, index: target.indexOf(parent) + 1 };\n }\n const shellRow = this.descend(section, ['table', 'tbody', 'tr']);\n const shellCell = shellRow && this.descend(shellRow, ['td']);\n const last = columns.at(-1);\n if (last && (parent === shellRow || parent === shellCell)) {\n const target = (last.body.children ??= []);\n return { parent: last.body, target, index: target.length };\n }\n }\n return undefined;\n }\n\n private sectionLevel(\n roots: MutableNode[],\n requestedParent: MutableNode | undefined,\n requestedIndex: number | undefined,\n units: readonly DocumentNode[],\n redirect: boolean,\n ): EmailInsertionPlan {\n this.assertBalanced(units);\n let parent = requestedParent;\n let index = requestedIndex;\n const body = parent ?? this.find(roots, 'body');\n if (redirect && (!parent || parent.tag === 'body')) {\n const siblings = body ? (body.children ??= []) : roots;\n const wrappers = siblings.filter((node) => this.wrapper(node));\n const wrapper = wrappers.length === 1 ? wrappers[0] : undefined;\n if (wrapper) {\n // New sections belong to the article which already holds the message.\n const length = (wrapper.children ??= []).length;\n index = index === undefined || index > siblings.indexOf(wrapper) ? length : 0;\n parent = wrapper;\n } else parent = body;\n }\n const target = parent ? (parent.children ??= []) : roots;\n let position = this.position(index, target.length);\n const previous = target\n .slice(0, position)\n .reverse()\n .find((node) => !this.blank(node));\n const next = target.slice(position).find((node) => !this.blank(node));\n // Never split a section from the comment which opens or closes its Outlook table.\n if (next && this.conditional(next) === 'close') position = target.indexOf(next) + 1;\n else if (previous && this.conditional(previous) === 'open') position = target.indexOf(previous);\n else if (units.length) {\n const bridge = [next, previous].find((node) => node && this.conditional(node) === 'bridge');\n if (bridge) position = this.splitBridge(target, bridge);\n }\n return { parent, target, index: position, nodes: units };\n }\n\n /**\n * Between two sections one comment closes a ghost table and opens the next. It becomes\n * its two halves, so a new section fits between them with a pair of its own.\n */\n private splitBridge(target: MutableNode[], bridge: MutableNode): number {\n const value = bridge.value ?? '';\n const opening = value.slice(CONDITIONAL_PREFIX.length + GHOST_CLOSE.length);\n const index = target.indexOf(bridge);\n target.splice(\n index,\n 1,\n { ...bridge, value: `${CONDITIONAL_PREFIX}${GHOST_CLOSE}${CONDITIONAL_SUFFIX}` },\n { id: this.id(), type: 'comment', value: `${CONDITIONAL_PREFIX}${opening}` },\n );\n return index + 1;\n }\n\n private assertBalanced(units: readonly DocumentNode[]): void {\n let depth = 0;\n for (const node of units) {\n const kind = this.conditional(node);\n if (kind === undefined || kind === 'inline') continue;\n if (kind === 'other') throw new Error('Unsupported e-mail conditional');\n if (kind === 'open') depth++;\n else if (depth < 1) throw new Error('Unbalanced e-mail conditional');\n else if (kind === 'close') depth--;\n }\n if (depth !== 0) throw new Error('Unbalanced e-mail conditional');\n }\n\n /** Flow content next to Outlook ghost cells would land in the wrong table for one client. */\n private assertFlowDestination(parent: MutableNode): void {\n if (\n (parent.children ?? []).some((node) =>\n ['open', 'close', 'bridge', 'other'].includes(this.conditional(node) ?? ''),\n )\n )\n throw new Error('Unsupported e-mail block destination');\n }\n\n private columns<T extends TreeNode<T>>(section: T): readonly EmailColumn<T>[] | undefined {\n if (section.type !== 'element' || section.tag !== 'div') return undefined;\n const cell = this.descend(section, ['table', 'tbody', 'tr', 'td']);\n if (!cell) return undefined;\n const columns: EmailColumn<T>[] = [];\n for (const child of cell.children ?? []) {\n if (child.type === 'comment' || this.blank(child)) continue;\n if (child.type !== 'element' || child.tag !== 'div') return undefined;\n const table = this.descend(child, ['table']);\n const body = table && this.descend(table, ['tbody']);\n if (!table || !body) return undefined;\n const rows = (body.children ?? []).filter((row) => !this.blank(row));\n if (rows.some((row) => row.type !== 'element' || row.tag !== 'tr')) return undefined;\n columns.push({ table, body, rows });\n }\n return columns.length ? columns : undefined;\n }\n\n private descend<T extends TreeNode<T>>(node: T, tags: readonly string[]): T | undefined {\n let current = node;\n for (const tag of tags) {\n const children = (current.children ?? []).filter((child) => !this.blank(child));\n const child = children[0];\n if (\n children.length !== 1 ||\n !child ||\n child.type !== 'element' ||\n child.tag !== tag ||\n (tag === 'table' && child.attrs?.role !== 'presentation')\n )\n return undefined;\n current = child;\n }\n return current;\n }\n\n private conditional(node: TreeNode<unknown>): ConditionalKind | undefined {\n const value = node.type === 'comment' ? (node.value ?? '') : '';\n if (!value.startsWith(CONDITIONAL_PREFIX) || !value.endsWith(CONDITIONAL_SUFFIX))\n return undefined;\n const markup = value.slice(CONDITIONAL_PREFIX.length, -CONDITIONAL_SUFFIX.length);\n if (markup === GHOST_CLOSE) return 'close';\n if (markup.startsWith(`${GHOST_CLOSE}<table`))\n return markup.endsWith('</table>') ? 'other' : 'bridge';\n if (!markup.startsWith('<table')) return 'other';\n // A table opened and closed by the same comment (an Outlook divider) changes no nesting.\n return markup.endsWith('</table>') ? 'inline' : 'open';\n }\n\n private layoutUnit(node: MutableNode): boolean {\n if (node.tag === 'table') return true;\n const elements = (node.children ?? []).filter((child) => child.type === 'element');\n return node.tag === 'div' && elements.length === 1 && elements[0]?.tag === 'table';\n }\n\n private wrapper(node: TreeNode<unknown>): boolean {\n return (\n node.type === 'element' &&\n node.tag === 'div' &&\n node.attrs?.role === 'article' &&\n node.attrs['aria-roledescription'] === 'email'\n );\n }\n\n private preheader(node: DocumentNode): boolean {\n return (\n node.type === 'element' &&\n node.tag === 'div' &&\n (node.children ?? []).every((child) => child.type === 'text') &&\n this.hidden(node.attrs?.style ?? '')\n );\n }\n\n private blank(node: TreeNode<unknown>): boolean {\n return node.type === 'text' && !node.value?.trim();\n }\n\n private trim(nodes: readonly DocumentNode[]): readonly DocumentNode[] {\n const first = nodes.findIndex((node) => !this.blank(node));\n if (first < 0) return [];\n const trailing = [...nodes].reverse().findIndex((node) => !this.blank(node));\n return nodes.slice(first, nodes.length - trailing);\n }\n\n private position(index: number | undefined, length: number): number {\n if (index === undefined) return length;\n if (!Number.isInteger(index) || index < 0 || index > length)\n throw new Error('Invalid insertion index');\n return index;\n }\n\n private find(nodes: MutableNode[], tag: string): MutableNode | undefined {\n for (const node of nodes) {\n if (node.tag === tag) return node;\n const found = this.find(node.children ?? [], tag);\n if (found) return found;\n }\n return undefined;\n }\n\n /** Ancestors of the node, outermost first and ending with the node itself. */\n private chain(nodes: MutableNode[], id: string): MutableNode[] {\n for (const node of nodes) {\n if (node.id === id) return [node];\n const nested = this.chain(node.children ?? [], id);\n if (nested.length) return [node, ...nested];\n }\n return [];\n }\n}\n","import type { DocumentNode, EditorDocumentData, SourceInput } from '../core/document';\nimport { EditorDocument } from '../core/document';\nimport { BlockCatalog } from '../core/catalog';\nimport { RichTextMarkup } from '../core/rich-text-markup';\nimport {\n RichTextFormatPolicy,\n RICH_TEXT_ORIGIN_ATTRIBUTE,\n RICH_TEXT_REMOVED_ATTRIBUTE,\n} from '../core/rich-text-format';\nimport type { BlockType } from '../core/catalog';\nimport { ContentService } from './content-service';\nimport { EmailInsertionPlanner } from './email-insertion';\nimport type { EmailInsertionUnit, MutableNode } from './email-insertion';\nimport type { AssetReference } from './host';\n\n/** Source of a block to insert. Generated e-mail blocks may state the unit they stand for. */\nexport interface InsertionSource extends SourceInput {\n readonly insertion?: EmailInsertionUnit;\n}\n\nconst EMAIL_IMAGE_STYLE = 'display:block;max-width:100%;height:auto;border:0';\nconst PAGE_IMAGE_STYLE = 'max-width:100%;height:auto';\n\ntype MutableDocument = {\n -readonly [K in keyof EditorDocumentData]: K extends 'nodes'\n ? MutableNode[]\n : EditorDocumentData[K];\n};\n\nexport class DocumentMutationService {\n private sequence = 0;\n private readonly formats = new RichTextFormatPolicy();\n private readonly markup = new RichTextMarkup();\n private readonly emails: EmailInsertionPlanner;\n constructor(\n private readonly content: ContentService,\n private readonly catalog: BlockCatalog,\n ) {\n this.emails = new EmailInsertionPlanner(\n () => this.id(),\n (style) => this.hidden(style),\n );\n }\n\n text(document: EditorDocumentData, id: string, value: string): EditorDocument {\n return this.mutate(document, id, (node) => {\n if (node.type === 'text') node.value = value;\n else {\n this.assertText(node);\n node.children = [{ id: this.id(), type: 'text', value }];\n }\n });\n }\n\n canEditRichText(document: EditorDocumentData, id: string): boolean {\n const node = this.find(document.nodes, id);\n return !!node && node.type === 'element' && this.catalog.canEditRichText(node);\n }\n\n validateRichTextProjection(document: EditorDocumentData, id: string, html: string): void {\n const imported = this.content.inspect({ html, css: '' }, document.kind);\n // A projection is written by the editor: anything the kind would remove makes it invalid.\n if (!imported.document || imported.diagnostics.some((item) => item.severity !== 'info'))\n throw new Error('Invalid rich text projection');\n this.content.assertWritable(imported.document.nodes);\n const violation = this.markup.violation(imported.document.nodes, 'block', {\n extraAttributes: [RICH_TEXT_ORIGIN_ATTRIBUTE, RICH_TEXT_REMOVED_ATTRIBUTE],\n style: (value) => !value || !!this.content.richTextStyles(value),\n element: (node) => {\n const removed = node.attrs?.[RICH_TEXT_REMOVED_ATTRIBUTE];\n return (\n removed === undefined ||\n (!!node.attrs?.[RICH_TEXT_ORIGIN_ATTRIBUTE] &&\n node.tag === 'span' &&\n this.formats.isFormat(removed))\n );\n },\n });\n if (violation === 'tag') throw new Error('Unsupported rich text projection');\n if (violation === 'attribute') throw new Error('Unsafe host projection attribute');\n if (violation === 'node') throw new Error('Invalid rich text removal');\n if (violation === 'style') throw new Error('Unsafe host projection style');\n const node = this.find(document.nodes, id);\n if (!node || node.type !== 'element' || !this.catalog.canEditRichText(node))\n throw new Error('Native content cannot be replaced');\n const children = this.richTextChildren(\n node,\n this.body(imported.document.nodes),\n document.nodes,\n document.css,\n );\n if (!this.catalog.acceptsRichText(node, children))\n throw new Error('Unsupported rich text content');\n }\n\n richText(document: EditorDocumentData, id: string, html: string): EditorDocument {\n const imported = this.content.inspect({ html, css: '' }, document.kind);\n if (!imported.document || imported.diagnostics.some((item) => item.severity !== 'info'))\n throw new Error('Invalid rich text');\n this.content.assertWritable(imported.document.nodes);\n const importedNodes = this.body(imported.document.nodes);\n return this.mutate(document, id, (node) => {\n if (!this.catalog.canEditRichText(node)) throw new Error('Native content cannot be replaced');\n const inlineOnly = !this.catalog.richTextAllowsBlocks(node);\n const paragraph =\n inlineOnly && importedNodes.length === 1 && importedNodes[0]?.tag === 'p'\n ? importedNodes[0]\n : undefined;\n const reconciled = this.restoreRichAttributes(\n paragraph?.children ?? importedNodes,\n node.children ?? [],\n document.nodes,\n document.css,\n );\n const children = this.unique(reconciled);\n if (!this.catalog.acceptsRichText(node, children))\n throw new Error('Unsupported rich text content');\n node.children = children;\n });\n }\n\n attribute(document: EditorDocumentData, id: string, name: string, value: string): EditorDocument {\n return this.mutate(document, id, (node) => {\n if (!this.catalog.acceptsProperty(node, name, 'attribute'))\n throw new Error('Unsupported visual attribute');\n this.content.assertWritable([\n { id: node.id, type: 'element', tag: node.tag ?? 'div', attrs: { [name]: value } },\n ]);\n node.attrs = { ...node.attrs, [name]: value };\n });\n }\n\n style(document: EditorDocumentData, id: string, property: string, value: string): EditorDocument {\n if (value.includes(';') || value.includes('{') || value.includes('}'))\n throw new Error('Unsupported visual style');\n return this.mutate(document, id, (node) => {\n if (!this.catalog.acceptsProperty(node, property, 'style'))\n throw new Error('Unsupported visual style');\n node.attrs = {\n ...node.attrs,\n style: this.content.setStyle(node.attrs?.style ?? '', property, value),\n };\n });\n }\n\n connectFormReference(\n document: EditorDocumentData,\n reference: string,\n id?: string,\n parentId?: string,\n index?: number,\n ): EditorDocument {\n if (document.kind !== 'page' || !/^[A-Za-z0-9_-]{1,128}$/.test(reference))\n throw new Error('Invalid form reference');\n if (id)\n return this.mutate(document, id, (node) => {\n if (\n node.type !== 'element' ||\n node.tag !== 'div' ||\n node.attrs?.['data-host-slot'] !== 'form' ||\n (node.children ?? []).length\n )\n throw new Error('Invalid form slot');\n node.attrs = { ...node.attrs, 'data-host-reference': reference };\n });\n return this.insert(\n document,\n {\n html: `<div data-host-slot=\"form\" data-host-reference=\"${reference}\"></div>`,\n css: '',\n },\n parentId,\n index,\n );\n }\n\n attachAsset(\n document: EditorDocumentData,\n asset: AssetReference,\n id?: string,\n parentId?: string,\n index?: number,\n ): EditorDocument {\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(asset.id)) throw new Error('Invalid asset reference');\n this.content.assertWritable([\n { id: 'asset', type: 'element', tag: 'img', attrs: { src: asset.url, alt: asset.alt } },\n ]);\n if (id)\n return this.mutate(document, id, (node) => {\n if (node.type !== 'element' || node.tag !== 'img') throw new Error('Invalid image target');\n const attrs: Record<string, string> = {\n ...node.attrs,\n src: asset.url,\n alt: asset.alt,\n 'data-host-asset-id': asset.id,\n };\n delete attrs['data-lyads-asset-id'];\n node.attrs = attrs;\n });\n const data = this.mutable(document);\n const parent = parentId ? this.find(data.nodes, parentId) : this.findTag(data.nodes, 'body');\n if (parentId && !parent) throw new Error('Missing parent');\n const image: MutableNode = {\n id: this.id(),\n type: 'element',\n tag: 'img',\n attrs: {\n src: asset.url,\n alt: asset.alt,\n style: document.kind === 'email' ? EMAIL_IMAGE_STYLE : PAGE_IMAGE_STYLE,\n 'data-host-asset-id': asset.id,\n },\n };\n if (document.kind === 'email') {\n // The image is born inside a content cell, never loose between layout tables.\n const plan = this.emails.placeImage(data.nodes, parent, index, image);\n this.assertParent(plan.parent, plan.parent?.id, plan.nodes);\n plan.target.splice(plan.index, 0, ...plan.nodes.map((node) => this.copyNode(node)));\n return this.next(document, data);\n }\n this.assertParent(parent, parentId, [image]);\n const target = parent ? (parent.children ??= []) : data.nodes;\n target.splice(this.position(index, target.length), 0, image);\n return this.next(document, data);\n }\n\n insert(\n document: EditorDocumentData,\n source: InsertionSource,\n parentId?: string,\n index?: number,\n ): EditorDocument {\n const imported = this.content.inspect({ html: source.html, css: source.css }, document.kind);\n if (!imported.document || imported.diagnostics.some((item) => item.severity === 'error'))\n throw new Error('Invalid block');\n const data = this.mutable(document);\n const parent = parentId ? this.find(data.nodes, parentId) : this.findTag(data.nodes, 'body');\n if (parentId && !parent) throw new Error('Missing parent');\n const body = this.body(imported.document.nodes);\n const block = document.kind === 'email' ? this.emails.block(body) : undefined;\n if (block?.compiled) {\n // Only the unit which fits the destination travels: never the preheader, the article\n // wrapper or, inside a column, the section shell with its Outlook ghost table.\n const unit =\n source.insertion === 'content' || source.insertion === 'section'\n ? source.insertion\n : undefined;\n const plan = this.emails.place(data.nodes, parent, index, block, unit);\n const nodes = this.unique(plan.nodes);\n this.assertParent(plan.parent, plan.parent?.id, nodes);\n plan.target.splice(plan.index, 0, ...nodes);\n } else {\n const target = parent ? (parent.children ??= []) : data.nodes;\n const nodes = this.insertionNodes(this.unique(body), parent, document.kind);\n this.assertParent(parent, parentId, nodes);\n target.splice(this.position(index, target.length), 0, ...nodes);\n }\n const head = this.findTag(imported.document.nodes, 'head');\n const styles =\n head?.children\n ?.filter((node) => node.tag === 'style')\n .map((node) => (node.children ?? []).map((child) => child.value ?? '').join('')) ?? [];\n data.css = this.content.addDefaultStyles(data.css, [imported.document.css, ...styles]);\n return this.next(document, data);\n }\n\n add(\n document: EditorDocumentData,\n type: BlockType,\n parentId?: string,\n index?: number,\n ): EditorDocument {\n const data = this.mutable(document);\n const parent = parentId ? this.find(data.nodes, parentId) : this.findTag(data.nodes, 'body');\n const block = this.copyNode(this.catalog.create(type, this.id(), data.kind));\n this.assertParent(parent, parentId, [block]);\n const target = parent ? (parent.children ??= []) : data.nodes;\n target.splice(this.position(index, target.length), 0, block);\n return this.next(document, data);\n }\n\n remove(document: EditorDocumentData, id: string): EditorDocument {\n const data = this.mutable(document);\n const parent = this.parent(data.nodes, id);\n if (!parent) throw new Error('Missing node');\n this.assertStructuralEdit(parent.nodes[parent.index]);\n parent.nodes.splice(parent.index, 1);\n return this.next(document, data);\n }\n\n duplicate(document: EditorDocumentData, id: string): EditorDocument {\n const data = this.mutable(document);\n const parent = this.parent(data.nodes, id);\n if (!parent) throw new Error('Missing node');\n const original = parent.nodes[parent.index];\n if (!original) throw new Error('Missing node');\n this.assertStructuralEdit(original);\n const copies = this.unique([original]);\n const clearIdentities = (nodes: MutableNode[]): void => {\n for (const node of nodes) {\n if (node.attrs) {\n delete node.attrs.id;\n delete node.attrs.name;\n }\n clearIdentities(node.children ?? []);\n }\n };\n clearIdentities(copies);\n parent.nodes.splice(parent.index + 1, 0, ...copies);\n return this.next(document, data);\n }\n\n move(\n document: EditorDocumentData,\n id: string,\n parentId: string | undefined,\n index: number,\n ): EditorDocument {\n const data = this.mutable(document);\n const source = this.parent(data.nodes, id);\n const node = source?.nodes[source.index];\n if (!source || !node) throw new Error('Missing node');\n this.assertStructuralEdit(node);\n if (parentId && (parentId === id || this.find(node.children ?? [], parentId)))\n throw new Error('Cyclic move');\n const parent = parentId ? this.find(data.nodes, parentId) : this.findTag(data.nodes, 'body');\n this.assertParent(parent, parentId, [node]);\n const target = parent ? (parent.children ??= []) : data.nodes;\n const finalLength = target.length - (source.nodes === target ? 1 : 0);\n const position = this.position(index, finalLength);\n source.nodes.splice(source.index, 1);\n target.splice(position, 0, node);\n return this.next(document, data);\n }\n\n private richTextChildren(\n parent: DocumentNode,\n imported: readonly DocumentNode[],\n documentNodes: readonly DocumentNode[],\n documentCss: string,\n ): readonly DocumentNode[] {\n const paragraph =\n !this.catalog.richTextAllowsBlocks(parent) &&\n imported.length === 1 &&\n imported[0]?.tag === 'p'\n ? imported[0]\n : undefined;\n return this.restoreRichAttributes(\n paragraph?.children ?? imported,\n parent.children ?? [],\n documentNodes,\n documentCss,\n );\n }\n\n private insertionNodes(\n nodes: MutableNode[],\n parent: MutableNode | undefined,\n kind: EditorDocumentData['kind'],\n ): MutableNode[] {\n if (kind !== 'email' || !parent || this.catalog.acceptsChildren(parent, nodes)) return nodes;\n // Generated email snippets keep their native HTML envelope inside a valid table unit.\n // This composes new MJML output; it does not reverse-compile an imported document.\n if (['tbody', 'thead', 'tfoot'].includes(parent.tag ?? '')) {\n return [\n {\n id: this.id(),\n type: 'element',\n tag: 'tr',\n children: [{ id: this.id(), type: 'element', tag: 'td', children: nodes }],\n },\n ];\n }\n if (parent.tag === 'tr')\n return [{ id: this.id(), type: 'element', tag: 'td', children: nodes }];\n return nodes;\n }\n\n private restoreRichAttributes(\n next: readonly DocumentNode[],\n previous: readonly DocumentNode[],\n documentNodes: readonly DocumentNode[],\n documentCss: string,\n ): readonly DocumentNode[] {\n const originals = new Map<string, DocumentNode>();\n const collect = (nodes: readonly DocumentNode[]): void => {\n for (const node of nodes) {\n originals.set(node.id, node);\n collect(node.children ?? []);\n }\n };\n collect(previous);\n const identities = new Map<string, Set<string>>();\n const collectIdentities = (nodes: readonly DocumentNode[]): void => {\n for (const node of nodes) {\n for (const value of [node.attrs?.id, node.attrs?.name]) {\n if (!value) continue;\n const owners = identities.get(value) ?? new Set<string>();\n owners.add(node.id);\n identities.set(value, owners);\n }\n collectIdentities(node.children ?? []);\n }\n };\n collectIdentities(documentNodes);\n let decorationRules: boolean | undefined;\n const ambiguousDecoration = (): boolean => {\n if (decorationRules !== undefined) return decorationRules;\n const stylesheets = [documentCss];\n const collectStylesheets = (nodes: readonly DocumentNode[]): void => {\n for (const node of nodes) {\n if (node.tag === 'style')\n stylesheets.push((node.children ?? []).map((child) => child.value ?? '').join(''));\n collectStylesheets(node.children ?? []);\n }\n };\n collectStylesheets(documentNodes);\n decorationRules = stylesheets.some((css) => this.content.hasDecorationRules(css));\n return decorationRules;\n };\n const used = new Set<string>();\n const equivalent = (tag: string | undefined): string | undefined =>\n (({ b: 'strong', i: 'em', small: 'span' }) as Readonly<Record<string, string>>)[tag ?? ''] ??\n tag;\n const restore = (nodes: readonly DocumentNode[]): readonly DocumentNode[] =>\n nodes.map((node) => {\n if (node.type !== 'element') return node;\n const origin = node.attrs?.[RICH_TEXT_ORIGIN_ATTRIBUTE];\n const original = origin ? originals.get(origin) : undefined;\n const removed = node.attrs?.[RICH_TEXT_REMOVED_ATTRIBUTE];\n if (removed !== undefined) {\n if (!origin || !original || !this.formats.canRemove(original.tag, node.tag, removed))\n throw new Error('Invalid rich text removal');\n } else if (origin && (!original || equivalent(original.tag) !== equivalent(node.tag)))\n throw new Error('Invalid rich text origin');\n const split = !!origin && used.has(origin);\n if (origin) used.add(origin);\n const attrs = { ...original?.attrs, ...node.attrs };\n if (node.attrs?.style)\n attrs.style = this.content.mergeRichTextStyle(\n original?.attrs?.style ?? '',\n node.attrs.style,\n );\n delete attrs[RICH_TEXT_ORIGIN_ATTRIBUTE];\n delete attrs[RICH_TEXT_REMOVED_ATTRIBUTE];\n if (this.formats.isFormat(removed)) {\n for (const attribute of this.formats.removedAttributes(removed)) delete attrs[attribute];\n if (removed === 'link' && attrs.name) {\n const owners = identities.get(attrs.name);\n if (!attrs.id && owners?.size === 1 && original && owners.has(original.id))\n attrs.id = attrs.name;\n delete attrs.name;\n }\n for (const [property, value] of Object.entries(this.formats.resets(removed)))\n attrs.style = this.content.setStyle(attrs.style ?? '', property, value);\n const decoration = this.formats.decorationFor(removed);\n if (decoration) {\n if (ambiguousDecoration()) throw new Error('AMBIGUOUS_TEXT_DECORATION');\n attrs.style = this.content.removeDecoration(attrs.style ?? '', decoration);\n }\n }\n // Rich editors split a mark/paragraph when formatting or pressing Enter.\n // Safe presentation attributes follow each segment; HTML identity stays unique.\n if (split) {\n delete attrs.id;\n delete attrs.name;\n }\n return {\n ...node,\n ...(removed !== undefined ? { tag: 'span' } : original?.tag ? { tag: original.tag } : {}),\n ...(Object.keys(attrs).length ? { attrs } : { attrs: {} }),\n ...(node.children ? { children: restore(node.children) } : {}),\n };\n });\n return restore(next);\n }\n\n private mutate(\n document: EditorDocumentData,\n id: string,\n change: (node: MutableNode) => void,\n ): EditorDocument {\n const data = this.mutable(document);\n const node = this.find(data.nodes, id);\n if (!node) throw new Error('Missing node');\n change(node);\n return this.next(document, data);\n }\n\n private next(previous: EditorDocumentData, next: MutableDocument): EditorDocument {\n next.revision = previous.revision + 1;\n return this.content.document(next);\n }\n\n private id(): string {\n return `inserted-${Date.now().toString(36)}-${++this.sequence}`;\n }\n\n private hidden(style: string): boolean {\n if (!style.trim()) return false;\n try {\n return this.content.inlineDeclarations(style).display === 'none';\n } catch {\n return false;\n }\n }\n private position(index: number | undefined, length: number): number {\n if (index === undefined) return length;\n if (!Number.isInteger(index) || index < 0 || index > length)\n throw new Error('Invalid insertion index');\n return index;\n }\n\n private find(nodes: MutableNode[], id: string): MutableNode | undefined;\n private find(nodes: readonly DocumentNode[], id: string): DocumentNode | undefined;\n private find(nodes: readonly DocumentNode[], id: string): DocumentNode | undefined {\n for (const node of nodes) {\n if (node.id === id) return node;\n const found = this.find(node.children ?? [], id);\n if (found) return found;\n }\n return undefined;\n }\n\n private findTag(nodes: MutableNode[], tag: string): MutableNode | undefined;\n private findTag(nodes: readonly DocumentNode[], tag: string): DocumentNode | undefined;\n private findTag(nodes: readonly DocumentNode[], tag: string): DocumentNode | undefined {\n for (const node of nodes) {\n if (node.tag === tag) return node;\n const found = this.findTag(node.children ?? [], tag);\n if (found) return found;\n }\n return undefined;\n }\n\n private parent(\n nodes: MutableNode[],\n id: string,\n ): { nodes: MutableNode[]; index: number } | undefined {\n const index = nodes.findIndex((node) => node.id === id);\n if (index >= 0) return { nodes, index };\n for (const node of nodes) {\n const found = this.parent(node.children ?? [], id);\n if (found) return found;\n }\n return undefined;\n }\n\n private body(nodes: readonly DocumentNode[]): readonly DocumentNode[] {\n return (\n this.findTag(nodes, 'body')?.children ??\n nodes.filter((node) => node.type !== 'doctype' && node.tag !== 'head')\n );\n }\n\n private assertText(node: MutableNode): void {\n if (!this.catalog.canEditText(node)) throw new Error('Native content cannot be replaced');\n }\n\n private assertStructuralEdit(node: MutableNode | undefined): void {\n if (\n !node ||\n node.type === 'doctype' ||\n ['html', 'head', 'body', 'meta', 'style', 'title'].includes(node.tag ?? '')\n )\n throw new Error('Document infrastructure is not a content block');\n }\n\n private assertParent(\n parent: MutableNode | undefined,\n id: string | undefined,\n children: readonly DocumentNode[],\n ): void {\n if (id && !parent) throw new Error('Missing parent');\n if (!parent) {\n if (!this.catalog.acceptsRootChildren(children)) throw new Error('Unsupported root content');\n return;\n }\n if (!this.catalog.acceptsChildren(parent, children))\n throw new Error('Unsupported insertion parent');\n }\n private unique(nodes: readonly DocumentNode[]): MutableNode[] {\n return nodes.map((node) => {\n const clone = this.copyNode(node);\n clone.id = this.id();\n // Source positions and recognition belong to the original. How a comment was written\n // (`<![if !mso]>`, `<?xml ?>`) is part of what it means and travels with the copy.\n const opener = clone.metadata?.commentOpener;\n delete clone.metadata;\n if (opener !== undefined) clone.metadata = { commentOpener: opener };\n if (clone.children) clone.children = this.unique(clone.children);\n return clone;\n });\n }\n\n private mutable(document: EditorDocumentData): MutableDocument {\n return { ...document, nodes: document.nodes.map((node) => this.copyNode(node)) };\n }\n\n private copyNode(node: DocumentNode): MutableNode {\n return {\n id: node.id,\n type: node.type,\n ...(node.tag !== undefined ? { tag: node.tag } : {}),\n ...(node.value !== undefined ? { value: node.value } : {}),\n ...(node.attrs ? { attrs: { ...node.attrs } } : {}),\n ...(node.children ? { children: node.children.map((child) => this.copyNode(child)) } : {}),\n ...(node.metadata ? { metadata: { ...node.metadata } } : {}),\n };\n }\n}\n","import { EditorDocument } from '../core/document';\nimport type { DocumentNode, EditorDocumentData, SourceInput } from '../core/document';\nimport { SectionLayoutPolicy } from '../core/section-layout';\nimport type {\n SectionLayoutContext,\n SectionLayoutPatch,\n SectionLayoutProjection,\n SectionLayoutSettings,\n} from '../core/section-layout';\nimport { ContentService } from './content-service';\n\nexport interface SectionScaffoldPort {\n create(settings: SectionLayoutSettings, original: SectionLayoutProjection): Promise<SourceInput>;\n supports(projection: SectionLayoutProjection): boolean;\n}\nexport interface SectionIdentityPort {\n next(): string;\n}\n\n/** Changes a supported section, retaining content identities and untouched document regions. */\nexport class SectionLayoutService {\n private readonly policy = new SectionLayoutPolicy();\n constructor(\n private readonly content: ContentService,\n private readonly identities: SectionIdentityPort,\n private readonly scaffold?: SectionScaffoldPort,\n ) {}\n context(document: EditorDocumentData, id: string): SectionLayoutContext | undefined {\n const context = this.policy.context(document, id);\n if (!context) return undefined;\n const projection = this.policy.projection(document, id);\n if (document.kind === 'email' && (!projection || !this.scaffold?.supports(projection)))\n return { ...context, editable: false, reason: 'unsupported-structure' };\n return context;\n }\n async update(\n document: EditorDocumentData,\n id: string,\n patch: SectionLayoutPatch,\n ): Promise<EditorDocument> {\n const context = this.context(document, id);\n const projection = this.policy.projection(document, id);\n if (!context?.editable || !projection)\n throw new Error(context?.reason ?? 'unsupported-structure');\n const settings = this.policy.settings(context, patch);\n for (const column of projection.columns.slice(settings.ratios.length)) {\n const reason = this.policy.removalReason(column, document.kind);\n if (reason) throw new Error(reason);\n }\n const ids = new Set(this.all(document.nodes).map((node) => node.id));\n let section: DocumentNode;\n let extraCss = '';\n if (document.kind === 'page') {\n const columns = projection.columns.slice(0, settings.ratios.length);\n while (columns.length < settings.ratios.length)\n columns.push({\n id: this.fresh(ids),\n type: 'element',\n tag: 'div',\n attrs: { 'data-editor-layout-column': 'true' },\n children: [],\n });\n const retained = new Set(columns.map((column) => column.id));\n const children = (projection.section.children ?? []).filter(\n (node) => node.type !== 'element' || retained.has(node.id),\n );\n children.push(\n ...columns.filter((column) => !projection.columns.some((old) => old.id === column.id)),\n );\n section = {\n ...projection.section,\n attrs: {\n ...projection.section.attrs,\n ...this.policy.attributes(settings),\n style: this.content.withoutStyles(projection.section.attrs?.style ?? '', [\n 'display',\n 'grid-template-columns',\n 'grid-template',\n 'grid',\n 'flex-direction',\n 'flex-flow',\n ]),\n },\n children,\n };\n } else {\n if (!this.scaffold) throw new Error('unavailable');\n const source = await this.scaffold.create(settings, projection);\n const imported = this.content.inspect(source, 'email');\n if (!imported.document) throw new Error('unsupported-structure');\n const generated = this.all(imported.document.nodes).find((node) =>\n this.policy.hasClass(node, 'editor-layout-section'),\n );\n const shell = generated && this.policy.projection(imported.document, generated.id);\n if (!shell || !this.scaffold.supports(shell)) throw new Error('unsupported-structure');\n const columnMap = new Map(shell.columns.map((column, index) => [column.id, index]));\n const shellMap = new Map(\n (shell.shell ?? []).map((node, index) => [node.id, projection.shell?.[index]]),\n );\n const transplant = (node: DocumentNode): DocumentNode => {\n if (node.type !== 'element') return { ...node, id: this.fresh(ids) };\n const index = columnMap.get(node.id);\n if (index !== undefined) {\n const old = projection.columns[index];\n if (old)\n return {\n ...old,\n attrs: {\n ...old.attrs,\n class: [\n ...(old.attrs?.class ?? '')\n .split(/\\s+/)\n .filter((value) => value && !value.startsWith('mj-column-per-')),\n 'editor-layout-column',\n ]\n .filter((value, position, values) => values.indexOf(value) === position)\n .join(' '),\n style: this.content.withoutStyles(old.attrs?.style ?? '', [\n 'width',\n 'max-width',\n 'display',\n ]),\n },\n };\n }\n const old = shellMap.get(node.id);\n const attrs: Record<string, string> = old ? { ...old.attrs } : { ...node.attrs };\n if (index !== undefined) {\n attrs.class = (attrs.class ?? '')\n .split(/\\s+/)\n .filter((value) => value && !value.startsWith('mj-column-per-'))\n .join(' ');\n attrs.style = this.content.withoutStyles(attrs.style ?? '', [\n 'width',\n 'max-width',\n 'display',\n ]);\n }\n if (node.id === shell.contentParent?.id)\n attrs.style = this.content.withoutStyles(attrs.style ?? '', ['direction']);\n return {\n ...node,\n id: old?.id ?? this.fresh(ids),\n attrs,\n children: (node.children ?? []).map(transplant),\n };\n };\n section = transplant(shell.section);\n section = { ...section, attrs: { ...section.attrs, ...this.policy.attributes(settings) } };\n extraCss = imported.document.css;\n }\n const css = this.content.addDefaultStyles(document.css, [\n extraCss,\n this.styles(settings, document.kind),\n ]);\n const nodes = this.replace(document.nodes, projection.section.id, section);\n return this.content.document(\n EditorDocument.from(document).withChanges({ nodes, css }).snapshot(),\n );\n }\n private styles(settings: SectionLayoutSettings, kind: 'email' | 'page'): string {\n const key = `[data-editor-layout=\"columns\"][data-editor-layout-ratios=\"${settings.ratios.join('-')}\"][data-editor-layout-stacking=\"${settings.stacking}\"][data-editor-layout-breakpoint=\"${settings.breakpoint}\"]`;\n const host = kind === 'page' ? key : `${key}>table>tbody>tr>td`;\n const children = `${host}>${kind === 'page' ? '*' : '.editor-layout-column'}`;\n const total = settings.ratios.reduce((sum, weight) => sum + weight, 0);\n const desktop =\n kind === 'page'\n ? `${host}{display:grid!important;grid-template-columns:${settings.ratios.map((weight) => `minmax(0,${weight}fr)`).join(' ')}!important}`\n : `${host}{direction:ltr!important}${settings.ratios.map((weight, index) => `${children}:nth-of-type(${index + 1}){display:inline-block!important;width:${Math.round((weight / total) * 1000000) / 10000}%!important;vertical-align:top}`).join('')}`;\n const stack =\n settings.stacking === 'none'\n ? ''\n : `@media(max-width:${settings.breakpoint}px){${host}{display:flex!important;flex-direction:${settings.stacking === 'reverse' ? 'column-reverse' : 'column'}!important}${children}{width:100%!important;max-width:100%!important}}`;\n return `${desktop}${children}{min-width:0;box-sizing:border-box}${stack}`;\n }\n private fresh(ids: Set<string>): string {\n for (let attempt = 0; attempt < 16; attempt++) {\n const id = this.identities.next();\n if (id && !ids.has(id)) {\n ids.add(id);\n return id;\n }\n }\n throw new Error('IDENTITY_COLLISION');\n }\n private all(nodes: readonly DocumentNode[]): readonly DocumentNode[] {\n return nodes.flatMap((node) => [node, ...this.all(node.children ?? [])]);\n }\n private replace(\n nodes: readonly DocumentNode[],\n id: string,\n replacement: DocumentNode,\n ): readonly DocumentNode[] {\n return nodes.map((node) =>\n node.id === id\n ? replacement\n : node.children\n ? { ...node, children: this.replace(node.children, id, replacement) }\n : node,\n );\n }\n}\n","import type { EditorDocumentData, SourceInput } from '../core/document';\nimport type { DocumentOutputCodec, DocumentOutputPolicy } from './page-renderer';\n\nexport interface MjmlCompilerPort {\n compile(source: string): Promise<string>;\n}\n\n/** MJML is for creating supported content; imported HTML is never recompiled. */\nexport class MjmlEmailRenderer {\n constructor(\n private readonly codec: DocumentOutputCodec,\n private readonly policy: DocumentOutputPolicy,\n private readonly compiler: MjmlCompilerPort,\n ) {}\n\n render(document: EditorDocumentData): SourceInput {\n if (document.kind !== 'email') throw new Error('renderer.kind_mismatch');\n this.policy.assertSafe(document);\n return this.codec.export(document);\n }\n\n async createSource(mjml: string): Promise<SourceInput> {\n // Catalog-owned MJML only. The compiler adapter enforces limits and no includes.\n return { html: await this.compiler.compile(mjml), css: '' };\n }\n}\n","import { Tokenizer } from 'parse5';\nimport type { Token } from 'parse5';\nimport type { SectionScaffoldPort } from '../application/section-layout';\nimport type { SectionLayoutProjection, SectionLayoutSettings } from '../core/section-layout';\nimport type { DocumentNode, SourceInput } from '../core/document';\nimport type { CssDocumentCodec } from '../codecs/css';\nimport { MjmlEmailRenderer } from './email-renderer';\n\n/** Generates only an empty MJML layout shell. Existing column HTML is transplanted by application. */\nexport class MjmlSectionScaffold implements SectionScaffoldPort {\n constructor(\n private readonly renderer: MjmlEmailRenderer,\n private readonly styles: Pick<CssDocumentCodec, 'inspect' | 'readDeclarations'>,\n ) {}\n create(settings: SectionLayoutSettings, original: SectionLayoutProjection): Promise<SourceInput> {\n const geometry = this.geometry(original);\n if (!geometry) throw new Error('unsupported-structure');\n const total = settings.ratios.reduce((sum, value) => sum + value, 0);\n const columns = settings.ratios\n .map(\n (weight) =>\n `<mj-column css-class=\"editor-layout-column\" width=\"${Math.round((weight / total) * 1000000) / 10000}%\"></mj-column>`,\n )\n .join('');\n return this.renderer.createSource(\n `<mjml><mj-head><mj-breakpoint width=\"${settings.breakpoint + 1}px\" /></mj-head><mj-body width=\"600px\"><mj-section css-class=\"editor-layout-section\" padding=\"${geometry.padding}\">${columns}</mj-section></mj-body></mjml>`,\n );\n }\n supports(projection: SectionLayoutProjection): boolean {\n if (\n projection.section.type !== 'element' ||\n projection.section.tag !== 'div' ||\n !projection.shell ||\n projection.shell.length !== 5 ||\n !this.geometry(projection)\n )\n return false;\n return (\n projection.shell.every((node) =>\n (node.children ?? []).every(\n (child) => child.type !== 'comment' || this.layoutComment(child),\n ),\n ) &&\n projection.columns.every((column) =>\n (column.children ?? []).every((child) => child.type !== 'text' || !child.value?.trim()),\n )\n );\n }\n private geometry(projection: SectionLayoutProjection): { padding: string } | undefined {\n const root = this.styles.inspect(projection.section.attrs?.style ?? '', 'declarationList');\n const inner = this.styles.inspect(\n projection.contentParent?.attrs?.style ?? '',\n 'declarationList',\n );\n if (root.diagnostics.length || inner.diagnostics.length) return undefined;\n const rootDeclarations = this.styles.readDeclarations(projection.section.attrs?.style ?? '');\n const innerDeclarations = this.styles.readDeclarations(\n projection.contentParent?.attrs?.style ?? '',\n );\n const padding = innerDeclarations.padding ?? '20px 0';\n if (\n root.diagnostics.length ||\n inner.diagnostics.length ||\n rootDeclarations['max-width'] !== '600px' ||\n Object.keys(innerDeclarations).some(\n (property) => property.startsWith('padding-') || property.startsWith('border'),\n ) ||\n !/^(?:[0-9]+(?:\\.[0-9]+)?(?:px)?)(?:\\s+[0-9]+(?:\\.[0-9]+)?(?:px)?){0,3}$/.test(padding) ||\n padding.split(/\\s+/).some((value) => parseFloat(value) > 200)\n )\n return undefined;\n return { padding };\n }\n private layoutComment(node: DocumentNode): boolean {\n const value = (node.value ?? '').trim();\n const start = value.indexOf(']>');\n const end = value.toLowerCase().lastIndexOf('<![endif]');\n if (\n start < 0 ||\n end < start ||\n !['[if mso | IE', '[if mso', '[if IE'].includes(value.slice(0, start))\n )\n return false;\n let valid = true;\n // Conditional fragments deliberately contain unmatched table boundaries. Tokenization\n // retains every attribute, unlike HTML fragment tree building which can drop a table opener.\n const tokenizer = new Tokenizer(\n {},\n {\n onStartTag: (token) => {\n if (!this.layoutTag(token)) valid = false;\n },\n onEndTag: (token) => {\n if (!['table', 'tbody', 'tr', 'td'].includes(token.tagName) || token.attrs.length)\n valid = false;\n },\n onCharacter: (token) => {\n if (token.chars.trim()) valid = false;\n },\n onWhitespaceCharacter: () => undefined,\n onNullCharacter: () => {\n valid = false;\n },\n onComment: () => {\n valid = false;\n },\n onDoctype: () => {\n valid = false;\n },\n onParseError: () => {\n valid = false;\n },\n onEof: () => undefined,\n },\n );\n tokenizer.write(value.slice(start + 2, end), true);\n return valid;\n }\n private layoutTag(token: Token.TagToken): boolean {\n if (!['table', 'tbody', 'tr', 'td'].includes(token.tagName)) return false;\n const fixedValues: Readonly<Record<string, string>> = {\n role: 'presentation',\n border: '0',\n cellpadding: '0',\n cellspacing: '0',\n align: 'center',\n };\n for (const attr of token.attrs) {\n if (Object.hasOwn(fixedValues, attr.name)) {\n if (token.tagName !== 'table' || attr.value !== fixedValues[attr.name]) return false;\n continue;\n }\n if (attr.name === 'width') {\n if (\n !['table', 'td'].includes(token.tagName) ||\n !/^[0-9]+(?:\\.[0-9]+)?(?:px)?$/.test(attr.value) ||\n parseFloat(attr.value) <= 0 ||\n parseFloat(attr.value) > 600\n )\n return false;\n continue;\n }\n if (attr.name === 'class') {\n if (\n token.tagName !== 'td' ||\n attr.value\n .split(/\\s+/)\n .some(\n (name) =>\n !['editor-layout-column-outlook', 'editor-layout-section-outlook'].includes(name),\n )\n )\n return false;\n continue;\n }\n if (attr.name !== 'style') return false;\n const inspected = this.styles.inspect(attr.value, 'declarationList');\n if (\n inspected.diagnostics.length ||\n Object.keys(inspected.declarations).some(\n (property) => !['vertical-align', 'width'].includes(property),\n )\n )\n return false;\n }\n return true;\n }\n}\n","import type { DocumentNode, EditorDocumentData } from '../core/document';\nimport { EditorDocument } from '../core/document';\nimport { ContentService } from './content-service';\n\nexport interface ImageLinkOptions {\n readonly target?: '_blank' | '_self';\n}\nexport interface ImageLinkContext {\n readonly imageId: string;\n readonly anchorId?: string;\n readonly href: string;\n readonly target: string;\n readonly rel: string;\n readonly shared: boolean;\n readonly editable: boolean;\n readonly reason?: 'shared-structure' | 'shared-identity' | 'nested-link';\n}\nexport interface ImageLinkUrlPort {\n isSafe(value: string, purpose: 'link'): boolean;\n}\nexport interface ImageLinkIdentityPort {\n next(): string;\n}\ninterface ImageLinkLocation {\n readonly image: DocumentNode;\n readonly anchor?: DocumentNode;\n readonly branch?: DocumentNode;\n readonly shared: boolean;\n readonly editable: boolean;\n readonly reason?: ImageLinkContext['reason'];\n}\n\n/** Changes the link of one image while retaining unrelated content and link destinations. */\nexport class ImageLinkService {\n constructor(\n private readonly content: ContentService,\n private readonly urls: ImageLinkUrlPort,\n private readonly identifiers: ImageLinkIdentityPort,\n ) {}\n\n context(document: EditorDocumentData, imageId: string): ImageLinkContext | undefined {\n const location = this.locate(document, imageId);\n if (!location) return undefined;\n return {\n imageId: location.image.id,\n ...(location.anchor ? { anchorId: location.anchor.id } : {}),\n href: location.anchor?.attrs?.href ?? '',\n target: location.anchor?.attrs?.target ?? '_self',\n rel: location.anchor?.attrs?.rel ?? '',\n shared: location.shared,\n editable: location.editable,\n ...(location.reason ? { reason: location.reason } : {}),\n };\n }\n\n update(\n document: EditorDocumentData,\n imageId: string,\n href: string,\n options: ImageLinkOptions = {},\n ): EditorDocument {\n if (typeof href !== 'string' || !this.urls.isSafe(href, 'link'))\n throw new Error('IMAGE_LINK_INVALID_URL');\n if (options.target !== undefined && !['_blank', '_self'].includes(options.target))\n throw new Error('IMAGE_LINK_INVALID_TARGET');\n const location = this.locate(document, imageId);\n if (!location || !location.editable) throw new Error('IMAGE_LINK_UNSUPPORTED_CONTEXT');\n const value = href.trim();\n const ids = new Set<string>();\n const collect = (nodes: readonly DocumentNode[]): void => {\n for (const node of nodes) {\n ids.add(node.id);\n collect(node.children ?? []);\n }\n };\n collect(document.nodes);\n const freshId = (): string => {\n for (let attempt = 0; attempt < 16; attempt++) {\n const id = `image-link-${this.identifiers.next()}`;\n if (!ids.has(id)) {\n ids.add(id);\n return id;\n }\n }\n throw new Error('IMAGE_LINK_IDENTITY_UNAVAILABLE');\n };\n const anchor = location.anchor;\n const attrs = this.attributes(anchor, value, options);\n let targetId: string;\n let replacement: readonly DocumentNode[];\n if (!anchor) {\n if (!value) return this.content.document(document);\n targetId = location.image.id;\n replacement = [\n { id: freshId(), type: 'element', tag: 'a', attrs, children: [location.image] },\n ];\n } else if (!location.shared) {\n targetId = anchor.id;\n replacement = value ? [{ ...anchor, attrs }] : (anchor.children ?? []);\n } else {\n const branch = location.branch;\n if (!branch) throw new Error('IMAGE_LINK_UNSUPPORTED_CONTEXT');\n const children = anchor.children ?? [];\n const position = children.findIndex((node) => node.id === branch.id);\n if (position < 0) throw new Error('IMAGE_LINK_UNSUPPORTED_CONTEXT');\n const before = children.slice(0, position);\n const after = children.slice(position + 1);\n const pieces: DocumentNode[] = [];\n let originalUsed = false;\n const retain = (nodes: readonly DocumentNode[]): void => {\n if (!nodes.length) return;\n pieces.push({\n id: originalUsed ? freshId() : anchor.id,\n type: 'element',\n tag: 'a',\n ...(anchor.attrs ? { attrs: { ...anchor.attrs } } : {}),\n children: nodes,\n });\n originalUsed = true;\n };\n retain(before);\n pieces.push(\n value ? { id: freshId(), type: 'element', tag: 'a', attrs, children: [branch] } : branch,\n );\n retain(after);\n targetId = anchor.id;\n replacement = pieces;\n }\n const nodes = this.replace(document.nodes, targetId, replacement);\n return this.content.document(EditorDocument.from(document).withChanges({ nodes }).snapshot());\n }\n\n private attributes(\n anchor: DocumentNode | undefined,\n href: string,\n options: ImageLinkOptions,\n ): Readonly<Record<string, string>> {\n const attrs: Record<string, string> = { ...anchor?.attrs, href };\n if (options.target !== undefined) attrs.target = options.target;\n if (attrs.target === '_blank') {\n const rel = new Set((attrs.rel ?? '').split(/\\s+/).filter(Boolean));\n rel.delete('opener');\n rel.add('noopener');\n rel.add('noreferrer');\n attrs.rel = [...rel].join(' ');\n }\n return attrs;\n }\n\n private locate(document: EditorDocumentData, imageId: string): ImageLinkLocation | undefined {\n const path = this.path(document.nodes, imageId);\n const image = path?.at(-1);\n if (!path || image?.type !== 'element' || image.tag !== 'img') return undefined;\n const anchors = path.filter((node) => node.tag === 'a');\n const anchor = anchors.at(-1);\n if (!anchor) return { image, shared: false, editable: true };\n if (anchors.length !== 1)\n return { image, anchor, shared: true, editable: false, reason: 'nested-link' };\n const anchorIndex = path.findIndex((node) => node.id === anchor.id);\n const branch = path[anchorIndex + 1];\n if (!branch) return undefined;\n const exclusiveBranch = path.slice(anchorIndex + 1, -1).every((node, offset) => {\n const next = path[anchorIndex + 2 + offset];\n return (node.children ?? []).every(\n (child) => child.id === next?.id || !this.substantive(child),\n );\n });\n const shared =\n !exclusiveBranch ||\n (anchor.children ?? []).some((node) => node.id !== branch.id && this.substantive(node));\n if (!exclusiveBranch)\n return { image, anchor, branch, shared, editable: false, reason: 'shared-structure' };\n if (shared && (anchor.attrs?.id || anchor.attrs?.name))\n return { image, anchor, branch, shared, editable: false, reason: 'shared-identity' };\n return { image, anchor, branch, shared, editable: true };\n }\n\n private substantive(node: DocumentNode): boolean {\n return node.type !== 'text' || !!node.value?.trim();\n }\n\n private path(\n nodes: readonly DocumentNode[],\n id: string,\n parents: readonly DocumentNode[] = [],\n ): readonly DocumentNode[] | undefined {\n for (const node of nodes) {\n if (node.id === id) return [...parents, node];\n const found = this.path(node.children ?? [], id, [...parents, node]);\n if (found) return found;\n }\n return undefined;\n }\n\n private replace(\n nodes: readonly DocumentNode[],\n id: string,\n replacement: readonly DocumentNode[],\n ): readonly DocumentNode[] {\n return nodes.flatMap((node) => {\n if (node.id === id) return replacement;\n return node.children\n ? [{ ...node, children: this.replace(node.children, id, replacement) }]\n : [node];\n });\n }\n}\n","import type { EditorDocumentData, SourceInput } from '../core/document';\n\nexport interface AssetReference {\n readonly id: string;\n readonly url: string;\n readonly alt: string;\n}\n\nexport interface AssetPort {\n upload(file: File, signal?: AbortSignal): Promise<AssetReference>;\n resolve(id: string, signal?: AbortSignal): Promise<{ url: string; alt: string }>;\n}\n\nexport interface StorePort {\n save(\n document: EditorDocumentData,\n source: SourceInput,\n expectedRevision: number,\n signal?: AbortSignal,\n ): Promise<{ revision: number }>;\n}\n\nexport interface SlotsPort {\n resolve(kind: 'form' | 'footer', id: string, signal?: AbortSignal): Promise<string>;\n}\n\nexport interface HostAdapters {\n assets?: AssetPort;\n store?: StorePort;\n slots?: SlotsPort;\n}\n\nexport class HostIntegration {\n private saveSequence = 0;\n private active: AbortController | undefined;\n constructor(private readonly adapters: HostAdapters = {}) {}\n\n async save(\n document: EditorDocumentData,\n source: SourceInput,\n expectedRevision: number,\n ): Promise<number | undefined> {\n if (!this.adapters.store) return undefined;\n this.active?.abort();\n const controller = new AbortController();\n this.active = controller;\n const job = ++this.saveSequence;\n const result = await this.adapters.store.save(\n structuredClone(document),\n { ...source },\n expectedRevision,\n controller.signal,\n );\n return controller.signal.aborted || job !== this.saveSequence ? undefined : result.revision;\n }\n\n get assets(): AssetPort | undefined {\n return this.adapters.assets;\n }\n get slots(): SlotsPort | undefined {\n return this.adapters.slots;\n }\n dispose(): void {\n this.saveSequence++;\n this.active?.abort();\n }\n}\n","import { EditorDocument } from '../core/document';\nimport { DocumentPresentationService } from './document-presentation';\nimport { DocumentMetadataService } from './document-metadata';\nimport type { DocumentMetadata } from './document-metadata';\nimport type { DocumentStyleProperty, ImageSizeSettings } from './document-presentation';\nimport type {\n Diagnostic,\n DocumentNode,\n EditorDocumentData,\n EditorMode,\n SourceInput,\n} from '../core/document';\nimport { DocumentHistory } from '../core/history';\nimport { DocumentBudget } from '../core/budget';\nimport type { BlockType } from '../core/catalog';\nimport { ContentService } from './content-service';\nimport { DocumentMutationService } from './document-commands';\nimport type { InsertionSource } from './document-commands';\nimport { SectionLayoutService } from './section-layout';\nimport type { SectionLayoutContext, SectionLayoutPatch } from '../core/section-layout';\nimport { ImageLinkService } from './image-link';\nimport type { ImageLinkContext, ImageLinkOptions } from './image-link';\nimport { HostIntegration } from './host';\nimport type { AssetReference } from './host';\n\nexport interface PendingRichTextDraft {\n readonly id: string;\n readonly html: string;\n readonly originalHtml: string;\n readonly changed: boolean;\n readonly valid: boolean;\n readonly blocked?: 'oversized';\n readonly documentId: string;\n readonly baseRevision: number;\n readonly editGeneration: number;\n}\n\nexport interface EditorState {\n readonly document: EditorDocumentData;\n readonly mode: EditorMode;\n readonly source: SourceInput;\n readonly draftSource: SourceInput;\n readonly diagnostics: readonly Diagnostic[];\n readonly selectedNodeId: string | undefined;\n readonly pendingRichText?: PendingRichTextDraft;\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n readonly readOnly: boolean;\n readonly readonly: boolean;\n readonly dirty: boolean;\n readonly editGeneration: number;\n}\n\nexport interface SessionOptions {\n readonly document: EditorDocumentData;\n /** Notices of the import which produced the initial document, e.g. what was removed. */\n readonly diagnostics?: readonly Diagnostic[];\n readonly readOnly?: boolean;\n readonly persistedRevision?: number;\n readonly onObserverError?: (error: unknown) => void;\n}\nexport interface SessionServices {\n readonly content: ContentService;\n readonly mutations: DocumentMutationService;\n readonly imageLinks: ImageLinkService;\n readonly presentation?: DocumentPresentationService;\n readonly metadata?: DocumentMetadataService;\n readonly sectionLayouts?: SectionLayoutService;\n readonly history: DocumentHistory;\n readonly host: HostIntegration;\n}\n\nexport class EditorSession {\n #document: EditorDocument;\n #mode: EditorMode = 'visual';\n #draft: SourceInput;\n #source: SourceInput;\n #diagnostics: readonly Diagnostic[] = [];\n #selection: string | undefined;\n #pendingRichText: PendingRichTextDraft | undefined;\n #disposed = false;\n #revision: number;\n #persistedRevision: number;\n #savedDocumentRevision: number;\n #saving = false;\n #readOnly: boolean;\n #editGeneration = 0;\n #listeners = new Set<(state: EditorState) => void>();\n #emitting = false;\n #emitQueued = false;\n\n constructor(\n private readonly services: SessionServices,\n private readonly options: SessionOptions,\n ) {\n const admitted = services.content.admit(options.document);\n this.#document = admitted.document;\n this.#diagnostics = this.notices(\n [...(options.diagnostics ?? []), ...admitted.diagnostics],\n services.content.validate(this.#document.snapshot()),\n );\n this.#readOnly = options.readOnly ?? false;\n this.#revision = this.#document.revision;\n this.#persistedRevision = options.persistedRevision ?? this.#revision;\n this.#savedDocumentRevision = this.#revision;\n this.#source = services.content.export(this.#document);\n this.#draft = { ...this.#source };\n services.history.reset(this.#document);\n }\n\n getState(): EditorState {\n this.assertActive();\n return Object.freeze({\n document: this.#document.snapshot(),\n mode: this.#mode,\n source: this.exportSource(),\n draftSource: { ...this.#draft },\n diagnostics: structuredClone(this.#diagnostics),\n selectedNodeId: this.#selection,\n ...(this.#pendingRichText ? { pendingRichText: { ...this.#pendingRichText } } : {}),\n canUndo:\n this.services.history.canUndo ||\n !!(this.#pendingRichText?.changed && this.#pendingRichText.valid),\n canRedo: this.services.history.canRedo && !this.#pendingRichText?.changed,\n readOnly: this.#readOnly,\n readonly: this.#readOnly,\n dirty:\n this.#revision !== this.#savedDocumentRevision ||\n this.hasPendingDraft() ||\n !!this.#pendingRichText?.changed,\n editGeneration: this.#editGeneration,\n });\n }\n\n snapshot(): EditorDocumentData {\n this.assertActive();\n return this.#document.snapshot();\n }\n exportSource(): SourceInput {\n this.assertActive();\n return { ...this.#source };\n }\n\n setReadOnly(value: boolean): void {\n this.assertActive();\n if (typeof value !== 'boolean') throw new TypeError('INVALID_READ_ONLY');\n if (value === this.#readOnly) return;\n this.#readOnly = value;\n this.#editGeneration++;\n if (this.#pendingRichText)\n this.#pendingRichText = { ...this.#pendingRichText, editGeneration: this.#editGeneration };\n this.emit();\n }\n\n subscribe(listener: (state: EditorState) => void): () => void {\n this.assertActive();\n this.#listeners.add(listener);\n this.notify(listener);\n return () => this.#listeners.delete(listener);\n }\n\n select(id: string | undefined): boolean {\n this.assertActive();\n if (id && !this.find(this.#document.snapshot().nodes, id)) return false;\n if (id !== this.#selection && !this.commitRichText()) return false;\n this.#selection = id;\n this.emit();\n return true;\n }\n\n setDraftSource(source: SourceInput): void {\n if (!this.canWrite() || !this.commitRichText()) return;\n this.#editGeneration++;\n this.#draft = { ...source };\n this.#diagnostics = [];\n this.emit();\n }\n\n commitDraft(): boolean {\n return this.importSource(this.#draft);\n }\n\n importSource(source: SourceInput): boolean {\n if (!this.canWrite() || !this.commitRichText()) return false;\n if (source.html === this.#source.html && source.css === this.#source.css) {\n this.#draft = { ...source };\n this.#diagnostics = [];\n this.#editGeneration++;\n this.emit();\n return true;\n }\n this.#draft = { ...source };\n this.#editGeneration++;\n try {\n const imported = this.services.content.import(\n source,\n this.#document.kind,\n this.#document.snapshot(),\n );\n this.#diagnostics = imported.diagnostics;\n if (!imported.document || imported.diagnostics.some((item) => item.severity === 'error')) {\n this.emit();\n return false;\n }\n this.commit(\n this.services.content.document(imported.document),\n true,\n false,\n imported.diagnostics,\n );\n return true;\n } catch {\n return this.fail('IMPORT_INVALID', 'diagnostics.invalidDocument');\n }\n }\n\n importJson(input: unknown): boolean {\n if (!this.canWrite() || !this.commitRichText()) return false;\n try {\n const { document, diagnostics } = this.services.content.admit(input);\n if (document.kind !== this.#document.kind)\n return this.fail('KIND_MISMATCH', 'diagnostics.kindMismatch');\n this.commit(document, true, false, diagnostics);\n return true;\n } catch {\n return this.fail('IMPORT_INVALID', 'diagnostics.invalidDocument');\n }\n }\n\n setMode(mode: EditorMode): boolean {\n this.assertActive();\n if (mode !== 'html' && mode !== 'visual') return false;\n if (mode === this.#mode) return true;\n if (!this.commitRichText()) return false;\n if (mode === 'visual' && !this.#readOnly) {\n const current = this.exportSource();\n if (\n (current.html !== this.#draft.html || current.css !== this.#draft.css) &&\n !this.commitDraft()\n )\n return false;\n }\n this.#mode = mode;\n this.#editGeneration++;\n this.emit();\n return true;\n }\n\n beginRichText(id: string, initialHtml: string): boolean {\n if (!this.canWrite() || this.#mode !== 'visual' || this.hasPendingDraft()) return false;\n if (this.#pendingRichText?.id === id) return true;\n if (!this.commitRichText() || !this.services.mutations.canEditRichText(this.snapshot(), id))\n return false;\n if (!this.boundedRichText(initialHtml))\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n try {\n this.services.mutations.validateRichTextProjection(this.snapshot(), id, initialHtml);\n } catch {\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n }\n this.#pendingRichText = {\n id,\n html: initialHtml,\n originalHtml: initialHtml,\n changed: false,\n valid: true,\n documentId: this.#document.id,\n baseRevision: this.#revision,\n editGeneration: this.#editGeneration,\n };\n this.emit();\n return true;\n }\n\n updateRichTextDraft(html: string): boolean {\n if (!this.canWrite() || !this.#pendingRichText) return false;\n if (!this.boundedRichText(html)) return this.rejectRichTextSize();\n const draft = this.#pendingRichText;\n let valid = false;\n try {\n this.services.mutations.validateRichTextProjection(this.snapshot(), draft.id, html);\n valid = true;\n } catch {\n // Invalid input stays recoverable but never becomes an HTML projection in the host.\n }\n this.#editGeneration++;\n this.#pendingRichText = {\n id: draft.id,\n originalHtml: draft.originalHtml,\n documentId: draft.documentId,\n baseRevision: draft.baseRevision,\n html,\n changed: html !== draft.originalHtml,\n valid,\n editGeneration: this.#editGeneration,\n };\n this.#diagnostics = valid\n ? []\n : [{ code: 'CHANGE_INVALID', severity: 'error', messageKey: 'diagnostics.invalidChange' }];\n this.emit();\n return valid;\n }\n\n restoreRichTextDraft(\n draft: Pick<PendingRichTextDraft, 'id' | 'html' | 'blocked'>,\n initialHtml: string,\n ): boolean {\n if (draft.blocked !== undefined && draft.blocked !== 'oversized') return false;\n if (!this.beginRichText(draft.id, initialHtml)) return false;\n this.updateRichTextDraft(draft.html);\n if (draft.blocked === 'oversized') this.rejectRichTextSize();\n return !!this.#pendingRichText;\n }\n\n commitRichText(): boolean {\n this.assertActive();\n const draft = this.#pendingRichText;\n if (!draft) return true;\n if (!draft.changed) {\n this.#pendingRichText = undefined;\n this.emit();\n return true;\n }\n if (!this.canWrite()) return false;\n if (!draft.valid) return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n if (\n draft.documentId !== this.#document.id ||\n draft.baseRevision !== this.#revision ||\n draft.editGeneration !== this.#editGeneration ||\n this.hasPendingDraft()\n )\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n try {\n const next = this.services.mutations.richText(this.snapshot(), draft.id, draft.html);\n this.commit(next, true, true);\n return true;\n } catch {\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n }\n }\n\n cancelRichText(): void {\n this.assertActive();\n if (!this.#pendingRichText) return;\n this.#pendingRichText = undefined;\n this.#editGeneration++;\n this.#diagnostics = [];\n this.emit();\n }\n\n inlineStyles(id: string): Readonly<Record<string, string>> {\n const node = this.find(this.snapshot().nodes, id);\n if (!node) return {};\n try {\n return this.services.content.inlineDeclarations(node.attrs?.style ?? '');\n } catch {\n // An imported style may hold hacks the strict reader does not vouch for.\n return {};\n }\n }\n\n /** Title and, in an e-mail, preheader of the document. */\n documentMetadata(): DocumentMetadata | undefined {\n return this.services.metadata?.read(this.snapshot());\n }\n updateTitle(value: string): boolean {\n return this.change((document) => this.metadata().title(document, value));\n }\n updatePreheader(value: string): boolean {\n return this.change((document) => this.metadata().preheader(document, value));\n }\n\n imageSize(id: string) {\n return this.services.presentation?.image(this.snapshot(), id);\n }\n updateImageSize(id: string, settings: ImageSizeSettings): boolean {\n return this.change((document) => this.presentation().resize(document, id, settings));\n }\n documentStyles() {\n return this.services.presentation?.styles(this.snapshot());\n }\n updateDocumentStyle(property: DocumentStyleProperty, value: string): boolean {\n return this.change((document) => this.presentation().style(document, property, value));\n }\n\n updateText(id: string, value: string): boolean {\n return this.change((document) => this.services.mutations.text(document, id, value));\n }\n updateRichText(id: string, html: string): boolean {\n return this.change((document) => this.services.mutations.richText(document, id, html));\n }\n updateAttribute(id: string, name: string, value: string): boolean {\n return this.change((document) => this.services.mutations.attribute(document, id, name, value));\n }\n updateStyle(id: string, property: string, value: string): boolean {\n return this.change((document) => this.services.mutations.style(document, id, property, value));\n }\n connectFormReference(reference: string, id?: string, parentId?: string, index?: number): boolean {\n return this.change((document) =>\n this.services.mutations.connectFormReference(document, reference, id, parentId, index),\n );\n }\n attachAsset(asset: AssetReference, id?: string, parentId?: string, index?: number): boolean {\n return this.change((document) =>\n this.services.mutations.attachAsset(document, asset, id, parentId, index),\n );\n }\n imageLink(imageId: string): ImageLinkContext | undefined {\n this.assertActive();\n return this.services.imageLinks.context(this.#document.snapshot(), imageId);\n }\n updateImageLink(imageId: string, href: string, options?: ImageLinkOptions): boolean {\n return this.change((document) =>\n this.services.imageLinks.update(document, imageId, href, options),\n );\n }\n layoutSettings(id: string): SectionLayoutContext | undefined {\n this.assertActive();\n const context = this.services.sectionLayouts?.context(this.snapshot(), id);\n return context && this.#readOnly\n ? { ...context, editable: false, reason: 'readonly' }\n : context;\n }\n async updateLayout(id: string, patch: SectionLayoutPatch): Promise<boolean> {\n if (!this.canWrite() || !this.commitRichText()) return false;\n if (this.hasPendingDraft()) return this.fail('DRAFT_PENDING', 'diagnostics.invalidChange');\n const service = this.services.sectionLayouts;\n if (!service) return this.fail('LAYOUT_UNAVAILABLE', 'diagnostics.invalidChange');\n const initial = this.getState();\n try {\n const next = await service.update(initial.document, id, patch);\n if (\n this.#disposed ||\n this.#readOnly ||\n this.#editGeneration !== initial.editGeneration ||\n this.#document.id !== initial.document.id ||\n this.#revision !== initial.document.revision ||\n this.#selection !== initial.selectedNodeId ||\n this.#mode !== initial.mode\n )\n return false;\n this.commit(next, true);\n return true;\n } catch (error: unknown) {\n if (this.#disposed || this.#readOnly || this.#editGeneration !== initial.editGeneration)\n return false;\n const reason = error instanceof Error ? error.message : '';\n const codes: Readonly<Record<string, string>> = {\n 'column-not-empty': 'LAYOUT_COLUMN_NOT_EMPTY',\n 'identity-bearing-column': 'LAYOUT_IDENTITY_BEARING_COLUMN',\n 'unsupported-structure': 'LAYOUT_UNSUPPORTED_STRUCTURE',\n 'invalid-settings': 'LAYOUT_INVALID_SETTINGS',\n unavailable: 'LAYOUT_UNAVAILABLE',\n };\n return this.fail(\n Object.hasOwn(codes, reason)\n ? (codes[reason] ?? 'LAYOUT_INVALID_SETTINGS')\n : 'LAYOUT_INVALID_SETTINGS',\n 'diagnostics.invalidChange',\n );\n }\n }\n\n addBlock(type: BlockType, parentId?: string, index?: number): boolean {\n return this.change((document) => this.services.mutations.add(document, type, parentId, index));\n }\n insertSource(source: InsertionSource, parentId?: string, index?: number): boolean {\n return this.change((document) =>\n this.services.mutations.insert(document, source, parentId, index),\n );\n }\n removeBlock(id: string): boolean {\n return this.change((document) => this.services.mutations.remove(document, id));\n }\n duplicateBlock(id: string): boolean {\n return this.change((document) => this.services.mutations.duplicate(document, id));\n }\n moveBlock(id: string, parentId: string | undefined, index: number): boolean {\n return this.change((document) => this.services.mutations.move(document, id, parentId, index));\n }\n\n undo(): boolean {\n return this.restore('undo');\n }\n redo(): boolean {\n return this.restore('redo');\n }\n\n async save(): Promise<boolean> {\n if (!this.canWrite() || this.#saving || !this.commitRichText()) return false;\n if (this.#mode === 'html') {\n const source = this.exportSource();\n if (\n (source.html !== this.#draft.html || source.css !== this.#draft.css) &&\n !this.commitDraft()\n )\n return false;\n }\n const revision = this.#revision;\n this.#saving = true;\n try {\n const persisted = await this.services.host.save(\n this.snapshot(),\n this.exportSource(),\n this.#persistedRevision,\n );\n if (this.#disposed || persisted === undefined) return false;\n this.#persistedRevision = persisted;\n this.#savedDocumentRevision = revision;\n this.emit();\n return true;\n } catch {\n return this.#disposed ? false : this.fail('SAVE_FAILED', 'diagnostics.saveFailed');\n } finally {\n this.#saving = false;\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n this.#disposed = true;\n this.#pendingRichText = undefined;\n this.services.host.dispose();\n this.#listeners.clear();\n this.services.history.reset();\n }\n\n private metadata(): DocumentMetadataService {\n if (!this.services.metadata) throw new Error('UNSUPPORTED_METADATA');\n return this.services.metadata;\n }\n\n /** What an import removed stays visible next to what the committed document holds. */\n private notices(\n imported: readonly Diagnostic[],\n current: readonly Diagnostic[],\n ): readonly Diagnostic[] {\n const merged = new Map<string, Diagnostic>();\n for (const diagnostic of [\n ...imported.filter(\n (entry) => entry.severity === 'warning' || entry.code === 'HTML_NORMALIZED',\n ),\n ...current,\n ])\n if (!merged.has(diagnostic.code)) merged.set(diagnostic.code, diagnostic);\n return [...merged.values()];\n }\n\n private presentation(): DocumentPresentationService {\n if (!this.services.presentation) throw new Error('UNSUPPORTED_PRESENTATION');\n return this.services.presentation;\n }\n\n private change(action: (document: EditorDocumentData) => EditorDocument): boolean {\n if (!this.canWrite() || !this.commitRichText()) return false;\n if (this.hasPendingDraft()) return this.fail('DRAFT_PENDING', 'diagnostics.invalidChange');\n try {\n this.commit(action(this.snapshot()), true);\n return true;\n } catch {\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n }\n }\n\n private restore(direction: 'undo' | 'redo'): boolean {\n if (!this.canWrite() || !this.commitRichText()) return false;\n if (this.hasPendingDraft()) return this.fail('DRAFT_PENDING', 'diagnostics.invalidChange');\n const previous = this.services.history[direction]();\n if (!previous) return false;\n try {\n this.commit(previous, false);\n return true;\n } catch {\n // The entry could not become the current document: step the pointer back where it was.\n this.services.history[direction === 'undo' ? 'redo' : 'undo']();\n return this.fail('HISTORY_RESTORE_FAILED', 'diagnostics.invalidChange');\n }\n }\n\n private commit(\n document: EditorDocument,\n history: boolean,\n clearRichText = false,\n imported: readonly Diagnostic[] = [],\n ): void {\n // The document was validated when it was built; the revision alone changes here.\n const next = document.withRevision(this.#revision + 1);\n const { source, diagnostics } = this.services.content.render(next);\n if (history) this.services.history.push(next);\n if (clearRichText) this.#pendingRichText = undefined;\n this.#document = next;\n this.#revision = next.revision;\n this.#editGeneration++;\n this.#source = source;\n this.#draft = source;\n this.#diagnostics = this.notices(imported, diagnostics);\n if (this.#selection && !this.find(this.snapshot().nodes, this.#selection))\n this.#selection = undefined;\n this.emit();\n }\n\n private fail(code: string, messageKey: string): false {\n this.#diagnostics = [{ code, messageKey, severity: 'error' }];\n this.emit();\n return false;\n }\n\n private rejectRichTextSize(): false {\n const draft = this.#pendingRichText;\n if (draft) {\n this.#editGeneration++;\n this.#pendingRichText = {\n ...draft,\n valid: false,\n changed: true,\n blocked: 'oversized',\n editGeneration: this.#editGeneration,\n };\n }\n return this.fail('CHANGE_INVALID', 'diagnostics.invalidChange');\n }\n\n private boundedRichText(html: string): boolean {\n return (\n typeof html === 'string' &&\n new DocumentBudget().byteLength(html) <= DocumentBudget.limits.sourceBytes\n );\n }\n\n private canWrite(): boolean {\n this.assertActive();\n return !this.#readOnly;\n }\n private assertActive(): void {\n if (this.#disposed) throw new Error('SESSION_DISPOSED');\n }\n private hasPendingDraft(): boolean {\n const current = this.exportSource();\n return current.html !== this.#draft.html || current.css !== this.#draft.css;\n }\n private emit(): void {\n if (!this.#listeners.size) return;\n if (this.#emitting) {\n this.#emitQueued = true;\n return;\n }\n this.#emitting = true;\n // A listener which failed is not served again by this emission: an error handler which\n // changes the session would otherwise redeliver to it forever. It stays subscribed.\n const failed = new Set<(state: EditorState) => void>();\n try {\n do {\n this.#emitQueued = false;\n const state = this.getState();\n this.freezeBroadcast(state);\n for (const listener of this.#listeners) {\n if (failed.has(listener)) continue;\n if (!this.notify(listener, state)) failed.add(listener);\n if (this.#emitQueued) break;\n }\n } while (this.#emitQueued && !this.#disposed);\n } finally {\n this.#emitting = false;\n }\n }\n\n private freezeBroadcast(state: EditorState): void {\n const stack: unknown[] = [state];\n while (stack.length) {\n const value = stack.pop();\n if (!value || typeof value !== 'object') continue;\n Object.freeze(value);\n stack.push(...Object.values(value));\n }\n }\n\n /** False when the listener threw; the failure was already reported. */\n private notify(listener: (state: EditorState) => void, state?: EditorState): boolean {\n try {\n listener(state ?? this.getState());\n return true;\n } catch (error) {\n // One failed delivery is isolated; the listener keeps receiving later states.\n try {\n this.options.onObserverError?.(error);\n } catch {\n /* A failed observer cannot corrupt an accepted document transaction. */\n }\n return false;\n }\n }\n private find(nodes: readonly DocumentNode[], id: string): DocumentNode | undefined {\n for (const node of nodes) {\n if (node.id === id) return node;\n const found = this.find(node.children ?? [], id);\n if (found) return found;\n }\n return undefined;\n }\n}\n","import type { EditorDocument, EditorDocumentData, SourceInput } from '../core/document';\n\nexport interface DocumentOutputCodec {\n export(document: EditorDocumentData): SourceInput;\n}\n\nexport interface DocumentOutputPolicy {\n /** An `EditorDocument` was validated when it was built; its content is checked again. */\n assertSafe(document: EditorDocumentData | EditorDocument): void;\n}\n\n/** Serializes the canonical page rather than rebuilding it from recognized blocks. */\nexport class PageRenderer {\n constructor(\n private readonly codec: DocumentOutputCodec,\n private readonly policy: DocumentOutputPolicy,\n ) {}\n\n render(document: EditorDocumentData): SourceInput {\n if (document.kind !== 'page') throw new Error('renderer.kind_mismatch');\n this.policy.assertSafe(document);\n return this.codec.export(document);\n }\n}\n","import { defaultTreeAdapter, html, parse, parseFragment, serialize } from 'parse5';\nimport type { DefaultTreeAdapterMap } from 'parse5';\nimport type { DocumentKind, EditorDocumentData, ImportResult, SourceInput } from '../core/document';\nimport type { DocumentOutputPolicy } from './page-renderer';\nimport { documentParts, markupChildren, stripReservedAttributes } from './markup-tree';\n\nexport interface SourceValidationCodec {\n import(source: SourceInput, kind: DocumentKind): ImportResult;\n /** Read without touching the preservation cache of the documents being edited. */\n inspect?(source: SourceInput, kind: DocumentKind): ImportResult;\n /** Needed when the rules of the kind changed what the given source parses to. */\n export?(document: EditorDocumentData): SourceInput;\n}\n\n/** `<meta http-equiv>` values which act on the window that renders them. */\nconst ACTIVE_META: ReadonlySet<string> = new Set([\n 'refresh',\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'set-cookie',\n]);\n\n/**\n * The only policy of the editing frame. Nothing of the document may run: `script-src` is\n * left to `default-src 'none'` here and narrowed by the selection preview to the SHA-256 digest\n * of the one runtime script, which\n * also covers inline handlers and `javascript:` URLs. Styles, fonts and images of the author\n * load over HTTPS so that the piece looks like itself while it is edited; frames, objects,\n * connections, forms, workers and a `<base>` do not.\n */\nconst PREVIEW_POLICY: readonly string[] = Object.freeze([\n \"default-src 'none'\",\n \"style-src 'unsafe-inline' https:\",\n 'font-src https: data:',\n 'media-src https: data: blob:',\n \"connect-src 'none'\",\n \"frame-src 'none'\",\n \"child-src 'none'\",\n \"worker-src 'none'\",\n \"manifest-src 'none'\",\n \"form-action 'none'\",\n \"base-uri 'none'\",\n \"object-src 'none'\",\n]);\n\nexport interface HtmlAssemblyPort {\n build(source: SourceInput, kind: DocumentKind, preview?: boolean): string;\n}\n\n/** Produces a complete portable file from an already policy-validated source. */\nexport class HtmlDocumentAssembler {\n readonly #imageOrigins: readonly string[];\n\n constructor(\n private readonly codec: SourceValidationCodec,\n private readonly policy: DocumentOutputPolicy,\n imageOrigins: readonly string[] = [],\n ) {\n if (imageOrigins.length > 10) throw new Error('PREVIEW_ORIGIN_LIMIT');\n this.#imageOrigins = Object.freeze(\n imageOrigins.map((value) => {\n const url = new URL(value);\n const loopback = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);\n if (\n url.username ||\n url.password ||\n url.pathname !== '/' ||\n url.search ||\n url.hash ||\n (url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback))\n )\n throw new Error('INVALID_PREVIEW_ORIGIN');\n return url.origin;\n }),\n );\n }\n\n build(source: SourceInput, kind: DocumentKind, preview = false): string {\n const imported = this.codec.inspect\n ? this.codec.inspect(source, kind)\n : this.codec.import(source, kind);\n if (\n !imported.document ||\n imported.diagnostics.some((diagnostic) => diagnostic.severity === 'error')\n )\n throw new Error('preview.invalid_document');\n // The policy checks the content again; the aggregate spares it a second schema parse.\n this.policy.assertSafe(imported.validated ?? imported.document);\n if (source.css.toLowerCase().includes('</style')) throw new Error('preview.invalid_styles');\n // A source the kind rules had to clean is not the document: its clean form is built.\n let markup = source.html;\n if (imported.diagnostics.some((diagnostic) => diagnostic.severity === 'warning')) {\n if (!this.codec.export) throw new Error('preview.invalid_document');\n markup = this.codec.export(imported.document).html;\n }\n const document = parse(markup);\n const { head } = documentParts(document);\n if (!head) throw new Error('preview.invalid_document');\n if (source.css) {\n const style = defaultTreeAdapter.createElement('style', html.NS.HTML, []);\n defaultTreeAdapter.insertText(style, source.css);\n defaultTreeAdapter.appendChild(head, style);\n }\n if (preview) {\n this.neutralize(document);\n const policy = [\n ...PREVIEW_POLICY,\n ['img-src data: blob: https:', ...this.#imageOrigins].join(' '),\n ].join('; ');\n const csp = defaultTreeAdapter.createElement('meta', html.NS.HTML, [\n { name: 'http-equiv', value: 'Content-Security-Policy' },\n { name: 'content', value: policy },\n ]);\n const first = head.childNodes[0];\n if (first) defaultTreeAdapter.insertBefore(head, csp, first);\n else defaultTreeAdapter.appendChild(head, csp);\n defaultTreeAdapter.appendChild(\n head,\n defaultTreeAdapter.createElement('meta', html.NS.HTML, [\n { name: 'name', value: 'referrer' },\n { name: 'content', value: 'no-referrer' },\n ]),\n );\n }\n const hasDoctype = document.childNodes.some((node) => node.nodeName === '#documentType');\n return `${hasDoctype ? '' : '<!doctype html>'}${serialize(document)}`;\n }\n\n /**\n * Changes only the copy shown in the editor, never the document. A policy written by the\n * author cannot stand next to the editor's (it could neither loosen it nor break the\n * editing script), a refresh would navigate the frame away, and a base would redirect\n * every relative reference. The elements which stay keep their place in the tree.\n *\n * The content of `noscript` is text to a parser with scripting and markup to one without: the\n * editing frame reads it the first way, the plain preview and the parser which reconciles a\n * revision read it the second. It is read here as markup, given the same treatment, cleared\n * of every attribute reserved to the editor and written back as text.\n */\n private neutralize(document: DefaultTreeAdapterMap['parentNode']): void {\n const stack: DefaultTreeAdapterMap['parentNode'][] = [document];\n while (stack.length) {\n const parent = stack.pop();\n if (!parent) break;\n for (const node of [...markupChildren(parent)]) {\n if (!defaultTreeAdapter.isElementNode(node)) continue;\n if (node.namespaceURI === html.NS.HTML && node.tagName === 'meta') {\n const directive = node.attrs\n .find((attribute) => attribute.name === 'http-equiv')\n ?.value.trim()\n .toLowerCase();\n if (directive !== undefined && ACTIVE_META.has(directive)) {\n defaultTreeAdapter.detachNode(node);\n continue;\n }\n }\n if (node.namespaceURI === html.NS.HTML && node.tagName === 'base')\n node.attrs = node.attrs.filter(\n (attribute) => attribute.name !== 'href' && attribute.name !== 'target',\n );\n // Read without scripting, as here inside another `noscript`, it holds ordinary elements.\n if (\n node.namespaceURI === html.NS.HTML &&\n node.tagName === 'noscript' &&\n node.childNodes.every((entry) => defaultTreeAdapter.isTextNode(entry))\n ) {\n this.noscript(node);\n continue;\n }\n stack.push(node);\n }\n }\n }\n\n private noscript(node: DefaultTreeAdapterMap['element']): void {\n const source = node.childNodes\n .map((entry) => (defaultTreeAdapter.isTextNode(entry) ? entry.value : ''))\n .join('');\n if (!source) return;\n const fragment = parseFragment(source, { scriptingEnabled: false });\n this.neutralize(fragment);\n stripReservedAttributes(fragment);\n const safe = serialize(fragment, { scriptingEnabled: false });\n node.childNodes = [];\n // Nothing written back may end the element for the parser which reads it as text.\n if (!safe.toLowerCase().includes('</noscript')) defaultTreeAdapter.insertText(node, safe);\n }\n}\n\n/** Sandbox remains mandatory even with CSP; no user markup reaches the host DOM. */\nexport class PreviewDocument {\n constructor(private readonly assembler: HtmlAssemblyPort) {}\n build(source: SourceInput, kind: DocumentKind): string {\n return this.assembler.build(source, kind, true);\n }\n}\n","/**\n * Output of the MJML compiler for `BLANK_EMAIL_MJML`, stored so that an editor can be created\n * without waiting for a compilation. Do not edit by hand: `tests/unit/templates` compares it\n * with what the compiler produces and fails when the two differ.\n */\nexport const BLANK_EMAIL_HTML =\n '<!doctype html>\\n<html lang=\"und\" dir=\"auto\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\\n <head>\\n <title></title>\\n <!--[if !mso]><!-->\\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\\n <!--<![endif]-->\\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\\n <style type=\"text/css\">\\n #outlook a { padding:0; }\\n body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }\\n table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }\\n img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }\\n p { display:block;margin:13px 0; }\\n </style>\\n <!--[if mso]>\\n <noscript>\\n <xml>\\n <o:OfficeDocumentSettings>\\n <o:AllowPNG/>\\n <o:PixelsPerInch>96</o:PixelsPerInch>\\n </o:OfficeDocumentSettings>\\n </xml>\\n </noscript>\\n <![endif]-->\\n <!--[if lte mso 11]>\\n <style type=\"text/css\">\\n .mj-outlook-group-fix { width:100% !important; }\\n </style>\\n <![endif]-->\\n \\n \\n <style type=\"text/css\">\\n @media only screen and (min-width:641px) {\\n .mj-column-per-100 { width:100% !important; max-width: 100%; }\\n }\\n </style>\\n <style media=\"screen and (min-width:641px)\">\\n .moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }\\n </style>\\n \\n \\n \\n \\n \\n \\n </head>\\n \\n <body style=\"word-spacing:normal;\">\\n \\n <div\\n aria-roledescription=\"email\" role=\"article\" lang=\"und\" dir=\"auto\" style=\"word-spacing:normal;\"\\n >\\n \\n \\n <!--[if mso | IE]><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"editor-layout-section-outlook\" role=\"presentation\" style=\"width:600px;\" width=\"600\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\\n \\n \\n <div class=\"editor-layout-section\" style=\"margin:0px auto;max-width:600px;\">\\n \\n <table\\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"width:100%;\"\\n >\\n <tbody>\\n <tr>\\n <td\\n style=\"direction:ltr;font-size:0px;padding:20px 0;text-align:center;\"\\n >\\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"editor-layout-column-outlook\" style=\"vertical-align:top;width:600px;\" ><![endif]-->\\n \\n <div\\n class=\"mj-column-per-100 mj-outlook-group-fix editor-layout-column\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\\n >\\n \\n <table\\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\\n >\\n <tbody>\\n \\n <tr>\\n <td\\n align=\"left\" style=\"font-size:0px;padding:10px 25px;word-break:break-word;\"\\n >\\n \\n <div\\n style=\"font-family:Arial, sans-serif;font-size:16px;line-height:1.65;text-align:left;color:#243746;\"\\n >Escreva seu conteúdo.</div>\\n \\n </td>\\n </tr>\\n \\n </tbody>\\n </table>\\n \\n </div>\\n \\n <!--[if mso | IE]></td></tr></table><![endif]-->\\n </td>\\n </tr>\\n </tbody>\\n </table>\\n \\n </div>\\n \\n \\n <!--[if mso | IE]></td></tr></table><![endif]-->\\n \\n \\n </div>\\n </body>\\n \\n</html>\\n ';\n","import type { DocumentKind, SourceInput } from '../core/document';\nimport type { MjmlEmailRenderer } from '../renderers/email-renderer';\nimport { BLANK_EMAIL_HTML } from './blank-email';\n\n/** A block source; e-mail blocks state whether they are a content row or a whole section. */\nexport interface BlockSource extends SourceInput {\n readonly insertion?: 'content' | 'section';\n}\n\nexport interface TemplateDescriptor {\n readonly id: string;\n readonly kind: DocumentKind;\n readonly titleKey: string;\n readonly descriptionKey: string;\n}\n\ninterface TemplateDefinition extends TemplateDescriptor {\n readonly source: string;\n readonly css?: string;\n}\n\n// A title and a preheader reach the recipient: models are born without sample ones. They\n// are set through the document metadata commands of the session.\nconst EMAIL_STYLE = `<mj-head><mj-breakpoint width=\"641px\" /><mj-attributes><mj-all font-family=\"Arial, sans-serif\" /><mj-text color=\"#243746\" line-height=\"1.65\" font-size=\"16px\" /><mj-button background-color=\"#0d766e\" border-radius=\"8px\" font-size=\"16px\" /></mj-attributes></mj-head>`;\n// Blocks are fragments of a message: they carry neither a title nor a preheader of their own.\nconst EMAIL_BLOCK_STYLE = `<mj-head><mj-breakpoint width=\"641px\" /><mj-attributes><mj-all font-family=\"Arial, sans-serif\" /><mj-text color=\"#243746\" line-height=\"1.65\" font-size=\"16px\" /><mj-button background-color=\"#0d766e\" border-radius=\"8px\" font-size=\"16px\" /></mj-attributes></mj-head>`;\nconst EMAIL_SECTION_BLOCKS: ReadonlySet<string> = new Set(['section', 'columns', 'footer']);\nconst EMAIL_FOOTER = `<mj-section><mj-column><mj-divider border-color=\"#dce4e7\" /><mj-text font-size=\"12px\" color=\"#536674\">Mensagem de exemplo. O rodapé de envio é fornecido pelo aplicativo.</mj-text></mj-column></mj-section>`;\nconst PAGE_CSS = `:root{font-family:Arial,sans-serif;color:#16302e;background:#f7faf9}*{box-sizing:border-box}body{margin:0}main{max-width:1120px;margin:auto;padding:40px 24px}section{padding:48px 0}h1{font-size:clamp(2.3rem,6vw,4.2rem);line-height:1.08;letter-spacing:-.045em;max-width:850px}h2{font-size:2rem;letter-spacing:-.025em}p{line-height:1.7;max-width:720px}a.cta{display:inline-block;padding:14px 22px;background:#0d766e;color:white;text-decoration:none;border-radius:8px;font-weight:600}.eyebrow{text-transform:uppercase;letter-spacing:.12em;font-size:12px}.columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}.card{border:1px solid #d5e3df;border-radius:12px;padding:24px;background:white}img{max-width:100%;height:auto}details{border-bottom:1px solid #d5e3df;padding:18px 0}summary{cursor:pointer;font-weight:600}footer{border-top:1px solid #d5e3df;padding:28px 0;color:#526b65}.host-form{min-height:96px;padding:24px;border:1px dashed #6e9187;border-radius:12px;background:#edf5f1}@media(max-width:640px){main{padding:24px 16px}.columns{grid-template-columns:1fr}section{padding:28px 0}}`;\nconst BLOCK_CSS = `[data-editor-block=\"hero\"]{padding:48px 24px}[data-editor-block=\"hero\"]>h1{font-size:clamp(2.3rem,6vw,4.2rem);line-height:1.08;letter-spacing:-.045em}[data-editor-block=\"hero\"]>p{line-height:1.7}[data-editor-block=\"hero\"]>.eyebrow{text-transform:uppercase;letter-spacing:.12em;font-size:12px}[data-editor-block=\"hero\"]>.cta,[data-editor-block=\"button\"]{display:inline-block;padding:14px 22px;background:#0d766e;color:white;text-decoration:none;border-radius:8px;font-weight:600}[data-editor-block=\"columns\"]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px;padding:24px}[data-editor-block=\"columns\"]>.card{border:1px solid #d5e3df;border-radius:12px;padding:24px;background:white;min-width:0}[data-editor-block=\"text\"]{line-height:1.7}[data-editor-block=\"heading\"]{font-size:2rem;letter-spacing:-.025em}[data-editor-block=\"image\"]>img{max-width:100%;height:auto}[data-editor-block=\"faq\"]{padding:24px}[data-editor-block=\"faq\"]>details{border-bottom:1px solid #d5e3df;padding:18px 0}[data-editor-block=\"faq\"]>details>summary{cursor:pointer;font-weight:600}[data-editor-block=\"footer\"]{border-top:1px solid #d5e3df;padding:28px 24px;color:#526b65}[data-editor-block=\"form\"]{padding:24px}[data-editor-block=\"form\"]>.host-form{min-height:96px;padding:24px;border:1px dashed #6e9187;border-radius:12px;background:#edf5f1}@media(max-width:640px){[data-editor-block=\"columns\"]{grid-template-columns:1fr}[data-editor-block=\"hero\"]{padding:28px 16px}}`;\n\nconst DEFINITIONS: readonly TemplateDefinition[] = [\n {\n id: 'email-newsletter',\n kind: 'email',\n titleKey: 'templates.newsletter',\n descriptionKey: 'templates.newsletterDescription',\n source: `<mjml>${EMAIL_STYLE}<mj-body background-color=\"#f3f7f6\" width=\"600px\"><mj-section background-color=\"#ffffff\" padding=\"32px\"><mj-column><mj-text font-size=\"12px\" color=\"#0d766e\">NOVIDADES</mj-text><mj-text font-size=\"30px\" font-weight=\"700\">Olá, Nico Robin</mj-text><mj-text>Reunimos as novidades para sua próxima conversa. Edite esta mensagem antes de enviar.</mj-text><mj-divider border-color=\"#dce4e7\" /><mj-text font-size=\"22px\" font-weight=\"700\">O destaque do mês</mj-text><mj-text>Conte uma novidade relevante e convide as pessoas a conhecer mais.</mj-text><mj-button href=\"https://example.com/novidades\">Conhecer as novidades</mj-button></mj-column></mj-section>${EMAIL_FOOTER}</mj-body></mjml>`,\n },\n {\n id: 'email-welcome',\n kind: 'email',\n titleKey: 'templates.welcome',\n descriptionKey: 'templates.welcomeDescription',\n source: `<mjml>${EMAIL_STYLE}<mj-body background-color=\"#f3f7f6\"><mj-section background-color=\"#ffffff\" padding=\"32px\"><mj-column><mj-text font-size=\"12px\" color=\"#0d766e\">BOAS-VINDAS</mj-text><mj-text font-size=\"30px\" font-weight=\"700\">Uma nova conversa começa aqui</mj-text><mj-text>Olá, Nico Robin. Obrigado pelo interesse. Veja como dar o próximo passo.</mj-text><mj-button href=\"https://example.com/comecar\">Começar agora</mj-button></mj-column></mj-section><mj-section background-color=\"#ffffff\"><mj-column><mj-text font-weight=\"700\">1. Conheça a proposta</mj-text><mj-text>Encontre o que você precisa.</mj-text></mj-column><mj-column><mj-text font-weight=\"700\">2. Fale com a equipe</mj-text><mj-text>Escolha o melhor momento.</mj-text></mj-column></mj-section>${EMAIL_FOOTER}</mj-body></mjml>`,\n },\n {\n id: 'email-announcement',\n kind: 'email',\n titleKey: 'templates.announcement',\n descriptionKey: 'templates.announcementDescription',\n source: `<mjml>${EMAIL_STYLE}<mj-body background-color=\"#f3f7f6\"><mj-section background-color=\"#ffffff\" padding=\"32px\"><mj-column><mj-text font-size=\"12px\" color=\"#0d766e\">COMUNICADO</mj-text><mj-text font-size=\"30px\" font-weight=\"700\">Temos uma novidade para compartilhar</mj-text><mj-text>Explique a novidade, para quem ela é relevante e o próximo passo.</mj-text><mj-spacer height=\"16px\" /><mj-button href=\"https://example.com/saiba-mais\">Saiba mais</mj-button></mj-column></mj-section>${EMAIL_FOOTER}</mj-body></mjml>`,\n },\n {\n id: 'page-material',\n kind: 'page',\n titleKey: 'templates.material',\n descriptionKey: 'templates.materialDescription',\n css: PAGE_CSS,\n source: `<main><section data-editor-block=\"hero\"><p class=\"eyebrow\">MATERIAL GRATUITO</p><h1>Uma ideia para o seu próximo passo</h1><p>Apresente o conteúdo e mostre como ele pode ajudar quem chega até esta página.</p><a class=\"cta\" href=\"#interesse\">Receber o material</a></section><section class=\"columns\" data-editor-block=\"columns\"><article class=\"card\"><h2>O que você vai encontrar</h2><p>Uma apresentação objetiva para transformar interesse em ação.</p></article><article class=\"card\"><h2>Para quem é</h2><p>Descreva a pessoa que mais se beneficia deste conteúdo.</p></article></section><section id=\"interesse\" data-editor-block=\"form\"><h2>Receba o conteúdo</h2><div class=\"host-form\" data-host-slot=\"form\" data-editor-block=\"form\"></div></section><footer data-editor-block=\"footer\">Conteúdo de demonstração. Edite antes de publicar.</footer></main>`,\n },\n {\n id: 'page-service',\n kind: 'page',\n titleKey: 'templates.service',\n descriptionKey: 'templates.serviceDescription',\n css: PAGE_CSS,\n source: `<main><section data-editor-block=\"hero\"><p class=\"eyebrow\">PARA SUA EQUIPE</p><h1>Apresente uma solução para um problema real</h1><p>Conte o que a sua equipe entrega, para quem e como começar.</p><a class=\"cta\" href=\"#contato\">Conversar com a equipe</a></section><section class=\"columns\" data-editor-block=\"columns\"><article class=\"card\"><h2>Clareza em cada etapa</h2><p>Explique o resultado esperado com um exemplo concreto.</p></article><article class=\"card\"><h2>Acompanhamento próximo</h2><p>Mostre como o trabalho acontece na prática.</p></article></section><section data-editor-block=\"faq\"><h2>Perguntas frequentes</h2><details><summary>Como funciona o primeiro contato?</summary><p>A equipe combina o próximo passo de acordo com sua necessidade.</p></details><details><summary>O que preciso para começar?</summary><p>Compartilhe seu objetivo e o contexto da sua operação.</p></details></section><section id=\"contato\" data-editor-block=\"form\"><div class=\"host-form\" data-host-slot=\"form\" data-editor-block=\"form\"></div></section><footer data-editor-block=\"footer\">Conteúdo de demonstração.</footer></main>`,\n },\n {\n id: 'page-event',\n kind: 'page',\n titleKey: 'templates.event',\n descriptionKey: 'templates.eventDescription',\n css: PAGE_CSS,\n source: `<main><section data-editor-block=\"hero\"><p class=\"eyebrow\">ENCONTRO</p><h1>Uma conversa que merece seu tempo</h1><p>Apresente o tema do encontro e o que os participantes vão aprender.</p><a class=\"cta\" href=\"#inscricao\">Quero participar</a></section><section class=\"columns\" data-editor-block=\"columns\"><article class=\"card\"><h2>Uma visão prática</h2><p>Compartilhe ideias que possam ser aplicadas no dia a dia.</p></article><article class=\"card\"><h2>Espaço para perguntas</h2><p>Inclua as principais dúvidas na conversa.</p></article></section><section id=\"inscricao\" data-editor-block=\"form\"><h2>Reserve seu lugar</h2><div class=\"host-form\" data-host-slot=\"form\" data-editor-block=\"form\"></div></section><footer data-editor-block=\"footer\">Conteúdo de demonstração.</footer></main>`,\n },\n];\n\n/** The structure a new e-mail starts from: one section, one column, one editable text. */\nexport const BLANK_EMAIL_MJML = `<mjml>${EMAIL_BLOCK_STYLE}<mj-body width=\"600px\"><mj-section css-class=\"editor-layout-section\"><mj-column css-class=\"editor-layout-column\"><mj-text>Escreva seu conteúdo.</mj-text></mj-column></mj-section></mj-body></mjml>`;\n\nexport class TemplateCatalog {\n constructor(private readonly emailRenderer: MjmlEmailRenderer) {}\n\n list(kind: DocumentKind): readonly TemplateDescriptor[] {\n return DEFINITIONS.filter((entry) => entry.kind === kind).map(\n ({ id, kind: entryKind, titleKey, descriptionKey }) =>\n Object.freeze({ id, kind: entryKind, titleKey, descriptionKey }),\n );\n }\n\n async create(id: string): Promise<SourceInput> {\n const definition = DEFINITIONS.find((entry) => entry.id === id);\n if (!definition) throw new Error('template.not_found');\n return definition.kind === 'email'\n ? this.emailRenderer.createSource(this.emailLayout(definition.source))\n : { html: definition.source, css: definition.css ?? '' };\n }\n\n /**\n * The document an editor opens with when it is given none. The e-mail is the compiled\n * `BLANK_EMAIL_MJML`, stored so that an editor can be created synchronously; a test keeps\n * it equal to what the compiler produces. It has the layout of every generated e-mail, so\n * blocks can be inserted above and below its text and moved.\n */\n blank(kind: DocumentKind): SourceInput {\n return kind === 'email'\n ? { html: BLANK_EMAIL_HTML, css: '' }\n : { html: '<p>Escreva seu conteúdo.</p>', css: '' };\n }\n\n blocks(kind: DocumentKind): readonly string[] {\n return Object.freeze(Object.keys(this.blockDefinitions(kind)));\n }\n\n async createBlock(type: string, kind: DocumentKind): Promise<BlockSource> {\n const block = this.blockDefinitions(kind)[type];\n if (!block) throw new Error('block.not_supported');\n if (kind !== 'email') return { html: block, css: BLOCK_CSS };\n const source = await this.emailRenderer.createSource(\n this.emailLayout(`<mjml>${EMAIL_BLOCK_STYLE}<mj-body>${block}</mj-body></mjml>`),\n );\n return {\n html: source.html,\n css: source.css,\n insertion: EMAIL_SECTION_BLOCKS.has(type) ? 'section' : 'content',\n };\n }\n\n private emailLayout(source: string): string {\n return source\n .replaceAll('<mj-section', '<mj-section css-class=\"editor-layout-section\"')\n .replaceAll('<mj-column', '<mj-column css-class=\"editor-layout-column\"');\n }\n\n private blockDefinitions(kind: DocumentKind): Readonly<Record<string, string>> {\n const emailBlocks: Readonly<Record<string, string>> = {\n section:\n '<mj-section background-color=\"#ffffff\" padding=\"24px\"><mj-column><mj-text>Uma nova seção para sua mensagem.</mj-text></mj-column></mj-section>',\n text: '<mj-section><mj-column><mj-text>Escreva uma mensagem para sua próxima conversa.</mj-text></mj-column></mj-section>',\n heading:\n '<mj-section><mj-column><mj-text><h2 style=\"margin:0;font-size:28px;line-height:1.3;font-weight:700\">Seu próximo título</h2></mj-text></mj-column></mj-section>',\n image:\n '<mj-section><mj-column><mj-image src=\"https://placehold.co/600x260/png\" alt=\"Imagem de demonstração\" /></mj-column></mj-section>',\n button:\n '<mj-section><mj-column><mj-button href=\"https://example.com\">Saiba mais</mj-button></mj-column></mj-section>',\n columns:\n '<mj-section><mj-column><mj-text>Primeira coluna</mj-text></mj-column><mj-column><mj-text>Segunda coluna</mj-text></mj-column></mj-section>',\n divider:\n '<mj-section><mj-column><mj-divider border-color=\"#dce4e7\" /></mj-column></mj-section>',\n spacer: '<mj-section><mj-column><mj-spacer height=\"24px\" /></mj-column></mj-section>',\n footer: EMAIL_FOOTER,\n };\n const pageBlocks: Readonly<Record<string, string>> = {\n section:\n '<section data-editor-block=\"section\" style=\"padding:24px\"><div><h2>Uma nova seção</h2><p>Organize uma parte da sua página.</p></div></section>',\n hero: '<section data-editor-block=\"hero\"><p class=\"eyebrow\">SEU PRÓXIMO PASSO</p><h1>Apresente sua proposta</h1><p>Conte o que você entrega e convide a pessoa a começar.</p><a class=\"cta\" href=\"https://example.com\">Saiba mais</a></section>',\n heading: '<h2 data-editor-block=\"heading\">Seu próximo título</h2>',\n text: '<div data-editor-block=\"text\"><p>Escreva uma mensagem para sua próxima conversa.</p></div>',\n image:\n '<figure data-editor-block=\"image\"><img src=\"https://placehold.co/800x400/png\" alt=\"Imagem de demonstração\"><figcaption>Descreva a imagem.</figcaption></figure>',\n button: '<a data-editor-block=\"button\" class=\"cta\" href=\"https://example.com\">Saiba mais</a>',\n columns:\n '<section class=\"columns\" data-editor-block=\"columns\" style=\"gap:24px\"><article class=\"card\"><h2>Primeira coluna</h2><p>Apresente uma ideia.</p></article><article class=\"card\"><h2>Segunda coluna</h2><p>Apresente outra ideia.</p></article></section>',\n divider: '<hr>',\n spacer: '<div data-editor-block=\"spacer\" style=\"height:24px\"></div>',\n footer: '<footer data-editor-block=\"footer\">Edite as informações do rodapé.</footer>',\n faq: '<section data-editor-block=\"faq\"><h2>Perguntas frequentes</h2><details><summary>Como funciona?</summary><p>Explique o próximo passo.</p></details></section>',\n form: '<section data-editor-block=\"form\"><h2>Comece por aqui</h2><div data-host-slot=\"form\" data-editor-block=\"form\" class=\"host-form\"></div></section>',\n };\n return kind === 'email' ? emailBlocks : pageBlocks;\n }\n}\n","import { DocumentPresentationService } from '../application/document-presentation';\nimport { DocumentMetadataService } from '../application/document-metadata';\nimport { BlockCatalog } from '../core/catalog';\nimport { CanvasLayout } from '../core/canvas-layout';\nimport { DocumentHistory } from '../core/history';\nimport type { Diagnostic, DocumentKind, EditorDocumentData, SourceInput } from '../core/document';\nimport { HtmlDocumentCodec } from '../codecs/html';\nimport { CssDocumentCodec } from '../codecs/css';\nimport { ContentPolicy } from '../security/policy';\nimport { UrlPolicy } from '../security/url-policy';\nimport { ContentService } from '../application/content-service';\nimport { DocumentMutationService } from '../application/document-commands';\nimport { SectionLayoutService } from '../application/section-layout';\nimport { MjmlSectionScaffold } from '../renderers/section-scaffold';\nimport { ImageLinkService } from '../application/image-link';\nimport { SecureIdentifier } from '../security/identity';\nimport { HostIntegration } from '../application/host';\nimport type { HostAdapters } from '../application/host';\nimport { EditorSession } from '../application/session';\nimport { MjmlEmailRenderer } from '../renderers/email-renderer';\nimport type { MjmlCompilerPort } from '../renderers/email-renderer';\nimport { PageRenderer } from '../renderers/page-renderer';\nimport { HtmlDocumentAssembler } from '../renderers/preview-document';\nimport { SelectionPreviewRenderer } from '../renderers/selection-preview';\nimport { TemplateCatalog } from '../templates/catalog';\nimport { EditorController } from '../vue/controller';\n\nexport interface EditorOptions {\n readonly kind?: DocumentKind;\n readonly document?: EditorDocumentData;\n readonly source?: SourceInput;\n readonly readOnly?: boolean;\n readonly persistedRevision?: number;\n readonly host?: HostAdapters;\n readonly compiler?: MjmlCompilerPort;\n readonly exactUrlPlaceholders?: readonly string[];\n readonly previewImageOrigins?: readonly string[];\n /** Receives an exception thrown by a `session.subscribe` listener; the listener stays. */\n readonly onObserverError?: (error: unknown) => void;\n}\n\nexport interface EditorInstance {\n readonly session: EditorSession;\n readonly controller: EditorController;\n readonly templates: TemplateCatalog;\n readonly pageRenderer: PageRenderer;\n readonly emailRenderer: MjmlEmailRenderer;\n readonly selectionRenderer: SelectionPreviewRenderer;\n dispose(): void;\n}\n\n/**\n * The initial source could not become a document. Since the tolerant import this only\n * happens over the limits or with markup no parser reads back the same; `diagnostics`\n * carries the specific code (`DOCUMENT_TOO_LARGE`, `DOCUMENT_TOO_MANY_NODES`...).\n */\nexport class InitialDocumentError extends Error {\n constructor(readonly diagnostics: readonly Diagnostic[]) {\n super('INVALID_INITIAL_DOCUMENT');\n this.name = 'InitialDocumentError';\n }\n}\n\n/** The only place that constructs the dependency graph. Every editor owns its state. */\nexport class EditorFactory {\n constructor(private readonly compilerFactory: () => MjmlCompilerPort & { dispose?(): void }) {}\n\n create(options: EditorOptions = {}): EditorInstance {\n const compiler = options.compiler ?? this.compilerFactory();\n const catalog = new BlockCatalog();\n // One catalog and one layout for the whole editor: session, preview and controller agree.\n const structure = { catalog, layout: new CanvasLayout(catalog) };\n const urls = new UrlPolicy(\n options.exactUrlPlaceholders ? { exactUrlPlaceholders: options.exactUrlPlaceholders } : {},\n );\n const css = new CssDocumentCodec(urls);\n const policy = new ContentPolicy(urls, css);\n const codec = new HtmlDocumentCodec(policy, catalog);\n const content = new ContentService(codec, policy, css);\n const emailRenderer = new MjmlEmailRenderer(codec, policy, compiler);\n const templates = new TemplateCatalog(emailRenderer);\n // Without a source a document is born with the structure of its kind: an e-mail starts\n // as a generated section with one text, never as a loose paragraph.\n const imported = options.document\n ? undefined\n : content.import(\n options.source ?? templates.blank(options.kind ?? 'page'),\n options.kind ?? 'page',\n );\n const document = options.document ?? imported?.document;\n if (!document) throw new InitialDocumentError(imported?.diagnostics ?? []);\n if (options.kind && options.kind !== document.kind) throw new Error('INITIAL_KIND_MISMATCH');\n const host = new HostIntegration(options.host);\n const session = new EditorSession(\n {\n content,\n mutations: new DocumentMutationService(content, catalog),\n imageLinks: new ImageLinkService(content, urls, new SecureIdentifier()),\n presentation: new DocumentPresentationService(content),\n metadata: new DocumentMetadataService(content, new SecureIdentifier()),\n sectionLayouts: new SectionLayoutService(\n content,\n new SecureIdentifier(),\n new MjmlSectionScaffold(emailRenderer, css),\n ),\n history: new DocumentHistory(),\n host,\n },\n {\n document,\n ...(imported ? { diagnostics: imported.diagnostics } : {}),\n ...(options.readOnly !== undefined ? { readOnly: options.readOnly } : {}),\n ...(options.persistedRevision !== undefined\n ? { persistedRevision: options.persistedRevision }\n : {}),\n ...(options.onObserverError ? { onObserverError: options.onObserverError } : {}),\n },\n );\n const assembler = new HtmlDocumentAssembler(codec, policy, options.previewImageOrigins);\n return Object.freeze({\n session,\n templates,\n emailRenderer,\n selectionRenderer: new SelectionPreviewRenderer(codec, policy, assembler, structure),\n pageRenderer: new PageRenderer(codec, policy),\n controller: new EditorController(session, templates, assembler, urls, structure),\n dispose() {\n session.dispose();\n if (!options.compiler && 'dispose' in compiler && typeof compiler.dispose === 'function')\n compiler.dispose();\n },\n });\n }\n}\n","import * as v from 'valibot';\nimport { DocumentBudget, DocumentBudgetError } from './budget';\nimport { DocumentValidationError } from './document';\nimport type { DocumentKind } from './document';\n\n/**\n * Schema 2: a piece made of blocks. Each block keeps only the values its author set; what is\n * absent is inherited from the global styles of the piece, and those from the defaults of the\n * catalog. The HTML of an e-mail and of a page is generated from this tree, never edited.\n *\n * The aggregate knows the shape of the tree and its invariants. What each block type accepts\n * (children, properties, content rules) comes from a `BlockRules` port, implemented by the\n * block definitions outside `core`.\n */\nexport const BLOCK_NODE_TYPES = [\n 'section',\n 'column',\n 'text',\n 'heading',\n 'image',\n 'button',\n 'divider',\n 'spacer',\n 'footer',\n 'form',\n 'html',\n] as const;\nexport type BlockNodeType = (typeof BLOCK_NODE_TYPES)[number];\n\nexport type BlockPropValue = string | number | boolean;\nexport type BlockProps = Readonly<Record<string, BlockPropValue>>;\nexport type StyleValue = string | number;\nexport type GlobalStyles = Readonly<Record<string, Readonly<Record<string, StyleValue>>>>;\n\nexport interface Block {\n readonly id: string;\n readonly type: BlockNodeType;\n readonly props: BlockProps;\n /**\n * Values the block uses on small screens instead of its own (or inherited) ones. Only the\n * fields the rules call responsive may appear here; absent when the block has none.\n */\n readonly mobile?: BlockProps;\n readonly children?: readonly Block[];\n}\n\n/** The screen a value applies to: `desktop` writes `props`, `mobile` writes `mobile`. */\nexport type BlockDevice = 'desktop' | 'mobile';\nexport const BLOCK_DEVICES: readonly BlockDevice[] = Object.freeze(['desktop', 'mobile']);\n\nexport interface BlockDocumentMeta {\n readonly lang: string;\n}\n\nexport interface BlockDocumentData {\n readonly schemaVersion: 2;\n readonly id: string;\n readonly kind: DocumentKind;\n readonly revision: number;\n /** Internal label of the piece. The subject, preheader and SEO title belong to the host. */\n readonly title: string;\n readonly meta: BlockDocumentMeta;\n readonly styles: GlobalStyles;\n readonly blocks: readonly Block[];\n}\n\n/** Where an inserted or moved block goes. `inside` without a parent means the root. */\nexport type BlockTarget =\n | { readonly position: 'before' | 'after'; readonly id: string }\n | { readonly position: 'inside'; readonly parentId?: string; readonly index?: number };\n\nexport type StylePatch = Readonly<Record<string, Readonly<Record<string, StyleValue>>>>;\n\n/** What a block type accepts. Implemented by the block definitions. */\nexport interface BlockRules {\n /** Types which may stand at the root of the piece. */\n isRoot(type: BlockNodeType): boolean;\n /** Types a block of this type may contain; empty for a leaf. */\n childTypes(type: BlockNodeType): readonly BlockNodeType[];\n childCount(type: BlockNodeType): { readonly min: number; readonly max: number };\n allows(type: BlockNodeType, kind: DocumentKind): boolean;\n /** Error code for the properties of one block, or undefined when they are valid. */\n validateProps(type: BlockNodeType, props: BlockProps, kind: DocumentKind): string | undefined;\n /** The value a command writes: normalized, or a thrown `BlockDocumentError`. */\n normalizeProp(\n type: BlockNodeType,\n key: string,\n value: BlockPropValue,\n kind: DocumentKind,\n ): BlockPropValue;\n /** Keys whose value is a text the author edits in place. */\n textKeys(type: BlockNodeType): readonly string[];\n /**\n * Whether a property may take a value of its own on small screens. Without this method no\n * block of the piece accepts mobile values.\n */\n responsive?(type: BlockNodeType, key: string, kind: DocumentKind): boolean;\n validateStyles(styles: GlobalStyles, kind: DocumentKind): string | undefined;\n /**\n * Error code for the piece as a whole, once its tree is valid: e.g. an output larger than\n * the compilation or the conversion accepts. Optional.\n */\n validateDocument?(data: BlockDocumentData): string | undefined;\n normalizeStyle(group: string, key: string, value: StyleValue, kind: DocumentKind): StyleValue;\n}\n\nexport const BLOCK_DOCUMENT_LIMITS = Object.freeze({\n blocks: 5_000,\n depth: 8,\n childrenPerBlock: 500,\n propsPerBlock: 64,\n propValueLength: 500_000,\n styleGroups: 32,\n stylesPerGroup: 32,\n styleValueLength: 200,\n titleLength: 1_000,\n});\n\n/** Identifiers end up in class names, selectors and MJML attributes: nothing else is allowed. */\nexport const BLOCK_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;\nconst KEY_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{0,63}$/;\n/** A language tag as `<html lang>` takes it: `pt-BR`, `en`, `es-419`. */\nexport const LANGUAGE_TAG_PATTERN = /^[A-Za-z]{2,8}(-[A-Za-z0-9]{1,8}){0,4}$/;\n\nconst keySchema = v.pipe(v.string(), v.regex(KEY_PATTERN));\nconst propValueSchema = v.union([\n v.pipe(v.string(), v.maxLength(BLOCK_DOCUMENT_LIMITS.propValueLength)),\n v.pipe(v.number(), v.finite()),\n v.boolean(),\n]);\nconst styleValueSchema = v.union([\n v.pipe(v.string(), v.maxLength(BLOCK_DOCUMENT_LIMITS.styleValueLength)),\n v.pipe(v.number(), v.finite()),\n]);\n\nexport const BlockSchema: v.GenericSchema<Block> = v.lazy(() =>\n v.strictObject({\n id: v.pipe(v.string(), v.regex(BLOCK_ID_PATTERN)),\n type: v.picklist(BLOCK_NODE_TYPES),\n props: v.record(keySchema, propValueSchema),\n mobile: v.exactOptional(v.record(keySchema, propValueSchema)),\n children: v.exactOptional(v.array(BlockSchema)),\n }),\n);\n\nexport const GlobalStylesSchema: v.GenericSchema<GlobalStyles> = v.record(\n keySchema,\n v.record(keySchema, styleValueSchema),\n);\n\nexport const BlockDocumentSchema: v.GenericSchema<BlockDocumentData> = v.strictObject({\n schemaVersion: v.literal(2),\n id: v.pipe(v.string(), v.minLength(1), v.maxLength(200)),\n kind: v.picklist(['email', 'page']),\n revision: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(Number.MAX_SAFE_INTEGER)),\n title: v.pipe(v.string(), v.maxLength(BLOCK_DOCUMENT_LIMITS.titleLength)),\n meta: v.strictObject({ lang: v.pipe(v.string(), v.regex(LANGUAGE_TAG_PATTERN)) }),\n styles: GlobalStylesSchema,\n blocks: v.array(BlockSchema),\n});\n\nexport class BlockDocumentError extends DocumentValidationError {\n constructor(code: string) {\n super(code);\n this.name = 'BlockDocumentError';\n }\n}\n\ninterface MutableBlock {\n id: string;\n type: BlockNodeType;\n props: Record<string, BlockPropValue>;\n mobile?: Record<string, BlockPropValue>;\n children?: MutableBlock[];\n}\n\ninterface Location {\n readonly list: MutableBlock[];\n readonly index: number;\n readonly parent: MutableBlock | undefined;\n}\n\n/**\n * Immutable aggregate of a block piece. Every operation is pure: it returns a new document\n * with the next revision, validated as a whole, or throws `BlockDocumentError`.\n */\nexport class BlockDocument {\n readonly #data: BlockDocumentData;\n readonly #rules: BlockRules;\n #bytes: number | undefined;\n /** The copies the current command made, so a block on two paths is copied once. */\n #opened = new WeakSet<MutableBlock>();\n /** Each block by id with its parent, built once: the document never changes. */\n #index: Map<string, { readonly block: Block; readonly parent: Block | undefined }> | undefined;\n\n private constructor(data: BlockDocumentData, rules: BlockRules) {\n this.#data = BlockDocument.freeze(data);\n this.#rules = rules;\n }\n\n static from(input: unknown, rules: BlockRules): BlockDocument {\n try {\n new DocumentBudget().assertInput(input);\n } catch (error: unknown) {\n throw new BlockDocumentError(\n error instanceof DocumentBudgetError && error.code !== 'INVALID_DOCUMENT_SCHEMA'\n ? error.code\n : 'INVALID_BLOCK_DOCUMENT_SCHEMA',\n );\n }\n const parsed = v.safeParse(BlockDocumentSchema, input);\n if (!parsed.success) throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n return BlockDocument.checked(structuredClone(parsed.output), rules);\n }\n\n /** The invariants of the tree and of the piece, over data of the schema's shape. */\n private static checked(data: BlockDocumentData, rules: BlockRules): BlockDocument {\n BlockDocument.assertStyles(data, rules);\n BlockDocument.assertTree(data, rules);\n const error = rules.validateDocument?.(data);\n if (error) throw new BlockDocumentError(error);\n return new BlockDocument(data, rules);\n }\n\n get id(): string {\n return this.#data.id;\n }\n get kind(): DocumentKind {\n return this.#data.kind;\n }\n get revision(): number {\n return this.#data.revision;\n }\n get title(): string {\n return this.#data.title;\n }\n get meta(): BlockDocumentMeta {\n return this.#data.meta;\n }\n /** Frozen view of the overridden global styles. */\n get styles(): GlobalStyles {\n return this.#data.styles;\n }\n /** Frozen view of the tree; `snapshot()` gives an independent copy. */\n get blocks(): readonly Block[] {\n return this.#data.blocks;\n }\n\n snapshot(): BlockDocumentData {\n return structuredClone(this.#data);\n }\n\n /** The data itself, deeply frozen: what reads it never pays for a copy. */\n get data(): BlockDocumentData {\n return this.#data;\n }\n\n /** Size of the JSON of the piece, for the byte budget of the history. */\n serializedBytes(): number {\n this.#bytes ??= new DocumentBudget().byteLength(JSON.stringify(this.#data));\n return this.#bytes;\n }\n\n /**\n * Only the revision changes: the validated tree is not checked a second time. A session uses\n * it to move forward when it restores an earlier step of its history.\n */\n withRevision(revision: number): BlockDocument {\n if (!Number.isSafeInteger(revision) || revision < 0)\n throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n return revision === this.#data.revision\n ? this\n : new BlockDocument({ ...this.snapshot(), revision }, this.#rules);\n }\n\n find(id: string): Block | undefined {\n return this.index().get(id)?.block;\n }\n\n /** Id of the block which contains this one; undefined at the root or when absent. */\n parentOf(id: string): string | undefined {\n return this.index().get(id)?.parent?.id;\n }\n\n private index(): Map<string, { readonly block: Block; readonly parent: Block | undefined }> {\n if (this.#index) return this.#index;\n const index = new Map<string, { block: Block; parent: Block | undefined }>();\n const stack: { block: Block; parent: Block | undefined }[] = this.#data.blocks.map((block) => ({\n block,\n parent: undefined,\n }));\n while (stack.length) {\n const entry = stack.pop();\n if (!entry) break;\n index.set(entry.block.id, entry);\n for (const child of entry.block.children ?? [])\n stack.push({ block: child, parent: entry.block });\n }\n this.#index = index;\n return index;\n }\n\n insert(block: Block, target: BlockTarget): BlockDocument {\n // The block comes from outside the document: its shape is parsed like any input.\n if (!v.safeParse(BlockSchema, block).success)\n throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n const blocks = this.mutableBlocks();\n this.place(blocks, structuredClone(block) as MutableBlock, target);\n return this.next({ blocks });\n }\n\n /**\n * `inside` with an index counts the slots of the parent as it is before the move, like a\n * drop indicator between two blocks: moving the first of `[a, b]` to index 2 gives `[b, a]`.\n */\n move(id: string, target: BlockTarget): BlockDocument {\n const blocks = this.mutableBlocks();\n const location = this.require(blocks, id);\n const moving = location.list[location.index];\n if (!moving) throw new BlockDocumentError('BLOCK_NOT_FOUND');\n const anchor = target.position === 'inside' ? target.parentId : target.id;\n if (anchor !== undefined && this.contains(moving, anchor))\n throw new BlockDocumentError('INVALID_BLOCK_TARGET');\n let destination = target;\n if (\n target.position === 'inside' &&\n target.index !== undefined &&\n target.parentId === location.parent?.id\n ) {\n if (\n !Number.isInteger(target.index) ||\n target.index < 0 ||\n target.index > location.list.length\n )\n throw new BlockDocumentError('INVALID_BLOCK_TARGET');\n if (target.index > location.index) destination = { ...target, index: target.index - 1 };\n }\n location.list.splice(location.index, 1);\n this.place(blocks, moving, destination);\n return this.next({ blocks });\n }\n\n /** Copies a block and its children with new ids, right after the original. */\n duplicate(id: string, nextId: () => string): BlockDocument {\n const blocks = this.mutableBlocks();\n const location = this.require(blocks, id);\n const original = location.list[location.index];\n if (!original) throw new BlockDocumentError('BLOCK_NOT_FOUND');\n const copy = this.reidentify(original, nextId);\n location.list.splice(location.index + 1, 0, copy);\n return this.next({ blocks });\n }\n\n remove(id: string): BlockDocument {\n const blocks = this.mutableBlocks();\n const location = this.require(blocks, id);\n location.list.splice(location.index, 1);\n return this.next({ blocks });\n }\n\n /**\n * Sets values the author chose, for every screen or only for small ones; a patch which\n * changes nothing returns this document. A mobile value equal to the one the block already\n * uses on every screen is still kept: the author chose it for the small screen.\n */\n updateProps(id: string, patch: BlockProps, device: BlockDevice = 'desktop'): BlockDocument {\n const blocks = this.mutableBlocks();\n const block = this.blockAt(blocks, id);\n if (device === 'mobile' && Object.keys(patch).some((key) => !this.responsive(block.type, key)))\n throw new BlockDocumentError('BLOCK_PROP_NOT_RESPONSIVE');\n const target = device === 'mobile' ? (block.mobile ??= {}) : block.props;\n let changed = false;\n for (const [key, value] of Object.entries(patch)) {\n const normalized = this.#rules.normalizeProp(block.type, key, value, this.kind);\n if (target[key] === normalized) continue;\n target[key] = normalized;\n changed = true;\n }\n if (block.mobile && !Object.keys(block.mobile).length) delete block.mobile;\n return changed ? this.next({ blocks }) : this;\n }\n\n /**\n * \"Restore default\": the keys disappear and the block inherits again. On mobile only the\n * mobile values go, and the block uses its value of every screen again.\n */\n restoreDefault(\n id: string,\n keys: readonly string[],\n device: BlockDevice = 'desktop',\n ): BlockDocument {\n const blocks = this.mutableBlocks();\n const block = this.blockAt(blocks, id);\n const target = device === 'mobile' ? block.mobile : block.props;\n if (!target) return this;\n const present = keys.filter((key) => Object.hasOwn(target, key));\n if (!present.length) return this;\n for (const key of present) delete target[key];\n if (block.mobile && !Object.keys(block.mobile).length) delete block.mobile;\n return this.next({ blocks });\n }\n\n /** Whether this property of the block may take a value of its own on small screens. */\n responsive(type: BlockNodeType, key: string): boolean {\n return this.#rules.responsive?.(type, key, this.kind) === true;\n }\n\n /** The text of a block, in the rich-text projection its type accepts. */\n updateText(id: string, key: string, value: string): BlockDocument {\n const block = this.find(id);\n if (!block) throw new BlockDocumentError('BLOCK_NOT_FOUND');\n if (!this.#rules.textKeys(block.type).includes(key))\n throw new BlockDocumentError('BLOCK_TEXT_NOT_EDITABLE');\n return this.updateProps(id, { [key]: value });\n }\n\n updateStyles(patch: StylePatch): BlockDocument {\n const styles: Record<string, Record<string, StyleValue>> = structuredClone(\n this.#data.styles,\n ) as Record<string, Record<string, StyleValue>>;\n let changed = false;\n for (const [group, values] of Object.entries(patch)) {\n for (const [key, value] of Object.entries(values)) {\n const normalized = this.#rules.normalizeStyle(group, key, value, this.kind);\n if (styles[group]?.[key] === normalized) continue;\n (styles[group] ??= {})[key] = normalized;\n changed = true;\n }\n }\n return changed ? this.next({ styles }) : this;\n }\n\n /**\n * Back to the catalog defaults: every style without a group, a whole group without keys,\n * or only the given keys of a group.\n */\n restoreStyleDefault(group?: string, keys?: readonly string[]): BlockDocument {\n if (group === undefined)\n return Object.keys(this.#data.styles).length ? this.next({ styles: {} }) : this;\n if (!this.#data.styles[group]) return this;\n const styles = structuredClone(this.#data.styles) as Record<string, Record<string, StyleValue>>;\n if (keys === undefined) delete styles[group];\n else {\n const values = styles[group];\n if (values) {\n if (!keys.some((key) => Object.hasOwn(values, key))) return this;\n for (const key of keys) delete values[key];\n if (!Object.keys(values).length) delete styles[group];\n }\n }\n return this.next({ styles });\n }\n\n withMeta(meta: BlockDocumentMeta): BlockDocument {\n return meta.lang === this.#data.meta.lang ? this : this.next({ meta });\n }\n\n withTitle(title: string): BlockDocument {\n return title === this.#data.title ? this : this.next({ title });\n }\n\n /**\n * The next revision. The data was built here from a validated document and from values the\n * rules normalized, so it keeps the shape of the schema; the parsing of the schema is not\n * paid again, but every invariant of the tree and of the piece is checked as for any input.\n */\n private next(change: {\n blocks?: readonly MutableBlock[];\n styles?: GlobalStyles;\n meta?: BlockDocumentMeta;\n title?: string;\n }): BlockDocument {\n if (change.title !== undefined && change.title.length > BLOCK_DOCUMENT_LIMITS.titleLength)\n throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n if (change.meta !== undefined && !LANGUAGE_TAG_PATTERN.test(change.meta.lang))\n throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n if (this.#data.revision + 1 > Number.MAX_SAFE_INTEGER)\n throw new BlockDocumentError('INVALID_BLOCK_DOCUMENT_SCHEMA');\n const data: BlockDocumentData = {\n schemaVersion: 2,\n id: this.#data.id,\n kind: this.#data.kind,\n revision: this.#data.revision + 1,\n title: change.title ?? this.#data.title,\n meta: change.meta ? { lang: change.meta.lang } : this.#data.meta,\n styles: change.styles ? structuredClone(change.styles) : this.#data.styles,\n blocks: change.blocks ? (change.blocks as readonly Block[]) : this.#data.blocks,\n };\n return BlockDocument.checked(data, this.#rules);\n }\n\n /**\n * The tree a command changes, copied on write: the root list is new, and `locate` copies\n * only the blocks on the path to what it finds. Every other block stays the frozen object of\n * this document, shared by the next one (and never validated again: see `assertTree`).\n */\n private mutableBlocks(): MutableBlock[] {\n this.#opened = new WeakSet();\n return [...this.#data.blocks] as MutableBlock[];\n }\n\n /** A block of the tree being changed, as a copy the command may write. */\n private open(block: MutableBlock): MutableBlock {\n if (this.#opened.has(block)) return block;\n const copy: MutableBlock = {\n ...block,\n props: { ...block.props },\n ...(block.mobile ? { mobile: { ...block.mobile } } : {}),\n ...(block.children ? { children: [...block.children] } : {}),\n };\n this.#opened.add(copy);\n return copy;\n }\n\n private place(blocks: MutableBlock[], block: MutableBlock, target: BlockTarget): void {\n if (target.position === 'inside') {\n let list = blocks;\n if (target.parentId !== undefined) {\n const parent = this.blockAt(blocks, target.parentId);\n list = parent.children ??= [];\n }\n const index = target.index ?? list.length;\n if (!Number.isInteger(index) || index < 0 || index > list.length)\n throw new BlockDocumentError('INVALID_BLOCK_TARGET');\n list.splice(index, 0, block);\n return;\n }\n const location = this.require(blocks, target.id);\n location.list.splice(location.index + (target.position === 'after' ? 1 : 0), 0, block);\n }\n\n private contains(block: MutableBlock, id: string): boolean {\n const stack = [block];\n while (stack.length) {\n const current = stack.pop();\n if (!current) break;\n if (current.id === id) return true;\n stack.push(...(current.children ?? []));\n }\n return false;\n }\n\n private reidentify(block: MutableBlock, nextId: () => string): MutableBlock {\n return {\n ...structuredClone(block),\n id: nextId(),\n ...(block.children\n ? { children: block.children.map((child) => this.reidentify(child, nextId)) }\n : {}),\n };\n }\n\n private blockAt(blocks: MutableBlock[], id: string): MutableBlock {\n const location = this.require(blocks, id);\n const block = location.list[location.index];\n if (!block) throw new BlockDocumentError('BLOCK_NOT_FOUND');\n return block;\n }\n\n private require(blocks: MutableBlock[], id: string): Location {\n const location = this.locate(blocks, id);\n if (!location) throw new BlockDocumentError('BLOCK_NOT_FOUND');\n return location;\n }\n\n /**\n * Where a block of this document stands in the tree being changed. The path comes from the\n * index of this document (a command never moves a block inside itself), and each block on it\n * is opened for writing, the found one included.\n */\n private locate(blocks: MutableBlock[], id: string): Location | undefined {\n const chain: string[] = [];\n const index = this.index();\n for (let entry = index.get(id); entry; entry = entry.parent && index.get(entry.parent.id))\n chain.unshift(entry.block.id);\n if (!chain.length) return undefined;\n let list = blocks;\n let parent: MutableBlock | undefined;\n for (let depth = 0; depth < chain.length; depth++) {\n const position = list.findIndex((block) => block.id === chain[depth]);\n const found = list[position];\n if (!found) return undefined;\n const opened = this.open(found);\n list[position] = opened;\n if (depth === chain.length - 1) return { list, index: position, parent };\n parent = opened;\n list = opened.children ??= [];\n }\n return undefined;\n }\n\n private static assertStyles(data: BlockDocumentData, rules: BlockRules): void {\n const groups = Object.values(data.styles);\n if (\n groups.length > BLOCK_DOCUMENT_LIMITS.styleGroups ||\n groups.some((group) => Object.keys(group).length > BLOCK_DOCUMENT_LIMITS.stylesPerGroup)\n )\n throw new BlockDocumentError('INVALID_GLOBAL_STYLES');\n const error = rules.validateStyles(data.styles, data.kind);\n if (error) throw new BlockDocumentError(error);\n }\n\n /**\n * Frozen blocks whose own values were already accepted by these rules for a kind. The values\n * of a block depend only on its type and the kind, and a frozen block never changes: a block\n * shared by the next revision is not checked again. Its place in the tree always is.\n */\n private static readonly accepted = new WeakMap<\n BlockRules,\n Record<DocumentKind, WeakSet<Block>>\n >();\n\n private static acceptedFor(rules: BlockRules, kind: DocumentKind): WeakSet<Block> {\n let sets = BlockDocument.accepted.get(rules);\n if (!sets) {\n sets = { email: new WeakSet(), page: new WeakSet() };\n BlockDocument.accepted.set(rules, sets);\n }\n return sets[kind];\n }\n\n private static assertTree(data: BlockDocumentData, rules: BlockRules): void {\n const accepted = BlockDocument.acceptedFor(rules, data.kind);\n const seen = new Set<string>();\n const stack: { block: Block; depth: number; parent: Block | undefined }[] = data.blocks.map(\n (block) => ({ block, depth: 0, parent: undefined }),\n );\n while (stack.length) {\n const frame = stack.pop();\n if (!frame) break;\n const { block, depth, parent } = frame;\n if (depth > BLOCK_DOCUMENT_LIMITS.depth)\n throw new BlockDocumentError('BLOCK_DOCUMENT_TOO_DEEP');\n if (seen.has(block.id)) throw new BlockDocumentError('DUPLICATE_BLOCK_ID');\n seen.add(block.id);\n if (seen.size > BLOCK_DOCUMENT_LIMITS.blocks)\n throw new BlockDocumentError('BLOCK_DOCUMENT_TOO_MANY_BLOCKS');\n if (!rules.allows(block.type, data.kind))\n throw new BlockDocumentError('BLOCK_KIND_NOT_ALLOWED');\n if (parent === undefined && !rules.isRoot(block.type))\n throw new BlockDocumentError('BLOCK_NOT_ALLOWED_AT_ROOT');\n if (parent !== undefined && !rules.childTypes(parent.type).includes(block.type))\n throw new BlockDocumentError('BLOCK_CHILD_NOT_ALLOWED');\n const allowed = rules.childTypes(block.type);\n if (!allowed.length && block.children !== undefined)\n throw new BlockDocumentError('BLOCK_CHILD_NOT_ALLOWED');\n if (allowed.length) {\n const count = block.children?.length ?? 0;\n const limits = rules.childCount(block.type);\n if (count < limits.min) throw new BlockDocumentError('TOO_FEW_CHILDREN');\n if (count > Math.min(limits.max, BLOCK_DOCUMENT_LIMITS.childrenPerBlock))\n throw new BlockDocumentError('TOO_MANY_CHILDREN');\n }\n if (!accepted.has(block)) {\n if (Object.keys(block.props).length > BLOCK_DOCUMENT_LIMITS.propsPerBlock)\n throw new BlockDocumentError('INVALID_BLOCK_PROPS');\n if (\n !BlockDocument.values(block.props) ||\n (block.mobile && !BlockDocument.values(block.mobile))\n )\n throw new BlockDocumentError('INVALID_BLOCK_PROPS');\n const error = rules.validateProps(block.type, block.props, data.kind);\n if (error) throw new BlockDocumentError(error);\n if (block.mobile !== undefined) BlockDocument.assertMobile(block, data.kind, rules);\n if (\n Object.isFrozen(block) &&\n Object.isFrozen(block.props) &&\n (!block.mobile || Object.isFrozen(block.mobile))\n )\n accepted.add(block);\n }\n for (const child of block.children ?? [])\n stack.push({ block: child, depth: depth + 1, parent: block });\n }\n }\n\n /**\n * Mobile values: at least one, each of a responsive property, each one a value the property\n * accepts. They are checked over the values of every screen, so the rules see a whole block.\n */\n private static assertMobile(block: Block, kind: DocumentKind, rules: BlockRules): void {\n const mobile = block.mobile ?? {};\n const keys = Object.keys(mobile);\n if (!keys.length || keys.length > BLOCK_DOCUMENT_LIMITS.propsPerBlock)\n throw new BlockDocumentError('INVALID_BLOCK_PROPS');\n if (keys.some((key) => rules.responsive?.(block.type, key, kind) !== true))\n throw new BlockDocumentError('BLOCK_PROP_NOT_RESPONSIVE');\n const error = rules.validateProps(block.type, { ...block.props, ...mobile }, kind);\n if (error) throw new BlockDocumentError(error);\n }\n\n /** Keys and values of the schema's shape, checked again for data built by a command. */\n private static values(props: BlockProps): boolean {\n for (const [key, value] of Object.entries(props)) {\n if (!KEY_PATTERN.test(key)) return false;\n if (typeof value === 'string') {\n if (value.length > BLOCK_DOCUMENT_LIMITS.propValueLength) return false;\n } else if (typeof value === 'number') {\n if (!Number.isFinite(value)) return false;\n } else if (typeof value !== 'boolean') return false;\n }\n return true;\n }\n\n private static freeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value);\n for (const entry of Object.values(value)) BlockDocument.freeze(entry);\n }\n return value;\n }\n}\n","import { BlockDocument } from './block-document';\nimport type { BlockRules } from './block-document';\nimport { DocumentValidationError, EditorDocument } from './document';\n\n/** A stored piece in either format. Nothing converts one into the other on the way in. */\nexport type AnyDocument =\n | { readonly schemaVersion: 1; readonly document: EditorDocument }\n | { readonly schemaVersion: 2; readonly document: BlockDocument };\n\n/**\n * Dispatches by `schemaVersion`: 1 is the HTML document of the editor, 2 the block piece.\n * Throws `DocumentValidationError` (or its `BlockDocumentError` subclass) like each format.\n */\nexport function parseAnyDocument(input: unknown, rules: BlockRules): AnyDocument {\n if (!input || typeof input !== 'object' || Array.isArray(input))\n throw new DocumentValidationError('INVALID_DOCUMENT_SCHEMA');\n const version: unknown = Object.getOwnPropertyDescriptor(input, 'schemaVersion')?.value;\n if (version === 1) return { schemaVersion: 1, document: EditorDocument.from(input) };\n if (version === 2) return { schemaVersion: 2, document: BlockDocument.from(input, rules) };\n throw new DocumentValidationError('UNSUPPORTED_SCHEMA_VERSION');\n}\n","import { BlockDocument } from '../core/block-document';\nimport type {\n Block,\n BlockDevice,\n BlockDocumentData,\n BlockNodeType,\n BlockProps,\n BlockTarget,\n StylePatch,\n} from '../core/block-document';\nimport { DocumentBudget } from '../core/budget';\nimport { DocumentValidationError } from '../core/document';\nimport type { Diagnostic, SourceInput } from '../core/document';\nimport { DocumentHistory } from '../core/history';\n\n/** The final output of a piece: the compiled e-mail, or the HTML and CSS of the page. */\nexport interface BlockOutputPort {\n render(document: BlockDocument): Promise<SourceInput>;\n}\n\n/** Where the host keeps a block piece, with the output generated from it. */\nexport interface BlockStorePort {\n save(\n document: BlockDocumentData,\n output: SourceInput,\n expectedRevision: number,\n signal?: AbortSignal,\n ): Promise<{ revision: number }>;\n}\n\n/** Creates the blocks of each type and says which keys hold a text edited in place. */\nexport interface BlockFactoryPort {\n create(type: BlockNodeType, nextId: () => string, props?: BlockProps): Block;\n textKeys(type: BlockNodeType): readonly string[];\n}\n\nexport interface IdentifierPort {\n next(): string;\n}\n\n/** An image chosen for a block: the asset of the host, when there is one. */\nexport interface BlockImageChoice {\n readonly url: string;\n readonly alt?: string;\n readonly assetId?: string;\n}\n\nexport interface BlockEditorState {\n readonly document: BlockDocumentData;\n readonly selectedBlockId: string | undefined;\n /** The text being edited in place, until it is confirmed or cancelled. */\n readonly pendingText: { readonly id: string; readonly key: string } | undefined;\n readonly diagnostics: readonly Diagnostic[];\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n readonly readOnly: boolean;\n readonly dirty: boolean;\n readonly saving: boolean;\n}\n\nexport interface BlockSessionServices {\n readonly factory: BlockFactoryPort;\n readonly output: BlockOutputPort;\n readonly identifiers: IdentifierPort;\n readonly store?: BlockStorePort;\n readonly history?: DocumentHistory<BlockDocument>;\n}\n\nexport interface BlockSessionOptions {\n readonly document: BlockDocument;\n readonly readOnly?: boolean;\n readonly persistedRevision?: number;\n readonly onObserverError?: (error: unknown) => void;\n}\n\ninterface PendingText {\n readonly id: string;\n readonly key: string;\n readonly original: string;\n html: string;\n}\n\n/**\n * The editing session of a block piece (schema 2), beside the session of the HTML document\n * (schema 1). Every command is one step of history; the document is the immutable aggregate,\n * so a refused command changes nothing. Undoing moves forward in revision, as in schema 1, so a\n * host saving by compare-and-swap never goes back.\n */\nexport class BlockEditorSession {\n #document: BlockDocument;\n #selection: string | undefined;\n #text: PendingText | undefined;\n #diagnostics: readonly Diagnostic[] = [];\n #readOnly: boolean;\n #persistedRevision: number;\n #savedRevision: number;\n #saving = false;\n #saveSequence = 0;\n #saveAbort: AbortController | undefined;\n #disposed = false;\n readonly #history: DocumentHistory<BlockDocument>;\n readonly #listeners = new Set<(state: BlockEditorState) => void>();\n\n constructor(\n private readonly services: BlockSessionServices,\n private readonly options: BlockSessionOptions,\n ) {\n this.#document = options.document;\n this.#readOnly = options.readOnly ?? false;\n this.#persistedRevision = options.persistedRevision ?? this.#document.revision;\n this.#savedRevision = this.#document.revision;\n this.#history = services.history ?? new DocumentHistory<BlockDocument>();\n this.#history.reset(this.#document);\n }\n\n /** The current piece; immutable, so it can be handed to generators as it is. */\n document(): BlockDocument {\n this.assertActive();\n return this.#document;\n }\n\n snapshot(): BlockDocumentData {\n return this.document().snapshot();\n }\n\n getState(): BlockEditorState {\n this.assertActive();\n return Object.freeze({\n // Deeply frozen and never changed: the listeners share it instead of a copy each.\n document: this.#document.data,\n selectedBlockId: this.#selection,\n pendingText: this.#text\n ? Object.freeze({ id: this.#text.id, key: this.#text.key })\n : undefined,\n diagnostics: this.#diagnostics,\n canUndo: this.#history.canUndo || this.textChanged(),\n canRedo: this.#history.canRedo && !this.textChanged(),\n readOnly: this.#readOnly,\n dirty: this.#document.revision !== this.#savedRevision || this.textChanged(),\n saving: this.#saving,\n });\n }\n\n subscribe(listener: (state: BlockEditorState) => void): () => void {\n this.assertActive();\n this.#listeners.add(listener);\n this.deliver(listener, this.getState());\n return () => this.#listeners.delete(listener);\n }\n\n setReadOnly(value: boolean): void {\n this.assertActive();\n if (typeof value !== 'boolean') throw new TypeError('INVALID_READ_ONLY');\n if (value === this.#readOnly) return;\n this.#readOnly = value;\n this.#text = undefined;\n this.emit();\n }\n\n select(id: string | undefined): boolean {\n this.assertActive();\n if (id !== undefined && !this.#document.find(id)) return false;\n if (id === this.#selection) return true;\n if (this.#text && this.#text.id !== id && !this.commitText()) return false;\n this.#selection = id;\n this.emit();\n return true;\n }\n\n /** A new block of a type; it becomes the selection. Returns its id, or undefined. */\n insert(type: BlockNodeType, target: BlockTarget, props?: BlockProps): string | undefined {\n let block: Block;\n try {\n block = this.services.factory.create(type, () => this.newId(), props);\n } catch {\n this.fail('CHANGE_INVALID');\n return undefined;\n }\n return this.insertBlock(block, target);\n }\n\n /** A block with its children, made with ids of `newId()`; it becomes the selection. */\n insertBlock(block: Block, target: BlockTarget): string | undefined {\n if (!this.change((document) => document.insert(block, target))) return undefined;\n this.#selection = block.id;\n this.emit();\n return block.id;\n }\n\n /** A new block id, unique in practice: 80 random bits. */\n newId(): string {\n return `b${this.services.identifiers.next().slice(0, 20)}`;\n }\n\n move(id: string, target: BlockTarget): boolean {\n return this.change((document) => document.move(id, target));\n }\n\n duplicate(id: string): boolean {\n return this.change((document) => document.duplicate(id, () => this.newId()));\n }\n\n remove(id: string): boolean {\n const parent = this.#document.parentOf(id);\n const applied = this.change((document) => document.remove(id));\n if (applied && this.#selection === undefined && parent && this.#document.find(parent)) {\n this.#selection = parent;\n this.emit();\n }\n return applied;\n }\n\n /**\n * Properties of a block in one step. A new address typed by hand (`url` without `assetId`)\n * no longer points at the asset of the host library chosen before: that asset goes in the\n * same step, so the host never keeps a stale reference.\n */\n updateProps(id: string, patch: BlockProps, device: BlockDevice = 'desktop'): boolean {\n if (device === 'mobile')\n return this.change((document) => document.updateProps(id, patch, device));\n return this.change((document) => {\n const next = document.updateProps(id, patch);\n const staleAsset =\n 'url' in patch &&\n !('assetId' in patch) &&\n next !== document &&\n next.find(id)?.props.assetId !== undefined;\n return staleAsset ? next.restoreDefault(id, ['assetId']) : next;\n });\n }\n\n restoreDefault(id: string, keys: readonly string[], device: BlockDevice = 'desktop'): boolean {\n if (device === 'mobile')\n return this.change((document) => document.restoreDefault(id, keys, device));\n // The address goes back to the default: the asset it came from goes with it.\n const all = keys.includes('url') && !keys.includes('assetId') ? [...keys, 'assetId'] : keys;\n return this.change((document) => document.restoreDefault(id, all));\n }\n\n /**\n * Address, description and asset of an image in one step of history. What the choice does\n * not bring goes: the description and the asset of the previous image never describe the new\n * one.\n */\n replaceImage(id: string, choice: BlockImageChoice): boolean {\n return this.change((document) => {\n const patch: Record<string, string> = { url: choice.url };\n if (choice.alt !== undefined) patch.alt = choice.alt;\n if (choice.assetId !== undefined) patch.assetId = choice.assetId;\n const stale = [\n ...(choice.alt === undefined ? ['alt'] : []),\n ...(choice.assetId === undefined ? ['assetId'] : []),\n ];\n const next = document.updateProps(id, patch);\n return stale.length ? next.restoreDefault(id, stale) : next;\n });\n }\n\n updateStyles(patch: StylePatch): boolean {\n return this.change((document) => document.updateStyles(patch));\n }\n\n restoreStyleDefault(group?: string, keys?: readonly string[]): boolean {\n return this.change((document) => document.restoreStyleDefault(group, keys));\n }\n\n setLanguage(lang: string): boolean {\n return this.change((document) => document.withMeta({ lang }));\n }\n\n setTitle(title: string): boolean {\n return this.change((document) => document.withTitle(title));\n }\n\n /** A whole piece of the same kind and id, e.g. made from a template: one step of history. */\n replace(document: BlockDocument): boolean {\n if (document.id !== this.#document.id || document.kind !== this.#document.kind) return false;\n return this.change(() => document);\n }\n\n /** Opens the text of a block for editing in place. */\n beginText(id: string): boolean {\n if (!this.canWrite()) return false;\n if (this.#text?.id === id) return true;\n const block = this.#document.find(id);\n const key = block ? this.services.factory.textKeys(block.type)[0] : undefined;\n if (!block || !key || (this.#text && !this.commitText())) return false;\n const value = block.props[key];\n const original = typeof value === 'string' ? value : '';\n this.#text = { id, key, original, html: original };\n this.#selection = id;\n this.emit();\n return true;\n }\n\n updateTextDraft(html: string): boolean {\n if (!this.canWrite() || !this.#text) return false;\n if (typeof html !== 'string' || new DocumentBudget().byteLength(html) > 1_000_000)\n return this.fail('INVALID_BLOCK_TEXT');\n const changed = this.textChanged();\n this.#text.html = html;\n if (changed !== this.textChanged()) this.emit();\n return true;\n }\n\n /**\n * Confirms the text being edited: the block takes it in the projection of its type. A refused\n * text stays open as it was typed, with the diagnostic, as in the HTML document: nothing the\n * person wrote is lost because the piece did not accept it.\n */\n commitText(): boolean {\n const text = this.#text;\n if (!text) return true;\n if (!this.canWrite()) return false;\n if (text.html === text.original) {\n this.#text = undefined;\n this.emit();\n return true;\n }\n const next = this.attempt((document) => document.updateText(text.id, text.key, text.html));\n if (!next) return false;\n this.#text = undefined;\n if (next === this.#document) this.emit();\n else this.apply(next);\n return true;\n }\n\n cancelText(): void {\n if (!this.#text) return;\n this.#text = undefined;\n this.emit();\n }\n\n undo(): boolean {\n return this.restore('undo');\n }\n\n redo(): boolean {\n return this.restore('redo');\n }\n\n /** Generates the final output and hands both to the host store. */\n async save(): Promise<boolean> {\n return (await this.saveDocument()) !== undefined;\n }\n\n /**\n * As `save`, returning the exact piece the store received (changes made while it was being\n * saved are not in it), or undefined when nothing was saved.\n */\n async saveDocument(): Promise<BlockDocumentData | undefined> {\n if (!this.canWrite() || this.#saving || !this.commitText()) return undefined;\n const store = this.services.store;\n if (!store) return undefined;\n const document = this.#document;\n this.#saving = true;\n this.#saveAbort?.abort();\n const abort = new AbortController();\n this.#saveAbort = abort;\n const job = ++this.#saveSequence;\n this.emit();\n try {\n const output = await this.services.output.render(document);\n if (this.#disposed || abort.signal.aborted) return undefined;\n const saved = document.snapshot();\n const result = await store.save(saved, { ...output }, this.#persistedRevision, abort.signal);\n if (this.#disposed || abort.signal.aborted || job !== this.#saveSequence) return undefined;\n this.#persistedRevision = result.revision;\n this.#savedRevision = document.revision;\n this.#diagnostics = [];\n return saved;\n } catch {\n if (!this.#disposed) this.fail('SAVE_FAILED', 'diagnostics.saveFailed');\n return undefined;\n } finally {\n if (!this.#disposed) {\n this.#saving = false;\n this.emit();\n }\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n this.#disposed = true;\n this.#saveSequence++;\n this.#saveAbort?.abort();\n this.#text = undefined;\n this.#listeners.clear();\n this.#history.reset();\n }\n\n private change(action: (document: BlockDocument) => BlockDocument): boolean {\n if (!this.canWrite() || !this.commitText()) return false;\n const next = this.attempt(action);\n if (!next) return false;\n this.apply(next);\n return true;\n }\n\n /** The piece a command makes, or undefined (with the diagnostic) when it is refused. */\n private attempt(action: (document: BlockDocument) => BlockDocument): BlockDocument | undefined {\n try {\n return action(this.#document);\n } catch (error: unknown) {\n this.fail(error instanceof DocumentValidationError ? error.code : 'CHANGE_INVALID');\n return undefined;\n }\n }\n\n private apply(next: BlockDocument): void {\n if (next !== this.#document) this.commit(next.withRevision(this.#document.revision + 1), true);\n }\n\n private restore(direction: 'undo' | 'redo'): boolean {\n if (!this.canWrite() || !this.commitText()) return false;\n const previous = this.#history[direction]();\n if (!previous) return false;\n this.commit(previous.withRevision(this.#document.revision + 1), false);\n return true;\n }\n\n private commit(document: BlockDocument, history: boolean): void {\n if (history) this.#history.push(document);\n this.#document = document;\n this.#diagnostics = [];\n if (this.#selection && !document.find(this.#selection)) this.#selection = undefined;\n this.emit();\n }\n\n private textChanged(): boolean {\n return !!this.#text && this.#text.html !== this.#text.original;\n }\n\n private fail(code: string, messageKey = 'diagnostics.invalidChange'): false {\n this.#diagnostics = [{ code, messageKey, severity: 'error' }];\n this.emit();\n return false;\n }\n\n private canWrite(): boolean {\n this.assertActive();\n return !this.#readOnly;\n }\n\n private assertActive(): void {\n if (this.#disposed) throw new Error('SESSION_DISPOSED');\n }\n\n private emit(): void {\n if (this.#disposed || !this.#listeners.size) return;\n const state = this.getState();\n for (const listener of [...this.#listeners]) this.deliver(listener, state);\n }\n\n private deliver(listener: (state: BlockEditorState) => void, state: BlockEditorState): void {\n try {\n listener(state);\n } catch (error: unknown) {\n try {\n this.options.onObserverError?.(error);\n } catch {\n /* A failed observer cannot undo an accepted change. */\n }\n }\n }\n}\n","import type {\n Block,\n BlockDocument,\n BlockNodeType,\n BlockRules,\n BlockTarget,\n} from '../core/block-document';\n\nexport type BlockPlacement = 'before' | 'after' | 'inside';\n\n/** Where a block may land next to or inside one other block. */\nexport interface BlockPlacementTarget {\n readonly targetId: string;\n readonly placements: readonly BlockPlacement[];\n}\n\ninterface Located {\n readonly block: Block;\n readonly parent: Block | undefined;\n readonly siblings: readonly Block[];\n readonly index: number;\n}\n\n/**\n * Where a block may go, by the rules of the block types: the drop targets of a drag, of a block\n * from the palette and the single step of \"move up/down\". Nothing here changes the piece; the\n * aggregate checks every command again.\n */\nexport class BlockPlacementService {\n constructor(private readonly rules: BlockRules) {}\n\n /** Targets for an existing block: never inside itself, never leaving a parent too empty. */\n movementTargets(document: BlockDocument, id: string): readonly BlockPlacementTarget[] {\n const located = this.locate(document, id);\n if (!located) return [];\n const leaving = located.parent;\n if (leaving && located.siblings.length - 1 < this.rules.childCount(leaving.type).min) return [];\n return this.targets(document, located.block.type, located.block);\n }\n\n /** Targets for a new block of a type. */\n insertionTargets(document: BlockDocument, type: BlockNodeType): readonly BlockPlacementTarget[] {\n if (!this.rules.allows(type, document.kind)) return [];\n return this.targets(document, type, undefined);\n }\n\n /** The command target of a placement next to or inside a block. */\n target(targetId: string, placement: BlockPlacement): BlockTarget {\n return placement === 'inside'\n ? { position: 'inside', parentId: targetId }\n : { position: placement, id: targetId };\n }\n\n /**\n * One step up or down: past the sibling on that side, or, at the edge of its parent, into the\n * neighbouring container of the same type (the next column or section).\n */\n step(document: BlockDocument, id: string, direction: 'up' | 'down'): BlockTarget | undefined {\n const located = this.locate(document, id);\n if (!located) return undefined;\n const neighbour = located.siblings[located.index + (direction === 'up' ? -1 : 1)];\n if (neighbour)\n return direction === 'up'\n ? { position: 'before', id: neighbour.id }\n : { position: 'after', id: neighbour.id };\n const parent = located.parent;\n if (!parent) return undefined;\n if (located.siblings.length - 1 < this.rules.childCount(parent.type).min) return undefined;\n const outer = this.locate(document, parent.id);\n const container = outer?.siblings[outer.index + (direction === 'up' ? -1 : 1)];\n if (!container || !this.accepts(container, located.block.type)) return undefined;\n return {\n position: 'inside',\n parentId: container.id,\n index: direction === 'up' ? (container.children?.length ?? 0) : 0,\n };\n }\n\n private targets(\n document: BlockDocument,\n type: BlockNodeType,\n moving: Block | undefined,\n ): readonly BlockPlacementTarget[] {\n const result: BlockPlacementTarget[] = [];\n const visit = (blocks: readonly Block[], parent: Block | undefined): void => {\n const besides =\n parent === undefined\n ? this.rules.isRoot(type)\n : this.rules.childTypes(parent.type).includes(type) &&\n (blocks.includes(moving as Block) ||\n blocks.length < this.rules.childCount(parent.type).max);\n for (const block of blocks) {\n if (block === moving) continue;\n const placements: BlockPlacement[] = besides ? ['before', 'after'] : [];\n if (this.accepts(block, type) && !block.children?.includes(moving as Block))\n placements.push('inside');\n if (placements.length) result.push({ targetId: block.id, placements });\n visit(block.children ?? [], block);\n }\n };\n visit(document.blocks, undefined);\n return result;\n }\n\n private accepts(container: Block, type: BlockNodeType): boolean {\n return (\n this.rules.childTypes(container.type).includes(type) &&\n (container.children?.length ?? 0) < this.rules.childCount(container.type).max\n );\n }\n\n private locate(document: BlockDocument, id: string): Located | undefined {\n const stack: { blocks: readonly Block[]; parent: Block | undefined }[] = [\n { blocks: document.blocks, parent: undefined },\n ];\n while (stack.length) {\n const frame = stack.pop();\n if (!frame) break;\n for (let index = 0; index < frame.blocks.length; index++) {\n const block = frame.blocks[index];\n if (!block) continue;\n if (block.id === id) return { block, parent: frame.parent, siblings: frame.blocks, index };\n if (block.children) stack.push({ blocks: block.children, parent: block });\n }\n }\n return undefined;\n }\n}\n","import { parseFragment, serialize } from 'parse5';\nimport type { DefaultTreeAdapterMap } from 'parse5';\nimport { BlockDocumentError } from '../core/block-document';\nimport type { DocumentKind, DocumentNode, EditorDocumentData } from '../core/document';\nimport { isReservedAttribute } from '../core/canvas-contract';\nimport { HtmlDocumentCodec } from '../codecs/html';\nimport { CssDocumentCodec } from '../codecs/css';\nimport { ContentPolicy } from '../security/policy';\nimport { RichTextProjection } from '../security/rich-text-projection';\nimport { UrlPolicy } from '../security/url-policy';\nimport type { UrlPurpose } from '../security/url-policy';\nimport { sha256Base64 } from '../security/sha256';\nimport { RichTextMarkup } from '../core/rich-text-markup';\nimport type { RichTextMode } from '../core/rich-text-markup';\n\nconst HTML_LIMITS: Readonly<Record<DocumentKind, number>> = Object.freeze({\n // Kept under the compilation ceiling of a whole e-mail.\n email: 150_000,\n page: 500_000,\n});\nconst CACHE_SIZE = 2_000;\n/** `plaintext` swallows everything after it, closing tags included, in either kind. */\nconst PAGE_FORBIDDEN_TAGS: ReadonlySet<string> = new Set(['plaintext']);\n/** An e-mail also loses what redirects it and what renders markup as text. */\nconst EMAIL_FORBIDDEN_TAGS: ReadonlySet<string> = new Set([\n 'plaintext',\n 'xmp',\n 'listing',\n 'meta',\n 'base',\n]);\nconst CLASS_ATTRIBUTE = /class\\s*=\\s*[\"']?/gi;\nconst GENERATED_PREFIX = /\\bve-/i;\n\n/**\n * Whether markup kept as text (a comment, a conditional comment) writes a generated class,\n * `class=\"… ve-…\"`. Linear in the length of the text: each attribute value is read once up to\n * its closing quote or `>`, and a `class=` inside a value already read is skipped (a value it\n * starts has the same end, so it cannot hold a match the longer one did not).\n */\nfunction writesGeneratedClass(text: string): boolean {\n let scannedTo = 0;\n for (const match of text.matchAll(CLASS_ATTRIBUTE)) {\n const start = match.index + match[0].length;\n if (start < scannedTo) continue;\n let end = start;\n while (end < text.length) {\n const character = text[end];\n if (character === '\"' || character === \"'\" || character === '>') break;\n end++;\n }\n if (GENERATED_PREFIX.test(text.slice(start, end))) return true;\n scannedTo = end;\n }\n return false;\n}\nconst GOOGLE_FONTS_CSS = 'https://fonts.googleapis.com/';\nconst GOOGLE_FONTS_FILES = 'https://fonts.gstatic.com/';\n\n/**\n * The content rules of the texts, links and free HTML a block carries. A text is the rich\n * text projection the in-place editing protocol already transports: it is accepted only when\n * it is a fixed point of `RichTextProjection`, imports without any notice other than `info`,\n * is writable under `ContentPolicy.writable` and uses only the tags and attributes of its\n * mode. A free HTML block of an e-mail is refused when the e-mail rules would remove anything.\n */\nexport class BlockContentGuard {\n readonly #urls: UrlPolicy;\n readonly #policy: ContentPolicy;\n readonly #codec: HtmlDocumentCodec;\n readonly #css: CssDocumentCodec;\n readonly #projection: RichTextProjection;\n readonly #cache = new Map<string, boolean>();\n readonly #markup = new RichTextMarkup();\n\n constructor(urls = new UrlPolicy()) {\n this.#urls = urls;\n this.#css = new CssDocumentCodec(urls);\n this.#policy = new ContentPolicy(urls, this.#css);\n this.#codec = new HtmlDocumentCodec(this.#policy);\n this.#projection = new RichTextProjection(urls);\n }\n\n acceptsUrl(value: string, purpose: UrlPurpose): boolean {\n return this.#urls.isSafe(value, purpose);\n }\n\n /** The settled projection of a text; throws `INVALID_BLOCK_TEXT` when it has none. */\n normalizeText(value: string, mode: RichTextMode, kind: DocumentKind): string {\n void kind;\n try {\n const projected = this.#projection.project(value, mode === 'block').html;\n return mode === 'block' ? projected : this.flatten(projected, mode === 'button');\n } catch {\n throw new BlockDocumentError('INVALID_BLOCK_TEXT');\n }\n }\n\n acceptsText(value: string, mode: RichTextMode, kind: DocumentKind): boolean {\n if (value === '') return true;\n return this.cached(`t\\u0000${kind}\\u0000${mode}`, value, () => {\n let settled: string;\n try {\n settled = this.normalizeText(value, mode, kind);\n } catch {\n return false;\n }\n if (settled !== value) return false;\n const nodes = this.inspected(value, kind)?.nodes;\n return !!nodes && this.#policy.writable(nodes) && this.projectionNodes(nodes, mode);\n });\n }\n\n /** Balanced markup as the parser reads it back; nothing is removed here. */\n normalizeHtml(value: string): string {\n const imported = this.#codec.inspect({ html: value, css: '' }, 'page');\n if (!imported.document) throw new BlockDocumentError('INVALID_BLOCK_HTML');\n try {\n return this.#codec.export(imported.document).html;\n } catch {\n throw new BlockDocumentError('INVALID_BLOCK_HTML');\n }\n }\n\n acceptsHtml(value: string, kind: DocumentKind): boolean {\n if (value.length > HTML_LIMITS[kind]) return false;\n return this.cached(`h\\u0000${kind}`, value, () => {\n try {\n if (this.normalizeHtml(value) !== value) return false;\n } catch {\n return false;\n }\n // MJML ends a raw region at its closing tag wherever it appears, even in an attribute.\n if (kind === 'email' && /<\\/?mj-/i.test(value)) return false;\n // The canvas marks are the editor's: an author's copy would leak to the output and\n // could pose as another block in the preview.\n if (/data-visual-editor-/i.test(value)) return false;\n const document = this.inspected(value, kind);\n if (\n !document ||\n document.nodes.some(\n (node) => node.type === 'doctype' || ['html', 'head', 'body'].includes(node.tag ?? ''),\n )\n )\n return false;\n return this.authorElements(value, kind) && (kind === 'page' || this.emailResources(document));\n });\n }\n\n /**\n * Every element as a browser without scripting reads it (inside SVG, `noscript` and\n * `template` too): no generated class, no element which swallows the rest of the output\n * and, in an e-mail, nothing that redirects it or renders markup as text.\n */\n private authorElements(value: string, kind: DocumentKind): boolean {\n const forbidden = kind === 'email' ? EMAIL_FORBIDDEN_TAGS : PAGE_FORBIDDEN_TAGS;\n const stack: DefaultTreeAdapterMap['parentNode'][] = [\n parseFragment(value, { scriptingEnabled: false }),\n ];\n while (stack.length) {\n const parent = stack.pop();\n if (!parent) break;\n for (const child of parent.childNodes) {\n if ('data' in child && writesGeneratedClass(child.data)) return false;\n if (!('tagName' in child)) continue;\n if (forbidden.has(child.tagName)) return false;\n for (const attribute of child.attrs)\n if (\n isReservedAttribute(attribute.name) ||\n (attribute.name === 'class' &&\n attribute.value.split(/\\s+/).some((token) => token.toLowerCase().startsWith('ve-')))\n )\n return false;\n stack.push('content' in child ? child.content : child);\n }\n }\n return true;\n }\n\n /**\n * The only external style resources an e-mail may load are Google Fonts: style sheets from\n * `fonts.googleapis.com` and font files from `fonts.gstatic.com`.\n */\n private emailResources(document: EditorDocumentData): boolean {\n const inventory = this.#policy.inspect(document);\n if (inventory.metaRefresh || inventory.baseUrls.length) return false;\n if (!inventory.stylesheets.every((entry) => entry.url.startsWith(GOOGLE_FONTS_CSS)))\n return false;\n if (\n !inventory.links.every(\n (entry) =>\n entry.url.startsWith(GOOGLE_FONTS_CSS) || entry.url.startsWith(GOOGLE_FONTS_FILES),\n )\n )\n return false;\n const stack: DocumentNode[] = [...document.nodes];\n while (stack.length) {\n const node = stack.pop();\n if (!node) break;\n if (node.type === 'element' && node.tag === 'style') {\n const css = this.#css.inspect(\n (node.children ?? []).map((child) => child.value ?? '').join(''),\n );\n if (\n ![...css.urls, ...css.urlCandidates].every(\n (url) => url.startsWith(GOOGLE_FONTS_CSS) || url.startsWith(GOOGLE_FONTS_FILES),\n )\n )\n return false;\n }\n stack.push(...(node.children ?? []));\n }\n return true;\n }\n\n /** The document a fragment imports as, when the codec reads it with nothing but `info`. */\n private inspected(value: string, kind: DocumentKind): EditorDocumentData | undefined {\n const imported = this.#codec.inspect({ html: value, css: '' }, kind);\n if (!imported.document) return undefined;\n if (imported.diagnostics.some((item) => item.severity !== 'info')) return undefined;\n return imported.document;\n }\n\n private projectionNodes(nodes: readonly DocumentNode[], mode: RichTextMode): boolean {\n return (\n this.#markup.violation(nodes, mode, {\n style: (value) => !!this.#css.richTextStyles(value),\n }) === undefined\n );\n }\n\n /**\n * One line: paragraphs become line breaks and, for a button, links become their text. The\n * result is projected again, so it is a fixed point.\n */\n private flatten(html: string, dropLinks: boolean): string {\n const fragment = parseFragment(html);\n if (dropLinks) this.unwrapLinks(fragment);\n const lines: DefaultTreeAdapterMap['childNode'][][] = [];\n let current: DefaultTreeAdapterMap['childNode'][] = [];\n for (const node of fragment.childNodes) {\n if ('tagName' in node && node.tagName === 'p') {\n if (current.length) lines.push(current);\n lines.push([...node.childNodes]);\n current = [];\n } else current.push(node);\n }\n if (current.length) lines.push(current);\n const render = (nodes: readonly DefaultTreeAdapterMap['childNode'][]): string => {\n const holder = parseFragment('');\n holder.childNodes.push(...nodes);\n return serialize(holder);\n };\n const flat = lines\n .map(render)\n .filter((line) => line !== '')\n .join('<br>');\n return this.#projection.project(flat, false).html;\n }\n\n private unwrapLinks(parent: DefaultTreeAdapterMap['parentNode']): void {\n const children: DefaultTreeAdapterMap['childNode'][] = [];\n for (const child of parent.childNodes) {\n if (!('tagName' in child)) {\n children.push(child);\n continue;\n }\n this.unwrapLinks(child);\n if (child.tagName === 'a') children.push(...child.childNodes);\n else children.push(child);\n }\n parent.childNodes = children;\n }\n\n /**\n * Results by kind, mode and SHA-256 of the value: the cache keeps 2.000 short keys, never\n * the texts themselves (an HTML block may have hundreds of kilobytes).\n */\n private cached(scope: string, value: string, compute: () => boolean): boolean {\n const key = `${scope}\\u0000${sha256Base64(value)}`;\n const known = this.#cache.get(key);\n if (known !== undefined) {\n this.#cache.delete(key);\n this.#cache.set(key, known);\n return known;\n }\n const result = compute();\n this.#cache.set(key, result);\n if (this.#cache.size > CACHE_SIZE) {\n const oldest = this.#cache.keys().next().value;\n if (oldest !== undefined) this.#cache.delete(oldest);\n }\n return result;\n }\n\n /** Entries currently held and the characters of their keys, for the bound on memory. */\n cacheFootprint(): { readonly entries: number; readonly keyCharacters: number } {\n let keyCharacters = 0;\n for (const key of this.#cache.keys()) keyCharacters += key.length;\n return { entries: this.#cache.size, keyCharacters };\n }\n}\n","import type { Block, BlockPropValue } from '../core/block-document';\nimport type { DocumentKind } from '../core/document';\nimport { EDIT_NODE_ATTRIBUTE, NODE_ATTRIBUTE } from '../core/canvas-contract';\nimport { escapeHtml } from '../core/html-escape';\nimport type {\n BlockTypeDefinition,\n EmailBlockContext,\n OutputMode,\n PageBlockContext,\n} from './block-type';\nimport type { StyleResolver } from './styles';\n\n/**\n * Class of a block in the page output: `ve-b-<id>`. The prefix keeps it apart from the\n * structural classes (`ve-page`, `ve-section`, `ve-button`...) whatever the id is.\n */\nexport function blockClass(block: Block): string {\n return `ve-b-${block.id}`;\n}\n\n/**\n * Class of a block in an e-mail preview: `ve-p-<token>-<id>`, with a token drawn for each\n * rendering, so markup of the author can never pose as a block for the marker.\n */\nexport function previewClass(token: string, block: Block): string {\n return `ve-p-${token}-${block.id}`;\n}\n\n/** Classes of a block hidden on a screen; the generators write what each one does. */\nexport const HIDE_DESKTOP_CLASS = 've-hide-d';\nexport const HIDE_MOBILE_CLASS = 've-hide-m';\n\n/** Class of the cell of an e-mail block with mobile values: `ve-m-<id>`. */\nexport function mobileClass(block: Block): string {\n return `ve-m-${block.id}`;\n}\n\n/** The visibility classes of a block, in a fixed order. */\nexport function visibilityClasses(block: Block): readonly string[] {\n return [\n ...(block.props.hideOnDesktop === true ? [HIDE_DESKTOP_CLASS] : []),\n ...(block.props.hideOnMobile === true ? [HIDE_MOBILE_CLASS] : []),\n ];\n}\n\n/** Shared reading of values: own, else inherited, else the field default. */\nabstract class BaseContext {\n constructor(\n readonly block: Block,\n readonly definition: BlockTypeDefinition,\n readonly kind: DocumentKind,\n readonly mode: OutputMode,\n readonly styles: StyleResolver,\n private readonly renderChildren: (reverse: boolean) => string,\n ) {}\n\n value(key: string): BlockPropValue | undefined {\n const own = this.block.props[key];\n if (own !== undefined) return own;\n const field = this.definition.fields.find((entry) => entry.key === key);\n if (field?.inherits) return this.styles.value(field.inherits);\n return field?.defaultValue;\n }\n\n children(reverse = false): string {\n return this.renderChildren(reverse);\n }\n}\n\nexport class EmailRenderContext extends BaseContext implements EmailBlockContext {\n constructor(\n block: Block,\n definition: BlockTypeDefinition,\n mode: OutputMode,\n styles: StyleResolver,\n renderChildren: (reverse: boolean) => string,\n private readonly fragments: string[],\n private readonly token: string,\n readonly columnWidth?: string,\n /** Whether the generator wrote mobile rules for the cell of this block. */\n private readonly mobile = false,\n ) {\n super(block, definition, 'email', mode, styles, renderChildren);\n }\n\n attributes(extra: Readonly<Record<string, string | undefined>> = {}): string {\n const pairs: [string, string][] = [];\n for (const field of this.definition.fields) {\n const own = this.block.props[field.key];\n if (!field.mjml || own === undefined) continue;\n const value = field.mjml.map ? field.mjml.map[String(own)] : String(own);\n if (value !== undefined) pairs.push([field.mjml.attribute, value]);\n }\n for (const [name, value] of Object.entries(extra))\n if (value !== undefined) pairs.push([name, value]);\n const cellClass = this.cellClass();\n if (cellClass) pairs.push(['css-class', cellClass]);\n return pairs.map(([name, value]) => ` ${name}=\"${escapeHtml(value)}\"`).join('');\n }\n\n cellClass(): string | undefined {\n const preview = this.previewClass();\n const classes = [\n ...(preview ? [preview] : []),\n ...visibilityClasses(this.block),\n ...(this.mobile ? [mobileClass(this.block)] : []),\n ];\n return classes.length ? classes.join(' ') : undefined;\n }\n\n raw(fragment: string): string {\n this.fragments.push(fragment);\n return `<mj-raw>${fragment}</mj-raw>`;\n }\n\n previewClass(): string | undefined {\n return this.mode === 'preview' ? previewClass(this.token, this.block) : undefined;\n }\n}\n\nexport class PageRenderContext extends BaseContext implements PageBlockContext {\n constructor(\n block: Block,\n definition: BlockTypeDefinition,\n mode: OutputMode,\n styles: StyleResolver,\n renderChildren: (reverse: boolean) => string,\n private readonly rules: string[],\n private readonly mobileRules: string[] = [],\n ) {\n super(block, definition, 'page', mode, styles, renderChildren);\n }\n\n classes(base: string): string {\n return ` class=\"${[base, blockClass(this.block), ...visibilityClasses(this.block)].join(' ')}\"`;\n }\n\n node(): string {\n return this.mode === 'preview' ? ` ${NODE_ATTRIBUTE}=\"${this.block.id}\"` : '';\n }\n\n editable(): string {\n return this.mode === 'preview' ? ` ${EDIT_NODE_ATTRIBUTE}=\"${this.block.id}\"` : '';\n }\n\n rule(selectorSuffix: string, declarations: string): void {\n this.rules.push(`.${blockClass(this.block)}${selectorSuffix}{${declarations}}`);\n }\n\n mobileRule(selectorSuffix: string, declarations: string): void {\n this.mobileRules.push(`.${blockClass(this.block)}${selectorSuffix}{${declarations}}`);\n }\n}\n","import type { BlockPropValue, StyleValue } from '../core/block-document';\nimport type { DocumentKind } from '../core/document';\nimport type { UrlPurpose } from '../security/url-policy';\nimport type { BlockContentGuard } from './content-guard';\nimport type { RichTextMode } from '../core/rich-text-markup';\n\n/** The kind of value a property or a global style holds, and what it may contain. */\nexport type ValueSpec =\n | { readonly type: 'color' }\n | { readonly type: 'length'; readonly units: readonly ('px' | '%')[]; readonly max: number }\n | { readonly type: 'box' }\n | { readonly type: 'fontFamily' }\n | { readonly type: 'ratio' }\n | { readonly type: 'select'; readonly options: readonly string[] }\n | { readonly type: 'integer'; readonly min: number; readonly max: number }\n | { readonly type: 'toggle' }\n | { readonly type: 'plain'; readonly max: number; readonly pattern?: RegExp }\n | { readonly type: 'url'; readonly purpose: UrlPurpose }\n | { readonly type: 'richtext'; readonly mode: RichTextMode }\n | { readonly type: 'html' };\n\n/** The font stacks a piece may use: written as they are into CSS and MJML, never typed. */\nexport const FONT_STACKS = [\n { value: 'Arial, Helvetica, sans-serif', labelKey: 'properties.fontSans' },\n { value: 'Georgia, Times New Roman, serif', labelKey: 'properties.fontSerif' },\n { value: 'Courier New, Courier, monospace', labelKey: 'properties.fontMonospace' },\n] as const;\n\nconst COLOR =\n /^(#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|transparent|rgba?\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*(,\\s*(0|1|0?\\.\\d{1,4})\\s*)?\\))$/;\nconst LENGTH = /^(0|\\d{1,4}(\\.\\d{1,2})?)(px|%)?$/;\nconst BOX_PART = /^(0|\\d{1,3})(px)?$/;\nconst RATIO = /^\\d(\\.\\d{1,3})?$/;\nconst URL_LENGTH = 16_384;\nconst TEXT_LENGTH = 100_000;\n\n/**\n * Every value that reaches CSS, an MJML attribute or a URL passes one of these patterns: they\n * have no quote, semicolon, brace or angle bracket, so a value can never end the declaration\n * or the attribute it is written into.\n */\nexport class ValueRules {\n constructor(private readonly content: BlockContentGuard) {}\n\n accepts(spec: ValueSpec, value: BlockPropValue | StyleValue, kind: DocumentKind): boolean {\n switch (spec.type) {\n case 'toggle':\n return typeof value === 'boolean';\n case 'integer':\n return (\n typeof value === 'number' &&\n Number.isInteger(value) &&\n value >= spec.min &&\n value <= spec.max\n );\n default:\n break;\n }\n if (typeof value !== 'string') return false;\n switch (spec.type) {\n case 'color':\n return COLOR.test(value);\n case 'length':\n return this.length(value, spec.units, spec.max);\n case 'box': {\n const parts = value.split(' ');\n return parts.length >= 1 && parts.length <= 4 && parts.every((part) => BOX_PART.test(part));\n }\n case 'fontFamily':\n return FONT_STACKS.some((stack) => stack.value === value);\n case 'ratio':\n return RATIO.test(value) && Number(value) > 0;\n case 'select':\n return spec.options.includes(value);\n case 'plain':\n return (\n value.length <= spec.max &&\n ![...value].some((character) => character.charCodeAt(0) < 32) &&\n (!spec.pattern || spec.pattern.test(value))\n );\n case 'url':\n return (\n value.trim().length > 0 &&\n value.length <= URL_LENGTH &&\n this.content.acceptsUrl(value, spec.purpose)\n );\n case 'richtext':\n return value.length <= TEXT_LENGTH && this.content.acceptsText(value, spec.mode, kind);\n case 'html':\n return this.content.acceptsHtml(value, kind);\n }\n }\n\n /** What a command stores: texts and HTML in their settled form, other values as given. */\n normalize(\n spec: ValueSpec,\n value: BlockPropValue | StyleValue,\n kind: DocumentKind,\n ): BlockPropValue | undefined {\n let candidate: BlockPropValue = value;\n if (typeof value === 'string') {\n if (spec.type === 'richtext') candidate = this.content.normalizeText(value, spec.mode, kind);\n else if (spec.type === 'html') candidate = this.content.normalizeHtml(value);\n else if (spec.type !== 'plain') candidate = value.trim();\n }\n return this.accepts(spec, candidate, kind) ? candidate : undefined;\n }\n\n private length(value: string, units: readonly ('px' | '%')[], max: number): boolean {\n const match = LENGTH.exec(value);\n if (!match) return false;\n const unit = match[3] as 'px' | '%' | undefined;\n if (unit === undefined) return value === '0';\n return units.includes(unit) && Number(match[1]) <= max;\n }\n}\n","import type { GlobalStyles, StyleValue } from '../core/block-document';\nimport type { DocumentKind } from '../core/document';\nimport { FONT_STACKS } from './values';\nimport type { ValueSpec } from './values';\n\n/** An MJML component, or a named `mj-class`, whose attribute carries a global style. */\nexport interface MjmlTarget {\n readonly element: 'mj-all' | 'mj-text' | 'mj-button' | 'mj-divider' | 'mj-section';\n readonly mjClass?: string;\n readonly attribute: string;\n}\n\nexport interface StyleKeySpec {\n readonly key: string;\n readonly labelKey: string;\n readonly control: 'color' | 'length' | 'select';\n readonly value: ValueSpec;\n readonly default: string | Readonly<Record<DocumentKind, string>>;\n readonly options?: readonly { readonly value: string; readonly labelKey: string }[];\n /** Where an e-mail carries it in `<mj-attributes>`; absent for page-only styles. */\n readonly mjml?: readonly MjmlTarget[];\n readonly kinds?: readonly DocumentKind[];\n}\n\nexport interface StyleGroupSpec {\n readonly group: string;\n readonly labelKey: string;\n readonly keys: readonly StyleKeySpec[];\n}\n\n/** `group.key` of a global style, the path a block field inherits from. */\nexport type StylePath = `${string}.${string}`;\n\nconst color: ValueSpec = { type: 'color' };\nconst pixels = (max: number): ValueSpec => ({ type: 'length', units: ['px'], max });\nconst fontWeights = [\n { value: '400', labelKey: 'properties.weightNormal' },\n { value: '500', labelKey: 'properties.weightMedium' },\n { value: '600', labelKey: 'properties.weightSemibold' },\n { value: '700', labelKey: 'properties.weightBold' },\n] as const;\nconst weight: ValueSpec = { type: 'select', options: fontWeights.map((entry) => entry.value) };\nconst fontFamily: ValueSpec = { type: 'fontFamily' };\n\n/**\n * The global styles of a piece and their catalog defaults. A piece stores only what differs;\n * \"restore default\" removes the key. Labels are keys of the package catalogs.\n */\nexport const GLOBAL_STYLE_GROUPS: readonly StyleGroupSpec[] = Object.freeze([\n {\n group: 'body',\n labelKey: 'blockStyles.body',\n keys: [\n {\n key: 'background',\n labelKey: 'blockStyles.pageBackground',\n control: 'color',\n value: color,\n default: '#f3f7f6',\n },\n {\n key: 'contentBackground',\n labelKey: 'blockStyles.contentBackground',\n control: 'color',\n value: color,\n default: '#ffffff',\n mjml: [{ element: 'mj-section', attribute: 'background-color' }],\n },\n {\n key: 'width',\n labelKey: 'blockStyles.contentWidth',\n control: 'length',\n value: pixels(1_600),\n default: { email: '600px', page: '1120px' },\n },\n {\n key: 'fontFamily',\n labelKey: 'properties.fontFamily',\n control: 'select',\n value: fontFamily,\n default: 'Arial, Helvetica, sans-serif',\n options: FONT_STACKS,\n mjml: [{ element: 'mj-all', attribute: 'font-family' }],\n },\n {\n key: 'textColor',\n labelKey: 'properties.color',\n control: 'color',\n value: color,\n default: '#243746',\n mjml: [{ element: 'mj-text', attribute: 'color' }],\n },\n {\n key: 'fontSize',\n labelKey: 'properties.fontSize',\n control: 'length',\n value: pixels(96),\n default: '16px',\n mjml: [{ element: 'mj-text', attribute: 'font-size' }],\n },\n {\n key: 'lineHeight',\n labelKey: 'properties.lineHeight',\n control: 'length',\n value: { type: 'ratio' },\n default: '1.65',\n mjml: [{ element: 'mj-text', attribute: 'line-height' }],\n },\n {\n key: 'linkColor',\n labelKey: 'blockStyles.linkColor',\n control: 'color',\n value: color,\n default: '#0d766e',\n },\n ],\n },\n {\n group: 'heading',\n labelKey: 'blockStyles.heading',\n keys: [\n {\n key: 'fontFamily',\n labelKey: 'properties.fontFamily',\n control: 'select',\n value: fontFamily,\n default: 'Arial, Helvetica, sans-serif',\n options: FONT_STACKS,\n mjml: [{ element: 'mj-text', mjClass: 've-heading', attribute: 'font-family' }],\n },\n {\n key: 'color',\n labelKey: 'properties.color',\n control: 'color',\n value: color,\n default: '#10302c',\n mjml: [{ element: 'mj-text', mjClass: 've-heading', attribute: 'color' }],\n },\n {\n key: 'fontSize',\n labelKey: 'properties.fontSize',\n control: 'length',\n value: pixels(160),\n default: '28px',\n mjml: [{ element: 'mj-text', mjClass: 've-heading', attribute: 'font-size' }],\n },\n {\n key: 'fontWeight',\n labelKey: 'properties.fontWeight',\n control: 'select',\n value: weight,\n default: '700',\n options: fontWeights,\n mjml: [{ element: 'mj-text', mjClass: 've-heading', attribute: 'font-weight' }],\n },\n {\n key: 'lineHeight',\n labelKey: 'properties.lineHeight',\n control: 'length',\n value: { type: 'ratio' },\n default: '1.25',\n mjml: [{ element: 'mj-text', mjClass: 've-heading', attribute: 'line-height' }],\n },\n ],\n },\n {\n group: 'button',\n labelKey: 'blockStyles.button',\n keys: [\n {\n key: 'background',\n labelKey: 'properties.background',\n control: 'color',\n value: color,\n default: '#0d766e',\n mjml: [{ element: 'mj-button', attribute: 'background-color' }],\n },\n {\n key: 'color',\n labelKey: 'properties.color',\n control: 'color',\n value: color,\n default: '#ffffff',\n mjml: [{ element: 'mj-button', attribute: 'color' }],\n },\n {\n key: 'radius',\n labelKey: 'properties.borderRadius',\n control: 'length',\n value: pixels(64),\n default: '8px',\n mjml: [{ element: 'mj-button', attribute: 'border-radius' }],\n },\n {\n key: 'fontSize',\n labelKey: 'properties.fontSize',\n control: 'length',\n value: pixels(64),\n default: '16px',\n mjml: [{ element: 'mj-button', attribute: 'font-size' }],\n },\n {\n key: 'fontWeight',\n labelKey: 'properties.fontWeight',\n control: 'select',\n value: weight,\n default: '600',\n options: fontWeights,\n mjml: [{ element: 'mj-button', attribute: 'font-weight' }],\n },\n {\n key: 'padding',\n labelKey: 'properties.padding',\n control: 'length',\n value: { type: 'box' },\n default: '12px 24px',\n mjml: [{ element: 'mj-button', attribute: 'inner-padding' }],\n },\n ],\n },\n {\n group: 'divider',\n labelKey: 'blocks.divider',\n keys: [\n {\n key: 'color',\n labelKey: 'properties.borderColor',\n control: 'color',\n value: color,\n default: '#dce4e7',\n mjml: [{ element: 'mj-divider', attribute: 'border-color' }],\n },\n {\n key: 'width',\n labelKey: 'properties.borderWidth',\n control: 'length',\n value: pixels(16),\n default: '1px',\n mjml: [{ element: 'mj-divider', attribute: 'border-width' }],\n },\n ],\n },\n {\n group: 'footer',\n labelKey: 'blocks.footer',\n keys: [\n {\n key: 'color',\n labelKey: 'properties.color',\n control: 'color',\n value: color,\n default: '#536674',\n mjml: [{ element: 'mj-text', mjClass: 've-footer', attribute: 'color' }],\n },\n {\n key: 'fontSize',\n labelKey: 'properties.fontSize',\n control: 'length',\n value: pixels(48),\n default: '12px',\n mjml: [{ element: 'mj-text', mjClass: 've-footer', attribute: 'font-size' }],\n },\n ],\n },\n {\n group: 'section',\n labelKey: 'blocks.section',\n keys: [\n {\n key: 'padding',\n labelKey: 'properties.padding',\n control: 'length',\n value: { type: 'box' },\n default: '24px 0',\n mjml: [{ element: 'mj-section', attribute: 'padding' }],\n },\n {\n key: 'columnGap',\n labelKey: 'properties.columnGap',\n control: 'length',\n value: pixels(160),\n default: '24px',\n kinds: ['page'],\n },\n ],\n },\n]);\n\nexport class GlobalStyleSpec {\n readonly #keys = new Map<StylePath, StyleKeySpec>();\n\n constructor(readonly groups: readonly StyleGroupSpec[] = GLOBAL_STYLE_GROUPS) {\n for (const group of groups)\n for (const key of group.keys) this.#keys.set(`${group.group}.${key.key}`, key);\n }\n\n key(group: string, key: string): StyleKeySpec | undefined {\n return this.#keys.get(`${group}.${key}`);\n }\n\n has(path: string): path is StylePath {\n return this.#keys.has(path as StylePath);\n }\n\n paths(): readonly StylePath[] {\n return [...this.#keys.keys()];\n }\n\n defaultOf(path: StylePath, kind: DocumentKind): string {\n const spec = this.#keys.get(path);\n if (!spec) throw new Error('UNKNOWN_STYLE');\n return typeof spec.default === 'string' ? spec.default : spec.default[kind];\n }\n}\n\n/** The effective value of every global style: the piece's override, or the catalog default. */\nexport class StyleResolver {\n constructor(\n private readonly spec: GlobalStyleSpec,\n private readonly styles: GlobalStyles,\n private readonly kind: DocumentKind,\n ) {}\n\n value(path: StylePath): string {\n const [group = '', key = ''] = path.split('.');\n const own: StyleValue | undefined = this.styles[group]?.[key];\n return own !== undefined ? String(own) : this.spec.defaultOf(path, this.kind);\n }\n\n /** Whether the piece overrides this style; false means the catalog default applies. */\n overridden(path: StylePath): boolean {\n const [group = '', key = ''] = path.split('.');\n return this.styles[group]?.[key] !== undefined;\n }\n}\n","import type { BlockField, FieldOption } from './block-type';\nimport type { StylePath } from './styles';\nimport type { RichTextMode } from '../core/rich-text-markup';\n\n/** Builders of the fields several block types share. Defaults follow MJML's own. */\nexport const ALIGN_OPTIONS: readonly FieldOption[] = Object.freeze([\n { value: 'left', labelKey: 'properties.alignLeft' },\n { value: 'center', labelKey: 'properties.alignCenter' },\n { value: 'right', labelKey: 'properties.alignRight' },\n]);\n\nexport const BLOCK_PADDING = '10px 25px';\n\n/** The two visibility toggles every block but a column has. */\nexport const DEVICE_KEYS = ['hideOnDesktop', 'hideOnMobile'] as const;\n\n/** E-mail mobile rules shared by the text blocks: the cell and the text inside it. */\nexport const TEXT_MOBILE_EMAIL = Object.freeze({\n fontSize: { selectors: ['>div'] },\n lineHeight: { selectors: ['>div'] },\n align: { selectors: ['>div'] },\n padding: { selectors: [''] },\n});\n\nexport const fields = Object.freeze({\n text(mode: RichTextMode): BlockField {\n return {\n key: 'text',\n tab: 'content',\n control: 'richtext',\n labelKey: 'properties.text',\n value: { type: 'richtext', mode },\n defaultValue: '',\n };\n },\n color(key: string, labelKey: string, inherits?: StylePath, target?: 'inner'): BlockField {\n return {\n key,\n tab: 'style',\n control: 'color',\n labelKey,\n value: { type: 'color' },\n ...(inherits ? { inherits } : {}),\n mjml: { attribute: key === 'background' ? 'background-color' : 'color' },\n css: {\n property: key === 'background' ? 'background-color' : 'color',\n ...(target ? { target } : {}),\n },\n };\n },\n fontSize(inherits: StylePath, target?: 'inner'): BlockField {\n return {\n key: 'fontSize',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.fontSize',\n value: { type: 'length', units: ['px'], max: 160 },\n inherits,\n responsive: true,\n mjml: { attribute: 'font-size' },\n css: { property: 'font-size', ...(target ? { target } : {}) },\n };\n },\n lineHeight(inherits: StylePath): BlockField {\n return {\n key: 'lineHeight',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.lineHeight',\n value: { type: 'ratio' },\n inherits,\n responsive: true,\n mjml: { attribute: 'line-height' },\n css: { property: 'line-height' },\n };\n },\n align(defaultValue: 'left' | 'center' | 'right', property = 'text-align'): BlockField {\n return {\n key: 'align',\n tab: 'style',\n control: 'select',\n labelKey: 'properties.textAlign',\n value: { type: 'select', options: ALIGN_OPTIONS.map((option) => option.value) },\n options: ALIGN_OPTIONS,\n defaultValue,\n responsive: true,\n mjml: { attribute: 'align' },\n css: { property },\n };\n },\n padding(defaultValue = BLOCK_PADDING, inherits?: StylePath): BlockField {\n return {\n key: 'padding',\n tab: 'advanced',\n control: 'length',\n labelKey: 'properties.padding',\n value: { type: 'box' },\n ...(inherits ? { inherits } : { defaultValue }),\n responsive: true,\n mjml: { attribute: 'padding' },\n css: { property: 'padding' },\n };\n },\n /** Hide the block on large or on small screens. The generators read them, not `css`. */\n visibility(): readonly BlockField[] {\n return DEVICE_KEYS.map((key) => ({\n key,\n tab: 'advanced' as const,\n control: 'toggle' as const,\n labelKey: `blockFields.${key}`,\n value: { type: 'toggle' as const },\n defaultValue: false,\n }));\n },\n link(key = 'href'): BlockField {\n return {\n key,\n tab: 'content',\n control: 'link',\n labelKey: 'properties.link',\n value: { type: 'url', purpose: 'link' },\n };\n },\n});\n","import type { Block, BlockNodeType, BlockProps } from '../../core/block-document';\nimport { SECTION_LAYOUT_LIMITS } from '../../core/section-layout';\nimport type {\n BlockField,\n BlockTypeDefinition,\n EmailBlockContext,\n PageBlockContext,\n} from '../block-type';\nimport { fields } from '../fields';\n\n/** Content blocks a column holds. A form only exists in a page (checked by its definition). */\nexport const COLUMN_CONTENT: readonly BlockNodeType[] = Object.freeze([\n 'text',\n 'heading',\n 'image',\n 'button',\n 'divider',\n 'spacer',\n 'footer',\n 'form',\n 'html',\n]);\n\n/** Weight of a column within its section; the shares are the weights over their sum. */\nexport function columnWeight(block: Block): number {\n const weight = block.props.weight;\n return typeof weight === 'number' ? weight : 1;\n}\n\n/** A band of the piece: one to four real columns, side by side, stacked on small screens. */\nexport class SectionBlock implements BlockTypeDefinition {\n readonly type = 'section';\n readonly labelKey = 'blocks.section';\n readonly kinds = ['email', 'page'] as const;\n readonly root = true;\n readonly childTypes: readonly BlockNodeType[] = ['column'];\n readonly childCount = { min: 1, max: SECTION_LAYOUT_LIMITS.columns };\n readonly fields: readonly BlockField[] = [\n fields.color('background', 'properties.background', 'body.contentBackground'),\n fields.padding(undefined, 'section.padding'),\n {\n key: 'stackReverse',\n tab: 'advanced',\n control: 'toggle',\n labelKey: 'blockFields.stackReverse',\n value: { type: 'toggle' },\n defaultValue: false,\n },\n ...fields.visibility(),\n ];\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return {\n id: nextId(),\n type: 'section',\n props,\n children: [new ColumnBlock().create(nextId)],\n };\n }\n\n /**\n * Reversed stacking: the columns are written in reverse order and the section lays them out\n * right to left, so a large screen shows them as authored and a small one stacks them from\n * the last. MJML keeps the text of each column left to right.\n */\n email(context: EmailBlockContext): string {\n const reverse = context.value('stackReverse') === true;\n return `<mj-section${context.attributes(reverse ? { direction: 'rtl' } : {})}>${context.children(reverse)}</mj-section>`;\n }\n\n page(context: PageBlockContext): string {\n const columns = (context.block.children ?? []).map(columnWeight);\n if (columns.length > 1)\n context.rule(\n ' > .ve-columns',\n `grid-template-columns:${columns.map((weight) => `minmax(0,${weight}fr)`).join(' ')}`,\n );\n if (columns.length > 1 && context.value('stackReverse') === true)\n context.mobileRule(' > .ve-columns', 'display:flex;flex-direction:column-reverse');\n return `<section${context.classes('ve-section')}${context.node()}><div class=\"ve-columns\">${context.children()}</div></section>`;\n }\n}\n\nexport class ColumnBlock implements BlockTypeDefinition {\n readonly type = 'column';\n readonly labelKey = 'blocks.column';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = COLUMN_CONTENT;\n readonly childCount = { min: 0, max: 200 };\n readonly fields: readonly BlockField[] = [\n {\n key: 'weight',\n tab: 'style',\n control: 'select',\n labelKey: 'blockFields.columnWeight',\n value: { type: 'integer', min: 1, max: SECTION_LAYOUT_LIMITS.weight },\n defaultValue: 1,\n internal: true,\n },\n fields.color('background', 'properties.background'),\n {\n key: 'verticalAlign',\n tab: 'style',\n control: 'select',\n labelKey: 'blockFields.verticalAlign',\n value: { type: 'select', options: ['top', 'middle', 'bottom'] },\n options: [\n { value: 'top', labelKey: 'properties.alignStart' },\n { value: 'middle', labelKey: 'properties.alignCenter' },\n { value: 'bottom', labelKey: 'properties.alignEnd' },\n ],\n defaultValue: 'top',\n mjml: { attribute: 'vertical-align' },\n css: { property: 'align-self', map: { top: 'start', middle: 'center', bottom: 'end' } },\n },\n fields.padding('0'),\n ];\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'column', props, children: [] };\n }\n\n email(context: EmailBlockContext): string {\n return `<mj-column${context.attributes({ width: context.columnWidth })}>${context.children()}</mj-column>`;\n }\n\n page(context: PageBlockContext): string {\n return `<div${context.classes('ve-column')}${context.node()}>${context.children()}</div>`;\n }\n}\n","import type { Block, BlockPropValue } from '../core/block-document';\nimport type { BlockField, BlockTypeDefinition, OutputMode } from './block-type';\nimport { HIDE_DESKTOP_CLASS, HIDE_MOBILE_CLASS, blockClass, mobileClass } from './render-context';\n\n/** Which device classes a piece uses, so the generators write only the rules it needs. */\nexport interface DeviceUsage {\n hideDesktop: boolean;\n hideMobile: boolean;\n}\n\n/**\n * How a block hidden on the screen being edited looks in the editing frame: still there, so it\n * can be selected, but faded and outlined. The published piece hides it.\n */\nconst FADED = 'opacity:.35;outline:2px dashed #94a3b8;outline-offset:-2px';\n\n/**\n * A CSS value written from a block value. The values were already checked by their field\n * (lengths, colors, choices); this refuses anything that could close the declaration anyway.\n */\nexport function cssValue(field: BlockField, value: BlockPropValue): string | undefined {\n const mapped = field.css?.map ? field.css.map[String(value)] : String(value);\n if (mapped === undefined || mapped === '' || /[;{}<>\\\\]|\\/\\*/.test(mapped)) return undefined;\n return mapped;\n}\n\n/**\n * The device rules of a block piece: values of small screens and blocks hidden on one screen.\n * Pages write them as CSS on the classes of the blocks; e-mails as `mj-style`, where hiding on\n * large screens is inlined (Outlook for Windows reads no media rule) and every small-screen\n * rule sits in a media rule with `!important`, which wins over the inline styles of MJML.\n */\nexport class BlockDeviceStyles {\n constructor(private readonly breakpoint: number) {}\n\n usage(block: Block, usage: DeviceUsage): void {\n if (block.props.hideOnDesktop === true) usage.hideDesktop = true;\n if (block.props.hideOnMobile === true) usage.hideMobile = true;\n }\n\n /** Mobile rules of the cell `.ve-m-<id>` of an e-mail block; empty when it has none. */\n emailRules(block: Block, definition: BlockTypeDefinition): readonly string[] {\n const rules: string[] = [];\n for (const [key, value] of Object.entries(block.mobile ?? {})) {\n const rule = definition.mobileEmail?.[key];\n const field = definition.fields.find((entry) => entry.key === key);\n if (!rule || !field?.responsive) continue;\n const css = cssValue(field, value);\n const properties = rule.properties ?? (field.css ? [field.css.property] : []);\n if (css === undefined || !properties.length) continue;\n const declarations = properties.map((property) => `${property}:${css}!important`).join(';');\n const selectors = rule.selectors.map((suffix) => `.${mobileClass(block)}${suffix}`).join(',');\n rules.push(`${selectors}{${declarations}}`);\n }\n return rules;\n }\n\n /** Mobile rules of `.ve-b-<id>` (and its inner element) of a page block. */\n pageRules(block: Block, definition: BlockTypeDefinition): readonly string[] {\n const self: string[] = [];\n const inner: string[] = [];\n for (const [key, value] of Object.entries(block.mobile ?? {})) {\n const field = definition.fields.find((entry) => entry.key === key);\n if (!field?.responsive || !field.css) continue;\n const css = cssValue(field, value);\n if (css === undefined) continue;\n (field.css.target === 'inner' ? inner : self).push(`${field.css.property}:${css}`);\n }\n const selector = `.${blockClass(block)}`;\n return [\n ...(self.length ? [`${selector}{${self.join(';')}}`] : []),\n ...(inner.length && definition.innerSelector\n ? [`${selector} ${definition.innerSelector}{${inner.join(';')}}`]\n : []),\n ];\n }\n\n /** The `mj-style` elements of an e-mail; empty when the piece has no device rule. */\n emailHead(mode: OutputMode, usage: DeviceUsage, mobile: readonly string[]): string {\n const small = `@media only screen and (max-width:${this.breakpoint}px)`;\n const large = `@media only screen and (min-width:${this.breakpoint + 1}px)`;\n const desktop = `.${HIDE_DESKTOP_CLASS}`;\n const phone = `.${HIDE_MOBILE_CLASS}`;\n let inline = '';\n const rules: string[] = [];\n if (mode === 'preview') {\n if (usage.hideDesktop) rules.push(`${large}{${desktop}{${FADED}}}`);\n if (usage.hideMobile || mobile.length)\n rules.push(`${small}{${usage.hideMobile ? `${phone}{${FADED}}` : ''}${mobile.join('')}}`);\n } else {\n if (usage.hideDesktop)\n inline = `<mj-style inline=\"inline\">${desktop}{display:none;mso-hide:all;max-height:0;overflow:hidden}</mj-style>`;\n const shown = usage.hideDesktop\n ? `div${desktop}{display:block!important;max-height:none!important;overflow:visible!important}` +\n `td${desktop}{display:table-cell!important;max-height:none!important;overflow:visible!important}`\n : '';\n const hidden = usage.hideMobile\n ? `${phone}{display:none!important;mso-hide:all!important}`\n : '';\n if (shown || hidden || mobile.length)\n rules.push(`${small}{${hidden}${shown}${mobile.join('')}}`);\n }\n return `${inline}${rules.length ? `<mj-style>${rules.join('')}</mj-style>` : ''}`;\n }\n\n /** The device CSS of a page: visibility on each screen and the mobile rules. */\n pageCss(mode: OutputMode, usage: DeviceUsage, mobile: readonly string[]): string {\n const small = `@media (max-width:${this.breakpoint}px)`;\n const large = `@media (min-width:${this.breakpoint + 1}px)`;\n const hide = mode === 'preview' ? FADED : 'display:none!important';\n return (\n (usage.hideDesktop ? `${large}{.${HIDE_DESKTOP_CLASS}{${hide}}}` : '') +\n (usage.hideMobile || mobile.length\n ? `${small}{${mobile.join('')}${usage.hideMobile ? `.${HIDE_MOBILE_CLASS}{${hide}}` : ''}}`\n : '')\n );\n }\n}\n","import type { Block } from '../core/block-document';\nimport { escapeHtml } from '../core/html-escape';\nimport { GeneratedMjml } from '../compilation/generated-mjml';\nimport { SecureIdentifier } from '../security/identity';\nimport type { BlockDocumentView, BlockTypeCatalog, OutputMode } from './block-type';\nimport { EmailRenderContext } from './render-context';\nimport type { MjmlTarget } from './styles';\nimport { StyleResolver } from './styles';\nimport { columnWeight } from './types/layout';\nimport { BlockDeviceStyles } from './device-styles';\nimport type { DeviceUsage } from './device-styles';\n\n/** Columns sit side by side above this width and stack below it, as in the e-mail models. */\nexport const EMAIL_BREAKPOINT = '641px';\n/** Largest width that counts as a small screen: one below the breakpoint. */\nconst SMALL_SCREEN = 640;\n\ninterface EmailRun {\n readonly mode: OutputMode;\n readonly styles: StyleResolver;\n readonly fragments: string[];\n readonly token: string;\n readonly usage: DeviceUsage;\n readonly mobile: string[];\n}\n\n/**\n * Writes the MJML of a block e-mail. The global styles become `<mj-attributes>` (and named\n * `mj-class` for headings and footers), so a style is written once and MJML spreads it over\n * every element it generates (cell, link, Outlook markup). A block writes only the values it\n * overrides. Columns are real `mj-column`. In preview every component also carries\n * `css-class=\"ve-p-<token>-<id>\"`, with a token drawn for the rendering, which the preview\n * marker turns into the canvas attributes.\n */\nexport class BlockMjmlGenerator {\n readonly #devices = new BlockDeviceStyles(SMALL_SCREEN);\n\n constructor(private readonly registry: BlockTypeCatalog) {}\n\n toMjml(\n document: BlockDocumentView,\n mode: OutputMode,\n token: string = new SecureIdentifier().next(),\n ): GeneratedMjml {\n if (!/^[a-f0-9]{32}$/.test(token)) throw new Error('INVALID_PREVIEW_TOKEN');\n if (document.kind !== 'email') throw new Error('BLOCK_GENERATOR_KIND_MISMATCH');\n const styles = new StyleResolver(this.registry.styles, document.styles, 'email');\n const run: EmailRun = {\n mode,\n styles,\n fragments: [],\n token,\n usage: { hideDesktop: false, hideMobile: false },\n mobile: [],\n };\n const body = document.blocks.map((block) => this.block(block, run)).join('');\n const source =\n `<mjml lang=\"${escapeHtml(document.meta.lang)}\">` +\n `<mj-head><mj-breakpoint width=\"${EMAIL_BREAKPOINT}\" />` +\n `<mj-attributes>${this.attributes(styles)}</mj-attributes>` +\n `<mj-style>a { color: ${styles.value('body.linkColor')}; }</mj-style>` +\n `${this.#devices.emailHead(mode, run.usage, run.mobile)}</mj-head>` +\n `<mj-body background-color=\"${escapeHtml(styles.value('body.background'))}\" width=\"${escapeHtml(styles.value('body.width'))}\">` +\n `${body}</mj-body></mjml>`;\n return new GeneratedMjml(source, run.fragments);\n }\n\n private block(block: Block, run: EmailRun, columnWidth?: string): string {\n const definition = this.registry.definition(block.type);\n if (!definition.email) throw new Error('BLOCK_NOT_IN_EMAIL');\n const children = block.children ?? [];\n const widths = block.type === 'section' ? this.widths(children) : [];\n this.#devices.usage(block, run.usage);\n const mobile = this.#devices.emailRules(block, definition);\n run.mobile.push(...mobile);\n const context = new EmailRenderContext(\n block,\n definition,\n run.mode,\n run.styles,\n (reverse) => {\n const markup = children.map((child, index) => this.block(child, run, widths[index]));\n return (reverse ? markup.reverse() : markup).join('');\n },\n run.fragments,\n run.token,\n columnWidth,\n mobile.length > 0,\n );\n return definition.email(context);\n }\n\n /** Shares of the columns of a section, in percent with at most two decimals. */\n private widths(columns: readonly Block[]): readonly string[] {\n const weights = columns.map(columnWeight);\n const total = weights.reduce((sum, weight) => sum + weight, 0);\n return weights.map((weight) => `${Number(((weight / total) * 100).toFixed(2))}%`);\n }\n\n private attributes(styles: StyleResolver): string {\n const groups = new Map<string, { target: MjmlTarget; pairs: [string, string][] }>();\n for (const path of this.registry.styles.paths()) {\n const [group = '', key = ''] = path.split('.');\n for (const target of this.registry.styles.key(group, key)?.mjml ?? []) {\n const id = `${target.element}|${target.mjClass ?? ''}`;\n const entry = groups.get(id) ?? { target, pairs: [] };\n entry.pairs.push([target.attribute, styles.value(path)]);\n groups.set(id, entry);\n }\n }\n return [...groups.values()]\n .map(({ target, pairs }) => {\n const attributes = pairs.map(([name, value]) => ` ${name}=\"${escapeHtml(value)}\"`).join('');\n return target.mjClass\n ? `<mj-class name=\"${target.mjClass}\"${attributes} />`\n : `<${target.element}${attributes} />`;\n })\n .join('');\n }\n}\n","import type { Block } from '../core/block-document';\nimport type { SourceInput } from '../core/document';\nimport { escapeHtml } from '../core/html-escape';\nimport type { BlockDocumentView, BlockTypeCatalog, OutputMode } from './block-type';\nimport { PageRenderContext, blockClass } from './render-context';\nimport { StyleResolver } from './styles';\nimport type { StylePath } from './styles';\nimport { BlockDeviceStyles } from './device-styles';\nimport type { DeviceUsage } from './device-styles';\n\n/** Width below which the columns of a section stack, as in the e-mail breakpoint. */\nexport const PAGE_BREAKPOINT = 640;\n\n/** CSS variable of a global style: `body.textColor` is `--ve-body-text-color`. */\nexport function styleVariable(path: StylePath): string {\n return `--ve-${path.replace('.', '-').replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}`;\n}\n\nconst v = (path: StylePath): string => `var(${styleVariable(path)})`;\n\n/** Rules every generated page shares; the values come from the variables of `:root`. */\nconst BASE_CSS = [\n `body{margin:0;background:${v('body.background')}}`,\n `.ve-page{background:${v('body.background')};font-family:${v('body.fontFamily')};color:${v('body.textColor')};font-size:${v('body.fontSize')};line-height:${v('body.lineHeight')}}`,\n '.ve-page *,.ve-page *::before,.ve-page *::after{box-sizing:border-box}',\n `.ve-page a{color:${v('body.linkColor')}}`,\n `.ve-section{max-width:${v('body.width')};margin:0 auto;background-color:${v('body.contentBackground')};padding:${v('section.padding')}}`,\n `.ve-columns{display:grid;grid-template-columns:minmax(0,1fr);column-gap:${v('section.columnGap')}}`,\n '.ve-column{min-width:0;padding:0;align-self:start}',\n '.ve-block{padding:10px 25px}',\n '.ve-text>:first-child,.ve-footer>:first-child{margin-top:0}',\n '.ve-text>:last-child,.ve-footer>:last-child{margin-bottom:0}',\n `.ve-heading{margin:0;font-family:${v('heading.fontFamily')};color:${v('heading.color')};font-size:${v('heading.fontSize')};font-weight:${v('heading.fontWeight')};line-height:${v('heading.lineHeight')}}`,\n `.ve-footer{color:${v('footer.color')};font-size:${v('footer.fontSize')}}`,\n '.ve-image{text-align:center}',\n '.ve-image img{display:inline-block;max-width:100%;height:auto;border:0}',\n '.ve-image-empty{min-height:120px;background:#e8eef0}',\n '.ve-button-row{text-align:center}',\n `.ve-page .ve-button{display:inline-block;background-color:${v('button.background')};color:${v('button.color')};border-radius:${v('button.radius')};font-size:${v('button.fontSize')};font-weight:${v('button.fontWeight')};padding:${v('button.padding')};line-height:1.2;text-decoration:none}`,\n `.ve-divider hr{margin:0;border:0;border-top:${v('divider.width')} solid ${v('divider.color')}}`,\n '.ve-spacer{height:20px}',\n '.ve-html{padding:0}',\n].join('');\nconst MOBILE_CSS = `@media (max-width:${PAGE_BREAKPOINT}px){.ve-section>.ve-columns{grid-template-columns:minmax(0,1fr)}}`;\n\n/**\n * Writes the HTML and CSS of a block page, synchronously. The global styles become the\n * variables of `:root`; a block that overrides a value gets a rule on its own class\n * `.ve-b-<id>`. Sections are grids of real columns that stack on small screens. In preview the\n * selectable and editable elements carry the canvas attributes; the published page does not.\n */\ninterface PageRun {\n readonly mode: OutputMode;\n readonly styles: StyleResolver;\n readonly rules: string[];\n readonly overrides: string[];\n readonly mobile: string[];\n readonly usage: DeviceUsage;\n}\n\nexport class BlockPageGenerator {\n readonly #devices = new BlockDeviceStyles(PAGE_BREAKPOINT);\n\n constructor(private readonly registry: BlockTypeCatalog) {}\n\n toHtml(document: BlockDocumentView, mode: OutputMode): SourceInput {\n if (document.kind !== 'page') throw new Error('BLOCK_GENERATOR_KIND_MISMATCH');\n const styles = new StyleResolver(this.registry.styles, document.styles, 'page');\n const run: PageRun = {\n mode,\n styles,\n rules: [],\n overrides: [],\n mobile: [],\n usage: { hideDesktop: false, hideMobile: false },\n };\n const content = document.blocks.map((block) => this.block(block, run)).join('');\n const variables = this.registry.styles\n .paths()\n .filter((path) => {\n const [group = '', key = ''] = path.split('.');\n const kinds = this.registry.styles.key(group, key)?.kinds;\n return !kinds || kinds.includes('page');\n })\n .map((path) => `${styleVariable(path)}:${styles.value(path)}`)\n .join(';');\n return {\n html: `<main class=\"ve-page\" lang=\"${escapeHtml(document.meta.lang)}\">${content}</main>`,\n css: `:root{${variables}}${BASE_CSS}${run.rules.join('')}${run.overrides.join('')}${MOBILE_CSS}${this.#devices.pageCss(mode, run.usage, run.mobile)}`,\n };\n }\n\n private block(block: Block, run: PageRun): string {\n const definition = this.registry.definition(block.type);\n run.overrides.push(...this.overrides(block));\n this.#devices.usage(block, run.usage);\n run.mobile.push(...this.#devices.pageRules(block, definition));\n const context = new PageRenderContext(\n block,\n definition,\n run.mode,\n run.styles,\n (reverse) => {\n const markup = (block.children ?? []).map((child) => this.block(child, run));\n return (reverse ? markup.reverse() : markup).join('');\n },\n run.rules,\n run.mobile,\n );\n return definition.page(context);\n }\n\n /** `.ve-b-<id>{...}` and `.ve-b-<id> <inner>{...}` for the values the block overrides. */\n private overrides(block: Block): readonly string[] {\n const definition = this.registry.definition(block.type);\n const self: string[] = [];\n const inner: string[] = [];\n for (const field of definition.fields) {\n const own = block.props[field.key];\n if (!field.css || own === undefined) continue;\n const value = field.css.map ? field.css.map[String(own)] : String(own);\n if (value === undefined) continue;\n (field.css.target === 'inner' ? inner : self).push(`${field.css.property}:${value}`);\n }\n const selector = `.${blockClass(block)}`;\n return [\n ...(self.length ? [`${selector}{${self.join(';')}}`] : []),\n ...(inner.length && definition.innerSelector\n ? [`${selector} ${definition.innerSelector}{${inner.join(';')}}`]\n : []),\n ];\n }\n}\n","import type { Block, BlockProps } from '../../core/block-document';\nimport { escapeHtml } from '../../core/html-escape';\nimport type {\n BlockField,\n BlockTypeDefinition,\n EmailBlockContext,\n PageBlockContext,\n} from '../block-type';\nimport { TEXT_MOBILE_EMAIL, fields } from '../fields';\n\nfunction text(context: { value(key: string): unknown }): string {\n const value = context.value('text');\n return typeof value === 'string' ? value : '';\n}\n\n/** Paragraphs, lists and quotes in the body typography of the piece. */\nexport class TextBlock implements BlockTypeDefinition {\n readonly type = 'text';\n readonly labelKey = 'blocks.text';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n fields.text('block'),\n fields.color('color', 'properties.color', 'body.textColor'),\n fields.fontSize('body.fontSize'),\n fields.lineHeight('body.lineHeight'),\n fields.align('left'),\n fields.padding(),\n ...fields.visibility(),\n ];\n readonly mobileEmail = TEXT_MOBILE_EMAIL;\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'text', props };\n }\n\n email(context: EmailBlockContext): string {\n return `<mj-text${context.attributes()}>${text(context)}</mj-text>`;\n }\n\n page(context: PageBlockContext): string {\n return `<div${context.classes('ve-block ve-text')}${context.node()}${context.editable()}>${text(context)}</div>`;\n }\n}\n\nexport const HEADING_LEVELS = ['h1', 'h2', 'h3'] as const;\n\n/** A title in the heading typography of the piece, as a real `h1`-`h3`. */\nexport class HeadingBlock implements BlockTypeDefinition {\n readonly type = 'heading';\n readonly labelKey = 'blocks.heading';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n fields.text('inline'),\n {\n key: 'level',\n tab: 'content',\n control: 'select',\n labelKey: 'blockFields.headingLevel',\n value: { type: 'select', options: HEADING_LEVELS },\n options: HEADING_LEVELS.map((level) => ({ value: level, labelKey: `blockFields.${level}` })),\n defaultValue: 'h2',\n },\n fields.color('color', 'properties.color', 'heading.color'),\n fields.fontSize('heading.fontSize'),\n fields.align('left'),\n fields.padding(),\n ...fields.visibility(),\n ];\n // The heading element carries its own font size and alignment inline: the rule reaches it.\n readonly mobileEmail = {\n fontSize: { selectors: ['>div', '>div>h1', '>div>h2', '>div>h3'] },\n align: { selectors: ['>div', '>div>h1', '>div>h2', '>div>h3'] },\n padding: { selectors: [''] },\n };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'heading', props };\n }\n\n email(context: EmailBlockContext): string {\n // The heading element carries the effective values: some clients restyle `h1`-`h3`.\n const style = [\n 'margin:0',\n `font-family:${context.styles.value('heading.fontFamily')}`,\n `font-size:${String(context.value('fontSize'))}`,\n `font-weight:${context.styles.value('heading.fontWeight')}`,\n `line-height:${context.styles.value('heading.lineHeight')}`,\n `color:${String(context.value('color'))}`,\n ].join(';');\n return `<mj-text mj-class=\"ve-heading\"${context.attributes()}><${this.level(context)} style=\"${escapeHtml(style)}\">${text(context)}</${this.level(context)}></mj-text>`;\n }\n\n page(context: PageBlockContext): string {\n const level = this.level(context);\n return `<${level}${context.classes('ve-block ve-heading')}${context.node()}${context.editable()}>${text(context)}</${level}>`;\n }\n\n private level(context: { value(key: string): unknown }): string {\n const level = context.value('level');\n return HEADING_LEVELS.find((entry) => entry === level) ?? 'h2';\n }\n}\n\n/** The closing lines of a piece in the footer typography. */\nexport class FooterBlock implements BlockTypeDefinition {\n readonly type = 'footer';\n readonly labelKey = 'blocks.footer';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n fields.text('block'),\n fields.color('color', 'properties.color', 'footer.color'),\n fields.fontSize('footer.fontSize'),\n fields.align('left'),\n fields.padding(),\n ...fields.visibility(),\n ];\n readonly mobileEmail = TEXT_MOBILE_EMAIL;\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'footer', props };\n }\n\n email(context: EmailBlockContext): string {\n return `<mj-text mj-class=\"ve-footer\"${context.attributes()}>${text(context)}</mj-text>`;\n }\n\n page(context: PageBlockContext): string {\n return `<footer${context.classes('ve-block ve-footer')}${context.node()}${context.editable()}>${text(context)}</footer>`;\n }\n}\n","import type { Block, BlockProps } from '../../core/block-document';\nimport { escapeHtml } from '../../core/html-escape';\nimport type {\n BlockField,\n BlockTypeDefinition,\n EmailBlockContext,\n PageBlockContext,\n} from '../block-type';\nimport { fields } from '../fields';\n\nfunction string(context: { value(key: string): unknown }, key: string): string | undefined {\n const value = context.value(key);\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\n/** Placeholder of an image without address, only in the editing frame. */\nconst EMPTY_IMAGE_HEIGHT = '120px';\nconst EMPTY_IMAGE_COLOR = '#e8eef0';\n\n/**\n * An image from the media library (`assetId` + `url`) or an address, with its description.\n * Without an address it is only a placeholder in the preview and nothing in the output.\n */\nexport class ImageBlock implements BlockTypeDefinition {\n readonly type = 'image';\n readonly labelKey = 'blocks.image';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly innerSelector = 'img';\n readonly fields: readonly BlockField[] = [\n {\n key: 'url',\n tab: 'content',\n control: 'image',\n labelKey: 'properties.imageUrl',\n value: { type: 'url', purpose: 'image' },\n },\n {\n key: 'assetId',\n tab: 'content',\n control: 'text',\n labelKey: 'properties.imageUrl',\n value: { type: 'plain', max: 128, pattern: /^[A-Za-z0-9_-]{1,128}$/ },\n internal: true,\n },\n {\n key: 'alt',\n tab: 'content',\n control: 'text',\n labelKey: 'properties.alternativeText',\n value: { type: 'plain', max: 1_000 },\n defaultValue: '',\n },\n fields.link(),\n {\n key: 'width',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.width',\n value: { type: 'length', units: ['px'], max: 1_600 },\n mjml: { attribute: 'width' },\n css: { property: 'width', target: 'inner' },\n responsive: true,\n },\n fields.align('center'),\n fields.padding(),\n ...fields.visibility(),\n ];\n readonly mobileEmail = {\n width: { selectors: [' img'] },\n padding: { selectors: [''] },\n };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'image', props };\n }\n\n email(context: EmailBlockContext): string {\n const url = string(context, 'url');\n if (!url) {\n const previewClass = context.previewClass();\n return previewClass\n ? `<mj-spacer height=\"${EMPTY_IMAGE_HEIGHT}\" container-background-color=\"${EMPTY_IMAGE_COLOR}\" css-class=\"${context.cellClass() ?? previewClass}\"></mj-spacer>`\n : '';\n }\n return `<mj-image${context.attributes({\n src: url,\n alt: string(context, 'alt') ?? '',\n href: string(context, 'href'),\n })}></mj-image>`;\n }\n\n page(context: PageBlockContext): string {\n const url = string(context, 'url');\n if (!url)\n return context.mode === 'preview'\n ? `<div${context.classes('ve-block ve-image ve-image-empty')}${context.node()}></div>`\n : '';\n const href = string(context, 'href');\n const image = `<img src=\"${escapeHtml(url)}\" alt=\"${escapeHtml(string(context, 'alt') ?? '')}\">`;\n return `<div${context.classes('ve-block ve-image')}${context.node()}>${\n href ? `<a href=\"${escapeHtml(href)}\">${image}</a>` : image\n }</div>`;\n }\n}\n\n/** A call to action. Its colors come from the global button style unless it sets its own. */\nexport class ButtonBlock implements BlockTypeDefinition {\n readonly type = 'button';\n readonly labelKey = 'blocks.button';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly innerSelector = '.ve-button';\n readonly fields: readonly BlockField[] = [\n fields.text('button'),\n fields.link(),\n fields.color('background', 'properties.background', 'button.background', 'inner'),\n fields.color('color', 'properties.color', 'button.color', 'inner'),\n {\n key: 'radius',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.borderRadius',\n value: { type: 'length', units: ['px'], max: 64 },\n inherits: 'button.radius',\n mjml: { attribute: 'border-radius' },\n css: { property: 'border-radius', target: 'inner' },\n },\n fields.fontSize('button.fontSize', 'inner'),\n {\n key: 'fullWidth',\n tab: 'style',\n control: 'toggle',\n labelKey: 'blockFields.fullWidth',\n value: { type: 'toggle' },\n defaultValue: false,\n mjml: { attribute: 'width', map: { true: '100%' } },\n css: { property: 'display', target: 'inner', map: { true: 'block' } },\n },\n fields.align('center'),\n fields.padding(),\n ...fields.visibility(),\n ];\n // The alignment of a button is the `align` of its cell, which CSS does not move: page only.\n readonly mobileEmail = {\n fontSize: { selectors: [' a', ' p'] },\n padding: { selectors: [''] },\n };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'button', props };\n }\n\n email(context: EmailBlockContext): string {\n const text = string(context, 'text') ?? '';\n return `<mj-button${context.attributes({ href: string(context, 'href') })}>${text}</mj-button>`;\n }\n\n page(context: PageBlockContext): string {\n const href = string(context, 'href');\n const text = string(context, 'text') ?? '';\n return `<div${context.classes('ve-block ve-button-row')}${context.node()}><a class=\"ve-button\"${\n href ? ` href=\"${escapeHtml(href)}\"` : ''\n }${context.editable()}>${text}</a></div>`;\n }\n}\n","import type { Block, BlockProps } from '../../core/block-document';\nimport type {\n BlockField,\n BlockTypeDefinition,\n EmailBlockContext,\n PageBlockContext,\n} from '../block-type';\nimport { fields } from '../fields';\n\n/** A horizontal rule in the global divider style. */\nexport class DividerBlock implements BlockTypeDefinition {\n readonly type = 'divider';\n readonly labelKey = 'blocks.divider';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly innerSelector = 'hr';\n readonly fields: readonly BlockField[] = [\n {\n key: 'color',\n tab: 'style',\n control: 'color',\n labelKey: 'properties.borderColor',\n value: { type: 'color' },\n inherits: 'divider.color',\n mjml: { attribute: 'border-color' },\n css: { property: 'border-top-color', target: 'inner' },\n },\n {\n key: 'thickness',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.borderWidth',\n value: { type: 'length', units: ['px'], max: 16 },\n inherits: 'divider.width',\n mjml: { attribute: 'border-width' },\n css: { property: 'border-top-width', target: 'inner' },\n },\n fields.padding(),\n ...fields.visibility(),\n ];\n readonly mobileEmail = { padding: { selectors: [''] } };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'divider', props };\n }\n\n email(context: EmailBlockContext): string {\n return `<mj-divider${context.attributes()}></mj-divider>`;\n }\n\n page(context: PageBlockContext): string {\n return `<div${context.classes('ve-block ve-divider')}${context.node()}><hr></div>`;\n }\n}\n\n/** Vertical space. */\nexport class SpacerBlock implements BlockTypeDefinition {\n readonly type = 'spacer';\n readonly labelKey = 'blocks.spacer';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n {\n key: 'height',\n tab: 'style',\n control: 'length',\n labelKey: 'properties.height',\n value: { type: 'length', units: ['px'], max: 400 },\n defaultValue: '20px',\n mjml: { attribute: 'height' },\n css: { property: 'height' },\n responsive: true,\n },\n ...fields.visibility(),\n ];\n readonly mobileEmail = { height: { selectors: ['>div'], properties: ['height', 'line-height'] } };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'spacer', props };\n }\n\n email(context: EmailBlockContext): string {\n return `<mj-spacer${context.attributes()}></mj-spacer>`;\n }\n\n page(context: PageBlockContext): string {\n return `<div${context.classes('ve-spacer')}${context.node()} aria-hidden=\"true\"></div>`;\n }\n}\n","import type { Block, BlockProps } from '../../core/block-document';\nimport { escapeHtml } from '../../core/html-escape';\nimport type {\n BlockField,\n BlockTypeDefinition,\n EmailBlockContext,\n PageBlockContext,\n} from '../block-type';\nimport { fields } from '../fields';\n\n/** Where the host renders one of its forms. Only in a page; the reference is the host's. */\nexport class FormBlock implements BlockTypeDefinition {\n readonly type = 'form';\n readonly labelKey = 'blocks.form';\n readonly kinds = ['page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n {\n key: 'reference',\n tab: 'content',\n control: 'text',\n labelKey: 'properties.form',\n value: { type: 'plain', max: 128, pattern: /^[A-Za-z0-9_-]{1,128}$/ },\n },\n fields.padding(),\n ...fields.visibility(),\n ];\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'form', props };\n }\n\n page(context: PageBlockContext): string {\n const reference = context.value('reference');\n return `<div${context.classes('ve-block ve-form')}${context.node()} data-host-slot=\"form\"${\n typeof reference === 'string' ? ` data-host-reference=\"${escapeHtml(reference)}\"` : ''\n }></div>`;\n }\n}\n\n/**\n * Free HTML written by the author. In a page it is kept as written (balanced by the parser);\n * in an e-mail it must already follow the e-mail rules and is emitted through `mj-raw`, the\n * only raw region the compilation accepts, and only from this generator.\n */\nexport class HtmlBlock implements BlockTypeDefinition {\n readonly type = 'html';\n readonly labelKey = 'blocks.customHtml';\n readonly kinds = ['email', 'page'] as const;\n readonly childTypes = [];\n readonly childCount = { min: 0, max: 0 };\n readonly fields: readonly BlockField[] = [\n {\n key: 'html',\n tab: 'content',\n control: 'code',\n labelKey: 'blockFields.html',\n value: { type: 'html' },\n defaultValue: '',\n },\n fields.padding('0'),\n ...fields.visibility(),\n ];\n readonly mobileEmail = { padding: { selectors: [''] } };\n\n create(nextId: () => string, props: BlockProps = {}): Block {\n return { id: nextId(), type: 'html', props };\n }\n\n email(context: EmailBlockContext): string {\n const cellClass = context.cellClass();\n const html = context.value('html');\n // MJML zeroes the font size of a column (`font-size:0px`) and sets it again on each\n // component; the free HTML gets the text style of the piece back in its own wrapper.\n const text = escapeHtml(\n [\n `font-family:${context.styles.value('body.fontFamily')}`,\n `font-size:${context.styles.value('body.fontSize')}`,\n `line-height:${context.styles.value('body.lineHeight')}`,\n `color:${context.styles.value('body.textColor')}`,\n ].join(';'),\n );\n return context.raw(\n `<tr><td${cellClass ? ` class=\"${cellClass}\"` : ''} style=\"padding:${String(\n context.value('padding'),\n )}\"><div style=\"${text}\">${typeof html === 'string' ? html : ''}</div></td></tr>`,\n );\n }\n\n page(context: PageBlockContext): string {\n const html = context.value('html');\n return `<div${context.classes('ve-html')}${context.node()}>${typeof html === 'string' ? html : ''}</div>`;\n }\n}\n","import { BlockDocumentError } from '../core/block-document';\nimport type {\n Block,\n BlockDocumentData,\n BlockNodeType,\n BlockPropValue,\n BlockProps,\n BlockRules,\n GlobalStyles,\n StyleValue,\n} from '../core/block-document';\nimport type { DocumentKind } from '../core/document';\nimport { DocumentBudget } from '../core/budget';\nimport { COMPILE_LIMITS } from '../compilation/guard';\nimport type { BlockField, BlockTypeCatalog, BlockTypeDefinition } from './block-type';\nimport { BlockMjmlGenerator } from './email-generator';\nimport { BlockPageGenerator } from './page-generator';\nimport { BlockContentGuard } from './content-guard';\nimport { GlobalStyleSpec } from './styles';\nimport { ValueRules } from './values';\nimport type { ValueSpec } from './values';\nimport { ColumnBlock, SectionBlock } from './types/layout';\nimport { FooterBlock, HeadingBlock, TextBlock } from './types/text';\nimport { ButtonBlock, ImageBlock } from './types/media';\nimport { DividerBlock, SpacerBlock } from './types/structure';\nimport { FormBlock, HtmlBlock } from './types/embed';\n\nexport function defaultBlockTypes(): readonly BlockTypeDefinition[] {\n return [\n new SectionBlock(),\n new ColumnBlock(),\n new TextBlock(),\n new HeadingBlock(),\n new ImageBlock(),\n new ButtonBlock(),\n new DividerBlock(),\n new SpacerBlock(),\n new FooterBlock(),\n new FormBlock(),\n new HtmlBlock(),\n ];\n}\n\n/**\n * The catalog of block types and the rules the block document applies through its port:\n * where each type may stand, which properties it accepts and how each value is checked.\n */\n/** Token of the size check: as long as a real one, so the measured preview is not shorter. */\nconst MEASURE_TOKEN = '0'.repeat(32);\n\nexport class BlockDefinitionRegistry implements BlockRules, BlockTypeCatalog {\n readonly #types = new Map<BlockNodeType, BlockTypeDefinition>();\n readonly #fields = new Map<string, BlockField>();\n readonly #values: ValueRules;\n readonly styles: GlobalStyleSpec;\n\n constructor(\n content = new BlockContentGuard(),\n styles = new GlobalStyleSpec(),\n types: readonly BlockTypeDefinition[] = defaultBlockTypes(),\n ) {\n this.#values = new ValueRules(content);\n this.styles = styles;\n for (const definition of types) {\n if (this.#types.has(definition.type)) throw new Error('DUPLICATE_BLOCK_TYPE');\n this.#types.set(definition.type, definition);\n for (const field of definition.fields) {\n if (field.inherits && !styles.has(field.inherits)) throw new Error('UNKNOWN_STYLE');\n this.#fields.set(`${definition.type}.${field.key}`, field);\n }\n }\n }\n\n definition(type: BlockNodeType): BlockTypeDefinition {\n const definition = this.#types.get(type);\n if (!definition) throw new BlockDocumentError('UNKNOWN_BLOCK_TYPE');\n return definition;\n }\n\n /** The types an author may insert in a piece of this kind. */\n list(kind: DocumentKind): readonly BlockTypeDefinition[] {\n return [...this.#types.values()].filter((definition) => definition.kinds.includes(kind));\n }\n\n field(type: BlockNodeType, key: string): BlockField | undefined {\n return this.#fields.get(`${type}.${key}`);\n }\n\n /** A new block; the document validates it when it is inserted. */\n create(type: BlockNodeType, nextId: () => string, props: BlockProps = {}): Block {\n return this.definition(type).create(nextId, props);\n }\n\n isRoot(type: BlockNodeType): boolean {\n return this.definition(type).root === true;\n }\n\n childTypes(type: BlockNodeType): readonly BlockNodeType[] {\n return this.definition(type).childTypes;\n }\n\n childCount(type: BlockNodeType): { readonly min: number; readonly max: number } {\n return this.definition(type).childCount;\n }\n\n allows(type: BlockNodeType, kind: DocumentKind): boolean {\n return this.definition(type).kinds.includes(kind);\n }\n\n validateProps(type: BlockNodeType, props: BlockProps, kind: DocumentKind): string | undefined {\n const definition = this.definition(type);\n for (const [key, value] of Object.entries(props)) {\n const field = this.field(type, key);\n if (!field) return 'UNKNOWN_BLOCK_PROP';\n if (!this.#values.accepts(field.value, value, kind)) return this.refusal(field.value, kind);\n }\n if (definition.fields.some((field) => field.required && props[field.key] === undefined))\n return 'MISSING_BLOCK_PROP';\n return undefined;\n }\n\n normalizeProp(\n type: BlockNodeType,\n key: string,\n value: BlockPropValue,\n kind: DocumentKind,\n ): BlockPropValue {\n const field = this.field(type, key);\n if (!field) throw new BlockDocumentError('UNKNOWN_BLOCK_PROP');\n let normalized: BlockPropValue | undefined;\n try {\n normalized = this.#values.normalize(field.value, value, kind);\n } catch {\n normalized = undefined;\n }\n if (normalized === undefined) throw new BlockDocumentError(this.refusal(field.value, kind));\n return normalized;\n }\n\n textKeys(type: BlockNodeType): readonly string[] {\n return this.definition(type)\n .fields.filter((field) => field.control === 'richtext')\n .map((field) => field.key);\n }\n\n /**\n * A field with a mobile value: marked responsive and written by the output of the kind (CSS\n * in a page, a mobile rule of the definition in an e-mail).\n */\n responsive(type: BlockNodeType, key: string, kind: DocumentKind): boolean {\n const definition = this.#types.get(type);\n const field = this.field(type, key);\n if (!definition || !field?.responsive || !definition.kinds.includes(kind)) return false;\n return kind === 'page' ? field.css !== undefined : definition.mobileEmail?.[key] !== undefined;\n }\n\n validateStyles(styles: GlobalStyles, kind: DocumentKind): string | undefined {\n for (const [group, values] of Object.entries(styles))\n for (const [key, value] of Object.entries(values)) {\n const spec = this.styles.key(group, key);\n if (!spec || (spec.kinds && !spec.kinds.includes(kind))) return 'UNKNOWN_GLOBAL_STYLE';\n if (!this.#values.accepts(spec.value, value, kind)) return 'INVALID_GLOBAL_STYLES';\n }\n return undefined;\n }\n\n normalizeStyle(group: string, key: string, value: StyleValue, kind: DocumentKind): StyleValue {\n const spec = this.styles.key(group, key);\n if (!spec || (spec.kinds && !spec.kinds.includes(kind)))\n throw new BlockDocumentError('UNKNOWN_GLOBAL_STYLE');\n const normalized = this.#values.normalize(spec.value, value, kind);\n if (normalized === undefined || typeof normalized === 'boolean')\n throw new BlockDocumentError('INVALID_GLOBAL_STYLES');\n return normalized;\n }\n\n /**\n * The output of the piece must fit what consumes it: the MJML of an e-mail (preview, the\n * larger of the two) within the compilation limit, and the HTML and CSS of a page within\n * the source limits of the HTML document a conversion would create.\n */\n validateDocument(data: BlockDocumentData): string | undefined {\n const budget = new DocumentBudget();\n if (data.kind === 'email') {\n const mjml = new BlockMjmlGenerator(this).toMjml(data, 'preview', MEASURE_TOKEN);\n return budget.byteLength(mjml.source) > COMPILE_LIMITS.sourceBytes\n ? 'BLOCK_EMAIL_TOO_LARGE'\n : undefined;\n }\n const page = new BlockPageGenerator(this).toHtml(data, 'preview');\n return budget.byteLength(page.html) > DocumentBudget.limits.sourceBytes ||\n budget.byteLength(page.css) > DocumentBudget.limits.cssBytes\n ? 'BLOCK_PAGE_TOO_LARGE'\n : undefined;\n }\n\n /** Every label key the definitions and the global styles refer to. */\n labelKeys(): readonly string[] {\n const keys = new Set<string>();\n for (const definition of this.#types.values()) {\n keys.add(definition.labelKey);\n for (const field of definition.fields) {\n keys.add(field.labelKey);\n for (const option of field.options ?? []) keys.add(option.labelKey);\n }\n }\n for (const group of this.styles.groups) {\n keys.add(group.labelKey);\n for (const key of group.keys) {\n keys.add(key.labelKey);\n for (const option of key.options ?? []) keys.add(option.labelKey);\n }\n }\n return [...keys];\n }\n\n private refusal(spec: ValueSpec, kind: DocumentKind): string {\n switch (spec.type) {\n case 'richtext':\n return 'INVALID_BLOCK_TEXT';\n case 'url':\n return 'UNSAFE_BLOCK_URL';\n case 'html':\n return kind === 'email' ? 'UNSAFE_BLOCK_HTML' : 'INVALID_BLOCK_HTML';\n default:\n return 'INVALID_BLOCK_PROPS';\n }\n }\n}\n","import { parse, serialize } from 'parse5';\nimport type { DefaultTreeAdapterMap } from 'parse5';\nimport type { Block, BlockDocument, BlockNodeType } from '../core/block-document';\nimport { EDIT_NODE_ATTRIBUTE, NODE_ATTRIBUTE } from '../core/canvas-contract';\n\ntype Element = DefaultTreeAdapterMap['element'];\n\n/** Element, under the marked cell, whose text the author edits in place. */\nconst EDITABLE: Partial<Record<BlockNodeType, readonly string[]>> = {\n text: ['div'],\n footer: ['div'],\n heading: ['h1', 'h2', 'h3'],\n button: ['a', 'p'],\n};\n\n/**\n * Turns the preview classes `ve-p-<token>-<id>` of a compiled preview e-mail into the canvas\n * attributes: the selectable element of each block gets `data-visual-editor-node`, and the\n * element holding an editable text gets `data-visual-editor-edit-node`. Only classes with the\n * token of this rendering count, each block is marked once (its first element in document\n * order), and the preview classes are taken out again. Works on the parsed tree, never by text\n * replacement. The e-mail that is sent has neither class nor attribute.\n *\n * `<mj-html-attributes>` was tried first and dropped: it re-serializes the whole body with\n * cheerio in XML mode, which turns `<br>` into an element that swallows the following text and\n * changes white space, so the preview would no longer be the e-mail that is sent.\n */\nexport class EmailPreviewMarker {\n mark(html: string, document: Pick<BlockDocument, 'blocks'>, token: string): string {\n const types = new Map<string, BlockNodeType>();\n const stack: Block[] = [...document.blocks];\n while (stack.length) {\n const block = stack.pop();\n if (!block) break;\n types.set(block.id, block.type);\n stack.push(...(block.children ?? []));\n }\n const prefix = `ve-p-${token}-`;\n const marked = new Set<string>();\n const tree = parse(html);\n this.walk(tree, (element) => {\n const id = this.take(element, prefix);\n const type = id ? types.get(id) : undefined;\n if (!id || !type || marked.has(id)) return;\n marked.add(id);\n this.annotate(element, id, type);\n });\n return serialize(tree);\n }\n\n /** Depth-first, in document order, `template` contents included. */\n private walk(root: DefaultTreeAdapterMap['parentNode'], visit: (element: Element) => void): void {\n const stack: DefaultTreeAdapterMap['childNode'][] = [...root.childNodes].reverse();\n while (stack.length) {\n const node = stack.pop();\n if (!node || !('tagName' in node)) continue;\n visit(node);\n const children = 'content' in node ? node.content.childNodes : node.childNodes;\n stack.push(...[...children].reverse());\n }\n }\n\n /** Removes the preview classes of this rendering and returns the block id they name. */\n private take(element: Element, prefix: string): string | undefined {\n const attribute = element.attrs.find((entry) => entry.name === 'class');\n if (!attribute) return undefined;\n let id: string | undefined;\n const kept = attribute.value.split(/\\s+/).filter((token) => {\n if (!token.startsWith(prefix)) return token !== '';\n id ??= token.slice(prefix.length);\n return false;\n });\n if (id === undefined) return undefined;\n element.attrs = kept.length\n ? element.attrs.map((entry) =>\n entry === attribute ? { ...entry, value: kept.join(' ') } : entry,\n )\n : element.attrs.filter((entry) => entry !== attribute);\n return id;\n }\n\n private annotate(element: Element, id: string, type: BlockNodeType): void {\n this.set(element, NODE_ATTRIBUTE, id);\n const tags = EDITABLE[type];\n if (!tags) return;\n const target = this.descendant(element, tags);\n if (target) this.set(target, EDIT_NODE_ATTRIBUTE, id);\n }\n\n private descendant(element: Element, tags: readonly string[]): Element | undefined {\n const queue: Element[] = [];\n for (const child of element.childNodes) if ('tagName' in child) queue.push(child);\n while (queue.length) {\n const current = queue.shift();\n if (!current) break;\n if (tags.includes(current.tagName)) return current;\n for (const child of current.childNodes) if ('tagName' in child) queue.push(child);\n }\n return undefined;\n }\n\n private set(element: Element, name: string, value: string): void {\n element.attrs = [\n ...element.attrs.filter((attribute) => attribute.name !== name),\n { name, value },\n ];\n }\n}\n","import type { BlockDocument } from '../core/block-document';\nimport type { SourceInput } from '../core/document';\nimport { SecureIdentifier } from '../security/identity';\nimport type { GeneratedMjmlCompilerPort } from '../compilation/generated-mjml';\nimport type { OutputMode } from './block-type';\nimport type { BlockMjmlGenerator } from './email-generator';\nimport { EmailPreviewMarker } from './email-preview';\n\n/**\n * The HTML of a block e-mail: generated MJML, compiled by the isolated compiler (which checks\n * the output against the e-mail rules), and, for the preview, marked for the canvas.\n */\nexport class BlockEmailRenderer {\n constructor(\n private readonly generator: BlockMjmlGenerator,\n private readonly compiler: GeneratedMjmlCompilerPort,\n private readonly marker = new EmailPreviewMarker(),\n private readonly identity = new SecureIdentifier(),\n ) {}\n\n /** A new preview token for every rendering: markup of the author cannot guess it. */\n async render(document: BlockDocument, mode: OutputMode): Promise<SourceInput> {\n const token = this.identity.next();\n const html = await this.compiler.compileGenerated(this.generator.toMjml(document, mode, token));\n return { html: mode === 'preview' ? this.marker.mark(html, document, token) : html, css: '' };\n }\n}\n","import type { Block, BlockDocument } from '../core/block-document';\nimport type { SourceInput } from '../core/document';\nimport type { CanvasBridgeRegion } from '../renderers/canvas-bridge';\nimport type { BlockPreviewInput } from '../renderers/marked-preview';\nimport type { BlockDefinitionRegistry } from './definitions';\nimport type { BlockEmailRenderer } from './email-renderer';\nimport type { BlockPageGenerator } from './page-generator';\n\n/**\n * The two outputs of a block piece, by kind: the final one the host stores, sends or publishes\n * (the compiled e-mail, or the HTML and CSS of the page), and the marked preview of the editing\n * frame with the regions of its blocks.\n */\nexport class BlockOutputRenderer {\n constructor(\n private readonly registry: BlockDefinitionRegistry,\n private readonly pages: BlockPageGenerator,\n private readonly emails: BlockEmailRenderer,\n /** The e-mail renderer of the editing frame; its compiler may queue apart from the final one. */\n private readonly previewEmails: BlockEmailRenderer = emails,\n ) {}\n\n /** What is sent or published. */\n render(document: BlockDocument): Promise<SourceInput> {\n return document.kind === 'email'\n ? this.emails.render(document, 'final')\n : Promise.resolve(this.pages.toHtml(document, 'final'));\n }\n\n /** The marked markup of the editing frame and the regions of the blocks, in document order. */\n async preview(document: BlockDocument): Promise<BlockPreviewInput> {\n const source =\n document.kind === 'email'\n ? await this.previewEmails.render(document, 'preview')\n : this.pages.toHtml(document, 'preview');\n return Object.freeze({\n id: document.id,\n revision: document.revision,\n kind: document.kind,\n source,\n regions: this.regions(document),\n });\n }\n\n /** What the frame runtime needs of each block: place, text mode, container, image. */\n regions(document: Pick<BlockDocument, 'blocks'>): readonly CanvasBridgeRegion[] {\n const regions: CanvasBridgeRegion[] = [];\n const visit = (blocks: readonly Block[], parentId: string | null): void => {\n for (const block of blocks) {\n const definition = this.registry.definition(block.type);\n const text = definition.fields.find((field) => field.control === 'richtext')?.value;\n const mode = text?.type === 'richtext' ? text.mode : undefined;\n regions.push(\n Object.freeze({\n id: block.id,\n parentId,\n editable: mode !== undefined,\n container: definition.childTypes.length > 0,\n ...(mode !== undefined ? { blocks: mode === 'block', links: mode !== 'button' } : {}),\n ...(block.type === 'image' ? { media: 'image' as const } : {}),\n }),\n );\n visit(block.children ?? [], block.id);\n }\n };\n visit(document.blocks, null);\n return regions;\n }\n}\n","import type { BlockDevice, BlockDocumentData, BlockPropValue } from '../core/block-document';\nimport type { BlockField, FieldControl, FieldOption, FieldTab } from './block-type';\nimport type { BlockDefinitionRegistry } from './definitions';\nimport { StyleResolver } from './styles';\nimport type { StyleKeySpec, StylePath } from './styles';\n\n/** One property of the selected block, as the properties panel shows it. */\nexport interface BlockFieldModel {\n readonly key: string;\n readonly tab: FieldTab;\n readonly control: FieldControl;\n readonly labelKey: string;\n readonly options: readonly FieldOption[];\n /** The value the block sets; undefined while it inherits. */\n readonly own: BlockPropValue | undefined;\n /** What the output uses: the block's value, else the global style, else the default. */\n readonly effective: BlockPropValue | undefined;\n /** The global style the value comes from while the block does not set it. */\n readonly inherits: StylePath | undefined;\n /** The field may take a value of its own on small screens. */\n readonly responsive: boolean;\n /** The screen this model shows. On mobile, `own` is the mobile value of a responsive field. */\n readonly device: BlockDevice;\n /** The block sets a mobile value for this field (shown on both screens). */\n readonly mobileOverride: boolean;\n}\n\nexport interface GlobalStyleKeyModel {\n readonly group: string;\n readonly key: string;\n readonly labelKey: string;\n readonly control: StyleKeySpec['control'];\n readonly options: readonly FieldOption[];\n readonly value: string;\n readonly overridden: boolean;\n}\n\nexport interface GlobalStyleGroupModel {\n readonly group: string;\n readonly labelKey: string;\n readonly keys: readonly GlobalStyleKeyModel[];\n}\n\n/**\n * Reads a block piece the way the panels show it: the fields of a block by its definition,\n * with the inherited and default values resolved, and the global styles of its kind. The\n * panels are generated from this, never written per block type.\n */\nexport class BlockInspector {\n constructor(private readonly registry: BlockDefinitionRegistry) {}\n\n /**\n * The fields of a block. On mobile a responsive field shows its mobile value, and while it\n * has none the value every screen uses, as what it inherits.\n */\n fields(\n document: BlockDocumentData,\n id: string,\n device: BlockDevice = 'desktop',\n ): readonly BlockFieldModel[] {\n const block = this.find(document.blocks, id);\n if (!block) return [];\n const styles = new StyleResolver(this.registry.styles, document.styles, document.kind);\n return this.registry\n .definition(block.type)\n .fields.filter((field) => !field.internal)\n .map((field) => {\n const responsive = this.registry.responsive(block.type, field.key, document.kind);\n const mobile = responsive ? block.mobile?.[field.key] : undefined;\n const base = this.field(field, block.props[field.key], styles);\n const model = { ...base, responsive, device, mobileOverride: mobile !== undefined };\n if (device !== 'mobile' || !responsive) return { ...model, device: 'desktop' as const };\n return { ...model, own: mobile, effective: mobile ?? base.effective };\n });\n }\n\n styles(document: Pick<BlockDocumentData, 'kind' | 'styles'>): readonly GlobalStyleGroupModel[] {\n const resolver = new StyleResolver(this.registry.styles, document.styles, document.kind);\n return this.registry.styles.groups\n .map((group) => ({\n group: group.group,\n labelKey: group.labelKey,\n keys: group.keys\n .filter((key) => !key.kinds || key.kinds.includes(document.kind))\n .map((key) => {\n const path: StylePath = `${group.group}.${key.key}`;\n return {\n group: group.group,\n key: key.key,\n labelKey: key.labelKey,\n control: key.control,\n options: key.options ?? [],\n value: resolver.value(path),\n overridden: resolver.overridden(path),\n };\n }),\n }))\n .filter((group) => group.keys.length > 0);\n }\n\n private field(\n field: BlockField,\n own: BlockPropValue | undefined,\n styles: StyleResolver,\n ): Omit<BlockFieldModel, 'responsive' | 'device' | 'mobileOverride'> {\n const effective =\n own ?? (field.inherits ? styles.value(field.inherits) : undefined) ?? field.defaultValue;\n return {\n key: field.key,\n tab: field.tab,\n control: field.control,\n labelKey: field.labelKey,\n options: field.options ?? [],\n own,\n effective,\n inherits: field.inherits,\n };\n }\n\n private find(\n blocks: BlockDocumentData['blocks'],\n id: string,\n ): BlockDocumentData['blocks'][number] | undefined {\n const stack = [...blocks];\n while (stack.length) {\n const block = stack.pop();\n if (!block) break;\n if (block.id === id) return block;\n stack.push(...(block.children ?? []));\n }\n return undefined;\n }\n}\n","import type { BlockDocument } from '../core/block-document';\nimport { EditorDocument } from '../core/document';\nimport type { Diagnostic, EditorDocumentData, SourceInput } from '../core/document';\nimport type { HtmlDocumentCodec } from '../codecs/html';\nimport type { BlockEmailRenderer } from './email-renderer';\nimport type { BlockPageGenerator } from './page-generator';\n\nexport class BlockConversionError extends Error {\n constructor(readonly diagnostics: readonly Diagnostic[]) {\n super('BLOCK_CONVERSION_FAILED');\n this.name = 'BlockConversionError';\n }\n}\n\n/**\n * \"Convert to editable HTML\": one way only, from a block piece (schema 2) to the HTML document\n * of the editor (schema 1), made of the final output of the generators. Nothing converts back.\n * The new document keeps the id and the title; its revision follows the block piece, so a\n * host saving it over the same record moves forward.\n */\nexport class BlockToHtmlConversion {\n constructor(\n private readonly codec: HtmlDocumentCodec,\n private readonly email: BlockEmailRenderer,\n private readonly page: BlockPageGenerator,\n ) {}\n\n async convert(document: BlockDocument): Promise<EditorDocumentData> {\n const source: SourceInput =\n document.kind === 'email'\n ? await this.email.render(document, 'final')\n : this.page.toHtml(document, 'final');\n const imported = this.codec.import(source, document.kind);\n if (!imported.document) throw new BlockConversionError(imported.diagnostics);\n return EditorDocument.from({\n ...imported.document,\n id: document.id,\n title: document.title,\n revision: document.revision + 1,\n }).snapshot();\n }\n}\n","{\n \"id\": \"email-blank\",\n \"kind\": \"email\",\n \"titleKey\": \"templates.blank\",\n \"descriptionKey\": \"templates.blankDescription\",\n \"document\": {\n \"title\": \"\",\n \"meta\": {\n \"lang\": \"pt-BR\"\n },\n \"styles\": {},\n \"blocks\": [\n {\n \"id\": \"s1\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Escreva seu conteúdo.</p>\"\n }\n }\n ]\n }\n ]\n }\n ]\n },\n \"translations\": {\n \"en\": {\n \"s1t1\": \"<p>Write your content.</p>\"\n },\n \"es\": {\n \"s1t1\": \"<p>Escribe tu contenido.</p>\"\n }\n }\n}\n","{\n \"id\": \"email-newsletter\",\n \"kind\": \"email\",\n \"titleKey\": \"templates.newsletter\",\n \"descriptionKey\": \"templates.newsletterDescription\",\n \"document\": {\n \"title\": \"\",\n \"meta\": {\n \"lang\": \"pt-BR\"\n },\n \"styles\": {},\n \"blocks\": [\n {\n \"id\": \"s1\",\n \"type\": \"section\",\n \"props\": {\n \"padding\": \"32px 0\"\n },\n \"children\": [\n {\n \"id\": \"s1c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>NOVIDADES</p>\",\n \"fontSize\": \"12px\",\n \"color\": \"#0d766e\"\n }\n },\n {\n \"id\": \"s1h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Olá, Nico Robin\",\n \"level\": \"h1\"\n }\n },\n {\n \"id\": \"s1t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Reunimos as novidades para sua próxima conversa. Edite esta mensagem antes de enviar.</p>\"\n }\n },\n {\n \"id\": \"s1d1\",\n \"type\": \"divider\",\n \"props\": {}\n },\n {\n \"id\": \"s1h2\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"O destaque do mês\",\n \"fontSize\": \"22px\"\n }\n },\n {\n \"id\": \"s1t3\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Conte uma novidade relevante e convide as pessoas a conhecer mais.</p>\"\n }\n },\n {\n \"id\": \"s1b1\",\n \"type\": \"button\",\n \"props\": {\n \"text\": \"Conhecer as novidades\",\n \"href\": \"https://example.com/novidades\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s2\",\n \"type\": \"section\",\n \"props\": {\n \"background\": \"transparent\"\n },\n \"children\": [\n {\n \"id\": \"s2c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2f1\",\n \"type\": \"footer\",\n \"props\": {\n \"text\": \"<p>Mensagem de exemplo. O rodapé de envio é fornecido pelo aplicativo.</p>\"\n }\n }\n ]\n }\n ]\n }\n ]\n },\n \"translations\": {\n \"en\": {\n \"s1t1\": \"<p>WHAT IS NEW</p>\",\n \"s1h1\": \"Hello, Nico Robin\",\n \"s1t2\": \"<p>Here is what is new for your next conversation. Edit this message before sending it.</p>\",\n \"s1h2\": \"The highlight of the month\",\n \"s1t3\": \"<p>Share something relevant and invite people to learn more.</p>\",\n \"s1b1\": \"See what is new\",\n \"s2f1\": \"<p>Sample message. The sending footer is added by the application.</p>\"\n },\n \"es\": {\n \"s1t1\": \"<p>NOVEDADES</p>\",\n \"s1h1\": \"Hola, Nico Robin\",\n \"s1t2\": \"<p>Reunimos las novedades para tu próxima conversación. Edita este mensaje antes de enviarlo.</p>\",\n \"s1h2\": \"Lo destacado del mes\",\n \"s1t3\": \"<p>Cuenta una novedad relevante e invita a las personas a conocer más.</p>\",\n \"s1b1\": \"Conocer las novedades\",\n \"s2f1\": \"<p>Mensaje de ejemplo. El pie de envío lo agrega la aplicación.</p>\"\n }\n }\n}\n","{\n \"id\": \"email-welcome\",\n \"kind\": \"email\",\n \"titleKey\": \"templates.welcome\",\n \"descriptionKey\": \"templates.welcomeDescription\",\n \"document\": {\n \"title\": \"\",\n \"meta\": {\n \"lang\": \"pt-BR\"\n },\n \"styles\": {},\n \"blocks\": [\n {\n \"id\": \"s1\",\n \"type\": \"section\",\n \"props\": {\n \"padding\": \"32px 0\"\n },\n \"children\": [\n {\n \"id\": \"s1c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>BOAS-VINDAS</p>\",\n \"fontSize\": \"12px\",\n \"color\": \"#0d766e\"\n }\n },\n {\n \"id\": \"s1h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Uma nova conversa começa aqui\",\n \"level\": \"h1\"\n }\n },\n {\n \"id\": \"s1t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Olá, Nico Robin. Obrigado pelo interesse. Veja como dar o próximo passo.</p>\"\n }\n },\n {\n \"id\": \"s1b1\",\n \"type\": \"button\",\n \"props\": {\n \"text\": \"Começar agora\",\n \"href\": \"https://example.com/comecar\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s2\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"1. Conheça a proposta\",\n \"level\": \"h3\",\n \"fontSize\": \"18px\"\n }\n },\n {\n \"id\": \"s2t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Encontre o que você precisa.</p>\"\n }\n }\n ]\n },\n {\n \"id\": \"s2c2\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2h2\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"2. Fale com a equipe\",\n \"level\": \"h3\",\n \"fontSize\": \"18px\"\n }\n },\n {\n \"id\": \"s2t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Escolha o melhor momento.</p>\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s3\",\n \"type\": \"section\",\n \"props\": {\n \"background\": \"transparent\"\n },\n \"children\": [\n {\n \"id\": \"s3c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s3f1\",\n \"type\": \"footer\",\n \"props\": {\n \"text\": \"<p>Mensagem de exemplo. O rodapé de envio é fornecido pelo aplicativo.</p>\"\n }\n }\n ]\n }\n ]\n }\n ]\n },\n \"translations\": {\n \"en\": {\n \"s1t1\": \"<p>WELCOME</p>\",\n \"s1h1\": \"A new conversation starts here\",\n \"s1t2\": \"<p>Hello, Nico Robin. Thank you for your interest. Here is how to take the next step.</p>\",\n \"s1b1\": \"Get started\",\n \"s2h1\": \"1. Get to know the offer\",\n \"s2t1\": \"<p>Find what you need.</p>\",\n \"s2h2\": \"2. Talk to the team\",\n \"s2t2\": \"<p>Choose the best time.</p>\",\n \"s3f1\": \"<p>Sample message. The sending footer is added by the application.</p>\"\n },\n \"es\": {\n \"s1t1\": \"<p>BIENVENIDA</p>\",\n \"s1h1\": \"Una nueva conversación empieza aquí\",\n \"s1t2\": \"<p>Hola, Nico Robin. Gracias por tu interés. Mira cómo dar el próximo paso.</p>\",\n \"s1b1\": \"Empezar ahora\",\n \"s2h1\": \"1. Conoce la propuesta\",\n \"s2t1\": \"<p>Encuentra lo que necesitas.</p>\",\n \"s2h2\": \"2. Habla con el equipo\",\n \"s2t2\": \"<p>Elige el mejor momento.</p>\",\n \"s3f1\": \"<p>Mensaje de ejemplo. El pie de envío lo agrega la aplicación.</p>\"\n }\n }\n}\n","{\n \"id\": \"page-event\",\n \"kind\": \"page\",\n \"titleKey\": \"templates.event\",\n \"descriptionKey\": \"templates.eventDescription\",\n \"document\": {\n \"title\": \"\",\n \"meta\": {\n \"lang\": \"pt-BR\"\n },\n \"styles\": {\n \"button\": {\n \"background\": \"#1f4e79\"\n },\n \"heading\": {\n \"color\": \"#13253a\"\n }\n },\n \"blocks\": [\n {\n \"id\": \"s1\",\n \"type\": \"section\",\n \"props\": {\n \"padding\": \"48px 0\"\n },\n \"children\": [\n {\n \"id\": \"s1c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>ENCONTRO</p>\",\n \"fontSize\": \"12px\"\n }\n },\n {\n \"id\": \"s1h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Uma conversa que merece seu tempo\",\n \"level\": \"h1\",\n \"fontSize\": \"48px\"\n }\n },\n {\n \"id\": \"s1t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Apresente o tema do encontro e o que os participantes vão aprender.</p>\"\n }\n },\n {\n \"id\": \"s1b1\",\n \"type\": \"button\",\n \"props\": {\n \"text\": \"Quero participar\",\n \"href\": \"#inscricao\",\n \"align\": \"left\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s2\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2c1\",\n \"type\": \"column\",\n \"props\": {\n \"weight\": 2\n },\n \"children\": [\n {\n \"id\": \"s2h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Uma visão prática\"\n }\n },\n {\n \"id\": \"s2t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Compartilhe ideias que possam ser aplicadas no dia a dia.</p>\"\n }\n }\n ]\n },\n {\n \"id\": \"s2c2\",\n \"type\": \"column\",\n \"props\": {\n \"weight\": 1\n },\n \"children\": [\n {\n \"id\": \"s2h2\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Espaço para perguntas\"\n }\n },\n {\n \"id\": \"s2t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Inclua as principais dúvidas na conversa.</p>\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s3\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s3c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s3h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Reserve seu lugar\"\n }\n },\n {\n \"id\": \"s3f1\",\n \"type\": \"form\",\n \"props\": {}\n },\n {\n \"id\": \"s3f2\",\n \"type\": \"footer\",\n \"props\": {\n \"text\": \"<p>Conteúdo de demonstração.</p>\"\n }\n }\n ]\n }\n ]\n }\n ]\n },\n \"translations\": {\n \"en\": {\n \"s1t1\": \"<p>EVENT</p>\",\n \"s1h1\": \"A conversation worth your time\",\n \"s1t2\": \"<p>Present the topic of the event and what participants will learn.</p>\",\n \"s1b1\": \"I want to join\",\n \"s2h1\": \"A practical view\",\n \"s2t1\": \"<p>Share ideas people can apply day to day.</p>\",\n \"s2h2\": \"Room for questions\",\n \"s2t2\": \"<p>Bring the main questions into the conversation.</p>\",\n \"s3h1\": \"Save your seat\",\n \"s3f2\": \"<p>Demonstration content.</p>\"\n },\n \"es\": {\n \"s1t1\": \"<p>ENCUENTRO</p>\",\n \"s1h1\": \"Una conversación que merece tu tiempo\",\n \"s1t2\": \"<p>Presenta el tema del encuentro y lo que los participantes van a aprender.</p>\",\n \"s1b1\": \"Quiero participar\",\n \"s2h1\": \"Una visión práctica\",\n \"s2t1\": \"<p>Comparte ideas que se puedan aplicar en el día a día.</p>\",\n \"s2h2\": \"Espacio para preguntas\",\n \"s2t2\": \"<p>Incluye las principales dudas en la conversación.</p>\",\n \"s3h1\": \"Reserva tu lugar\",\n \"s3f2\": \"<p>Contenido de demostración.</p>\"\n }\n }\n}\n","{\n \"id\": \"page-material\",\n \"kind\": \"page\",\n \"titleKey\": \"templates.material\",\n \"descriptionKey\": \"templates.materialDescription\",\n \"document\": {\n \"title\": \"\",\n \"meta\": {\n \"lang\": \"pt-BR\"\n },\n \"styles\": {},\n \"blocks\": [\n {\n \"id\": \"s1\",\n \"type\": \"section\",\n \"props\": {\n \"padding\": \"48px 0\"\n },\n \"children\": [\n {\n \"id\": \"s1c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s1t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>MATERIAL GRATUITO</p>\",\n \"fontSize\": \"12px\"\n }\n },\n {\n \"id\": \"s1h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Uma ideia para o seu próximo passo\",\n \"level\": \"h1\",\n \"fontSize\": \"48px\"\n }\n },\n {\n \"id\": \"s1t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Apresente o conteúdo e mostre como ele pode ajudar quem chega até esta página.</p>\"\n }\n },\n {\n \"id\": \"s1b1\",\n \"type\": \"button\",\n \"props\": {\n \"text\": \"Receber o material\",\n \"href\": \"#interesse\",\n \"align\": \"left\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s2\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"O que você vai encontrar\"\n }\n },\n {\n \"id\": \"s2t1\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Uma apresentação objetiva para transformar interesse em ação.</p>\"\n }\n }\n ]\n },\n {\n \"id\": \"s2c2\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s2h2\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Para quem é\"\n }\n },\n {\n \"id\": \"s2t2\",\n \"type\": \"text\",\n \"props\": {\n \"text\": \"<p>Descreva a pessoa que mais se beneficia deste conteúdo.</p>\"\n }\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s3\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s3c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s3h1\",\n \"type\": \"heading\",\n \"props\": {\n \"text\": \"Receba o conteúdo\"\n }\n },\n {\n \"id\": \"s3f1\",\n \"type\": \"form\",\n \"props\": {}\n }\n ]\n }\n ]\n },\n {\n \"id\": \"s4\",\n \"type\": \"section\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s4c1\",\n \"type\": \"column\",\n \"props\": {},\n \"children\": [\n {\n \"id\": \"s4d1\",\n \"type\": \"divider\",\n \"props\": {}\n },\n {\n \"id\": \"s4f1\",\n \"type\": \"footer\",\n \"props\": {\n \"text\": \"<p>Conteúdo de demonstração. Edite antes de publicar.</p>\"\n }\n }\n ]\n }\n ]\n }\n ]\n },\n \"translations\": {\n \"en\": {\n \"s1t1\": \"<p>FREE MATERIAL</p>\",\n \"s1h1\": \"An idea for your next step\",\n \"s1t2\": \"<p>Present the content and show how it can help whoever reaches this page.</p>\",\n \"s1b1\": \"Get the material\",\n \"s2h1\": \"What you will find\",\n \"s2t1\": \"<p>A clear overview to turn interest into action.</p>\",\n \"s2h2\": \"Who it is for\",\n \"s2t2\": \"<p>Describe the person who benefits most from this content.</p>\",\n \"s3h1\": \"Get the content\",\n \"s4f1\": \"<p>Demonstration content. Edit it before publishing.</p>\"\n },\n \"es\": {\n \"s1t1\": \"<p>MATERIAL GRATUITO</p>\",\n \"s1h1\": \"Una idea para tu próximo paso\",\n \"s1t2\": \"<p>Presenta el contenido y muestra cómo puede ayudar a quien llega a esta página.</p>\",\n \"s1b1\": \"Recibir el material\",\n \"s2h1\": \"Lo que vas a encontrar\",\n \"s2t1\": \"<p>Una presentación objetiva para convertir el interés en acción.</p>\",\n \"s2h2\": \"Para quién es\",\n \"s2t2\": \"<p>Describe a la persona que más se beneficia de este contenido.</p>\",\n \"s3h1\": \"Recibe el contenido\",\n \"s4f1\": \"<p>Contenido de demostración. Edítalo antes de publicar.</p>\"\n }\n }\n}\n","import { BlockDocument, LANGUAGE_TAG_PATTERN } from '../../core/block-document';\nimport type { Block, BlockRules } from '../../core/block-document';\nimport type { DocumentKind } from '../../core/document';\nimport emailBlank from './email-blank.json';\nimport emailNewsletter from './email-newsletter.json';\nimport emailWelcome from './email-welcome.json';\nimport pageEvent from './page-event.json';\nimport pageMaterial from './page-material.json';\n\nexport interface BlockTemplateDescriptor {\n readonly id: string;\n readonly kind: DocumentKind;\n readonly titleKey: string;\n readonly descriptionKey: string;\n}\n\nconst TEMPLATES: readonly unknown[] = [\n emailBlank,\n emailNewsletter,\n emailWelcome,\n pageMaterial,\n pageEvent,\n];\n\n/** Languages a template is written in besides its own (pt-BR): the texts of its blocks by id. */\nexport const TEMPLATE_LANGUAGES = ['en', 'es'] as const;\ntype TemplateLanguage = (typeof TEMPLATE_LANGUAGES)[number];\n\ninterface TemplateEntry extends BlockTemplateDescriptor {\n readonly document: { readonly title: string; readonly meta: unknown; readonly styles: unknown };\n readonly blocks: readonly Block[];\n readonly translations: Readonly<\n Partial<Record<TemplateLanguage, Readonly<Record<string, string>>>>\n >;\n}\n\n/** The template language of a language tag: `en-US` reads the English texts. */\nfunction templateLanguage(tag: string | undefined): TemplateLanguage | undefined {\n const base = tag?.toLowerCase().split('-')[0];\n return TEMPLATE_LANGUAGES.find((language) => language === base);\n}\n\n/**\n * Starting points of block pieces (schema 2), stored as JSON. They sit beside the schema 1\n * models of `TemplateCatalog`, which stay as they are. A piece made from a template gets new\n * block ids, so two pieces never share them.\n */\nexport class BlockTemplateCatalog {\n readonly #entries: readonly TemplateEntry[];\n\n constructor(private readonly rules: BlockRules) {\n this.#entries = TEMPLATES.map((template) => this.entry(template));\n }\n\n list(kind: DocumentKind): readonly BlockTemplateDescriptor[] {\n return this.#entries\n .filter((entry) => entry.kind === kind)\n .map(({ id, kind: entryKind, titleKey, descriptionKey }) =>\n Object.freeze({ id, kind: entryKind, titleKey, descriptionKey }),\n );\n }\n\n /** The blank piece of a kind: one section, one column, one text (a page has the same). */\n blank(\n kind: DocumentKind,\n documentId: string,\n nextId: () => string,\n language?: string,\n ): BlockDocument {\n return this.create('email-blank', documentId, nextId, kind, language);\n }\n\n /**\n * A new piece from a template, in the language given (pt-BR, English or Spanish texts; any\n * other language keeps pt-BR). The piece declares the language of its texts.\n */\n create(\n id: string,\n documentId: string,\n nextId: () => string,\n kind?: DocumentKind,\n language?: string,\n ): BlockDocument {\n const entry = this.#entries.find((candidate) => candidate.id === id);\n if (!entry) throw new Error('template.not_found');\n const translated = templateLanguage(language);\n const texts = translated ? entry.translations[translated] : undefined;\n const lang = texts && language && LANGUAGE_TAG_PATTERN.test(language) ? language : undefined;\n return BlockDocument.from(\n {\n schemaVersion: 2,\n id: documentId,\n kind: kind ?? entry.kind,\n revision: 0,\n title: entry.document.title,\n meta: lang ? { lang } : entry.document.meta,\n styles: entry.document.styles,\n blocks: entry.blocks.map((block) => this.reidentify(block, nextId, texts)),\n },\n this.rules,\n );\n }\n\n private reidentify(\n block: Block,\n nextId: () => string,\n texts?: Readonly<Record<string, string>>,\n ): Block {\n const text = texts?.[block.id];\n return {\n id: nextId(),\n type: block.type,\n props: { ...block.props, ...(text !== undefined ? { text } : {}) },\n ...(block.children\n ? { children: block.children.map((child) => this.reidentify(child, nextId, texts)) }\n : {}),\n };\n }\n\n private entry(template: unknown): TemplateEntry {\n // Validated once with the template's own ids, so a broken template fails at start-up.\n const value = template as {\n id: string;\n kind: DocumentKind;\n titleKey: string;\n descriptionKey: string;\n document: { title: string; meta: unknown; styles: unknown; blocks: unknown };\n translations?: Partial<Record<TemplateLanguage, Record<string, string>>>;\n };\n const document = BlockDocument.from(\n {\n schemaVersion: 2,\n id: value.id,\n kind: value.kind,\n revision: 0,\n title: value.document.title,\n meta: value.document.meta,\n styles: value.document.styles,\n blocks: value.document.blocks,\n },\n this.rules,\n );\n // Each translation names a block of the template with a text and passes its rules: a piece\n // in another language is built and validated here once.\n const translations = value.translations ?? {};\n for (const [language, texts] of Object.entries(translations)) {\n if (!templateLanguage(language)) throw new Error('template.invalid_translation');\n let translated = document;\n for (const [blockId, text] of Object.entries(texts ?? {})) {\n if (typeof translated.find(blockId)?.props.text !== 'string')\n throw new Error('template.invalid_translation');\n translated = translated.updateText(blockId, 'text', text);\n }\n }\n return {\n id: value.id,\n kind: value.kind,\n titleKey: value.titleKey,\n descriptionKey: value.descriptionKey,\n document: { title: document.title, meta: document.meta, styles: document.styles },\n blocks: document.blocks,\n translations,\n };\n }\n}\n","import { BlockDocument } from '../core/block-document';\nimport type { BlockDocumentData } from '../core/block-document';\nimport { parseAnyDocument } from '../core/any-document';\nimport type { AnyDocument } from '../core/any-document';\nimport type { DocumentKind, EditorDocumentData, SourceInput } from '../core/document';\nimport { DocumentHistory } from '../core/history';\nimport { BlockEditorSession } from '../application/block-session';\nimport type { BlockStorePort } from '../application/block-session';\nimport { BlockPlacementService } from '../application/block-placement';\nimport { BlockContentGuard } from '../blocks/content-guard';\nimport { BlockDefinitionRegistry } from '../blocks/definitions';\nimport { BlockMjmlGenerator } from '../blocks/email-generator';\nimport { BlockEmailRenderer } from '../blocks/email-renderer';\nimport { BlockPageGenerator } from '../blocks/page-generator';\nimport { BlockOutputRenderer } from '../blocks/block-output';\nimport { BlockInspector } from '../blocks/block-inspector';\nimport { BlockToHtmlConversion } from '../blocks/conversion';\nimport type { OutputMode } from '../blocks/block-type';\nimport { HtmlDocumentCodec } from '../codecs/html';\nimport { CssDocumentCodec } from '../codecs/css';\nimport type { GeneratedMjml, GeneratedMjmlCompilerPort } from '../compilation/generated-mjml';\nimport { CompileLanes } from '../compilation/compile-lanes';\nimport type { MjmlCompilerPort } from '../renderers/email-renderer';\nimport { HtmlDocumentAssembler } from '../renderers/preview-document';\nimport { SelectionPreviewRenderer } from '../renderers/selection-preview';\nimport { ContentPolicy } from '../security/policy';\nimport { SecureIdentifier } from '../security/identity';\nimport { UrlPolicy } from '../security/url-policy';\nimport { BlockTemplateCatalog } from '../templates/blocks/catalog';\nimport { BlockEditorController } from '../vue/block-controller';\n\n/** A compiler of both kinds of MJML; the browser and the Node compilers are. */\nexport type BlockCompiler = MjmlCompilerPort & GeneratedMjmlCompilerPort & { dispose?(): void };\n\nexport interface BlockToolkitOptions {\n /** A compiler the host owns; otherwise the toolkit creates one and disposes of it. */\n readonly compiler?: BlockCompiler;\n /** Placeholders accepted as whole link addresses, e.g. `{{unsubscribe_url}}`. */\n readonly exactUrlPlaceholders?: readonly string[];\n}\n\n/**\n * What a host needs of block pieces (schema 2) without the editor: validate what it stores,\n * generate and compile the output, and convert a piece to the HTML document (schema 1).\n */\nexport interface BlockToolkit {\n readonly registry: BlockDefinitionRegistry;\n readonly templates: BlockTemplateCatalog;\n /** A stored piece of either schema; throws `DocumentValidationError` (or a subclass). */\n parse(input: unknown): AnyDocument;\n /** A block piece; throws `BlockDocumentError`. */\n parseBlocks(input: unknown): BlockDocument;\n /** A new piece of a kind, blank or from a template, with fresh block ids. */\n /**\n * A new piece from a template (the blank one by default), with the texts in `language`\n * (pt-BR by default; English and Spanish are written too).\n */\n create(\n kind: DocumentKind,\n documentId: string,\n templateId?: string,\n language?: string,\n ): BlockDocument;\n /** The HTML and CSS of a page piece. */\n generatePage(document: BlockDocument, mode?: OutputMode): SourceInput;\n /** The MJML of an e-mail piece, with the raw regions only the compilers accept. */\n generateMjml(document: BlockDocument, mode?: OutputMode): GeneratedMjml;\n /** The compiled HTML of an e-mail piece, checked against the e-mail rules. */\n compileEmail(document: BlockDocument): Promise<SourceInput>;\n /** The final output of a piece of either kind: what is stored, sent or published. */\n render(document: BlockDocument): Promise<SourceInput>;\n /** \"Convert to editable HTML\": one way only, to a schema 1 document. */\n convert(document: BlockDocument): Promise<EditorDocumentData>;\n dispose(): void;\n}\n\nexport interface BlockEditorOptions extends BlockToolkitOptions {\n readonly kind?: DocumentKind;\n /** A stored piece (schema 2); validated here. */\n readonly document?: BlockDocumentData;\n /** The template a new piece starts from; the blank one of its kind by default. */\n readonly template?: string;\n /** Language of the texts of a new piece and of the templates applied to it. */\n readonly language?: string;\n /** Id of a new piece. */\n readonly documentId?: string;\n readonly readOnly?: boolean;\n readonly persistedRevision?: number;\n readonly store?: BlockStorePort;\n readonly previewImageOrigins?: readonly string[];\n readonly onObserverError?: (error: unknown) => void;\n}\n\nexport interface BlockEditorInstance {\n readonly session: BlockEditorSession;\n readonly controller: BlockEditorController;\n readonly selectionRenderer: SelectionPreviewRenderer;\n readonly toolkit: BlockToolkit;\n dispose(): void;\n}\n\ninterface Parts {\n readonly toolkit: BlockToolkit;\n readonly urls: UrlPolicy;\n readonly codec: HtmlDocumentCodec;\n readonly policy: ContentPolicy;\n readonly output: BlockOutputRenderer;\n}\n\n/** The only place that builds the graph of block pieces; every instance owns its state. */\nexport class BlockEditorFactory {\n constructor(private readonly compilerFactory: () => BlockCompiler) {}\n\n toolkit(options: BlockToolkitOptions = {}): BlockToolkit {\n return this.parts(options).toolkit;\n }\n\n create(options: BlockEditorOptions = {}): BlockEditorInstance {\n const { toolkit, urls, codec, policy, output } = this.parts(options);\n const identifiers = new SecureIdentifier();\n const kind = options.kind ?? options.document?.kind ?? 'page';\n const document = options.document\n ? toolkit.parseBlocks(options.document)\n : toolkit.create(\n kind,\n options.documentId ?? `piece-${identifiers.next()}`,\n options.template,\n options.language,\n );\n if (document.kind !== kind) throw new Error('INITIAL_KIND_MISMATCH');\n const session = new BlockEditorSession(\n {\n factory: toolkit.registry,\n output: { render: (piece) => toolkit.render(piece) },\n identifiers,\n history: new DocumentHistory<BlockDocument>(),\n ...(options.store ? { store: options.store } : {}),\n },\n {\n document,\n ...(options.readOnly !== undefined ? { readOnly: options.readOnly } : {}),\n ...(options.persistedRevision !== undefined\n ? { persistedRevision: options.persistedRevision }\n : {}),\n ...(options.onObserverError ? { onObserverError: options.onObserverError } : {}),\n },\n );\n const controller = new BlockEditorController({\n session,\n registry: toolkit.registry,\n inspector: new BlockInspector(toolkit.registry),\n placement: new BlockPlacementService(toolkit.registry),\n templates: toolkit.templates,\n output,\n urls,\n });\n const assembler = new HtmlDocumentAssembler(codec, policy, options.previewImageOrigins);\n return Object.freeze({\n session,\n controller,\n toolkit,\n selectionRenderer: new SelectionPreviewRenderer(codec, policy, assembler),\n dispose() {\n session.dispose();\n toolkit.dispose();\n },\n });\n }\n\n private static ofKind(document: BlockDocument, kind: DocumentKind): BlockDocument {\n if (document.kind !== kind) throw new Error('BLOCK_KIND_MISMATCH');\n return document;\n }\n\n private parts(options: BlockToolkitOptions): Parts {\n const compiler = options.compiler ?? this.compilerFactory();\n const urls = new UrlPolicy(\n options.exactUrlPlaceholders ? { exactUrlPlaceholders: options.exactUrlPlaceholders } : {},\n );\n const css = new CssDocumentCodec(urls);\n const policy = new ContentPolicy(urls, css);\n const codec = new HtmlDocumentCodec(policy);\n const registry = new BlockDefinitionRegistry(new BlockContentGuard(urls));\n const mjml = new BlockMjmlGenerator(registry);\n const pages = new BlockPageGenerator(registry);\n // The preview of every revision and the save share the compiler without taking each other's\n // place: previews run one at a time (the newest waiting), the final output in its own lane.\n const lanes = new CompileLanes(compiler);\n const emails = new BlockEmailRenderer(mjml, lanes.final);\n const output = new BlockOutputRenderer(\n registry,\n pages,\n emails,\n new BlockEmailRenderer(mjml, lanes.preview),\n );\n const conversion = new BlockToHtmlConversion(codec, emails, pages);\n const templates = new BlockTemplateCatalog(registry);\n const identifiers = new SecureIdentifier();\n const nextId = (): string => `b${identifiers.next().slice(0, 20)}`;\n const toolkit: BlockToolkit = Object.freeze({\n registry,\n templates,\n parse: (input: unknown) => parseAnyDocument(input, registry),\n parseBlocks: (input: unknown) => BlockDocument.from(input, registry),\n create: (kind: DocumentKind, documentId: string, templateId?: string, language?: string) =>\n templateId\n ? templates.create(templateId, documentId, nextId, kind, language)\n : templates.blank(kind, documentId, nextId, language),\n generatePage: (document: BlockDocument, mode: OutputMode = 'final') =>\n pages.toHtml(BlockEditorFactory.ofKind(document, 'page'), mode),\n generateMjml: (document: BlockDocument, mode: OutputMode = 'final') =>\n mjml.toMjml(BlockEditorFactory.ofKind(document, 'email'), mode),\n compileEmail: (document: BlockDocument) =>\n emails.render(BlockEditorFactory.ofKind(document, 'email'), 'final'),\n render: (document: BlockDocument) => output.render(document),\n convert: (document: BlockDocument) => conversion.convert(document),\n dispose: () => {\n if (!options.compiler) compiler.dispose?.();\n },\n });\n return { toolkit, urls, codec, policy, output };\n }\n}\n"],"mappings":"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"}