@richscripts/richtexteditor 2.4.0 → 2.4.1

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 (58) hide show
  1. package/migration/README.md +100 -0
  2. package/migration/cli.js +294 -0
  3. package/migration/index.d.ts +18 -0
  4. package/migration/index.js +242 -0
  5. package/migration/report-schema-v2.json +127 -0
  6. package/package.json +11 -1
  7. package/richtexteditor/CHANGELOG.md +326 -1
  8. package/richtexteditor/all_plugins.js +14959 -4832
  9. package/richtexteditor/all_plugins.min.js +62 -42
  10. package/richtexteditor/plugins/accessibilitychecker.js +8 -7
  11. package/richtexteditor/plugins/aitoolkit.css +17 -8
  12. package/richtexteditor/plugins/aitoolkit.js +8 -8
  13. package/richtexteditor/plugins/all_plugins.js +14959 -4832
  14. package/richtexteditor/plugins/all_plugins.min.js +62 -42
  15. package/richtexteditor/plugins/autocorrect.js +353 -0
  16. package/richtexteditor/plugins/bookmarkcard.js +12 -1
  17. package/richtexteditor/plugins/changecase.js +238 -0
  18. package/richtexteditor/plugins/comments.js +15 -28
  19. package/richtexteditor/plugins/contentminimap.js +6 -5
  20. package/richtexteditor/plugins/crossreference.js +408 -0
  21. package/richtexteditor/plugins/documentimport.js +915 -21
  22. package/richtexteditor/plugins/documentoutline.js +5 -4
  23. package/richtexteditor/plugins/docxexport.js +960 -0
  24. package/richtexteditor/plugins/draghandle.js +309 -0
  25. package/richtexteditor/plugins/footnotes.js +398 -0
  26. package/richtexteditor/plugins/formatpainter.js +298 -0
  27. package/richtexteditor/plugins/formattingmarks.js +246 -0
  28. package/richtexteditor/plugins/html2pdf.js +108 -4
  29. package/richtexteditor/plugins/imageeditor.js +37 -7
  30. package/richtexteditor/plugins/insertgallery.js +553 -170
  31. package/richtexteditor/plugins/keyboarda11y.js +316 -0
  32. package/richtexteditor/plugins/linenumbers.js +352 -0
  33. package/richtexteditor/plugins/linkchecker.js +396 -0
  34. package/richtexteditor/plugins/mentionplugin.js +4 -3
  35. package/richtexteditor/plugins/mergefields.js +328 -0
  36. package/richtexteditor/plugins/multilevellist.js +137 -0
  37. package/richtexteditor/plugins/pagination.js +505 -0
  38. package/richtexteditor/plugins/pdfexport.js +1137 -0
  39. package/richtexteditor/plugins/permanentpen.js +211 -0
  40. package/richtexteditor/plugins/revisionhistory.js +47 -34
  41. package/richtexteditor/plugins/rtlui.js +150 -0
  42. package/richtexteditor/plugins/sanitizer.js +486 -0
  43. package/richtexteditor/plugins/slashcommand.js +142 -17
  44. package/richtexteditor/plugins/spellcheck.js +6 -3
  45. package/richtexteditor/plugins/tableofcontents.js +353 -0
  46. package/richtexteditor/plugins/tabletools.js +342 -0
  47. package/richtexteditor/plugins/textdirection.js +313 -0
  48. package/richtexteditor/plugins/trackedchanges.js +37 -6
  49. package/richtexteditor/plugins/tui.image-editor/tui-code-snippet.min.js +1 -1
  50. package/richtexteditor/plugins/tui.image-editor/tui-color-picker.min.js +1 -1
  51. package/richtexteditor/plugins/tui.image-editor/tui-image-editor.min.js +1 -1
  52. package/richtexteditor/plugins/vendor/html2pdf.bundle.min.js +3 -0
  53. package/richtexteditor/plugins/watermark.js +214 -0
  54. package/richtexteditor/plugins/wordexport.js +0 -0
  55. package/richtexteditor/plugins/yjscollab.js +49 -11
  56. package/richtexteditor/rte-config.js +44 -44
  57. package/richtexteditor/rte.js +91 -63
  58. package/richtexteditor/rte_theme_default.css +462 -384
