@richscripts/richtexteditor 2.14.1 → 2.16.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 (244) hide show
  1. package/README.md +182 -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 +40 -52
  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 +68 -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 +8816 -2373
  17. package/richtexteditor/all_plugins.min.js +77 -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 +1050 -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 +1056 -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 +1056 -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 +1056 -2
  60. package/richtexteditor/lang/rte-lang-ja.js +1056 -2
  61. package/richtexteditor/lang/rte-lang-kn.js +1 -0
  62. package/richtexteditor/lang/rte-lang-ko.js +1056 -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 +1056 -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 +1056 -2
  78. package/richtexteditor/lang/rte-lang-pt.js +1056 -2
  79. package/richtexteditor/lang/rte-lang-ro.js +1 -0
  80. package/richtexteditor/lang/rte-lang-ru.js +1056 -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 +1050 -2
  101. package/richtexteditor/lang/rte-lang-zh-Hant.js +1050 -2
  102. package/richtexteditor/plugins/a11yenhance.js +4 -1
  103. package/richtexteditor/plugins/a11yenhance.min.js +1 -1
  104. package/richtexteditor/plugins/accessibilitychecker.js +256 -64
  105. package/richtexteditor/plugins/accessibilitychecker.min.js +1 -1
  106. package/richtexteditor/plugins/aitoolkit.js +1057 -386
  107. package/richtexteditor/plugins/aitoolkit.min.js +7 -7
  108. package/richtexteditor/plugins/all_plugins.js +8816 -2373
  109. package/richtexteditor/plugins/all_plugins.min.js +77 -59
  110. package/richtexteditor/plugins/autocorrect.js +66 -31
  111. package/richtexteditor/plugins/autocorrect.min.js +1 -1
  112. package/richtexteditor/plugins/autoembed.js +18 -1
  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 +460 -61
  123. package/richtexteditor/plugins/comments.min.js +4 -3
  124. package/richtexteditor/plugins/contentminimap.js +28 -9
  125. package/richtexteditor/plugins/contentminimap.min.js +1 -1
  126. package/richtexteditor/plugins/crdt-engine.js +27 -1
  127. package/richtexteditor/plugins/crossreference.js +1 -1
  128. package/richtexteditor/plugins/crossreference.min.js +1 -1
  129. package/richtexteditor/plugins/dialoga11y.js +26 -4
  130. package/richtexteditor/plugins/dialoga11y.min.js +1 -1
  131. package/richtexteditor/plugins/dictation.js +1 -1
  132. package/richtexteditor/plugins/documentimport.js +250 -59
  133. package/richtexteditor/plugins/documentimport.min.js +4 -4
  134. package/richtexteditor/plugins/documentoutline.js +47 -8
  135. package/richtexteditor/plugins/documentoutline.min.js +1 -1
  136. package/richtexteditor/plugins/docxexport.js +233 -32
  137. package/richtexteditor/plugins/docxexport.min.js +2 -2
  138. package/richtexteditor/plugins/draghandle.js +267 -3
  139. package/richtexteditor/plugins/draghandle.min.js +1 -1
  140. package/richtexteditor/plugins/emailtoolkit.js +28 -14
  141. package/richtexteditor/plugins/emailtoolkit.min.js +1 -1
  142. package/richtexteditor/plugins/emojiautocomplete.js +111 -57
  143. package/richtexteditor/plugins/emojiautocomplete.min.js +1 -1
  144. package/richtexteditor/plugins/footnotes.js +65 -11
  145. package/richtexteditor/plugins/footnotes.min.js +1 -1
  146. package/richtexteditor/plugins/formatpainter.js +10 -0
  147. package/richtexteditor/plugins/formatpainter.min.js +1 -1
  148. package/richtexteditor/plugins/formattingmarks.js +6 -6
  149. package/richtexteditor/plugins/formattingmarks.min.js +1 -1
  150. package/richtexteditor/plugins/gapcursor.js +60 -0
  151. package/richtexteditor/plugins/gapcursor.min.js +1 -1
  152. package/richtexteditor/plugins/ghostcomplete.js +1 -1
  153. package/richtexteditor/plugins/html2pdf.js +8 -8
  154. package/richtexteditor/plugins/html2pdf.min.js +1 -1
  155. package/richtexteditor/plugins/imageeditor.js +31 -12
  156. package/richtexteditor/plugins/imageeditor.min.js +1 -1
  157. package/richtexteditor/plugins/importstyles.js +1 -1
  158. package/richtexteditor/plugins/inlinecode.js +25 -0
  159. package/richtexteditor/plugins/inlinecode.min.js +1 -1
  160. package/richtexteditor/plugins/insertcode.js +29 -11
  161. package/richtexteditor/plugins/insertcode.min.js +6 -6
  162. package/richtexteditor/plugins/insertemoji.js +113 -16
  163. package/richtexteditor/plugins/insertemoji.min.js +1 -1
  164. package/richtexteditor/plugins/insertgallery.js +46 -40
  165. package/richtexteditor/plugins/insertgallery.min.js +1 -1
  166. package/richtexteditor/plugins/inserttemplate.js +43 -19
  167. package/richtexteditor/plugins/inserttemplate.min.js +1 -1
  168. package/richtexteditor/plugins/keyboarda11y.js +66 -3
  169. package/richtexteditor/plugins/keyboarda11y.min.js +1 -1
  170. package/richtexteditor/plugins/layouttable.js +20 -0
  171. package/richtexteditor/plugins/layouttable.min.js +1 -1
  172. package/richtexteditor/plugins/linkchecker.js +29 -9
  173. package/richtexteditor/plugins/linkchecker.min.js +1 -1
  174. package/richtexteditor/plugins/localdraft.js +51 -7
  175. package/richtexteditor/plugins/localdraft.min.js +1 -1
  176. package/richtexteditor/plugins/markdownexport.js +159 -0
  177. package/richtexteditor/plugins/markdownexport.min.js +2 -2
  178. package/richtexteditor/plugins/mathdialog.js +11 -5
  179. package/richtexteditor/plugins/mathdialog.min.js +1 -1
  180. package/richtexteditor/plugins/mentionplugin.js +90 -27
  181. package/richtexteditor/plugins/mentionplugin.min.js +1 -1
  182. package/richtexteditor/plugins/mermaiddiagram.js +14 -8
  183. package/richtexteditor/plugins/mermaiddiagram.min.js +2 -2
  184. package/richtexteditor/plugins/multilevellist.js +4 -0
  185. package/richtexteditor/plugins/multilevellist.min.js +1 -1
  186. package/richtexteditor/plugins/nodetypes.js +1 -1
  187. package/richtexteditor/plugins/nodetypes.min.js +1 -1
  188. package/richtexteditor/plugins/pagination.js +2 -2
  189. package/richtexteditor/plugins/pagination.min.js +1 -1
  190. package/richtexteditor/plugins/pdfexport.js +1752 -1167
  191. package/richtexteditor/plugins/pdfexport.min.js +28 -13
  192. package/richtexteditor/plugins/permanentpen.js +3 -3
  193. package/richtexteditor/plugins/permanentpen.min.js +1 -1
  194. package/richtexteditor/plugins/readabilitystats.js +25 -11
  195. package/richtexteditor/plugins/readabilitystats.min.js +1 -1
  196. package/richtexteditor/plugins/readaloud.js +30 -16
  197. package/richtexteditor/plugins/readaloud.min.js +1 -1
  198. package/richtexteditor/plugins/restrictedediting.js +166 -0
  199. package/richtexteditor/plugins/restrictedediting.min.js +2 -2
  200. package/richtexteditor/plugins/revisionhistory.js +173 -41
  201. package/richtexteditor/plugins/revisionhistory.min.js +3 -3
  202. package/richtexteditor/plugins/rubyannotation.js +21 -11
  203. package/richtexteditor/plugins/rubyannotation.min.js +1 -1
  204. package/richtexteditor/plugins/sanitizer.js +119 -7
  205. package/richtexteditor/plugins/sanitizer.min.js +1 -1
  206. package/richtexteditor/plugins/slashcommand.js +32 -18
  207. package/richtexteditor/plugins/slashcommand.min.js +2 -2
  208. package/richtexteditor/plugins/smartchips.js +39 -25
  209. package/richtexteditor/plugins/smartchips.min.js +2 -2
  210. package/richtexteditor/plugins/spellcheck.js +20 -11
  211. package/richtexteditor/plugins/spellcheck.min.js +2 -2
  212. package/richtexteditor/plugins/stateinspector.js +21 -11
  213. package/richtexteditor/plugins/stateinspector.min.js +2 -2
  214. package/richtexteditor/plugins/structured-content-bridge.js +90 -32
  215. package/richtexteditor/plugins/structured-content-bridge.min.js +8 -8
  216. package/richtexteditor/plugins/tableofcontents.js +5 -2
  217. package/richtexteditor/plugins/tableofcontents.min.js +1 -1
  218. package/richtexteditor/plugins/tabletools.js +388 -3
  219. package/richtexteditor/plugins/tabletools.min.js +1 -1
  220. package/richtexteditor/plugins/textdirection.js +19 -6
  221. package/richtexteditor/plugins/textdirection.min.js +1 -1
  222. package/richtexteditor/plugins/textpartlanguage.js +161 -32
  223. package/richtexteditor/plugins/textpartlanguage.min.js +1 -1
  224. package/richtexteditor/plugins/todolist.js +90 -6
  225. package/richtexteditor/plugins/todolist.min.js +1 -1
  226. package/richtexteditor/plugins/trackedchanges.js +1812 -25
  227. package/richtexteditor/plugins/trackedchanges.min.js +5 -3
  228. package/richtexteditor/plugins/wordexport.js +2 -2
  229. package/richtexteditor/plugins/yjscollab.js +11 -6
  230. package/richtexteditor/plugins/yjscollab.min.js +1 -1
  231. package/richtexteditor/plugins/zz_richtextbox_dialog_style.js +22 -13
  232. package/richtexteditor/plugins/zz_richtextbox_dialog_style.min.js +1 -1
  233. package/richtexteditor/rte-config.js +144 -86
  234. package/richtexteditor/rte-headless.js +19 -4
  235. package/richtexteditor/rte-watchdog.js +3 -1
  236. package/richtexteditor/rte-webcomponent.js +91 -16
  237. package/richtexteditor/rte.js +146 -88
  238. package/richtexteditor/runtime/colorpicker_more_ns.htm +3 -1
  239. package/scripts/build-angular.mjs +97 -0
  240. package/svelte/index.d.ts +2 -1
  241. package/svelte/index.js +80 -9
  242. package/vue/index.js +130 -34
  243. package/angular/component.ts +0 -297
  244. package/angular/index.ts +0 -24
