@richscripts/richtexteditor 2.14.0 → 2.15.0

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 (238) hide show
  1. package/README.md +173 -10
  2. package/angular/build-manifest.json +23 -0
  3. package/angular/index.d.ts +71 -76
  4. package/angular/index.mjs +2 -0
  5. package/angular/package.json +4 -0
  6. package/headless/index.d.ts +3 -1
  7. package/headless/index.js +72 -16
  8. package/index.d.ts +33 -54
  9. package/integrations/initialization-scope.js +27 -0
  10. package/integrations/native-mount.js +30 -0
  11. package/integrations/shared.d.ts +23 -1
  12. package/integrations/shared.js +58 -22
  13. package/package.json +25 -3
  14. package/react/index.js +118 -37
  15. package/react/index.mjs +29 -0
  16. package/richtexteditor/all_plugins.js +7113 -1111
  17. package/richtexteditor/all_plugins.min.js +62 -59
  18. package/richtexteditor/lang/emoji/LICENSE-CLDR.txt +41 -0
  19. package/richtexteditor/lang/emoji/rte-emoji-de.js +3 -0
  20. package/richtexteditor/lang/emoji/rte-emoji-es.js +3 -0
  21. package/richtexteditor/lang/emoji/rte-emoji-fr.js +3 -0
  22. package/richtexteditor/lang/emoji/rte-emoji-it.js +3 -0
  23. package/richtexteditor/lang/emoji/rte-emoji-ja.js +3 -0
  24. package/richtexteditor/lang/emoji/rte-emoji-ko.js +3 -0
  25. package/richtexteditor/lang/emoji/rte-emoji-nl.js +3 -0
  26. package/richtexteditor/lang/emoji/rte-emoji-pt-pt.js +3 -0
  27. package/richtexteditor/lang/emoji/rte-emoji-pt.js +3 -0
  28. package/richtexteditor/lang/emoji/rte-emoji-ru.js +3 -0
  29. package/richtexteditor/lang/emoji/rte-emoji-zh-Hans.js +3 -0
  30. package/richtexteditor/lang/emoji/rte-emoji-zh-Hant.js +3 -0
  31. package/richtexteditor/lang/rte-lang-af.js +1 -0
  32. package/richtexteditor/lang/rte-lang-ar.js +1 -0
  33. package/richtexteditor/lang/rte-lang-bg.js +1 -0
  34. package/richtexteditor/lang/rte-lang-bn.js +1 -0
  35. package/richtexteditor/lang/rte-lang-bs.js +1 -0
  36. package/richtexteditor/lang/rte-lang-ca.js +1 -0
  37. package/richtexteditor/lang/rte-lang-cs.js +1 -0
  38. package/richtexteditor/lang/rte-lang-cy.js +1 -0
  39. package/richtexteditor/lang/rte-lang-da.js +1 -0
  40. package/richtexteditor/lang/rte-lang-de.js +1017 -2
  41. package/richtexteditor/lang/rte-lang-el.js +1 -0
  42. package/richtexteditor/lang/rte-lang-en.js +1 -0
  43. package/richtexteditor/lang/rte-lang-es.js +1023 -2
  44. package/richtexteditor/lang/rte-lang-et.js +1 -0
  45. package/richtexteditor/lang/rte-lang-fa.js +1 -0
  46. package/richtexteditor/lang/rte-lang-fi.js +1 -0
  47. package/richtexteditor/lang/rte-lang-fil.js +1 -0
  48. package/richtexteditor/lang/rte-lang-fj.js +1 -0
  49. package/richtexteditor/lang/rte-lang-fr.js +1023 -2
  50. package/richtexteditor/lang/rte-lang-ga.js +1 -0
  51. package/richtexteditor/lang/rte-lang-gu.js +1 -0
  52. package/richtexteditor/lang/rte-lang-he.js +1 -0
  53. package/richtexteditor/lang/rte-lang-hi.js +1 -0
  54. package/richtexteditor/lang/rte-lang-hr.js +1 -0
  55. package/richtexteditor/lang/rte-lang-ht.js +1 -0
  56. package/richtexteditor/lang/rte-lang-hu.js +1 -0
  57. package/richtexteditor/lang/rte-lang-id.js +1 -0
  58. package/richtexteditor/lang/rte-lang-is.js +1 -0
  59. package/richtexteditor/lang/rte-lang-it.js +1023 -2
  60. package/richtexteditor/lang/rte-lang-ja.js +1023 -2
  61. package/richtexteditor/lang/rte-lang-kn.js +1 -0
  62. package/richtexteditor/lang/rte-lang-ko.js +1023 -2
  63. package/richtexteditor/lang/rte-lang-lt.js +1 -0
  64. package/richtexteditor/lang/rte-lang-lv.js +1 -0
  65. package/richtexteditor/lang/rte-lang-mg.js +1 -0
  66. package/richtexteditor/lang/rte-lang-mi.js +1 -0
  67. package/richtexteditor/lang/rte-lang-ml.js +1 -0
  68. package/richtexteditor/lang/rte-lang-mr.js +1 -0
  69. package/richtexteditor/lang/rte-lang-ms.js +1 -0
  70. package/richtexteditor/lang/rte-lang-mt.js +1 -0
  71. package/richtexteditor/lang/rte-lang-mww.js +1 -0
  72. package/richtexteditor/lang/rte-lang-nb.js +1 -0
  73. package/richtexteditor/lang/rte-lang-nl.js +1023 -2
  74. package/richtexteditor/lang/rte-lang-otq.js +1 -0
  75. package/richtexteditor/lang/rte-lang-pa.js +1 -0
  76. package/richtexteditor/lang/rte-lang-pl.js +1 -0
  77. package/richtexteditor/lang/rte-lang-pt-pt.js +1023 -2
  78. package/richtexteditor/lang/rte-lang-pt.js +1023 -2
  79. package/richtexteditor/lang/rte-lang-ro.js +1 -0
  80. package/richtexteditor/lang/rte-lang-ru.js +1023 -2
  81. package/richtexteditor/lang/rte-lang-sk.js +1 -0
  82. package/richtexteditor/lang/rte-lang-sl.js +1 -0
  83. package/richtexteditor/lang/rte-lang-sm.js +1 -0
  84. package/richtexteditor/lang/rte-lang-sr-Cyrl.js +1 -0
  85. package/richtexteditor/lang/rte-lang-sr-Latn.js +1 -0
  86. package/richtexteditor/lang/rte-lang-sv.js +1 -0
  87. package/richtexteditor/lang/rte-lang-sw.js +1 -0
  88. package/richtexteditor/lang/rte-lang-ta.js +1 -0
  89. package/richtexteditor/lang/rte-lang-te.js +1 -0
  90. package/richtexteditor/lang/rte-lang-th.js +1 -0
  91. package/richtexteditor/lang/rte-lang-tlh-Latn.js +1 -0
  92. package/richtexteditor/lang/rte-lang-tlh-Piqd.js +1 -0
  93. package/richtexteditor/lang/rte-lang-to.js +1 -0
  94. package/richtexteditor/lang/rte-lang-tr.js +1 -0
  95. package/richtexteditor/lang/rte-lang-ty.js +1 -0
  96. package/richtexteditor/lang/rte-lang-uk.js +1 -0
  97. package/richtexteditor/lang/rte-lang-ur.js +1 -0
  98. package/richtexteditor/lang/rte-lang-vi.js +1 -0
  99. package/richtexteditor/lang/rte-lang-yua.js +1 -0
  100. package/richtexteditor/lang/rte-lang-zh-Hans.js +1017 -2
  101. package/richtexteditor/lang/rte-lang-zh-Hant.js +1017 -2
  102. package/richtexteditor/plugins/a11yenhance.js +2 -1
  103. package/richtexteditor/plugins/a11yenhance.min.js +1 -1
  104. package/richtexteditor/plugins/accessibilitychecker.js +252 -60
  105. package/richtexteditor/plugins/accessibilitychecker.min.js +1 -1
  106. package/richtexteditor/plugins/aitoolkit.js +966 -303
  107. package/richtexteditor/plugins/aitoolkit.min.js +7 -7
  108. package/richtexteditor/plugins/all_plugins.js +7113 -1111
  109. package/richtexteditor/plugins/all_plugins.min.js +62 -59
  110. package/richtexteditor/plugins/autocorrect.js +66 -31
  111. package/richtexteditor/plugins/autocorrect.min.js +1 -1
  112. package/richtexteditor/plugins/autoembed.js +17 -0
  113. package/richtexteditor/plugins/autoembed.min.js +1 -1
  114. package/richtexteditor/plugins/blocktypes.js +18 -9
  115. package/richtexteditor/plugins/blocktypes.min.js +1 -1
  116. package/richtexteditor/plugins/bookmarkcard.js +12 -5
  117. package/richtexteditor/plugins/bookmarkcard.min.js +2 -2
  118. package/richtexteditor/plugins/changecase.js +72 -19
  119. package/richtexteditor/plugins/changecase.min.js +1 -1
  120. package/richtexteditor/plugins/charlimit.js +62 -2
  121. package/richtexteditor/plugins/charlimit.min.js +2 -2
  122. package/richtexteditor/plugins/comments.js +458 -59
  123. package/richtexteditor/plugins/comments.min.js +4 -3
  124. package/richtexteditor/plugins/contentminimap.js +25 -6
  125. package/richtexteditor/plugins/contentminimap.min.js +1 -1
  126. package/richtexteditor/plugins/crossreference.js +1 -1
  127. package/richtexteditor/plugins/crossreference.min.js +1 -1
  128. package/richtexteditor/plugins/dialoga11y.js +26 -4
  129. package/richtexteditor/plugins/dialoga11y.min.js +1 -1
  130. package/richtexteditor/plugins/dictation.js +1 -1
  131. package/richtexteditor/plugins/documentimport.js +220 -51
  132. package/richtexteditor/plugins/documentimport.min.js +4 -4
  133. package/richtexteditor/plugins/documentoutline.js +88 -38
  134. package/richtexteditor/plugins/documentoutline.min.js +1 -1
  135. package/richtexteditor/plugins/docxexport.js +204 -32
  136. package/richtexteditor/plugins/docxexport.min.js +2 -2
  137. package/richtexteditor/plugins/draghandle.js +267 -3
  138. package/richtexteditor/plugins/draghandle.min.js +1 -1
  139. package/richtexteditor/plugins/emailtoolkit.js +28 -14
  140. package/richtexteditor/plugins/emailtoolkit.min.js +1 -1
  141. package/richtexteditor/plugins/emojiautocomplete.js +110 -56
  142. package/richtexteditor/plugins/emojiautocomplete.min.js +1 -1
  143. package/richtexteditor/plugins/footnotes.js +65 -11
  144. package/richtexteditor/plugins/footnotes.min.js +1 -1
  145. package/richtexteditor/plugins/formatpainter.js +10 -0
  146. package/richtexteditor/plugins/formatpainter.min.js +1 -1
  147. package/richtexteditor/plugins/formattingmarks.js +53 -8
  148. package/richtexteditor/plugins/formattingmarks.min.js +1 -1
  149. package/richtexteditor/plugins/gapcursor.js +60 -0
  150. package/richtexteditor/plugins/gapcursor.min.js +1 -1
  151. package/richtexteditor/plugins/ghostcomplete.js +1 -1
  152. package/richtexteditor/plugins/html2pdf.js +1 -1
  153. package/richtexteditor/plugins/html2pdf.min.js +1 -1
  154. package/richtexteditor/plugins/imageeditor.js +12 -6
  155. package/richtexteditor/plugins/imageeditor.min.js +1 -1
  156. package/richtexteditor/plugins/importstyles.js +1 -1
  157. package/richtexteditor/plugins/inlinecode.js +25 -0
  158. package/richtexteditor/plugins/inlinecode.min.js +1 -1
  159. package/richtexteditor/plugins/insertcode.js +21 -3
  160. package/richtexteditor/plugins/insertcode.min.js +4 -4
  161. package/richtexteditor/plugins/insertemoji.js +112 -15
  162. package/richtexteditor/plugins/insertemoji.min.js +1 -1
  163. package/richtexteditor/plugins/insertgallery.js +42 -36
  164. package/richtexteditor/plugins/insertgallery.min.js +1 -1
  165. package/richtexteditor/plugins/inserttemplate.js +33 -17
  166. package/richtexteditor/plugins/inserttemplate.min.js +1 -1
  167. package/richtexteditor/plugins/keyboarda11y.js +66 -3
  168. package/richtexteditor/plugins/keyboarda11y.min.js +1 -1
  169. package/richtexteditor/plugins/layouttable.js +20 -0
  170. package/richtexteditor/plugins/layouttable.min.js +1 -1
  171. package/richtexteditor/plugins/linkchecker.js +29 -9
  172. package/richtexteditor/plugins/linkchecker.min.js +1 -1
  173. package/richtexteditor/plugins/localdraft.js +51 -7
  174. package/richtexteditor/plugins/localdraft.min.js +1 -1
  175. package/richtexteditor/plugins/markdownexport.js +159 -0
  176. package/richtexteditor/plugins/markdownexport.min.js +2 -2
  177. package/richtexteditor/plugins/mathdialog.js +11 -5
  178. package/richtexteditor/plugins/mathdialog.min.js +1 -1
  179. package/richtexteditor/plugins/mentionplugin.js +88 -25
  180. package/richtexteditor/plugins/mentionplugin.min.js +1 -1
  181. package/richtexteditor/plugins/mermaiddiagram.js +9 -3
  182. package/richtexteditor/plugins/mermaiddiagram.min.js +2 -2
  183. package/richtexteditor/plugins/multilevellist.js +4 -0
  184. package/richtexteditor/plugins/multilevellist.min.js +1 -1
  185. package/richtexteditor/plugins/pdfexport.js +235 -35
  186. package/richtexteditor/plugins/pdfexport.min.js +12 -12
  187. package/richtexteditor/plugins/permanentpen.js +3 -3
  188. package/richtexteditor/plugins/permanentpen.min.js +1 -1
  189. package/richtexteditor/plugins/readabilitystats.js +25 -11
  190. package/richtexteditor/plugins/readabilitystats.min.js +1 -1
  191. package/richtexteditor/plugins/readaloud.js +29 -15
  192. package/richtexteditor/plugins/readaloud.min.js +1 -1
  193. package/richtexteditor/plugins/restrictedediting.js +166 -0
  194. package/richtexteditor/plugins/restrictedediting.min.js +2 -2
  195. package/richtexteditor/plugins/revisionhistory.js +169 -37
  196. package/richtexteditor/plugins/revisionhistory.min.js +3 -3
  197. package/richtexteditor/plugins/rubyannotation.js +19 -9
  198. package/richtexteditor/plugins/rubyannotation.min.js +1 -1
  199. package/richtexteditor/plugins/sanitizer.js +86 -4
  200. package/richtexteditor/plugins/sanitizer.min.js +1 -1
  201. package/richtexteditor/plugins/slashcommand.js +30 -16
  202. package/richtexteditor/plugins/slashcommand.min.js +2 -2
  203. package/richtexteditor/plugins/smartchips.js +36 -22
  204. package/richtexteditor/plugins/smartchips.min.js +2 -2
  205. package/richtexteditor/plugins/spellcheck.js +17 -8
  206. package/richtexteditor/plugins/spellcheck.min.js +2 -2
  207. package/richtexteditor/plugins/stateinspector.js +19 -9
  208. package/richtexteditor/plugins/stateinspector.min.js +2 -2
  209. package/richtexteditor/plugins/structured-content-bridge.js +56 -24
  210. package/richtexteditor/plugins/structured-content-bridge.min.js +7 -7
  211. package/richtexteditor/plugins/tableofcontents.js +5 -2
  212. package/richtexteditor/plugins/tableofcontents.min.js +1 -1
  213. package/richtexteditor/plugins/tabletools.js +388 -3
  214. package/richtexteditor/plugins/tabletools.min.js +1 -1
  215. package/richtexteditor/plugins/textdirection.js +18 -5
  216. package/richtexteditor/plugins/textdirection.min.js +1 -1
  217. package/richtexteditor/plugins/textpartlanguage.js +161 -32
  218. package/richtexteditor/plugins/textpartlanguage.min.js +1 -1
  219. package/richtexteditor/plugins/todolist.js +90 -6
  220. package/richtexteditor/plugins/todolist.min.js +1 -1
  221. package/richtexteditor/plugins/trackedchanges.js +1812 -25
  222. package/richtexteditor/plugins/trackedchanges.min.js +5 -3
  223. package/richtexteditor/plugins/wordexport.js +2 -2
  224. package/richtexteditor/plugins/yjscollab.js +9 -4
  225. package/richtexteditor/plugins/yjscollab.min.js +1 -1
  226. package/richtexteditor/plugins/zz_richtextbox_dialog_style.js +22 -13
  227. package/richtexteditor/plugins/zz_richtextbox_dialog_style.min.js +1 -1
  228. package/richtexteditor/rte-config.js +131 -50
  229. package/richtexteditor/rte-headless.js +19 -4
  230. package/richtexteditor/rte-webcomponent.js +89 -16
  231. package/richtexteditor/rte.js +133 -52
  232. package/richtexteditor/runtime/colorpicker_more_ns.htm +93 -16
  233. package/scripts/build-angular.mjs +97 -0
  234. package/svelte/index.d.ts +2 -1
  235. package/svelte/index.js +80 -9
  236. package/vue/index.js +130 -34
  237. package/angular/component.ts +0 -297
  238. package/angular/index.ts +0 -24
