@richscripts/richtexteditor 2.14.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +173 -10
  2. package/angular/build-manifest.json +23 -0
  3. package/angular/index.d.ts +71 -76
  4. package/angular/index.mjs +2 -0
  5. package/angular/package.json +4 -0
  6. package/headless/index.d.ts +3 -1
  7. package/headless/index.js +72 -16
  8. package/index.d.ts +33 -54
  9. package/integrations/initialization-scope.js +27 -0
  10. package/integrations/native-mount.js +30 -0
  11. package/integrations/shared.d.ts +23 -1
  12. package/integrations/shared.js +58 -22
  13. package/package.json +25 -3
  14. package/react/index.js +118 -37
  15. package/react/index.mjs +29 -0
  16. package/richtexteditor/all_plugins.js +7113 -1111
  17. package/richtexteditor/all_plugins.min.js +62 -59
  18. package/richtexteditor/lang/emoji/LICENSE-CLDR.txt +41 -0
  19. package/richtexteditor/lang/emoji/rte-emoji-de.js +3 -0
  20. package/richtexteditor/lang/emoji/rte-emoji-es.js +3 -0
  21. package/richtexteditor/lang/emoji/rte-emoji-fr.js +3 -0
  22. package/richtexteditor/lang/emoji/rte-emoji-it.js +3 -0
  23. package/richtexteditor/lang/emoji/rte-emoji-ja.js +3 -0
  24. package/richtexteditor/lang/emoji/rte-emoji-ko.js +3 -0
  25. package/richtexteditor/lang/emoji/rte-emoji-nl.js +3 -0
  26. package/richtexteditor/lang/emoji/rte-emoji-pt-pt.js +3 -0
  27. package/richtexteditor/lang/emoji/rte-emoji-pt.js +3 -0
  28. package/richtexteditor/lang/emoji/rte-emoji-ru.js +3 -0
  29. package/richtexteditor/lang/emoji/rte-emoji-zh-Hans.js +3 -0
  30. package/richtexteditor/lang/emoji/rte-emoji-zh-Hant.js +3 -0
  31. package/richtexteditor/lang/rte-lang-af.js +1 -0
  32. package/richtexteditor/lang/rte-lang-ar.js +1 -0
  33. package/richtexteditor/lang/rte-lang-bg.js +1 -0
  34. package/richtexteditor/lang/rte-lang-bn.js +1 -0
  35. package/richtexteditor/lang/rte-lang-bs.js +1 -0
  36. package/richtexteditor/lang/rte-lang-ca.js +1 -0
  37. package/richtexteditor/lang/rte-lang-cs.js +1 -0
  38. package/richtexteditor/lang/rte-lang-cy.js +1 -0
  39. package/richtexteditor/lang/rte-lang-da.js +1 -0
  40. package/richtexteditor/lang/rte-lang-de.js +1017 -2
  41. package/richtexteditor/lang/rte-lang-el.js +1 -0
  42. package/richtexteditor/lang/rte-lang-en.js +1 -0
  43. package/richtexteditor/lang/rte-lang-es.js +1023 -2
  44. package/richtexteditor/lang/rte-lang-et.js +1 -0
  45. package/richtexteditor/lang/rte-lang-fa.js +1 -0
  46. package/richtexteditor/lang/rte-lang-fi.js +1 -0
  47. package/richtexteditor/lang/rte-lang-fil.js +1 -0
  48. package/richtexteditor/lang/rte-lang-fj.js +1 -0
  49. package/richtexteditor/lang/rte-lang-fr.js +1023 -2
  50. package/richtexteditor/lang/rte-lang-ga.js +1 -0
  51. package/richtexteditor/lang/rte-lang-gu.js +1 -0
  52. package/richtexteditor/lang/rte-lang-he.js +1 -0
  53. package/richtexteditor/lang/rte-lang-hi.js +1 -0
  54. package/richtexteditor/lang/rte-lang-hr.js +1 -0
  55. package/richtexteditor/lang/rte-lang-ht.js +1 -0
  56. package/richtexteditor/lang/rte-lang-hu.js +1 -0
  57. package/richtexteditor/lang/rte-lang-id.js +1 -0
  58. package/richtexteditor/lang/rte-lang-is.js +1 -0
  59. package/richtexteditor/lang/rte-lang-it.js +1023 -2
  60. package/richtexteditor/lang/rte-lang-ja.js +1023 -2
  61. package/richtexteditor/lang/rte-lang-kn.js +1 -0
  62. package/richtexteditor/lang/rte-lang-ko.js +1023 -2
  63. package/richtexteditor/lang/rte-lang-lt.js +1 -0
  64. package/richtexteditor/lang/rte-lang-lv.js +1 -0
  65. package/richtexteditor/lang/rte-lang-mg.js +1 -0
  66. package/richtexteditor/lang/rte-lang-mi.js +1 -0
  67. package/richtexteditor/lang/rte-lang-ml.js +1 -0
  68. package/richtexteditor/lang/rte-lang-mr.js +1 -0
  69. package/richtexteditor/lang/rte-lang-ms.js +1 -0
  70. package/richtexteditor/lang/rte-lang-mt.js +1 -0
  71. package/richtexteditor/lang/rte-lang-mww.js +1 -0
  72. package/richtexteditor/lang/rte-lang-nb.js +1 -0
  73. package/richtexteditor/lang/rte-lang-nl.js +1023 -2
  74. package/richtexteditor/lang/rte-lang-otq.js +1 -0
  75. package/richtexteditor/lang/rte-lang-pa.js +1 -0
  76. package/richtexteditor/lang/rte-lang-pl.js +1 -0
  77. package/richtexteditor/lang/rte-lang-pt-pt.js +1023 -2
  78. package/richtexteditor/lang/rte-lang-pt.js +1023 -2
  79. package/richtexteditor/lang/rte-lang-ro.js +1 -0
  80. package/richtexteditor/lang/rte-lang-ru.js +1023 -2
  81. package/richtexteditor/lang/rte-lang-sk.js +1 -0
  82. package/richtexteditor/lang/rte-lang-sl.js +1 -0
  83. package/richtexteditor/lang/rte-lang-sm.js +1 -0
  84. package/richtexteditor/lang/rte-lang-sr-Cyrl.js +1 -0
  85. package/richtexteditor/lang/rte-lang-sr-Latn.js +1 -0
  86. package/richtexteditor/lang/rte-lang-sv.js +1 -0
  87. package/richtexteditor/lang/rte-lang-sw.js +1 -0
  88. package/richtexteditor/lang/rte-lang-ta.js +1 -0
  89. package/richtexteditor/lang/rte-lang-te.js +1 -0
  90. package/richtexteditor/lang/rte-lang-th.js +1 -0
  91. package/richtexteditor/lang/rte-lang-tlh-Latn.js +1 -0
  92. package/richtexteditor/lang/rte-lang-tlh-Piqd.js +1 -0
  93. package/richtexteditor/lang/rte-lang-to.js +1 -0
  94. package/richtexteditor/lang/rte-lang-tr.js +1 -0
  95. package/richtexteditor/lang/rte-lang-ty.js +1 -0
  96. package/richtexteditor/lang/rte-lang-uk.js +1 -0
  97. package/richtexteditor/lang/rte-lang-ur.js +1 -0
  98. package/richtexteditor/lang/rte-lang-vi.js +1 -0
  99. package/richtexteditor/lang/rte-lang-yua.js +1 -0
  100. package/richtexteditor/lang/rte-lang-zh-Hans.js +1017 -2
  101. package/richtexteditor/lang/rte-lang-zh-Hant.js +1017 -2
  102. package/richtexteditor/plugins/a11yenhance.js +2 -1
  103. package/richtexteditor/plugins/a11yenhance.min.js +1 -1
  104. package/richtexteditor/plugins/accessibilitychecker.js +252 -60
  105. package/richtexteditor/plugins/accessibilitychecker.min.js +1 -1
  106. package/richtexteditor/plugins/aitoolkit.js +966 -303
  107. package/richtexteditor/plugins/aitoolkit.min.js +7 -7
  108. package/richtexteditor/plugins/all_plugins.js +7113 -1111
  109. package/richtexteditor/plugins/all_plugins.min.js +62 -59
  110. package/richtexteditor/plugins/autocorrect.js +66 -31
  111. package/richtexteditor/plugins/autocorrect.min.js +1 -1
  112. package/richtexteditor/plugins/autoembed.js +17 -0
  113. package/richtexteditor/plugins/autoembed.min.js +1 -1
  114. package/richtexteditor/plugins/blocktypes.js +18 -9
  115. package/richtexteditor/plugins/blocktypes.min.js +1 -1
  116. package/richtexteditor/plugins/bookmarkcard.js +12 -5
  117. package/richtexteditor/plugins/bookmarkcard.min.js +2 -2
  118. package/richtexteditor/plugins/changecase.js +72 -19
  119. package/richtexteditor/plugins/changecase.min.js +1 -1
  120. package/richtexteditor/plugins/charlimit.js +62 -2
  121. package/richtexteditor/plugins/charlimit.min.js +2 -2
  122. package/richtexteditor/plugins/comments.js +458 -59
  123. package/richtexteditor/plugins/comments.min.js +4 -3
  124. package/richtexteditor/plugins/contentminimap.js +25 -6
  125. package/richtexteditor/plugins/contentminimap.min.js +1 -1
  126. package/richtexteditor/plugins/crossreference.js +1 -1
  127. package/richtexteditor/plugins/crossreference.min.js +1 -1
  128. package/richtexteditor/plugins/dialoga11y.js +26 -4
  129. package/richtexteditor/plugins/dialoga11y.min.js +1 -1
  130. package/richtexteditor/plugins/dictation.js +1 -1
  131. package/richtexteditor/plugins/documentimport.js +220 -51
  132. package/richtexteditor/plugins/documentimport.min.js +4 -4
  133. package/richtexteditor/plugins/documentoutline.js +88 -38
  134. package/richtexteditor/plugins/documentoutline.min.js +1 -1
  135. package/richtexteditor/plugins/docxexport.js +204 -32
  136. package/richtexteditor/plugins/docxexport.min.js +2 -2
  137. package/richtexteditor/plugins/draghandle.js +267 -3
  138. package/richtexteditor/plugins/draghandle.min.js +1 -1
  139. package/richtexteditor/plugins/emailtoolkit.js +28 -14
  140. package/richtexteditor/plugins/emailtoolkit.min.js +1 -1
  141. package/richtexteditor/plugins/emojiautocomplete.js +110 -56
  142. package/richtexteditor/plugins/emojiautocomplete.min.js +1 -1
  143. package/richtexteditor/plugins/footnotes.js +65 -11
  144. package/richtexteditor/plugins/footnotes.min.js +1 -1
  145. package/richtexteditor/plugins/formatpainter.js +10 -0
  146. package/richtexteditor/plugins/formatpainter.min.js +1 -1
  147. package/richtexteditor/plugins/formattingmarks.js +53 -8
  148. package/richtexteditor/plugins/formattingmarks.min.js +1 -1
  149. package/richtexteditor/plugins/gapcursor.js +60 -0
  150. package/richtexteditor/plugins/gapcursor.min.js +1 -1
  151. package/richtexteditor/plugins/ghostcomplete.js +1 -1
  152. package/richtexteditor/plugins/html2pdf.js +1 -1
  153. package/richtexteditor/plugins/html2pdf.min.js +1 -1
  154. package/richtexteditor/plugins/imageeditor.js +12 -6
  155. package/richtexteditor/plugins/imageeditor.min.js +1 -1
  156. package/richtexteditor/plugins/importstyles.js +1 -1
  157. package/richtexteditor/plugins/inlinecode.js +25 -0
  158. package/richtexteditor/plugins/inlinecode.min.js +1 -1
  159. package/richtexteditor/plugins/insertcode.js +21 -3
  160. package/richtexteditor/plugins/insertcode.min.js +4 -4
  161. package/richtexteditor/plugins/insertemoji.js +112 -15
  162. package/richtexteditor/plugins/insertemoji.min.js +1 -1
  163. package/richtexteditor/plugins/insertgallery.js +42 -36
  164. package/richtexteditor/plugins/insertgallery.min.js +1 -1
  165. package/richtexteditor/plugins/inserttemplate.js +33 -17
  166. package/richtexteditor/plugins/inserttemplate.min.js +1 -1
  167. package/richtexteditor/plugins/keyboarda11y.js +66 -3
  168. package/richtexteditor/plugins/keyboarda11y.min.js +1 -1
  169. package/richtexteditor/plugins/layouttable.js +20 -0
  170. package/richtexteditor/plugins/layouttable.min.js +1 -1
  171. package/richtexteditor/plugins/linkchecker.js +29 -9
  172. package/richtexteditor/plugins/linkchecker.min.js +1 -1
  173. package/richtexteditor/plugins/localdraft.js +51 -7
  174. package/richtexteditor/plugins/localdraft.min.js +1 -1
  175. package/richtexteditor/plugins/markdownexport.js +159 -0
  176. package/richtexteditor/plugins/markdownexport.min.js +2 -2
  177. package/richtexteditor/plugins/mathdialog.js +11 -5
  178. package/richtexteditor/plugins/mathdialog.min.js +1 -1
  179. package/richtexteditor/plugins/mentionplugin.js +88 -25
  180. package/richtexteditor/plugins/mentionplugin.min.js +1 -1
  181. package/richtexteditor/plugins/mermaiddiagram.js +9 -3
  182. package/richtexteditor/plugins/mermaiddiagram.min.js +2 -2
  183. package/richtexteditor/plugins/multilevellist.js +4 -0
  184. package/richtexteditor/plugins/multilevellist.min.js +1 -1
  185. package/richtexteditor/plugins/pdfexport.js +235 -35
  186. package/richtexteditor/plugins/pdfexport.min.js +12 -12
  187. package/richtexteditor/plugins/permanentpen.js +3 -3
  188. package/richtexteditor/plugins/permanentpen.min.js +1 -1
  189. package/richtexteditor/plugins/readabilitystats.js +25 -11
  190. package/richtexteditor/plugins/readabilitystats.min.js +1 -1
  191. package/richtexteditor/plugins/readaloud.js +29 -15
  192. package/richtexteditor/plugins/readaloud.min.js +1 -1
  193. package/richtexteditor/plugins/restrictedediting.js +166 -0
  194. package/richtexteditor/plugins/restrictedediting.min.js +2 -2
  195. package/richtexteditor/plugins/revisionhistory.js +169 -37
  196. package/richtexteditor/plugins/revisionhistory.min.js +3 -3
  197. package/richtexteditor/plugins/rubyannotation.js +19 -9
  198. package/richtexteditor/plugins/rubyannotation.min.js +1 -1
  199. package/richtexteditor/plugins/sanitizer.js +86 -4
  200. package/richtexteditor/plugins/sanitizer.min.js +1 -1
  201. package/richtexteditor/plugins/slashcommand.js +30 -16
  202. package/richtexteditor/plugins/slashcommand.min.js +2 -2
  203. package/richtexteditor/plugins/smartchips.js +36 -22
  204. package/richtexteditor/plugins/smartchips.min.js +2 -2
  205. package/richtexteditor/plugins/spellcheck.js +17 -8
  206. package/richtexteditor/plugins/spellcheck.min.js +2 -2
  207. package/richtexteditor/plugins/stateinspector.js +19 -9
  208. package/richtexteditor/plugins/stateinspector.min.js +2 -2
  209. package/richtexteditor/plugins/structured-content-bridge.js +56 -24
  210. package/richtexteditor/plugins/structured-content-bridge.min.js +7 -7
  211. package/richtexteditor/plugins/tableofcontents.js +5 -2
  212. package/richtexteditor/plugins/tableofcontents.min.js +1 -1
  213. package/richtexteditor/plugins/tabletools.js +388 -3
  214. package/richtexteditor/plugins/tabletools.min.js +1 -1
  215. package/richtexteditor/plugins/textdirection.js +18 -5
  216. package/richtexteditor/plugins/textdirection.min.js +1 -1
  217. package/richtexteditor/plugins/textpartlanguage.js +161 -32
  218. package/richtexteditor/plugins/textpartlanguage.min.js +1 -1
  219. package/richtexteditor/plugins/todolist.js +90 -6
  220. package/richtexteditor/plugins/todolist.min.js +1 -1
  221. package/richtexteditor/plugins/trackedchanges.js +1812 -25
  222. package/richtexteditor/plugins/trackedchanges.min.js +5 -3
  223. package/richtexteditor/plugins/wordexport.js +2 -2
  224. package/richtexteditor/plugins/yjscollab.js +9 -4
  225. package/richtexteditor/plugins/yjscollab.min.js +1 -1
  226. package/richtexteditor/plugins/zz_richtextbox_dialog_style.js +22 -13
  227. package/richtexteditor/plugins/zz_richtextbox_dialog_style.min.js +1 -1
  228. package/richtexteditor/rte-config.js +131 -50
  229. package/richtexteditor/rte-headless.js +19 -4
  230. package/richtexteditor/rte-webcomponent.js +89 -16
  231. package/richtexteditor/rte.js +133 -52
  232. package/richtexteditor/runtime/colorpicker_more_ns.htm +93 -16
  233. package/scripts/build-angular.mjs +97 -0
  234. package/svelte/index.d.ts +2 -1
  235. package/svelte/index.js +80 -9
  236. package/vue/index.js +130 -34
  237. package/angular/component.ts +0 -297
  238. package/angular/index.ts +0 -24
