@richscripts/richtexteditor 2.4.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 (184) hide show
  1. package/README.md +360 -0
  2. package/admin/index.d.ts +100 -0
  3. package/admin/index.js +94 -0
  4. package/angular/component.ts +284 -0
  5. package/angular/index.d.ts +80 -0
  6. package/angular/index.ts +24 -0
  7. package/headless/index.d.ts +65 -0
  8. package/headless/index.js +272 -0
  9. package/index.d.ts +1412 -0
  10. package/integrations/shared.d.ts +138 -0
  11. package/integrations/shared.js +5182 -0
  12. package/package.json +130 -0
  13. package/react/index.d.ts +104 -0
  14. package/react/index.js +310 -0
  15. package/richtexteditor/CHANGELOG.md +1876 -0
  16. package/richtexteditor/all_plugins.js +31125 -0
  17. package/richtexteditor/all_plugins.min.js +78 -0
  18. package/richtexteditor/lang/rte-lang-af.js +193 -0
  19. package/richtexteditor/lang/rte-lang-ar.js +193 -0
  20. package/richtexteditor/lang/rte-lang-bg.js +193 -0
  21. package/richtexteditor/lang/rte-lang-bn.js +193 -0
  22. package/richtexteditor/lang/rte-lang-bs.js +193 -0
  23. package/richtexteditor/lang/rte-lang-ca.js +193 -0
  24. package/richtexteditor/lang/rte-lang-cs.js +193 -0
  25. package/richtexteditor/lang/rte-lang-cy.js +193 -0
  26. package/richtexteditor/lang/rte-lang-da.js +193 -0
  27. package/richtexteditor/lang/rte-lang-de.js +193 -0
  28. package/richtexteditor/lang/rte-lang-el.js +193 -0
  29. package/richtexteditor/lang/rte-lang-en.js +6 -0
  30. package/richtexteditor/lang/rte-lang-es.js +193 -0
  31. package/richtexteditor/lang/rte-lang-et.js +193 -0
  32. package/richtexteditor/lang/rte-lang-fa.js +193 -0
  33. package/richtexteditor/lang/rte-lang-fi.js +193 -0
  34. package/richtexteditor/lang/rte-lang-fil.js +193 -0
  35. package/richtexteditor/lang/rte-lang-fj.js +193 -0
  36. package/richtexteditor/lang/rte-lang-fr.js +193 -0
  37. package/richtexteditor/lang/rte-lang-ga.js +193 -0
  38. package/richtexteditor/lang/rte-lang-gu.js +193 -0
  39. package/richtexteditor/lang/rte-lang-he.js +193 -0
  40. package/richtexteditor/lang/rte-lang-hi.js +193 -0
  41. package/richtexteditor/lang/rte-lang-hr.js +193 -0
  42. package/richtexteditor/lang/rte-lang-ht.js +193 -0
  43. package/richtexteditor/lang/rte-lang-hu.js +193 -0
  44. package/richtexteditor/lang/rte-lang-id.js +193 -0
  45. package/richtexteditor/lang/rte-lang-is.js +193 -0
  46. package/richtexteditor/lang/rte-lang-it.js +193 -0
  47. package/richtexteditor/lang/rte-lang-ja.js +193 -0
  48. package/richtexteditor/lang/rte-lang-kn.js +193 -0
  49. package/richtexteditor/lang/rte-lang-ko.js +193 -0
  50. package/richtexteditor/lang/rte-lang-lt.js +193 -0
  51. package/richtexteditor/lang/rte-lang-lv.js +193 -0
  52. package/richtexteditor/lang/rte-lang-mg.js +193 -0
  53. package/richtexteditor/lang/rte-lang-mi.js +193 -0
  54. package/richtexteditor/lang/rte-lang-ml.js +193 -0
  55. package/richtexteditor/lang/rte-lang-mr.js +193 -0
  56. package/richtexteditor/lang/rte-lang-ms.js +193 -0
  57. package/richtexteditor/lang/rte-lang-mt.js +193 -0
  58. package/richtexteditor/lang/rte-lang-mww.js +193 -0
  59. package/richtexteditor/lang/rte-lang-nb.js +193 -0
  60. package/richtexteditor/lang/rte-lang-nl.js +193 -0
  61. package/richtexteditor/lang/rte-lang-otq.js +193 -0
  62. package/richtexteditor/lang/rte-lang-pa.js +193 -0
  63. package/richtexteditor/lang/rte-lang-pl.js +193 -0
  64. package/richtexteditor/lang/rte-lang-pt-pt.js +193 -0
  65. package/richtexteditor/lang/rte-lang-pt.js +193 -0
  66. package/richtexteditor/lang/rte-lang-ro.js +193 -0
  67. package/richtexteditor/lang/rte-lang-ru.js +193 -0
  68. package/richtexteditor/lang/rte-lang-sk.js +193 -0
  69. package/richtexteditor/lang/rte-lang-sl.js +193 -0
  70. package/richtexteditor/lang/rte-lang-sm.js +193 -0
  71. package/richtexteditor/lang/rte-lang-sr-Cyrl.js +193 -0
  72. package/richtexteditor/lang/rte-lang-sr-Latn.js +193 -0
  73. package/richtexteditor/lang/rte-lang-sv.js +193 -0
  74. package/richtexteditor/lang/rte-lang-sw.js +193 -0
  75. package/richtexteditor/lang/rte-lang-ta.js +193 -0
  76. package/richtexteditor/lang/rte-lang-te.js +193 -0
  77. package/richtexteditor/lang/rte-lang-th.js +193 -0
  78. package/richtexteditor/lang/rte-lang-tlh-Latn.js +193 -0
  79. package/richtexteditor/lang/rte-lang-tlh-Piqd.js +193 -0
  80. package/richtexteditor/lang/rte-lang-to.js +193 -0
  81. package/richtexteditor/lang/rte-lang-tr.js +193 -0
  82. package/richtexteditor/lang/rte-lang-ty.js +193 -0
  83. package/richtexteditor/lang/rte-lang-uk.js +193 -0
  84. package/richtexteditor/lang/rte-lang-ur.js +193 -0
  85. package/richtexteditor/lang/rte-lang-vi.js +193 -0
  86. package/richtexteditor/lang/rte-lang-yua.js +193 -0
  87. package/richtexteditor/lang/rte-lang-zh-Hans.js +193 -0
  88. package/richtexteditor/lang/rte-lang-zh-Hant.js +193 -0
  89. package/richtexteditor/lang/rte-lang.js +1 -0
  90. package/richtexteditor/plugins/-combine-plugin.txt +2 -0
  91. package/richtexteditor/plugins/-combine-plugins.bat +20 -0
  92. package/richtexteditor/plugins/a11yenhance.js +90 -0
  93. package/richtexteditor/plugins/accessibilitychecker.js +579 -0
  94. package/richtexteditor/plugins/aitoolkit.css +15830 -0
  95. package/richtexteditor/plugins/aitoolkit.js +19171 -0
  96. package/richtexteditor/plugins/all_plugins.js +31125 -0
  97. package/richtexteditor/plugins/all_plugins.min.js +78 -0
  98. package/richtexteditor/plugins/autoembed.js +174 -0
  99. package/richtexteditor/plugins/blocktypes.js +175 -0
  100. package/richtexteditor/plugins/bookmarkcard.js +226 -0
  101. package/richtexteditor/plugins/charlimit.js +195 -0
  102. package/richtexteditor/plugins/comments.js +672 -0
  103. package/richtexteditor/plugins/contentminimap.js +369 -0
  104. package/richtexteditor/plugins/crdt-engine.js +8905 -0
  105. package/richtexteditor/plugins/crdt-engine.min.js +5 -0
  106. package/richtexteditor/plugins/dialoga11y.js +174 -0
  107. package/richtexteditor/plugins/dictation.js +268 -0
  108. package/richtexteditor/plugins/documentimport.js +369 -0
  109. package/richtexteditor/plugins/documentoutline.js +341 -0
  110. package/richtexteditor/plugins/emailtoolkit.js +165 -0
  111. package/richtexteditor/plugins/emojiautocomplete.js +241 -0
  112. package/richtexteditor/plugins/foldheadings.js +181 -0
  113. package/richtexteditor/plugins/ghostcomplete.js +297 -0
  114. package/richtexteditor/plugins/html2pdf.js +158 -0
  115. package/richtexteditor/plugins/imageeditor.js +159 -0
  116. package/richtexteditor/plugins/insertcode.js +319 -0
  117. package/richtexteditor/plugins/insertemoji.js +229 -0
  118. package/richtexteditor/plugins/insertgallery.js +362 -0
  119. package/richtexteditor/plugins/inserttemplate.js +261 -0
  120. package/richtexteditor/plugins/localdraft.js +213 -0
  121. package/richtexteditor/plugins/markdownexport.js +110 -0
  122. package/richtexteditor/plugins/mathdialog.js +153 -0
  123. package/richtexteditor/plugins/mentionplugin.js +534 -0
  124. package/richtexteditor/plugins/mermaiddiagram.js +294 -0
  125. package/richtexteditor/plugins/readabilitystats.js +148 -0
  126. package/richtexteditor/plugins/readaloud.js +243 -0
  127. package/richtexteditor/plugins/restrictedediting.js +208 -0
  128. package/richtexteditor/plugins/revisionhistory.js +670 -0
  129. package/richtexteditor/plugins/samples/insertcode_v1.js +76 -0
  130. package/richtexteditor/plugins/slashcommand.js +705 -0
  131. package/richtexteditor/plugins/smartchips.js +250 -0
  132. package/richtexteditor/plugins/spellcheck.js +181 -0
  133. package/richtexteditor/plugins/todolist.js +137 -0
  134. package/richtexteditor/plugins/trackedchanges.js +658 -0
  135. package/richtexteditor/plugins/tui.image-editor/fabric.min.js +8 -0
  136. package/richtexteditor/plugins/tui.image-editor/note.txt +5 -0
  137. package/richtexteditor/plugins/tui.image-editor/svg/icon-a.svg +235 -0
  138. package/richtexteditor/plugins/tui.image-editor/svg/icon-b.svg +224 -0
  139. package/richtexteditor/plugins/tui.image-editor/svg/icon-c.svg +224 -0
  140. package/richtexteditor/plugins/tui.image-editor/svg/icon-d.svg +224 -0
  141. package/richtexteditor/plugins/tui.image-editor/tui-code-snippet.min.js +7 -0
  142. package/richtexteditor/plugins/tui.image-editor/tui-color-picker.min.css +6 -0
  143. package/richtexteditor/plugins/tui.image-editor/tui-color-picker.min.js +7 -0
  144. package/richtexteditor/plugins/tui.image-editor/tui-image-editor.min.css +7 -0
  145. package/richtexteditor/plugins/tui.image-editor/tui-image-editor.min.js +15 -0
  146. package/richtexteditor/plugins/typewriter.js +203 -0
  147. package/richtexteditor/plugins/wordexport.js +0 -0
  148. package/richtexteditor/plugins/yjscollab.js +693 -0
  149. package/richtexteditor/plugins/zz_richtextbox_dialog_style.js +335 -0
  150. package/richtexteditor/rte-config.js +933 -0
  151. package/richtexteditor/rte.js +943 -0
  152. package/richtexteditor/rte_mobile.css +234 -0
  153. package/richtexteditor/rte_theme_default.css +4819 -0
  154. package/richtexteditor/runtime/colorpicker_more_ns.htm +2613 -0
  155. package/richtexteditor/runtime/help.htm +162 -0
  156. package/richtexteditor/runtime/images/1x1.gif +0 -0
  157. package/richtexteditor/runtime/images/cpie_Color.cur +0 -0
  158. package/richtexteditor/runtime/images/cpie_GradientPositionDark.gif +0 -0
  159. package/richtexteditor/runtime/images/cpie_GradientPositionLight.gif +0 -0
  160. package/richtexteditor/runtime/images/cpie_VerticalPosition.gif +0 -0
  161. package/richtexteditor/runtime/images/cpie_WebSafe.gif +0 -0
  162. package/richtexteditor/runtime/images/cpie_gradients.png +0 -0
  163. package/richtexteditor/runtime/images/cpns_Color.cur +0 -0
  164. package/richtexteditor/runtime/images/cpns_ColorSpace1.png +0 -0
  165. package/richtexteditor/runtime/images/cpns_ColorSpace2.png +0 -0
  166. package/richtexteditor/runtime/images/cpns_GradientPositionDark.gif +0 -0
  167. package/richtexteditor/runtime/images/cpns_GradientPositionLight.gif +0 -0
  168. package/richtexteditor/runtime/images/cpns_Vertical1.png +0 -0
  169. package/richtexteditor/runtime/images/cpns_Vertical2.png +0 -0
  170. package/richtexteditor/runtime/images/cpns_VerticalPosition.gif +0 -0
  171. package/richtexteditor/runtime/images/cpns_WebSafe.gif +0 -0
  172. package/richtexteditor/runtime/images/cpns_gradients.png +0 -0
  173. package/richtexteditor/runtime/images/cpns_hue2.png +0 -0
  174. package/richtexteditor/runtime/images/formbn.gif +0 -0
  175. package/richtexteditor/runtime/images/multiclavier.gif +0 -0
  176. package/richtexteditor/runtime/richtexteditor_content.css +362 -0
  177. package/richtexteditor/runtime/richtexteditor_preview.css +302 -0
  178. package/richtexteditor/runtime/richtexteditor_preview.js +1 -0
  179. package/server/index.d.ts +21 -0
  180. package/server/index.js +23 -0
  181. package/svelte/index.d.ts +19 -0
  182. package/svelte/index.js +59 -0
  183. package/vue/index.d.ts +94 -0
  184. package/vue/index.js +291 -0