@@ -0,0 +1,27 @@
1
+ // Private framework lifecycle helper. Never abort a caller's shared controller.
2
+ function createInitializationScope(parentSignal) {
3
+ var controller = typeof AbortController === "function" ? new AbortController() : null;
4
+ var disposed = false;
5
+ var forwardAbort = null;
6
+ function complete() {
7
+ if (parentSignal && forwardAbort) parentSignal.removeEventListener("abort", forwardAbort);
8
+ forwardAbort = null;
9
+ parentSignal = null;
10
+ }
11
+ if (controller && parentSignal) {
12
+ forwardAbort = function () { controller.abort(parentSignal.reason); };
13
+ if (parentSignal.aborted) forwardAbort();
14
+ else parentSignal.addEventListener("abort", forwardAbort, { once: true });
15
+ }
16
+ return {
17
+ signal: controller ? controller.signal : parentSignal,
18
+ complete: complete,
19
+ dispose: function () {
20
+ if (disposed) return;
21
+ disposed = true;
22
+ complete();
23
+ if (controller) controller.abort();
24
+ }
25
+ };
26
+ }
27
+ module.exports = { createInitializationScope: createInitializationScope };
@@ -0,0 +1,30 @@
1
+ // Native inputs are converted into a sibling editor by the core. Frameworks
2
+ // remove their input, not that sibling; retain ownership of only the generated
3
+ // chrome and restore the input's original visibility during teardown.
4
+ function captureNativeMount(host) {
5
+ if (!host || !/^(INPUT|TEXTAREA)$/i.test(host.tagName || host.nodeName || "")) return null;
6
+ var previous = host.__rteIntegrationNativeMount;
7
+ var ownership = { host: host, parent: host.parentNode, display: previous ? previous.display : host.style && host.style.display,
8
+ hidden: previous ? previous.hidden : host.__rteHidden,
9
+ hadHidden: previous ? previous.hadHidden : Object.prototype.hasOwnProperty.call(host, "__rteHidden") };
10
+ host.__rteIntegrationNativeMount = ownership;
11
+ return ownership;
12
+ }
13
+ function releaseNativeMount(editor, ownership) {
14
+ if (!ownership) return;
15
+ var host = ownership.host, parent = ownership.parent, root = editor && editor.container;
16
+ if (root && root !== host && parent) {
17
+ while (root && root.parentNode !== parent) root = root.parentNode;
18
+ // Never remove the framework-owned input or a wrapper containing it.
19
+ var cursor = host, containsHost = false;
20
+ while (cursor) { if (cursor === root) { containsHost = true; break; } cursor = cursor.parentNode; }
21
+ if (root && root !== host && !containsHost && root.parentNode === parent) parent.removeChild(root);
22
+ }
23
+ if (host.__rteIntegrationNativeMount === ownership) {
24
+ if (host.style) host.style.display = ownership.display || "";
25
+ if (ownership.hadHidden) host.__rteHidden = ownership.hidden;
26
+ else delete host.__rteHidden;
27
+ delete host.__rteIntegrationNativeMount;
28
+ }
29
+ }
30
+ module.exports = { captureNativeMount: captureNativeMount, releaseNativeMount: releaseNativeMount };
@@ -9,6 +9,7 @@ import type {
9
9
  RichTextEditorInstance,
10
10
  RichTextEditorLinkAuditOptions,
11
11
  RichTextEditorLinkAuditResult,
12
+ RichTextEditorPageSetup,
12
13
  RichTextEditorStructuredDocument,
13
14
  RichTextEditorStructuredNode,
14
15
  RichTextEditorStructuredInput,
@@ -19,10 +20,24 @@ import type {
19
20
  RichTextEditorValueFormat
20
21
  } from "../index";
21
22
 
23
+ /** An instance after the structured-content bridge has been installed. */
24
+ export interface RichTextEditorBridgedInstance extends RichTextEditorInstance {
25
+ getJSON(): RichTextEditorStructuredDocument;
26
+ setJSON(value: RichTextEditorStructuredInput): this;
27
+ }
28
+
29
+ export interface RichTextEditorChangeCoalescer {
30
+ (): void;
31
+ flush(): void;
32
+ cancel(): void;
33
+ }
34
+
35
+ export function createChangeCoalescer(emit: () => void, delay?: number): RichTextEditorChangeCoalescer;
36
+
22
37
  export function createEditor(
23
38
  element: string | Element,
24
39
  config?: Record<string, unknown>
25
- ): RichTextEditorInstance;
40
+ ): RichTextEditorBridgedInstance;
26
41
 