@@ -1,3 +1,3 @@
1
- window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.svgCode_revisionhistory||(RTE_DefaultConfig.svgCode_revisionhistory='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/><path d="M12 8v4l3 2"/></svg>'),RTE_DefaultConfig.plugin_revisionhistory=RTE_Plugin_RevisionHistory;function RTE_Plugin_RevisionHistory(){var F=this,a,n,d=null,K=null,L="";F.PluginName="RevisionHistory",F.InitConfig=function(r){a=r,a.revisionHistoryEnabled!==!1&&(a.revisionHistoryMaxEntries=a.revisionHistoryMaxEntries||50,a.revisionHistoryAutoSnapshotMs=a.revisionHistoryAutoSnapshotMs||0,a.revisionHistoryUrl=a.revisionHistoryUrl||"",a.revisionHistoryRequestHeaders=a.revisionHistoryRequestHeaders||null,a.onRevisionHistorySyncError=a.onRevisionHistorySyncError||null,a.text_revisionhistory=a.text_revisionhistory||"Revision history",I("toolbar_default","#{revisionhistory}"),I("toolbar_full","#{revisionhistory}"),I("toolbar_mobile","#{revisionhistory}"),(a.controltoolbar_TEXT||"").indexOf("revisionhistory")===-1&&(a.controltoolbar_TEXT=(a.controltoolbar_TEXT||"")+"|{revisionhistory}"))},F.InitEditor=function(r){n=r,a.revisionHistoryEnabled!==!1&&(n.revisionHistory={snapshot:function(e,t){return j(e,t)},promptAndSnapshot:function(e){return ae(e)},rename:function(e,t){return se(e,t)},list:function(){return C().slice().sort(function(e,t){return(t.createdAt||0)-(e.createdAt||0)})},listNamed:function(){return C().slice().filter(function(e){return e.isNamed===!0}).sort(function(e,t){return(t.createdAt||0)-(e.createdAt||0)})},get:function(e){return g(e)},restore:function(e,t){return B(e,t||{})},delete:function(e){return ee(e)},clear:function(){return ce()},diff:function(e,t){return le(e,t)},openBrowser:function(){V()},closeBrowser:function(){N()}},n.toolbarFactoryMap=n.toolbarFactoryMap||{},n.toolbarFactoryMap.revisionhistory=function(e){return n.createToolbarButton(e)},n.attachEvent("exec_command_revisionhistory",function(e){e.returnValue=!0,e.stopBubble=!0,V()}),ve(),ie(),L=n.getHTML?n.getHTML():"",a.revisionHistoryAutoSnapshotMs>0&&n.getDocument().addEventListener("input",function(){K&&clearTimeout(K),K=setTimeout(function(){var e=n.getHTML();e!==L&&j("Auto",{auto:!0})},a.revisionHistoryAutoSnapshotMs)},!0),n.getDocument().addEventListener("keydown",function(e){(e.ctrlKey||e.metaKey)&&e.shiftKey&&(e.key==="H"||e.key==="h")&&(e.preventDefault(),V())},!0))};function I(r,e){a[r]&&a[r].indexOf(e)===-1&&(a[r]=a[r]+e)}function te(){return a.currentUser&&a.currentUser.id?a.currentUser:{id:"user",name:"User",color:"#64748b"}}function W(){var r=a.aiToolkitPersistenceKey||"default";return"RTE.Revisions."+r}function C(){return n.__revisions||(n.__revisions=[]),n.__revisions}function g(r){for(var e=C(),t=0;t<e.length;t++)if(e[t].id===r)return e[t];return null}function _(){for(var r=C();r.length>a.revisionHistoryMaxEntries;)r.shift();try{window.localStorage&&window.localStorage.setItem(W(),JSON.stringify(r))}catch(e){console.warn("revisionhistory: localStorage quota or access issue:",e&&e.message)}a.revisionHistoryUrl&&ne(r)}function ne(r){try{var e=new XMLHttpRequest;e.open("POST",a.revisionHistoryUrl,!0),e.setRequestHeader("Content-Type","application/json");var t=oe();for(var o in t)if(Object.prototype.hasOwnProperty.call(t,o)&&/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(o)){var l=String(t[o]);if(!/\r|\n/.test(l))try{e.setRequestHeader(o,l)}catch{}}e.onerror=function(){R({reason:"network",status:e.status||0})},e.onload=function(){(e.status<200||e.status>=300)&&R({reason:"http",status:e.status,responseText:(e.responseText||"").slice(0,512)})},e.send(JSON.stringify({documentKey:a.aiToolkitPersistenceKey||"",savedAt:Date.now(),revisions:r}))}catch(c){R({reason:"exception",error:c})}}function oe(){var r=a.revisionHistoryRequestHeaders;if(typeof r=="function")try{r=r(n)}catch(e){return R({reason:"header-provider",error:e}),{}}return r&&typeof r=="object"?r:{}}function R(r){console.warn("revisionhistory: remote persistence failed:",r&&r.reason,r&&r.status);try{typeof a.onRevisionHistorySyncError=="function"&&a.onRevisionHistorySyncError(r)}catch{}try{typeof n.fireEvent=="function"&&n.fireEvent("revision_history_sync_error",r)}catch{}}function ie(){try{if(!window.localStorage)return;var r=window.localStorage.getItem(W());if(!r)return;var e=JSON.parse(r);Array.isArray(e)&&(n.__revisions=e)}catch{}}function j(r,e){var t=n.getHTML?n.getHTML():n.getHTMLCode?n.getHTMLCode():"",o=te(),l=(r||"").toString().slice(0,120),c=l.length>0&&(!e||e.auto!==!0),i={id:"rev-"+Date.now()+"-"+Math.floor(Math.random()*1e4),html:t,text:n.getText?n.getText():S(t),label:l||de(),isNamed:c,author:{id:o.id,name:o.name,color:o.color},createdAt:Date.now(),metadata:e||{}};C().push(i),L=t,_(),d&&d.isConnected&&b();try{typeof n.fireEvent=="function"&&n.fireEvent("revision_snapshot",{id:i.id,label:i.label,isNamed:i.isNamed,createdAt:i.createdAt})}catch{}return i}function ae(r){var e=n.iframe?n.iframe.ownerDocument:document,t=e.defaultView||window,o=t.prompt('Name this version (e.g. "Draft sent to legal"):',r||"");if(o===null)return null;var l=(o||"").trim();return l?j(l,{user:!0}):null}function se(r,e){var t=g(r);if(!t)return!1;var o=(e||"").toString().trim().slice(0,120);return o?(t.label=o,t.isNamed=!0,_(),d&&d.isConnected&&b(),!0):!1}function le(r,e){var t=g(r),o=g(e);if(!t||!o)return null;var l=t.text||S(t.html),c=o.text||S(o.html);return{oldEntry:t,newEntry:o,oldText:l,newText:c,lines:re(l,c)}}function de(){var r=new Date;function e(t){return t<10?"0"+t:""+t}return e(r.getHours())+":"+e(r.getMinutes())+":"+e(r.getSeconds())}function B(r,e){e=e||{};var t=g(r);if(!t)return!1;if(!e.skipConfirm){var o=n.iframe?n.iframe.ownerDocument:document;if(!o.defaultView.confirm("Restore this version? Your current content will be replaced (this itself is not auto-snapshotted)."))return!1}return n.setHTMLCode?n.setHTMLCode(t.html):n.setHTML&&n.setHTML(t.html),L=t.html,d&&d.isConnected&&N(),!0}function ee(r){for(var e=C(),t=0;t<e.length;t++)if(e[t].id===r)return e.splice(t,1),_(),d&&d.isConnected&&b(),!0;return!1}function ce(){n.__revisions=[],_(),d&&d.isConnected&&b()}function re(r,e){for(var t=String(r||"").split(/\r?\n/),o=String(e||"").split(/\r?\n/),l=[],c=fe(t,o),i=0,v=0,s=0;i<t.length&&v<o.length;)s<c.length&&t[i]===c[s]&&o[v]===c[s]?(l.push({type:"eq",text:t[i]}),i++,v++,s++):s<c.length&&t[i]!==c[s]?(l.push({type:"del",text:t[i]}),i++):s<c.length&&o[v]!==c[s]?(l.push({type:"add",text:o[v]}),v++):i<t.length?(l.push({type:"del",text:t[i]}),i++):v<o.length&&(l.push({type:"add",text:o[v]}),v++);for(;i<t.length;)l.push({type:"del",text:t[i]}),i++;for(;v<o.length;)l.push({type:"add",text:o[v]}),v++;return l}function fe(r,e){for(var t=r.length,o=e.length,l=new Array(o+1).fill(0),c=new Array(o+1).fill(0),i=[],s=0;s<=t;s++)i.push(new Array(o+1).fill(0));for(var s=1;s<=t;s++)for(var u=1;u<=o;u++)r[s-1]===e[u-1]?i[s][u]=i[s-1][u-1]+1:i[s][u]=Math.max(i[s-1][u],i[s][u-1]);for(var v=[],s=t,u=o;s>0&&u>0;)r[s-1]===e[u-1]?(v.unshift(r[s-1]),s--,u--):i[s-1][u]>=i[s][u-1]?s--:u--;return v}function S(r){var e=document.createElement("div");return e.innerHTML=r||"",e.innerText||e.textContent||""}function V(){if(!(d&&d.isConnected)&&!(!n||!n.iframe||!n.iframe.ownerDocument)){d&&!d.isConnected&&(d=null);var r=n.iframe.ownerDocument;if(!(!r||!r.body)){d=r.createElement("div");var e=!1;try{var t=n.container||n.getEditable&&n.getEditable().closest&&n.getEditable().closest(".richtexteditor");e=!!(t&&t.classList&&t.classList.contains("rte-dark"))}catch{}d.className="rte-rev-dialog"+(e?" rte-rev-dark":""),d.setAttribute("role","dialog"),d.setAttribute("aria-modal","true"),d.setAttribute("aria-labelledby","rte-rev-dialog-title");var o=r.createElement("div");o.className="rte-rev-backdrop",o.addEventListener("mousedown",function(c){c.target===o&&N()});var l=r.createElement("div");l.className="rte-rev-panel",o.appendChild(l),d.appendChild(o),r.body.appendChild(d),b()}}}function N(){d&&d.parentNode&&d.parentNode.removeChild(d),d=null}var h=null,m="preview";function b(){if(d){var r=d.ownerDocument,e=d.querySelector(".rte-rev-panel");if(!e){N();return}e.innerHTML="";var t=r.createElement("div");t.className="rte-rev-header";var o=r.createElement("div");o.id="rte-rev-dialog-title",o.className="rte-rev-title",o.textContent="Revision history",t.appendChild(o);var l=r.createElement("div");l.className="rte-rev-header-actions";var c=r.createElement("button");c.type="button",c.className="rte-rev-btn rte-rev-btn-ghost",c.textContent="Save version now",c.addEventListener("mousedown",function(f){f.preventDefault();var p=r.defaultView.prompt("Label this version (optional):","");p!==null&&j(p||"")}),l.appendChild(c);var i=r.createElement("button");i.type="button",i.className="rte-rev-btn rte-rev-btn-ghost",i.textContent="Close",i.setAttribute("aria-label","Close revision history"),i.addEventListener("mousedown",function(f){f.preventDefault(),N()}),l.appendChild(i),t.appendChild(l),e.appendChild(t);var v=r.createElement("div");v.className="rte-rev-body";var s=r.createElement("div");s.className="rte-rev-list",s.setAttribute("role","listbox"),s.setAttribute("aria-label","Saved revisions");var u=n.revisionHistory.list();if(u.length){(!h||!g(h))&&(h=u[0].id);for(var Y=0;Y<u.length;Y++)(function(f){var p=r.createElement("button");p.type="button",p.className="rte-rev-row"+(f.id===h?" rte-rev-row-active":""),p.setAttribute("role","option"),p.setAttribute("aria-selected",f.id===h?"true":"false");var Z=r.createElement("span");Z.className="rte-rev-dot",Z.style.background=f.author&&f.author.color||"#64748b";var G=r.createElement("div");G.className="rte-rev-row-who",G.textContent=f.author&&f.author.name||"User";var Q=r.createElement("div");Q.className="rte-rev-row-when",Q.textContent=ue(f.createdAt)+" \xB7 "+(f.label||"");var O=r.createElement("div");O.className="rte-rev-row-col",O.appendChild(G),O.appendChild(Q),p.appendChild(Z),p.appendChild(O),p.addEventListener("mousedown",function(be){be.preventDefault(),h=f.id,b()}),s.appendChild(p)})(u[Y])}else{var X=r.createElement("div");X.className="rte-rev-empty",X.textContent='No revisions yet. Click "Save version now" to capture the current document.',s.appendChild(X)}v.appendChild(s);var A=r.createElement("div");if(A.className="rte-rev-pane",u.length){var x=g(h)||u[0],E=r.createElement("div");E.className="rte-rev-tabs",E.setAttribute("role","tablist"),E.setAttribute("aria-label","Revision view");var y=r.createElement("button");y.type="button",y.className="rte-rev-tab"+(m==="preview"?" rte-rev-tab-active":""),y.setAttribute("role","tab"),y.setAttribute("aria-selected",m==="preview"?"true":"false"),y.textContent="Preview",y.addEventListener("mousedown",function(f){f.preventDefault(),m="preview",b()});var w=r.createElement("button");w.type="button",w.className="rte-rev-tab"+(m==="diff"?" rte-rev-tab-active":""),w.setAttribute("role","tab"),w.setAttribute("aria-selected",m==="diff"?"true":"false"),w.textContent="Diff vs current",w.addEventListener("mousedown",function(f){f.preventDefault(),m="diff",b()}),E.appendChild(y),E.appendChild(w),A.appendChild(E);var q=r.createElement("div");if(q.className="rte-rev-content",m==="preview"){var k=r.createElement("iframe");k.className="rte-rev-preview-frame",k.setAttribute("title","Revision preview"),k.setAttribute("sandbox","allow-same-origin"),q.appendChild(k),setTimeout(function(){try{k.contentDocument.open(),k.contentDocument.write('<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;padding:16px;color:#0f172a;line-height:1.6}img{max-width:100%}</style></head><body>'+(x.html||"")+"</body></html>"),k.contentDocument.close()}catch{}},0)}else{var pe=n.getText?n.getText():S(n.getHTML()),D=re(x.text||S(x.html),pe),J=r.createElement("pre");J.className="rte-rev-diff";for(var H=0;H<D.length;H++){var P=r.createElement("span");P.className="rte-rev-diff-line rte-rev-diff-"+D[H].type,P.textContent=(D[H].type==="add"?"+ ":D[H].type==="del"?"- ":" ")+D[H].text+`
2
- `,J.appendChild(P)}q.appendChild(J)}A.appendChild(q);var U=r.createElement("div");U.className="rte-rev-footer";var $=r.createElement("div");$.className="rte-rev-footer-info",$.textContent=x.label?"Label: "+x.label:"";var z=r.createElement("div");z.className="rte-rev-footer-btns";var M=r.createElement("button");M.type="button",M.className="rte-rev-btn rte-rev-btn-danger",M.textContent="Delete",M.addEventListener("mousedown",function(f){f.preventDefault(),ee(x.id)});var T=r.createElement("button");T.type="button",T.className="rte-rev-btn rte-rev-btn-primary",T.textContent="Restore this version",T.addEventListener("mousedown",function(f){f.preventDefault()}),T.addEventListener("click",function(f){f.preventDefault(),B(x.id)}),z.appendChild(M),z.appendChild(T),U.appendChild($),U.appendChild(z),A.appendChild(U)}v.appendChild(A),e.appendChild(v)}}function ue(r){if(!r)return"";var e=new Date(r),t=new Date;function o(c){return c<10?"0"+c:""+c}var l=o(e.getHours())+":"+o(e.getMinutes());return e.toDateString()===t.toDateString()?"Today "+l:e.getFullYear()+"-"+o(e.getMonth()+1)+"-"+o(e.getDate())+" "+l}function ve(){var r=n&&n.iframe&&n.iframe.ownerDocument||document;if(!r.querySelector("style[data-rte-revisionhistory]")){var e=r.createElement("style");e.setAttribute("data-rte-revisionhistory","1"),e.textContent=[".rte-rev-dialog{position:fixed;inset:0;z-index:2147483600;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:13px;color:#172033}",".rte-rev-backdrop{position:absolute;inset:0;background:linear-gradient(135deg,rgba(12,18,32,.44),rgba(40,54,77,.26));display:flex;align-items:center;justify-content:center;padding:18px}","/* 2026-07-12 revision dialog precision */",".rte-rev-panel{background:linear-gradient(180deg,#ffffff 0%,#f8fbff 100%);border:1px solid rgba(117,137,163,.28);border-radius:8px;width:min(960px,calc(100vw - 28px));max-height:min(82vh,740px);display:flex;flex-direction:column;box-shadow:0 16px 40px rgba(35,48,72,.18);overflow:hidden}",".rte-rev-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border-bottom:1px solid rgba(117,137,163,.18);background:rgba(255,255,255,.72)}",".rte-rev-title{font-size:16px;font-weight:760;letter-spacing:-.01em;color:#172033}",".rte-rev-header-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}",".rte-rev-btn{padding:8px 12px;border-radius:7px;border:1px solid rgba(116,135,162,.25);font:inherit;font-size:12px;font-weight:680;line-height:1;cursor:pointer;background:#fff;color:#223652;box-shadow:0 1px 2px rgba(32,45,66,.06);transition:background .14s ease,border-color .14s ease,box-shadow .14s ease,transform .14s ease}",".rte-rev-btn:hover{background:#f5f8fc;border-color:rgba(81,111,151,.42);box-shadow:0 5px 14px rgba(32,45,66,.09);transform:translateY(-1px)}",".rte-rev-btn:focus-visible{outline:2px solid rgba(56,122,255,.34);outline-offset:2px}",".rte-rev-btn-ghost{background:#fff;color:#34506f}",".rte-rev-btn-primary{background:linear-gradient(135deg,#2563eb,#1d67ba);color:#fff;border-color:rgba(29,103,186,.85);box-shadow:0 8px 18px rgba(37,99,235,.22)}",".rte-rev-btn-primary:hover{background:linear-gradient(135deg,#1d4ed8,#195fad);color:#fff;border-color:rgba(29,78,216,.9);box-shadow:0 9px 20px rgba(37,99,235,.28)}",".rte-rev-btn-danger{background:#fff5f5;color:#9f1d1d;border-color:rgba(190,45,45,.22)}",".rte-rev-body{display:flex;flex:1;min-height:0;background:linear-gradient(90deg,#f8fbff 0%,#fff 42%)}",".rte-rev-list{width:258px;flex:0 0 258px;border-right:1px solid rgba(117,137,163,.18);overflow-y:auto;background:rgba(244,248,253,.78);padding:10px}",".rte-rev-empty{padding:16px;border:1px dashed rgba(99,118,145,.28);border-radius:8px;background:#fff;color:#5b6c81;font-size:12px;line-height:1.5}",".rte-rev-row{display:flex;align-items:center;gap:10px;width:100%;padding:10px;border:1px solid transparent;border-radius:8px;background:transparent;text-align:left;cursor:pointer;font:inherit;color:inherit}",".rte-rev-row:hover{background:#fff;border-color:rgba(93,122,161,.24);box-shadow:0 8px 18px rgba(33,48,70,.08)}",".rte-rev-row-active{background:#eef6ff;border-color:rgba(37,99,235,.28);box-shadow:0 8px 22px rgba(37,99,235,.12)}",".rte-rev-dot{width:9px;height:9px;border-radius:50%;flex:0 0 9px;box-shadow:0 0 0 3px rgba(255,255,255,.95),0 0 0 4px rgba(96,116,140,.18)}",".rte-rev-row-col{flex:1;min-width:0}",".rte-rev-row-who{font-weight:720;font-size:12px;line-height:1.25;color:#172033}",".rte-rev-row-when{margin-top:2px;font-size:11px;color:#637487;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",".rte-rev-pane{flex:1;display:flex;flex-direction:column;min-width:0;padding:10px}",".rte-rev-tabs{display:flex;align-self:flex-start;gap:3px;padding:3px;margin:0 0 10px;border:1px solid rgba(117,137,163,.2);border-radius:7px;background:#eef3f8}",".rte-rev-tab{padding:7px 12px;border:0;border-radius:6px;background:transparent;font:inherit;font-size:12px;font-weight:680;color:#637487;cursor:pointer}",".rte-rev-tab:hover{color:#1d3557;background:rgba(255,255,255,.58)}",".rte-rev-tab:focus-visible{outline:2px solid rgba(56,122,255,.34);outline-offset:2px}",".rte-rev-tab-active{color:#163966;background:#fff;box-shadow:0 2px 7px rgba(35,48,72,.08)}",".rte-rev-content{flex:1;overflow:auto;padding:0;border:1px solid rgba(117,137,163,.18);border-radius:8px;background:#fff;min-height:300px}",".rte-rev-preview-frame{width:100%;height:100%;min-height:330px;border:0;display:block;background:#fff}",".rte-rev-diff{margin:0;padding:14px 16px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.55;white-space:pre-wrap;color:#172033;background:#fbfdff;min-height:100%}",".rte-rev-diff-line{display:block}",".rte-rev-diff-add{background:#e8f8ef;color:#17633f}",".rte-rev-diff-del{background:#fff0f0;color:#9f1d1d}",".rte-rev-diff-eq{color:#556575}",".rte-rev-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 0 0;background:transparent}",".rte-rev-footer-info{font-size:12px;color:#637487;min-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",".rte-rev-footer-btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}","@media(max-width:720px){.rte-rev-backdrop{padding:10px;align-items:flex-start}.rte-rev-panel{width:calc(100vw - 20px);max-height:calc(100vh - 20px);border-radius:8px}.rte-rev-header{align-items:flex-start;flex-direction:column}.rte-rev-body{flex-direction:column}.rte-rev-list{width:auto;flex:0 0 auto;max-height:178px;border-right:0;border-bottom:1px solid rgba(117,137,163,.18)}.rte-rev-pane{min-height:360px}.rte-rev-footer{align-items:stretch;flex-direction:column}.rte-rev-footer-info{white-space:normal}.rte-rev-footer-btns{justify-content:stretch}.rte-rev-footer-btns .rte-rev-btn{flex:1}}",".rte-rev-dark{color:#e2e8f0}",".rte-rev-dark .rte-rev-panel{background:linear-gradient(180deg,#1e293b,#0f172a);border-color:#334155}",".rte-rev-dark .rte-rev-header{background:rgba(30,41,59,.72);border-color:#334155}",".rte-rev-dark .rte-rev-title,.rte-rev-dark .rte-rev-row-who{color:#e2e8f0}",".rte-rev-dark .rte-rev-btn,.rte-rev-dark .rte-rev-btn-ghost{background:#0f172a;color:#cbd5e1;border-color:#334155}",".rte-rev-dark .rte-rev-btn:hover{background:#334155}",".rte-rev-dark .rte-rev-btn-primary,.rte-rev-dark .rte-rev-btn-primary:hover{background:linear-gradient(135deg,#2563eb,#1d4ed8);color:#fff;border-color:#3b82f6}",".rte-rev-dark .rte-rev-body{background:#0f172a}",".rte-rev-dark .rte-rev-list{background:rgba(15,23,42,.6);border-color:#334155}",".rte-rev-dark .rte-rev-empty{background:#1e293b;color:#94a3b8;border-color:#334155}",".rte-rev-dark .rte-rev-row:hover{background:#1e293b;border-color:#334155}",".rte-rev-dark .rte-rev-row-active{background:#1e3a8a;border-color:#3b82f6}",".rte-rev-dark .rte-rev-row-when,.rte-rev-dark .rte-rev-footer-info{color:#94a3b8}",".rte-rev-dark .rte-rev-tabs{background:#1e293b;border-color:#334155}",".rte-rev-dark .rte-rev-tab{color:#94a3b8}.rte-rev-dark .rte-rev-tab-active{color:#fff;background:#1d4ed8}",".rte-rev-dark .rte-rev-diff{background:#0f172a;color:#cbd5e1}.rte-rev-dark .rte-rev-diff-eq{color:#94a3b8}",".rte-rev-dark .rte-rev-diff-add{background:rgba(16,185,129,.16);color:#6ee7b7}",".rte-rev-dark .rte-rev-diff-del{background:rgba(244,63,94,.16);color:#fda4af}"].join(`
3
- `),r.head.appendChild(e),n&&typeof n.ensureStyleSheetLive=="function"&&n.ensureStyleSheetLive(r,e,"rte-revisionhistory-style",e.textContent)}}}
1
+ window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.svgCode_revisionhistory||(RTE_DefaultConfig.svgCode_revisionhistory='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/><path d="M12 8v4l3 2"/></svg>'),RTE_DefaultConfig.plugin_revisionhistory=RTE_Plugin_RevisionHistory;function RTE_Plugin_RevisionHistory(){var z=this,a,o,s=null,Y=null,K="";z.PluginName="RevisionHistory",z.InitConfig=function(r){a=r,a.revisionHistoryEnabled!==!1&&(a.revisionHistoryMaxEntries=a.revisionHistoryMaxEntries||50,a.revisionHistoryAutoSnapshotMs=a.revisionHistoryAutoSnapshotMs||0,a.revisionHistoryUrl=a.revisionHistoryUrl||"",a.revisionHistoryRequestHeaders=a.revisionHistoryRequestHeaders||null,a.onRevisionHistorySyncError=a.onRevisionHistorySyncError||null,a.text_revisionhistory=a.text_revisionhistory||"Revision history",P("toolbar_default","#{revisionhistory}"),P("toolbar_full","#{revisionhistory}"),P("toolbar_mobile","#{revisionhistory}"),(a.controltoolbar_TEXT||"").indexOf("revisionhistory")===-1&&(a.controltoolbar_TEXT=(a.controltoolbar_TEXT||"")+"|{revisionhistory}"))},z.InitEditor=function(r){o=r,a.revisionHistoryEnabled!==!1&&(o.revisionHistory={snapshot:function(e,t){return D(e,t)},promptAndSnapshot:function(e){return pe(e)},rename:function(e,t){return he(e,t)},list:function(){return g().slice().sort(function(e,t){return(t.createdAt||0)-(e.createdAt||0)})},listNamed:function(){return g().slice().filter(function(e){return e.isNamed===!0}).sort(function(e,t){return(t.createdAt||0)-(e.createdAt||0)})},get:function(e){return m(e)},restore:function(e,t){return ie(e,t||{})},delete:function(e){return ae(e)},clear:function(){return me()},diff:function(e,t){return ge(e,t)},openBrowser:function(){$()},closeBrowser:function(){S()}},o.toolbarFactoryMap=o.toolbarFactoryMap||{},o.toolbarFactoryMap.revisionhistory=function(e){return o.createToolbarButton(e)},o.attachEvent("exec_command_revisionhistory",function(e){e.returnValue=!0,e.stopBubble=!0,$()}),ke(),ve(),K=o.getHTML?o.getHTML():"",a.revisionHistoryAutoSnapshotMs>0&&(o.bindDocumentEvent?function(e){o.bindDocumentEvent("input",e,!0)}:function(e){o.getDocument().addEventListener("input",e,!0)})(function(){Y&&clearTimeout(Y),Y=setTimeout(function(){var e=o.getHTML();e!==K&&D("Auto",{auto:!0})},a.revisionHistoryAutoSnapshotMs)}),(o.bindDocumentEvent?function(e){o.bindDocumentEvent("keydown",e,!0)}:function(e){o.getDocument().addEventListener("keydown",e,!0)})(function(e){(e.ctrlKey||e.metaKey)&&e.altKey&&e.shiftKey&&(e.key==="H"||e.key==="h"||e.code==="KeyH")&&(e.preventDefault(),$())}))};function P(r,e){a[r]&&a[r].indexOf(e)===-1&&(a[r]=a[r]+e)}function de(){return a.currentUser&&a.currentUser.id?a.currentUser:{id:"user",name:"User",color:"#64748b"}}var V=null,J="RTE.Revisions.default";function X(){if(a.revisionHistoryKey)return"RTE.Revisions."+a.revisionHistoryKey;if(a.aiToolkitPersistenceKey)return"RTE.Revisions."+a.aiToolkitPersistenceKey;if(V)return V;var r="default";try{r=location.pathname+location.search}catch{}var e="";try{var t=o.input;if(t&&(e=t.id||t.getAttribute("name")||""),!e&&o.container&&o.container.id&&(e=o.container.id),!e){for(var n=document.querySelectorAll(".richtexteditor"),l=1;l<n.length;l++)if(n[l]===o.container){e="editor-"+l;break}}}catch{}return V="RTE.Revisions."+r+(e?"#"+e:"")}function ce(){if(!(a.revisionHistoryKey||a.aiToolkitPersistenceKey||g().length))try{if(!window.localStorage||document.querySelectorAll(".richtexteditor").length!==1)return;var r=X(),e=window.localStorage.getItem(J);if(!e||r===J||window.localStorage.getItem(r))return;var t=JSON.parse(e);if(!Array.isArray(t))return;window.localStorage.setItem(r,e),window.localStorage.removeItem(J),o.__revisions=t,s&&s.isConnected&&h()}catch{}}function g(){return o.__revisions||(o.__revisions=[]),o.__revisions}function m(r){for(var e=g(),t=0;t<e.length;t++)if(e[t].id===r)return e[t];return null}function q(){for(var r=g();r.length>a.revisionHistoryMaxEntries;)r.shift();try{window.localStorage&&window.localStorage.setItem(X(),JSON.stringify(r))}catch(e){console.warn("revisionhistory: localStorage quota or access issue:",e&&e.message)}a.revisionHistoryUrl&&fe(r)}function fe(r){try{var e=new XMLHttpRequest;e.open("POST",a.revisionHistoryUrl,!0),e.setRequestHeader("Content-Type","application/json");var t=ue();for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(n)){var l=String(t[n]);if(!/\r|\n/.test(l))try{e.setRequestHeader(n,l)}catch{}}e.onerror=function(){j({reason:"network",status:e.status||0})},e.onload=function(){(e.status<200||e.status>=300)&&j({reason:"http",status:e.status,responseText:(e.responseText||"").slice(0,512)})},e.send(JSON.stringify({documentKey:a.aiToolkitPersistenceKey||"",savedAt:Date.now(),revisions:r}))}catch(c){j({reason:"exception",error:c})}}function ue(){var r=a.revisionHistoryRequestHeaders;if(typeof r=="function")try{r=r(o)}catch(e){return j({reason:"header-provider",error:e}),{}}return r&&typeof r=="object"?r:{}}function j(r){console.warn("revisionhistory: remote persistence failed:",r&&r.reason,r&&r.status);try{typeof a.onRevisionHistorySyncError=="function"&&a.onRevisionHistorySyncError(r)}catch{}try{typeof o.fireEvent=="function"&&o.fireEvent("revision_history_sync_error",r)}catch{}}function ve(){setTimeout(ce,0);try{if(!window.localStorage)return;var r=window.localStorage.getItem(X());if(!r)return;var e=JSON.parse(r);Array.isArray(e)&&(o.__revisions=e)}catch{}}function D(r,e){var t=o.getHTML?o.getHTML():o.getHTMLCode?o.getHTMLCode():"",n=de(),l=(r||"").toString().slice(0,120),c=l.length>0&&(!e||e.auto!==!0),i={id:"rev-"+Date.now()+"-"+Math.floor(Math.random()*1e4),html:t,text:o.getText?o.getText():N(t),label:l||be(),isNamed:c,author:{id:n.id,name:n.name,color:n.color},createdAt:Date.now(),metadata:e||{}};g().push(i),K=t,q(),s&&s.isConnected&&h();try{typeof o.fireEvent=="function"&&o.fireEvent("revision_snapshot",{id:i.id,label:i.label,isNamed:i.isNamed,createdAt:i.createdAt})}catch{}return i}function v(r,e,t){var n=a&&a["text_"+r]||e;return t===void 0?n:n.split("{0}").join(String(t))}function pe(r){var e=o.iframe?o.iframe.ownerDocument:document,t=e.defaultView||window,n=t.prompt(v("rh_nameversion",'Name this version (e.g. "Draft sent to legal"):'),r||"");if(n===null)return null;var l=(n||"").trim();return l?D(l,{user:!0}):null}function he(r,e){var t=m(r);if(!t)return!1;var n=(e||"").toString().trim().slice(0,120);return n?(t.label=n,t.isNamed=!0,q(),s&&s.isConnected&&h(),!0):!1}function ge(r,e){var t=m(r),n=m(e);if(!t||!n)return null;var l=t.text||N(t.html),c=n.text||N(n.html);return{oldEntry:t,newEntry:n,oldText:l,newText:c,lines:se(l,c)}}function be(){var r=new Date;function e(t){return t<10?"0"+t:""+t}return e(r.getHours())+":"+e(r.getMinutes())+":"+e(r.getSeconds())}function ie(r,e){e=e||{};var t=m(r);if(!t)return!1;var n=a.revisionHistorySnapshotBeforeRestore!==!1;if(!e.skipConfirm){var l=o.iframe?o.iframe.ownerDocument:document,c=n?v("rh_restorekeep","Restore this version? Your current content is kept as a version first, so you can go back to it."):v("rh_restorereplace","Restore this version? Your current content will be replaced (this itself is not auto-snapshotted).");if(!l.defaultView.confirm(c))return!1}if(n){for(var i=o.getHTML?o.getHTML():o.getHTMLCode?o.getHTMLCode():"",u=null,d=g(),f=0;f<d.length;f++)(!u||(d[f].createdAt||0)>=(u.createdAt||0))&&(u=d[f]);i!==t.html&&(!u||u.html!==i)&&D(v("rh_beforerestore","Before restoring {0}",t.label),{beforeRestore:t.id})}return o.setHTMLCode?o.setHTMLCode(t.html,{undoable:!0}):o.setHTML&&o.setHTML(t.html),K=t.html,s&&s.isConnected&&S(),!0}function ae(r){for(var e=g(),t=0;t<e.length;t++)if(e[t].id===r)return e.splice(t,1),q(),s&&s.isConnected&&h(),!0;return!1}function me(){o.__revisions=[],q(),s&&s.isConnected&&h()}function se(r,e){for(var t=String(r||"").split(/\r?\n/),n=String(e||"").split(/\r?\n/),l=[],c=ye(t,n),i=0,u=0,d=0;i<t.length&&u<n.length;)d<c.length&&t[i]===c[d]&&n[u]===c[d]?(l.push({type:"eq",text:t[i]}),i++,u++,d++):d<c.length&&t[i]!==c[d]?(l.push({type:"del",text:t[i]}),i++):d<c.length&&n[u]!==c[d]?(l.push({type:"add",text:n[u]}),u++):i<t.length?(l.push({type:"del",text:t[i]}),i++):u<n.length&&(l.push({type:"add",text:n[u]}),u++);for(;i<t.length;)l.push({type:"del",text:t[i]}),i++;for(;u<n.length;)l.push({type:"add",text:n[u]}),u++;return l}function ye(r,e){for(var t=r.length,n=e.length,l=new Array(n+1).fill(0),c=new Array(n+1).fill(0),i=[],d=0;d<=t;d++)i.push(new Array(n+1).fill(0));for(var d=1;d<=t;d++)for(var f=1;f<=n;f++)r[d-1]===e[f-1]?i[d][f]=i[d-1][f-1]+1:i[d][f]=Math.max(i[d-1][f],i[d][f-1]);for(var u=[],d=t,f=n;d>0&&f>0;)r[d-1]===e[f-1]?(u.unshift(r[d-1]),d--,f--):i[d-1][f]>=i[d][f-1]?d--:f--;return u}function N(r){var e=document.createElement("div");return e.innerHTML=r||"",e.innerText||e.textContent||""}function $(){if(!(s&&s.isConnected)&&!(!o||!o.iframe||!o.iframe.ownerDocument)){s&&!s.isConnected&&(s=null);var r=o.iframe.ownerDocument;if(!(!r||!r.body)){s=r.createElement("div");var e=!1;try{var t=o.container||o.getEditable&&o.getEditable().closest&&o.getEditable().closest(".richtexteditor");e=!!(t&&t.classList&&t.classList.contains("rte-dark"))}catch{}s.className="rte-rev-dialog"+(e?" rte-rev-dark":""),s.setAttribute("role","dialog"),s.setAttribute("aria-modal","true"),s.setAttribute("aria-labelledby","rte-rev-dialog-title");var n=r.createElement("div");n.className="rte-rev-backdrop",n.addEventListener("mousedown",function(c){c.target===n&&S()});var l=r.createElement("div");l.className="rte-rev-panel",n.appendChild(l),s.appendChild(n),G=r.activeElement,s.addEventListener("keydown",xe,!0),r.body.appendChild(s),h(),setTimeout(Z,0),setTimeout(function(){s&&!s.contains(s.ownerDocument.activeElement)&&Z()},250)}}}var G=null;function le(){if(!s)return[];for(var r=s.querySelectorAll("button, input, select, textarea, a[href], [tabindex]:not([tabindex='-1'])"),e=[],t=0;t<r.length;t++)!r[t].disabled&&r[t].offsetParent!==null&&e.push(r[t]);return e}function Z(){var r=le();if(r.length)try{r[0].focus()}catch{}}function T(r,e,t){r.setAttribute("data-rte-rev-key",e),r.addEventListener("mousedown",function(n){n.preventDefault()}),r.addEventListener("click",function(n){n.preventDefault();var l=n.detail===0;if(t(),!(!l||!s)){for(var c=s.querySelectorAll("[data-rte-rev-key]"),i=0;i<c.length;i++)if(c[i].getAttribute("data-rte-rev-key")===e){try{c[i].focus()}catch{}return}s.contains(s.ownerDocument.activeElement)||Z()}})}function xe(r){if(r.key==="Escape"||r.key==="Esc"){r.preventDefault(),r.stopPropagation(),S();return}if(r.key==="Tab"){var e=le();if(e.length){var t=s.ownerDocument.activeElement,n=e.indexOf(t);r.shiftKey&&n<=0?(r.preventDefault(),e[e.length-1].focus()):!r.shiftKey&&(n===-1||n===e.length-1)&&(r.preventDefault(),e[0].focus())}}}function S(){s&&s.parentNode&&s.parentNode.removeChild(s),s=null;var r=G;G=null;try{r&&r.isConnected&&r.tagName!=="IFRAME"&&r!==r.ownerDocument.body?r.focus():typeof o.focus=="function"&&o.focus()}catch{}}var y=null,x="preview";function h(){if(s){var r=s.ownerDocument,e=s.querySelector(".rte-rev-panel");if(!e){S();return}e.innerHTML="";var t=r.createElement("div");t.className="rte-rev-header";var n=r.createElement("div");n.id="rte-rev-dialog-title",n.className="rte-rev-title",n.textContent=v("revisionhistory","Revision history"),t.appendChild(n);var l=r.createElement("div");l.className="rte-rev-header-actions";var c=r.createElement("button");c.type="button",c.className="rte-rev-btn rte-rev-btn-ghost",c.textContent=v("rh_savenow","Save version now"),T(c,"save",function(){var p=r.defaultView.prompt(v("rh_labelversion","Label this version (optional):"),"");p!==null&&D(p||"")}),l.appendChild(c);var i=r.createElement("button");i.type="button",i.className="rte-rev-btn rte-rev-btn-ghost",i.textContent=v("close","Close"),i.setAttribute("aria-label",v("rh_closehistory","Close revision history")),T(i,"close",S),l.appendChild(i),t.appendChild(l),e.appendChild(t);var u=r.createElement("div");u.className="rte-rev-body";var d=r.createElement("div");d.className="rte-rev-list";var f=o.revisionHistory.list();if(f.length&&(d.setAttribute("role","listbox"),d.setAttribute("aria-label",v("rh_saved","Saved revisions"))),f.length){(!y||!m(y))&&(y=f[0].id);for(var Q=0;Q<f.length;Q++)(function(p){var b=r.createElement("button");b.type="button",b.className="rte-rev-row"+(p.id===y?" rte-rev-row-active":""),b.setAttribute("role","option"),b.setAttribute("aria-selected",p.id===y?"true":"false");var te=r.createElement("span");te.className="rte-rev-dot",te.style.background=p.author&&p.author.color||"#64748b";var oe=r.createElement("div");oe.className="rte-rev-row-who",oe.textContent=p.author&&p.author.name||v("rh_user","User");var ne=r.createElement("div");ne.className="rte-rev-row-when",ne.textContent=we(p.createdAt)+" \xB7 "+(p.label||"");var U=r.createElement("div");U.className="rte-rev-row-col",U.appendChild(oe),U.appendChild(ne),b.appendChild(te),b.appendChild(U),T(b,"row-"+p.id,function(){y=p.id,h()}),d.appendChild(b)})(f[Q])}else{var B=r.createElement("div");B.className="rte-rev-empty",B.textContent=v("rh_empty",'No revisions yet. Click "Save version now" to capture the current document.'),d.appendChild(B)}u.appendChild(d);var R=r.createElement("div");if(R.className="rte-rev-pane",f.length){var w=m(y)||f[0],H=r.createElement("div");H.className="rte-rev-tabs",H.setAttribute("role","tablist"),H.setAttribute("aria-label",v("rh_view","Revision view"));var k=r.createElement("button");k.type="button",k.className="rte-rev-tab"+(x==="preview"?" rte-rev-tab-active":""),k.setAttribute("role","tab"),k.setAttribute("aria-selected",x==="preview"?"true":"false"),k.textContent=v("rh_preview","Preview"),T(k,"tab-preview",function(){x="preview",h()});var E=r.createElement("button");E.type="button",E.className="rte-rev-tab"+(x==="diff"?" rte-rev-tab-active":""),E.setAttribute("role","tab"),E.setAttribute("aria-selected",x==="diff"?"true":"false"),E.textContent=v("rh_diff","Diff vs current"),T(E,"tab-diff",function(){x="diff",h()}),H.appendChild(k),H.appendChild(E),R.appendChild(H);var F=r.createElement("div");if(F.className="rte-rev-content",x==="preview"){var C=r.createElement("iframe");C.className="rte-rev-preview-frame",C.setAttribute("title",v("rh_previewframe","Revision preview")),C.setAttribute("sandbox","allow-same-origin"),F.appendChild(C),setTimeout(function(){try{C.contentDocument.open(),C.contentDocument.write('<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;padding:16px;color:#0f172a;line-height:1.6}img{max-width:100%}</style></head><body>'+(w.html||"")+"</body></html>"),C.contentDocument.close()}catch{}},0)}else{var Ee=o.getText?o.getText():N(o.getHTML()),M=se(w.text||N(w.html),Ee),W=r.createElement("pre");W.className="rte-rev-diff";for(var _=0;_<M.length;_++){var ee=r.createElement("span");ee.className="rte-rev-diff-line rte-rev-diff-"+M[_].type,ee.textContent=(M[_].type==="add"?"+ ":M[_].type==="del"?"- ":" ")+M[_].text+`
2
+ `,W.appendChild(ee)}F.appendChild(W)}R.appendChild(F);var I=r.createElement("div");I.className="rte-rev-footer";var re=r.createElement("div");re.className="rte-rev-footer-info",re.textContent=w.label?v("rh_label","Label: {0}",w.label):"";var O=r.createElement("div");O.className="rte-rev-footer-btns";var L=r.createElement("button");L.type="button",L.className="rte-rev-btn rte-rev-btn-danger",L.textContent=v("delete","Delete"),T(L,"delete",function(){ae(w.id)});var A=r.createElement("button");A.type="button",A.className="rte-rev-btn rte-rev-btn-primary",A.textContent=v("rh_restore","Restore this version"),A.addEventListener("mousedown",function(p){p.preventDefault()}),A.addEventListener("click",function(p){p.preventDefault(),ie(w.id)}),O.appendChild(L),O.appendChild(A),I.appendChild(re),I.appendChild(O),R.appendChild(I)}f.length?u.appendChild(R):d.classList.add("rte-rev-list-solo"),e.appendChild(u)}}function we(r){if(!r)return"";var e=new Date(r),t=new Date;function n(c){return c<10?"0"+c:""+c}var l=n(e.getHours())+":"+n(e.getMinutes());return e.toDateString()===t.toDateString()?v("rh_today","Today {0}",l):e.getFullYear()+"-"+n(e.getMonth()+1)+"-"+n(e.getDate())+" "+l}function ke(){var r=o&&o.iframe&&o.iframe.ownerDocument||document;if(!r.querySelector("style[data-rte-revisionhistory]")){var e=r.createElement("style");e.setAttribute("data-rte-revisionhistory","1"),e.textContent=[".rte-rev-dialog{position:fixed;inset:0;z-index:2147483600;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:13px;color:#172033}",".rte-rev-backdrop{position:absolute;inset:0;background:linear-gradient(135deg,rgba(12,18,32,.44),rgba(40,54,77,.26));display:flex;align-items:center;justify-content:center;padding:18px}","/* 2026-07-12 revision dialog precision */",".rte-rev-panel{background:linear-gradient(180deg,#ffffff 0%,#f8fbff 100%);border:1px solid rgba(117,137,163,.28);border-radius:8px;width:min(960px,calc(100vw - 28px));max-height:min(82vh,740px);display:flex;flex-direction:column;box-shadow:0 16px 40px rgba(35,48,72,.18);overflow:hidden}",".rte-rev-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border-bottom:1px solid rgba(117,137,163,.18);background:rgba(255,255,255,.72)}",".rte-rev-title{font-size:16px;font-weight:760;letter-spacing:-.01em;color:#172033}",".rte-rev-header-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}",".rte-rev-btn{padding:8px 12px;border-radius:7px;border:1px solid rgba(116,135,162,.25);font:inherit;font-size:12px;font-weight:680;line-height:1;cursor:pointer;background:#fff;color:#223652;box-shadow:0 1px 2px rgba(32,45,66,.06);transition:background .14s ease,border-color .14s ease,box-shadow .14s ease,transform .14s ease}",".rte-rev-btn:hover{background:#f5f8fc;border-color:rgba(81,111,151,.42);box-shadow:0 5px 14px rgba(32,45,66,.09);transform:translateY(-1px)}",".rte-rev-btn:focus-visible{outline:2px solid rgba(56,122,255,.34);outline-offset:2px}",".rte-rev-btn-ghost{background:#fff;color:#34506f}",".rte-rev-btn-primary{background:linear-gradient(135deg,#2563eb,#1d67ba);color:#fff;border-color:rgba(29,103,186,.85);box-shadow:0 8px 18px rgba(37,99,235,.22)}",".rte-rev-btn-primary:hover{background:linear-gradient(135deg,#1d4ed8,#195fad);color:#fff;border-color:rgba(29,78,216,.9);box-shadow:0 9px 20px rgba(37,99,235,.28)}",".rte-rev-btn-danger{background:#fff5f5;color:#9f1d1d;border-color:rgba(190,45,45,.22)}",".rte-rev-body{display:flex;flex:1;min-height:0;background:linear-gradient(90deg,#f8fbff 0%,#fff 42%)}",".rte-rev-list{width:258px;flex:0 0 258px;border-right:1px solid rgba(117,137,163,.18);overflow-y:auto;background:rgba(244,248,253,.78);padding:10px}",".rte-rev-empty{padding:16px;border:1px dashed rgba(99,118,145,.28);border-radius:8px;background:#fff;color:#5b6c81;font-size:12px;line-height:1.5}",".rte-rev-row{display:flex;align-items:center;gap:10px;width:100%;padding:10px;border:1px solid transparent;border-radius:8px;background:transparent;text-align:left;cursor:pointer;font:inherit;color:inherit}",".rte-rev-row:hover{background:#fff;border-color:rgba(93,122,161,.24);box-shadow:0 8px 18px rgba(33,48,70,.08)}",".rte-rev-row-active{background:#eef6ff;border-color:rgba(37,99,235,.28);box-shadow:0 8px 22px rgba(37,99,235,.12)}",".rte-rev-dot{width:9px;height:9px;border-radius:50%;flex:0 0 9px;box-shadow:0 0 0 3px rgba(255,255,255,.95),0 0 0 4px rgba(96,116,140,.18)}",".rte-rev-row-col{flex:1;min-width:0}",".rte-rev-row-who{font-weight:720;font-size:12px;line-height:1.25;color:#172033}",".rte-rev-row-when{margin-top:2px;font-size:11px;color:#637487;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",".rte-rev-pane{flex:1;display:flex;flex-direction:column;min-width:0;padding:10px}",".rte-rev-list.rte-rev-list-solo{flex:1 1 auto;width:auto;max-height:none;border-right:0;border-bottom:0}",".rte-rev-tabs{display:flex;align-self:flex-start;gap:3px;padding:3px;margin:0 0 10px;border:1px solid rgba(117,137,163,.2);border-radius:7px;background:#eef3f8}",".rte-rev-tab{padding:7px 12px;border:0;border-radius:6px;background:transparent;font:inherit;font-size:12px;font-weight:680;color:#637487;cursor:pointer}",".rte-rev-tab:hover{color:#1d3557;background:rgba(255,255,255,.58)}",".rte-rev-tab:focus-visible{outline:2px solid rgba(56,122,255,.34);outline-offset:2px}",".rte-rev-tab-active{color:#163966;background:#fff;box-shadow:0 2px 7px rgba(35,48,72,.08)}",".rte-rev-content{flex:1;overflow:auto;padding:0;border:1px solid rgba(117,137,163,.18);border-radius:8px;background:#fff;min-height:300px}",".rte-rev-preview-frame{width:100%;height:100%;min-height:330px;border:0;display:block;background:#fff}",".rte-rev-diff{margin:0;padding:14px 16px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.55;white-space:pre-wrap;color:#172033;background:#fbfdff;min-height:100%}",".rte-rev-diff-line{display:block}",".rte-rev-diff-add{background:#e8f8ef;color:#17633f}",".rte-rev-diff-del{background:#fff0f0;color:#9f1d1d}",".rte-rev-diff-eq{color:#556575}",".rte-rev-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 0 0;background:transparent}",".rte-rev-footer-info{font-size:12px;color:#637487;min-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",".rte-rev-footer-btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}","@media(max-width:720px){.rte-rev-backdrop{padding:10px;align-items:flex-start}.rte-rev-panel{width:calc(100vw - 20px);max-height:calc(100vh - 20px);border-radius:8px}.rte-rev-header{align-items:flex-start;flex-direction:column}.rte-rev-body{flex-direction:column}.rte-rev-list{width:auto;flex:0 0 auto;max-height:178px;border-right:0;border-bottom:1px solid rgba(117,137,163,.18)}.rte-rev-pane{min-height:360px}.rte-rev-footer{align-items:stretch;flex-direction:column}.rte-rev-footer-info{white-space:normal}.rte-rev-footer-btns{justify-content:stretch}.rte-rev-footer-btns .rte-rev-btn{flex:1}}",".rte-rev-dark{color:#e2e8f0}",".rte-rev-dark .rte-rev-panel{background:linear-gradient(180deg,#1e293b,#0f172a);border-color:#334155}",".rte-rev-dark .rte-rev-header{background:rgba(30,41,59,.72);border-color:#334155}",".rte-rev-dark .rte-rev-title,.rte-rev-dark .rte-rev-row-who{color:#e2e8f0}",".rte-rev-dark .rte-rev-btn,.rte-rev-dark .rte-rev-btn-ghost{background:#0f172a;color:#cbd5e1;border-color:#334155}",".rte-rev-dark .rte-rev-btn:hover{background:#334155}",".rte-rev-dark .rte-rev-btn-primary,.rte-rev-dark .rte-rev-btn-primary:hover{background:linear-gradient(135deg,#2563eb,#1d4ed8);color:#fff;border-color:#3b82f6}",".rte-rev-dark .rte-rev-body{background:#0f172a}",".rte-rev-dark .rte-rev-list{background:rgba(15,23,42,.6);border-color:#334155}",".rte-rev-dark .rte-rev-empty{background:#1e293b;color:#94a3b8;border-color:#334155}",".rte-rev-dark .rte-rev-row:hover{background:#1e293b;border-color:#334155}",".rte-rev-dark .rte-rev-row-active{background:#1e3a8a;border-color:#3b82f6}",".rte-rev-dark .rte-rev-row-when,.rte-rev-dark .rte-rev-footer-info{color:#94a3b8}",".rte-rev-dark .rte-rev-tabs{background:#1e293b;border-color:#334155}",".rte-rev-dark .rte-rev-tab{color:#94a3b8}.rte-rev-dark .rte-rev-tab-active{color:#fff;background:#1d4ed8}",".rte-rev-dark .rte-rev-diff{background:#0f172a;color:#cbd5e1}.rte-rev-dark .rte-rev-diff-eq{color:#94a3b8}",".rte-rev-dark .rte-rev-diff-add{background:rgba(16,185,129,.16);color:#6ee7b7}",".rte-rev-dark .rte-rev-diff-del{background:rgba(244,63,94,.16);color:#fda4af}"].join(`
3
+ `),r.head.appendChild(e),o&&typeof o.ensureStyleSheetLive=="function"&&o.ensureStyleSheetLive(r,e,"rte-revisionhistory-style",e.textContent)}}}
@@ -33,6 +33,10 @@ function RTE_Plugin_RubyAnnotation() {
33
33
  if (config.rubyAnnotationEnabled === false) return;
34
34
 
35
35
  if (typeof config.rubyAnnotationParentheses !== "boolean") config.rubyAnnotationParentheses = true;
36
+ // 2026-10-15 no string for the button: getLangText returned the key, so it was announced "rubyannotation".
37
+ // tools/a11y/raw-lang-keys.mjs
38
+ if (!config.text_rubyannotation) config.text_rubyannotation = "Ruby annotation";
39
+ if (!config.text_rubyannotationtitle) config.text_rubyannotationtitle = "Ruby annotation";
36
40
 
37
41
  // BOTH toolbars. config.toolbar defaults to "default", which resolves to
38
42
  // toolbar_default, so appending only to toolbar_full would leave the
@@ -205,48 +209,54 @@ function RTE_Plugin_RubyAnnotation() {
205
209
  return el;
206
210
  }
207
211
 
212
+ // getLangText returns the key itself when there is no string, so `|| fallback` never ran ("rubyannotationtitle")
213
+ function rubyTitle() {
214
+ var t = editor.getLangText ? editor.getLangText("rubyannotationtitle") : "";
215
+ return t && String(t).toLowerCase() !== "rubyannotationtitle" ? t : "Ruby annotation";
216
+ }
217
+
208
218
  obj.OpenRubyDialog = function () {
209
219
  var existing = findRubyAtSelection();
210
220
  var range = currentRange();
211
221
  var baseText = existing ? baseOf(existing) : (range ? String(range.toString() || "") : "");
212
222
 
213
223
  var dlg = editor.createDialog(
214
- (editor.getLangText && editor.getLangText("rubyannotationtitle")) || "Ruby annotation",
224
+ rubyTitle(),
215
225
  "rte-dialog-ruby"
216
226
  );
217
227
  var close = typeof dlg.close === "function" ? function () { dlg.close(); } : function () { editor.closeCurrentPopup(); };
218
228
 
219
229
  var wrap = append(dlg, "div", "padding:14px;min-width:340px;font:13px -apple-system,Segoe UI,sans-serif");
220
230
 
221
- append(wrap, "div", "font-weight:600;margin-bottom:4px").innerText = "Base text";
231
+ append(wrap, "div", "font-weight:600;margin-bottom:4px").innerText = ((config && config.text_ruby_base) || "Base text");
222
232
  var baseView = append(wrap, "div",
223
233
  "padding:8px 10px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;min-height:20px;word-break:break-word");
224
234
  baseView.textContent = baseText;
225
235
 
226
- append(wrap, "div", "font-weight:600;margin:10px 0 4px").innerText = "Reading";
236
+ append(wrap, "div", "font-weight:600;margin:10px 0 4px").innerText = ((config && config.text_ruby_reading) || "Reading");
227
237
  var input = append(wrap, "input",
228
238
  "width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid #cbd5e1;border-radius:8px;font:13px inherit");
229
239
  input.type = "text";
230
240
  input.value = existing ? readingOf(existing) : "";
231
- input.placeholder = "e.g. かんじ";
241
+ input.placeholder = "e.g. \u304b\u3093\u3058";
232
242
 
233
243
  var note = append(wrap, "div", "font-size:11px;color:#94a3b8;margin-top:6px");
234
244
  note.innerText = baseText
235
- ? "Shown above the base text. Parentheses are emitted for readers without ruby support."
236
- : "Select the text to annotate first, then reopen this dialog.";
245
+ ? ((config && config.text_ruby_note) || "Shown above the base text. Parentheses are emitted for readers without ruby support.")
246
+ : ((config && config.text_ruby_selectfirst) || "Select the text to annotate first, then reopen this dialog.");
237
247
 
238
248
  var footer = append(wrap, "div", "display:flex;justify-content:space-between;gap:8px;margin-top:14px");
239
249
  var left = append(footer, "div", "display:flex;gap:8px");
240
250
  if (existing) {
241
251
  var rm = append(left, "button", "padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#b91c1c;cursor:pointer");
242
- rm.type = "button"; rm.textContent = "Remove";
252
+ rm.type = "button"; rm.textContent = ((config && config.text_ruby_remove) || "Remove");
243
253
  rm.onclick = function () { removeRuby(); close(); };
244
254
  }
245
255
  var right = append(footer, "div", "display:flex;gap:8px");
246
256
  var cancel = append(right, "button", "padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;cursor:pointer");
247
- cancel.type = "button"; cancel.textContent = "Cancel"; cancel.onclick = close;
257
+ cancel.type = "button"; cancel.textContent = ((config && config.text_ruby_cancel) || "Cancel"); cancel.onclick = close;
248
258
  var ok = append(right, "button", "padding:6px 14px;border:1px solid #1d67ba;border-radius:8px;background:#1d67ba;color:#fff;cursor:pointer");
249
- ok.type = "button"; ok.textContent = existing ? "Update" : "Add";
259
+ ok.type = "button"; ok.textContent = existing ? ((config && config.text_ruby_update) || "Update") : ((config && config.text_ruby_add) || "Add");
250
260
  ok.disabled = !baseText;
251
261
 
252
262
  ok.onclick = function () {
@@ -1 +1 @@
1
- window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_rubyannotation=RTE_Plugin_RubyAnnotation;function RTE_Plugin_RubyAnnotation(){var d=this,a,r;d.PluginName="RubyAnnotation",d.InitConfig=function(e){a=e,a.rubyAnnotationEnabled!==!1&&(typeof a.rubyAnnotationParentheses!="boolean"&&(a.rubyAnnotationParentheses=!0),w("toolbar_full","#{rubyannotation}"),S("subtoolbar_more","rubyannotation"))},d.InitEditor=function(e){r=e,a.rubyAnnotationEnabled!==!1&&(r.ruby={add:function(t){return h(t)},get:function(){var t=p();return t?y(t):null},isRuby:function(){return!!p()},open:function(){d.OpenRubyDialog()},remove:function(){return m()}},E(),r.toolbarFactoryMap=r.toolbarFactoryMap||{},r.toolbarFactoryMap.rubyannotation=function(t){return r.createToolbarButton(t)},r.attachEvent("exec_command_rubyannotation",function(t){t.returnValue=!0,t.stopBubble=!0,d.OpenRubyDialog()}))};function w(e,t){a[e]&&a[e].indexOf(t)===-1&&(a[e]=a[e]+t)}function S(e,t){var n=a[e];if(!(!n||n.indexOf(t)!==-1)){var o=n.indexOf("}");o!==-1&&(a[e]=n.substring(0,o)+","+t+n.substring(o))}}function E(){var e=a.container.ownerDocument;if(!e.getElementById("rte-ruby-style")){var t=e.createElement("style");t.id="rte-ruby-style",t.innerHTML=[".rte-ruby-annotated{ruby-position:over;}",".rte-ruby-annotated>rt{font-size:.55em;line-height:1.15;opacity:.85;user-select:none;}","@supports (display:ruby){.rte-ruby-annotated>rp{display:none;}}"].join(""),e.head.appendChild(t),r&&typeof r.ensureStyleSheetLive=="function"&&r.ensureStyleSheetLive(e,t,"rte-ruby-style",t.textContent)}}function D(){return r&&r.getEditable?r.getEditable():null}function b(){var e=r.getDocument();try{var t=e.getSelection();return!t||!t.rangeCount?null:t.getRangeAt(0)}catch{return null}}function p(){var e=b(),t=D();if(!e||!t)return null;for(var n=e.startContainer;n&&n!==t;){if(n.nodeType===1&&n.nodeName==="RUBY")return n;n=n.parentNode}return null}function y(e){var t=e.querySelector("rt");return t&&t.textContent||""}function x(e){for(var t="",n=0;n<e.childNodes.length;n++){var o=e.childNodes[n];o.nodeType===3?t+=o.nodeValue:o.nodeType===1&&o.nodeName!=="RT"&&o.nodeName!=="RP"&&(t+=o.textContent||"")}return t}function v(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function k(e,t){var n=a.rubyAnnotationParentheses;return'<ruby class="rte-ruby-annotated">'+v(e)+(n?"<rp>(</rp>":"")+"<rt>"+v(t)+"</rt>"+(n?"<rp>)</rp>":"")+"</ruby>"}function h(e){var t=p();if(t){var n=t.querySelector("rt");return n||(n=t.ownerDocument.createElement("rt"),t.appendChild(n)),n.textContent=String(e??""),r.focus(),t}var o=b();if(!o||o.collapsed)return null;var u=String(o.toString()||"");return u?(r.insertHTML(k(u,e)),r.focus(),!0):null}function m(){var e=p();if(!e)return!1;var t=e.ownerDocument,n=t.createTextNode(x(e));return e.parentNode.insertBefore(n,e),e.parentNode.removeChild(e),r.focus(),!0}function i(e,t,n,o){var u=e.ownerDocument.createElement(t);return n&&(u.style.cssText=n),o&&(u.className=o),e.appendChild(u),u}d.OpenRubyDialog=function(){var e=p(),t=b(),n=e?x(e):t?String(t.toString()||""):"",o=r.createDialog(r.getLangText&&r.getLangText("rubyannotationtitle")||"Ruby annotation","rte-dialog-ruby"),u=typeof o.close=="function"?function(){o.close()}:function(){r.closeCurrentPopup()},l=i(o,"div","padding:14px;min-width:340px;font:13px -apple-system,Segoe UI,sans-serif");i(l,"div","font-weight:600;margin-bottom:4px").innerText="Base text";var A=i(l,"div","padding:8px 10px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;min-height:20px;word-break:break-word");A.textContent=n,i(l,"div","font-weight:600;margin:10px 0 4px").innerText="Reading";var f=i(l,"input","width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid #cbd5e1;border-radius:8px;font:13px inherit");f.type="text",f.value=e?y(e):"",f.placeholder="e.g. \u304B\u3093\u3058";var N=i(l,"div","font-size:11px;color:#94a3b8;margin-top:6px");N.innerText=n?"Shown above the base text. Parentheses are emitted for readers without ruby support.":"Select the text to annotate first, then reopen this dialog.";var R=i(l,"div","display:flex;justify-content:space-between;gap:8px;margin-top:14px"),_=i(R,"div","display:flex;gap:8px");if(e){var s=i(_,"button","padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#b91c1c;cursor:pointer");s.type="button",s.textContent="Remove",s.onclick=function(){m(),u()}}var C=i(R,"div","display:flex;gap:8px"),g=i(C,"button","padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;cursor:pointer");g.type="button",g.textContent="Cancel",g.onclick=u;var c=i(C,"button","padding:6px 14px;border:1px solid #1d67ba;border-radius:8px;background:#1d67ba;color:#fff;cursor:pointer");c.type="button",c.textContent=e?"Update":"Add",c.disabled=!n,c.onclick=function(){var T=f.value.trim();if(!T||!n){u();return}h(T),u()},setTimeout(function(){f.focus()},0)}}
1
+ window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_rubyannotation=RTE_Plugin_RubyAnnotation;function RTE_Plugin_RubyAnnotation(){var d=this,r,o;d.PluginName="RubyAnnotation",d.InitConfig=function(t){r=t,r.rubyAnnotationEnabled!==!1&&(typeof r.rubyAnnotationParentheses!="boolean"&&(r.rubyAnnotationParentheses=!0),r.text_rubyannotation||(r.text_rubyannotation="Ruby annotation"),r.text_rubyannotationtitle||(r.text_rubyannotationtitle="Ruby annotation"),T("toolbar_full","#{rubyannotation}"),w("subtoolbar_more","rubyannotation"))},d.InitEditor=function(t){o=t,r.rubyAnnotationEnabled!==!1&&(o.ruby={add:function(e){return h(e)},get:function(){var e=p();return e?x(e):null},isRuby:function(){return!!p()},open:function(){d.OpenRubyDialog()},remove:function(){return m()}},S(),o.toolbarFactoryMap=o.toolbarFactoryMap||{},o.toolbarFactoryMap.rubyannotation=function(e){return o.createToolbarButton(e)},o.attachEvent("exec_command_rubyannotation",function(e){e.returnValue=!0,e.stopBubble=!0,d.OpenRubyDialog()}))};function T(t,e){r[t]&&r[t].indexOf(e)===-1&&(r[t]=r[t]+e)}function w(t,e){var n=r[t];if(!(!n||n.indexOf(e)!==-1)){var a=n.indexOf("}");a!==-1&&(r[t]=n.substring(0,a)+","+e+n.substring(a))}}function S(){var t=r.container.ownerDocument;if(!t.getElementById("rte-ruby-style")){var e=t.createElement("style");e.id="rte-ruby-style",e.innerHTML=[".rte-ruby-annotated{ruby-position:over;}",".rte-ruby-annotated>rt{font-size:.55em;line-height:1.15;opacity:.85;user-select:none;}","@supports (display:ruby){.rte-ruby-annotated>rp{display:none;}}"].join(""),t.head.appendChild(e),o&&typeof o.ensureStyleSheetLive=="function"&&o.ensureStyleSheetLive(t,e,"rte-ruby-style",e.textContent)}}function E(){return o&&o.getEditable?o.getEditable():null}function c(){var t=o.getDocument();try{var e=t.getSelection();return!e||!e.rangeCount?null:e.getRangeAt(0)}catch{return null}}function p(){var t=c(),e=E();if(!t||!e)return null;for(var n=t.startContainer;n&&n!==e;){if(n.nodeType===1&&n.nodeName==="RUBY")return n;n=n.parentNode}return null}function x(t){var e=t.querySelector("rt");return e&&e.textContent||""}function g(t){for(var e="",n=0;n<t.childNodes.length;n++){var a=t.childNodes[n];a.nodeType===3?e+=a.nodeValue:a.nodeType===1&&a.nodeName!=="RT"&&a.nodeName!=="RP"&&(e+=a.textContent||"")}return e}function v(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function D(t,e){var n=r.rubyAnnotationParentheses;return'<ruby class="rte-ruby-annotated">'+v(t)+(n?"<rp>(</rp>":"")+"<rt>"+v(e)+"</rt>"+(n?"<rp>)</rp>":"")+"</ruby>"}function h(t){var e=p();if(e){var n=e.querySelector("rt");return n||(n=e.ownerDocument.createElement("rt"),e.appendChild(n)),n.textContent=String(t??""),o.focus(),e}var a=c();if(!a||a.collapsed)return null;var u=String(a.toString()||"");return u?(o.insertHTML(D(u,t)),o.focus(),!0):null}function m(){var t=p();if(!t)return!1;var e=t.ownerDocument,n=e.createTextNode(g(t));return t.parentNode.insertBefore(n,t),t.parentNode.removeChild(t),o.focus(),!0}function i(t,e,n,a){var u=t.ownerDocument.createElement(e);return n&&(u.style.cssText=n),a&&(u.className=a),t.appendChild(u),u}function k(){var t=o.getLangText?o.getLangText("rubyannotationtitle"):"";return t&&String(t).toLowerCase()!=="rubyannotationtitle"?t:"Ruby annotation"}d.OpenRubyDialog=function(){var t=p(),e=c(),n=t?g(t):e?String(e.toString()||""):"",a=o.createDialog(k(),"rte-dialog-ruby"),u=typeof a.close=="function"?function(){a.close()}:function(){o.closeCurrentPopup()},l=i(a,"div","padding:14px;min-width:340px;font:13px -apple-system,Segoe UI,sans-serif");i(l,"div","font-weight:600;margin-bottom:4px").innerText=r&&r.text_ruby_base||"Base text";var A=i(l,"div","padding:8px 10px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;min-height:20px;word-break:break-word");A.textContent=n,i(l,"div","font-weight:600;margin:10px 0 4px").innerText=r&&r.text_ruby_reading||"Reading";var f=i(l,"input","width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid #cbd5e1;border-radius:8px;font:13px inherit");f.type="text",f.value=t?x(t):"",f.placeholder="e.g. \u304B\u3093\u3058";var N=i(l,"div","font-size:11px;color:#94a3b8;margin-top:6px");N.innerText=n?r&&r.text_ruby_note||"Shown above the base text. Parentheses are emitted for readers without ruby support.":r&&r.text_ruby_selectfirst||"Select the text to annotate first, then reopen this dialog.";var _=i(l,"div","display:flex;justify-content:space-between;gap:8px;margin-top:14px"),O=i(_,"div","display:flex;gap:8px");if(t){var s=i(O,"button","padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#b91c1c;cursor:pointer");s.type="button",s.textContent=r&&r.text_ruby_remove||"Remove",s.onclick=function(){m(),u()}}var R=i(_,"div","display:flex;gap:8px"),y=i(R,"button","padding:6px 14px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;cursor:pointer");y.type="button",y.textContent=r&&r.text_ruby_cancel||"Cancel",y.onclick=u;var b=i(R,"button","padding:6px 14px;border:1px solid #1d67ba;border-radius:8px;background:#1d67ba;color:#fff;cursor:pointer");b.type="button",b.textContent=t?r&&r.text_ruby_update||"Update":r&&r.text_ruby_add||"Add",b.disabled=!n,b.onclick=function(){var C=f.value.trim();if(!C||!n){u();return}h(C),u()},setTimeout(function(){f.focus()},0)}}
@@ -91,6 +91,10 @@ function RTE_Plugin_Sanitizer() {
91
91
  "blockquote,pre,code,figure,figcaption," +
92
92
  "section,article,header,footer,main,aside,nav,address,details,summary," +
93
93
  "a,img,picture,source,video,audio,track,map,area," +
94
+ // 2026-10-18 the editor's own video wrapper: its overlay (content CSS) is what lets a click select an
95
+ // embedded video. Unwrapped, the click went into the video's frame and the video could never be selected.
96
+ // tools/video/video-click-select.mjs
97
+ "video-container," +
94
98
  // Chips, task lists and the code plugin put these in content.
95
99
  "input,label,button," +
96
100
  // Inline SVG (icons, diagrams). Its dangerous children are dropped below.
@@ -116,8 +120,8 @@ function RTE_Plugin_Sanitizer() {
116
120
  // an embed MORE powerful.
117
121
  "contenteditable,spellcheck,autocomplete,draggable,sandbox,allowfullscreen,allow,frameborder,scrolling," +
118
122
  "href,src,srcset,sizes,alt,width,height,loading,decoding,referrerpolicy," +
119
- "target,rel,download,type,value,name,placeholder,checked,disabled,readonly," +
120
- "colspan,rowspan,headers,scope,span,align,valign,bgcolor,border,cellpadding,cellspacing," +
123
+ "target,rel,hreflang,media,download,type,value,name,placeholder,checked,disabled,readonly," +
124
+ "colspan,rowspan,headers,scope,abbr,span,align,valign,bgcolor,border,cellpadding,cellspacing," +
121
125
  "start,reversed,datetime,cite,open,controls,autoplay,loop,muted,playsinline,poster,preload,kind,srclang,label," +
122
126
  "usemap,ismap,coords,shape," +
123
127
  // SVG presentation
@@ -211,6 +215,28 @@ function RTE_Plugin_Sanitizer() {
211
215
  // - allow-scripts + allow-same-origin isolates nothing when the frame is
212
216
  // served from the page's OWN origin: the framed page can reach the parent
213
217
  // and remove its own sandbox. Same-origin frames lose allow-same-origin.
218
+ // 2026-10-01 <font> is not allowed, and unknown elements are unwrapped - which threw away
219
+ // the font, colour and size of every <font> in loaded or pasted content (older editor
220
+ // versions and many tools write it). It is converted to an equivalent styled <span>
221
+ // instead. Every value becomes CSS, so each is validated and anything else is dropped.
222
+ var FONT_SIZES = { "1": "x-small", "2": "small", "3": "medium", "4": "large", "5": "x-large", "6": "xx-large", "7": "xxx-large" };
223
+ function fontTagStyle(el) {
224
+ var css = [];
225
+ var face = el.getAttribute("face");
226
+ if (face) {
227
+ var names = face.split(",").map(function (n) { return n.trim().replace(/^['"]|['"]$/g, ""); })
228
+ .filter(function (n) { return /^[A-Za-z0-9][A-Za-z0-9 \-]{0,63}$/.test(n); })
229
+ .map(function (n) { return /\s/.test(n) ? "'" + n + "'" : n; });
230
+ if (names.length) css.push("font-family:" + names.join(","));
231
+ }
232
+ var color = (el.getAttribute("color") || "").trim();
233
+ if (/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(color) || /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/i.test(color) || /^[a-z]{3,20}$/i.test(color))
234
+ css.push("color:" + color);
235
+ var size = FONT_SIZES[(el.getAttribute("size") || "").trim()];
236
+ if (size) css.push("font-size:" + size);
237
+ return css.join(";");
238
+ }
239
+
214
240
  function applyDefaultSandbox(el, src) {
215
241
  var allowed = DEFAULT_IFRAME_SANDBOX.split(" ");
216
242
  var sameOrigin = false;
@@ -367,6 +393,26 @@ function RTE_Plugin_Sanitizer() {
367
393
  el.parentNode.removeChild(el);
368
394
  continue;
369
395
  }
396
+ } else if (tag === "center" || tag === "big" || tag === "tt") {
397
+ // 2026-10-01 Other legacy presentational tags, converted like <font> instead of
398
+ // unwrapped: <center> lost its centring AND left its text loose at the top level,
399
+ // <big> lost its size, <tt> its monospace.
400
+ note(report.removedTags, tag);
401
+ var legacyEl = el.ownerDocument.createElement(tag === "center" ? "div" : tag === "big" ? "span" : "code");
402
+ if (tag === "center") legacyEl.setAttribute("style", "text-align:center");
403
+ if (tag === "big") legacyEl.setAttribute("style", "font-size:larger");
404
+ while (el.firstChild) legacyEl.appendChild(el.firstChild);
405
+ el.parentNode.replaceChild(legacyEl, el);
406
+ continue;
407
+ } else if (tag === "font") {
408
+ var fontCss = fontTagStyle(el);
409
+ note(report.removedTags, "font");
410
+ if (!fontCss) { unwrap(el); continue; }
411
+ var fontSpan = el.ownerDocument.createElement("span");
412
+ fontSpan.setAttribute("style", fontCss);
413
+ while (el.firstChild) fontSpan.appendChild(el.firstChild);
414
+ el.parentNode.replaceChild(fontSpan, el);
415
+ continue;
370
416
  } else if (DROP_WHOLE[tag]) {
371
417
  note(report.removedTags, tag);
372
418
  el.parentNode.removeChild(el);
@@ -380,6 +426,7 @@ function RTE_Plugin_Sanitizer() {
380
426
  }
381
427
 
382
428
  var attrs = [];
429
+ var strippedSrc = false;
383
430
  for (var a = 0; a < el.attributes.length; a++) attrs.push(el.attributes[a]);
384
431
  for (var k = 0; k < attrs.length; k++) {
385
432
  var name = attrs[k].name.toLowerCase();
@@ -394,10 +441,25 @@ function RTE_Plugin_Sanitizer() {
394
441
  }
395
442
  if (name === "srcdoc") { note(report.removedAttributes, "srcdoc"); el.removeAttribute(attrs[k].name); continue; }
396
443
  if (name === "style") { el.setAttribute("style", cleanStyle(value)); continue; }
444
+ // 2026-10-02 A lazy-load source (data-src, data-lazy-src, data-original, data-srcset)
445
+ // is copied into src by the HOST page's lazy-loader, so it is a URL like any other:
446
+ // data-src="javascript:..." kept in saved HTML was a script waiting for that loader.
447
+ // tools/clipboard/lazy-images-paste.mjs
448
+ if (/^data-(.*-)?(src|srcset|original)$/i.test(name)) {
449
+ var lazyOk = /srcset$/i.test(name)
450
+ ? value.split(",").every(function (part) { var u = part.trim().split(/\s+/)[0]; return !u || isSafeUrl(u, tag, "src"); })
451
+ : isSafeUrl(value, tag, "src");
452
+ if (!lazyOk) { note(report.removedAttributes, tag + "[" + name + "]"); el.removeAttribute(attrs[k].name); }
453
+ continue;
454
+ }
397
455
  if (name.indexOf("data-") === 0 || name.indexOf("aria-") === 0) continue;
398
456
 
399
457
  if (URL_ATTRS[name]) {
400
- if (!isSafeUrl(value, tag, name)) { note(report.removedAttributes, tag + "[" + name + "]"); el.removeAttribute(attrs[k].name); }
458
+ if (!isSafeUrl(value, tag, name)) {
459
+ note(report.removedAttributes, tag + "[" + name + "]");
460
+ el.removeAttribute(attrs[k].name);
461
+ if (name === "src") strippedSrc = true;
462
+ }
401
463
  continue;
402
464
  }
403
465
  if (!ALLOWED_ATTRS[name] && !attrExtra(name)) {
@@ -406,6 +468,18 @@ function RTE_Plugin_Sanitizer() {
406
468
  }
407
469
  }
408
470
 
471
+ // An <img> whose only source was just stripped is an empty box that
472
+ // saves as <img> with no src -- dragging a page image into the editor
473
+ // from a page opened on disk did exactly that (its file: src is not a
474
+ // safe scheme). Drop the element when nothing is left to show. Keep it
475
+ // when srcset or a lazy-load data-*src still carries an image, and never
476
+ // touch an <img> that arrived without a src (an app placeholder).
477
+ if (tag === "img" && strippedSrc && !el.hasAttribute("srcset") && !hasDataSource(el)) {
478
+ note(report.removedTags, "img");
479
+ el.parentNode.removeChild(el);
480
+ continue;
481
+ }
482
+
409
483
  // A link that opens a new tab without rel="noopener" hands the
410
484
  // opener window to the destination.
411
485
  if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
@@ -422,9 +496,17 @@ function RTE_Plugin_Sanitizer() {
422
496
  parent.removeChild(el);
423
497
  }
424
498
  function note(list, what) { if (list.indexOf(what) < 0) list.push(what); }
499
+ function hasDataSource(el) {
500
+ for (var i = 0; i < el.attributes.length; i++) {
501
+ if (/^data-(.*-)?(src|srcset|original)$/i.test(el.attributes[i].name)) return true;
502
+ }
503
+ return false;
504
+ }
425
505
 
426
506
  function sanitizeHtml(html) {
427
- var out = html;
507
+ // The clipboard's fragment markers are not content (they leaked into saved HTML as
508
+ // <p><!--StartFragment--></p> on this path).
509
+ var out = String(html).replace(/<!--\s*(Start|End)Fragment\s*-->/gi, "");
428
510
  report.calls++;
429
511
  // Parsing into an inert document means nothing loads or executes while
430
512
  // we inspect it -- innerHTML on a live div would fire <img onerror>
@@ -1 +1 @@
1
- window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_sanitizer=RTE_Plugin_Sanitizer,typeof RTE_DefaultConfig.contentSanitizer>"u"&&(RTE_DefaultConfig.contentSanitizer=!0);function RTE_Plugin_Sanitizer(){var y=this,g,l,E=!1,b={removedTags:[],removedAttributes:[],calls:0,lastPasses:0},k=[];y.PluginName="Sanitizer",y.InitConfig=function(e){g=e},y.InitEditor=function(e){if(l=e,g.contentSanitizer===!1)return;l.sanitizeHtml=function(r){return m(String(r??""))},l.getSanitizerReport=function(){return JSON.parse(JSON.stringify(b))};function t(){try{B(),W()}catch{}try{X()}catch{}try{$()}catch{}}t();try{l.attachEvent("ready",t)}catch{}setTimeout(t,0),setTimeout(t,400)};var L={};"p,div,span,br,hr,h1,h2,h3,h4,h5,h6,b,strong,i,em,u,s,strike,del,ins,mark,small,sub,sup,abbr,cite,q,dfn,kbd,samp,var,time,data,bdi,bdo,wbr,ruby,rt,rp,ul,ol,li,dl,dt,dd,table,thead,tbody,tfoot,tr,td,th,caption,colgroup,col,blockquote,pre,code,figure,figcaption,section,article,header,footer,main,aside,nav,address,details,summary,a,img,picture,source,video,audio,track,map,area,input,label,button,svg,g,path,circle,ellipse,rect,line,polyline,polygon,text,tspan,defs,marker,linearGradient,radialGradient,stop,clipPath,mask,pattern,use,symbol,title,desc".split(",").forEach(function(e){L[e]=!0});var R={script:1,noscript:1,template:1,object:1,embed:1,applet:1,base:1,meta:1,link:1,frame:1,frameset:1,foreignobject:1,xml:1,"script:":1},z={};"id,class,style,title,lang,dir,translate,hidden,tabindex,role,contenteditable,spellcheck,autocomplete,draggable,sandbox,allowfullscreen,allow,frameborder,scrolling,href,src,srcset,sizes,alt,width,height,loading,decoding,referrerpolicy,target,rel,download,type,value,name,placeholder,checked,disabled,readonly,colspan,rowspan,headers,scope,span,align,valign,bgcolor,border,cellpadding,cellspacing,start,reversed,datetime,cite,open,controls,autoplay,loop,muted,playsinline,poster,preload,kind,srclang,label,usemap,ismap,coords,shape,viewbox,xmlns,fill,stroke,stroke-width,stroke-linecap,stroke-linejoin,stroke-dasharray,d,cx,cy,r,rx,ry,x,y,x1,y1,x2,y2,points,transform,opacity,fill-rule,clip-rule,gradientunits,offset,stop-color,stop-opacity,text-anchor,font-size,font-family,font-weight,preserveaspectratio,version".split(",").forEach(function(e){z[e]=!0});var M={href:1,src:1,action:1,formaction:1,poster:1,cite:1,data:1,longdesc:1,background:1,ping:1,srcset:1},I=/^(https?|mailto|tel|ftp|sms|callto|webcal|geo|bitcoin):/i,H=/^data:image\/(png|jpe?g|gif|webp|bmp|x-icon|avif);base64,[a-z0-9+/=\s]+$/i;function w(e,t,r){var n=String(e??"").replace(/[\u0000-\u0020\u007F-\u00A0]+/g,"").trim();if(!n)return!1;if(t==="use")return n.charAt(0)==="#";if(/^[#?/]/.test(n))return!0;var o=/^([a-z][a-z0-9+.\-]*):/i.exec(n);return o?H.test(n)?t==="img"||t==="source"||r==="poster"||r==="srcset":/^blob:/i.test(n)?t==="img"||t==="video"||t==="audio"||t==="source":I.test(n):!0}function P(e){for(var t=[],r=String(e??"").split(";"),n=0;n<r.length;n++){var o=r[n];if(o.trim()&&!/expression\s*\(|(javascript|vbscript|livescript)\s*:|-moz-binding|behaviou?r\s*:|@import|-o-link/i.test(o)){var i=/url\s*\(\s*(['"]?)([^'")]*)\1\s*\)/i.exec(o);i&&!w(i[2],"img","src")||t.push(o.trim())}}return t.join("; ")}var j="allow-scripts allow-same-origin allow-presentation";function G(e,t){var r=j.split(" "),n=!1;try{n=new URL(t,location.href).origin===location.origin}catch{}if(n&&(r=r.filter(function(i){return i!=="allow-same-origin"})),e.hasAttribute("sandbox")){var o=(e.getAttribute("sandbox")||"").toLowerCase().split(/\s+/);r=r.filter(function(i){return o.indexOf(i)>=0})}e.setAttribute("sandbox",r.join(" "))}function U(e){if(g.sanitizerAllowIframes===!1)return!1;var t=e.getAttribute("src")||"";if(!/^https?:/i.test(t))return!1;var r=g.sanitizerAllowedIframeHosts;if(!r||!r.length)return G(e,t),!0;try{for(var n=new URL(t).hostname.toLowerCase(),o=0;o<r.length;o++){var i=String(r[o]).toLowerCase();if(n===i||n.slice(-(i.length+1))==="."+i)return!0}}catch{}return!1}function C(e){var t={},r=[],n=[];(e||[]).forEach(function(i){if(i instanceof RegExp){n.push(i);return}var s=String(i).toLowerCase();if(s.indexOf("*")===-1){t[s]=!0;return}r.push(s.split("*"))});function o(i,s){var a=i[0];if(s.lastIndexOf(a,0)!==0)return!1;var u=i[i.length-1];if(u&&(s.length<u.length||s.indexOf(u,s.length-u.length)===-1))return!1;for(var c=a.length,p=1;p<i.length;p++)if(i[p]){var v=s.indexOf(i[p],c);if(v===-1)return!1;c=v+i[p].length}return!0}return function(i){if(t[i])return!0;for(var s=0;s<r.length;s++)if(o(r[s],i))return!0;for(var a=0;a<n.length;a++)if(n[a].test(i))return!0;return!1}}function x(e,t){var r=C(g.sanitizerAllowTags),n=C(g.sanitizerAllowAttributes),o=g.sanitizerAllowStyleTags===!0,i=[];(function K(D){for(var _=0;_<D.childNodes.length;_++){var h=D.childNodes[_];h.nodeType===1?(i.push(h),K(h)):h.nodeType===8&&i.push(h)}})(e);for(var s=0;s<i.length;s++){var a=i[s];if(a.parentNode){if(a.nodeType===8){O(a.data)&&(d(t.removedTags,"#comment"),a.parentNode.removeChild(a));continue}var u=(a.localName||a.nodeName||"").toLowerCase();if(u==="style"){if(!o){d(t.removedTags,"style"),a.parentNode.removeChild(a);continue}}else if(u==="iframe"){if(a.hasAttribute("srcdoc")&&(d(t.removedAttributes,"iframe[srcdoc]"),a.removeAttribute("srcdoc")),!U(a)){d(t.removedTags,"iframe"),a.parentNode.removeChild(a);continue}}else if(u==="title"||u==="desc"){if(!a.closest||!a.closest("svg")){d(t.removedTags,u),a.parentNode.removeChild(a);continue}}else if(R[u]){d(t.removedTags,u),a.parentNode.removeChild(a);continue}else if(!L[u]&&!r(u)){d(t.removedTags,u),F(a);continue}for(var c=[],p=0;p<a.attributes.length;p++)c.push(a.attributes[p]);for(var v=0;v<c.length;v++){var f=c[v].name.toLowerCase(),T=c[v].value;if(f.indexOf("on")===0){d(t.removedAttributes,f),a.removeAttribute(c[v].name);continue}if(f==="xlink:href"||f==="xmlns:xlink"){w(T,u,f)||(d(t.removedAttributes,f),a.removeAttribute(c[v].name));continue}if(f==="srcdoc"){d(t.removedAttributes,"srcdoc"),a.removeAttribute(c[v].name);continue}if(f==="style"){a.setAttribute("style",P(T));continue}if(!(f.indexOf("data-")===0||f.indexOf("aria-")===0)){if(M[f]){w(T,u,f)||(d(t.removedAttributes,u+"["+f+"]"),a.removeAttribute(c[v].name));continue}!z[f]&&!n(f)&&(d(t.removedAttributes,f),a.removeAttribute(c[v].name))}}if(u==="a"&&(a.getAttribute("target")||"").toLowerCase()==="_blank"){var S=(a.getAttribute("rel")||"").toLowerCase();S.indexOf("noopener")<0&&a.setAttribute("rel",(S?S+" ":"")+"noopener noreferrer")}}}return e}function F(e){for(var t=e.parentNode;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}function d(e,t){e.indexOf(t)<0&&e.push(t)}function m(e){var t=e;b.calls++;for(var r=0;r<3;r++){var n=new DOMParser().parseFromString("<body>"+t+"</body>","text/html");x(n.body,b);var o=n.body.innerHTML;if(b.lastPasses=r+1,o===t)break;t=o}return t}function B(){if(!E){for(var e=["getHTMLCode","getHTMLContent"],t=!1,r=0;r<e.length;r++)(function(n){var o=l[n];if(!(typeof o!="function"||o.__rteSanitized)){var i=function(){var s=o.apply(l,arguments);return typeof s!="string"?s:m(s)};i.__rteSanitized=!0,l[n]=i,t=!0}})(e[r]);t&&(E=!0)}}function W(){for(var e=["setHTMLCode","setHTMLContent"],t=0;t<e.length;t++)(function(r){var n=l[r];if(!(typeof n!="function"||n.__rteSanitizedIn)){var o=function(i){var s=[].slice.call(arguments);return typeof i=="string"&&(s[0]=m(i)),n.apply(l,s)};o.__rteSanitizedIn=!0,l[r]=o}})(e[t])}function q(e){return/\son[a-z]+\s*=/i.test(e)||/<\s*(script|iframe|object|embed|base)\b/i.test(e)||/srcdoc\s*=/i.test(e)||/(javascript|vbscript)\s*:/i.test(e)||/data:\s*text\/html/i.test(e)}function O(e){var t=String(e??"");return t.indexOf("-->")!==-1||t.indexOf("--!>")!==-1||t.charAt(0)===">"||t.charAt(0)==="-"&&t.charAt(1)===">"}var N=/^(script|iframe|object|embed|base|meta|link|form)$/;function A(e){if(!e.attributes)return!1;for(var t=0;t<e.attributes.length;t++){var r=e.attributes[t].name.toLowerCase();if(r.indexOf("on")===0||r==="srcdoc"||(r==="href"||r==="src"||r==="data"||r==="action"||r==="xlink:href")&&/(javascript|vbscript)\s*:|data:\s*text\/html/i.test(e.attributes[t].value||""))return!0}return!1}function J(e){if(N.test(e.localName||"")||A(e))return!0;for(var t=e.getElementsByTagName?e.getElementsByTagName("*"):[],r=0;r<t.length;r++)if(N.test(t[r].localName||"")||A(t[r]))return!0;return!1}function $(){if(g.sanitizerGuardLiveDom!==!1){var e=null;try{e=l.getEditable()}catch{return}if(!(!e||e.__rteLiveGuard)){e.__rteLiveGuard=!0;var t=new MutationObserver(function(r){for(var n=!1,o=0;o<r.length&&!n;o++){var i=r[o];if(i.type==="attributes"){var s=(i.attributeName||"").toLowerCase();(s.indexOf("on")===0||s==="srcdoc"||A(i.target))&&(n=!0);continue}for(var a=0;a<i.addedNodes.length;a++){var u=i.addedNodes[a];if(u.nodeType===8){if(O(u.data)){n=!0;break}continue}if(u.nodeType===1&&J(u)){n=!0;break}}}if(n)try{x(e,b)}catch{}});t.observe(e,{childList:!0,subtree:!0,attributes:!0}),k.push(t)}}}function X(){var e=null;try{e=l.getEditable()}catch{return}if(!e||e.__rteSanitizePaste)return;e.__rteSanitizePaste=!0,e.addEventListener("paste",function(r){var n=r.clipboardData||window.clipboardData;if(n){var o="";try{o=n.getData("text/html")||""}catch{return}if(!(!o||!q(o))){r.preventDefault(),r.stopImmediatePropagation();var i=m(o);try{l.insertHTML(i)}catch{try{l.insertText(n.getData("text/plain")||"")}catch{}}}}},!0);function t(){var r=function(){try{x(e,b)}catch{}};setTimeout(r,0),setTimeout(r,250)}e.addEventListener("paste",t,!1),e.addEventListener("drop",t,!0)}}
1
+ window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_sanitizer=RTE_Plugin_Sanitizer,typeof RTE_DefaultConfig.contentSanitizer>"u"&&(RTE_DefaultConfig.contentSanitizer=!0);function RTE_Plugin_Sanitizer(){var S=this,p,l,O=!1,m={removedTags:[],removedAttributes:[],calls:0,lastPasses:0},P=[];S.PluginName="Sanitizer",S.InitConfig=function(t){p=t},S.InitEditor=function(t){if(l=t,p.contentSanitizer===!1)return;l.sanitizeHtml=function(r){return T(String(r??""))},l.getSanitizerReport=function(){return JSON.parse(JSON.stringify(m))};function e(){try{Q(),V()}catch{}try{re()}catch{}try{te()}catch{}}e();try{l.attachEvent("ready",e)}catch{}setTimeout(e,0),setTimeout(e,400)};var D={};"p,div,span,br,hr,h1,h2,h3,h4,h5,h6,b,strong,i,em,u,s,strike,del,ins,mark,small,sub,sup,abbr,cite,q,dfn,kbd,samp,var,time,data,bdi,bdo,wbr,ruby,rt,rp,ul,ol,li,dl,dt,dd,table,thead,tbody,tfoot,tr,td,th,caption,colgroup,col,blockquote,pre,code,figure,figcaption,section,article,header,footer,main,aside,nav,address,details,summary,a,img,picture,source,video,audio,track,map,area,video-container,input,label,button,svg,g,path,circle,ellipse,rect,line,polyline,polygon,text,tspan,defs,marker,linearGradient,radialGradient,stop,clipPath,mask,pattern,use,symbol,title,desc".split(",").forEach(function(t){D[t]=!0});var G={script:1,noscript:1,template:1,object:1,embed:1,applet:1,base:1,meta:1,link:1,frame:1,frameset:1,foreignobject:1,xml:1,"script:":1},k={};"id,class,style,title,lang,dir,translate,hidden,tabindex,role,contenteditable,spellcheck,autocomplete,draggable,sandbox,allowfullscreen,allow,frameborder,scrolling,href,src,srcset,sizes,alt,width,height,loading,decoding,referrerpolicy,target,rel,hreflang,media,download,type,value,name,placeholder,checked,disabled,readonly,colspan,rowspan,headers,scope,abbr,span,align,valign,bgcolor,border,cellpadding,cellspacing,start,reversed,datetime,cite,open,controls,autoplay,loop,muted,playsinline,poster,preload,kind,srclang,label,usemap,ismap,coords,shape,viewbox,xmlns,fill,stroke,stroke-width,stroke-linecap,stroke-linejoin,stroke-dasharray,d,cx,cy,r,rx,ry,x,y,x1,y1,x2,y2,points,transform,opacity,fill-rule,clip-rule,gradientunits,offset,stop-color,stop-opacity,text-anchor,font-size,font-family,font-weight,preserveaspectratio,version".split(",").forEach(function(t){k[t]=!0});var $={href:1,src:1,action:1,formaction:1,poster:1,cite:1,data:1,longdesc:1,background:1,ping:1,srcset:1},F=/^(https?|mailto|tel|ftp|sms|callto|webcal|geo|bitcoin):/i,U=/^data:image\/(png|jpe?g|gif|webp|bmp|x-icon|avif);base64,[a-z0-9+/=\s]+$/i;function y(t,e,r){var a=String(t??"").replace(/[\u0000-\u0020\u007F-\u00A0]+/g,"").trim();if(!a)return!1;if(e==="use")return a.charAt(0)==="#";if(/^[#?/]/.test(a))return!0;var o=/^([a-z][a-z0-9+.\-]*):/i.exec(a);return o?U.test(a)?e==="img"||e==="source"||r==="poster"||r==="srcset":/^blob:/i.test(a)?e==="img"||e==="video"||e==="audio"||e==="source":F.test(a):!0}function B(t){for(var e=[],r=String(t??"").split(";"),a=0;a<r.length;a++){var o=r[a];if(o.trim()&&!/expression\s*\(|(javascript|vbscript|livescript)\s*:|-moz-binding|behaviou?r\s*:|@import|-o-link/i.test(o)){var n=/url\s*\(\s*(['"]?)([^'")]*)\1\s*\)/i.exec(o);n&&!y(n[2],"img","src")||e.push(o.trim())}}return e.join("; ")}var W="allow-scripts allow-same-origin allow-presentation",Z={1:"x-small",2:"small",3:"medium",4:"large",5:"x-large",6:"xx-large",7:"xxx-large"};function q(t){var e=[],r=t.getAttribute("face");if(r){var a=r.split(",").map(function(s){return s.trim().replace(/^['"]|['"]$/g,"")}).filter(function(s){return/^[A-Za-z0-9][A-Za-z0-9 \-]{0,63}$/.test(s)}).map(function(s){return/\s/.test(s)?"'"+s+"'":s});a.length&&e.push("font-family:"+a.join(","))}var o=(t.getAttribute("color")||"").trim();(/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(o)||/^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/i.test(o)||/^[a-z]{3,20}$/i.test(o))&&e.push("color:"+o);var n=Z[(t.getAttribute("size")||"").trim()];return n&&e.push("font-size:"+n),e.join(";")}function J(t,e){var r=W.split(" "),a=!1;try{a=new URL(e,location.href).origin===location.origin}catch{}if(a&&(r=r.filter(function(n){return n!=="allow-same-origin"})),t.hasAttribute("sandbox")){var o=(t.getAttribute("sandbox")||"").toLowerCase().split(/\s+/);r=r.filter(function(n){return o.indexOf(n)>=0})}t.setAttribute("sandbox",r.join(" "))}function X(t){if(p.sanitizerAllowIframes===!1)return!1;var e=t.getAttribute("src")||"";if(!/^https?:/i.test(e))return!1;var r=p.sanitizerAllowedIframeHosts;if(!r||!r.length)return J(t,e),!0;try{for(var a=new URL(e).hostname.toLowerCase(),o=0;o<r.length;o++){var n=String(r[o]).toLowerCase();if(a===n||a.slice(-(n.length+1))==="."+n)return!0}}catch{}return!1}function R(t){var e={},r=[],a=[];(t||[]).forEach(function(n){if(n instanceof RegExp){a.push(n);return}var s=String(n).toLowerCase();if(s.indexOf("*")===-1){e[s]=!0;return}r.push(s.split("*"))});function o(n,s){var i=n[0];if(s.lastIndexOf(i,0)!==0)return!1;var u=n[n.length-1];if(u&&(s.length<u.length||s.indexOf(u,s.length-u.length)===-1))return!1;for(var b=i.length,h=1;h<n.length;h++)if(n[h]){var g=s.indexOf(n[h],b);if(g===-1)return!1;b=g+n[h].length}return!0}return function(n){if(e[n])return!0;for(var s=0;s<r.length;s++)if(o(r[s],n))return!0;for(var i=0;i<a.length;i++)if(a[i].test(n))return!0;return!1}}function z(t,e){var r=R(p.sanitizerAllowTags),a=R(p.sanitizerAllowAttributes),o=p.sanitizerAllowStyleTags===!0,n=[];(function L(x){for(var N=0;N<x.childNodes.length;N++){var w=x.childNodes[N];w.nodeType===1?(n.push(w),L(w)):w.nodeType===8&&n.push(w)}})(t);for(var s=0;s<n.length;s++){var i=n[s];if(i.parentNode){if(i.nodeType===8){M(i.data)&&(c(e.removedTags,"#comment"),i.parentNode.removeChild(i));continue}var u=(i.localName||i.nodeName||"").toLowerCase();if(u==="style"){if(!o){c(e.removedTags,"style"),i.parentNode.removeChild(i);continue}}else if(u==="iframe"){if(i.hasAttribute("srcdoc")&&(c(e.removedAttributes,"iframe[srcdoc]"),i.removeAttribute("srcdoc")),!X(i)){c(e.removedTags,"iframe"),i.parentNode.removeChild(i);continue}}else if(u==="title"||u==="desc"){if(!i.closest||!i.closest("svg")){c(e.removedTags,u),i.parentNode.removeChild(i);continue}}else if(u==="center"||u==="big"||u==="tt"){c(e.removedTags,u);var b=i.ownerDocument.createElement(u==="center"?"div":u==="big"?"span":"code");for(u==="center"&&b.setAttribute("style","text-align:center"),u==="big"&&b.setAttribute("style","font-size:larger");i.firstChild;)b.appendChild(i.firstChild);i.parentNode.replaceChild(b,i);continue}else if(u==="font"){var h=q(i);if(c(e.removedTags,"font"),!h){I(i);continue}var g=i.ownerDocument.createElement("span");for(g.setAttribute("style",h);i.firstChild;)g.appendChild(i.firstChild);i.parentNode.replaceChild(g,i);continue}else if(G[u]){c(e.removedTags,u),i.parentNode.removeChild(i);continue}else if(!D[u]&&!r(u)){c(e.removedTags,u),I(i);continue}for(var d=[],H=!1,_=0;_<i.attributes.length;_++)d.push(i.attributes[_]);for(var v=0;v<d.length;v++){var f=d[v].name.toLowerCase(),A=d[v].value;if(f.indexOf("on")===0){c(e.removedAttributes,f),i.removeAttribute(d[v].name);continue}if(f==="xlink:href"||f==="xmlns:xlink"){y(A,u,f)||(c(e.removedAttributes,f),i.removeAttribute(d[v].name));continue}if(f==="srcdoc"){c(e.removedAttributes,"srcdoc"),i.removeAttribute(d[v].name);continue}if(f==="style"){i.setAttribute("style",B(A));continue}if(/^data-(.*-)?(src|srcset|original)$/i.test(f)){var ie=/srcset$/i.test(f)?A.split(",").every(function(L){var x=L.trim().split(/\s+/)[0];return!x||y(x,u,"src")}):y(A,u,"src");ie||(c(e.removedAttributes,u+"["+f+"]"),i.removeAttribute(d[v].name));continue}if(!(f.indexOf("data-")===0||f.indexOf("aria-")===0)){if($[f]){y(A,u,f)||(c(e.removedAttributes,u+"["+f+"]"),i.removeAttribute(d[v].name),f==="src"&&(H=!0));continue}!k[f]&&!a(f)&&(c(e.removedAttributes,f),i.removeAttribute(d[v].name))}}if(u==="img"&&H&&!i.hasAttribute("srcset")&&!K(i)){c(e.removedTags,"img"),i.parentNode.removeChild(i);continue}if(u==="a"&&(i.getAttribute("target")||"").toLowerCase()==="_blank"){var E=(i.getAttribute("rel")||"").toLowerCase();E.indexOf("noopener")<0&&i.setAttribute("rel",(E?E+" ":"")+"noopener noreferrer")}}}return t}function I(t){for(var e=t.parentNode;t.firstChild;)e.insertBefore(t.firstChild,t);e.removeChild(t)}function c(t,e){t.indexOf(e)<0&&t.push(e)}function K(t){for(var e=0;e<t.attributes.length;e++)if(/^data-(.*-)?(src|srcset|original)$/i.test(t.attributes[e].name))return!0;return!1}function T(t){var e=String(t).replace(/<!--\s*(Start|End)Fragment\s*-->/gi,"");m.calls++;for(var r=0;r<3;r++){var a=new DOMParser().parseFromString("<body>"+e+"</body>","text/html");z(a.body,m);var o=a.body.innerHTML;if(m.lastPasses=r+1,o===e)break;e=o}return e}function Q(){if(!O){for(var t=["getHTMLCode","getHTMLContent"],e=!1,r=0;r<t.length;r++)(function(a){var o=l[a];if(!(typeof o!="function"||o.__rteSanitized)){var n=function(){var s=o.apply(l,arguments);return typeof s!="string"?s:T(s)};n.__rteSanitized=!0,l[a]=n,e=!0}})(t[r]);e&&(O=!0)}}function V(){for(var t=["setHTMLCode","setHTMLContent"],e=0;e<t.length;e++)(function(r){var a=l[r];if(!(typeof a!="function"||a.__rteSanitizedIn)){var o=function(n){var s=[].slice.call(arguments);return typeof n=="string"&&(s[0]=T(n)),a.apply(l,s)};o.__rteSanitizedIn=!0,l[r]=o}})(t[e])}function Y(t){return/\son[a-z]+\s*=/i.test(t)||/<\s*(script|iframe|object|embed|base)\b/i.test(t)||/srcdoc\s*=/i.test(t)||/(javascript|vbscript)\s*:/i.test(t)||/data:\s*text\/html/i.test(t)}function M(t){var e=String(t??"");return e.indexOf("-->")!==-1||e.indexOf("--!>")!==-1||e.charAt(0)===">"||e.charAt(0)==="-"&&e.charAt(1)===">"}var j=/^(script|iframe|object|embed|base|meta|link|form)$/;function C(t){if(!t.attributes)return!1;for(var e=0;e<t.attributes.length;e++){var r=t.attributes[e].name.toLowerCase();if(r.indexOf("on")===0||r==="srcdoc"||(r==="href"||r==="src"||r==="data"||r==="action"||r==="xlink:href")&&/(javascript|vbscript)\s*:|data:\s*text\/html/i.test(t.attributes[e].value||""))return!0}return!1}function ee(t){if(j.test(t.localName||"")||C(t))return!0;for(var e=t.getElementsByTagName?t.getElementsByTagName("*"):[],r=0;r<e.length;r++)if(j.test(e[r].localName||"")||C(e[r]))return!0;return!1}function te(){if(p.sanitizerGuardLiveDom!==!1){var t=null;try{t=l.getEditable()}catch{return}if(!(!t||t.__rteLiveGuard)){t.__rteLiveGuard=!0;var e=new MutationObserver(function(r){for(var a=!1,o=0;o<r.length&&!a;o++){var n=r[o];if(n.type==="attributes"){var s=(n.attributeName||"").toLowerCase();(s.indexOf("on")===0||s==="srcdoc"||C(n.target))&&(a=!0);continue}for(var i=0;i<n.addedNodes.length;i++){var u=n.addedNodes[i];if(u.nodeType===8){if(M(u.data)){a=!0;break}continue}if(u.nodeType===1&&ee(u)){a=!0;break}}}if(a)try{z(t,m)}catch{}});e.observe(t,{childList:!0,subtree:!0,attributes:!0}),P.push(e)}}}function re(){var t=null;try{t=l.getEditable()}catch{return}if(!t||t.__rteSanitizePaste)return;t.__rteSanitizePaste=!0,t.addEventListener("paste",function(r){var a=r.clipboardData||window.clipboardData;if(a){var o="";try{o=a.getData("text/html")||""}catch{return}if(!(!o||!Y(o))){r.preventDefault(),r.stopImmediatePropagation();var n=T(o);try{l.insertHTML(n)}catch{try{l.insertText(a.getData("text/plain")||"")}catch{}}}}},!0);function e(){var r=function(){try{z(t,m)}catch{}};setTimeout(r,0),setTimeout(r,250)}t.addEventListener("paste",e,!1),t.addEventListener("drop",e,!0)}}
@@ -59,13 +59,19 @@ function RTE_Plugin_SlashCommand() {
59
59
 
60
60
  injectStyles();
61
61
 
62
- var editdoc = editor.getDocument();
63
- editdoc.addEventListener("keydown", onEditDocKeyDown, true);
64
- editdoc.addEventListener("input", onEditDocInput, true);
65
- editdoc.addEventListener("compositionstart", function () { composing = true; });
66
- editdoc.addEventListener("compositionend", function () { composing = false; });
67
- editdoc.addEventListener("mousedown", function () { closePopup(); }, true);
68
- editdoc.addEventListener("blur", function () { setTimeout(closePopup, 150); }, true);
62
+ // 2026-10-03 Bound through editor.bindDocumentEvent, so the listeners follow the live document:
63
+ // shell plugins move the iframe during the init loop, and listeners added to editdoc here stayed
64
+ // on the dead document (this feature never fired). tools/keyboard/plugin-listeners.mjs
65
+ var on = function (type, fn, capture) {
66
+ if (editor.bindDocumentEvent) editor.bindDocumentEvent(type, fn, capture);
67
+ else editor.getDocument().addEventListener(type, fn, capture);
68
+ };
69
+ on("keydown", onEditDocKeyDown, true);
70
+ on("input", onEditDocInput, true);
71
+ on("compositionstart", function () { composing = true; });
72
+ on("compositionend", function () { composing = false; });
73
+ on("mousedown", function () { closePopup(); }, true);
74
+ on("blur", function () { setTimeout(closePopup, 150); }, true);
69
75
 
70
76
  window.addEventListener("scroll", onHostScrollOrResize, true);
71
77
  window.addEventListener("resize", onHostScrollOrResize, true);
@@ -291,9 +297,9 @@ function RTE_Plugin_SlashCommand() {
291
297
  if (typeof editor.setTableLayoutMode === "function") {
292
298
  push("Insert", "layouttable", "Layout table", "Insert a borderless table for positioning content (role=presentation)", ["layout", "table", "grid", "email", "columns", "presentation"], iconTable(),
293
299
  function () { editor.insertLayoutTable(2, 2); });
294
- push("Tools", "tablelayoutmode", "Mark table as layout", "This table only positions content — stop screen readers announcing it as data", ["layout", "table", "presentation", "accessibility", "screen reader"], iconTable(),
300
+ push("Tools", "tablelayoutmode", "Mark table as layout", "This table only positions content \u2014 stop screen readers announcing it as data", ["layout", "table", "presentation", "accessibility", "screen reader"], iconTable(),
295
301
  function () { editor.setTableLayoutMode("layout"); });
296
- push("Tools", "tabledatamode", "Mark table as data", "This table states relationships — restore its header cells", ["data", "table", "header", "accessibility"], iconTable(),
302
+ push("Tools", "tabledatamode", "Mark table as data", "This table states relationships \u2014 restore its header cells", ["data", "table", "header", "accessibility"], iconTable(),
297
303
  function () { editor.setTableLayoutMode("data", null, { promoteFirstRow: true }); });
298
304
  }
299
305
  if (typeof editor.moveBlockUp === "function") {
@@ -401,7 +407,7 @@ function RTE_Plugin_SlashCommand() {
401
407
  // this menu without any error. These checks are re-run by refreshDefaults()
402
408
  // after all plugins have initialised and again each time the menu opens.
403
409
  if (typeof editor.exportToPdf === "function") {
404
- push("Tools", "exportpdf", "Export to PDF", "Real text, not a screenshot — selectable, searchable and screen-reader friendly", ["pdf", "export", "download", "save", "print", "text", "accessible", "searchable"], iconPdfText(),
410
+ push("Tools", "exportpdf", "Export to PDF", "Real text, not a screenshot \u2014 selectable, searchable and screen-reader friendly", ["pdf", "export", "download", "save", "print", "text", "accessible", "searchable"], iconPdfText(),
405
411
  function () { editor.exportToPdf(); });
406
412
  }
407
413
  if (typeof editor.exportToDocx === "function") {
@@ -439,6 +445,8 @@ function RTE_Plugin_SlashCommand() {
439
445
  function () { editor.copyAsMarkdown(); });
440
446
  push("Tools", "downloadmarkdown", "Download as Markdown", "Save the document as a .md file", ["markdown", "md", "download", "export", "save", "file"], iconMarkdown(),
441
447
  function () { editor.downloadMarkdown(); });
448
+ push("Tools", "markdownmode", "Edit as Markdown", "Show the document as Markdown text, and back to the visual view", ["markdown", "md", "source", "text", "edit", "mode"], iconMarkdown(),
449
+ function () { editor.toggleMarkdownMode(); });
442
450
  }
443
451
  if (typeof editor.toggleTypewriterMode === "function") {
444
452
  push("Tools", "typewriter", "Typewriter mode", "Keep the caret line centred as you type", ["typewriter", "center", "scroll", "focus", "distraction", "zen"], iconTypewriter(),
@@ -451,6 +459,10 @@ function RTE_Plugin_SlashCommand() {
451
459
  function () { editor.execCommand("inserttable"); });
452
460
  push("Insert", "image", "Image", "Upload or embed an image", ["picture", "photo", "img"], iconImage(),
453
461
  function () { editor.execCommand("imageupload"); });
462
+ if (typeof editor.openImageGenerator === "function") {
463
+ push("Insert", "generate-image", "Generate image", "Describe an image and insert it (your own image provider)", ["picture", "generate", "ai", "draw", "image", "create"], iconImage(),
464
+ function () { editor.openImageGenerator(); });
465
+ }
454
466
  push("Insert", "link", "Link", "Insert a hyperlink", ["url", "anchor"], iconLink(),
455
467
  function () { editor.execCommand("insertlink"); });
456
468
  push("Insert", "emoji", "Emoji", "Insert an emoji", ["smiley", "icon"], iconEmoji(),
@@ -641,7 +653,7 @@ function RTE_Plugin_SlashCommand() {
641
653
  if (host && host.classList && host.classList.contains("rte-dark")) popupEl.className += " rte-slash-popup-dark";
642
654
  } catch (e) {}
643
655
  popupEl.setAttribute("role", "listbox");
644
- popupEl.setAttribute("aria-label", "Slash commands");
656
+ popupEl.setAttribute("aria-label", (config && config.text_slash_aria) || "Slash commands");
645
657
  popupHost.body.appendChild(popupEl);
646
658
  }
647
659
 
@@ -652,7 +664,7 @@ function RTE_Plugin_SlashCommand() {
652
664
  if (!filtered.length) {
653
665
  var empty = popupHost.createElement("div");
654
666
  empty.className = "rte-slash-empty";
655
- empty.textContent = "No matching commands";
667
+ empty.textContent = (config && config.text_slash_none) || "No matching commands";
656
668
  popupEl.appendChild(empty);
657
669
  return;
658
670
  }
@@ -799,8 +811,10 @@ function RTE_Plugin_SlashCommand() {
799
811
  var r = rects && rects.length ? rects[rects.length - 1] : null;
800
812
  if (!r) r = trigger.range.getBoundingClientRect();
801
813
 
802
- var left = ir.left + (r.left || 0) + window.pageXOffset;
803
- var top = ir.top + (r.bottom || r.top || 0) + window.pageYOffset + 4;
814
+ // the caret rect is in iframe pixels, scaled on screen inside a transform:scale() ancestor
815
+ var sk = iframe.offsetWidth && ir.width > 0 ? ir.width / iframe.offsetWidth : 1;
816
+ var left = ir.left + (r.left || 0) * sk + window.pageXOffset;
817
+ var top = ir.top + (r.bottom || r.top || 0) * sk + window.pageYOffset + 4;
804
818
 
805
819
  popupEl.style.position = "absolute";
806
820
  popupEl.style.left = left + "px";
@@ -809,8 +823,8 @@ function RTE_Plugin_SlashCommand() {
809
823
  // Flip up if would overflow viewport
810
824
  var vh = window.innerHeight || document.documentElement.clientHeight;
811
825
  var popupRect = popupEl.getBoundingClientRect();
812
- if (popupRect.bottom > vh - 8 && (ir.top + (r.top || 0)) > popupRect.height + 16) {
813
- popupEl.style.top = (ir.top + (r.top || 0) + window.pageYOffset - popupRect.height - 4) + "px";
826
+ if (popupRect.bottom > vh - 8 && (ir.top + (r.top || 0) * sk) > popupRect.height + 16) {
827
+ popupEl.style.top = (ir.top + (r.top || 0) * sk + window.pageYOffset - popupRect.height - 4) + "px";
814
828
  }
815
829
  }
816
830