@aquera/nile-elements 2.0.16 → 2.0.17

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 (354) hide show
  1. package/README.md +3 -0
  2. package/dist/{index-f6944844.cjs.js → index-0c0c869d.cjs.js} +2 -2
  3. package/dist/{index-f6944844.cjs.js.map → index-0c0c869d.cjs.js.map} +1 -1
  4. package/dist/{index-403841c7.cjs.js → index-129ef6fb.cjs.js} +3 -3
  5. package/dist/{index-403841c7.cjs.js.map → index-129ef6fb.cjs.js.map} +1 -1
  6. package/dist/{index-1faa963c.esm.js → index-36f2a6b5.esm.js} +1 -1
  7. package/dist/index-4df50481.esm.js +1 -0
  8. package/dist/index-5d34cff1.esm.js +1 -0
  9. package/dist/index-7ae95edd.cjs.js +2 -0
  10. package/dist/{index-3ca67627.cjs.js.map → index-7ae95edd.cjs.js.map} +1 -1
  11. package/dist/index-7ca72b78.esm.js +1 -0
  12. package/dist/index-bbe23ad8.cjs.js +2 -0
  13. package/dist/index-bbe23ad8.cjs.js.map +1 -0
  14. package/dist/index-ccc6a799.cjs.js +5 -0
  15. package/dist/index-ccc6a799.cjs.js.map +1 -0
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.esm.js +1 -1
  18. package/dist/index.js +122 -70
  19. package/dist/nile-auto-complete/index.cjs.js +1 -1
  20. package/dist/nile-auto-complete/nile-auto-complete.cjs.js +1 -1
  21. package/dist/nile-auto-complete/portal-manager.cjs.js +1 -1
  22. package/dist/nile-auto-complete/portal-utils.cjs.js +1 -1
  23. package/dist/nile-code-editor/extensionSetup.cjs.js +2 -2
  24. package/dist/nile-code-editor/index.cjs.js +1 -1
  25. package/dist/nile-code-editor/nile-code-editor.cjs.js +1 -1
  26. package/dist/nile-code-editor/theme.cjs.js +1 -1
  27. package/dist/nile-color-picker/index.cjs.js +1 -1
  28. package/dist/nile-color-picker/nile-color-picker.cjs.js +1 -1
  29. package/dist/nile-combobox/index.cjs.js +1 -1
  30. package/dist/nile-combobox/nile-combobox.cjs.js +1 -1
  31. package/dist/nile-combobox/portal-manager.cjs.js +1 -1
  32. package/dist/nile-context-menu/index.cjs.js +1 -1
  33. package/dist/nile-context-menu/nile-context-menu.cjs.js +1 -1
  34. package/dist/nile-context-submenu/index.cjs.js +1 -1
  35. package/dist/nile-context-submenu/nile-context-submenu.cjs.js +1 -1
  36. package/dist/nile-detail/index.cjs.js +1 -1
  37. package/dist/nile-detail/nile-detail.cjs.js +1 -1
  38. package/dist/nile-dropdown/index.cjs.js +1 -1
  39. package/dist/nile-dropdown/nile-dropdown.cjs.js +1 -1
  40. package/dist/nile-dropdown/portal-manager.cjs.js +1 -1
  41. package/dist/nile-file-upload/index.cjs.js +1 -1
  42. package/dist/nile-file-upload/nile-file-upload.cjs.js +1 -1
  43. package/dist/nile-file-upload/nile-file-upload.template.cjs.js +1 -1
  44. package/dist/nile-floating-panel/index.cjs.js +1 -1
  45. package/dist/nile-floating-panel/nile-floating-panel.cjs.js +1 -1
  46. package/dist/nile-lite-tooltip/index.cjs.js +1 -1
  47. package/dist/nile-lite-tooltip/nile-lite-tooltip.cjs.js +1 -1
  48. package/dist/nile-markdown-editor/index.cjs.js +1 -1
  49. package/dist/nile-markdown-editor/nile-markdown-editor.cjs.js +1 -1
  50. package/dist/nile-popover/index.cjs.js +1 -1
  51. package/dist/nile-popover/nile-popover.cjs.js +1 -1
  52. package/dist/nile-popover/portal-manager.cjs.js +1 -1
  53. package/dist/nile-popup/index.cjs.js +1 -1
  54. package/dist/nile-popup/nile-popup.cjs.js +1 -1
  55. package/dist/nile-segmented-progress-bar/index.cjs.js +1 -1
  56. package/dist/nile-segmented-progress-bar/nile-segmented-progress-bar.cjs.js +1 -1
  57. package/dist/nile-select/index.cjs.js +1 -1
  58. package/dist/nile-select/nile-select.cjs.js +1 -1
  59. package/dist/nile-select/portal-manager.cjs.js +1 -1
  60. package/dist/nile-side-bar-action/index.cjs.js +1 -1
  61. package/dist/nile-side-bar-action/nile-side-bar-action.cjs.js +1 -1
  62. package/dist/nile-side-bar-action/portal-manager.cjs.js +1 -1
  63. package/dist/nile-tooltip/index.cjs.js +1 -1
  64. package/dist/nile-tooltip/nile-tooltip.cjs.js +1 -1
  65. package/dist/nile-virtual-select/index.cjs.js +1 -1
  66. package/dist/nile-virtual-select/nile-virtual-select.cjs.js +1 -1
  67. package/dist/nile-virtual-select/portal-manager.cjs.js +1 -1
  68. package/dist/nile-virtual-select/renderer.cjs.js +1 -1
  69. package/dist/nile-wysiwyg-editor/engine/commands.cjs.js +1 -1
  70. package/dist/nile-wysiwyg-editor/engine/commands.cjs.js.map +1 -1
  71. package/dist/nile-wysiwyg-editor/engine/commands.esm.js +1 -1
  72. package/dist/nile-wysiwyg-editor/engine/create-state.cjs.js +1 -1
  73. package/dist/nile-wysiwyg-editor/engine/create-state.cjs.js.map +1 -1
  74. package/dist/nile-wysiwyg-editor/engine/create-state.esm.js +1 -1
  75. package/dist/nile-wysiwyg-editor/engine/email-css.cjs.js +2 -0
  76. package/dist/nile-wysiwyg-editor/engine/email-css.cjs.js.map +1 -0
  77. package/dist/nile-wysiwyg-editor/engine/email-css.esm.js +1 -0
  78. package/dist/nile-wysiwyg-editor/engine/email-render.cjs.js +2 -0
  79. package/dist/nile-wysiwyg-editor/engine/email-render.cjs.js.map +1 -0
  80. package/dist/nile-wysiwyg-editor/engine/email-render.esm.js +1 -0
  81. package/dist/nile-wysiwyg-editor/engine/html-detect.cjs.js +2 -0
  82. package/dist/nile-wysiwyg-editor/engine/html-detect.cjs.js.map +1 -0
  83. package/dist/nile-wysiwyg-editor/engine/html-detect.esm.js +1 -0
  84. package/dist/nile-wysiwyg-editor/engine/index.cjs.js +1 -1
  85. package/dist/nile-wysiwyg-editor/engine/index.esm.js +1 -1
  86. package/dist/nile-wysiwyg-editor/engine/inputrules.cjs.js +1 -1
  87. package/dist/nile-wysiwyg-editor/engine/inputrules.cjs.js.map +1 -1
  88. package/dist/nile-wysiwyg-editor/engine/inputrules.esm.js +1 -1
  89. package/dist/nile-wysiwyg-editor/engine/keymap.cjs.js +1 -1
  90. package/dist/nile-wysiwyg-editor/engine/keymap.cjs.js.map +1 -1
  91. package/dist/nile-wysiwyg-editor/engine/keymap.esm.js +1 -1
  92. package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.cjs.js +1 -1
  93. package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.cjs.js.map +1 -1
  94. package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.esm.js +1 -1
  95. package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.cjs.js +1 -1
  96. package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.cjs.js.map +1 -1
  97. package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.esm.js +1 -1
  98. package/dist/nile-wysiwyg-editor/engine/plugins/embeds.cjs.js +1 -1
  99. package/dist/nile-wysiwyg-editor/engine/plugins/embeds.cjs.js.map +1 -1
  100. package/dist/nile-wysiwyg-editor/engine/plugins/embeds.esm.js +1 -1
  101. package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.cjs.js +1 -1
  102. package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.cjs.js.map +1 -1
  103. package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.esm.js +1 -1
  104. package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.cjs.js +1 -1
  105. package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.cjs.js.map +1 -1
  106. package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.esm.js +1 -1
  107. package/dist/nile-wysiwyg-editor/engine/plugins/image-view.cjs.js +1 -1
  108. package/dist/nile-wysiwyg-editor/engine/plugins/image-view.cjs.js.map +1 -1
  109. package/dist/nile-wysiwyg-editor/engine/plugins/image-view.esm.js +1 -1
  110. package/dist/nile-wysiwyg-editor/engine/plugins/image.cjs.js +1 -1
  111. package/dist/nile-wysiwyg-editor/engine/plugins/image.cjs.js.map +1 -1
  112. package/dist/nile-wysiwyg-editor/engine/plugins/image.esm.js +1 -1
  113. package/dist/nile-wysiwyg-editor/engine/plugins/link.cjs.js +1 -1
  114. package/dist/nile-wysiwyg-editor/engine/plugins/link.cjs.js.map +1 -1
  115. package/dist/nile-wysiwyg-editor/engine/plugins/link.esm.js +1 -1
  116. package/dist/nile-wysiwyg-editor/engine/plugins/max-length.cjs.js +1 -1
  117. package/dist/nile-wysiwyg-editor/engine/plugins/max-length.cjs.js.map +1 -1
  118. package/dist/nile-wysiwyg-editor/engine/plugins/max-length.esm.js +1 -1
  119. package/dist/nile-wysiwyg-editor/engine/plugins/paste.cjs.js +1 -1
  120. package/dist/nile-wysiwyg-editor/engine/plugins/paste.cjs.js.map +1 -1
  121. package/dist/nile-wysiwyg-editor/engine/plugins/paste.esm.js +1 -1
  122. package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.cjs.js +1 -1
  123. package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.cjs.js.map +1 -1
  124. package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.esm.js +1 -1
  125. package/dist/nile-wysiwyg-editor/engine/plugins/single-line.cjs.js +1 -1
  126. package/dist/nile-wysiwyg-editor/engine/plugins/single-line.cjs.js.map +1 -1
  127. package/dist/nile-wysiwyg-editor/engine/plugins/single-line.esm.js +1 -1
  128. package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.cjs.js +1 -1
  129. package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.cjs.js.map +1 -1
  130. package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.esm.js +1 -1
  131. package/dist/nile-wysiwyg-editor/engine/plugins/tables.cjs.js +1 -1
  132. package/dist/nile-wysiwyg-editor/engine/plugins/tables.cjs.js.map +1 -1
  133. package/dist/nile-wysiwyg-editor/engine/plugins/tables.esm.js +1 -1
  134. package/dist/nile-wysiwyg-editor/engine/sanitize.cjs.js +2 -1
  135. package/dist/nile-wysiwyg-editor/engine/sanitize.cjs.js.map +1 -1
  136. package/dist/nile-wysiwyg-editor/engine/sanitize.esm.js +1 -1
  137. package/dist/nile-wysiwyg-editor/engine/schema.cjs.js +1 -1
  138. package/dist/nile-wysiwyg-editor/engine/schema.cjs.js.map +1 -1
  139. package/dist/nile-wysiwyg-editor/engine/schema.esm.js +1 -1
  140. package/dist/nile-wysiwyg-editor/engine/selection-state.cjs.js +1 -1
  141. package/dist/nile-wysiwyg-editor/engine/selection-state.cjs.js.map +1 -1
  142. package/dist/nile-wysiwyg-editor/engine/selection-state.esm.js +1 -1
  143. package/dist/nile-wysiwyg-editor/engine/serializer.cjs.js +1 -1
  144. package/dist/nile-wysiwyg-editor/engine/serializer.cjs.js.map +1 -1
  145. package/dist/nile-wysiwyg-editor/engine/serializer.esm.js +1 -1
  146. package/dist/nile-wysiwyg-editor/index.cjs.js +1 -1
  147. package/dist/nile-wysiwyg-editor/index.esm.js +1 -1
  148. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.cjs.js +1 -1
  149. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.cjs.js.map +1 -1
  150. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.cjs.js +1 -1
  151. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.cjs.js.map +1 -1
  152. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.esm.js +45 -4
  153. package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.esm.js +2 -2
  154. package/dist/nile-wysiwyg-editor/nile-wysiwyg-toolbar/index.cjs.js +1 -1
  155. package/dist/nile-wysiwyg-editor/nile-wysiwyg-toolbar/nile-wysiwyg-toolbar.cjs.js +1 -1
  156. package/dist/nile-wysiwyg-editor/ui/bookmark-panel.cjs.js +1 -1
  157. package/dist/nile-wysiwyg-editor/ui/bookmark-panel.cjs.js.map +1 -1
  158. package/dist/nile-wysiwyg-editor/ui/bookmark-panel.esm.js +2 -2
  159. package/dist/nile-wysiwyg-editor/ui/bubble-menu.cjs.js +1 -1
  160. package/dist/nile-wysiwyg-editor/ui/bubble-menu.cjs.js.map +1 -1
  161. package/dist/nile-wysiwyg-editor/ui/bubble-menu.esm.js +5 -5
  162. package/dist/nile-wysiwyg-editor/ui/code-block-menu.cjs.js +1 -1
  163. package/dist/nile-wysiwyg-editor/ui/code-block-menu.cjs.js.map +1 -1
  164. package/dist/nile-wysiwyg-editor/ui/code-block-menu.esm.js +1 -1
  165. package/dist/nile-wysiwyg-editor/ui/embed-menu.cjs.js +1 -1
  166. package/dist/nile-wysiwyg-editor/ui/embed-menu.cjs.js.map +1 -1
  167. package/dist/nile-wysiwyg-editor/ui/embed-menu.esm.js +1 -1
  168. package/dist/nile-wysiwyg-editor/ui/embed-panel.cjs.js +1 -1
  169. package/dist/nile-wysiwyg-editor/ui/embed-panel.cjs.js.map +1 -1
  170. package/dist/nile-wysiwyg-editor/ui/embed-panel.esm.js +2 -2
  171. package/dist/nile-wysiwyg-editor/ui/emoji-picker.cjs.js +1 -1
  172. package/dist/nile-wysiwyg-editor/ui/emoji-picker.cjs.js.map +1 -1
  173. package/dist/nile-wysiwyg-editor/ui/emoji-picker.esm.js +1 -1
  174. package/dist/nile-wysiwyg-editor/ui/find-replace.cjs.js +1 -1
  175. package/dist/nile-wysiwyg-editor/ui/find-replace.cjs.js.map +1 -1
  176. package/dist/nile-wysiwyg-editor/ui/find-replace.esm.js +3 -3
  177. package/dist/nile-wysiwyg-editor/ui/image-menu.cjs.js +1 -1
  178. package/dist/nile-wysiwyg-editor/ui/image-menu.cjs.js.map +1 -1
  179. package/dist/nile-wysiwyg-editor/ui/image-menu.esm.js +3 -3
  180. package/dist/nile-wysiwyg-editor/ui/image-panel.cjs.js +1 -1
  181. package/dist/nile-wysiwyg-editor/ui/image-panel.cjs.js.map +1 -1
  182. package/dist/nile-wysiwyg-editor/ui/image-panel.esm.js +1 -1
  183. package/dist/nile-wysiwyg-editor/ui/insert-menu.cjs.js +1 -1
  184. package/dist/nile-wysiwyg-editor/ui/insert-menu.cjs.js.map +1 -1
  185. package/dist/nile-wysiwyg-editor/ui/insert-menu.esm.js +1 -1
  186. package/dist/nile-wysiwyg-editor/ui/link-editor.cjs.js +1 -1
  187. package/dist/nile-wysiwyg-editor/ui/link-editor.cjs.js.map +1 -1
  188. package/dist/nile-wysiwyg-editor/ui/link-editor.esm.js +9 -9
  189. package/dist/nile-wysiwyg-editor/ui/markdown-panel.cjs.js +1 -1
  190. package/dist/nile-wysiwyg-editor/ui/markdown-panel.cjs.js.map +1 -1
  191. package/dist/nile-wysiwyg-editor/ui/markdown-panel.esm.js +1 -1
  192. package/dist/nile-wysiwyg-editor/ui/math-panel.cjs.js +1 -1
  193. package/dist/nile-wysiwyg-editor/ui/math-panel.cjs.js.map +1 -1
  194. package/dist/nile-wysiwyg-editor/ui/math-panel.esm.js +1 -1
  195. package/dist/nile-wysiwyg-editor/ui/shortcut-help.cjs.js +1 -1
  196. package/dist/nile-wysiwyg-editor/ui/shortcut-help.cjs.js.map +1 -1
  197. package/dist/nile-wysiwyg-editor/ui/shortcut-help.esm.js +1 -1
  198. package/dist/nile-wysiwyg-editor/ui/source-view.cjs.js +1 -1
  199. package/dist/nile-wysiwyg-editor/ui/source-view.cjs.js.map +1 -1
  200. package/dist/nile-wysiwyg-editor/ui/source-view.esm.js +4 -4
  201. package/dist/nile-wysiwyg-editor/ui/special-chars.cjs.js +1 -1
  202. package/dist/nile-wysiwyg-editor/ui/special-chars.cjs.js.map +1 -1
  203. package/dist/nile-wysiwyg-editor/ui/special-chars.esm.js +1 -1
  204. package/dist/nile-wysiwyg-editor/ui/suggest-list.cjs.js +1 -1
  205. package/dist/nile-wysiwyg-editor/ui/suggest-list.cjs.js.map +1 -1
  206. package/dist/nile-wysiwyg-editor/ui/suggest-list.esm.js +23 -12
  207. package/dist/nile-wysiwyg-editor/ui/table-grid-picker.cjs.js +1 -1
  208. package/dist/nile-wysiwyg-editor/ui/table-grid-picker.cjs.js.map +1 -1
  209. package/dist/nile-wysiwyg-editor/ui/table-grid-picker.esm.js +7 -7
  210. package/dist/nile-wysiwyg-editor/ui/table-menu.cjs.js +1 -1
  211. package/dist/nile-wysiwyg-editor/ui/table-menu.cjs.js.map +1 -1
  212. package/dist/nile-wysiwyg-editor/ui/table-menu.esm.js +1 -1
  213. package/dist/src/nile-wysiwyg-editor/engine/create-state.d.ts +5 -0
  214. package/dist/src/nile-wysiwyg-editor/engine/create-state.js +2 -0
  215. package/dist/src/nile-wysiwyg-editor/engine/create-state.js.map +1 -1
  216. package/dist/src/nile-wysiwyg-editor/engine/email-css.d.ts +14 -0
  217. package/dist/src/nile-wysiwyg-editor/engine/email-css.js +140 -0
  218. package/dist/src/nile-wysiwyg-editor/engine/email-css.js.map +1 -0
  219. package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.d.ts +1 -0
  220. package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.js +1045 -0
  221. package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.js.map +1 -0
  222. package/dist/src/nile-wysiwyg-editor/engine/email-render.d.ts +11 -0
  223. package/dist/src/nile-wysiwyg-editor/engine/email-render.js +93 -0
  224. package/dist/src/nile-wysiwyg-editor/engine/email-render.js.map +1 -0
  225. package/dist/src/nile-wysiwyg-editor/engine/html-detect.d.ts +2 -0
  226. package/dist/src/nile-wysiwyg-editor/engine/html-detect.js +24 -0
  227. package/dist/src/nile-wysiwyg-editor/engine/html-detect.js.map +1 -0
  228. package/dist/src/nile-wysiwyg-editor/engine/index.d.ts +4 -1
  229. package/dist/src/nile-wysiwyg-editor/engine/index.js +3 -1
  230. package/dist/src/nile-wysiwyg-editor/engine/index.js.map +1 -1
  231. package/dist/src/nile-wysiwyg-editor/engine/inputrules.d.ts +0 -5
  232. package/dist/src/nile-wysiwyg-editor/engine/inputrules.js +19 -0
  233. package/dist/src/nile-wysiwyg-editor/engine/inputrules.js.map +1 -1
  234. package/dist/src/nile-wysiwyg-editor/engine/plugins/image-view.js +3 -2
  235. package/dist/src/nile-wysiwyg-editor/engine/plugins/image-view.js.map +1 -1
  236. package/dist/src/nile-wysiwyg-editor/engine/plugins/link.d.ts +4 -0
  237. package/dist/src/nile-wysiwyg-editor/engine/plugins/link.js +56 -1
  238. package/dist/src/nile-wysiwyg-editor/engine/plugins/link.js.map +1 -1
  239. package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.d.ts +5 -0
  240. package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.js +27 -6
  241. package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.js.map +1 -1
  242. package/dist/src/nile-wysiwyg-editor/engine/plugins/tables.js +30 -7
  243. package/dist/src/nile-wysiwyg-editor/engine/plugins/tables.js.map +1 -1
  244. package/dist/src/nile-wysiwyg-editor/engine/pm.test.js +46 -0
  245. package/dist/src/nile-wysiwyg-editor/engine/pm.test.js.map +1 -1
  246. package/dist/src/nile-wysiwyg-editor/engine/sanitize.d.ts +9 -1
  247. package/dist/src/nile-wysiwyg-editor/engine/sanitize.js +730 -7
  248. package/dist/src/nile-wysiwyg-editor/engine/sanitize.js.map +1 -1
  249. package/dist/src/nile-wysiwyg-editor/engine/schema.d.ts +3 -0
  250. package/dist/src/nile-wysiwyg-editor/engine/schema.js +215 -34
  251. package/dist/src/nile-wysiwyg-editor/engine/schema.js.map +1 -1
  252. package/dist/src/nile-wysiwyg-editor/engine/selection-state.js +3 -1
  253. package/dist/src/nile-wysiwyg-editor/engine/selection-state.js.map +1 -1
  254. package/dist/src/nile-wysiwyg-editor/engine/serializer.d.ts +12 -4
  255. package/dist/src/nile-wysiwyg-editor/engine/serializer.js +18 -8
  256. package/dist/src/nile-wysiwyg-editor/engine/serializer.js.map +1 -1
  257. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.d.ts +1 -0
  258. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.js +287 -0
  259. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.js.map +1 -0
  260. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.js +45 -4
  261. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.js.map +1 -1
  262. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.d.ts +23 -0
  263. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.js +113 -15
  264. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.js.map +1 -1
  265. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.js +213 -0
  266. package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.js.map +1 -1
  267. package/dist/src/nile-wysiwyg-editor/ui/bookmark-panel.js +2 -2
  268. package/dist/src/nile-wysiwyg-editor/ui/bookmark-panel.js.map +1 -1
  269. package/dist/src/nile-wysiwyg-editor/ui/bubble-menu.js +1 -1
  270. package/dist/src/nile-wysiwyg-editor/ui/bubble-menu.js.map +1 -1
  271. package/dist/src/nile-wysiwyg-editor/ui/embed-menu.js +1 -1
  272. package/dist/src/nile-wysiwyg-editor/ui/embed-menu.js.map +1 -1
  273. package/dist/src/nile-wysiwyg-editor/ui/embed-panel.js +1 -1
  274. package/dist/src/nile-wysiwyg-editor/ui/embed-panel.js.map +1 -1
  275. package/dist/src/nile-wysiwyg-editor/ui/emoji-picker.js +1 -1
  276. package/dist/src/nile-wysiwyg-editor/ui/emoji-picker.js.map +1 -1
  277. package/dist/src/nile-wysiwyg-editor/ui/find-replace.js +1 -1
  278. package/dist/src/nile-wysiwyg-editor/ui/find-replace.js.map +1 -1
  279. package/dist/src/nile-wysiwyg-editor/ui/image-menu.js +1 -1
  280. package/dist/src/nile-wysiwyg-editor/ui/image-menu.js.map +1 -1
  281. package/dist/src/nile-wysiwyg-editor/ui/image-panel.js +1 -1
  282. package/dist/src/nile-wysiwyg-editor/ui/image-panel.js.map +1 -1
  283. package/dist/src/nile-wysiwyg-editor/ui/insert-menu.js +1 -1
  284. package/dist/src/nile-wysiwyg-editor/ui/insert-menu.js.map +1 -1
  285. package/dist/src/nile-wysiwyg-editor/ui/link-editor.js +2 -2
  286. package/dist/src/nile-wysiwyg-editor/ui/link-editor.js.map +1 -1
  287. package/dist/src/nile-wysiwyg-editor/ui/markdown-panel.js +1 -1
  288. package/dist/src/nile-wysiwyg-editor/ui/markdown-panel.js.map +1 -1
  289. package/dist/src/nile-wysiwyg-editor/ui/math-panel.js +1 -1
  290. package/dist/src/nile-wysiwyg-editor/ui/math-panel.js.map +1 -1
  291. package/dist/src/nile-wysiwyg-editor/ui/shortcut-help.js +1 -1
  292. package/dist/src/nile-wysiwyg-editor/ui/shortcut-help.js.map +1 -1
  293. package/dist/src/nile-wysiwyg-editor/ui/source-view.js +2 -2
  294. package/dist/src/nile-wysiwyg-editor/ui/source-view.js.map +1 -1
  295. package/dist/src/nile-wysiwyg-editor/ui/special-chars.js +1 -1
  296. package/dist/src/nile-wysiwyg-editor/ui/special-chars.js.map +1 -1
  297. package/dist/src/nile-wysiwyg-editor/ui/suggest-list.js +14 -3
  298. package/dist/src/nile-wysiwyg-editor/ui/suggest-list.js.map +1 -1
  299. package/dist/src/nile-wysiwyg-editor/ui/table-grid-picker.js +2 -2
  300. package/dist/src/nile-wysiwyg-editor/ui/table-grid-picker.js.map +1 -1
  301. package/dist/src/nile-wysiwyg-editor/ui/table-menu.js +1 -1
  302. package/dist/src/nile-wysiwyg-editor/ui/table-menu.js.map +1 -1
  303. package/dist/src/version.js +1 -1
  304. package/dist/src/version.js.map +1 -1
  305. package/dist/tsconfig.tsbuildinfo +1 -1
  306. package/package.json +1 -1
  307. package/src/nile-wysiwyg-editor/engine/create-state.ts +7 -0
  308. package/src/nile-wysiwyg-editor/engine/email-css.ts +136 -0
  309. package/src/nile-wysiwyg-editor/engine/email-fidelity.test.ts +1347 -0
  310. package/src/nile-wysiwyg-editor/engine/email-render.ts +99 -0
  311. package/src/nile-wysiwyg-editor/engine/html-detect.ts +26 -0
  312. package/src/nile-wysiwyg-editor/engine/index.ts +10 -1
  313. package/src/nile-wysiwyg-editor/engine/inputrules.ts +18 -1
  314. package/src/nile-wysiwyg-editor/engine/plugins/image-view.ts +3 -2
  315. package/src/nile-wysiwyg-editor/engine/plugins/link.ts +58 -2
  316. package/src/nile-wysiwyg-editor/engine/plugins/paste.ts +31 -8
  317. package/src/nile-wysiwyg-editor/engine/plugins/tables.ts +29 -7
  318. package/src/nile-wysiwyg-editor/engine/pm.test.ts +73 -0
  319. package/src/nile-wysiwyg-editor/engine/sanitize.ts +729 -7
  320. package/src/nile-wysiwyg-editor/engine/schema.ts +206 -33
  321. package/src/nile-wysiwyg-editor/engine/selection-state.ts +3 -1
  322. package/src/nile-wysiwyg-editor/engine/serializer.ts +30 -8
  323. package/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.ts +357 -0
  324. package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.ts +45 -4
  325. package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.ts +258 -0
  326. package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.ts +119 -12
  327. package/src/nile-wysiwyg-editor/ui/bookmark-panel.ts +2 -2
  328. package/src/nile-wysiwyg-editor/ui/bubble-menu.ts +1 -1
  329. package/src/nile-wysiwyg-editor/ui/embed-menu.ts +1 -1
  330. package/src/nile-wysiwyg-editor/ui/embed-panel.ts +1 -1
  331. package/src/nile-wysiwyg-editor/ui/emoji-picker.ts +1 -1
  332. package/src/nile-wysiwyg-editor/ui/find-replace.ts +1 -1
  333. package/src/nile-wysiwyg-editor/ui/image-menu.ts +1 -1
  334. package/src/nile-wysiwyg-editor/ui/image-panel.ts +1 -1
  335. package/src/nile-wysiwyg-editor/ui/insert-menu.ts +1 -1
  336. package/src/nile-wysiwyg-editor/ui/link-editor.ts +2 -2
  337. package/src/nile-wysiwyg-editor/ui/markdown-panel.ts +1 -1
  338. package/src/nile-wysiwyg-editor/ui/math-panel.ts +1 -1
  339. package/src/nile-wysiwyg-editor/ui/shortcut-help.ts +1 -1
  340. package/src/nile-wysiwyg-editor/ui/source-view.ts +2 -2
  341. package/src/nile-wysiwyg-editor/ui/special-chars.ts +1 -1
  342. package/src/nile-wysiwyg-editor/ui/suggest-list.ts +14 -3
  343. package/src/nile-wysiwyg-editor/ui/table-grid-picker.ts +2 -2
  344. package/src/nile-wysiwyg-editor/ui/table-menu.ts +1 -1
  345. package/vscode-html-custom-data.json +15 -1
  346. package/web-test-runner.config.mjs +4 -0
  347. package/dist/index-3ca67627.cjs.js +0 -2
  348. package/dist/index-6f3fa4ab.esm.js +0 -1
  349. package/dist/index-7b1c9857.esm.js +0 -1
  350. package/dist/index-89c520e9.cjs.js +0 -5
  351. package/dist/index-89c520e9.cjs.js.map +0 -1
  352. package/dist/index-ba47645d.esm.js +0 -1
  353. package/dist/index-c3210a9c.cjs.js +0 -2
  354. package/dist/index-c3210a9c.cjs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../../src/nile-wysiwyg-editor/engine/sanitize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTML sanitization pre-pass. The ProseMirror schema is the real whitelist —\n * anything it can't parse is dropped — but this pass removes actively\n * dangerous content (scripts, event handlers, javascript: URLs) before the\n * string ever touches a live DOM, and strips style declarations down to the\n * set the schema understands.\n */\n\nimport { isAllowedEmbedSrc, EMBED_SANDBOX, EMBED_REFERRER_POLICY } from './plugins/embeds';\n\n/** Elements removed together with their content. */\nconst DROP_WITH_CONTENT = new Set([\n 'script', 'frame', 'frameset', 'object', 'embed',\n 'applet', 'form', 'input', 'textarea', 'select', 'button', 'meta', 'link',\n 'base', 'title', 'noscript', 'template', 'svg', 'math', 'canvas', 'audio',\n 'video', 'dialog', 'slot',\n]);\n\n/** Elements kept as-is (with filtered attributes). Extended in later phases. */\nconst ALLOWED_TAGS = new Set([\n 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'ul', 'ol', 'li',\n 'br', 'hr', 'a', 'b', 'strong', 'i', 'em', 'u', 's', 'strike', 'del',\n 'span', 'code', 'sub', 'sup', 'div', 'font',\n 'pre', 'figure', 'figcaption', 'img', 'iframe',\n 'table', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th', 'colgroup', 'col',\n]);\n\n/** Attributes allowed per tag (on top of GLOBAL_ATTRS). */\nconst TAG_ATTRS: Record<string, Set<string>> = {\n a: new Set(['href', 'title', 'target', 'rel', 'id', 'name', 'data-bookmark']),\n table: new Set(['role', 'data-layout']),\n ol: new Set(['start', 'type', 'data-list-style']),\n ul: new Set(['data-task-list']),\n figure: new Set(['data-align']),\n li: new Set(['data-task-item', 'data-checked']),\n span: new Set([\n 'data-mention-trigger', 'data-mention-key', 'data-mention-label',\n 'data-merge-field', 'data-merge-label', 'data-math', 'data-math-display',\n ]),\n pre: new Set(['data-language']),\n img: new Set(['src', 'alt', 'title', 'width', 'height']),\n td: new Set(['colspan', 'rowspan', 'data-colwidth']),\n th: new Set(['colspan', 'rowspan', 'data-colwidth']),\n col: new Set(['span', 'width']),\n div: new Set(['data-embed-provider', 'data-width', 'data-align']),\n iframe: new Set([\n 'src', 'title', 'frameborder', 'allowfullscreen', 'allow', 'sandbox', 'referrerpolicy',\n ]),\n};\n\nconst GLOBAL_ATTRS = new Set(['style', 'align', 'class', 'id']);\n\n/** Author class/id names starting with these are the editor's own; drop them so\n * content can't impersonate or restyle the chrome. */\nconst RESERVED_NAME = /^(?:nile-wysiwyg|ProseMirror)/;\n\n/** Filtered `class`: reserved-prefixed tokens removed. Empty → drop attribute. */\nfunction cleanClassAttr(value: string): string {\n return value\n .split(/\\s+/)\n .filter(token => token && !RESERVED_NAME.test(token))\n .join(' ');\n}\n\n/** Style declarations the schema can represent. Everything else is noise. */\nconst ALLOWED_STYLES = new Set([\n 'color', 'background-color', 'font-family', 'font-size', 'font-style',\n 'font-weight', 'text-align', 'text-decoration', 'text-decoration-line',\n 'vertical-align', 'margin-left', 'margin-inline-start', 'list-style-type',\n 'line-height',\n]);\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nexport function isSafeUrl(url: string, allowDataImage = false): boolean {\n const trimmed = url.trim();\n if (trimmed === '') return false;\n // Relative URLs and fragments have no protocol — safe.\n if (/^(#|\\/|\\.\\/|\\.\\.\\/)/.test(trimmed)) return true;\n const match = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);\n if (!match) return true;\n const protocol = `${match[1].toLowerCase()}:`;\n if (SAFE_URL_PROTOCOLS.includes(protocol)) return true;\n if (allowDataImage && protocol === 'data:') {\n // Raster images only — data:image/svg+xml can carry scripts.\n return /^data:image\\/(png|gif|jpe?g|webp|avif|bmp);/i.test(trimmed);\n }\n return false;\n}\n\n/** Size styles allowed only where they are part of the document model. */\nconst SIZED_TAGS: Record<string, Set<string>> = {\n img: new Set(['width', 'height']),\n figure: new Set(['width', 'margin-right']),\n div: new Set(['width', 'max-width']),\n};\n\nfunction filterStyle(value: string, tag: string): string {\n const extra = SIZED_TAGS[tag];\n return value\n .split(';')\n .map(decl => decl.trim())\n .filter(decl => {\n const name = decl.slice(0, decl.indexOf(':')).trim().toLowerCase();\n if (!ALLOWED_STYLES.has(name) && !(extra && extra.has(name))) return false;\n // Defense in depth: CSS url()/expression() smuggling.\n return !/url\\s*\\(|expression\\s*\\(/i.test(decl);\n })\n .join('; ');\n}\n\n/**\n * Sanitizes the CSS inside a <style> block. Neutralizes the vectors that make\n * a raw stylesheet dangerous while leaving ordinary rules intact:\n * - `@import` (external fetch / data exfiltration) — removed,\n * - `expression()`, `behavior:`, `-moz-binding:` (script execution) — broken,\n * - `url(...)` pointing anywhere other than a safe data: image or a local\n * `#fragment` — replaced with `url(#)`,\n * - any `</style` sequence — stripped so the text can't break out of the\n * element when the document is re-serialized.\n * CSS comments are dropped first so none of the above can hide inside one.\n */\nexport function sanitizeCss(css: string): string {\n return css\n .replace(/<\\/style/gi, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/@import[^;]*;?/gi, '')\n .replace(/expression\\s*\\(/gi, 'blocked(')\n .replace(/(behavior|-moz-binding)(\\s*):/gi, 'blocked-prop$2:')\n .replace(/url\\(\\s*(['\"]?)([^)]*?)\\1\\s*\\)/gi, (full, _quote, raw) => {\n const url = String(raw).trim();\n if (/^#/.test(url)) return full;\n if (/^data:image\\/(png|gif|jpe?g|webp|avif|bmp);/i.test(url)) return full;\n return 'url(#)';\n })\n .trim();\n}\n\nfunction sanitizeElement(el: Element): void {\n const tag = el.tagName.toLowerCase();\n const allowed = TAG_ATTRS[tag];\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n const keep =\n (GLOBAL_ATTRS.has(name) || (allowed !== undefined && allowed.has(name))) &&\n !name.startsWith('on');\n if (!keep) {\n el.removeAttribute(attr.name);\n continue;\n }\n if (name === 'style') {\n const filtered = filterStyle(attr.value, tag);\n if (filtered) el.setAttribute('style', filtered);\n else el.removeAttribute('style');\n } else if (name === 'class') {\n const cleaned = cleanClassAttr(attr.value);\n if (cleaned) el.setAttribute('class', cleaned);\n else el.removeAttribute('class');\n } else if (name === 'id') {\n if (RESERVED_NAME.test(attr.value)) el.removeAttribute('id');\n } else if (name === 'href' || name === 'src') {\n // Raster data: URLs are allowed on images only.\n if (!isSafeUrl(attr.value, tag === 'img')) el.removeAttribute(attr.name);\n } else if (name === 'target') {\n if (attr.value === '_blank') el.setAttribute('rel', 'noopener noreferrer');\n else el.removeAttribute('target');\n }\n }\n}\n\nfunction walk(node: Element): void {\n for (const child of Array.from(node.children)) {\n const tag = child.tagName.toLowerCase();\n if (DROP_WITH_CONTENT.has(tag)) {\n child.remove();\n continue;\n }\n // iframes are allowed for any https src, but always force-sandboxed so an\n // untrusted embed can never navigate the top window or run unrestricted.\n if (tag === 'iframe') {\n if (!isAllowedEmbedSrc(child.getAttribute('src') ?? '')) {\n child.remove();\n continue;\n }\n child.setAttribute('sandbox', EMBED_SANDBOX);\n child.setAttribute('referrerpolicy', EMBED_REFERRER_POLICY);\n }\n // <style> blocks are kept, but their CSS is sanitized and any attributes\n // (media, nonce, …) dropped. Handled before the unwrap branch below so the\n // raw CSS is never spilled into the document as visible text.\n if (tag === 'style') {\n child.textContent = sanitizeCss(child.textContent ?? '');\n for (const attr of Array.from(child.attributes)) child.removeAttribute(attr.name);\n continue;\n }\n if (!ALLOWED_TAGS.has(tag)) {\n // Unknown wrapper (article, section, table for now, …): keep its\n // content, drop the element itself.\n walk(child);\n child.replaceWith(...Array.from(child.childNodes));\n continue;\n }\n sanitizeElement(child);\n walk(child);\n }\n}\n\n/**\n * Sanitizes an HTML string. Parsing happens in an inert document created by\n * DOMParser, so embedded scripts never execute and images never load.\n */\nexport function sanitizeHtml(html: string): string {\n // Wrap in an explicit <body> so metadata-like tags (notably <style>) stay in\n // the body instead of being hoisted into <head> by the HTML parser — which\n // would drop them before walk() ever sees them. Mirrors htmlToDoc's parse.\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n walk(doc.body);\n return doc.body.innerHTML;\n}\n"]}
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../../src/nile-wysiwyg-editor/engine/sanitize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTML sanitization pre-pass. The ProseMirror schema is the real whitelist —\n * anything it can't parse is dropped — but this pass removes actively\n * dangerous content (scripts, event handlers, javascript: URLs) before the\n * string ever touches a live DOM, and strips style declarations down to the\n * set the schema understands.\n */\n\nimport { isAllowedEmbedSrc, EMBED_SANDBOX, EMBED_REFERRER_POLICY } from './plugins/embeds';\nimport { isExtensionValueValid, NormalizedAllowedStyles } from './email-css';\n\n/** Elements removed together with their content. */\nconst DROP_WITH_CONTENT = new Set([\n 'script', 'frame', 'frameset', 'object', 'embed',\n 'applet', 'form', 'input', 'textarea', 'select', 'button', 'meta', 'link',\n 'base', 'title', 'noscript', 'template', 'svg', 'math', 'canvas', 'audio',\n 'video', 'dialog', 'slot',\n]);\n\n/** Elements kept as-is (with filtered attributes). Extended in later phases. */\nconst ALLOWED_TAGS = new Set([\n 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'ul', 'ol', 'li',\n 'br', 'hr', 'a', 'b', 'strong', 'i', 'em', 'u', 's', 'strike', 'del',\n 'span', 'code', 'sub', 'sup', 'div', 'font',\n 'pre', 'figure', 'figcaption', 'img', 'iframe',\n 'table', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th', 'colgroup', 'col',\n]);\n\n/** Attributes allowed per tag (on top of GLOBAL_ATTRS). */\nconst TAG_ATTRS: Record<string, Set<string>> = {\n a: new Set(['href', 'title', 'target', 'rel', 'id', 'name', 'data-bookmark']),\n table: new Set(['role', 'data-layout']),\n ol: new Set(['start', 'type', 'data-list-style']),\n ul: new Set(['data-task-list']),\n figure: new Set(['data-align']),\n li: new Set(['data-task-item', 'data-checked']),\n span: new Set([\n 'data-mention-trigger', 'data-mention-key', 'data-mention-label',\n 'data-merge-field', 'data-merge-label', 'data-math', 'data-math-display',\n ]),\n pre: new Set(['data-language']),\n img: new Set(['src', 'alt', 'title', 'width', 'height']),\n td: new Set(['colspan', 'rowspan', 'data-colwidth']),\n th: new Set(['colspan', 'rowspan', 'data-colwidth']),\n col: new Set(['span', 'width']),\n div: new Set(['data-embed-provider', 'data-width', 'data-align']),\n iframe: new Set([\n 'src', 'title', 'frameborder', 'allowfullscreen', 'allow', 'sandbox', 'referrerpolicy',\n ]),\n};\n\nconst GLOBAL_ATTRS = new Set(['style', 'align', 'class', 'id']);\n\n/** Author class/id names starting with these are the editor's own; drop them so\n * content can't impersonate or restyle the chrome. */\nconst RESERVED_NAME = /^(?:nile-wysiwyg|ProseMirror)/;\n\n/** Filtered `class`: reserved-prefixed tokens removed. Empty → drop attribute. */\nfunction cleanClassAttr(value: string): string {\n return value\n .split(/\\s+/)\n .filter(token => token && !RESERVED_NAME.test(token))\n .join(' ');\n}\n\n/** Style declarations the schema can represent. Everything else is noise. */\nconst ALLOWED_STYLES = new Set([\n 'color', 'background-color', 'font-family', 'font-size', 'font-style',\n 'font-weight', 'text-align', 'text-decoration', 'text-decoration-line',\n 'vertical-align', 'margin-left', 'margin-inline-start', 'list-style-type',\n 'line-height',\n]);\n\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nexport function isSafeUrl(url: string, allowDataImage = false): boolean {\n const trimmed = url.trim();\n if (trimmed === '') return false;\n // Relative URLs and fragments have no protocol — safe.\n if (/^(#|\\/|\\.\\/|\\.\\.\\/)/.test(trimmed)) return true;\n const match = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);\n if (!match) return true;\n const protocol = `${match[1].toLowerCase()}:`;\n if (SAFE_URL_PROTOCOLS.includes(protocol)) return true;\n if (allowDataImage && protocol === 'data:') {\n // Raster images only — data:image/svg+xml can carry scripts.\n return /^data:image\\/(png|gif|jpe?g|webp|avif|bmp);/i.test(trimmed);\n }\n return false;\n}\n\n/** Size styles allowed only where they are part of the document model. */\nconst SIZED_TAGS: Record<string, Set<string>> = {\n img: new Set(['width', 'height']),\n figure: new Set(['width', 'margin-right']),\n div: new Set(['width', 'max-width']),\n};\n\nfunction filterStyle(value: string, tag: string): string {\n const extra = SIZED_TAGS[tag];\n return value\n .split(';')\n .map(decl => decl.trim())\n .filter(decl => {\n const name = decl.slice(0, decl.indexOf(':')).trim().toLowerCase();\n if (!ALLOWED_STYLES.has(name) && !(extra && extra.has(name))) return false;\n // Defense in depth: CSS url()/expression() smuggling.\n return !/url\\s*\\(|expression\\s*\\(/i.test(decl);\n })\n .join('; ');\n}\n\n/* --- email-fidelity: container styles become node attrs, not per-run marks (flag-gated) --- */\n\n/** Containers whose inline styles must not become per-run marks. */\nconst CONTAINER_TAGS = new Set([\n 'table', 'td', 'th', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'div', 'li', 'blockquote', 'tr', 'tbody',\n]);\n\n/** Mark-triggering declarations dropped on any container. */\nconst CONTAINER_DROP = new Set([\n 'color', 'background-color', 'font-family', 'font-size', 'font-weight',\n 'font-style', 'text-decoration', 'text-decoration-line',\n 'text-decoration-style', 'text-decoration-color',\n]);\n\n/** Layout declarations allowed on cells with fidelity. */\nconst CELL_LAYOUT = new Set([\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'width', 'vertical-align', 'border', 'border-top', 'border-right',\n 'border-bottom', 'border-left', 'border-radius',\n]);\n\n/** `border-width`, `border-top-color`, … — resolved per side through CSSOM instead. */\nconst CELL_BORDER_LONGHAND = /^border-(?:(?:top|right|bottom|left)-)?(?:width|style|color)$/;\n\n/** Layout declarations allowed on tables with fidelity. */\nconst TABLE_LAYOUT = new Set(['width', 'max-width', 'border', 'margin-left', 'margin-right']);\n\n/** Block margins allowed on paragraphs/headings with fidelity. */\nconst BLOCK_LAYOUT = new Set(['margin', 'margin-top', 'margin-bottom']);\n\nconst BORDER_STYLES = new Set(['solid', 'dashed', 'dotted', 'double', 'none']);\nconst VALIGN_KEYWORDS = new Set([\n 'top', 'middle', 'bottom', 'baseline', 'sub', 'super', 'text-top', 'text-bottom',\n]);\nconst LENGTH_TOKEN = /^-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px|%|em|rem|pt)$/;\n\nfunction isAscii(value: string): boolean {\n // eslint-disable-next-line no-control-regex\n return !/[^\\x00-\\x7f]/.test(value);\n}\n\n/** Forbidden function-ish / escape tokens shared by the length & border grammars. */\nfunction hasUnsafeToken(value: string): boolean {\n return /[\\\\/(]|url|var|calc|expression/i.test(value);\n}\n\nfunction isLengthToken(token: string): boolean {\n return token === '0' || token === 'auto' || LENGTH_TOKEN.test(token);\n}\n\n/** 1–4 whitespace-separated length tokens (padding/margin/width/radius). */\nfunction isLengthList(value: string): boolean {\n if (!isAscii(value) || hasUnsafeToken(value)) return false;\n const tokens = value.trim().split(/\\s+/);\n return tokens.length >= 1 && tokens.length <= 4 && tokens.every(isLengthToken);\n}\n\nfunction isColor(value: string): boolean {\n if (!isAscii(value)) return false;\n const v = value.trim();\n if (/^[a-z]+$/i.test(v)) return true;\n if (/^#[0-9a-f]{3,8}$/i.test(v)) return true;\n // rgb()/rgba() with numeric (optionally %) arguments only.\n if (/^rgba?\\(\\s*[\\d.]+%?(?:\\s*,\\s*[\\d.]+%?){2,3}\\s*\\)$/i.test(v)) return true;\n // hsl()/hsla() with numeric (optionally %) arguments only — numeric-only, so a\n // smuggled `hsl(var(--x))` still fails (it has letters inside the parens).\n return /^hsla?\\(\\s*[\\d.]+%?(?:\\s*,\\s*[\\d.]+%?){2,3}\\s*\\)$/i.test(v);\n}\n\n/** Line-height for tables: a unitless number or a single length token. */\nfunction isLineHeight(value: string): boolean {\n if (!isAscii(value) || hasUnsafeToken(value)) return false;\n const v = value.trim();\n if (/^\\d+(?:\\.\\d+)?$/.test(v)) return true;\n return isLengthToken(v);\n}\n\n/** Cell `text-align` keyword set (also the legacy `align` conversion source). */\nconst TEXT_ALIGN_KEYWORDS = new Set(['left', 'center', 'right', 'justify', 'start', 'end']);\nconst LEGACY_ALIGN_KEYWORDS = new Set(['left', 'center', 'right', 'justify']);\n\nfunction isBorder(value: string): boolean {\n if (!isAscii(value)) return false;\n if (/[\\\\/]|url|var|calc|expression/i.test(value)) return false;\n const tokens = value.trim().match(/rgba?\\([^)]*\\)|\\S+/gi) ?? [];\n if (!tokens.length) return false;\n let hasStyle = false;\n for (const token of tokens) {\n if (BORDER_STYLES.has(token.toLowerCase())) {\n hasStyle = true;\n continue;\n }\n if (isLengthToken(token) || isColor(token)) continue;\n return false;\n }\n return hasStyle;\n}\n\nfunction isValign(value: string): boolean {\n const v = value.trim().toLowerCase();\n return VALIGN_KEYWORDS.has(v) || isLengthToken(v);\n}\n\nfunction isLayoutValid(name: string, value: string): boolean {\n if (name === 'vertical-align') return isValign(value);\n // `border-radius` is a length list (a corner rounding), not the width/style/\n // colour grammar the `border*` shorthands use — validate it as such.\n if (name === 'border-radius') return isLengthList(value);\n if (name.startsWith('border')) return isBorder(value);\n return isLengthList(value);\n}\n\n/** Validates a cell `color`/`font-*` declaration kept as part of `textStyle`. */\nfunction isCellTextValid(name: string, value: string): boolean {\n if (!isAscii(value) || /url|expression|var|calc/i.test(value)) return false;\n if (name === 'color') return isColor(value);\n if (name === 'font-size') return isLengthToken(value);\n if (name === 'font-weight') {\n return /^(normal|bold|bolder|lighter|[1-9]00)$/i.test(value.trim());\n }\n // font-family: names, commas and quotes only — no function-ish characters.\n return !/[(){}<>;\\\\]/.test(value);\n}\n\n/** A container's kept style under fidelity: validated layout, carried background/font, legacy attrs. */\nfunction computeContainerStyle(el: Element, tag: string): string {\n const isCell = tag === 'td' || tag === 'th';\n const isTable = tag === 'table';\n const isBlock = /^(?:p|h[1-6])$/.test(tag);\n const extra = SIZED_TAGS[tag];\n const kept: string[] = [];\n\n for (const decl of (el.getAttribute('style') ?? '').split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const name = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (!value || /url\\s*\\(|expression\\s*\\(/i.test(decl)) continue;\n\n if (name === 'background-color') {\n if ((isCell || isTable) && isColor(value)) kept.push(`${name}: ${value}`);\n continue;\n }\n if (name === 'color' || name === 'font-family' || name === 'font-size' || name === 'font-weight') {\n // Blocks and tables keep their own text style; cells inherit the table's.\n if ((isCell || isBlock || isTable) && isCellTextValid(name, value)) {\n kept.push(`${name}: ${value}`);\n }\n continue;\n }\n if (name === 'text-align') {\n // Cells keep a validated text-align (lifted to data-cell-align); blocks let\n // it fall through to the align attr via the ALLOWED_STYLES branch below.\n if (isCell && TEXT_ALIGN_KEYWORDS.has(value.toLowerCase())) {\n kept.push(`text-align: ${value.toLowerCase()}`);\n continue;\n }\n }\n if (name === 'line-height' && isTable) {\n if (isLineHeight(value)) kept.push(`line-height: ${value}`);\n continue;\n }\n if (name === 'margin' && isTable) {\n // `margin: 0 auto` centring: keep only the horizontal parts as longhands so\n // the table parseDOM's `margin-left/right: auto` check recognises it.\n if (isLengthList(value)) {\n const tokens = value.trim().split(/\\s+/);\n const [, right] = tokens.length === 1\n ? [tokens[0], tokens[0]]\n : [tokens[0], tokens[1]];\n const left = tokens.length >= 4 ? tokens[3] : right;\n kept.push(`margin-left: ${left}`, `margin-right: ${right}`);\n }\n continue;\n }\n if (CONTAINER_DROP.has(name)) continue;\n // Border longhand groups (`border-width/-style/-color`, per side or not) are\n // how the browser re-serializes four equal sides; recombined per side below.\n if (isCell && CELL_BORDER_LONGHAND.test(name)) continue;\n\n if (isCell && CELL_LAYOUT.has(name) && isLayoutValid(name, value)) {\n kept.push(`${name}: ${value}`);\n } else if (isTable && TABLE_LAYOUT.has(name) && isLayoutValid(name, value)) {\n kept.push(`${name}: ${value}`);\n } else if (isBlock && BLOCK_LAYOUT.has(name) && isLengthList(value)) {\n kept.push(`${name}: ${value}`);\n } else if (ALLOWED_STYLES.has(name)) {\n kept.push(`${name}: ${value}`);\n } else if (extra && extra.has(name)) {\n kept.push(`${name}: ${value}`);\n }\n }\n\n // A cell border written as longhand groups: read each side back through CSSOM,\n // which resolves any mix of shorthands and longhands to `width style color`.\n if (isCell && !kept.some(d => d.startsWith('border:'))) {\n const style = (el as HTMLElement).style;\n for (const side of ['top', 'right', 'bottom', 'left']) {\n const prop = `border-${side}`;\n if (kept.some(d => d.startsWith(`${prop}:`))) continue;\n const value = style?.getPropertyValue(prop);\n if (value && isBorder(value)) kept.push(`${prop}: ${value}`);\n }\n }\n\n // Legacy presentational attributes → validated styles (raw attr removed by the\n // standard attribute pass, which doesn't list them).\n if (isCell || isTable) {\n const bgcolor = el.getAttribute('bgcolor');\n if (bgcolor && isColor(bgcolor) && !kept.some(d => d.startsWith('background-color'))) {\n kept.push(`background-color: ${bgcolor}`);\n }\n const widthAttr = el.getAttribute('width');\n if (widthAttr && !kept.some(d => d.startsWith('width'))) {\n const width = /^\\d+$/.test(widthAttr)\n ? `${widthAttr}px`\n : /^\\d+%$/.test(widthAttr)\n ? widthAttr\n : null;\n if (width) kept.push(`width: ${width}`);\n }\n const valign = el.getAttribute('valign');\n if (isCell && valign && isValign(valign) && !kept.some(d => d.startsWith('vertical-align'))) {\n kept.push(`vertical-align: ${valign}`);\n }\n // Legacy cell align → text-align; the attr stays for table centring.\n const alignAttr = el.getAttribute('align');\n if (\n isCell &&\n alignAttr &&\n LEGACY_ALIGN_KEYWORDS.has(alignAttr.toLowerCase()) &&\n !kept.some(d => d.startsWith('text-align'))\n ) {\n kept.push(`text-align: ${alignAttr.toLowerCase()}`);\n }\n }\n\n return kept.join('; ');\n}\n\n/** Cell text declarations lifted onto `data-cell-text-style` before PM parse. */\nconst CELL_TEXT_PROPS = ['color', 'font-family', 'font-size', 'font-weight'];\n\n/** Table text declarations lifted onto `data-table-text-style` before PM parse. */\nconst TABLE_TEXT_PROPS = ['color', 'font-family', 'font-size', 'font-weight', 'line-height'];\n\n/** Moves carried background/font declarations onto data-attrs so they never become marks. */\nfunction relocateElement(el: HTMLElement, tag: string): void {\n if (tag === 'td' || tag === 'th') {\n const bg = el.style.backgroundColor;\n if (bg) {\n el.setAttribute('data-cell-bg', bg);\n el.style.removeProperty('background-color');\n }\n const parts: string[] = [];\n for (const prop of CELL_TEXT_PROPS) {\n const value = el.style.getPropertyValue(prop);\n if (value) {\n parts.push(`${prop}: ${value}`);\n el.style.removeProperty(prop);\n }\n }\n if (parts.length) el.setAttribute('data-cell-text-style', parts.join('; '));\n // Cell text-align → data-cell-align (so it stays a node attr, never a mark).\n const align = el.style.textAlign;\n if (align) {\n el.setAttribute('data-cell-align', align);\n el.style.removeProperty('text-align');\n }\n if (!el.getAttribute('style')) el.removeAttribute('style');\n } else if (tag === 'table') {\n const bg = el.style.backgroundColor;\n if (bg) {\n el.setAttribute('data-table-bg', bg);\n el.style.removeProperty('background-color');\n }\n const textParts: string[] = [];\n for (const prop of TABLE_TEXT_PROPS) {\n const value = el.style.getPropertyValue(prop);\n if (value) {\n textParts.push(`${prop}: ${value}`);\n el.style.removeProperty(prop);\n }\n }\n if (textParts.length) el.setAttribute('data-table-text-style', textParts.join('; '));\n // Email containers are centred with `align=\"center\"` on the table or on\n // the cell that holds it.\n const holder = el.parentElement?.closest('td, th');\n if (\n el.getAttribute('align')?.toLowerCase() === 'center' ||\n holder?.getAttribute('align')?.toLowerCase() === 'center'\n ) {\n el.setAttribute('data-table-align', 'center');\n }\n if (!el.getAttribute('style')) el.removeAttribute('style');\n }\n}\n\nfunction relocateWalk(node: Element): void {\n for (const child of Array.from(node.children)) {\n relocateElement(child as HTMLElement, child.tagName.toLowerCase());\n relocateWalk(child);\n }\n}\n\n/** A `<col>` width (style width or `width` attr) normalized to a px/% token. */\nfunction colWidth(col: Element): string | null {\n const styleWidth = /width\\s*:\\s*([^;]+)/i.exec(col.getAttribute('style') ?? '')?.[1]?.trim();\n const v = (styleWidth || col.getAttribute('width') || '').trim();\n if (!v) return null;\n if (/^\\d+$/.test(v)) return `${v}px`;\n if (LENGTH_TOKEN.test(v) && /(?:px|%)$/.test(v)) return v;\n return null;\n}\n\n/** Per-column widths of a table's own colgroup, expanding `span`. */\nfunction tableColWidths(table: Element): (string | null)[] {\n const widths: (string | null)[] = [];\n for (const col of Array.from(table.querySelectorAll(':scope > colgroup > col, :scope > col'))) {\n const span = parseInt(col.getAttribute('span') ?? '1', 10);\n const n = Number.isFinite(span) && span > 0 ? span : 1;\n const w = colWidth(col);\n for (let i = 0; i < n; i += 1) widths.push(w);\n }\n return widths;\n}\n\n/** A table's own rows (not nested tables' rows). */\nfunction directRows(table: Element): Element[] {\n const rows: Element[] = [];\n for (const child of Array.from(table.children)) {\n const t = child.tagName.toLowerCase();\n if (t === 'tr') rows.push(child);\n else if (t === 'thead' || t === 'tbody' || t === 'tfoot') {\n for (const row of Array.from(child.children)) {\n if (row.tagName.toLowerCase() === 'tr') rows.push(row);\n }\n }\n }\n return rows;\n}\n\n/** Copies colgroup widths onto unsized cells (rows with a colspan are skipped). */\nfunction applyColgroupWidths(table: Element): void {\n const widths = tableColWidths(table);\n if (!widths.some(Boolean)) return;\n for (const row of directRows(table)) {\n const cells = Array.from(row.children).filter(c => /^t[dh]$/.test(c.tagName.toLowerCase()));\n if (cells.some(c => parseInt(c.getAttribute('colspan') ?? '1', 10) > 1)) continue;\n cells.forEach((cell, idx) => {\n const w = widths[idx];\n if (!w) return;\n const hasWidth =\n /(?:^|;)\\s*width\\s*:/i.test(cell.getAttribute('style') ?? '') || cell.hasAttribute('width');\n if (hasWidth) return;\n const style = cell.getAttribute('style') ?? '';\n cell.setAttribute('style', style ? `${style}; width: ${w}` : `width: ${w}`);\n });\n }\n}\n\n/** Fidelity-only pass run right before parsing; see `relocateElement`. */\nexport function relocateEmailContainers(html: string): string {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n relocateWalk(doc.body);\n return doc.body.innerHTML;\n}\n\n/**\n * Sanitizes the CSS inside a <style> block. Neutralizes the vectors that make\n * a raw stylesheet dangerous while leaving ordinary rules intact:\n * - `@import` (external fetch / data exfiltration) — removed,\n * - `expression()`, `behavior:`, `-moz-binding:` (script execution) — broken,\n * - `url(...)` pointing anywhere other than a safe data: image or a local\n * `#fragment` — replaced with `url(#)`,\n * - any `</style` sequence — stripped so the text can't break out of the\n * element when the document is re-serialized.\n * CSS comments are dropped first so none of the above can hide inside one.\n */\nexport function sanitizeCss(css: string): string {\n return css\n .replace(/<\\/style/gi, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/@import[^;]*;?/gi, '')\n .replace(/expression\\s*\\(/gi, 'blocked(')\n .replace(/(behavior|-moz-binding)(\\s*):/gi, 'blocked-prop$2:')\n .replace(/url\\(\\s*(['\"]?)([^)]*?)\\1\\s*\\)/gi, (full, _quote, raw) => {\n const url = String(raw).trim();\n if (/^#/.test(url)) return full;\n if (/^data:image\\/(png|gif|jpe?g|webp|avif|bmp);/i.test(url)) return full;\n return 'url(#)';\n })\n .trim();\n}\n\n/** Container tags an app may widen with `allowedStyles`. */\nconst EXTENSION_TAGS = new Set(['td', 'th', 'table', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']);\n\n/** The allowlisted, grammar-valid extension declarations for a container, or ''. */\nfunction computeExtraStyle(el: Element, allowed: Set<string> | undefined): string {\n if (!allowed) return '';\n const kept: string[] = [];\n for (const decl of (el.getAttribute('style') ?? '').split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const name = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (allowed.has(name) && isExtensionValueValid(value)) kept.push(`${name}: ${value}`);\n }\n return kept.join('; ');\n}\n\n/** Re-validates a stored cell/table text style on write-back. */\nexport function sanitizeTableTextStyleForWrite(s: string): string {\n const kept: string[] = [];\n for (const decl of String(s ?? '').split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const name = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (!value) continue;\n const ok =\n name === 'line-height'\n ? isLineHeight(value)\n : TABLE_TEXT_PROPS.includes(name) && isCellTextValid(name, value);\n if (ok) kept.push(`${name}: ${value}`);\n }\n return kept.join('; ');\n}\n\nfunction sanitizeElement(\n el: Element,\n emailFidelity = false,\n allowedStyles?: NormalizedAllowedStyles\n): void {\n const tag = el.tagName.toLowerCase();\n // With fidelity, a table pushes its colgroup column widths down onto its own\n // cells before they are sanitized (the <col> widths are stripped otherwise).\n if (emailFidelity && tag === 'table') applyColgroupWidths(el);\n // Fidelity recomputes the container style, written back after the attribute pass.\n const email =\n emailFidelity && CONTAINER_TAGS.has(tag) ? computeContainerStyle(el, tag) : null;\n // Extension declarations come from the original style and move to data-extra-style.\n const extra =\n emailFidelity && EXTENSION_TAGS.has(tag)\n ? computeExtraStyle(el, allowedStyles?.get(tag))\n : '';\n const allowed = TAG_ATTRS[tag];\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n const keep =\n (GLOBAL_ATTRS.has(name) || (allowed !== undefined && allowed.has(name))) &&\n !name.startsWith('on');\n if (!keep) {\n el.removeAttribute(attr.name);\n continue;\n }\n if (name === 'style') {\n const filtered = filterStyle(attr.value, tag);\n if (filtered) el.setAttribute('style', filtered);\n else el.removeAttribute('style');\n } else if (name === 'class') {\n const cleaned = cleanClassAttr(attr.value);\n if (cleaned) el.setAttribute('class', cleaned);\n else el.removeAttribute('class');\n } else if (name === 'id') {\n if (RESERVED_NAME.test(attr.value)) el.removeAttribute('id');\n } else if (name === 'href' || name === 'src') {\n // Raster data: URLs are allowed on images only.\n if (!isSafeUrl(attr.value, tag === 'img')) el.removeAttribute(attr.name);\n } else if (name === 'target') {\n if (attr.value === '_blank') el.setAttribute('rel', 'noopener noreferrer');\n else el.removeAttribute('target');\n }\n }\n\n if (email !== null) {\n if (email) el.setAttribute('style', email);\n else el.removeAttribute('style');\n }\n if (extra) el.setAttribute('data-extra-style', extra);\n}\n\nfunction walk(\n node: Element,\n emailFidelity = false,\n allowedStyles?: NormalizedAllowedStyles\n): void {\n for (const child of Array.from(node.children)) {\n const tag = child.tagName.toLowerCase();\n if (DROP_WITH_CONTENT.has(tag)) {\n child.remove();\n continue;\n }\n // Email preheaders: elements hidden with display:none / mso-hide are dropped\n // together with their content so they don't surface as 1px text.\n if (emailFidelity) {\n const style = child.getAttribute('style') ?? '';\n if (/display\\s*:\\s*none/i.test(style) || /mso-hide\\s*:\\s*all/i.test(style)) {\n child.remove();\n continue;\n }\n }\n // iframes are allowed for any https src, but always force-sandboxed so an\n // untrusted embed can never navigate the top window or run unrestricted.\n if (tag === 'iframe') {\n if (!isAllowedEmbedSrc(child.getAttribute('src') ?? '')) {\n child.remove();\n continue;\n }\n child.setAttribute('sandbox', EMBED_SANDBOX);\n child.setAttribute('referrerpolicy', EMBED_REFERRER_POLICY);\n }\n // <style> blocks are kept, but their CSS is sanitized and any attributes\n // (media, nonce, …) dropped. Handled before the unwrap branch below so the\n // raw CSS is never spilled into the document as visible text.\n if (tag === 'style') {\n child.textContent = sanitizeCss(child.textContent ?? '');\n for (const attr of Array.from(child.attributes)) child.removeAttribute(attr.name);\n continue;\n }\n if (!ALLOWED_TAGS.has(tag)) {\n // Unknown wrapper (article, section, table for now, …): keep its\n // content, drop the element itself.\n walk(child, emailFidelity, allowedStyles);\n child.replaceWith(...Array.from(child.childNodes));\n continue;\n }\n sanitizeElement(child, emailFidelity, allowedStyles);\n walk(child, emailFidelity, allowedStyles);\n }\n}\n\n/* --- email-fidelity: button links → one-cell table buttons (flag-gated) --- */\n\n/** Box declarations an email \"button\" link carries; moved onto the new cell. */\nconst BUTTON_CELL_PROPS = new Set([\n 'background-color', 'padding', 'padding-top', 'padding-right',\n 'padding-bottom', 'padding-left', 'border-radius', 'width', 'border',\n 'border-top', 'border-right', 'border-bottom', 'border-left', 'text-align',\n]);\n\n/** Text-level declarations kept on the link (they become marks on its text). */\nconst BUTTON_LINK_PROPS = new Set([\n 'color', 'font-size', 'font-weight', 'font-family', 'font-style',\n 'text-decoration', 'text-decoration-line', 'line-height',\n]);\n\n/** Block parents whose sole-child button link may be lifted into a table. */\nconst BUTTON_PARENT_TAGS = new Set(['td', 'th', 'div', 'p']);\n\ninterface Decl {\n name: string;\n value: string;\n}\n\n/** Splits an inline `style` into `{name, value}` pairs (names lowercased). */\nfunction parseDecls(style: string): Decl[] {\n const out: Decl[] = [];\n for (const decl of style.split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const name = decl.slice(0, idx).trim().toLowerCase();\n const value = decl.slice(idx + 1).trim();\n if (name && value) out.push({ name, value });\n }\n return out;\n}\n\n/** A button link: `display:inline-block|block` plus a background or padding. */\nfunction isButtonLink(decls: Decl[]): boolean {\n const display = decls.find(d => d.name === 'display')?.value.toLowerCase();\n if (display !== 'inline-block' && display !== 'block') return false;\n return decls.some(d => d.name === 'background-color' || d.name.startsWith('padding'));\n}\n\n/** True when the link is horizontally auto-centred (`margin: 0 auto`, etc.). */\nfunction hasAutoHMargin(decls: Decl[]): boolean {\n const ml = decls.find(d => d.name === 'margin-left')?.value.toLowerCase();\n const mr = decls.find(d => d.name === 'margin-right')?.value.toLowerCase();\n if (ml === 'auto' || mr === 'auto') return true;\n const margin = decls.find(d => d.name === 'margin')?.value;\n if (!margin) return false;\n const tokens = margin.trim().split(/\\s+/);\n const right = tokens.length >= 2 ? tokens[1] : tokens[0];\n const left = tokens.length >= 4 ? tokens[3] : right;\n return left.toLowerCase() === 'auto' || right.toLowerCase() === 'auto';\n}\n\n/** True when a block centres its content via text-align / legacy align. */\nfunction blockCentered(el: Element): boolean {\n if (/text-align\\s*:\\s*center/i.test(el.getAttribute('style') ?? '')) return true;\n return el.getAttribute('align')?.toLowerCase() === 'center';\n}\n\n/** The link is the only non-whitespace content of its parent block. */\nfunction isSoleContent(parent: Element, child: Element): boolean {\n for (const node of Array.from(parent.childNodes)) {\n if (node === child) continue;\n if (node.nodeType === 3) {\n if ((node.textContent ?? '').trim() !== '') return false;\n } else {\n return false;\n }\n }\n return true;\n}\n\n/** Rebuilds each email button link as a one-cell layout table. */\nfunction convertButtonLinks(body: HTMLElement): void {\n const doc = body.ownerDocument;\n for (const a of Array.from(body.querySelectorAll('a[href]'))) {\n const decls = parseDecls(a.getAttribute('style') ?? '');\n if (!isButtonLink(decls)) continue;\n const parent = a.parentElement;\n if (!parent) continue;\n if (!BUTTON_PARENT_TAGS.has(parent.tagName.toLowerCase())) continue;\n if (!isSoleContent(parent, a)) continue;\n\n // Box declarations go to the cell; text declarations stay on the link;\n // margins/display are dropped (margins only inform centring below).\n const cell = decls.filter(d => BUTTON_CELL_PROPS.has(d.name));\n if (!cell.some(d => d.name === 'text-align')) {\n cell.push({ name: 'text-align', value: 'center' });\n }\n const linkStyle = decls\n .filter(d => BUTTON_LINK_PROPS.has(d.name))\n .map(d => `${d.name}: ${d.value}`)\n .join('; ');\n const centred = hasAutoHMargin(decls) || blockCentered(parent);\n\n const table = doc.createElement('table');\n table.setAttribute('role', 'presentation');\n if (centred) table.setAttribute('align', 'center');\n const tbody = doc.createElement('tbody');\n const tr = doc.createElement('tr');\n const td = doc.createElement('td');\n td.setAttribute('style', cell.map(d => `${d.name}: ${d.value}`).join('; '));\n if (linkStyle) a.setAttribute('style', linkStyle);\n else a.removeAttribute('style');\n td.appendChild(a); // detaches the link from its original parent\n tr.appendChild(td);\n tbody.appendChild(tr);\n table.appendChild(tbody);\n\n const parentTag = parent.tagName.toLowerCase();\n if (parentTag === 'p' || parentTag === 'div') parent.replaceWith(table);\n else parent.appendChild(table);\n }\n}\n\n/* --- email-fidelity: push centring onto blocks that can carry it (flag-gated) --- */\n\n/** Inline tags: loose runs of these (and text) inside a div/center are wrapped. */\nconst INLINE_TAGS = new Set([\n 'a', 'b', 'strong', 'i', 'em', 'u', 's', 'strike', 'del', 'span', 'code',\n 'sub', 'sup', 'font', 'br', 'img', 'small', 'big', 'mark', 'abbr', 'q', 'cite',\n 'label', 'bdi', 'bdo', 'wbr', 'time', 'kbd', 'samp', 'var',\n]);\n\n/** A node that may be lifted into a wrapping paragraph (inline element or text). */\nfunction isLooseInline(node: Node): boolean {\n if (node.nodeType === 3) return true;\n if (node.nodeType !== 1) return false;\n return INLINE_TAGS.has((node as Element).tagName.toLowerCase());\n}\n\n/** True when `el` already declares a valid `text-align` or legacy `align`. */\nfunction hasOwnTextAlign(el: Element): boolean {\n const styleAlign = /text-align\\s*:\\s*([a-z-]+)/i.exec(el.getAttribute('style') ?? '')?.[1];\n if (styleAlign && TEXT_ALIGN_KEYWORDS.has(styleAlign.toLowerCase())) return true;\n const attr = el.getAttribute('align');\n return !!(attr && LEGACY_ALIGN_KEYWORDS.has(attr.toLowerCase()));\n}\n\n/** Appends `text-align: value` to an element's inline style. */\nfunction addTextAlign(el: Element, value: string): void {\n const style = (el.getAttribute('style') ?? '').trim();\n el.setAttribute('style', style ? `${style}; text-align: ${value}` : `text-align: ${value}`);\n}\n\n/** Direct cells of a table (its own rows', not a nested table's). */\nfunction directCells(table: Element): Element[] {\n const cells: Element[] = [];\n for (const row of directRows(table)) {\n for (const child of Array.from(row.children)) {\n if (/^t[dh]$/.test(child.tagName.toLowerCase())) cells.push(child);\n }\n }\n return cells;\n}\n\n/** True when `el` sits inside a table that is itself a descendant of `wrapper`. */\nfunction insideNestedTable(el: Element, wrapper: Element): boolean {\n let p = el.parentElement;\n while (p && p !== wrapper) {\n if (p.tagName.toLowerCase() === 'table') return true;\n p = p.parentElement;\n }\n return false;\n}\n\n/** The block descendants (p/h1-6/li) of `wrapper` not inside a nested table. */\nfunction alignableBlocks(wrapper: Element): Element[] {\n return Array.from(wrapper.querySelectorAll('p, h1, h2, h3, h4, h5, h6, li')).filter(\n el => !insideNestedTable(el, wrapper)\n );\n}\n\n/** Wraps each loose inline run directly inside `wrapper` in an aligned `<p>`. */\nfunction wrapLooseInline(wrapper: Element, value: string): void {\n const doc = wrapper.ownerDocument;\n let group: ChildNode[] = [];\n const flush = (): void => {\n // Trim trailing whitespace-only text nodes so they stay outside the paragraph.\n while (group.length && group[group.length - 1].nodeType === 3\n && (group[group.length - 1].textContent ?? '').trim() === '') {\n group.pop();\n }\n if (!group.length) return;\n const p = doc.createElement('p');\n p.setAttribute('style', `text-align: ${value}`);\n group[0].before(p);\n for (const node of group) p.appendChild(node);\n group = [];\n };\n for (const node of Array.from(wrapper.childNodes)) {\n if (isLooseInline(node)) {\n const blank = node.nodeType === 3 && (node.textContent ?? '').trim() === '';\n // Leading whitespace with nothing accumulated is left where it is.\n if (blank && !group.length) continue;\n group.push(node as ChildNode);\n } else {\n flush();\n }\n }\n flush();\n}\n\n/** Pushes a `<center>`/aligned-`<div>` alignment onto its blocks (and tables, for legacy forms). */\nfunction propagateBlockAlignment(wrapper: Element, value: string, centreTables: boolean): void {\n wrapLooseInline(wrapper, value);\n for (const block of alignableBlocks(wrapper)) {\n if (!hasOwnTextAlign(block)) addTextAlign(block, value);\n }\n if (centreTables) {\n for (const table of Array.from(wrapper.querySelectorAll('table'))) {\n if (insideNestedTable(table, wrapper)) continue;\n if (!table.getAttribute('align')) table.setAttribute('align', value);\n }\n }\n}\n\n/** Pre-pass: resolve container-level alignment onto blocks/cells (see above). */\nfunction propagateEmailAlignment(body: HTMLElement): void {\n // Cases 2–4: <center>, div[align], div[style text-align].\n for (const el of Array.from(body.querySelectorAll('center, div'))) {\n const tag = el.tagName.toLowerCase();\n if (tag === 'center') {\n propagateBlockAlignment(el, 'center', true);\n continue;\n }\n const attr = el.getAttribute('align')?.toLowerCase();\n if (attr && LEGACY_ALIGN_KEYWORDS.has(attr)) {\n propagateBlockAlignment(el, attr, true);\n continue;\n }\n const styleAlign = /text-align\\s*:\\s*([a-z-]+)/i.exec(el.getAttribute('style') ?? '')?.[1]\n ?.toLowerCase();\n if (styleAlign && TEXT_ALIGN_KEYWORDS.has(styleAlign)) {\n propagateBlockAlignment(el, styleAlign, false);\n }\n }\n\n // Case 1: a cell's align must not leak into a table nested directly in it.\n for (const cell of Array.from(body.querySelectorAll('td[align], th[align]'))) {\n const attr = cell.getAttribute('align')?.toLowerCase();\n if (!attr || !LEGACY_ALIGN_KEYWORDS.has(attr)) continue;\n for (const table of Array.from(cell.querySelectorAll('table'))) {\n if (table.closest('td, th') !== cell) continue;\n for (const nested of directCells(table)) {\n if (!hasOwnTextAlign(nested)) addTextAlign(nested, 'left');\n }\n }\n }\n\n // Case 5: CSS text-align on a table → its direct cells that have none.\n for (const table of Array.from(body.querySelectorAll('table'))) {\n const styleAlign = /text-align\\s*:\\s*([a-z-]+)/i.exec(table.getAttribute('style') ?? '')?.[1]\n ?.toLowerCase();\n if (!styleAlign || !TEXT_ALIGN_KEYWORDS.has(styleAlign)) continue;\n for (const cell of directCells(table)) {\n if (!hasOwnTextAlign(cell)) addTextAlign(cell, styleAlign);\n }\n }\n\n // Case 6: tr[align] → its own cells that have none.\n for (const tr of Array.from(body.querySelectorAll('tr[align]'))) {\n const attr = tr.getAttribute('align')?.toLowerCase();\n if (!attr || !LEGACY_ALIGN_KEYWORDS.has(attr)) continue;\n for (const child of Array.from(tr.children)) {\n if (!/^t[dh]$/.test(child.tagName.toLowerCase())) continue;\n if (!hasOwnTextAlign(child)) addTextAlign(child, attr);\n }\n }\n}\n\n/**\n * Sanitizes an HTML string. Parsing happens in an inert document created by\n * DOMParser, so embedded scripts never execute and images never load.\n */\nexport function sanitizeHtml(\n html: string,\n options?: { emailFidelity?: boolean; allowedStyles?: NormalizedAllowedStyles }\n): string {\n // Wrap in an explicit <body> so metadata-like tags (notably <style>) stay in\n // the body instead of being hoisted into <head> by the HTML parser — which\n // would drop them before walk() ever sees them. Mirrors htmlToDoc's parse.\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n // Button links are restructured into one-cell tables before the walk, so the\n // cell/link styles they produce pass through the normal validators.\n if (options?.emailFidelity) {\n convertButtonLinks(doc.body);\n propagateEmailAlignment(doc.body);\n }\n walk(doc.body, options?.emailFidelity ?? false, options?.allowedStyles);\n return doc.body.innerHTML;\n}\n"]}
@@ -1,10 +1,13 @@
1
1
  import { Schema } from 'prosemirror-model';
2
2
  export type Alignment = 'left' | 'center' | 'right' | 'justify';
3
+ export declare function imageWidthCss(width: number | string | null): string | null;
3
4
  /** Indent depth in 40px steps, like CKEditor/Google Docs. */
4
5
  export declare const INDENT_STEP_PX = 40;
5
6
  export declare const MAX_INDENT = 8;
6
7
  export declare function cleanClass(value: string | null): string | null;
7
8
  export declare function cleanId(value: string | null): string | null;
9
+ /** Inline styles for a table's fidelity attrs; shared by toDOM and the live TableView. */
10
+ export declare function tableStyles(attrs: Record<string, unknown>): string[];
8
11
  /** Bullet markers CSS understands; anything else falls back to default. */
9
12
  export declare const BULLET_STYLES: readonly ["disc", "circle", "square"];
10
13
  /** Numbering styles, keyed by the HTML `type` attribute letter. */
@@ -3,7 +3,11 @@ import { addListNodes } from 'prosemirror-schema-list';
3
3
  import { tableNodes } from 'prosemirror-tables';
4
4
  import OrderedMap from 'orderedmap';
5
5
  import { EMBED_SANDBOX, EMBED_REFERRER_POLICY } from './plugins/embeds';
6
+ import { sanitizeExtraStyleForWrite } from './email-css';
7
+ import { sanitizeTableTextStyleForWrite } from './sanitize';
6
8
  const ALIGN_VALUES = ['left', 'center', 'right', 'justify'];
9
+ /** Keywords a cell's `text-align` attr may hold (email-fidelity). */
10
+ const CELL_ALIGN_KEYWORDS = new Set(['left', 'center', 'right', 'justify', 'start', 'end']);
7
11
  function getAlignFromDom(dom) {
8
12
  const value = dom.style.textAlign || dom.getAttribute('align') || '';
9
13
  return ALIGN_VALUES.includes(value) ? value : null;
@@ -11,6 +15,40 @@ function getAlignFromDom(dom) {
11
15
  function alignStyle(align) {
12
16
  return align ? `text-align: ${align}` : null;
13
17
  }
18
+ /** Image/figure width: a number is px, a `<n>%` string a percentage. */
19
+ const IMAGE_PERCENT = /^(\d{1,3}(?:\.\d{1,2})?)%$/;
20
+ export function imageWidthCss(width) {
21
+ if (typeof width === 'number')
22
+ return width > 0 ? `${width}px` : null;
23
+ if (typeof width === 'string') {
24
+ const match = IMAGE_PERCENT.exec(width.trim());
25
+ if (match) {
26
+ const n = parseFloat(match[1]);
27
+ if (n > 0 && n <= 100)
28
+ return width.trim();
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ /** Reads an img/figure width: a valid `<n>%` keeps the string, else px rounds. */
34
+ function imageWidthFromDom(styleWidth, attrWidth) {
35
+ const trimmed = styleWidth.trim();
36
+ // A percentage style width is kept only in range; an out-of-range/invalid one
37
+ // (e.g. '150%') is dropped rather than silently reinterpreted as px.
38
+ if (trimmed.endsWith('%')) {
39
+ const match = IMAGE_PERCENT.exec(trimmed);
40
+ if (match) {
41
+ const n = parseFloat(match[1]);
42
+ if (n > 0 && n <= 100)
43
+ return trimmed;
44
+ }
45
+ return null;
46
+ }
47
+ const sw = parseFloat(styleWidth);
48
+ const aw = parseFloat(attrWidth ?? '');
49
+ const px = Number.isFinite(sw) ? Math.round(sw) : Number.isFinite(aw) ? Math.round(aw) : null;
50
+ return px && px > 0 ? px : null;
51
+ }
14
52
  /** Indent depth in 40px steps, like CKEditor/Google Docs. */
15
53
  export const INDENT_STEP_PX = 40;
16
54
  export const MAX_INDENT = 8;
@@ -36,9 +74,23 @@ function getLineHeightFromDom(dom) {
36
74
  return String(num / 100);
37
75
  return raw;
38
76
  }
39
- /** Combined style string for align + indent + line-height textblock attrs. */
77
+ /** Fidelity block margin, stored as a ready-to-emit declaration string. */
78
+ function getMarginFromDom(dom) {
79
+ const s = dom.style;
80
+ if (s.margin)
81
+ return `margin: ${s.margin}`;
82
+ const parts = [];
83
+ if (s.marginTop)
84
+ parts.push(`margin-top: ${s.marginTop}`);
85
+ if (s.marginBottom)
86
+ parts.push(`margin-bottom: ${s.marginBottom}`);
87
+ return parts.length ? parts.join('; ') : null;
88
+ }
89
+ /** Combined style string for margin + align + indent + line-height textblock attrs. */
40
90
  function blockStyle(attrs) {
41
91
  const parts = [];
92
+ if (attrs.margin)
93
+ parts.push(attrs.margin);
42
94
  const align = alignStyle(attrs.align ?? null);
43
95
  if (align)
44
96
  parts.push(align);
@@ -46,6 +98,13 @@ function blockStyle(attrs) {
46
98
  parts.push(`margin-inline-start: ${attrs.indent * INDENT_STEP_PX}px`);
47
99
  if (attrs.lineHeight)
48
100
  parts.push(`line-height: ${attrs.lineHeight}`);
101
+ // Per-app extension declarations, re-validated against the permanent denylist
102
+ // + value grammar (the singleton schema can't see the per-app allowlist).
103
+ if (attrs.extraStyle) {
104
+ const safe = sanitizeExtraStyleForWrite(attrs.extraStyle);
105
+ if (safe)
106
+ parts.push(safe);
107
+ }
49
108
  return parts.length ? parts.join('; ') : null;
50
109
  }
51
110
  /* -------------------------------------------------------------------------
@@ -152,6 +211,8 @@ const nodes = {
152
211
  align: { default: null },
153
212
  indent: { default: 0 },
154
213
  lineHeight: { default: null },
214
+ margin: { default: null },
215
+ extraStyle: { default: null },
155
216
  },
156
217
  parseDOM: [
157
218
  {
@@ -160,6 +221,8 @@ const nodes = {
160
221
  align: getAlignFromDom(dom),
161
222
  indent: getIndentFromDom(dom),
162
223
  lineHeight: getLineHeightFromDom(dom),
224
+ margin: getMarginFromDom(dom),
225
+ extraStyle: dom.getAttribute('data-extra-style'),
163
226
  }),
164
227
  },
165
228
  ],
@@ -177,6 +240,8 @@ const nodes = {
177
240
  align: { default: null },
178
241
  indent: { default: 0 },
179
242
  lineHeight: { default: null },
243
+ margin: { default: null },
244
+ extraStyle: { default: null },
180
245
  },
181
246
  parseDOM: [1, 2, 3, 4, 5, 6].map(level => ({
182
247
  tag: `h${level}`,
@@ -185,6 +250,8 @@ const nodes = {
185
250
  align: getAlignFromDom(dom),
186
251
  indent: getIndentFromDom(dom),
187
252
  lineHeight: getLineHeightFromDom(dom),
253
+ margin: getMarginFromDom(dom),
254
+ extraStyle: dom.getAttribute('data-extra-style'),
188
255
  }),
189
256
  })),
190
257
  toDOM(node) {
@@ -243,10 +310,7 @@ const nodes = {
243
310
  return ['pre', attrs, ['code', 0]];
244
311
  },
245
312
  },
246
- /**
247
- * ProseMirror's canonical inline image, extended with a `width` attr (px)
248
- * written by the drag-resize handles.
249
- */
313
+ /** Inline image with a `width` attr (px number or `<n>%`). */
250
314
  image: {
251
315
  inline: true,
252
316
  group: 'inline',
@@ -260,21 +324,12 @@ const nodes = {
260
324
  parseDOM: [
261
325
  {
262
326
  tag: 'img[src]',
263
- getAttrs: (dom) => {
264
- const styleWidth = parseFloat(dom.style.width);
265
- const attrWidth = parseFloat(dom.getAttribute('width') ?? '');
266
- const width = Number.isFinite(styleWidth)
267
- ? Math.round(styleWidth)
268
- : Number.isFinite(attrWidth)
269
- ? Math.round(attrWidth)
270
- : null;
271
- return {
272
- src: dom.getAttribute('src'),
273
- alt: dom.getAttribute('alt'),
274
- title: dom.getAttribute('title'),
275
- width: width && width > 0 ? width : null,
276
- };
277
- },
327
+ getAttrs: (dom) => ({
328
+ src: dom.getAttribute('src'),
329
+ alt: dom.getAttribute('alt'),
330
+ title: dom.getAttribute('title'),
331
+ width: imageWidthFromDom(dom.style.width, dom.getAttribute('width') ?? ''),
332
+ }),
278
333
  },
279
334
  ],
280
335
  toDOM(node) {
@@ -284,8 +339,9 @@ const nodes = {
284
339
  attrs.alt = alt;
285
340
  if (title)
286
341
  attrs.title = title;
287
- if (width)
288
- attrs.style = `width: ${width}px`;
342
+ const css = imageWidthCss(width);
343
+ if (css)
344
+ attrs.style = `width: ${css}`;
289
345
  return ['img', attrs];
290
346
  },
291
347
  },
@@ -315,15 +371,12 @@ const nodes = {
315
371
  const img = dom.querySelector('img[src]');
316
372
  if (!img)
317
373
  return false;
318
- const styleWidth = parseFloat(img.style.width || dom.style.width);
319
374
  const align = dom.getAttribute('data-align');
320
375
  return {
321
376
  src: img.getAttribute('src'),
322
377
  alt: img.getAttribute('alt'),
323
378
  title: img.getAttribute('title'),
324
- width: Number.isFinite(styleWidth) && styleWidth > 0
325
- ? Math.round(styleWidth)
326
- : null,
379
+ width: imageWidthFromDom(img.style.width || dom.style.width),
327
380
  align: align === 'left' || align === 'center' || align === 'right' ? align : null,
328
381
  };
329
382
  },
@@ -335,8 +388,9 @@ const nodes = {
335
388
  if (align)
336
389
  figureAttrs['data-align'] = align;
337
390
  const styles = [];
338
- if (width)
339
- styles.push(`width: ${width}px`);
391
+ const widthCss = imageWidthCss(width);
392
+ if (widthCss)
393
+ styles.push(`width: ${widthCss}`);
340
394
  if (align === 'center')
341
395
  styles.push('margin-left: auto; margin-right: auto');
342
396
  else if (align === 'right')
@@ -640,7 +694,20 @@ const nodes = {
640
694
  },
641
695
  },
642
696
  };
643
- /** Table nodes from prosemirror-tables, with cell background support. */
697
+ /** A cell attr that reads and writes one inline-style declaration. */
698
+ function cellStyleAttr(cssName) {
699
+ return {
700
+ default: null,
701
+ getFromDOM(dom) {
702
+ return dom.style.getPropertyValue(cssName) || null;
703
+ },
704
+ setDOMAttr(value, attrs) {
705
+ if (value)
706
+ attrs.style = `${attrs.style || ''}${cssName}: ${value};`;
707
+ },
708
+ };
709
+ }
710
+ /** Table nodes from prosemirror-tables, with cell background + email-layout support. */
644
711
  const tableNodeSpecs = tableNodes({
645
712
  tableGroup: 'block',
646
713
  cellContent: 'block+',
@@ -648,7 +715,11 @@ const tableNodeSpecs = tableNodes({
648
715
  background: {
649
716
  default: null,
650
717
  getFromDOM(dom) {
651
- return dom.style.backgroundColor || null;
718
+ // Fidelity stashes the cell background on a data-attr (so it never
719
+ // becomes a bg mark); legacy/non-fidelity content keeps it in the style.
720
+ return (dom.getAttribute('data-cell-bg') ||
721
+ dom.style.backgroundColor ||
722
+ null);
652
723
  },
653
724
  setDOMAttr(value, attrs) {
654
725
  if (value) {
@@ -656,6 +727,57 @@ const tableNodeSpecs = tableNodes({
656
727
  }
657
728
  },
658
729
  },
730
+ // Padding is read per side so partial shorthands round-trip.
731
+ paddingTop: cellStyleAttr('padding-top'),
732
+ paddingRight: cellStyleAttr('padding-right'),
733
+ paddingBottom: cellStyleAttr('padding-bottom'),
734
+ paddingLeft: cellStyleAttr('padding-left'),
735
+ width: cellStyleAttr('width'),
736
+ valign: cellStyleAttr('vertical-align'),
737
+ borderTop: cellStyleAttr('border-top'),
738
+ borderRight: cellStyleAttr('border-right'),
739
+ borderBottom: cellStyleAttr('border-bottom'),
740
+ borderLeft: cellStyleAttr('border-left'),
741
+ borderRadius: cellStyleAttr('border-radius'),
742
+ // Cell text colour/font, carried on a data-attr so it inherits through the
743
+ // cell's style instead of spawning a span on every text run.
744
+ textStyle: {
745
+ default: null,
746
+ getFromDOM(dom) {
747
+ return dom.getAttribute('data-cell-text-style') || null;
748
+ },
749
+ setDOMAttr(value, attrs) {
750
+ const safe = sanitizeTableTextStyleForWrite(value);
751
+ if (safe)
752
+ attrs.style = `${attrs.style || ''}${safe};`;
753
+ },
754
+ },
755
+ // Cell text-align, carried on data-cell-align (never the live style) so
756
+ // flag-off output is unchanged; validated against the keyword set on write.
757
+ textAlign: {
758
+ default: null,
759
+ getFromDOM(dom) {
760
+ return dom.getAttribute('data-cell-align') || null;
761
+ },
762
+ setDOMAttr(value, attrs) {
763
+ const v = String(value ?? '').toLowerCase();
764
+ if (CELL_ALIGN_KEYWORDS.has(v)) {
765
+ attrs.style = `${attrs.style || ''}text-align: ${v};`;
766
+ }
767
+ },
768
+ },
769
+ // Per-app extension declarations, re-validated on write-back.
770
+ extraStyle: {
771
+ default: null,
772
+ getFromDOM(dom) {
773
+ return dom.getAttribute('data-extra-style') || null;
774
+ },
775
+ setDOMAttr(value, attrs) {
776
+ const safe = sanitizeExtraStyleForWrite(value);
777
+ if (safe)
778
+ attrs.style = `${attrs.style || ''}${safe};`;
779
+ },
780
+ },
659
781
  },
660
782
  });
661
783
  /**
@@ -664,21 +786,80 @@ const tableNodeSpecs = tableNodes({
664
786
  * borderless, with dashed guides visible only while editing.
665
787
  */
666
788
  const baseTableSpec = tableNodeSpecs.table;
789
+ /** Inline styles for a table's fidelity attrs; shared by toDOM and the live TableView. */
790
+ export function tableStyles(attrs) {
791
+ const { width, maxWidth, background, border, align, textStyle, extraStyle } = attrs;
792
+ const styles = [];
793
+ if (width)
794
+ styles.push(`width: ${width}`);
795
+ if (maxWidth)
796
+ styles.push(`max-width: ${maxWidth}`);
797
+ if (background)
798
+ styles.push(`background-color: ${background}`);
799
+ if (border)
800
+ styles.push(`border: ${border}`);
801
+ if (align === 'center')
802
+ styles.push('margin-left: auto', 'margin-right: auto');
803
+ // Table-level font/colour/line-height, re-validated on write-back (same
804
+ // validators as the sanitizer) so cells/paragraphs inherit it through CSS.
805
+ if (textStyle) {
806
+ const safe = sanitizeTableTextStyleForWrite(textStyle);
807
+ if (safe)
808
+ styles.push(safe);
809
+ }
810
+ // Per-app extension declarations, re-validated against the permanent denylist
811
+ // + value grammar on write-back (the singleton schema can't see the allowlist).
812
+ if (extraStyle) {
813
+ const safe = sanitizeExtraStyleForWrite(extraStyle);
814
+ if (safe)
815
+ styles.push(safe);
816
+ }
817
+ return styles;
818
+ }
667
819
  const tableSpec = {
668
820
  ...baseTableSpec,
669
- attrs: { ...(baseTableSpec.attrs ?? {}), layout: { default: false } },
821
+ attrs: {
822
+ ...(baseTableSpec.attrs ?? {}),
823
+ layout: { default: false },
824
+ width: { default: null },
825
+ maxWidth: { default: null },
826
+ background: { default: null },
827
+ border: { default: null },
828
+ align: { default: null },
829
+ textStyle: { default: null },
830
+ extraStyle: { default: null },
831
+ },
670
832
  parseDOM: [
671
833
  {
672
834
  tag: 'table',
673
835
  getAttrs: (dom) => ({
674
836
  layout: dom.getAttribute('role') === 'presentation' || dom.hasAttribute('data-layout'),
837
+ width: dom.style.width || null,
838
+ maxWidth: dom.style.maxWidth || null,
839
+ extraStyle: dom.getAttribute('data-extra-style') || null,
840
+ // Table font/colour comes only from the fidelity data-attr (so flag-off
841
+ // tables keep today's no-table-text-style behaviour).
842
+ textStyle: dom.getAttribute('data-table-text-style') || null,
843
+ // Table background comes only from the fidelity data-attr.
844
+ background: dom.getAttribute('data-table-bg') || null,
845
+ border: dom.style.border || null,
846
+ // Centring comes from the fidelity data-attr (email `align="center"`) or
847
+ // from auto side margins written back by toDOM.
848
+ align: dom.getAttribute('data-table-align') === 'center' ||
849
+ (dom.style.marginLeft === 'auto' && dom.style.marginRight === 'auto')
850
+ ? 'center'
851
+ : null,
675
852
  }),
676
853
  },
677
854
  ],
678
855
  toDOM(node) {
679
- return node.attrs.layout
680
- ? ['table', { role: 'presentation', 'data-layout': 'true' }, ['tbody', 0]]
681
- : ['table', ['tbody', 0]];
856
+ const styles = tableStyles(node.attrs);
857
+ const attrs = node.attrs.layout
858
+ ? { role: 'presentation', 'data-layout': 'true' }
859
+ : {};
860
+ if (styles.length)
861
+ attrs.style = styles.join('; ');
862
+ return ['table', attrs, ['tbody', 0]];
682
863
  },
683
864
  };
684
865
  /**