@notectl/core 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/{AttrRegistry-I-VdmRnN.mjs → AttrRegistry-D9Jx_RVb.mjs} +2 -2
  3. package/dist/chunks/{AttrRegistry-I-VdmRnN.mjs.map → AttrRegistry-D9Jx_RVb.mjs.map} +1 -1
  4. package/dist/chunks/AttributedMarkCommands-BtLea72z.mjs +80 -0
  5. package/dist/chunks/AttributedMarkCommands-BtLea72z.mjs.map +1 -0
  6. package/dist/chunks/{CaretNavigation-CAJXoaae.mjs → CaretNavigation-7JYpIKbs.mjs} +56 -56
  7. package/dist/chunks/{CaretNavigation-CAJXoaae.mjs.map → CaretNavigation-7JYpIKbs.mjs.map} +1 -1
  8. package/dist/chunks/ColorGrid-Dneqb8if.mjs +81 -0
  9. package/dist/chunks/ColorGrid-Dneqb8if.mjs.map +1 -0
  10. package/dist/chunks/ColorPickerPopup-CiCLBbe9.mjs +37 -0
  11. package/dist/chunks/ColorPickerPopup-CiCLBbe9.mjs.map +1 -0
  12. package/dist/chunks/ColorValidation-CV4f1wu6.mjs +39 -0
  13. package/dist/chunks/ColorValidation-CV4f1wu6.mjs.map +1 -0
  14. package/dist/chunks/{Document-CuwE73FF.mjs → Document-Brtw2jL1.mjs} +18 -18
  15. package/dist/chunks/{Document-CuwE73FF.mjs.map → Document-Brtw2jL1.mjs.map} +1 -1
  16. package/dist/chunks/MarkCommands-6RUJ4L3r.mjs +94 -0
  17. package/dist/chunks/MarkCommands-6RUJ4L3r.mjs.map +1 -0
  18. package/dist/chunks/{NavigationUtils-CyW0Vo8A.mjs → NavigationUtils-Cspt2ZrK.mjs} +3 -3
  19. package/dist/chunks/{NavigationUtils-CyW0Vo8A.mjs.map → NavigationUtils-Cspt2ZrK.mjs.map} +1 -1
  20. package/dist/chunks/{NodeResolver-B-wzthAQ.mjs → NodeResolver-C2XYkeOi.mjs} +2 -2
  21. package/dist/chunks/{NodeResolver-B-wzthAQ.mjs.map → NodeResolver-C2XYkeOi.mjs.map} +1 -1
  22. package/dist/chunks/PopupPositioning-BTT-_pQ3.mjs +32 -0
  23. package/dist/chunks/PopupPositioning-BTT-_pQ3.mjs.map +1 -0
  24. package/dist/chunks/RangeIterator-Bh4Vl_6D.mjs +16 -0
  25. package/dist/chunks/RangeIterator-Bh4Vl_6D.mjs.map +1 -0
  26. package/dist/chunks/{Selection-DmFDwiPJ.mjs → Selection-BRTab5hO.mjs} +7 -7
  27. package/dist/chunks/{Selection-DmFDwiPJ.mjs.map → Selection-BRTab5hO.mjs.map} +1 -1
  28. package/dist/chunks/StyleRuntime-ChRjVQwL.mjs +239 -0
  29. package/dist/chunks/StyleRuntime-ChRjVQwL.mjs.map +1 -0
  30. package/dist/chunks/ToolbarItem-BpZggUGo.mjs.map +1 -1
  31. package/dist/chunks/{ToolbarKeyboardNav-B32OMv8r.mjs → ToolbarKeyboardNav-DhpL8zNV.mjs} +3 -3
  32. package/dist/chunks/{ToolbarKeyboardNav-B32OMv8r.mjs.map → ToolbarKeyboardNav-DhpL8zNV.mjs.map} +1 -1
  33. package/dist/chunks/{ToolbarPlugin-B6JETWaw.mjs → ToolbarPlugin-DpLVJ71w.mjs} +348 -135
  34. package/dist/chunks/ToolbarPlugin-DpLVJ71w.mjs.map +1 -0
  35. package/dist/chunks/index--n1RGpq-.mjs +171 -0
  36. package/dist/chunks/index--n1RGpq-.mjs.map +1 -0
  37. package/dist/chunks/index-4or5UzNO.mjs +168 -0
  38. package/dist/chunks/index-4or5UzNO.mjs.map +1 -0
  39. package/dist/chunks/{index-pxbbDHVH.mjs → index-ABlTDvEX.mjs} +20 -19
  40. package/dist/chunks/index-ABlTDvEX.mjs.map +1 -0
  41. package/dist/chunks/{index--z_Txzej.mjs → index-BAke7kNL.mjs} +45 -45
  42. package/dist/chunks/{index--z_Txzej.mjs.map → index-BAke7kNL.mjs.map} +1 -1
  43. package/dist/chunks/{index-DMt3ojrY.mjs → index-BXtw5PNN.mjs} +2 -2
  44. package/dist/chunks/{index-DMt3ojrY.mjs.map → index-BXtw5PNN.mjs.map} +1 -1
  45. package/dist/chunks/{index-FlTg80Pk.mjs → index-BhDXjueu.mjs} +285 -325
  46. package/dist/chunks/index-BhDXjueu.mjs.map +1 -0
  47. package/dist/chunks/{index-D0s0Q8Wc.mjs → index-BqNUfq-y.mjs} +43 -35
  48. package/dist/chunks/index-BqNUfq-y.mjs.map +1 -0
  49. package/dist/chunks/{index-CflvcXSd.mjs → index-BvqkuEY1.mjs} +21 -17
  50. package/dist/chunks/index-BvqkuEY1.mjs.map +1 -0
  51. package/dist/chunks/{index-C9gc3Bws.mjs → index-C1opJocO.mjs} +32 -32
  52. package/dist/chunks/{index-C9gc3Bws.mjs.map → index-C1opJocO.mjs.map} +1 -1
  53. package/dist/chunks/index-CWltg1wK.mjs +124 -0
  54. package/dist/chunks/index-CWltg1wK.mjs.map +1 -0
  55. package/dist/chunks/{index-D8tbbW97.mjs → index-Cd3uJLP3.mjs} +2 -2
  56. package/dist/chunks/{index-D8tbbW97.mjs.map → index-Cd3uJLP3.mjs.map} +1 -1
  57. package/dist/chunks/{index-C0cEs7Jc.mjs → index-CluzpB2b.mjs} +10 -10
  58. package/dist/chunks/{index-C0cEs7Jc.mjs.map → index-CluzpB2b.mjs.map} +1 -1
  59. package/dist/chunks/{index-CoeD4T9-.mjs → index-D3NlpmT1.mjs} +15 -11
  60. package/dist/chunks/index-D3NlpmT1.mjs.map +1 -0
  61. package/dist/chunks/{index-CAV2N-fF.mjs → index-D515iymW.mjs} +75 -74
  62. package/dist/chunks/{index-CAV2N-fF.mjs.map → index-D515iymW.mjs.map} +1 -1
  63. package/dist/chunks/{index-B-NSeaM4.mjs → index-Dk49P9N4.mjs} +2 -2
  64. package/dist/chunks/{index-B-NSeaM4.mjs.map → index-Dk49P9N4.mjs.map} +1 -1
  65. package/dist/chunks/index-DyzigvbZ.mjs +410 -0
  66. package/dist/chunks/index-DyzigvbZ.mjs.map +1 -0
  67. package/dist/chunks/index-ErZ5_a1o.mjs +296 -0
  68. package/dist/chunks/index-ErZ5_a1o.mjs.map +1 -0
  69. package/dist/chunks/{index-CNs4QQ8l.mjs → index-fsVJLutn.mjs} +52 -64
  70. package/dist/chunks/index-fsVJLutn.mjs.map +1 -0
  71. package/dist/commands/AttributedMarkCommands.d.ts +46 -0
  72. package/dist/commands/AttributedMarkCommands.d.ts.map +1 -0
  73. package/dist/commands/CommandHelpers.d.ts +21 -0
  74. package/dist/commands/CommandHelpers.d.ts.map +1 -0
  75. package/dist/commands/Commands.d.ts +2 -8
  76. package/dist/commands/Commands.d.ts.map +1 -1
  77. package/dist/commands/DeleteCommands.d.ts.map +1 -1
  78. package/dist/commands/GapCursorCommands.d.ts.map +1 -1
  79. package/dist/commands/NodeSelectionCommands.d.ts.map +1 -1
  80. package/dist/commands/PasteCommand.d.ts.map +1 -1
  81. package/dist/commands/RangeIterator.d.ts +10 -0
  82. package/dist/commands/RangeIterator.d.ts.map +1 -0
  83. package/dist/editor/DocumentParser.d.ts.map +1 -1
  84. package/dist/editor/DocumentSerializer.d.ts +2 -0
  85. package/dist/editor/DocumentSerializer.d.ts.map +1 -1
  86. package/dist/editor/EditorThemeController.d.ts +3 -0
  87. package/dist/editor/EditorThemeController.d.ts.map +1 -1
  88. package/dist/editor/MarkSerializer.d.ts +11 -0
  89. package/dist/editor/MarkSerializer.d.ts.map +1 -0
  90. package/dist/editor/NotectlEditor.d.ts +19 -3
  91. package/dist/editor/NotectlEditor.d.ts.map +1 -1
  92. package/dist/editor/PaperLayoutController.d.ts +2 -0
  93. package/dist/editor/PaperLayoutController.d.ts.map +1 -1
  94. package/dist/editor/styles/font-select.d.ts +1 -1
  95. package/dist/editor/styles/font-select.d.ts.map +1 -1
  96. package/dist/editor/styles/font-size-select.d.ts +1 -1
  97. package/dist/editor/styles/font-size-select.d.ts.map +1 -1
  98. package/dist/editor/styles/heading-select.d.ts +1 -1
  99. package/dist/editor/styles/heading-select.d.ts.map +1 -1
  100. package/dist/editor/styles/toolbar.d.ts +1 -1
  101. package/dist/editor/styles/toolbar.d.ts.map +1 -1
  102. package/dist/index.d.ts +9 -2
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/input/ClipboardHandler.d.ts +0 -2
  105. package/dist/input/ClipboardHandler.d.ts.map +1 -1
  106. package/dist/input/LegacyHTMLNormalizer.d.ts.map +1 -1
  107. package/dist/model/MarkSpec.d.ts +6 -0
  108. package/dist/model/MarkSpec.d.ts.map +1 -1
  109. package/dist/notectl-core.mjs +2244 -2095
  110. package/dist/notectl-core.mjs.map +1 -1
  111. package/dist/notectl-core.umd.js +2862 -2415
  112. package/dist/notectl-core.umd.js.map +1 -1
  113. package/dist/plugins/PluginManager.d.ts +2 -0
  114. package/dist/plugins/PluginManager.d.ts.map +1 -1
  115. package/dist/plugins/alignment/AlignmentPlugin.d.ts.map +1 -1
  116. package/dist/plugins/alignment.mjs +1 -1
  117. package/dist/plugins/blockquote.mjs +1 -1
  118. package/dist/plugins/caret-navigation.mjs +1 -1
  119. package/dist/plugins/code-block/CodeBlockNodeView.d.ts.map +1 -1
  120. package/dist/plugins/code-block.mjs +1 -1
  121. package/dist/plugins/font/FontPlugin.d.ts +0 -6
  122. package/dist/plugins/font/FontPlugin.d.ts.map +1 -1
  123. package/dist/plugins/font-size/FontSizeOperations.d.ts.map +1 -1
  124. package/dist/plugins/font-size/FontSizePlugin.d.ts +0 -5
  125. package/dist/plugins/font-size/FontSizePlugin.d.ts.map +1 -1
  126. package/dist/plugins/font-size.mjs +1 -1
  127. package/dist/plugins/font.mjs +1 -1
  128. package/dist/plugins/gap-cursor.mjs +2 -2
  129. package/dist/plugins/hard-break.mjs +2 -25
  130. package/dist/plugins/hard-break.mjs.map +1 -1
  131. package/dist/plugins/heading/HeadingBlockTypePicker.d.ts +1 -7
  132. package/dist/plugins/heading/HeadingBlockTypePicker.d.ts.map +1 -1
  133. package/dist/plugins/heading/HeadingPlugin.d.ts +0 -6
  134. package/dist/plugins/heading/HeadingPlugin.d.ts.map +1 -1
  135. package/dist/plugins/heading.mjs +1 -1
  136. package/dist/plugins/highlight/HighlightPlugin.d.ts.map +1 -1
  137. package/dist/plugins/highlight.mjs +1 -1
  138. package/dist/plugins/horizontal-rule.mjs +1 -1
  139. package/dist/plugins/image/ImageNodeView.d.ts.map +1 -1
  140. package/dist/plugins/image/ImagePlugin.d.ts.map +1 -1
  141. package/dist/plugins/image.mjs +1 -1
  142. package/dist/plugins/link/LinkPlugin.d.ts.map +1 -1
  143. package/dist/plugins/link.mjs +1 -1
  144. package/dist/plugins/list/ListPlugin.d.ts.map +1 -1
  145. package/dist/plugins/list.mjs +1 -1
  146. package/dist/plugins/print/PrintContentPreparer.d.ts.map +1 -1
  147. package/dist/plugins/shared/ColorGrid.d.ts +25 -0
  148. package/dist/plugins/shared/ColorGrid.d.ts.map +1 -0
  149. package/dist/plugins/shared/ColorMarkOperations.d.ts.map +1 -1
  150. package/dist/plugins/shared/ColorPickerPopup.d.ts.map +1 -1
  151. package/dist/plugins/shared/ColorValidation.d.ts +13 -2
  152. package/dist/plugins/shared/ColorValidation.d.ts.map +1 -1
  153. package/dist/plugins/shared/PopupKeyboardPatterns.d.ts +43 -0
  154. package/dist/plugins/shared/PopupKeyboardPatterns.d.ts.map +1 -0
  155. package/dist/plugins/shared/PopupManager.d.ts +45 -0
  156. package/dist/plugins/shared/PopupManager.d.ts.map +1 -0
  157. package/dist/plugins/shared/PopupPositioning.d.ts +21 -0
  158. package/dist/plugins/shared/PopupPositioning.d.ts.map +1 -0
  159. package/dist/plugins/strikethrough.mjs +1 -1
  160. package/dist/plugins/super-sub.mjs +1 -1
  161. package/dist/plugins/table/TableBorderColor.d.ts.map +1 -1
  162. package/dist/plugins/table/TableContextMenu.d.ts +2 -1
  163. package/dist/plugins/table/TableContextMenu.d.ts.map +1 -1
  164. package/dist/plugins/table/TableControls.d.ts.map +1 -1
  165. package/dist/plugins/table/TableControlsDOM.d.ts.map +1 -1
  166. package/dist/plugins/table/TableControlsLayout.d.ts.map +1 -1
  167. package/dist/plugins/table/TableNodeViews.d.ts.map +1 -1
  168. package/dist/plugins/table.mjs +1 -1
  169. package/dist/plugins/text-color/TextColorPlugin.d.ts.map +1 -1
  170. package/dist/plugins/text-color.mjs +1 -1
  171. package/dist/plugins/text-formatting.mjs +1 -1
  172. package/dist/plugins/toolbar/ToolbarItem.d.ts +11 -2
  173. package/dist/plugins/toolbar/ToolbarItem.d.ts.map +1 -1
  174. package/dist/plugins/toolbar/ToolbarOverflowController.d.ts +5 -1
  175. package/dist/plugins/toolbar/ToolbarOverflowController.d.ts.map +1 -1
  176. package/dist/plugins/toolbar/ToolbarPlugin.d.ts +1 -0
  177. package/dist/plugins/toolbar/ToolbarPlugin.d.ts.map +1 -1
  178. package/dist/plugins/toolbar/ToolbarPopupController.d.ts +9 -1
  179. package/dist/plugins/toolbar/ToolbarPopupController.d.ts.map +1 -1
  180. package/dist/plugins/toolbar/ToolbarRenderers.d.ts.map +1 -1
  181. package/dist/plugins/toolbar/ToolbarTooltip.d.ts.map +1 -1
  182. package/dist/plugins/toolbar/index.d.ts +1 -1
  183. package/dist/plugins/toolbar/index.d.ts.map +1 -1
  184. package/dist/plugins/toolbar.mjs +1 -1
  185. package/dist/state/BlockTreeOps.d.ts +21 -0
  186. package/dist/state/BlockTreeOps.d.ts.map +1 -0
  187. package/dist/state/InlineContentOps.d.ts +37 -0
  188. package/dist/state/InlineContentOps.d.ts.map +1 -0
  189. package/dist/state/StepApplication.d.ts.map +1 -1
  190. package/dist/style/StyleRuntime.d.ts +38 -0
  191. package/dist/style/StyleRuntime.d.ts.map +1 -0
  192. package/dist/test/PluginTestUtils.d.ts +4 -0
  193. package/dist/test/PluginTestUtils.d.ts.map +1 -1
  194. package/dist/view/Reconciler.d.ts.map +1 -1
  195. package/package.json +2 -2
  196. package/dist/chunks/ColorNames-BdsHwA2f.mjs +0 -59
  197. package/dist/chunks/ColorNames-BdsHwA2f.mjs.map +0 -1
  198. package/dist/chunks/ColorPickerPopup-xL8ZUfpB.mjs +0 -125
  199. package/dist/chunks/ColorPickerPopup-xL8ZUfpB.mjs.map +0 -1
  200. package/dist/chunks/Commands-CicwYoTQ.mjs +0 -286
  201. package/dist/chunks/Commands-CicwYoTQ.mjs.map +0 -1
  202. package/dist/chunks/MarkCommands-CC37WA7Z.mjs +0 -94
  203. package/dist/chunks/MarkCommands-CC37WA7Z.mjs.map +0 -1
  204. package/dist/chunks/ToolbarPlugin-B6JETWaw.mjs.map +0 -1
  205. package/dist/chunks/index-B9GkDVsx.mjs +0 -187
  206. package/dist/chunks/index-B9GkDVsx.mjs.map +0 -1
  207. package/dist/chunks/index-CKPrAOr6.mjs +0 -209
  208. package/dist/chunks/index-CKPrAOr6.mjs.map +0 -1
  209. package/dist/chunks/index-CNs4QQ8l.mjs.map +0 -1
  210. package/dist/chunks/index-CflvcXSd.mjs.map +0 -1
  211. package/dist/chunks/index-CoeD4T9-.mjs.map +0 -1
  212. package/dist/chunks/index-D0s0Q8Wc.mjs.map +0 -1
  213. package/dist/chunks/index-DfzCof6H.mjs +0 -191
  214. package/dist/chunks/index-DfzCof6H.mjs.map +0 -1
  215. package/dist/chunks/index-DyIwN_67.mjs +0 -404
  216. package/dist/chunks/index-DyIwN_67.mjs.map +0 -1
  217. package/dist/chunks/index-FlTg80Pk.mjs.map +0 -1
  218. package/dist/chunks/index-pxbbDHVH.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-D0s0Q8Wc.mjs","sources":["../../src/editor/styles/list.ts","../../src/plugins/list/ListLocale.ts","../../src/plugins/list/ListPlugin.ts"],"sourcesContent":["/** Width of the list marker / checkbox area in pixels. */\nexport const LIST_MARKER_WIDTH = 24;\n\n/** 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 ${LIST_MARKER_WIDTH}px;\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: ${LIST_MARKER_WIDTH}px;\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, LIST_MARKER_WIDTH } 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 {\n\tcreateCollapsedSelection,\n\tisCollapsed,\n\tisGapCursor,\n\tisNodeSelection,\n} from '../../model/Selection.js';\nimport { type BlockId, blockId, 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\t/**\n\t * When true, checklist checkboxes remain interactive even in read-only mode.\n\t * Defaults to false (checkboxes are fully read-only).\n\t */\n\treadonly interactiveCheckboxes?: 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\tprivate context: PluginContext | null = null;\n\tprivate checkboxClickHandler: ((e: MouseEvent) => void) | null = null;\n\n\tconstructor(config?: Partial<ListConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.context = context;\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\tthis.registerCheckboxClickHandler(context);\n\t}\n\n\tdestroy(): void {\n\t\tif (this.checkboxClickHandler && this.context) {\n\t\t\tconst container: HTMLElement = this.context.getContainer();\n\t\t\tcontainer.removeEventListener('mousedown', this.checkboxClickHandler);\n\t\t}\n\t\tthis.checkboxClickHandler = null;\n\t\tthis.context = null;\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 * LIST_MARKER_WIDTH}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', () => this.toggleChecked(context), {\n\t\t\t\treadonlyAllowed: true,\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) || isGapCursor(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) || isGapCursor(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) || isGapCursor(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) || isGapCursor(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) || isGapCursor(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, targetId?: BlockId): boolean {\n\t\tif (context.isReadOnly() && !this.config.interactiveCheckboxes) return false;\n\n\t\tconst state = context.getState();\n\t\tconst bid: BlockId | null =\n\t\t\ttargetId ??\n\t\t\t(isNodeSelection(state.selection) || isGapCursor(state.selection)\n\t\t\t\t? null\n\t\t\t\t: state.selection.anchor.blockId);\n\t\tif (!bid) return false;\n\n\t\tconst block = state.getBlock(bid);\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: boolean = !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(bid, 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) || isGapCursor(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) || isGapCursor(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// --- Checkbox Click Handling ---\n\n\tprivate registerCheckboxClickHandler(context: PluginContext): void {\n\t\tif (!this.config.types.includes('checklist')) return;\n\n\t\tthis.checkboxClickHandler = (e: MouseEvent) => {\n\t\t\tif (context.isReadOnly() && !this.config.interactiveCheckboxes) return;\n\n\t\t\tconst target: EventTarget | null = e.target;\n\t\t\tif (!(target instanceof HTMLElement)) return;\n\n\t\t\tconst li: HTMLElement | null = target.closest('.notectl-list-item--checklist');\n\t\t\tif (!li) return;\n\n\t\t\tconst rect: DOMRect = li.getBoundingClientRect();\n\t\t\tif (e.clientX - rect.left >= LIST_MARKER_WIDTH) return;\n\n\t\t\te.preventDefault();\n\n\t\t\tconst bid: string | null = li.getAttribute('data-block-id');\n\t\t\tif (!bid) return;\n\n\t\t\tthis.toggleChecked(context, blockId(bid));\n\t\t};\n\n\t\tconst container: HTMLElement = context.getContainer();\n\t\tcontainer.addEventListener('mousedown', this.checkboxClickHandler);\n\t}\n\n\t// --- Helpers ---\n\n\tprivate isListActive(state: EditorState, listType: ListType): boolean {\n\t\tif (isNodeSelection(state.selection) || isGapCursor(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","context","checkboxClickHandler","this","resolvePluginLocale","registerStyleSheet","registerNodeSpec","registerCommands","registerKeymaps","registerInputRules","registerToolbarItems","registerCheckboxClickHandler","destroy","getContainer","removeEventListener","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","readonlyAllowed","registerKeymap","Enter","handleEnter","Backspace","handleBackspace","Tab","registerInputRule","pattern","handler","state","match","start","_end","sel","selection","isNodeSelection","isGapCursor","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","targetId","isReadOnly","interactiveCheckboxes","bid","offset","getBlockText","newBlockId","generateBlockId","splitBlock","e","target","HTMLElement","closest","rect","getBoundingClientRect","clientX","left","preventDefault","getAttribute","addEventListener","filter"],"mappings":"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"}