@@ -33,6 +33,12 @@ function RTE_Plugin_InsertGallery() {
33
33
 
34
34
  obj.PluginName = "InsertGallery";
35
35
 
36
+ // 2026-10-18 the gallery's words read config.text_gl_* (language packs), English as the fallback; {0} fills a
37
+ // template. tools/i18n/gallery-language.mjs
38
+ function glText(key, fallback, arg) {
39
+ var s = (config && config["text_" + key]) || fallback;
40
+ return arg === undefined ? s : s.split("{0}").join(String(arg));
41
+ }
36
42
  obj.InitConfig = function (argconfig) {
37
43
  config = argconfig;
38
44
  if (!config.galleryImages) {
@@ -113,7 +119,7 @@ function RTE_Plugin_InsertGallery() {
113
119
  name = decodeURIComponent(name);
114
120
  } catch (ex) {
115
121
  }
116
- return name || "Image";
122
+ return name || glText("gl_image", "Image");
117
123
  }
118
124
 
119
125
  function humanSize(size) {
@@ -249,14 +255,14 @@ function RTE_Plugin_InsertGallery() {
249
255
  var header = append(browser, "div", "", "rte-dialog-browser-header");
250
256
  var copy = append(header, "div", "", "rte-dialog-browser-copy");
251
257
  copy.innerText = serverMode
252
- ? "Browse folders, upload new files, and insert the selected image into the editor."
253
- : "Browse the available images, filter by name, and insert the selected image into the editor.";
258
+ ? glText("gl_copyserver", "Browse folders, upload new files, and insert the selected image into the editor.")
259
+ : glText("gl_copylocal", "Browse the available images, filter by name, and insert the selected image into the editor.");
254
260
 
255
261
  // State the accepted formats up front. Previously the only way to learn
256
262
  // them was to pick an unsupported file and read "Invalid file extension".
257
263
  var acceptHint = append(header, "div", "", "rte-dialog-browser-accept");
258
- acceptHint.innerText = "Accepted formats: " +
259
- GALLERY_ACCEPT.map(function (ext) { return ext.replace(".", "").toUpperCase(); }).join(", ");
264
+ acceptHint.innerText = glText("gl_accepted", "Accepted formats: {0}",
265
+ GALLERY_ACCEPT.map(function (ext) { return ext.replace(".", "").toUpperCase(); }).join(", "));
260
266
 
261
267
  var toolbar = append(browser, "div", "", "rte-gallery-browser-toolbar");
262
268
  var toolbarLeft = append(toolbar, "div", "", "rte-gallery-browser-toolbar-group");
@@ -264,31 +270,31 @@ function RTE_Plugin_InsertGallery() {
264
270
 
265
271
  var upButton = append(toolbarLeft, "button", "", "rte-gallery-browser-button");
266
272
  upButton.type = "button";
267
- upButton.innerText = "Up";
268
- upButton.setAttribute("aria-label", "Go to the parent folder");
273
+ upButton.innerText = glText("gl_up", "Up");
274
+ upButton.setAttribute("aria-label", glText("gl_uparia", "Go to the parent folder"));
269
275
 
270
276
  var path = append(toolbarLeft, "div", "", "rte-gallery-browser-path");
271
277
  path.innerText = "/";
272
278
 
273
279
  var type = append(toolbarLeft, "div", "", "rte-gallery-browser-type");
274
- type.innerText = "Image files";
280
+ type.innerText = glText("gl_imagefiles", "Image files");
275
281
 
276
282
  var createFolderButton = append(toolbarLeft, "button", "", "rte-gallery-browser-button");
277
283
  createFolderButton.type = "button";
278
- createFolderButton.innerText = "New folder";
284
+ createFolderButton.innerText = glText("gl_newfolder", "New folder");
279
285
 
280
286
  var uploadButton = append(toolbarLeft, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
281
287
  uploadButton.type = "button";
282
- uploadButton.innerText = "Upload";
288
+ uploadButton.innerText = glText("gl_upload", "Upload");
283
289
 
284
290
  var refreshButton = append(toolbarLeft, "button", "", "rte-gallery-browser-button");
285
291
  refreshButton.type = "button";
286
- refreshButton.innerText = "Refresh";
292
+ refreshButton.innerText = glText("gl_refresh", "Refresh");
287
293
 
288
294
  var search = append(toolbarRight, "input", "", "rte-gallery-browser-search");
289
295
  search.type = "search";
290
- search.placeholder = "Search images";
291
- search.setAttribute("aria-label", "Search images");
296
+ search.placeholder = glText("gl_search", "Search images");
297
+ search.setAttribute("aria-label", glText("gl_search", "Search images"));
292
298
 
293
299
  var fileInput = append(toolbarRight, "input", "display:none;");
294
300
  fileInput.type = "file";
@@ -312,11 +318,11 @@ function RTE_Plugin_InsertGallery() {
312
318
  // listbox — a non-option child of a listbox is invalid ARIA.
313
319
  var folderGrid = append(surface, "div", "", "rte-gallery-browser-grid rte-gallery-browser-grid-folders");
314
320
  folderGrid.setAttribute("role", "group");
315
- folderGrid.setAttribute("aria-label", "Folders");
321
+ folderGrid.setAttribute("aria-label", glText("gl_folders", "Folders"));
316
322
 
317
323
  var grid = append(surface, "div", "", "rte-gallery-browser-grid");
318
324
  grid.setAttribute("role", "listbox");
319
- grid.setAttribute("aria-label", "Available images");
325
+ grid.setAttribute("aria-label", glText("gl_available", "Available images"));
320
326
 
321
327
  // Non-blocking failure notice. Sits above the grid instead of replacing
322
328
  // it, so a rejected upload never hides the images you can still pick.
@@ -331,11 +337,11 @@ function RTE_Plugin_InsertGallery() {
331
337
 
332
338
  var cancelButton = append(footer, "button", "", "rte-gallery-browser-button");
333
339
  cancelButton.type = "button";
334
- cancelButton.innerText = "Cancel";
340
+ cancelButton.innerText = glText("cancel", "Cancel");
335
341
 
336
342
  var insertButton = append(footer, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
337
343
  insertButton.type = "button";
338
- insertButton.innerText = "Insert";
344
+ insertButton.innerText = glText("insert", "Insert");
339
345
 
340
346
  var state = {
341
347
  currentFolder: "",
@@ -394,20 +400,20 @@ function RTE_Plugin_InsertGallery() {
394
400
 
395
401
  function updateStatus(folderCount, imageCount) {
396
402
  var total = folderCount + imageCount;
397
- var where = serverMode ? (" in " + state.currentFolderDisplay) : "";
398
- var message = total + " item" + (total === 1 ? "" : "s") + where + ". ";
403
+ var where = serverMode ? glText("gl_in", " in {0}", state.currentFolderDisplay) : "";
404
+ var message = (total === 1 ? glText("gl_item", "1 item") : glText("gl_items", "{0} items", total)) + where + ". ";
399
405
 
400
406
  if (!state.selectedUrl) {
401
- status.innerText = message + "No image selected.";
407
+ status.innerText = message + glText("gl_noselection", "No image selected.");
402
408
  footerText.innerText = state.fallbackMode && serverMode
403
- ? "Showing packaged gallery items. Uploads still save into the current folder."
404
- : "Choose an image to enable insert.";
409
+ ? glText("gl_presetnote", "Showing packaged gallery items. Uploads still save into the current folder.")
410
+ : glText("gl_choose", "Choose an image to enable insert.");
405
411
  setDisabled(insertButton, true);
406
412
  return;
407
413
  }
408
414
 
409
415
  var selectedName = getFileName(state.selectedUrl);
410
- status.innerText = message + "Selected: " + selectedName + ".";
416
+ status.innerText = message + glText("gl_selected", "Selected: {0}.", selectedName);
411
417
  setDisabled(insertButton, state.loading);
412
418
 
413
419
  for (var index = 0; index < state.images.length; index++) {
@@ -424,10 +430,10 @@ function RTE_Plugin_InsertGallery() {
424
430
  function createFolderCard(item) {
425
431
  var button = append(folderGrid, "button", "", "rte-gallery-browser-card rte-gallery-folder-card");
426
432
  button.type = "button";
427
- button.title = "Open " + item.name;
433
+ button.title = glText("gl_open", "Open {0}", item.name);
428
434
 
429
435
  var selection = append(button, "div", "", "rte-gallery-browser-selection");
430
- selection.innerHTML = "&nbsp;";
436
+ selection.innerHTML = __RTE_TT("&nbsp;");
431
437
 
432
438
  var thumbnail = append(button, "div", "", "rte-gallery-browser-thumbnail rte-gallery-browser-thumbnail-folder");
433
439
  append(thumbnail, "div", "", "rte-gallery-browser-folder-icon");
@@ -436,7 +442,7 @@ function RTE_Plugin_InsertGallery() {
436
442
  label.innerText = item.name;
437
443
 
438
444
  var meta = append(button, "div", "", "rte-gallery-browser-meta");
439
- meta.innerText = "Folder";
445
+ meta.innerText = glText("gl_folder", "Folder");
440
446
 
441
447
  button.onclick = function () {
442
448
  loadFolder(item.folder);
@@ -452,7 +458,7 @@ function RTE_Plugin_InsertGallery() {
452
458
  button.setAttribute("aria-selected", isSelected ? "true" : "false");
453
459
 
454
460
  var selection = append(button, "div", "", "rte-gallery-browser-selection");
455
- selection.innerHTML = isSelected ? "&#10003;" : "&nbsp;";
461
+ selection.innerHTML = __RTE_TT(isSelected ? "&#10003;" : "&nbsp;");
456
462
 
457
463
  var thumbnail = append(button, "div", "", "rte-gallery-browser-thumbnail");
458
464
  var image = append(thumbnail, "img", "", "rte-gallery-browser-thumbnail-image");
@@ -463,7 +469,7 @@ function RTE_Plugin_InsertGallery() {
463
469
  label.innerText = item.name;
464
470
 
465
471
  var meta = append(button, "div", "", "rte-gallery-browser-meta");
466
- meta.innerText = item.meta || (item.source === "preset" ? "Preset image" : humanSize(item.size)) || item.url;
472
+ meta.innerText = item.meta || (item.source === "preset" ? glText("gl_preset", "Preset image") : humanSize(item.size)) || item.url;
467
473
 
468
474
  button.onclick = function () {
469
475
  setSelected(item.url);
@@ -510,14 +516,14 @@ function RTE_Plugin_InsertGallery() {
510
516
  setDisabled(uploadButton, state.loading);
511
517
  setDisabled(refreshButton, state.loading);
512
518
 
513
- folderGrid.innerHTML = "";
514
- grid.innerHTML = "";
519
+ folderGrid.innerHTML = __RTE_TT("");
520
+ grid.innerHTML = __RTE_TT("");
515
521
  show(empty, false);
516
522
  show(folderGrid, false);
517
523
  show(grid, true);
518
524
 
519
525
  if (state.loading) {
520
- empty.innerText = "Loading gallery...";
526
+ empty.innerText = glText("gl_loading", "Loading gallery...");
521
527
  show(empty, true);
522
528
  show(grid, false);
523
529
  updateStatus(0, 0);
@@ -550,10 +556,10 @@ function RTE_Plugin_InsertGallery() {
550
556
 
551
557
  if (!visibleFolders.length && !visibleImages.length) {
552
558
  empty.innerText = search.value
553
- ? "No folders or images match the current filter."
559
+ ? glText("gl_nomatch", "No folders or images match the current filter.")
554
560
  : (serverMode
555
- ? "This folder is empty. Create a folder or upload an image to get started."
556
- : "No images are available. Upload a file to get started.");
561
+ ? glText("gl_emptyfolder", "This folder is empty. Create a folder or upload an image to get started.")
562
+ : glText("gl_noimages", "No images are available. Upload a file to get started."));
557
563
  show(empty, true);
558
564
  }
559
565
  }
@@ -613,7 +619,7 @@ function RTE_Plugin_InsertGallery() {
613
619
  images: []
614
620
  }, true);
615
621
  state.images = presetImages.slice(0);
616
- state.error = presetImages.length ? "" : ("The image gallery is unavailable right now (" + errorCode + ").");
622
+ state.error = presetImages.length ? "" : glText("gl_unavailable", "The image gallery is unavailable right now ({0}).", errorCode);
617
623
  state.loading = false;
618
624
  render();
619
625
  }
@@ -652,7 +658,7 @@ function RTE_Plugin_InsertGallery() {
652
658
  }
653
659
 
654
660
  function createFolder() {
655
- var folderName = window.prompt("New folder name", "");
661
+ var folderName = window.prompt(glText("gl_foldername", "New folder name"), "");
656
662
  if (!folderName) {
657
663
  return;
658
664
  }
@@ -669,7 +675,7 @@ function RTE_Plugin_InsertGallery() {
669
675
  requestJson("POST", endpoint, formData, function (payload, errorCode) {
670
676
  if (errorCode) {
671
677
  state.loading = false;
672
- state.error = "The folder could not be created right now.";
678
+ state.error = glText("gl_foldererror", "The folder could not be created right now.");
673
679
  render();
674
680
  return;
675
681
  }
@@ -774,7 +780,7 @@ function RTE_Plugin_InsertGallery() {
774
780
  if (url) {
775
781
  uploadedUrls.push(url);
776
782
  } else {
777
- problems.push(typeof errorText === "string" && errorText ? errorText : ("Upload failed for " + file.name + "."));
783
+ problems.push(typeof errorText === "string" && errorText ? errorText : glText("gl_uploadfailed", "Upload failed for {0}.", file.name));
778
784
  }
779
785
  uploadNext(nextIndex + 1);
780
786
  }
@@ -782,7 +788,7 @@ function RTE_Plugin_InsertGallery() {
782
788
  try {
783
789
  if (uploadToFolder) {
784
790
  window.richTextBoxUploadFile(file, function (url, errorCode) {
785
- done(errorCode ? "" : url, errorCode ? ("Upload failed for " + file.name + ".") : "");
791
+ done(errorCode ? "" : url, errorCode ? glText("gl_uploadfailed", "Upload failed for {0}.", file.name) : "");
786
792
  }, { folder: state.currentFolder }, nextIndex, files);
787
793
  return;
788
794
  }
@@ -792,7 +798,7 @@ function RTE_Plugin_InsertGallery() {
792
798
  }, nextIndex, files);
793
799
  } catch (ex) {
794
800
  // a handler that throws must not leave the dialog stuck on "Loading"
795
- done("", "Upload failed for " + file.name + ".");
801
+ done("", glText("gl_uploadfailed", "Upload failed for {0}.", file.name));
796
802
  }
797
803
  }
798
804
 
@@ -1 +1 @@
1
- RTE_DefaultConfig.plugin_insertgallery=RTE_Plugin_InsertGallery;function RTE_Plugin_InsertGallery(){var L=this,T,F;L.PluginName="InsertGallery",L.InitConfig=function(e){T=e,T.galleryImages||(T.galleryImages=[])},L.InitEditor=function(e){F=e,F.attachEvent("exec_command_insertgallery",function(a){a.returnValue=!0,L.DoInsertGallery()})};function i(e,a,d,g){var u=e.ownerDocument.createElement(a);return d&&(u.style.cssText=d),g&&(u.className=g),e.appendChild(u),u}function ge(){return T.galleryEndpoint||window.RichTextBoxGalleryUrl||""}function ve(e,a){var d=e.indexOf("?")>=0?"&":"?";return e+d+"folder="+encodeURIComponent(a||"")}function re(e,a,d,g){var u=new XMLHttpRequest;if(u.open(e,a,!0),u.onreadystatechange=function(){if(u.readyState===4){if(u.status<200||u.status>=300){g(null,"http-"+u.status);return}try{g(JSON.parse(u.responseText),null)}catch{g(null,"invalid-json")}}},u.onerror=function(){g(null,"network-error")},d){u.send(d);return}u.send()}function x(e){var a=String(e||"").split("#")[0].split("?")[0],d=a.lastIndexOf("/"),g=d>=0?a.substring(d+1):a;try{g=decodeURIComponent(g)}catch{}return g||"Image"}function P(e){return e?e<1024?e+" B":e<1024*1024?Math.round(e/1024)+" KB":Math.round(e*10/(1024*1024))/10+" MB":""}function te(e){var a=null;if(typeof e=="string")a={url:e,thumbnail:e,name:x(e)};else if(e instanceof Array)a={url:e[0],thumbnail:e[0],name:e[1]||x(e[0]),meta:e[2]||""};else if(e&&typeof e=="object"){var d=e.url||e.src||e.href;if(!d)return null;a={url:d,thumbnail:e.thumbnail||e.thumb||e.preview||d,name:e.name||e.text||e.title||x(d),meta:e.meta||e.description||e.alt||"",alt:typeof e.alt=="string"?e.alt:void 0}}return!a||!a.url?null:(a.thumbnail=a.thumbnail||a.url,a.name=a.name||x(a.url),a.source="preset",a.folder="",a.searchText=(a.name+" "+(a.meta||"")+" "+a.url).toLowerCase(),a)}function pe(e){if(!e||!e.folder)return null;var a=e.name||x(e.folder)||e.folder;return{name:a,folder:e.folder,searchText:(a+" "+e.folder).toLowerCase()}}function be(e){if(!e||!e.url)return null;var a=e.name||x(e.url);return{name:a,url:e.url,thumbnail:e.thumbnail||e.url,folder:e.folder||"",source:e.source||"upload",size:e.size||0,alt:typeof e.alt=="string"?e.alt:void 0,searchText:(a+" "+e.url).toLowerCase()}}function C(e,a){e.disabled=!!a,a?e.setAttribute("aria-disabled","true"):e.removeAttribute("aria-disabled")}function c(e,a){e.style.display=a?"":"none"}L.DoInsertGallery=function(){var e=ge(),a=!!e,d=typeof window.richTextBoxUploadFile=="function",g=typeof window.rte_file_upload_handler=="function",u=d||g,p=[],ae=T.galleryImages||[],H;for(H=0;H<ae.length;H++){var le=te(ae[H]);le&&p.push(le)}var X=F.createDialog(F.getLangText("insertgallerytitle")||"Image gallery","rte-dialog-insertgallery"),ne=typeof X.close=="function"?function(){X.close()}:function(){F.closeCurrentPopup()},_=i(X,"div","","rte-gallery-browser"),Y=[".jpg",".jpeg",".jfif",".png",".gif",".webp",".bmp",".avif"],oe=i(_,"div","","rte-dialog-browser-header"),he=i(oe,"div","","rte-dialog-browser-copy");he.innerText=a?"Browse folders, upload new files, and insert the selected image into the editor.":"Browse the available images, filter by name, and insert the selected image into the editor.";var ye=i(oe,"div","","rte-dialog-browser-accept");ye.innerText="Accepted formats: "+Y.map(function(r){return r.replace(".","").toUpperCase()}).join(", ");var ie=i(_,"div","","rte-gallery-browser-toolbar"),B=i(ie,"div","","rte-gallery-browser-toolbar-group"),se=i(ie,"div","","rte-gallery-browser-toolbar-group rte-gallery-browser-toolbar-group-right"),k=i(B,"button","","rte-gallery-browser-button");k.type="button",k.innerText="Up",k.setAttribute("aria-label","Go to the parent folder");var Q=i(B,"div","","rte-gallery-browser-path");Q.innerText="/";var me=i(B,"div","","rte-gallery-browser-type");me.innerText="Image files";var j=i(B,"button","","rte-gallery-browser-button");j.type="button",j.innerText="New folder";var M=i(B,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");M.type="button",M.innerText="Upload";var z=i(B,"button","","rte-gallery-browser-button");z.type="button",z.innerText="Refresh";var U=i(se,"input","","rte-gallery-browser-search");U.type="search",U.placeholder="Search images",U.setAttribute("aria-label","Search images");var E=i(se,"input","display:none;");E.type="file",E.accept=Y.join(","),E.multiple=!0,c(k,a),c(Q,a),c(j,a),c(M,u);var q=i(_,"div","","rte-gallery-browser-status");q.setAttribute("role","status"),q.setAttribute("aria-live","polite");var J=i(_,"div","","rte-gallery-browser-surface"),D=i(J,"div","","rte-gallery-browser-grid rte-gallery-browser-grid-folders");D.setAttribute("role","group"),D.setAttribute("aria-label","Folders");var S=i(J,"div","","rte-gallery-browser-grid");S.setAttribute("role","listbox"),S.setAttribute("aria-label","Available images");var N=i(J,"div","","rte-gallery-browser-error");N.setAttribute("role","status"),c(N,!1);var R=i(J,"div","","rte-gallery-browser-empty"),V=i(_,"div","","rte-gallery-browser-footer"),W=i(V,"div","","rte-gallery-browser-footer-text"),Z=i(V,"button","","rte-gallery-browser-button");Z.type="button",Z.innerText="Cancel";var G=i(V,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");G.type="button",G.innerText="Insert";var t={currentFolder:"",currentFolderDisplay:"/",parentFolder:null,folders:[],images:p.slice(0),selectedUrl:"",loading:!1,error:"",fallbackMode:!a};function ue(r){var l=U.value.toLowerCase();if(!l)return r.slice(0);for(var o=[],n=0;n<r.length;n++)r[n].searchText.indexOf(l)>=0&&o.push(r[n]);return o}function fe(r){t.selectedUrl=r||"",t.error="",v()}function de(){for(var r=null,l=0;l<t.images.length;l++)if(t.images[l].url===t.selectedUrl){r=t.images[l];break}r&&(F.insertImageByUrl(r.url,r.alt),ne(),F.focus())}function ce(r,l){var o=r+l,n=a?" in "+t.currentFolderDisplay:"",s=o+" item"+(o===1?"":"s")+n+". ";if(!t.selectedUrl){q.innerText=s+"No image selected.",W.innerText=t.fallbackMode&&a?"Showing packaged gallery items. Uploads still save into the current folder.":"Choose an image to enable insert.",C(G,!0);return}var f=x(t.selectedUrl);q.innerText=s+"Selected: "+f+".",C(G,t.loading);for(var b=0;b<t.images.length;b++)if(t.images[b].url===t.selectedUrl){var h=P(t.images[b].size);W.innerText=f+" ready to insert"+(h?" ("+h+").":".");return}W.innerText=f+" ready to insert."}function we(r){var l=i(D,"button","","rte-gallery-browser-card rte-gallery-folder-card");l.type="button",l.title="Open "+r.name;var o=i(l,"div","","rte-gallery-browser-selection");o.innerHTML="&nbsp;";var n=i(l,"div","","rte-gallery-browser-thumbnail rte-gallery-browser-thumbnail-folder");i(n,"div","","rte-gallery-browser-folder-icon");var s=i(l,"div","","rte-gallery-browser-name");s.innerText=r.name;var f=i(l,"div","","rte-gallery-browser-meta");f.innerText="Folder",l.onclick=function(){O(r.folder)}}function Te(r){var l=r.url===t.selectedUrl,o=i(S,"button","","rte-gallery-browser-card rte-gallery-image-card"+(l?" is-selected":""));o.type="button",o.title=r.name,o.setAttribute("role","option"),o.setAttribute("aria-selected",l?"true":"false");var n=i(o,"div","","rte-gallery-browser-selection");n.innerHTML=l?"&#10003;":"&nbsp;";var s=i(o,"div","","rte-gallery-browser-thumbnail"),f=i(s,"img","","rte-gallery-browser-thumbnail-image");f.src=r.thumbnail||r.url,f.alt=r.name;var b=i(o,"div","","rte-gallery-browser-name");b.innerText=r.name;var h=i(o,"div","","rte-gallery-browser-meta");h.innerText=r.meta||(r.source==="preset"?"Preset image":P(r.size))||r.url,o.onclick=function(){fe(r.url)},o.ondblclick=function(){fe(r.url),de()}}function Fe(r){var l=[],o={},n;for(n=0;n<r.length;n++)l.push(r[n]),o[r[n].url]=!0;if(t.currentFolder)return l;for(n=0;n<p.length;n++)o[p[n].url]||l.push(p[n]);return l}function v(){var r=ue(t.folders),l=ue(t.images);if(Q.innerText=t.currentFolderDisplay||"/",C(k,t.loading||t.parentFolder===null),C(j,t.loading),C(M,t.loading),C(z,t.loading),D.innerHTML="",S.innerHTML="",c(R,!1),c(D,!1),c(S,!0),t.loading){R.innerText="Loading gallery...",c(R,!0),c(S,!1),ce(0,0);return}t.error?(N.innerText=t.error,c(N,!0)):c(N,!1);for(var o=0;o<r.length;o++)we(r[o]);c(D,r.length>0);for(var n=0;n<l.length;n++)Te(l[n]);c(S,l.length>0),ce(r.length,l.length),!r.length&&!l.length&&(R.innerText=U.value?"No folders or images match the current filter.":a?"This folder is empty. Create a folder or upload an image to get started.":"No images are available. Upload a file to get started.",c(R,!0))}function $(r,l){var o=[],n=[],s;if(t.currentFolder=r.currentFolder||"",t.currentFolderDisplay=r.currentFolderDisplay||"/",t.parentFolder=typeof r.parentFolder>"u"?null:r.parentFolder,t.fallbackMode=!!l,t.error="",r.folders)for(s=0;s<r.folders.length;s++){var f=pe(r.folders[s]);f&&o.push(f)}if(r.images)for(s=0;s<r.images.length;s++){var b=be(r.images[s]);b&&n.push(b)}if(t.folders=o,t.images=Fe(n),t.selectedUrl){var h=!1;for(s=0;s<t.images.length;s++)if(t.images[s].url===t.selectedUrl){h=!0;break}h||(t.selectedUrl="")}}function xe(r){$({currentFolder:"",currentFolderDisplay:"/",parentFolder:null,folders:[],images:[]},!0),t.images=p.slice(0),t.error=p.length?"":"The image gallery is unavailable right now ("+r+").",t.loading=!1,v()}var K="";function O(r,l){if(!a){t.images=p.slice(0),v();return}t.loading=!0,t.error="",v(),re("GET",ve(e,r),null,function(o,n){if(n){K="",xe(n);return}$(o||{},!1),l&&(t.selectedUrl=l),t.error=K,K="",t.loading=!1,v()})}function Ue(){var r=window.prompt("New folder name","");if(r){t.loading=!0,t.error="",v();var l=new FormData;l.append("action","create-folder"),l.append("folder",t.currentFolder||""),l.append("name",r),re("POST",e,l,function(o,n){if(n){t.loading=!1,t.error="The folder could not be created right now.",v();return}$(o||{},!1),t.loading=!1,v()})}}function Se(r){var l=String(r.name||"").toLowerCase(),o=l.lastIndexOf(".");if(o<0||Y.indexOf(l.substring(o))<0)return r.name+" is not an accepted image format.";var n=parseInt(T.maxUploadFileSize,10);return n>0&&r.size>n?r.name+" is "+P(r.size)+". The maximum allowed size is "+P(n)+".":""}function Ae(r){var l=[],o=[],n;for(n=0;n<r.length;n++){var s=Se(r[n]);s?o.push(s):l.push(r[n])}if(!u)return;if(!l.length){o.length&&(t.error=o.join(" "),v());return}var f=[];function b(){var m=f.length?f[f.length-1]:"";if(a){K=o.join(" "),O(t.currentFolder,m||t.selectedUrl);return}for(var y=0;y<f.length;y++){var I=te(f[y]);I&&(I.source="upload",p.unshift(I),T.galleryImages.unshift(f[y]))}m&&(t.selectedUrl=m),t.images=p.slice(0),t.loading=!1,t.error=o.join(" "),v()}function h(m){if(m>=l.length){b();return}var y=l[m],I=!1;function ee(A,w){I||(I=!0,A?f.push(A):o.push(typeof w=="string"&&w?w:"Upload failed for "+y.name+"."),h(m+1))}try{if(d){window.richTextBoxUploadFile(y,function(A,w){ee(w?"":A,w?"Upload failed for "+y.name+".":"")},{folder:t.currentFolder},m,l);return}window.rte_file_upload_handler(y,function(A,w){ee(A,w)},m,l)}catch{ee("","Upload failed for "+y.name+".")}}t.loading=!0,t.error="",v(),h(0)}k.onclick=function(){t.parentFolder!==null&&O(t.parentFolder)},j.onclick=Ue,M.onclick=function(){E.click()},E.onchange=function(){Ae(this.files),this.value=""},z.onclick=function(){O(t.currentFolder,t.selectedUrl)},U.oninput=v,Z.onclick=ne,G.onclick=de,a?O(""):v(),U.focus()}}
1
+ RTE_DefaultConfig.plugin_insertgallery=RTE_Plugin_InsertGallery;function RTE_Plugin_InsertGallery(){var I=this,w,F;I.PluginName="InsertGallery";function s(e,l,d){var c=w&&w["text_"+e]||l;return d===void 0?c:c.split("{0}").join(String(d))}I.InitConfig=function(e){w=e,w.galleryImages||(w.galleryImages=[])},I.InitEditor=function(e){F=e,F.attachEvent("exec_command_insertgallery",function(l){l.returnValue=!0,I.DoInsertGallery()})};function i(e,l,d,c){var f=e.ownerDocument.createElement(l);return d&&(f.style.cssText=d),c&&(f.className=c),e.appendChild(f),f}function pe(){return w.galleryEndpoint||window.RichTextBoxGalleryUrl||""}function ve(e,l){var d=e.indexOf("?")>=0?"&":"?";return e+d+"folder="+encodeURIComponent(l||"")}function te(e,l,d,c){var f=new XMLHttpRequest;if(f.open(e,l,!0),f.onreadystatechange=function(){if(f.readyState===4){if(f.status<200||f.status>=300){c(null,"http-"+f.status);return}try{c(JSON.parse(f.responseText),null)}catch{c(null,"invalid-json")}}},f.onerror=function(){c(null,"network-error")},d){f.send(d);return}f.send()}function x(e){var l=String(e||"").split("#")[0].split("?")[0],d=l.lastIndexOf("/"),c=d>=0?l.substring(d+1):l;try{c=decodeURIComponent(c)}catch{}return c||s("gl_image","Image")}function H(e){return e?e<1024?e+" B":e<1024*1024?Math.round(e/1024)+" KB":Math.round(e*10/(1024*1024))/10+" MB":""}function le(e){var l=null;if(typeof e=="string")l={url:e,thumbnail:e,name:x(e)};else if(e instanceof Array)l={url:e[0],thumbnail:e[0],name:e[1]||x(e[0]),meta:e[2]||""};else if(e&&typeof e=="object"){var d=e.url||e.src||e.href;if(!d)return null;l={url:d,thumbnail:e.thumbnail||e.thumb||e.preview||d,name:e.name||e.text||e.title||x(d),meta:e.meta||e.description||e.alt||"",alt:typeof e.alt=="string"?e.alt:void 0}}return!l||!l.url?null:(l.thumbnail=l.thumbnail||l.url,l.name=l.name||x(l.url),l.source="preset",l.folder="",l.searchText=(l.name+" "+(l.meta||"")+" "+l.url).toLowerCase(),l)}function be(e){if(!e||!e.folder)return null;var l=e.name||x(e.folder)||e.folder;return{name:l,folder:e.folder,searchText:(l+" "+e.folder).toLowerCase()}}function he(e){if(!e||!e.url)return null;var l=e.name||x(e.url);return{name:l,url:e.url,thumbnail:e.thumbnail||e.url,folder:e.folder||"",source:e.source||"upload",size:e.size||0,alt:typeof e.alt=="string"?e.alt:void 0,searchText:(l+" "+e.url).toLowerCase()}}function C(e,l){e.disabled=!!l,l?e.setAttribute("aria-disabled","true"):e.removeAttribute("aria-disabled")}function p(e,l){e.style.display=l?"":"none"}I.DoInsertGallery=function(){var e=pe(),l=!!e,d=typeof window.richTextBoxUploadFile=="function",c=typeof window.rte_file_upload_handler=="function",f=d||c,b=[],ae=w.galleryImages||[],z;for(z=0;z<ae.length;z++){var ne=le(ae[z]);ne&&b.push(ne)}var Y=F.createDialog(F.getLangText("insertgallerytitle")||"Image gallery","rte-dialog-insertgallery"),oe=typeof Y.close=="function"?function(){Y.close()}:function(){F.closeCurrentPopup()},R=i(Y,"div","","rte-gallery-browser"),Q=[".jpg",".jpeg",".jfif",".png",".gif",".webp",".bmp",".avif"],ie=i(R,"div","","rte-dialog-browser-header"),ye=i(ie,"div","","rte-dialog-browser-copy");ye.innerText=l?s("gl_copyserver","Browse folders, upload new files, and insert the selected image into the editor."):s("gl_copylocal","Browse the available images, filter by name, and insert the selected image into the editor.");var me=i(ie,"div","","rte-dialog-browser-accept");me.innerText=s("gl_accepted","Accepted formats: {0}",Q.map(function(r){return r.replace(".","").toUpperCase()}).join(", "));var se=i(R,"div","","rte-gallery-browser-toolbar"),B=i(se,"div","","rte-gallery-browser-toolbar-group"),ue=i(se,"div","","rte-gallery-browser-toolbar-group rte-gallery-browser-toolbar-group-right"),k=i(B,"button","","rte-gallery-browser-button");k.type="button",k.innerText=s("gl_up","Up"),k.setAttribute("aria-label",s("gl_uparia","Go to the parent folder"));var V=i(B,"div","","rte-gallery-browser-path");V.innerText="/";var we=i(B,"div","","rte-gallery-browser-type");we.innerText=s("gl_imagefiles","Image files");var j=i(B,"button","","rte-gallery-browser-button");j.type="button",j.innerText=s("gl_newfolder","New folder");var L=i(B,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");L.type="button",L.innerText=s("gl_upload","Upload");var q=i(B,"button","","rte-gallery-browser-button");q.type="button",q.innerText=s("gl_refresh","Refresh");var U=i(ue,"input","","rte-gallery-browser-search");U.type="search",U.placeholder=s("gl_search","Search images"),U.setAttribute("aria-label",s("gl_search","Search images"));var M=i(ue,"input","display:none;");M.type="file",M.accept=Q.join(","),M.multiple=!0,p(k,l),p(V,l),p(j,l),p(L,f);var J=i(R,"div","","rte-gallery-browser-status");J.setAttribute("role","status"),J.setAttribute("aria-live","polite");var K=i(R,"div","","rte-gallery-browser-surface"),D=i(K,"div","","rte-gallery-browser-grid rte-gallery-browser-grid-folders");D.setAttribute("role","group"),D.setAttribute("aria-label",s("gl_folders","Folders"));var S=i(K,"div","","rte-gallery-browser-grid");S.setAttribute("role","listbox"),S.setAttribute("aria-label",s("gl_available","Available images"));var N=i(K,"div","","rte-gallery-browser-error");N.setAttribute("role","status"),p(N,!1);var G=i(K,"div","","rte-gallery-browser-empty"),W=i(R,"div","","rte-gallery-browser-footer"),Z=i(W,"div","","rte-gallery-browser-footer-text"),$=i(W,"button","","rte-gallery-browser-button");$.type="button",$.innerText=s("cancel","Cancel");var O=i(W,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");O.type="button",O.innerText=s("insert","Insert");var t={currentFolder:"",currentFolderDisplay:"/",parentFolder:null,folders:[],images:b.slice(0),selectedUrl:"",loading:!1,error:"",fallbackMode:!l};function de(r){var a=U.value.toLowerCase();if(!a)return r.slice(0);for(var o=[],n=0;n<r.length;n++)r[n].searchText.indexOf(a)>=0&&o.push(r[n]);return o}function fe(r){t.selectedUrl=r||"",t.error="",v()}function ge(){for(var r=null,a=0;a<t.images.length;a++)if(t.images[a].url===t.selectedUrl){r=t.images[a];break}r&&(F.insertImageByUrl(r.url,r.alt),oe(),F.focus())}function ce(r,a){var o=r+a,n=l?s("gl_in"," in {0}",t.currentFolderDisplay):"",u=(o===1?s("gl_item","1 item"):s("gl_items","{0} items",o))+n+". ";if(!t.selectedUrl){J.innerText=u+s("gl_noselection","No image selected."),Z.innerText=t.fallbackMode&&l?s("gl_presetnote","Showing packaged gallery items. Uploads still save into the current folder."):s("gl_choose","Choose an image to enable insert."),C(O,!0);return}var g=x(t.selectedUrl);J.innerText=u+s("gl_selected","Selected: {0}.",g),C(O,t.loading);for(var h=0;h<t.images.length;h++)if(t.images[h].url===t.selectedUrl){var y=H(t.images[h].size);Z.innerText=g+" ready to insert"+(y?" ("+y+").":".");return}Z.innerText=g+" ready to insert."}function _e(r){var a=i(D,"button","","rte-gallery-browser-card rte-gallery-folder-card");a.type="button",a.title=s("gl_open","Open {0}",r.name);var o=i(a,"div","","rte-gallery-browser-selection");o.innerHTML=__RTE_TT("&nbsp;");var n=i(a,"div","","rte-gallery-browser-thumbnail rte-gallery-browser-thumbnail-folder");i(n,"div","","rte-gallery-browser-folder-icon");var u=i(a,"div","","rte-gallery-browser-name");u.innerText=r.name;var g=i(a,"div","","rte-gallery-browser-meta");g.innerText=s("gl_folder","Folder"),a.onclick=function(){P(r.folder)}}function Te(r){var a=r.url===t.selectedUrl,o=i(S,"button","","rte-gallery-browser-card rte-gallery-image-card"+(a?" is-selected":""));o.type="button",o.title=r.name,o.setAttribute("role","option"),o.setAttribute("aria-selected",a?"true":"false");var n=i(o,"div","","rte-gallery-browser-selection");n.innerHTML=__RTE_TT(a?"&#10003;":"&nbsp;");var u=i(o,"div","","rte-gallery-browser-thumbnail"),g=i(u,"img","","rte-gallery-browser-thumbnail-image");g.src=r.thumbnail||r.url,g.alt=r.name;var h=i(o,"div","","rte-gallery-browser-name");h.innerText=r.name;var y=i(o,"div","","rte-gallery-browser-meta");y.innerText=r.meta||(r.source==="preset"?s("gl_preset","Preset image"):H(r.size))||r.url,o.onclick=function(){fe(r.url)},o.ondblclick=function(){fe(r.url),ge()}}function Fe(r){var a=[],o={},n;for(n=0;n<r.length;n++)a.push(r[n]),o[r[n].url]=!0;if(t.currentFolder)return a;for(n=0;n<b.length;n++)o[b[n].url]||a.push(b[n]);return a}function v(){var r=de(t.folders),a=de(t.images);if(V.innerText=t.currentFolderDisplay||"/",C(k,t.loading||t.parentFolder===null),C(j,t.loading),C(L,t.loading),C(q,t.loading),D.innerHTML=__RTE_TT(""),S.innerHTML=__RTE_TT(""),p(G,!1),p(D,!1),p(S,!0),t.loading){G.innerText=s("gl_loading","Loading gallery..."),p(G,!0),p(S,!1),ce(0,0);return}t.error?(N.innerText=t.error,p(N,!0)):p(N,!1);for(var o=0;o<r.length;o++)_e(r[o]);p(D,r.length>0);for(var n=0;n<a.length;n++)Te(a[n]);p(S,a.length>0),ce(r.length,a.length),!r.length&&!a.length&&(G.innerText=U.value?s("gl_nomatch","No folders or images match the current filter."):l?s("gl_emptyfolder","This folder is empty. Create a folder or upload an image to get started."):s("gl_noimages","No images are available. Upload a file to get started."),p(G,!0))}function ee(r,a){var o=[],n=[],u;if(t.currentFolder=r.currentFolder||"",t.currentFolderDisplay=r.currentFolderDisplay||"/",t.parentFolder=typeof r.parentFolder>"u"?null:r.parentFolder,t.fallbackMode=!!a,t.error="",r.folders)for(u=0;u<r.folders.length;u++){var g=be(r.folders[u]);g&&o.push(g)}if(r.images)for(u=0;u<r.images.length;u++){var h=he(r.images[u]);h&&n.push(h)}if(t.folders=o,t.images=Fe(n),t.selectedUrl){var y=!1;for(u=0;u<t.images.length;u++)if(t.images[u].url===t.selectedUrl){y=!0;break}y||(t.selectedUrl="")}}function xe(r){ee({currentFolder:"",currentFolderDisplay:"/",parentFolder:null,folders:[],images:[]},!0),t.images=b.slice(0),t.error=b.length?"":s("gl_unavailable","The image gallery is unavailable right now ({0}).",r),t.loading=!1,v()}var X="";function P(r,a){if(!l){t.images=b.slice(0),v();return}t.loading=!0,t.error="",v(),te("GET",ve(e,r),null,function(o,n){if(n){X="",xe(n);return}ee(o||{},!1),a&&(t.selectedUrl=a),t.error=X,X="",t.loading=!1,v()})}function Ue(){var r=window.prompt(s("gl_foldername","New folder name"),"");if(r){t.loading=!0,t.error="",v();var a=new FormData;a.append("action","create-folder"),a.append("folder",t.currentFolder||""),a.append("name",r),te("POST",e,a,function(o,n){if(n){t.loading=!1,t.error=s("gl_foldererror","The folder could not be created right now."),v();return}ee(o||{},!1),t.loading=!1,v()})}}function Se(r){var a=String(r.name||"").toLowerCase(),o=a.lastIndexOf(".");if(o<0||Q.indexOf(a.substring(o))<0)return r.name+" is not an accepted image format.";var n=parseInt(w.maxUploadFileSize,10);return n>0&&r.size>n?r.name+" is "+H(r.size)+". The maximum allowed size is "+H(n)+".":""}function Ae(r){var a=[],o=[],n;for(n=0;n<r.length;n++){var u=Se(r[n]);u?o.push(u):a.push(r[n])}if(!f)return;if(!a.length){o.length&&(t.error=o.join(" "),v());return}var g=[];function h(){var _=g.length?g[g.length-1]:"";if(l){X=o.join(" "),P(t.currentFolder,_||t.selectedUrl);return}for(var m=0;m<g.length;m++){var E=le(g[m]);E&&(E.source="upload",b.unshift(E),w.galleryImages.unshift(g[m]))}_&&(t.selectedUrl=_),t.images=b.slice(0),t.loading=!1,t.error=o.join(" "),v()}function y(_){if(_>=a.length){h();return}var m=a[_],E=!1;function re(A,T){E||(E=!0,A?g.push(A):o.push(typeof T=="string"&&T?T:s("gl_uploadfailed","Upload failed for {0}.",m.name)),y(_+1))}try{if(d){window.richTextBoxUploadFile(m,function(A,T){re(T?"":A,T?s("gl_uploadfailed","Upload failed for {0}.",m.name):"")},{folder:t.currentFolder},_,a);return}window.rte_file_upload_handler(m,function(A,T){re(A,T)},_,a)}catch{re("",s("gl_uploadfailed","Upload failed for {0}.",m.name))}}t.loading=!0,t.error="",v(),y(0)}k.onclick=function(){t.parentFolder!==null&&P(t.parentFolder)},j.onclick=Ue,L.onclick=function(){M.click()},M.onchange=function(){Ae(this.files),this.value=""},q.onclick=function(){P(t.currentFolder,t.selectedUrl)},U.oninput=v,$.onclick=oe,O.onclick=ge,l?P(""):v(),U.focus()}}
@@ -7,6 +7,12 @@ function RTE_Plugin_InsertTemplate() {
7
7
 
8
8
  obj.PluginName = "InsertTemplate";
9
9
 
10
+ // 2026-10-18 the words read config.text_ keys (language packs), English as the fallback; {0} fills a template.
11
+ // tools/i18n/plugin-panels-language.mjs
12
+ function pText(key, fallback, arg) {
13
+ var s = (config && config["text_" + key]) || fallback;
14
+ return arg === undefined ? s : s.split("{0}").join(String(arg));
15
+ }
10
16
  obj.InitConfig = function (argconfig) {
11
17
  config = argconfig;
12
18
  if (!config.htmlTemplates) {
@@ -43,7 +49,7 @@ function RTE_Plugin_InsertTemplate() {
43
49
 
44
50
  function stripHtml(html) {
45
51
  var div = document.createElement("div");
46
- div.innerHTML = html || "";
52
+ div.innerHTML = __RTE_TT(html || "");
47
53
  return div.innerText || div.textContent || "";
48
54
  }
49
55
 
@@ -51,7 +57,7 @@ function RTE_Plugin_InsertTemplate() {
51
57
  if (item instanceof Array) {
52
58
  return {
53
59
  id: "template-" + index,
54
- title: item[0] || ("Template " + (index + 1)),
60
+ title: item[0] || pText("tp_template", "Template {0}", index + 1),
55
61
  html: item[1] || "",
56
62
  meta: item[2] || ""
57
63
  };
@@ -60,7 +66,7 @@ function RTE_Plugin_InsertTemplate() {
60
66
  if (item && typeof item === "object") {
61
67
  return {
62
68
  id: item.id || ("template-" + index),
63
- title: item.title || item.name || item.text || ("Template " + (index + 1)),
69
+ title: item.title || item.name || item.text || pText("tp_template", "Template {0}", index + 1),
64
70
  html: item.html || item.content || "",
65
71
  meta: item.meta || item.description || ""
66
72
  };
@@ -69,7 +75,7 @@ function RTE_Plugin_InsertTemplate() {
69
75
  if (typeof item === "string") {
70
76
  return {
71
77
  id: "template-" + index,
72
- title: "Template " + (index + 1),
78
+ title: pText("tp_template", "Template {0}", index + 1),
73
79
  html: item,
74
80
  meta: ""
75
81
  };
@@ -103,13 +109,13 @@ function RTE_Plugin_InsertTemplate() {
103
109
  // The outer dialog frame supplies the title bar — only render a subtitle here.
104
110
  var header = append(browser, "div", "", "rte-dialog-browser-header");
105
111
  var copy = append(header, "div", "", "rte-dialog-browser-copy");
106
- copy.innerText = "Preview reusable layouts, search by name, and replace the current editor content with a selected template.";
112
+ copy.innerText = pText("tp_copy", "Preview reusable layouts, search by name, and replace the current editor content with a selected template.");
107
113
 
108
114
  var toolbar = append(browser, "div", "", "rte-dialog-browser-toolbar");
109
115
  var search = append(toolbar, "input", "", "rte-dialog-browser-search");
110
116
  search.type = "search";
111
- search.placeholder = "Search templates";
112
- search.setAttribute("aria-label", "Search templates");
117
+ search.placeholder = pText("tp_search", "Search templates");
118
+ search.setAttribute("aria-label", pText("tp_search", "Search templates"));
113
119
  var count = append(toolbar, "div", "", "rte-dialog-browser-count");
114
120
  count.setAttribute("role", "status");
115
121
  count.setAttribute("aria-live", "polite");
@@ -117,21 +123,21 @@ function RTE_Plugin_InsertTemplate() {
117
123
  var scrollpanel = append(browser, "div", "", "rte-dialog-browser-scrollpanel");
118
124
  var grid = append(scrollpanel, "div", "", "rte-dialog-browser-grid rte-template-grid");
119
125
  grid.setAttribute("role", "listbox");
120
- grid.setAttribute("aria-label", "Available templates");
126
+ grid.setAttribute("aria-label", pText("tp_available", "Available templates"));
121
127
  var empty = append(scrollpanel, "div", "", "rte-dialog-browser-empty");
122
- empty.innerText = "No templates match the current filter.";
128
+ empty.innerText = pText("tp_nomatch", "No templates match the current filter.");
123
129
 
124
130
  var footer = append(browser, "div", "", "rte-gallery-browser-footer");
125
131
  var footerText = append(footer, "div", "", "rte-gallery-browser-footer-text");
126
- footerText.innerText = "Select a template to replace the current content.";
132
+ footerText.innerText = pText("tp_select", "Select a template to replace the current content.");
127
133
 
128
134
  var cancelButton = append(footer, "button", "", "rte-gallery-browser-button");
129
135
  cancelButton.type = "button";
130
- cancelButton.innerText = "Cancel";
136
+ cancelButton.innerText = pText("cancel", "Cancel");
131
137
 
132
138
  var applyButton = append(footer, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
133
139
  applyButton.type = "button";
134
- applyButton.innerText = "Replace Content";
140
+ applyButton.innerText = pText("tp_replace", "Replace Content");
135
141
  applyButton.disabled = true;
136
142
 
137
143
  var selectedId = "";
@@ -174,10 +180,10 @@ function RTE_Plugin_InsertTemplate() {
174
180
  }
175
181
  }
176
182
 
177
- count.innerText = items.length + " template" + (items.length === 1 ? "" : "s");
183
+ count.innerText = items.length === 1 ? pText("tp_count1", "1 template") : pText("tp_countn", "{0} templates", items.length);
178
184
  footerText.innerText = selectedTemplate
179
- ? ("Ready to replace the editor content with " + selectedTemplate.title + ".")
180
- : "Select a template to replace the current content.";
185
+ ? pText("tp_ready", "Ready to replace the editor content with {0}.", selectedTemplate.title)
186
+ : pText("tp_select", "Select a template to replace the current content.");
181
187
  applyButton.disabled = !selectedTemplate;
182
188
  }
183
189
 
@@ -186,7 +192,9 @@ function RTE_Plugin_InsertTemplate() {
186
192
  var i;
187
193
  for (i = 0; i < items.length; i++) {
188
194
  if (items[i].id === selectedId) {
189
- editor.setHTMLCode(items[i].html);
195
+ // 2026-10-03 undoable: Ctrl+Z gives back exactly the document this replaced, edits made just
196
+ // before included (tools/import/replace-undo-plugins.mjs)
197
+ editor.setHTMLCode(items[i].html, { undoable: true });
190
198
  closeDialog();
191
199
  editor.focus();
192
200
  return;
@@ -200,6 +208,14 @@ function RTE_Plugin_InsertTemplate() {
200
208
  var i;
201
209
 
202
210
  empty.style.display = items.length ? "none" : "block";
211
+ // 2026-10-26 with no templates configured at all, "No templates match the current filter." was wrong: say
212
+ // there are none (the default list is empty since it shipped two "My Doc 1" demos).
213
+ // tools/templates/template-defaults.mjs
214
+ if (!items.length) {
215
+ empty.innerText = getTemplates().length
216
+ ? pText("tp_nomatch", "No templates match the current filter.")
217
+ : pText("tp_none", "No templates are available.");
218
+ }
203
219
 
204
220
  for (i = 0; i < items.length; i++) {
205
221
  (function (item) {
@@ -214,18 +230,26 @@ function RTE_Plugin_InsertTemplate() {
214
230
  var preview = append(card, "div", "", "rte-template-card-preview");
215
231
  var previewBody = append(preview, "div", "", "rte-template-card-preview-body");
216
232
  var canvas = append(previewBody, "div", "", "rte-template-card-preview-canvas");
217
- canvas.innerHTML = item.html;
233
+ canvas.innerHTML = __RTE_TT(item.html);
218
234
  scalePreview(previewBody, canvas);
219
235
 
220
236
  var footer = append(card, "div", "", "rte-template-card-footer");
221
237
  var title = append(footer, "div", "", "rte-template-card-title");
222
238
  title.innerText = item.title;
223
239
  var meta = append(footer, "div", "", "rte-template-card-meta");
224
- meta.innerText = item.meta || stripHtml(item.html).substring(0, 80) || "Reusable template";
240
+ meta.innerText = item.meta || stripHtml(item.html).substring(0, 80) || pText("tp_reusable", "Reusable template");
225
241
 
242
+ // 2026-10-03 Select IN PLACE: re-rendering every card here meant the second click of a
243
+ // double-click hit a new element, so Firefox fired no dblclick and nothing was applied.
244
+ // tools/templates/template-dblclick.mjs
226
245
  card.onclick = function () {
227
246
  selectedId = item.id;
228
- render();
247
+ var cards = grid.querySelectorAll(".rte-dialog-browser-card");
248
+ for (var c = 0; c < cards.length; c++) {
249
+ cards[c].classList.toggle("is-selected", cards[c] === card);
250
+ cards[c].setAttribute("aria-selected", cards[c] === card ? "true" : "false");
251
+ }
252
+ updateFooter(getFilteredTemplates());
229
253
  };
230
254
 
231
255
  card.ondblclick = function () {
@@ -1 +1 @@
1
- RTE_DefaultConfig.plugin_inserttemplate=RTE_Plugin_InsertTemplate;function RTE_Plugin_InsertTemplate(){var f=this,b,u;f.PluginName="InsertTemplate",f.InitConfig=function(e){b=e,b.htmlTemplates||(b.htmlTemplates=[])},f.InitEditor=function(e){u=e,u.attachEvent("exec_command_inserttemplate",function(r){r.returnValue=!0,f.DoInsertTemplate()})};function l(e,r,o,v){var c=e.ownerDocument.createElement(r);return o&&(c.style.cssText=o),v&&(c.className=v),e.appendChild(c),c}function _(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function C(e){var r=document.createElement("div");return r.innerHTML=e||"",r.innerText||r.textContent||""}function P(e,r){return e instanceof Array?{id:"template-"+r,title:e[0]||"Template "+(r+1),html:e[1]||"",meta:e[2]||""}:e&&typeof e=="object"?{id:e.id||"template-"+r,title:e.title||e.name||e.text||"Template "+(r+1),html:e.html||e.content||"",meta:e.meta||e.description||""}:typeof e=="string"?{id:"template-"+r,title:"Template "+(r+1),html:e,meta:""}:null}function R(e,r){var o=206,v=166,c=Math.max(r.scrollWidth,1),h=Math.max(r.scrollHeight,1),d=Math.min(1,o/c,v/h);r.style.transformOrigin="top left",r.style.transform="scale("+d+")",r.style.width=c+"px",r.style.height=h+"px"}f.DoInsertTemplate=function(){var e=u.createDialog(u.getLangText("inserttemplatetitle")||"Insert template","rte-dialog-inserttemplate"),r=typeof e.close=="function"?function(){e.close()}:function(){u.closeCurrentPopup()},o=l(e,"div","","rte-dialog-browser"),v=l(o,"div","","rte-dialog-browser-header"),c=l(v,"div","","rte-dialog-browser-copy");c.innerText="Preview reusable layouts, search by name, and replace the current editor content with a selected template.";var h=l(o,"div","","rte-dialog-browser-toolbar"),d=l(h,"input","","rte-dialog-browser-search");d.type="search",d.placeholder="Search templates",d.setAttribute("aria-label","Search templates");var w=l(h,"div","","rte-dialog-browser-count");w.setAttribute("role","status"),w.setAttribute("aria-live","polite");var A=l(o,"div","","rte-dialog-browser-scrollpanel"),g=l(A,"div","","rte-dialog-browser-grid rte-template-grid");g.setAttribute("role","listbox"),g.setAttribute("aria-label","Available templates");var I=l(A,"div","","rte-dialog-browser-empty");I.innerText="No templates match the current filter.";var y=l(o,"div","","rte-gallery-browser-footer"),L=l(y,"div","","rte-gallery-browser-footer-text");L.innerText="Select a template to replace the current content.";var T=l(y,"button","","rte-gallery-browser-button");T.type="button",T.innerText="Cancel";var m=l(y,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");m.type="button",m.innerText="Replace Content",m.disabled=!0;var s="";function k(){var a=[],t=b.htmlTemplates||[],n;for(n=0;n<t.length;n++){var i=P(t[n],n);i&&i.html&&a.push(i)}return a}function S(){var a=d.value.replace(/^\s+|\s+$/g,"").toLowerCase(),t=k();return a?t.filter(function(n){var i=C(n.html).toLowerCase();return n.title.toLowerCase().indexOf(a)>=0||i.indexOf(a)>=0||n.meta&&n.meta.toLowerCase().indexOf(a)>=0}):t}function O(a){var t=null,n;for(n=0;n<a.length;n++)if(a[n].id===s){t=a[n];break}w.innerText=a.length+" template"+(a.length===1?"":"s"),L.innerText=t?"Ready to replace the editor content with "+t.title+".":"Select a template to replace the current content.",m.disabled=!t}function D(){var a=k(),t;for(t=0;t<a.length;t++)if(a[t].id===s){u.setHTMLCode(a[t].html),r(),u.focus();return}}function x(){_(g);var a=S(),t;for(I.style.display=a.length?"none":"block",t=0;t<a.length;t++)(function(i){var p=l(g,"button","","rte-dialog-browser-card");p.type="button",p.setAttribute("role","option"),p.setAttribute("aria-selected",i.id===s?"true":"false"),i.id===s&&p.classList.add("is-selected");var B=l(p,"div","","rte-template-card-preview"),E=l(B,"div","","rte-template-card-preview-body"),H=l(E,"div","","rte-template-card-preview-canvas");H.innerHTML=i.html,R(E,H);var M=l(p,"div","","rte-template-card-footer"),j=l(M,"div","","rte-template-card-title");j.innerText=i.title;var F=l(M,"div","","rte-template-card-meta");F.innerText=i.meta||C(i.html).substring(0,80)||"Reusable template",p.onclick=function(){s=i.id,x()},p.ondblclick=function(){s=i.id,D()}})(a[t]);if(s){var n=!1;for(t=0;t<a.length;t++)if(a[t].id===s){n=!0;break}n||(s="")}O(a)}d.oninput=x,T.onclick=r,m.onclick=D,x(),d.focus()}}
1
+ RTE_DefaultConfig.plugin_inserttemplate=RTE_Plugin_InsertTemplate;function RTE_Plugin_InsertTemplate(){var b=this,h,f;b.PluginName="InsertTemplate";function o(e,t,s){var p=h&&h["text_"+e]||t;return s===void 0?p:p.split("{0}").join(String(s))}b.InitConfig=function(e){h=e,h.htmlTemplates||(h.htmlTemplates=[])},b.InitEditor=function(e){f=e,f.attachEvent("exec_command_inserttemplate",function(t){t.returnValue=!0,b.DoInsertTemplate()})};function l(e,t,s,p){var d=e.ownerDocument.createElement(t);return s&&(d.style.cssText=s),p&&(d.className=p),e.appendChild(d),d}function O(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function I(e){var t=document.createElement("div");return t.innerHTML=__RTE_TT(e||""),t.innerText||t.textContent||""}function j(e,t){return e instanceof Array?{id:"template-"+t,title:e[0]||o("tp_template","Template {0}",t+1),html:e[1]||"",meta:e[2]||""}:e&&typeof e=="object"?{id:e.id||"template-"+t,title:e.title||e.name||e.text||o("tp_template","Template {0}",t+1),html:e.html||e.content||"",meta:e.meta||e.description||""}:typeof e=="string"?{id:"template-"+t,title:o("tp_template","Template {0}",t+1),html:e,meta:""}:null}function B(e,t){var s=206,p=166,d=Math.max(t.scrollWidth,1),g=Math.max(t.scrollHeight,1),v=Math.min(1,s/d,p/g);t.style.transformOrigin="top left",t.style.transform="scale("+v+")",t.style.width=d+"px",t.style.height=g+"px"}b.DoInsertTemplate=function(){var e=f.createDialog(f.getLangText("inserttemplatetitle")||"Insert template","rte-dialog-inserttemplate"),t=typeof e.close=="function"?function(){e.close()}:function(){f.closeCurrentPopup()},s=l(e,"div","","rte-dialog-browser"),p=l(s,"div","","rte-dialog-browser-header"),d=l(p,"div","","rte-dialog-browser-copy");d.innerText=o("tp_copy","Preview reusable layouts, search by name, and replace the current editor content with a selected template.");var g=l(s,"div","","rte-dialog-browser-toolbar"),v=l(g,"input","","rte-dialog-browser-search");v.type="search",v.placeholder=o("tp_search","Search templates"),v.setAttribute("aria-label",o("tp_search","Search templates"));var _=l(g,"div","","rte-dialog-browser-count");_.setAttribute("role","status"),_.setAttribute("aria-live","polite");var k=l(s,"div","","rte-dialog-browser-scrollpanel"),T=l(k,"div","","rte-dialog-browser-grid rte-template-grid");T.setAttribute("role","listbox"),T.setAttribute("aria-label",o("tp_available","Available templates"));var x=l(k,"div","","rte-dialog-browser-empty");x.innerText=o("tp_nomatch","No templates match the current filter.");var C=l(s,"div","","rte-gallery-browser-footer"),E=l(C,"div","","rte-gallery-browser-footer-text");E.innerText=o("tp_select","Select a template to replace the current content.");var A=l(C,"button","","rte-gallery-browser-button");A.type="button",A.innerText=o("cancel","Cancel");var y=l(C,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");y.type="button",y.innerText=o("tp_replace","Replace Content"),y.disabled=!0;var u="";function L(){var r=[],a=h.htmlTemplates||[],n;for(n=0;n<a.length;n++){var i=j(a[n],n);i&&i.html&&r.push(i)}return r}function R(){var r=v.value.replace(/^\s+|\s+$/g,"").toLowerCase(),a=L();return r?a.filter(function(n){var i=I(n.html).toLowerCase();return n.title.toLowerCase().indexOf(r)>=0||i.indexOf(r)>=0||n.meta&&n.meta.toLowerCase().indexOf(r)>=0}):a}function S(r){var a=null,n;for(n=0;n<r.length;n++)if(r[n].id===u){a=r[n];break}_.innerText=r.length===1?o("tp_count1","1 template"):o("tp_countn","{0} templates",r.length),E.innerText=a?o("tp_ready","Ready to replace the editor content with {0}.",a.title):o("tp_select","Select a template to replace the current content."),y.disabled=!a}function D(){var r=L(),a;for(a=0;a<r.length;a++)if(r[a].id===u){f.setHTMLCode(r[a].html,{undoable:!0}),t(),f.focus();return}}function H(){O(T);var r=R(),a;for(x.style.display=r.length?"none":"block",r.length||(x.innerText=L().length?o("tp_nomatch","No templates match the current filter."):o("tp_none","No templates are available.")),a=0;a<r.length;a++)(function(i){var c=l(T,"button","","rte-dialog-browser-card");c.type="button",c.setAttribute("role","option"),c.setAttribute("aria-selected",i.id===u?"true":"false"),i.id===u&&c.classList.add("is-selected");var F=l(c,"div","","rte-template-card-preview"),M=l(F,"div","","rte-template-card-preview-body"),P=l(M,"div","","rte-template-card-preview-canvas");P.innerHTML=__RTE_TT(i.html),B(M,P);var N=l(c,"div","","rte-template-card-footer"),W=l(N,"div","","rte-template-card-title");W.innerText=i.title;var q=l(N,"div","","rte-template-card-meta");q.innerText=i.meta||I(i.html).substring(0,80)||o("tp_reusable","Reusable template"),c.onclick=function(){u=i.id;for(var w=T.querySelectorAll(".rte-dialog-browser-card"),m=0;m<w.length;m++)w[m].classList.toggle("is-selected",w[m]===c),w[m].setAttribute("aria-selected",w[m]===c?"true":"false");S(R())},c.ondblclick=function(){u=i.id,D()}})(r[a]);if(u){var n=!1;for(a=0;a<r.length;a++)if(r[a].id===u){n=!0;break}n||(u="")}S(r)}v.oninput=H,A.onclick=t,y.onclick=D,H(),v.focus()}}