@notectl/core 2.0.4 → 2.0.6

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 (56) hide show
  1. package/dist/chunks/{CaretNavigationPlugin-mQ1nxJ6m.mjs → CaretNavigationPlugin-C-6zNBbl.mjs} +2 -2
  2. package/dist/chunks/{CaretNavigationPlugin-mQ1nxJ6m.mjs.map → CaretNavigationPlugin-C-6zNBbl.mjs.map} +1 -1
  3. package/dist/chunks/{CodeBlockPlugin-oPGiMno0.mjs → CodeBlockPlugin-C8H0nfF6.mjs} +2 -2
  4. package/dist/chunks/{CodeBlockPlugin-oPGiMno0.mjs.map → CodeBlockPlugin-C8H0nfF6.mjs.map} +1 -1
  5. package/dist/chunks/FontPlugin-BDjM9v3y.mjs +2 -0
  6. package/dist/chunks/FontPlugin-BDjM9v3y.mjs.map +1 -0
  7. package/dist/chunks/{ListPlugin-CZgkinoS.mjs → ListPlugin-C_YjbVjT.mjs} +2 -2
  8. package/dist/chunks/ListPlugin-C_YjbVjT.mjs.map +1 -0
  9. package/dist/chunks/{SmartPastePlugin-BvYBbHSA.mjs → SmartPastePlugin-pejM1Zyk.mjs} +2 -2
  10. package/dist/chunks/{SmartPastePlugin-BvYBbHSA.mjs.map → SmartPastePlugin-pejM1Zyk.mjs.map} +1 -1
  11. package/dist/chunks/XmlDetector-B1y1NzDL.mjs +2 -0
  12. package/dist/chunks/XmlDetector-B1y1NzDL.mjs.map +1 -0
  13. package/dist/chunks/{XmlSupport-Czr8xQB1.mjs → XmlSupport-DRkIIe34.mjs} +2 -2
  14. package/dist/chunks/{XmlSupport-Czr8xQB1.mjs.map → XmlSupport-DRkIIe34.mjs.map} +1 -1
  15. package/dist/chunks/{full-B-bw4M7L.mjs → full-NtKyNKJ6.mjs} +2 -2
  16. package/dist/chunks/{full-B-bw4M7L.mjs.map → full-NtKyNKJ6.mjs.map} +1 -1
  17. package/dist/chunks/minimal-gSvMMQTU.mjs +2 -0
  18. package/dist/chunks/{minimal-CMt909kl.mjs.map → minimal-gSvMMQTU.mjs.map} +1 -1
  19. package/dist/chunks/src-CHVVMZB_.mjs +2 -0
  20. package/dist/chunks/src-CHVVMZB_.mjs.map +1 -0
  21. package/dist/editor/styles/list.d.ts +1 -1
  22. package/dist/editor/styles/list.d.ts.map +1 -1
  23. package/dist/full.mjs +1 -1
  24. package/dist/model/KeymapRegistry.d.ts.map +1 -1
  25. package/dist/notectl-core.mjs +1 -1
  26. package/dist/notectl-core.umd.js +1 -1
  27. package/dist/notectl-core.umd.js.map +1 -1
  28. package/dist/plugins/caret-navigation.mjs +1 -1
  29. package/dist/plugins/code-block.mjs +1 -1
  30. package/dist/plugins/font/FontPlugin.d.ts.map +1 -1
  31. package/dist/plugins/font.mjs +1 -1
  32. package/dist/plugins/language.mjs +1 -1
  33. package/dist/plugins/list.mjs +1 -1
  34. package/dist/plugins/smart-paste/detectors/JavaDetector.d.ts.map +1 -1
  35. package/dist/plugins/smart-paste.mjs +1 -1
  36. package/dist/presets/full.mjs +1 -1
  37. package/dist/presets/minimal.mjs +1 -1
  38. package/dist/presets.mjs +1 -1
  39. package/dist/view/BlockWrapperManagement.d.ts +6 -4
  40. package/dist/view/BlockWrapperManagement.d.ts.map +1 -1
  41. package/dist/view/CaretNavigation.d.ts +5 -4
  42. package/dist/view/CaretNavigation.d.ts.map +1 -1
  43. package/dist/view/EditorView.d.ts +9 -1
  44. package/dist/view/EditorView.d.ts.map +1 -1
  45. package/dist/view/EditorViewEvents.d.ts +1 -1
  46. package/dist/view/EditorViewEvents.d.ts.map +1 -1
  47. package/dist/view/Reconciler.d.ts.map +1 -1
  48. package/package.json +8 -8
  49. package/dist/chunks/FontPlugin-DYntd3gN.mjs +0 -2
  50. package/dist/chunks/FontPlugin-DYntd3gN.mjs.map +0 -1
  51. package/dist/chunks/ListPlugin-CZgkinoS.mjs.map +0 -1
  52. package/dist/chunks/XmlDetector-BiWxa0RJ.mjs +0 -2
  53. package/dist/chunks/XmlDetector-BiWxa0RJ.mjs.map +0 -1
  54. package/dist/chunks/minimal-CMt909kl.mjs +0 -2
  55. package/dist/chunks/src-dxsvbiql.mjs +0 -2
  56. package/dist/chunks/src-dxsvbiql.mjs.map +0 -1