27
42
  export function auditAccessibility(
28
43
  value: RichTextEditorStructuredInput
@@ -67,6 +82,13 @@ export function getDocumentMetrics(
67
82
  }
68
83
  ): RichTextEditorDocumentMetrics;
69
84
 
85
+ export function getDocumentPageSetup(value: RichTextEditorStructuredInput): RichTextEditorPageSetup | null;
86
+
87
+ export function setDocumentPageSetup(
88
+ value: RichTextEditorStructuredInput,
89
+ pageSetup: RichTextEditorPageSetup | null
90
+ ): RichTextEditorStructuredDocument;
91
+
70
92
  export function getMarkdownShortcutAction(
71
93
  value: string | null | undefined
72
94
  ): {
@@ -1,4 +1,5 @@
1
- var pendingLoadsByBasePath = {};
1
+ var pendingLoadsByBasePath = Object.create(null);
2
+ var failedLoadsByBasePath = Object.create(null);
2
3
 
3
4
  var INLINE_CONTAINER_TAGS = {
4
5
  a: true,
@@ -1789,7 +1790,7 @@ function parseBlockNode(node) {
1789
1790
  }
1790
1791
  var orderedListAttrs = {};
1791
1792
  if (startValue) {
1792
- orderedListAttrs.start = parseInt(startValue, 10) || 1;
1793
+ orderedListAttrs.start = (isFinite(parseInt(startValue, 10)) ? parseInt(startValue, 10) : 1);
1793
1794
  }
1794
1795
  if (orderedListType) {
1795
1796
  orderedListAttrs.orderedListType = orderedListType;
@@ -2529,7 +2530,7 @@ function escapeHtml(value) {
2529
2530
  }
2530
2531
 
2531
2532
  function escapeAttribute(value) {
2532
- return escapeHtml(value).replace(/"/g, "&quot;");
2533
+ return escapeHtml(value === undefined || value === null ? "" : String(value)).replace(/"/g, "&quot;");
2533
2534
  }
2534
2535
 
2535
2536
  function buildAttributeString(attrs) {
@@ -2782,7 +2783,7 @@ function serializeNode(node, inlineMode) {
2782
2783
 
2783
2784
  if (node.type === "orderedList") {
2784
2785
  var listAttrs = {};
2785
- if (node.attrs && node.attrs.start) {
2786
+ if (node.attrs && node.attrs.start !== undefined && node.attrs.start !== null) {
2786
2787
  listAttrs.start = node.attrs.start;
2787
2788
  }
2788
2789
  if (node.attrs) {
@@ -3183,8 +3184,8 @@ function validateNode(node, path, mode, issues) {
3183
3184
 
3184
3185
  if (node.type === "bulletList" || node.type === "orderedList") {
3185
3186
  if (node.type === "orderedList" && node.attrs && node.attrs.start !== undefined) {
3186
- if (typeof node.attrs.start !== "number" || node.attrs.start < 1) {
3187
- issues.push(createValidationIssue(path + ".attrs.start", "Ordered lists require a positive numeric start value."));
3187
+ if (typeof node.attrs.start !== "number" || !isFinite(node.attrs.start) || Math.floor(node.attrs.start) !== node.attrs.start || Math.abs(node.attrs.start) > 9007199254740991) {
3188
+ issues.push(createValidationIssue(path + ".attrs.start", "Ordered lists require a finite safe integer start value."));
3188
3189
  }
3189
3190
  }
3190
3191
  if (node.type === "orderedList" && node.attrs && node.attrs.orderedListType !== undefined) {
@@ -3919,12 +3920,12 @@ function getMarkdownListMatch(line) {
3919
3920
  };
3920
3921
  }
3921
3922
 
3922
- var orderedMatch = /^(\s*)(\d+)\.\s+(.*)$/.exec(line);
3923
+ var orderedMatch = /^(\s*)(\d{1,9})\.\s+(.*)$/.exec(line);
3923
3924
  if (orderedMatch) {
3924
3925
  return {
3925
3926
  indent: orderedMatch[1].length,
3926
3927
  ordered: true,
3927
- start: parseInt(orderedMatch[2], 10) || 1,
3928
+ start: parseInt(orderedMatch[2], 10),
3928
3929
  text: orderedMatch[3],
3929
3930
  marker: orderedMatch[2] + ".",
3930
3931
  contentIndent: orderedMatch[1].length + orderedMatch[2].length + 2,
@@ -4914,8 +4915,13 @@ function serializeMarkdownBlocks(nodes) {
4914
4915
 
4915
4916
  if (node.type === "bulletList" || node.type === "orderedList") {
4916
4917
  var listParts = [];
4917
- var start = node.type === "orderedList" && node.attrs && node.attrs.start ? parseInt(node.attrs.start, 10) || 1 : 1;
4918
+ var start = node.type === "orderedList" && node.attrs && node.attrs.start !== undefined ? parseInt(node.attrs.start, 10) : 1;
4919
+ if (!isFinite(start)) start = 1;
4918
4920
  var listItems = node.content || [];
4921
+ if (node.type === "orderedList" && (start < 0 || start + Math.max(0, listItems.length - 1) > 999999999)) {
4922
+ parts.push(serializeNode(node, false));
4923
+ continue;
4924
+ }
4919
4925
  for (var itemIndex = 0; itemIndex < listItems.length; itemIndex++) {
4920
4926
  var prefix = node.type === "orderedList" ? (start + itemIndex) + ". " : "- ";
4921
4927
  listParts.push(serializeMarkdownListItem(listItems[itemIndex].content || [], prefix));
@@ -5060,15 +5066,28 @@ function installStructuredContentBridge() {
5060
5066
  }
5061
5067
 
5062
5068
  function ensureStylesheet(href) {
5063
- if (document.querySelector('link[data-rte-style="' + href + '"]')) {
5064
- return;
5065
- }
5066
-
5067
- var link = document.createElement("link");
5068
- link.rel = "stylesheet";
5069
- link.href = href;
5070
- link.setAttribute("data-rte-style", href);
5071
- document.head.appendChild(link);
5069
+ return new Promise(function (resolve, reject) {
5070
+ var existing = document.querySelector('link[data-rte-style="' + href + '"]');
5071
+ if (existing && (existing.getAttribute("data-rte-loaded") === "true" || existing.sheet)) {
5072
+ resolve();
5073
+ return;
5074
+ }
5075
+ var link = existing || document.createElement("link");
5076
+ link.addEventListener("load", function () {
5077
+ link.setAttribute("data-rte-loaded", "true");
5078
+ resolve();
5079
+ }, { once: true });
5080
+ link.addEventListener("error", function () {
5081
+ if (link.parentNode) link.parentNode.removeChild(link);
5082
+ reject(new Error("Failed to load " + href));
5083
+ }, { once: true });
5084
+ if (!existing) {
5085
+ link.rel = "stylesheet";
5086
+ link.href = href;
5087
+ link.setAttribute("data-rte-style", href);
5088
+ document.head.appendChild(link);
5089
+ }
5090
+ });
5072
5091
  }
5073
5092
 
5074
5093
  function loadScript(src) {
@@ -5098,6 +5117,9 @@ function loadScript(src) {
5098
5117
  resolve(script);
5099
5118
  };
5100
5119
  script.onerror = function () {
5120
+ // A failed tag will never fire load again. Let an explicit retry
5121
+ // create a fresh request, without removing successfully loaded core.
5122
+ if (script.parentNode) script.parentNode.removeChild(script);
5101
5123
  reject(new Error("Failed to load " + src));
5102
5124
  };
5103
5125
 
@@ -5114,18 +5136,32 @@ function loadRichTextEditorAssets(options) {
5114
5136
 
5115
5137
  var basePath = trimTrailingSlash(options && options.basePath ? options.basePath : "/richtexteditor");
5116
5138
 
5117
- if (window.RichTextEditor) {
5139
+ // Core becomes global before plugins finish. All concurrent mounts must
5140
+ // await the same complete attempt rather than treating core as readiness.
5141
+ if (pendingLoadsByBasePath[basePath]) {
5142
+ return pendingLoadsByBasePath[basePath];
5143
+ }
5144
+
5145
+ if (window.RichTextEditor && !failedLoadsByBasePath[basePath]) {
5118
5146
  return Promise.resolve(installStructuredContentBridge());
5119
5147
  }
5120
5148
 
5121
5149
  if (!pendingLoadsByBasePath[basePath]) {
5122
- ensureStylesheet(basePath + "/rte_theme_default.css");
5123
- pendingLoadsByBasePath[basePath] = loadScript(basePath + "/rte.js")
5150
+ var themeReady = ensureStylesheet(basePath + "/rte_theme_default.css");
5151
+ var scriptsReady = loadScript(basePath + "/rte.js")
5124
5152
  .then(function () {
5153
+ if (window.RTE_DefaultConfig) window.RTE_DefaultConfig.url_base = basePath;
5125
5154
  return loadScript(basePath + "/plugins/all_plugins.js");
5126
- })
5155
+ });
5156
+ pendingLoadsByBasePath[basePath] = Promise.all([themeReady, scriptsReady])
5127
5157
  .then(function () {
5158
+ delete failedLoadsByBasePath[basePath];
5128
5159
  return installStructuredContentBridge();
5160
+ })
5161
+ .catch(function (error) {
5162
+ delete pendingLoadsByBasePath[basePath];
5163
+ failedLoadsByBasePath[basePath] = true;
5164
+ throw error;
5129
5165
  });
5130
5166
  }
5131
5167
 
package/package.json CHANGED
@@ -3,13 +3,15 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.14.0",
6
+ "version": "2.15.0",
7
7
  "description": "A full-featured JavaScript rich text editor (WYSIWYG) with toolbar, plugins, i18n support, a built-in AI Toolkit (Ask AI, AI Chat, AI Review drawer, BYOK resolver), structured content APIs (JSON/Markdown), and an optional collaboration / review stack: slash commands, @mentions, human-author Track Changes, threaded comments, revision history, and Yjs-backed presence. Ships first-class React, Vue, Angular and Svelte bindings, a headless \"bring your own UI\" core, and server-safe conversion helpers.",
8
8
  "main": "./richtexteditor/rte.js",
9
9
  "bin": {
10
10
  "rte-migration-report": "./migration/cli.js"
11
11
  },
12
12
  "scripts": {
13
+ "build:angular": "node scripts/build-angular.mjs",
14
+ "prepack": "node scripts/build-angular.mjs",
13
15
  "test:server": "node tests/run-all.test.js",
14
16
  "test:admin": "node tests/run-all.test.js",
15
17
  "test": "node tests/run-all.test.js",
@@ -28,10 +30,12 @@
28
30
  },
29
31
  "./angular": {
30
32
  "types": "./angular/index.d.ts",
31
- "default": "./angular/index.ts"
33
+ "default": "./angular/index.mjs"
32
34
  },
33
35
  "./react": {
34
36
  "types": "./react/index.d.ts",
37
+ "import": "./react/index.mjs",
38
+ "require": "./react/index.js",
35
39
  "default": "./react/index.js"
36
40
  },
37
41
  "./vue": {
@@ -66,7 +70,11 @@
66
70
  "./package.json": "./package.json"
67
71
  },
68
72
  "files": [
69
- "angular",
73
+ "angular/*.mjs",
74
+ "angular/*.d.ts",
75
+ "angular/package.json",
76
+ "angular/build-manifest.json",
77
+ "scripts/build-angular.mjs",
70
78
  "admin",
71
79
  "headless",
72
80
  "index.d.ts",
@@ -78,12 +86,26 @@
78
86
  "svelte",
79
87
  "vue"
80
88
  ],
89
+ "devDependencies": {
90
+ "@angular/common": "20.3.31",
91
+ "@angular/compiler": "20.3.31",
92
+ "@angular/compiler-cli": "20.3.31",
93
+ "@angular/core": "20.3.31",
94
+ "@angular/forms": "20.3.31",
95
+ "esbuild": "0.28.1",
96
+ "rxjs": "~7.8.2",
97
+ "typescript": "~5.9.3"
98
+ },
81
99
  "peerDependencies": {
100
+ "@angular/core": ">=20.3.0",
101
+ "@angular/forms": ">=20.3.0",
82
102
  "react": ">=18",
83
103
  "svelte": ">=3",
84
104
  "vue": ">=3"
85
105
  },
86
106
  "peerDependenciesMeta": {
107
+ "@angular/core": { "optional": true },
108
+ "@angular/forms": { "optional": true },
87
109
  "react": {
88
110
  "optional": true
89
111
  },
package/react/index.js CHANGED
@@ -1,6 +1,9 @@
1
+ "use client";
2
+
1
3
  var React = require("react");
2
4
  var shared = require("../integrations/shared");
3
5
  var headless = require("../headless");
6
+ var initializationScope = require("../integrations/initialization-scope");
4
7
 
5
8
  function pluginAccessor(editorRef, name) {
6
9
  return function () {
@@ -113,6 +116,9 @@ var RichTextEditorReact = React.forwardRef(function RichTextEditorReact(props, f
113
116
  var editorRef = React.useRef(null);
114
117
  var onChangeRef = React.useRef(props.onChange);
115
118
  var lastEmittedRef = React.useRef(undefined);
119
+ var initialValueRef = React.useRef(props.value !== undefined ? props.value : props.defaultValue);
120
+ var lastKnownHtmlRef = React.useRef(null);
121
+ var writingValueRef = React.useRef(false);
116
122
  // 0 disables coalescing and restores the pre-2.6 behaviour of emitting
117
123
  // synchronously on every change.
118
124
  var changeDelayRef = React.useRef(props.changeDelay == null ? 120 : props.changeDelay);
@@ -127,6 +133,7 @@ var RichTextEditorReact = React.forwardRef(function RichTextEditorReact(props, f
127
133
  onErrorRef.current = props.onError;
128
134
  formatRef.current = props.valueFormat || "html";
129
135
  configRef.current = props.config || {};
136
+ initialValueRef.current = props.value !== undefined ? props.value : props.defaultValue;
130
137
  });
131
138
 
132
139
  React.useImperativeHandle(forwardedRef, function () {
@@ -136,8 +143,41 @@ var RichTextEditorReact = React.forwardRef(function RichTextEditorReact(props, f
136
143
  React.useEffect(function () {
137
144
  var disposed = false;
138
145
  var changeHandler = null;
146
+ var blurHandler = null;
139
147
  var emitChange = null;
140
148
  var activeHost = hostRef.current;
149
+ var ownedEditor = null;
150
+
151
+ function emitCurrentValue() {
152
+ var editor = ownedEditor;
153
+ if (!editor || writingValueRef.current) return;
154
+ var value = shared.getEditorValue(editor, formatRef.current);
155
+ var html = typeof value === "string" ? value : (typeof value.html === "string" ? value.html : editor.getHTMLCode());
156
+ if (html === lastKnownHtmlRef.current) return;
157
+ lastKnownHtmlRef.current = html;
158
+ lastEmittedRef.current = value;
159
+ if (onChangeRef.current) onChangeRef.current(value, editor);
160
+ }
161
+
162
+ function releaseEditor() {
163
+ if (emitChange) emitChange.cancel();
164
+ emitChange = null;
165
+ var editor = ownedEditor;
166
+ ownedEditor = null;
167
+ if (editorRef.current === editor) editorRef.current = null;
168
+ if (editor && changeHandler && typeof editor.detachEvent === "function") {
169
+ try { editor.detachEvent("change", changeHandler); } catch (e) { /* Continue cleanup. */ }
170
+ }
171
+ changeHandler = null;
172
+ if (editor && blurHandler && typeof editor.detachEvent === "function") {
173
+ try { editor.detachEvent("blur", blurHandler); } catch (e) { /* Continue cleanup. */ }
174
+ }
175
+ blurHandler = null;
176
+ if (editor && typeof editor.destroy === "function") {
177
+ try { editor.destroy(); } catch (e) { /* Continue cleanup. */ }
178
+ }
179
+ if (activeHost && !editorRef.current) activeHost.innerHTML = "";
180
+ }
141
181
 
142
182
  var readyPromise = props.autoload === false
143
183
  ? Promise.resolve().then(function () {
@@ -151,59 +191,60 @@ var RichTextEditorReact = React.forwardRef(function RichTextEditorReact(props, f
151
191
  return;
152
192
  }
153
193
 
154
- var editor = shared.createEditor(activeHost, configRef.current);
194
+ // Plugins may wrap/move their container. Never give them the
195
+ // React-owned root: React removes that exact child on unmount.
196
+ var editorMount = activeHost.ownerDocument.createElement("div");
197
+ activeHost.appendChild(editorMount);
198
+ var editor = shared.createEditor(editorMount, configRef.current);
199
+ if (disposed) {
200
+ try { editor.destroy(); } catch (e) { /* Continue cleanup. */ }
201
+ return;
202
+ }
203
+ ownedEditor = editor;
155
204
  editorRef.current = editor;
156
205
 
157
- var initialValue = props.value !== undefined ? props.value : props.defaultValue;
206
+ var initialValue = initialValueRef.current;
158
207
  if (initialValue !== undefined) {
159
208
  shared.setEditorValue(editor, initialValue, formatRef.current);
160
209
  }
210
+ if (disposed) return;
211
+ lastKnownHtmlRef.current = editor.getHTMLCode();
212
+ lastEmittedRef.current = undefined;
161
213
 
162
214
  // Serialise at most once per quiet period rather than once per
163
215
  // keystroke. lastEmittedRef lets the value-sync effect below skip a
164
216
  // SECOND full serialisation when the parent hands back exactly what
165
217
  // we just emitted, which is the common controlled-component case.
166
- emitChange = shared.createChangeCoalescer(function () {
167
- var value = shared.getEditorValue(editor, formatRef.current);
168
- lastEmittedRef.current = value;
169
- if (onChangeRef.current) {
170
- onChangeRef.current(value, editor);
171
- }
172
- }, changeDelayRef.current);
218
+ emitChange = shared.createChangeCoalescer(emitCurrentValue, changeDelayRef.current);
173
219
 
174
- changeHandler = function () { emitChange(); };
220
+ changeHandler = function () { if (!disposed && !writingValueRef.current && emitChange) emitChange(); };
175
221
 
176
222
  editor.attachEvent("change", changeHandler);
223
+ blurHandler = function () {
224
+ if (disposed || writingValueRef.current) return;
225
+ if (emitChange) emitChange.flush();
226
+ emitCurrentValue();
227
+ };
228
+ editor.attachEvent("blur", blurHandler);
177
229
 
178
230
  if (onReadyRef.current) {
179
231
  onReadyRef.current(editor);
180
232
  }
181
233
  })
182
234
  .catch(function (error) {
183
- if (!disposed && onErrorRef.current) {
184
- onErrorRef.current(error);
235
+ if (!disposed) {
236
+ releaseEditor();
237
+ if (onErrorRef.current) onErrorRef.current(error);
185
238
  }
186
239
  });
187
240
 
188
241
  return function () {
242
+ if (disposed) return;
189
243
  disposed = true;
190
- // Flush before teardown or the last keystroke never reaches onChange.
191
- if (emitChange) { emitChange.flush(); }
192
- var ed = editorRef.current;
193
- if (ed) {
194
- if (changeHandler && typeof ed.detachEvent === "function") {
195
- ed.detachEvent("change", changeHandler);
196
- }
197
- // Tear down the editor's instance-level global listeners so an
198
- // unmount (or React 18 StrictMode's mount→unmount→mount) doesn't leak.
199
- if (typeof ed.destroy === "function") {
200
- try { ed.destroy(); } catch (e) { /* ignore */ }
201
- }
202
- }
203
- if (activeHost) {
204
- activeHost.innerHTML = "";
205
- }
206
- editorRef.current = null;
244
+ try {
245
+ if (emitChange) emitChange.flush();
246
+ if (changeHandler) emitCurrentValue();
247
+ } finally { releaseEditor(); }
207
248
  };
208
249
  }, []);
209
250
 
@@ -221,13 +262,18 @@ var RichTextEditorReact = React.forwardRef(function RichTextEditorReact(props, f
221
262
  return;
222
263
  }
223
264
  if (editorRef.current.getHTMLCode() !== nextHtml) {
224
- shared.setEditorValue(editorRef.current, props.value, props.valueFormat || "html");
265
+ writingValueRef.current = true;
266
+ try { shared.setEditorValue(editorRef.current, props.value, props.valueFormat || "html"); }
267
+ finally { writingValueRef.current = false; }
225
268
  }
269
+ if (editorRef.current) lastKnownHtmlRef.current = editorRef.current.getHTMLCode();
270
+ lastEmittedRef.current = undefined;
226
271
  }, [props.value, props.valueFormat]);
227
272
 
228
273
  var divProps = Object.assign({}, props);
229
274
  delete divProps.assetBasePath;
230
275
  delete divProps.autoload;
276
+ delete divProps.changeDelay;
231
277
  delete divProps.config;
232
278
  delete divProps.defaultValue;
233
279
  delete divProps.onChange;
@@ -249,8 +295,9 @@ RichTextEditorReact.defaultProps = {
249
295
 
250
296
  // ---- Headless hook: bring-your-own-UI, Tiptap-style ----
251
297
  // const editor = useRichTextEditor({ value: "<p>Hi</p>" });
252
- // <button onMouseDown={e => { e.preventDefault(); editor.run("bold"); }}
253
- // className={editor.state.bold ? "is-active" : ""}>B</button>
298
+ // <button type="button" onPointerDown={e => e.preventDefault()}
299
+ // onClick={() => editor.run("bold")} disabled={!editor.editor}
300
+ // aria-pressed={!!editor.state.bold}>Bold</button>
254
301
  // <EditorContent editor={editor} />
255
302
  function useRichTextEditor(options) {
256
303
  var optionsRef = React.useRef(options || {});
@@ -259,32 +306,66 @@ function useRichTextEditor(options) {
259
306
  var stateRef = React.useRef({});
260
307
  var rerender = React.useReducer(function (c) { return (c + 1) | 0; }, 0)[1];
261
308
 
309
+ React.useEffect(function () { optionsRef.current = options || {}; });
310
+
262
311
  React.useEffect(function () {
263
312
  var disposed = false;
264
313
  var ctl = null;
265
- headless.createHeadlessEditor(hostRef.current, optionsRef.current)
314
+ var pendingScope = null;
315
+ var activeHost = hostRef.current;
316
+ function releaseController() {
317
+ var owned = ctl;
318
+ ctl = null;
319
+ if (controllerRef.current === owned) controllerRef.current = null;
320
+ if (owned) { try { owned.destroy(); } catch (e) { /* Continue cleanup. */ } }
321
+ if (activeHost && !controllerRef.current) activeHost.innerHTML = "";
322
+ }
323
+ Promise.resolve().then(function () {
324
+ if (disposed) return null;
325
+ if (!activeHost) throw new Error("useRichTextEditor: render EditorContent before initialization.");
326
+ pendingScope = initializationScope.createInitializationScope(optionsRef.current.signal);
327
+ var editorMount = activeHost.ownerDocument.createElement("div");
328
+ activeHost.appendChild(editorMount);
329
+ return headless.createHeadlessEditor(editorMount, Object.assign({}, optionsRef.current, { signal: pendingScope.signal }));
330
+ })
266
331
  .then(function (controller) {
332
+ if (pendingScope) pendingScope.complete();
333
+ if (!controller) return;
267
334
  if (disposed) { controller.destroy(); return; }
268
335
  ctl = controller;
269
336
  controllerRef.current = controller;
337
+ var value = optionsRef.current.value;
338
+ if (value != null && value !== controller.getHTML()) controller.setHTML(value);
270
339
  controller.on("update", function (snapshot) {
340
+ if (disposed) return;
271
341
  stateRef.current = snapshot;
272
342
  rerender();
273
343
  });
274
344
  stateRef.current = controller.state();
275
345
  if (optionsRef.current.onReady) { optionsRef.current.onReady(controller); }
276
- rerender();
346
+ if (!disposed) rerender();
277
347
  })
278
348
  .catch(function (error) {
279
- if (optionsRef.current.onError) { optionsRef.current.onError(error); }
349
+ if (pendingScope) pendingScope.complete();
350
+ if (!disposed) {
351
+ releaseController();
352
+ if (optionsRef.current.onError) optionsRef.current.onError(error);
353
+ }
280
354
  });
281
355
  return function () {
356
+ if (disposed) return;
282
357
  disposed = true;
283
- if (ctl) { ctl.destroy(); }
284
- controllerRef.current = null;
358
+ if (pendingScope) pendingScope.dispose();
359
+ releaseController();
285
360
  };
286
361
  }, []);
287
362
 
363
+ React.useEffect(function () {
364
+ var controller = controllerRef.current;
365
+ var value = options && options.value;
366
+ if (controller && value != null && value !== controller.getHTML()) controller.setHTML(value);
367
+ }, [options && options.value]);
368
+
288
369
  return {
289
370
  ref: hostRef,
290
371
  get editor() { return controllerRef.current; }, // controller (null until ready)
@@ -0,0 +1,29 @@
1
+ "use client";
2
+
3
+ // A real ESM client boundary for React Server Component bundlers. Keep the CJS
4
+ // implementation available to require() consumers and conventional React SSR.
5
+ import bindings from "./index.js";
6
+
7
+ export const RichTextEditor = bindings.RichTextEditor;
8
+ export const RichTextEditorReact = bindings.RichTextEditorReact;
9
+ export const useRichTextEditor = bindings.useRichTextEditor;
10
+ export const EditorContent = bindings.EditorContent;
11
+ export const auditAccessibility = bindings.auditAccessibility;
12
+ export const auditLinks = bindings.auditLinks;
13
+ export const createStructuredDocument = bindings.createStructuredDocument;
14
+ export const createHeadlessEditor = bindings.createHeadlessEditor;
15
+ export const createStructuredContent = bindings.createStructuredContent;
16
+ export const fromMarkdown = bindings.fromMarkdown;
17
+ export const getDocumentPageSetup = bindings.getDocumentPageSetup;
18
+ export const getDocumentMetrics = bindings.getDocumentMetrics;
19
+ export const getDocumentOutline = bindings.getDocumentOutline;
20
+ export const getFootnotes = bindings.getFootnotes;
21
+ export const getTableOfContents = bindings.getTableOfContents;
22
+ export const getTextStatistics = bindings.getTextStatistics;
23
+ export const loadRichTextEditorAssets = bindings.loadRichTextEditorAssets;
24
+ export const renderHTML = bindings.renderHTML;
25
+ export const setDocumentPageSetup = bindings.setDocumentPageSetup;
26
+ export const syncTableOfContents = bindings.syncTableOfContents;
27
+ export const toMarkdown = bindings.toMarkdown;
28
+ export const validateStructuredContent = bindings.validateStructuredContent;
29
+ export default bindings;