@aquera/nile-elements 2.0.16 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/{index-f6944844.cjs.js → index-0c0c869d.cjs.js} +2 -2
- package/dist/{index-f6944844.cjs.js.map → index-0c0c869d.cjs.js.map} +1 -1
- package/dist/{index-403841c7.cjs.js → index-129ef6fb.cjs.js} +3 -3
- package/dist/{index-403841c7.cjs.js.map → index-129ef6fb.cjs.js.map} +1 -1
- package/dist/{index-1faa963c.esm.js → index-36f2a6b5.esm.js} +1 -1
- package/dist/index-4df50481.esm.js +1 -0
- package/dist/index-5d34cff1.esm.js +1 -0
- package/dist/index-7ae95edd.cjs.js +2 -0
- package/dist/{index-3ca67627.cjs.js.map → index-7ae95edd.cjs.js.map} +1 -1
- package/dist/index-7ca72b78.esm.js +1 -0
- package/dist/index-bbe23ad8.cjs.js +2 -0
- package/dist/index-bbe23ad8.cjs.js.map +1 -0
- package/dist/index-ccc6a799.cjs.js +5 -0
- package/dist/index-ccc6a799.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +686 -464
- package/dist/nile-auto-complete/index.cjs.js +1 -1
- package/dist/nile-auto-complete/nile-auto-complete.cjs.js +1 -1
- package/dist/nile-auto-complete/portal-manager.cjs.js +1 -1
- package/dist/nile-auto-complete/portal-utils.cjs.js +1 -1
- package/dist/nile-code-editor/extensionSetup.cjs.js +2 -2
- package/dist/nile-code-editor/index.cjs.js +1 -1
- package/dist/nile-code-editor/nile-code-editor.cjs.js +1 -1
- package/dist/nile-code-editor/theme.cjs.js +1 -1
- package/dist/nile-color-picker/index.cjs.js +1 -1
- package/dist/nile-color-picker/nile-color-picker.cjs.js +1 -1
- package/dist/nile-combobox/index.cjs.js +1 -1
- package/dist/nile-combobox/nile-combobox.cjs.js +1 -1
- package/dist/nile-combobox/portal-manager.cjs.js +1 -1
- package/dist/nile-context-menu/index.cjs.js +1 -1
- package/dist/nile-context-menu/nile-context-menu.cjs.js +1 -1
- package/dist/nile-context-submenu/index.cjs.js +1 -1
- package/dist/nile-context-submenu/nile-context-submenu.cjs.js +1 -1
- package/dist/nile-detail/index.cjs.js +1 -1
- package/dist/nile-detail/nile-detail.cjs.js +1 -1
- package/dist/nile-dropdown/index.cjs.js +1 -1
- package/dist/nile-dropdown/nile-dropdown.cjs.js +1 -1
- package/dist/nile-dropdown/portal-manager.cjs.js +1 -1
- package/dist/nile-file-upload/index.cjs.js +1 -1
- package/dist/nile-file-upload/nile-file-upload.cjs.js +1 -1
- package/dist/nile-file-upload/nile-file-upload.template.cjs.js +1 -1
- package/dist/nile-floating-panel/index.cjs.js +1 -1
- package/dist/nile-floating-panel/nile-floating-panel.cjs.js +1 -1
- package/dist/nile-lite-tooltip/index.cjs.js +1 -1
- package/dist/nile-lite-tooltip/nile-lite-tooltip.cjs.js +1 -1
- package/dist/nile-markdown-editor/index.cjs.js +1 -1
- package/dist/nile-markdown-editor/nile-markdown-editor.cjs.js +1 -1
- package/dist/nile-minimap/index.cjs.js +2 -0
- package/dist/nile-minimap/index.cjs.js.map +1 -0
- package/dist/nile-minimap/index.esm.js +1 -0
- package/dist/nile-minimap/nile-minimap.cjs.js +2 -0
- package/dist/nile-minimap/nile-minimap.cjs.js.map +1 -0
- package/dist/nile-minimap/nile-minimap.css.cjs.js +2 -0
- package/dist/nile-minimap/nile-minimap.css.cjs.js.map +1 -0
- package/dist/nile-minimap/nile-minimap.css.esm.js +150 -0
- package/dist/nile-minimap/nile-minimap.esm.js +22 -0
- package/dist/nile-popover/index.cjs.js +1 -1
- package/dist/nile-popover/nile-popover.cjs.js +1 -1
- package/dist/nile-popover/portal-manager.cjs.js +1 -1
- package/dist/nile-popup/index.cjs.js +1 -1
- package/dist/nile-popup/nile-popup.cjs.js +1 -1
- package/dist/nile-segmented-progress-bar/index.cjs.js +1 -1
- package/dist/nile-segmented-progress-bar/nile-segmented-progress-bar.cjs.js +1 -1
- package/dist/nile-select/index.cjs.js +1 -1
- package/dist/nile-select/nile-select.cjs.js +1 -1
- package/dist/nile-select/portal-manager.cjs.js +1 -1
- package/dist/nile-side-bar-action/index.cjs.js +1 -1
- package/dist/nile-side-bar-action/nile-side-bar-action.cjs.js +1 -1
- package/dist/nile-side-bar-action/portal-manager.cjs.js +1 -1
- package/dist/nile-tooltip/index.cjs.js +1 -1
- package/dist/nile-tooltip/nile-tooltip.cjs.js +1 -1
- package/dist/nile-virtual-select/index.cjs.js +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +1 -1
- package/dist/nile-virtual-select/portal-manager.cjs.js +1 -1
- package/dist/nile-virtual-select/renderer.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/commands.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/commands.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/commands.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/create-state.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/create-state.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/create-state.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/email-css.cjs.js +2 -0
- package/dist/nile-wysiwyg-editor/engine/email-css.cjs.js.map +1 -0
- package/dist/nile-wysiwyg-editor/engine/email-css.esm.js +1 -0
- package/dist/nile-wysiwyg-editor/engine/email-render.cjs.js +2 -0
- package/dist/nile-wysiwyg-editor/engine/email-render.cjs.js.map +1 -0
- package/dist/nile-wysiwyg-editor/engine/email-render.esm.js +1 -0
- package/dist/nile-wysiwyg-editor/engine/html-detect.cjs.js +2 -0
- package/dist/nile-wysiwyg-editor/engine/html-detect.cjs.js.map +1 -0
- package/dist/nile-wysiwyg-editor/engine/html-detect.esm.js +1 -0
- package/dist/nile-wysiwyg-editor/engine/index.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/index.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/inputrules.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/inputrules.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/inputrules.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/keymap.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/keymap.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/keymap.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/code-highlight.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embed-view.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embeds.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embeds.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/embeds.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/find-replace.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/format-painter.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image-view.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image-view.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image-view.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/image.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/link.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/link.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/link.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/max-length.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/max-length.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/max-length.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/paste.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/paste.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/paste.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/placeholder.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/single-line.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/single-line.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/single-line.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/suggestions.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/tables.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/tables.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/plugins/tables.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/sanitize.cjs.js +2 -1
- package/dist/nile-wysiwyg-editor/engine/sanitize.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/sanitize.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/schema.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/schema.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/schema.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/selection-state.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/selection-state.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/selection-state.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/serializer.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/engine/serializer.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/engine/serializer.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/index.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/index.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.css.esm.js +45 -4
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-editor.esm.js +2 -2
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-toolbar/index.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/nile-wysiwyg-toolbar/nile-wysiwyg-toolbar.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/bookmark-panel.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/bookmark-panel.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/bookmark-panel.esm.js +2 -2
- package/dist/nile-wysiwyg-editor/ui/bubble-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/bubble-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/bubble-menu.esm.js +5 -5
- package/dist/nile-wysiwyg-editor/ui/code-block-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/code-block-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/code-block-menu.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-menu.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-panel.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-panel.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/embed-panel.esm.js +2 -2
- package/dist/nile-wysiwyg-editor/ui/emoji-picker.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/emoji-picker.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/emoji-picker.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/find-replace.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/find-replace.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/find-replace.esm.js +3 -3
- package/dist/nile-wysiwyg-editor/ui/image-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/image-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/image-menu.esm.js +3 -3
- package/dist/nile-wysiwyg-editor/ui/image-panel.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/image-panel.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/image-panel.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/insert-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/insert-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/insert-menu.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/link-editor.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/link-editor.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/link-editor.esm.js +9 -9
- package/dist/nile-wysiwyg-editor/ui/markdown-panel.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/markdown-panel.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/markdown-panel.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/math-panel.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/math-panel.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/math-panel.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/shortcut-help.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/shortcut-help.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/shortcut-help.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/source-view.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/source-view.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/source-view.esm.js +4 -4
- package/dist/nile-wysiwyg-editor/ui/special-chars.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/special-chars.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/special-chars.esm.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/suggest-list.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/suggest-list.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/suggest-list.esm.js +23 -12
- package/dist/nile-wysiwyg-editor/ui/table-grid-picker.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/table-grid-picker.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/table-grid-picker.esm.js +7 -7
- package/dist/nile-wysiwyg-editor/ui/table-menu.cjs.js +1 -1
- package/dist/nile-wysiwyg-editor/ui/table-menu.cjs.js.map +1 -1
- package/dist/nile-wysiwyg-editor/ui/table-menu.esm.js +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/nile-minimap/index.d.ts +1 -0
- package/dist/src/nile-minimap/index.js +2 -0
- package/dist/src/nile-minimap/index.js.map +1 -0
- package/dist/src/nile-minimap/nile-minimap.css.d.ts +12 -0
- package/dist/src/nile-minimap/nile-minimap.css.js +162 -0
- package/dist/src/nile-minimap/nile-minimap.css.js.map +1 -0
- package/dist/src/nile-minimap/nile-minimap.d.ts +131 -0
- package/dist/src/nile-minimap/nile-minimap.js +704 -0
- package/dist/src/nile-minimap/nile-minimap.js.map +1 -0
- package/dist/src/nile-minimap/nile-minimap.test.d.ts +1 -0
- package/dist/src/nile-minimap/nile-minimap.test.js +785 -0
- package/dist/src/nile-minimap/nile-minimap.test.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/create-state.d.ts +5 -0
- package/dist/src/nile-wysiwyg-editor/engine/create-state.js +2 -0
- package/dist/src/nile-wysiwyg-editor/engine/create-state.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/email-css.d.ts +14 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-css.js +140 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-css.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.d.ts +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.js +1045 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-fidelity.test.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-render.d.ts +11 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-render.js +93 -0
- package/dist/src/nile-wysiwyg-editor/engine/email-render.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/html-detect.d.ts +2 -0
- package/dist/src/nile-wysiwyg-editor/engine/html-detect.js +24 -0
- package/dist/src/nile-wysiwyg-editor/engine/html-detect.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/engine/index.d.ts +4 -1
- package/dist/src/nile-wysiwyg-editor/engine/index.js +3 -1
- package/dist/src/nile-wysiwyg-editor/engine/index.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/inputrules.d.ts +0 -5
- package/dist/src/nile-wysiwyg-editor/engine/inputrules.js +19 -0
- package/dist/src/nile-wysiwyg-editor/engine/inputrules.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/plugins/image-view.js +3 -2
- package/dist/src/nile-wysiwyg-editor/engine/plugins/image-view.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/plugins/link.d.ts +4 -0
- package/dist/src/nile-wysiwyg-editor/engine/plugins/link.js +56 -1
- package/dist/src/nile-wysiwyg-editor/engine/plugins/link.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.d.ts +5 -0
- package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.js +27 -6
- package/dist/src/nile-wysiwyg-editor/engine/plugins/paste.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/plugins/tables.js +30 -7
- package/dist/src/nile-wysiwyg-editor/engine/plugins/tables.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/pm.test.js +46 -0
- package/dist/src/nile-wysiwyg-editor/engine/pm.test.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/sanitize.d.ts +9 -1
- package/dist/src/nile-wysiwyg-editor/engine/sanitize.js +730 -7
- package/dist/src/nile-wysiwyg-editor/engine/sanitize.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/schema.d.ts +3 -0
- package/dist/src/nile-wysiwyg-editor/engine/schema.js +215 -34
- package/dist/src/nile-wysiwyg-editor/engine/schema.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/selection-state.js +3 -1
- package/dist/src/nile-wysiwyg-editor/engine/selection-state.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/engine/serializer.d.ts +12 -4
- package/dist/src/nile-wysiwyg-editor/engine/serializer.js +18 -8
- package/dist/src/nile-wysiwyg-editor/engine/serializer.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.d.ts +1 -0
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.js +287 -0
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.js.map +1 -0
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.js +45 -4
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.d.ts +23 -0
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.js +113 -15
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.js +213 -0
- package/dist/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/bookmark-panel.js +2 -2
- package/dist/src/nile-wysiwyg-editor/ui/bookmark-panel.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/bubble-menu.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/bubble-menu.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/embed-menu.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/embed-menu.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/embed-panel.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/embed-panel.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/emoji-picker.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/emoji-picker.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/find-replace.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/find-replace.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/image-menu.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/image-menu.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/image-panel.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/image-panel.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/insert-menu.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/insert-menu.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/link-editor.js +2 -2
- package/dist/src/nile-wysiwyg-editor/ui/link-editor.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/markdown-panel.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/markdown-panel.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/math-panel.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/math-panel.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/shortcut-help.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/shortcut-help.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/source-view.js +2 -2
- package/dist/src/nile-wysiwyg-editor/ui/source-view.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/special-chars.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/special-chars.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/suggest-list.js +14 -3
- package/dist/src/nile-wysiwyg-editor/ui/suggest-list.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/table-grid-picker.js +2 -2
- package/dist/src/nile-wysiwyg-editor/ui/table-grid-picker.js.map +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/table-menu.js +1 -1
- package/dist/src/nile-wysiwyg-editor/ui/table-menu.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/index.ts +1 -0
- package/src/nile-minimap/index.ts +1 -0
- package/src/nile-minimap/nile-minimap.css.ts +164 -0
- package/src/nile-minimap/nile-minimap.test.ts +924 -0
- package/src/nile-minimap/nile-minimap.ts +796 -0
- package/src/nile-wysiwyg-editor/engine/create-state.ts +7 -0
- package/src/nile-wysiwyg-editor/engine/email-css.ts +136 -0
- package/src/nile-wysiwyg-editor/engine/email-fidelity.test.ts +1347 -0
- package/src/nile-wysiwyg-editor/engine/email-render.ts +99 -0
- package/src/nile-wysiwyg-editor/engine/html-detect.ts +26 -0
- package/src/nile-wysiwyg-editor/engine/index.ts +10 -1
- package/src/nile-wysiwyg-editor/engine/inputrules.ts +18 -1
- package/src/nile-wysiwyg-editor/engine/plugins/image-view.ts +3 -2
- package/src/nile-wysiwyg-editor/engine/plugins/link.ts +58 -2
- package/src/nile-wysiwyg-editor/engine/plugins/paste.ts +31 -8
- package/src/nile-wysiwyg-editor/engine/plugins/tables.ts +29 -7
- package/src/nile-wysiwyg-editor/engine/pm.test.ts +73 -0
- package/src/nile-wysiwyg-editor/engine/sanitize.ts +729 -7
- package/src/nile-wysiwyg-editor/engine/schema.ts +206 -33
- package/src/nile-wysiwyg-editor/engine/selection-state.ts +3 -1
- package/src/nile-wysiwyg-editor/engine/serializer.ts +30 -8
- package/src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.ts +357 -0
- package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.ts +45 -4
- package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.test.ts +258 -0
- package/src/nile-wysiwyg-editor/nile-wysiwyg-editor.ts +119 -12
- package/src/nile-wysiwyg-editor/ui/bookmark-panel.ts +2 -2
- package/src/nile-wysiwyg-editor/ui/bubble-menu.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/embed-menu.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/embed-panel.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/emoji-picker.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/find-replace.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/image-menu.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/image-panel.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/insert-menu.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/link-editor.ts +2 -2
- package/src/nile-wysiwyg-editor/ui/markdown-panel.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/math-panel.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/shortcut-help.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/source-view.ts +2 -2
- package/src/nile-wysiwyg-editor/ui/special-chars.ts +1 -1
- package/src/nile-wysiwyg-editor/ui/suggest-list.ts +14 -3
- package/src/nile-wysiwyg-editor/ui/table-grid-picker.ts +2 -2
- package/src/nile-wysiwyg-editor/ui/table-menu.ts +1 -1
- package/vscode-html-custom-data.json +116 -25
- package/web-test-runner.config.mjs +4 -0
- package/dist/index-3ca67627.cjs.js +0 -2
- package/dist/index-6f3fa4ab.esm.js +0 -1
- package/dist/index-7b1c9857.esm.js +0 -1
- package/dist/index-89c520e9.cjs.js +0 -5
- package/dist/index-89c520e9.cjs.js.map +0 -1
- package/dist/index-ba47645d.esm.js +0 -1
- package/dist/index-c3210a9c.cjs.js +0 -2
- 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
|
-
/**
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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:
|
|
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
|
-
|
|
339
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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: {
|
|
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
|
-
|
|
680
|
-
|
|
681
|
-
:
|
|
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
|
/**
|