@@ -1 +1 @@
1
- import{n as a,r,t as s}from"../chunks/CaretNavigationPlugin-mQ1nxJ6m.mjs";export{a as CARET_NAVIGATION_LOCALE_EN,s as CaretNavigationPlugin,r as loadCaretNavigationLocale};
1
+ import{n as a,r,t as s}from"../chunks/CaretNavigationPlugin-C-6zNBbl.mjs";export{a as CARET_NAVIGATION_LOCALE_EN,s as CaretNavigationPlugin,r as loadCaretNavigationLocale};
@@ -1 +1 @@
1
- import{a as s,i as a,n as o,o as m,r,t as i}from"../chunks/CodeBlockPlugin-oPGiMno0.mjs";import{i as n,n as p,o as t}from"../chunks/XmlSupport-Czr8xQB1.mjs";export{s as CODE_BLOCK_LOCALE_EN,r as CODE_BLOCK_SERVICE_KEY,i as CodeBlockPlugin,t as JAVA_LANGUAGE,n as JSON_LANGUAGE,o as RegexTokenizer,a as SYNTAX_HIGHLIGHTER_SERVICE_KEY,p as XML_LANGUAGE,m as loadCodeBlockLocale};
1
+ import{a as s,i as a,n as o,o as m,r,t as i}from"../chunks/CodeBlockPlugin-C8H0nfF6.mjs";import{i as n,n as p,o as t}from"../chunks/XmlSupport-DRkIIe34.mjs";export{s as CODE_BLOCK_LOCALE_EN,r as CODE_BLOCK_SERVICE_KEY,i as CodeBlockPlugin,t as JAVA_LANGUAGE,n as JSON_LANGUAGE,o as RegexTokenizer,a as SYNTAX_HIGHLIGHTER_SERVICE_KEY,p as XML_LANGUAGE,m as loadCodeBlockLocale};
@@ -1 +1 @@
1
- {"version":3,"file":"FontPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/font/FontPlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,EAAkB,KAAK,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAIlF,OAAO,QAAQ,6BAA6B,CAAC;IAC5C,UAAU,gBAAgB;QACzB,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACzB;CACD;AAID,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IAClC,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;IACrF;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACnD;AAID,MAAM,WAAW,UAAU;IAC1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;CAC7B;AAID,qBAAa,UAAW,YAAW,MAAM;IACxC,QAAQ,CAAC,EAAE,UAAU;IACrB,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,OAAO,CAA8B;gBAEjC,MAAM,EAAE,UAAU;IAIxB,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjD,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,gBAAgB;IA8CxB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,KAAK,WAAW,GAUtB;IAED,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,YAAY;IAIpB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI;IAMhD,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAS9E,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,eAAe;IAoCvB,OAAO,CAAC,eAAe;IAiDvB,OAAO,CAAC,cAAc;CAkCtB"}
1
+ {"version":3,"file":"FontPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/font/FontPlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,EAAkB,KAAK,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAIlF,OAAO,QAAQ,6BAA6B,CAAC;IAC5C,UAAU,gBAAgB;QACzB,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACzB;CACD;AAID,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IAClC,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;IACrF;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACnD;AAID,MAAM,WAAW,UAAU;IAC1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;CAC7B;AAID,qBAAa,UAAW,YAAW,MAAM;IACxC,QAAQ,CAAC,EAAE,UAAU;IACrB,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,OAAO,CAA8B;gBAEjC,MAAM,EAAE,UAAU;IAIxB,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAajD,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,gBAAgB;IA8CxB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,KAAK,WAAW,GAQtB;IAED,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,YAAY;IAIpB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI;IAMhD,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAS9E,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,eAAe;IAoCvB,OAAO,CAAC,eAAe;IAiDvB,OAAO,CAAC,cAAc;CAkCtB"}
@@ -1 +1 @@
1
- import{n as s,r as n,t as o}from"../chunks/FontPlugin-DYntd3gN.mjs";export{s as FONT_LOCALE_EN,o as FontPlugin,n as loadFontLocale};
1
+ import{n as s,r as n,t as o}from"../chunks/FontPlugin-BDjM9v3y.mjs";export{s as FONT_LOCALE_EN,o as FontPlugin,n as loadFontLocale};
@@ -1 +1 @@
1
- import{i as m}from"../chunks/XmlDetector-BiWxa0RJ.mjs";import{a as r,r as s,t as o}from"../chunks/XmlSupport-Czr8xQB1.mjs";export{r as JAVA_SUPPORT,s as JSON_SUPPORT,m as LANGUAGE_REGISTRY_SERVICE_KEY,o as XML_SUPPORT};
1
+ import{i as m}from"../chunks/XmlDetector-B1y1NzDL.mjs";import{a as r,r as s,t as o}from"../chunks/XmlSupport-DRkIIe34.mjs";export{r as JAVA_SUPPORT,s as JSON_SUPPORT,m as LANGUAGE_REGISTRY_SERVICE_KEY,o as XML_SUPPORT};
@@ -1 +1 @@
1
- import{n as s,r,t}from"../chunks/ListPlugin-CZgkinoS.mjs";export{s as LIST_LOCALE_EN,t as ListPlugin,r as loadListLocale};
1
+ import{n as s,r,t}from"../chunks/ListPlugin-C_YjbVjT.mjs";export{s as LIST_LOCALE_EN,t as ListPlugin,r as loadListLocale};
@@ -1 +1 @@
1
- {"version":3,"file":"JavaDetector.d.ts","sourceRoot":"","sources":["../../../../src/plugins/smart-paste/detectors/JavaDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkD9E,qBAAa,YAAa,YAAW,eAAe;IACnD,QAAQ,CAAC,EAAE,UAAU;IAErB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAe5C,OAAO,CAAC,YAAY;CA0BpB"}
1
+ {"version":3,"file":"JavaDetector.d.ts","sourceRoot":"","sources":["../../../../src/plugins/smart-paste/detectors/JavaDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAqD9E,qBAAa,YAAa,YAAW,eAAe;IACnD,QAAQ,CAAC,EAAE,UAAU;IAErB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAgB5C,OAAO,CAAC,YAAY;CA0BpB"}
@@ -1 +1 @@
1
- import{n as s,r as a,t as r}from"../chunks/XmlDetector-BiWxa0RJ.mjs";import{i as t,n as m,r as o,t as n}from"../chunks/SmartPastePlugin-BvYBbHSA.mjs";export{a as JavaDetector,s as JsonDetector,o as SMART_PASTE_LOCALE_EN,m as SMART_PASTE_SERVICE_KEY,n as SmartPastePlugin,r as XmlDetector,t as loadSmartPasteLocale};
1
+ import{n as s,r as a,t as r}from"../chunks/XmlDetector-B1y1NzDL.mjs";import{i as t,n as m,r as o,t as n}from"../chunks/SmartPastePlugin-pejM1Zyk.mjs";export{a as JavaDetector,s as JsonDetector,o as SMART_PASTE_LOCALE_EN,m as SMART_PASTE_SERVICE_KEY,n as SmartPastePlugin,r as XmlDetector,t as loadSmartPasteLocale};
@@ -1 +1 @@
1
- import{t as m}from"../chunks/full-B-bw4M7L.mjs";export{m as createFullPreset};
1
+ import{t as m}from"../chunks/full-NtKyNKJ6.mjs";export{m as createFullPreset};
@@ -1 +1 @@
1
- import{t as m}from"../chunks/minimal-CMt909kl.mjs";export{m as createMinimalPreset};
1
+ import{t as m}from"../chunks/minimal-gSvMMQTU.mjs";export{m as createMinimalPreset};
package/dist/presets.mjs CHANGED
@@ -1 +1 @@
1
- import{t as m}from"./chunks/minimal-CMt909kl.mjs";import{t as s}from"./chunks/full-B-bw4M7L.mjs";export{s as createFullPreset,m as createMinimalPreset};
1
+ import{t as m}from"./chunks/minimal-gSvMMQTU.mjs";import{t as s}from"./chunks/full-NtKyNKJ6.mjs";export{s as createFullPreset,m as createMinimalPreset};
@@ -1,13 +1,15 @@
1
1
  import { BlockNode } from '../model/Document.js';
2
2
  import { SchemaRegistry } from '../model/SchemaRegistry.js';
3
3
  /**
4
- * Moves block elements out of wrapper elements (e.g. `<ul>`, `<ol>`) so the
5
- * main reconciliation loop sees all blocks as direct children of the container.
4
+ * Reconciles wrapper elements in the container to match the desired structure
5
+ * derived from the block model. Uses a fast-path comparison to avoid any DOM
6
+ * mutations when the wrapper structure is unchanged (e.g. selection-only updates).
6
7
  */
7
- export declare function unwrapBlocks(container: HTMLElement): void;
8
+ export declare function reconcileWrappers(container: HTMLElement, blocks: readonly BlockNode[], registry: SchemaRegistry): void;
8
9
  /**
9
10
  * Groups consecutive blocks that declare the same wrapper key into shared
10
- * wrapper elements (`<ul>`, `<ol>`, etc.). Called after the main reconcile loop.
11
+ * wrapper elements (`<ul>`, `<ol>`, etc.). Used for initial rendering of
12
+ * nested container children (e.g. list items inside table cells).
11
13
  */
12
14
  export declare function wrapBlocks(container: HTMLElement, blocks: readonly BlockNode[], registry?: SchemaRegistry): void;
13
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"BlockWrapperManagement.d.ts","sourceRoot":"","sources":["../../src/view/BlockWrapperManagement.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAUzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACzB,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACvB,IAAI,CA+DN;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,CAkBvF;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAExD;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,WAAW,GACpB,IAAI,CAON;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACzC,SAAS,EAAE,WAAW,EACtB,eAAe,EAAE,OAAO,GAAG,IAAI,EAC/B,KAAK,EAAE,WAAW,GAChB,IAAI,CAgBN"}
1
+ {"version":3,"file":"BlockWrapperManagement.d.ts","sourceRoot":"","sources":["../../src/view/BlockWrapperManagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AA6RjE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,QAAQ,EAAE,cAAc,GACtB,IAAI,CAkHN;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACzB,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACvB,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,CAkBvF;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAExD;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,WAAW,GACpB,IAAI,CAON;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACzC,SAAS,EAAE,WAAW,EACtB,eAAe,EAAE,OAAO,GAAG,IAAI,EAC/B,KAAK,EAAE,WAAW,GAChB,IAAI,CAgBN"}
@@ -39,10 +39,11 @@ export declare function skipInlineNode(state: EditorState, direction: CaretDirec
39
39
  /**
40
40
  * Returns the bounding rect of the current caret position, or null.
41
41
  *
42
- * Tries the standard `getRangeAt(0)` path first. When `container` is
43
- * provided and the standard path yields no useful rect (height = 0),
44
- * falls back to `readDOMSelectionEndpoints()` to handle Shadow DOM cases
45
- * where `getRangeAt(0)` returns cross-boundary results (e.g. `<li>` elements).
42
+ * When `container` is provided, validates that `getRangeAt(0)` is inside
43
+ * the container before using its rects. In Shadow DOM, `getRangeAt(0)` may
44
+ * return a cross-boundary range whose rects reflect the shadow host position
45
+ * rather than the actual caret position (e.g. inside `<li>` elements).
46
+ * Falls back to composed selection endpoints via `readDOMSelectionEndpoints()`.
46
47
  */
47
48
  export declare function getCaretRectFromSelection(domSel: globalThis.Selection, container?: HTMLElement): DOMRect | null;
48
49
  //# sourceMappingURL=CaretNavigation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CaretNavigation.d.ts","sourceRoot":"","sources":["../../src/view/CaretNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAWjE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAQ9D;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,cAAc,EACzB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,GACxB,OAAO,CAiCT;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,cAAc,GACvB,WAAW,GAAG,IAAI,CAcpB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC7C,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,IAAI,GAAG,MAAM,EACxB,UAAU,EAAE,MAAM,GAAG,IAAI,GACvB,WAAW,GAAG,IAAI,CA8BpB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI,CAgBhG;AAyBD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,UAAU,CAAC,SAAS,EAC5B,SAAS,CAAC,EAAE,WAAW,GACrB,OAAO,GAAG,IAAI,CA6BhB"}
1
+ {"version":3,"file":"CaretNavigation.d.ts","sourceRoot":"","sources":["../../src/view/CaretNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAWjE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAQ9D;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,cAAc,EACzB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,GACxB,OAAO,CAiCT;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,cAAc,GACvB,WAAW,GAAG,IAAI,CAcpB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC7C,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,IAAI,GAAG,MAAM,EACxB,UAAU,EAAE,MAAM,GAAG,IAAI,GACvB,WAAW,GAAG,IAAI,CA8BpB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI,CAgBhG;AAyBD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,UAAU,CAAC,SAAS,EAC5B,SAAS,CAAC,EAAE,WAAW,GACrB,OAAO,GAAG,IAAI,CAkChB"}
@@ -57,7 +57,15 @@ export declare class EditorView {
57
57
  replaceState(newState: EditorState): void;
58
58
  /** Syncs the DOM selection into editor state. */
59
59
  syncSelection(): void;
60
- /** Reconciles DOM and syncs selection, updating decoration state. */
60
+ /**
61
+ * Reconciles DOM and syncs selection, updating decoration state.
62
+ *
63
+ * When `skipSelectionSync` is true, the DOM selection is not written
64
+ * back. This is used when the update was triggered by reading the
65
+ * DOM selection (e.g. mouse click, drag) — the DOM is already correct,
66
+ * and re-writing via `setBaseAndExtent` would disrupt native browser
67
+ * behaviors like drag-selection and double-click word selection.
68
+ */
61
69
  private reconcileAndSync;
62
70
  private reconcileOptions;
63
71
  /** Cleans up all event listeners and handlers. */
@@ -1 +1 @@
1
- {"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../src/view/EditorView.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,MAAM,mBAAmB,GAAG,CACjC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,WAAW,KACX,IAAI,CAAC;AAEV,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,WAAW,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,WAAW,KAAK,aAAa,CAAC;IACzE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED,qBAAa,UAAU;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAA0D;IAC1F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB;IAmDnE,wCAAwC;IACxC,QAAQ,IAAI,WAAW;IAIvB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmCnB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAK/B,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,yCAAyC;IACzC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAQxD,wEAAwE;IACxE,YAAY,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAkCzC,iDAAiD;IACjD,aAAa,IAAI,IAAI;IAIrB,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,gBAAgB;IAmBxB,kDAAkD;IAClD,OAAO,IAAI,IAAI;CASf"}
1
+ {"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../src/view/EditorView.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,MAAM,mBAAmB,GAAG,CACjC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,WAAW,KACX,IAAI,CAAC;AAEV,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,WAAW,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,WAAW,KAAK,aAAa,CAAC;IACzE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED,qBAAa,UAAU;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAA0D;IAC1F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB;IAoDnE,wCAAwC;IACxC,QAAQ,IAAI,WAAW;IAIvB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmCnB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAK/B,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,yCAAyC;IACzC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAQxD,wEAAwE;IACxE,YAAY,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAkCzC,iDAAiD;IACjD,aAAa,IAAI,IAAI;IAIrB;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,gBAAgB;IAmBxB,kDAAkD;IAClD,OAAO,IAAI,IAAI;CASf"}
@@ -7,7 +7,7 @@ export interface EventCoordinatorDeps {
7
7
  readonly contentElement: HTMLElement;
8
8
  readonly getState: () => EditorState;
9
9
  readonly dispatch: (tr: Transaction) => void;
10
- readonly applyUpdate: (newState: EditorState, tr: Transaction) => void;
10
+ readonly applyUpdate: (newState: EditorState, tr: Transaction, skipSelectionSync?: boolean) => void;
11
11
  readonly isUpdating: () => boolean;
12
12
  readonly compositionState: CompositionState;
13
13
  readonly cursorWrapper: CursorWrapper;
@@ -1 +1 @@
1
- {"version":3,"file":"EditorViewEvents.d.ts","sourceRoot":"","sources":["../../src/view/EditorViewEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAW3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAa;IAClD,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,IAAI,EAAE,oBAAoB;IAyBtC,iDAAiD;IACjD,oBAAoB,IAAI,IAAI;IAiC5B,mCAAmC;IACnC,OAAO,IAAI,IAAI;IAUf,0DAA0D;IAC1D,OAAO,CAAC,iBAAiB;IAczB,mDAAmD;IACnD,OAAO,CAAC,WAAW;IAmDnB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAwC/B,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAQlB,sDAAsD;IACtD,OAAO,CAAC,MAAM;IA0Bd,yDAAyD;IACzD,OAAO,CAAC,oBAAoB;IAU5B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;CASjC"}
1
+ {"version":3,"file":"EditorViewEvents.d.ts","sourceRoot":"","sources":["../../src/view/EditorViewEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAW3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,CACrB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,WAAW,EACf,iBAAiB,CAAC,EAAE,OAAO,KACvB,IAAI,CAAC;IACV,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAa;IAClD,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,IAAI,EAAE,oBAAoB;IAyBtC,iDAAiD;IACjD,oBAAoB,IAAI,IAAI;IAoC5B,mCAAmC;IACnC,OAAO,IAAI,IAAI;IAUf,0DAA0D;IAC1D,OAAO,CAAC,iBAAiB;IAczB,mDAAmD;IACnD,OAAO,CAAC,WAAW;IAmDnB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAwC/B,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAQlB,sDAAsD;IACtD,OAAO,CAAC,MAAM;IA0Bd,yDAAyD;IACzD,OAAO,CAAC,oBAAoB;IAU5B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;CASjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Reconciler.d.ts","sourceRoot":"","sources":["../../src/view/Reconciler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,8BAA8B,CAAC;AAGzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAU3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,yBAAyB,EAAE,WAAW,KAAK,IAAI,CAAC;IACvE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qGAAqG;IACrG,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CACxB,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,WAAW,GAAG,IAAI,EAC5B,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACxB,IAAI,CA4IN"}
1
+ {"version":3,"file":"Reconciler.d.ts","sourceRoot":"","sources":["../../src/view/Reconciler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,8BAA8B,CAAC;AAGzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAS3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,yBAAyB,EAAE,WAAW,KAAK,IAAI,CAAC;IACvE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qGAAqG;IACrG,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CACxB,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,WAAW,GAAG,IAAI,EAC5B,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACxB,IAAI,CAyIN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notectl/core",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "A modern and accessible rich text editor shipped as a single Web Component. Immutable state, transaction-based architecture, and a plugin system that powers every feature.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -366,16 +366,16 @@
366
366
  }
367
367
  ],
368
368
  "dependencies": {
369
- "dompurify": "^3.3.2"
369
+ "dompurify": "^3.3.3"
370
370
  },
371
371
  "devDependencies": {
372
- "@size-limit/preset-small-lib": "^12.0.0",
373
- "happy-dom": "^20.7.0",
372
+ "@size-limit/preset-small-lib": "^12.0.1",
373
+ "happy-dom": "^20.8.9",
374
374
  "rollup-plugin-visualizer": "^7.0.1",
375
- "size-limit": "^12.0.0",
376
- "terser": "^5.46.0",
377
- "vite": "^8.0.0",
375
+ "size-limit": "^12.0.1",
376
+ "terser": "^5.46.1",
377
+ "vite": "^8.0.3",
378
378
  "vite-plugin-dts": "^4.5.4",
379
- "vitest": "^4.1.0"
379
+ "vitest": "^4.1.2"
380
380
  }
381
381
  }
@@ -1,2 +0,0 @@
1
- import{i as t}from"./TypeBrands-BQR8dEYU.mjs";import{r as e}from"./HTMLUtils-BLwp5G4f.mjs";import{i as n,n as o,r as i,t as r}from"./AttributedMarkCommands-BiJtiHpx.mjs";import{r as s,s as a}from"./StyleRuntime-Bwde5icB.mjs";import{i as l}from"./PluginHelpers-BZU5rE44.mjs";import{n as c}from"./ColorValidation-rOrJxBBt.mjs";var m={label:"Font",tooltip:"Font Family"},p=/* @__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-CqD9pUY0.mjs"),"./locales/de.ts":()=>import("./de-hneXQd4z.mjs"),"./locales/es.ts":()=>import("./es-DFCDhXJb.mjs"),"./locales/fr.ts":()=>import("./fr-DGBuhK3D.mjs"),"./locales/hi.ts":()=>import("./hi-ClSwgZfK.mjs"),"./locales/pt.ts":()=>import("./pt-kFy3gqNp.mjs"),"./locales/ru.ts":()=>import("./ru-DZge62_-.mjs"),"./locales/zh.ts":()=>import("./zh-CyX2tIRP.mjs")});async function f(t){if("en"===t)return m;const e=p[`./locales/${t}.ts`];if(!e)return m;try{return(await e()).default}catch{return m}}var d=class{id="font";name="Font";priority=22;config;locale;injectedStyleElement=null;context=null;constructor(t){this.config=t}async init(t){this.locale=await l(t,this.config.locale,m,f),t.registerStyleSheet("\n/* Font Select — Width overrides for combobox button */\n.notectl-toolbar-btn--font {\n\tmin-width: 100px;\n\tmax-width: 160px;\n}\n\n/* Font Picker Popup */\n.notectl-font-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-font-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-font-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: var(--notectl-fg);\n\tline-height: 1.4;\n\ttext-align: start;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n@media (hover: hover) {\n\t.notectl-font-picker__item:hover {\n\t\tbackground: var(--notectl-hover-bg);\n\t}\n}\n\n.notectl-font-picker__item--active {\n\tbackground: var(--notectl-active-bg);\n\tcolor: var(--notectl-primary-fg);\n}\n\n@media (hover: hover) {\n\t.notectl-font-picker__item--active:hover {\n\t\tbackground: var(--notectl-active-bg);\n\t}\n}\n\n.notectl-font-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--notectl-primary-fg);\n}\n\n.notectl-font-picker__label {\n\tflex: 1;\n}\n\n.notectl-font-picker__separator {\n\theight: 1px;\n\tbackground: var(--notectl-border);\n\tmargin: 4px 8px;\n}\n"),this.context=t,this.registerMarkSpec(t),this.registerCommands(t),this.registerToolbarItem(t),this.injectFontFaces()}destroy(){this.injectedStyleElement?.remove(),this.injectedStyleElement=null,this.context=null}registerMarkSpec(t){t.registerMarkSpec({type:"font",rank:6,attrs:{family:{default:""}},toDOM(t){const e=document.createElement("span"),n=t.attrs?.family??"";return n&&a(e,"fontFamily",n),e},toHTMLString:(t,n,o)=>{const i=String(t.attrs?.family??"");if(!i||!c(i))return n;const r=`font-family: ${e(i)}`;return`<span${o?.styleAttr(r)??` style="${r}"`}>${n}</span>`},toHTMLStyle:t=>{const n=String(t.attrs?.family??"");return n&&c(n)?`font-family: ${e(n)}`:null},parseHTML:[{tag:"span",getAttrs:t=>{const e=t.style.fontFamily;return!!e&&{family:e.replace(/"/g,"'")}}}],sanitize:{tags:["span"]}})}registerCommands(t){t.registerCommand("removeFont",()=>{const e=t.getState();return this.removeFont(t,e)}),t.registerCommand("setFont",()=>!1)}get defaultFont(){if(this.config.defaultFont){const t=this.config.fonts.find(t=>t.name===this.config.defaultFont);if(t)return t}const t=this.config.fonts[0];if(!t)throw new Error("FontPlugin: fonts list is empty");return t}registerToolbarItem(t){t.registerToolbarItem({id:"font",group:"format",label:this.locale.label,tooltip:this.locale.tooltip,command:"removeFont",popupType:"combobox",getLabel:t=>this.resolveFontName(this.getActiveFont(t)),renderPopup:(t,e,n)=>{this.renderFontPopup(t,e,n)},isActive:t=>this.isFontActive(t)})}resolveFontName(t){return t?this.config.fonts.find(e=>e.family===t)?.name??(t.split(",")[0]??"").trim().replace(/['"]/g,""):this.defaultFont.name}isFontActive(t){return i(t,"font")}getActiveFont(t){return o(t,"font",t=>t.attrs.family??null)}applyFont(e,n,o){const i=r(n,{type:t("font"),attrs:{family:o}});return!!i&&(e.dispatch(i),!0)}removeFont(e,o){const i=n(o,t("font"));return!!i&&(e.dispatch(i),!0)}injectFontFaces(){const t=[];for(const o of this.config.fonts)if(o.fontFaces?.length)for(const e of o.fontFaces){const n=[`font-family: '${(o.family.split(",")[0]??"").trim().replace(/['"]/g,"")}'`,`src: ${e.src}`];e.weight&&n.push(`font-weight: ${e.weight}`),e.style&&n.push(`font-style: ${e.style}`),n.push(`font-display: ${e.display??"swap"}`),t.push(`@font-face {\n\t${n.join(";\n\t")};\n}`)}if(0===t.length)return;const e=document.createElement("style");e.setAttribute("data-notectl-fonts","");const n=this.context?s(this.context.getContainer()):void 0;n&&e.setAttribute("nonce",n),e.textContent=t.join("\n\n"),document.head.appendChild(e),this.injectedStyleElement=e}renderFontPopup(t,e,n){t.classList.add("notectl-font-picker");const o=e.getState(),i=this.getActiveFont(o),r=this.defaultFont.family,s=e.getContainer(),a=document.createElement("div");a.className="notectl-font-picker__list",a.setAttribute("role","listbox"),a.setAttribute("aria-label",this.locale.label);for(const l of this.config.fonts){const t=l.family===r,o=t&&!i||i===l.family,c=this.createFontItem(l.name,l.family,o,o=>{o.preventDefault(),o.stopPropagation(),t?e.executeCommand("removeFont"):this.applyFont(e,e.getState(),l.family),n({restoreFocusTo:s})});l.category&&c.setAttribute("data-category",l.category),a.appendChild(c)}t.appendChild(a)}createFontItem(t,e,n,o){const i=document.createElement("button");i.type="button",i.className="notectl-font-picker__item",i.setAttribute("role","option"),i.setAttribute("aria-selected",String(n)),n&&i.classList.add("notectl-font-picker__item--active");const r=document.createElement("span");r.className="notectl-font-picker__check",r.textContent=n?"✓":"",i.appendChild(r);const s=document.createElement("span");return s.className="notectl-font-picker__label",s.textContent=t,e&&a(s,"fontFamily",e),i.appendChild(s),i.addEventListener("mousedown",o),i}};export{m as n,f as r,d as t};
2
- //# sourceMappingURL=FontPlugin-DYntd3gN.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FontPlugin-DYntd3gN.mjs","names":[],"sources":["../../src/editor/styles/font-select.ts","../../src/plugins/font/FontLocale.ts","../../src/plugins/font/FontPlugin.ts"],"sourcesContent":["/** Font picker toolbar combobox + popup styles. */\nexport const FONT_SELECT_CSS = `\n/* Font Select — Width overrides for combobox button */\n.notectl-toolbar-btn--font {\n\tmin-width: 100px;\n\tmax-width: 160px;\n}\n\n/* Font Picker Popup */\n.notectl-font-picker {\n\tmin-width: 200px;\n\tmax-height: 320px;\n\toverflow-y: auto;\n}\n\n.notectl-font-picker__list {\n\tpadding: 4px 0;\n}\n\n.notectl-font-picker__item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 7px 12px;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: var(--notectl-fg);\n\tline-height: 1.4;\n\ttext-align: start;\n\twhite-space: nowrap;\n\tfont-family: inherit;\n\ttransition: background 0.1s;\n}\n\n@media (hover: hover) {\n\t.notectl-font-picker__item:hover {\n\t\tbackground: var(--notectl-hover-bg);\n\t}\n}\n\n.notectl-font-picker__item--active {\n\tbackground: var(--notectl-active-bg);\n\tcolor: var(--notectl-primary-fg);\n}\n\n@media (hover: hover) {\n\t.notectl-font-picker__item--active:hover {\n\t\tbackground: var(--notectl-active-bg);\n\t}\n}\n\n.notectl-font-picker__check {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\tflex-shrink: 0;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--notectl-primary-fg);\n}\n\n.notectl-font-picker__label {\n\tflex: 1;\n}\n\n.notectl-font-picker__separator {\n\theight: 1px;\n\tbackground: var(--notectl-border);\n\tmargin: 4px 8px;\n}\n`;\n","/** Locale interface and default English locale for the FontPlugin. */\n\n// --- Locale Interface ---\n\nexport interface FontLocale {\n\treadonly label: string;\n\treadonly tooltip: string;\n}\n\n// --- Default English Locale ---\n\nexport const FONT_LOCALE_EN: FontLocale = {\n\tlabel: 'Font',\n\ttooltip: 'Font Family',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: Record<string, () => Promise<{ default: FontLocale }>> = import.meta.glob<{\n\tdefault: FontLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadFontLocale(lang: string): Promise<FontLocale> {\n\tif (lang === 'en') return FONT_LOCALE_EN;\n\tconst loader = localeModules[`./locales/${lang}.ts`];\n\tif (!loader) return FONT_LOCALE_EN;\n\ttry {\n\t\tconst mod = await loader();\n\t\treturn mod.default;\n\t} catch {\n\t\treturn FONT_LOCALE_EN;\n\t}\n}\n","/**\n * FontPlugin: registers a font-family mark, a combobox-style toolbar selector\n * for font selection, and a developer-friendly API for registering custom fonts\n * (WOFF2, TTF, OTF).\n */\n\nimport {\n\tapplyAttributedMark,\n\tgetMarkAttrAtSelection,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from '../../commands/AttributedMarkCommands.js';\nimport { FONT_SELECT_CSS } from '../../editor/styles/font-select.js';\nimport { escapeHTML } from '../../model/HTMLUtils.js';\nimport type { HTMLExportContext } from '../../model/NodeSpec.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { getStyleNonceForNode, setStyleProperty } from '../../style/StyleRuntime.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { isValidCSSFontFamily } from '../shared/ColorValidation.js';\nimport { resolveLocale } from '../shared/PluginHelpers.js';\nimport type { PopupCloseOptions } from '../shared/PopupManager.js';\nimport { FONT_LOCALE_EN, type FontLocale, loadFontLocale } from './FontLocale.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tfont: { family: string };\n\t}\n}\n\n// --- Public Types ---\n\n/** Describes a single @font-face source. */\nexport interface FontFaceDescriptor {\n\t/** CSS `src` value, e.g. `\"url('/fonts/My.woff2') format('woff2')\"`. */\n\treadonly src: string;\n\t/** Font weight, e.g. `'400'` or `'300 700'` for variable fonts. */\n\treadonly weight?: string;\n\t/** Font style, e.g. `'normal'` or `'italic'`. */\n\treadonly style?: string;\n\t/** Font display strategy. Defaults to `'swap'`. */\n\treadonly display?: string;\n}\n\n/** Defines a font available in the editor. */\nexport interface FontDefinition {\n\t/** Display name shown in the toolbar dropdown. */\n\treadonly name: string;\n\t/** CSS `font-family` value, e.g. `\"'Fira Code', monospace\"`. */\n\treadonly family: string;\n\t/** Font category for grouping in the UI. */\n\treadonly category?: 'serif' | 'sans-serif' | 'monospace' | 'display' | 'handwriting';\n\t/**\n\t * Optional `@font-face` descriptors. When provided, the plugin\n\t * auto-injects the corresponding CSS rules into the document.\n\t */\n\treadonly fontFaces?: readonly FontFaceDescriptor[];\n}\n\n// --- Configuration ---\n\nexport interface FontConfig {\n\t/**\n\t * Fonts available in the editor. System fonts require no `fontFaces`.\n\t * Custom fonts with `fontFaces` get their `@font-face` rules auto-injected.\n\t *\n\t * Use `STARTER_FONTS` for a pre-configured set of fonts:\n\t * ```ts\n\t * new FontPlugin({ fonts: [...STARTER_FONTS] })\n\t * ```\n\t */\n\treadonly fonts: readonly FontDefinition[];\n\t/**\n\t * Name of the font that acts as the editor's default.\n\t * Selecting this font removes the mark (since the editor already uses it).\n\t * Defaults to the first font in the list.\n\t */\n\treadonly defaultFont?: string;\n\treadonly locale?: FontLocale;\n}\n\n// --- Plugin ---\n\nexport class FontPlugin implements Plugin {\n\treadonly id = 'font';\n\treadonly name = 'Font';\n\treadonly priority = 22;\n\n\tprivate readonly config: FontConfig;\n\tprivate locale!: FontLocale;\n\tprivate injectedStyleElement: HTMLStyleElement | null = null;\n\tprivate context: PluginContext | null = null;\n\n\tconstructor(config: FontConfig) {\n\t\tthis.config = config;\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(context, this.config.locale, FONT_LOCALE_EN, loadFontLocale);\n\n\t\tcontext.registerStyleSheet(FONT_SELECT_CSS);\n\t\tthis.context = context;\n\t\tthis.registerMarkSpec(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.injectFontFaces();\n\t}\n\n\tdestroy(): void {\n\t\tthis.injectedStyleElement?.remove();\n\t\tthis.injectedStyleElement = null;\n\t\tthis.context = null;\n\t}\n\n\t// --- Schema ---\n\n\tprivate registerMarkSpec(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'font',\n\t\t\trank: 6,\n\t\t\tattrs: {\n\t\t\t\tfamily: { default: '' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst span: HTMLElement = document.createElement('span');\n\t\t\t\tconst family: string = mark.attrs?.family ?? '';\n\t\t\t\tif (family) {\n\t\t\t\t\tsetStyleProperty(span, 'fontFamily', family);\n\t\t\t\t}\n\t\t\t\treturn span;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content, ctx?: HTMLExportContext) => {\n\t\t\t\tconst family: string = String(mark.attrs?.family ?? '');\n\t\t\t\tif (!family || !isValidCSSFontFamily(family)) return content;\n\t\t\t\tconst decl: string = `font-family: ${escapeHTML(family)}`;\n\t\t\t\tconst attr: string = ctx?.styleAttr(decl) ?? ` style=\"${decl}\"`;\n\t\t\t\treturn `<span${attr}>${content}</span>`;\n\t\t\t},\n\t\t\ttoHTMLStyle: (mark) => {\n\t\t\t\tconst family: string = String(mark.attrs?.family ?? '');\n\t\t\t\tif (!family || !isValidCSSFontFamily(family)) return null;\n\t\t\t\treturn `font-family: ${escapeHTML(family)}`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'span',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\tconst family: string = el.style.fontFamily;\n\t\t\t\t\t\tif (!family) return false;\n\t\t\t\t\t\t// Browsers normalize CSS quotes to double-quotes;\n\t\t\t\t\t\t// our internal convention uses single-quotes.\n\t\t\t\t\t\tconst normalized: string = family.replace(/\"/g, \"'\");\n\t\t\t\t\t\treturn { family: normalized };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['span'] },\n\t\t});\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('removeFont', () => {\n\t\t\tconst state: EditorState = context.getState();\n\t\t\treturn this.removeFont(context, state);\n\t\t});\n\n\t\tcontext.registerCommand('setFont', () => {\n\t\t\treturn false;\n\t\t});\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate get defaultFont(): FontDefinition {\n\t\tif (this.config.defaultFont) {\n\t\t\tconst found: FontDefinition | undefined = this.config.fonts.find(\n\t\t\t\t(f) => f.name === this.config.defaultFont,\n\t\t\t);\n\t\t\tif (found) return found;\n\t\t}\n\t\tconst first: FontDefinition | undefined = this.config.fonts[0];\n\t\tif (!first) throw new Error('FontPlugin: fonts list is empty');\n\t\treturn first;\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'font',\n\t\t\tgroup: 'format',\n\t\t\tlabel: this.locale.label,\n\t\t\ttooltip: this.locale.tooltip,\n\t\t\tcommand: 'removeFont',\n\t\t\tpopupType: 'combobox',\n\t\t\tgetLabel: (state: EditorState): string => this.resolveFontName(this.getActiveFont(state)),\n\t\t\trenderPopup: (container, ctx, onClose) => {\n\t\t\t\tthis.renderFontPopup(container, ctx, onClose);\n\t\t\t},\n\t\t\tisActive: (state) => this.isFontActive(state),\n\t\t});\n\t}\n\n\tprivate resolveFontName(family: string | null): string {\n\t\tif (!family) return this.defaultFont.name;\n\t\tconst match: FontDefinition | undefined = this.config.fonts.find((f) => f.family === family);\n\t\treturn match?.name ?? (family.split(',')[0] ?? '').trim().replace(/['\"]/g, '');\n\t}\n\n\t// --- State Queries ---\n\n\tprivate isFontActive(state: EditorState): boolean {\n\t\treturn isAttributedMarkActive(state, 'font');\n\t}\n\n\tgetActiveFont(state: EditorState): string | null {\n\t\treturn getMarkAttrAtSelection(state, 'font', (m) => m.attrs.family ?? null);\n\t}\n\n\t// --- Font Application ---\n\n\tapplyFont(context: PluginContext, state: EditorState, family: string): boolean {\n\t\tconst mark = { type: markType('font'), attrs: { family } };\n\t\tconst tr = applyAttributedMark(state, mark);\n\t\tif (!tr) return false;\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tprivate removeFont(context: PluginContext, state: EditorState): boolean {\n\t\tconst tr = removeAttributedMark(state, markType('font'));\n\t\tif (!tr) return false;\n\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\t// --- @font-face Injection ---\n\n\tprivate injectFontFaces(): void {\n\t\tconst rules: string[] = [];\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tif (!font.fontFaces?.length) continue;\n\n\t\t\tfor (const face of font.fontFaces) {\n\t\t\t\tconst familyName: string = (font.family.split(',')[0] ?? '').trim().replace(/['\"]/g, '');\n\t\t\t\tconst declarations: string[] = [`font-family: '${familyName}'`, `src: ${face.src}`];\n\t\t\t\tif (face.weight) {\n\t\t\t\t\tdeclarations.push(`font-weight: ${face.weight}`);\n\t\t\t\t}\n\t\t\t\tif (face.style) {\n\t\t\t\t\tdeclarations.push(`font-style: ${face.style}`);\n\t\t\t\t}\n\t\t\t\tdeclarations.push(`font-display: ${face.display ?? 'swap'}`);\n\n\t\t\t\trules.push(`@font-face {\\n\\t${declarations.join(';\\n\\t')};\\n}`);\n\t\t\t}\n\t\t}\n\n\t\tif (rules.length === 0) return;\n\n\t\tconst style: HTMLStyleElement = document.createElement('style');\n\t\tstyle.setAttribute('data-notectl-fonts', '');\n\t\tconst nonce = this.context ? getStyleNonceForNode(this.context.getContainer()) : undefined;\n\t\tif (nonce) {\n\t\t\tstyle.setAttribute('nonce', nonce);\n\t\t}\n\t\tstyle.textContent = rules.join('\\n\\n');\n\t\tdocument.head.appendChild(style);\n\t\tthis.injectedStyleElement = style;\n\t}\n\n\t// --- Popup Rendering ---\n\n\tprivate renderFontPopup(\n\t\tcontainer: HTMLElement,\n\t\tcontext: PluginContext,\n\t\tonClose: (options?: PopupCloseOptions) => void,\n\t): void {\n\t\tcontainer.classList.add('notectl-font-picker');\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst activeFont: string | null = this.getActiveFont(state);\n\t\tconst defaultFamily: string = this.defaultFont.family;\n\t\tconst contentElement: HTMLElement = context.getContainer();\n\n\t\tconst list: HTMLDivElement = document.createElement('div');\n\t\tlist.className = 'notectl-font-picker__list';\n\t\tlist.setAttribute('role', 'listbox');\n\t\tlist.setAttribute('aria-label', this.locale.label);\n\n\t\tfor (const font of this.config.fonts) {\n\t\t\tconst isDefault: boolean = font.family === defaultFamily;\n\t\t\tconst isActive: boolean = isDefault\n\t\t\t\t? !activeFont || activeFont === font.family\n\t\t\t\t: activeFont === font.family;\n\n\t\t\tconst item: HTMLButtonElement = this.createFontItem(\n\t\t\t\tfont.name,\n\t\t\t\tfont.family,\n\t\t\t\tisActive,\n\t\t\t\t(e: MouseEvent) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tif (isDefault) {\n\t\t\t\t\t\tcontext.executeCommand('removeFont');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.applyFont(context, context.getState(), font.family);\n\t\t\t\t\t}\n\t\t\t\t\tonClose({ restoreFocusTo: contentElement });\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (font.category) {\n\t\t\t\titem.setAttribute('data-category', font.category);\n\t\t\t}\n\n\t\t\tlist.appendChild(item);\n\t\t}\n\n\t\tcontainer.appendChild(list);\n\t}\n\n\tprivate createFontItem(\n\t\tname: string,\n\t\tfamily: string,\n\t\tisActive: boolean,\n\t\thandler: (e: MouseEvent) => void,\n\t): HTMLButtonElement {\n\t\tconst item: HTMLButtonElement = document.createElement('button');\n\t\titem.type = 'button';\n\t\titem.className = 'notectl-font-picker__item';\n\t\titem.setAttribute('role', 'option');\n\t\titem.setAttribute('aria-selected', String(isActive));\n\n\t\tif (isActive) {\n\t\t\titem.classList.add('notectl-font-picker__item--active');\n\t\t}\n\n\t\t// Checkmark indicator\n\t\tconst check: HTMLSpanElement = document.createElement('span');\n\t\tcheck.className = 'notectl-font-picker__check';\n\t\tcheck.textContent = isActive ? '\\u2713' : '';\n\t\titem.appendChild(check);\n\n\t\t// Font name label (rendered in the font itself for preview)\n\t\tconst label: HTMLSpanElement = document.createElement('span');\n\t\tlabel.className = 'notectl-font-picker__label';\n\t\tlabel.textContent = name;\n\t\tif (family) {\n\t\t\tsetStyleProperty(label, 'fontFamily', family);\n\t\t}\n\t\titem.appendChild(label);\n\n\t\titem.addEventListener('mousedown', handler);\n\t\treturn item;\n\t}\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ListPlugin-CZgkinoS.mjs","names":[],"sources":["../../src/editor/styles/list.ts","../../src/plugins/list/ListAttrsFactory.ts","../../src/plugins/list/ListCommands.ts","../../src/plugins/list/ListDefinitions.ts","../../src/plugins/list/ListInputRules.ts","../../src/plugins/list/ListKeyboardHandlers.ts","../../src/plugins/list/ListLocale.ts","../../src/plugins/list/ListToolbarItems.ts","../../src/plugins/list/ListPlugin.ts"],"sourcesContent":["/** Width of the list marker / checkbox area in pixels. */\nexport const LIST_MARKER_WIDTH = 24;\n\n/** List styles — bullet, ordered, checklist items. */\nexport const LIST_CSS = `\n/* List Wrappers — suppress native markers, we use ::before pseudo-elements */\n.notectl-list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Ordered List — each <ol> wrapper resets the counter */\n.notectl-list--ordered {\n\tcounter-reset: notectl-ordered;\n}\n\n/* List Items */\n.notectl-list-item {\n\tmargin: 0;\n\tpadding: 2px 0;\n\tpadding-inline-start: ${LIST_MARKER_WIDTH}px;\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: ${LIST_MARKER_WIDTH}px;\n\ttext-align: center;\n}\n\n/* Bullet List */\n.notectl-list-item--bullet::before {\n\tcontent: '\\\\2022';\n\tcolor: var(--notectl-fg);\n}\n\n/* Ordered List — counter increment per item */\n.notectl-list-item--ordered {\n\tcounter-increment: notectl-ordered;\n}\n\n.notectl-list-item--ordered::before {\n\tcontent: counter(notectl-ordered) '.';\n\tcolor: var(--notectl-fg);\n\tfont-size: 14px;\n}\n\n/* Checklist */\n.notectl-list-item--checklist::before {\n\tcontent: '\\\\2610';\n\tfont-size: 16px;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"]::before {\n\tcontent: '\\\\2611';\n\tcolor: var(--notectl-success);\n}\n\n.notectl-list-item--checklist[data-checked=\"true\"] {\n\tcolor: var(--notectl-fg-muted);\n\ttext-decoration: line-through;\n}\n`;\n","/**\n * Factory for building list item block attributes.\n * Centralizes attribute construction to avoid repetitive inline object literals.\n */\n\nimport type { BlockAttrs } from '../../model/Document.js';\nimport type { ListType } from './ListPlugin.js';\n\n/** Builds a `BlockAttrs` object for a list_item block. */\nexport function buildListItemAttrs(\n\tlistType: ListType,\n\tindent: number,\n\tchecked?: boolean,\n): BlockAttrs {\n\tif (listType === 'checklist') {\n\t\treturn { listType, indent, checked: checked ?? false };\n\t}\n\treturn { listType, indent };\n}\n","/**\n * Command registration and implementations for list block types.\n * Handles toggle between list types and paragraph, indent/outdent,\n * and checklist toggle.\n */\n\nimport { forEachBlockIdInRange } from '../../commands/RangeIterator.js';\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport { isTextSelection, selectionRange } from '../../model/Selection.js';\nimport { type BlockId, nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { buildListItemAttrs } from './ListAttrsFactory.js';\nimport type { ListTypeDefinition } from './ListDefinitions.js';\nimport type { ListConfig, ListType } from './ListPlugin.js';\n\n/** Registers all list commands (toggleList:*, indent, outdent, toggleChecklistItem). */\nexport function registerListCommands(\n\tcontext: PluginContext,\n\tconfig: ListConfig,\n\tenabledTypes: readonly ListTypeDefinition[],\n): void {\n\tfor (const def of enabledTypes) {\n\t\tcontext.registerCommand(`toggleList:${def.type}`, () => {\n\t\t\treturn toggleList(context, def.type);\n\t\t});\n\t}\n\n\tcontext.registerCommand('indentListItem', () => changeIndent(context, 1, config.maxIndent));\n\n\tcontext.registerCommand('outdentListItem', () => changeIndent(context, -1, config.maxIndent));\n\n\tif (config.types.includes('checklist')) {\n\t\tcontext.registerCommand(\n\t\t\t'toggleChecklistItem',\n\t\t\t() => toggleChecked(context, config.interactiveCheckboxes),\n\t\t\t{ readonlyAllowed: true },\n\t\t);\n\t}\n\n\tcontext.registerKeymap({\n\t\tTab: () => changeIndent(context, 1, config.maxIndent),\n\t\t'Shift-Tab': () => changeIndent(context, -1, config.maxIndent),\n\t});\n}\n\n// --- Command Implementations ---\n\nfunction toggleList(context: PluginContext, listType: ListType): boolean {\n\tconst state: EditorState = context.getState();\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return false;\n\n\tif (sel.anchor.blockId !== sel.head.blockId) {\n\t\treturn toggleListRange(context, state, listType);\n\t}\n\treturn toggleListSingleBlock(context, state, listType);\n}\n\nfunction toggleListSingleBlock(\n\tcontext: PluginContext,\n\tstate: EditorState,\n\tlistType: ListType,\n): boolean {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return false;\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return false;\n\n\tif (block.type === 'list_item' && block.attrs?.listType === listType) {\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setBlockType(sel.anchor.blockId, nodeType('paragraph'))\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t}\n\n\tconst existingIndent: number = isNodeOfType(block, 'list_item') ? block.attrs.indent : 0;\n\tconst attrs = buildListItemAttrs(listType, existingIndent);\n\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t.setSelection(sel)\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\nfunction toggleListRange(context: PluginContext, state: EditorState, listType: ListType): boolean {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return false;\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst toggleOff: boolean = allBlocksMatchListType(state, range, listType);\n\tconst builder = state.transaction('command');\n\n\tforEachBlockIdInRange(state, range, (bid: BlockId) => {\n\t\tconst block = state.getBlock(bid);\n\t\tif (!block) return;\n\n\t\tif (toggleOff) {\n\t\t\tbuilder.setBlockType(bid, nodeType('paragraph'));\n\t\t} else {\n\t\t\tconst existingIndent: number = isNodeOfType(block, 'list_item') ? block.attrs.indent : 0;\n\t\t\tconst existingChecked: boolean =\n\t\t\t\tisNodeOfType(block, 'list_item') &&\n\t\t\t\tblock.attrs.listType === 'checklist' &&\n\t\t\t\tblock.attrs.checked;\n\t\t\tbuilder.setBlockType(\n\t\t\t\tbid,\n\t\t\t\tnodeType('list_item'),\n\t\t\t\tbuildListItemAttrs(listType, existingIndent, existingChecked),\n\t\t\t);\n\t\t}\n\t});\n\n\tbuilder.setSelection(sel);\n\tcontext.dispatch(builder.build());\n\treturn true;\n}\n\n// --- Indent / Outdent ---\n\nfunction changeIndent(context: PluginContext, delta: 1 | -1, maxIndent: number): boolean {\n\tconst state: EditorState = context.getState();\n\tif (!isTextSelection(state.selection)) return false;\n\n\tif (state.selection.anchor.blockId !== state.selection.head.blockId) {\n\t\treturn changeIndentRange(context, state, delta, maxIndent);\n\t}\n\n\tconst sel = state.selection;\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block || !isNodeOfType(block, 'list_item')) return false;\n\n\tconst newIndent: number = block.attrs.indent + delta;\n\tif (newIndent < 0 || newIndent > maxIndent) return false;\n\n\tconst attrs = buildListItemAttrs(block.attrs.listType, newIndent, block.attrs.checked);\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t.setSelection(sel)\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\nfunction changeIndentRange(\n\tcontext: PluginContext,\n\tstate: EditorState,\n\tdelta: 1 | -1,\n\tmaxIndent: number,\n): boolean {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return false;\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst builder = state.transaction('command');\n\tlet changed = false;\n\n\tforEachBlockIdInRange(state, range, (bid: BlockId) => {\n\t\tconst block = state.getBlock(bid);\n\t\tif (!block || !isNodeOfType(block, 'list_item')) return;\n\n\t\tconst newIndent: number = block.attrs.indent + delta;\n\t\tif (newIndent < 0 || newIndent > maxIndent) return;\n\n\t\tbuilder.setBlockType(\n\t\t\tbid,\n\t\t\tnodeType('list_item'),\n\t\t\tbuildListItemAttrs(block.attrs.listType, newIndent, block.attrs.checked),\n\t\t);\n\t\tchanged = true;\n\t});\n\n\tif (!changed) return false;\n\n\tbuilder.setSelection(sel);\n\tcontext.dispatch(builder.build());\n\treturn true;\n}\n\n// --- Checklist Toggle ---\n\n/** Toggles the checked state of a checklist item. Exported for use in checkbox click handler. */\nexport function toggleChecked(\n\tcontext: PluginContext,\n\tinteractiveCheckboxes?: boolean,\n\ttargetId?: BlockId,\n): boolean {\n\tif (context.isReadOnly() && !interactiveCheckboxes) return false;\n\n\tconst state: EditorState = context.getState();\n\tconst bid: BlockId | null =\n\t\ttargetId ?? (!isTextSelection(state.selection) ? null : state.selection.anchor.blockId);\n\tif (!bid) return false;\n\n\tconst block = state.getBlock(bid);\n\tif (!block || !isNodeOfType(block, 'list_item') || block.attrs.listType !== 'checklist') {\n\t\treturn false;\n\t}\n\n\tconst attrs = buildListItemAttrs(block.attrs.listType, block.attrs.indent, !block.attrs.checked);\n\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setBlockType(bid, nodeType('list_item'), attrs)\n\t\t.setSelection(state.selection)\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n// --- Helpers ---\n\n/** Checks whether all blocks in a range are list items of the given type. Exported for toolbar. */\nexport function allBlocksMatchListType(\n\tstate: EditorState,\n\trange: ReturnType<typeof selectionRange>,\n\tlistType: ListType,\n): boolean {\n\tlet allMatch = true;\n\tforEachBlockIdInRange(state, range, (bid: BlockId) => {\n\t\tconst block = state.getBlock(bid);\n\t\tif (!block || block.type !== 'list_item' || block.attrs?.listType !== listType) {\n\t\t\tallMatch = false;\n\t\t}\n\t});\n\treturn allMatch;\n}\n","/**\n * List type metadata: icons, patterns, and type definitions.\n * Pure data constants shared across list plugin modules.\n */\n\nimport type { ListType } from './ListPlugin.js';\n\n// --- List Type Metadata ---\n\nexport interface ListTypeDefinition {\n\treadonly type: ListType;\n\treadonly icon: string;\n\treadonly inputPattern: RegExp;\n\treadonly inputPrefix: string;\n}\n\nconst BULLET_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z\"/></svg>';\nconst NUMBERED_LIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z\"/></svg>';\nconst CHECKLIST_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M22 7h-9v2h9V7zm0 8h-9v2h9v-2zM5.54 11L2 7.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 11zm0 8L2 15.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 19z\"/></svg>';\n\nexport const LIST_TYPE_DEFINITIONS: readonly ListTypeDefinition[] = [\n\t{\n\t\ttype: 'bullet',\n\t\ticon: BULLET_LIST_ICON,\n\t\tinputPattern: /^[-*] $/,\n\t\tinputPrefix: '- ',\n\t},\n\t{\n\t\ttype: 'ordered',\n\t\ticon: NUMBERED_LIST_ICON,\n\t\tinputPattern: /^\\d+\\. $/,\n\t\tinputPrefix: '1. ',\n\t},\n\t{\n\t\ttype: 'checklist',\n\t\ticon: CHECKLIST_ICON,\n\t\tinputPattern: /^\\[[ x]] $/,\n\t\tinputPrefix: '[ ] ',\n\t},\n];\n","/**\n * Input rule registration for list block types.\n * Converts `- `, `* `, `1. `, `[ ] `, `[x] ` at the start of a paragraph into list items.\n */\n\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { buildListItemAttrs } from './ListAttrsFactory.js';\nimport type { ListTypeDefinition } from './ListDefinitions.js';\n\n/** Registers markdown-style input rules for configured list types. */\nexport function registerListInputRules(\n\tcontext: PluginContext,\n\tenabledTypes: readonly ListTypeDefinition[],\n): void {\n\tfor (const def of enabledTypes) {\n\t\tcontext.registerInputRule({\n\t\t\tpattern: def.inputPattern,\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 = state.getBlock(sel.anchor.blockId);\n\t\t\t\tif (!block || block.type !== 'paragraph') return null;\n\n\t\t\t\tconst matchStr = match[0] ?? '';\n\t\t\t\tconst matchLen = matchStr.length;\n\t\t\t\tconst attrs = buildListItemAttrs(def.type, 0, matchStr.includes('[x]'));\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, start, start + matchLen)\n\t\t\t\t\t.setBlockType(sel.anchor.blockId, nodeType('list_item'), attrs)\n\t\t\t\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, 0))\n\t\t\t\t\t.build();\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * Keyboard handlers for list block types.\n * Handles Enter (split/exit list) and Backspace (convert to paragraph).\n */\n\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport { generateBlockId, getBlockText } from '../../model/Document.js';\nimport { createCollapsedSelection, isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { buildListItemAttrs } from './ListAttrsFactory.js';\n\n// --- Context Guard ---\n\ninterface ListContext {\n\treadonly state: EditorState;\n\treadonly block: BlockNode;\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n}\n\n/**\n * Guards against NodeSelection, non-collapsed selections, and non-list blocks.\n * Returns false (not handled) if the cursor is not inside a list_item block.\n */\nfunction withListContext(context: PluginContext, handler: (ctx: ListContext) => boolean): boolean {\n\tconst state: EditorState = context.getState();\n\tif (!isTextSelection(state.selection)) return false;\n\n\tconst sel = state.selection;\n\tif (!isCollapsed(sel)) return false;\n\n\tconst block: BlockNode | undefined = state.getBlock(sel.anchor.blockId);\n\tif (!block || block.type !== 'list_item') return false;\n\n\treturn handler({\n\t\tstate,\n\t\tblock,\n\t\tblockId: sel.anchor.blockId,\n\t\toffset: sel.anchor.offset,\n\t});\n}\n\n/** Registers Enter and Backspace keymaps for list items. */\nexport function registerListKeymaps(context: PluginContext): void {\n\tcontext.registerKeymap({\n\t\tEnter: () => handleEnter(context),\n\t\tBackspace: () => handleBackspace(context),\n\t});\n}\n\n// --- Enter Handler ---\n\n/**\n * Handles Enter inside a list item.\n * Empty item → exit list (convert to paragraph).\n * Non-empty item → split and create a new list item with the same type.\n */\nfunction handleEnter(context: PluginContext): boolean {\n\treturn withListContext(context, (ctx) => {\n\t\tconst text: string = getBlockText(ctx.block);\n\n\t\tif (text === '') {\n\t\t\tconst tr = ctx.state\n\t\t\t\t.transaction('input')\n\t\t\t\t.setBlockType(ctx.blockId, nodeType('paragraph'))\n\t\t\t\t.setSelection(ctx.state.selection)\n\t\t\t\t.build();\n\t\t\tcontext.dispatch(tr);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst newBlockId = generateBlockId();\n\t\tconst listType = isNodeOfType(ctx.block, 'list_item') ? ctx.block.attrs.listType : 'bullet';\n\t\tconst indent: number = isNodeOfType(ctx.block, 'list_item') ? ctx.block.attrs.indent : 0;\n\t\tconst attrs = buildListItemAttrs(listType, indent);\n\n\t\tconst tr = ctx.state\n\t\t\t.transaction('input')\n\t\t\t.splitBlock(ctx.blockId, ctx.offset, newBlockId)\n\t\t\t.setBlockType(newBlockId, nodeType('list_item'), attrs)\n\t\t\t.setSelection(createCollapsedSelection(newBlockId, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t});\n}\n\n// --- Backspace Handler ---\n\n/**\n * Handles Backspace at the start of a list item.\n * Converts the list item back to a paragraph, preserving text.\n */\nfunction handleBackspace(context: PluginContext): boolean {\n\treturn withListContext(context, (ctx) => {\n\t\tif (ctx.offset !== 0) return false;\n\n\t\tconst tr = ctx.state\n\t\t\t.transaction('input')\n\t\t\t.setBlockType(ctx.blockId, nodeType('paragraph'))\n\t\t\t.setSelection(ctx.state.selection)\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t});\n}\n","/**\n * Locale interface and default English locale for the ListPlugin.\n */\n\n// --- Locale Interface ---\n\nexport interface ListLocale {\n\treadonly bulletList: string;\n\treadonly numberedList: string;\n\treadonly checklist: string;\n}\n\n// --- Default English Locale ---\n\nexport const LIST_LOCALE_EN: ListLocale = {\n\tbulletList: 'Bullet List',\n\tnumberedList: 'Numbered List',\n\tchecklist: 'Checklist',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: Record<string, () => Promise<{ default: ListLocale }>> = import.meta.glob<{\n\tdefault: ListLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadListLocale(lang: string): Promise<ListLocale> {\n\tif (lang === 'en') return LIST_LOCALE_EN;\n\tconst loader = localeModules[`./locales/${lang}.ts`];\n\tif (!loader) return LIST_LOCALE_EN;\n\ttry {\n\t\tconst mod = await loader();\n\t\treturn mod.default;\n\t} catch {\n\t\treturn LIST_LOCALE_EN;\n\t}\n}\n","/**\n * Toolbar item registration for list block types.\n * Registers bullet, ordered, and checklist toolbar buttons with active-state detection.\n */\n\nimport { isTextSelection, selectionRange } from '../../model/Selection.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { allBlocksMatchListType } from './ListCommands.js';\nimport type { ListTypeDefinition } from './ListDefinitions.js';\nimport type { ListLocale } from './ListLocale.js';\nimport type { ListType } from './ListPlugin.js';\n\n/** Registers toolbar items for each enabled list type. */\nexport function registerListToolbarItems(\n\tcontext: PluginContext,\n\tenabledTypes: readonly ListTypeDefinition[],\n\tlocale: ListLocale,\n): void {\n\tfor (const def of enabledTypes) {\n\t\tcontext.registerToolbarItem({\n\t\t\tid: `list-${def.type}`,\n\t\t\tgroup: 'block',\n\t\t\ticon: def.icon,\n\t\t\tlabel: getListLabel(def.type, locale),\n\t\t\tcommand: `toggleList:${def.type}`,\n\t\t\tisActive: (state) => isListActive(state, def.type),\n\t\t});\n\t}\n}\n\n// --- Helpers ---\n\nfunction getListLabel(type: ListType, locale: ListLocale): string {\n\tconst labels: Record<ListType, string> = {\n\t\tbullet: locale.bulletList,\n\t\tordered: locale.numberedList,\n\t\tchecklist: locale.checklist,\n\t};\n\treturn labels[type];\n}\n\nfunction isListActive(state: EditorState, listType: ListType): boolean {\n\tif (!isTextSelection(state.selection)) return false;\n\n\tif (state.selection.anchor.blockId !== state.selection.head.blockId) {\n\t\tconst range = selectionRange(state.selection, state.getBlockOrder());\n\t\treturn allBlocksMatchListType(state, range, listType);\n\t}\n\n\tconst block = state.getBlock(state.selection.anchor.blockId);\n\treturn block?.type === 'list_item' && block.attrs?.listType === listType;\n}\n","/**\n * ListPlugin: registers ordered, unordered, and checklist block types\n * with NodeSpecs, toggle commands, indent/outdent (Tab/Shift-Tab),\n * input rules, and toolbar buttons.\n *\n * This file is a thin orchestrator — command logic, input rules, keyboard\n * handlers, and toolbar rendering are delegated to dedicated modules.\n *\n * List items are modeled as flat blocks with a `listType` and `indent` attribute,\n * allowing simple nesting representation without deep tree structures.\n */\n\nimport { LIST_CSS, LIST_MARKER_WIDTH } from '../../editor/styles/list.js';\nimport { blockId } from '../../model/TypeBrands.js';\nimport { setStyleProperty } from '../../style/StyleRuntime.js';\nimport { createBlockElement } from '../../view/DomUtils.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { resolveLocale } from '../shared/PluginHelpers.js';\nimport { registerListCommands, toggleChecked } from './ListCommands.js';\nimport { LIST_TYPE_DEFINITIONS, type ListTypeDefinition } from './ListDefinitions.js';\nimport { registerListInputRules } from './ListInputRules.js';\nimport { registerListKeymaps } from './ListKeyboardHandlers.js';\nimport { LIST_LOCALE_EN, type ListLocale, loadListLocale } from './ListLocale.js';\nimport { registerListToolbarItems } from './ListToolbarItems.js';\n\n// --- Attribute Registry Augmentation ---\n\nexport type ListType = 'bullet' | 'ordered' | 'checklist';\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\tlist_item: { listType: ListType; indent: number; checked: boolean };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface ListConfig {\n\t/** Which list types to enable. Defaults to all. */\n\treadonly types: readonly ListType[];\n\t/** Maximum indent depth. Defaults to 4. */\n\treadonly maxIndent: number;\n\t/**\n\t * When true, checklist checkboxes remain interactive even in read-only mode.\n\t * Defaults to false (checkboxes are fully read-only).\n\t */\n\treadonly interactiveCheckboxes?: boolean;\n\treadonly locale?: ListLocale;\n}\n\nconst DEFAULT_CONFIG: ListConfig = {\n\ttypes: ['bullet', 'ordered', 'checklist'],\n\tmaxIndent: 4,\n};\n\n// --- Plugin ---\n\nexport class ListPlugin implements Plugin {\n\treadonly id = 'list';\n\treadonly name = 'List';\n\treadonly priority = 35;\n\n\tprivate readonly config: ListConfig;\n\tprivate locale!: ListLocale;\n\tprivate context: PluginContext | null = null;\n\tprivate checkboxClickHandler: ((e: MouseEvent) => void) | null = null;\n\n\tconstructor(config?: Partial<ListConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.context = context;\n\t\tthis.locale = await resolveLocale(context, this.config.locale, LIST_LOCALE_EN, loadListLocale);\n\t\tconst enabledTypes = this.getEnabledTypes();\n\n\t\tcontext.registerStyleSheet(LIST_CSS);\n\t\tthis.registerNodeSpec(context);\n\t\tregisterListCommands(context, this.config, enabledTypes);\n\t\tregisterListKeymaps(context);\n\t\tregisterListInputRules(context, enabledTypes);\n\t\tregisterListToolbarItems(context, enabledTypes, this.locale);\n\t\tthis.registerCheckboxClickHandler(context);\n\t}\n\n\tdestroy(): void {\n\t\tif (this.checkboxClickHandler && this.context) {\n\t\t\tconst container: HTMLElement = this.context.getContainer();\n\t\t\tcontainer.removeEventListener('mousedown', this.checkboxClickHandler);\n\t\t}\n\t\tthis.checkboxClickHandler = null;\n\t\tthis.context = null;\n\t}\n\n\tprivate registerNodeSpec(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'list_item',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['text'] },\n\t\t\tattrs: {\n\t\t\t\tlistType: { default: 'bullet' },\n\t\t\t\tindent: { default: 0 },\n\t\t\t\tchecked: { default: false },\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\tconst listType = node.attrs?.listType ?? 'bullet';\n\t\t\t\tconst indent = node.attrs?.indent ?? 0;\n\t\t\t\tconst checked = node.attrs?.checked ?? false;\n\n\t\t\t\tconst li = createBlockElement('li', node.id);\n\t\t\t\tli.setAttribute('role', 'listitem');\n\t\t\t\tli.setAttribute('data-list-type', listType);\n\t\t\t\tli.setAttribute('data-indent', String(indent));\n\t\t\t\tli.className = `notectl-list-item notectl-list-item--${listType}`;\n\n\t\t\t\tif (indent > 0) {\n\t\t\t\t\tsetStyleProperty(li, 'marginLeft', `${indent * LIST_MARKER_WIDTH}px`);\n\t\t\t\t}\n\n\t\t\t\tif (listType === 'checklist') {\n\t\t\t\t\tli.setAttribute('data-checked', String(checked));\n\t\t\t\t\tli.setAttribute('aria-checked', String(checked));\n\t\t\t\t}\n\t\t\t\tli.setAttribute('aria-level', String(indent + 1));\n\n\t\t\t\treturn li;\n\t\t\t},\n\t\t\twrapper(node) {\n\t\t\t\tconst listType = node.attrs?.listType ?? 'bullet';\n\t\t\t\tconst tag = listType === 'ordered' ? 'ol' : 'ul';\n\t\t\t\treturn {\n\t\t\t\t\ttag,\n\t\t\t\t\tkey: `list-${listType}`,\n\t\t\t\t\tclassName: `notectl-list notectl-list--${listType}`,\n\t\t\t\t\tattrs: { role: 'list' },\n\t\t\t\t};\n\t\t\t},\n\t\t\ttoHTML(node, content) {\n\t\t\t\tconst listType: string = (node.attrs?.listType as string) ?? 'bullet';\n\t\t\t\tconst checked: boolean = (node.attrs?.checked as boolean) ?? false;\n\n\t\t\t\tif (listType === 'checklist') {\n\t\t\t\t\tconst checkedAttr: string = checked ? ' checked' : '';\n\t\t\t\t\tconst ariaChecked: string = String(checked);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t`<li role=\"checkbox\" aria-checked=\"${ariaChecked}\">` +\n\t\t\t\t\t\t`<input type=\"checkbox\" disabled${checkedAttr}>` +\n\t\t\t\t\t\t`${content || '<br>'}</li>`\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn `<li>${content || '<br>'}</li>`;\n\t\t\t},\n\t\t\tparseHTML: [{ tag: 'li' }],\n\t\t\tsanitize: {\n\t\t\t\ttags: ['ul', 'ol', 'li', 'input'],\n\t\t\t\tattrs: ['type', 'disabled', 'checked', 'role', 'aria-checked'],\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerCheckboxClickHandler(context: PluginContext): void {\n\t\tif (!this.config.types.includes('checklist')) return;\n\n\t\tthis.checkboxClickHandler = (e: MouseEvent) => {\n\t\t\tif (context.isReadOnly() && !this.config.interactiveCheckboxes) return;\n\n\t\t\tconst target: EventTarget | null = e.target;\n\t\t\tif (!(target instanceof HTMLElement)) return;\n\n\t\t\tconst li: HTMLElement | null = target.closest('.notectl-list-item--checklist');\n\t\t\tif (!li) return;\n\n\t\t\tconst rect: DOMRect = li.getBoundingClientRect();\n\t\t\tconst isRtl: boolean = getComputedStyle(li).direction === 'rtl';\n\t\t\tconst markerDistance: number = isRtl ? rect.right - e.clientX : e.clientX - rect.left;\n\t\t\tif (markerDistance >= LIST_MARKER_WIDTH) return;\n\n\t\t\te.preventDefault();\n\n\t\t\tconst bid: string | null = li.getAttribute('data-block-id');\n\t\t\tif (!bid) return;\n\n\t\t\ttoggleChecked(context, this.config.interactiveCheckboxes, blockId(bid));\n\t\t};\n\n\t\tconst container: HTMLElement = context.getContainer();\n\t\tcontainer.addEventListener('mousedown', this.checkboxClickHandler);\n\t}\n\n\tprivate getEnabledTypes(): readonly ListTypeDefinition[] {\n\t\treturn LIST_TYPE_DEFINITIONS.filter((def) => this.config.types.includes(def.type));\n\t}\n}\n"],"mappings":"wZCSA,SAAgB,EACf,EACA,EACA,GAEA,MAAiB,cAAb,EACI,CAAE,WAAU,SAAQ,QAAS,IAAW,GAEzC,CAAE,WAAU,UC+BpB,SAAS,EAAW,EAAwB,GAC3C,MAAM,EAAqB,EAAQ,WAC7B,EAAM,EAAM,UAClB,QAAK,EAAgB,KAEjB,EAAI,OAAO,UAAY,EAAI,KAAK,QAsCrC,SAAyB,EAAwB,EAAoB,GACpE,MAAM,EAAM,EAAM,UAClB,IAAK,EAAgB,GAAM,OAAO,EAElC,MAAM,EAAQ,EAAe,EAAK,EAAM,iBAClC,EAAqB,EAAuB,EAAO,EAAO,GAC1D,EAAU,EAAM,YAAY,WAwBlC,OAtBA,EAAsB,EAAO,EAAQ,IACpC,MAAM,EAAQ,EAAM,SAAS,GAC7B,GAAK,EAEL,GAAI,EACH,EAAQ,aAAa,EAAK,EAAS,kBAC7B,CACN,MAAM,EAAyB,EAAa,EAAO,aAAe,EAAM,MAAM,OAAS,EACjF,EACL,EAAa,EAAO,cACK,cAAzB,EAAM,MAAM,UACZ,EAAM,MAAM,QACb,EAAQ,aACP,EACA,EAAS,aACT,EAAmB,EAAU,EAAgB,OAKhD,EAAQ,aAAa,GACrB,EAAQ,SAAS,EAAQ,UAClB,EAnEC,CAAgB,EAAS,EAAO,GAKzC,SACC,EACA,EACA,GAEA,MAAM,EAAM,EAAM,UAClB,IAAK,EAAgB,GAAM,OAAO,EAClC,MAAM,EAAQ,EAAM,SAAS,EAAI,OAAO,SACxC,IAAK,EAAO,OAAO,EAEnB,GAAmB,cAAf,EAAM,MAAwB,EAAM,OAAO,WAAa,EAAU,CACrE,MAAM,EAAK,EACT,YAAY,WACZ,aAAa,EAAI,OAAO,QAAS,EAAS,cAC1C,aAAa,GACb,QAEF,OADA,EAAQ,SAAS,IACV,EAIR,MAAM,EAAQ,EAAmB,EADF,EAAa,EAAO,aAAe,EAAM,MAAM,OAAS,GAGjF,EAAK,EACT,YAAY,WACZ,aAAa,EAAI,OAAO,QAAS,EAAS,aAAc,GACxD,aAAa,GACb,QAEF,OADA,EAAQ,SAAS,IACV,EAhCA,CAAsB,EAAS,EAAO,IAsE9C,SAAS,EAAa,EAAwB,EAAe,GAC5D,MAAM,EAAqB,EAAQ,WACnC,IAAK,EAAgB,EAAM,WAAY,OAAO,EAE9C,GAAI,EAAM,UAAU,OAAO,UAAY,EAAM,UAAU,KAAK,QAC3D,OAoBF,SACC,EACA,EACA,EACA,GAEA,MAAM,EAAM,EAAM,UAClB,IAAK,EAAgB,GAAM,OAAO,EAElC,MAAM,EAAQ,EAAe,EAAK,EAAM,iBAClC,EAAU,EAAM,YAAY,WAClC,IAAI,GAAU,EAiBd,OAfA,EAAsB,EAAO,EAAQ,IACpC,MAAM,EAAQ,EAAM,SAAS,GAC7B,IAAK,IAAU,EAAa,EAAO,aAAc,OAEjD,MAAM,EAAoB,EAAM,MAAM,OAAS,EAC3C,EAAY,GAAK,EAAY,IAEjC,EAAQ,aACP,EACA,EAAS,aACT,EAAmB,EAAM,MAAM,SAAU,EAAW,EAAM,MAAM,UAEjE,GAAU,OAGN,IAEL,EAAQ,aAAa,GACrB,EAAQ,SAAS,EAAQ,UAClB,GApDC,CAAkB,EAAS,EAAO,EAAO,GAGjD,MAAM,EAAM,EAAM,UACZ,EAAQ,EAAM,SAAS,EAAI,OAAO,SACxC,IAAK,IAAU,EAAa,EAAO,aAAc,OAAO,EAExD,MAAM,EAAoB,EAAM,MAAM,OAAS,EAC/C,GAAI,EAAY,GAAK,EAAY,EAAW,OAAO,EAEnD,MAAM,EAAQ,EAAmB,EAAM,MAAM,SAAU,EAAW,EAAM,MAAM,SACxE,EAAK,EACT,YAAY,WACZ,aAAa,EAAI,OAAO,QAAS,EAAS,aAAc,GACxD,aAAa,GACb,QAEF,OADA,EAAQ,SAAS,IACV,EAyCR,SAAgB,EACf,EACA,EACA,GAEA,GAAI,EAAQ,eAAiB,EAAuB,OAAO,EAE3D,MAAM,EAAqB,EAAQ,WAC7B,EACL,IAAc,EAAgB,EAAM,WAAoB,EAAM,UAAU,OAAO,QAA9B,MAClD,IAAK,EAAK,OAAO,EAEjB,MAAM,EAAQ,EAAM,SAAS,GAC7B,IAAK,IAAU,EAAa,EAAO,cAAyC,cAAzB,EAAM,MAAM,SAC9D,OAAO,EAGR,MAAM,EAAQ,EAAmB,EAAM,MAAM,SAAU,EAAM,MAAM,QAAS,EAAM,MAAM,SAElF,EAAK,EACT,YAAY,WACZ,aAAa,EAAK,EAAS,aAAc,GACzC,aAAa,EAAM,WACnB,QAEF,OADA,EAAQ,SAAS,IACV,EAMR,SAAgB,EACf,EACA,EACA,GAEA,IAAI,GAAW,EAOf,OANA,EAAsB,EAAO,EAAQ,IACpC,MAAM,EAAQ,EAAM,SAAS,GACxB,GAAwB,cAAf,EAAM,MAAwB,EAAM,OAAO,WAAa,IACrE,GAAW,KAGN,ECxNR,IAOa,EAAuD,CACnE,CACC,KAAM,SACN,KATD,gWAUC,aAAc,UACd,YAAa,MAEd,CACC,KAAM,UACN,KAbD,2NAcC,aAAc,WACd,YAAa,OAEd,CACC,KAAM,YACN,KAjBD,4OAkBC,aAAc,aACd,YAAa,SEZf,SAAS,EAAgB,EAAwB,GAChD,MAAM,EAAqB,EAAQ,WACnC,IAAK,EAAgB,EAAM,WAAY,OAAO,EAE9C,MAAM,EAAM,EAAM,UAClB,IAAK,EAAY,GAAM,OAAO,EAE9B,MAAM,EAA+B,EAAM,SAAS,EAAI,OAAO,SAC/D,SAAK,GAAwB,cAAf,EAAM,OAEb,EAAQ,CACd,QACA,QACA,QAAS,EAAI,OAAO,QACpB,OAAQ,EAAI,OAAO,SC5BrB,IAAa,EAA6B,CACzC,WAAY,cACZ,aAAc,gBACd,UAAW,aAKN,iBAAwE,OAAA,OAAA,CAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,qBAAA,kBAAA,IAAA,OAAA,uBAI9E,eAAsB,EAAe,GACpC,GAAa,OAAT,EAAe,OAAO,EAC1B,MAAM,EAAS,EAAc,aAAa,QAC1C,IAAK,EAAQ,OAAO,EACpB,IAEC,aADkB,KACP,cAEX,OAAO,GCDT,SAAS,EAAa,EAAgB,GAMrC,MALyC,CACxC,OAAQ,EAAO,WACf,QAAS,EAAO,aAChB,UAAW,EAAO,WAEL,GAGf,SAAS,EAAa,EAAoB,GACzC,IAAK,EAAgB,EAAM,WAAY,OAAO,EAE9C,GAAI,EAAM,UAAU,OAAO,UAAY,EAAM,UAAU,KAAK,QAE3D,OAAO,EAAuB,EADhB,EAAe,EAAM,UAAW,EAAM,iBACR,GAG7C,MAAM,EAAQ,EAAM,SAAS,EAAM,UAAU,OAAO,SACpD,MAAuB,cAAhB,GAAO,MAAwB,EAAM,OAAO,WAAa,ECDjE,IAAM,EAA6B,CAClC,MAAO,CAAC,SAAU,UAAW,aAC7B,UAAW,GAKC,EAAb,MACC,GAAc,OACd,KAAgB,OAChB,SAAoB,GAEpB,OACA,OACA,QAAwC,KACxC,qBAAiE,KAEjE,WAAA,CAAY,GACX,KAAK,OAAS,IAAK,KAAmB,GAGvC,UAAM,CAAK,GACV,KAAK,QAAU,EACf,KAAK,aAAe,EAAc,EAAS,KAAK,OAAO,OAAQ,EAAgB,GAC/E,MAAM,EAAe,KAAK,kBAE1B,EAAQ,mBRxEc,21CQyEtB,KAAK,iBAAiB,GN5DxB,SACC,EACA,EACA,GAEA,IAAK,MAAM,KAAO,EACjB,EAAQ,gBAAgB,cAAc,EAAI,OAAA,IAClC,EAAW,EAAS,EAAI,OAIjC,EAAQ,gBAAgB,iBAAA,IAAwB,EAAa,EAAS,EAAG,EAAO,YAEhF,EAAQ,gBAAgB,kBAAA,IAAyB,EAAa,GAAS,EAAI,EAAO,YAE9E,EAAO,MAAM,SAAS,cACzB,EAAQ,gBACP,sBAAA,IACM,EAAc,EAAS,EAAO,uBACpC,CAAE,iBAAiB,IAIrB,EAAQ,eAAe,CACtB,IAAA,IAAW,EAAa,EAAS,EAAG,EAAO,WAC3C,YAAA,IAAmB,EAAa,GAAS,EAAI,EAAO,aMoCpD,CAAqB,EAAS,KAAK,OAAQ,GH/B7C,SAAoC,GACnC,EAAQ,eAAe,CACtB,MAAA,IAYF,SAAqB,GACpB,OAAO,EAAgB,EAAU,IAGhC,GAAa,KAFQ,EAAa,EAAI,OAErB,CAChB,MAAM,EAAK,EAAI,MACb,YAAY,SACZ,aAAa,EAAI,QAAS,EAAS,cACnC,aAAa,EAAI,MAAM,WACvB,QAEF,OADA,EAAQ,SAAS,IACV,EAGR,MAAM,EAAa,IAGb,EAAQ,EAFG,EAAa,EAAI,MAAO,aAAe,EAAI,MAAM,MAAM,SAAW,SAC5D,EAAa,EAAI,MAAO,aAAe,EAAI,MAAM,MAAM,OAAS,GAGjF,EAAK,EAAI,MACb,YAAY,SACZ,WAAW,EAAI,QAAS,EAAI,OAAQ,GACpC,aAAa,EAAY,EAAS,aAAc,GAChD,aAAa,EAAyB,EAAY,IAClD,QAEF,OADA,EAAQ,SAAS,IACV,IAtCM,CAAY,GACzB,UAAA,IA+CF,SAAyB,GACxB,OAAO,EAAgB,EAAU,IAChC,GAAmB,IAAf,EAAI,OAAc,OAAO,EAE7B,MAAM,EAAK,EAAI,MACb,YAAY,SACZ,aAAa,EAAI,QAAS,EAAS,cACnC,aAAa,EAAI,MAAM,WACvB,QAEF,OADA,EAAQ,SAAS,IACV,IAzDU,CAAgB,KG6BjC,CAAoB,GJnEtB,SACC,EACA,GAEA,IAAK,MAAM,KAAO,EACjB,EAAQ,kBAAkB,CACzB,QAAS,EAAI,aACb,QAAA,CAAU,EAAO,EAAO,EAAO,KAC9B,MAAM,EAAM,EAAM,UAClB,IAAK,EAAgB,GAAM,OAAO,KAClC,IAAK,EAAY,GAAM,OAAO,KAE9B,MAAM,EAAQ,EAAM,SAAS,EAAI,OAAO,SACxC,IAAK,GAAwB,cAAf,EAAM,KAAsB,OAAO,KAEjD,MAAM,EAAW,EAAM,IAAM,GACvB,EAAW,EAAS,OACpB,EAAQ,EAAmB,EAAI,KAAM,EAAG,EAAS,SAAS,QAEhE,OAAO,EACL,YAAY,SACZ,aAAa,EAAI,OAAO,QAAS,EAAO,EAAQ,GAChD,aAAa,EAAI,OAAO,QAAS,EAAS,aAAc,GACxD,aAAa,EAAyB,EAAI,OAAO,QAAS,IAC1D,WI4CJ,CAAuB,EAAS,GDlElC,SACC,EACA,EACA,GAEA,IAAK,MAAM,KAAO,EACjB,EAAQ,oBAAoB,CAC3B,GAAI,QAAQ,EAAI,OAChB,MAAO,QACP,KAAM,EAAI,KACV,MAAO,EAAa,EAAI,KAAM,GAC9B,QAAS,cAAc,EAAI,OAC3B,SAAW,GAAU,EAAa,EAAO,EAAI,QCuD9C,CAAyB,EAAS,EAAc,KAAK,QACrD,KAAK,6BAA6B,GAGnC,OAAA,GACK,KAAK,sBAAwB,KAAK,SACN,KAAK,QAAQ,eAClC,oBAAoB,YAAa,KAAK,sBAEjD,KAAK,qBAAuB,KAC5B,KAAK,QAAU,KAGhB,gBAAA,CAAyB,GACxB,EAAQ,iBAAiB,CACxB,KAAM,YACN,MAAO,QACP,QAAS,CAAE,MAAO,CAAC,SACnB,MAAO,CACN,SAAU,CAAE,QAAS,UACrB,OAAQ,CAAE,QAAS,GACnB,QAAS,CAAE,SAAS,IAErB,KAAA,CAAM,GACL,MAAM,EAAW,EAAK,OAAO,UAAY,SACnC,EAAS,EAAK,OAAO,QAAU,EAC/B,EAAU,EAAK,OAAO,UAAW,EAEjC,EAAK,EAAmB,KAAM,EAAK,IAgBzC,OAfA,EAAG,aAAa,OAAQ,YACxB,EAAG,aAAa,iBAAkB,GAClC,EAAG,aAAa,cAAe,OAAO,IACtC,EAAG,UAAY,wCAAwC,IAEnD,EAAS,GACZ,EAAiB,EAAI,aAAiB,GAAA,EAAH,MAGnB,cAAb,IACH,EAAG,aAAa,eAAgB,OAAO,IACvC,EAAG,aAAa,eAAgB,OAAO,KAExC,EAAG,aAAa,aAAc,OAAO,EAAS,IAEvC,GAER,OAAA,CAAQ,GACP,MAAM,EAAW,EAAK,OAAO,UAAY,SAEzC,MAAO,CACN,IAFwB,YAAb,EAAyB,KAAO,KAG3C,IAAK,QAAQ,IACb,UAAW,8BAA8B,IACzC,MAAO,CAAE,KAAM,UAGjB,MAAA,CAAO,EAAM,GACZ,MAAM,EAAoB,EAAK,OAAO,UAAuB,SACvD,EAAoB,EAAK,OAAO,UAAuB,EAE7D,GAAiB,cAAb,EAA0B,CAC7B,MAAM,EAAsB,EAAU,WAAa,GAEnD,MACC,qCAF2B,OAAO,sCAGA,KAC/B,GAAW,cAIhB,MAAO,OAAO,GAAW,eAE1B,UAAW,CAAC,CAAE,IAAK,OACnB,SAAU,CACT,KAAM,CAAC,KAAM,KAAM,KAAM,SACzB,MAAO,CAAC,OAAQ,WAAY,UAAW,OAAQ,mBAKlD,4BAAA,CAAqC,GAC/B,KAAK,OAAO,MAAM,SAAS,eAEhC,KAAK,qBAAwB,IAC5B,GAAI,EAAQ,eAAiB,KAAK,OAAO,sBAAuB,OAEhE,MAAM,EAA6B,EAAE,OACrC,KAAM,aAAkB,aAAc,OAEtC,MAAM,EAAyB,EAAO,QAAQ,iCAC9C,IAAK,EAAI,OAET,MAAM,EAAgB,EAAG,wBAGzB,IAF0D,QAAnC,iBAAiB,GAAI,UACL,EAAK,MAAQ,EAAE,QAAU,EAAE,QAAU,EAAK,OAAA,GACxC,OAEzC,EAAE,iBAEF,MAAM,EAAqB,EAAG,aAAa,iBACtC,GAEL,EAAc,EAAS,KAAK,OAAO,sBAAuB,EAAQ,KAGpC,EAAQ,eAC7B,iBAAiB,YAAa,KAAK,uBAG9C,eAAA,GACC,OAAO,EAAsB,OAAQ,GAAQ,KAAK,OAAO,MAAM,SAAS,EAAI"}
@@ -1,2 +0,0 @@
1
- import{n as t}from"./Plugin-C4cBw3bs.mjs";import{n as e,t as s}from"./XmlPatterns-B-V-mHF4.mjs";var n=new t("languageRegistry"),r=/(?:public|private|protected|abstract|final|sealed|non-sealed)?\s*(?:class|interface|enum|record)\s+\w+/,i=/^package\s+[\w.]+\s*;/m,l=/^import\s+(?:static\s+)?[\w.*]+\s*;/m,a=/(?:public|private|protected|static|final|abstract|synchronized|native)\s+(?:[\w<>\[\]?,\s]+)\s+\w+\s*\(/,o=/^[ \t]*@\w+/m,c=/;\s*$/gm,m=/[{}\s]*[{}]\s*$/gm,u=/public\s+static\s+void\s+main\s*\(\s*String\s*\[\s*\]\s+\w+\s*\)/,g=/\b(?:String|Integer|Boolean|List|Map|Set|Optional|void|int|long|double|boolean|char|byte|float|short)\b/,p=/System\s*\.\s*(?:out|err)\s*\.\s*\w+\s*\(/,h=/\btry\s*\{[\s\S]*?\}\s*catch\s*\(/,f=/\bnew\s+[A-Z]\w*\s*[<(]/,d=class{id="java";detect(t){const e=t.trim();return e.split("\n").filter(t=>t.trim().length>0).length<2||this.computeScore(e)<3?null:{language:"java",formattedText:e,confidence:.8}}computeScore(t){let e=0;return r.test(t)&&(e+=2),i.test(t)&&(e+=2),l.test(t)&&(e+=2),u.test(t)&&(e+=2),p.test(t)&&(e+=2),h.test(t)&&(e+=2),a.test(t)&&(e+=1),o.test(t)&&(e+=1),g.test(t)&&(e+=1),f.test(t)&&(e+=1),(t.match(c)??[]).length>=2&&(e+=1),(t.match(m)??[]).length>=2&&(e+=1),e}},x=class{id="json";detect(t){const e=t.trim();if(!e.startsWith("{")&&!e.startsWith("["))return null;try{const t=JSON.parse(e);if("object"!=typeof t||null===t)return null;const s=JSON.stringify(t,null,2);return s.length<=5?null:{language:"json",formattedText:s,confidence:.9}}catch{return null}}},w=/^(<\?[\s\S]*?\?>\s*)+/,b=new RegExp(`^<${e}${s}\\/?>`),S=new RegExp(["<\\?[^?]*\\?>","\x3c!--[\\s\\S]*?--\x3e","<!\\[CDATA\\[[\\s\\S]*?\\]\\]>",`<\\/(${e})>`,`<(${e})${s}\\/>`,`<(${e})${s}>`].join("|"),"g"),W=new RegExp(`<\\/${e}>\\s*$`),$=class{id="xml";detect(t){const e=t.trim();if(!e.startsWith("<"))return null;const s=e.replace(w,"");if(!b.test(s))return null;if(!this.isWellFormed(e))return null;const n=this.formatXml(e);return n.length<=10?null:{language:"xml",formattedText:n,confidence:.85}}isWellFormed(t){const e=[];let s=!1;S.lastIndex=0;let n=S.exec(t);for(;n;){const r=n[1],i=n[2],l=n[3];if(r){if(0===e.length||e[e.length-1]!==r)return!1;e.pop(),s=!0}else i?s=!0:l&&(e.push(l),s=!0);n=S.exec(t)}return s&&0===e.length}formatXml(t){const e=this.splitIntoTokens(t),s=[];let n=0;for(const r of e){const t=j[v(r)];"decrease"===t&&(n=Math.max(0,n-1)),s.push(" ".repeat(2*n)+r),"increase"===t&&n++}return s.join("\n")}splitIntoTokens(t){return t.replace(/>\s*</g,">\n<").split("\n").map(t=>t.trim()).filter(t=>t.length>0)}},j={pi:"none",comment:"none",cdata:"none",closing:"decrease",selfClosing:"none",inline:"none",opening:"increase",text:"none"};function v(t){return t.startsWith("<?")?"pi":t.startsWith("\x3c!--")?"comment":t.startsWith("<![CDATA[")?"cdata":t.startsWith("</")?"closing":t.endsWith("/>")?"selfClosing":t.startsWith("<")&&W.test(t)?"inline":t.startsWith("<")?"opening":"text"}export{n as i,x as n,d as r,$ as t};
2
- //# sourceMappingURL=XmlDetector-BiWxa0RJ.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"XmlDetector-BiWxa0RJ.mjs","names":[],"sources":["../../src/plugins/language/LanguageTypes.ts","../../src/plugins/smart-paste/detectors/JavaDetector.ts","../../src/plugins/smart-paste/detectors/JsonDetector.ts","../../src/plugins/smart-paste/detectors/XmlDetector.ts"],"sourcesContent":["/**\n * Unified language support types for programming language registration.\n *\n * Bundles syntax highlighting and paste detection into a single\n * registration unit so that all artifacts for one language live together.\n */\n\nimport { ServiceKey } from '../Plugin.js';\nimport type { LanguageDefinition } from '../code-block/highlighter/TokenizerTypes.js';\nimport type { ContentDetector } from '../smart-paste/SmartPasteTypes.js';\n\n/**\n * Unified language support bundle grouping all artifacts for one\n * programming language: syntax highlighting, paste detection, and\n * (optionally) code formatting.\n *\n * Pass to `LanguageRegistryService.register()` to make a language\n * available across all participating plugins in a single call.\n */\nexport interface LanguageSupport {\n\t/** Canonical lowercase identifier (e.g. `'java'`, `'python'`). */\n\treadonly id: string;\n\n\t/** Human-readable name shown in the language picker (e.g. `'Java'`). */\n\treadonly displayName: string;\n\n\t/** Alternative names accepted as aliases (e.g. `['py', 'py3']`). */\n\treadonly aliases?: readonly string[];\n\n\t/** Syntax highlighting token patterns for the RegexTokenizer. */\n\treadonly highlighting?: LanguageDefinition;\n\n\t/** Smart-paste detector for auto-detecting this language in pasted text. */\n\treadonly detection?: ContentDetector;\n\n\t/**\n\t * Code formatter for reformatting code block content on demand.\n\t * @experimental Not yet consumed by any built-in plugin.\n\t */\n\treadonly formatter?: CodeFormatter;\n}\n\n/**\n * Formatter that can reformat source code.\n * @experimental Reserved for future use.\n */\nexport interface CodeFormatter {\n\tformat(code: string): string | Promise<string>;\n}\n\n/** Service for registering and querying language support bundles. */\nexport interface LanguageRegistryService {\n\t/** Registers a language bundle. Re-registering the same `id` overwrites. */\n\tregister(support: LanguageSupport): void;\n\n\t/**\n\t * Subscribes to language registrations with replay semantics.\n\t * The listener is immediately called for all already-registered\n\t * bundles, then called for each future registration.\n\t */\n\tonRegister(listener: LanguageRegistryListener): void;\n\n\t/** Returns the bundle for the given language id, or `undefined`. */\n\tget(id: string): LanguageSupport | undefined;\n\n\t/** Returns all registered language support bundles. */\n\tgetAll(): readonly LanguageSupport[];\n}\n\n/** Internal listener type for registry change notifications. */\nexport type LanguageRegistryListener = (support: LanguageSupport) => void;\n\nexport const LANGUAGE_REGISTRY_SERVICE_KEY = new ServiceKey<LanguageRegistryService>(\n\t'languageRegistry',\n);\n","/**\n * Java content detector - identifies Java source code for code block insertion.\n *\n * Uses a scoring system based on structural patterns:\n * - Class/interface/enum/record declarations\n * - Package and import statements\n * - Method signatures with access modifiers\n * - Java-specific keywords and syntax patterns\n *\n * Requires multiple signals to avoid false positives on plain text.\n */\n\nimport type { ContentDetector, DetectionResult } from '../SmartPasteTypes.js';\n\n/** Minimum number of non-empty lines to consider as code. */\nconst MIN_LINES = 2;\n\n/** Minimum score to consider the text as Java code. */\nconst MIN_SCORE = 3;\n\n/** Confidence score for detected Java code. */\nconst JAVA_CONFIDENCE = 0.8;\n\n/** Matches class, interface, enum, record declarations. */\nconst CLASS_DECLARATION =\n\t/(?:public|private|protected|abstract|final|sealed|non-sealed)?\\s*(?:class|interface|enum|record)\\s+\\w+/;\n\n/** Matches package statements. */\nconst PACKAGE_STATEMENT = /^package\\s+[\\w.]+\\s*;/m;\n\n/** Matches import statements. */\nconst IMPORT_STATEMENT = /^import\\s+(?:static\\s+)?[\\w.*]+\\s*;/m;\n\n/** Matches method signatures with return type. */\nconst METHOD_SIGNATURE =\n\t/(?:public|private|protected|static|final|abstract|synchronized|native)\\s+(?:[\\w<>\\[\\]?,\\s]+)\\s+\\w+\\s*\\(/;\n\n/** Matches annotation usage. */\nconst ANNOTATION = /^[ \\t]*@\\w+/m;\n\n/** Matches lines ending with semicolons (excluding CSS-like patterns). */\nconst SEMICOLON_LINES = /;\\s*$/gm;\n\n/** Matches Java-style braces on their own line or after code. */\nconst BRACE_PATTERN = /[{}\\s]*[{}]\\s*$/gm;\n\n/** Matches Java main method. */\nconst MAIN_METHOD = /public\\s+static\\s+void\\s+main\\s*\\(\\s*String\\s*\\[\\s*\\]\\s+\\w+\\s*\\)/;\n\n/** Matches common Java types. */\nconst JAVA_TYPES =\n\t/\\b(?:String|Integer|Boolean|List|Map|Set|Optional|void|int|long|double|boolean|char|byte|float|short)\\b/;\n\n/** Matches System.out or System.err calls. */\nconst SYSTEM_CALL = /System\\s*\\.\\s*(?:out|err)\\s*\\.\\s*\\w+\\s*\\(/;\n\n/** Matches try-catch blocks. */\nconst TRY_CATCH = /\\btry\\s*\\{[\\s\\S]*?\\}\\s*catch\\s*\\(/;\n\n/** Matches new keyword with type. */\nconst NEW_INSTANCE = /\\bnew\\s+[A-Z]\\w*\\s*[<(]/;\n\nexport class JavaDetector implements ContentDetector {\n\treadonly id = 'java';\n\n\tdetect(text: string): DetectionResult | null {\n\t\tconst trimmed: string = text.trim();\n\t\tconst lines: string[] = trimmed.split('\\n').filter((l: string) => l.trim().length > 0);\n\t\tif (lines.length < MIN_LINES) return null;\n\n\t\tconst score: number = this.computeScore(trimmed);\n\t\tif (score < MIN_SCORE) return null;\n\n\t\treturn {\n\t\t\tlanguage: 'java',\n\t\t\tformattedText: trimmed,\n\t\t\tconfidence: JAVA_CONFIDENCE,\n\t\t};\n\t}\n\n\tprivate computeScore(text: string): number {\n\t\tlet score = 0;\n\n\t\t// Strong signals (2 points each)\n\t\tif (CLASS_DECLARATION.test(text)) score += 2;\n\t\tif (PACKAGE_STATEMENT.test(text)) score += 2;\n\t\tif (IMPORT_STATEMENT.test(text)) score += 2;\n\t\tif (MAIN_METHOD.test(text)) score += 2;\n\t\tif (SYSTEM_CALL.test(text)) score += 2;\n\t\tif (TRY_CATCH.test(text)) score += 2;\n\n\t\t// Medium signals (1 point each)\n\t\tif (METHOD_SIGNATURE.test(text)) score += 1;\n\t\tif (ANNOTATION.test(text)) score += 1;\n\t\tif (JAVA_TYPES.test(text)) score += 1;\n\t\tif (NEW_INSTANCE.test(text)) score += 1;\n\n\t\t// Structural signals\n\t\tconst semicolonCount: number = (text.match(SEMICOLON_LINES) ?? []).length;\n\t\tif (semicolonCount >= 2) score += 1;\n\n\t\tconst braceCount: number = (text.match(BRACE_PATTERN) ?? []).length;\n\t\tif (braceCount >= 2) score += 1;\n\n\t\treturn score;\n\t}\n}\n","/**\n * JSON content detector — validates and formats JSON for code block insertion.\n */\n\nimport type { ContentDetector, DetectionResult } from '../SmartPasteTypes.js';\n\n/** Minimum length for formatted JSON to be considered meaningful. */\nconst MIN_FORMATTED_LENGTH = 5;\n\n/** Confidence score for valid JSON detected via JSON.parse. */\nconst JSON_CONFIDENCE = 0.9;\n\nexport class JsonDetector implements ContentDetector {\n\treadonly id = 'json';\n\n\tdetect(text: string): DetectionResult | null {\n\t\tconst trimmed: string = text.trim();\n\t\tif (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null;\n\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(trimmed);\n\t\t\tif (typeof parsed !== 'object' || parsed === null) return null;\n\n\t\t\tconst formatted: string = JSON.stringify(parsed, null, 2);\n\t\t\tif (formatted.length <= MIN_FORMATTED_LENGTH) return null;\n\n\t\t\treturn { language: 'json', formattedText: formatted, confidence: JSON_CONFIDENCE };\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n","/**\n * XML content detector — validates and formats XML for code block insertion.\n */\n\nimport { XML_ATTRS, XML_TAG_NAME } from '../../shared/XmlPatterns.js';\nimport type { ContentDetector, DetectionResult } from '../SmartPasteTypes.js';\n\n/** Minimum length for formatted XML to be considered meaningful. */\nconst MIN_FORMATTED_LENGTH = 10;\n\n/** Confidence score for valid XML detected via structural analysis. */\nconst XML_CONFIDENCE = 0.85;\n\n/** Matches any leading processing instructions like <?xml ...?> or <?xml-stylesheet ...?> */\nconst LEADING_PIS_PATTERN = /^(<\\?[\\s\\S]*?\\?>\\s*)+/;\n\n/** Matches an opening tag like <root> or <ns:tag attr=\"val\"> */\nconst OPENING_TAG_PATTERN = new RegExp(`^<${XML_TAG_NAME}${XML_ATTRS}\\\\/?>`);\n\n// --- Well-formedness regex (decomposed for readability) ---\n\nconst PI_FRAGMENT = '<\\\\?[^?]*\\\\?>';\nconst COMMENT_FRAGMENT = '<!--[\\\\s\\\\S]*?-->';\nconst CDATA_FRAGMENT = '<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>';\nconst CLOSING_TAG_FRAGMENT = `<\\\\/(${XML_TAG_NAME})>`;\nconst SELF_CLOSING_TAG_FRAGMENT = `<(${XML_TAG_NAME})${XML_ATTRS}\\\\/>`;\nconst OPENING_TAG_FRAGMENT = `<(${XML_TAG_NAME})${XML_ATTRS}>`;\n\nconst WELL_FORMED_TAG_PATTERN = new RegExp(\n\t[\n\t\tPI_FRAGMENT,\n\t\tCOMMENT_FRAGMENT,\n\t\tCDATA_FRAGMENT,\n\t\tCLOSING_TAG_FRAGMENT,\n\t\tSELF_CLOSING_TAG_FRAGMENT,\n\t\tOPENING_TAG_FRAGMENT,\n\t].join('|'),\n\t'g',\n);\n\n/** Matches an inline element where open + close tag appear on the same token. */\nconst INLINE_ELEMENT_PATTERN = new RegExp(`<\\\\/${XML_TAG_NAME}>\\\\s*$`);\n\n/**\n * Detects well-formed XML content and formats it with proper indentation.\n *\n * Detection strategy:\n * 1. Text must start with `<` (after trimming)\n * 2. Must begin with an XML declaration, processing instruction, or opening tag\n * 3. All opened tags must be properly closed (basic well-formedness check)\n * 4. Must contain at least one tag pair or self-closing tag\n */\nexport class XmlDetector implements ContentDetector {\n\treadonly id = 'xml';\n\n\tdetect(text: string): DetectionResult | null {\n\t\tconst trimmed: string = text.trim();\n\t\tif (!trimmed.startsWith('<')) return null;\n\n\t\t// Quick structural check: strip leading PIs, then must start with an opening tag\n\t\tconst remainder: string = trimmed.replace(LEADING_PIS_PATTERN, '');\n\t\tif (!OPENING_TAG_PATTERN.test(remainder)) return null;\n\n\t\t// Validate well-formedness via tag balancing\n\t\tif (!this.isWellFormed(trimmed)) return null;\n\n\t\tconst formatted: string = this.formatXml(trimmed);\n\t\tif (formatted.length <= MIN_FORMATTED_LENGTH) return null;\n\n\t\treturn { language: 'xml', formattedText: formatted, confidence: XML_CONFIDENCE };\n\t}\n\n\t/**\n\t * Checks basic XML well-formedness by verifying that all opened tags\n\t * are properly closed in the correct nesting order.\n\t */\n\tprivate isWellFormed(xml: string): boolean {\n\t\tconst tagStack: string[] = [];\n\t\tlet foundTag = false;\n\n\t\t// Reset lastIndex — RegExp with 'g' flag is stateful\n\t\tWELL_FORMED_TAG_PATTERN.lastIndex = 0;\n\t\tlet match: RegExpExecArray | null = WELL_FORMED_TAG_PATTERN.exec(xml);\n\n\t\twhile (match) {\n\t\t\tconst closingTag: string | undefined = match[1];\n\t\t\tconst selfClosingTag: string | undefined = match[2];\n\t\t\tconst openingTag: string | undefined = match[3];\n\n\t\t\tif (closingTag) {\n\t\t\t\tif (tagStack.length === 0 || tagStack[tagStack.length - 1] !== closingTag) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\ttagStack.pop();\n\t\t\t\tfoundTag = true;\n\t\t\t} else if (selfClosingTag) {\n\t\t\t\tfoundTag = true;\n\t\t\t} else if (openingTag) {\n\t\t\t\ttagStack.push(openingTag);\n\t\t\t\tfoundTag = true;\n\t\t\t}\n\n\t\t\tmatch = WELL_FORMED_TAG_PATTERN.exec(xml);\n\t\t}\n\n\t\treturn foundTag && tagStack.length === 0;\n\t}\n\n\t/**\n\t * Formats XML with consistent 2-space indentation.\n\t */\n\tprivate formatXml(xml: string): string {\n\t\tconst tokens: string[] = this.splitIntoTokens(xml);\n\t\tconst parts: string[] = [];\n\t\tlet indent = 0;\n\t\tconst INDENT_STEP = 2;\n\n\t\tfor (const token of tokens) {\n\t\t\tconst kind: XmlTokenKind = classifyXmlToken(token);\n\t\t\tconst indentChange: IndentChange = INDENT_BEHAVIOR[kind];\n\n\t\t\tif (indentChange === 'decrease') {\n\t\t\t\tindent = Math.max(0, indent - 1);\n\t\t\t}\n\n\t\t\tparts.push(' '.repeat(indent * INDENT_STEP) + token);\n\n\t\t\tif (indentChange === 'increase') {\n\t\t\t\tindent++;\n\t\t\t}\n\t\t}\n\n\t\treturn parts.join('\\n');\n\t}\n\n\t/** Splits XML into line-level tokens by breaking between adjacent tags. */\n\tprivate splitIntoTokens(xml: string): string[] {\n\t\treturn xml\n\t\t\t.replace(/>\\s*</g, '>\\n<')\n\t\t\t.split('\\n')\n\t\t\t.map((line: string) => line.trim())\n\t\t\t.filter((line: string) => line.length > 0);\n\t}\n}\n\n// --- Token Classification ---\n\ntype XmlTokenKind =\n\t| 'pi'\n\t| 'comment'\n\t| 'cdata'\n\t| 'closing'\n\t| 'selfClosing'\n\t| 'inline'\n\t| 'opening'\n\t| 'text';\ntype IndentChange = 'increase' | 'decrease' | 'none';\n\nconst INDENT_BEHAVIOR: Readonly<Record<XmlTokenKind, IndentChange>> = {\n\tpi: 'none',\n\tcomment: 'none',\n\tcdata: 'none',\n\tclosing: 'decrease',\n\tselfClosing: 'none',\n\tinline: 'none',\n\topening: 'increase',\n\ttext: 'none',\n};\n\nfunction classifyXmlToken(token: string): XmlTokenKind {\n\tif (token.startsWith('<?')) return 'pi';\n\tif (token.startsWith('<!--')) return 'comment';\n\tif (token.startsWith('<![CDATA[')) return 'cdata';\n\tif (token.startsWith('</')) return 'closing';\n\tif (token.endsWith('/>')) return 'selfClosing';\n\tif (token.startsWith('<') && INLINE_ELEMENT_PATTERN.test(token)) return 'inline';\n\tif (token.startsWith('<')) return 'opening';\n\treturn 'text';\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{t}from"./FontPlugin-DYntd3gN.mjs";function n(n){return{toolbar:[[new t({fonts:[],...n?.font})]],plugins:[]}}export{n as t};
2
- //# sourceMappingURL=minimal-CMt909kl.mjs.map