@@ -1,191 +0,0 @@
1
- import { f as t } from "./Commands-CicwYoTQ.mjs";
2
- import { r as n } from "./resolvePluginLocale-B4w1OkPy.mjs";
3
- import { i as e } from "./AttrRegistry-I-VdmRnN.mjs";
4
- import { g as o, h as r, w as i } from "./Document-CuwE73FF.mjs";
5
- import { i as l, a, b as s, s as c } from "./Selection-DmFDwiPJ.mjs";
6
- import { m as f } from "./TypeBrands-C09nE2qO.mjs";
7
- import { a as p } from "./ToolbarPlugin-B6JETWaw.mjs";
8
- const m = { label: "Font", tooltip: "Font Family" }, d = { en: m, de: { label: "Schriftart", tooltip: "Schriftfamilie" }, es: { label: "Fuente", tooltip: "Familia de fuente" }, fr: { label: "Police", tooltip: "Famille de police" }, zh: { label: "字体", tooltip: "字体系列" }, ru: { label: "Шрифт", tooltip: "Семейство шрифтов" }, ar: { label: "الخط", tooltip: "عائلة الخط" }, hi: { label: "फ़ॉन्ट", tooltip: "फ़ॉन्ट परिवार" } };
9
- class h {
10
- id = "font";
11
- name = "Font";
12
- priority = 22;
13
- config;
14
- locale;
15
- injectedStyleElement = null;
16
- context = null;
17
- comboLabel = null;
18
- constructor(t2) {
19
- this.config = t2;
20
- }
21
- init(t2) {
22
- this.locale = n(d, t2, this.config.locale), t2.registerStyleSheet("\n/* Font Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--font {\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--font:hover {\n background: var(--notectl-hover-bg);\n border-color: var(--notectl-fg-muted);\n}\n\n.notectl-toolbar-btn--font.notectl-toolbar-btn--active {\n background: var(--notectl-bg);\n border-color: var(--notectl-primary-muted);\n}\n\n.notectl-toolbar-btn--font .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--font .notectl-toolbar-btn__icon svg {\n display: none;\n}\n\n.notectl-font-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-font-select__arrow {\n flex-shrink: 0;\n font-size: 11px;\n color: var(--notectl-fg-muted);\n line-height: 30px;\n}\n\n/* Font Picker Popup */\n.notectl-font-picker {\n min-width: 200px;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.notectl-font-picker__list {\n padding: 4px 0;\n}\n\n.notectl-font-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 line-height: 1.4;\n text-align: left;\n white-space: nowrap;\n font-family: inherit;\n transition: background 0.1s;\n}\n\n.notectl-font-picker__item:hover {\n background: var(--notectl-hover-bg);\n}\n\n.notectl-font-picker__item--active {\n background: var(--notectl-active-bg);\n color: var(--notectl-primary-fg);\n}\n\n.notectl-font-picker__item--active:hover {\n background: var(--notectl-active-bg);\n}\n\n.notectl-font-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-font-picker__label {\n flex: 1;\n}\n\n.notectl-font-picker__separator {\n height: 1px;\n background: var(--notectl-border);\n margin: 4px 8px;\n}\n"), this.context = t2, this.registerMarkSpec(t2), this.registerCommands(t2), this.registerToolbarItem(t2), this.injectFontFaces();
23
- }
24
- destroy() {
25
- this.injectedStyleElement?.remove(), this.injectedStyleElement = null, this.context = null, this.comboLabel = null;
26
- }
27
- onStateChange(t2, n2, e2) {
28
- this.updateComboLabel(n2);
29
- }
30
- registerMarkSpec(t2) {
31
- t2.registerMarkSpec({ type: "font", rank: 6, attrs: { family: { default: "" } }, toDOM(t3) {
32
- const n2 = document.createElement("span"), e2 = t3.attrs?.family ?? "";
33
- return e2 && (n2.style.fontFamily = e2), n2;
34
- }, toHTMLString: (t3, n2) => {
35
- const e2 = String(t3.attrs?.family ?? "");
36
- return e2 ? `<span style="font-family: ${e2}">${n2}</span>` : n2;
37
- }, parseHTML: [{ tag: "span", getAttrs: (t3) => {
38
- const n2 = t3.style.fontFamily;
39
- return !!n2 && { family: n2 };
40
- } }], sanitize: { tags: ["span"] } });
41
- }
42
- registerCommands(t2) {
43
- t2.registerCommand("removeFont", () => {
44
- const n2 = t2.getState();
45
- return this.removeFont(t2, n2);
46
- }), t2.registerCommand("setFont", () => false);
47
- }
48
- get defaultFont() {
49
- if (this.config.defaultFont) {
50
- const t3 = this.config.fonts.find((t4) => t4.name === this.config.defaultFont);
51
- if (t3) return t3;
52
- }
53
- const t2 = this.config.fonts[0];
54
- if (!t2) throw new Error("FontPlugin: fonts list is empty");
55
- return t2;
56
- }
57
- registerToolbarItem(t2) {
58
- const n2 = `<span class="notectl-font-select__label" data-font-label>${this.defaultFont.name}</span><span class="notectl-font-select__arrow">▾</span>`;
59
- t2.registerToolbarItem({ id: "font", group: "format", icon: n2, label: this.locale.label, tooltip: this.locale.tooltip, command: "removeFont", priority: 5, popupType: "custom", separatorAfter: this.config.separatorAfter, renderPopup: (t3, n3) => {
60
- this.renderFontPopup(t3, n3);
61
- }, isActive: (t3) => this.isFontActive(t3) });
62
- }
63
- updateComboLabel(t2) {
64
- if (!this.comboLabel) {
65
- const t3 = this.context?.getPluginContainer("top");
66
- if (!t3) return;
67
- if (this.comboLabel = t3.querySelector("[data-font-label]") ?? null, !this.comboLabel) return;
68
- }
69
- const n2 = this.getActiveFont(t2), e2 = this.resolveFontName(n2);
70
- this.comboLabel.textContent = e2;
71
- }
72
- resolveFontName(t2) {
73
- if (!t2) return this.defaultFont.name;
74
- const n2 = this.config.fonts.find((n3) => n3.family === t2);
75
- return n2?.name ?? (t2.split(",")[0] ?? "").trim().replace(/'/g, "");
76
- }
77
- isFontActive(t2) {
78
- return null !== this.getActiveFont(t2);
79
- }
80
- getActiveFont(t2) {
81
- const n2 = t2.selection;
82
- if (l(n2) || a(n2)) return null;
83
- if (s(n2)) {
84
- if (t2.storedMarks) {
85
- const n3 = t2.storedMarks.find((t3) => "font" === t3.type);
86
- return n3 && e(n3, "font") ? n3.attrs.family ?? null : null;
87
- }
88
- const r3 = t2.getBlock(n2.anchor.blockId);
89
- if (!r3) return null;
90
- const i3 = o(r3, n2.anchor.offset).find((t3) => "font" === t3.type);
91
- return i3 && e(i3, "font") ? i3.attrs.family ?? null : null;
92
- }
93
- const r2 = t2.getBlock(n2.anchor.blockId);
94
- if (!r2) return null;
95
- const i2 = o(r2, n2.anchor.offset).find((t3) => "font" === t3.type);
96
- return i2 && e(i2, "font") ? i2.attrs.family ?? null : null;
97
- }
98
- applyFont(n2, e2, r2) {
99
- const i2 = e2.selection;
100
- if (l(i2) || a(i2)) return false;
101
- if (s(i2)) {
102
- const t2 = e2.getBlock(i2.anchor.blockId);
103
- if (!t2) return false;
104
- const l2 = [...(e2.storedMarks ?? o(t2, i2.anchor.offset)).filter((t3) => "font" !== t3.type), { type: f("font"), attrs: { family: r2 } }], a2 = e2.transaction("command").setStoredMarks(l2, e2.storedMarks).setSelection(i2).build();
105
- return n2.dispatch(a2), true;
106
- }
107
- const p2 = c(i2, e2.getBlockOrder()), m2 = e2.transaction("command"), d2 = { type: f("font"), attrs: { family: r2 } };
108
- return t(e2, p2, (t2, n3, o2) => {
109
- const r3 = e2.getBlock(t2);
110
- if (r3) {
111
- const e3 = this.findFontMarkInRange(r3, n3, o2);
112
- e3 && m2.removeMark(t2, n3, o2, e3);
113
- }
114
- m2.addMark(t2, n3, o2, d2);
115
- }), m2.setSelection(i2), n2.dispatch(m2.build()), true;
116
- }
117
- removeFont(n2, e2) {
118
- const i2 = e2.selection;
119
- if (l(i2) || a(i2)) return false;
120
- if (s(i2)) {
121
- const t2 = e2.getBlock(i2.anchor.blockId);
122
- if (!t2) return false;
123
- const l2 = e2.storedMarks ?? o(t2, i2.anchor.offset);
124
- if (!r(l2, f("font"))) return false;
125
- const a2 = l2.filter((t3) => "font" !== t3.type), s2 = e2.transaction("command").setStoredMarks(a2, e2.storedMarks).setSelection(i2).build();
126
- return n2.dispatch(s2), true;
127
- }
128
- const p2 = c(i2, e2.getBlockOrder()), m2 = e2.transaction("command");
129
- return t(e2, p2, (t2, n3, o2) => {
130
- const r2 = e2.getBlock(t2);
131
- if (r2) {
132
- const e3 = this.findFontMarkInRange(r2, n3, o2);
133
- e3 && m2.removeMark(t2, n3, o2, e3);
134
- }
135
- }), m2.setSelection(i2), n2.dispatch(m2.build()), true;
136
- }
137
- findFontMarkInRange(t2, n2, e2) {
138
- const o2 = i(t2);
139
- let r2 = 0;
140
- for (const t3 of o2) {
141
- const o3 = r2 + t3.text.length;
142
- if (o3 > n2 && r2 < e2) {
143
- const n3 = t3.marks.find((t4) => "font" === t4.type);
144
- if (n3) return n3;
145
- }
146
- r2 = o3;
147
- }
148
- }
149
- injectFontFaces() {
150
- const t2 = [];
151
- for (const n3 of this.config.fonts) if (n3.fontFaces?.length) for (const e2 of n3.fontFaces) {
152
- const o2 = [`font-family: '${(n3.family.split(",")[0] ?? "").trim().replace(/'/g, "")}'`, `src: ${e2.src}`];
153
- e2.weight && o2.push(`font-weight: ${e2.weight}`), e2.style && o2.push(`font-style: ${e2.style}`), o2.push(`font-display: ${e2.display ?? "swap"}`), t2.push(`@font-face {
154
- ${o2.join(";\n ")};
155
- }`);
156
- }
157
- if (0 === t2.length) return;
158
- const n2 = document.createElement("style");
159
- n2.setAttribute("data-notectl-fonts", ""), n2.textContent = t2.join("\n\n"), document.head.appendChild(n2), this.injectedStyleElement = n2;
160
- }
161
- dismissPopup() {
162
- const t2 = this.context?.getService(p);
163
- t2?.closePopup();
164
- }
165
- renderFontPopup(t2, n2) {
166
- t2.classList.add("notectl-font-picker");
167
- const e2 = n2.getState(), o2 = this.getActiveFont(e2), r2 = this.defaultFont.family, i2 = document.createElement("div");
168
- i2.className = "notectl-font-picker__list";
169
- for (const t3 of this.config.fonts) {
170
- const e3 = t3.family === r2, l2 = e3 && !o2 || o2 === t3.family, a2 = this.createFontItem(t3.name, t3.family, l2, (o3) => {
171
- o3.preventDefault(), o3.stopPropagation(), e3 ? n2.executeCommand("removeFont") : this.applyFont(n2, n2.getState(), t3.family), this.dismissPopup();
172
- });
173
- t3.category && a2.setAttribute("data-category", t3.category), i2.appendChild(a2);
174
- }
175
- t2.appendChild(i2);
176
- }
177
- createFontItem(t2, n2, e2, o2) {
178
- const r2 = document.createElement("button");
179
- r2.type = "button", r2.className = "notectl-font-picker__item", e2 && r2.classList.add("notectl-font-picker__item--active");
180
- const i2 = document.createElement("span");
181
- i2.className = "notectl-font-picker__check", i2.textContent = e2 ? "✓" : "", r2.appendChild(i2);
182
- const l2 = document.createElement("span");
183
- return l2.className = "notectl-font-picker__label", l2.textContent = t2, n2 && (l2.style.fontFamily = n2), r2.appendChild(l2), r2.addEventListener("mousedown", o2), r2;
184
- }
185
- }
186
- export {
187
- h as F,
188
- d as a,
189
- m as b
190
- };
191
- //# sourceMappingURL=index-DfzCof6H.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DfzCof6H.mjs","sources":["../../src/editor/styles/font-select.ts","../../src/plugins/font/FontLocale.ts","../../src/plugins/font/FontPlugin.ts"],"sourcesContent":["/** Font picker toolbar combobox + popup styles. */\nexport const FONT_SELECT_CSS = `\n/* Font Select — Combobox-style toolbar button */\n.notectl-toolbar-btn--font {\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--font:hover {\n\tbackground: var(--notectl-hover-bg);\n\tborder-color: var(--notectl-fg-muted);\n}\n\n.notectl-toolbar-btn--font.notectl-toolbar-btn--active {\n\tbackground: var(--notectl-bg);\n\tborder-color: var(--notectl-primary-muted);\n}\n\n.notectl-toolbar-btn--font .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--font .notectl-toolbar-btn__icon svg {\n\tdisplay: none;\n}\n\n.notectl-font-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-font-select__arrow {\n\tflex-shrink: 0;\n\tfont-size: 11px;\n\tcolor: var(--notectl-fg-muted);\n\tline-height: 30px;\n}\n\n/* Font Picker Popup */\n.notectl-font-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-font-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-font-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\tline-height: 1.4;\n\ttext-align: left;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n.notectl-font-picker__item:hover {\n\tbackground: var(--notectl-hover-bg);\n}\n\n.notectl-font-picker__item--active {\n\tbackground: var(--notectl-active-bg);\n\tcolor: var(--notectl-primary-fg);\n}\n\n.notectl-font-picker__item--active:hover {\n\tbackground: var(--notectl-active-bg);\n}\n\n.notectl-font-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-font-picker__label {\n\tflex: 1;\n}\n\n.notectl-font-picker__separator {\n\theight: 1px;\n\tbackground: var(--notectl-border);\n\tmargin: 4px 8px;\n}\n`;\n","/** Locale interface and default English locale for the FontPlugin. */\n\n// --- Locale Interface ---\n\nexport interface FontLocale {\n\treadonly label: string;\n\treadonly tooltip: string;\n}\n\n// --- Default English Locale ---\n\nexport const FONT_LOCALE_EN: FontLocale = {\n\tlabel: 'Font',\n\ttooltip: 'Font Family',\n};\n\n// --- German Locale ---\n\nexport const FONT_LOCALE_DE: FontLocale = {\n\tlabel: 'Schriftart',\n\ttooltip: 'Schriftfamilie',\n};\n\n// --- Spanish Locale ---\n\nexport const FONT_LOCALE_ES: FontLocale = {\n\tlabel: 'Fuente',\n\ttooltip: 'Familia de fuente',\n};\n\n// --- French Locale ---\n\nexport const FONT_LOCALE_FR: FontLocale = {\n\tlabel: 'Police',\n\ttooltip: 'Famille de police',\n};\n\n// --- Chinese (Simplified) Locale ---\n\nexport const FONT_LOCALE_ZH: FontLocale = {\n\tlabel: '字体',\n\ttooltip: '字体系列',\n};\n\n// --- Russian Locale ---\n\nexport const FONT_LOCALE_RU: FontLocale = {\n\tlabel: 'Шрифт',\n\ttooltip: 'Семейство шрифтов',\n};\n\n// --- Arabic Locale ---\n\nexport const FONT_LOCALE_AR: FontLocale = {\n\tlabel: 'الخط',\n\ttooltip: 'عائلة الخط',\n};\n\n// --- Hindi Locale ---\n\nexport const FONT_LOCALE_HI: FontLocale = {\n\tlabel: 'फ़ॉन्ट',\n\ttooltip: 'फ़ॉन्ट परिवार',\n};\n\n// --- Locale Map ---\n\nexport const FONT_LOCALES: Record<string, FontLocale> = {\n\ten: FONT_LOCALE_EN,\n\tde: FONT_LOCALE_DE,\n\tes: FONT_LOCALE_ES,\n\tfr: FONT_LOCALE_FR,\n\tzh: FONT_LOCALE_ZH,\n\tru: FONT_LOCALE_RU,\n\tar: FONT_LOCALE_AR,\n\thi: FONT_LOCALE_HI,\n};\n","/**\n * FontPlugin: registers a font-family mark, a combobox-style toolbar selector\n * for font selection, and a developer-friendly API for registering custom fonts\n * (WOFF2, TTF, OTF).\n */\n\nimport { forEachBlockInRange } from '../../commands/Commands.js';\nimport { FONT_SELECT_CSS } from '../../editor/styles/font-select.js';\nimport { resolvePluginLocale } from '../../i18n/resolvePluginLocale.js';\nimport { isMarkOfType } from '../../model/AttrRegistry.js';\nimport { getBlockMarksAtOffset, getTextChildren, hasMark } from '../../model/Document.js';\nimport type { BlockNode, Mark } from '../../model/Document.js';\nimport {\n\tisCollapsed,\n\tisGapCursor,\n\tisNodeSelection,\n\tselectionRange,\n} from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { ToolbarServiceKey } from '../toolbar/ToolbarPlugin.js';\nimport { FONT_LOCALES, type FontLocale } from './FontLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tfont: { family: string };\n\t}\n}\n\n// --- Public Types ---\n\n/** Describes a single @font-face source. */\nexport interface FontFaceDescriptor {\n\t/** CSS `src` value, e.g. `\"url('/fonts/My.woff2') format('woff2')\"`. */\n\treadonly src: string;\n\t/** Font weight, e.g. `'400'` or `'300 700'` for variable fonts. */\n\treadonly weight?: string;\n\t/** Font style, e.g. `'normal'` or `'italic'`. */\n\treadonly style?: string;\n\t/** Font display strategy. Defaults to `'swap'`. */\n\treadonly display?: string;\n}\n\n/** Defines a font available in the editor. */\nexport interface FontDefinition {\n\t/** Display name shown in the toolbar dropdown. */\n\treadonly name: string;\n\t/** CSS `font-family` value, e.g. `\"'Fira Code', monospace\"`. */\n\treadonly family: string;\n\t/** Font category for grouping in the UI. */\n\treadonly category?: 'serif' | 'sans-serif' | 'monospace' | 'display' | 'handwriting';\n\t/**\n\t * Optional `@font-face` descriptors. When provided, the plugin\n\t * auto-injects the corresponding CSS rules into the document.\n\t */\n\treadonly fontFaces?: readonly FontFaceDescriptor[];\n}\n\n// --- Configuration ---\n\nexport interface FontConfig {\n\t/**\n\t * Fonts available in the editor. System fonts require no `fontFaces`.\n\t * Custom fonts with `fontFaces` get their `@font-face` rules auto-injected.\n\t *\n\t * Use `STARTER_FONTS` for a pre-configured set of fonts:\n\t * ```ts\n\t * new FontPlugin({ fonts: [...STARTER_FONTS] })\n\t * ```\n\t */\n\treadonly fonts: readonly FontDefinition[];\n\t/**\n\t * Name of the font that acts as the editor's default.\n\t * Selecting this font removes the mark (since the editor already uses it).\n\t * Defaults to the first font in the list.\n\t */\n\treadonly defaultFont?: string;\n\t/** When true, a separator is rendered after the font toolbar item. */\n\treadonly separatorAfter?: boolean;\n\treadonly locale?: FontLocale;\n}\n\n// --- Plugin ---\n\nexport class FontPlugin implements Plugin {\n\treadonly id = 'font';\n\treadonly name = 'Font';\n\treadonly priority = 22;\n\n\tprivate readonly config: FontConfig;\n\tprivate locale!: FontLocale;\n\tprivate injectedStyleElement: HTMLStyleElement | null = null;\n\tprivate context: PluginContext | null = null;\n\tprivate comboLabel: HTMLSpanElement | null = null;\n\n\tconstructor(config: FontConfig) {\n\t\tthis.config = config;\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tthis.locale = resolvePluginLocale(FONT_LOCALES, context, this.config.locale);\n\n\t\tcontext.registerStyleSheet(FONT_SELECT_CSS);\n\t\tthis.context = context;\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.injectFontFaces();\n\t}\n\n\tdestroy(): void {\n\t\tthis.injectedStyleElement?.remove();\n\t\tthis.injectedStyleElement = null;\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\t// --- Schema ---\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'font',\n\t\t\trank: 6,\n\t\t\tattrs: {\n\t\t\t\tfamily: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span: HTMLElement = document.createElement('span');\n\t\t\t\tconst family: string = mark.attrs?.family ?? '';\n\t\t\t\tif (family) {\n\t\t\t\t\tspan.style.fontFamily = family;\n\t\t\t\t}\n\t\t\t\treturn span;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst family: string = String(mark.attrs?.family ?? '');\n\t\t\t\tif (!family) return content;\n\t\t\t\treturn `<span style=\"font-family: ${family}\">${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 family: string = el.style.fontFamily;\n\t\t\t\t\t\tif (!family) return false;\n\t\t\t\t\t\treturn { family };\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\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeFont', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.removeFont(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setFont', () => {\n\t\t\treturn false;\n\t\t});\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate get defaultFont(): FontDefinition {\n\t\tif (this.config.defaultFont) {\n\t\t\tconst found: FontDefinition | undefined = this.config.fonts.find(\n\t\t\t\t(f) => f.name === this.config.defaultFont,\n\t\t\t);\n\t\t\tif (found) return found;\n\t\t}\n\t\tconst first: FontDefinition | undefined = this.config.fonts[0];\n\t\tif (!first) throw new Error('FontPlugin: fonts list is empty');\n\t\treturn first;\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\t// The icon content renders as a combobox label + dropdown arrow.\n\t\t// The actual label text is updated via onStateChange → updateComboLabel.\n\t\tconst defaultName: string = this.defaultFont.name;\n\t\tconst label: string = `<span class=\"notectl-font-select__label\" data-font-label>${defaultName}</span>`;\n\t\tconst arrow = '<span class=\"notectl-font-select__arrow\">\\u25BE</span>';\n\t\tconst icon = `${label}${arrow}`;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'font',\n\t\t\tgroup: 'format',\n\t\t\ticon,\n\t\t\tlabel: this.locale.label,\n\t\t\ttooltip: this.locale.tooltip,\n\t\t\tcommand: 'removeFont',\n\t\t\tpriority: 5,\n\t\t\tpopupType: 'custom',\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\trenderPopup: (container, ctx) => {\n\t\t\t\tthis.renderFontPopup(container, ctx);\n\t\t\t},\n\t\t\tisActive: (state) => this.isFontActive(state),\n\t\t});\n\t}\n\n\tprivate updateComboLabel(state: EditorState): void {\n\t\t// Lazily find the label element in the DOM\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-font-label]') ?? null;\n\t\t\tif (!this.comboLabel) return;\n\t\t}\n\n\t\tconst activeFamily: string | null = this.getActiveFont(state);\n\t\tconst displayName: string = this.resolveFontName(activeFamily);\n\t\tthis.comboLabel.textContent = displayName;\n\t}\n\n\tprivate resolveFontName(family: string | null): string {\n\t\tif (!family) return this.defaultFont.name;\n\t\tconst match: FontDefinition | undefined = this.config.fonts.find((f) => f.family === family);\n\t\treturn match?.name ?? (family.split(',')[0] ?? '').trim().replace(/'/g, '');\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isFontActive(state: EditorState): boolean {\n\t\treturn this.getActiveFont(state) !== null;\n\t}\n\n\tgetActiveFont(state: EditorState): string | null {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel) || isGapCursor(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 === 'font');\n\t\t\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? 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 === 'font');\n\t\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? 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 === 'font');\n\t\treturn mark && isMarkOfType(mark, 'font') ? (mark.attrs.family ?? null) : null;\n\t}\n\n\t// --- Font Application ---\n\n\tapplyFont(context: PluginContext, state: EditorState, family: string): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel) || isGapCursor(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 withoutFont = currentMarks.filter((m) => m.type !== 'font');\n\t\t\tconst newMarks = [...withoutFont, { type: markType('font'), attrs: { family } }];\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('font'), attrs: { family } };\n\n\t\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\t\tconst block = state.getBlock(blockId);\n\t\t\tif (block) {\n\t\t\t\tconst existing: Mark | undefined = this.findFontMarkInRange(block, from, to);\n\t\t\t\tif (existing) {\n\t\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t\t}\n\t\t\t}\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 removeFont(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tif (isNodeSelection(sel) || isGapCursor(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('font'))) return false;\n\n\t\t\tconst newMarks = currentMarks.filter((m) => m.type !== 'font');\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\tconst block = state.getBlock(blockId);\n\t\t\tif (block) {\n\t\t\t\tconst existing: Mark | undefined = this.findFontMarkInRange(block, from, to);\n\t\t\t\tif (existing) {\n\t\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tbuilder.setSelection(sel);\n\t\tcontext.dispatch(builder.build());\n\t\treturn true;\n\t}\n\n\t/** Finds the first font mark in a block's text range (for proper step inversion). */\n\tprivate findFontMarkInRange(block: BlockNode, from: number, to: number): Mark | undefined {\n\t\tconst textChildren = getTextChildren(block);\n\t\tlet pos = 0;\n\t\tfor (const node of textChildren) {\n\t\t\tconst nodeEnd: number = pos + node.text.length;\n\t\t\tif (nodeEnd > from && pos < to) {\n\t\t\t\tconst fontMark: Mark | undefined = node.marks.find((m) => m.type === 'font');\n\t\t\t\tif (fontMark) return fontMark;\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// --- @font-face Injection ---\n\n\tprivate injectFontFaces(): void {\n\t\tconst rules: string[] = [];\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tif (!font.fontFaces?.length) continue;\n\n\t\t\tfor (const face of font.fontFaces) {\n\t\t\t\tconst familyName: string = (font.family.split(',')[0] ?? '').trim().replace(/'/g, '');\n\t\t\t\tconst declarations: string[] = [`font-family: '${familyName}'`, `src: ${face.src}`];\n\t\t\t\tif (face.weight) {\n\t\t\t\t\tdeclarations.push(`font-weight: ${face.weight}`);\n\t\t\t\t}\n\t\t\t\tif (face.style) {\n\t\t\t\t\tdeclarations.push(`font-style: ${face.style}`);\n\t\t\t\t}\n\t\t\t\tdeclarations.push(`font-display: ${face.display ?? 'swap'}`);\n\n\t\t\t\trules.push(`@font-face {\\n\\t${declarations.join(';\\n\\t')};\\n}`);\n\t\t\t}\n\t\t}\n\n\t\tif (rules.length === 0) return;\n\n\t\tconst style: HTMLStyleElement = document.createElement('style');\n\t\tstyle.setAttribute('data-notectl-fonts', '');\n\t\tstyle.textContent = rules.join('\\n\\n');\n\t\tdocument.head.appendChild(style);\n\t\tthis.injectedStyleElement = style;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate dismissPopup(): void {\n\t\tconst toolbar = this.context?.getService(ToolbarServiceKey);\n\t\ttoolbar?.closePopup();\n\t}\n\n\tprivate renderFontPopup(container: HTMLElement, context: PluginContext): void {\n\t\tcontainer.classList.add('notectl-font-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst activeFont: string | null = this.getActiveFont(state);\n\t\tconst defaultFamily: string = this.defaultFont.family;\n\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-font-picker__list';\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tconst isDefault: boolean = font.family === defaultFamily;\n\t\t\tconst isActive: boolean = isDefault\n\t\t\t\t? !activeFont || activeFont === font.family\n\t\t\t\t: activeFont === font.family;\n\n\t\t\tconst item: HTMLButtonElement = this.createFontItem(\n\t\t\t\tfont.name,\n\t\t\t\tfont.family,\n\t\t\t\tisActive,\n\t\t\t\t(e: MouseEvent) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tif (isDefault) {\n\t\t\t\t\t\tcontext.executeCommand('removeFont');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.applyFont(context, context.getState(), font.family);\n\t\t\t\t\t}\n\t\t\t\t\tthis.dismissPopup();\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (font.category) {\n\t\t\t\titem.setAttribute('data-category', font.category);\n\t\t\t}\n\n\t\t\tlist.appendChild(item);\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\t}\n\n\tprivate createFontItem(\n\t\tname: string,\n\t\tfamily: string,\n\t\tisActive: boolean,\n\t\thandler: (e: MouseEvent) => void,\n\t): HTMLButtonElement {\n\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\titem.type = 'button';\n\t\titem.className = 'notectl-font-picker__item';\n\n\t\tif (isActive) {\n\t\t\titem.classList.add('notectl-font-picker__item--active');\n\t\t}\n\n\t\t// Checkmark indicator\n\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\tcheck.className = 'notectl-font-picker__check';\n\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\titem.appendChild(check);\n\n\t\t// Font name label (rendered in the font itself for preview)\n\t\tconst label: HTMLSpanElement = document.createElement('span');\n\t\tlabel.className = 'notectl-font-picker__label';\n\t\tlabel.textContent = name;\n\t\tif (family) {\n\t\t\tlabel.style.fontFamily = family;\n\t\t}\n\t\titem.appendChild(label);\n\n\t\titem.addEventListener('mousedown', handler);\n\t\treturn item;\n\t}\n}\n"],"names":["FONT_LOCALE_EN","label","tooltip","FONT_LOCALES","en","de","es","fr","zh","ru","ar","hi","FontPlugin","id","name","priority","config","locale","injectedStyleElement","context","comboLabel","this","resolvePluginLocale","registerStyleSheet","registerMarkSpec","registerCommands","registerToolbarItem","injectFontFaces","destroy","remove","_oldState","newState","_tr","updateComboLabel","type","rank","attrs","family","default","mark","span","document","createElement","style","fontFamily","toHTMLString","content","String","parseHTML","tag","getAttrs","el","sanitize","tags","registerCommand","state","getState","removeFont","defaultFont","found","fonts","find","f","first","Error","icon","group","command","popupType","separatorAfter","renderPopup","container","ctx","renderFontPopup","isActive","isFontActive","getPluginContainer","querySelector","activeFamily","getActiveFont","displayName","resolveFontName","textContent","match","split","trim","replace","sel","selection","isNodeSelection","isGapCursor","isCollapsed","storedMarks","m","isMarkOfType","block","getBlock","anchor","blockId","getBlockMarksAtOffset","offset","anchorBlock","newMarks","filter","markType","tr","transaction","setStoredMarks","setSelection","build","dispatch","range","selectionRange","getBlockOrder","builder","forEachBlockInRange","from","to","existing","findFontMarkInRange","removeMark","addMark","currentMarks","hasMark","textChildren","getTextChildren","pos","node","nodeEnd","text","length","fontMark","marks","rules","font","fontFaces","face","declarations","src","weight","push","display","join","setAttribute","head","appendChild","dismissPopup","toolbar","getService","ToolbarServiceKey","closePopup","classList","add","activeFont","defaultFamily","list","className","isDefault","item","createFontItem","e","preventDefault","stopPropagation","executeCommand","applyFont","category","handler","check","addEventListener"],"mappings":"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"}