@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
@@ -31,7 +31,31 @@ function RTE_Plugin_TableTools() {
31
31
 
32
32
  obj.PluginName = "TableTools";
33
33
 
34
- obj.InitConfig = function (argconfig) { config = argconfig; };
34
+ obj.InitConfig = function (argconfig) {
35
+ config = argconfig;
36
+ // 2026-10-15 Move Row Up/Down and Move Column Left/Right in the table menus: the single-pointer way to do what
37
+ // the row and column grips do by dragging (WCAG 2.2 SC 2.5.7, Dragging Movements). tools/tables/table-move-buttons.mjs
38
+ appendMenuItems("subtoolbar_tablerow", ["tablerowmoveup", "tablerowmovedown"]);
39
+ appendMenuItems("subtoolbar_tablecolumn", ["tablecolumnmoveleft", "tablecolumnmoveright"]);
40
+ var labels = { tablerowmoveup: "Move Row Up", tablerowmovedown: "Move Row Down", tablecolumnmoveleft: "Move Column Left", tablecolumnmoveright: "Move Column Right" };
41
+ var arrows = { tablerowmoveup: "M12 19V5M6 11l6-6 6 6", tablerowmovedown: "M12 5v14M6 13l6 6 6-6", tablecolumnmoveleft: "M19 12H5M11 6l-6 6 6 6", tablecolumnmoveright: "M5 12h14M13 6l6 6-6 6" };
42
+ for (var k in labels) {
43
+ if (config["text_" + k] == null) config["text_" + k] = labels[k];
44
+ if (config["svgCode_" + k] == null) config["svgCode_" + k] = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="' + arrows[k] + '"/></svg>';
45
+ }
46
+ };
47
+
48
+ // subtoolbar_* lists are comma-separated, sometimes inside braces
49
+ function appendMenuItems(name, items) {
50
+ var val = config[name];
51
+ if (typeof val !== "string" || !val) return;
52
+ for (var i = 0; i < items.length; i++) {
53
+ if (val.indexOf(items[i]) !== -1) continue;
54
+ var at = val.lastIndexOf("}");
55
+ val = at === -1 ? val + "," + items[i] : val.substring(0, at) + "," + items[i] + val.substring(at);
56
+ }
57
+ config[name] = val;
58
+ }
35
59
 
36
60
  obj.InitEditor = function (argeditor) {
37
61
  editor = argeditor;
@@ -51,6 +75,22 @@ function RTE_Plugin_TableTools() {
51
75
  editor.canSortTable = function () { return canSort(tableAtCaret()); };
52
76
  editor.addTableRowNumbers = function (opts) { return obj.AddRowNumbers(opts); };
53
77
  editor.removeTableRowNumbers = function () { return obj.RemoveRowNumbers(); };
78
+ ["tablerowmoveup", "tablerowmovedown", "tablecolumnmoveleft", "tablecolumnmoveright"].forEach(function (cmd) {
79
+ editor.toolbarFactoryMap = editor.toolbarFactoryMap || {};
80
+ if (!editor.toolbarFactoryMap[cmd]) editor.toolbarFactoryMap[cmd] = function (c) { return editor.createToolbarButton(c); };
81
+ editor.attachEvent("exec_command_" + cmd, function (state) {
82
+ state.returnValue = true;
83
+ state.stopBubble = true;
84
+ if (cmd === "tablerowmoveup") moveRowBy(-1);
85
+ else if (cmd === "tablerowmovedown") moveRowBy(1);
86
+ else if (cmd === "tablecolumnmoveleft") moveColumnBy(-1);
87
+ else moveColumnBy(1);
88
+ });
89
+ });
90
+ editor.moveTableRow = function (dir) { return moveRowBy(dir < 0 ? -1 : 1); };
91
+ editor.moveTableColumn = function (dir) { return moveColumnBy(dir < 0 ? -1 : 1); };
92
+ if (config.tableRowDrag !== false) initRowDrag();
93
+ if (config.tableColumnDrag !== false) initColumnDrag();
54
94
  editor.hasTableRowNumbers = function () {
55
95
  var t = tableAtCaret();
56
96
  return !!(t && t.querySelector("[data-rte-rownum]"));
@@ -142,7 +182,7 @@ function RTE_Plugin_TableTools() {
142
182
  if (/\d/.test(t)) {
143
183
  // Strip currency, spaces, thousands separators; (500) is accounting
144
184
  // notation for negative.
145
- var num = t.replace(/[\s ,]/g, "").replace(/^\(([^)]*)\)$/, "-$1").replace(/[^0-9.eE+-]/g, "");
185
+ var num = t.replace(/[\s\xa0,]/g, "").replace(/^\(([^)]*)\)$/, "-$1").replace(/[^0-9.eE+-]/g, "");
146
186
  if (num && /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(num)) {
147
187
  return { type: "number", v: parseFloat(num) };
148
188
  }
@@ -179,6 +219,11 @@ function RTE_Plugin_TableTools() {
179
219
  obj.Sort = function (table, index, dir) {
180
220
  var check = canSort(table);
181
221
  if (!check.ok) return check;
222
+ // 2026-10-14 Suggesting mode: a sort reorders rows and is not tracked yet, so the track hook refuses it.
223
+ // tools/tables/table-row-move.mjs
224
+ if (editor.__trackHook && editor.__trackHook("move", { direction: 0 }) === true) {
225
+ return { ok: false, reason: "Suggesting is on, so the table was not sorted. Turn suggesting off to sort it." };
226
+ }
182
227
  var descending = String(dir).toLowerCase() === "desc";
183
228
  var rows = bodyRows(table);
184
229
  var type = columnType(rows, index);
@@ -230,6 +275,337 @@ function RTE_Plugin_TableTools() {
230
275
  return { ok: true, reason: "", sortedBy: index, direction: descending ? "desc" : "asc", detectedType: type };
231
276
  };
232
277
 
278
+ // 2026-10-14 Row drag: a grip beside a body row drags that row to another place in its table. It is the same move
279
+ // as Alt+ArrowUp / Alt+ArrowDown, with the same limits: the header rows stay put, a table with merged cells is left
280
+ // alone, and suggesting mode refuses the move because a move is not tracked yet. config.tableRowDrag = false turns
281
+ // the grip off. Escape cancels a drag. tools/tables/table-row-drag.mjs
282
+ // 2026-10-15 grips and drop lines use z-index 99998, under the floating table toolbar (99999), so they never cover
283
+ // its menu buttons. tools/tables/table-move-buttons.mjs
284
+ function initRowDrag() {
285
+ var frame = editor.iframe;
286
+ if (!frame || !frame.ownerDocument) return;
287
+ var host = frame.ownerDocument;
288
+ var edoc = editor.getDocument();
289
+ var grip = host.createElement("div");
290
+ grip.className = "rte-row-grip";
291
+ grip.setAttribute("aria-hidden", "true");
292
+ // 2026-10-15 this was the quoted text "String.fromCharCode(0x283f)", shown as code in the grip. tools/tables/table-column-drag.mjs
293
+ grip.textContent = "\u283f";
294
+ var gs = grip.style;
295
+ gs.position = "fixed"; gs.display = "none"; gs.zIndex = "99998"; gs.width = "12px"; gs.height = "22px";
296
+ gs.lineHeight = "22px"; gs.textAlign = "center"; gs.fontSize = "14px"; gs.color = "#64748b"; gs.cursor = "grab";
297
+ gs.userSelect = "none"; gs.borderRadius = "3px"; gs.background = "rgba(15,23,42,.06)";
298
+ var line = host.createElement("div");
299
+ line.className = "rte-row-drop";
300
+ var ls = line.style;
301
+ ls.position = "fixed"; ls.display = "none"; ls.zIndex = "99998"; ls.height = "2px";
302
+ ls.background = "#2563eb"; ls.pointerEvents = "none";
303
+ host.body.appendChild(grip);
304
+ host.body.appendChild(line);
305
+
306
+ var hoverRow = null, hideTid = 0, drag = null;
307
+
308
+ function frameRect() { return frame.getBoundingClientRect(); }
309
+ function inEditable(node) { try { return !!editor.getEditable() && editor.getEditable().contains(node); } catch (e) { return false; } }
310
+ // The row under a node, if it is a body row that may move.
311
+ function movableRowAt(node) {
312
+ var el = node && node.nodeType === 1 ? node : (node && node.parentNode);
313
+ while (el && el.nodeName !== "TR") el = el.parentNode;
314
+ if (!el || !inEditable(el)) return null;
315
+ var sec = el.parentNode && el.parentNode.nodeName;
316
+ if (sec === "THEAD" || sec === "TFOOT") return null;
317
+ var table = el.closest ? el.closest("table") : null;
318
+ if (!table || bodyRows(table).indexOf(el) < 0) return null;
319
+ return el;
320
+ }
321
+ function placeGrip(row) {
322
+ var fr = frameRect(), tr = row.getBoundingClientRect(), table = row.closest("table");
323
+ var left = table.getBoundingClientRect().left - 14;
324
+ // no room in the gutter: no grip, so it never covers the first cell (the keyboard still moves rows)
325
+ if (left < fr.left) { gs.display = "none"; return; }
326
+ gs.left = Math.round(left) + "px";
327
+ gs.top = Math.round(fr.top + tr.top + tr.height / 2 - 11) + "px";
328
+ gs.display = "block";
329
+ }
330
+ function hideGripSoon() {
331
+ clearTimeout(hideTid);
332
+ hideTid = setTimeout(function () { if (!drag) { gs.display = "none"; hoverRow = null; } }, 350);
333
+ }
334
+ // a pointer event from the editing frame has its y in the frame; the grip lives in the host page
335
+ function hostY(e) { return e.view === frame.contentWindow ? frameRect().top + e.clientY : e.clientY; }
336
+ function hasMergedCells(table) {
337
+ var rows = bodyRows(table);
338
+ for (var i = 0; i < rows.length; i++) for (var c = 0; c < rows[i].cells.length; c++) {
339
+ var cell = rows[i].cells[c];
340
+ if ((cell.rowSpan || 1) > 1 || (cell.colSpan || 1) > 1) return true;
341
+ }
342
+ return false;
343
+ }
344
+ function say(text) { try { if (typeof editor.announce === "function") editor.announce(text); } catch (e) { /* ignore */ } }
345
+
346
+ edoc.addEventListener("mousemove", function (e) {
347
+ if (drag) return;
348
+ var row = movableRowAt(e.target);
349
+ if (row) { clearTimeout(hideTid); hoverRow = row; placeGrip(row); } else { hideGripSoon(); }
350
+ });
351
+ grip.addEventListener("mouseenter", function () { clearTimeout(hideTid); });
352
+ grip.addEventListener("mouseleave", hideGripSoon);
353
+
354
+ function endDrag() {
355
+ drag = null;
356
+ host.removeEventListener("mousemove", onDragMove, true);
357
+ edoc.removeEventListener("mousemove", onDragMove, true);
358
+ host.removeEventListener("mouseup", onDragEnd, true);
359
+ edoc.removeEventListener("mouseup", onDragEnd, true);
360
+ host.removeEventListener("keydown", onDragKey, true);
361
+ edoc.removeEventListener("keydown", onDragKey, true);
362
+ ls.display = "none"; gs.display = "none"; gs.cursor = "grab";
363
+ }
364
+ function onDragMove(e) {
365
+ if (!drag) return;
366
+ var y = hostY(e), fr = frameRect(), rows = drag.rows, drop = rows.length;
367
+ for (var i = 0; i < rows.length; i++) {
368
+ var rr = rows[i].getBoundingClientRect();
369
+ if (y < fr.top + rr.top + rr.height / 2) { drop = i; break; }
370
+ }
371
+ drag.drop = drop;
372
+ // dropping the row where it already is, or just below itself, changes nothing
373
+ var noop = drop === drag.from || drop === drag.from + 1;
374
+ drag.noop = noop;
375
+ var at = drop < rows.length ? fr.top + rows[drop].getBoundingClientRect().top
376
+ : fr.top + rows[rows.length - 1].getBoundingClientRect().bottom;
377
+ var tb = drag.table.getBoundingClientRect();
378
+ ls.left = Math.round(fr.left + tb.left) + "px";
379
+ ls.width = Math.round(tb.width) + "px";
380
+ ls.top = Math.round(at - 1) + "px";
381
+ ls.display = noop ? "none" : "block";
382
+ }
383
+ function moveRow(d) {
384
+ // 2026-10-14 Read-only (designMode off) or comments-only: a move changes the document, so it does nothing. tools/review/readonly-audit.mjs
385
+ try { if (String(editor.getDocument().designMode).toLowerCase() === "off" || (editor.getCommentsOnly && editor.getCommentsOnly())) return false; } catch (e) { /* ignore */ }
386
+ if (hasMergedCells(d.table)) { say("This table has merged cells, so the row was not moved."); return false; }
387
+ // a move is not tracked yet: suggesting mode refuses it (the track hook answers "move")
388
+ if (editor.__trackHook && editor.__trackHook("move", { direction: 0 }) === true) return false;
389
+ var ref = d.drop < d.rows.length ? d.rows[d.drop] : null;
390
+ if (typeof editor.recordUndo === "function") editor.recordUndo();
391
+ d.row.parentNode.insertBefore(d.row, ref);
392
+ renumber(d.table);
393
+ // the caret goes into the moved row and the editor takes focus, so Ctrl+Z reaches the editor (as after Alt+Arrow)
394
+ try { restoreCaret(d.row.cells[0]); if (typeof editor.focus === "function") editor.focus(); } catch (e) { /* ignore */ }
395
+ fireChange();
396
+ return true;
397
+ }
398
+ function onDragEnd(e) {
399
+ if (!drag) return;
400
+ var d = drag;
401
+ endDrag();
402
+ if (d.drop < 0 || d.noop) return;
403
+ moveRow(d);
404
+ }
405
+ function onDragKey(e) {
406
+ if (e.key === "Escape") { endDrag(); }
407
+ }
408
+ grip.addEventListener("mousedown", function (e) {
409
+ if (!hoverRow || e.button !== 0) return;
410
+ e.preventDefault();
411
+ var table = hoverRow.closest("table");
412
+ var rows = bodyRows(table).filter(function (r) { return r.parentNode === hoverRow.parentNode; });
413
+ drag = { row: hoverRow, table: table, rows: rows, from: rows.indexOf(hoverRow), drop: -1, noop: true };
414
+ gs.cursor = "grabbing";
415
+ host.addEventListener("mousemove", onDragMove, true);
416
+ edoc.addEventListener("mousemove", onDragMove, true);
417
+ host.addEventListener("mouseup", onDragEnd, true);
418
+ edoc.addEventListener("mouseup", onDragEnd, true);
419
+ host.addEventListener("keydown", onDragKey, true);
420
+ edoc.addEventListener("keydown", onDragKey, true);
421
+ });
422
+ }
423
+
424
+ // 2026-10-15 Column drag: a grip above a column drags it to another place in its table (Tiptap, CKEditor and
425
+ // BlockNote move columns). Every row moves the cell, header rows too, and the column's <col> width goes with it.
426
+ // Same limits as the row grip: merged cells or ragged rows leave the table alone, suggesting mode refuses (a move
427
+ // is not tracked), read-only does nothing, and the row-number column stays first. config.tableColumnDrag = false
428
+ // turns it off; Escape cancels. tools/tables/table-column-drag.mjs
429
+ function say(text) { try { if (typeof editor.announce === "function") editor.announce(text); } catch (e) { /* ignore */ } }
430
+ // read-only and comments-only change nothing; suggesting mode refuses a move, which is not tracked yet
431
+ function moveRefused() {
432
+ try { if (String(editor.getDocument().designMode).toLowerCase() === "off" || (editor.getCommentsOnly && editor.getCommentsOnly())) return true; } catch (e) { /* ignore */ }
433
+ return !!(editor.__trackHook && editor.__trackHook("move", { direction: 0 }) === true);
434
+ }
435
+ // a rectangular table: every row has the same number of cells and none spans
436
+ function isRectangular(table) {
437
+ var rows = table.rows, n = rows.length ? rows[0].cells.length : 0;
438
+ for (var i = 0; i < rows.length; i++) {
439
+ if (rows[i].cells.length !== n) return false;
440
+ for (var c = 0; c < n; c++) if ((rows[i].cells[c].rowSpan || 1) > 1 || (rows[i].cells[c].colSpan || 1) > 1) return false;
441
+ }
442
+ return n > 1;
443
+ }
444
+ // the first column that may move: the row-number column stays put
445
+ function firstMovableColumn(table) { return table.querySelector("[data-rte-rownum]") ? 1 : 0; }
446
+ // Move column `from` so it sits before column `drop` (drop = column count: to the end). caretCell, when given,
447
+ // keeps the caret; otherwise it goes into the moved column's first body cell.
448
+ function moveColumnTo(table, from, drop, caretCell) {
449
+ if (moveRefused()) return false;
450
+ if (!isRectangular(table)) { say("This table has merged cells, so the column was not moved."); return false; }
451
+ var rows = table.rows, n = rows[0].cells.length;
452
+ if (from < 0 || from >= n || drop < 0 || drop > n || drop === from || drop === from + 1) return false;
453
+ if (typeof editor.recordUndo === "function") editor.recordUndo();
454
+ for (var i = 0; i < rows.length; i++) {
455
+ var cells = rows[i].cells;
456
+ rows[i].insertBefore(cells[from], drop < n ? cells[drop] : null);
457
+ }
458
+ // the <col> widths follow, when the colgroup describes these columns (it may leave out the number column)
459
+ var cols = [];
460
+ for (var k = 0; k < table.children.length; k++) {
461
+ var g = table.children[k];
462
+ if (g.nodeName === "COLGROUP") for (var m = 0; m < g.children.length; m++) if (g.children[m].nodeName === "COL") cols.push(g.children[m]);
463
+ }
464
+ var off = n - cols.length, spans = false;
465
+ for (var s = 0; s < cols.length; s++) if ((parseInt(cols[s].getAttribute("span"), 10) || 1) > 1) spans = true;
466
+ if (cols.length && !spans && (off === 0 || off === firstMovableColumn(table)) && from >= off) {
467
+ var col = cols[from - off], ref = drop < n ? cols[drop - off] : null;
468
+ if (col && col !== ref) (ref ? ref.parentNode : col.parentNode).insertBefore(col, ref);
469
+ }
470
+ var at = drop > from ? drop - 1 : drop;
471
+ try { restoreCaret(caretCell || rows[rows.length > 1 ? 1 : 0].cells[at]); if (typeof editor.focus === "function") editor.focus(); } catch (e) { /* ignore */ }
472
+ fireChange();
473
+ return true;
474
+ }
475
+ function moveColumnBy(dir) {
476
+ var cell = cellAtCaret();
477
+ if (!cell || cell.hasAttribute("data-rte-rownum")) return false;
478
+ var table = cell.closest("table");
479
+ if (!table || !table.rows.length) return false;
480
+ var from = cell.cellIndex, n = table.rows[0].cells.length;
481
+ if (dir < 0 ? from - 1 < firstMovableColumn(table) : from + 1 >= n) return false;
482
+ return moveColumnTo(table, from, dir < 0 ? from - 1 : from + 2, cell);
483
+ }
484
+ // a body row moves one place within its section; header rows stay put, as for the grip and Alt+Arrow
485
+ function moveRowBy(dir) {
486
+ var cell = cellAtCaret();
487
+ if (!cell) return false;
488
+ var row = cell.parentNode, table = cell.closest("table");
489
+ var rows = bodyRows(table).filter(function (r) { return r.parentNode === row.parentNode; });
490
+ var i = rows.indexOf(row), j = i + (dir < 0 ? -1 : 1);
491
+ if (i < 0 || j < 0 || j >= rows.length) return false;
492
+ if (moveRefused()) return false;
493
+ for (var r = 0; r < rows.length; r++) for (var c = 0; c < rows[r].cells.length; c++) {
494
+ if ((rows[r].cells[c].rowSpan || 1) > 1 || (rows[r].cells[c].colSpan || 1) > 1) { say("This table has merged cells, so the row was not moved."); return false; }
495
+ }
496
+ if (typeof editor.recordUndo === "function") editor.recordUndo();
497
+ row.parentNode.insertBefore(row, dir < 0 ? rows[j] : rows[j].nextSibling);
498
+ renumber(table);
499
+ try { restoreCaret(cell); if (typeof editor.focus === "function") editor.focus(); } catch (e) { /* ignore */ }
500
+ fireChange();
501
+ return true;
502
+ }
503
+
504
+ function initColumnDrag() {
505
+ var frame = editor.iframe;
506
+ if (!frame || !frame.ownerDocument) return;
507
+ var host = frame.ownerDocument;
508
+ var edoc = editor.getDocument();
509
+ var grip = host.createElement("div");
510
+ grip.className = "rte-col-grip";
511
+ grip.setAttribute("aria-hidden", "true");
512
+ grip.textContent = "\u283f";
513
+ var gs = grip.style;
514
+ gs.position = "fixed"; gs.display = "none"; gs.zIndex = "99998"; gs.width = "22px"; gs.height = "12px";
515
+ gs.lineHeight = "12px"; gs.textAlign = "center"; gs.fontSize = "12px"; gs.color = "#64748b"; gs.cursor = "grab";
516
+ gs.userSelect = "none"; gs.borderRadius = "3px"; gs.background = "rgba(15,23,42,.06)"; gs.overflow = "hidden";
517
+ var line = host.createElement("div");
518
+ line.className = "rte-col-drop";
519
+ var ls = line.style;
520
+ ls.position = "fixed"; ls.display = "none"; ls.zIndex = "99998"; ls.width = "2px";
521
+ ls.background = "#2563eb"; ls.pointerEvents = "none";
522
+ host.body.appendChild(grip);
523
+ host.body.appendChild(line);
524
+
525
+ var hoverCell = null, hideTid = 0, drag = null;
526
+ function frameRect() { return frame.getBoundingClientRect(); }
527
+ function inEditable(node) { try { return !!editor.getEditable() && editor.getEditable().contains(node); } catch (e) { return false; } }
528
+ function cellAt(node) {
529
+ var el = node && node.nodeType === 1 ? node : (node && node.parentNode);
530
+ while (el && el.nodeName !== "TD" && el.nodeName !== "TH") el = el.parentNode;
531
+ if (!el || !inEditable(el) || el.hasAttribute("data-rte-rownum")) return null;
532
+ return el.closest && el.closest("table") ? el : null;
533
+ }
534
+ function placeGrip(cell) {
535
+ var fr = frameRect(), cr = cell.getBoundingClientRect(), tb = cell.closest("table").getBoundingClientRect();
536
+ var top = fr.top + tb.top - 14;
537
+ // no room above the table: no grip, so it never covers the first row
538
+ if (top < fr.top) { gs.display = "none"; return; }
539
+ gs.left = Math.round(fr.left + cr.left + cr.width / 2 - 11) + "px";
540
+ gs.top = Math.round(top) + "px";
541
+ gs.display = "block";
542
+ }
543
+ function hideGripSoon() {
544
+ clearTimeout(hideTid);
545
+ hideTid = setTimeout(function () { if (!drag) { gs.display = "none"; hoverCell = null; } }, 350);
546
+ }
547
+ function hostX(e) { return e.view === frame.contentWindow ? frameRect().left + e.clientX : e.clientX; }
548
+
549
+ edoc.addEventListener("mousemove", function (e) {
550
+ if (drag) return;
551
+ var cell = cellAt(e.target);
552
+ if (cell) { clearTimeout(hideTid); hoverCell = cell; placeGrip(cell); } else { hideGripSoon(); }
553
+ });
554
+ grip.addEventListener("mouseenter", function () { clearTimeout(hideTid); });
555
+ grip.addEventListener("mouseleave", hideGripSoon);
556
+
557
+ function endDrag() {
558
+ drag = null;
559
+ host.removeEventListener("mousemove", onDragMove, true);
560
+ edoc.removeEventListener("mousemove", onDragMove, true);
561
+ host.removeEventListener("mouseup", onDragEnd, true);
562
+ edoc.removeEventListener("mouseup", onDragEnd, true);
563
+ host.removeEventListener("keydown", onDragKey, true);
564
+ edoc.removeEventListener("keydown", onDragKey, true);
565
+ ls.display = "none"; gs.display = "none"; gs.cursor = "grab";
566
+ }
567
+ function onDragMove(e) {
568
+ if (!drag) return;
569
+ var x = hostX(e), fr = frameRect(), cells = drag.table.rows[0].cells, n = cells.length, drop = n;
570
+ for (var i = drag.min; i < n; i++) {
571
+ var cr = cells[i].getBoundingClientRect();
572
+ if (x < fr.left + cr.left + cr.width / 2) { drop = i; break; }
573
+ }
574
+ drag.drop = drop;
575
+ // dropping the column where it already is, or just after itself, changes nothing
576
+ drag.noop = drop === drag.from || drop === drag.from + 1;
577
+ var at = drop < n ? fr.left + cells[drop].getBoundingClientRect().left : fr.left + cells[n - 1].getBoundingClientRect().right;
578
+ var tb = drag.table.getBoundingClientRect();
579
+ ls.left = Math.round(at - 1) + "px";
580
+ ls.top = Math.round(fr.top + tb.top) + "px";
581
+ ls.height = Math.round(tb.height) + "px";
582
+ ls.display = drag.noop ? "none" : "block";
583
+ }
584
+ function moveColumn(d) { return moveColumnTo(d.table, d.from, d.drop); }
585
+ function onDragEnd() {
586
+ if (!drag) return;
587
+ var d = drag;
588
+ endDrag();
589
+ if (d.drop < 0 || d.noop) return;
590
+ moveColumn(d);
591
+ }
592
+ function onDragKey(e) { if (e.key === "Escape") endDrag(); }
593
+ grip.addEventListener("mousedown", function (e) {
594
+ if (!hoverCell || e.button !== 0) return;
595
+ e.preventDefault();
596
+ var table = hoverCell.closest("table");
597
+ if (!table.rows.length) return;
598
+ drag = { table: table, from: hoverCell.cellIndex, min: firstMovableColumn(table), drop: -1, noop: true };
599
+ gs.cursor = "grabbing";
600
+ host.addEventListener("mousemove", onDragMove, true);
601
+ edoc.addEventListener("mousemove", onDragMove, true);
602
+ host.addEventListener("mouseup", onDragEnd, true);
603
+ edoc.addEventListener("mouseup", onDragEnd, true);
604
+ host.addEventListener("keydown", onDragKey, true);
605
+ edoc.addEventListener("keydown", onDragKey, true);
606
+ });
607
+ }
608
+
233
609
  // ---- row numbering ----------------------------------------------------
234
610
 
235
611
  function seriesLabel(n, series) {
@@ -259,7 +635,13 @@ function RTE_Plugin_TableTools() {
259
635
  obj.AddRowNumbers = function (opts) {
260
636
  var table = tableAtCaret();
261
637
  if (!table) return false;
262
- if (table.querySelector("[data-rte-rownum]")) { renumber(table); return true; }
638
+ if (editor.commitBookmark) editor.commitBookmark();
639
+ if (table.querySelector("[data-rte-rownum]")) {
640
+ renumber(table);
641
+ fireChange();
642
+ if (editor.recordUndo) editor.recordUndo();
643
+ return true;
644
+ }
263
645
  opts = opts || {};
264
646
  var series = opts.series || config.tableNumberSeries;
265
647
  var doc = table.ownerDocument;
@@ -281,6 +663,7 @@ function RTE_Plugin_TableTools() {
281
663
  table.setAttribute("data-rte-rownum-series", series);
282
664
  renumber(table);
283
665
  fireChange();
666
+ if (editor.recordUndo) editor.recordUndo();
284
667
  return true;
285
668
  };
286
669
 
@@ -296,9 +679,11 @@ function RTE_Plugin_TableTools() {
296
679
  if (!table) return false;
297
680
  var cells = table.querySelectorAll("[data-rte-rownum]");
298
681
  if (!cells.length) return false;
682
+ if (editor.commitBookmark) editor.commitBookmark();
299
683
  for (var i = 0; i < cells.length; i++) if (cells[i].parentNode) cells[i].parentNode.removeChild(cells[i]);
300
684
  table.removeAttribute("data-rte-rownum-series");
301
685
  fireChange();
686
+ if (editor.recordUndo) editor.recordUndo();
302
687
  return true;
303
688
  };
304
689
 
@@ -1 +1 @@
1
- window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_tabletools=RTE_Plugin_TableTools,typeof RTE_DefaultConfig.tableNumberSeries>"u"&&(RTE_DefaultConfig.tableNumberSeries="numeric"),typeof RTE_DefaultConfig.tableNumberHeader>"u"&&(RTE_DefaultConfig.tableNumberHeader="#");function RTE_Plugin_TableTools(){var o=this,g,u;o.PluginName="TableTools",o.InitConfig=function(r){g=r},o.InitEditor=function(r){u=r,u.attachEvent("exec_command_sorttable",function(e){e.returnValue=!0,o.SortAtCaret(e&&e.value==="desc"?"desc":"asc")}),u.attachEvent("exec_command_tablerownumbers",function(e){e.returnValue=!0,o.ToggleRowNumbers()}),u.sortTableByColumn=function(e,t){return o.Sort(c(),e,t)},u.sortTableAtCaret=function(e){return o.SortAtCaret(e)},u.canSortTable=function(){return A(c())},u.addTableRowNumbers=function(e){return o.AddRowNumbers(e)},u.removeTableRowNumbers=function(){return o.RemoveRowNumbers()},u.hasTableRowNumbers=function(){var e=c();return!!(e&&e.querySelector("[data-rte-rownum]"))}};function R(){try{return u.getEditable()}catch{return null}}function c(){try{var r=u.getSelection();if(!r||r.rangeCount===0)return null;var e=r.getRangeAt(0).startContainer;e&&e.nodeType===3&&(e=e.parentNode);for(var t=R();e&&e!==t;){if(e.nodeName==="TABLE")return e;e=e.parentNode}return null}catch{return null}}function _(){try{var r=u.getSelection();if(!r||r.rangeCount===0)return null;var e=r.getRangeAt(0).startContainer;e&&e.nodeType===3&&(e=e.parentNode);for(var t=R();e&&e!==t;){if(e.nodeName==="TD"||e.nodeName==="TH")return e;e=e.parentNode}return null}catch{return null}}function y(r){if(!r)return[];for(var e=Array.prototype.slice.call(r.rows||[]),t=[],a=0;a<e.length;a++){var n=e[a],l=n.parentNode?n.parentNode.nodeName:"";l==="THEAD"||l==="TFOOT"||t.length===0&&a===0&&n.cells.length&&L(n)||t.push(n)}return t}function L(r){for(var e=0;e<r.cells.length;e++)if(r.cells[e].nodeName!=="TH")return!1;return!0}function A(r){if(!r)return{ok:!1,reason:"The caret is not inside a table."};var e=y(r);if(e.length<2)return{ok:!1,reason:"The table has fewer than two sortable rows."};for(var t=0;t<e.length;t++)for(var a=0;a<e[t].cells.length;a++){var n=e[t].cells[a];if((n.rowSpan||1)>1||(n.colSpan||1)>1)return{ok:!1,reason:"This table has merged cells. Sorting would move rows out from under a rowspan and break the table, so it has been left alone."}}return{ok:!0,reason:""}}function E(r){var e=String(r??"").trim();if(!e)return{type:"empty",v:""};if(/\d/.test(e)){var t=e.replace(/[\s ,]/g,"").replace(/^\(([^)]*)\)$/,"-$1").replace(/[^0-9.eE+-]/g,"");if(t&&/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(t))return{type:"number",v:parseFloat(t)};var a=Date.parse(e);if(!isNaN(a))return{type:"date",v:a}}return{type:"text",v:e.toLowerCase()}}function V(r,e){for(var t={number:0,date:0,text:0},a=0;a<r.length;a++){var n=r[a].cells[e];if(n){var l=E(n.textContent);l.type!=="empty"&&t[l.type]++}}return t.number>=t.date&&t.number>=t.text&&t.number>0?"number":t.date>=t.text&&t.date>0?"date":"text"}o.SortAtCaret=function(r){var e=c(),t=_();return!e||!t?!1:o.Sort(e,t.cellIndex,r)},o.Sort=function(r,e,t){var a=A(r);if(!a.ok)return a;for(var n=String(t).toLowerCase()==="desc",l=y(r),s=V(l,e),i=[],f=0;f<l.length;f++){var m=l[f].cells[e];i.push({row:l[f],order:f,val:E(m?m.textContent:"")})}i.sort(function(v,d){if(v.val.type==="empty"&&d.val.type==="empty")return v.order-d.order;if(v.val.type==="empty")return 1;if(d.val.type==="empty")return-1;var h;if(s==="number"||s==="date"){var x=v.val.type===s?v.val.v:Number.POSITIVE_INFINITY,H=d.val.type===s?d.val.v:Number.POSITIVE_INFINITY;h=x<H?-1:x>H?1:0}else{var w=String(v.val.v),S=String(d.val.v);h=w.localeCompare?w.localeCompare(S,void 0,{numeric:!0,sensitivity:"base"}):w<S?-1:w>S?1:0}return h===0?v.order-d.order:n?-h:h});var p=i.length?i[0].row.parentNode:null;if(!p)return{ok:!1,reason:"The table has no sortable rows."};for(var b=_(),T=0;T<i.length;T++)p.appendChild(i[T].row);return K(b),C(r),N(),{ok:!0,reason:"",sortedBy:e,direction:n?"desc":"asc",detectedType:s}};function q(r,e){switch(String(e)){case"upper-alpha":return I(r).toUpperCase();case"lower-alpha":return I(r);case"upper-roman":return D(r);case"lower-roman":return D(r).toLowerCase();default:return String(r)}}function I(r){for(var e="";r>0;){var t=(r-1)%26;e=String.fromCharCode(97+t)+e,r=Math.floor((r-1)/26)}return e||"a"}function D(r){for(var e=[[1e3,"M"],[900,"CM"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"],[1,"I"]],t="",a=0;a<e.length;a++)for(;r>=e[a][0];)t+=e[a][1],r-=e[a][0];return t||"I"}o.AddRowNumbers=function(r){var e=c();if(!e)return!1;if(e.querySelector("[data-rte-rownum]"))return C(e),!0;r=r||{};for(var t=r.series||g.tableNumberSeries,a=e.ownerDocument,n=Array.prototype.slice.call(e.rows||[]),l=y(e),s={},i=0;i<l.length;i++)s[k(l[i])]=!0;for(var f=0;f<n.length;f++){var m=n[f],p=s[k(m)],b=a.createElement(p?"td":"th");b.setAttribute("data-rte-rownum",p?"value":"header"),p||(b.textContent=String(g.tableNumberHeader==null?"#":g.tableNumberHeader)),m.insertBefore(b,m.firstChild)}return e.setAttribute("data-rte-rownum-series",t),C(e),N(),!0};var F=0;function k(r){return r.__rteKey||(r.__rteKey="r"+F++),r.__rteKey}o.RemoveRowNumbers=function(){var r=c();if(!r)return!1;var e=r.querySelectorAll("[data-rte-rownum]");if(!e.length)return!1;for(var t=0;t<e.length;t++)e[t].parentNode&&e[t].parentNode.removeChild(e[t]);return r.removeAttribute("data-rte-rownum-series"),N(),!0},o.ToggleRowNumbers=function(){var r=c();return r?r.querySelector("[data-rte-rownum]")?o.RemoveRowNumbers():o.AddRowNumbers():!1};function C(r){if(r)for(var e=r.getAttribute("data-rte-rownum-series")||g.tableNumberSeries,t=y(r),a=1,n=0;n<t.length;n++){var l=t[n].querySelector("[data-rte-rownum='value']");l&&(l.textContent=q(a++,e))}}function K(r){if(!(!r||!r.parentNode))try{var e=r.ownerDocument,t=e.createRange();t.selectNodeContents(r),t.collapse(!0);var a=u.getSelection();a.removeAllRanges(),a.addRange(t)}catch{}}function N(){try{typeof u.updateDesign=="function"&&u.updateDesign()}catch{}try{typeof u.fireChange=="function"&&u.fireChange()}catch{}}}
1
+ window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_tabletools=RTE_Plugin_TableTools,typeof RTE_DefaultConfig.tableNumberSeries>"u"&&(RTE_DefaultConfig.tableNumberSeries="numeric"),typeof RTE_DefaultConfig.tableNumberHeader>"u"&&(RTE_DefaultConfig.tableNumberHeader="#");function RTE_Plugin_TableTools(){var b=this,T,a;b.PluginName="TableTools",b.InitConfig=function(r){T=r,z("subtoolbar_tablerow",["tablerowmoveup","tablerowmovedown"]),z("subtoolbar_tablecolumn",["tablecolumnmoveleft","tablecolumnmoveright"]);var e={tablerowmoveup:"Move Row Up",tablerowmovedown:"Move Row Down",tablecolumnmoveleft:"Move Column Left",tablecolumnmoveright:"Move Column Right"},t={tablerowmoveup:"M12 19V5M6 11l6-6 6 6",tablerowmovedown:"M12 5v14M6 13l6 6 6-6",tablecolumnmoveleft:"M19 12H5M11 6l-6 6 6 6",tablecolumnmoveright:"M5 12h14M13 6l6 6-6 6"};for(var o in e)T["text_"+o]==null&&(T["text_"+o]=e[o]),T["svgCode_"+o]==null&&(T["svgCode_"+o]='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="'+t[o]+'"/></svg>')};function z(r,e){var t=T[r];if(!(typeof t!="string"||!t)){for(var o=0;o<e.length;o++)if(t.indexOf(e[o])===-1){var n=t.lastIndexOf("}");t=n===-1?t+","+e[o]:t.substring(0,n)+","+e[o]+t.substring(n)}T[r]=t}}b.InitEditor=function(r){a=r,a.attachEvent("exec_command_sorttable",function(e){e.returnValue=!0,b.SortAtCaret(e&&e.value==="desc"?"desc":"asc")}),a.attachEvent("exec_command_tablerownumbers",function(e){e.returnValue=!0,b.ToggleRowNumbers()}),a.sortTableByColumn=function(e,t){return b.Sort(D(),e,t)},a.sortTableAtCaret=function(e){return b.SortAtCaret(e)},a.canSortTable=function(){return G(D())},a.addTableRowNumbers=function(e){return b.AddRowNumbers(e)},a.removeTableRowNumbers=function(){return b.RemoveRowNumbers()},["tablerowmoveup","tablerowmovedown","tablecolumnmoveleft","tablecolumnmoveright"].forEach(function(e){a.toolbarFactoryMap=a.toolbarFactoryMap||{},a.toolbarFactoryMap[e]||(a.toolbarFactoryMap[e]=function(t){return a.createToolbarButton(t)}),a.attachEvent("exec_command_"+e,function(t){t.returnValue=!0,t.stopBubble=!0,e==="tablerowmoveup"?X(-1):e==="tablerowmovedown"?X(1):q(e==="tablecolumnmoveleft"?-1:1)})}),a.moveTableRow=function(e){return X(e<0?-1:1)},a.moveTableColumn=function(e){return q(e<0?-1:1)},T.tableRowDrag!==!1&&re(),T.tableColumnDrag!==!1&&oe(),a.hasTableRowNumbers=function(){var e=D();return!!(e&&e.querySelector("[data-rte-rownum]"))}};function K(){try{return a.getEditable()}catch{return null}}function D(){try{var r=a.getSelection();if(!r||r.rangeCount===0)return null;var e=r.getRangeAt(0).startContainer;e&&e.nodeType===3&&(e=e.parentNode);for(var t=K();e&&e!==t;){if(e.nodeName==="TABLE")return e;e=e.parentNode}return null}catch{return null}}function O(){try{var r=a.getSelection();if(!r||r.rangeCount===0)return null;var e=r.getRangeAt(0).startContainer;e&&e.nodeType===3&&(e=e.parentNode);for(var t=K();e&&e!==t;){if(e.nodeName==="TD"||e.nodeName==="TH")return e;e=e.parentNode}return null}catch{return null}}function _(r){if(!r)return[];for(var e=Array.prototype.slice.call(r.rows||[]),t=[],o=0;o<e.length;o++){var n=e[o],c=n.parentNode?n.parentNode.nodeName:"";c==="THEAD"||c==="TFOOT"||t.length===0&&o===0&&n.cells.length&&ee(n)||t.push(n)}return t}function ee(r){for(var e=0;e<r.cells.length;e++)if(r.cells[e].nodeName!=="TH")return!1;return!0}function G(r){if(!r)return{ok:!1,reason:"The caret is not inside a table."};var e=_(r);if(e.length<2)return{ok:!1,reason:"The table has fewer than two sortable rows."};for(var t=0;t<e.length;t++)for(var o=0;o<e[t].cells.length;o++){var n=e[t].cells[o];if((n.rowSpan||1)>1||(n.colSpan||1)>1)return{ok:!1,reason:"This table has merged cells. Sorting would move rows out from under a rowspan and break the table, so it has been left alone."}}return{ok:!0,reason:""}}function P(r){var e=String(r??"").trim();if(!e)return{type:"empty",v:""};if(/\d/.test(e)){var t=e.replace(/[\s\xa0,]/g,"").replace(/^\(([^)]*)\)$/,"-$1").replace(/[^0-9.eE+-]/g,"");if(t&&/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(t))return{type:"number",v:parseFloat(t)};var o=Date.parse(e);if(!isNaN(o))return{type:"date",v:o}}return{type:"text",v:e.toLowerCase()}}function te(r,e){for(var t={number:0,date:0,text:0},o=0;o<r.length;o++){var n=r[o].cells[e];if(n){var c=P(n.textContent);c.type!=="empty"&&t[c.type]++}}return t.number>=t.date&&t.number>=t.text&&t.number>0?"number":t.date>=t.text&&t.date>0?"date":"text"}b.SortAtCaret=function(r){var e=D(),t=O();return!e||!t?!1:b.Sort(e,t.cellIndex,r)},b.Sort=function(r,e,t){var o=G(r);if(!o.ok)return o;if(a.__trackHook&&a.__trackHook("move",{direction:0})===!0)return{ok:!1,reason:"Suggesting is on, so the table was not sorted. Turn suggesting off to sort it."};for(var n=String(t).toLowerCase()==="desc",c=_(r),f=te(c,e),d=[],v=0;v<c.length;v++){var u=c[v].cells[e];d.push({row:c[v],order:v,val:P(u?u.textContent:"")})}d.sort(function(E,w){if(E.val.type==="empty"&&w.val.type==="empty")return E.order-w.order;if(E.val.type==="empty")return 1;if(w.val.type==="empty")return-1;var N;if(f==="number"||f==="date"){var S=E.val.type===f?E.val.v:Number.POSITIVE_INFINITY,k=w.val.type===f?w.val.v:Number.POSITIVE_INFINITY;N=S<k?-1:S>k?1:0}else{var L=String(E.val.v),x=String(w.val.v);N=L.localeCompare?L.localeCompare(x,void 0,{numeric:!0,sensitivity:"base"}):L<x?-1:L>x?1:0}return N===0?E.order-w.order:n?-N:N});var h=d.length?d[0].row.parentNode:null;if(!h)return{ok:!1,reason:"The table has no sortable rows."};for(var C=O(),R=0;R<d.length;R++)h.appendChild(d[R].row);return U(C),I(r),M(),{ok:!0,reason:"",sortedBy:e,direction:n?"desc":"asc",detectedType:f}};function re(){var r=a.iframe;if(!r||!r.ownerDocument)return;var e=r.ownerDocument,t=a.getDocument(),o=e.createElement("div");o.className="rte-row-grip",o.setAttribute("aria-hidden","true"),o.textContent="\u283F";var n=o.style;n.position="fixed",n.display="none",n.zIndex="99998",n.width="12px",n.height="22px",n.lineHeight="22px",n.textAlign="center",n.fontSize="14px",n.color="#64748b",n.cursor="grab",n.userSelect="none",n.borderRadius="3px",n.background="rgba(15,23,42,.06)";var c=e.createElement("div");c.className="rte-row-drop";var f=c.style;f.position="fixed",f.display="none",f.zIndex="99998",f.height="2px",f.background="#2563eb",f.pointerEvents="none",e.body.appendChild(o),e.body.appendChild(c);var d=null,v=0,u=null;function h(){return r.getBoundingClientRect()}function C(l){try{return!!a.getEditable()&&a.getEditable().contains(l)}catch{return!1}}function R(l){for(var i=l&&l.nodeType===1?l:l&&l.parentNode;i&&i.nodeName!=="TR";)i=i.parentNode;if(!i||!C(i))return null;var p=i.parentNode&&i.parentNode.nodeName;if(p==="THEAD"||p==="TFOOT")return null;var g=i.closest?i.closest("table"):null;return!g||_(g).indexOf(i)<0?null:i}function E(l){var i=h(),p=l.getBoundingClientRect(),g=l.closest("table"),y=g.getBoundingClientRect().left-14;if(y<i.left){n.display="none";return}n.left=Math.round(y)+"px",n.top=Math.round(i.top+p.top+p.height/2-11)+"px",n.display="block"}function w(){clearTimeout(v),v=setTimeout(function(){u||(n.display="none",d=null)},350)}function N(l){return l.view===r.contentWindow?h().top+l.clientY:l.clientY}function S(l){for(var i=_(l),p=0;p<i.length;p++)for(var g=0;g<i[p].cells.length;g++){var y=i[p].cells[g];if((y.rowSpan||1)>1||(y.colSpan||1)>1)return!0}return!1}function k(l){try{typeof a.announce=="function"&&a.announce(l)}catch{}}t.addEventListener("mousemove",function(l){if(!u){var i=R(l.target);i?(clearTimeout(v),d=i,E(i)):w()}}),o.addEventListener("mouseenter",function(){clearTimeout(v)}),o.addEventListener("mouseleave",w);function L(){u=null,e.removeEventListener("mousemove",x,!0),t.removeEventListener("mousemove",x,!0),e.removeEventListener("mouseup",s,!0),t.removeEventListener("mouseup",s,!0),e.removeEventListener("keydown",m,!0),t.removeEventListener("keydown",m,!0),f.display="none",n.display="none",n.cursor="grab"}function x(l){if(u){for(var i=N(l),p=h(),g=u.rows,y=g.length,A=0;A<g.length;A++){var F=g[A].getBoundingClientRect();if(i<p.top+F.top+F.height/2){y=A;break}}u.drop=y;var H=y===u.from||y===u.from+1;u.noop=H;var ue=y<g.length?p.top+g[y].getBoundingClientRect().top:p.top+g[g.length-1].getBoundingClientRect().bottom,Z=u.table.getBoundingClientRect();f.left=Math.round(p.left+Z.left)+"px",f.width=Math.round(Z.width)+"px",f.top=Math.round(ue-1)+"px",f.display=H?"none":"block"}}function B(l){try{if(String(a.getDocument().designMode).toLowerCase()==="off"||a.getCommentsOnly&&a.getCommentsOnly())return!1}catch{}if(S(l.table))return k("This table has merged cells, so the row was not moved."),!1;if(a.__trackHook&&a.__trackHook("move",{direction:0})===!0)return!1;var i=l.drop<l.rows.length?l.rows[l.drop]:null;typeof a.recordUndo=="function"&&a.recordUndo(),l.row.parentNode.insertBefore(l.row,i),I(l.table);try{U(l.row.cells[0]),typeof a.focus=="function"&&a.focus()}catch{}return M(),!0}function s(l){if(u){var i=u;L(),!(i.drop<0||i.noop)&&B(i)}}function m(l){l.key==="Escape"&&L()}o.addEventListener("mousedown",function(l){if(!(!d||l.button!==0)){l.preventDefault();var i=d.closest("table"),p=_(i).filter(function(g){return g.parentNode===d.parentNode});u={row:d,table:i,rows:p,from:p.indexOf(d),drop:-1,noop:!0},n.cursor="grabbing",e.addEventListener("mousemove",x,!0),t.addEventListener("mousemove",x,!0),e.addEventListener("mouseup",s,!0),t.addEventListener("mouseup",s,!0),e.addEventListener("keydown",m,!0),t.addEventListener("keydown",m,!0)}})}function Y(r){try{typeof a.announce=="function"&&a.announce(r)}catch{}}function $(){try{if(String(a.getDocument().designMode).toLowerCase()==="off"||a.getCommentsOnly&&a.getCommentsOnly())return!0}catch{}return!!(a.__trackHook&&a.__trackHook("move",{direction:0})===!0)}function ne(r){for(var e=r.rows,t=e.length?e[0].cells.length:0,o=0;o<e.length;o++){if(e[o].cells.length!==t)return!1;for(var n=0;n<t;n++)if((e[o].cells[n].rowSpan||1)>1||(e[o].cells[n].colSpan||1)>1)return!1}return t>1}function V(r){return r.querySelector("[data-rte-rownum]")?1:0}function W(r,e,t,o){if($())return!1;if(!ne(r))return Y("This table has merged cells, so the column was not moved."),!1;var n=r.rows,c=n[0].cells.length;if(e<0||e>=c||t<0||t>c||t===e||t===e+1)return!1;typeof a.recordUndo=="function"&&a.recordUndo();for(var f=0;f<n.length;f++){var d=n[f].cells;n[f].insertBefore(d[e],t<c?d[t]:null)}for(var v=[],u=0;u<r.children.length;u++){var h=r.children[u];if(h.nodeName==="COLGROUP")for(var C=0;C<h.children.length;C++)h.children[C].nodeName==="COL"&&v.push(h.children[C])}for(var R=c-v.length,E=!1,w=0;w<v.length;w++)(parseInt(v[w].getAttribute("span"),10)||1)>1&&(E=!0);if(v.length&&!E&&(R===0||R===V(r))&&e>=R){var N=v[e-R],S=t<c?v[t-R]:null;N&&N!==S&&(S?S.parentNode:N.parentNode).insertBefore(N,S)}var k=t>e?t-1:t;try{U(o||n[n.length>1?1:0].cells[k]),typeof a.focus=="function"&&a.focus()}catch{}return M(),!0}function q(r){var e=O();if(!e||e.hasAttribute("data-rte-rownum"))return!1;var t=e.closest("table");if(!t||!t.rows.length)return!1;var o=e.cellIndex,n=t.rows[0].cells.length;return(r<0?o-1<V(t):o+1>=n)?!1:W(t,o,r<0?o-1:o+2,e)}function X(r){var e=O();if(!e)return!1;var t=e.parentNode,o=e.closest("table"),n=_(o).filter(function(u){return u.parentNode===t.parentNode}),c=n.indexOf(t),f=c+(r<0?-1:1);if(c<0||f<0||f>=n.length||$())return!1;for(var d=0;d<n.length;d++)for(var v=0;v<n[d].cells.length;v++)if((n[d].cells[v].rowSpan||1)>1||(n[d].cells[v].colSpan||1)>1)return Y("This table has merged cells, so the row was not moved."),!1;typeof a.recordUndo=="function"&&a.recordUndo(),t.parentNode.insertBefore(t,r<0?n[f]:n[f].nextSibling),I(o);try{U(e),typeof a.focus=="function"&&a.focus()}catch{}return M(),!0}function oe(){var r=a.iframe;if(!r||!r.ownerDocument)return;var e=r.ownerDocument,t=a.getDocument(),o=e.createElement("div");o.className="rte-col-grip",o.setAttribute("aria-hidden","true"),o.textContent="\u283F";var n=o.style;n.position="fixed",n.display="none",n.zIndex="99998",n.width="22px",n.height="12px",n.lineHeight="12px",n.textAlign="center",n.fontSize="12px",n.color="#64748b",n.cursor="grab",n.userSelect="none",n.borderRadius="3px",n.background="rgba(15,23,42,.06)",n.overflow="hidden";var c=e.createElement("div");c.className="rte-col-drop";var f=c.style;f.position="fixed",f.display="none",f.zIndex="99998",f.width="2px",f.background="#2563eb",f.pointerEvents="none",e.body.appendChild(o),e.body.appendChild(c);var d=null,v=0,u=null;function h(){return r.getBoundingClientRect()}function C(s){try{return!!a.getEditable()&&a.getEditable().contains(s)}catch{return!1}}function R(s){for(var m=s&&s.nodeType===1?s:s&&s.parentNode;m&&m.nodeName!=="TD"&&m.nodeName!=="TH";)m=m.parentNode;return!m||!C(m)||m.hasAttribute("data-rte-rownum")?null:m.closest&&m.closest("table")?m:null}function E(s){var m=h(),l=s.getBoundingClientRect(),i=s.closest("table").getBoundingClientRect(),p=m.top+i.top-14;if(p<m.top){n.display="none";return}n.left=Math.round(m.left+l.left+l.width/2-11)+"px",n.top=Math.round(p)+"px",n.display="block"}function w(){clearTimeout(v),v=setTimeout(function(){u||(n.display="none",d=null)},350)}function N(s){return s.view===r.contentWindow?h().left+s.clientX:s.clientX}t.addEventListener("mousemove",function(s){if(!u){var m=R(s.target);m?(clearTimeout(v),d=m,E(m)):w()}}),o.addEventListener("mouseenter",function(){clearTimeout(v)}),o.addEventListener("mouseleave",w);function S(){u=null,e.removeEventListener("mousemove",k,!0),t.removeEventListener("mousemove",k,!0),e.removeEventListener("mouseup",x,!0),t.removeEventListener("mouseup",x,!0),e.removeEventListener("keydown",B,!0),t.removeEventListener("keydown",B,!0),f.display="none",n.display="none",n.cursor="grab"}function k(s){if(u){for(var m=N(s),l=h(),i=u.table.rows[0].cells,p=i.length,g=p,y=u.min;y<p;y++){var A=i[y].getBoundingClientRect();if(m<l.left+A.left+A.width/2){g=y;break}}u.drop=g,u.noop=g===u.from||g===u.from+1;var F=g<p?l.left+i[g].getBoundingClientRect().left:l.left+i[p-1].getBoundingClientRect().right,H=u.table.getBoundingClientRect();f.left=Math.round(F-1)+"px",f.top=Math.round(l.top+H.top)+"px",f.height=Math.round(H.height)+"px",f.display=u.noop?"none":"block"}}function L(s){return W(s.table,s.from,s.drop)}function x(){if(u){var s=u;S(),!(s.drop<0||s.noop)&&L(s)}}function B(s){s.key==="Escape"&&S()}o.addEventListener("mousedown",function(s){if(!(!d||s.button!==0)){s.preventDefault();var m=d.closest("table");m.rows.length&&(u={table:m,from:d.cellIndex,min:V(m),drop:-1,noop:!0},n.cursor="grabbing",e.addEventListener("mousemove",k,!0),t.addEventListener("mousemove",k,!0),e.addEventListener("mouseup",x,!0),t.addEventListener("mouseup",x,!0),e.addEventListener("keydown",B,!0),t.addEventListener("keydown",B,!0))}})}function ae(r,e){switch(String(e)){case"upper-alpha":return j(r).toUpperCase();case"lower-alpha":return j(r);case"upper-roman":return J(r);case"lower-roman":return J(r).toLowerCase();default:return String(r)}}function j(r){for(var e="";r>0;){var t=(r-1)%26;e=String.fromCharCode(97+t)+e,r=Math.floor((r-1)/26)}return e||"a"}function J(r){for(var e=[[1e3,"M"],[900,"CM"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"],[1,"I"]],t="",o=0;o<e.length;o++)for(;r>=e[o][0];)t+=e[o][1],r-=e[o][0];return t||"I"}b.AddRowNumbers=function(r){var e=D();if(!e)return!1;if(a.commitBookmark&&a.commitBookmark(),e.querySelector("[data-rte-rownum]"))return I(e),M(),a.recordUndo&&a.recordUndo(),!0;r=r||{};for(var t=r.series||T.tableNumberSeries,o=e.ownerDocument,n=Array.prototype.slice.call(e.rows||[]),c=_(e),f={},d=0;d<c.length;d++)f[Q(c[d])]=!0;for(var v=0;v<n.length;v++){var u=n[v],h=f[Q(u)],C=o.createElement(h?"td":"th");C.setAttribute("data-rte-rownum",h?"value":"header"),h||(C.textContent=String(T.tableNumberHeader==null?"#":T.tableNumberHeader)),u.insertBefore(C,u.firstChild)}return e.setAttribute("data-rte-rownum-series",t),I(e),M(),a.recordUndo&&a.recordUndo(),!0};var le=0;function Q(r){return r.__rteKey||(r.__rteKey="r"+le++),r.__rteKey}b.RemoveRowNumbers=function(){var r=D();if(!r)return!1;var e=r.querySelectorAll("[data-rte-rownum]");if(!e.length)return!1;a.commitBookmark&&a.commitBookmark();for(var t=0;t<e.length;t++)e[t].parentNode&&e[t].parentNode.removeChild(e[t]);return r.removeAttribute("data-rte-rownum-series"),M(),a.recordUndo&&a.recordUndo(),!0},b.ToggleRowNumbers=function(){var r=D();return r?r.querySelector("[data-rte-rownum]")?b.RemoveRowNumbers():b.AddRowNumbers():!1};function I(r){if(r)for(var e=r.getAttribute("data-rte-rownum-series")||T.tableNumberSeries,t=_(r),o=1,n=0;n<t.length;n++){var c=t[n].querySelector("[data-rte-rownum='value']");c&&(c.textContent=ae(o++,e))}}function U(r){if(!(!r||!r.parentNode))try{var e=r.ownerDocument,t=e.createRange();t.selectNodeContents(r),t.collapse(!0);var o=a.getSelection();o.removeAllRanges(),o.addRange(t)}catch{}}function M(){try{typeof a.updateDesign=="function"&&a.updateDesign()}catch{}try{typeof a.fireChange=="function"&&a.fireChange()}catch{}}}
@@ -43,15 +43,23 @@ function RTE_Plugin_TextDirection() {
43
43
 
44
44
  // Strongly right-to-left ranges: Hebrew, Arabic (+ supplement, extended),
45
45
  // Syriac, Thaana, NKo, Samaritan, Mandaic, and the Arabic presentation forms.
46
- var RTL_RE = /[֐-׿؀-ۿ܀-ݏݐ-ݿހ-޿߀-߿ࠀ-࠿ࡀ-࡟ࢠ-ࣿיִ-﷿ﹰ-]/;
46
+ var RTL_RE = /[\u0590-\u05ff\u0600-\u06ff\u0700-\u074f\u0750-\u077f\u0780-\u07bf\u07c0-\u07ff\u0800-\u083f\u0840-\u085f\u08a0-\u08ff\ufb1d-\ufdff\ufe70-\ufeff]/;
47
47
  // Strongly left-to-right: Latin, Greek, Cyrillic, Armenian, and CJK/Kana
48
48
  // (which are LTR for bidi purposes).
49
- var LTR_RE = /[A-Za-zÀ-ʯͰ-֏ऀ-႟Ḁ-῿Ⰰ-ⷿ⺀-꓏가-힯]/;
49
+ var LTR_RE = /[A-Za-z\xc0-\u02af\u0370-\u058f\u0900-\u109f\u1e00-\u1fff\u2c00-\u2dff\u2e80-\ua4cf\uac00-\ud7af]/;
50
50
 
51
51
  obj.PluginName = "TextDirection";
52
52
 
53
53
  obj.InitConfig = function (argconfig) { config = argconfig; };
54
54
 
55
+ // record the change as its own undo step: seal the step before, run, save the snapshot, seal it
56
+ function undoStep(run) {
57
+ try { if (editor.commitBookmark) editor.commitBookmark(); } catch (er) { /* ignore */ }
58
+ var result = run();
59
+ try { if (editor.recordUndo) editor.recordUndo(); else if (editor.notifySelectionChange) editor.notifySelectionChange(); if (editor.commitBookmark) editor.commitBookmark(); } catch (er) { /* ignore */ }
60
+ return result;
61
+ }
62
+
55
63
  obj.InitEditor = function (argeditor) {
56
64
  editor = argeditor;
57
65
 
@@ -68,10 +76,12 @@ function RTE_Plugin_TextDirection() {
68
76
  setTimeout(function () { setup(); afterLoad(); }, 0);
69
77
 
70
78
  // Public API.
71
- editor.setTextDirection = function (dir) { return obj.Apply(dir); };
72
- editor.toggleTextDirection = function () { return obj.Toggle(); };
79
+ // 2026-10-04 one undo step when called directly (execCommand does this for the button; a direct
80
+ // call could not be undone). tools/api/plugin-api-undo.mjs
81
+ editor.setTextDirection = function (dir) { return undoStep(function () { return obj.Apply(dir); }); };
82
+ editor.toggleTextDirection = function () { return undoStep(function () { return obj.Toggle(); }); };
73
83
  editor.getTextDirection = function () { return obj.Current(); };
74
- editor.setBaseDirection = function (dir) { return obj.Base(dir); };
84
+ editor.setBaseDirection = function (dir) { return undoStep(function () { return obj.Base(dir); }); };
75
85
  editor.getBaseDirection = function () {
76
86
  var ed = getEditable();
77
87
  return ed ? (ed.getAttribute("dir") || "ltr") : "ltr";
@@ -183,6 +193,9 @@ function RTE_Plugin_TextDirection() {
183
193
  dir = (dir === "rtl") ? "rtl" : (dir === "auto" ? "auto" : "ltr");
184
194
  var blocks = blocksInSelection();
185
195
  if (!blocks.length) return false;
196
+ // 2026-10-14 Suggesting mode: a direction change is not tracked yet, so the track hook refuses it.
197
+ // tools/review/suggesting-structure-audit.mjs
198
+ if (editor.__trackHook && editor.__trackHook("refuse", { message: "Suggesting is on, so the direction was not changed. Turn suggesting off to change it." }) === true) return false;
186
199
  for (var i = 0; i < blocks.length; i++) {
187
200
  var b = blocks[i];
188
201
  var was = b.getAttribute("dir") || "ltr";
@@ -1 +1 @@
1
- window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_textdirection=RTE_Plugin_TextDirection,typeof RTE_DefaultConfig.defaultTextDirection>"u"&&(RTE_DefaultConfig.defaultTextDirection=null),typeof RTE_DefaultConfig.textDirectionAutoDetect>"u"&&(RTE_DefaultConfig.textDirectionAutoDetect=!1),typeof RTE_DefaultConfig.textDirectionSwapAlign>"u"&&(RTE_DefaultConfig.textDirectionSwapAlign=!0);function RTE_Plugin_TextDirection(){var u=this,l,i,D=null,d={P:1,DIV:1,LI:1,H1:1,H2:1,H3:1,H4:1,H5:1,H6:1,BLOCKQUOTE:1,TD:1,TH:1,PRE:1,UL:1,OL:1,TABLE:1,SECTION:1,ARTICLE:1},m=/[֐-׿؀-ۿ܀-ݏݐ-ݿހ-޿߀-߿ࠀ-࠿ࡀ-࡟ࢠ-ࣿיִ-﷿ﹰ-]/,S=/[A-Za-zÀ-ʯͰ-֏ऀ-႟Ḁ-῿Ⰰ-ⷿ⺀-꓏가-힯]/;u.PluginName="TextDirection",u.InitConfig=function(t){l=t},u.InitEditor=function(t){i=t,i.attachEvent("exec_command_textdirection",function(e){e.returnValue=!0;var r=e&&e.value;r==="rtl"||r==="ltr"?u.Apply(r):u.Toggle()}),s();try{i.attachEvent("ready",s)}catch{}try{i.attachEvent("aftersethtml",function(){s(),y()})}catch{}setTimeout(function(){s(),y()},0),i.setTextDirection=function(e){return u.Apply(e)},i.toggleTextDirection=function(){return u.Toggle()},i.getTextDirection=function(){return u.Current()},i.setBaseDirection=function(e){return u.Base(e)},i.getBaseDirection=function(){var e=f();return e&&e.getAttribute("dir")||"ltr"},i.detectTextDirection=function(e){return A(String(e??""))},i.autoDetectTextDirection=function(){return u.AutoDetect()},i.isolateBidi=function(e,r){return u.Isolate(e,r)},i.insertIsolated=function(e,r){return u.InsertIsolated(e,r)},i.getTextDirectionCss=function(){return E()}};function s(){var t=h();!t||t===D||(D=t,_(t))}function y(){var t=f();t&&((l.defaultTextDirection==="rtl"||l.defaultTextDirection==="ltr")&&(t.getAttribute("dir")||u.Base(l.defaultTextDirection)),l.textDirectionAutoDetect&&u.AutoDetect())}function h(){try{return i.getDocument()}catch{return null}}function f(){try{return i.getEditable()}catch{return null}}function A(t){for(var e=0;e<t.length;e++){var r=t.charAt(e);if(m.test(r))return"rtl";if(S.test(r))return"ltr"}return"neutral"}function T(){var t=f(),e=[];try{var r=i.getSelection();if(!r||r.rangeCount===0)return e;var n=r.getRangeAt(0),a=x(n.startContainer),o=x(n.endContainer);if(!a)return e;if(a===o||n.collapsed)return[a];for(var v=t.querySelectorAll("*"),b=!1,p=0;p<v.length;p++){var g=v[p];if(d[g.nodeName]&&(g===a&&(b=!0),b&&!C(g)&&e.push(g),g===o))break}e.length||e.push(a)}catch{}return e}function C(t){for(var e=0;e<t.children.length;e++)if(d[t.children[e].nodeName])return!0;return!1}function x(t){for(var e=f(),r=t&&t.nodeType===3?t.parentNode:t;r&&r!==e;){if(r.nodeType===1&&d[r.nodeName])return r;r=r.parentNode}return e&&e.firstElementChild?e.firstElementChild:null}u.Current=function(){var t=T()[0];if(!t)return i.getBaseDirection?i.getBaseDirection():"ltr";var e=t.getAttribute("dir");if(e)return e;try{var r=h(),n=r&&(r.defaultView||r.parentWindow);if(n)return n.getComputedStyle(t).direction||"ltr"}catch{}return"ltr"},u.Apply=function(t){t=t==="rtl"?"rtl":t==="auto"?"auto":"ltr";var e=T();if(!e.length)return!1;for(var r=0;r<e.length;r++){var n=e[r],a=n.getAttribute("dir")||"ltr";n.setAttribute("dir",t),l.textDirectionSwapAlign!==!1&&t!=="auto"&&a!==t&&R(n,t)}return c(),t},u.Toggle=function(){return u.Apply(u.Current()==="rtl"?"ltr":"rtl")};function R(t,e){var r=t.style&&t.style.textAlign||t.getAttribute("align")||"";if(r){var n=null;if(r==="left"?n="right":r==="right"&&(n="left"),!!n){var a=e==="rtl"?"right":"left";t.style&&(t.style.textAlign=n===a?"":n),t.getAttribute("align")&&t.removeAttribute("align")}}}u.Base=function(t){var e=f();return e?(t=t==="rtl"?"rtl":t==="auto"?"auto":"ltr",e.setAttribute("dir",t),c(),t):!1},u.AutoDetect=function(){var t=f();if(!t)return[];for(var e=[],r=t.querySelectorAll("*"),n=0;n<r.length;n++){var a=r[n];if(!(!d[a.nodeName]||C(a))){var o=A(a.textContent||"");o!=="neutral"&&a.getAttribute("dir")!==o&&(a.setAttribute("dir",o),e.push({tag:a.nodeName,dir:o}))}}return e.length&&c(),e},u.Isolate=function(t,e){var r=e==="rtl"||e==="ltr"?e:"auto";return'<bdi dir="'+r+'">'+String(t??"")+"</bdi>"},u.InsertIsolated=function(t,e){var r=h();if(!r)return!1;var n=r.createElement("bdi");n.setAttribute("dir",e==="rtl"||e==="ltr"?e:"auto"),n.innerHTML=String(t??"");try{if(typeof i.insertElement=="function")return i.insertElement(n),c(),!0}catch{}try{var a=i.getSelection();if(a&&a.rangeCount){var o=a.getRangeAt(0);return o.collapse(!1),o.insertNode(n),o.setStartAfter(n),o.collapse(!0),a.removeAllRanges(),a.addRange(o),c(),!0}}catch{}return!1};function c(){try{typeof i.updateDesign=="function"&&i.updateDesign()}catch{}try{typeof i.fireChange=="function"&&i.fireChange()}catch{}}function E(){return"[dir='rtl'] ul,[dir='rtl'] ol{padding-right:1.6em;padding-left:0;}[dir='rtl'] blockquote{border-right:3px solid #ddd;border-left:0;padding-right:.9em;padding-left:0;margin-right:0;}[dir='rtl'] table{direction:rtl;}bdi{unicode-bidi:isolate;}"}function _(t){if(t){var e=t.getElementById("rte-textdirection-styles"),r=E();if(e){if(e.getAttribute("data-css")===r)return;e.parentNode&&e.parentNode.removeChild(e)}var n=t.createElement("style");n.id="rte-textdirection-styles",n.setAttribute("data-css",r),n.appendChild(t.createTextNode(r)),(t.head||t.getElementsByTagName("head")[0]||t.documentElement).appendChild(n),i&&typeof i.ensureStyleSheetLive=="function"&&i.ensureStyleSheetLive(t,n,"rte-textdirection-styles",n.textContent)}}}
1
+ window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_textdirection=RTE_Plugin_TextDirection,typeof RTE_DefaultConfig.defaultTextDirection>"u"&&(RTE_DefaultConfig.defaultTextDirection=null),typeof RTE_DefaultConfig.textDirectionAutoDetect>"u"&&(RTE_DefaultConfig.textDirectionAutoDetect=!1),typeof RTE_DefaultConfig.textDirectionSwapAlign>"u"&&(RTE_DefaultConfig.textDirectionSwapAlign=!0);function RTE_Plugin_TextDirection(){var u=this,f,n,y=null,d={P:1,DIV:1,LI:1,H1:1,H2:1,H3:1,H4:1,H5:1,H6:1,BLOCKQUOTE:1,TD:1,TH:1,PRE:1,UL:1,OL:1,TABLE:1,SECTION:1,ARTICLE:1},S=/[\u0590-\u05ff\u0600-\u06ff\u0700-\u074f\u0750-\u077f\u0780-\u07bf\u07c0-\u07ff\u0800-\u083f\u0840-\u085f\u08a0-\u08ff\ufb1d-\ufdff\ufe70-\ufeff]/,R=/[A-Za-z\xc0-\u02af\u0370-\u058f\u0900-\u109f\u1e00-\u1fff\u2c00-\u2dff\u2e80-\ua4cf\uac00-\ud7af]/;u.PluginName="TextDirection",u.InitConfig=function(t){f=t};function h(t){try{n.commitBookmark&&n.commitBookmark()}catch{}var e=t();try{n.recordUndo?n.recordUndo():n.notifySelectionChange&&n.notifySelectionChange(),n.commitBookmark&&n.commitBookmark()}catch{}return e}u.InitEditor=function(t){n=t,n.attachEvent("exec_command_textdirection",function(e){e.returnValue=!0;var r=e&&e.value;r==="rtl"||r==="ltr"?u.Apply(r):u.Toggle()}),s();try{n.attachEvent("ready",s)}catch{}try{n.attachEvent("aftersethtml",function(){s(),T()})}catch{}setTimeout(function(){s(),T()},0),n.setTextDirection=function(e){return h(function(){return u.Apply(e)})},n.toggleTextDirection=function(){return h(function(){return u.Toggle()})},n.getTextDirection=function(){return u.Current()},n.setBaseDirection=function(e){return h(function(){return u.Base(e)})},n.getBaseDirection=function(){var e=l();return e&&e.getAttribute("dir")||"ltr"},n.detectTextDirection=function(e){return m(String(e??""))},n.autoDetectTextDirection=function(){return u.AutoDetect()},n.isolateBidi=function(e,r){return u.Isolate(e,r)},n.insertIsolated=function(e,r){return u.InsertIsolated(e,r)},n.getTextDirectionCss=function(){return b()}};function s(){var t=p();!t||t===y||(y=t,k(t))}function T(){var t=l();t&&((f.defaultTextDirection==="rtl"||f.defaultTextDirection==="ltr")&&(t.getAttribute("dir")||u.Base(f.defaultTextDirection)),f.textDirectionAutoDetect&&u.AutoDetect())}function p(){try{return n.getDocument()}catch{return null}}function l(){try{return n.getEditable()}catch{return null}}function m(t){for(var e=0;e<t.length;e++){var r=t.charAt(e);if(S.test(r))return"rtl";if(R.test(r))return"ltr"}return"neutral"}function A(){var t=l(),e=[];try{var r=n.getSelection();if(!r||r.rangeCount===0)return e;var i=r.getRangeAt(0),o=x(i.startContainer),a=x(i.endContainer);if(!o)return e;if(o===a||i.collapsed)return[o];for(var v=t.querySelectorAll("*"),E=!1,D=0;D<v.length;D++){var g=v[D];if(d[g.nodeName]&&(g===o&&(E=!0),E&&!C(g)&&e.push(g),g===a))break}e.length||e.push(o)}catch{}return e}function C(t){for(var e=0;e<t.children.length;e++)if(d[t.children[e].nodeName])return!0;return!1}function x(t){for(var e=l(),r=t&&t.nodeType===3?t.parentNode:t;r&&r!==e;){if(r.nodeType===1&&d[r.nodeName])return r;r=r.parentNode}return e&&e.firstElementChild?e.firstElementChild:null}u.Current=function(){var t=A()[0];if(!t)return n.getBaseDirection?n.getBaseDirection():"ltr";var e=t.getAttribute("dir");if(e)return e;try{var r=p(),i=r&&(r.defaultView||r.parentWindow);if(i)return i.getComputedStyle(t).direction||"ltr"}catch{}return"ltr"},u.Apply=function(t){t=t==="rtl"?"rtl":t==="auto"?"auto":"ltr";var e=A();if(!e.length||n.__trackHook&&n.__trackHook("refuse",{message:"Suggesting is on, so the direction was not changed. Turn suggesting off to change it."})===!0)return!1;for(var r=0;r<e.length;r++){var i=e[r],o=i.getAttribute("dir")||"ltr";i.setAttribute("dir",t),f.textDirectionSwapAlign!==!1&&t!=="auto"&&o!==t&&_(i,t)}return c(),t},u.Toggle=function(){return u.Apply(u.Current()==="rtl"?"ltr":"rtl")};function _(t,e){var r=t.style&&t.style.textAlign||t.getAttribute("align")||"";if(r){var i=null;if(r==="left"?i="right":r==="right"&&(i="left"),!!i){var o=e==="rtl"?"right":"left";t.style&&(t.style.textAlign=i===o?"":i),t.getAttribute("align")&&t.removeAttribute("align")}}}u.Base=function(t){var e=l();return e?(t=t==="rtl"?"rtl":t==="auto"?"auto":"ltr",e.setAttribute("dir",t),c(),t):!1},u.AutoDetect=function(){var t=l();if(!t)return[];for(var e=[],r=t.querySelectorAll("*"),i=0;i<r.length;i++){var o=r[i];if(!(!d[o.nodeName]||C(o))){var a=m(o.textContent||"");a!=="neutral"&&o.getAttribute("dir")!==a&&(o.setAttribute("dir",a),e.push({tag:o.nodeName,dir:a}))}}return e.length&&c(),e},u.Isolate=function(t,e){var r=e==="rtl"||e==="ltr"?e:"auto";return'<bdi dir="'+r+'">'+String(t??"")+"</bdi>"},u.InsertIsolated=function(t,e){var r=p();if(!r)return!1;var i=r.createElement("bdi");i.setAttribute("dir",e==="rtl"||e==="ltr"?e:"auto"),i.innerHTML=String(t??"");try{if(typeof n.insertElement=="function")return n.insertElement(i),c(),!0}catch{}try{var o=n.getSelection();if(o&&o.rangeCount){var a=o.getRangeAt(0);return a.collapse(!1),a.insertNode(i),a.setStartAfter(i),a.collapse(!0),o.removeAllRanges(),o.addRange(a),c(),!0}}catch{}return!1};function c(){try{typeof n.updateDesign=="function"&&n.updateDesign()}catch{}try{typeof n.fireChange=="function"&&n.fireChange()}catch{}}function b(){return"[dir='rtl'] ul,[dir='rtl'] ol{padding-right:1.6em;padding-left:0;}[dir='rtl'] blockquote{border-right:3px solid #ddd;border-left:0;padding-right:.9em;padding-left:0;margin-right:0;}[dir='rtl'] table{direction:rtl;}bdi{unicode-bidi:isolate;}"}function k(t){if(t){var e=t.getElementById("rte-textdirection-styles"),r=b();if(e){if(e.getAttribute("data-css")===r)return;e.parentNode&&e.parentNode.removeChild(e)}var i=t.createElement("style");i.id="rte-textdirection-styles",i.setAttribute("data-css",r),i.appendChild(t.createTextNode(r)),(t.head||t.getElementsByTagName("head")[0]||t.documentElement).appendChild(i),n&&typeof n.ensureStyleSheetLive=="function"&&n.ensureStyleSheetLive(t,i,"rte-textdirection-styles",i.textContent)}}}