@notectl/core 2.3.1 → 2.3.3

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 (197) hide show
  1. package/README.md +1 -1
  2. package/THIRD-PARTY-NOTICES.md +129 -0
  3. package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs → AlignmentPlugin-C9Rr_R-g.mjs} +2 -2
  4. package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs.map → AlignmentPlugin-C9Rr_R-g.mjs.map} +1 -1
  5. package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs → AttributedMarkCommands-BCvmqeFZ.mjs} +2 -2
  6. package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs.map → AttributedMarkCommands-BCvmqeFZ.mjs.map} +1 -1
  7. package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs → BidiIsolationPlugin-Cw2KMk-H.mjs} +2 -2
  8. package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs.map → BidiIsolationPlugin-Cw2KMk-H.mjs.map} +1 -1
  9. package/dist/chunks/{BlockInsertion-CJusvrDL.mjs → BlockInsertion-CYH2gRkY.mjs} +2 -2
  10. package/dist/chunks/{BlockInsertion-CJusvrDL.mjs.map → BlockInsertion-CYH2gRkY.mjs.map} +1 -1
  11. package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs → BlockquotePlugin-0bZSbkyo.mjs} +2 -2
  12. package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs.map → BlockquotePlugin-0bZSbkyo.mjs.map} +1 -1
  13. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs +2 -0
  14. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs.map +1 -0
  15. package/dist/chunks/CodeBlockPlugin-BCJ3faXx.mjs +2 -0
  16. package/dist/chunks/{CodeBlockPlugin-C1hrdbSZ.mjs.map → CodeBlockPlugin-BCJ3faXx.mjs.map} +1 -1
  17. package/dist/chunks/{ColorGrid-C9RQoEWF.mjs → ColorGrid-DQEkJ-0y.mjs} +2 -2
  18. package/dist/chunks/{ColorGrid-C9RQoEWF.mjs.map → ColorGrid-DQEkJ-0y.mjs.map} +1 -1
  19. package/dist/chunks/ColorPickerPopup-CyF26zIU.mjs +2 -0
  20. package/dist/chunks/{ColorPickerPopup-DiA68Pzz.mjs.map → ColorPickerPopup-CyF26zIU.mjs.map} +1 -1
  21. package/dist/chunks/Commands-D5ND50PQ.mjs +2 -0
  22. package/dist/chunks/{Commands-1dFFldi7.mjs.map → Commands-D5ND50PQ.mjs.map} +1 -1
  23. package/dist/chunks/{Decoration-BpoEOANl.mjs → Decoration-BOP1TAUd.mjs} +2 -2
  24. package/dist/chunks/{Decoration-BpoEOANl.mjs.map → Decoration-BOP1TAUd.mjs.map} +1 -1
  25. package/dist/chunks/{FontPlugin-By-TGrQo.mjs → FontPlugin-D041tiLe.mjs} +2 -2
  26. package/dist/chunks/{FontPlugin-By-TGrQo.mjs.map → FontPlugin-D041tiLe.mjs.map} +1 -1
  27. package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs → FontSizePlugin-8CAvj1RD.mjs} +2 -2
  28. package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs.map → FontSizePlugin-8CAvj1RD.mjs.map} +1 -1
  29. package/dist/chunks/{FormulaPlugin-By1befrR.mjs → FormulaPlugin-DJ39BtqV.mjs} +2 -2
  30. package/dist/chunks/FormulaPlugin-DJ39BtqV.mjs.map +1 -0
  31. package/dist/chunks/GapCursorNavigation-DCWOmopl.mjs +2 -0
  32. package/dist/chunks/{GapCursorNavigation-BuXngVu-.mjs.map → GapCursorNavigation-DCWOmopl.mjs.map} +1 -1
  33. package/dist/chunks/GapCursorPlugin-2iR6506y.mjs +2 -0
  34. package/dist/chunks/{GapCursorPlugin-DAxVzXRs.mjs.map → GapCursorPlugin-2iR6506y.mjs.map} +1 -1
  35. package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs → HardBreakPlugin-vniSvTgq.mjs} +2 -2
  36. package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs.map → HardBreakPlugin-vniSvTgq.mjs.map} +1 -1
  37. package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs → HeadingPlugin-DUKsLuMd.mjs} +2 -2
  38. package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs.map → HeadingPlugin-DUKsLuMd.mjs.map} +1 -1
  39. package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs → HighlightPlugin-DRTAE1N5.mjs} +2 -2
  40. package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs.map → HighlightPlugin-DRTAE1N5.mjs.map} +1 -1
  41. package/dist/chunks/HorizontalRulePlugin-B9OvwrKB.mjs +2 -0
  42. package/dist/chunks/{HorizontalRulePlugin-DUVmTQpX.mjs.map → HorizontalRulePlugin-B9OvwrKB.mjs.map} +1 -1
  43. package/dist/chunks/{ImagePlugin-FToCOjd5.mjs → ImagePlugin-CwxTRr6d.mjs} +2 -2
  44. package/dist/chunks/{ImagePlugin-FToCOjd5.mjs.map → ImagePlugin-CwxTRr6d.mjs.map} +1 -1
  45. package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs → InlineCodePlugin-uxgMUX_E.mjs} +2 -2
  46. package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs.map → InlineCodePlugin-uxgMUX_E.mjs.map} +1 -1
  47. package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs → LinkPlugin-CvWHbSkb.mjs} +2 -2
  48. package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs.map → LinkPlugin-CvWHbSkb.mjs.map} +1 -1
  49. package/dist/chunks/{ListPlugin-DAY5ezNs.mjs → ListPlugin-BchSFWVn.mjs} +2 -2
  50. package/dist/chunks/{ListPlugin-DAY5ezNs.mjs.map → ListPlugin-BchSFWVn.mjs.map} +1 -1
  51. package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs → MarkdownHTMLRegistry-Q7l0d6Ma.mjs} +2 -2
  52. package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs.map → MarkdownHTMLRegistry-Q7l0d6Ma.mjs.map} +1 -1
  53. package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs → MarkdownParser-Dp62mfUq.mjs} +2 -2
  54. package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs.map → MarkdownParser-Dp62mfUq.mjs.map} +1 -1
  55. package/dist/chunks/{MarkdownSerializer-J-i28out.mjs → MarkdownSerializer-DBELFAeo.mjs} +2 -2
  56. package/dist/chunks/{MarkdownSerializer-J-i28out.mjs.map → MarkdownSerializer-DBELFAeo.mjs.map} +1 -1
  57. package/dist/chunks/MathFont-BS8IwYh2.mjs +2 -0
  58. package/dist/chunks/MathFont-BS8IwYh2.mjs.map +1 -0
  59. package/dist/chunks/NodeSelectionCommands-WH5snxr_.mjs +2 -0
  60. package/dist/chunks/{NodeSelectionCommands-1PjwUDTJ.mjs.map → NodeSelectionCommands-WH5snxr_.mjs.map} +1 -1
  61. package/dist/chunks/PluginHelpers-KDuTlmXm.mjs +2 -0
  62. package/dist/chunks/{PluginHelpers-Dx_0hfDe.mjs.map → PluginHelpers-KDuTlmXm.mjs.map} +1 -1
  63. package/dist/chunks/{PopupManager-CT-fMZJn.mjs → PopupManager-Cj86uDEB.mjs} +2 -2
  64. package/dist/chunks/{PopupManager-CT-fMZJn.mjs.map → PopupManager-Cj86uDEB.mjs.map} +1 -1
  65. package/dist/chunks/PrintPlugin-D2javl_d.mjs +2 -0
  66. package/dist/chunks/{PrintPlugin-7zz9mhhU.mjs.map → PrintPlugin-D2javl_d.mjs.map} +1 -1
  67. package/dist/chunks/SimpleMark-gTQaSJcO.mjs +2 -0
  68. package/dist/chunks/{SimpleMark-7CQcA4RK.mjs.map → SimpleMark-gTQaSJcO.mjs.map} +1 -1
  69. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs +2 -0
  70. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs.map +1 -0
  71. package/dist/chunks/StarterFonts-BDQPg-cu.mjs +2 -0
  72. package/dist/chunks/StarterFonts-BDQPg-cu.mjs.map +1 -0
  73. package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs → StrikethroughPlugin-BdrG1TTY.mjs} +2 -2
  74. package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs.map → StrikethroughPlugin-BdrG1TTY.mjs.map} +1 -1
  75. package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs → SuperSubPlugin-DTZB0Y3D.mjs} +2 -2
  76. package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs.map → SuperSubPlugin-DTZB0Y3D.mjs.map} +1 -1
  77. package/dist/chunks/{TablePlugin-PJe3zwr-.mjs → TablePlugin-CPvg9YZS.mjs} +2 -2
  78. package/dist/chunks/{TablePlugin-PJe3zwr-.mjs.map → TablePlugin-CPvg9YZS.mjs.map} +1 -1
  79. package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs → TextColorPlugin-Ckg3KWvb.mjs} +2 -2
  80. package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs.map → TextColorPlugin-Ckg3KWvb.mjs.map} +1 -1
  81. package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs → TextDirectionAutoPlugin-DRGbgTlx.mjs} +2 -2
  82. package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs.map → TextDirectionAutoPlugin-DRGbgTlx.mjs.map} +1 -1
  83. package/dist/chunks/TextDirectionPlugin-BCeYyJHo.mjs +2 -0
  84. package/dist/chunks/{TextDirectionPlugin-Bns_03vL.mjs.map → TextDirectionPlugin-BCeYyJHo.mjs.map} +1 -1
  85. package/dist/chunks/TextDirectionService-OFOU6r_s.mjs +2 -0
  86. package/dist/chunks/{TextDirectionService-BcX07mw2.mjs.map → TextDirectionService-OFOU6r_s.mjs.map} +1 -1
  87. package/dist/chunks/TextFormattingPlugin-BhRxSC8q.mjs +2 -0
  88. package/dist/chunks/{TextFormattingPlugin-DBVlePqj.mjs.map → TextFormattingPlugin-BhRxSC8q.mjs.map} +1 -1
  89. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs +3 -0
  90. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs.map +1 -0
  91. package/dist/chunks/ToolbarPlugin-dmTj1jIz.mjs +2 -0
  92. package/dist/chunks/{ToolbarPlugin-DtfGTO_V.mjs.map → ToolbarPlugin-dmTj1jIz.mjs.map} +1 -1
  93. package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs → VideoPlugin-BugkI7-m.mjs} +2 -2
  94. package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs.map → VideoPlugin-BugkI7-m.mjs.map} +1 -1
  95. package/dist/chunks/XmlSupport-DIXH5on9.mjs +2 -0
  96. package/dist/chunks/XmlSupport-DIXH5on9.mjs.map +1 -0
  97. package/dist/chunks/full-JM0-SwWy.mjs +2 -0
  98. package/dist/chunks/{full-DSWM4cKQ.mjs.map → full-JM0-SwWy.mjs.map} +1 -1
  99. package/dist/chunks/minimal-DSlR2A27.mjs +2 -0
  100. package/dist/chunks/{minimal-CFkkPXef.mjs.map → minimal-DSlR2A27.mjs.map} +1 -1
  101. package/dist/chunks/register-BjsdJ3Aq.mjs +2 -0
  102. package/dist/chunks/register-BjsdJ3Aq.mjs.map +1 -0
  103. package/dist/chunks/src-5GKFQ2mQ.mjs +2 -0
  104. package/dist/chunks/src-5GKFQ2mQ.mjs.map +1 -0
  105. package/dist/chunks/xml-BsV44TrJ.mjs +2 -0
  106. package/dist/chunks/xml-BsV44TrJ.mjs.map +1 -0
  107. package/dist/editor/NotectlEditor.d.ts.map +1 -1
  108. package/dist/fonts/math.d.ts +3 -0
  109. package/dist/fonts/math.d.ts.map +1 -0
  110. package/dist/fonts/math.mjs +1 -0
  111. package/dist/fonts/starter.d.ts +3 -0
  112. package/dist/fonts/starter.d.ts.map +1 -0
  113. package/dist/fonts/starter.mjs +1 -0
  114. package/dist/fonts.d.ts +4 -4
  115. package/dist/fonts.mjs +1 -1
  116. package/dist/full.d.ts +1 -1
  117. package/dist/full.mjs +1 -1
  118. package/dist/index.d.ts +2 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/markdown.mjs +1 -1
  121. package/dist/notectl-core.mjs +1 -1
  122. package/dist/notectl-core.umd.js +1 -1
  123. package/dist/notectl-core.umd.js.map +1 -1
  124. package/dist/plugins/alignment.mjs +1 -1
  125. package/dist/plugins/bidi-isolation.mjs +1 -1
  126. package/dist/plugins/blockquote.mjs +1 -1
  127. package/dist/plugins/caret-navigation.mjs +1 -1
  128. package/dist/plugins/code-block/CodeBlockHighlighting.d.ts.map +1 -1
  129. package/dist/plugins/code-block.mjs +1 -1
  130. package/dist/plugins/font-size.mjs +1 -1
  131. package/dist/plugins/font.mjs +1 -1
  132. package/dist/plugins/formula/FormulaTypes.d.ts +1 -1
  133. package/dist/plugins/formula.mjs +1 -1
  134. package/dist/plugins/gap-cursor.mjs +1 -1
  135. package/dist/plugins/hard-break.mjs +1 -1
  136. package/dist/plugins/heading.mjs +1 -1
  137. package/dist/plugins/highlight.mjs +1 -1
  138. package/dist/plugins/horizontal-rule.mjs +1 -1
  139. package/dist/plugins/image.mjs +1 -1
  140. package/dist/plugins/inline-code.mjs +1 -1
  141. package/dist/plugins/language.mjs +1 -1
  142. package/dist/plugins/link.mjs +1 -1
  143. package/dist/plugins/list.mjs +1 -1
  144. package/dist/plugins/print.mjs +1 -1
  145. package/dist/plugins/shared.mjs +1 -1
  146. package/dist/plugins/smart-paste/SmartPastePlugin.d.ts.map +1 -1
  147. package/dist/plugins/smart-paste.mjs +1 -1
  148. package/dist/plugins/strikethrough.mjs +1 -1
  149. package/dist/plugins/super-sub.mjs +1 -1
  150. package/dist/plugins/table.mjs +1 -1
  151. package/dist/plugins/text-color.mjs +1 -1
  152. package/dist/plugins/text-direction-auto.mjs +1 -1
  153. package/dist/plugins/text-direction.mjs +1 -1
  154. package/dist/plugins/text-formatting.mjs +1 -1
  155. package/dist/plugins/toolbar.mjs +1 -1
  156. package/dist/plugins/video.mjs +1 -1
  157. package/dist/presets/full.d.ts +1 -1
  158. package/dist/presets/full.mjs +1 -1
  159. package/dist/presets/minimal.d.ts +1 -1
  160. package/dist/presets/minimal.mjs +1 -1
  161. package/dist/presets.d.ts +1 -1
  162. package/dist/presets.mjs +1 -1
  163. package/dist/register.d.ts +3 -0
  164. package/dist/register.d.ts.map +1 -0
  165. package/dist/register.mjs +1 -0
  166. package/package.json +24 -223
  167. package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs +0 -2
  168. package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs.map +0 -1
  169. package/dist/chunks/CodeBlockPlugin-C1hrdbSZ.mjs +0 -2
  170. package/dist/chunks/ColorPickerPopup-DiA68Pzz.mjs +0 -2
  171. package/dist/chunks/Commands-1dFFldi7.mjs +0 -2
  172. package/dist/chunks/FormulaPlugin-By1befrR.mjs.map +0 -1
  173. package/dist/chunks/GapCursorNavigation-BuXngVu-.mjs +0 -2
  174. package/dist/chunks/GapCursorPlugin-DAxVzXRs.mjs +0 -2
  175. package/dist/chunks/HorizontalRulePlugin-DUVmTQpX.mjs +0 -2
  176. package/dist/chunks/NodeSelectionCommands-1PjwUDTJ.mjs +0 -2
  177. package/dist/chunks/PluginHelpers-Dx_0hfDe.mjs +0 -2
  178. package/dist/chunks/PrintPlugin-7zz9mhhU.mjs +0 -2
  179. package/dist/chunks/PrintTypes-CxU69qu3.mjs +0 -3
  180. package/dist/chunks/PrintTypes-CxU69qu3.mjs.map +0 -1
  181. package/dist/chunks/SimpleMark-7CQcA4RK.mjs +0 -2
  182. package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs +0 -2
  183. package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs.map +0 -1
  184. package/dist/chunks/TextDirectionPlugin-Bns_03vL.mjs +0 -2
  185. package/dist/chunks/TextDirectionService-BcX07mw2.mjs +0 -2
  186. package/dist/chunks/TextFormattingPlugin-DBVlePqj.mjs +0 -2
  187. package/dist/chunks/ToolbarPlugin-DtfGTO_V.mjs +0 -2
  188. package/dist/chunks/XmlDetector-D7TQpw-e.mjs +0 -2
  189. package/dist/chunks/XmlDetector-D7TQpw-e.mjs.map +0 -1
  190. package/dist/chunks/XmlSupport-BYiRwlkK.mjs +0 -2
  191. package/dist/chunks/XmlSupport-BYiRwlkK.mjs.map +0 -1
  192. package/dist/chunks/fonts-DQC6Uj4r.mjs +0 -2
  193. package/dist/chunks/fonts-DQC6Uj4r.mjs.map +0 -1
  194. package/dist/chunks/full-DSWM4cKQ.mjs +0 -2
  195. package/dist/chunks/minimal-CFkkPXef.mjs +0 -2
  196. package/dist/chunks/src-DiAOfuOT.mjs +0 -2
  197. package/dist/chunks/src-DiAOfuOT.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"InlineCodePlugin-pISIoGQE.mjs","names":[],"sources":["../../src/plugins/inline-code/InlineCodeLocale.ts","../../src/plugins/inline-code/InlineCodePlugin.ts"],"sourcesContent":["/**\n * Locale interface and default English locale for the InlineCodePlugin.\n */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\n// --- Locale Interface ---\n\nexport interface InlineCodeLocale {\n\treadonly label: string;\n\treadonly tooltip: (shortcut: string) => string;\n}\n\n// --- Default English Locale ---\n\nexport const INLINE_CODE_LOCALE_EN: InlineCodeLocale = {\n\tlabel: 'Inline Code',\n\ttooltip: (shortcut: string) => `Inline Code (${shortcut})`,\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<InlineCodeLocale> = import.meta.glob<{\n\tdefault: InlineCodeLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadInlineCodeLocale(lang: string): Promise<InlineCodeLocale> {\n\treturn loadLocaleModule(localeModules, lang, INLINE_CODE_LOCALE_EN);\n}\n","/**\n * InlineCodePlugin: registers an inline code mark with MarkSpec,\n * toggle command, keyboard shortcut (Mod-E), backtick InputRule,\n * toolbar button, and mark exclusivity middleware.\n */\n\nimport type { BlockNode, Mark } from '../../model/Document.js';\nimport { getBlockContentSegmentsInRange } from '../../model/Document.js';\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { Step } from '../../state/Steps.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { registerSimpleMark } from '../shared/SimpleMark.js';\nimport {\n\tINLINE_CODE_LOCALE_EN,\n\ttype InlineCodeLocale,\n\tloadInlineCodeLocale,\n} from './InlineCodeLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tcode: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\nexport interface InlineCodeConfig {\n\t/** Show toolbar button. Default: true */\n\treadonly toolbar?: boolean;\n\t/** Override keyboard shortcut. Set to null to disable. Default: 'Mod-E' */\n\treadonly keymap?: string | null;\n\t/** Enable backtick InputRule. Default: true */\n\treadonly inputRule?: boolean;\n\t/** Override locale strings */\n\treadonly locale?: InlineCodeLocale;\n}\n\nconst DEFAULT_CONFIG: InlineCodeConfig = {\n\ttoolbar: true,\n\tkeymap: 'Mod-E',\n\tinputRule: true,\n};\n\n// --- CSS ---\n\nconst INLINE_CODE_CSS = `\n.notectl-content code {\n\tfont-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;\n\tfont-size: 0.9em;\n\tpadding: 0.15em 0.35em;\n\tborder-radius: 4px;\n\tbackground-color: var(--notectl-code-bg);\n\tcolor: var(--notectl-code-color);\n\tword-break: break-word;\n}\n@media (forced-colors: active) {\n\t.notectl-content code {\n\t\tborder: 1px solid LinkText;\n\t}\n}\n`;\n\n// --- Mark Exclusivity ---\n\nconst EXCLUDED_WITH_CODE: ReadonlySet<string> = new Set([\n\t'bold',\n\t'italic',\n\t'underline',\n\t'strikethrough',\n\t'highlight',\n\t'font',\n\t'fontSize',\n\t'superscript',\n\t'subscript',\n]);\n\n// --- Plugin ---\n\nexport class InlineCodePlugin implements Plugin {\n\treadonly id = 'inline-code';\n\treadonly name = 'Inline Code';\n\treadonly priority = 22;\n\n\tprivate readonly config: InlineCodeConfig;\n\tprivate locale!: InlineCodeLocale;\n\n\tconstructor(config?: Partial<InlineCodeConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tINLINE_CODE_LOCALE_EN,\n\t\t\tloadInlineCodeLocale,\n\t\t);\n\t\tcontext.registerStyleSheet(INLINE_CODE_CSS);\n\t\tthis.registerMark(context);\n\n\t\tif (this.config.inputRule !== false) {\n\t\t\tthis.registerInputRule(context);\n\t\t}\n\t\tthis.registerExclusivityMiddleware(context);\n\t}\n\n\tprivate registerMark(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6-1.4-1.4z\"/></svg>';\n\n\t\tregisterSimpleMark(context, {\n\t\t\tmarkSpec: {\n\t\t\t\ttype: 'code',\n\t\t\t\trank: 3,\n\t\t\t\ttoDOM() {\n\t\t\t\t\treturn document.createElement('code');\n\t\t\t\t},\n\t\t\t\ttoHTMLString: (_mark, content) => `<code>${content}</code>`,\n\t\t\t\tparseHTML: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'code',\n\t\t\t\t\t\tgetAttrs: (el: HTMLElement) => {\n\t\t\t\t\t\t\tif (el.parentElement?.tagName === 'PRE') return false;\n\t\t\t\t\t\t\treturn {};\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'span',\n\t\t\t\t\t\tgetAttrs: (el: HTMLElement) => {\n\t\t\t\t\t\t\tconst fontFamily: string = el.style.fontFamily.replace(/['\"]/g, '').trim();\n\t\t\t\t\t\t\tif (/^monospace$/i.test(fontFamily)) return {};\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tsanitize: { tags: ['code'] },\n\t\t\t},\n\t\t\tcommand: 'toggleInlineCode',\n\t\t\tkeyBinding: this.config.keymap !== null ? (this.config.keymap ?? 'Mod-E') : null,\n\t\t\ttoolbar:\n\t\t\t\tthis.config.toolbar !== false\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tid: 'inline_code',\n\t\t\t\t\t\t\tgroup: 'format',\n\t\t\t\t\t\t\ticon,\n\t\t\t\t\t\t\tlabel: this.locale.label,\n\t\t\t\t\t\t\ttooltip: this.locale.tooltip(formatShortcut(this.config.keymap ?? 'Mod-E')),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\tprivate registerInputRule(context: PluginContext): void {\n\t\t// The inline-node placeholder (U+FFFC) is excluded from the span body so\n\t\t// the rule never matches across an inline node nor re-inserts it.\n\t\tconst pattern: RegExp = /(?:^|[^`])(`([^`\\uFFFC]+)`)$/;\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel)) return null;\n\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst innerText: string | undefined = match[2];\n\t\t\t\tconst backtickExpr: string | undefined = match[1];\n\t\t\t\tif (!innerText || !backtickExpr) return null;\n\n\t\t\t\tconst backtickExprStart: number = end - backtickExpr.length;\n\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, backtickExprStart, end)\n\t\t\t\t\t.insertText(sel.anchor.blockId, backtickExprStart, innerText, [\n\t\t\t\t\t\t{ type: markType('code') },\n\t\t\t\t\t])\n\t\t\t\t\t.setSelection(\n\t\t\t\t\t\tcreateCollapsedSelection(sel.anchor.blockId, backtickExprStart + innerText.length),\n\t\t\t\t\t)\n\t\t\t\t\t.build();\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Prevents formatting marks from coexisting with the code mark.\n\t * Bold, italic, underline, etc. are stripped when code is applied,\n\t * and code is blocked on text that already has formatting marks.\n\t * The link mark is allowed to coexist.\n\t */\n\tprivate registerExclusivityMiddleware(context: PluginContext): void {\n\t\tcontext.registerMiddleware(\n\t\t\t(tr, state, next) => {\n\t\t\t\tlet patched = false;\n\t\t\t\tconst patchedSteps: Step[] = [];\n\n\t\t\t\tfor (const step of tr.steps) {\n\t\t\t\t\tif (step.type !== 'addMark') {\n\t\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stepMarkType: string = step.mark.type;\n\n\t\t\t\t\tif (stepMarkType === 'code') {\n\t\t\t\t\t\t// Adding code mark: inject removeMark steps for excluded marks\n\t\t\t\t\t\tconst block: BlockNode | undefined = state.getBlock(step.blockId);\n\t\t\t\t\t\tif (block) {\n\t\t\t\t\t\t\tconst segments = getBlockContentSegmentsInRange(block, step.from, step.to);\n\t\t\t\t\t\t\tconst marksToRemove: Set<string> = new Set();\n\t\t\t\t\t\t\tfor (const seg of segments) {\n\t\t\t\t\t\t\t\tif (seg.kind !== 'text') continue;\n\t\t\t\t\t\t\t\tfor (const m of seg.marks) {\n\t\t\t\t\t\t\t\t\tif (EXCLUDED_WITH_CODE.has(m.type)) {\n\t\t\t\t\t\t\t\t\t\tmarksToRemove.add(m.type);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (const mt of marksToRemove) {\n\t\t\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t\t\t\tpatchedSteps.push({\n\t\t\t\t\t\t\t\t\ttype: 'removeMark',\n\t\t\t\t\t\t\t\t\tblockId: step.blockId,\n\t\t\t\t\t\t\t\t\tfrom: step.from,\n\t\t\t\t\t\t\t\t\tto: step.to,\n\t\t\t\t\t\t\t\t\tmark: { type: markType(mt) },\n\t\t\t\t\t\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (EXCLUDED_WITH_CODE.has(stepMarkType)) {\n\t\t\t\t\t\t// Adding a formatting mark: block if target range has code mark\n\t\t\t\t\t\tconst block: BlockNode | undefined = state.getBlock(step.blockId);\n\t\t\t\t\t\tif (block) {\n\t\t\t\t\t\t\tconst segments = getBlockContentSegmentsInRange(block, step.from, step.to);\n\t\t\t\t\t\t\tconst hasCode: boolean = segments.some(\n\t\t\t\t\t\t\t\t(seg) => seg.kind === 'text' && seg.marks.some((m) => m.type === 'code'),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (hasCode) {\n\t\t\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t\t\t\tcontinue; // skip this step\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t}\n\n\t\t\t\t// Handle stored marks\n\t\t\t\tlet storedMarksAfter: readonly Mark[] | null = tr.storedMarksAfter;\n\t\t\t\tif (storedMarksAfter) {\n\t\t\t\t\tconst hasCode: boolean = storedMarksAfter.some((m) => m.type === 'code');\n\t\t\t\t\tconst hasExcluded: boolean = storedMarksAfter.some((m) => EXCLUDED_WITH_CODE.has(m.type));\n\n\t\t\t\t\tif (hasCode && hasExcluded) {\n\t\t\t\t\t\t// Keep code, strip formatting marks\n\t\t\t\t\t\tstoredMarksAfter = storedMarksAfter.filter((m) => !EXCLUDED_WITH_CODE.has(m.type));\n\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnext(patched ? { ...tr, steps: patchedSteps, storedMarksAfter } : tr);\n\t\t\t},\n\t\t\t{ name: 'inline-code:mark-exclusivity', priority: 50 },\n\t\t);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InlineCodePlugin-uxgMUX_E.mjs","names":[],"sources":["../../src/plugins/inline-code/InlineCodeLocale.ts","../../src/plugins/inline-code/InlineCodePlugin.ts"],"sourcesContent":["/**\n * Locale interface and default English locale for the InlineCodePlugin.\n */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\n// --- Locale Interface ---\n\nexport interface InlineCodeLocale {\n\treadonly label: string;\n\treadonly tooltip: (shortcut: string) => string;\n}\n\n// --- Default English Locale ---\n\nexport const INLINE_CODE_LOCALE_EN: InlineCodeLocale = {\n\tlabel: 'Inline Code',\n\ttooltip: (shortcut: string) => `Inline Code (${shortcut})`,\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<InlineCodeLocale> = import.meta.glob<{\n\tdefault: InlineCodeLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadInlineCodeLocale(lang: string): Promise<InlineCodeLocale> {\n\treturn loadLocaleModule(localeModules, lang, INLINE_CODE_LOCALE_EN);\n}\n","/**\n * InlineCodePlugin: registers an inline code mark with MarkSpec,\n * toggle command, keyboard shortcut (Mod-E), backtick InputRule,\n * toolbar button, and mark exclusivity middleware.\n */\n\nimport type { BlockNode, Mark } from '../../model/Document.js';\nimport { getBlockContentSegmentsInRange } from '../../model/Document.js';\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { Step } from '../../state/Steps.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { registerSimpleMark } from '../shared/SimpleMark.js';\nimport {\n\tINLINE_CODE_LOCALE_EN,\n\ttype InlineCodeLocale,\n\tloadInlineCodeLocale,\n} from './InlineCodeLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tcode: Record<string, never>;\n\t}\n}\n\n// --- Configuration ---\n\nexport interface InlineCodeConfig {\n\t/** Show toolbar button. Default: true */\n\treadonly toolbar?: boolean;\n\t/** Override keyboard shortcut. Set to null to disable. Default: 'Mod-E' */\n\treadonly keymap?: string | null;\n\t/** Enable backtick InputRule. Default: true */\n\treadonly inputRule?: boolean;\n\t/** Override locale strings */\n\treadonly locale?: InlineCodeLocale;\n}\n\nconst DEFAULT_CONFIG: InlineCodeConfig = {\n\ttoolbar: true,\n\tkeymap: 'Mod-E',\n\tinputRule: true,\n};\n\n// --- CSS ---\n\nconst INLINE_CODE_CSS = `\n.notectl-content code {\n\tfont-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;\n\tfont-size: 0.9em;\n\tpadding: 0.15em 0.35em;\n\tborder-radius: 4px;\n\tbackground-color: var(--notectl-code-bg);\n\tcolor: var(--notectl-code-color);\n\tword-break: break-word;\n}\n@media (forced-colors: active) {\n\t.notectl-content code {\n\t\tborder: 1px solid LinkText;\n\t}\n}\n`;\n\n// --- Mark Exclusivity ---\n\nconst EXCLUDED_WITH_CODE: ReadonlySet<string> = new Set([\n\t'bold',\n\t'italic',\n\t'underline',\n\t'strikethrough',\n\t'highlight',\n\t'font',\n\t'fontSize',\n\t'superscript',\n\t'subscript',\n]);\n\n// --- Plugin ---\n\nexport class InlineCodePlugin implements Plugin {\n\treadonly id = 'inline-code';\n\treadonly name = 'Inline Code';\n\treadonly priority = 22;\n\n\tprivate readonly config: InlineCodeConfig;\n\tprivate locale!: InlineCodeLocale;\n\n\tconstructor(config?: Partial<InlineCodeConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tINLINE_CODE_LOCALE_EN,\n\t\t\tloadInlineCodeLocale,\n\t\t);\n\t\tcontext.registerStyleSheet(INLINE_CODE_CSS);\n\t\tthis.registerMark(context);\n\n\t\tif (this.config.inputRule !== false) {\n\t\t\tthis.registerInputRule(context);\n\t\t}\n\t\tthis.registerExclusivityMiddleware(context);\n\t}\n\n\tprivate registerMark(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6-1.4-1.4z\"/></svg>';\n\n\t\tregisterSimpleMark(context, {\n\t\t\tmarkSpec: {\n\t\t\t\ttype: 'code',\n\t\t\t\trank: 3,\n\t\t\t\ttoDOM() {\n\t\t\t\t\treturn document.createElement('code');\n\t\t\t\t},\n\t\t\t\ttoHTMLString: (_mark, content) => `<code>${content}</code>`,\n\t\t\t\tparseHTML: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'code',\n\t\t\t\t\t\tgetAttrs: (el: HTMLElement) => {\n\t\t\t\t\t\t\tif (el.parentElement?.tagName === 'PRE') return false;\n\t\t\t\t\t\t\treturn {};\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'span',\n\t\t\t\t\t\tgetAttrs: (el: HTMLElement) => {\n\t\t\t\t\t\t\tconst fontFamily: string = el.style.fontFamily.replace(/['\"]/g, '').trim();\n\t\t\t\t\t\t\tif (/^monospace$/i.test(fontFamily)) return {};\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tsanitize: { tags: ['code'] },\n\t\t\t},\n\t\t\tcommand: 'toggleInlineCode',\n\t\t\tkeyBinding: this.config.keymap !== null ? (this.config.keymap ?? 'Mod-E') : null,\n\t\t\ttoolbar:\n\t\t\t\tthis.config.toolbar !== false\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tid: 'inline_code',\n\t\t\t\t\t\t\tgroup: 'format',\n\t\t\t\t\t\t\ticon,\n\t\t\t\t\t\t\tlabel: this.locale.label,\n\t\t\t\t\t\t\ttooltip: this.locale.tooltip(formatShortcut(this.config.keymap ?? 'Mod-E')),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\tprivate registerInputRule(context: PluginContext): void {\n\t\t// The inline-node placeholder (U+FFFC) is excluded from the span body so\n\t\t// the rule never matches across an inline node nor re-inserts it.\n\t\tconst pattern: RegExp = /(?:^|[^`])(`([^`\\uFFFC]+)`)$/;\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel)) return null;\n\t\t\t\tif (!isCollapsed(sel)) return null;\n\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst innerText: string | undefined = match[2];\n\t\t\t\tconst backtickExpr: string | undefined = match[1];\n\t\t\t\tif (!innerText || !backtickExpr) return null;\n\n\t\t\t\tconst backtickExprStart: number = end - backtickExpr.length;\n\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.deleteTextAt(sel.anchor.blockId, backtickExprStart, end)\n\t\t\t\t\t.insertText(sel.anchor.blockId, backtickExprStart, innerText, [\n\t\t\t\t\t\t{ type: markType('code') },\n\t\t\t\t\t])\n\t\t\t\t\t.setSelection(\n\t\t\t\t\t\tcreateCollapsedSelection(sel.anchor.blockId, backtickExprStart + innerText.length),\n\t\t\t\t\t)\n\t\t\t\t\t.build();\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Prevents formatting marks from coexisting with the code mark.\n\t * Bold, italic, underline, etc. are stripped when code is applied,\n\t * and code is blocked on text that already has formatting marks.\n\t * The link mark is allowed to coexist.\n\t */\n\tprivate registerExclusivityMiddleware(context: PluginContext): void {\n\t\tcontext.registerMiddleware(\n\t\t\t(tr, state, next) => {\n\t\t\t\tlet patched = false;\n\t\t\t\tconst patchedSteps: Step[] = [];\n\n\t\t\t\tfor (const step of tr.steps) {\n\t\t\t\t\tif (step.type !== 'addMark') {\n\t\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stepMarkType: string = step.mark.type;\n\n\t\t\t\t\tif (stepMarkType === 'code') {\n\t\t\t\t\t\t// Adding code mark: inject removeMark steps for excluded marks\n\t\t\t\t\t\tconst block: BlockNode | undefined = state.getBlock(step.blockId);\n\t\t\t\t\t\tif (block) {\n\t\t\t\t\t\t\tconst segments = getBlockContentSegmentsInRange(block, step.from, step.to);\n\t\t\t\t\t\t\tconst marksToRemove: Set<string> = new Set();\n\t\t\t\t\t\t\tfor (const seg of segments) {\n\t\t\t\t\t\t\t\tif (seg.kind !== 'text') continue;\n\t\t\t\t\t\t\t\tfor (const m of seg.marks) {\n\t\t\t\t\t\t\t\t\tif (EXCLUDED_WITH_CODE.has(m.type)) {\n\t\t\t\t\t\t\t\t\t\tmarksToRemove.add(m.type);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (const mt of marksToRemove) {\n\t\t\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t\t\t\tpatchedSteps.push({\n\t\t\t\t\t\t\t\t\ttype: 'removeMark',\n\t\t\t\t\t\t\t\t\tblockId: step.blockId,\n\t\t\t\t\t\t\t\t\tfrom: step.from,\n\t\t\t\t\t\t\t\t\tto: step.to,\n\t\t\t\t\t\t\t\t\tmark: { type: markType(mt) },\n\t\t\t\t\t\t\t\t\t...(step.path ? { path: step.path } : {}),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (EXCLUDED_WITH_CODE.has(stepMarkType)) {\n\t\t\t\t\t\t// Adding a formatting mark: block if target range has code mark\n\t\t\t\t\t\tconst block: BlockNode | undefined = state.getBlock(step.blockId);\n\t\t\t\t\t\tif (block) {\n\t\t\t\t\t\t\tconst segments = getBlockContentSegmentsInRange(block, step.from, step.to);\n\t\t\t\t\t\t\tconst hasCode: boolean = segments.some(\n\t\t\t\t\t\t\t\t(seg) => seg.kind === 'text' && seg.marks.some((m) => m.type === 'code'),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (hasCode) {\n\t\t\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t\t\t\tcontinue; // skip this step\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tpatchedSteps.push(step);\n\t\t\t\t}\n\n\t\t\t\t// Handle stored marks\n\t\t\t\tlet storedMarksAfter: readonly Mark[] | null = tr.storedMarksAfter;\n\t\t\t\tif (storedMarksAfter) {\n\t\t\t\t\tconst hasCode: boolean = storedMarksAfter.some((m) => m.type === 'code');\n\t\t\t\t\tconst hasExcluded: boolean = storedMarksAfter.some((m) => EXCLUDED_WITH_CODE.has(m.type));\n\n\t\t\t\t\tif (hasCode && hasExcluded) {\n\t\t\t\t\t\t// Keep code, strip formatting marks\n\t\t\t\t\t\tstoredMarksAfter = storedMarksAfter.filter((m) => !EXCLUDED_WITH_CODE.has(m.type));\n\t\t\t\t\t\tpatched = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnext(patched ? { ...tr, steps: patchedSteps, storedMarksAfter } : tr);\n\t\t\t},\n\t\t\t{ name: 'inline-code:mark-exclusivity', priority: 50 },\n\t\t);\n\t}\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as t,r as e,s as n}from"./HTMLUtils-Bhg3_P8B.mjs";import{S as r}from"./Document-827l3P80.mjs";import{o as i,t as o,u as l}from"./Selection-HYoVFpAx.mjs";import{i as s}from"./TypeBrands-Ch9856Gb.mjs";import{i as a,r as c,t as u}from"./AttributedMarkCommands-bagbH8Qt.mjs";import{c as m,n as p,o as d}from"./PluginHelpers-Dx_0hfDe.mjs";import{t as h}from"./ShortcutFormatting-TwiufqeV.mjs";var f={label:"Link",tooltip:t=>`Insert Link (${t})`,removeLink:"Remove Link",removeLinkAria:"Remove link",urlPlaceholder:"https://...",urlAria:"Link URL",apply:"Apply",applyAria:"Apply link",invalidUrl:"Only http(s), mailto, tel, fragments, and relative paths are allowed."},g=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Ctrv6cIi.mjs"),"./locales/de.ts":()=>import("./de-JhGflzS5.mjs"),"./locales/es.ts":()=>import("./es-Bv7bDbMp.mjs"),"./locales/fr.ts":()=>import("./fr-DtzIu6tU.mjs"),"./locales/hi.ts":()=>import("./hi-Bu799xIO.mjs"),"./locales/pt.ts":()=>import("./pt-DmN9u3NX.mjs"),"./locales/ru.ts":()=>import("./ru-BxySx7an.mjs"),"./locales/zh.ts":()=>import("./zh-DuucmOns.mjs")});async function k(t){return m(g,t,f)}var v={openInNewTab:!0},b=/(?:^|[^!])(\[([^\]\uFFFC]+)\]\(([^)\s\uFFFC]+)(?:\s+"([^"\uFFFC]*)")?\))$/,L=/(<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\s\uFFFC]+)>)$/;function C(t,e){return e&&!t.startsWith("#")}var A=class{id="link";name="Link";priority=25;config;locale;fragmentClickContainer=null;fragmentClickHandler=null;constructor(t){this.config={...v,...t}}async init(t){this.locale=await d(t,this.config.locale,f,k),this.registerMarkSpec(t),this.registerCommands(t),this.registerKeymap(t),this.registerToolbarItem(t),!1!==this.config.inputRule&&this.registerInputRules(t),this.installFragmentClickHandler(t)}destroy(){this.removeFragmentClickHandler()}registerInputRules(t){const e=(t,e,n,r,i,l,a)=>{const c={href:l};return a&&(c.title=a),t.transaction("input").deleteTextAt(e,n,r).insertText(e,n,i,[{type:s("link"),attrs:c}]).setSelection(o(e,n+i.length)).build()};t.registerInputRule({pattern:b,handler(t,r,o,s){const a=t.selection;if(!l(a)||!i(a))return null;const c=t.getBlock(a.anchor.blockId);if(!c||"code_block"===c.type)return null;const u=r[1],m=r[2],p=r[3],d=r[4];if(!u||!m||!p)return null;const h=n(p);return""===h?null:e(t,a.anchor.blockId,s-u.length,s,m,h,d)}}),t.registerInputRule({pattern:L,handler(t,r,o,s){const a=t.selection;if(!l(a)||!i(a))return null;const c=t.getBlock(a.anchor.blockId);if(!c||"code_block"===c.type)return null;const u=r[1],m=r[2];if(!u||!m)return null;const p=n(m);return""===p?null:e(t,a.anchor.blockId,s-u.length,s,m,p)}})}registerMarkSpec(t){const r=this.config.openInNewTab;t.registerMarkSpec({type:"link",rank:10,inclusive:!1,attrs:{href:{default:""},title:{default:""}},toDOM(t){const e=document.createElement("a"),i=n(String(t.attrs?.href??""));e.setAttribute("href",i);const o=String(t.attrs?.title??"");return o&&e.setAttribute("title",o),C(i,r)&&(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer")),e},toHTMLString:(t,i)=>{const o=n(String(t.attrs?.href??"")),l=e(o),s=String(t.attrs?.title??""),a=s?` title="${e(s)}"`:"";return C(o,r)?`<a href="${l}"${a} target="_blank" rel="noopener noreferrer">${i}</a>`:`<a href="${l}"${a}>${i}</a>`},parseHTML:[{tag:"a",getAttrs:t=>{const e=n(t.getAttribute("href")??""),r=t.getAttribute("title")??"";return r?{href:e,title:r}:{href:e}}}],sanitize:{tags:["a"],attrs:["href","title","target","rel"]}})}installFragmentClickHandler(e){this.removeFragmentClickHandler();const n=e.getContainer(),r=e=>{if(e.defaultPrevented||0!==e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;const r=function(t,e){let n=e instanceof Element?e:e instanceof Node?e.parentElement:null;for(;n&&t.contains(n);){if(n instanceof HTMLAnchorElement)return n;if(n===t)break;n=n.parentElement}return null}(n,e.target);if(!r)return;const i=t(r.getAttribute("href")??"");if(0===i.length)return;const o=function(t,e){for(const n of e){if(t.id===n)return t;const e=t.getElementsByTagName("*");for(let t=0;t<e.length;t++){const r=e.item(t);if(r?.id===n)return r}}return null}(n,i);o&&(e.preventDefault(),o.scrollIntoView())};this.fragmentClickContainer=n,this.fragmentClickHandler=r,n.addEventListener("click",r)}removeFragmentClickHandler(){this.fragmentClickContainer&&this.fragmentClickHandler&&this.fragmentClickContainer.removeEventListener("click",this.fragmentClickHandler),this.fragmentClickContainer=null,this.fragmentClickHandler=null}registerCommands(t){t.registerCommand("toggleLink",()=>{const e=t.getState();return this.toggleLink(t,e)}),t.registerCommand("setLink",()=>!1),t.registerCommand("removeLink",()=>{const e=t.getState();return this.removeLink(t,e)})}registerKeymap(t){t.registerKeymap({"Mod-K":()=>t.executeCommand("toggleLink")})}registerToolbarItem(t){t.registerToolbarItem({id:"link",group:"insert",icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>',label:this.locale.label,tooltip:this.locale.tooltip(h("Mod-K")),command:"toggleLink",popupType:"custom",renderPopup:(t,e,n)=>{this.renderLinkPopup(t,e,n)},isActive:t=>this.isLinkActive(t),isEnabled:t=>!i(t.selection)})}isLinkActive(t){return c(t,"link")}toggleLink(t,e){return!!this.isLinkActive(e)&&this.removeLink(t,e)}addLink(t,e,n){const r=e.selection;return!!l(r)&&!i(r)&&p(t,u(e,{type:s("link"),attrs:{href:n}}))}removeLink(t,e){const n=e.selection;if(!l(n))return!1;if(i(n)){const i=e.getBlock(n.anchor.blockId);if(!i)return!1;const o=[];let l=0;for(const t of i.children){if(!("text"in t))continue;const e=l+t.text.length;o.push({pos:l,end:e,hasLink:r(t.marks,s("link"))}),l=e}const a=o.findIndex(t=>n.anchor.offset>=t.pos&&n.anchor.offset<=t.end),c=a>=0?o[a]:void 0;if(-1===a||!c?.hasLink)return!1;let u=a;for(;u>0&&o[u-1]?.hasLink;)u--;let m=a;for(;m<o.length-1&&o[m+1]?.hasLink;)m++;const p=o[u],d=o[m];if(!p||!d)return!1;const h=p.pos,f=d.end,g=e.transaction("command");return g.removeMark(n.anchor.blockId,h,f,{type:s("link")}),g.setSelection(n),t.dispatch(g.build()),!0}return p(t,a(e,s("link")))}renderLinkPopup(t,e,r){t.classList.add("notectl-link-popup");const i=e.getState();if(this.isLinkActive(i)){const n=document.createElement("button");n.type="button",n.className="notectl-link-popup__button",n.textContent=this.locale.removeLink,n.setAttribute("aria-label",this.locale.removeLinkAria),n.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),e.executeCommand("removeLink"),r(),e.getContainer().focus()}),t.appendChild(n)}else{const i=document.createElement("input");i.type="url",i.className="notectl-link-popup__input",i.placeholder=this.locale.urlPlaceholder,i.setAttribute("aria-label",this.locale.urlAria);const o=document.createElement("button");o.type="button",o.className="notectl-link-popup__button notectl-link-popup__button--apply",o.textContent=this.locale.apply,o.setAttribute("aria-label",this.locale.applyAria);const l=document.createElement("div");l.className="notectl-link-popup__error",l.setAttribute("role","alert"),l.hidden=!0;const s=()=>{const t=i.value.trim();if(""===t)return;const o=n(t);if(""===o)return l.textContent=this.locale.invalidUrl,l.hidden=!1,i.setAttribute("aria-invalid","true"),void i.focus();l.hidden=!0,i.removeAttribute("aria-invalid"),this.addLink(e,e.getState(),o),r(),e.getContainer().focus()};o.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),s()}),i.addEventListener("keydown",t=>{"Enter"===t.key&&(t.preventDefault(),s())}),i.addEventListener("input",()=>{l.hidden||(l.hidden=!0,i.removeAttribute("aria-invalid"))}),t.appendChild(i),t.appendChild(o),t.appendChild(l),requestAnimationFrame(()=>i.focus())}}};export{f as n,k as r,A as t};
2
- //# sourceMappingURL=LinkPlugin-Ct5Z180S.mjs.map
1
+ import{a as t,r as e,s as n}from"./HTMLUtils-Bhg3_P8B.mjs";import{S as r}from"./Document-827l3P80.mjs";import{o as i,t as o,u as l}from"./Selection-HYoVFpAx.mjs";import{i as s}from"./TypeBrands-Ch9856Gb.mjs";import{i as a,r as c,t as u}from"./AttributedMarkCommands-BCvmqeFZ.mjs";import{c as m,n as p,o as d}from"./PluginHelpers-KDuTlmXm.mjs";import{t as h}from"./ShortcutFormatting-TwiufqeV.mjs";var f={label:"Link",tooltip:t=>`Insert Link (${t})`,removeLink:"Remove Link",removeLinkAria:"Remove link",urlPlaceholder:"https://...",urlAria:"Link URL",apply:"Apply",applyAria:"Apply link",invalidUrl:"Only http(s), mailto, tel, fragments, and relative paths are allowed."},g=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Ctrv6cIi.mjs"),"./locales/de.ts":()=>import("./de-JhGflzS5.mjs"),"./locales/es.ts":()=>import("./es-Bv7bDbMp.mjs"),"./locales/fr.ts":()=>import("./fr-DtzIu6tU.mjs"),"./locales/hi.ts":()=>import("./hi-Bu799xIO.mjs"),"./locales/pt.ts":()=>import("./pt-DmN9u3NX.mjs"),"./locales/ru.ts":()=>import("./ru-BxySx7an.mjs"),"./locales/zh.ts":()=>import("./zh-DuucmOns.mjs")});async function k(t){return m(g,t,f)}var v={openInNewTab:!0},b=/(?:^|[^!])(\[([^\]\uFFFC]+)\]\(([^)\s\uFFFC]+)(?:\s+"([^"\uFFFC]*)")?\))$/,L=/(<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\s\uFFFC]+)>)$/;function C(t,e){return e&&!t.startsWith("#")}var A=class{id="link";name="Link";priority=25;config;locale;fragmentClickContainer=null;fragmentClickHandler=null;constructor(t){this.config={...v,...t}}async init(t){this.locale=await d(t,this.config.locale,f,k),this.registerMarkSpec(t),this.registerCommands(t),this.registerKeymap(t),this.registerToolbarItem(t),!1!==this.config.inputRule&&this.registerInputRules(t),this.installFragmentClickHandler(t)}destroy(){this.removeFragmentClickHandler()}registerInputRules(t){const e=(t,e,n,r,i,l,a)=>{const c={href:l};return a&&(c.title=a),t.transaction("input").deleteTextAt(e,n,r).insertText(e,n,i,[{type:s("link"),attrs:c}]).setSelection(o(e,n+i.length)).build()};t.registerInputRule({pattern:b,handler(t,r,o,s){const a=t.selection;if(!l(a)||!i(a))return null;const c=t.getBlock(a.anchor.blockId);if(!c||"code_block"===c.type)return null;const u=r[1],m=r[2],p=r[3],d=r[4];if(!u||!m||!p)return null;const h=n(p);return""===h?null:e(t,a.anchor.blockId,s-u.length,s,m,h,d)}}),t.registerInputRule({pattern:L,handler(t,r,o,s){const a=t.selection;if(!l(a)||!i(a))return null;const c=t.getBlock(a.anchor.blockId);if(!c||"code_block"===c.type)return null;const u=r[1],m=r[2];if(!u||!m)return null;const p=n(m);return""===p?null:e(t,a.anchor.blockId,s-u.length,s,m,p)}})}registerMarkSpec(t){const r=this.config.openInNewTab;t.registerMarkSpec({type:"link",rank:10,inclusive:!1,attrs:{href:{default:""},title:{default:""}},toDOM(t){const e=document.createElement("a"),i=n(String(t.attrs?.href??""));e.setAttribute("href",i);const o=String(t.attrs?.title??"");return o&&e.setAttribute("title",o),C(i,r)&&(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer")),e},toHTMLString:(t,i)=>{const o=n(String(t.attrs?.href??"")),l=e(o),s=String(t.attrs?.title??""),a=s?` title="${e(s)}"`:"";return C(o,r)?`<a href="${l}"${a} target="_blank" rel="noopener noreferrer">${i}</a>`:`<a href="${l}"${a}>${i}</a>`},parseHTML:[{tag:"a",getAttrs:t=>{const e=n(t.getAttribute("href")??""),r=t.getAttribute("title")??"";return r?{href:e,title:r}:{href:e}}}],sanitize:{tags:["a"],attrs:["href","title","target","rel"]}})}installFragmentClickHandler(e){this.removeFragmentClickHandler();const n=e.getContainer(),r=e=>{if(e.defaultPrevented||0!==e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;const r=function(t,e){let n=e instanceof Element?e:e instanceof Node?e.parentElement:null;for(;n&&t.contains(n);){if(n instanceof HTMLAnchorElement)return n;if(n===t)break;n=n.parentElement}return null}(n,e.target);if(!r)return;const i=t(r.getAttribute("href")??"");if(0===i.length)return;const o=function(t,e){for(const n of e){if(t.id===n)return t;const e=t.getElementsByTagName("*");for(let t=0;t<e.length;t++){const r=e.item(t);if(r?.id===n)return r}}return null}(n,i);o&&(e.preventDefault(),o.scrollIntoView())};this.fragmentClickContainer=n,this.fragmentClickHandler=r,n.addEventListener("click",r)}removeFragmentClickHandler(){this.fragmentClickContainer&&this.fragmentClickHandler&&this.fragmentClickContainer.removeEventListener("click",this.fragmentClickHandler),this.fragmentClickContainer=null,this.fragmentClickHandler=null}registerCommands(t){t.registerCommand("toggleLink",()=>{const e=t.getState();return this.toggleLink(t,e)}),t.registerCommand("setLink",()=>!1),t.registerCommand("removeLink",()=>{const e=t.getState();return this.removeLink(t,e)})}registerKeymap(t){t.registerKeymap({"Mod-K":()=>t.executeCommand("toggleLink")})}registerToolbarItem(t){t.registerToolbarItem({id:"link",group:"insert",icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>',label:this.locale.label,tooltip:this.locale.tooltip(h("Mod-K")),command:"toggleLink",popupType:"custom",renderPopup:(t,e,n)=>{this.renderLinkPopup(t,e,n)},isActive:t=>this.isLinkActive(t),isEnabled:t=>!i(t.selection)})}isLinkActive(t){return c(t,"link")}toggleLink(t,e){return!!this.isLinkActive(e)&&this.removeLink(t,e)}addLink(t,e,n){const r=e.selection;return!!l(r)&&!i(r)&&p(t,u(e,{type:s("link"),attrs:{href:n}}))}removeLink(t,e){const n=e.selection;if(!l(n))return!1;if(i(n)){const i=e.getBlock(n.anchor.blockId);if(!i)return!1;const o=[];let l=0;for(const t of i.children){if(!("text"in t))continue;const e=l+t.text.length;o.push({pos:l,end:e,hasLink:r(t.marks,s("link"))}),l=e}const a=o.findIndex(t=>n.anchor.offset>=t.pos&&n.anchor.offset<=t.end),c=a>=0?o[a]:void 0;if(-1===a||!c?.hasLink)return!1;let u=a;for(;u>0&&o[u-1]?.hasLink;)u--;let m=a;for(;m<o.length-1&&o[m+1]?.hasLink;)m++;const p=o[u],d=o[m];if(!p||!d)return!1;const h=p.pos,f=d.end,g=e.transaction("command");return g.removeMark(n.anchor.blockId,h,f,{type:s("link")}),g.setSelection(n),t.dispatch(g.build()),!0}return p(t,a(e,s("link")))}renderLinkPopup(t,e,r){t.classList.add("notectl-link-popup");const i=e.getState();if(this.isLinkActive(i)){const n=document.createElement("button");n.type="button",n.className="notectl-link-popup__button",n.textContent=this.locale.removeLink,n.setAttribute("aria-label",this.locale.removeLinkAria),n.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),e.executeCommand("removeLink"),r(),e.getContainer().focus()}),t.appendChild(n)}else{const i=document.createElement("input");i.type="url",i.className="notectl-link-popup__input",i.placeholder=this.locale.urlPlaceholder,i.setAttribute("aria-label",this.locale.urlAria);const o=document.createElement("button");o.type="button",o.className="notectl-link-popup__button notectl-link-popup__button--apply",o.textContent=this.locale.apply,o.setAttribute("aria-label",this.locale.applyAria);const l=document.createElement("div");l.className="notectl-link-popup__error",l.setAttribute("role","alert"),l.hidden=!0;const s=()=>{const t=i.value.trim();if(""===t)return;const o=n(t);if(""===o)return l.textContent=this.locale.invalidUrl,l.hidden=!1,i.setAttribute("aria-invalid","true"),void i.focus();l.hidden=!0,i.removeAttribute("aria-invalid"),this.addLink(e,e.getState(),o),r(),e.getContainer().focus()};o.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),s()}),i.addEventListener("keydown",t=>{"Enter"===t.key&&(t.preventDefault(),s())}),i.addEventListener("input",()=>{l.hidden||(l.hidden=!0,i.removeAttribute("aria-invalid"))}),t.appendChild(i),t.appendChild(o),t.appendChild(l),requestAnimationFrame(()=>i.focus())}}};export{f as n,k as r,A as t};
2
+ //# sourceMappingURL=LinkPlugin-CvWHbSkb.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkPlugin-Ct5Z180S.mjs","names":[],"sources":["../../src/plugins/link/LinkLocale.ts","../../src/plugins/link/LinkPlugin.ts"],"sourcesContent":["/**\n * Locale interface and default English locale for the LinkPlugin.\n */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\n// --- Locale Interface ---\n\nexport interface LinkLocale {\n\treadonly label: string;\n\treadonly tooltip: (shortcut: string) => string;\n\treadonly removeLink: string;\n\treadonly removeLinkAria: string;\n\treadonly urlPlaceholder: string;\n\treadonly urlAria: string;\n\treadonly apply: string;\n\treadonly applyAria: string;\n\treadonly invalidUrl: string;\n}\n\n// --- Default English Locale ---\n\nexport const LINK_LOCALE_EN: LinkLocale = {\n\tlabel: 'Link',\n\ttooltip: (shortcut: string) => `Insert Link (${shortcut})`,\n\tremoveLink: 'Remove Link',\n\tremoveLinkAria: 'Remove link',\n\turlPlaceholder: 'https://...',\n\turlAria: 'Link URL',\n\tapply: 'Apply',\n\tapplyAria: 'Apply link',\n\tinvalidUrl: 'Only http(s), mailto, tel, fragments, and relative paths are allowed.',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<LinkLocale> = import.meta.glob<{\n\tdefault: LinkLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadLinkLocale(lang: string): Promise<LinkLocale> {\n\treturn loadLocaleModule(localeModules, lang, LINK_LOCALE_EN);\n}\n","/**\n * LinkPlugin: registers a link mark type with href attribute,\n * toggle command, keyboard shortcut (Mod-K), and toolbar button\n * with a URL input popup.\n */\n\nimport {\n\tapplyAttributedMark,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from '../../commands/AttributedMarkCommands.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport { hasMark } from '../../model/Document.js';\nimport { escapeHTML, fragmentIdentifiers, sanitizeHref } from '../../model/HTMLUtils.js';\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { dispatchIfPresent, resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { LINK_LOCALE_EN, type LinkLocale, loadLinkLocale } from './LinkLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tlink: { href: string; title?: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface LinkConfig {\n\t/** Whether to add rel=\"noopener noreferrer\" and target=\"_blank\" by default. */\n\treadonly openInNewTab: boolean;\n\t/** Live Markdown shortcuts: `[text](url \"title\")` and `<url>` autolink. Default true. */\n\treadonly inputRule?: boolean;\n\treadonly locale?: LinkLocale;\n}\n\nconst DEFAULT_CONFIG: LinkConfig = {\n\topenInNewTab: true,\n};\n\n// The inline-node placeholder (U+FFFC) is excluded from every re-inserted\n// capture so a live link rule never spans an inline node nor writes the\n// sentinel back as literal text.\n/** `[text](url \"optional title\")`, not preceded by `!` (which would be an image). */\nconst LINK_RULE = /(?:^|[^!])(\\[([^\\]\\uFFFC]+)\\]\\(([^)\\s\\uFFFC]+)(?:\\s+\"([^\"\\uFFFC]*)\")?\\))$/;\n/** `<scheme:...>` autolink. */\nconst AUTOLINK_RULE = /(<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\\s\\uFFFC]+)>)$/;\n\n/** Fragment-only links stay in the current editor even when external links open in a new tab. */\nfunction shouldOpenInNewTab(href: string, openInNewTab: boolean): boolean {\n\treturn openInNewTab && !href.startsWith('#');\n}\n\n/** Finds the clicked anchor without interpolating user-controlled data into a CSS selector. */\nfunction findClickedAnchor(\n\tcontainer: HTMLElement,\n\ttarget: EventTarget | null,\n): HTMLAnchorElement | null {\n\tlet element: Element | null =\n\t\ttarget instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n\n\twhile (element && container.contains(element)) {\n\t\tif (element instanceof HTMLAnchorElement) return element;\n\t\tif (element === container) break;\n\t\telement = element.parentElement;\n\t}\n\n\treturn null;\n}\n\n/** Resolves an ID inside this editor by direct string comparison, never through a CSS selector. */\nfunction findFragmentTarget(\n\tcontainer: HTMLElement,\n\tidentifiers: readonly string[],\n): Element | null {\n\tfor (const identifier of identifiers) {\n\t\tif (container.id === identifier) return container;\n\n\t\tconst descendants: HTMLCollectionOf<Element> = container.getElementsByTagName('*');\n\t\tfor (let index = 0; index < descendants.length; index++) {\n\t\t\tconst descendant: Element | null = descendants.item(index);\n\t\t\tif (descendant?.id === identifier) return descendant;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n// --- Plugin ---\n\nexport class LinkPlugin implements Plugin {\n\treadonly id = 'link';\n\treadonly name = 'Link';\n\treadonly priority = 25;\n\n\tprivate readonly config: LinkConfig;\n\tprivate locale!: LinkLocale;\n\tprivate fragmentClickContainer: HTMLElement | null = null;\n\tprivate fragmentClickHandler: ((event: MouseEvent) => void) | null = null;\n\n\tconstructor(config?: Partial<LinkConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(context, this.config.locale, LINK_LOCALE_EN, loadLinkLocale);\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymap(context);\n\t\tthis.registerToolbarItem(context);\n\t\tif (this.config.inputRule !== false) {\n\t\t\tthis.registerInputRules(context);\n\t\t}\n\t\tthis.installFragmentClickHandler(context);\n\t}\n\n\tdestroy(): void {\n\t\tthis.removeFragmentClickHandler();\n\t}\n\n\t/**\n\t * Live Markdown link rules: `[text](url \"title\")` and `<url>` autolink. Bespoke\n\t * (not the shared wrapping-mark helper) because links carry an `href`/`title`\n\t * attribute and two capture groups (D6).\n\t */\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tconst buildLink = (\n\t\t\tstate: EditorState,\n\t\t\tblockId: BlockNode['id'],\n\t\t\tstart: number,\n\t\t\tend: number,\n\t\t\ttext: string,\n\t\t\thref: string,\n\t\t\ttitle?: string,\n\t\t) => {\n\t\t\tconst attrs: Record<string, string> = { href };\n\t\t\tif (title) attrs.title = title;\n\t\t\treturn state\n\t\t\t\t.transaction('input')\n\t\t\t\t.deleteTextAt(blockId, start, end)\n\t\t\t\t.insertText(blockId, start, text, [{ type: markType('link'), attrs }])\n\t\t\t\t.setSelection(createCollapsedSelection(blockId, start + text.length))\n\t\t\t\t.build();\n\t\t};\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern: LINK_RULE,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel) || !isCollapsed(sel)) return null;\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst expr = match[1];\n\t\t\t\tconst text = match[2];\n\t\t\t\tconst rawHref = match[3];\n\t\t\t\tconst title = match[4];\n\t\t\t\tif (!expr || !text || !rawHref) return null;\n\t\t\t\tconst href: string = sanitizeHref(rawHref);\n\t\t\t\tif (href === '') return null;\n\n\t\t\t\treturn buildLink(state, sel.anchor.blockId, end - expr.length, end, text, href, title);\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern: AUTOLINK_RULE,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel) || !isCollapsed(sel)) return null;\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst expr = match[1];\n\t\t\t\tconst url = match[2];\n\t\t\t\tif (!expr || !url) return null;\n\t\t\t\tconst href: string = sanitizeHref(url);\n\t\t\t\tif (href === '') return null;\n\n\t\t\t\treturn buildLink(state, sel.anchor.blockId, end - expr.length, end, url, href);\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tconst openInNewTab = this.config.openInNewTab;\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'link',\n\t\t\trank: 10,\n\t\t\tinclusive: false,\n\t\t\tattrs: {\n\t\t\t\thref: { default: '' },\n\t\t\t\ttitle: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst a = document.createElement('a');\n\t\t\t\tconst href: string = sanitizeHref(String(mark.attrs?.href ?? ''));\n\t\t\t\ta.setAttribute('href', href);\n\t\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\t\tif (title) a.setAttribute('title', title);\n\t\t\t\tif (shouldOpenInNewTab(href, openInNewTab)) {\n\t\t\t\t\ta.setAttribute('target', '_blank');\n\t\t\t\t\ta.setAttribute('rel', 'noopener noreferrer');\n\t\t\t\t}\n\t\t\t\treturn a;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst safeHref: string = sanitizeHref(String(mark.attrs?.href ?? ''));\n\t\t\t\tconst href: string = escapeHTML(safeHref);\n\t\t\t\tconst titleValue: string = String(mark.attrs?.title ?? '');\n\t\t\t\tconst titleAttr: string = titleValue ? ` title=\"${escapeHTML(titleValue)}\"` : '';\n\t\t\t\tif (shouldOpenInNewTab(safeHref, openInNewTab)) {\n\t\t\t\t\treturn `<a href=\"${href}\"${titleAttr} target=\"_blank\" rel=\"noopener noreferrer\">${content}</a>`;\n\t\t\t\t}\n\t\t\t\treturn `<a href=\"${href}\"${titleAttr}>${content}</a>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'a',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\t// Returning an empty href (instead of `false`) keeps the link mark\n\t\t\t\t\t\t// applied so the parser does not fall back to the core HTMLParser's\n\t\t\t\t\t\t// raw-href default; the empty value renders as a no-op anchor.\n\t\t\t\t\t\tconst href: string = sanitizeHref(el.getAttribute('href') ?? '');\n\t\t\t\t\t\tconst title: string = el.getAttribute('title') ?? '';\n\t\t\t\t\t\treturn title ? { href, title } : { href };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['a'], attrs: ['href', 'title', 'target', 'rel'] },\n\t\t});\n\t}\n\n\tprivate installFragmentClickHandler(context: PluginContext): void {\n\t\tthis.removeFragmentClickHandler();\n\n\t\tconst container: HTMLElement = context.getContainer();\n\t\tconst handler = (event: MouseEvent): void => {\n\t\t\tif (\n\t\t\t\tevent.defaultPrevented ||\n\t\t\t\tevent.button !== 0 ||\n\t\t\t\tevent.metaKey ||\n\t\t\t\tevent.ctrlKey ||\n\t\t\t\tevent.shiftKey ||\n\t\t\t\tevent.altKey\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst anchor: HTMLAnchorElement | null = findClickedAnchor(container, event.target);\n\t\t\tif (!anchor) return;\n\n\t\t\tconst identifiers: readonly string[] = fragmentIdentifiers(anchor.getAttribute('href') ?? '');\n\t\t\tif (identifiers.length === 0) return;\n\n\t\t\tconst target: Element | null = findFragmentTarget(container, identifiers);\n\t\t\tif (!target) return;\n\n\t\t\tevent.preventDefault();\n\t\t\ttarget.scrollIntoView();\n\t\t};\n\n\t\tthis.fragmentClickContainer = container;\n\t\tthis.fragmentClickHandler = handler;\n\t\tcontainer.addEventListener('click', handler);\n\t}\n\n\tprivate removeFragmentClickHandler(): void {\n\t\tif (this.fragmentClickContainer && this.fragmentClickHandler) {\n\t\t\tthis.fragmentClickContainer.removeEventListener('click', this.fragmentClickHandler);\n\t\t}\n\t\tthis.fragmentClickContainer = null;\n\t\tthis.fragmentClickHandler = null;\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.toggleLink(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setLink', () => {\n\t\t\t// setLink is called by the popup after URL input\n\t\t\t// The actual URL is set via the popup's custom render\n\t\t\treturn false;\n\t\t});\n\n\t\tcontext.registerCommand('removeLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeLink(context, state);\n\t\t});\n\t}\n\n\tprivate registerKeymap(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-K': () => context.executeCommand('toggleLink'),\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'link',\n\t\t\tgroup: 'insert',\n\t\t\ticon,\n\t\t\tlabel: this.locale.label,\n\t\t\ttooltip: this.locale.tooltip(formatShortcut('Mod-K')),\n\t\t\tcommand: 'toggleLink',\n\t\t\tpopupType: 'custom',\n\t\t\trenderPopup: (container, ctx, onClose) => {\n\t\t\t\tthis.renderLinkPopup(container, ctx, onClose);\n\t\t\t},\n\t\t\tisActive: (state) => this.isLinkActive(state),\n\t\t\tisEnabled: (state) => !isCollapsed(state.selection),\n\t\t});\n\t}\n\n\tprivate isLinkActive(state: EditorState): boolean {\n\t\treturn isAttributedMarkActive(state, 'link');\n\t}\n\n\tprivate toggleLink(context: PluginContext, state: EditorState): boolean {\n\t\tif (this.isLinkActive(state)) {\n\t\t\treturn this.removeLink(context, state);\n\t\t}\n\t\t// Adding links requires the toolbar popup for URL input\n\t\treturn false;\n\t}\n\n\tprivate addLink(context: PluginContext, state: EditorState, href: string): boolean {\n\t\tconst sel = state.selection;\n\t\tif (!isTextSelection(sel)) return false;\n\t\tif (isCollapsed(sel)) return false;\n\n\t\tconst mark = { type: markType('link'), attrs: { href } };\n\t\treturn dispatchIfPresent(context, applyAttributedMark(state, mark));\n\t}\n\n\tprivate removeLink(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tif (!isTextSelection(sel)) return false;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\t// Remove link from entire link span around cursor (plugin-specific extent scan)\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return false;\n\n\t\t\tconst textChildren: { pos: number; end: number; hasLink: boolean }[] = [];\n\t\t\tlet pos = 0;\n\t\t\tfor (const child of block.children) {\n\t\t\t\tif (!('text' in child)) continue;\n\t\t\t\tconst end = pos + child.text.length;\n\t\t\t\ttextChildren.push({ pos, end, hasLink: hasMark(child.marks, markType('link')) });\n\t\t\t\tpos = end;\n\t\t\t}\n\n\t\t\tconst cursorIdx = textChildren.findIndex(\n\t\t\t\t(c) => sel.anchor.offset >= c.pos && sel.anchor.offset <= c.end,\n\t\t\t);\n\t\t\tconst cursorEntry = cursorIdx >= 0 ? textChildren[cursorIdx] : undefined;\n\t\t\tif (cursorIdx === -1 || !cursorEntry?.hasLink) return false;\n\n\t\t\tlet startIdx = cursorIdx;\n\t\t\twhile (startIdx > 0 && textChildren[startIdx - 1]?.hasLink) {\n\t\t\t\tstartIdx--;\n\t\t\t}\n\n\t\t\tlet endIdx = cursorIdx;\n\t\t\twhile (endIdx < textChildren.length - 1 && textChildren[endIdx + 1]?.hasLink) {\n\t\t\t\tendIdx++;\n\t\t\t}\n\n\t\t\tconst startEntry = textChildren[startIdx];\n\t\t\tconst endEntry = textChildren[endIdx];\n\t\t\tif (!startEntry || !endEntry) return false;\n\n\t\t\tconst linkStart = startEntry.pos;\n\t\t\tconst linkEnd = endEntry.end;\n\n\t\t\tconst builder = state.transaction('command');\n\t\t\tbuilder.removeMark(sel.anchor.blockId, linkStart, linkEnd, { type: markType('link') });\n\t\t\tbuilder.setSelection(sel);\n\t\t\tcontext.dispatch(builder.build());\n\t\t\treturn true;\n\t\t}\n\n\t\t// Range selection: delegate to shared helper\n\t\treturn dispatchIfPresent(context, removeAttributedMark(state, markType('link')));\n\t}\n\n\tprivate renderLinkPopup(\n\t\tcontainer: HTMLElement,\n\t\tcontext: PluginContext,\n\t\tonClose: () => void,\n\t): void {\n\t\tcontainer.classList.add('notectl-link-popup');\n\n\t\tconst state = context.getState();\n\t\tconst isActive = this.isLinkActive(state);\n\n\t\tif (isActive) {\n\t\t\t// Show remove link button\n\t\t\tconst removeBtn = document.createElement('button');\n\t\t\tremoveBtn.type = 'button';\n\t\t\tremoveBtn.className = 'notectl-link-popup__button';\n\t\t\tremoveBtn.textContent = this.locale.removeLink;\n\t\t\tremoveBtn.setAttribute('aria-label', this.locale.removeLinkAria);\n\t\t\tremoveBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tcontext.executeCommand('removeLink');\n\t\t\t\tonClose();\n\t\t\t\tcontext.getContainer().focus();\n\t\t\t});\n\t\t\tcontainer.appendChild(removeBtn);\n\t\t} else {\n\t\t\t// Show URL input\n\t\t\tconst input = document.createElement('input');\n\t\t\tinput.type = 'url';\n\t\t\tinput.className = 'notectl-link-popup__input';\n\t\t\tinput.placeholder = this.locale.urlPlaceholder;\n\t\t\tinput.setAttribute('aria-label', this.locale.urlAria);\n\n\t\t\tconst applyBtn = document.createElement('button');\n\t\t\tapplyBtn.type = 'button';\n\t\t\tapplyBtn.className = 'notectl-link-popup__button notectl-link-popup__button--apply';\n\t\t\tapplyBtn.textContent = this.locale.apply;\n\t\t\tapplyBtn.setAttribute('aria-label', this.locale.applyAria);\n\n\t\t\tconst errorMsg = document.createElement('div');\n\t\t\terrorMsg.className = 'notectl-link-popup__error';\n\t\t\terrorMsg.setAttribute('role', 'alert');\n\t\t\terrorMsg.hidden = true;\n\n\t\t\tconst applyLink = (): void => {\n\t\t\t\tconst raw: string = input.value.trim();\n\t\t\t\tif (raw === '') return;\n\t\t\t\tconst sanitized: string = sanitizeHref(raw);\n\t\t\t\tif (sanitized === '') {\n\t\t\t\t\terrorMsg.textContent = this.locale.invalidUrl;\n\t\t\t\t\terrorMsg.hidden = false;\n\t\t\t\t\tinput.setAttribute('aria-invalid', 'true');\n\t\t\t\t\tinput.focus();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\terrorMsg.hidden = true;\n\t\t\t\tinput.removeAttribute('aria-invalid');\n\t\t\t\tthis.addLink(context, context.getState(), sanitized);\n\t\t\t\tonClose();\n\t\t\t\tcontext.getContainer().focus();\n\t\t\t};\n\n\t\t\tapplyBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tapplyLink();\n\t\t\t});\n\n\t\t\tinput.addEventListener('keydown', (e) => {\n\t\t\t\tif (e.key === 'Enter') {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tapplyLink();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tinput.addEventListener('input', () => {\n\t\t\t\tif (!errorMsg.hidden) {\n\t\t\t\t\terrorMsg.hidden = true;\n\t\t\t\t\tinput.removeAttribute('aria-invalid');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tcontainer.appendChild(input);\n\t\t\tcontainer.appendChild(applyBtn);\n\t\t\tcontainer.appendChild(errorMsg);\n\n\t\t\t// Auto-focus input\n\t\t\trequestAnimationFrame(() => input.focus());\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LinkPlugin-CvWHbSkb.mjs","names":[],"sources":["../../src/plugins/link/LinkLocale.ts","../../src/plugins/link/LinkPlugin.ts"],"sourcesContent":["/**\n * Locale interface and default English locale for the LinkPlugin.\n */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\n// --- Locale Interface ---\n\nexport interface LinkLocale {\n\treadonly label: string;\n\treadonly tooltip: (shortcut: string) => string;\n\treadonly removeLink: string;\n\treadonly removeLinkAria: string;\n\treadonly urlPlaceholder: string;\n\treadonly urlAria: string;\n\treadonly apply: string;\n\treadonly applyAria: string;\n\treadonly invalidUrl: string;\n}\n\n// --- Default English Locale ---\n\nexport const LINK_LOCALE_EN: LinkLocale = {\n\tlabel: 'Link',\n\ttooltip: (shortcut: string) => `Insert Link (${shortcut})`,\n\tremoveLink: 'Remove Link',\n\tremoveLinkAria: 'Remove link',\n\turlPlaceholder: 'https://...',\n\turlAria: 'Link URL',\n\tapply: 'Apply',\n\tapplyAria: 'Apply link',\n\tinvalidUrl: 'Only http(s), mailto, tel, fragments, and relative paths are allowed.',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<LinkLocale> = import.meta.glob<{\n\tdefault: LinkLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadLinkLocale(lang: string): Promise<LinkLocale> {\n\treturn loadLocaleModule(localeModules, lang, LINK_LOCALE_EN);\n}\n","/**\n * LinkPlugin: registers a link mark type with href attribute,\n * toggle command, keyboard shortcut (Mod-K), and toolbar button\n * with a URL input popup.\n */\n\nimport {\n\tapplyAttributedMark,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from '../../commands/AttributedMarkCommands.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport { hasMark } from '../../model/Document.js';\nimport { escapeHTML, fragmentIdentifiers, sanitizeHref } from '../../model/HTMLUtils.js';\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { dispatchIfPresent, resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { LINK_LOCALE_EN, type LinkLocale, loadLinkLocale } from './LinkLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tlink: { href: string; title?: string };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface LinkConfig {\n\t/** Whether to add rel=\"noopener noreferrer\" and target=\"_blank\" by default. */\n\treadonly openInNewTab: boolean;\n\t/** Live Markdown shortcuts: `[text](url \"title\")` and `<url>` autolink. Default true. */\n\treadonly inputRule?: boolean;\n\treadonly locale?: LinkLocale;\n}\n\nconst DEFAULT_CONFIG: LinkConfig = {\n\topenInNewTab: true,\n};\n\n// The inline-node placeholder (U+FFFC) is excluded from every re-inserted\n// capture so a live link rule never spans an inline node nor writes the\n// sentinel back as literal text.\n/** `[text](url \"optional title\")`, not preceded by `!` (which would be an image). */\nconst LINK_RULE = /(?:^|[^!])(\\[([^\\]\\uFFFC]+)\\]\\(([^)\\s\\uFFFC]+)(?:\\s+\"([^\"\\uFFFC]*)\")?\\))$/;\n/** `<scheme:...>` autolink. */\nconst AUTOLINK_RULE = /(<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\\s\\uFFFC]+)>)$/;\n\n/** Fragment-only links stay in the current editor even when external links open in a new tab. */\nfunction shouldOpenInNewTab(href: string, openInNewTab: boolean): boolean {\n\treturn openInNewTab && !href.startsWith('#');\n}\n\n/** Finds the clicked anchor without interpolating user-controlled data into a CSS selector. */\nfunction findClickedAnchor(\n\tcontainer: HTMLElement,\n\ttarget: EventTarget | null,\n): HTMLAnchorElement | null {\n\tlet element: Element | null =\n\t\ttarget instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n\n\twhile (element && container.contains(element)) {\n\t\tif (element instanceof HTMLAnchorElement) return element;\n\t\tif (element === container) break;\n\t\telement = element.parentElement;\n\t}\n\n\treturn null;\n}\n\n/** Resolves an ID inside this editor by direct string comparison, never through a CSS selector. */\nfunction findFragmentTarget(\n\tcontainer: HTMLElement,\n\tidentifiers: readonly string[],\n): Element | null {\n\tfor (const identifier of identifiers) {\n\t\tif (container.id === identifier) return container;\n\n\t\tconst descendants: HTMLCollectionOf<Element> = container.getElementsByTagName('*');\n\t\tfor (let index = 0; index < descendants.length; index++) {\n\t\t\tconst descendant: Element | null = descendants.item(index);\n\t\t\tif (descendant?.id === identifier) return descendant;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n// --- Plugin ---\n\nexport class LinkPlugin implements Plugin {\n\treadonly id = 'link';\n\treadonly name = 'Link';\n\treadonly priority = 25;\n\n\tprivate readonly config: LinkConfig;\n\tprivate locale!: LinkLocale;\n\tprivate fragmentClickContainer: HTMLElement | null = null;\n\tprivate fragmentClickHandler: ((event: MouseEvent) => void) | null = null;\n\n\tconstructor(config?: Partial<LinkConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(context, this.config.locale, LINK_LOCALE_EN, loadLinkLocale);\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymap(context);\n\t\tthis.registerToolbarItem(context);\n\t\tif (this.config.inputRule !== false) {\n\t\t\tthis.registerInputRules(context);\n\t\t}\n\t\tthis.installFragmentClickHandler(context);\n\t}\n\n\tdestroy(): void {\n\t\tthis.removeFragmentClickHandler();\n\t}\n\n\t/**\n\t * Live Markdown link rules: `[text](url \"title\")` and `<url>` autolink. Bespoke\n\t * (not the shared wrapping-mark helper) because links carry an `href`/`title`\n\t * attribute and two capture groups (D6).\n\t */\n\tprivate registerInputRules(context: PluginContext): void {\n\t\tconst buildLink = (\n\t\t\tstate: EditorState,\n\t\t\tblockId: BlockNode['id'],\n\t\t\tstart: number,\n\t\t\tend: number,\n\t\t\ttext: string,\n\t\t\thref: string,\n\t\t\ttitle?: string,\n\t\t) => {\n\t\t\tconst attrs: Record<string, string> = { href };\n\t\t\tif (title) attrs.title = title;\n\t\t\treturn state\n\t\t\t\t.transaction('input')\n\t\t\t\t.deleteTextAt(blockId, start, end)\n\t\t\t\t.insertText(blockId, start, text, [{ type: markType('link'), attrs }])\n\t\t\t\t.setSelection(createCollapsedSelection(blockId, start + text.length))\n\t\t\t\t.build();\n\t\t};\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern: LINK_RULE,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel) || !isCollapsed(sel)) return null;\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst expr = match[1];\n\t\t\t\tconst text = match[2];\n\t\t\t\tconst rawHref = match[3];\n\t\t\t\tconst title = match[4];\n\t\t\t\tif (!expr || !text || !rawHref) return null;\n\t\t\t\tconst href: string = sanitizeHref(rawHref);\n\t\t\t\tif (href === '') return null;\n\n\t\t\t\treturn buildLink(state, sel.anchor.blockId, end - expr.length, end, text, href, title);\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerInputRule({\n\t\t\tpattern: AUTOLINK_RULE,\n\t\t\thandler(state, match, _start, end) {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\tif (!isTextSelection(sel) || !isCollapsed(sel)) return null;\n\t\t\t\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type === 'code_block') return null;\n\n\t\t\t\tconst expr = match[1];\n\t\t\t\tconst url = match[2];\n\t\t\t\tif (!expr || !url) return null;\n\t\t\t\tconst href: string = sanitizeHref(url);\n\t\t\t\tif (href === '') return null;\n\n\t\t\t\treturn buildLink(state, sel.anchor.blockId, end - expr.length, end, url, href);\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tconst openInNewTab = this.config.openInNewTab;\n\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'link',\n\t\t\trank: 10,\n\t\t\tinclusive: false,\n\t\t\tattrs: {\n\t\t\t\thref: { default: '' },\n\t\t\t\ttitle: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst a = document.createElement('a');\n\t\t\t\tconst href: string = sanitizeHref(String(mark.attrs?.href ?? ''));\n\t\t\t\ta.setAttribute('href', href);\n\t\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\t\tif (title) a.setAttribute('title', title);\n\t\t\t\tif (shouldOpenInNewTab(href, openInNewTab)) {\n\t\t\t\t\ta.setAttribute('target', '_blank');\n\t\t\t\t\ta.setAttribute('rel', 'noopener noreferrer');\n\t\t\t\t}\n\t\t\t\treturn a;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst safeHref: string = sanitizeHref(String(mark.attrs?.href ?? ''));\n\t\t\t\tconst href: string = escapeHTML(safeHref);\n\t\t\t\tconst titleValue: string = String(mark.attrs?.title ?? '');\n\t\t\t\tconst titleAttr: string = titleValue ? ` title=\"${escapeHTML(titleValue)}\"` : '';\n\t\t\t\tif (shouldOpenInNewTab(safeHref, openInNewTab)) {\n\t\t\t\t\treturn `<a href=\"${href}\"${titleAttr} target=\"_blank\" rel=\"noopener noreferrer\">${content}</a>`;\n\t\t\t\t}\n\t\t\t\treturn `<a href=\"${href}\"${titleAttr}>${content}</a>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'a',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\t// Returning an empty href (instead of `false`) keeps the link mark\n\t\t\t\t\t\t// applied so the parser does not fall back to the core HTMLParser's\n\t\t\t\t\t\t// raw-href default; the empty value renders as a no-op anchor.\n\t\t\t\t\t\tconst href: string = sanitizeHref(el.getAttribute('href') ?? '');\n\t\t\t\t\t\tconst title: string = el.getAttribute('title') ?? '';\n\t\t\t\t\t\treturn title ? { href, title } : { href };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['a'], attrs: ['href', 'title', 'target', 'rel'] },\n\t\t});\n\t}\n\n\tprivate installFragmentClickHandler(context: PluginContext): void {\n\t\tthis.removeFragmentClickHandler();\n\n\t\tconst container: HTMLElement = context.getContainer();\n\t\tconst handler = (event: MouseEvent): void => {\n\t\t\tif (\n\t\t\t\tevent.defaultPrevented ||\n\t\t\t\tevent.button !== 0 ||\n\t\t\t\tevent.metaKey ||\n\t\t\t\tevent.ctrlKey ||\n\t\t\t\tevent.shiftKey ||\n\t\t\t\tevent.altKey\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst anchor: HTMLAnchorElement | null = findClickedAnchor(container, event.target);\n\t\t\tif (!anchor) return;\n\n\t\t\tconst identifiers: readonly string[] = fragmentIdentifiers(anchor.getAttribute('href') ?? '');\n\t\t\tif (identifiers.length === 0) return;\n\n\t\t\tconst target: Element | null = findFragmentTarget(container, identifiers);\n\t\t\tif (!target) return;\n\n\t\t\tevent.preventDefault();\n\t\t\ttarget.scrollIntoView();\n\t\t};\n\n\t\tthis.fragmentClickContainer = container;\n\t\tthis.fragmentClickHandler = handler;\n\t\tcontainer.addEventListener('click', handler);\n\t}\n\n\tprivate removeFragmentClickHandler(): void {\n\t\tif (this.fragmentClickContainer && this.fragmentClickHandler) {\n\t\t\tthis.fragmentClickContainer.removeEventListener('click', this.fragmentClickHandler);\n\t\t}\n\t\tthis.fragmentClickContainer = null;\n\t\tthis.fragmentClickHandler = null;\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.toggleLink(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setLink', () => {\n\t\t\t// setLink is called by the popup after URL input\n\t\t\t// The actual URL is set via the popup's custom render\n\t\t\treturn false;\n\t\t});\n\n\t\tcontext.registerCommand('removeLink', () => {\n\t\t\tconst state = context.getState();\n\t\t\treturn this.removeLink(context, state);\n\t\t});\n\t}\n\n\tprivate registerKeymap(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-K': () => context.executeCommand('toggleLink'),\n\t\t});\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst icon =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/></svg>';\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'link',\n\t\t\tgroup: 'insert',\n\t\t\ticon,\n\t\t\tlabel: this.locale.label,\n\t\t\ttooltip: this.locale.tooltip(formatShortcut('Mod-K')),\n\t\t\tcommand: 'toggleLink',\n\t\t\tpopupType: 'custom',\n\t\t\trenderPopup: (container, ctx, onClose) => {\n\t\t\t\tthis.renderLinkPopup(container, ctx, onClose);\n\t\t\t},\n\t\t\tisActive: (state) => this.isLinkActive(state),\n\t\t\tisEnabled: (state) => !isCollapsed(state.selection),\n\t\t});\n\t}\n\n\tprivate isLinkActive(state: EditorState): boolean {\n\t\treturn isAttributedMarkActive(state, 'link');\n\t}\n\n\tprivate toggleLink(context: PluginContext, state: EditorState): boolean {\n\t\tif (this.isLinkActive(state)) {\n\t\t\treturn this.removeLink(context, state);\n\t\t}\n\t\t// Adding links requires the toolbar popup for URL input\n\t\treturn false;\n\t}\n\n\tprivate addLink(context: PluginContext, state: EditorState, href: string): boolean {\n\t\tconst sel = state.selection;\n\t\tif (!isTextSelection(sel)) return false;\n\t\tif (isCollapsed(sel)) return false;\n\n\t\tconst mark = { type: markType('link'), attrs: { href } };\n\t\treturn dispatchIfPresent(context, applyAttributedMark(state, mark));\n\t}\n\n\tprivate removeLink(context: PluginContext, state: EditorState): boolean {\n\t\tconst sel = state.selection;\n\t\tif (!isTextSelection(sel)) return false;\n\n\t\tif (isCollapsed(sel)) {\n\t\t\t// Remove link from entire link span around cursor (plugin-specific extent scan)\n\t\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\t\tif (!block) return false;\n\n\t\t\tconst textChildren: { pos: number; end: number; hasLink: boolean }[] = [];\n\t\t\tlet pos = 0;\n\t\t\tfor (const child of block.children) {\n\t\t\t\tif (!('text' in child)) continue;\n\t\t\t\tconst end = pos + child.text.length;\n\t\t\t\ttextChildren.push({ pos, end, hasLink: hasMark(child.marks, markType('link')) });\n\t\t\t\tpos = end;\n\t\t\t}\n\n\t\t\tconst cursorIdx = textChildren.findIndex(\n\t\t\t\t(c) => sel.anchor.offset >= c.pos && sel.anchor.offset <= c.end,\n\t\t\t);\n\t\t\tconst cursorEntry = cursorIdx >= 0 ? textChildren[cursorIdx] : undefined;\n\t\t\tif (cursorIdx === -1 || !cursorEntry?.hasLink) return false;\n\n\t\t\tlet startIdx = cursorIdx;\n\t\t\twhile (startIdx > 0 && textChildren[startIdx - 1]?.hasLink) {\n\t\t\t\tstartIdx--;\n\t\t\t}\n\n\t\t\tlet endIdx = cursorIdx;\n\t\t\twhile (endIdx < textChildren.length - 1 && textChildren[endIdx + 1]?.hasLink) {\n\t\t\t\tendIdx++;\n\t\t\t}\n\n\t\t\tconst startEntry = textChildren[startIdx];\n\t\t\tconst endEntry = textChildren[endIdx];\n\t\t\tif (!startEntry || !endEntry) return false;\n\n\t\t\tconst linkStart = startEntry.pos;\n\t\t\tconst linkEnd = endEntry.end;\n\n\t\t\tconst builder = state.transaction('command');\n\t\t\tbuilder.removeMark(sel.anchor.blockId, linkStart, linkEnd, { type: markType('link') });\n\t\t\tbuilder.setSelection(sel);\n\t\t\tcontext.dispatch(builder.build());\n\t\t\treturn true;\n\t\t}\n\n\t\t// Range selection: delegate to shared helper\n\t\treturn dispatchIfPresent(context, removeAttributedMark(state, markType('link')));\n\t}\n\n\tprivate renderLinkPopup(\n\t\tcontainer: HTMLElement,\n\t\tcontext: PluginContext,\n\t\tonClose: () => void,\n\t): void {\n\t\tcontainer.classList.add('notectl-link-popup');\n\n\t\tconst state = context.getState();\n\t\tconst isActive = this.isLinkActive(state);\n\n\t\tif (isActive) {\n\t\t\t// Show remove link button\n\t\t\tconst removeBtn = document.createElement('button');\n\t\t\tremoveBtn.type = 'button';\n\t\t\tremoveBtn.className = 'notectl-link-popup__button';\n\t\t\tremoveBtn.textContent = this.locale.removeLink;\n\t\t\tremoveBtn.setAttribute('aria-label', this.locale.removeLinkAria);\n\t\t\tremoveBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tcontext.executeCommand('removeLink');\n\t\t\t\tonClose();\n\t\t\t\tcontext.getContainer().focus();\n\t\t\t});\n\t\t\tcontainer.appendChild(removeBtn);\n\t\t} else {\n\t\t\t// Show URL input\n\t\t\tconst input = document.createElement('input');\n\t\t\tinput.type = 'url';\n\t\t\tinput.className = 'notectl-link-popup__input';\n\t\t\tinput.placeholder = this.locale.urlPlaceholder;\n\t\t\tinput.setAttribute('aria-label', this.locale.urlAria);\n\n\t\t\tconst applyBtn = document.createElement('button');\n\t\t\tapplyBtn.type = 'button';\n\t\t\tapplyBtn.className = 'notectl-link-popup__button notectl-link-popup__button--apply';\n\t\t\tapplyBtn.textContent = this.locale.apply;\n\t\t\tapplyBtn.setAttribute('aria-label', this.locale.applyAria);\n\n\t\t\tconst errorMsg = document.createElement('div');\n\t\t\terrorMsg.className = 'notectl-link-popup__error';\n\t\t\terrorMsg.setAttribute('role', 'alert');\n\t\t\terrorMsg.hidden = true;\n\n\t\t\tconst applyLink = (): void => {\n\t\t\t\tconst raw: string = input.value.trim();\n\t\t\t\tif (raw === '') return;\n\t\t\t\tconst sanitized: string = sanitizeHref(raw);\n\t\t\t\tif (sanitized === '') {\n\t\t\t\t\terrorMsg.textContent = this.locale.invalidUrl;\n\t\t\t\t\terrorMsg.hidden = false;\n\t\t\t\t\tinput.setAttribute('aria-invalid', 'true');\n\t\t\t\t\tinput.focus();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\terrorMsg.hidden = true;\n\t\t\t\tinput.removeAttribute('aria-invalid');\n\t\t\t\tthis.addLink(context, context.getState(), sanitized);\n\t\t\t\tonClose();\n\t\t\t\tcontext.getContainer().focus();\n\t\t\t};\n\n\t\t\tapplyBtn.addEventListener('mousedown', (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tapplyLink();\n\t\t\t});\n\n\t\t\tinput.addEventListener('keydown', (e) => {\n\t\t\t\tif (e.key === 'Enter') {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tapplyLink();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tinput.addEventListener('input', () => {\n\t\t\t\tif (!errorMsg.hidden) {\n\t\t\t\t\terrorMsg.hidden = true;\n\t\t\t\t\tinput.removeAttribute('aria-invalid');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tcontainer.appendChild(input);\n\t\t\tcontainer.appendChild(applyBtn);\n\t\t\tcontainer.appendChild(errorMsg);\n\n\t\t\t// Auto-focus input\n\t\t\trequestAnimationFrame(() => input.focus());\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{E as t,_ as e,f as n,o as i,p as s,u as c}from"./Document-827l3P80.mjs";import{d as r,o,t as l,u as a}from"./Selection-HYoVFpAx.mjs";import{a as d,t as h}from"./TypeBrands-Ch9856Gb.mjs";import{r as u}from"./AttrRegistry-B3zB02z9.mjs";import{n as m}from"./DomUtils-Bf7JLFlx.mjs";import{l as p}from"./BlockInsertion-CJusvrDL.mjs";import{t as k}from"./RangeIterator-DP7Ud3Gp.mjs";import{c as f}from"./StyleRuntime-DW6omotc.mjs";import{c as b,o as g}from"./PluginHelpers-Dx_0hfDe.mjs";function y(t,e,n){return"checklist"===t?{listType:t,indent:e,checked:n??!1}:{listType:t,indent:e}}function v(t,e){const n=t.getBlock(e);if("list_item"===n?.type)return n;const i=t.getNodePath(e);if(i)for(let s=i.length-2;s>=0;s--){const e=i[s],n=e?t.getBlock(e):void 0;if("list_item"===n?.type)return n}}function x(t,e){const n=t.getBlock(e);if(!n||"list_item"!==n.type)return;const i=t.getNodePath(e);if(!i)return;const c=i.slice(0,-1),r=c[c.length-1],o=(r?s(t.getBlock(r)):t.doc.children).findIndex(t=>t.id===e);return o<0?void 0:{item:n,parentPath:c,index:o}}function I(t,e){t.removeNode(e.parentPath,e.index),s(e.item).forEach((n,i)=>{t.insertNode(e.parentPath,e.index+i,n)})}function T(e,n){const i=e.getState(),s=i.selection;return!!a(s)&&(s.anchor.blockId!==s.head.blockId?function(e,n,i){const s=n.selection;if(!a(s))return!1;const c=r(s,n.getBlockOrder()),o=w(n,c,i),l=n.transaction("command"),h=function(t,e){const n=[],i=/* @__PURE__ */new Set;return k(t,e,e=>{const s=t.getBlock(e);if(!s)return;const c=v(t,e)??s;i.has(c.id)||(i.add(c.id),n.push(c))}),n}(n,c);for(let r=h.length-1;r>=0;r--){const e=h[r];if(e)if(o)if(t(e))l.setBlockType(e.id,d("paragraph"));else{const t=x(n,e.id);t&&I(l,t)}else{const t=u(e,"list_item")?e.attrs.indent:0,n=u(e,"list_item")&&"checklist"===e.attrs.listType&&e.attrs.checked;l.setBlockType(e.id,d("list_item"),y(i,t,n))}}return l.setSelection(s),e.dispatch(l.build()),!0}(e,i,n):function(e,n,i){const s=n.selection;if(!a(s))return!1;const c=n.getBlock(s.anchor.blockId);if(!c)return!1;const r=v(n,s.anchor.blockId),o=r??c;if(r&&r.attrs?.listType===i){const i=n.transaction("command");if(t(r))i.setBlockType(r.id,d("paragraph"));else{const t=x(n,r.id);if(!t)return!1;I(i,t)}return i.setSelection(s),e.dispatch(i.build()),!0}const l=y(i,u(o,"list_item")?o.attrs.indent:0),h=n.transaction("command").setBlockType(o.id,d("list_item"),l).setSelection(s).build();return e.dispatch(h),!0}(e,i,n))}function S(t,e,n){const i=t.getState();if(!a(i.selection))return!1;if(i.selection.anchor.blockId!==i.selection.head.blockId)return function(t,e,n,i){const s=e.selection;if(!a(s))return!1;const c=r(s,e.getBlockOrder()),o=e.transaction("command");let l=!1;const h=/* @__PURE__ */new Set;return k(e,c,t=>{const s=v(e,t);if(!s||!u(s,"list_item"))return;if(h.has(s.id))return;h.add(s.id);const c=s.attrs.indent+n;c<0||c>i||(o.setBlockType(s.id,d("list_item"),y(s.attrs.listType,c,s.attrs.checked)),l=!0)}),!!l&&(o.setSelection(s),t.dispatch(o.build()),!0)}(t,i,e,n);const s=i.selection,c=v(i,s.anchor.blockId);if(!c||!u(c,"list_item"))return!1;const o=c.attrs.indent+e;if(o<0||o>n)return!1;const l=y(c.attrs.listType,o,c.attrs.checked),h=i.transaction("command").setBlockType(c.id,d("list_item"),l).setSelection(s).build();return t.dispatch(h),!0}function C(t,e){const{interactiveCheckboxes:n,targetId:i,locale:s}=e;if(t.isReadOnly()&&!n)return!1;const c=t.getState(),r=i??(a(c.selection)?c.selection.anchor.blockId:null);if(!r)return!1;const o=v(c,r);if(!o||!u(o,"list_item")||"checklist"!==o.attrs.listType)return!1;const l=!o.attrs.checked,h=y(o.attrs.listType,o.attrs.indent,l),m=c.transaction("command").setBlockType(o.id,d("list_item"),h).setSelection(c.selection).build();return t.dispatch(m),t.announce(l?s.checkedAnnouncement:s.uncheckedAnnouncement),!0}function w(t,e,n){let i=!0;return k(t,e,e=>{const s=v(t,e);s&&"list_item"===s.type&&s.attrs?.listType===n||(i=!1)}),i}var B=[{type:"bullet",icon:'<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>',inputPattern:/^[-*] $/,inputPrefix:"- "},{type:"ordered",icon:'<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>',inputPattern:/^\d+\. $/,inputPrefix:"1. "},{type:"checklist",icon:'<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>',inputPattern:/^\[[ x]] $/,inputPrefix:"[ ] "}];function L(t,e){const n=t.getState();if(!a(n.selection))return!1;const i=n.selection;if(!o(i))return!1;const c=n.getBlock(i.anchor.blockId);if(!c)return!1;if("list_item"===c.type)return e({state:n,item:c,child:void 0,childIndex:-1,childCount:0,blockId:i.anchor.blockId,offset:i.anchor.offset});const r=n.getParent(i.anchor.blockId);if(!r||"list_item"!==r.type)return!1;const l=s(r),d=l.findIndex(t=>t.id===c.id);return!(d<0)&&e({state:n,item:r,child:c,childIndex:d,childCount:l.length,blockId:i.anchor.blockId,offset:i.anchor.offset})}var _={bulletList:"Bullet List",numberedList:"Numbered List",checklist:"Checklist",checkboxLabel:"To-do item",checkedAnnouncement:"Checked",uncheckedAnnouncement:"Unchecked"},H=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Cy_77yRf.mjs"),"./locales/de.ts":()=>import("./de-CaeEIyzV.mjs"),"./locales/es.ts":()=>import("./es-DFokqQst.mjs"),"./locales/fr.ts":()=>import("./fr-5HkMazAf.mjs"),"./locales/hi.ts":()=>import("./hi-BzbMD_cP.mjs"),"./locales/pt.ts":()=>import("./pt-CR4j8gtE.mjs"),"./locales/ru.ts":()=>import("./ru-DiwQV30V.mjs"),"./locales/zh.ts":()=>import("./zh-BQqf3wJZ.mjs")});async function z(t){return b(H,t,_)}var A="notectl-checklist-marker";function j(t,e){return{bullet:e.bulletList,ordered:e.numberedList,checklist:e.checklist}[t]}function P(t,e){if(!a(t.selection))return!1;if(t.selection.anchor.blockId!==t.selection.head.blockId)return w(t,r(t.selection,t.getBlockOrder()),e);const n=v(t,t.selection.anchor.blockId);return"list_item"===n?.type&&n.attrs?.listType===e}var $={types:["bullet","ordered","checklist"],maxIndent:4},N=class{id="list";name="List";priority=35;config;locale;context=null;checkboxClickHandler=null;constructor(t){this.config={...$,...t}}async init(t){this.context=t,this.locale=await g(t,this.config.locale,_,z);const s=this.getEnabledTypes();t.registerStyleSheet("\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;\n\tpadding-inline-start: 24px;\n\tmin-height: 1.6em;\n\tposition: relative;\n}\n\n.notectl-list-item::before {\n\tposition: absolute;\n\tinset-inline-start: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n\t-webkit-user-select: none;\n\tuser-select: none;\n\tpointer-events: none;\n}\n\n/* Container items (#194): block children inherit the item's start padding.\n Trim the first/last child paragraph padding so the first text line sits on\n the marker's line and the item keeps the leaf item's vertical rhythm. */\n.notectl-list-item > p:first-of-type {\n\tpadding-top: 0;\n}\n\n.notectl-list-item > p:last-of-type {\n\tpadding-bottom: 0;\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 — the marker is a real role=\"checkbox\" element (see ListMarker.ts)\n positioned over the reserved marker zone. inline-block keeps the parent's\n line-through (on checked items) from striking the glyph. */\n.notectl-checklist-marker {\n\tposition: absolute;\n\tinset-inline-start: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n\tfont-size: 16px;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n\ttext-decoration: none;\n\t-webkit-user-select: none;\n\tuser-select: none;\n}\n\n.notectl-checklist-marker::before {\n\tcontent: '\\2610';\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] .notectl-checklist-marker {\n\tcolor: var(--notectl-success);\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] .notectl-checklist-marker::before {\n\tcontent: '\\2611';\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] {\n\tcolor: var(--notectl-fg-muted);\n\ttext-decoration: line-through;\n}\n"),this.registerNodeSpec(t),function(t,e,n,i){for(const s of n)t.registerCommand(`toggleList:${s.type}`,()=>T(t,s.type));if(t.registerCommand("indentListItem",()=>S(t,1,e.maxIndent)),t.registerCommand("outdentListItem",()=>S(t,-1,e.maxIndent)),e.types.includes("checklist")){const n=()=>C(t,{interactiveCheckboxes:e.interactiveCheckboxes,locale:i});t.registerCommand("toggleChecklistItem",n,{readonlyAllowed:!0}),t.registerKeymap({"Mod-Enter":n},{priority:"navigation"})}t.registerKeymap({Tab:()=>S(t,1,e.maxIndent),"Shift-Tab":()=>S(t,-1,e.maxIndent)})}(t,this.config,s,this.locale),function(t){t.registerKeymap({Enter:()=>function(t){return L(t,s=>{if(s.child)return function(t,e,s){if(!p(s))return!1;if(e.childIndex!==e.childCount-1)return!1;const r=x(e.state,e.item.id);if(!r)return!1;const o=e.state.transaction("input");if(1===e.childCount)return I(o,r),o.setSelection(e.state.selection),t.dispatch(o.build()),!0;const a=u(e.item,"list_item")?e.item.attrs.listType:"bullet",h=u(e.item,"list_item")?e.item.attrs.indent:0,m=n(),k=i(d("list_item"),[c("")],m,y(a,h));return o.removeNode([...r.parentPath,e.item.id],e.childIndex).insertNode(r.parentPath,r.index+1,k).setSelection(l(m,0)),t.dispatch(o.build()),!0}(t,s,s.child);if(""===e(s.item)){const e=s.state.transaction("input").setBlockType(s.blockId,d("paragraph")).setSelection(s.state.selection).build();return t.dispatch(e),!0}const r=n(),o=y(u(s.item,"list_item")?s.item.attrs.listType:"bullet",u(s.item,"list_item")?s.item.attrs.indent:0),a=s.state.transaction("input").splitBlock(s.blockId,s.offset,r).setBlockType(r,d("list_item"),o).setSelection(l(r,0)).build();return t.dispatch(a),!0})}(t),Backspace:()=>function(t){return L(t,e=>{if(0!==e.offset)return!1;if(e.child){if(0!==e.childIndex)return!1;const n=x(e.state,e.item.id);if(!n)return!1;const i=e.state.transaction("input");return I(i,n),i.setSelection(e.state.selection),t.dispatch(i.build()),!0}const n=e.state.transaction("input").setBlockType(e.blockId,d("paragraph")).setSelection(e.state.selection).build();return t.dispatch(n),!0})}(t)})}(t),!1!==this.config.inputRule&&function(t,e){for(const n of e)t.registerInputRule({pattern:n.inputPattern,handler:(t,e,i,s)=>{const c=t.selection;if(!a(c))return null;if(!o(c))return null;const r=t.getBlock(c.anchor.blockId);if(!r||"paragraph"!==r.type)return null;if("list_item"===t.getParent(c.anchor.blockId)?.type)return null;const h=e[0]??"",u=h.length,m=y(n.type,0,h.includes("[x]"));return t.transaction("input").deleteTextAt(c.anchor.blockId,i,i+u).setBlockType(c.anchor.blockId,d("list_item"),m).setSelection(l(c.anchor.blockId,0)).build()}})}(t,s),function(t,e,n){for(const i of e)t.registerToolbarItem({id:`list-${i.type}`,group:"block",icon:i.icon,label:j(i.type,n),command:`toggleList:${i.type}`,isActive:t=>P(t,i.type)})}(t,s,this.locale),this.registerCheckboxClickHandler(t)}destroy(){this.checkboxClickHandler&&this.context&&this.context.getContainer().removeEventListener("mousedown",this.checkboxClickHandler),this.checkboxClickHandler=null,this.context=null}registerNodeSpec(t){const e=this.locale.checkboxLabel;t.registerNodeSpec({type:"list_item",group:"block",content:{allow:["text","paragraph","heading","code_block","blockquote","horizontal_rule"]},attrs:{listType:{default:"bullet"},indent:{default:0},checked:{default:!1}},toDOM(t){const n=t.attrs?.listType??"bullet",i=t.attrs?.indent??0,s=t.attrs?.checked??!1,c=m("li",t.id);return c.setAttribute("role","listitem"),c.setAttribute("data-list-type",n),c.setAttribute("data-indent",String(i)),c.className=`notectl-list-item notectl-list-item--${n}`,i>0&&f(c,"marginLeft",24*i+"px"),"checklist"===n&&(c.setAttribute("data-checked",String(s)),c.appendChild(function(t,e){const n=document.createElement("span");return n.className=A,n.setAttribute("role","checkbox"),n.setAttribute("aria-checked",String(t)),n.setAttribute("aria-label",e),n.setAttribute("contenteditable","false"),n.setAttribute("data-widget","true"),n}(s,e))),c.setAttribute("aria-level",String(i+1)),c},wrapper(t){const e=t.attrs?.listType??"bullet";return{tag:"ordered"===e?"ol":"ul",key:`list-${e}`,className:`notectl-list notectl-list--${e}`,attrs:{role:"list"}}},toHTML(t,e){const n=t.attrs?.listType??"bullet",i=t.attrs?.checked??!1;return"checklist"===n?`<li role="checkbox" aria-checked="${String(i)}"><input type="checkbox" disabled${i?" checked":""}>${e||"<br>"}</li>`:`<li>${e||"<br>"}</li>`},parseHTML:[{tag:"li"}],sanitize:{tags:["ul","ol","li","input"],attrs:["type","disabled","checked","role","aria-checked"]}})}registerCheckboxClickHandler(t){this.config.types.includes("checklist")&&(this.checkboxClickHandler=e=>{if(t.isReadOnly()&&!this.config.interactiveCheckboxes)return;const n=e.target;if(!(n instanceof HTMLElement))return;const i=n.closest(`.${A}`);if(!i)return;const s=i.closest(".notectl-list-item--checklist");if(!s)return;e.preventDefault();const c=s.getAttribute("data-block-id");c&&C(t,{interactiveCheckboxes:this.config.interactiveCheckboxes,targetId:h(c),locale:this.locale})},t.getContainer().addEventListener("mousedown",this.checkboxClickHandler))}getEnabledTypes(){return B.filter(t=>this.config.types.includes(t.type))}};export{_ as n,z as r,N as t};
2
- //# sourceMappingURL=ListPlugin-DAY5ezNs.mjs.map
1
+ import{E as t,_ as e,f as n,o as i,p as s,u as c}from"./Document-827l3P80.mjs";import{d as r,o,t as l,u as a}from"./Selection-HYoVFpAx.mjs";import{a as d,t as u}from"./TypeBrands-Ch9856Gb.mjs";import{l as h}from"./BlockInsertion-CYH2gRkY.mjs";import{t as m}from"./RangeIterator-DP7Ud3Gp.mjs";import{r as p}from"./AttrRegistry-B3zB02z9.mjs";import{c as k,o as f}from"./PluginHelpers-KDuTlmXm.mjs";import{c as b}from"./StyleRuntime-DW6omotc.mjs";import{n as g}from"./DomUtils-Bf7JLFlx.mjs";function y(t,e,n){return"checklist"===t?{listType:t,indent:e,checked:n??!1}:{listType:t,indent:e}}function v(t,e){const n=t.getBlock(e);if("list_item"===n?.type)return n;const i=t.getNodePath(e);if(i)for(let s=i.length-2;s>=0;s--){const e=i[s],n=e?t.getBlock(e):void 0;if("list_item"===n?.type)return n}}function x(t,e){const n=t.getBlock(e);if(!n||"list_item"!==n.type)return;const i=t.getNodePath(e);if(!i)return;const c=i.slice(0,-1),r=c[c.length-1],o=(r?s(t.getBlock(r)):t.doc.children).findIndex(t=>t.id===e);return o<0?void 0:{item:n,parentPath:c,index:o}}function I(t,e){t.removeNode(e.parentPath,e.index),s(e.item).forEach((n,i)=>{t.insertNode(e.parentPath,e.index+i,n)})}function T(e,n){const i=e.getState(),s=i.selection;return!!a(s)&&(s.anchor.blockId!==s.head.blockId?function(e,n,i){const s=n.selection;if(!a(s))return!1;const c=r(s,n.getBlockOrder()),o=B(n,c,i),l=n.transaction("command"),u=function(t,e){const n=[],i=/* @__PURE__ */new Set;return m(t,e,e=>{const s=t.getBlock(e);if(!s)return;const c=v(t,e)??s;i.has(c.id)||(i.add(c.id),n.push(c))}),n}(n,c);for(let r=u.length-1;r>=0;r--){const e=u[r];if(e)if(o)if(t(e))l.setBlockType(e.id,d("paragraph"));else{const t=x(n,e.id);t&&I(l,t)}else{const t=p(e,"list_item")?e.attrs.indent:0,n=p(e,"list_item")&&"checklist"===e.attrs.listType&&e.attrs.checked;l.setBlockType(e.id,d("list_item"),y(i,t,n))}}return l.setSelection(s),e.dispatch(l.build()),!0}(e,i,n):function(e,n,i){const s=n.selection;if(!a(s))return!1;const c=n.getBlock(s.anchor.blockId);if(!c)return!1;const r=v(n,s.anchor.blockId),o=r??c;if(r&&r.attrs?.listType===i){const i=n.transaction("command");if(t(r))i.setBlockType(r.id,d("paragraph"));else{const t=x(n,r.id);if(!t)return!1;I(i,t)}return i.setSelection(s),e.dispatch(i.build()),!0}const l=y(i,p(o,"list_item")?o.attrs.indent:0),u=n.transaction("command").setBlockType(o.id,d("list_item"),l).setSelection(s).build();return e.dispatch(u),!0}(e,i,n))}function S(t,e,n){const i=t.getState();if(!a(i.selection))return!1;if(i.selection.anchor.blockId!==i.selection.head.blockId)return function(t,e,n,i){const s=e.selection;if(!a(s))return!1;const c=r(s,e.getBlockOrder()),o=e.transaction("command");let l=!1;const u=/* @__PURE__ */new Set;return m(e,c,t=>{const s=v(e,t);if(!s||!p(s,"list_item"))return;if(u.has(s.id))return;u.add(s.id);const c=s.attrs.indent+n;c<0||c>i||(o.setBlockType(s.id,d("list_item"),y(s.attrs.listType,c,s.attrs.checked)),l=!0)}),!!l&&(o.setSelection(s),t.dispatch(o.build()),!0)}(t,i,e,n);const s=i.selection,c=v(i,s.anchor.blockId);if(!c||!p(c,"list_item"))return!1;const o=c.attrs.indent+e;if(o<0||o>n)return!1;const l=y(c.attrs.listType,o,c.attrs.checked),u=i.transaction("command").setBlockType(c.id,d("list_item"),l).setSelection(s).build();return t.dispatch(u),!0}function C(t,e){const{interactiveCheckboxes:n,targetId:i,locale:s}=e;if(t.isReadOnly()&&!n)return!1;const c=t.getState(),r=i??(a(c.selection)?c.selection.anchor.blockId:null);if(!r)return!1;const o=v(c,r);if(!o||!p(o,"list_item")||"checklist"!==o.attrs.listType)return!1;const l=!o.attrs.checked,u=y(o.attrs.listType,o.attrs.indent,l),h=c.transaction("command").setBlockType(o.id,d("list_item"),u).setSelection(c.selection).build();return t.dispatch(h),t.announce(l?s.checkedAnnouncement:s.uncheckedAnnouncement),!0}function B(t,e,n){let i=!0;return m(t,e,e=>{const s=v(t,e);s&&"list_item"===s.type&&s.attrs?.listType===n||(i=!1)}),i}var L=[{type:"bullet",icon:'<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>',inputPattern:/^[-*] $/,inputPrefix:"- "},{type:"ordered",icon:'<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>',inputPattern:/^\d+\. $/,inputPrefix:"1. "},{type:"checklist",icon:'<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>',inputPattern:/^\[[ x]] $/,inputPrefix:"[ ] "}];function w(t,e){const n=t.getState();if(!a(n.selection))return!1;const i=n.selection;if(!o(i))return!1;const c=n.getBlock(i.anchor.blockId);if(!c)return!1;if("list_item"===c.type)return e({state:n,item:c,child:void 0,childIndex:-1,childCount:0,blockId:i.anchor.blockId,offset:i.anchor.offset});const r=n.getParent(i.anchor.blockId);if(!r||"list_item"!==r.type)return!1;const l=s(r),d=l.findIndex(t=>t.id===c.id);return!(d<0)&&e({state:n,item:r,child:c,childIndex:d,childCount:l.length,blockId:i.anchor.blockId,offset:i.anchor.offset})}var _={bulletList:"Bullet List",numberedList:"Numbered List",checklist:"Checklist",checkboxLabel:"To-do item",checkedAnnouncement:"Checked",uncheckedAnnouncement:"Unchecked"},H=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Cy_77yRf.mjs"),"./locales/de.ts":()=>import("./de-CaeEIyzV.mjs"),"./locales/es.ts":()=>import("./es-DFokqQst.mjs"),"./locales/fr.ts":()=>import("./fr-5HkMazAf.mjs"),"./locales/hi.ts":()=>import("./hi-BzbMD_cP.mjs"),"./locales/pt.ts":()=>import("./pt-CR4j8gtE.mjs"),"./locales/ru.ts":()=>import("./ru-DiwQV30V.mjs"),"./locales/zh.ts":()=>import("./zh-BQqf3wJZ.mjs")});async function z(t){return k(H,t,_)}var A="notectl-checklist-marker";function j(t,e){return{bullet:e.bulletList,ordered:e.numberedList,checklist:e.checklist}[t]}function P(t,e){if(!a(t.selection))return!1;if(t.selection.anchor.blockId!==t.selection.head.blockId)return B(t,r(t.selection,t.getBlockOrder()),e);const n=v(t,t.selection.anchor.blockId);return"list_item"===n?.type&&n.attrs?.listType===e}var $={types:["bullet","ordered","checklist"],maxIndent:4},N=class{id="list";name="List";priority=35;config;locale;context=null;checkboxClickHandler=null;constructor(t){this.config={...$,...t}}async init(t){this.context=t,this.locale=await f(t,this.config.locale,_,z);const s=this.getEnabledTypes();t.registerStyleSheet("\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;\n\tpadding-inline-start: 24px;\n\tmin-height: 1.6em;\n\tposition: relative;\n}\n\n.notectl-list-item::before {\n\tposition: absolute;\n\tinset-inline-start: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n\t-webkit-user-select: none;\n\tuser-select: none;\n\tpointer-events: none;\n}\n\n/* Container items (#194): block children inherit the item's start padding.\n Trim the first/last child paragraph padding so the first text line sits on\n the marker's line and the item keeps the leaf item's vertical rhythm. */\n.notectl-list-item > p:first-of-type {\n\tpadding-top: 0;\n}\n\n.notectl-list-item > p:last-of-type {\n\tpadding-bottom: 0;\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 — the marker is a real role=\"checkbox\" element (see ListMarker.ts)\n positioned over the reserved marker zone. inline-block keeps the parent's\n line-through (on checked items) from striking the glyph. */\n.notectl-checklist-marker {\n\tposition: absolute;\n\tinset-inline-start: 0;\n\tdisplay: inline-block;\n\twidth: 24px;\n\ttext-align: center;\n\tfont-size: 16px;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n\ttext-decoration: none;\n\t-webkit-user-select: none;\n\tuser-select: none;\n}\n\n.notectl-checklist-marker::before {\n\tcontent: '\\2610';\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] .notectl-checklist-marker {\n\tcolor: var(--notectl-success);\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] .notectl-checklist-marker::before {\n\tcontent: '\\2611';\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] {\n\tcolor: var(--notectl-fg-muted);\n\ttext-decoration: line-through;\n}\n"),this.registerNodeSpec(t),function(t,e,n,i){for(const s of n)t.registerCommand(`toggleList:${s.type}`,()=>T(t,s.type));if(t.registerCommand("indentListItem",()=>S(t,1,e.maxIndent)),t.registerCommand("outdentListItem",()=>S(t,-1,e.maxIndent)),e.types.includes("checklist")){const n=()=>C(t,{interactiveCheckboxes:e.interactiveCheckboxes,locale:i});t.registerCommand("toggleChecklistItem",n,{readonlyAllowed:!0}),t.registerKeymap({"Mod-Enter":n},{priority:"navigation"})}t.registerKeymap({Tab:()=>S(t,1,e.maxIndent),"Shift-Tab":()=>S(t,-1,e.maxIndent)})}(t,this.config,s,this.locale),function(t){t.registerKeymap({Enter:()=>function(t){return w(t,s=>{if(s.child)return function(t,e,s){if(!h(s))return!1;if(e.childIndex!==e.childCount-1)return!1;const r=x(e.state,e.item.id);if(!r)return!1;const o=e.state.transaction("input");if(1===e.childCount)return I(o,r),o.setSelection(e.state.selection),t.dispatch(o.build()),!0;const a=p(e.item,"list_item")?e.item.attrs.listType:"bullet",u=p(e.item,"list_item")?e.item.attrs.indent:0,m=n(),k=i(d("list_item"),[c("")],m,y(a,u));return o.removeNode([...r.parentPath,e.item.id],e.childIndex).insertNode(r.parentPath,r.index+1,k).setSelection(l(m,0)),t.dispatch(o.build()),!0}(t,s,s.child);if(""===e(s.item)){const e=s.state.transaction("input").setBlockType(s.blockId,d("paragraph")).setSelection(s.state.selection).build();return t.dispatch(e),!0}const r=n(),o=y(p(s.item,"list_item")?s.item.attrs.listType:"bullet",p(s.item,"list_item")?s.item.attrs.indent:0),a=s.state.transaction("input").splitBlock(s.blockId,s.offset,r).setBlockType(r,d("list_item"),o).setSelection(l(r,0)).build();return t.dispatch(a),!0})}(t),Backspace:()=>function(t){return w(t,e=>{if(0!==e.offset)return!1;if(e.child){if(0!==e.childIndex)return!1;const n=x(e.state,e.item.id);if(!n)return!1;const i=e.state.transaction("input");return I(i,n),i.setSelection(e.state.selection),t.dispatch(i.build()),!0}const n=e.state.transaction("input").setBlockType(e.blockId,d("paragraph")).setSelection(e.state.selection).build();return t.dispatch(n),!0})}(t)})}(t),!1!==this.config.inputRule&&function(t,e){for(const n of e)t.registerInputRule({pattern:n.inputPattern,handler:(t,e,i,s)=>{const c=t.selection;if(!a(c))return null;if(!o(c))return null;const r=t.getBlock(c.anchor.blockId);if(!r||"paragraph"!==r.type)return null;if("list_item"===t.getParent(c.anchor.blockId)?.type)return null;const u=e[0]??"",h=u.length,m=y(n.type,0,u.includes("[x]"));return t.transaction("input").deleteTextAt(c.anchor.blockId,i,i+h).setBlockType(c.anchor.blockId,d("list_item"),m).setSelection(l(c.anchor.blockId,0)).build()}})}(t,s),function(t,e,n){for(const i of e)t.registerToolbarItem({id:`list-${i.type}`,group:"block",icon:i.icon,label:j(i.type,n),command:`toggleList:${i.type}`,isActive:t=>P(t,i.type)})}(t,s,this.locale),this.registerCheckboxClickHandler(t)}destroy(){this.checkboxClickHandler&&this.context&&this.context.getContainer().removeEventListener("mousedown",this.checkboxClickHandler),this.checkboxClickHandler=null,this.context=null}registerNodeSpec(t){const e=this.locale.checkboxLabel;t.registerNodeSpec({type:"list_item",group:"block",content:{allow:["text","paragraph","heading","code_block","blockquote","horizontal_rule"]},attrs:{listType:{default:"bullet"},indent:{default:0},checked:{default:!1}},toDOM(t){const n=t.attrs?.listType??"bullet",i=t.attrs?.indent??0,s=t.attrs?.checked??!1,c=g("li",t.id);return c.setAttribute("role","listitem"),c.setAttribute("data-list-type",n),c.setAttribute("data-indent",String(i)),c.className=`notectl-list-item notectl-list-item--${n}`,i>0&&b(c,"marginLeft",24*i+"px"),"checklist"===n&&(c.setAttribute("data-checked",String(s)),c.appendChild(function(t,e){const n=document.createElement("span");return n.className=A,n.setAttribute("role","checkbox"),n.setAttribute("aria-checked",String(t)),n.setAttribute("aria-label",e),n.setAttribute("contenteditable","false"),n.setAttribute("data-widget","true"),n}(s,e))),c.setAttribute("aria-level",String(i+1)),c},wrapper(t){const e=t.attrs?.listType??"bullet";return{tag:"ordered"===e?"ol":"ul",key:`list-${e}`,className:`notectl-list notectl-list--${e}`,attrs:{role:"list"}}},toHTML(t,e){const n=t.attrs?.listType??"bullet",i=t.attrs?.checked??!1;return"checklist"===n?`<li role="checkbox" aria-checked="${String(i)}"><input type="checkbox" disabled${i?" checked":""}>${e||"<br>"}</li>`:`<li>${e||"<br>"}</li>`},parseHTML:[{tag:"li"}],sanitize:{tags:["ul","ol","li","input"],attrs:["type","disabled","checked","role","aria-checked"]}})}registerCheckboxClickHandler(t){this.config.types.includes("checklist")&&(this.checkboxClickHandler=e=>{if(t.isReadOnly()&&!this.config.interactiveCheckboxes)return;const n=e.target;if(!(n instanceof HTMLElement))return;const i=n.closest(`.${A}`);if(!i)return;const s=i.closest(".notectl-list-item--checklist");if(!s)return;e.preventDefault();const c=s.getAttribute("data-block-id");c&&C(t,{interactiveCheckboxes:this.config.interactiveCheckboxes,targetId:u(c),locale:this.locale})},t.getContainer().addEventListener("mousedown",this.checkboxClickHandler))}getEnabledTypes(){return L.filter(t=>this.config.types.includes(t.type))}};export{_ as n,z as r,N as t};
2
+ //# sourceMappingURL=ListPlugin-BchSFWVn.mjs.map