@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
@@ -6,9 +6,53 @@ if (!RTE_DefaultConfig.svgCode_html2pdf) {
6
6
 
7
7
  RTE_DefaultConfig.plugin_html2pdf = RTE_Plugin_Html2PDF;
8
8
 
9
+ // Where to load the html2pdf renderer from. Leave null to use the pinned copy
10
+ // shipped in <url_base>/plugins/vendor/. Set it to serve the bundle from your own
11
+ // CDN, a versioned asset path, or a different build.
12
+ if (typeof RTE_DefaultConfig.html2pdfScriptUrl === "undefined") RTE_DefaultConfig.html2pdfScriptUrl = null;
13
+
9
14
  function RTE_Plugin_Html2PDF() {
10
15
 
11
- var scripturl = "https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js";
16
+ // The html2pdf renderer (jsPDF + html2canvas) is ~900 KB, so it is loaded on
17
+ // demand rather than bundled — but it is served from YOUR OWN assets by
18
+ // default, alongside the rest of the editor.
19
+ //
20
+ // It used to be pulled from a GitHub raw-CDN URL that tracked a branch rather
21
+ // than a release. That meant PDF export required a public network round-trip
22
+ // (so it failed offline / air-gapped), demanded a third-party `script-src`
23
+ // entry in any Content-Security-Policy, and could change underneath the
24
+ // product with no version pin. The bundled copy is pinned at html2pdf.js
25
+ // 0.14.0.
26
+ //
27
+ // Resolution order:
28
+ // 1. config.html2pdfScriptUrl — explicit override (absolute or relative)
29
+ // 2. <url_base>/plugins/vendor/... — the copy shipped with the editor
30
+ // 3. a pinned CDN URL — last resort if url_base is unknown
31
+ var VENDOR_PATH = "/plugins/vendor/html2pdf.bundle.min.js";
32
+ // 2026-07-31 There is deliberately NO built-in CDN fallback any more.
33
+ //
34
+ // A fallback that silently reaches a third-party CDN when url_base happens to
35
+ // be unset is the worst of both worlds: it hides a misconfiguration, and it
36
+ // puts a public URL in a file that security-scanned deployments must ship.
37
+ // Failing loudly is better -- the host either serves the vendored copy or
38
+ // points html2pdfScriptUrl wherever it wants, including its own CDN.
39
+
40
+ // The script tag is written into a generated iframe whose base URL is not the
41
+ // host page, so the URL has to be absolute by the time it is injected.
42
+ function absoluteUrl(url) {
43
+ try { return new URL(url, document.baseURI || location.href).href; }
44
+ catch (e) { return url; }
45
+ }
46
+
47
+ function resolveScriptUrl() {
48
+ if (config && config.html2pdfScriptUrl) return absoluteUrl(config.html2pdfScriptUrl);
49
+ var base = config && config.url_base ? String(config.url_base).replace(/\/+$/, "") : "";
50
+ if (base) return absoluteUrl(base + VENDOR_PATH);
51
+ // No url_base and no explicit override: resolve against the page instead
52
+ // of reaching outside. If that 404s the failure is visible and local,
53
+ // which is what a misconfigured deployment should look like.
54
+ return absoluteUrl("." + VENDOR_PATH);
55
+ }
12
56
 
13
57
  var obj = this;
14
58
 
@@ -36,6 +80,59 @@ function RTE_Plugin_Html2PDF() {
36
80
 
37
81
  }
38
82
 
83
+ // Paper size / orientation / margins for the exported PDF, taken from the
84
+ // document's page setup when it has one. Returns the historical
85
+ // letter/portrait/0.5in defaults otherwise, so documents without a page
86
+ // setup export exactly as they always have.
87
+ obj.GetPdfPageOptions = function () {
88
+ var fallback = { format: 'letter', orientation: 'portrait', margin: 0.5 };
89
+
90
+ var setup = null;
91
+ try {
92
+ if (editor && typeof editor.getDocumentPageSetup === "function") setup = editor.getDocumentPageSetup();
93
+ } catch (e) { setup = null; }
94
+ if (!setup || typeof setup !== "object") return fallback;
95
+
96
+ // jsPDF understands these page-format names.
97
+ var SUPPORTED = { a3: 1, a4: 1, a5: 1, letter: 1, legal: 1, tabloid: 1 };
98
+ var fmt = String(setup.format || "").toLowerCase();
99
+ var orientation = String(setup.orientation || "").toLowerCase() === "landscape" ? "landscape" : fallback.orientation;
100
+
101
+ var result = {
102
+ format: SUPPORTED[fmt] ? fmt : fallback.format,
103
+ orientation: orientation,
104
+ margin: fallback.margin
105
+ };
106
+
107
+ // Margins are emitted in inches, matching jsPDF's unit: 'in'.
108
+ var m = setup.margins;
109
+ if (m && typeof m === "object") {
110
+ var top = __ToInches(m.top), right = __ToInches(m.right);
111
+ var bottom = __ToInches(m.bottom), left = __ToInches(m.left);
112
+ if (top !== null && right !== null && bottom !== null && left !== null) {
113
+ result.margin = [top, right, bottom, left];
114
+ }
115
+ }
116
+ return result;
117
+ };
118
+
119
+ // Accepts a bare number (already inches) or a CSS length string.
120
+ function __ToInches(v) {
121
+ if (typeof v === "number" && isFinite(v)) return v;
122
+ if (typeof v !== "string") return null;
123
+ var m = /^\s*(-?[\d.]+)\s*(mm|cm|in|px|pt)?\s*$/.exec(v);
124
+ if (!m) return null;
125
+ var n = parseFloat(m[1]);
126
+ if (!isFinite(n)) return null;
127
+ switch (m[2]) {
128
+ case "mm": return n / 25.4;
129
+ case "cm": return n / 2.54;
130
+ case "pt": return n / 72;
131
+ case "px": return n / 96;
132
+ default: return n; // bare number or explicit "in"
133
+ }
134
+ }
135
+
39
136
  function __Append(parent, tagname, csstext, cssclass) {
40
137
  var tag = parent.ownerDocument.createElement(tagname);
41
138
  if (csstext) tag.style.cssText = csstext;
@@ -76,12 +173,19 @@ function RTE_Plugin_Html2PDF() {
76
173
 
77
174
  div2.innerHTML = "Exporting...";
78
175
 
176
+ // Honor the document's own page setup (paper size, orientation and
177
+ // margins) so the exported PDF matches the paginated page view and the
178
+ // Word export instead of always emitting US Letter. Falls back to the
179
+ // previous fixed letter/portrait/0.5in defaults when the document
180
+ // carries no page setup, so existing integrations are unaffected.
181
+ var page = obj.GetPdfPageOptions();
182
+
79
183
  var opt = {
80
- margin: 0.5,
184
+ margin: page.margin,
81
185
  filename: 'myfile.pdf',
82
186
  image: { type: 'jpeg', quality: 0.98 },
83
187
  html2canvas: { scale: 2 },
84
- jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
188
+ jsPDF: { unit: 'in', format: page.format, orientation: page.orientation }
85
189
  };
86
190
 
87
191
  var promimg = win.html2pdf().set(opt).from(win.document.body).outputImg();
@@ -145,7 +249,7 @@ function RTE_Plugin_Html2PDF() {
145
249
  iframe = __Append(div1, "iframe", "align-self:center;flex:99;width:100%;height:0px;border:0px;", "rte-editable");
146
250
  iframe.contentDocument.open("text/html");
147
251
  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'>"
252
+ + "<script src='" + editor.htmlEncode(resolveScriptUrl()) + "'></script></head><body style='padding:10px;margin:0px'>"
149
253
  + editor.getHTMLCode() + "</body>"
150
254
  + "<script>window.onload=function(){setTimeout(function(){parent.html2pdf_callback(window)},100)}</script></html>")
151
255
  iframe.contentDocument.close();
@@ -70,14 +70,40 @@ function RTE_Plugin_ImageEditor() {
70
70
  var scriptbase = config.url_base + "/plugins/tui.image-editor/";
71
71
 
72
72
  window.rte_image_editor_callback = function (win) {
73
+ // 2026-07-31 No outbound calls from the image editor, at any layer.
74
+ //
75
+ // Upstream Toast UI ships a "usage statistics" beacon (in
76
+ // tui-code-snippet and tui-color-picker) that reports the host's own
77
+ // hostname to a third-party analytics endpoint, and its default theme
78
+ // loads a branding logo from the vendor's CDN. Both endpoint strings
79
+ // have been removed from the vendored copies in
80
+ // plugins/tui.image-editor/ -- deliberately from the FILES, not just
81
+ // disabled at runtime, because static scanners (Fortify CWE-297) flag
82
+ // the literal URL and a runtime flag does not satisfy them.
83
+ //
84
+ // Do NOT write those hostnames into this file either: it is
85
+ // concatenated into all_plugins.js, which is what customers scan.
86
+ //
87
+ // The settings below are the belt to that braces -- they switch the
88
+ // beacon off through the library's own supported option, so a future
89
+ // vendor upgrade that reintroduces the endpoint still does not phone
90
+ // home until someone re-applies the patch.
91
+ try { win.tui = win.tui || {}; win.tui.usageStatistics = false; } catch (e) {}
92
+
73
93
  var options = {
94
+ usageStatistics: false,
74
95
  includeUI: {
75
96
  loadImage: {
76
97
  path: img.src,
77
98
  name: 'RteImage'
78
99
  },
100
+ usageStatistics: false,
79
101
  //locale: locale_ru_RU,
80
102
  theme: {
103
+ // Blank rather than Toast's CDN-hosted logo.
104
+ 'common.bi.image': '',
105
+ 'common.bisize.width': '0',
106
+ 'common.bisize.height': '0',
81
107
  // main icons
82
108
  'menu.normalIcon.path': scriptbase + 'svg/icon-d.svg',
83
109
  'menu.activeIcon.path': scriptbase + 'svg/icon-b.svg',
@@ -106,7 +132,13 @@ function RTE_Plugin_ImageEditor() {
106
132
  btns.innerHTML = '';
107
133
  var savebtn = __Append(btns, "button", "");
108
134
  savebtn.innerText = "Save";
135
+ var status = __Append(btns, "div", "margin-left:10px;font-size:12px;color:#b42318;", "rte-imageeditor-upload-status");
136
+ status.setAttribute("role", "status");
137
+ status.setAttribute("aria-live", "polite");
109
138
  savebtn.onclick = function () {
139
+ status.innerText = "";
140
+ savebtn.disabled = true;
141
+ savebtn.innerText = "Saving...";
110
142
 
111
143
  var dataurl = imgeditor.toDataURL();
112
144
  if (!config.file_upload_handler) {
@@ -125,13 +157,11 @@ function RTE_Plugin_ImageEditor() {
125
157
  dialoginner.close();
126
158
  return;
127
159
  }
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
- }
160
+ savebtn.disabled = false;
161
+ savebtn.innerText = "Save";
162
+ status.innerText = error
163
+ ? "Upload failed. Check your connection and try again."
164
+ : "The upload did not return a file URL. Please try again.";
135
165
  });
136
166
 
137
167