@@ -0,0 +1,297 @@
1
+ if (!window.RTE_DefaultConfig) window.RTE_DefaultConfig = {};
2
+
3
+ // 2026-06-06 AI ghost-text autocomplete. GitHub-Copilot / Notion-AI-style inline
4
+ // completion: after you pause typing, a greyed suggestion appears after the caret
5
+ // continuing your sentence; press Tab to accept it, Esc (or just keep typing) to
6
+ // dismiss. Distinct from the command-driven AI Toolkit — this is ambient,
7
+ // inline, and hands-free.
8
+ //
9
+ // Bring-your-own-key: supply config.ghostTextResolver(context) returning a string
10
+ // (or a Promise of one). `context` = { before, after, full } around the caret.
11
+ // Nothing ships a model or makes network calls on its own.
12
+ //
13
+ // config.ghostText = true | { delayMs, minChars, maxContext }
14
+ // config.ghostTextResolver = async ({ before }) => " the rest of the sentence"
15
+ //
16
+ // Serialization-safe: the suggestion lives in a contenteditable=false
17
+ // `<span class="rte-ghost">` decoration that is never part of the saved content —
18
+ // getHTMLCode / getJSON are wrapped to strip any ghost span, and the caret is
19
+ // always kept BEFORE the ghost so typing and saving behave normally.
20
+ RTE_DefaultConfig.plugin_ghostcomplete = RTE_Plugin_GhostComplete;
21
+ if (typeof RTE_DefaultConfig.ghostText === "undefined") RTE_DefaultConfig.ghostText = false;
22
+ if (typeof RTE_DefaultConfig.ghostTextResolver === "undefined") RTE_DefaultConfig.ghostTextResolver = null;
23
+
24
+ function RTE_Plugin_GhostComplete() {
25
+ var obj = this;
26
+ var config, editor;
27
+ var opts = null, boundDoc = null, wrapped = false;
28
+ var timer = null, reqToken = 0, busy = false;
29
+ var ghostEl = null, ghostText = "";
30
+
31
+ obj.PluginName = "GhostComplete";
32
+
33
+ obj.InitConfig = function (argconfig) { config = argconfig; };
34
+
35
+ obj.InitEditor = function (argeditor) {
36
+ editor = argeditor;
37
+ opts = (typeof config.ghostText === "object" && config.ghostText) ? config.ghostText : {};
38
+
39
+ setup();
40
+ try { editor.attachEvent("ready", setup); } catch (e) {}
41
+ try { editor.attachEvent("aftersethtml", setup); } catch (e) {}
42
+ setTimeout(setup, 0); setTimeout(setup, 200);
43
+
44
+ // Public API.
45
+ editor.setGhostTextResolver = function (fn) { config.ghostTextResolver = (typeof fn === "function") ? fn : null; };
46
+ editor.requestGhostText = function () {
47
+ // Manual invocation (slash menu / API) with no resolver configured
48
+ // used to be a silent no-op — surface a transient setup hint so
49
+ // the user learns WHY nothing happened and how to enable it.
50
+ if (typeof config.ghostTextResolver !== "function") { showSetupHint(); return; }
51
+ scheduleRequest(0);
52
+ };
53
+ editor.acceptGhostText = function () { return accept(); };
54
+ editor.dismissGhostText = function () { clearGhost(); };
55
+ editor.hasGhostText = function () { return !!ghostEl; };
56
+ };
57
+
58
+ function enabled() { return !!config.ghostText && typeof config.ghostTextResolver === "function"; }
59
+
60
+ function setup() {
61
+ var doc = editor.getDocument(); if (!doc) return;
62
+ injectStyles(doc);
63
+ if (doc !== boundDoc) {
64
+ doc.addEventListener("keydown", onKeyDown, true);
65
+ doc.addEventListener("input", onInput, true);
66
+ doc.addEventListener("mousedown", onPointerDown, true);
67
+ // Touch devices have no Tab key — tapping the suggestion accepts it.
68
+ doc.addEventListener("touchstart", onPointerDown, true);
69
+ boundDoc = doc;
70
+ }
71
+ wrapSerializers();
72
+ }
73
+
74
+ function delayMs() { var n = opts && +opts.delayMs; return (n && n >= 0) ? n : 600; }
75
+ function minChars() { var n = opts && +opts.minChars; return (n && n > 0) ? n : 3; }
76
+ function maxContext() { var n = opts && +opts.maxContext; return (n && n > 0) ? n : 2000; }
77
+
78
+ function onInput() {
79
+ if (busy) return;
80
+ clearGhost(); // any edit invalidates a showing suggestion
81
+ if (!enabled()) return;
82
+ scheduleRequest(delayMs());
83
+ }
84
+
85
+ function onKeyDown(e) {
86
+ if (!ghostEl) {
87
+ // Allow manual trigger: nothing here; ghost only shows after a pause.
88
+ return;
89
+ }
90
+ if (e.key === "Tab") { e.preventDefault(); e.stopPropagation(); accept(); return; }
91
+ if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); clearGhost(); return; }
92
+ // Arrow / navigation keys dismiss; character keys are handled by onInput.
93
+ if (/^Arrow|^Home$|^End$|^PageUp$|^PageDown$/.test(e.key)) { clearGhost(); }
94
+ }
95
+
96
+ // Pointer/touch on the suggestion accepts it (the only way on mobile, and a
97
+ // handy shortcut on desktop); a pointer anywhere else dismisses it.
98
+ function onPointerDown(e) {
99
+ if (!ghostEl) return;
100
+ var t = e.target;
101
+ if (t === ghostEl || (ghostEl.contains && ghostEl.contains(t))) {
102
+ e.preventDefault(); e.stopPropagation();
103
+ accept();
104
+ } else {
105
+ clearGhost();
106
+ }
107
+ }
108
+
109
+ function scheduleRequest(ms) {
110
+ if (timer) { clearTimeout(timer); timer = null; }
111
+ if (!enabled()) return;
112
+ timer = setTimeout(runRequest, ms);
113
+ }
114
+
115
+ function runRequest() {
116
+ timer = null;
117
+ if (!enabled() || ghostEl) return;
118
+ var ctx = caretContext();
119
+ if (!ctx || ctx.before.replace(/\s/g, "").length < minChars()) return;
120
+
121
+ var token = ++reqToken;
122
+ var out;
123
+ try { out = config.ghostTextResolver({ before: ctx.before, after: ctx.after, full: ctx.full }); }
124
+ catch (e) { return; }
125
+
126
+ Promise.resolve(out).then(function (text) {
127
+ if (token !== reqToken) return; // superseded by newer input
128
+ if (ghostEl) return; // already showing
129
+ if (typeof text !== "string") return;
130
+ text = text.replace(/\r/g, "");
131
+ if (!text) return;
132
+ // Only show if the caret is still collapsed where we measured.
133
+ showGhost(text);
134
+ }, function () { /* resolver failed — stay silent */ });
135
+ }
136
+
137
+ // The text immediately around the caret (within the current block), trimmed
138
+ // to maxContext characters of left-context.
139
+ function caretContext() {
140
+ try {
141
+ var sel = editor.getSelection();
142
+ if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return null;
143
+ var editable = editor.getEditable(); if (!editable) return null;
144
+ var r = sel.getRangeAt(0);
145
+ // before = text from block start to caret; after = caret to block end.
146
+ var block = blockOf(r.startContainer, editable) || editable;
147
+ var beforeRange = r.cloneRange();
148
+ beforeRange.setStart(block, 0);
149
+ var afterRange = r.cloneRange();
150
+ afterRange.setEnd(block, block.childNodes.length);
151
+ var before = textOf(beforeRange);
152
+ var after = textOf(afterRange);
153
+ if (before.length > maxContext()) before = before.slice(before.length - maxContext());
154
+ return { before: before, after: after, full: textOf(rangeOfNode(editable)) };
155
+ } catch (e) { return null; }
156
+ }
157
+
158
+ function rangeOfNode(node) { var d = editor.getDocument(); var r = d.createRange(); r.selectNodeContents(node); return r; }
159
+ function textOf(range) {
160
+ try {
161
+ var frag = range.cloneContents();
162
+ // strip any ghost spans from the measured text
163
+ var ghosts = frag.querySelectorAll ? frag.querySelectorAll(".rte-ghost") : [];
164
+ for (var i = 0; i < ghosts.length; i++) ghosts[i].parentNode.removeChild(ghosts[i]);
165
+ var tmp = editor.getDocument().createElement("div");
166
+ tmp.appendChild(frag);
167
+ return tmp.textContent || "";
168
+ } catch (e) { return ""; }
169
+ }
170
+ function blockOf(node, editable) {
171
+ var n = (node && node.nodeType === 3) ? node.parentNode : node;
172
+ while (n && n !== editable) {
173
+ if (n.nodeType === 1 && /^(P|H[1-6]|LI|BLOCKQUOTE|PRE|TD|TH|DIV|FIGCAPTION)$/.test(n.nodeName)) return n;
174
+ n = n.parentNode;
175
+ }
176
+ return null;
177
+ }
178
+
179
+ function showGhost(text) {
180
+ var doc = editor.getDocument(), sel = editor.getSelection();
181
+ if (!doc || !sel || sel.rangeCount === 0 || !sel.isCollapsed) return;
182
+ busy = true;
183
+ try {
184
+ var r = sel.getRangeAt(0);
185
+ var span = doc.createElement("span");
186
+ span.className = "rte-ghost";
187
+ span.setAttribute("contenteditable", "false");
188
+ span.setAttribute("data-rte-ghost", "1");
189
+ // The suggestion is unconfirmed, predicted text — hide it from the
190
+ // accessibility tree so screen readers don't read it as real content.
191
+ span.setAttribute("aria-hidden", "true");
192
+ span.textContent = text;
193
+ r.insertNode(span);
194
+ ghostEl = span; ghostText = text;
195
+ // keep the caret BEFORE the ghost so typing/saving are unaffected
196
+ var cr = doc.createRange();
197
+ cr.setStartBefore(span); cr.collapse(true);
198
+ sel.removeAllRanges(); sel.addRange(cr);
199
+ } catch (e) { ghostEl = null; ghostText = ""; }
200
+ finally { busy = false; }
201
+ }
202
+
203
+ function clearGhost() {
204
+ if (!ghostEl) return;
205
+ busy = true;
206
+ try {
207
+ var sel = editor.getSelection();
208
+ var caret = null;
209
+ if (sel && sel.rangeCount) { var c = sel.getRangeAt(0); caret = { n: c.startContainer, o: c.startOffset }; }
210
+ if (ghostEl.parentNode) ghostEl.parentNode.removeChild(ghostEl);
211
+ // restore caret if it still resolves
212
+ try { if (caret && caret.n) { var d = editor.getDocument(), nr = d.createRange(); nr.setStart(caret.n, Math.min(caret.o, (caret.n.length != null ? caret.n.length : caret.o))); nr.collapse(true); sel.removeAllRanges(); sel.addRange(nr); } } catch (e2) {}
213
+ } catch (e) {}
214
+ finally { ghostEl = null; ghostText = ""; busy = false; }
215
+ }
216
+
217
+ function accept() {
218
+ if (!ghostEl) return false;
219
+ var text = ghostText;
220
+ var doc = editor.getDocument(), sel = editor.getSelection();
221
+ busy = true;
222
+ try {
223
+ // caret is before the ghost; remove ghost, then insert real text so it
224
+ // lands on the native undo stack.
225
+ if (ghostEl.parentNode) ghostEl.parentNode.removeChild(ghostEl);
226
+ ghostEl = null; ghostText = "";
227
+ var done = false;
228
+ try { done = doc.execCommand("insertText", false, text); } catch (e) { done = false; }
229
+ if (!done && sel && sel.rangeCount) {
230
+ var r = sel.getRangeAt(0);
231
+ var tn = doc.createTextNode(text);
232
+ r.insertNode(tn);
233
+ var cr = doc.createRange(); cr.setStartAfter(tn); cr.collapse(true);
234
+ sel.removeAllRanges(); sel.addRange(cr);
235
+ }
236
+ } catch (e) {} finally { busy = false; }
237
+ try { if (typeof editor.fireChange === "function") editor.fireChange(); } catch (e) {}
238
+ return true;
239
+ }
240
+
241
+ function showSetupHint() {
242
+ try {
243
+ var ifr = editor.iframe || (editor.getDocument && editor.getDocument().defaultView && editor.getDocument().defaultView.frameElement);
244
+ var host = ifr && ifr.parentNode ? ifr.parentNode : document.body;
245
+ if (host.querySelector && host.querySelector(".rte-ghost-hint")) return;
246
+ var tip = (host.ownerDocument || document).createElement("div");
247
+ tip.className = "rte-ghost-hint";
248
+ tip.setAttribute("role", "status");
249
+ tip.textContent = "AI completion isn't configured — supply config.ghostTextResolver (or editor.setGhostTextResolver) to enable inline suggestions.";
250
+ tip.style.cssText = "position:absolute;left:50%;bottom:12px;transform:translateX(-50%);z-index:20;" +
251
+ "max-width:90%;padding:7px 14px;border-radius:8px;background:#1f2937;color:#f9fafb;" +
252
+ "font:12px/1.5 -apple-system,Segoe UI,sans-serif;box-shadow:0 4px 14px rgba(0,0,0,.25);pointer-events:none";
253
+ try { if (host !== document.body && (host.ownerDocument.defaultView || window).getComputedStyle(host).position === "static") host.style.position = "relative"; } catch (e2) {}
254
+ host.appendChild(tip);
255
+ setTimeout(function () { try { if (tip.parentNode) tip.parentNode.removeChild(tip); } catch (e3) {} }, 4500);
256
+ } catch (e) {}
257
+ }
258
+
259
+ function injectStyles(doc) {
260
+ if (!doc || doc.getElementById("rte-ghost-styles")) return;
261
+ var css = ".rte-ghost{color:#9aa3b2;opacity:.85;font-style:normal;" +
262
+ "user-select:none;-webkit-user-select:none;cursor:pointer;white-space:pre-wrap;}";
263
+ var st = doc.createElement("style");
264
+ st.id = "rte-ghost-styles";
265
+ st.appendChild(doc.createTextNode(css));
266
+ (doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement).appendChild(st);
267
+ }
268
+
269
+ function stripFor() {
270
+ var ed = editor.getEditable(); if (!ed) return function () {};
271
+ var ghosts = ed.querySelectorAll(".rte-ghost");
272
+ var parents = [];
273
+ for (var i = 0; i < ghosts.length; i++) { parents.push([ghosts[i], ghosts[i].nextSibling, ghosts[i].parentNode]); ghosts[i].parentNode.removeChild(ghosts[i]); }
274
+ return function restore() {
275
+ for (var j = 0; j < parents.length; j++) {
276
+ var node = parents[j][0], ref = parents[j][1], par = parents[j][2];
277
+ if (par) { try { par.insertBefore(node, ref); } catch (e) {} }
278
+ }
279
+ };
280
+ }
281
+ function wrapSerializers() {
282
+ if (wrapped) return;
283
+ var names = ["getHTMLCode", "getJSON", "getHTMLContent"];
284
+ var did = false;
285
+ for (var i = 0; i < names.length; i++) {
286
+ (function (name) {
287
+ var orig = editor[name];
288
+ if (typeof orig !== "function" || orig.__rteGhostWrapped) return;
289
+ var w = function () { var restore = stripFor(); try { return orig.apply(editor, arguments); } finally { restore(); } };
290
+ w.__rteGhostWrapped = true;
291
+ editor[name] = w;
292
+ did = true;
293
+ })(names[i]);
294
+ }
295
+ if (did) wrapped = true;
296
+ }
297
+ }
@@ -0,0 +1,158 @@
1
+
2
+
3
+ if (!RTE_DefaultConfig.svgCode_html2pdf) {
4
+ RTE_DefaultConfig.svgCode_html2pdf = '<svg viewBox="-2 -2 36 36" fill="#5F6368"><polygon points="30 11 30 9 22 9 22 23 24 23 24 17 29 17 29 15 24 15 24 11 30 11"></polygon><path d="M8,9H2V23H4V18H8a2,2,0,0,0,2-2V11A2,2,0,0,0,8,9Zm0,7H4V11H8Z"></path><path d="M16,23H12V9h4a4,4,0,0,1,4,4v6A4,4,0,0,1,16,23Zm-2-2h2a2,2,0,0,0,2-2V13a2,2,0,0,0-2-2H14Z"></path><title>PDF</title></svg>'
5
+ }
6
+
7
+ RTE_DefaultConfig.plugin_html2pdf = RTE_Plugin_Html2PDF;
8
+
9
+ function RTE_Plugin_Html2PDF() {
10
+
11
+ var scripturl = "https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js";
12
+
13
+ var obj = this;
14
+
15
+ var config, editor;
16
+
17
+ obj.PluginName = "Html2PDF";
18
+
19
+ obj.InitConfig = function (argconfig) {
20
+ config = argconfig;
21
+ }
22
+ obj.InitEditor = function (argeditor) {
23
+ editor = argeditor;
24
+
25
+ editor.attachEvent("exec_command_html2pdf", function (state, cmd, value) {
26
+ obj.DoHtml2PDF();
27
+ state.returnValue = true;
28
+ });
29
+
30
+ editor.toolbarFactoryMap["html2pdf"] = function (cmd) {
31
+ //console.log(cmd);
32
+ var span = editor.createToolbarButton(cmd);
33
+ span.style.backgroundColor = ''
34
+ return span;
35
+ };
36
+
37
+ }
38
+
39
+ function __Append(parent, tagname, csstext, cssclass) {
40
+ var tag = parent.ownerDocument.createElement(tagname);
41
+ if (csstext) tag.style.cssText = csstext;
42
+ if (cssclass) tag.className = cssclass;
43
+ parent.appendChild(tag);
44
+ return tag;
45
+ }
46
+
47
+
48
+ function dataURLToBlob(dataurl) {
49
+ var arr = dataurl.split(',');
50
+ var mime = arr[0].match(/:(.*?);/)[1];
51
+ var bstr = atob(arr[1]);
52
+ var n = bstr.length;
53
+ var u8arr = new Uint8Array(n);
54
+ while (n--) {
55
+ u8arr[n] = bstr.charCodeAt(n);
56
+ }
57
+ return new Blob([u8arr], { type: mime });
58
+ }
59
+
60
+ obj.DoHtml2PDF = function () {
61
+
62
+ var dialoginner = editor.createDialog("Html2PDF", "rte-dialog-html2pdf");
63
+
64
+ var div2 = __Append(dialoginner, "div", "position:relative;text-align:center;");
65
+
66
+ div2.innerHTML = "Loading...";
67
+
68
+ var imgrect = __Append(dialoginner, "div", "position:relative;text-align:center;")
69
+
70
+ window.html2pdf_callback = function (win) {
71
+
72
+ if (!win.html2pdf) {
73
+ div2.innerHTML = "Failed to load script.";
74
+ return;
75
+ }
76
+
77
+ div2.innerHTML = "Exporting...";
78
+
79
+ var opt = {
80
+ margin: 0.5,
81
+ filename: 'myfile.pdf',
82
+ image: { type: 'jpeg', quality: 0.98 },
83
+ html2canvas: { scale: 2 },
84
+ jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
85
+ };
86
+
87
+ var promimg = win.html2pdf().set(opt).from(win.document.body).outputImg();
88
+ promimg.then(function (img) {
89
+
90
+ var dataurl = img.getAttribute('src');
91
+ if (dataurl.indexOf("base64") == -1) {
92
+ div2.innerHTML = "Error, no data.";
93
+ return;
94
+ }
95
+
96
+ var imgblob = dataURLToBlob(dataurl);
97
+ var imgurl = URL.createObjectURL(imgblob);
98
+ img.setAttribute("src", imgurl);
99
+
100
+ var prom = win.html2pdf().set(opt).from(win.document.body).outputPdf();
101
+ prom.then(function (str) {
102
+ var bin = new Array(str.length);
103
+ for (var i = 0; i < str.length; i++)
104
+ bin[i] = str.charCodeAt(i);
105
+ var blob = new Blob([new Uint8Array(bin)], { type: "application/pdf" })
106
+ var url = URL.createObjectURL(blob);
107
+ div2.innerHTML = Math.ceil(str.length / 1024) + "KB Exported<br/><a href='" + url + "' target=_blank>Download PDF</a>";
108
+
109
+ var pdflink = div2.querySelector("a");
110
+
111
+ var date = new Date();
112
+ var ymd = String(date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate()).substring(2);
113
+ var hms = String(1000000 + date.getHours() * 10000 + date.getMinutes() * 100 + date.getSeconds()).substring(1);
114
+ pdflink.download = "Export-" + ymd + "-" + hms + ".pdf";
115
+
116
+ //a.rel = 'noopener'
117
+
118
+ pdflink.click();
119
+
120
+ img.style.cssText = "max-width:300px;max-height:200px;margin:5px;padding:10px;border:solid 1px #eee;box-shadow:2px 2px 6px #eee"
121
+ imgrect.appendChild(img)
122
+
123
+ __Append(imgrect, "br");
124
+ var imglink = __Append(imgrect, "a");
125
+ imglink.setAttribute("href", imgurl);
126
+ imglink.setAttribute("target", "_blank");
127
+ imglink.download = "Export-" + ymd + "-" + hms + ".jpg";
128
+ imglink.innerText = "Download Img";
129
+
130
+ //dialoginner.close();
131
+
132
+ }).catch(function (x) {
133
+ console.error(x);
134
+ })
135
+
136
+ }).catch(function (x) {
137
+ console.error(x);
138
+ })
139
+
140
+
141
+ }
142
+
143
+ var div1 = __Append(dialoginner, "div", "position:relative;text-align:center;");
144
+
145
+ iframe = __Append(div1, "iframe", "align-self:center;flex:99;width:100%;height:0px;border:0px;", "rte-editable");
146
+ iframe.contentDocument.open("text/html");
147
+ iframe.contentDocument.write("<html><head><link id='url-css-preview' rel='stylesheet' href='" + editor.htmlEncode(config.previewCssUrl) + "'/>"
148
+ + "<script src='" + editor.htmlEncode(scripturl) + "'></script></head><body style='padding:10px;margin:0px'>"
149
+ + editor.getHTMLCode() + "</body>"
150
+ + "<script>window.onload=function(){setTimeout(function(){parent.html2pdf_callback(window)},100)}</script></html>")
151
+ iframe.contentDocument.close();
152
+
153
+ }
154
+ }
155
+
156
+
157
+
158
+
@@ -0,0 +1,159 @@
1
+
2
+
3
+ if (!RTE_DefaultConfig.svgCode_imageeditor) {
4
+ RTE_DefaultConfig.svgCode_imageeditor = '<svg viewBox="-2 -2 20 20" fill="#5F6368"><style>.st0{fill:#f6f6f6}.st1{fill:#424242}.st2{fill:none}.st3{fill:#f0eff1}</style><path class="st0" d="M1 0v6H0v10h10v-1h6V0z" id="outline"/><g id="icon_x5F_bg"><path class="st1" d="M2 5h1v1H2zM2 3h1v1H2zM2 1h1v1H2zM4 1h1.001v1H4zM6 1h1v1H6zM8 1h1v1H8zM10 1h1v1h-1zM12 1h1v1h-1zM14 1h1v1h-1zM14 3h1v1h-1zM14 5h1v1h-1zM14 7h1v1h-1zM14 9h1v1h-1zM14 10.999h1V12h-1zM14 13h1v1h-1zM12 13h1v1h-1zM11 11V5H5v1H4V4h8v7z"/><circle class="st1" cx="6.192" cy="9.807" r=".807"/><path class="st1" d="M1 7v8h8V7H1zm1 7.001v-.28l2.537-1.463L7.554 14l.001.001H2zm6-.93l-3.463-1.982L2 12.491v-4.49h6v5.07zM10 13h1v1h-1z"/></g><g id="icon_x5F_fg"><path class="st2" d="M2 14h5.554v.001H2z"/><path class="st3" d="M11 5v6h-1V6H5V5z"/><path class="st3" d="M2 12.491l2.537-1.402L8 13.071v-5.07H2v4.49zM6.192 9a.807.807 0 1 1 .001 1.615A.807.807 0 0 1 6.192 9z"/><path class="st3" d="M2 13.721V14h5.554l-3.017-1.742z"/></g></svg>';
5
+ }
6
+
7
+ RTE_DefaultConfig.plugin_imageeditor = RTE_Plugin_ImageEditor;
8
+
9
+ function RTE_Plugin_ImageEditor() {
10
+
11
+
12
+
13
+ var obj = this;
14
+
15
+ var config, editor;
16
+
17
+ obj.PluginName = "ImageEditor";
18
+
19
+ obj.InitConfig = function (argconfig) {
20
+ config = argconfig;
21
+ }
22
+ obj.InitEditor = function (argeditor) {
23
+ editor = argeditor;
24
+
25
+ editor.attachEvent("exec_command_imageeditor", function (state, cmd, value) {
26
+ obj.DoImageEditor();
27
+ state.returnValue = true;
28
+ });
29
+
30
+ editor.toolbarFactoryMap["imageeditor"] = function (cmd) {
31
+ var span = editor.createToolbarButton(cmd);
32
+ span.style.backgroundColor = ''
33
+ return span;
34
+ };
35
+
36
+ }
37
+
38
+ function __Append(parent, tagname, csstext, cssclass) {
39
+ var tag = parent.ownerDocument.createElement(tagname);
40
+ if (csstext) tag.style.cssText = csstext;
41
+ if (cssclass) tag.className = cssclass;
42
+ parent.appendChild(tag);
43
+ return tag;
44
+ }
45
+
46
+ function dataURLToBlob(dataurl) {
47
+ var arr = dataurl.split(',');
48
+ var mime = arr[0].match(/:(.*?);/)[1];
49
+ var bstr = atob(arr[1]);
50
+ var n = bstr.length;
51
+ var u8arr = new Uint8Array(n);
52
+ while (n--) {
53
+ u8arr[n] = bstr.charCodeAt(n);
54
+ }
55
+ return new Blob([u8arr], { type: mime });
56
+ }
57
+
58
+ obj.DoImageEditor = function () {
59
+
60
+ var img = editor.getSelectedControl();
61
+ if (!img)
62
+ return;
63
+
64
+ var dialoginner = editor.createDialog("ImageEditor", "rte-dialog-imageeditor");
65
+
66
+ dialoginner.style.width = "90%";
67
+ dialoginner.style.height = "90%";
68
+
69
+
70
+ var scriptbase = config.url_base + "/plugins/tui.image-editor/";
71
+
72
+ window.rte_image_editor_callback = function (win) {
73
+ var options = {
74
+ includeUI: {
75
+ loadImage: {
76
+ path: img.src,
77
+ name: 'RteImage'
78
+ },
79
+ //locale: locale_ru_RU,
80
+ theme: {
81
+ // main icons
82
+ 'menu.normalIcon.path': scriptbase + 'svg/icon-d.svg',
83
+ 'menu.activeIcon.path': scriptbase + 'svg/icon-b.svg',
84
+ 'menu.disabledIcon.path': scriptbase + 'svg/icon-a.svg',
85
+ 'menu.hoverIcon.path': scriptbase + 'svg/icon-c.svg',
86
+ // submenu icons
87
+ 'submenu.normalIcon.path': scriptbase + 'svg/icon-d.svg',
88
+ 'submenu.normalIcon.name': 'icon-d',
89
+ 'submenu.activeIcon.path': scriptbase + 'svg/icon-c.svg',
90
+ 'submenu.activeIcon.name': 'icon-c'
91
+ },
92
+ //initMenu: 'filter',
93
+ menuBarPosition: 'bottom'
94
+ },
95
+
96
+ cssMaxWidth: 700,
97
+ cssMaxHeight: 500,
98
+ selectionStyle: {
99
+ cornerSize: 20,
100
+ rotatingPointOffset: 70
101
+ }
102
+ };
103
+ var imgeditor = new win.tui.ImageEditor(win.document.querySelector('#tui-image-editor'), options);
104
+
105
+ var btns = win.document.querySelector('.tui-image-editor-header-buttons');
106
+ btns.innerHTML = '';
107
+ var savebtn = __Append(btns, "button", "");
108
+ savebtn.innerText = "Save";
109
+ savebtn.onclick = function () {
110
+
111
+ var dataurl = imgeditor.toDataURL();
112
+ if (!config.file_upload_handler) {
113
+ img.src = dataurl;
114
+ editor.notifySelectionChange();
115
+ dialoginner.close();
116
+ return;
117
+ }
118
+
119
+ var file = dataURLToBlob(dataurl);
120
+
121
+ config.file_upload_handler(file, function (url, error) {
122
+ if (url) {
123
+ img.src = url;
124
+ editor.notifySelectionChange();
125
+ dialoginner.close();
126
+ return;
127
+ }
128
+ if (error) {
129
+ //TODO:retry dialog or cancel
130
+ alert("upload failed , TODO:show retry dialog or cancel");
131
+ }
132
+ else {
133
+ alert("Developer warning : ");
134
+ }
135
+ });
136
+
137
+
138
+ }
139
+
140
+ }
141
+
142
+ iframe = __Append(dialoginner, "iframe", "align-self:center;flex:99;width:100%;height:100%px;border:0px;", "rte-editable");
143
+ iframe.contentDocument.open("text/html");
144
+ iframe.contentDocument.write("<html><head><base href='" + editor.htmlEncode(location.href) + "'/>"
145
+ + "<link id='url-css-preview' rel='stylesheet' href='" + editor.htmlEncode(scriptbase + "tui-color-picker.min.css") + "'/>"
146
+ + "<link id='url-css-preview' rel='stylesheet' href='" + editor.htmlEncode(scriptbase + "tui-image-editor.min.css") + "'/>"
147
+ + "<script src='" + editor.htmlEncode(scriptbase + "fabric.min.js") + "'></script>"
148
+ + "<script src='" + editor.htmlEncode(scriptbase + "tui-color-picker.min.js") + "'></script>"
149
+ + "<script src='" + editor.htmlEncode(scriptbase + "tui-code-snippet.min.js") + "'></script>"
150
+ + "<script src='" + editor.htmlEncode(scriptbase + "tui-image-editor.min.js") + "'></script>"
151
+ + "</head><body style='padding:10px;margin:0px'><div id='tui-image-editor'></div></body>"
152
+ + "<script>window.onload=function(){setTimeout(function(){parent.rte_image_editor_callback(window)},100)}</script></html>")
153
+ iframe.contentDocument.close();
154
+ }
155
+ }
156
+
157
+
158
+
159
+