@notectl/core 1.0.4 → 1.0.5
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 +51 -148
- package/dist/chunks/AttrRegistry-DTsHyDVA.mjs +16 -0
- package/dist/chunks/AttrRegistry-DTsHyDVA.mjs.map +1 -0
- package/dist/chunks/Commands-DLP85Mp5.mjs +461 -0
- package/dist/chunks/Commands-DLP85Mp5.mjs.map +1 -0
- package/dist/chunks/Document-CI3iCwEP.mjs +177 -0
- package/dist/chunks/Document-CI3iCwEP.mjs.map +1 -0
- package/dist/chunks/HTMLUtils-0wvCRvJc.mjs +7 -0
- package/dist/chunks/HTMLUtils-0wvCRvJc.mjs.map +1 -0
- package/dist/chunks/NodeResolver-D68ZLXti.mjs +81 -0
- package/dist/chunks/NodeResolver-D68ZLXti.mjs.map +1 -0
- package/dist/chunks/NodeSpec-NZVvcCuH.mjs +8 -0
- package/dist/chunks/NodeSpec-NZVvcCuH.mjs.map +1 -0
- package/dist/chunks/Plugin-B9OZ6Y4c.mjs +15 -0
- package/dist/chunks/Plugin-B9OZ6Y4c.mjs.map +1 -0
- package/dist/chunks/Selection-D5ZjXoB7.mjs +44 -0
- package/dist/chunks/Selection-D5ZjXoB7.mjs.map +1 -0
- package/dist/chunks/ToolbarItem-ugDymuXi.mjs +7 -0
- package/dist/chunks/ToolbarItem-ugDymuXi.mjs.map +1 -0
- package/dist/chunks/ToolbarPlugin-D5VqeBPT.mjs +398 -0
- package/dist/chunks/ToolbarPlugin-D5VqeBPT.mjs.map +1 -0
- package/dist/chunks/TypeBrands-C09nE2qO.mjs +27 -0
- package/dist/chunks/TypeBrands-C09nE2qO.mjs.map +1 -0
- package/dist/chunks/color-picker-Csf0wx5a.mjs +5 -0
- package/dist/chunks/color-picker-Csf0wx5a.mjs.map +1 -0
- package/dist/chunks/index-CPPb-Jah.mjs +569 -0
- package/dist/chunks/index-CPPb-Jah.mjs.map +1 -0
- package/dist/commands/Commands.d.ts +71 -0
- package/dist/commands/Commands.d.ts.map +1 -0
- package/dist/commands/PasteCommand.d.ts +9 -0
- package/dist/commands/PasteCommand.d.ts.map +1 -0
- package/dist/decorations/Decoration.d.ts +76 -0
- package/dist/decorations/Decoration.d.ts.map +1 -0
- package/dist/decorations/PositionMapping.d.ts +9 -0
- package/dist/decorations/PositionMapping.d.ts.map +1 -0
- package/dist/editor/Announcer.d.ts +12 -0
- package/dist/editor/Announcer.d.ts.map +1 -0
- package/dist/editor/DocumentParser.d.ts +5 -0
- package/dist/editor/DocumentParser.d.ts.map +1 -0
- package/dist/editor/DocumentSerializer.d.ts +5 -0
- package/dist/editor/DocumentSerializer.d.ts.map +1 -0
- package/dist/editor/EditorDOM.d.ts +18 -0
- package/dist/editor/EditorDOM.d.ts.map +1 -0
- package/dist/editor/EditorThemeController.d.ts +21 -0
- package/dist/editor/EditorThemeController.d.ts.map +1 -0
- package/dist/editor/NotectlEditor.d.ts +131 -0
- package/dist/editor/NotectlEditor.d.ts.map +1 -0
- package/dist/editor/styles/base.d.ts +3 -0
- package/dist/editor/styles/base.d.ts.map +1 -0
- package/dist/editor/styles/code-block.d.ts +3 -0
- package/dist/editor/styles/code-block.d.ts.map +1 -0
- package/dist/editor/styles/color-picker.d.ts +3 -0
- package/dist/editor/styles/color-picker.d.ts.map +1 -0
- package/dist/editor/styles/font-select.d.ts +3 -0
- package/dist/editor/styles/font-select.d.ts.map +1 -0
- package/dist/editor/styles/font-size-select.d.ts +3 -0
- package/dist/editor/styles/font-size-select.d.ts.map +1 -0
- package/dist/editor/styles/heading-select.d.ts +3 -0
- package/dist/editor/styles/heading-select.d.ts.map +1 -0
- package/dist/editor/styles/image.d.ts +3 -0
- package/dist/editor/styles/image.d.ts.map +1 -0
- package/dist/editor/styles/list.d.ts +3 -0
- package/dist/editor/styles/list.d.ts.map +1 -0
- package/dist/editor/styles/reduced-motion.d.ts +3 -0
- package/dist/editor/styles/reduced-motion.d.ts.map +1 -0
- package/dist/editor/styles/table.d.ts +3 -0
- package/dist/editor/styles/table.d.ts.map +1 -0
- package/dist/editor/styles/toolbar.d.ts +3 -0
- package/dist/editor/styles/toolbar.d.ts.map +1 -0
- package/dist/editor/styles.d.ts +12 -0
- package/dist/editor/styles.d.ts.map +1 -0
- package/dist/editor/theme/ThemeEngine.d.ts +6 -0
- package/dist/editor/theme/ThemeEngine.d.ts.map +1 -0
- package/dist/editor/theme/ThemeTokens.d.ts +73 -0
- package/dist/editor/theme/ThemeTokens.d.ts.map +1 -0
- package/dist/fonts.d.ts +17 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.mjs +7 -0
- package/dist/fonts.mjs.map +1 -0
- package/dist/index.d.ts +81 -2360
- package/dist/index.d.ts.map +1 -0
- package/dist/input/ClipboardHandler.d.ts +29 -0
- package/dist/input/ClipboardHandler.d.ts.map +1 -0
- package/dist/input/InputHandler.d.ts +32 -0
- package/dist/input/InputHandler.d.ts.map +1 -0
- package/dist/input/InputRule.d.ts +9 -0
- package/dist/input/InputRule.d.ts.map +1 -0
- package/dist/input/InternalClipboard.d.ts +23 -0
- package/dist/input/InternalClipboard.d.ts.map +1 -0
- package/dist/input/KeyboardHandler.d.ts +42 -0
- package/dist/input/KeyboardHandler.d.ts.map +1 -0
- package/dist/input/Keymap.d.ts +11 -0
- package/dist/input/Keymap.d.ts.map +1 -0
- package/dist/input/PasteHandler.d.ts +38 -0
- package/dist/input/PasteHandler.d.ts.map +1 -0
- package/dist/input/SourceNormalizer.d.ts +7 -0
- package/dist/input/SourceNormalizer.d.ts.map +1 -0
- package/dist/model/AttrRegistry.d.ts +39 -0
- package/dist/model/AttrRegistry.d.ts.map +1 -0
- package/dist/model/BuiltinSpecs.d.ts +4 -0
- package/dist/model/BuiltinSpecs.d.ts.map +1 -0
- package/dist/model/ContentModel.d.ts +12 -0
- package/dist/model/ContentModel.d.ts.map +1 -0
- package/dist/model/ContentSlice.d.ts +17 -0
- package/dist/model/ContentSlice.d.ts.map +1 -0
- package/dist/model/Document.d.ts +127 -0
- package/dist/model/Document.d.ts.map +1 -0
- package/dist/model/HTMLParser.d.ts +36 -0
- package/dist/model/HTMLParser.d.ts.map +1 -0
- package/dist/model/HTMLUtils.d.ts +6 -0
- package/dist/model/HTMLUtils.d.ts.map +1 -0
- package/dist/model/InlineNodeSpec.d.ts +20 -0
- package/dist/model/InlineNodeSpec.d.ts.map +1 -0
- package/dist/model/MarkSpec.d.ts +22 -0
- package/dist/model/MarkSpec.d.ts.map +1 -0
- package/dist/model/NodeResolver.d.ts +36 -0
- package/dist/model/NodeResolver.d.ts.map +1 -0
- package/dist/model/NodeSpec.d.ts +67 -0
- package/dist/model/NodeSpec.d.ts.map +1 -0
- package/dist/model/ParseRule.d.ts +11 -0
- package/dist/model/ParseRule.d.ts.map +1 -0
- package/dist/model/SanitizeConfig.d.ts +9 -0
- package/dist/model/SanitizeConfig.d.ts.map +1 -0
- package/dist/model/Schema.d.ts +17 -0
- package/dist/model/Schema.d.ts.map +1 -0
- package/dist/model/SchemaRegistry.d.ts +81 -0
- package/dist/model/SchemaRegistry.d.ts.map +1 -0
- package/dist/model/Selection.d.ts +52 -0
- package/dist/model/Selection.d.ts.map +1 -0
- package/dist/model/TypeBrands.d.ts +28 -0
- package/dist/model/TypeBrands.d.ts.map +1 -0
- package/dist/notectl-core.mjs +2576 -11104
- package/dist/notectl-core.mjs.map +1 -1
- package/dist/notectl-core.umd.js +6810 -0
- package/dist/notectl-core.umd.js.map +1 -0
- package/dist/plugins/EventBus.d.ts +13 -0
- package/dist/plugins/EventBus.d.ts.map +1 -0
- package/dist/plugins/Plugin.d.ts +85 -0
- package/dist/plugins/Plugin.d.ts.map +1 -0
- package/dist/plugins/PluginManager.d.ts +66 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -0
- package/dist/plugins/alignment/AlignmentPlugin.d.ts +48 -0
- package/dist/plugins/alignment/AlignmentPlugin.d.ts.map +1 -0
- package/dist/plugins/alignment/index.d.ts +2 -0
- package/dist/plugins/alignment/index.d.ts.map +1 -0
- package/dist/plugins/alignment.mjs +92 -0
- package/dist/plugins/alignment.mjs.map +1 -0
- package/dist/plugins/blockquote/BlockquotePlugin.d.ts +30 -0
- package/dist/plugins/blockquote/BlockquotePlugin.d.ts.map +1 -0
- package/dist/plugins/blockquote/index.d.ts +2 -0
- package/dist/plugins/blockquote/index.d.ts.map +1 -0
- package/dist/plugins/blockquote.mjs +58 -0
- package/dist/plugins/blockquote.mjs.map +1 -0
- package/dist/plugins/code-block/CodeBlockNodeView.d.ts +5 -0
- package/dist/plugins/code-block/CodeBlockNodeView.d.ts.map +1 -0
- package/dist/plugins/code-block/CodeBlockPlugin.d.ts +135 -0
- package/dist/plugins/code-block/CodeBlockPlugin.d.ts.map +1 -0
- package/dist/plugins/code-block/index.d.ts +2 -0
- package/dist/plugins/code-block/index.d.ts.map +1 -0
- package/dist/plugins/code-block.mjs +6 -0
- package/dist/plugins/code-block.mjs.map +1 -0
- package/dist/plugins/font/FontPlugin.d.ts +85 -0
- package/dist/plugins/font/FontPlugin.d.ts.map +1 -0
- package/dist/plugins/font/StarterFonts.d.ts +10 -0
- package/dist/plugins/font/StarterFonts.d.ts.map +1 -0
- package/dist/plugins/font/index.d.ts +2 -0
- package/dist/plugins/font/index.d.ts.map +1 -0
- package/dist/plugins/font-size/FontSizePlugin.d.ts +65 -0
- package/dist/plugins/font-size/FontSizePlugin.d.ts.map +1 -0
- package/dist/plugins/font-size/index.d.ts +2 -0
- package/dist/plugins/font-size/index.d.ts.map +1 -0
- package/dist/plugins/font-size.mjs +220 -0
- package/dist/plugins/font-size.mjs.map +1 -0
- package/dist/plugins/font.mjs +186 -0
- package/dist/plugins/font.mjs.map +1 -0
- package/dist/plugins/hard-break/HardBreakPlugin.d.ts +16 -0
- package/dist/plugins/hard-break/HardBreakPlugin.d.ts.map +1 -0
- package/dist/plugins/hard-break/index.d.ts +2 -0
- package/dist/plugins/hard-break/index.d.ts.map +1 -0
- package/dist/plugins/hard-break.mjs +28 -0
- package/dist/plugins/hard-break.mjs.map +1 -0
- package/dist/plugins/heading/BlockTypePickerEntry.d.ts +20 -0
- package/dist/plugins/heading/BlockTypePickerEntry.d.ts.map +1 -0
- package/dist/plugins/heading/HeadingPlugin.d.ts +78 -0
- package/dist/plugins/heading/HeadingPlugin.d.ts.map +1 -0
- package/dist/plugins/heading/index.d.ts +3 -0
- package/dist/plugins/heading/index.d.ts.map +1 -0
- package/dist/plugins/heading.mjs +188 -0
- package/dist/plugins/heading.mjs.map +1 -0
- package/dist/plugins/highlight/HighlightPlugin.d.ts +37 -0
- package/dist/plugins/highlight/HighlightPlugin.d.ts.map +1 -0
- package/dist/plugins/highlight/index.d.ts +2 -0
- package/dist/plugins/highlight/index.d.ts.map +1 -0
- package/dist/plugins/highlight.mjs +126 -0
- package/dist/plugins/highlight.mjs.map +1 -0
- package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts +29 -0
- package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts.map +1 -0
- package/dist/plugins/horizontal-rule/index.d.ts +2 -0
- package/dist/plugins/horizontal-rule/index.d.ts.map +1 -0
- package/dist/plugins/horizontal-rule.mjs +59 -0
- package/dist/plugins/horizontal-rule.mjs.map +1 -0
- package/dist/plugins/image/ImageCommands.d.ts +26 -0
- package/dist/plugins/image/ImageCommands.d.ts.map +1 -0
- package/dist/plugins/image/ImageNodeView.d.ts +6 -0
- package/dist/plugins/image/ImageNodeView.d.ts.map +1 -0
- package/dist/plugins/image/ImagePlugin.d.ts +43 -0
- package/dist/plugins/image/ImagePlugin.d.ts.map +1 -0
- package/dist/plugins/image/ImageUpload.d.ts +48 -0
- package/dist/plugins/image/ImageUpload.d.ts.map +1 -0
- package/dist/plugins/image/index.d.ts +3 -0
- package/dist/plugins/image/index.d.ts.map +1 -0
- package/dist/plugins/image.mjs +381 -0
- package/dist/plugins/image.mjs.map +1 -0
- package/dist/plugins/link/LinkPlugin.d.ts +32 -0
- package/dist/plugins/link/LinkPlugin.d.ts.map +1 -0
- package/dist/plugins/link/index.d.ts +2 -0
- package/dist/plugins/link/index.d.ts.map +1 -0
- package/dist/plugins/link.mjs +127 -0
- package/dist/plugins/link.mjs.map +1 -0
- package/dist/plugins/list/ListPlugin.d.ts +51 -0
- package/dist/plugins/list/ListPlugin.d.ts.map +1 -0
- package/dist/plugins/list/index.d.ts +2 -0
- package/dist/plugins/list/index.d.ts.map +1 -0
- package/dist/plugins/list.mjs +193 -0
- package/dist/plugins/list.mjs.map +1 -0
- package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts +23 -0
- package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts.map +1 -0
- package/dist/plugins/strikethrough/index.d.ts +2 -0
- package/dist/plugins/strikethrough/index.d.ts.map +1 -0
- package/dist/plugins/strikethrough.mjs +35 -0
- package/dist/plugins/strikethrough.mjs.map +1 -0
- package/dist/plugins/super-sub/SuperSubPlugin.d.ts +44 -0
- package/dist/plugins/super-sub/SuperSubPlugin.d.ts.map +1 -0
- package/dist/plugins/super-sub/index.d.ts +2 -0
- package/dist/plugins/super-sub/index.d.ts.map +1 -0
- package/dist/plugins/super-sub.mjs +81 -0
- package/dist/plugins/super-sub.mjs.map +1 -0
- package/dist/plugins/table/TableCommands.d.ts +50 -0
- package/dist/plugins/table/TableCommands.d.ts.map +1 -0
- package/dist/plugins/table/TableControls.d.ts +10 -0
- package/dist/plugins/table/TableControls.d.ts.map +1 -0
- package/dist/plugins/table/TableControlsDOM.d.ts +18 -0
- package/dist/plugins/table/TableControlsDOM.d.ts.map +1 -0
- package/dist/plugins/table/TableControlsLayout.d.ts +34 -0
- package/dist/plugins/table/TableControlsLayout.d.ts.map +1 -0
- package/dist/plugins/table/TableHelpers.d.ts +39 -0
- package/dist/plugins/table/TableHelpers.d.ts.map +1 -0
- package/dist/plugins/table/TableNavigation.d.ts +4 -0
- package/dist/plugins/table/TableNavigation.d.ts.map +1 -0
- package/dist/plugins/table/TableNodeViews.d.ts +18 -0
- package/dist/plugins/table/TableNodeViews.d.ts.map +1 -0
- package/dist/plugins/table/TablePlugin.d.ts +39 -0
- package/dist/plugins/table/TablePlugin.d.ts.map +1 -0
- package/dist/plugins/table/TableSelection.d.ts +26 -0
- package/dist/plugins/table/TableSelection.d.ts.map +1 -0
- package/dist/plugins/table/TableTestUtils.d.ts +45 -0
- package/dist/plugins/table/TableTestUtils.d.ts.map +1 -0
- package/dist/plugins/table/index.d.ts +4 -0
- package/dist/plugins/table/index.d.ts.map +1 -0
- package/dist/plugins/table.mjs +663 -0
- package/dist/plugins/table.mjs.map +1 -0
- package/dist/plugins/text-color/TextColorPlugin.d.ts +37 -0
- package/dist/plugins/text-color/TextColorPlugin.d.ts.map +1 -0
- package/dist/plugins/text-color/index.d.ts +2 -0
- package/dist/plugins/text-color/index.d.ts.map +1 -0
- package/dist/plugins/text-color.mjs +126 -0
- package/dist/plugins/text-color.mjs.map +1 -0
- package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts +34 -0
- package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts.map +1 -0
- package/dist/plugins/text-formatting/index.d.ts +2 -0
- package/dist/plugins/text-formatting/index.d.ts.map +1 -0
- package/dist/plugins/text-formatting.mjs +52 -0
- package/dist/plugins/text-formatting.mjs.map +1 -0
- package/dist/plugins/toolbar/ToolbarItem.d.ts +66 -0
- package/dist/plugins/toolbar/ToolbarItem.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarKeyboardNav.d.ts +25 -0
- package/dist/plugins/toolbar/ToolbarKeyboardNav.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarPlugin.d.ts +47 -0
- package/dist/plugins/toolbar/ToolbarPlugin.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarPopupController.d.ts +25 -0
- package/dist/plugins/toolbar/ToolbarPopupController.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarRenderers.d.ts +19 -0
- package/dist/plugins/toolbar/ToolbarRenderers.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarTooltip.d.ts +17 -0
- package/dist/plugins/toolbar/ToolbarTooltip.d.ts.map +1 -0
- package/dist/plugins/toolbar/index.d.ts +4 -0
- package/dist/plugins/toolbar/index.d.ts.map +1 -0
- package/dist/plugins/toolbar.mjs +8 -0
- package/dist/plugins/toolbar.mjs.map +1 -0
- package/dist/state/EditorState.d.ts +40 -0
- package/dist/state/EditorState.d.ts.map +1 -0
- package/dist/state/History.d.ts +38 -0
- package/dist/state/History.d.ts.map +1 -0
- package/dist/state/StepApplication.d.ts +5 -0
- package/dist/state/StepApplication.d.ts.map +1 -0
- package/dist/state/Transaction.d.ts +185 -0
- package/dist/state/Transaction.d.ts.map +1 -0
- package/dist/test/PluginTestUtils.d.ts +127 -0
- package/dist/test/PluginTestUtils.d.ts.map +1 -0
- package/dist/test/TestUtils.d.ts +153 -0
- package/dist/test/TestUtils.d.ts.map +1 -0
- package/dist/view/EditorView.d.ts +74 -0
- package/dist/view/EditorView.d.ts.map +1 -0
- package/dist/view/NodeView.d.ts +18 -0
- package/dist/view/NodeView.d.ts.map +1 -0
- package/dist/view/Reconciler.d.ts +23 -0
- package/dist/view/Reconciler.d.ts.map +1 -0
- package/dist/view/SelectionSync.d.ts +8 -0
- package/dist/view/SelectionSync.d.ts.map +1 -0
- package/package.json +112 -11
- package/dist/notectl-core.js +0 -1463
- package/dist/notectl-core.js.map +0 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { p as t, g as e, b as n, j as o, k as r } from "../chunks/Document-CI3iCwEP.mjs";
|
|
2
|
+
import { c as i } from "../chunks/NodeSpec-NZVvcCuH.mjs";
|
|
3
|
+
import { i as l, a, c as s } from "../chunks/Selection-D5ZjXoB7.mjs";
|
|
4
|
+
import { n as c } from "../chunks/TypeBrands-C09nE2qO.mjs";
|
|
5
|
+
import { a as g } from "../chunks/ToolbarPlugin-D5VqeBPT.mjs";
|
|
6
|
+
const d = { levels: [1, 2, 3, 4, 5, 6] }, p = { 1: "h1", 2: "h2", 3: "h3", 4: "h4", 5: "h5", 6: "h6" }, h = { 1: "Heading 1", 2: "Heading 2", 3: "Heading 3", 4: "Heading 4", 5: "Heading 5", 6: "Heading 6" }, u = "Paragraph";
|
|
7
|
+
class b {
|
|
8
|
+
id = "heading";
|
|
9
|
+
name = "Heading";
|
|
10
|
+
priority = 30;
|
|
11
|
+
config;
|
|
12
|
+
context = null;
|
|
13
|
+
comboLabel = null;
|
|
14
|
+
constructor(t2) {
|
|
15
|
+
this.config = { ...d, ...t2 };
|
|
16
|
+
}
|
|
17
|
+
init(t2) {
|
|
18
|
+
t2.registerStyleSheet("\n/* Heading Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--heading {\n width: auto;\n min-width: 100px;\n max-width: 160px;\n padding: 0 8px;\n gap: 4px;\n border: 1px solid var(--notectl-border);\n border-radius: 4px;\n background: var(--notectl-bg);\n}\n\n.notectl-toolbar-btn--heading:hover {\n background: var(--notectl-hover-bg);\n border-color: var(--notectl-fg-muted);\n}\n\n.notectl-toolbar-btn--heading.notectl-toolbar-btn--active {\n background: var(--notectl-bg);\n border-color: var(--notectl-primary-muted);\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon {\n display: flex;\n align-items: center;\n gap: 4px;\n width: 100%;\n overflow: hidden;\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon svg {\n display: none;\n}\n\n.notectl-heading-select__label {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: var(--notectl-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n text-align: left;\n line-height: 30px;\n}\n\n.notectl-heading-select__arrow {\n flex-shrink: 0;\n font-size: 11px;\n color: var(--notectl-fg-muted);\n line-height: 30px;\n}\n\n/* Heading Picker Popup */\n.notectl-heading-picker {\n min-width: 200px;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.notectl-heading-picker__list {\n padding: 4px 0;\n}\n\n.notectl-heading-picker__item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 12px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 14px;\n color: var(--notectl-fg);\n text-align: left;\n white-space: nowrap;\n font-family: inherit;\n transition: background 0.1s;\n}\n\n.notectl-heading-picker__item:hover {\n background: var(--notectl-hover-bg);\n}\n\n.notectl-heading-picker__item--active {\n background: var(--notectl-active-bg);\n color: var(--notectl-primary-fg);\n}\n\n.notectl-heading-picker__item--active:hover {\n background: var(--notectl-active-bg);\n}\n\n.notectl-heading-picker__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n flex-shrink: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--notectl-primary-fg);\n}\n\n.notectl-heading-picker__label {\n flex: 1;\n}\n"), this.context = t2, this.registerNodeSpecs(t2), this.registerCommands(t2), this.registerKeymaps(t2), this.registerInputRules(t2), this.registerPickerEntries(t2), this.registerToolbarItem(t2);
|
|
19
|
+
}
|
|
20
|
+
destroy() {
|
|
21
|
+
this.context = null, this.comboLabel = null;
|
|
22
|
+
}
|
|
23
|
+
onStateChange(t2, e2, n2) {
|
|
24
|
+
this.updateComboLabel(e2);
|
|
25
|
+
}
|
|
26
|
+
registerNodeSpecs(t2) {
|
|
27
|
+
t2.registerNodeSpec({ type: "title", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], toDOM(t3) {
|
|
28
|
+
const e2 = i("h1", t3.id);
|
|
29
|
+
return e2.classList.add("notectl-title"), e2;
|
|
30
|
+
}, toHTML: (t3, e2) => `<h1>${e2 || "<br>"}</h1>`, sanitize: { tags: ["h1"] } }), t2.registerNodeSpec({ type: "subtitle", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], toDOM(t3) {
|
|
31
|
+
const e2 = i("h2", t3.id);
|
|
32
|
+
return e2.classList.add("notectl-subtitle"), e2;
|
|
33
|
+
}, toHTML: (t3, e2) => `<h2>${e2 || "<br>"}</h2>`, sanitize: { tags: ["h2"] } }), t2.registerNodeSpec({ type: "heading", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], attrs: { level: { default: 1 } }, toDOM(t3) {
|
|
34
|
+
const e2 = t3.attrs?.level ?? 1;
|
|
35
|
+
return i(p[e2] ?? "h1", t3.id);
|
|
36
|
+
}, toHTML(t3, e2) {
|
|
37
|
+
const n2 = t3.attrs?.level ?? 1, o2 = p[n2] ?? "h1";
|
|
38
|
+
return `<${o2}>${e2 || "<br>"}</${o2}>`;
|
|
39
|
+
}, parseHTML: [{ tag: "h1", getAttrs: () => ({ level: 1 }) }, { tag: "h2", getAttrs: () => ({ level: 2 }) }, { tag: "h3", getAttrs: () => ({ level: 3 }) }, { tag: "h4", getAttrs: () => ({ level: 4 }) }, { tag: "h5", getAttrs: () => ({ level: 5 }) }, { tag: "h6", getAttrs: () => ({ level: 6 }) }], sanitize: { tags: ["h1", "h2", "h3", "h4", "h5", "h6"] } });
|
|
40
|
+
}
|
|
41
|
+
registerCommands(t2) {
|
|
42
|
+
t2.registerCommand("setTitle", () => this.toggleSpecialBlock(t2, "title")), t2.registerCommand("setSubtitle", () => this.toggleSpecialBlock(t2, "subtitle"));
|
|
43
|
+
for (const e2 of this.config.levels) t2.registerCommand(`setHeading${e2}`, () => this.toggleHeading(t2, e2));
|
|
44
|
+
t2.registerCommand("toggleHeading", () => this.toggleHeading(t2, 1)), t2.registerCommand("setParagraph", () => this.setBlockType(t2, c("paragraph")));
|
|
45
|
+
}
|
|
46
|
+
registerKeymaps(t2) {
|
|
47
|
+
const e2 = { Enter: () => this.handleEnter(t2) };
|
|
48
|
+
for (const n2 of this.config.levels) n2 <= 6 && (e2[`Mod-Shift-${n2}`] = () => t2.executeCommand(`setHeading${n2}`));
|
|
49
|
+
t2.registerKeymap(e2);
|
|
50
|
+
}
|
|
51
|
+
registerInputRules(t2) {
|
|
52
|
+
for (const e2 of this.config.levels) {
|
|
53
|
+
const n2 = "#".repeat(e2), o2 = new RegExp(`^${n2} $`);
|
|
54
|
+
t2.registerInputRule({ pattern: o2, handler(t3, n3, o3, r2) {
|
|
55
|
+
const i2 = t3.selection;
|
|
56
|
+
if (l(i2)) return null;
|
|
57
|
+
if (!a(i2)) return null;
|
|
58
|
+
const g2 = t3.getBlock(i2.anchor.blockId);
|
|
59
|
+
return g2 && "paragraph" === g2.type ? t3.transaction("input").deleteTextAt(i2.anchor.blockId, o3, o3 + e2 + 1).setBlockType(i2.anchor.blockId, c("heading"), { level: e2 }).setSelection(s(i2.anchor.blockId, 0)).build() : null;
|
|
60
|
+
} });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
registerPickerEntries(t2) {
|
|
64
|
+
t2.registerBlockTypePickerEntry({ id: "paragraph", label: u, command: "setParagraph", priority: 10, isActive: (t3) => {
|
|
65
|
+
if (l(t3.selection)) return false;
|
|
66
|
+
const e2 = t3.getBlock(t3.selection.anchor.blockId);
|
|
67
|
+
return "paragraph" === e2?.type;
|
|
68
|
+
} }), t2.registerBlockTypePickerEntry({ id: "title", label: "Title", command: "setTitle", priority: 20, style: { fontSize: "1.6em", fontWeight: "700" }, isActive: (t3) => {
|
|
69
|
+
if (l(t3.selection)) return false;
|
|
70
|
+
const e2 = t3.getBlock(t3.selection.anchor.blockId);
|
|
71
|
+
return "title" === e2?.type;
|
|
72
|
+
} }), t2.registerBlockTypePickerEntry({ id: "subtitle", label: "Subtitle", command: "setSubtitle", priority: 30, style: { fontSize: "1.3em", fontWeight: "500" }, isActive: (t3) => {
|
|
73
|
+
if (l(t3.selection)) return false;
|
|
74
|
+
const e2 = t3.getBlock(t3.selection.anchor.blockId);
|
|
75
|
+
return "subtitle" === e2?.type;
|
|
76
|
+
} });
|
|
77
|
+
for (const e2 of this.config.levels) t2.registerBlockTypePickerEntry({ id: `heading-${e2}`, label: h[e2], command: `setHeading${e2}`, priority: 100 + e2, style: { fontSize: 1.4 - 0.1 * e2 + "em", fontWeight: "600" }, isActive: (t3) => {
|
|
78
|
+
if (l(t3.selection)) return false;
|
|
79
|
+
const n2 = t3.getBlock(t3.selection.anchor.blockId);
|
|
80
|
+
return "heading" === n2?.type && n2.attrs?.level === e2;
|
|
81
|
+
} });
|
|
82
|
+
}
|
|
83
|
+
registerToolbarItem(t2) {
|
|
84
|
+
const e2 = `<span class="notectl-heading-select__label" data-heading-label>${u}</span><span class="notectl-heading-select__arrow">▾</span>`;
|
|
85
|
+
t2.registerToolbarItem({ id: "heading", group: "block", icon: e2, label: "Block Type", tooltip: "Block Type", command: "setParagraph", priority: 50, popupType: "custom", separatorAfter: this.config.separatorAfter, renderPopup: (t3, e3) => {
|
|
86
|
+
this.renderHeadingPopup(t3, e3);
|
|
87
|
+
}, isActive: (e3) => t2.getSchemaRegistry().getBlockTypePickerEntries().some((t3) => "paragraph" !== t3.id && t3.isActive(e3)) });
|
|
88
|
+
}
|
|
89
|
+
updateComboLabel(t2) {
|
|
90
|
+
if (!this.comboLabel) {
|
|
91
|
+
const t3 = this.context?.getPluginContainer("top");
|
|
92
|
+
if (!t3) return;
|
|
93
|
+
if (this.comboLabel = t3.querySelector("[data-heading-label]") ?? null, !this.comboLabel) return;
|
|
94
|
+
}
|
|
95
|
+
this.comboLabel.textContent = this.getActiveLabel(t2);
|
|
96
|
+
}
|
|
97
|
+
getActiveLabel(t2) {
|
|
98
|
+
if (l(t2.selection)) return u;
|
|
99
|
+
const e2 = this.context?.getSchemaRegistry().getBlockTypePickerEntries() ?? [];
|
|
100
|
+
for (const n2 of e2) if (n2.isActive(t2)) return n2.label;
|
|
101
|
+
return u;
|
|
102
|
+
}
|
|
103
|
+
dismissPopup() {
|
|
104
|
+
const t2 = this.context?.getService(g);
|
|
105
|
+
t2?.closePopup();
|
|
106
|
+
}
|
|
107
|
+
renderHeadingPopup(t2, e2) {
|
|
108
|
+
t2.classList.add("notectl-heading-picker");
|
|
109
|
+
const n2 = e2.getState();
|
|
110
|
+
if (l(n2.selection)) return;
|
|
111
|
+
const o2 = document.createElement("div");
|
|
112
|
+
o2.className = "notectl-heading-picker__list", o2.setAttribute("role", "listbox"), o2.setAttribute("aria-label", "Block types");
|
|
113
|
+
const r2 = e2.getSchemaRegistry().getBlockTypePickerEntries();
|
|
114
|
+
for (const t3 of r2) {
|
|
115
|
+
const r3 = t3.isActive(n2);
|
|
116
|
+
o2.appendChild(this.createPickerItem(t3.label, r3, (n3) => {
|
|
117
|
+
n3.preventDefault(), n3.stopPropagation(), e2.executeCommand(t3.command), this.dismissPopup();
|
|
118
|
+
}, t3.style));
|
|
119
|
+
}
|
|
120
|
+
t2.appendChild(o2);
|
|
121
|
+
}
|
|
122
|
+
createPickerItem(t2, e2, n2, o2) {
|
|
123
|
+
const r2 = document.createElement("button");
|
|
124
|
+
r2.type = "button", r2.className = "notectl-heading-picker__item", r2.setAttribute("role", "option"), r2.setAttribute("aria-selected", String(e2)), e2 && r2.classList.add("notectl-heading-picker__item--active");
|
|
125
|
+
const i2 = document.createElement("span");
|
|
126
|
+
i2.className = "notectl-heading-picker__check", i2.textContent = e2 ? "✓" : "", r2.appendChild(i2);
|
|
127
|
+
const l2 = document.createElement("span");
|
|
128
|
+
return l2.className = "notectl-heading-picker__label", l2.textContent = t2, o2 && (l2.style.fontSize = o2.fontSize, l2.style.fontWeight = o2.fontWeight), r2.appendChild(l2), r2.addEventListener("mousedown", n2), r2;
|
|
129
|
+
}
|
|
130
|
+
static HEADING_TYPES = /* @__PURE__ */ new Set(["heading", "title", "subtitle"]);
|
|
131
|
+
handleEnter(o2) {
|
|
132
|
+
const r2 = o2.getState(), i2 = r2.selection;
|
|
133
|
+
if (l(i2)) return false;
|
|
134
|
+
if (!a(i2)) return false;
|
|
135
|
+
const g2 = r2.getBlock(i2.anchor.blockId);
|
|
136
|
+
if (!g2 || !b.HEADING_TYPES.has(g2.type)) return false;
|
|
137
|
+
if ("" === t(g2)) {
|
|
138
|
+
const t2 = r2.transaction("input").setBlockType(i2.anchor.blockId, c("paragraph")).setSelection(i2).build();
|
|
139
|
+
return o2.dispatch(t2), true;
|
|
140
|
+
}
|
|
141
|
+
const d2 = e(g2);
|
|
142
|
+
if (i2.anchor.offset >= d2) {
|
|
143
|
+
const t2 = n(), e2 = r2.transaction("input").splitBlock(i2.anchor.blockId, i2.anchor.offset, t2).setBlockType(t2, c("paragraph")).setSelection(s(t2, 0)).build();
|
|
144
|
+
return o2.dispatch(e2), true;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
toggleSpecialBlock(t2, e2) {
|
|
149
|
+
const n2 = t2.getState();
|
|
150
|
+
if (l(n2.selection)) return false;
|
|
151
|
+
const o2 = n2.getBlock(n2.selection.anchor.blockId);
|
|
152
|
+
return !!o2 && (o2.type === e2 ? this.setBlockType(t2, c("paragraph")) : this.setBlockType(t2, c(e2)));
|
|
153
|
+
}
|
|
154
|
+
toggleHeading(t2, e2) {
|
|
155
|
+
const n2 = t2.getState(), o2 = n2.selection;
|
|
156
|
+
if (l(o2)) return false;
|
|
157
|
+
const r2 = n2.getBlock(o2.anchor.blockId);
|
|
158
|
+
return !!r2 && ("heading" === r2.type && r2.attrs?.level === e2 ? this.setBlockType(t2, c("paragraph")) : this.setBlockType(t2, c("heading"), { level: e2 }));
|
|
159
|
+
}
|
|
160
|
+
setBlockType(t2, e2, n2) {
|
|
161
|
+
const o2 = t2.getState(), r2 = o2.selection;
|
|
162
|
+
if (l(r2)) return false;
|
|
163
|
+
const i2 = o2.getBlock(r2.anchor.blockId);
|
|
164
|
+
if (!i2) return false;
|
|
165
|
+
const a2 = o2.transaction("command"), s2 = t2.getSchemaRegistry().getNodeSpec(e2);
|
|
166
|
+
s2?.excludeMarks && s2.excludeMarks.length > 0 && (this.stripExcludedMarks(a2, i2, s2.excludeMarks), this.clearExcludedStoredMarks(a2, o2, s2.excludeMarks));
|
|
167
|
+
const c2 = a2.setBlockType(r2.anchor.blockId, e2, n2).setSelection(r2).build();
|
|
168
|
+
return t2.dispatch(c2), true;
|
|
169
|
+
}
|
|
170
|
+
stripExcludedMarks(t2, n2, i2) {
|
|
171
|
+
if (0 === e(n2)) return;
|
|
172
|
+
const l2 = new Set(i2), a2 = o(n2);
|
|
173
|
+
let s2 = 0;
|
|
174
|
+
for (const e2 of a2) if (r(e2)) {
|
|
175
|
+
if (e2.text.length > 0) for (const o2 of e2.marks) l2.has(o2.type) && t2.removeMark(n2.id, s2, s2 + e2.text.length, o2);
|
|
176
|
+
s2 += e2.text.length;
|
|
177
|
+
} else s2 += 1;
|
|
178
|
+
}
|
|
179
|
+
clearExcludedStoredMarks(t2, e2, n2) {
|
|
180
|
+
if (!e2.storedMarks) return;
|
|
181
|
+
const o2 = new Set(n2), r2 = e2.storedMarks.filter((t3) => !o2.has(t3.type));
|
|
182
|
+
r2.length !== e2.storedMarks.length && t2.setStoredMarks(r2.length > 0 ? r2 : null, e2.storedMarks);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export {
|
|
186
|
+
b as HeadingPlugin
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=heading.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heading.mjs","sources":["../../src/editor/styles/heading-select.ts","../../src/plugins/heading/HeadingPlugin.ts"],"sourcesContent":["/** Heading picker toolbar combobox + popup styles. */\nexport const HEADING_SELECT_CSS = `\n/* Heading Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--heading {\n\twidth: auto;\n\tmin-width: 100px;\n\tmax-width: 160px;\n\tpadding: 0 8px;\n\tgap: 4px;\n\tborder: 1px solid var(--notectl-border);\n\tborder-radius: 4px;\n\tbackground: var(--notectl-bg);\n}\n\n.notectl-toolbar-btn--heading:hover {\n\tbackground: var(--notectl-hover-bg);\n\tborder-color: var(--notectl-fg-muted);\n}\n\n.notectl-toolbar-btn--heading.notectl-toolbar-btn--active {\n\tbackground: var(--notectl-bg);\n\tborder-color: var(--notectl-primary-muted);\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 4px;\n\twidth: 100%;\n\toverflow: hidden;\n}\n\n.notectl-toolbar-btn--heading .notectl-toolbar-btn__icon svg {\n\tdisplay: none;\n}\n\n.notectl-heading-select__label {\n\tflex: 1;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: var(--notectl-fg);\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\ttext-align: left;\n\tline-height: 30px;\n}\n\n.notectl-heading-select__arrow {\n\tflex-shrink: 0;\n\tfont-size: 11px;\n\tcolor: var(--notectl-fg-muted);\n\tline-height: 30px;\n}\n\n/* Heading Picker Popup */\n.notectl-heading-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-heading-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-heading-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: var(--notectl-fg);\n\ttext-align: left;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n.notectl-heading-picker__item:hover {\n\tbackground: var(--notectl-hover-bg);\n}\n\n.notectl-heading-picker__item--active {\n\tbackground: var(--notectl-active-bg);\n\tcolor: var(--notectl-primary-fg);\n}\n\n.notectl-heading-picker__item--active:hover {\n\tbackground: var(--notectl-active-bg);\n}\n\n.notectl-heading-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--notectl-primary-fg);\n}\n\n.notectl-heading-picker__label {\n\tflex: 1;\n}\n`;\n","/**\n * HeadingPlugin: registers Title, Subtitle, and H1–H6 heading block types\n * with NodeSpec, toggle commands, keyboard shortcuts, input rules, and a\n * combobox-style toolbar dropdown that reflects the current block type.\n */\n\nimport { HEADING_SELECT_CSS } from '../../editor/styles/heading-select.js';\nimport type { BlockNode, Mark } from '../../model/Document.js';\nimport {\n\tgenerateBlockId,\n\tgetBlockLength,\n\tgetBlockText,\n\tgetInlineChildren,\n\tisTextNode,\n} from '../../model/Document.js';\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { createCollapsedSelection, isCollapsed, isNodeSelection } from '../../model/Selection.js';\nimport { type NodeTypeName, nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction, TransactionBuilder } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport type { BlockAlignment } from '../alignment/AlignmentPlugin.js';\nimport { ToolbarServiceKey } from '../toolbar/ToolbarPlugin.js';\nimport type { PickerEntryStyle } from './BlockTypePickerEntry.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\theading: { level: HeadingLevel; align?: BlockAlignment };\n\t\ttitle: { align?: BlockAlignment };\n\t\tsubtitle: { align?: BlockAlignment };\n\t}\n}\n\n// --- Configuration ---\n\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport interface HeadingConfig {\n\t/** Which heading levels to enable. Defaults to [1, 2, 3, 4, 5, 6]. */\n\treadonly levels: readonly HeadingLevel[];\n\t/** When true, a separator is rendered after the heading toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: HeadingConfig = {\n\tlevels: [1, 2, 3, 4, 5, 6],\n};\n\n// --- Heading Tag Mapping ---\n\nconst HEADING_TAGS: Record<HeadingLevel, string> = {\n\t1: 'h1',\n\t2: 'h2',\n\t3: 'h3',\n\t4: 'h4',\n\t5: 'h5',\n\t6: 'h6',\n};\n\n// --- Display Labels ---\n\nconst HEADING_LABELS: Record<HeadingLevel, string> = {\n\t1: 'Heading 1',\n\t2: 'Heading 2',\n\t3: 'Heading 3',\n\t4: 'Heading 4',\n\t5: 'Heading 5',\n\t6: 'Heading 6',\n};\n\nconst TITLE_LABEL = 'Title';\nconst SUBTITLE_LABEL = 'Subtitle';\nconst PARAGRAPH_LABEL = 'Paragraph';\n\n// --- Plugin ---\n\nexport class HeadingPlugin implements Plugin {\n\treadonly id = 'heading';\n\treadonly name = 'Heading';\n\treadonly priority = 30;\n\n\tprivate readonly config: HeadingConfig;\n\tprivate context: PluginContext | null = null;\n\tprivate comboLabel: HTMLSpanElement | null = null;\n\n\tconstructor(config?: Partial<HeadingConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tcontext.registerStyleSheet(HEADING_SELECT_CSS);\n\t\tthis.context = context;\n\t\tthis.registerNodeSpecs(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInputRules(context);\n\t\tthis.registerPickerEntries(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tdestroy(): void {\n\t\tthis.context = null;\n\t\tthis.comboLabel = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\tthis.updateComboLabel(newState);\n\t}\n\n\tprivate registerNodeSpecs(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'title',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\texcludeMarks: ['fontSize'],\n\t\t\ttoDOM(node) {\n\t\t\t\tconst el = createBlockElement('h1', node.id);\n\t\t\t\tel.classList.add('notectl-title');\n\t\t\t\treturn el;\n\t\t\t},\n\t\t\ttoHTML(_node, content) {\n\t\t\t\treturn `<h1>${content || '<br>'}</h1>`;\n\t\t\t},\n\t\t\tsanitize: { tags: ['h1'] },\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'subtitle',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\texcludeMarks: ['fontSize'],\n\t\t\ttoDOM(node) {\n\t\t\t\tconst el = createBlockElement('h2', node.id);\n\t\t\t\tel.classList.add('notectl-subtitle');\n\t\t\t\treturn el;\n\t\t\t},\n\t\t\ttoHTML(_node, content) {\n\t\t\t\treturn `<h2>${content || '<br>'}</h2>`;\n\t\t\t},\n\t\t\tsanitize: { tags: ['h2'] },\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'heading',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\texcludeMarks: ['fontSize'],\n\t\t\tattrs: {\n\t\t\t\tlevel: { default: 1 },\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\tconst level = node.attrs?.level ?? 1;\n\t\t\t\tconst tag = HEADING_TAGS[level] ?? 'h1';\n\t\t\t\treturn createBlockElement(tag, node.id);\n\t\t\t},\n\t\t\ttoHTML(node, content) {\n\t\t\t\tconst level = (node.attrs?.level ?? 1) as HeadingLevel;\n\t\t\t\tconst tag: string = HEADING_TAGS[level] ?? 'h1';\n\t\t\t\treturn `<${tag}>${content || '<br>'}</${tag}>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{ tag: 'h1', getAttrs: () => ({ level: 1 }) },\n\t\t\t\t{ tag: 'h2', getAttrs: () => ({ level: 2 }) },\n\t\t\t\t{ tag: 'h3', getAttrs: () => ({ level: 3 }) },\n\t\t\t\t{ tag: 'h4', getAttrs: () => ({ level: 4 }) },\n\t\t\t\t{ tag: 'h5', getAttrs: () => ({ level: 5 }) },\n\t\t\t\t{ tag: 'h6', getAttrs: () => ({ level: 6 }) },\n\t\t\t],\n\t\t\tsanitize: { tags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\t// Title / Subtitle\n\t\tcontext.registerCommand('setTitle', () => {\n\t\t\treturn this.toggleSpecialBlock(context, 'title');\n\t\t});\n\n\t\tcontext.registerCommand('setSubtitle', () => {\n\t\t\treturn this.toggleSpecialBlock(context, 'subtitle');\n\t\t});\n\n\t\t// Heading levels\n\t\tfor (const level of this.config.levels) {\n\t\t\tcontext.registerCommand(`setHeading${level}`, () => {\n\t\t\t\treturn this.toggleHeading(context, level);\n\t\t\t});\n\t\t}\n\n\t\t// Generic command that toggles back to paragraph\n\t\tcontext.registerCommand('toggleHeading', () => {\n\t\t\treturn this.toggleHeading(context, 1);\n\t\t});\n\n\t\t// Set paragraph (reset heading)\n\t\tcontext.registerCommand('setParagraph', () => {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t});\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tconst keymap: Record<string, () => boolean> = {\n\t\t\tEnter: () => this.handleEnter(context),\n\t\t};\n\n\t\tfor (const level of this.config.levels) {\n\t\t\tif (level <= 6) {\n\t\t\t\tkeymap[`Mod-Shift-${level}`] = () => context.executeCommand(`setHeading${level}`);\n\t\t\t}\n\t\t}\n\n\t\tcontext.registerKeymap(keymap);\n\t}\n\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tfor (const level of this.config.levels) {\n\t\t\tconst hashes = '#'.repeat(level);\n\t\t\tconst pattern = new RegExp(`^${hashes} $`);\n\n\t\t\tcontext.registerInputRule({\n\t\t\t\tpattern,\n\t\t\t\thandler(state, _match, start, _end) {\n\t\t\t\t\tconst sel = state.selection;\n\t\t\t\t\tif (isNodeSelection(sel)) return null;\n\t\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\t\treturn state\n\t\t\t\t\t\t.transaction('input')\n\t\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, start, start + level + 1)\n\t\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('heading'), { level })\n\t\t\t\t\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, 0))\n\t\t\t\t\t\t.build();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerPickerEntries(context: PluginContext): void {\n\t\tcontext.registerBlockTypePickerEntry({\n\t\t\tid: 'paragraph',\n\t\t\tlabel: PARAGRAPH_LABEL,\n\t\t\tcommand: 'setParagraph',\n\t\t\tpriority: 10,\n\t\t\tisActive: (state) => {\n\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\treturn block?.type === 'paragraph';\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerBlockTypePickerEntry({\n\t\t\tid: 'title',\n\t\t\tlabel: TITLE_LABEL,\n\t\t\tcommand: 'setTitle',\n\t\t\tpriority: 20,\n\t\t\tstyle: { fontSize: '1.6em', fontWeight: '700' },\n\t\t\tisActive: (state) => {\n\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\treturn block?.type === 'title';\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerBlockTypePickerEntry({\n\t\t\tid: 'subtitle',\n\t\t\tlabel: SUBTITLE_LABEL,\n\t\t\tcommand: 'setSubtitle',\n\t\t\tpriority: 30,\n\t\t\tstyle: { fontSize: '1.3em', fontWeight: '500' },\n\t\t\tisActive: (state) => {\n\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\treturn block?.type === 'subtitle';\n\t\t\t},\n\t\t});\n\n\t\tfor (const level of this.config.levels) {\n\t\t\tcontext.registerBlockTypePickerEntry({\n\t\t\t\tid: `heading-${level}`,\n\t\t\t\tlabel: HEADING_LABELS[level],\n\t\t\t\tcommand: `setHeading${level}`,\n\t\t\t\tpriority: 100 + level,\n\t\t\t\tstyle: { fontSize: `${1.4 - level * 0.1}em`, fontWeight: '600' },\n\t\t\t\tisActive: (state) => {\n\t\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\t\t\t\treturn block?.type === 'heading' && block.attrs?.level === level;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon: string = `<span class=\"notectl-heading-select__label\" data-heading-label>${PARAGRAPH_LABEL}</span><span class=\"notectl-heading-select__arrow\">\\u25BE</span>`;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'heading',\n\t\t\tgroup: 'block',\n\t\t\ticon,\n\t\t\tlabel: 'Block Type',\n\t\t\ttooltip: 'Block Type',\n\t\t\tcommand: 'setParagraph',\n\t\t\tpriority: 50,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderHeadingPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => {\n\t\t\t\tconst entries = context.getSchemaRegistry().getBlockTypePickerEntries();\n\t\t\t\treturn entries.some((entry) => entry.id !== 'paragraph' && entry.isActive(state));\n\t\t\t},\n\t\t});\n\t}\n\n\t// --- Combo Label ---\n\n\tprivate updateComboLabel(state: EditorState): void {\n\t\tif (!this.comboLabel) {\n\t\t\tconst container: HTMLElement | undefined = this.context?.getPluginContainer('top');\n\t\t\tif (!container) return;\n\t\t\tthis.comboLabel = container.querySelector<HTMLSpanElement>('[data-heading-label]') ?? null;\n\t\t\tif (!this.comboLabel) return;\n\t\t}\n\n\t\tthis.comboLabel.textContent = this.getActiveLabel(state);\n\t}\n\n\tprivate getActiveLabel(state: EditorState): string {\n\t\tif (isNodeSelection(state.selection)) return PARAGRAPH_LABEL;\n\t\tconst entries = this.context?.getSchemaRegistry().getBlockTypePickerEntries() ?? [];\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.isActive(state)) return entry.label;\n\t\t}\n\t\treturn PARAGRAPH_LABEL;\n\t}\n\n\t// --- Custom Popup ---\n\n\tprivate dismissPopup(): void {\n\t\tconst toolbar = this.context?.getService(ToolbarServiceKey);\n\t\ttoolbar?.closePopup();\n\t}\n\n\tprivate renderHeadingPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-heading-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tif (isNodeSelection(state.selection)) return;\n\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-heading-picker__list';\n\t\tlist.setAttribute('role', 'listbox');\n\t\tlist.setAttribute('aria-label', 'Block types');\n\n\t\tconst entries = context.getSchemaRegistry().getBlockTypePickerEntries();\n\t\tfor (const entry of entries) {\n\t\t\tconst active: boolean = entry.isActive(state);\n\t\t\tlist.appendChild(\n\t\t\t\tthis.createPickerItem(\n\t\t\t\t\tentry.label,\n\t\t\t\t\tactive,\n\t\t\t\t\t(e: MouseEvent) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\tcontext.executeCommand(entry.command);\n\t\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t\t},\n\t\t\t\t\tentry.style,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\t}\n\n\tprivate createPickerItem(\n\t\tlabel: string,\n\t\tisActive: boolean,\n\t\thandler: (e: MouseEvent) => void,\n\t\tstyle?: PickerEntryStyle,\n\t): HTMLButtonElement {\n\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\titem.type = 'button';\n\t\titem.className = 'notectl-heading-picker__item';\n\t\titem.setAttribute('role', 'option');\n\t\titem.setAttribute('aria-selected', String(isActive));\n\n\t\tif (isActive) {\n\t\t\titem.classList.add('notectl-heading-picker__item--active');\n\t\t}\n\n\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\tcheck.className = 'notectl-heading-picker__check';\n\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\titem.appendChild(check);\n\n\t\tconst labelSpan: HTMLSpanElement = document.createElement('span');\n\t\tlabelSpan.className = 'notectl-heading-picker__label';\n\t\tlabelSpan.textContent = label;\n\t\tif (style) {\n\t\t\tlabelSpan.style.fontSize = style.fontSize;\n\t\t\tlabelSpan.style.fontWeight = style.fontWeight;\n\t\t}\n\t\titem.appendChild(labelSpan);\n\n\t\titem.addEventListener('mousedown', handler);\n\t\treturn item;\n\t}\n\n\t// --- Enter Handling ---\n\n\tprivate static readonly HEADING_TYPES: ReadonlySet<string> = new Set([\n\t\t'heading',\n\t\t'title',\n\t\t'subtitle',\n\t]);\n\n\t/**\n\t * Handles Enter inside a heading block.\n\t * Empty heading → convert to paragraph.\n\t * Cursor at end → split and convert new block to paragraph.\n\t * Cursor in middle → normal split (both stay heading).\n\t */\n\tprivate handleEnter(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return false;\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block || !HeadingPlugin.HEADING_TYPES.has(block.type)) return false;\n\n\t\tconst text: string = getBlockText(block);\n\n\t\tif (text === '') {\n\t\t\t// Empty heading → convert to paragraph\n\t\t\tconst tr = state\n\t\t\t\t.transaction('input')\n\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst blockLength: number = getBlockLength(block);\n\n\t\tif (sel.anchor.offset >= blockLength) {\n\t\t\t// Cursor at end → split and convert new block to paragraph\n\t\t\tconst newBlockId = generateBlockId();\n\t\t\tconst tr = state\n\t\t\t\t.transaction('input')\n\t\t\t\t.splitBlock(sel.anchor.blockId, sel.anchor.offset, newBlockId)\n\t\t\t\t.setBlockType(newBlockId, nodeType('paragraph'))\n\t\t\t\t.setSelection(createCollapsedSelection(newBlockId, 0))\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Cursor in middle → default split (both parts stay heading)\n\t\treturn false;\n\t}\n\n\t/**\n\t * Toggles between a special block type (title/subtitle) and paragraph.\n\t * If the block is already that type, resets to paragraph.\n\t */\n\tprivate toggleSpecialBlock(context: PluginContext, type: string): boolean {\n\t\tconst state = context.getState();\n\t\tif (isNodeSelection(state.selection)) return false;\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tif (block.type === type) {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t}\n\n\t\treturn this.setBlockType(context, nodeType(type) as NodeTypeName);\n\t}\n\n\t/**\n\t * Toggles between heading (at given level) and paragraph.\n\t * If the block is already a heading at the same level, resets to paragraph.\n\t */\n\tprivate toggleHeading(context: PluginContext, level: HeadingLevel): boolean {\n\t\tconst state = context.getState();\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return false;\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tif (block.type === 'heading' && block.attrs?.level === level) {\n\t\t\treturn this.setBlockType(context, nodeType('paragraph'));\n\t\t}\n\n\t\treturn this.setBlockType(context, nodeType('heading'), { level });\n\t}\n\n\tprivate setBlockType(\n\t\tcontext: PluginContext,\n\t\ttype: NodeTypeName,\n\t\tattrs?: Record<string, string | number | boolean>,\n\t): boolean {\n\t\tconst state: EditorState = context.getState();\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return false;\n\n\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst builder = state.transaction('command');\n\n\t\tconst spec = context.getSchemaRegistry().getNodeSpec(type);\n\t\tif (spec?.excludeMarks && spec.excludeMarks.length > 0) {\n\t\t\tthis.stripExcludedMarks(builder, block, spec.excludeMarks);\n\t\t\tthis.clearExcludedStoredMarks(builder, state, spec.excludeMarks);\n\t\t}\n\n\t\tconst tr = builder.setBlockType(sel.anchor.blockId, type, attrs).setSelection(sel).build();\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Adds removeMark steps for each excluded mark type found\n\t * on the block's inline text content.\n\t */\n\tprivate stripExcludedMarks(\n\t\tbuilder: TransactionBuilder,\n\t\tblock: BlockNode,\n\t\texcludeMarks: readonly string[],\n\t): void {\n\t\tconst blockLength: number = getBlockLength(block);\n\t\tif (blockLength === 0) return;\n\n\t\tconst excludeSet: Set<string> = new Set(excludeMarks);\n\t\tconst inlineChildren = getInlineChildren(block);\n\t\tlet offset = 0;\n\n\t\tfor (const child of inlineChildren) {\n\t\t\tif (isTextNode(child)) {\n\t\t\t\tif (child.text.length > 0) {\n\t\t\t\t\tfor (const mark of child.marks) {\n\t\t\t\t\t\tif (excludeSet.has(mark.type)) {\n\t\t\t\t\t\t\tbuilder.removeMark(block.id, offset, offset + child.text.length, mark);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\toffset += child.text.length;\n\t\t\t} else {\n\t\t\t\toffset += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clears excluded mark types from stored marks so that\n\t * subsequent typing does not reintroduce them.\n\t */\n\tprivate clearExcludedStoredMarks(\n\t\tbuilder: TransactionBuilder,\n\t\tstate: EditorState,\n\t\texcludeMarks: readonly string[],\n\t): void {\n\t\tif (!state.storedMarks) return;\n\n\t\tconst excludeSet: Set<string> = new Set(excludeMarks);\n\t\tconst filtered: readonly Mark[] = state.storedMarks.filter(\n\t\t\t(m: Mark) => !excludeSet.has(m.type),\n\t\t);\n\n\t\tif (filtered.length !== state.storedMarks.length) {\n\t\t\tbuilder.setStoredMarks(filtered.length > 0 ? filtered : null, state.storedMarks);\n\t\t}\n\t}\n}\n"],"names":["DEFAULT_CONFIG","levels","HEADING_TAGS","HEADING_LABELS","PARAGRAPH_LABEL","HeadingPlugin","id","name","priority","config","context","comboLabel","this","registerStyleSheet","registerNodeSpecs","registerCommands","registerKeymaps","registerInputRules","registerPickerEntries","registerToolbarItem","_oldState","newState","_tr","updateComboLabel","registerNodeSpec","type","group","content","allow","excludeMarks","node","el","createBlockElement","classList","add","toHTML","_node","sanitize","tags","attrs","level","default","tag","parseHTML","getAttrs","registerCommand","toggleSpecialBlock","toggleHeading","setBlockType","nodeType","keymap","Enter","handleEnter","executeCommand","registerKeymap","hashes","repeat","pattern","RegExp","registerInputRule","state","_match","start","_end","sel","selection","isNodeSelection","isCollapsed","block","getBlock","anchor","blockId","transaction","deleteTextAt","setSelection","createCollapsedSelection","build","registerBlockTypePickerEntry","label","command","isActive","style","fontSize","fontWeight","icon","tooltip","popupType","separatorAfter","renderPopup","container","ctx","renderHeadingPopup","getSchemaRegistry","getBlockTypePickerEntries","some","entry","getPluginContainer","querySelector","textContent","getActiveLabel","entries","dismissPopup","toolbar","getService","ToolbarServiceKey","closePopup","getState","list","document","createElement","className","setAttribute","active","appendChild","createPickerItem","e","preventDefault","stopPropagation","handler","item","String","check","labelSpan","addEventListener","static","Set","HEADING_TYPES","has","getBlockText","tr","dispatch","blockLength","getBlockLength","offset","newBlockId","generateBlockId","splitBlock","builder","spec","getNodeSpec","length","stripExcludedMarks","clearExcludedStoredMarks","excludeSet","inlineChildren","getInlineChildren","child","isTextNode","text","mark","marks","removeMark","storedMarks","filtered","filter","m","setStoredMarks"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Plugin, PluginContext } from '../Plugin.js';
|
|
2
|
+
declare module '../../model/AttrRegistry.js' {
|
|
3
|
+
interface MarkAttrRegistry {
|
|
4
|
+
highlight: {
|
|
5
|
+
color: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export interface HighlightConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Restricts the color picker to a specific set of hex colors.
|
|
12
|
+
* Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).
|
|
13
|
+
* Duplicates are removed automatically (case-insensitive).
|
|
14
|
+
* When omitted, the full default palette is shown.
|
|
15
|
+
*/
|
|
16
|
+
readonly colors?: readonly string[];
|
|
17
|
+
/** When true, a separator is rendered after the highlight toolbar item. */
|
|
18
|
+
readonly separatorAfter?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class HighlightPlugin implements Plugin {
|
|
21
|
+
readonly id = "highlight";
|
|
22
|
+
readonly name = "Highlight";
|
|
23
|
+
readonly priority = 24;
|
|
24
|
+
private readonly config;
|
|
25
|
+
private readonly colors;
|
|
26
|
+
constructor(config?: Partial<HighlightConfig>);
|
|
27
|
+
init(context: PluginContext): void;
|
|
28
|
+
private registerMarkSpec;
|
|
29
|
+
private registerCommands;
|
|
30
|
+
private registerToolbarItem;
|
|
31
|
+
private isHighlightActive;
|
|
32
|
+
private getActiveColor;
|
|
33
|
+
private applyHighlight;
|
|
34
|
+
private removeHighlight;
|
|
35
|
+
private renderHighlightPopup;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=HighlightPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HighlightPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/highlight/HighlightPlugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,QAAQ,6BAA6B,CAAC;IAC5C,UAAU,gBAAgB;QACzB,SAAS,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7B;CACD;AAID,MAAM,WAAW,eAAe;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CAClC;AA0GD,qBAAa,eAAgB,YAAW,MAAM;IAC7C,QAAQ,CAAC,EAAE,eAAe;IAC1B,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;gBAE/B,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAK7C,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAOlC,OAAO,CAAC,gBAAgB;IA+BxB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,eAAe;IAmCvB,OAAO,CAAC,oBAAoB;CA6C5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/highlight/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { t } from "../chunks/Commands-DLP85Mp5.mjs";
|
|
2
|
+
import { C as e } from "../chunks/color-picker-Csf0wx5a.mjs";
|
|
3
|
+
import { b as o } from "../chunks/AttrRegistry-DTsHyDVA.mjs";
|
|
4
|
+
import { e as r, h as i } from "../chunks/Document-CI3iCwEP.mjs";
|
|
5
|
+
import { i as s, a as n, s as c } from "../chunks/Selection-D5ZjXoB7.mjs";
|
|
6
|
+
import { m as a } from "../chunks/TypeBrands-C09nE2qO.mjs";
|
|
7
|
+
const l = {}, h = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
8
|
+
const f = ["#fff176", "#aed581", "#4dd0e1", "#64b5f6", "#ce93d8", "#f48fb1", "#ffab91", "#ff8a65", "#e6ee9c", "#80cbc4", "#fff9c4", "#dcedc8", "#e0f7fa", "#e3f2fd", "#f3e5f5", "#fce4ec", "#fff3e0", "#fbe9e7", "#f9fbe7", "#e0f2f1", "#fff59d", "#c5e1a5", "#80deea", "#90caf9", "#e1bee7", "#f8bbd0", "#ffcc80", "#ffab91", "#e6ee9c", "#a5d6a7", "#ffee58", "#9ccc65", "#26c6da", "#42a5f5", "#ab47bc", "#ec407a", "#ffa726", "#ff7043", "#d4e157", "#66bb6a", "#ffffff", "#fafafa", "#f5f5f5", "#eeeeee", "#e0e0e0", "#bdbdbd", "#e8eaf6", "#efebe9", "#eceff1", "#fafafa"];
|
|
9
|
+
class g {
|
|
10
|
+
id = "highlight";
|
|
11
|
+
name = "Highlight";
|
|
12
|
+
priority = 24;
|
|
13
|
+
config;
|
|
14
|
+
colors;
|
|
15
|
+
constructor(t2) {
|
|
16
|
+
this.config = { ...l, ...t2 }, this.colors = (function(t3) {
|
|
17
|
+
if (!t3 || 0 === t3.length) return f;
|
|
18
|
+
const e2 = t3.filter((t4) => {
|
|
19
|
+
return e3 = t4, !h.test(e3);
|
|
20
|
+
var e3;
|
|
21
|
+
});
|
|
22
|
+
if (e2.length > 0) throw new Error(`HighlightPlugin: invalid hex color(s): ${e2.join(", ")}. Expected format: #RGB or #RRGGBB.`);
|
|
23
|
+
const o2 = /* @__PURE__ */ new Set(), r2 = [];
|
|
24
|
+
for (const e3 of t3) {
|
|
25
|
+
const t4 = e3.toLowerCase();
|
|
26
|
+
o2.has(t4) || (o2.add(t4), r2.push(t4));
|
|
27
|
+
}
|
|
28
|
+
return r2;
|
|
29
|
+
})(t2?.colors);
|
|
30
|
+
}
|
|
31
|
+
init(t2) {
|
|
32
|
+
t2.registerStyleSheet(e), this.registerMarkSpec(t2), this.registerCommands(t2), this.registerToolbarItem(t2);
|
|
33
|
+
}
|
|
34
|
+
registerMarkSpec(t2) {
|
|
35
|
+
t2.registerMarkSpec({ type: "highlight", rank: 4, attrs: { color: { default: "" } }, toDOM(t3) {
|
|
36
|
+
const e2 = document.createElement("span"), o2 = t3.attrs?.color ?? "";
|
|
37
|
+
return e2.style.backgroundColor = o2, e2;
|
|
38
|
+
}, toHTMLString: (t3, e2) => `<span style="background-color: ${String(t3.attrs?.color ?? "")}">${e2}</span>`, parseHTML: [{ tag: "span", getAttrs: (t3) => {
|
|
39
|
+
const e2 = t3.style.backgroundColor;
|
|
40
|
+
return !!e2 && { color: e2 };
|
|
41
|
+
} }], sanitize: { tags: ["span"] } });
|
|
42
|
+
}
|
|
43
|
+
registerCommands(t2) {
|
|
44
|
+
t2.registerCommand("removeHighlight", () => {
|
|
45
|
+
const e2 = t2.getState();
|
|
46
|
+
return this.removeHighlight(t2, e2);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
registerToolbarItem(t2) {
|
|
50
|
+
const e2 = ['<svg xmlns="http://www.w3.org/2000/svg"', ' viewBox="0 0 24 24">', '<path d="M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2zm-1.38 9L12 5.67 14.38 12H9.62z"/>', '<rect x="3" y="17" width="18" height="6"', ' rx="0.5" fill="#fff176"/>', "</svg>"].join("");
|
|
51
|
+
t2.registerToolbarItem({ id: "highlight", group: "format", icon: e2, label: "Highlight", tooltip: "Highlight Color", command: "removeHighlight", priority: 46, popupType: "custom", separatorAfter: this.config.separatorAfter, renderPopup: (t3, e3) => {
|
|
52
|
+
this.renderHighlightPopup(t3, e3);
|
|
53
|
+
}, isActive: (t3) => this.isHighlightActive(t3) });
|
|
54
|
+
}
|
|
55
|
+
isHighlightActive(t2) {
|
|
56
|
+
return null !== this.getActiveColor(t2);
|
|
57
|
+
}
|
|
58
|
+
getActiveColor(t2) {
|
|
59
|
+
const e2 = t2.selection;
|
|
60
|
+
if (s(e2)) return null;
|
|
61
|
+
if (n(e2)) {
|
|
62
|
+
if (t2.storedMarks) {
|
|
63
|
+
const e3 = t2.storedMarks.find((t3) => "highlight" === t3.type);
|
|
64
|
+
return e3 && o(e3, "highlight") ? e3.attrs.color ?? null : null;
|
|
65
|
+
}
|
|
66
|
+
const i3 = t2.getBlock(e2.anchor.blockId);
|
|
67
|
+
if (!i3) return null;
|
|
68
|
+
const s2 = r(i3, e2.anchor.offset).find((t3) => "highlight" === t3.type);
|
|
69
|
+
return s2 && o(s2, "highlight") ? s2.attrs.color ?? null : null;
|
|
70
|
+
}
|
|
71
|
+
const i2 = t2.getBlock(e2.anchor.blockId);
|
|
72
|
+
if (!i2) return null;
|
|
73
|
+
const c2 = r(i2, e2.anchor.offset).find((t3) => "highlight" === t3.type);
|
|
74
|
+
return c2 && o(c2, "highlight") ? c2.attrs.color ?? null : null;
|
|
75
|
+
}
|
|
76
|
+
applyHighlight(e2, o2, i2) {
|
|
77
|
+
const l2 = o2.selection;
|
|
78
|
+
if (s(l2)) return false;
|
|
79
|
+
if (n(l2)) {
|
|
80
|
+
const t2 = o2.getBlock(l2.anchor.blockId);
|
|
81
|
+
if (!t2) return false;
|
|
82
|
+
const s2 = [...(o2.storedMarks ?? r(t2, l2.anchor.offset)).filter((t3) => "highlight" !== t3.type), { type: a("highlight"), attrs: { color: i2 } }], n2 = o2.transaction("command").setStoredMarks(s2, o2.storedMarks).setSelection(l2).build();
|
|
83
|
+
return e2.dispatch(n2), true;
|
|
84
|
+
}
|
|
85
|
+
const h2 = c(l2, o2.getBlockOrder()), f2 = o2.transaction("command"), g2 = { type: a("highlight"), attrs: { color: i2 } };
|
|
86
|
+
return t(o2, h2, (t2, e3, o3) => {
|
|
87
|
+
f2.removeMark(t2, e3, o3, { type: a("highlight") }), f2.addMark(t2, e3, o3, g2);
|
|
88
|
+
}), f2.setSelection(l2), e2.dispatch(f2.build()), true;
|
|
89
|
+
}
|
|
90
|
+
removeHighlight(e2, o2) {
|
|
91
|
+
const l2 = o2.selection;
|
|
92
|
+
if (s(l2)) return false;
|
|
93
|
+
if (n(l2)) {
|
|
94
|
+
const t2 = o2.getBlock(l2.anchor.blockId);
|
|
95
|
+
if (!t2) return false;
|
|
96
|
+
const s2 = o2.storedMarks ?? r(t2, l2.anchor.offset);
|
|
97
|
+
if (!i(s2, a("highlight"))) return false;
|
|
98
|
+
const n2 = s2.filter((t3) => "highlight" !== t3.type), c2 = o2.transaction("command").setStoredMarks(n2, o2.storedMarks).setSelection(l2).build();
|
|
99
|
+
return e2.dispatch(c2), true;
|
|
100
|
+
}
|
|
101
|
+
const h2 = c(l2, o2.getBlockOrder()), f2 = o2.transaction("command");
|
|
102
|
+
return t(o2, h2, (t2, e3, o3) => {
|
|
103
|
+
f2.removeMark(t2, e3, o3, { type: a("highlight") });
|
|
104
|
+
}), f2.setSelection(l2), e2.dispatch(f2.build()), true;
|
|
105
|
+
}
|
|
106
|
+
renderHighlightPopup(t2, e2) {
|
|
107
|
+
t2.classList.add("notectl-color-picker");
|
|
108
|
+
const o2 = e2.getState(), r2 = this.getActiveColor(o2), i2 = document.createElement("button");
|
|
109
|
+
i2.type = "button", i2.className = "notectl-color-picker__default", i2.textContent = "None", i2.addEventListener("mousedown", (t3) => {
|
|
110
|
+
t3.preventDefault(), t3.stopPropagation(), e2.executeCommand("removeHighlight");
|
|
111
|
+
}), t2.appendChild(i2);
|
|
112
|
+
const s2 = document.createElement("div");
|
|
113
|
+
s2.className = "notectl-color-picker__grid";
|
|
114
|
+
for (const t3 of this.colors) {
|
|
115
|
+
const o3 = document.createElement("button");
|
|
116
|
+
o3.type = "button", o3.className = "notectl-color-picker__swatch", r2 && r2.toLowerCase() === t3.toLowerCase() && o3.classList.add("notectl-color-picker__swatch--active"), o3.style.backgroundColor = t3, "#ffffff" === t3 && (o3.style.border = "1px solid #d0d0d0"), o3.title = t3, o3.setAttribute("aria-label", `Highlight color ${t3}`), o3.addEventListener("mousedown", (o4) => {
|
|
117
|
+
o4.preventDefault(), o4.stopPropagation(), this.applyHighlight(e2, e2.getState(), t3);
|
|
118
|
+
}), s2.appendChild(o3);
|
|
119
|
+
}
|
|
120
|
+
t2.appendChild(s2);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export {
|
|
124
|
+
g as HighlightPlugin
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=highlight.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.mjs","sources":["../../src/plugins/highlight/HighlightPlugin.ts"],"sourcesContent":["/**\n * HighlightPlugin: registers a highlight (background-color) mark with attrs,\n * toolbar button with a color picker popup, and removeHighlight command.\n */\n\nimport { forEachBlockInRange } from '../../commands/Commands.js';\nimport { COLOR_PICKER_CSS } from '../../editor/styles/color-picker.js';\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, hasMark } from '../../model/Document.js';\nimport { isCollapsed, isNodeSelection, selectionRange } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\thighlight: { color: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface HighlightConfig {\n\t/**\n\t * Restricts the color picker to a specific set of hex colors.\n\t * Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).\n\t * Duplicates are removed automatically (case-insensitive).\n\t * When omitted, the full default palette is shown.\n\t */\n\treadonly colors?: readonly string[];\n\t/** When true, a separator is rendered after the highlight toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: HighlightConfig = {};\n\n// --- Color Validation ---\n\nconst HEX_COLOR_PATTERN: RegExp = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\nfunction isValidHexColor(value: string): boolean {\n\treturn HEX_COLOR_PATTERN.test(value);\n}\n\n/**\n * Validates, deduplicates, and normalizes the user-supplied color list.\n * Returns the default palette when no custom colors are provided.\n *\n * @throws {Error} if any value is not a valid hex color code.\n */\nfunction resolveColors(colors: readonly string[] | undefined): readonly string[] {\n\tif (!colors || colors.length === 0) return HIGHLIGHT_PALETTE;\n\n\tconst invalid: string[] = colors.filter((c) => !isValidHexColor(c));\n\tif (invalid.length > 0) {\n\t\tthrow new Error(\n\t\t\t`HighlightPlugin: invalid hex color(s): ${invalid.join(', ')}. Expected format: #RGB or #RRGGBB.`,\n\t\t);\n\t}\n\n\tconst seen: Set<string> = new Set();\n\tconst unique: string[] = [];\n\tfor (const color of colors) {\n\t\tconst normalized: string = color.toLowerCase();\n\t\tif (!seen.has(normalized)) {\n\t\t\tseen.add(normalized);\n\t\t\tunique.push(normalized);\n\t\t}\n\t}\n\treturn unique;\n}\n\n// --- Color Palette (Highlight-optimized: 10 columns x 5 rows) ---\n\nconst HIGHLIGHT_PALETTE: readonly string[] = [\n\t// Row 1 — Classic highlighter colors (bright, vivid)\n\t'#fff176',\n\t'#aed581',\n\t'#4dd0e1',\n\t'#64b5f6',\n\t'#ce93d8',\n\t'#f48fb1',\n\t'#ffab91',\n\t'#ff8a65',\n\t'#e6ee9c',\n\t'#80cbc4',\n\n\t// Row 2 — Light pastels\n\t'#fff9c4',\n\t'#dcedc8',\n\t'#e0f7fa',\n\t'#e3f2fd',\n\t'#f3e5f5',\n\t'#fce4ec',\n\t'#fff3e0',\n\t'#fbe9e7',\n\t'#f9fbe7',\n\t'#e0f2f1',\n\n\t// Row 3 — Medium pastels\n\t'#fff59d',\n\t'#c5e1a5',\n\t'#80deea',\n\t'#90caf9',\n\t'#e1bee7',\n\t'#f8bbd0',\n\t'#ffcc80',\n\t'#ffab91',\n\t'#e6ee9c',\n\t'#a5d6a7',\n\n\t// Row 4 — Bold pastels\n\t'#ffee58',\n\t'#9ccc65',\n\t'#26c6da',\n\t'#42a5f5',\n\t'#ab47bc',\n\t'#ec407a',\n\t'#ffa726',\n\t'#ff7043',\n\t'#d4e157',\n\t'#66bb6a',\n\n\t// Row 5 — Grays and neutral highlights\n\t'#ffffff',\n\t'#fafafa',\n\t'#f5f5f5',\n\t'#eeeeee',\n\t'#e0e0e0',\n\t'#bdbdbd',\n\t'#e8eaf6',\n\t'#efebe9',\n\t'#eceff1',\n\t'#fafafa',\n];\n\n// --- Plugin ---\n\nexport class HighlightPlugin implements Plugin {\n\treadonly id = 'highlight';\n\treadonly name = 'Highlight';\n\treadonly priority = 24;\n\n\tprivate readonly config: HighlightConfig;\n\tprivate readonly colors: readonly string[];\n\n\tconstructor(config?: Partial<HighlightConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t\tthis.colors = resolveColors(config?.colors);\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tcontext.registerStyleSheet(COLOR_PICKER_CSS);\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'highlight',\n\t\t\trank: 4,\n\t\t\tattrs: {\n\t\t\t\tcolor: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span = document.createElement('span');\n\t\t\t\tconst color = mark.attrs?.color ?? '';\n\t\t\t\tspan.style.backgroundColor = color;\n\t\t\t\treturn span;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst color: string = String(mark.attrs?.color ?? '');\n\t\t\t\treturn `<span style=\"background-color: ${color}\">${content}</span>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'span',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\tconst color: string = el.style.backgroundColor;\n\t\t\t\t\t\tif (!color) return false;\n\t\t\t\t\t\treturn { color };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['span'] },\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeHighlight', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeHighlight(context, state);\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst pathD =\n\t\t\t'M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2z' + 'm-1.38 9L12 5.67 14.38 12H9.62z';\n\t\tconst icon: string = [\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t' viewBox=\"0 0 24 24\">',\n\t\t\t`<path d=\"${pathD}\"/>`,\n\t\t\t'<rect x=\"3\" y=\"17\" width=\"18\" height=\"6\"',\n\t\t\t' rx=\"0.5\" fill=\"#fff176\"/>',\n\t\t\t'</svg>',\n\t\t].join('');\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'highlight',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: 'Highlight',\n\t\t\ttooltip: 'Highlight Color',\n\t\t\tcommand: 'removeHighlight',\n\t\t\tpriority: 46,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderHighlightPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isHighlightActive(state),\n\t\t});\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isHighlightActive(state: EditorState): boolean {\n\t\treturn this.getActiveColor(state) !== null;\n\t}\n\n\tprivate getActiveColor(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return null;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tif (state.storedMarks) {\n\t\t\t\tconst mark = state.storedMarks.find((m) => m.type === 'highlight');\n\t\t\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t\t\t}\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return null;\n\t\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\t\tconst mark = marks.find((m) => m.type === 'highlight');\n\t\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t\t}\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tconst marks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t\tconst mark = marks.find((m) => m.type === 'highlight');\n\t\treturn mark && isMarkOfType(mark, 'highlight') ? (mark.attrs.color ?? null) : null;\n\t}\n\n\t// --- Highlight Application ---\n\n\tprivate applyHighlight(context: PluginContext, state: EditorState, color: string): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return false;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tconst withoutHighlight = currentMarks.filter((m) => m.type !== 'highlight');\n\t\t\tconst newMarks = [...withoutHighlight, { type: markType('highlight'), attrs: { color } }];\n\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst range = selectionRange(sel, state.getBlockOrder());\n\t\tconst builder = state.transaction('command');\n\t\tconst mark = { type: markType('highlight'), attrs: { color } };\n\n\t\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\t\tbuilder.removeMark(blockId, from, to, { type: markType('highlight') });\n\t\t\tbuilder.addMark(blockId, from, to, mark);\n\t\t});\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\tprivate removeHighlight(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel)) return false;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!anchorBlock) return false;\n\t\t\tconst currentMarks =\n\t\t\t\tstate.storedMarks ?? getBlockMarksAtOffset(anchorBlock, sel.anchor.offset);\n\t\t\tif (!hasMark(currentMarks, markType('highlight'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'highlight');\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\n\t\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t\t.setSelection(sel)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst range = selectionRange(sel, state.getBlockOrder());\n\t\tconst builder = state.transaction('command');\n\n\t\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\t\tbuilder.removeMark(blockId, from, to, { type: markType('highlight') });\n\t\t});\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate renderHighlightPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-color-picker');\n\n\t\tconst state = context.getState();\n\t\tconst activeColor = this.getActiveColor(state);\n\n\t\tconst defaultBtn = document.createElement('button');\n\t\tdefaultBtn.type = 'button';\n\t\tdefaultBtn.className = 'notectl-color-picker__default';\n\t\tdefaultBtn.textContent = 'None';\n\t\tdefaultBtn.addEventListener('mousedown', (e) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tcontext.executeCommand('removeHighlight');\n\t\t});\n\t\tcontainer.appendChild(defaultBtn);\n\n\t\tconst grid = document.createElement('div');\n\t\tgrid.className = 'notectl-color-picker__grid';\n\n\t\tfor (const color of this.colors) {\n\t\t\tconst swatch = document.createElement('button');\n\t\t\tswatch.type = 'button';\n\t\t\tswatch.className = 'notectl-color-picker__swatch';\n\t\t\tif (activeColor && activeColor.toLowerCase() === color.toLowerCase()) {\n\t\t\t\tswatch.classList.add('notectl-color-picker__swatch--active');\n\t\t\t}\n\t\t\tswatch.style.backgroundColor = color;\n\t\t\tif (color === '#ffffff') {\n\t\t\t\tswatch.style.border = '1px solid #d0d0d0';\n\t\t\t}\n\t\t\tswatch.title = color;\n\t\t\tswatch.setAttribute('aria-label', `Highlight color ${color}`);\n\n\t\t\tswatch.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tthis.applyHighlight(context, context.getState(), color);\n\t\t\t});\n\n\t\t\tgrid.appendChild(swatch);\n\t\t}\n\n\t\tcontainer.appendChild(grid);\n\t}\n}\n"],"names":["DEFAULT_CONFIG","HEX_COLOR_PATTERN","HIGHLIGHT_PALETTE","HighlightPlugin","id","name","priority","config","colors","this","length","invalid","filter","c","value","test","Error","join","seen","Set","unique","color","normalized","toLowerCase","has","add","push","context","registerStyleSheet","COLOR_PICKER_CSS","registerMarkSpec","registerCommands","registerToolbarItem","type","rank","attrs","default","mark","span","document","createElement","style","backgroundColor","toHTMLString","content","String","parseHTML","tag","getAttrs","el","sanitize","tags","registerCommand","state","getState","removeHighlight","icon","group","label","tooltip","command","popupType","separatorAfter","renderPopup","container","ctx","renderHighlightPopup","isActive","isHighlightActive","getActiveColor","sel","selection","isNodeSelection","isCollapsed","storedMarks","find","m","isMarkOfType","block","getBlock","anchor","blockId","getBlockMarksAtOffset","offset","anchorBlock","newMarks","markType","tr","transaction","setStoredMarks","setSelection","build","dispatch","range","selectionRange","getBlockOrder","builder","forEachBlockInRange","from","to","removeMark","addMark","currentMarks","hasMark","classList","activeColor","defaultBtn","className","textContent","addEventListener","e","preventDefault","stopPropagation","executeCommand","appendChild","grid","swatch","border","title","setAttribute","applyHighlight"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Plugin, PluginContext } from '../Plugin.js';
|
|
2
|
+
declare module '../../model/AttrRegistry.js' {
|
|
3
|
+
interface NodeAttrRegistry {
|
|
4
|
+
horizontal_rule: Record<string, never>;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export interface HorizontalRuleConfig {
|
|
8
|
+
/** When true, a separator is rendered after the toolbar item. */
|
|
9
|
+
readonly separatorAfter?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class HorizontalRulePlugin implements Plugin {
|
|
12
|
+
readonly id = "horizontal-rule";
|
|
13
|
+
readonly name = "Horizontal Rule";
|
|
14
|
+
readonly priority = 40;
|
|
15
|
+
private readonly config;
|
|
16
|
+
constructor(config?: Partial<HorizontalRuleConfig>);
|
|
17
|
+
init(context: PluginContext): void;
|
|
18
|
+
private registerNodeSpec;
|
|
19
|
+
private registerCommands;
|
|
20
|
+
private registerKeymap;
|
|
21
|
+
private registerInputRule;
|
|
22
|
+
private registerToolbarItem;
|
|
23
|
+
/**
|
|
24
|
+
* Inserts a horizontal rule after the current block,
|
|
25
|
+
* followed by a new paragraph for continued editing.
|
|
26
|
+
*/
|
|
27
|
+
private insertHorizontalRule;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=HorizontalRulePlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HorizontalRulePlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/horizontal-rule/HorizontalRulePlugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAK1D,OAAO,QAAQ,6BAA6B,CAAC;IAC5C,UAAU,gBAAgB;QACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;KACvC;CACD;AAID,MAAM,WAAW,oBAAoB;IACpC,iEAAiE;IACjE,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CAClC;AAeD,qBAAa,oBAAqB,YAAW,MAAM;IAClD,QAAQ,CAAC,EAAE,qBAAqB;IAChC,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;gBAElC,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAIlD,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAQlC,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,iBAAiB;IA2BzB,OAAO,CAAC,mBAAmB;IAiB3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAmB5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/horizontal-rule/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,KAAK,oBAAoB,GACzB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { c as e } from "../chunks/Document-CI3iCwEP.mjs";
|
|
2
|
+
import { c as t } from "../chunks/NodeSpec-NZVvcCuH.mjs";
|
|
3
|
+
import { i as r, a as o, c as i } from "../chunks/Selection-D5ZjXoB7.mjs";
|
|
4
|
+
import { n } from "../chunks/TypeBrands-C09nE2qO.mjs";
|
|
5
|
+
import { f as s } from "../chunks/ToolbarItem-ugDymuXi.mjs";
|
|
6
|
+
const a = {};
|
|
7
|
+
function l(e2) {
|
|
8
|
+
const t2 = e2.selection;
|
|
9
|
+
return r(t2) ? -1 : e2.doc.children.findIndex((e3) => e3.id === t2.anchor.blockId);
|
|
10
|
+
}
|
|
11
|
+
class c {
|
|
12
|
+
id = "horizontal-rule";
|
|
13
|
+
name = "Horizontal Rule";
|
|
14
|
+
priority = 40;
|
|
15
|
+
config;
|
|
16
|
+
constructor(e2) {
|
|
17
|
+
this.config = { ...a, ...e2 };
|
|
18
|
+
}
|
|
19
|
+
init(e2) {
|
|
20
|
+
this.registerNodeSpec(e2), this.registerCommands(e2), this.registerKeymap(e2), this.registerInputRule(e2), this.registerToolbarItem(e2);
|
|
21
|
+
}
|
|
22
|
+
registerNodeSpec(e2) {
|
|
23
|
+
e2.registerNodeSpec({ type: "horizontal_rule", group: "block", isVoid: true, toDOM: (e3) => t("hr", e3.id), toHTML: () => "<hr>", parseHTML: [{ tag: "hr" }], sanitize: { tags: ["hr"] } });
|
|
24
|
+
}
|
|
25
|
+
registerCommands(e2) {
|
|
26
|
+
e2.registerCommand("insertHorizontalRule", () => this.insertHorizontalRule(e2));
|
|
27
|
+
}
|
|
28
|
+
registerKeymap(e2) {
|
|
29
|
+
e2.registerKeymap({ "Mod-Shift-H": () => e2.executeCommand("insertHorizontalRule") });
|
|
30
|
+
}
|
|
31
|
+
registerInputRule(t2) {
|
|
32
|
+
t2.registerInputRule({ pattern: /^-{3,} $/, handler(t3, s2, a2, c2) {
|
|
33
|
+
const u = t3.selection;
|
|
34
|
+
if (r(u)) return null;
|
|
35
|
+
if (!o(u)) return null;
|
|
36
|
+
const p = t3.getBlock(u.anchor.blockId);
|
|
37
|
+
if (!p || "paragraph" !== p.type) return null;
|
|
38
|
+
const d = l(t3);
|
|
39
|
+
if (-1 === d) return null;
|
|
40
|
+
const h = e(n("paragraph"));
|
|
41
|
+
return t3.transaction("input").deleteTextAt(u.anchor.blockId, 0, c2).setBlockType(u.anchor.blockId, n("horizontal_rule")).insertNode([], d + 1, h).setSelection(i(h.id, 0)).build();
|
|
42
|
+
} });
|
|
43
|
+
}
|
|
44
|
+
registerToolbarItem(e2) {
|
|
45
|
+
e2.registerToolbarItem({ id: "horizontal-rule", group: "block", icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11h16v2H4z"/></svg>', label: "Horizontal Rule", tooltip: `Horizontal Rule (${s("Mod-Shift-H")})`, command: "insertHorizontalRule", priority: 60, separatorAfter: this.config.separatorAfter, isActive: () => false });
|
|
46
|
+
}
|
|
47
|
+
insertHorizontalRule(t2) {
|
|
48
|
+
const o2 = t2.getState();
|
|
49
|
+
if (r(o2.selection)) return false;
|
|
50
|
+
const s2 = l(o2);
|
|
51
|
+
if (-1 === s2) return false;
|
|
52
|
+
const a2 = e(n("horizontal_rule")), c2 = e(n("paragraph")), u = o2.transaction("command").insertNode([], s2 + 1, a2).insertNode([], s2 + 2, c2).setSelection(i(c2.id, 0)).build();
|
|
53
|
+
return t2.dispatch(u), true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
c as HorizontalRulePlugin
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=horizontal-rule.mjs.map
|