@aquera/nile-elements 2.0.15 → 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.
- package/README.md +6 -0
- package/demo/nxtgen-classes.css +5 -5
- package/demo/nxtgen-dark.css +16 -16
- package/demo/nxtgen-properties.css +2 -2
- package/demo/nxtgen-utilities.css +5 -5
- package/demo/nxtgen.css +5 -5
- package/demo/utilities.css +2 -2
- package/demo/variables.css +2 -2
- 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 +124 -72
- 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-lite-tooltip/nile-lite-tooltip.css.cjs.js +1 -1
- package/dist/nile-lite-tooltip/nile-lite-tooltip.css.cjs.js.map +1 -1
- package/dist/nile-lite-tooltip/nile-lite-tooltip.css.esm.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-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-tooltip/nile-tooltip.css.cjs.js +1 -1
- package/dist/nile-tooltip/nile-tooltip.css.cjs.js.map +1 -1
- package/dist/nile-tooltip/nile-tooltip.css.esm.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/nile-lite-tooltip/nile-lite-tooltip.css.js +1 -1
- package/dist/src/nile-lite-tooltip/nile-lite-tooltip.css.js.map +1 -1
- package/dist/src/nile-tooltip/nile-tooltip.css.js +1 -1
- package/dist/src/nile-tooltip/nile-tooltip.css.js.map +1 -1
- 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/dist/version.cjs.js +1 -1
- package/dist/version.cjs.js.map +1 -1
- package/dist/version.esm.js +1 -1
- package/package.json +1 -1
- package/src/nile-lite-tooltip/nile-lite-tooltip.css.ts +1 -1
- package/src/nile-tooltip/nile-tooltip.css.ts +1 -1
- 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 +15 -1
- 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
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { fixture, expect } from '@open-wc/testing';
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import '../index';
|
|
4
|
+
import { TextSelection } from 'prosemirror-state';
|
|
5
|
+
async function editorFixture(template = html `<nile-wysiwyg-editor></nile-wysiwyg-editor>`) {
|
|
6
|
+
const el = await fixture(template);
|
|
7
|
+
await el.updateComplete;
|
|
8
|
+
return el;
|
|
9
|
+
}
|
|
10
|
+
/** A compact table-based email with cell padding and a 600px container. */
|
|
11
|
+
const EMAIL_FIXTURE = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">' +
|
|
12
|
+
'<tr><td align="center" style="padding:32px 12px;">' +
|
|
13
|
+
'<table role="presentation" width="600" style="width:100%; max-width:600px; background-color:#ffffff; border:1px solid #d9dee4;">' +
|
|
14
|
+
'<tr><td style="padding:28px 40px; background-color:#1f3a5f;">' +
|
|
15
|
+
'<p style="margin:0; font-family:Georgia, serif; color:#ffffff;">Company Name</p>' +
|
|
16
|
+
'</td></tr>' +
|
|
17
|
+
'<tr><td style="padding:36px 40px; font-family:Arial, sans-serif; color:#2b2f36;">' +
|
|
18
|
+
'<p style="margin:0 0 18px 0;">Hello there.</p>' +
|
|
19
|
+
'</td></tr>' +
|
|
20
|
+
'</table></td></tr></table>';
|
|
21
|
+
/** A full standalone HTML document, the kind that lands in text/plain. */
|
|
22
|
+
const FULL_DOC = '<!doctype html><html><body>' +
|
|
23
|
+
'<table role="presentation"><tr><td style="padding:16px">Pasted cell</td></tr></table>' +
|
|
24
|
+
'</body></html>';
|
|
25
|
+
/** Fire a paste through the ProseMirror view's handlePaste prop. */
|
|
26
|
+
function firePaste(el, data) {
|
|
27
|
+
const view = el.pmView;
|
|
28
|
+
const dt = new DataTransfer();
|
|
29
|
+
for (const [type, value] of Object.entries(data))
|
|
30
|
+
dt.setData(type, value);
|
|
31
|
+
const event = new ClipboardEvent('paste', { clipboardData: dt });
|
|
32
|
+
return view.someProp('handlePaste', f => f(view, event, view.state.tr.doc.slice(0)));
|
|
33
|
+
}
|
|
34
|
+
describe('nile-wysiwyg-editor email-fidelity: property reflection', () => {
|
|
35
|
+
it('1. defaults emailFidelity to false', async () => {
|
|
36
|
+
const el = await editorFixture();
|
|
37
|
+
expect(el.emailFidelity).to.equal(false);
|
|
38
|
+
expect(el.hasAttribute('email-fidelity')).to.equal(false);
|
|
39
|
+
});
|
|
40
|
+
it('2. reflects the property to the kebab attribute', async () => {
|
|
41
|
+
const el = await editorFixture();
|
|
42
|
+
el.emailFidelity = true;
|
|
43
|
+
await el.updateComplete;
|
|
44
|
+
expect(el.hasAttribute('email-fidelity')).to.equal(true);
|
|
45
|
+
});
|
|
46
|
+
it('3. reads the attribute into the property', async () => {
|
|
47
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`);
|
|
48
|
+
expect(el.emailFidelity).to.equal(true);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('nile-wysiwyg-editor email-fidelity: value parsing', () => {
|
|
52
|
+
it('4. keeps cell padding in value with the flag on', async () => {
|
|
53
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`);
|
|
54
|
+
el.value = EMAIL_FIXTURE;
|
|
55
|
+
await el.updateComplete;
|
|
56
|
+
const doc = new DOMParser().parseFromString(el.value, 'text/html');
|
|
57
|
+
const padded = Array.from(doc.querySelectorAll('td')).some(td => td.style.padding !== '' || td.style.paddingTop !== '');
|
|
58
|
+
expect(padded, 'a td keeps padding').to.equal(true);
|
|
59
|
+
});
|
|
60
|
+
it('5. strips cell padding in value with the flag off', async () => {
|
|
61
|
+
const el = await editorFixture();
|
|
62
|
+
el.value = EMAIL_FIXTURE;
|
|
63
|
+
await el.updateComplete;
|
|
64
|
+
expect(el.value).to.not.include('padding');
|
|
65
|
+
});
|
|
66
|
+
it('6. re-parses value when the flag toggles on', async () => {
|
|
67
|
+
const el = await editorFixture();
|
|
68
|
+
el.value = EMAIL_FIXTURE;
|
|
69
|
+
await el.updateComplete;
|
|
70
|
+
expect(el.value).to.not.include('padding');
|
|
71
|
+
el.emailFidelity = true;
|
|
72
|
+
el.value = EMAIL_FIXTURE;
|
|
73
|
+
await el.updateComplete;
|
|
74
|
+
expect(el.value).to.match(/padding/);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('nile-wysiwyg-editor email-fidelity: paste', () => {
|
|
78
|
+
it('7. parses a text/plain-only HTML document when the flag is on', async () => {
|
|
79
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`);
|
|
80
|
+
const handled = firePaste(el, { 'text/plain': FULL_DOC });
|
|
81
|
+
expect(handled).to.equal(true);
|
|
82
|
+
await el.updateComplete;
|
|
83
|
+
expect(el.getHTML()).to.include('<table');
|
|
84
|
+
expect(el.getHTML()).to.not.include('<table');
|
|
85
|
+
});
|
|
86
|
+
it('8. inserts the HTML document literally when the flag is off', async () => {
|
|
87
|
+
const el = await editorFixture();
|
|
88
|
+
firePaste(el, { 'text/plain': FULL_DOC });
|
|
89
|
+
await el.updateComplete;
|
|
90
|
+
// No real table node — the markup is kept as literal text.
|
|
91
|
+
expect(el.getHTML()).to.not.include('<table');
|
|
92
|
+
expect(el.getText()).to.include('<table');
|
|
93
|
+
});
|
|
94
|
+
it('9. paste-as-plain-text wins over HTML detection', async () => {
|
|
95
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity paste-as-plain-text></nile-wysiwyg-editor>`);
|
|
96
|
+
firePaste(el, { 'text/plain': FULL_DOC });
|
|
97
|
+
await el.updateComplete;
|
|
98
|
+
expect(el.getHTML()).to.not.include('<table');
|
|
99
|
+
expect(el.getText()).to.include('<table');
|
|
100
|
+
});
|
|
101
|
+
it('10. markdown text still goes through markdown with the flag on', async () => {
|
|
102
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`);
|
|
103
|
+
firePaste(el, { 'text/plain': '# Heading\n\nSome **bold** text.' });
|
|
104
|
+
await el.updateComplete;
|
|
105
|
+
const out = el.getHTML();
|
|
106
|
+
expect(out).to.include('<h1>');
|
|
107
|
+
expect(out).to.include('<strong>');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
/** Focuses the editor with the caret inside the first text that equals `text`. */
|
|
111
|
+
async function caretIn(el, text) {
|
|
112
|
+
const view = el.pmView;
|
|
113
|
+
let pos = -1;
|
|
114
|
+
view.state.doc.descendants((node, at) => {
|
|
115
|
+
if (pos === -1 && node.isText && node.text === text)
|
|
116
|
+
pos = at + 1;
|
|
117
|
+
return pos === -1;
|
|
118
|
+
});
|
|
119
|
+
view.focus();
|
|
120
|
+
view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, pos)));
|
|
121
|
+
await el.updateComplete;
|
|
122
|
+
await new Promise(r => setTimeout(r, 50));
|
|
123
|
+
}
|
|
124
|
+
function tableMenuOpen(el) {
|
|
125
|
+
return !!el.shadowRoot.querySelector('nile-wysiwyg-table-menu').hasAttribute('open');
|
|
126
|
+
}
|
|
127
|
+
const DATA_TABLE = '<table><tr><td>data cell</td></tr></table>';
|
|
128
|
+
const LAYOUT_TABLE = '<table role="presentation"><tr><td><p>layout cell</p></td></tr></table>';
|
|
129
|
+
const DATA_IN_LAYOUT = '<table role="presentation"><tr><td><table><tr><td>inner data</td></tr></table></td></tr></table>';
|
|
130
|
+
describe('nile-wysiwyg-editor: table menu visibility', () => {
|
|
131
|
+
it('11. shows in a data table by default', async () => {
|
|
132
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor .value=${DATA_TABLE}></nile-wysiwyg-editor>`);
|
|
133
|
+
await caretIn(el, 'data cell');
|
|
134
|
+
expect(tableMenuOpen(el)).to.equal(true);
|
|
135
|
+
});
|
|
136
|
+
it('12. no-table-menu hides it', async () => {
|
|
137
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor no-table-menu .value=${DATA_TABLE}></nile-wysiwyg-editor>`);
|
|
138
|
+
expect(el.noTableMenu).to.equal(true);
|
|
139
|
+
await caretIn(el, 'data cell');
|
|
140
|
+
expect(tableMenuOpen(el)).to.equal(false);
|
|
141
|
+
});
|
|
142
|
+
it('13. toggling noTableMenu while focused closes and reopens it', async () => {
|
|
143
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor .value=${DATA_TABLE}></nile-wysiwyg-editor>`);
|
|
144
|
+
await caretIn(el, 'data cell');
|
|
145
|
+
el.noTableMenu = true;
|
|
146
|
+
await el.updateComplete;
|
|
147
|
+
expect(tableMenuOpen(el)).to.equal(false);
|
|
148
|
+
el.noTableMenu = false;
|
|
149
|
+
await el.updateComplete;
|
|
150
|
+
expect(tableMenuOpen(el)).to.equal(true);
|
|
151
|
+
});
|
|
152
|
+
it('14. email-fidelity hides it inside a layout table', async () => {
|
|
153
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity .value=${LAYOUT_TABLE}></nile-wysiwyg-editor>`);
|
|
154
|
+
await caretIn(el, 'layout cell');
|
|
155
|
+
expect(tableMenuOpen(el)).to.equal(false);
|
|
156
|
+
});
|
|
157
|
+
it('15. without email-fidelity a layout table still shows it (unchanged)', async () => {
|
|
158
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor .value=${LAYOUT_TABLE}></nile-wysiwyg-editor>`);
|
|
159
|
+
await caretIn(el, 'layout cell');
|
|
160
|
+
expect(tableMenuOpen(el)).to.equal(true);
|
|
161
|
+
});
|
|
162
|
+
it('16. email-fidelity still shows it in a data table nested in a layout table', async () => {
|
|
163
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor email-fidelity .value=${DATA_IN_LAYOUT}></nile-wysiwyg-editor>`);
|
|
164
|
+
await caretIn(el, 'inner data');
|
|
165
|
+
expect(tableMenuOpen(el)).to.equal(true);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
describe('nile-wysiwyg-editor email-fidelity: saved HTML matches the editor', () => {
|
|
169
|
+
/** A table with no role="presentation" and no layout styles of its own. */
|
|
170
|
+
const DATA_TABLE = '<table><tbody><tr><td><p>Employee Number:</p></td><td><p>1342</p></td></tr></tbody></table>';
|
|
171
|
+
const AUTHORED = '<table style="width: 600px"><tbody><tr><td style="padding: 20px; vertical-align: middle">' +
|
|
172
|
+
'<p style="margin: 0 0 12px 0">Kept</p></td></tr></tbody></table>';
|
|
173
|
+
const LAYOUT = '<table role="presentation"><tbody><tr><td><p>layout cell</p></td></tr></tbody></table>';
|
|
174
|
+
const parse = (out) => new DOMParser().parseFromString(out, 'text/html').body;
|
|
175
|
+
async function load(value, fidelity = true) {
|
|
176
|
+
const el = await editorFixture(fidelity
|
|
177
|
+
? html `<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`
|
|
178
|
+
: html `<nile-wysiwyg-editor></nile-wysiwyg-editor>`);
|
|
179
|
+
el.value = value;
|
|
180
|
+
await el.updateComplete;
|
|
181
|
+
return el;
|
|
182
|
+
}
|
|
183
|
+
it('1. writes the editor table rendering into a data table that sets none', async () => {
|
|
184
|
+
const el = await load(DATA_TABLE);
|
|
185
|
+
const body = parse(el.getHTML());
|
|
186
|
+
const table = body.querySelector('table');
|
|
187
|
+
expect(table.getAttribute('cellpadding')).to.equal('0');
|
|
188
|
+
expect(table.getAttribute('cellspacing')).to.equal('0');
|
|
189
|
+
expect(table.style.width).to.equal('100%');
|
|
190
|
+
expect(table.style.borderCollapse).to.equal('collapse');
|
|
191
|
+
expect(table.style.tableLayout).to.equal('fixed');
|
|
192
|
+
const td = body.querySelector('td');
|
|
193
|
+
expect(td.style.padding).to.equal('6px 8px');
|
|
194
|
+
expect(td.style.verticalAlign).to.equal('top');
|
|
195
|
+
const p = body.querySelector('p');
|
|
196
|
+
expect(p.style.marginTop).to.equal('0px');
|
|
197
|
+
expect(p.style.marginBottom).to.equal('0px');
|
|
198
|
+
});
|
|
199
|
+
it('2. keeps values the content sets itself', async () => {
|
|
200
|
+
const el = await load(AUTHORED);
|
|
201
|
+
const body = parse(el.getHTML());
|
|
202
|
+
expect(body.querySelector('table').style.width).to.equal('600px');
|
|
203
|
+
const td = body.querySelector('td');
|
|
204
|
+
expect(td.style.padding).to.equal('20px');
|
|
205
|
+
expect(td.style.verticalAlign).to.equal('middle');
|
|
206
|
+
expect(body.querySelector('p').style.margin).to.equal('0px 0px 12px');
|
|
207
|
+
});
|
|
208
|
+
it('3. leaves layout-table cells as authored, adding only cellpadding/cellspacing and collapse', async () => {
|
|
209
|
+
const el = await load(LAYOUT);
|
|
210
|
+
const body = parse(el.getHTML());
|
|
211
|
+
const table = body.querySelector('table');
|
|
212
|
+
expect(table.getAttribute('cellpadding')).to.equal('0');
|
|
213
|
+
expect(table.style.borderCollapse).to.equal('collapse');
|
|
214
|
+
expect(table.style.tableLayout).to.equal('');
|
|
215
|
+
expect(table.style.width).to.equal('');
|
|
216
|
+
const td = body.querySelector('td');
|
|
217
|
+
expect(td.style.padding).to.equal('');
|
|
218
|
+
expect(td.style.verticalAlign).to.equal('');
|
|
219
|
+
});
|
|
220
|
+
it('4. without email-fidelity the output is unchanged', async () => {
|
|
221
|
+
const el = await load(DATA_TABLE, false);
|
|
222
|
+
const out = el.getHTML();
|
|
223
|
+
expect(out).to.not.include('cellpadding');
|
|
224
|
+
expect(out).to.not.include('padding');
|
|
225
|
+
expect(out).to.not.include('border-collapse');
|
|
226
|
+
});
|
|
227
|
+
it('5. is stable across save and reload', async () => {
|
|
228
|
+
const first = await load(DATA_TABLE);
|
|
229
|
+
const saved = first.getHTML();
|
|
230
|
+
const second = await load(saved);
|
|
231
|
+
expect(second.getHTML()).to.equal(saved);
|
|
232
|
+
expect(second.value).to.equal(saved);
|
|
233
|
+
});
|
|
234
|
+
it('6. writes cell borders and the header fill in the colours the theme draws', async () => {
|
|
235
|
+
const el = await editorFixture(html `<nile-wysiwyg-editor
|
|
236
|
+
email-fidelity
|
|
237
|
+
style="--nile-wysiwyg-table-border: rgb(1, 2, 3); --nile-wysiwyg-table-header-bg: rgb(4, 5, 6)"
|
|
238
|
+
></nile-wysiwyg-editor>`);
|
|
239
|
+
el.value =
|
|
240
|
+
'<table><tbody><tr><th><p>Attribute</p></th></tr><tr><td><p>Email</p></td></tr></tbody></table>';
|
|
241
|
+
await el.updateComplete;
|
|
242
|
+
const body = parse(el.getHTML());
|
|
243
|
+
const td = body.querySelector('td');
|
|
244
|
+
expect(td.style.borderTop).to.equal('1px solid rgb(1, 2, 3)');
|
|
245
|
+
expect(td.style.borderLeft).to.equal('1px solid rgb(1, 2, 3)');
|
|
246
|
+
const th = body.querySelector('th');
|
|
247
|
+
expect(th.style.backgroundColor).to.equal('rgb(4, 5, 6)');
|
|
248
|
+
expect(th.style.textAlign).to.equal('left');
|
|
249
|
+
expect(th.style.fontWeight).to.equal('600');
|
|
250
|
+
const again = await load(el.getHTML());
|
|
251
|
+
expect(parse(again.getHTML()).querySelector('td').style.borderTop).to.equal('1px solid rgb(1, 2, 3)');
|
|
252
|
+
});
|
|
253
|
+
it('6b. keeps an imported cell border across two saves', async () => {
|
|
254
|
+
const first = await load('<table role="presentation"><tbody><tr><td style="border: 1px solid #d9dee4"><p>x</p></td></tr></tbody></table>');
|
|
255
|
+
const second = await load(first.getHTML());
|
|
256
|
+
const td = parse(second.getHTML()).querySelector('td');
|
|
257
|
+
expect(td.style.borderTop).to.equal('1px solid rgb(217, 222, 228)');
|
|
258
|
+
expect(td.style.borderRight).to.equal('1px solid rgb(217, 222, 228)');
|
|
259
|
+
expect(second.getHTML()).to.equal(first.getHTML());
|
|
260
|
+
});
|
|
261
|
+
it('7. writes no border when the theme draws none', async () => {
|
|
262
|
+
const el = await load(DATA_TABLE);
|
|
263
|
+
expect(el.getHTML()).to.not.include('border-top');
|
|
264
|
+
});
|
|
265
|
+
it('8. writes a resized column width onto its cells', async () => {
|
|
266
|
+
const el = await load('<table><tbody><tr><td data-colwidth="120"><p>a</p></td><td><p>b</p></td></tr></tbody></table>');
|
|
267
|
+
const tds = parse(el.getHTML()).querySelectorAll('td');
|
|
268
|
+
expect(tds[0].style.width).to.equal('120px');
|
|
269
|
+
expect(tds[1].style.width).to.equal('');
|
|
270
|
+
});
|
|
271
|
+
it('9. draws layout-table cells the way a mail client does, data cells as before', async () => {
|
|
272
|
+
const el = await load(LAYOUT + DATA_TABLE);
|
|
273
|
+
const cells = [...el.shadowRoot.querySelectorAll('.ProseMirror td')];
|
|
274
|
+
const layoutCell = cells.find(c => c.textContent === 'layout cell');
|
|
275
|
+
const dataCell = cells.find(c => c.textContent === '1342');
|
|
276
|
+
expect(getComputedStyle(layoutCell).padding).to.equal('0px');
|
|
277
|
+
expect(getComputedStyle(layoutCell).verticalAlign).to.equal('middle');
|
|
278
|
+
expect(getComputedStyle(dataCell).padding).to.equal('6px 8px');
|
|
279
|
+
expect(getComputedStyle(dataCell).verticalAlign).to.equal('top');
|
|
280
|
+
});
|
|
281
|
+
it('10. adds no editor-only margin around tables', async () => {
|
|
282
|
+
const el = await load(DATA_TABLE);
|
|
283
|
+
const wrapper = el.shadowRoot.querySelector('.ProseMirror .tableWrapper');
|
|
284
|
+
expect(getComputedStyle(wrapper).marginTop).to.equal('0px');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
//# sourceMappingURL=nile-wysiwyg-editor-email-fidelity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nile-wysiwyg-editor-email-fidelity.test.js","sourceRoot":"","sources":["../../../src/nile-wysiwyg-editor/nile-wysiwyg-editor-email-fidelity.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { fixture, expect } from '@open-wc/testing';\nimport { html } from 'lit';\nimport '../index';\nimport { TextSelection } from 'prosemirror-state';\nimport type { NileWysiwygEditor } from './nile-wysiwyg-editor';\n\nasync function editorFixture(template = html`<nile-wysiwyg-editor></nile-wysiwyg-editor>`) {\n const el = await fixture<NileWysiwygEditor>(template);\n await el.updateComplete;\n return el;\n}\n\n/** A compact table-based email with cell padding and a 600px container. */\nconst EMAIL_FIXTURE =\n '<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">' +\n '<tr><td align=\"center\" style=\"padding:32px 12px;\">' +\n '<table role=\"presentation\" width=\"600\" style=\"width:100%; max-width:600px; background-color:#ffffff; border:1px solid #d9dee4;\">' +\n '<tr><td style=\"padding:28px 40px; background-color:#1f3a5f;\">' +\n '<p style=\"margin:0; font-family:Georgia, serif; color:#ffffff;\">Company Name</p>' +\n '</td></tr>' +\n '<tr><td style=\"padding:36px 40px; font-family:Arial, sans-serif; color:#2b2f36;\">' +\n '<p style=\"margin:0 0 18px 0;\">Hello there.</p>' +\n '</td></tr>' +\n '</table></td></tr></table>';\n\n/** A full standalone HTML document, the kind that lands in text/plain. */\nconst FULL_DOC =\n '<!doctype html><html><body>' +\n '<table role=\"presentation\"><tr><td style=\"padding:16px\">Pasted cell</td></tr></table>' +\n '</body></html>';\n\n/** Fire a paste through the ProseMirror view's handlePaste prop. */\nfunction firePaste(el: NileWysiwygEditor, data: Record<string, string>) {\n const view = el.pmView!;\n const dt = new DataTransfer();\n for (const [type, value] of Object.entries(data)) dt.setData(type, value);\n const event = new ClipboardEvent('paste', { clipboardData: dt });\n return view.someProp('handlePaste', f => f(view, event, view.state.tr.doc.slice(0)));\n}\n\ndescribe('nile-wysiwyg-editor email-fidelity: property reflection', () => {\n it('1. defaults emailFidelity to false', async () => {\n const el = await editorFixture();\n expect(el.emailFidelity).to.equal(false);\n expect(el.hasAttribute('email-fidelity')).to.equal(false);\n });\n\n it('2. reflects the property to the kebab attribute', async () => {\n const el = await editorFixture();\n el.emailFidelity = true;\n await el.updateComplete;\n expect(el.hasAttribute('email-fidelity')).to.equal(true);\n });\n\n it('3. reads the attribute into the property', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`\n );\n expect(el.emailFidelity).to.equal(true);\n });\n});\n\ndescribe('nile-wysiwyg-editor email-fidelity: value parsing', () => {\n it('4. keeps cell padding in value with the flag on', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`\n );\n el.value = EMAIL_FIXTURE;\n await el.updateComplete;\n const doc = new DOMParser().parseFromString(el.value, 'text/html');\n const padded = Array.from(doc.querySelectorAll<HTMLElement>('td')).some(\n td => td.style.padding !== '' || td.style.paddingTop !== ''\n );\n expect(padded, 'a td keeps padding').to.equal(true);\n });\n\n it('5. strips cell padding in value with the flag off', async () => {\n const el = await editorFixture();\n el.value = EMAIL_FIXTURE;\n await el.updateComplete;\n expect(el.value).to.not.include('padding');\n });\n\n it('6. re-parses value when the flag toggles on', async () => {\n const el = await editorFixture();\n el.value = EMAIL_FIXTURE;\n await el.updateComplete;\n expect(el.value).to.not.include('padding');\n\n el.emailFidelity = true;\n el.value = EMAIL_FIXTURE;\n await el.updateComplete;\n expect(el.value).to.match(/padding/);\n });\n});\n\ndescribe('nile-wysiwyg-editor email-fidelity: paste', () => {\n it('7. parses a text/plain-only HTML document when the flag is on', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`\n );\n const handled = firePaste(el, { 'text/plain': FULL_DOC });\n expect(handled).to.equal(true);\n await el.updateComplete;\n expect(el.getHTML()).to.include('<table');\n expect(el.getHTML()).to.not.include('<table');\n });\n\n it('8. inserts the HTML document literally when the flag is off', async () => {\n const el = await editorFixture();\n firePaste(el, { 'text/plain': FULL_DOC });\n await el.updateComplete;\n // No real table node — the markup is kept as literal text.\n expect(el.getHTML()).to.not.include('<table');\n expect(el.getText()).to.include('<table');\n });\n\n it('9. paste-as-plain-text wins over HTML detection', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity paste-as-plain-text></nile-wysiwyg-editor>`\n );\n firePaste(el, { 'text/plain': FULL_DOC });\n await el.updateComplete;\n expect(el.getHTML()).to.not.include('<table');\n expect(el.getText()).to.include('<table');\n });\n\n it('10. markdown text still goes through markdown with the flag on', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`\n );\n firePaste(el, { 'text/plain': '# Heading\\n\\nSome **bold** text.' });\n await el.updateComplete;\n const out = el.getHTML();\n expect(out).to.include('<h1>');\n expect(out).to.include('<strong>');\n });\n});\n\n/** Focuses the editor with the caret inside the first text that equals `text`. */\nasync function caretIn(el: NileWysiwygEditor, text: string) {\n const view = el.pmView!;\n let pos = -1;\n view.state.doc.descendants((node, at) => {\n if (pos === -1 && node.isText && node.text === text) pos = at + 1;\n return pos === -1;\n });\n view.focus();\n view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, pos)));\n await el.updateComplete;\n await new Promise(r => setTimeout(r, 50));\n}\n\nfunction tableMenuOpen(el: NileWysiwygEditor): boolean {\n return !!el.shadowRoot!.querySelector('nile-wysiwyg-table-menu')!.hasAttribute('open');\n}\n\nconst DATA_TABLE = '<table><tr><td>data cell</td></tr></table>';\nconst LAYOUT_TABLE = '<table role=\"presentation\"><tr><td><p>layout cell</p></td></tr></table>';\nconst DATA_IN_LAYOUT =\n '<table role=\"presentation\"><tr><td><table><tr><td>inner data</td></tr></table></td></tr></table>';\n\ndescribe('nile-wysiwyg-editor: table menu visibility', () => {\n it('11. shows in a data table by default', async () => {\n const el = await editorFixture(html`<nile-wysiwyg-editor .value=${DATA_TABLE}></nile-wysiwyg-editor>`);\n await caretIn(el, 'data cell');\n expect(tableMenuOpen(el)).to.equal(true);\n });\n\n it('12. no-table-menu hides it', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor no-table-menu .value=${DATA_TABLE}></nile-wysiwyg-editor>`\n );\n expect(el.noTableMenu).to.equal(true);\n await caretIn(el, 'data cell');\n expect(tableMenuOpen(el)).to.equal(false);\n });\n\n it('13. toggling noTableMenu while focused closes and reopens it', async () => {\n const el = await editorFixture(html`<nile-wysiwyg-editor .value=${DATA_TABLE}></nile-wysiwyg-editor>`);\n await caretIn(el, 'data cell');\n el.noTableMenu = true;\n await el.updateComplete;\n expect(tableMenuOpen(el)).to.equal(false);\n el.noTableMenu = false;\n await el.updateComplete;\n expect(tableMenuOpen(el)).to.equal(true);\n });\n\n it('14. email-fidelity hides it inside a layout table', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity .value=${LAYOUT_TABLE}></nile-wysiwyg-editor>`\n );\n await caretIn(el, 'layout cell');\n expect(tableMenuOpen(el)).to.equal(false);\n });\n\n it('15. without email-fidelity a layout table still shows it (unchanged)', async () => {\n const el = await editorFixture(html`<nile-wysiwyg-editor .value=${LAYOUT_TABLE}></nile-wysiwyg-editor>`);\n await caretIn(el, 'layout cell');\n expect(tableMenuOpen(el)).to.equal(true);\n });\n\n it('16. email-fidelity still shows it in a data table nested in a layout table', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor email-fidelity .value=${DATA_IN_LAYOUT}></nile-wysiwyg-editor>`\n );\n await caretIn(el, 'inner data');\n expect(tableMenuOpen(el)).to.equal(true);\n });\n});\n\ndescribe('nile-wysiwyg-editor email-fidelity: saved HTML matches the editor', () => {\n /** A table with no role=\"presentation\" and no layout styles of its own. */\n const DATA_TABLE =\n '<table><tbody><tr><td><p>Employee Number:</p></td><td><p>1342</p></td></tr></tbody></table>';\n const AUTHORED =\n '<table style=\"width: 600px\"><tbody><tr><td style=\"padding: 20px; vertical-align: middle\">' +\n '<p style=\"margin: 0 0 12px 0\">Kept</p></td></tr></tbody></table>';\n const LAYOUT =\n '<table role=\"presentation\"><tbody><tr><td><p>layout cell</p></td></tr></tbody></table>';\n\n const parse = (out: string) => new DOMParser().parseFromString(out, 'text/html').body;\n\n async function load(value: string, fidelity = true) {\n const el = await editorFixture(\n fidelity\n ? html`<nile-wysiwyg-editor email-fidelity></nile-wysiwyg-editor>`\n : html`<nile-wysiwyg-editor></nile-wysiwyg-editor>`\n );\n el.value = value;\n await el.updateComplete;\n return el;\n }\n\n it('1. writes the editor table rendering into a data table that sets none', async () => {\n const el = await load(DATA_TABLE);\n const body = parse(el.getHTML());\n const table = body.querySelector('table')!;\n expect(table.getAttribute('cellpadding')).to.equal('0');\n expect(table.getAttribute('cellspacing')).to.equal('0');\n expect(table.style.width).to.equal('100%');\n expect(table.style.borderCollapse).to.equal('collapse');\n expect(table.style.tableLayout).to.equal('fixed');\n const td = body.querySelector('td')!;\n expect(td.style.padding).to.equal('6px 8px');\n expect(td.style.verticalAlign).to.equal('top');\n const p = body.querySelector('p')!;\n expect(p.style.marginTop).to.equal('0px');\n expect(p.style.marginBottom).to.equal('0px');\n });\n\n it('2. keeps values the content sets itself', async () => {\n const el = await load(AUTHORED);\n const body = parse(el.getHTML());\n expect(body.querySelector('table')!.style.width).to.equal('600px');\n const td = body.querySelector('td')!;\n expect(td.style.padding).to.equal('20px');\n expect(td.style.verticalAlign).to.equal('middle');\n expect(body.querySelector('p')!.style.margin).to.equal('0px 0px 12px');\n });\n\n it('3. leaves layout-table cells as authored, adding only cellpadding/cellspacing and collapse', async () => {\n const el = await load(LAYOUT);\n const body = parse(el.getHTML());\n const table = body.querySelector('table')!;\n expect(table.getAttribute('cellpadding')).to.equal('0');\n expect(table.style.borderCollapse).to.equal('collapse');\n expect(table.style.tableLayout).to.equal('');\n expect(table.style.width).to.equal('');\n const td = body.querySelector('td')!;\n expect(td.style.padding).to.equal('');\n expect(td.style.verticalAlign).to.equal('');\n });\n\n it('4. without email-fidelity the output is unchanged', async () => {\n const el = await load(DATA_TABLE, false);\n const out = el.getHTML();\n expect(out).to.not.include('cellpadding');\n expect(out).to.not.include('padding');\n expect(out).to.not.include('border-collapse');\n });\n\n it('5. is stable across save and reload', async () => {\n const first = await load(DATA_TABLE);\n const saved = first.getHTML();\n const second = await load(saved);\n expect(second.getHTML()).to.equal(saved);\n expect(second.value).to.equal(saved);\n });\n\n it('6. writes cell borders and the header fill in the colours the theme draws', async () => {\n const el = await editorFixture(\n html`<nile-wysiwyg-editor\n email-fidelity\n style=\"--nile-wysiwyg-table-border: rgb(1, 2, 3); --nile-wysiwyg-table-header-bg: rgb(4, 5, 6)\"\n ></nile-wysiwyg-editor>`\n );\n el.value =\n '<table><tbody><tr><th><p>Attribute</p></th></tr><tr><td><p>Email</p></td></tr></tbody></table>';\n await el.updateComplete;\n const body = parse(el.getHTML());\n const td = body.querySelector('td')!;\n expect(td.style.borderTop).to.equal('1px solid rgb(1, 2, 3)');\n expect(td.style.borderLeft).to.equal('1px solid rgb(1, 2, 3)');\n const th = body.querySelector('th')!;\n expect(th.style.backgroundColor).to.equal('rgb(4, 5, 6)');\n expect(th.style.textAlign).to.equal('left');\n expect(th.style.fontWeight).to.equal('600');\n const again = await load(el.getHTML());\n expect(parse(again.getHTML()).querySelector('td')!.style.borderTop).to.equal(\n '1px solid rgb(1, 2, 3)'\n );\n });\n\n it('6b. keeps an imported cell border across two saves', async () => {\n const first = await load(\n '<table role=\"presentation\"><tbody><tr><td style=\"border: 1px solid #d9dee4\"><p>x</p></td></tr></tbody></table>'\n );\n const second = await load(first.getHTML());\n const td = parse(second.getHTML()).querySelector('td')!;\n expect(td.style.borderTop).to.equal('1px solid rgb(217, 222, 228)');\n expect(td.style.borderRight).to.equal('1px solid rgb(217, 222, 228)');\n expect(second.getHTML()).to.equal(first.getHTML());\n });\n\n it('7. writes no border when the theme draws none', async () => {\n const el = await load(DATA_TABLE);\n expect(el.getHTML()).to.not.include('border-top');\n });\n\n it('8. writes a resized column width onto its cells', async () => {\n const el = await load(\n '<table><tbody><tr><td data-colwidth=\"120\"><p>a</p></td><td><p>b</p></td></tr></tbody></table>'\n );\n const tds = parse(el.getHTML()).querySelectorAll('td');\n expect((tds[0] as HTMLElement).style.width).to.equal('120px');\n expect((tds[1] as HTMLElement).style.width).to.equal('');\n });\n\n it('9. draws layout-table cells the way a mail client does, data cells as before', async () => {\n const el = await load(LAYOUT + DATA_TABLE);\n const cells = [...el.shadowRoot!.querySelectorAll('.ProseMirror td')] as HTMLElement[];\n const layoutCell = cells.find(c => c.textContent === 'layout cell')!;\n const dataCell = cells.find(c => c.textContent === '1342')!;\n expect(getComputedStyle(layoutCell).padding).to.equal('0px');\n expect(getComputedStyle(layoutCell).verticalAlign).to.equal('middle');\n expect(getComputedStyle(dataCell).padding).to.equal('6px 8px');\n expect(getComputedStyle(dataCell).verticalAlign).to.equal('top');\n });\n\n it('10. adds no editor-only margin around tables', async () => {\n const el = await load(DATA_TABLE);\n const wrapper = el.shadowRoot!.querySelector('.ProseMirror .tableWrapper') as HTMLElement;\n expect(getComputedStyle(wrapper).marginTop).to.equal('0px');\n });\n});\n"]}
|
|
@@ -331,12 +331,43 @@ export const styles = css `
|
|
|
331
331
|
cursor: col-resize;
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
/* --- Email fidelity: an unsized layout table (e.g. a button) fits its
|
|
335
|
+
content, as it does in mail clients, instead of the 100% default. --- */
|
|
336
|
+
:host([email-fidelity]) .ProseMirror table[data-autowidth] {
|
|
337
|
+
width: auto;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Column resizing sets an inline min-width of 100px per column; on a nested
|
|
341
|
+
layout table (e.g. a row of social icons) that overflows the cell holding it. */
|
|
342
|
+
:host([email-fidelity]) .ProseMirror table[data-layout-table] {
|
|
343
|
+
min-width: 0 !important;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Email fidelity: the wrapper is editor-only (it holds the resize handles), so
|
|
347
|
+
its margin would add space the saved email doesn't have. */
|
|
348
|
+
:host([email-fidelity]) .ProseMirror .tableWrapper {
|
|
349
|
+
margin: 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* Email fidelity: draw unstyled layout-table cells like a mail client (no padding, centred, no header fill). */
|
|
353
|
+
:host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > td,
|
|
354
|
+
:host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > th {
|
|
355
|
+
padding: 0;
|
|
356
|
+
vertical-align: middle;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
:host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > th {
|
|
360
|
+
background: none;
|
|
361
|
+
}
|
|
362
|
+
|
|
334
363
|
/* --- Layout tables (role="presentation"): borderless output, dashed
|
|
335
364
|
guides while editing so the structure stays visible. --- */
|
|
336
365
|
.ProseMirror table[data-layout] td,
|
|
337
366
|
.ProseMirror table[data-layout] th {
|
|
338
|
-
|
|
339
|
-
|
|
367
|
+
/* Draw the editing guide with an inset outline, not a border/background, so
|
|
368
|
+
author-set cell borders and backgrounds (email fidelity) are preserved. */
|
|
369
|
+
outline: 1px dashed var(--nile-colors-neutral-300, var(--ng-colors-border-primary));
|
|
370
|
+
outline-offset: -1px;
|
|
340
371
|
font-weight: inherit;
|
|
341
372
|
text-align: inherit;
|
|
342
373
|
}
|
|
@@ -390,7 +421,7 @@ export const styles = css `
|
|
|
390
421
|
width: 9px;
|
|
391
422
|
height: 9px;
|
|
392
423
|
background: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));
|
|
393
|
-
border: 1.5px solid var(--ng-colors-bg-primary);
|
|
424
|
+
border: 1.5px solid var(--nile-colors-white-base, var(--ng-colors-bg-primary));
|
|
394
425
|
border-radius: 2px;
|
|
395
426
|
z-index: 2;
|
|
396
427
|
}
|
|
@@ -661,7 +692,17 @@ export const styles = css `
|
|
|
661
692
|
background: var(--nile-wysiwyg-mention-bg, var(--nile-colors-primary-50, var(--ng-componentcolors-utility-blue-50)));
|
|
662
693
|
color: var(--nile-wysiwyg-mention-color, var(--nile-colors-primary-700, var(--ng-componentcolors-utility-blue-700)));
|
|
663
694
|
font-weight: 500;
|
|
664
|
-
|
|
695
|
+
/* Short mentions stay on one line; a long one (e.g. a deep field path) wraps
|
|
696
|
+
inside its container instead of overflowing a table cell or the editor. */
|
|
697
|
+
max-width: 100%;
|
|
698
|
+
overflow-wrap: anywhere;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/* The chip's 500 is only a default — bold, headings and an explicit
|
|
702
|
+
font-weight from the content win, so the chip looks the way it exports. */
|
|
703
|
+
.ProseMirror :is(strong, b, h1, h2, h3, h4, h5, h6, th, [style*='font-weight'])
|
|
704
|
+
span.nile-wysiwyg__mention {
|
|
705
|
+
font-weight: inherit;
|
|
665
706
|
}
|
|
666
707
|
|
|
667
708
|
.ProseMirror span.nile-wysiwyg__mention.ProseMirror-selectednode {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nile-wysiwyg-editor.css.js","sourceRoot":"","sources":["../../../src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+zBxB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const styles = css`\n :host {\n display: block;\n font-family: var(\n --nile-wysiwyg-font-family,\n var(\n --nile-font-family-sans-serif,\n var(--ng-font-family-body, system-ui, -apple-system, sans-serif)\n )\n );\n }\n\n .nile-wysiwyg {\n position: relative;\n display: flex;\n flex-direction: column;\n border: 1px solid\n var(\n --nile-wysiwyg-border-color,\n var(--nile-colors-neutral-400, var(--ng-colors-border-neutral))\n );\n border-radius: var(\n --nile-wysiwyg-radius,\n var(--nile-radius-radius-xl, var(--ng-radius-md, 8px))\n );\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n box-sizing: border-box;\n }\n\n /* --- Fullscreen (distraction-free) mode --- */\n :host([fullscreen]) {\n position: fixed;\n inset: 0;\n z-index: var(--nile-wysiwyg-fullscreen-z-index, 1000);\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n }\n\n :host([fullscreen]) .nile-wysiwyg {\n height: 100%;\n border: none;\n border-radius: 0;\n }\n\n :host([fullscreen]) .nile-wysiwyg__surface {\n max-height: none;\n }\n\n :host([disabled]) .nile-wysiwyg {\n border-color: var(--nile-colors-neutral-500, var(--ng-colors-border-disabled));\n background: var(\n --nile-wysiwyg-disabled-bg,\n var(--nile-colors-dark-200, var(--ng-colors-bg-disabled-subtle))\n );\n cursor: not-allowed;\n pointer-events: none;\n }\n\n :host([disabled]) .ProseMirror {\n background: var(--nile-colors-dark-200, var(--ng-colors-bg-disabled-subtle));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-disabled));\n }\n\n .nile-wysiwyg__surface {\n flex: 1;\n overflow-y: auto;\n max-height: var(--nile-wysiwyg-max-height, none);\n }\n\n /* --- ProseMirror base rules (inlined from prosemirror-view/style) --- */\n .ProseMirror {\n position: relative;\n word-wrap: break-word;\n white-space: pre-wrap;\n white-space: break-spaces;\n -webkit-font-variant-ligatures: none;\n font-variant-ligatures: none;\n font-feature-settings: 'liga' 0;\n outline: none;\n padding: var(--nile-wysiwyg-content-padding, 12px);\n min-height: var(--nile-wysiwyg-min-height, 160px);\n font-size: var(--nile-wysiwyg-font-size, inherit);\n line-height: var(--nile-wysiwyg-line-height, inherit);\n tab-size: 4;\n -moz-tab-size: 4;\n word-break: break-word;\n color: var(\n --nile-wysiwyg-color,\n var(--nile-colors-dark-900, var(--ng-colors-text-primary-900))\n );\n box-sizing: border-box;\n border-radius: 0 0 var(--nile-wysiwyg-radius, var(--nile-radius-radius-xl, 8px))\n var(--nile-wysiwyg-radius, var(--nile-radius-radius-xl, 8px));\n }\n\n .ProseMirror pre {\n white-space: pre-wrap;\n }\n\n .ProseMirror li {\n position: relative;\n }\n\n .ProseMirror-hideselection *::selection {\n background: transparent;\n }\n\n .ProseMirror-hideselection {\n caret-color: transparent;\n }\n\n .ProseMirror-selectednode {\n outline: 2px solid\n var(--nile-wysiwyg-focus-border-color, var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600)));\n }\n\n /* Gap cursor (inlined from prosemirror-gapcursor/style) */\n .ProseMirror-gapcursor {\n display: none;\n pointer-events: none;\n position: absolute;\n }\n\n .ProseMirror-gapcursor:after {\n content: '';\n display: block;\n position: absolute;\n top: -2px;\n width: 20px;\n border-top: 1px solid currentColor;\n animation: nile-wysiwyg-cursor-blink 1.1s steps(2, start) infinite;\n }\n\n @keyframes nile-wysiwyg-cursor-blink {\n to {\n visibility: hidden;\n }\n }\n\n .ProseMirror-focused .ProseMirror-gapcursor {\n display: block;\n }\n\n /* --- Placeholder (legacy: neutral-500 at 0.7 opacity) --- */\n .nile-wysiwyg__empty::before {\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n user-select: none;\n opacity: 0.7;\n color: var(\n --nile-wysiwyg-placeholder-color,\n var(--nile-colors-neutral-500, var(--ng-colors-text-secondary))\n );\n }\n\n /* --- Document content typography --- */\n .ProseMirror > :first-child {\n margin-top: 0;\n }\n\n .ProseMirror > :last-child {\n margin-bottom: 0;\n }\n\n /* Legacy nile-rich-text-editor typography */\n .ProseMirror p {\n margin: 1em 0;\n }\n\n .ProseMirror h1,\n .ProseMirror h2,\n .ProseMirror h3,\n .ProseMirror h4,\n .ProseMirror h5,\n .ProseMirror h6 {\n font-weight: bold;\n }\n\n .ProseMirror h1 {\n font-size: 2em;\n margin: 0.67em 0;\n }\n .ProseMirror h2 {\n font-size: 1.5em;\n margin: 0.83em 0;\n }\n .ProseMirror h3 {\n font-size: 1.17em;\n margin: 1em 0;\n }\n .ProseMirror h4 {\n font-size: 1em;\n margin: 1.33em 0;\n }\n .ProseMirror h5 {\n font-size: 0.83em;\n margin: 1.67em 0;\n }\n .ProseMirror h6 {\n font-size: 0.67em;\n margin: 2.33em 0;\n }\n\n .ProseMirror blockquote {\n margin: 0.5em 0;\n padding: 0.25em 0 0.25em 1em;\n border-left: 3px solid\n var(\n --nile-wysiwyg-blockquote-border,\n var(--nile-colors-neutral-300, var(--ng-colors-border-primary))\n );\n color: var(\n --nile-wysiwyg-blockquote-color,\n var(--nile-colors-neutral-600, var(--ng-colors-text-tertiary-600))\n );\n }\n\n .ProseMirror ul,\n .ProseMirror ol {\n list-style-position: outside;\n padding-inline-start: 24px;\n }\n\n .ProseMirror hr {\n border: none;\n border-top: 1px solid\n var(--nile-wysiwyg-border-color, var(--ng-colors-border-neutral));\n margin: 1em 0;\n }\n\n /* Legacy: brand color, no underline */\n .ProseMirror a {\n color: var(\n --nile-wysiwyg-link-color,\n var(--nile-colors-primary-600, var(--ng-colors-text-brand-tertiary-600))\n );\n text-decoration: none;\n cursor: pointer;\n }\n\n .ProseMirror code.nile-wysiwyg__inline-code {\n font-family: var(--nile-wysiwyg-code-font, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 0.9em;\n background: var(\n --nile-wysiwyg-code-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n border-radius: 4px;\n padding: 0.1em 0.35em;\n }\n\n /* --- Code blocks --- */\n .ProseMirror pre.nile-wysiwyg__code-block {\n font-family: var(--nile-wysiwyg-code-font, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 0.9em;\n background: var(\n --nile-wysiwyg-code-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n border: 1px solid var(--nile-colors-neutral-200, var(--ng-colors-border-secondary));\n border-radius: 6px;\n padding: 12px 14px;\n margin: 0.5em 0;\n overflow-x: auto;\n }\n\n /* --- Tables (rules required by prosemirror-tables) --- */\n .ProseMirror .tableWrapper {\n overflow-x: auto;\n margin: 0.5em 0;\n }\n\n .ProseMirror table {\n border-collapse: collapse;\n table-layout: fixed;\n width: 100%;\n overflow: hidden;\n }\n\n .ProseMirror td,\n .ProseMirror th {\n vertical-align: top;\n box-sizing: border-box;\n position: relative;\n border: 1px solid\n var(\n --nile-wysiwyg-table-border,\n var(--nile-colors-neutral-300, var(--ng-colors-border-primary))\n );\n padding: 6px 8px;\n min-width: 1em;\n }\n\n .ProseMirror th {\n background: var(\n --nile-wysiwyg-table-header-bg,\n var(--nile-colors-neutral-50, var(--ng-colors-bg-secondary))\n );\n font-weight: 600;\n text-align: left;\n }\n\n \n .ProseMirror td > *,\n .ProseMirror th > * {\n margin-top: 0;\n margin-bottom: 0;\n }\n\n .ProseMirror .column-resize-handle {\n position: absolute;\n right: -2px;\n top: 0;\n bottom: 0;\n width: 4px;\n z-index: 20;\n background-color: var(--nile-colors-primary-300, var(--ng-componentcolors-utility-purple-300));\n pointer-events: none;\n }\n\n .ProseMirror.resize-cursor {\n cursor: ew-resize;\n cursor: col-resize;\n }\n\n /* --- Layout tables (role=\"presentation\"): borderless output, dashed\n guides while editing so the structure stays visible. --- */\n .ProseMirror table[data-layout] td,\n .ProseMirror table[data-layout] th {\n border: 1px dashed var(--nile-colors-neutral-300, var(--ng-colors-border-primary));\n background: transparent;\n font-weight: inherit;\n text-align: inherit;\n }\n\n /* --- Bookmarks: invisible anchors get a flag marker while editing --- */\n .ProseMirror a[data-bookmark] {\n display: inline-block;\n vertical-align: baseline;\n cursor: default;\n text-decoration: none;\n }\n\n .ProseMirror a[data-bookmark]::after {\n content: '⚑';\n font-size: 12px;\n line-height: 1;\n padding: 0 1px;\n color: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror .selectedCell:after {\n z-index: 2;\n position: absolute;\n content: '';\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n background: var(--nile-wysiwyg-cell-selection, rgba(127, 86, 217, 0.12));\n pointer-events: none;\n }\n\n /* --- Images (ProseMirror's standard inline image node) --- */\n .ProseMirror img {\n max-width: 100%;\n height: auto;\n border-radius: 4px;\n }\n\n /* --- Image resize handles --- */\n .ProseMirror .nile-wysiwyg__image-resizer {\n position: relative;\n display: inline-block;\n line-height: 0;\n max-width: 100%;\n }\n\n .ProseMirror .nile-wysiwyg__resize-handle {\n display: none;\n position: absolute;\n width: 9px;\n height: 9px;\n background: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n border: 1.5px solid var(--ng-colors-bg-primary);\n border-radius: 2px;\n z-index: 2;\n }\n\n .ProseMirror .nile-wysiwyg__image-resizer--selected .nile-wysiwyg__resize-handle {\n display: block;\n }\n\n .ProseMirror .nile-wysiwyg__image-resizer--selected img {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror .nile-wysiwyg__resize-handle--nw { top: -5px; left: -5px; cursor: nwse-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--ne { top: -5px; right: -5px; cursor: nesw-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--sw { bottom: -5px; left: -5px; cursor: nesw-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--se { bottom: -5px; right: -5px; cursor: nwse-resize; }\n\n /* --- Captioned figures --- */\n .ProseMirror figure.nile-wysiwyg__figure {\n margin: 0.75em 0;\n max-width: 100%;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure[data-align='center'] {\n margin-left: auto;\n margin-right: auto;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure[data-align='right'] {\n margin-left: auto;\n margin-right: 0;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure img {\n width: 100%;\n display: block;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure .nile-wysiwyg__image-resizer {\n display: block;\n }\n\n .ProseMirror .nile-wysiwyg__figcaption {\n font-size: 0.85em;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-tertiary-600));\n text-align: center;\n padding: 4px 8px;\n line-height: 1.4;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure--empty-caption .nile-wysiwyg__figcaption::before {\n content: 'Add a caption…';\n float: left;\n width: 100%;\n pointer-events: none;\n color: var(--nile-colors-neutral-400, var(--ng-colors-text-quaternary-500));\n margin-bottom: -1.4em;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure--selected {\n border-radius: 4px;\n }\n\n /* --- Embeds --- */\n .ProseMirror div.nile-wysiwyg__embed {\n position: relative;\n aspect-ratio: 16 / 9;\n /* Default size; an inline width from drag-resize overrides it, capped by\n max-width. overflow stays visible so the resize handles aren't clipped\n (rounding lives on the iframe). */\n width: min(640px, 100%);\n max-width: 100%;\n margin: 0.75em 0;\n border-radius: 8px;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n }\n\n .ProseMirror div.nile-wysiwyg__embed iframe {\n width: 100%;\n height: 100%;\n border: 0;\n display: block;\n border-radius: 8px;\n /* Editing mode: the first click selects the node instead of hitting the\n iframe; once selected (or in readonly) the video is interactive. */\n pointer-events: none;\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode iframe,\n :host([readonly]) .ProseMirror div.nile-wysiwyg__embed iframe {\n pointer-events: auto;\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode .nile-wysiwyg__resize-handle {\n display: block;\n }\n\n /* A live resize drag must not lose mousemove to the embedded document. */\n .ProseMirror div.nile-wysiwyg__embed.nile-wysiwyg__resizing iframe {\n pointer-events: none !important;\n }\n\n /* --- Code highlighting (hljs tokens) ---\n Each hue routes through an --ng-componentcolors-utility-* token, which the\n token layer remaps to its lighter 400 step in the dark theme. Hardcoding the\n one-light palette here left syntax unreadable on the dark code surface. --- */\n .ProseMirror .hljs-comment,\n .ProseMirror .hljs-quote {\n color: var(--ng-componentcolors-utility-gray-500);\n font-style: italic;\n }\n\n .ProseMirror .hljs-keyword,\n .ProseMirror .hljs-selector-tag,\n .ProseMirror .hljs-formula,\n .ProseMirror .hljs-doctag {\n color: var(--ng-componentcolors-utility-purple-600);\n }\n\n .ProseMirror .hljs-section,\n .ProseMirror .hljs-name,\n .ProseMirror .hljs-selector-id,\n .ProseMirror .hljs-selector-class,\n .ProseMirror .hljs-deletion,\n .ProseMirror .hljs-subst,\n .ProseMirror .hljs-tag {\n color: var(--ng-componentcolors-utility-error-600);\n }\n\n .ProseMirror .hljs-literal,\n .ProseMirror .hljs-built_in,\n .ProseMirror .hljs-bullet {\n color: var(--ng-componentcolors-utility-blue-600);\n }\n\n .ProseMirror .hljs-string,\n .ProseMirror .hljs-regexp,\n .ProseMirror .hljs-addition,\n .ProseMirror .hljs-attribute,\n .ProseMirror .hljs-meta .hljs-string {\n color: var(--ng-componentcolors-utility-green-600);\n }\n\n .ProseMirror .hljs-attr,\n .ProseMirror .hljs-variable,\n .ProseMirror .hljs-template-variable,\n .ProseMirror .hljs-type,\n .ProseMirror .hljs-selector-attr,\n .ProseMirror .hljs-selector-pseudo,\n .ProseMirror .hljs-number {\n color: var(--ng-componentcolors-utility-orange-600);\n }\n\n .ProseMirror .hljs-symbol,\n .ProseMirror .hljs-meta,\n .ProseMirror .hljs-link,\n .ProseMirror .hljs-operator,\n .ProseMirror .hljs-title,\n .ProseMirror .hljs-title.class_,\n .ProseMirror .hljs-title.function_ {\n color: var(--ng-componentcolors-utility-indigo-600);\n }\n\n .ProseMirror .hljs-emphasis {\n font-style: italic;\n }\n\n .ProseMirror .hljs-strong {\n font-weight: bold;\n }\n\n /* --- Checklists --- */\n .ProseMirror ul.nile-wysiwyg__task-list {\n list-style: none;\n padding-inline-start: 4px;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > input[type='checkbox'] {\n /* Center on the first text line: (1 line box - checkbox height) / 2. */\n margin: calc((1em * 1.45 - 14px) / 2) 0 0;\n width: 14px;\n height: 14px;\n flex: none;\n cursor: pointer;\n accent-color: var(\n --nile-colors-primary-600,\n var(--ng-componentcolors-utility-blue-600)\n );\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content {\n flex: 1;\n min-width: 0;\n }\n\n /* The content's paragraph margins (legacy 1em) push text below the\n checkbox — strip them at the edges of each item. */\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content > :first-child {\n margin-top: 0;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content > :last-child {\n margin-bottom: 0;\n }\n\n .ProseMirror ul.nile-wysiwyg__task-list > li + li {\n margin-top: 0.35em;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item[data-checked='true'] > .nile-wysiwyg__task-content {\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-quaternary-500));\n text-decoration: line-through;\n }\n\n /* --- Counter footer --- */\n .nile-wysiwyg__counter {\n padding: 4px 12px 6px;\n text-align: right;\n font-size: 12px;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-secondary));\n border-top: 1px solid var(--nile-colors-neutral-200, var(--ng-colors-border-secondary));\n }\n\n .nile-wysiwyg__counter.over {\n color: var(--nile-colors-error-600, var(--ng-componentcolors-utility-error-600));\n font-weight: 600;\n }\n\n /* --- Author <style> block (from HTML source) ---\n Applied live by StyleBlockView (a hidden <style> host, scoped to the\n content); the block renders nothing in the editor. */\n .nile-wysiwyg__style-block {\n display: none;\n }\n\n /* --- Sticky toolbar ---\n Pins to the top of the scroll container. Note: sticky anchors to the\n container's PADDING box, so if the scroll container has top padding, a\n band of content shows above the toolbar — set --nile-wysiwyg-sticky-top\n (or remove the container's top padding) to compensate. The opaque\n background makes the pinned bar self-backing so content can never bleed\n through it. */\n :host([sticky-toolbar]) nile-wysiwyg-toolbar {\n position: sticky;\n top: var(--nile-wysiwyg-sticky-top, 0);\n z-index: 12;\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n }\n\n /* --- Mentions & suggestions --- */\n .ProseMirror span.nile-wysiwyg__mention {\n display: inline-block;\n padding: 0 4px;\n border-radius: 4px;\n background: var(--nile-wysiwyg-mention-bg, var(--nile-colors-primary-50, var(--ng-componentcolors-utility-blue-50)));\n color: var(--nile-wysiwyg-mention-color, var(--nile-colors-primary-700, var(--ng-componentcolors-utility-blue-700)));\n font-weight: 500;\n white-space: nowrap;\n }\n\n .ProseMirror span.nile-wysiwyg__mention.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n /* --- Merge fields --- */\n .ProseMirror span.nile-wysiwyg__merge-field {\n display: inline-block;\n padding: 0 4px;\n border-radius: 4px;\n background: var(\n --nile-wysiwyg-merge-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n color: var(\n --nile-wysiwyg-merge-color,\n var(--nile-colors-neutral-700, var(--ng-colors-text-primary-900))\n );\n border: 1px dashed var(--nile-colors-neutral-400, var(--ng-colors-border-primary));\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.9em;\n white-space: nowrap;\n }\n\n .ProseMirror span.nile-wysiwyg__merge-field.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n /* --- Math --- */\n .ProseMirror span.nile-wysiwyg__math {\n display: inline-block;\n padding: 0 2px;\n font-family: \"Cambria Math\", \"Latin Modern Math\", serif;\n }\n\n .ProseMirror span.nile-wysiwyg__math--block {\n display: block;\n text-align: center;\n margin: 8px 0;\n }\n\n .ProseMirror span.nile-wysiwyg__math.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n border-radius: 3px;\n }\n\n /* Format painter armed: hint the next selection will be painted. */\n .ProseMirror.nile-wysiwyg--painting {\n cursor: cell;\n }\n\n .ProseMirror .nile-wysiwyg__suggestion {\n background: var(--nile-colors-primary-50, var(--ng-componentcolors-utility-blue-50));\n border-radius: 3px;\n }\n\n /* --- Find & replace highlights --- */\n .ProseMirror .nile-wysiwyg__find-match {\n background: var(--nile-wysiwyg-find-bg, rgba(255, 214, 102, 0.45));\n border-radius: 2px;\n }\n\n .ProseMirror .nile-wysiwyg__find-active {\n background: var(--nile-wysiwyg-find-active-bg, rgba(255, 170, 0, 0.65));\n }\n\n /* --- Upload placeholder --- */\n .nile-wysiwyg__upload-placeholder {\n display: inline-block;\n padding: 6px 12px;\n border: 1px dashed var(--nile-colors-neutral-400, var(--ng-colors-border-primary));\n border-radius: 6px;\n background: var(--nile-colors-neutral-50, var(--ng-colors-bg-secondary));\n color: var(--nile-colors-neutral-600, var(--ng-colors-text-tertiary-600));\n font-size: 0.85em;\n }\n\n /* --- Multi-level (legal) ordered lists: 1 / 1.1 / 1.1.1 numbering.\n Serialized output carries data-list-style=\"multilevel\"; consumers\n rendering it outside the editor need these same counter rules. --- */\n .ProseMirror ol[data-list-style='multilevel'],\n .ProseMirror ol[data-list-style='multilevel'] ol {\n list-style: none;\n counter-reset: nile-multilevel;\n }\n\n .ProseMirror ol[data-list-style='multilevel'] > li,\n .ProseMirror ol[data-list-style='multilevel'] ol > li {\n counter-increment: nile-multilevel;\n }\n\n /* The number sits inside the item's first paragraph so it shares a line. */\n .ProseMirror ol[data-list-style='multilevel'] > li > p:first-child::before,\n .ProseMirror ol[data-list-style='multilevel'] ol > li > p:first-child::before {\n content: counters(nile-multilevel, '.') '. ';\n font-variant-numeric: tabular-nums;\n }\n\n /* --- Show blocks: dashed outlines + tag labels while editing --- */\n .nile-wysiwyg--show-blocks .ProseMirror p,\n .nile-wysiwyg--show-blocks .ProseMirror h1,\n .nile-wysiwyg--show-blocks .ProseMirror h2,\n .nile-wysiwyg--show-blocks .ProseMirror h3,\n .nile-wysiwyg--show-blocks .ProseMirror h4,\n .nile-wysiwyg--show-blocks .ProseMirror h5,\n .nile-wysiwyg--show-blocks .ProseMirror h6,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote,\n .nile-wysiwyg--show-blocks .ProseMirror pre,\n .nile-wysiwyg--show-blocks .ProseMirror figure,\n .nile-wysiwyg--show-blocks .ProseMirror ul,\n .nile-wysiwyg--show-blocks .ProseMirror ol,\n .nile-wysiwyg--show-blocks .ProseMirror li,\n .nile-wysiwyg--show-blocks .ProseMirror table {\n outline: 1px dashed\n var(\n --nile-wysiwyg-block-outline,\n var(--nile-colors-neutral-400, var(--ng-colors-border-primary))\n );\n outline-offset: -1px;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p,\n .nile-wysiwyg--show-blocks .ProseMirror h1,\n .nile-wysiwyg--show-blocks .ProseMirror h2,\n .nile-wysiwyg--show-blocks .ProseMirror h3,\n .nile-wysiwyg--show-blocks .ProseMirror h4,\n .nile-wysiwyg--show-blocks .ProseMirror h5,\n .nile-wysiwyg--show-blocks .ProseMirror h6,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote,\n .nile-wysiwyg--show-blocks .ProseMirror pre {\n position: relative;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p::after,\n .nile-wysiwyg--show-blocks .ProseMirror h1::after,\n .nile-wysiwyg--show-blocks .ProseMirror h2::after,\n .nile-wysiwyg--show-blocks .ProseMirror h3::after,\n .nile-wysiwyg--show-blocks .ProseMirror h4::after,\n .nile-wysiwyg--show-blocks .ProseMirror h5::after,\n .nile-wysiwyg--show-blocks .ProseMirror h6::after,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote::after,\n .nile-wysiwyg--show-blocks .ProseMirror pre::after {\n position: absolute;\n top: 0;\n left: 0;\n padding: 0 3px;\n font-family: system-ui, sans-serif;\n font-size: 9px;\n font-weight: 600;\n font-style: normal;\n line-height: 14px;\n letter-spacing: 0.5px;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-tertiary-600));\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n border-radius: 0 0 4px 0;\n pointer-events: none;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p::after { content: 'P'; }\n .nile-wysiwyg--show-blocks .ProseMirror h1::after { content: 'H1'; }\n .nile-wysiwyg--show-blocks .ProseMirror h2::after { content: 'H2'; }\n .nile-wysiwyg--show-blocks .ProseMirror h3::after { content: 'H3'; }\n .nile-wysiwyg--show-blocks .ProseMirror h4::after { content: 'H4'; }\n .nile-wysiwyg--show-blocks .ProseMirror h5::after { content: 'H5'; }\n .nile-wysiwyg--show-blocks .ProseMirror h6::after { content: 'H6'; }\n .nile-wysiwyg--show-blocks .ProseMirror blockquote::after { content: 'QUOTE'; }\n .nile-wysiwyg--show-blocks .ProseMirror pre::after { content: 'PRE'; }\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"nile-wysiwyg-editor.css.js","sourceRoot":"","sources":["../../../src/nile-wysiwyg-editor/nile-wysiwyg-editor.css.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw2BxB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const styles = css`\n :host {\n display: block;\n font-family: var(\n --nile-wysiwyg-font-family,\n var(\n --nile-font-family-sans-serif,\n var(--ng-font-family-body, system-ui, -apple-system, sans-serif)\n )\n );\n }\n\n .nile-wysiwyg {\n position: relative;\n display: flex;\n flex-direction: column;\n border: 1px solid\n var(\n --nile-wysiwyg-border-color,\n var(--nile-colors-neutral-400, var(--ng-colors-border-neutral))\n );\n border-radius: var(\n --nile-wysiwyg-radius,\n var(--nile-radius-radius-xl, var(--ng-radius-md, 8px))\n );\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n box-sizing: border-box;\n }\n\n /* --- Fullscreen (distraction-free) mode --- */\n :host([fullscreen]) {\n position: fixed;\n inset: 0;\n z-index: var(--nile-wysiwyg-fullscreen-z-index, 1000);\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n }\n\n :host([fullscreen]) .nile-wysiwyg {\n height: 100%;\n border: none;\n border-radius: 0;\n }\n\n :host([fullscreen]) .nile-wysiwyg__surface {\n max-height: none;\n }\n\n :host([disabled]) .nile-wysiwyg {\n border-color: var(--nile-colors-neutral-500, var(--ng-colors-border-disabled));\n background: var(\n --nile-wysiwyg-disabled-bg,\n var(--nile-colors-dark-200, var(--ng-colors-bg-disabled-subtle))\n );\n cursor: not-allowed;\n pointer-events: none;\n }\n\n :host([disabled]) .ProseMirror {\n background: var(--nile-colors-dark-200, var(--ng-colors-bg-disabled-subtle));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-disabled));\n }\n\n .nile-wysiwyg__surface {\n flex: 1;\n overflow-y: auto;\n max-height: var(--nile-wysiwyg-max-height, none);\n }\n\n /* --- ProseMirror base rules (inlined from prosemirror-view/style) --- */\n .ProseMirror {\n position: relative;\n word-wrap: break-word;\n white-space: pre-wrap;\n white-space: break-spaces;\n -webkit-font-variant-ligatures: none;\n font-variant-ligatures: none;\n font-feature-settings: 'liga' 0;\n outline: none;\n padding: var(--nile-wysiwyg-content-padding, 12px);\n min-height: var(--nile-wysiwyg-min-height, 160px);\n font-size: var(--nile-wysiwyg-font-size, inherit);\n line-height: var(--nile-wysiwyg-line-height, inherit);\n tab-size: 4;\n -moz-tab-size: 4;\n word-break: break-word;\n color: var(\n --nile-wysiwyg-color,\n var(--nile-colors-dark-900, var(--ng-colors-text-primary-900))\n );\n box-sizing: border-box;\n border-radius: 0 0 var(--nile-wysiwyg-radius, var(--nile-radius-radius-xl, 8px))\n var(--nile-wysiwyg-radius, var(--nile-radius-radius-xl, 8px));\n }\n\n .ProseMirror pre {\n white-space: pre-wrap;\n }\n\n .ProseMirror li {\n position: relative;\n }\n\n .ProseMirror-hideselection *::selection {\n background: transparent;\n }\n\n .ProseMirror-hideselection {\n caret-color: transparent;\n }\n\n .ProseMirror-selectednode {\n outline: 2px solid\n var(--nile-wysiwyg-focus-border-color, var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600)));\n }\n\n /* Gap cursor (inlined from prosemirror-gapcursor/style) */\n .ProseMirror-gapcursor {\n display: none;\n pointer-events: none;\n position: absolute;\n }\n\n .ProseMirror-gapcursor:after {\n content: '';\n display: block;\n position: absolute;\n top: -2px;\n width: 20px;\n border-top: 1px solid currentColor;\n animation: nile-wysiwyg-cursor-blink 1.1s steps(2, start) infinite;\n }\n\n @keyframes nile-wysiwyg-cursor-blink {\n to {\n visibility: hidden;\n }\n }\n\n .ProseMirror-focused .ProseMirror-gapcursor {\n display: block;\n }\n\n /* --- Placeholder (legacy: neutral-500 at 0.7 opacity) --- */\n .nile-wysiwyg__empty::before {\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n user-select: none;\n opacity: 0.7;\n color: var(\n --nile-wysiwyg-placeholder-color,\n var(--nile-colors-neutral-500, var(--ng-colors-text-secondary))\n );\n }\n\n /* --- Document content typography --- */\n .ProseMirror > :first-child {\n margin-top: 0;\n }\n\n .ProseMirror > :last-child {\n margin-bottom: 0;\n }\n\n /* Legacy nile-rich-text-editor typography */\n .ProseMirror p {\n margin: 1em 0;\n }\n\n .ProseMirror h1,\n .ProseMirror h2,\n .ProseMirror h3,\n .ProseMirror h4,\n .ProseMirror h5,\n .ProseMirror h6 {\n font-weight: bold;\n }\n\n .ProseMirror h1 {\n font-size: 2em;\n margin: 0.67em 0;\n }\n .ProseMirror h2 {\n font-size: 1.5em;\n margin: 0.83em 0;\n }\n .ProseMirror h3 {\n font-size: 1.17em;\n margin: 1em 0;\n }\n .ProseMirror h4 {\n font-size: 1em;\n margin: 1.33em 0;\n }\n .ProseMirror h5 {\n font-size: 0.83em;\n margin: 1.67em 0;\n }\n .ProseMirror h6 {\n font-size: 0.67em;\n margin: 2.33em 0;\n }\n\n .ProseMirror blockquote {\n margin: 0.5em 0;\n padding: 0.25em 0 0.25em 1em;\n border-left: 3px solid\n var(\n --nile-wysiwyg-blockquote-border,\n var(--nile-colors-neutral-300, var(--ng-colors-border-primary))\n );\n color: var(\n --nile-wysiwyg-blockquote-color,\n var(--nile-colors-neutral-600, var(--ng-colors-text-tertiary-600))\n );\n }\n\n .ProseMirror ul,\n .ProseMirror ol {\n list-style-position: outside;\n padding-inline-start: 24px;\n }\n\n .ProseMirror hr {\n border: none;\n border-top: 1px solid\n var(--nile-wysiwyg-border-color, var(--ng-colors-border-neutral));\n margin: 1em 0;\n }\n\n /* Legacy: brand color, no underline */\n .ProseMirror a {\n color: var(\n --nile-wysiwyg-link-color,\n var(--nile-colors-primary-600, var(--ng-colors-text-brand-tertiary-600))\n );\n text-decoration: none;\n cursor: pointer;\n }\n\n .ProseMirror code.nile-wysiwyg__inline-code {\n font-family: var(--nile-wysiwyg-code-font, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 0.9em;\n background: var(\n --nile-wysiwyg-code-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n border-radius: 4px;\n padding: 0.1em 0.35em;\n }\n\n /* --- Code blocks --- */\n .ProseMirror pre.nile-wysiwyg__code-block {\n font-family: var(--nile-wysiwyg-code-font, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 0.9em;\n background: var(\n --nile-wysiwyg-code-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n border: 1px solid var(--nile-colors-neutral-200, var(--ng-colors-border-secondary));\n border-radius: 6px;\n padding: 12px 14px;\n margin: 0.5em 0;\n overflow-x: auto;\n }\n\n /* --- Tables (rules required by prosemirror-tables) --- */\n .ProseMirror .tableWrapper {\n overflow-x: auto;\n margin: 0.5em 0;\n }\n\n .ProseMirror table {\n border-collapse: collapse;\n table-layout: fixed;\n width: 100%;\n overflow: hidden;\n }\n\n .ProseMirror td,\n .ProseMirror th {\n vertical-align: top;\n box-sizing: border-box;\n position: relative;\n border: 1px solid\n var(\n --nile-wysiwyg-table-border,\n var(--nile-colors-neutral-300, var(--ng-colors-border-primary))\n );\n padding: 6px 8px;\n min-width: 1em;\n }\n\n .ProseMirror th {\n background: var(\n --nile-wysiwyg-table-header-bg,\n var(--nile-colors-neutral-50, var(--ng-colors-bg-secondary))\n );\n font-weight: 600;\n text-align: left;\n }\n\n \n .ProseMirror td > *,\n .ProseMirror th > * {\n margin-top: 0;\n margin-bottom: 0;\n }\n\n .ProseMirror .column-resize-handle {\n position: absolute;\n right: -2px;\n top: 0;\n bottom: 0;\n width: 4px;\n z-index: 20;\n background-color: var(--nile-colors-primary-300, var(--ng-componentcolors-utility-purple-300));\n pointer-events: none;\n }\n\n .ProseMirror.resize-cursor {\n cursor: ew-resize;\n cursor: col-resize;\n }\n\n /* --- Email fidelity: an unsized layout table (e.g. a button) fits its\n content, as it does in mail clients, instead of the 100% default. --- */\n :host([email-fidelity]) .ProseMirror table[data-autowidth] {\n width: auto;\n }\n\n /* Column resizing sets an inline min-width of 100px per column; on a nested\n layout table (e.g. a row of social icons) that overflows the cell holding it. */\n :host([email-fidelity]) .ProseMirror table[data-layout-table] {\n min-width: 0 !important;\n }\n\n /* Email fidelity: the wrapper is editor-only (it holds the resize handles), so\n its margin would add space the saved email doesn't have. */\n :host([email-fidelity]) .ProseMirror .tableWrapper {\n margin: 0;\n }\n\n /* Email fidelity: draw unstyled layout-table cells like a mail client (no padding, centred, no header fill). */\n :host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > td,\n :host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > th {\n padding: 0;\n vertical-align: middle;\n }\n\n :host([email-fidelity]) .ProseMirror table[data-layout-table] > tbody > tr > th {\n background: none;\n }\n\n /* --- Layout tables (role=\"presentation\"): borderless output, dashed\n guides while editing so the structure stays visible. --- */\n .ProseMirror table[data-layout] td,\n .ProseMirror table[data-layout] th {\n /* Draw the editing guide with an inset outline, not a border/background, so\n author-set cell borders and backgrounds (email fidelity) are preserved. */\n outline: 1px dashed var(--nile-colors-neutral-300, var(--ng-colors-border-primary));\n outline-offset: -1px;\n font-weight: inherit;\n text-align: inherit;\n }\n\n /* --- Bookmarks: invisible anchors get a flag marker while editing --- */\n .ProseMirror a[data-bookmark] {\n display: inline-block;\n vertical-align: baseline;\n cursor: default;\n text-decoration: none;\n }\n\n .ProseMirror a[data-bookmark]::after {\n content: '⚑';\n font-size: 12px;\n line-height: 1;\n padding: 0 1px;\n color: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror .selectedCell:after {\n z-index: 2;\n position: absolute;\n content: '';\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n background: var(--nile-wysiwyg-cell-selection, rgba(127, 86, 217, 0.12));\n pointer-events: none;\n }\n\n /* --- Images (ProseMirror's standard inline image node) --- */\n .ProseMirror img {\n max-width: 100%;\n height: auto;\n border-radius: 4px;\n }\n\n /* --- Image resize handles --- */\n .ProseMirror .nile-wysiwyg__image-resizer {\n position: relative;\n display: inline-block;\n line-height: 0;\n max-width: 100%;\n }\n\n .ProseMirror .nile-wysiwyg__resize-handle {\n display: none;\n position: absolute;\n width: 9px;\n height: 9px;\n background: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n border: 1.5px solid var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n border-radius: 2px;\n z-index: 2;\n }\n\n .ProseMirror .nile-wysiwyg__image-resizer--selected .nile-wysiwyg__resize-handle {\n display: block;\n }\n\n .ProseMirror .nile-wysiwyg__image-resizer--selected img {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror .nile-wysiwyg__resize-handle--nw { top: -5px; left: -5px; cursor: nwse-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--ne { top: -5px; right: -5px; cursor: nesw-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--sw { bottom: -5px; left: -5px; cursor: nesw-resize; }\n .ProseMirror .nile-wysiwyg__resize-handle--se { bottom: -5px; right: -5px; cursor: nwse-resize; }\n\n /* --- Captioned figures --- */\n .ProseMirror figure.nile-wysiwyg__figure {\n margin: 0.75em 0;\n max-width: 100%;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure[data-align='center'] {\n margin-left: auto;\n margin-right: auto;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure[data-align='right'] {\n margin-left: auto;\n margin-right: 0;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure img {\n width: 100%;\n display: block;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure .nile-wysiwyg__image-resizer {\n display: block;\n }\n\n .ProseMirror .nile-wysiwyg__figcaption {\n font-size: 0.85em;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-tertiary-600));\n text-align: center;\n padding: 4px 8px;\n line-height: 1.4;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure--empty-caption .nile-wysiwyg__figcaption::before {\n content: 'Add a caption…';\n float: left;\n width: 100%;\n pointer-events: none;\n color: var(--nile-colors-neutral-400, var(--ng-colors-text-quaternary-500));\n margin-bottom: -1.4em;\n }\n\n .ProseMirror figure.nile-wysiwyg__figure--selected {\n border-radius: 4px;\n }\n\n /* --- Embeds --- */\n .ProseMirror div.nile-wysiwyg__embed {\n position: relative;\n aspect-ratio: 16 / 9;\n /* Default size; an inline width from drag-resize overrides it, capped by\n max-width. overflow stays visible so the resize handles aren't clipped\n (rounding lives on the iframe). */\n width: min(640px, 100%);\n max-width: 100%;\n margin: 0.75em 0;\n border-radius: 8px;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n }\n\n .ProseMirror div.nile-wysiwyg__embed iframe {\n width: 100%;\n height: 100%;\n border: 0;\n display: block;\n border-radius: 8px;\n /* Editing mode: the first click selects the node instead of hitting the\n iframe; once selected (or in readonly) the video is interactive. */\n pointer-events: none;\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode iframe,\n :host([readonly]) .ProseMirror div.nile-wysiwyg__embed iframe {\n pointer-events: auto;\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n .ProseMirror div.nile-wysiwyg__embed.ProseMirror-selectednode .nile-wysiwyg__resize-handle {\n display: block;\n }\n\n /* A live resize drag must not lose mousemove to the embedded document. */\n .ProseMirror div.nile-wysiwyg__embed.nile-wysiwyg__resizing iframe {\n pointer-events: none !important;\n }\n\n /* --- Code highlighting (hljs tokens) ---\n Each hue routes through an --ng-componentcolors-utility-* token, which the\n token layer remaps to its lighter 400 step in the dark theme. Hardcoding the\n one-light palette here left syntax unreadable on the dark code surface. --- */\n .ProseMirror .hljs-comment,\n .ProseMirror .hljs-quote {\n color: var(--ng-componentcolors-utility-gray-500);\n font-style: italic;\n }\n\n .ProseMirror .hljs-keyword,\n .ProseMirror .hljs-selector-tag,\n .ProseMirror .hljs-formula,\n .ProseMirror .hljs-doctag {\n color: var(--ng-componentcolors-utility-purple-600);\n }\n\n .ProseMirror .hljs-section,\n .ProseMirror .hljs-name,\n .ProseMirror .hljs-selector-id,\n .ProseMirror .hljs-selector-class,\n .ProseMirror .hljs-deletion,\n .ProseMirror .hljs-subst,\n .ProseMirror .hljs-tag {\n color: var(--ng-componentcolors-utility-error-600);\n }\n\n .ProseMirror .hljs-literal,\n .ProseMirror .hljs-built_in,\n .ProseMirror .hljs-bullet {\n color: var(--ng-componentcolors-utility-blue-600);\n }\n\n .ProseMirror .hljs-string,\n .ProseMirror .hljs-regexp,\n .ProseMirror .hljs-addition,\n .ProseMirror .hljs-attribute,\n .ProseMirror .hljs-meta .hljs-string {\n color: var(--ng-componentcolors-utility-green-600);\n }\n\n .ProseMirror .hljs-attr,\n .ProseMirror .hljs-variable,\n .ProseMirror .hljs-template-variable,\n .ProseMirror .hljs-type,\n .ProseMirror .hljs-selector-attr,\n .ProseMirror .hljs-selector-pseudo,\n .ProseMirror .hljs-number {\n color: var(--ng-componentcolors-utility-orange-600);\n }\n\n .ProseMirror .hljs-symbol,\n .ProseMirror .hljs-meta,\n .ProseMirror .hljs-link,\n .ProseMirror .hljs-operator,\n .ProseMirror .hljs-title,\n .ProseMirror .hljs-title.class_,\n .ProseMirror .hljs-title.function_ {\n color: var(--ng-componentcolors-utility-indigo-600);\n }\n\n .ProseMirror .hljs-emphasis {\n font-style: italic;\n }\n\n .ProseMirror .hljs-strong {\n font-weight: bold;\n }\n\n /* --- Checklists --- */\n .ProseMirror ul.nile-wysiwyg__task-list {\n list-style: none;\n padding-inline-start: 4px;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > input[type='checkbox'] {\n /* Center on the first text line: (1 line box - checkbox height) / 2. */\n margin: calc((1em * 1.45 - 14px) / 2) 0 0;\n width: 14px;\n height: 14px;\n flex: none;\n cursor: pointer;\n accent-color: var(\n --nile-colors-primary-600,\n var(--ng-componentcolors-utility-blue-600)\n );\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content {\n flex: 1;\n min-width: 0;\n }\n\n /* The content's paragraph margins (legacy 1em) push text below the\n checkbox — strip them at the edges of each item. */\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content > :first-child {\n margin-top: 0;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item > .nile-wysiwyg__task-content > :last-child {\n margin-bottom: 0;\n }\n\n .ProseMirror ul.nile-wysiwyg__task-list > li + li {\n margin-top: 0.35em;\n }\n\n .ProseMirror li.nile-wysiwyg__task-item[data-checked='true'] > .nile-wysiwyg__task-content {\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-quaternary-500));\n text-decoration: line-through;\n }\n\n /* --- Counter footer --- */\n .nile-wysiwyg__counter {\n padding: 4px 12px 6px;\n text-align: right;\n font-size: 12px;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-secondary));\n border-top: 1px solid var(--nile-colors-neutral-200, var(--ng-colors-border-secondary));\n }\n\n .nile-wysiwyg__counter.over {\n color: var(--nile-colors-error-600, var(--ng-componentcolors-utility-error-600));\n font-weight: 600;\n }\n\n /* --- Author <style> block (from HTML source) ---\n Applied live by StyleBlockView (a hidden <style> host, scoped to the\n content); the block renders nothing in the editor. */\n .nile-wysiwyg__style-block {\n display: none;\n }\n\n /* --- Sticky toolbar ---\n Pins to the top of the scroll container. Note: sticky anchors to the\n container's PADDING box, so if the scroll container has top padding, a\n band of content shows above the toolbar — set --nile-wysiwyg-sticky-top\n (or remove the container's top padding) to compensate. The opaque\n background makes the pinned bar self-backing so content can never bleed\n through it. */\n :host([sticky-toolbar]) nile-wysiwyg-toolbar {\n position: sticky;\n top: var(--nile-wysiwyg-sticky-top, 0);\n z-index: 12;\n background: var(\n --nile-wysiwyg-bg,\n var(--nile-colors-white-base, var(--ng-colors-bg-primary))\n );\n }\n\n /* --- Mentions & suggestions --- */\n .ProseMirror span.nile-wysiwyg__mention {\n display: inline-block;\n padding: 0 4px;\n border-radius: 4px;\n background: var(--nile-wysiwyg-mention-bg, var(--nile-colors-primary-50, var(--ng-componentcolors-utility-blue-50)));\n color: var(--nile-wysiwyg-mention-color, var(--nile-colors-primary-700, var(--ng-componentcolors-utility-blue-700)));\n font-weight: 500;\n /* Short mentions stay on one line; a long one (e.g. a deep field path) wraps\n inside its container instead of overflowing a table cell or the editor. */\n max-width: 100%;\n overflow-wrap: anywhere;\n }\n\n /* The chip's 500 is only a default — bold, headings and an explicit\n font-weight from the content win, so the chip looks the way it exports. */\n .ProseMirror :is(strong, b, h1, h2, h3, h4, h5, h6, th, [style*='font-weight'])\n span.nile-wysiwyg__mention {\n font-weight: inherit;\n }\n\n .ProseMirror span.nile-wysiwyg__mention.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n /* --- Merge fields --- */\n .ProseMirror span.nile-wysiwyg__merge-field {\n display: inline-block;\n padding: 0 4px;\n border-radius: 4px;\n background: var(\n --nile-wysiwyg-merge-bg,\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary))\n );\n color: var(\n --nile-wysiwyg-merge-color,\n var(--nile-colors-neutral-700, var(--ng-colors-text-primary-900))\n );\n border: 1px dashed var(--nile-colors-neutral-400, var(--ng-colors-border-primary));\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.9em;\n white-space: nowrap;\n }\n\n .ProseMirror span.nile-wysiwyg__merge-field.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n }\n\n /* --- Math --- */\n .ProseMirror span.nile-wysiwyg__math {\n display: inline-block;\n padding: 0 2px;\n font-family: \"Cambria Math\", \"Latin Modern Math\", serif;\n }\n\n .ProseMirror span.nile-wysiwyg__math--block {\n display: block;\n text-align: center;\n margin: 8px 0;\n }\n\n .ProseMirror span.nile-wysiwyg__math.ProseMirror-selectednode {\n outline: 2px solid var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600));\n border-radius: 3px;\n }\n\n /* Format painter armed: hint the next selection will be painted. */\n .ProseMirror.nile-wysiwyg--painting {\n cursor: cell;\n }\n\n .ProseMirror .nile-wysiwyg__suggestion {\n background: var(--nile-colors-primary-50, var(--ng-componentcolors-utility-blue-50));\n border-radius: 3px;\n }\n\n /* --- Find & replace highlights --- */\n .ProseMirror .nile-wysiwyg__find-match {\n background: var(--nile-wysiwyg-find-bg, rgba(255, 214, 102, 0.45));\n border-radius: 2px;\n }\n\n .ProseMirror .nile-wysiwyg__find-active {\n background: var(--nile-wysiwyg-find-active-bg, rgba(255, 170, 0, 0.65));\n }\n\n /* --- Upload placeholder --- */\n .nile-wysiwyg__upload-placeholder {\n display: inline-block;\n padding: 6px 12px;\n border: 1px dashed var(--nile-colors-neutral-400, var(--ng-colors-border-primary));\n border-radius: 6px;\n background: var(--nile-colors-neutral-50, var(--ng-colors-bg-secondary));\n color: var(--nile-colors-neutral-600, var(--ng-colors-text-tertiary-600));\n font-size: 0.85em;\n }\n\n /* --- Multi-level (legal) ordered lists: 1 / 1.1 / 1.1.1 numbering.\n Serialized output carries data-list-style=\"multilevel\"; consumers\n rendering it outside the editor need these same counter rules. --- */\n .ProseMirror ol[data-list-style='multilevel'],\n .ProseMirror ol[data-list-style='multilevel'] ol {\n list-style: none;\n counter-reset: nile-multilevel;\n }\n\n .ProseMirror ol[data-list-style='multilevel'] > li,\n .ProseMirror ol[data-list-style='multilevel'] ol > li {\n counter-increment: nile-multilevel;\n }\n\n /* The number sits inside the item's first paragraph so it shares a line. */\n .ProseMirror ol[data-list-style='multilevel'] > li > p:first-child::before,\n .ProseMirror ol[data-list-style='multilevel'] ol > li > p:first-child::before {\n content: counters(nile-multilevel, '.') '. ';\n font-variant-numeric: tabular-nums;\n }\n\n /* --- Show blocks: dashed outlines + tag labels while editing --- */\n .nile-wysiwyg--show-blocks .ProseMirror p,\n .nile-wysiwyg--show-blocks .ProseMirror h1,\n .nile-wysiwyg--show-blocks .ProseMirror h2,\n .nile-wysiwyg--show-blocks .ProseMirror h3,\n .nile-wysiwyg--show-blocks .ProseMirror h4,\n .nile-wysiwyg--show-blocks .ProseMirror h5,\n .nile-wysiwyg--show-blocks .ProseMirror h6,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote,\n .nile-wysiwyg--show-blocks .ProseMirror pre,\n .nile-wysiwyg--show-blocks .ProseMirror figure,\n .nile-wysiwyg--show-blocks .ProseMirror ul,\n .nile-wysiwyg--show-blocks .ProseMirror ol,\n .nile-wysiwyg--show-blocks .ProseMirror li,\n .nile-wysiwyg--show-blocks .ProseMirror table {\n outline: 1px dashed\n var(\n --nile-wysiwyg-block-outline,\n var(--nile-colors-neutral-400, var(--ng-colors-border-primary))\n );\n outline-offset: -1px;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p,\n .nile-wysiwyg--show-blocks .ProseMirror h1,\n .nile-wysiwyg--show-blocks .ProseMirror h2,\n .nile-wysiwyg--show-blocks .ProseMirror h3,\n .nile-wysiwyg--show-blocks .ProseMirror h4,\n .nile-wysiwyg--show-blocks .ProseMirror h5,\n .nile-wysiwyg--show-blocks .ProseMirror h6,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote,\n .nile-wysiwyg--show-blocks .ProseMirror pre {\n position: relative;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p::after,\n .nile-wysiwyg--show-blocks .ProseMirror h1::after,\n .nile-wysiwyg--show-blocks .ProseMirror h2::after,\n .nile-wysiwyg--show-blocks .ProseMirror h3::after,\n .nile-wysiwyg--show-blocks .ProseMirror h4::after,\n .nile-wysiwyg--show-blocks .ProseMirror h5::after,\n .nile-wysiwyg--show-blocks .ProseMirror h6::after,\n .nile-wysiwyg--show-blocks .ProseMirror blockquote::after,\n .nile-wysiwyg--show-blocks .ProseMirror pre::after {\n position: absolute;\n top: 0;\n left: 0;\n padding: 0 3px;\n font-family: system-ui, sans-serif;\n font-size: 9px;\n font-weight: 600;\n font-style: normal;\n line-height: 14px;\n letter-spacing: 0.5px;\n color: var(--nile-colors-neutral-500, var(--ng-colors-text-tertiary-600));\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n border-radius: 0 0 4px 0;\n pointer-events: none;\n }\n\n .nile-wysiwyg--show-blocks .ProseMirror p::after { content: 'P'; }\n .nile-wysiwyg--show-blocks .ProseMirror h1::after { content: 'H1'; }\n .nile-wysiwyg--show-blocks .ProseMirror h2::after { content: 'H2'; }\n .nile-wysiwyg--show-blocks .ProseMirror h3::after { content: 'H3'; }\n .nile-wysiwyg--show-blocks .ProseMirror h4::after { content: 'H4'; }\n .nile-wysiwyg--show-blocks .ProseMirror h5::after { content: 'H5'; }\n .nile-wysiwyg--show-blocks .ProseMirror h6::after { content: 'H6'; }\n .nile-wysiwyg--show-blocks .ProseMirror blockquote::after { content: 'QUOTE'; }\n .nile-wysiwyg--show-blocks .ProseMirror pre::after { content: 'PRE'; }\n`;\n"]}
|
|
@@ -114,6 +114,8 @@ export declare class NileWysiwygEditor extends NileElement {
|
|
|
114
114
|
noSlashCommands: boolean;
|
|
115
115
|
/** Disables the ":" emoji picker. */
|
|
116
116
|
noEmoji: boolean;
|
|
117
|
+
/** Hides the floating table toolbar; with `email-fidelity` it also hides in layout tables. */
|
|
118
|
+
noTableMenu: boolean;
|
|
117
119
|
/** Maximum character count; further input is rejected. 0 = unlimited. */
|
|
118
120
|
maxLength: number;
|
|
119
121
|
/** Always show the word/character counter footer (implied by maxlength). */
|
|
@@ -138,6 +140,10 @@ export declare class NileWysiwygEditor extends NileElement {
|
|
|
138
140
|
pasteAsPlainText: boolean;
|
|
139
141
|
/** Disables Markdown detection on plain-text pastes. */
|
|
140
142
|
noMarkdownPaste: boolean;
|
|
143
|
+
/** Opt-in mode for table-based email HTML; off by default (output unchanged). */
|
|
144
|
+
emailFidelity: boolean;
|
|
145
|
+
/** Extra inline CSS to keep per tag under `email-fidelity`: `{ td: ['letter-spacing'] }` or `"td: letter-spacing"`. */
|
|
146
|
+
allowedStyles: Record<string, string[]>;
|
|
141
147
|
/** Disables typography autocorrect (smart quotes, dashes, (c) → ©). */
|
|
142
148
|
noTextTransform: boolean;
|
|
143
149
|
/** Expands the editor to fill the viewport. Esc exits. */
|
|
@@ -172,6 +178,9 @@ export declare class NileWysiwygEditor extends NileElement {
|
|
|
172
178
|
private mathPanelEl;
|
|
173
179
|
private markdownPanelEl;
|
|
174
180
|
private view?;
|
|
181
|
+
/** Validated `allowedStyles`, recomputed once per config change (so the
|
|
182
|
+
* drop warnings fire once, not on every paste). */
|
|
183
|
+
private normalizedAllowedStyles;
|
|
175
184
|
private mentionMatch;
|
|
176
185
|
private slashMatch;
|
|
177
186
|
private emojiMatch;
|
|
@@ -183,6 +192,9 @@ export declare class NileWysiwygEditor extends NileElement {
|
|
|
183
192
|
private internals?;
|
|
184
193
|
private defaultValue;
|
|
185
194
|
private syncingValue;
|
|
195
|
+
/** Last raw HTML given to setContent; a re-parse reads it while the document is unedited. */
|
|
196
|
+
private lastSourceHtml;
|
|
197
|
+
private lastSerializedValue;
|
|
186
198
|
private changeTimer?;
|
|
187
199
|
private pendingChange;
|
|
188
200
|
/** Body overflow value before fullscreen locked it; null = not locked. */
|
|
@@ -214,6 +226,17 @@ export declare class NileWysiwygEditor extends NileElement {
|
|
|
214
226
|
* computeToolbarState can't know about (e.g. the paste-as-plain-text toggle).
|
|
215
227
|
*/
|
|
216
228
|
private snapshotToolbar;
|
|
229
|
+
/** HTML to re-parse when fidelity / the allowlist changes: the raw source when
|
|
230
|
+
* the document is still unedited (so a newly-allowed property can be recovered),
|
|
231
|
+
* otherwise the current serialized value (so user edits are kept). */
|
|
232
|
+
private reparseSource;
|
|
233
|
+
/** The saved HTML; with email-fidelity it carries the editor's table rendering. */
|
|
234
|
+
private serializeDoc;
|
|
235
|
+
private renderProbe;
|
|
236
|
+
/** Theme-resolved table border and header colours; null where the theme draws none. */
|
|
237
|
+
private emailRenderDefaults;
|
|
238
|
+
/** Email-fidelity options threaded to every sanitize/parse call. */
|
|
239
|
+
private emailOptions;
|
|
217
240
|
private mountView;
|
|
218
241
|
/**
|
|
219
242
|
* True while a drag-selection is in progress with the format painter armed.
|