@@ -0,0 +1,309 @@
1
+ if (!window.RTE_DefaultConfig) window.RTE_DefaultConfig = {};
2
+
3
+ // 2026-07-28 Drag handle — grab a paragraph, heading, list, table or callout by
4
+ // the ⠿ grip that appears beside it and drop it somewhere else. The block-
5
+ // reordering interaction Notion made standard.
6
+ //
7
+ // Positioning honesty: NOT claimed as a competitor gap. Tiptap's drag-handle
8
+ // docs state no pricing, and CKEditor supports block drag and drop in its free
9
+ // core — so this ships without a compare-table row. It is here because moving a
10
+ // clause with the mouse beats cut-and-paste, not because someone charges for it.
11
+ //
12
+ // Design notes:
13
+ // - The grip and the drop indicator live OUTSIDE the editable, in its offset
14
+ // parent — the same placement pagination.js uses for its overlay. Chrome
15
+ // that is not inside the editable structurally cannot leak into
16
+ // getHTMLCode(), which beats stripping it around every serialize.
17
+ // - Dragging is plain mouse events, not HTML5 drag-and-drop. Native DnD
18
+ // inside contenteditable is exactly the browser behaviour that half-works
19
+ // everywhere: it starts a text drag, draws the wrong ghost, and drops
20
+ // serialized HTML instead of moving the node.
21
+ // - Alt+Shift+Up/Down moves the caret's block — the same keys Word uses to
22
+ // move paragraphs. This is not a bonus: a pointer-only reordering feature
23
+ // is unusable from the keyboard, so the keyboard path is what makes the
24
+ // feature accessible at all.
25
+ // - The drop target is decided by the pointer's Y against each block's
26
+ // vertical midpoint, so the indicator always sits where the block will
27
+ // actually land.
28
+ RTE_DefaultConfig.plugin_draghandle = RTE_Plugin_DragHandle;
29
+
30
+ // Show the grip on hover.
31
+ if (typeof RTE_DefaultConfig.dragHandleEnabled === "undefined") RTE_DefaultConfig.dragHandleEnabled = true;
32
+ // Alt+Shift+ArrowUp / ArrowDown keyboard reordering.
33
+ if (typeof RTE_DefaultConfig.dragHandleKeyboard === "undefined") RTE_DefaultConfig.dragHandleKeyboard = true;
34
+
35
+ function RTE_Plugin_DragHandle() {
36
+ var obj = this;
37
+ var config, editor;
38
+ var boundDoc = null;
39
+ var grip = null; // the ⠿ element, in the editable's offset parent
40
+ var indicator = null; // the drop line
41
+ var hoverBlock = null; // block the grip is currently attached to
42
+ var dragging = null; // { block } while a drag is live
43
+ var dropBefore = null; // element to insert before (null = append at end)
44
+
45
+ obj.PluginName = "DragHandle";
46
+
47
+ obj.InitConfig = function (argconfig) { config = argconfig; };
48
+
49
+ obj.InitEditor = function (argeditor) {
50
+ editor = argeditor;
51
+ setup();
52
+ try { editor.attachEvent("ready", setup); } catch (e) {}
53
+ try { editor.attachEvent("aftersethtml", setup); } catch (e) {}
54
+ setTimeout(setup, 0);
55
+
56
+ // Public API — the drag is a thin layer over these, so everything the
57
+ // pointer can do is scriptable and testable without synthetic drags.
58
+ editor.moveBlock = function (block, beforeEl) { return moveBlock(block, beforeEl); };
59
+ editor.moveBlockUp = function () { return nudge(-1); };
60
+ editor.moveBlockDown = function () { return nudge(1); };
61
+ editor.setDragHandleEnabled = function (on) {
62
+ config.dragHandleEnabled = !!on;
63
+ if (!on) hideGrip();
64
+ return !!on;
65
+ };
66
+ editor.isDragHandleEnabled = function () { return config.dragHandleEnabled !== false; };
67
+ };
68
+
69
+ function setup() {
70
+ var doc = getDoc();
71
+ if (!doc || doc === boundDoc) return;
72
+ boundDoc = doc;
73
+ injectStyles(doc);
74
+ var ed = getEditable();
75
+ if (!ed) return;
76
+
77
+ // Grip placement follows the pointer over the editable.
78
+ doc.addEventListener("mousemove", onHover);
79
+ doc.addEventListener("mousedown", onMouseDown, true);
80
+ doc.addEventListener("mousemove", onDragMove, true);
81
+ doc.addEventListener("mouseup", onMouseUp, true);
82
+ doc.addEventListener("keydown", onKeyDown);
83
+ // Leaving the document entirely: tidy up.
84
+ doc.addEventListener("mouseleave", function () { if (!dragging) hideGrip(); });
85
+ }
86
+
87
+ function getDoc() { try { return editor.getDocument(); } catch (e) { return null; } }
88
+ function getEditable() { try { return editor.getEditable(); } catch (e) { return null; } }
89
+
90
+ // ---- block model -----------------------------------------------------
91
+
92
+ // Movable blocks: the editable's element children, minus any overlay chrome
93
+ // that other plugins park inside it.
94
+ function blocks() {
95
+ var ed = getEditable();
96
+ if (!ed) return [];
97
+ var out = [];
98
+ for (var i = 0; i < ed.children.length; i++) {
99
+ var el = ed.children[i];
100
+ if (el.nodeType !== 1) continue;
101
+ if (el.getAttribute &&
102
+ (el.getAttribute("data-rte-page-overlay") === "true" ||
103
+ el.getAttribute("data-rte-linenumbers") === "true")) continue;
104
+ out.push(el);
105
+ }
106
+ return out;
107
+ }
108
+
109
+ function topBlockOf(node) {
110
+ var ed = getEditable();
111
+ var n = node && node.nodeType === 3 ? node.parentNode : node;
112
+ var last = null;
113
+ while (n && n !== ed) { last = n; n = n.parentNode; }
114
+ return (n === ed && last && last.nodeType === 1) ? last : null;
115
+ }
116
+
117
+ function caretBlock() {
118
+ try {
119
+ var sel = editor.getSelection();
120
+ if (!sel || sel.rangeCount === 0) return null;
121
+ return topBlockOf(sel.getRangeAt(0).startContainer);
122
+ } catch (e) { return null; }
123
+ }
124
+
125
+ // ---- the move itself (shared by pointer and keyboard) ----------------
126
+
127
+ function moveBlock(block, beforeEl) {
128
+ var ed = getEditable();
129
+ if (!ed || !block || block.parentNode !== ed) return false;
130
+ if (beforeEl === block || (beforeEl && beforeEl.parentNode !== ed)) return false;
131
+ // Inserting before its own next sibling is a no-op move.
132
+ if (beforeEl === block.nextSibling) return false;
133
+ ed.insertBefore(block, beforeEl || null);
134
+ // Keep the caret with the block that moved — losing the caret is what
135
+ // makes programmatic moves feel broken (same lesson as tabletools sort).
136
+ try {
137
+ var doc = getDoc();
138
+ var r = doc.createRange();
139
+ r.selectNodeContents(block);
140
+ r.collapse(true);
141
+ var sel = editor.getSelection();
142
+ sel.removeAllRanges();
143
+ sel.addRange(r);
144
+ } catch (e) {}
145
+ fireChange();
146
+ return true;
147
+ }
148
+
149
+ function nudge(dir) {
150
+ var block = caretBlock();
151
+ if (!block) return false;
152
+ var list = blocks();
153
+ var i = list.indexOf(block);
154
+ if (i < 0) return false;
155
+ if (dir < 0) {
156
+ if (i === 0) return false;
157
+ return moveBlock(block, list[i - 1]);
158
+ }
159
+ if (i >= list.length - 1) return false;
160
+ // Moving down = inserting before the element after the next one.
161
+ return moveBlock(block, list[i + 1].nextSibling);
162
+ }
163
+
164
+ function onKeyDown(e) {
165
+ if (config.dragHandleKeyboard === false) return;
166
+ if (!e.altKey || !e.shiftKey || e.ctrlKey || e.metaKey) return;
167
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
168
+ if (nudge(e.key === "ArrowUp" ? -1 : 1)) {
169
+ e.preventDefault();
170
+ e.stopPropagation();
171
+ }
172
+ }
173
+
174
+ // ---- grip ------------------------------------------------------------
175
+
176
+ function ensureChrome(doc, ed) {
177
+ var host = ed.parentNode || doc.body;
178
+ if (!grip || !grip.parentNode) {
179
+ grip = doc.createElement("div");
180
+ grip.className = "rte-drag-grip";
181
+ grip.setAttribute("contenteditable", "false");
182
+ grip.setAttribute("aria-hidden", "true");
183
+ grip.textContent = "⠿"; // ⠿
184
+ host.appendChild(grip);
185
+ }
186
+ if (!indicator || !indicator.parentNode) {
187
+ indicator = doc.createElement("div");
188
+ indicator.className = "rte-drag-indicator";
189
+ indicator.setAttribute("contenteditable", "false");
190
+ indicator.setAttribute("aria-hidden", "true");
191
+ host.appendChild(indicator);
192
+ }
193
+ }
194
+
195
+ function hideGrip() {
196
+ if (grip) grip.style.display = "none";
197
+ hoverBlock = null;
198
+ }
199
+
200
+ function hideIndicator() {
201
+ if (indicator) indicator.style.display = "none";
202
+ }
203
+
204
+ function onHover(e) {
205
+ if (dragging || config.dragHandleEnabled === false) return;
206
+ var doc = getDoc();
207
+ var ed = getEditable();
208
+ if (!doc || !ed) return;
209
+ var block = null;
210
+ if (e.target === grip) return; // hovering the grip itself
211
+ if (ed.contains(e.target)) block = topBlockOf(e.target);
212
+ if (!block || blocks().indexOf(block) < 0) { hideGrip(); return; }
213
+ if (block === hoverBlock && grip && grip.style.display !== "none") return;
214
+
215
+ ensureChrome(doc, ed);
216
+ hoverBlock = block;
217
+ // RTL documents get the grip on the right, where the line starts.
218
+ var rtl = false;
219
+ try { rtl = (doc.defaultView.getComputedStyle(ed).direction === "rtl"); } catch (x) {}
220
+ grip.style.display = "block";
221
+ grip.style.top = block.offsetTop + "px";
222
+ if (rtl) grip.style.left = (block.offsetLeft + block.offsetWidth + 4) + "px";
223
+ else grip.style.left = Math.max(0, block.offsetLeft - 22) + "px";
224
+ }
225
+
226
+ // ---- drag ------------------------------------------------------------
227
+
228
+ function onMouseDown(e) {
229
+ if (e.target !== grip || !hoverBlock) return;
230
+ dragging = { block: hoverBlock };
231
+ dropBefore = null;
232
+ e.preventDefault();
233
+ e.stopPropagation();
234
+ var ed = getEditable();
235
+ if (ed && ed.classList) ed.classList.add("rte-drag-active");
236
+ if (grip) grip.classList.add("rte-drag-grip-held");
237
+ }
238
+
239
+ function onDragMove(e) {
240
+ if (!dragging) return;
241
+ e.preventDefault();
242
+ var doc = getDoc();
243
+ var ed = getEditable();
244
+ if (!doc || !ed) return;
245
+ ensureChrome(doc, ed);
246
+
247
+ // Decide the insertion point from the pointer's Y against each block's
248
+ // midpoint, in the same offsetTop space the indicator is drawn in.
249
+ var list = blocks();
250
+ if (!list.length) return;
251
+ var edRect = ed.getBoundingClientRect();
252
+ var y = e.clientY - edRect.top + (ed.scrollTop || 0);
253
+
254
+ dropBefore = null; // default: end of document
255
+ var lineTop = null;
256
+ for (var i = 0; i < list.length; i++) {
257
+ var b = list[i];
258
+ var mid = b.offsetTop + b.offsetHeight / 2;
259
+ if (y < mid) { dropBefore = b; lineTop = b.offsetTop; break; }
260
+ }
261
+ if (lineTop === null) {
262
+ var lastB = list[list.length - 1];
263
+ lineTop = lastB.offsetTop + lastB.offsetHeight;
264
+ }
265
+ indicator.style.display = "block";
266
+ indicator.style.top = Math.max(0, lineTop - 1) + "px";
267
+ indicator.style.left = ed.offsetLeft + "px";
268
+ indicator.style.width = ed.offsetWidth + "px";
269
+ }
270
+
271
+ function onMouseUp() {
272
+ if (!dragging) return;
273
+ var block = dragging.block;
274
+ var target = dropBefore;
275
+ dragging = null;
276
+ hideIndicator();
277
+ var ed = getEditable();
278
+ if (ed && ed.classList) ed.classList.remove("rte-drag-active");
279
+ if (grip) grip.classList.remove("rte-drag-grip-held");
280
+ hideGrip();
281
+ // Dropping a block onto itself moves nothing.
282
+ if (target !== block) moveBlock(block, target);
283
+ }
284
+
285
+ function fireChange() {
286
+ try { if (typeof editor.updateDesign === "function") editor.updateDesign(); } catch (e) {}
287
+ try { if (typeof editor.fireChange === "function") editor.fireChange(); } catch (e) {}
288
+ }
289
+
290
+ // ---- styles ----------------------------------------------------------
291
+
292
+ function injectStyles(doc) {
293
+ if (doc.getElementById("rte-drag-handle-styles")) return;
294
+ var st = doc.createElement("style");
295
+ st.id = "rte-drag-handle-styles";
296
+ st.appendChild(doc.createTextNode(
297
+ ".rte-drag-grip{position:absolute;display:none;width:18px;text-align:center;" +
298
+ "color:#94a3b8;font-size:14px;line-height:1.4;cursor:grab;user-select:none;z-index:20;" +
299
+ "border-radius:4px;}" +
300
+ ".rte-drag-grip:hover{background:rgba(148,163,184,.18);color:#475569;}" +
301
+ ".rte-drag-grip-held{cursor:grabbing;color:#1474ea;}" +
302
+ ".rte-drag-indicator{position:absolute;display:none;height:2px;background:#1474ea;" +
303
+ "border-radius:1px;pointer-events:none;z-index:19;}" +
304
+ ".rte-drag-active{cursor:grabbing;}" +
305
+ ".rte-drag-active *{cursor:grabbing !important;}"
306
+ ));
307
+ (doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement).appendChild(st);
308
+ }
309
+ }