@notectl/core 1.0.8 → 1.0.9
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/dist/chunks/ToolbarPlugin-DFkl1uYO.mjs +818 -0
- package/dist/chunks/ToolbarPlugin-DFkl1uYO.mjs.map +1 -0
- package/dist/chunks/{index-CxiWyUho.mjs → index-BCvuDpVr.mjs} +2 -2
- package/dist/chunks/{index-CxiWyUho.mjs.map → index-BCvuDpVr.mjs.map} +1 -1
- package/dist/chunks/{index-C2GQoHot.mjs → index-BFsYGsBR.mjs} +2 -2
- package/dist/chunks/{index-C2GQoHot.mjs.map → index-BFsYGsBR.mjs.map} +1 -1
- package/dist/chunks/{index-B_3qDrUN.mjs → index-BIL37LSL.mjs} +23 -14
- package/dist/chunks/index-BIL37LSL.mjs.map +1 -0
- package/dist/chunks/{index-Ct0ivLhO.mjs → index-BL56fbXt.mjs} +214 -219
- package/dist/chunks/{index-Ct0ivLhO.mjs.map → index-BL56fbXt.mjs.map} +1 -1
- package/dist/chunks/{index-BYgspns5.mjs → index-BQ8iIYLn.mjs} +2 -2
- package/dist/chunks/{index-BYgspns5.mjs.map → index-BQ8iIYLn.mjs.map} +1 -1
- package/dist/chunks/index-BTJfyJlJ.mjs +187 -0
- package/dist/chunks/index-BTJfyJlJ.mjs.map +1 -0
- package/dist/chunks/{index-D3CQWJiw.mjs → index-DA8TG2S8.mjs} +39 -19
- package/dist/chunks/index-DA8TG2S8.mjs.map +1 -0
- package/dist/chunks/{index-C-YWHOcC.mjs → index-DAFCISBN.mjs} +21 -21
- package/dist/chunks/{index-C-YWHOcC.mjs.map → index-DAFCISBN.mjs.map} +1 -1
- package/dist/chunks/{index-BAk1EG1x.mjs → index-DGrRWMlW.mjs} +2 -2
- package/dist/chunks/{index-BAk1EG1x.mjs.map → index-DGrRWMlW.mjs.map} +1 -1
- package/dist/chunks/{index-CT3HGdQt.mjs → index-DfO_fKw6.mjs} +6 -6
- package/dist/chunks/{index-CT3HGdQt.mjs.map → index-DfO_fKw6.mjs.map} +1 -1
- package/dist/chunks/resolvePluginLocale-B4w1OkPy.mjs.map +1 -1
- package/dist/editor/DocumentSerializer.d.ts.map +1 -1
- package/dist/editor/NotectlEditor.d.ts +27 -5
- package/dist/editor/NotectlEditor.d.ts.map +1 -1
- package/dist/editor/styles/list.d.ts +2 -0
- package/dist/editor/styles/list.d.ts.map +1 -1
- package/dist/editor/styles/toolbar.d.ts +1 -1
- package/dist/editor/styles/toolbar.d.ts.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/input/ClipboardHandler.d.ts +2 -0
- package/dist/input/ClipboardHandler.d.ts.map +1 -1
- package/dist/input/InputHandler.d.ts +2 -0
- package/dist/input/InputHandler.d.ts.map +1 -1
- package/dist/input/KeyboardHandler.d.ts +2 -0
- package/dist/input/KeyboardHandler.d.ts.map +1 -1
- package/dist/input/LegacyHTMLNormalizer.d.ts +18 -0
- package/dist/input/LegacyHTMLNormalizer.d.ts.map +1 -0
- package/dist/input/PasteHandler.d.ts +4 -0
- package/dist/input/PasteHandler.d.ts.map +1 -1
- package/dist/model/HTMLParser.d.ts +13 -0
- package/dist/model/HTMLParser.d.ts.map +1 -1
- package/dist/model/SchemaRegistry.d.ts +2 -2
- package/dist/model/SchemaRegistry.d.ts.map +1 -1
- package/dist/notectl-core.mjs +546 -394
- package/dist/notectl-core.mjs.map +1 -1
- package/dist/notectl-core.umd.js +1772 -1161
- package/dist/notectl-core.umd.js.map +1 -1
- package/dist/plugins/Plugin.d.ts +17 -2
- package/dist/plugins/Plugin.d.ts.map +1 -1
- package/dist/plugins/PluginManager.d.ts +17 -1
- package/dist/plugins/PluginManager.d.ts.map +1 -1
- package/dist/plugins/alignment/AlignmentPlugin.d.ts.map +1 -1
- package/dist/plugins/alignment.mjs +1 -1
- package/dist/plugins/code-block/CodeBlockPlugin.d.ts.map +1 -1
- package/dist/plugins/code-block.mjs +1 -1
- package/dist/plugins/font-size.mjs +1 -1
- package/dist/plugins/font.mjs +1 -1
- package/dist/plugins/heading/HeadingBlockTypePicker.d.ts +14 -0
- package/dist/plugins/heading/HeadingBlockTypePicker.d.ts.map +1 -0
- package/dist/plugins/heading/HeadingCommands.d.ts +5 -0
- package/dist/plugins/heading/HeadingCommands.d.ts.map +1 -0
- package/dist/plugins/heading/HeadingInputRules.d.ts +5 -0
- package/dist/plugins/heading/HeadingInputRules.d.ts.map +1 -0
- package/dist/plugins/heading/HeadingKeyboardHandlers.d.ts +5 -0
- package/dist/plugins/heading/HeadingKeyboardHandlers.d.ts.map +1 -0
- package/dist/plugins/heading/HeadingPlugin.d.ts +1 -41
- package/dist/plugins/heading/HeadingPlugin.d.ts.map +1 -1
- package/dist/plugins/heading.mjs +1 -1
- package/dist/plugins/image/ImagePlugin.d.ts.map +1 -1
- package/dist/plugins/image.mjs +1 -1
- package/dist/plugins/list/ListPlugin.d.ts +9 -0
- package/dist/plugins/list/ListPlugin.d.ts.map +1 -1
- package/dist/plugins/list.mjs +1 -1
- package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts.map +1 -1
- package/dist/plugins/strikethrough.mjs +1 -1
- package/dist/plugins/super-sub/SuperSubPlugin.d.ts.map +1 -1
- package/dist/plugins/super-sub.mjs +1 -1
- package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts.map +1 -1
- package/dist/plugins/text-formatting.mjs +1 -1
- package/dist/plugins/toolbar/ToolbarLocale.d.ts +1 -0
- package/dist/plugins/toolbar/ToolbarLocale.d.ts.map +1 -1
- package/dist/plugins/toolbar/ToolbarOverflowBehavior.d.ts +23 -0
- package/dist/plugins/toolbar/ToolbarOverflowBehavior.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarOverflowController.d.ts +56 -0
- package/dist/plugins/toolbar/ToolbarOverflowController.d.ts.map +1 -0
- package/dist/plugins/toolbar/ToolbarPlugin.d.ts +17 -0
- package/dist/plugins/toolbar/ToolbarPlugin.d.ts.map +1 -1
- package/dist/plugins/toolbar.mjs +1 -1
- package/dist/state/ReadonlyGuard.d.ts +6 -0
- package/dist/state/ReadonlyGuard.d.ts.map +1 -0
- package/dist/state/Transaction.d.ts +4 -0
- package/dist/state/Transaction.d.ts.map +1 -1
- package/dist/view/EditorView.d.ts +2 -0
- package/dist/view/EditorView.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/ToolbarPlugin-DY2xaJiu.mjs +0 -368
- package/dist/chunks/ToolbarPlugin-DY2xaJiu.mjs.map +0 -1
- package/dist/chunks/index-B_3qDrUN.mjs.map +0 -1
- package/dist/chunks/index-D3CQWJiw.mjs.map +0 -1
- package/dist/chunks/index-Dh76rR13.mjs +0 -196
- package/dist/chunks/index-Dh76rR13.mjs.map +0 -1
- package/dist/input/SourceNormalizer.d.ts +0 -7
- package/dist/input/SourceNormalizer.d.ts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-B_3qDrUN.mjs","sources":["../../src/plugins/text-formatting/TextFormattingLocale.ts","../../src/plugins/text-formatting/TextFormattingPlugin.ts"],"sourcesContent":["/**\n * Locale interface and default English locale for the TextFormattingPlugin.\n */\n\n// --- Locale Interface ---\n\nexport interface TextFormattingLocale {\n\treadonly boldLabel: string;\n\treadonly italicLabel: string;\n\treadonly underlineLabel: string;\n}\n\n// --- Default English Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_EN: TextFormattingLocale = {\n\tboldLabel: 'Bold',\n\titalicLabel: 'Italic',\n\tunderlineLabel: 'Underline',\n};\n\n// --- German Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_DE: TextFormattingLocale = {\n\tboldLabel: 'Fett',\n\titalicLabel: 'Kursiv',\n\tunderlineLabel: 'Unterstrichen',\n};\n\n// --- Spanish Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_ES: TextFormattingLocale = {\n\tboldLabel: 'Negrita',\n\titalicLabel: 'Cursiva',\n\tunderlineLabel: 'Subrayado',\n};\n\n// --- French Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_FR: TextFormattingLocale = {\n\tboldLabel: 'Gras',\n\titalicLabel: 'Italique',\n\tunderlineLabel: 'Souligné',\n};\n\n// --- Chinese (Simplified) Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_ZH: TextFormattingLocale = {\n\tboldLabel: '粗体',\n\titalicLabel: '斜体',\n\tunderlineLabel: '下划线',\n};\n\n// --- Russian Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_RU: TextFormattingLocale = {\n\tboldLabel: 'Жирный',\n\titalicLabel: 'Курсив',\n\tunderlineLabel: 'Подчёркнутый',\n};\n\n// --- Arabic Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_AR: TextFormattingLocale = {\n\tboldLabel: 'غامق',\n\titalicLabel: 'مائل',\n\tunderlineLabel: 'تحته خط',\n};\n\n// --- Hindi Locale ---\n\nexport const TEXT_FORMATTING_LOCALE_HI: TextFormattingLocale = {\n\tboldLabel: 'बोल्ड',\n\titalicLabel: 'इटैलिक',\n\tunderlineLabel: 'अंडरलाइन',\n};\n\n// --- Locale Map ---\n\nexport const TEXT_FORMATTING_LOCALES: Record<string, TextFormattingLocale> = {\n\ten: TEXT_FORMATTING_LOCALE_EN,\n\tde: TEXT_FORMATTING_LOCALE_DE,\n\tes: TEXT_FORMATTING_LOCALE_ES,\n\tfr: TEXT_FORMATTING_LOCALE_FR,\n\tzh: TEXT_FORMATTING_LOCALE_ZH,\n\tru: TEXT_FORMATTING_LOCALE_RU,\n\tar: TEXT_FORMATTING_LOCALE_AR,\n\thi: TEXT_FORMATTING_LOCALE_HI,\n};\n","/**\n * TextFormattingPlugin: registers inline marks (bold, italic, underline)\n * with their MarkSpecs, toggle commands, keyboard shortcuts, and toolbar items.\n *\n * This plugin is data-driven — each mark type is defined declaratively and\n * all registrations (MarkSpec, command, keymap, toolbar item) are derived\n * from the same definition.\n *\n * Supports two separate config dimensions:\n * - Feature config (bold/italic/underline): controls whether the mark is\n * registered in the schema. When disabled, the keyboard shortcut does nothing.\n * - Toolbar config: controls whether the toolbar button is visible.\n * When a feature is disabled but toolbar is enabled, the button renders as disabled.\n */\n\nimport { isMarkActive, toggleMark } from '../../commands/Commands.js';\nimport { resolvePluginLocale } from '../../i18n/resolvePluginLocale.js';\nimport type { ParseRule } from '../../model/ParseRule.js';\nimport type { SanitizeConfig } from '../../model/SanitizeConfig.js';\nimport { markType as mkType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { formatShortcut } from '../toolbar/ToolbarItem.js';\nimport { TEXT_FORMATTING_LOCALES, type TextFormattingLocale } from './TextFormattingLocale.js';\n\n// --- Configuration ---\n\n/** Controls toolbar button visibility per mark. */\nexport interface TextFormattingToolbarConfig {\n\treadonly bold?: boolean;\n\treadonly italic?: boolean;\n\treadonly underline?: boolean;\n}\n\n/** Controls which inline marks are enabled and which toolbar buttons are shown. */\nexport interface TextFormattingConfig {\n\treadonly bold: boolean;\n\treadonly italic: boolean;\n\treadonly underline: boolean;\n\treadonly toolbar?: TextFormattingToolbarConfig;\n\t/** When true, a separator is rendered after the last text-formatting toolbar item. */\n\treadonly separatorAfter?: boolean;\n\treadonly locale?: TextFormattingLocale;\n}\n\nconst DEFAULT_CONFIG: TextFormattingConfig = {\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n};\n\n// --- Mark Definitions ---\n\ninterface MarkDefinition {\n\treadonly type: string;\n\treadonly configKey: keyof Omit<TextFormattingConfig, 'toolbar' | 'separatorAfter' | 'locale'>;\n\treadonly rank: number;\n\treadonly tag: string;\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly keyBinding: string;\n\treadonly toHTMLString: (content: string) => string;\n\treadonly parseHTML: readonly ParseRule[];\n\treadonly sanitize: SanitizeConfig;\n}\n\nconst BOLD_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z\"/></svg>';\nconst ITALIC_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z\"/></svg>';\nconst UNDERLINE_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z\"/></svg>';\n\nconst MARK_DEFINITIONS: readonly MarkDefinition[] = [\n\t{\n\t\ttype: 'bold',\n\t\tconfigKey: 'bold',\n\t\trank: 0,\n\t\ttag: 'strong',\n\t\tlabel: 'Bold',\n\t\ticon: BOLD_ICON,\n\t\tkeyBinding: 'Mod-B',\n\t\ttoHTMLString: (content) => `<strong>${content}</strong>`,\n\t\tparseHTML: [{ tag: 'strong' }, { tag: 'b' }],\n\t\tsanitize: { tags: ['strong', 'b'] },\n\t},\n\t{\n\t\ttype: 'italic',\n\t\tconfigKey: 'italic',\n\t\trank: 1,\n\t\ttag: 'em',\n\t\tlabel: 'Italic',\n\t\ticon: ITALIC_ICON,\n\t\tkeyBinding: 'Mod-I',\n\t\ttoHTMLString: (content) => `<em>${content}</em>`,\n\t\tparseHTML: [{ tag: 'em' }, { tag: 'i' }],\n\t\tsanitize: { tags: ['em', 'i'] },\n\t},\n\t{\n\t\ttype: 'underline',\n\t\tconfigKey: 'underline',\n\t\trank: 2,\n\t\ttag: 'u',\n\t\tlabel: 'Underline',\n\t\ticon: UNDERLINE_ICON,\n\t\tkeyBinding: 'Mod-U',\n\t\ttoHTMLString: (content) => `<u>${content}</u>`,\n\t\tparseHTML: [{ tag: 'u' }],\n\t\tsanitize: { tags: ['u'] },\n\t},\n];\n\n// --- Plugin ---\n\nexport class TextFormattingPlugin implements Plugin {\n\treadonly id = 'text-formatting';\n\treadonly name = 'Text Formatting';\n\treadonly priority = 20;\n\n\tprivate readonly config: TextFormattingConfig;\n\tprivate locale!: TextFormattingLocale;\n\n\tconstructor(config?: Partial<TextFormattingConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.locale = resolvePluginLocale(TEXT_FORMATTING_LOCALES, context, this.config.locale);\n\n\t\tconst enabledMarks = MARK_DEFINITIONS.filter((def) => this.config[def.configKey]);\n\n\t\t// Determine which marks will have visible toolbar items\n\t\tconst visibleToolbarMarks = enabledMarks.filter((def) => this.isToolbarVisible(def.configKey));\n\t\tconst lastVisibleMark = visibleToolbarMarks.at(-1);\n\n\t\tfor (const def of enabledMarks) {\n\t\t\tconst isSeparatorTarget = this.config.separatorAfter && def === lastVisibleMark;\n\t\t\tthis.registerMark(context, def, isSeparatorTarget);\n\t\t}\n\n\t\tthis.registerKeymaps(context, enabledMarks);\n\n\t\t// Register disabled placeholder buttons for marks that are disabled\n\t\t// as features but explicitly requested in the toolbar config\n\t\tthis.registerDisabledToolbarItems(context);\n\t}\n\n\tprivate registerMark(\n\t\tcontext: PluginContext,\n\t\tdef: MarkDefinition,\n\t\tseparatorAfter?: boolean,\n\t): void {\n\t\tconst commandName = toCommandName(def.type);\n\t\tconst toolbarVisible = this.isToolbarVisible(def.configKey);\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: def.type,\n\t\t\trank: def.rank,\n\t\t\ttoDOM() {\n\t\t\t\treturn document.createElement(def.tag);\n\t\t\t},\n\t\t\ttoHTMLString: (_mark, content) => def.toHTMLString(content),\n\t\t\tparseHTML: def.parseHTML,\n\t\t\tsanitize: def.sanitize,\n\t\t});\n\n\t\tcontext.registerCommand(commandName, () => {\n\t\t\tconst tr = toggleMark(context.getState(), mkType(def.type));\n\t\t\tif (tr) {\n\t\t\t\tcontext.dispatch(tr);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\n\t\tif (toolbarVisible) {\n\t\t\tconst label: string = this.getMarkLabel(def.type);\n\t\t\tcontext.registerToolbarItem({\n\t\t\t\tid: def.type,\n\t\t\t\tgroup: 'format',\n\t\t\t\ticon: def.icon,\n\t\t\t\tlabel,\n\t\t\t\ttooltip: `${label} (${formatShortcut(def.keyBinding)})`,\n\t\t\t\tcommand: commandName,\n\t\t\t\tpriority: def.rank * 10 + 10,\n\t\t\t\tseparatorAfter,\n\t\t\t\tisActive: (state) => isMarkActive(state, mkType(def.type)),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerKeymaps(context: PluginContext, marks: readonly MarkDefinition[]): void {\n\t\tconst keymap: Record<string, () => boolean> = {};\n\t\tfor (const def of marks) {\n\t\t\tconst commandName = toCommandName(def.type);\n\t\t\tkeymap[def.keyBinding] = () => context.executeCommand(commandName);\n\t\t}\n\t\tif (Object.keys(keymap).length > 0) {\n\t\t\tcontext.registerKeymap(keymap);\n\t\t}\n\t}\n\n\t/**\n\t * Registers disabled toolbar buttons for marks whose feature is disabled\n\t * but whose toolbar button is explicitly requested.\n\t */\n\tprivate registerDisabledToolbarItems(context: PluginContext): void {\n\t\tif (!this.config.toolbar) return;\n\n\t\tfor (const def of MARK_DEFINITIONS) {\n\t\t\tconst featureEnabled = this.config[def.configKey];\n\t\t\tconst toolbarVisible = this.config.toolbar[def.configKey] ?? true;\n\n\t\t\tif (!featureEnabled && toolbarVisible) {\n\t\t\t\tcontext.registerToolbarItem({\n\t\t\t\t\tid: def.type,\n\t\t\t\t\tgroup: 'format',\n\t\t\t\t\ticon: def.icon,\n\t\t\t\t\tlabel: this.getMarkLabel(def.type),\n\t\t\t\t\tcommand: toCommandName(def.type),\n\t\t\t\t\tpriority: def.rank * 10 + 10,\n\t\t\t\t\tisEnabled: () => false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getMarkLabel(type: string): string {\n\t\tconst key = `${type}Label` as keyof TextFormattingLocale;\n\t\treturn this.locale[key] as string;\n\t}\n\n\t/** Checks if a toolbar button should be visible for a given mark. */\n\tprivate isToolbarVisible(\n\t\tconfigKey: keyof Omit<TextFormattingConfig, 'toolbar' | 'separatorAfter' | 'locale'>,\n\t): boolean {\n\t\tif (!this.config.toolbar) return true;\n\t\treturn this.config.toolbar[configKey] ?? true;\n\t}\n}\n\n/** Converts a mark type to its toggle command name (e.g. 'bold' → 'toggleBold'). */\nfunction toCommandName(markType: string): string {\n\treturn `toggle${markType.charAt(0).toUpperCase()}${markType.slice(1)}`;\n}\n"],"names":["TEXT_FORMATTING_LOCALE_EN","boldLabel","italicLabel","underlineLabel","TEXT_FORMATTING_LOCALES","en","de","es","fr","zh","ru","ar","hi","DEFAULT_CONFIG","bold","italic","underline","MARK_DEFINITIONS","type","configKey","rank","tag","label","icon","keyBinding","toHTMLString","content","parseHTML","sanitize","tags","TextFormattingPlugin","id","name","priority","config","locale","this","context","resolvePluginLocale","enabledMarks","filter","def","lastVisibleMark","isToolbarVisible","at","isSeparatorTarget","separatorAfter","registerMark","registerKeymaps","registerDisabledToolbarItems","commandName","toCommandName","toolbarVisible","registerMarkSpec","toDOM","document","createElement","_mark","registerCommand","tr","toggleMark","getState","mkType","dispatch","getMarkLabel","registerToolbarItem","group","tooltip","formatShortcut","command","isActive","state","isMarkActive","marks","keymap","executeCommand","Object","keys","length","registerKeymap","toolbar","featureEnabled","isEnabled","key","markType","charAt","toUpperCase","slice"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D3CQWJiw.mjs","sources":["../../src/editor/styles/list.ts","../../src/plugins/list/ListLocale.ts","../../src/plugins/list/ListPlugin.ts"],"sourcesContent":["/** List styles — bullet, ordered, checklist items. */\nexport const LIST_CSS = `\n/* List Wrappers — suppress native markers, we use ::before pseudo-elements */\n.notectl-list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Ordered List — each <ol> wrapper resets the counter */\n.notectl-list--ordered {\n\tcounter-reset: notectl-ordered;\n}\n\n/* List Items */\n.notectl-list-item {\n\tmargin: 0;\n\tpadding: 2px 0 2px 24px;\n\tmin-height: 1.6em;\n\tposition: relative;\n}\n\n.notectl-list-item::before {\n\tposition: absolute;\n\tleft: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n}\n\n/* Bullet List */\n.notectl-list-item--bullet::before {\n\tcontent: '\\\\2022';\n\tcolor: var(--notectl-fg);\n}\n\n/* Ordered List — counter increment per item */\n.notectl-list-item--ordered {\n\tcounter-increment: notectl-ordered;\n}\n\n.notectl-list-item--ordered::before {\n\tcontent: counter(notectl-ordered) '.';\n\tcolor: var(--notectl-fg);\n\tfont-size: 14px;\n}\n\n/* Checklist */\n.notectl-list-item--checklist::before {\n\tcontent: '\\\\2610';\n\tfont-size: 16px;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"]::before {\n\tcontent: '\\\\2611';\n\tcolor: var(--notectl-success);\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] {\n\tcolor: var(--notectl-fg-muted);\n\ttext-decoration: line-through;\n}\n`;\n","/**\n * Locale interface and default English locale for the ListPlugin.\n */\n\n// --- Locale Interface ---\n\nexport interface ListLocale {\n\treadonly bulletList: string;\n\treadonly numberedList: string;\n\treadonly checklist: string;\n}\n\n// --- Default English Locale ---\n\nexport const LIST_LOCALE_EN: ListLocale = {\n\tbulletList: 'Bullet List',\n\tnumberedList: 'Numbered List',\n\tchecklist: 'Checklist',\n};\n\n// --- German Locale ---\n\nexport const LIST_LOCALE_DE: ListLocale = {\n\tbulletList: 'Aufzählung',\n\tnumberedList: 'Nummerierte Liste',\n\tchecklist: 'Checkliste',\n};\n\n// --- Spanish Locale ---\n\nexport const LIST_LOCALE_ES: ListLocale = {\n\tbulletList: 'Lista con viñetas',\n\tnumberedList: 'Lista numerada',\n\tchecklist: 'Lista de verificación',\n};\n\n// --- French Locale ---\n\nexport const LIST_LOCALE_FR: ListLocale = {\n\tbulletList: 'Liste à puces',\n\tnumberedList: 'Liste numérotée',\n\tchecklist: 'Liste de contrôle',\n};\n\n// --- Chinese (Simplified) Locale ---\n\nexport const LIST_LOCALE_ZH: ListLocale = {\n\tbulletList: '无序列表',\n\tnumberedList: '有序列表',\n\tchecklist: '清单',\n};\n\n// --- Russian Locale ---\n\nexport const LIST_LOCALE_RU: ListLocale = {\n\tbulletList: 'Маркированный список',\n\tnumberedList: 'Нумерованный список',\n\tchecklist: 'Чек-лист',\n};\n\n// --- Arabic Locale ---\n\nexport const LIST_LOCALE_AR: ListLocale = {\n\tbulletList: 'قائمة نقطية',\n\tnumberedList: 'قائمة مرقمة',\n\tchecklist: 'قائمة تحقق',\n};\n\n// --- Hindi Locale ---\n\nexport const LIST_LOCALE_HI: ListLocale = {\n\tbulletList: 'बुलेट सूची',\n\tnumberedList: 'क्रमांकित सूची',\n\tchecklist: 'चेकलिस्ट',\n};\n\n// --- Locale Map ---\n\nexport const LIST_LOCALES: Record<string, ListLocale> = {\n\ten: LIST_LOCALE_EN,\n\tde: LIST_LOCALE_DE,\n\tes: LIST_LOCALE_ES,\n\tfr: LIST_LOCALE_FR,\n\tzh: LIST_LOCALE_ZH,\n\tru: LIST_LOCALE_RU,\n\tar: LIST_LOCALE_AR,\n\thi: LIST_LOCALE_HI,\n};\n","/**\n * ListPlugin: registers ordered, unordered, and checklist block types\n * with NodeSpecs, toggle commands, indent/outdent (Tab/Shift-Tab),\n * input rules, and toolbar buttons.\n *\n * List items are modeled as flat blocks with a `listType` and `indent` attribute,\n * allowing simple nesting representation without deep tree structures.\n */\n\nimport { LIST_CSS } from '../../editor/styles/list.js';\nimport { resolvePluginLocale } from '../../i18n/resolvePluginLocale.js';\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport { generateBlockId, getBlockText } from '../../model/Document.js';\nimport { createBlockElement } from '../../model/NodeSpec.js';\nimport { createCollapsedSelection, isCollapsed, isNodeSelection } from '../../model/Selection.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { LIST_LOCALES, type ListLocale } from './ListLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\nexport type ListType = 'bullet' | 'ordered' | 'checklist';\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\tlist_item: { listType: ListType; indent: number; checked: boolean };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface ListConfig {\n\t/** Which list types to enable. Defaults to all. */\n\treadonly types: readonly ListType[];\n\t/** Maximum indent depth. Defaults to 4. */\n\treadonly maxIndent: number;\n\t/** When true, a separator is rendered after the last list toolbar item. */\n\treadonly separatorAfter?: boolean;\n\treadonly locale?: ListLocale;\n}\n\nconst DEFAULT_CONFIG: ListConfig = {\n\ttypes: ['bullet', 'ordered', 'checklist'],\n\tmaxIndent: 4,\n};\n\n// --- List Type Metadata ---\n\ninterface ListTypeDefinition {\n\treadonly type: ListType;\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly inputPattern: RegExp;\n\treadonly inputPrefix: string;\n}\n\nconst BULLET_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z\"/></svg>';\nconst NUMBERED_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z\"/></svg>';\nconst CHECKLIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M22 7h-9v2h9V7zm0 8h-9v2h9v-2zM5.54 11L2 7.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 11zm0 8L2 15.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 19z\"/></svg>';\n\nconst LIST_TYPE_DEFINITIONS: readonly ListTypeDefinition[] = [\n\t{\n\t\ttype: 'bullet',\n\t\tlabel: 'Bullet List',\n\t\ticon: BULLET_LIST_ICON,\n\t\tinputPattern: /^[-*] $/,\n\t\tinputPrefix: '- ',\n\t},\n\t{\n\t\ttype: 'ordered',\n\t\tlabel: 'Numbered List',\n\t\ticon: NUMBERED_LIST_ICON,\n\t\tinputPattern: /^\\d+\\. $/,\n\t\tinputPrefix: '1. ',\n\t},\n\t{\n\t\ttype: 'checklist',\n\t\tlabel: 'Checklist',\n\t\ticon: CHECKLIST_ICON,\n\t\tinputPattern: /^\\[[ x]] $/,\n\t\tinputPrefix: '[ ] ',\n\t},\n];\n\n// --- Plugin ---\n\nexport class ListPlugin implements Plugin {\n\treadonly id = 'list';\n\treadonly name = 'List';\n\treadonly priority = 35;\n\n\tprivate readonly config: ListConfig;\n\tprivate locale!: ListLocale;\n\n\tconstructor(config?: Partial<ListConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.locale = resolvePluginLocale(LIST_LOCALES, context, this.config.locale);\n\t\tcontext.registerStyleSheet(LIST_CSS);\n\t\tthis.registerNodeSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInputRules(context);\n\t\tthis.registerToolbarItems(context);\n\t}\n\n\tprivate registerNodeSpec(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'list_item',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\tattrs: {\n\t\t\t\tlistType: { default: 'bullet' },\n\t\t\t\tindent: { default: 0 },\n\t\t\t\tchecked: { default: false },\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\tconst listType = node.attrs?.listType ?? 'bullet';\n\t\t\t\tconst indent = node.attrs?.indent ?? 0;\n\t\t\t\tconst checked = node.attrs?.checked ?? false;\n\n\t\t\t\tconst li = createBlockElement('li', node.id);\n\t\t\t\tli.setAttribute('role', 'listitem');\n\t\t\t\tli.setAttribute('data-list-type', listType);\n\t\t\t\tli.setAttribute('data-indent', String(indent));\n\t\t\t\tli.className = `notectl-list-item notectl-list-item--${listType}`;\n\n\t\t\t\tif (indent > 0) {\n\t\t\t\t\tli.style.marginLeft = `${indent * 24}px`;\n\t\t\t\t}\n\n\t\t\t\tif (listType === 'checklist') {\n\t\t\t\t\tli.setAttribute('data-checked', String(checked));\n\t\t\t\t\tli.setAttribute('aria-checked', String(checked));\n\t\t\t\t}\n\t\t\t\tli.setAttribute('aria-level', String(indent + 1));\n\n\t\t\t\treturn li;\n\t\t\t},\n\t\t\twrapper(node) {\n\t\t\t\tconst listType = node.attrs?.listType ?? 'bullet';\n\t\t\t\tconst tag = listType === 'ordered' ? 'ol' : 'ul';\n\t\t\t\treturn {\n\t\t\t\t\ttag,\n\t\t\t\t\tkey: `list-${listType}`,\n\t\t\t\t\tclassName: `notectl-list notectl-list--${listType}`,\n\t\t\t\t\tattrs: { role: 'list' },\n\t\t\t\t};\n\t\t\t},\n\t\t\ttoHTML(_node, content) {\n\t\t\t\treturn `<li>${content || '<br>'}</li>`;\n\t\t\t},\n\t\t\tparseHTML: [{ tag: 'li' }],\n\t\t\tsanitize: { tags: ['ul', 'ol', 'li'] },\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerCommand(`toggleList:${def.type}`, () => {\n\t\t\t\treturn this.toggleList(context, def.type);\n\t\t\t});\n\t\t}\n\n\t\tcontext.registerCommand('indentListItem', () => {\n\t\t\treturn this.indent(context);\n\t\t});\n\n\t\tcontext.registerCommand('outdentListItem', () => {\n\t\t\treturn this.outdent(context);\n\t\t});\n\n\t\tif (this.config.types.includes('checklist')) {\n\t\t\tcontext.registerCommand('toggleChecklistItem', () => {\n\t\t\t\treturn this.toggleChecked(context);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\tEnter: () => this.handleEnter(context),\n\t\t\tBackspace: () => this.handleBackspace(context),\n\t\t\tTab: () => this.indent(context),\n\t\t\t'Shift-Tab': () => this.outdent(context),\n\t\t});\n\t}\n\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerInputRule({\n\t\t\t\tpattern: def.inputPattern,\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\tconst matchStr = match[0] ?? '';\n\t\t\t\t\tconst matchLen = matchStr.length;\n\t\t\t\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\t\t\t\tlistType: def.type,\n\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (def.type === 'checklist') {\n\t\t\t\t\t\tattrs.checked = matchStr.includes('[x]');\n\t\t\t\t\t}\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 + matchLen)\n\t\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\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 getListLabel(type: ListType): string {\n\t\tconst labels: Record<ListType, string> = {\n\t\t\tbullet: this.locale.bulletList,\n\t\t\tordered: this.locale.numberedList,\n\t\t\tchecklist: this.locale.checklist,\n\t\t};\n\t\treturn labels[type];\n\t}\n\n\tprivate registerToolbarItems(context: PluginContext): void {\n\t\tconst enabledTypes = this.getEnabledTypes();\n\t\tconst lastType = enabledTypes.at(-1);\n\n\t\tfor (const def of enabledTypes) {\n\t\t\tcontext.registerToolbarItem({\n\t\t\t\tid: `list-${def.type}`,\n\t\t\t\tgroup: 'block',\n\t\t\t\ticon: def.icon,\n\t\t\t\tlabel: this.getListLabel(def.type),\n\t\t\t\tcommand: `toggleList:${def.type}`,\n\t\t\t\tpriority: def.type === 'bullet' ? 70 : def.type === 'ordered' ? 71 : 72,\n\t\t\t\tseparatorAfter: this.config.separatorAfter && def === lastType,\n\t\t\t\tisActive: (state) => this.isListActive(state, def.type),\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Command Implementations ---\n\n\tprivate toggleList(context: PluginContext, listType: ListType): 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\t// If already this list type, convert back to paragraph\n\t\tif (block.type === 'list_item' && block.attrs?.listType === listType) {\n\t\t\tconst tr = state\n\t\t\t\t.transaction('command')\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\t// Convert to list item\n\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\tlistType,\n\t\t\tindent: isNodeOfType(block, 'list_item') ? block.attrs.indent : 0,\n\t\t};\n\t\tif (listType === 'checklist') {\n\t\t\tattrs.checked = false;\n\t\t}\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate indent(context: PluginContext): 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 || !isNodeOfType(block, 'list_item')) return false;\n\n\t\tif (block.attrs.indent >= this.config.maxIndent) return false;\n\n\t\treturn this.setIndent(context, state, block.attrs.indent + 1);\n\t}\n\n\tprivate outdent(context: PluginContext): 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 || !isNodeOfType(block, 'list_item')) return false;\n\n\t\tif (block.attrs.indent <= 0) return false;\n\n\t\treturn this.setIndent(context, state, block.attrs.indent - 1);\n\t}\n\n\tprivate setIndent(context: PluginContext, state: EditorState, indent: number): boolean {\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\tconst attrs = { ...block.attrs, indent } as Record<string, string | number | boolean>;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate toggleChecked(context: PluginContext): 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 || block.type !== 'list_item' || block.attrs?.listType !== 'checklist') {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst checked = !block.attrs?.checked;\n\t\tconst attrs = { ...block.attrs, checked } as Record<string, string | number | boolean>;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(state.selection.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(state.selection)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Handles Backspace at the start of a list item.\n\t * Converts the list item back to a paragraph, preserving text.\n\t */\n\tprivate handleBackspace(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 || block.type !== 'list_item') return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst tr = state\n\t\t\t.transaction('input')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Handles Enter inside a list item.\n\t * Empty item → exit list (convert to paragraph).\n\t * Non-empty item → split and create a new list item with the same type.\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 || block.type !== 'list_item') return false;\n\n\t\tconst text = getBlockText(block);\n\n\t\tif (text === '') {\n\t\t\t// Empty list item → convert to paragraph (exit list)\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\t// Non-empty → split block and set new block to same list type\n\t\tconst newBlockId = generateBlockId();\n\t\tconst attrs: Record<string, string | number | boolean> = {\n\t\t\tlistType: isNodeOfType(block, 'list_item') ? block.attrs.listType : 'bullet',\n\t\t\tindent: isNodeOfType(block, 'list_item') ? block.attrs.indent : 0,\n\t\t};\n\t\tif (attrs.listType === 'checklist') {\n\t\t\tattrs.checked = false;\n\t\t}\n\n\t\tconst tr = state\n\t\t\t.transaction('input')\n\t\t\t.splitBlock(sel.anchor.blockId, sel.anchor.offset, newBlockId)\n\t\t\t.setBlockType(newBlockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(createCollapsedSelection(newBlockId, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t// --- Helpers ---\n\n\tprivate isListActive(state: EditorState, listType: ListType): boolean {\n\t\tif (isNodeSelection(state.selection)) return false;\n\t\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t\treturn block?.type === 'list_item' && block.attrs?.listType === listType;\n\t}\n\n\tprivate getEnabledTypes(): readonly ListTypeDefinition[] {\n\t\treturn LIST_TYPE_DEFINITIONS.filter((def) => this.config.types.includes(def.type));\n\t}\n}\n"],"names":["LIST_LOCALE_EN","bulletList","numberedList","checklist","LIST_LOCALES","en","de","es","fr","zh","ru","ar","hi","DEFAULT_CONFIG","types","maxIndent","LIST_TYPE_DEFINITIONS","type","label","icon","inputPattern","inputPrefix","ListPlugin","id","name","priority","config","locale","this","context","resolvePluginLocale","registerStyleSheet","registerNodeSpec","registerCommands","registerKeymaps","registerInputRules","registerToolbarItems","group","content","allow","attrs","listType","default","indent","checked","node","li","createBlockElement","setAttribute","String","className","style","marginLeft","tag","key","role","toHTML","_node","parseHTML","sanitize","tags","enabledTypes","getEnabledTypes","def","registerCommand","toggleList","outdent","includes","toggleChecked","registerKeymap","Enter","handleEnter","Backspace","handleBackspace","Tab","registerInputRule","pattern","handler","state","match","start","_end","sel","selection","isNodeSelection","isCollapsed","block","getBlock","anchor","blockId","matchStr","matchLen","length","transaction","deleteTextAt","setBlockType","nodeType","setSelection","createCollapsedSelection","build","bullet","ordered","lastType","at","registerToolbarItem","getListLabel","command","separatorAfter","isActive","isListActive","getState","tr","dispatch","isNodeOfType","setIndent","offset","getBlockText","newBlockId","generateBlockId","splitBlock","filter"],"mappings":"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"}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { r as e } from "./resolvePluginLocale-B4w1OkPy.mjs";
|
|
2
|
-
import { p as t, g as n, b as i, j as a, k as o } from "./Document-CI3iCwEP.mjs";
|
|
3
|
-
import { c as r } from "./NodeSpec-NZVvcCuH.mjs";
|
|
4
|
-
import { i as l, a as s, c } from "./Selection-D5ZjXoB7.mjs";
|
|
5
|
-
import { n as g } from "./TypeBrands-C09nE2qO.mjs";
|
|
6
|
-
import { a as d } from "./ToolbarPlugin-DY2xaJiu.mjs";
|
|
7
|
-
const h = { paragraph: "Paragraph", title: "Title", subtitle: "Subtitle", heading1: "Heading 1", heading2: "Heading 2", heading3: "Heading 3", heading4: "Heading 4", heading5: "Heading 5", heading6: "Heading 6", blockTypeLabel: "Block Type", blockTypesAria: "Block types" }, p = { en: h, de: { paragraph: "Absatz", title: "Titel", subtitle: "Untertitel", heading1: "Überschrift 1", heading2: "Überschrift 2", heading3: "Überschrift 3", heading4: "Überschrift 4", heading5: "Überschrift 5", heading6: "Überschrift 6", blockTypeLabel: "Blocktyp", blockTypesAria: "Blocktypen" }, es: { paragraph: "Párrafo", title: "Título", subtitle: "Subtítulo", heading1: "Encabezado 1", heading2: "Encabezado 2", heading3: "Encabezado 3", heading4: "Encabezado 4", heading5: "Encabezado 5", heading6: "Encabezado 6", blockTypeLabel: "Tipo de bloque", blockTypesAria: "Tipos de bloque" }, fr: { paragraph: "Paragraphe", title: "Titre", subtitle: "Sous-titre", heading1: "Titre 1", heading2: "Titre 2", heading3: "Titre 3", heading4: "Titre 4", heading5: "Titre 5", heading6: "Titre 6", blockTypeLabel: "Type de bloc", blockTypesAria: "Types de bloc" }, zh: { paragraph: "正文", title: "标题", subtitle: "副标题", heading1: "一级标题", heading2: "二级标题", heading3: "三级标题", heading4: "四级标题", heading5: "五级标题", heading6: "六级标题", blockTypeLabel: "块类型", blockTypesAria: "块类型列表" }, ru: { paragraph: "Абзац", title: "Заголовок", subtitle: "Подзаголовок", heading1: "Заголовок 1", heading2: "Заголовок 2", heading3: "Заголовок 3", heading4: "Заголовок 4", heading5: "Заголовок 5", heading6: "Заголовок 6", blockTypeLabel: "Тип блока", blockTypesAria: "Типы блоков" }, ar: { paragraph: "فقرة", title: "عنوان", subtitle: "عنوان فرعي", heading1: "عنوان 1", heading2: "عنوان 2", heading3: "عنوان 3", heading4: "عنوان 4", heading5: "عنوان 5", heading6: "عنوان 6", blockTypeLabel: "نوع الكتلة", blockTypesAria: "أنواع الكتل" }, hi: { paragraph: "अनुच्छेद", title: "शीर्षक", subtitle: "उपशीर्षक", heading1: "शीर्षक 1", heading2: "शीर्षक 2", heading3: "शीर्षक 3", heading4: "शीर्षक 4", heading5: "शीर्षक 5", heading6: "शीर्षक 6", blockTypeLabel: "ब्लॉक प्रकार", blockTypesAria: "ब्लॉक प्रकार सूची" } }, b = { levels: [1, 2, 3, 4, 5, 6] }, u = { 1: "h1", 2: "h2", 3: "h3", 4: "h4", 5: "h5", 6: "h6" };
|
|
8
|
-
class k {
|
|
9
|
-
id = "heading";
|
|
10
|
-
name = "Heading";
|
|
11
|
-
priority = 30;
|
|
12
|
-
config;
|
|
13
|
-
locale;
|
|
14
|
-
context = null;
|
|
15
|
-
comboLabel = null;
|
|
16
|
-
constructor(e2) {
|
|
17
|
-
this.config = { ...b, ...e2 };
|
|
18
|
-
}
|
|
19
|
-
init(t2) {
|
|
20
|
-
this.locale = e(p, t2, this.config.locale), 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);
|
|
21
|
-
}
|
|
22
|
-
destroy() {
|
|
23
|
-
this.context = null, this.comboLabel = null;
|
|
24
|
-
}
|
|
25
|
-
onStateChange(e2, t2, n2) {
|
|
26
|
-
this.updateComboLabel(t2);
|
|
27
|
-
}
|
|
28
|
-
registerNodeSpecs(e2) {
|
|
29
|
-
e2.registerNodeSpec({ type: "title", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], toDOM(e3) {
|
|
30
|
-
const t2 = r("h1", e3.id);
|
|
31
|
-
return t2.classList.add("notectl-title"), t2;
|
|
32
|
-
}, toHTML: (e3, t2) => `<h1>${t2 || "<br>"}</h1>`, sanitize: { tags: ["h1"] } }), e2.registerNodeSpec({ type: "subtitle", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], toDOM(e3) {
|
|
33
|
-
const t2 = r("h2", e3.id);
|
|
34
|
-
return t2.classList.add("notectl-subtitle"), t2;
|
|
35
|
-
}, toHTML: (e3, t2) => `<h2>${t2 || "<br>"}</h2>`, sanitize: { tags: ["h2"] } }), e2.registerNodeSpec({ type: "heading", group: "block", content: { allow: ["text"] }, excludeMarks: ["fontSize"], attrs: { level: { default: 1 } }, toDOM(e3) {
|
|
36
|
-
const t2 = e3.attrs?.level ?? 1;
|
|
37
|
-
return r(u[t2] ?? "h1", e3.id);
|
|
38
|
-
}, toHTML(e3, t2) {
|
|
39
|
-
const n2 = e3.attrs?.level ?? 1, i2 = u[n2] ?? "h1";
|
|
40
|
-
return `<${i2}>${t2 || "<br>"}</${i2}>`;
|
|
41
|
-
}, 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"] } });
|
|
42
|
-
}
|
|
43
|
-
registerCommands(e2) {
|
|
44
|
-
e2.registerCommand("setTitle", () => this.toggleSpecialBlock(e2, "title")), e2.registerCommand("setSubtitle", () => this.toggleSpecialBlock(e2, "subtitle"));
|
|
45
|
-
for (const t2 of this.config.levels) e2.registerCommand(`setHeading${t2}`, () => this.toggleHeading(e2, t2));
|
|
46
|
-
e2.registerCommand("toggleHeading", () => this.toggleHeading(e2, 1)), e2.registerCommand("setParagraph", () => this.setBlockType(e2, g("paragraph")));
|
|
47
|
-
}
|
|
48
|
-
registerKeymaps(e2) {
|
|
49
|
-
const t2 = { Enter: () => this.handleEnter(e2) };
|
|
50
|
-
for (const n2 of this.config.levels) n2 <= 6 && (t2[`Mod-Shift-${n2}`] = () => e2.executeCommand(`setHeading${n2}`));
|
|
51
|
-
e2.registerKeymap(t2);
|
|
52
|
-
}
|
|
53
|
-
registerInputRules(e2) {
|
|
54
|
-
for (const t2 of this.config.levels) {
|
|
55
|
-
const n2 = "#".repeat(t2), i2 = new RegExp(`^${n2} $`);
|
|
56
|
-
e2.registerInputRule({ pattern: i2, handler(e3, n3, i3, a2) {
|
|
57
|
-
const o2 = e3.selection;
|
|
58
|
-
if (l(o2)) return null;
|
|
59
|
-
if (!s(o2)) return null;
|
|
60
|
-
const r2 = e3.getBlock(o2.anchor.blockId);
|
|
61
|
-
return r2 && "paragraph" === r2.type ? e3.transaction("input").deleteTextAt(o2.anchor.blockId, i3, i3 + t2 + 1).setBlockType(o2.anchor.blockId, g("heading"), { level: t2 }).setSelection(c(o2.anchor.blockId, 0)).build() : null;
|
|
62
|
-
} });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
registerPickerEntries(e2) {
|
|
66
|
-
e2.registerBlockTypePickerEntry({ id: "paragraph", label: this.locale.paragraph, command: "setParagraph", priority: 10, isActive: (e3) => {
|
|
67
|
-
if (l(e3.selection)) return false;
|
|
68
|
-
const t2 = e3.getBlock(e3.selection.anchor.blockId);
|
|
69
|
-
return "paragraph" === t2?.type;
|
|
70
|
-
} }), e2.registerBlockTypePickerEntry({ id: "title", label: this.locale.title, command: "setTitle", priority: 20, style: { fontSize: "1.6em", fontWeight: "700" }, isActive: (e3) => {
|
|
71
|
-
if (l(e3.selection)) return false;
|
|
72
|
-
const t2 = e3.getBlock(e3.selection.anchor.blockId);
|
|
73
|
-
return "title" === t2?.type;
|
|
74
|
-
} }), e2.registerBlockTypePickerEntry({ id: "subtitle", label: this.locale.subtitle, command: "setSubtitle", priority: 30, style: { fontSize: "1.3em", fontWeight: "500" }, isActive: (e3) => {
|
|
75
|
-
if (l(e3.selection)) return false;
|
|
76
|
-
const t2 = e3.getBlock(e3.selection.anchor.blockId);
|
|
77
|
-
return "subtitle" === t2?.type;
|
|
78
|
-
} });
|
|
79
|
-
for (const t2 of this.config.levels) e2.registerBlockTypePickerEntry({ id: `heading-${t2}`, label: this.getHeadingLabel(t2), command: `setHeading${t2}`, priority: 100 + t2, style: { fontSize: 1.4 - 0.1 * t2 + "em", fontWeight: "600" }, isActive: (e3) => {
|
|
80
|
-
if (l(e3.selection)) return false;
|
|
81
|
-
const n2 = e3.getBlock(e3.selection.anchor.blockId);
|
|
82
|
-
return "heading" === n2?.type && n2.attrs?.level === t2;
|
|
83
|
-
} });
|
|
84
|
-
}
|
|
85
|
-
registerToolbarItem(e2) {
|
|
86
|
-
const t2 = `<span class="notectl-heading-select__label" data-heading-label>${this.locale.paragraph}</span><span class="notectl-heading-select__arrow">▾</span>`;
|
|
87
|
-
e2.registerToolbarItem({ id: "heading", group: "block", icon: t2, label: this.locale.blockTypeLabel, tooltip: this.locale.blockTypeLabel, command: "setParagraph", priority: 50, popupType: "custom", separatorAfter: this.config.separatorAfter, renderPopup: (e3, t3) => {
|
|
88
|
-
this.renderHeadingPopup(e3, t3);
|
|
89
|
-
}, isActive: (t3) => e2.getSchemaRegistry().getBlockTypePickerEntries().some((e3) => "paragraph" !== e3.id && e3.isActive(t3)) });
|
|
90
|
-
}
|
|
91
|
-
getHeadingLabel(e2) {
|
|
92
|
-
const t2 = `heading${e2}`;
|
|
93
|
-
return this.locale[t2];
|
|
94
|
-
}
|
|
95
|
-
updateComboLabel(e2) {
|
|
96
|
-
if (!this.comboLabel) {
|
|
97
|
-
const e3 = this.context?.getPluginContainer("top");
|
|
98
|
-
if (!e3) return;
|
|
99
|
-
if (this.comboLabel = e3.querySelector("[data-heading-label]") ?? null, !this.comboLabel) return;
|
|
100
|
-
}
|
|
101
|
-
this.comboLabel.textContent = this.getActiveLabel(e2);
|
|
102
|
-
}
|
|
103
|
-
getActiveLabel(e2) {
|
|
104
|
-
if (l(e2.selection)) return this.locale.paragraph;
|
|
105
|
-
const t2 = this.context?.getSchemaRegistry().getBlockTypePickerEntries() ?? [];
|
|
106
|
-
for (const n2 of t2) if (n2.isActive(e2)) return n2.label;
|
|
107
|
-
return this.locale.paragraph;
|
|
108
|
-
}
|
|
109
|
-
dismissPopup() {
|
|
110
|
-
const e2 = this.context?.getService(d);
|
|
111
|
-
e2?.closePopup();
|
|
112
|
-
}
|
|
113
|
-
renderHeadingPopup(e2, t2) {
|
|
114
|
-
e2.classList.add("notectl-heading-picker");
|
|
115
|
-
const n2 = t2.getState();
|
|
116
|
-
if (l(n2.selection)) return;
|
|
117
|
-
const i2 = document.createElement("div");
|
|
118
|
-
i2.className = "notectl-heading-picker__list", i2.setAttribute("role", "listbox"), i2.setAttribute("aria-label", this.locale.blockTypesAria);
|
|
119
|
-
const a2 = t2.getSchemaRegistry().getBlockTypePickerEntries();
|
|
120
|
-
for (const e3 of a2) {
|
|
121
|
-
const a3 = e3.isActive(n2);
|
|
122
|
-
i2.appendChild(this.createPickerItem(e3.label, a3, (n3) => {
|
|
123
|
-
n3.preventDefault(), n3.stopPropagation(), t2.executeCommand(e3.command), this.dismissPopup();
|
|
124
|
-
}, e3.style));
|
|
125
|
-
}
|
|
126
|
-
e2.appendChild(i2);
|
|
127
|
-
}
|
|
128
|
-
createPickerItem(e2, t2, n2, i2) {
|
|
129
|
-
const a2 = document.createElement("button");
|
|
130
|
-
a2.type = "button", a2.className = "notectl-heading-picker__item", a2.setAttribute("role", "option"), a2.setAttribute("aria-selected", String(t2)), t2 && a2.classList.add("notectl-heading-picker__item--active");
|
|
131
|
-
const o2 = document.createElement("span");
|
|
132
|
-
o2.className = "notectl-heading-picker__check", o2.textContent = t2 ? "✓" : "", a2.appendChild(o2);
|
|
133
|
-
const r2 = document.createElement("span");
|
|
134
|
-
return r2.className = "notectl-heading-picker__label", r2.textContent = e2, i2 && (r2.style.fontSize = i2.fontSize, r2.style.fontWeight = i2.fontWeight), a2.appendChild(r2), a2.addEventListener("mousedown", n2), a2;
|
|
135
|
-
}
|
|
136
|
-
static HEADING_TYPES = /* @__PURE__ */ new Set(["heading", "title", "subtitle"]);
|
|
137
|
-
handleEnter(e2) {
|
|
138
|
-
const a2 = e2.getState(), o2 = a2.selection;
|
|
139
|
-
if (l(o2)) return false;
|
|
140
|
-
if (!s(o2)) return false;
|
|
141
|
-
const r2 = a2.getBlock(o2.anchor.blockId);
|
|
142
|
-
if (!r2 || !k.HEADING_TYPES.has(r2.type)) return false;
|
|
143
|
-
if ("" === t(r2)) {
|
|
144
|
-
const t2 = a2.transaction("input").setBlockType(o2.anchor.blockId, g("paragraph")).setSelection(o2).build();
|
|
145
|
-
return e2.dispatch(t2), true;
|
|
146
|
-
}
|
|
147
|
-
const d2 = n(r2);
|
|
148
|
-
if (o2.anchor.offset >= d2) {
|
|
149
|
-
const t2 = i(), n2 = a2.transaction("input").splitBlock(o2.anchor.blockId, o2.anchor.offset, t2).setBlockType(t2, g("paragraph")).setSelection(c(t2, 0)).build();
|
|
150
|
-
return e2.dispatch(n2), true;
|
|
151
|
-
}
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
toggleSpecialBlock(e2, t2) {
|
|
155
|
-
const n2 = e2.getState();
|
|
156
|
-
if (l(n2.selection)) return false;
|
|
157
|
-
const i2 = n2.getBlock(n2.selection.anchor.blockId);
|
|
158
|
-
return !!i2 && (i2.type === t2 ? this.setBlockType(e2, g("paragraph")) : this.setBlockType(e2, g(t2)));
|
|
159
|
-
}
|
|
160
|
-
toggleHeading(e2, t2) {
|
|
161
|
-
const n2 = e2.getState(), i2 = n2.selection;
|
|
162
|
-
if (l(i2)) return false;
|
|
163
|
-
const a2 = n2.getBlock(i2.anchor.blockId);
|
|
164
|
-
return !!a2 && ("heading" === a2.type && a2.attrs?.level === t2 ? this.setBlockType(e2, g("paragraph")) : this.setBlockType(e2, g("heading"), { level: t2 }));
|
|
165
|
-
}
|
|
166
|
-
setBlockType(e2, t2, n2) {
|
|
167
|
-
const i2 = e2.getState(), a2 = i2.selection;
|
|
168
|
-
if (l(a2)) return false;
|
|
169
|
-
const o2 = i2.getBlock(a2.anchor.blockId);
|
|
170
|
-
if (!o2) return false;
|
|
171
|
-
const r2 = i2.transaction("command"), s2 = e2.getSchemaRegistry().getNodeSpec(t2);
|
|
172
|
-
s2?.excludeMarks && s2.excludeMarks.length > 0 && (this.stripExcludedMarks(r2, o2, s2.excludeMarks), this.clearExcludedStoredMarks(r2, i2, s2.excludeMarks));
|
|
173
|
-
const c2 = r2.setBlockType(a2.anchor.blockId, t2, n2).setSelection(a2).build();
|
|
174
|
-
return e2.dispatch(c2), true;
|
|
175
|
-
}
|
|
176
|
-
stripExcludedMarks(e2, t2, i2) {
|
|
177
|
-
if (0 === n(t2)) return;
|
|
178
|
-
const r2 = new Set(i2), l2 = a(t2);
|
|
179
|
-
let s2 = 0;
|
|
180
|
-
for (const n2 of l2) if (o(n2)) {
|
|
181
|
-
if (n2.text.length > 0) for (const i3 of n2.marks) r2.has(i3.type) && e2.removeMark(t2.id, s2, s2 + n2.text.length, i3);
|
|
182
|
-
s2 += n2.text.length;
|
|
183
|
-
} else s2 += 1;
|
|
184
|
-
}
|
|
185
|
-
clearExcludedStoredMarks(e2, t2, n2) {
|
|
186
|
-
if (!t2.storedMarks) return;
|
|
187
|
-
const i2 = new Set(n2), a2 = t2.storedMarks.filter((e3) => !i2.has(e3.type));
|
|
188
|
-
a2.length !== t2.storedMarks.length && e2.setStoredMarks(a2.length > 0 ? a2 : null, t2.storedMarks);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
export {
|
|
192
|
-
p as H,
|
|
193
|
-
h as a,
|
|
194
|
-
k as b
|
|
195
|
-
};
|
|
196
|
-
//# sourceMappingURL=index-Dh76rR13.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-Dh76rR13.mjs","sources":["../../src/editor/styles/heading-select.ts","../../src/plugins/heading/HeadingLocale.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 * Locale interface and default English locale for the HeadingPlugin.\n */\n\n// --- Locale Interface ---\n\nexport interface HeadingLocale {\n\treadonly paragraph: string;\n\treadonly title: string;\n\treadonly subtitle: string;\n\treadonly heading1: string;\n\treadonly heading2: string;\n\treadonly heading3: string;\n\treadonly heading4: string;\n\treadonly heading5: string;\n\treadonly heading6: string;\n\treadonly blockTypeLabel: string;\n\treadonly blockTypesAria: string;\n}\n\n// --- Default English Locale ---\n\nexport const HEADING_LOCALE_EN: HeadingLocale = {\n\tparagraph: 'Paragraph',\n\ttitle: 'Title',\n\tsubtitle: 'Subtitle',\n\theading1: 'Heading 1',\n\theading2: 'Heading 2',\n\theading3: 'Heading 3',\n\theading4: 'Heading 4',\n\theading5: 'Heading 5',\n\theading6: 'Heading 6',\n\tblockTypeLabel: 'Block Type',\n\tblockTypesAria: 'Block types',\n};\n\n// --- German Locale ---\n\nexport const HEADING_LOCALE_DE: HeadingLocale = {\n\tparagraph: 'Absatz',\n\ttitle: 'Titel',\n\tsubtitle: 'Untertitel',\n\theading1: 'Überschrift 1',\n\theading2: 'Überschrift 2',\n\theading3: 'Überschrift 3',\n\theading4: 'Überschrift 4',\n\theading5: 'Überschrift 5',\n\theading6: 'Überschrift 6',\n\tblockTypeLabel: 'Blocktyp',\n\tblockTypesAria: 'Blocktypen',\n};\n\n// --- Spanish Locale ---\n\nexport const HEADING_LOCALE_ES: HeadingLocale = {\n\tparagraph: 'Párrafo',\n\ttitle: 'Título',\n\tsubtitle: 'Subtítulo',\n\theading1: 'Encabezado 1',\n\theading2: 'Encabezado 2',\n\theading3: 'Encabezado 3',\n\theading4: 'Encabezado 4',\n\theading5: 'Encabezado 5',\n\theading6: 'Encabezado 6',\n\tblockTypeLabel: 'Tipo de bloque',\n\tblockTypesAria: 'Tipos de bloque',\n};\n\n// --- French Locale ---\n\nexport const HEADING_LOCALE_FR: HeadingLocale = {\n\tparagraph: 'Paragraphe',\n\ttitle: 'Titre',\n\tsubtitle: 'Sous-titre',\n\theading1: 'Titre 1',\n\theading2: 'Titre 2',\n\theading3: 'Titre 3',\n\theading4: 'Titre 4',\n\theading5: 'Titre 5',\n\theading6: 'Titre 6',\n\tblockTypeLabel: 'Type de bloc',\n\tblockTypesAria: 'Types de bloc',\n};\n\n// --- Chinese (Simplified) Locale ---\n\nexport const HEADING_LOCALE_ZH: HeadingLocale = {\n\tparagraph: '正文',\n\ttitle: '标题',\n\tsubtitle: '副标题',\n\theading1: '一级标题',\n\theading2: '二级标题',\n\theading3: '三级标题',\n\theading4: '四级标题',\n\theading5: '五级标题',\n\theading6: '六级标题',\n\tblockTypeLabel: '块类型',\n\tblockTypesAria: '块类型列表',\n};\n\n// --- Russian Locale ---\n\nexport const HEADING_LOCALE_RU: HeadingLocale = {\n\tparagraph: 'Абзац',\n\ttitle: 'Заголовок',\n\tsubtitle: 'Подзаголовок',\n\theading1: 'Заголовок 1',\n\theading2: 'Заголовок 2',\n\theading3: 'Заголовок 3',\n\theading4: 'Заголовок 4',\n\theading5: 'Заголовок 5',\n\theading6: 'Заголовок 6',\n\tblockTypeLabel: 'Тип блока',\n\tblockTypesAria: 'Типы блоков',\n};\n\n// --- Arabic Locale ---\n\nexport const HEADING_LOCALE_AR: HeadingLocale = {\n\tparagraph: 'فقرة',\n\ttitle: 'عنوان',\n\tsubtitle: 'عنوان فرعي',\n\theading1: 'عنوان 1',\n\theading2: 'عنوان 2',\n\theading3: 'عنوان 3',\n\theading4: 'عنوان 4',\n\theading5: 'عنوان 5',\n\theading6: 'عنوان 6',\n\tblockTypeLabel: 'نوع الكتلة',\n\tblockTypesAria: 'أنواع الكتل',\n};\n\n// --- Hindi Locale ---\n\nexport const HEADING_LOCALE_HI: HeadingLocale = {\n\tparagraph: 'अनुच्छेद',\n\ttitle: 'शीर्षक',\n\tsubtitle: 'उपशीर्षक',\n\theading1: 'शीर्षक 1',\n\theading2: 'शीर्षक 2',\n\theading3: 'शीर्षक 3',\n\theading4: 'शीर्षक 4',\n\theading5: 'शीर्षक 5',\n\theading6: 'शीर्षक 6',\n\tblockTypeLabel: 'ब्लॉक प्रकार',\n\tblockTypesAria: 'ब्लॉक प्रकार सूची',\n};\n\n// --- Locale Map ---\n\nexport const HEADING_LOCALES: Record<string, HeadingLocale> = {\n\ten: HEADING_LOCALE_EN,\n\tde: HEADING_LOCALE_DE,\n\tes: HEADING_LOCALE_ES,\n\tfr: HEADING_LOCALE_FR,\n\tzh: HEADING_LOCALE_ZH,\n\tru: HEADING_LOCALE_RU,\n\tar: HEADING_LOCALE_AR,\n\thi: HEADING_LOCALE_HI,\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 { resolvePluginLocale } from '../../i18n/resolvePluginLocale.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';\nimport { HEADING_LOCALES, type HeadingLocale } from './HeadingLocale.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\treadonly locale?: HeadingLocale;\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// --- 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 locale!: HeadingLocale;\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\tthis.locale = resolvePluginLocale(HEADING_LOCALES, context, this.config.locale);\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: this.locale.paragraph,\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: this.locale.title,\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: this.locale.subtitle,\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: this.getHeadingLabel(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>${this.locale.paragraph}</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: this.locale.blockTypeLabel,\n\t\t\ttooltip: this.locale.blockTypeLabel,\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\tprivate getHeadingLabel(level: HeadingLevel): string {\n\t\tconst key = `heading${level}` as keyof HeadingLocale;\n\t\treturn this.locale[key] as string;\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 this.locale.paragraph;\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 this.locale.paragraph;\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', this.locale.blockTypesAria);\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":["HEADING_LOCALE_EN","paragraph","title","subtitle","heading1","heading2","heading3","heading4","heading5","heading6","blockTypeLabel","blockTypesAria","HEADING_LOCALES","en","de","es","fr","zh","ru","ar","hi","DEFAULT_CONFIG","levels","HEADING_TAGS","HeadingPlugin","id","name","priority","config","locale","context","comboLabel","this","resolvePluginLocale","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","getHeadingLabel","icon","tooltip","popupType","separatorAfter","renderPopup","container","ctx","renderHeadingPopup","getSchemaRegistry","getBlockTypePickerEntries","some","entry","key","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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"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SourceNormalizer: normalizes vendor-specific HTML before parsing.
|
|
3
|
-
* Cleans up Word, Google Docs, and Apple Pages artifacts.
|
|
4
|
-
*/
|
|
5
|
-
/** Detects the source and normalizes the DOM container in-place. */
|
|
6
|
-
export declare function normalizeSource(rawHTML: string, container: DocumentFragment | HTMLElement): void;
|
|
7
|
-
//# sourceMappingURL=SourceNormalizer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SourceNormalizer.d.ts","sourceRoot":"","sources":["../../src/input/SourceNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,GAAG,WAAW,GAAG,IAAI,CAkBhG"}
|