@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.
- package/README.md +173 -10
- package/angular/build-manifest.json +23 -0
- package/angular/index.d.ts +71 -76
- package/angular/index.mjs +2 -0
- package/angular/package.json +4 -0
- package/headless/index.d.ts +3 -1
- package/headless/index.js +72 -16
- package/index.d.ts +33 -54
- package/integrations/initialization-scope.js +27 -0
- package/integrations/native-mount.js +30 -0
- package/integrations/shared.d.ts +23 -1
- package/integrations/shared.js +58 -22
- package/package.json +25 -3
- package/react/index.js +118 -37
- package/react/index.mjs +29 -0
- package/richtexteditor/all_plugins.js +7113 -1111
- package/richtexteditor/all_plugins.min.js +62 -59
- package/richtexteditor/lang/emoji/LICENSE-CLDR.txt +41 -0
- package/richtexteditor/lang/emoji/rte-emoji-de.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-es.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-fr.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-it.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-ja.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-ko.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-nl.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-pt-pt.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-pt.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-ru.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-zh-Hans.js +3 -0
- package/richtexteditor/lang/emoji/rte-emoji-zh-Hant.js +3 -0
- package/richtexteditor/lang/rte-lang-af.js +1 -0
- package/richtexteditor/lang/rte-lang-ar.js +1 -0
- package/richtexteditor/lang/rte-lang-bg.js +1 -0
- package/richtexteditor/lang/rte-lang-bn.js +1 -0
- package/richtexteditor/lang/rte-lang-bs.js +1 -0
- package/richtexteditor/lang/rte-lang-ca.js +1 -0
- package/richtexteditor/lang/rte-lang-cs.js +1 -0
- package/richtexteditor/lang/rte-lang-cy.js +1 -0
- package/richtexteditor/lang/rte-lang-da.js +1 -0
- package/richtexteditor/lang/rte-lang-de.js +1017 -2
- package/richtexteditor/lang/rte-lang-el.js +1 -0
- package/richtexteditor/lang/rte-lang-en.js +1 -0
- package/richtexteditor/lang/rte-lang-es.js +1023 -2
- package/richtexteditor/lang/rte-lang-et.js +1 -0
- package/richtexteditor/lang/rte-lang-fa.js +1 -0
- package/richtexteditor/lang/rte-lang-fi.js +1 -0
- package/richtexteditor/lang/rte-lang-fil.js +1 -0
- package/richtexteditor/lang/rte-lang-fj.js +1 -0
- package/richtexteditor/lang/rte-lang-fr.js +1023 -2
- package/richtexteditor/lang/rte-lang-ga.js +1 -0
- package/richtexteditor/lang/rte-lang-gu.js +1 -0
- package/richtexteditor/lang/rte-lang-he.js +1 -0
- package/richtexteditor/lang/rte-lang-hi.js +1 -0
- package/richtexteditor/lang/rte-lang-hr.js +1 -0
- package/richtexteditor/lang/rte-lang-ht.js +1 -0
- package/richtexteditor/lang/rte-lang-hu.js +1 -0
- package/richtexteditor/lang/rte-lang-id.js +1 -0
- package/richtexteditor/lang/rte-lang-is.js +1 -0
- package/richtexteditor/lang/rte-lang-it.js +1023 -2
- package/richtexteditor/lang/rte-lang-ja.js +1023 -2
- package/richtexteditor/lang/rte-lang-kn.js +1 -0
- package/richtexteditor/lang/rte-lang-ko.js +1023 -2
- package/richtexteditor/lang/rte-lang-lt.js +1 -0
- package/richtexteditor/lang/rte-lang-lv.js +1 -0
- package/richtexteditor/lang/rte-lang-mg.js +1 -0
- package/richtexteditor/lang/rte-lang-mi.js +1 -0
- package/richtexteditor/lang/rte-lang-ml.js +1 -0
- package/richtexteditor/lang/rte-lang-mr.js +1 -0
- package/richtexteditor/lang/rte-lang-ms.js +1 -0
- package/richtexteditor/lang/rte-lang-mt.js +1 -0
- package/richtexteditor/lang/rte-lang-mww.js +1 -0
- package/richtexteditor/lang/rte-lang-nb.js +1 -0
- package/richtexteditor/lang/rte-lang-nl.js +1023 -2
- package/richtexteditor/lang/rte-lang-otq.js +1 -0
- package/richtexteditor/lang/rte-lang-pa.js +1 -0
- package/richtexteditor/lang/rte-lang-pl.js +1 -0
- package/richtexteditor/lang/rte-lang-pt-pt.js +1023 -2
- package/richtexteditor/lang/rte-lang-pt.js +1023 -2
- package/richtexteditor/lang/rte-lang-ro.js +1 -0
- package/richtexteditor/lang/rte-lang-ru.js +1023 -2
- package/richtexteditor/lang/rte-lang-sk.js +1 -0
- package/richtexteditor/lang/rte-lang-sl.js +1 -0
- package/richtexteditor/lang/rte-lang-sm.js +1 -0
- package/richtexteditor/lang/rte-lang-sr-Cyrl.js +1 -0
- package/richtexteditor/lang/rte-lang-sr-Latn.js +1 -0
- package/richtexteditor/lang/rte-lang-sv.js +1 -0
- package/richtexteditor/lang/rte-lang-sw.js +1 -0
- package/richtexteditor/lang/rte-lang-ta.js +1 -0
- package/richtexteditor/lang/rte-lang-te.js +1 -0
- package/richtexteditor/lang/rte-lang-th.js +1 -0
- package/richtexteditor/lang/rte-lang-tlh-Latn.js +1 -0
- package/richtexteditor/lang/rte-lang-tlh-Piqd.js +1 -0
- package/richtexteditor/lang/rte-lang-to.js +1 -0
- package/richtexteditor/lang/rte-lang-tr.js +1 -0
- package/richtexteditor/lang/rte-lang-ty.js +1 -0
- package/richtexteditor/lang/rte-lang-uk.js +1 -0
- package/richtexteditor/lang/rte-lang-ur.js +1 -0
- package/richtexteditor/lang/rte-lang-vi.js +1 -0
- package/richtexteditor/lang/rte-lang-yua.js +1 -0
- package/richtexteditor/lang/rte-lang-zh-Hans.js +1017 -2
- package/richtexteditor/lang/rte-lang-zh-Hant.js +1017 -2
- package/richtexteditor/plugins/a11yenhance.js +2 -1
- package/richtexteditor/plugins/a11yenhance.min.js +1 -1
- package/richtexteditor/plugins/accessibilitychecker.js +252 -60
- package/richtexteditor/plugins/accessibilitychecker.min.js +1 -1
- package/richtexteditor/plugins/aitoolkit.js +966 -303
- package/richtexteditor/plugins/aitoolkit.min.js +7 -7
- package/richtexteditor/plugins/all_plugins.js +7113 -1111
- package/richtexteditor/plugins/all_plugins.min.js +62 -59
- package/richtexteditor/plugins/autocorrect.js +66 -31
- package/richtexteditor/plugins/autocorrect.min.js +1 -1
- package/richtexteditor/plugins/autoembed.js +17 -0
- package/richtexteditor/plugins/autoembed.min.js +1 -1
- package/richtexteditor/plugins/blocktypes.js +18 -9
- package/richtexteditor/plugins/blocktypes.min.js +1 -1
- package/richtexteditor/plugins/bookmarkcard.js +12 -5
- package/richtexteditor/plugins/bookmarkcard.min.js +2 -2
- package/richtexteditor/plugins/changecase.js +72 -19
- package/richtexteditor/plugins/changecase.min.js +1 -1
- package/richtexteditor/plugins/charlimit.js +62 -2
- package/richtexteditor/plugins/charlimit.min.js +2 -2
- package/richtexteditor/plugins/comments.js +458 -59
- package/richtexteditor/plugins/comments.min.js +4 -3
- package/richtexteditor/plugins/contentminimap.js +25 -6
- package/richtexteditor/plugins/contentminimap.min.js +1 -1
- package/richtexteditor/plugins/crossreference.js +1 -1
- package/richtexteditor/plugins/crossreference.min.js +1 -1
- package/richtexteditor/plugins/dialoga11y.js +26 -4
- package/richtexteditor/plugins/dialoga11y.min.js +1 -1
- package/richtexteditor/plugins/dictation.js +1 -1
- package/richtexteditor/plugins/documentimport.js +220 -51
- package/richtexteditor/plugins/documentimport.min.js +4 -4
- package/richtexteditor/plugins/documentoutline.js +88 -38
- package/richtexteditor/plugins/documentoutline.min.js +1 -1
- package/richtexteditor/plugins/docxexport.js +204 -32
- package/richtexteditor/plugins/docxexport.min.js +2 -2
- package/richtexteditor/plugins/draghandle.js +267 -3
- package/richtexteditor/plugins/draghandle.min.js +1 -1
- package/richtexteditor/plugins/emailtoolkit.js +28 -14
- package/richtexteditor/plugins/emailtoolkit.min.js +1 -1
- package/richtexteditor/plugins/emojiautocomplete.js +110 -56
- package/richtexteditor/plugins/emojiautocomplete.min.js +1 -1
- package/richtexteditor/plugins/footnotes.js +65 -11
- package/richtexteditor/plugins/footnotes.min.js +1 -1
- package/richtexteditor/plugins/formatpainter.js +10 -0
- package/richtexteditor/plugins/formatpainter.min.js +1 -1
- package/richtexteditor/plugins/formattingmarks.js +53 -8
- package/richtexteditor/plugins/formattingmarks.min.js +1 -1
- package/richtexteditor/plugins/gapcursor.js +60 -0
- package/richtexteditor/plugins/gapcursor.min.js +1 -1
- package/richtexteditor/plugins/ghostcomplete.js +1 -1
- package/richtexteditor/plugins/html2pdf.js +1 -1
- package/richtexteditor/plugins/html2pdf.min.js +1 -1
- package/richtexteditor/plugins/imageeditor.js +12 -6
- package/richtexteditor/plugins/imageeditor.min.js +1 -1
- package/richtexteditor/plugins/importstyles.js +1 -1
- package/richtexteditor/plugins/inlinecode.js +25 -0
- package/richtexteditor/plugins/inlinecode.min.js +1 -1
- package/richtexteditor/plugins/insertcode.js +21 -3
- package/richtexteditor/plugins/insertcode.min.js +4 -4
- package/richtexteditor/plugins/insertemoji.js +112 -15
- package/richtexteditor/plugins/insertemoji.min.js +1 -1
- package/richtexteditor/plugins/insertgallery.js +42 -36
- package/richtexteditor/plugins/insertgallery.min.js +1 -1
- package/richtexteditor/plugins/inserttemplate.js +33 -17
- package/richtexteditor/plugins/inserttemplate.min.js +1 -1
- package/richtexteditor/plugins/keyboarda11y.js +66 -3
- package/richtexteditor/plugins/keyboarda11y.min.js +1 -1
- package/richtexteditor/plugins/layouttable.js +20 -0
- package/richtexteditor/plugins/layouttable.min.js +1 -1
- package/richtexteditor/plugins/linkchecker.js +29 -9
- package/richtexteditor/plugins/linkchecker.min.js +1 -1
- package/richtexteditor/plugins/localdraft.js +51 -7
- package/richtexteditor/plugins/localdraft.min.js +1 -1
- package/richtexteditor/plugins/markdownexport.js +159 -0
- package/richtexteditor/plugins/markdownexport.min.js +2 -2
- package/richtexteditor/plugins/mathdialog.js +11 -5
- package/richtexteditor/plugins/mathdialog.min.js +1 -1
- package/richtexteditor/plugins/mentionplugin.js +88 -25
- package/richtexteditor/plugins/mentionplugin.min.js +1 -1
- package/richtexteditor/plugins/mermaiddiagram.js +9 -3
- package/richtexteditor/plugins/mermaiddiagram.min.js +2 -2
- package/richtexteditor/plugins/multilevellist.js +4 -0
- package/richtexteditor/plugins/multilevellist.min.js +1 -1
- package/richtexteditor/plugins/pdfexport.js +235 -35
- package/richtexteditor/plugins/pdfexport.min.js +12 -12
- package/richtexteditor/plugins/permanentpen.js +3 -3
- package/richtexteditor/plugins/permanentpen.min.js +1 -1
- package/richtexteditor/plugins/readabilitystats.js +25 -11
- package/richtexteditor/plugins/readabilitystats.min.js +1 -1
- package/richtexteditor/plugins/readaloud.js +29 -15
- package/richtexteditor/plugins/readaloud.min.js +1 -1
- package/richtexteditor/plugins/restrictedediting.js +166 -0
- package/richtexteditor/plugins/restrictedediting.min.js +2 -2
- package/richtexteditor/plugins/revisionhistory.js +169 -37
- package/richtexteditor/plugins/revisionhistory.min.js +3 -3
- package/richtexteditor/plugins/rubyannotation.js +19 -9
- package/richtexteditor/plugins/rubyannotation.min.js +1 -1
- package/richtexteditor/plugins/sanitizer.js +86 -4
- package/richtexteditor/plugins/sanitizer.min.js +1 -1
- package/richtexteditor/plugins/slashcommand.js +30 -16
- package/richtexteditor/plugins/slashcommand.min.js +2 -2
- package/richtexteditor/plugins/smartchips.js +36 -22
- package/richtexteditor/plugins/smartchips.min.js +2 -2
- package/richtexteditor/plugins/spellcheck.js +17 -8
- package/richtexteditor/plugins/spellcheck.min.js +2 -2
- package/richtexteditor/plugins/stateinspector.js +19 -9
- package/richtexteditor/plugins/stateinspector.min.js +2 -2
- package/richtexteditor/plugins/structured-content-bridge.js +56 -24
- package/richtexteditor/plugins/structured-content-bridge.min.js +7 -7
- package/richtexteditor/plugins/tableofcontents.js +5 -2
- package/richtexteditor/plugins/tableofcontents.min.js +1 -1
- package/richtexteditor/plugins/tabletools.js +388 -3
- package/richtexteditor/plugins/tabletools.min.js +1 -1
- package/richtexteditor/plugins/textdirection.js +18 -5
- package/richtexteditor/plugins/textdirection.min.js +1 -1
- package/richtexteditor/plugins/textpartlanguage.js +161 -32
- package/richtexteditor/plugins/textpartlanguage.min.js +1 -1
- package/richtexteditor/plugins/todolist.js +90 -6
- package/richtexteditor/plugins/todolist.min.js +1 -1
- package/richtexteditor/plugins/trackedchanges.js +1812 -25
- package/richtexteditor/plugins/trackedchanges.min.js +5 -3
- package/richtexteditor/plugins/wordexport.js +2 -2
- package/richtexteditor/plugins/yjscollab.js +9 -4
- package/richtexteditor/plugins/yjscollab.min.js +1 -1
- package/richtexteditor/plugins/zz_richtextbox_dialog_style.js +22 -13
- package/richtexteditor/plugins/zz_richtextbox_dialog_style.min.js +1 -1
- package/richtexteditor/rte-config.js +131 -50
- package/richtexteditor/rte-headless.js +19 -4
- package/richtexteditor/rte-webcomponent.js +89 -16
- package/richtexteditor/rte.js +133 -52
- package/richtexteditor/runtime/colorpicker_more_ns.htm +93 -16
- package/scripts/build-angular.mjs +97 -0
- package/svelte/index.d.ts +2 -1
- package/svelte/index.js +80 -9
- package/vue/index.js +130 -34
- package/angular/component.ts +0 -297
- package/angular/index.ts +0 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
RTE_DefaultConfig.plugin_inserttemplate=RTE_Plugin_InsertTemplate;function RTE_Plugin_InsertTemplate(){var
|
|
1
|
+
RTE_DefaultConfig.plugin_inserttemplate=RTE_Plugin_InsertTemplate;function RTE_Plugin_InsertTemplate(){var b=this,h,f;b.PluginName="InsertTemplate";function o(e,t,s){var p=h&&h["text_"+e]||t;return s===void 0?p:p.split("{0}").join(String(s))}b.InitConfig=function(e){h=e,h.htmlTemplates||(h.htmlTemplates=[])},b.InitEditor=function(e){f=e,f.attachEvent("exec_command_inserttemplate",function(t){t.returnValue=!0,b.DoInsertTemplate()})};function l(e,t,s,p){var d=e.ownerDocument.createElement(t);return s&&(d.style.cssText=s),p&&(d.className=p),e.appendChild(d),d}function j(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function A(e){var t=document.createElement("div");return t.innerHTML=e||"",t.innerText||t.textContent||""}function B(e,t){return e instanceof Array?{id:"template-"+t,title:e[0]||o("tp_template","Template {0}",t+1),html:e[1]||"",meta:e[2]||""}:e&&typeof e=="object"?{id:e.id||"template-"+t,title:e.title||e.name||e.text||o("tp_template","Template {0}",t+1),html:e.html||e.content||"",meta:e.meta||e.description||""}:typeof e=="string"?{id:"template-"+t,title:o("tp_template","Template {0}",t+1),html:e,meta:""}:null}function F(e,t){var s=206,p=166,d=Math.max(t.scrollWidth,1),g=Math.max(t.scrollHeight,1),v=Math.min(1,s/d,p/g);t.style.transformOrigin="top left",t.style.transform="scale("+v+")",t.style.width=d+"px",t.style.height=g+"px"}b.DoInsertTemplate=function(){var e=f.createDialog(f.getLangText("inserttemplatetitle")||"Insert template","rte-dialog-inserttemplate"),t=typeof e.close=="function"?function(){e.close()}:function(){f.closeCurrentPopup()},s=l(e,"div","","rte-dialog-browser"),p=l(s,"div","","rte-dialog-browser-header"),d=l(p,"div","","rte-dialog-browser-copy");d.innerText=o("tp_copy","Preview reusable layouts, search by name, and replace the current editor content with a selected template.");var g=l(s,"div","","rte-dialog-browser-toolbar"),v=l(g,"input","","rte-dialog-browser-search");v.type="search",v.placeholder=o("tp_search","Search templates"),v.setAttribute("aria-label",o("tp_search","Search templates"));var x=l(g,"div","","rte-dialog-browser-count");x.setAttribute("role","status"),x.setAttribute("aria-live","polite");var L=l(s,"div","","rte-dialog-browser-scrollpanel"),y=l(L,"div","","rte-dialog-browser-grid rte-template-grid");y.setAttribute("role","listbox"),y.setAttribute("aria-label",o("tp_available","Available templates"));var I=l(L,"div","","rte-dialog-browser-empty");I.innerText=o("tp_nomatch","No templates match the current filter.");var _=l(s,"div","","rte-gallery-browser-footer"),k=l(_,"div","","rte-gallery-browser-footer-text");k.innerText=o("tp_select","Select a template to replace the current content.");var C=l(_,"button","","rte-gallery-browser-button");C.type="button",C.innerText=o("cancel","Cancel");var w=l(_,"button","","rte-gallery-browser-button rte-gallery-browser-button-primary");w.type="button",w.innerText=o("tp_replace","Replace Content"),w.disabled=!0;var u="";function S(){var a=[],r=h.htmlTemplates||[],n;for(n=0;n<r.length;n++){var i=B(r[n],n);i&&i.html&&a.push(i)}return a}function D(){var a=v.value.replace(/^\s+|\s+$/g,"").toLowerCase(),r=S();return a?r.filter(function(n){var i=A(n.html).toLowerCase();return n.title.toLowerCase().indexOf(a)>=0||i.indexOf(a)>=0||n.meta&&n.meta.toLowerCase().indexOf(a)>=0}):r}function E(a){var r=null,n;for(n=0;n<a.length;n++)if(a[n].id===u){r=a[n];break}x.innerText=a.length===1?o("tp_count1","1 template"):o("tp_countn","{0} templates",a.length),k.innerText=r?o("tp_ready","Ready to replace the editor content with {0}.",r.title):o("tp_select","Select a template to replace the current content."),w.disabled=!r}function H(){var a=S(),r;for(r=0;r<a.length;r++)if(a[r].id===u){f.setHTMLCode(a[r].html,{undoable:!0}),t(),f.focus();return}}function M(){j(y);var a=D(),r;for(I.style.display=a.length?"none":"block",r=0;r<a.length;r++)(function(i){var c=l(y,"button","","rte-dialog-browser-card");c.type="button",c.setAttribute("role","option"),c.setAttribute("aria-selected",i.id===u?"true":"false"),i.id===u&&c.classList.add("is-selected");var N=l(c,"div","","rte-template-card-preview"),P=l(N,"div","","rte-template-card-preview-body"),R=l(P,"div","","rte-template-card-preview-canvas");R.innerHTML=i.html,F(P,R);var O=l(c,"div","","rte-template-card-footer"),W=l(O,"div","","rte-template-card-title");W.innerText=i.title;var q=l(O,"div","","rte-template-card-meta");q.innerText=i.meta||A(i.html).substring(0,80)||o("tp_reusable","Reusable template"),c.onclick=function(){u=i.id;for(var T=y.querySelectorAll(".rte-dialog-browser-card"),m=0;m<T.length;m++)T[m].classList.toggle("is-selected",T[m]===c),T[m].setAttribute("aria-selected",T[m]===c?"true":"false");E(D())},c.ondblclick=function(){u=i.id,H()}})(a[r]);if(u){var n=!1;for(r=0;r<a.length;r++)if(a[r].id===u){n=!0;break}n||(u="")}E(a)}v.oninput=M,C.onclick=t,w.onclick=H,M(),v.focus()}}
|
|
@@ -58,6 +58,10 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
58
58
|
// Public so plugins can report their own outcomes -- find/replace match
|
|
59
59
|
// counts, what the paste filter removed, export completion.
|
|
60
60
|
editor.announce = function (text, opts) { return announce(text, opts); };
|
|
61
|
+
// 2026-10-11 WCAG 4.1.3: the outcome of a formatting command is announced (see announceFormatOutcome).
|
|
62
|
+
try { editor.attachEvent("exec_command", function (state, cmd) { announceFormatOutcome(cmd); }); } catch (e) { }
|
|
63
|
+
// 2026-10-11 WCAG 4.1.3: a URL linked as it was typed is announced ("Link created: example.com"). rte.js fires "autolink".
|
|
64
|
+
try { editor.attachEvent("autolink", function (state, href, word) { announce((isSuggesting() ? "Link suggested: " : "Link created: ") + word); }); } catch (e) { }
|
|
61
65
|
// setReadOnly() lives in the core and cannot call into a plugin, so wrap
|
|
62
66
|
// it here rather than leaving the two states to drift apart.
|
|
63
67
|
if (typeof editor.setReadOnly === "function" && !editor.setReadOnly.__a11yWrapped) {
|
|
@@ -162,6 +166,56 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
162
166
|
return true;
|
|
163
167
|
}
|
|
164
168
|
|
|
169
|
+
// 2026-10-11 WCAG 4.1.3 (Status Messages): a formatting shortcut or button turned bold, italic or underline on or
|
|
170
|
+
// off, and nothing was spoken - a sighted user reads the highlighted button, a screen reader user could not tell
|
|
171
|
+
// whether bold was on. The event fires before the command runs, so the state is read on the next tick, from the
|
|
172
|
+
// editor's own report (isCommandActive). Only these inline toggles are spoken; typing announces nothing.
|
|
173
|
+
// tools/a11y/format-announce.mjs
|
|
174
|
+
var FORMAT_ANNOUNCE = { bold: "Bold", italic: "Italic", underline: "Underline", strikethrough: "Strikethrough",
|
|
175
|
+
subscript: "Subscript", superscript: "Superscript" };
|
|
176
|
+
// 2026-10-11 WCAG 4.1.3: a list button turns a list on or off and a heading command sets a level, and neither was
|
|
177
|
+
// spoken. A list is read the same way as the inline toggles. A block change names the block the caret is now in
|
|
178
|
+
// ("Heading 2", "Paragraph"), read from the selection because the event carries no level.
|
|
179
|
+
// tools/a11y/block-announce.mjs
|
|
180
|
+
var LIST_ANNOUNCE = { insertunorderedlist: "Bulleted list", insertorderedlist: "Numbered list" };
|
|
181
|
+
function currentBlockName() {
|
|
182
|
+
var doc = editor.getDocument();
|
|
183
|
+
var sel = doc && doc.getSelection();
|
|
184
|
+
var n = sel && sel.anchorNode;
|
|
185
|
+
while (n && n.nodeType !== 1) n = n.parentNode;
|
|
186
|
+
while (n && n !== doc.body) {
|
|
187
|
+
if (/^H[1-6]$/.test(n.tagName)) return "Heading " + n.tagName.charAt(1);
|
|
188
|
+
if (n.tagName === "P") return "Paragraph";
|
|
189
|
+
n = n.parentNode;
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
// 2026-10-11 WCAG 4.1.3: in suggesting mode the change is only a suggestion until it is accepted, so it is announced as
|
|
194
|
+
// one ("Suggested: Bulleted list on"). Outside suggesting mode the wording is unchanged.
|
|
195
|
+
// tools/a11y/suggest-announce.mjs
|
|
196
|
+
function isSuggesting() {
|
|
197
|
+
try { return !!(editor.trackedChanges && editor.trackedChanges.isEnabled()); } catch (e) { return false; }
|
|
198
|
+
}
|
|
199
|
+
function suggestionPrefix() {
|
|
200
|
+
return isSuggesting() ? "Suggested: " : "";
|
|
201
|
+
}
|
|
202
|
+
function announceFormatOutcome(cmd) {
|
|
203
|
+
var key = String(cmd || "").toLowerCase();
|
|
204
|
+
var name = FORMAT_ANNOUNCE[key] || LIST_ANNOUNCE[key];
|
|
205
|
+
if (!name && key !== "formatblock") return;
|
|
206
|
+
setTimeout(function () {
|
|
207
|
+
var prefix = suggestionPrefix();
|
|
208
|
+
if (key === "formatblock") {
|
|
209
|
+
var block = currentBlockName();
|
|
210
|
+
if (block) announce(prefix + block);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
var on = false;
|
|
214
|
+
try { on = !!editor.isCommandActive(key); } catch (e) { return; }
|
|
215
|
+
announce(prefix + name + (on ? " on" : " off"));
|
|
216
|
+
}, 0);
|
|
217
|
+
}
|
|
218
|
+
|
|
165
219
|
// ------------------------------------------------- 5. read-only state
|
|
166
220
|
//
|
|
167
221
|
// setReadOnly() flips designMode, which genuinely blocks editing -- but
|
|
@@ -221,6 +275,7 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
221
275
|
doc.addEventListener("keydown", function (e) {
|
|
222
276
|
if (e.key !== "Escape" && e.keyCode !== 27) return;
|
|
223
277
|
if (anythingOpen()) return; // let the panel close itself
|
|
278
|
+
if (e.defaultPrevented) return; // 2026-10-17 already handled (the link card closed itself)
|
|
224
279
|
e.preventDefault();
|
|
225
280
|
e.stopPropagation();
|
|
226
281
|
if (!focusFirstToolbarButton()) focusAfterEditor();
|
|
@@ -261,11 +316,12 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
261
316
|
// So: a host-supplied label still wins as the name; otherwise we supply a
|
|
262
317
|
// real one and the hint follows it.
|
|
263
318
|
function announceEscape(ed) {
|
|
264
|
-
|
|
319
|
+
// 2026-10-18 the default hint and name read the language pack. tools/i18n/plugin-default-keys.mjs
|
|
320
|
+
var hint = config.a11yEscapeHint || config.text_escleave ||
|
|
265
321
|
"Press Escape to leave the editing area.";
|
|
266
322
|
var label = ed.getAttribute("aria-label") || "";
|
|
267
323
|
if (label.indexOf(hint) >= 0) return;
|
|
268
|
-
var name = label || config.a11yEditorLabel || "Rich text editor";
|
|
324
|
+
var name = label || config.a11yEditorLabel || config.text_editorname || "Rich text editor";
|
|
269
325
|
ed.setAttribute("aria-label", name.replace(/\s*$/, "") + " " + hint);
|
|
270
326
|
}
|
|
271
327
|
|
|
@@ -389,7 +445,9 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
389
445
|
// which inserts a block rather than toggling the selection. They are kept —
|
|
390
446
|
// harmless, and correct the moment a toolbar button is added — but they
|
|
391
447
|
// cover nothing today, so do not read this list as evidence of coverage.
|
|
392
|
-
|
|
448
|
+
// 2026-10-15 the toolbar command is "strike", not "strikethrough", so Strikethrough never had aria-pressed;
|
|
449
|
+
// spellcheck is a toggle too. tools/a11y/toggle-pressed.mjs
|
|
450
|
+
var TOGGLE_CMD = /^(bold|italic|underline|strike|strikethrough|spellcheck|subscript|superscript|justifyleft|justifycenter|justifyright|justifyfull|insertorderedlist|insertunorderedlist|outdent|indent|insertblockquote|toggleborder|inlinecode|trackchanges|typewriter|focusmode|pagination|formattingmarks|linenumbers|permanentpen|rtlui)$/;
|
|
393
451
|
|
|
394
452
|
function syncToggleStates(root) {
|
|
395
453
|
var btns = [].slice.call(root.querySelectorAll('[role="button"][rte-cmd-name]'));
|
|
@@ -397,6 +455,11 @@ function RTE_Plugin_KeyboardA11y() {
|
|
|
397
455
|
var cmd = (btns[i].getAttribute("rte-cmd-name") || "").toLowerCase();
|
|
398
456
|
if (!TOGGLE_CMD.test(cmd)) continue;
|
|
399
457
|
var active = btns[i].classList.contains("rte-command-active");
|
|
458
|
+
// 2026-10-15 a split button's inner half (the list buttons) is the control a screen reader lands on, but
|
|
459
|
+
// the active class goes on the outer rte-toolbar-splitbutton: it said not pressed inside a list.
|
|
460
|
+
// tools/a11y/toggle-pressed.mjs
|
|
461
|
+
var outer = btns[i].parentNode;
|
|
462
|
+
if (!active && outer && outer.nodeName === "RTE-TOOLBAR-SPLITBUTTON") active = outer.classList.contains("rte-command-active");
|
|
400
463
|
var pressed = active ? "true" : "false";
|
|
401
464
|
if (btns[i].getAttribute("aria-pressed") !== pressed) btns[i].setAttribute("aria-pressed", pressed);
|
|
402
465
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_keyboarda11y=RTE_Plugin_KeyboardA11y,typeof RTE_DefaultConfig.keyboardA11y>"u"&&(RTE_DefaultConfig.keyboardA11y=!0);function RTE_Plugin_KeyboardA11y(){var
|
|
1
|
+
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_keyboarda11y=RTE_Plugin_KeyboardA11y,typeof RTE_DefaultConfig.keyboardA11y>"u"&&(RTE_DefaultConfig.keyboardA11y=!0);function RTE_Plugin_KeyboardA11y(){var w=this,d,i,O=[],p=null,y=[];w.PluginName="KeyboardA11y",w.InitConfig=function(r){d=r},w.InitEditor=function(r){if(i=r,d.keyboardA11y!==!1){i.focusToolbar=function(){return C()},i.announce=function(n,a){return h(n,a)};try{i.attachEvent("exec_command",function(n,a){H(a)})}catch{}try{i.attachEvent("autolink",function(n,a,o){h((N()?"Link suggested: ":"Link created: ")+o)})}catch{}if(typeof i.setReadOnly=="function"&&!i.setReadOnly.__a11yWrapped){var t=i.setReadOnly,e=function(n){var a=t.apply(i,arguments);try{R()}catch{}return a};e.__a11yWrapped=!0,i.setReadOnly=e}m();try{i.attachEvent("ready",m)}catch{}setTimeout(m,0),setTimeout(m,400)}};function b(){try{var r=i.getEditable();if(!r)return null;for(var t=r.ownerDocument.defaultView,e=t&&t.frameElement?t.frameElement:r;e&&e.classList&&!e.classList.contains("richtexteditor");)e=e.parentNode;return e&&e.classList?e:null}catch{return null}}function m(){var r=b();r&&(T(),R(),F(),k(r),S(r),E(r),G(r))}var v=null;function T(){if(v&&v.polite&&v.polite.isConnected)return v;var r=b();if(!r)return null;function t(e){var n=r.querySelector('[data-rte-live="'+e+'"]');return n||(n=document.createElement("div"),n.setAttribute("data-rte-live",e),n.setAttribute("aria-live",e),n.setAttribute("aria-atomic","true"),n.setAttribute("role",e==="assertive"?"alert":"status"),n.style.cssText="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;",r.appendChild(n),n)}return v={polite:t("polite"),assertive:t("assertive")},v}function h(r,t){var e=String(r??"").trim();if(!e)return!1;var n=T();if(!n)return!1;var a=t&&t.assertive?n.assertive:n.polite;return a.textContent="",setTimeout(function(){a.textContent=e},30),!0}var D={bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},I={insertunorderedlist:"Bulleted list",insertorderedlist:"Numbered list"};function q(){for(var r=i.getDocument(),t=r&&r.getSelection(),e=t&&t.anchorNode;e&&e.nodeType!==1;)e=e.parentNode;for(;e&&e!==r.body;){if(/^H[1-6]$/.test(e.tagName))return"Heading "+e.tagName.charAt(1);if(e.tagName==="P")return"Paragraph";e=e.parentNode}return null}function N(){try{return!!(i.trackedChanges&&i.trackedChanges.isEnabled())}catch{return!1}}function B(){return N()?"Suggested: ":""}function H(r){var t=String(r||"").toLowerCase(),e=D[t]||I[t];!e&&t!=="formatblock"||setTimeout(function(){var n=B();if(t==="formatblock"){var a=q();a&&h(n+a);return}var o=!1;try{o=!!i.isCommandActive(t)}catch{return}h(n+e+(o?" on":" off"))},0)}var x=null;function R(){var r;try{r=i.getEditable()}catch{return}if(r){var t=!1;try{t=!!(i.getReadOnly?i.getReadOnly():i.isReadOnly&&i.isReadOnly())}catch{}r.setAttribute("aria-readonly",t?"true":"false");var e=d.a11yReadOnlySuffix||"Read only.",n=r.getAttribute("aria-label")||"";n.length>=e.length&&n.slice(-e.length)===e&&(n=n.slice(0,-e.length).replace(/\s+$/,"")),r.setAttribute("aria-label",t?n+" "+e:n),x!==null&&x!==t&&h(t?e:d.a11yEditableAgain||"Editing enabled."),x=t}}function F(){var r,t;try{r=i.getEditable(),t=r&&r.ownerDocument}catch{return}!r||!t||(t.__rteEscapeHatch||(t.__rteEscapeHatch=!0,t.addEventListener("keydown",function(e){e.key!=="Escape"&&e.keyCode!==27||M()||e.defaultPrevented||(e.preventDefault(),e.stopPropagation(),C()||W())},!1)),U(r))}function M(){try{for(var r=document.querySelectorAll("rte-dropdown-panel, rte-dialog-float, rte-floatpanel"),t=0;t<r.length;t++){var e=getComputedStyle(r[t]);if(e.display!=="none"&&e.visibility!=="hidden")return!0}}catch{}return!1}function U(r){var t=d.a11yEscapeHint||d.text_escleave||"Press Escape to leave the editing area.",e=r.getAttribute("aria-label")||"";if(!(e.indexOf(t)>=0)){var n=e||d.a11yEditorLabel||d.text_editorname||"Rich text editor";r.setAttribute("aria-label",n.replace(/\s*$/,"")+" "+t)}}function W(){var r=b();if(!r)return!1;for(var t=[].slice.call(document.querySelectorAll('a[href],button,input,select,textarea,[tabindex]:not([tabindex="-1"])')).filter(function(n){return!r.contains(n)&&n.offsetParent!==null}),e=0;e<t.length;e++)if(r.compareDocumentPosition(t[e])&Node.DOCUMENT_POSITION_FOLLOWING)return t[e].focus(),!0;return!1}function L(r){return[].slice.call(r.querySelectorAll('[role="toolbar"]'))}function A(r){return[].slice.call(r.querySelectorAll('[role="button"]')).filter(function(t){return t.getAttribute("aria-disabled")==="true"||t.offsetParent===null?!1:(t.closest&&t.closest('[role="toolbar"]'))===r})}function k(r){if(d.a11yRovingToolbar!==!1)for(var t=L(r),e=0;e<t.length;e++)(function(n){var a=A(n);if(a.length){for(var o=a.filter(function(s){return s.getAttribute("tabindex")==="0"})[0]||a[0],l=0;l<a.length;l++)a[l].setAttribute("tabindex",a[l]===o?"0":"-1");n.__rteRoving||(n.__rteRoving=!0,n.addEventListener("keydown",function(s){var u=A(n),f=u.indexOf(document.activeElement);if(!(f<0)){var g=!!(n.closest&&n.closest('[dir="rtl"]')),c=null;if(s.key==="ArrowRight")c=u[(f+(g?-1:1)+u.length)%u.length];else if(s.key==="ArrowLeft")c=u[(f+(g?1:-1)+u.length)%u.length];else if(s.key==="Home")c=u[0];else if(s.key==="End")c=u[u.length-1];else return;s.preventDefault();for(var _=0;_<u.length;_++)u[_].setAttribute("tabindex",u[_]===c?"0":"-1");c.focus()}},!1),n.addEventListener("focusin",function(s){var u=A(n);if(!(u.indexOf(s.target)<0))for(var f=0;f<u.length;f++)u[f].setAttribute("tabindex",u[f]===s.target?"0":"-1")},!1))}})(t[e])}function C(){var r=b();if(!r)return!1;for(var t=L(r),e=0;e<t.length;e++){var n=A(t[e]);if(n.length){var a=n.filter(function(o){return o.getAttribute("tabindex")==="0"})[0]||n[0];return a.focus(),!0}}return!1}var $=/^(bold|italic|underline|strike|strikethrough|spellcheck|subscript|superscript|justifyleft|justifycenter|justifyright|justifyfull|insertorderedlist|insertunorderedlist|outdent|indent|insertblockquote|toggleborder|inlinecode|trackchanges|typewriter|focusmode|pagination|formattingmarks|linenumbers|permanentpen|rtlui)$/;function S(r){for(var t=[].slice.call(r.querySelectorAll('[role="button"][rte-cmd-name]')),e=0;e<t.length;e++){var n=(t[e].getAttribute("rte-cmd-name")||"").toLowerCase();if($.test(n)){var a=t[e].classList.contains("rte-command-active"),o=t[e].parentNode;!a&&o&&o.nodeName==="RTE-TOOLBAR-SPLITBUTTON"&&(a=o.classList.contains("rte-command-active"));var l=a?"true":"false";t[e].getAttribute("aria-pressed")!==l&&t[e].setAttribute("aria-pressed",l)}}}function E(r){for(var t=[].slice.call(r.querySelectorAll("[aria-haspopup]")),e=0;e<t.length;e++)t[e].hasAttribute("aria-expanded")||t[e].setAttribute("aria-expanded","false"),!t[e].__rtePopupBound&&(t[e].__rtePopupBound=!0,(function(a){function o(){p=a}a.addEventListener("mousedown",o,!0),a.addEventListener("keydown",function(l){(l.key==="Enter"||l.key===" "||l.key==="ArrowDown")&&o()},!0)})(t[e]));if(!E.bound){E.bound=!0;var n=new MutationObserver(function(a){for(var o=0;o<a.length;o++){for(var l=a[o],s=0;s<l.addedNodes.length;s++){var u=l.addedNodes[s];u.nodeType!==1||!P(u)||p&&(p.setAttribute("aria-expanded","true"),y.push({panel:u,owner:p}),p=null)}for(var f=0;f<l.removedNodes.length;f++){var g=l.removedNodes[f];if(!(g.nodeType!==1||!P(g)))for(var c=y.length-1;c>=0;c--)y[c].panel===g&&(y[c].owner.setAttribute("aria-expanded","false"),y.splice(c,1))}}});n.observe(document.body,{childList:!0,subtree:!0}),O.push(n)}}function P(r){var t=(r.tagName||"").toLowerCase();return t==="rte-dropdown-panel"||t==="rte-floatpanel"||t==="rte-dialog-float"}function G(r){if(!r.__rteA11yWatch){r.__rteA11yWatch=!0;var t=null,e=new MutationObserver(function(){t||(t=setTimeout(function(){t=null,S(r),k(r),E(r)},60))});e.observe(r,{subtree:!0,childList:!0,attributes:!0,attributeFilter:["class","aria-disabled"]}),O.push(e)}}}
|
|
@@ -331,6 +331,26 @@ function RTE_Plugin_LayoutTable() {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
function insertAtCaret(node, doc) {
|
|
334
|
+
// 2026-10-04 through the core's block placement: range.insertNode put the table INSIDE the
|
|
335
|
+
// paragraph (<p>one two<table>...</p>, invalid HTML). The caret then goes into the first cell.
|
|
336
|
+
// tools/tables/layout-table-placement.mjs
|
|
337
|
+
if (typeof editor.insertElement === "function") {
|
|
338
|
+
try {
|
|
339
|
+
editor.insertElement(node);
|
|
340
|
+
if (node.parentNode) {
|
|
341
|
+
var cell = node.querySelector("td,th");
|
|
342
|
+
var sel0 = editor.getSelection();
|
|
343
|
+
if (cell && sel0) {
|
|
344
|
+
var r0 = node.ownerDocument.createRange();
|
|
345
|
+
r0.setStart(cell, 0);
|
|
346
|
+
r0.collapse(true);
|
|
347
|
+
sel0.removeAllRanges();
|
|
348
|
+
sel0.addRange(r0);
|
|
349
|
+
}
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
} catch (e) { /* the plain insert below */ }
|
|
353
|
+
}
|
|
334
354
|
var inserted = false;
|
|
335
355
|
try {
|
|
336
356
|
var sel = editor.getSelection();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_layouttable=RTE_Plugin_LayoutTable,typeof RTE_DefaultConfig.layoutTableOutline>"u"&&(RTE_DefaultConfig.layoutTableOutline=!0);function RTE_Plugin_LayoutTable(){var i=this,
|
|
1
|
+
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_layouttable=RTE_Plugin_LayoutTable,typeof RTE_DefaultConfig.layoutTableOutline>"u"&&(RTE_DefaultConfig.layoutTableOutline=!0);function RTE_Plugin_LayoutTable(){var i=this,g,o,h=typeof WeakMap=="function"?new WeakMap:null;i.PluginName="LayoutTable",i.InitConfig=function(e){g=e},i.InitEditor=function(e){o=e,o.attachEvent("exec_command_tablelayoutmode",function(t){t.returnValue=!0,i.SetMode(s(),"layout")}),o.attachEvent("exec_command_tabledatamode",function(t){t.returnValue=!0,i.SetMode(s(),"data")}),o.attachEvent("exec_command_toggletablelayout",function(t){t.returnValue=!0,i.Toggle()}),o.attachEvent("exec_command_insertlayouttable",function(t){t.returnValue=!0,i.InsertLayoutTable()}),o.setTableLayoutMode=function(t,r,n){return i.SetMode(r||s(),t,n)},o.getTableLayoutMode=function(t){var r=t||s();return r?m(r)?"layout":"data":null},o.isLayoutTable=function(t){return m(t||s())},o.toggleTableLayoutMode=function(){return i.Toggle()},o.insertLayoutTable=function(t,r,n){return i.InsertLayoutTable(t,r,n)},o.listLayoutTables=function(){var t=C();if(!t)return[];for(var r=[],n=t.getElementsByTagName("table"),a=0;a<n.length;a++)m(n[a])&&r.push(n[a]);return r},o.showLayoutTableOutlines=function(t){return y=t!==!1,p(v()),y};try{g&&typeof g.layoutTableOutline<"u"&&(y=!!g.layoutTableOutline)}catch{}p(v());try{o.attachEvent("editor_ready",function(){p(v())}),o.attachEvent("update_design",function(){p(v())})}catch{}};var y=!0;i.SetMode=function(e,t,r){return e?String(t).toLowerCase()==="layout"?w(e):A(e,r):null},i.Toggle=function(){var e=s();return e?m(e)?A(e):w(e):null},i.InsertLayoutTable=function(e,t,r){var n=v();if(!n)return null;e=Math.max(1,parseInt(e,10)||2),t=Math.max(1,parseInt(t,10)||2),r=r||{};var a=n.createElement("table");a.setAttribute("role","presentation"),a.setAttribute("cellpadding","0"),a.setAttribute("cellspacing","0"),a.style.width=r.width||"100%",a.style.borderCollapse="collapse";for(var u=n.createElement("tbody"),l=0;l<e;l++){for(var f=n.createElement("tr"),c=0;c<t;c++){var d=n.createElement("td");d.style.verticalAlign="top",d.appendChild(n.createElement("br")),f.appendChild(d)}u.appendChild(f)}return a.appendChild(u),M(a,n),p(n),E(),a};function w(e){e.setAttribute("role","presentation");var t=b(e,"caption");if(t){var r=String(t.textContent||"").replace(/^\s+|\s+$/g,"");if(r){for(var n=e.ownerDocument.createElement("p");t.firstChild;)n.appendChild(t.firstChild);e.parentNode&&e.parentNode.insertBefore(n,e)}t.parentNode.removeChild(t)}e.removeAttribute("summary");for(var a=L(e),u=[],l=0;l<a.length;l++){var f=a[l];if(f.removeAttribute("scope"),f.removeAttribute("headers"),f.removeAttribute("abbr"),f.nodeName==="TH"){var c=T(f,"td");u.push(c)}}h&&u.length&&h.set(e,u);var d=b(e,"thead");return d&&R(e,d),E(),e}function A(e,t){e.removeAttribute("role");var r=h?h.get(e):null,n=!1;if(r&&r.length){for(var a=0;a<r.length;a++){var u=r[a];u&&u.parentNode&&D(e,u)&&(T(u,"th"),n=!0)}h.delete(e)}return!n&&t&&t.promoteFirstRow&&S(e),E(),e}function S(e){var t=_(e);if(t.length)for(var r=x(t[0]),n=0;n<r.length;n++){var a=T(r[n],"th");a.setAttribute("scope","col")}}function m(e){if(!e||e.nodeName!=="TABLE")return!1;var t=String(e.getAttribute("role")||"").toLowerCase();return t==="presentation"||t==="none"}function N(e,t){for(var r=t.parentNode;r&&r!==e;){if(r.nodeName==="TABLE")return!1;r=r.parentNode}return r===e}function L(e){for(var t=[],r=e.querySelectorAll?e.querySelectorAll("th,td"):[],n=0;n<r.length;n++)N(e,r[n])&&t.push(r[n]);return t}function _(e){for(var t=[],r=e.querySelectorAll?e.querySelectorAll("tr"):[],n=0;n<r.length;n++)N(e,r[n])&&t.push(r[n]);return t}function x(e){for(var t=[],r=e.firstChild;r;r=r.nextSibling)(r.nodeName==="TH"||r.nodeName==="TD")&&t.push(r);return t}function b(e,t){t=t.toUpperCase();for(var r=e.firstChild;r;r=r.nextSibling)if(r.nodeName===t)return r;return null}function D(e,t){for(var r=t;r;){if(r===e)return!0;r=r.parentNode}return!1}function R(e,t){var r=b(e,"tbody");for(r||(r=e.ownerDocument.createElement("tbody"),e.insertBefore(r,t.nextSibling));t.firstChild;)r.insertBefore(t.firstChild,r.firstChild);t.parentNode.removeChild(t)}function T(e,t){for(var r=e.ownerDocument,n=r.createElement(t),a=0;a<e.attributes.length;a++){var u=e.attributes[a];try{n.setAttribute(u.name,u.value)}catch{}}for(;e.firstChild;)n.appendChild(e.firstChild);return e.parentNode.replaceChild(n,e),n}function s(){var e=C();if(!e)return null;var t=null;try{var r=o.getSelection();r&&r.rangeCount&&(t=r.getRangeAt(0).startContainer)}catch{}if(!t)return null;for(t.nodeType===3&&(t=t.parentNode);t&&t!==e;){if(t.nodeName==="TABLE")return t;t=t.parentNode}return null}function M(e,t){if(typeof o.insertElement=="function")try{if(o.insertElement(e),e.parentNode){var r=e.querySelector("td,th"),n=o.getSelection();if(r&&n){var a=e.ownerDocument.createRange();a.setStart(r,0),a.collapse(!0),n.removeAllRanges(),n.addRange(a)}return!0}}catch{}var u=!1;try{var l=o.getSelection();if(l&&l.rangeCount){var f=l.getRangeAt(0);f.deleteContents(),f.insertNode(e),u=!0}}catch{}if(!u){var c=C();c&&(c.appendChild(e),u=!0)}return u}function C(){try{return o.getEditable()}catch{return null}}function v(){var e=C();return e?e.ownerDocument:null}function p(e){if(e){var t=y?"table[role=presentation]{outline:1px dashed rgba(120,120,140,.55);outline-offset:1px;}table[role=presentation] td{outline:1px dashed rgba(120,120,140,.28);}":"",r=e.getElementById("rte-layout-table-styles");if(r){if(r.getAttribute("data-css")===t)return;r.parentNode&&r.parentNode.removeChild(r)}if(t){var n=e.createElement("style");n.id="rte-layout-table-styles",n.setAttribute("data-css",t),n.appendChild(e.createTextNode(t)),(e.head||e.getElementsByTagName("head")[0]||e.documentElement).appendChild(n),o&&typeof o.ensureStyleSheetLive=="function"&&o.ensureStyleSheetLive(e,n,"rte-layout-table-styles",n.textContent)}}}function E(){try{typeof o.updateDesign=="function"&&o.updateDesign()}catch{}try{typeof o.fireChange=="function"&&o.fireChange()}catch{}}}
|
|
@@ -105,6 +105,31 @@ function RTE_Plugin_LinkChecker() {
|
|
|
105
105
|
return out;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
// 2026-10-03 Whether an in-document fragment lands somewhere. It was looked up with
|
|
109
|
+
// querySelector("#" + id), which THROWS for an id that is not a CSS identifier - one starting
|
|
110
|
+
// with a digit, which is what a numbered heading's generated id looks like ("1. Introduction" ->
|
|
111
|
+
// "1-introduction") - and the throw was reported as a broken anchor: every link to a numbered
|
|
112
|
+
// clause and every table-of-contents entry of a numbered document was flagged. Now the id is
|
|
113
|
+
// compared as a string, the percent-decoded form counts too (#caf%C3%A9 lands on the accented
|
|
114
|
+
// id, as in a browser), and "#top" lands at the top, as the HTML spec says.
|
|
115
|
+
// tools/links/link-checker.mjs
|
|
116
|
+
function anchorExists(editable, raw) {
|
|
117
|
+
var ids = [raw];
|
|
118
|
+
try {
|
|
119
|
+
var decoded = decodeURIComponent(raw);
|
|
120
|
+
if (decoded !== raw) ids.push(decoded);
|
|
121
|
+
} catch (e) { /* not valid percent-encoding: the raw form only */ }
|
|
122
|
+
var named = editable.querySelectorAll("[id], a[name]");
|
|
123
|
+
for (var i = 0; i < ids.length; i++) {
|
|
124
|
+
if (ids[i].toLowerCase() === "top") return true;
|
|
125
|
+
for (var j = 0; j < named.length; j++) {
|
|
126
|
+
if (named[j].getAttribute("id") === ids[i]) return true;
|
|
127
|
+
if (named[j].nodeName === "A" && named[j].getAttribute("name") === ids[i]) return true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
108
133
|
// Everything decidable without the network.
|
|
109
134
|
function offlineIssues() {
|
|
110
135
|
var editable = getEditable();
|
|
@@ -128,7 +153,7 @@ function RTE_Plugin_LinkChecker() {
|
|
|
128
153
|
|
|
129
154
|
if (!a.hasAttribute("href")) {
|
|
130
155
|
add("error", "empty-href",
|
|
131
|
-
"Link has no destination
|
|
156
|
+
"Link has no destination \u2014 its address may have been removed for being unsafe.");
|
|
132
157
|
continue;
|
|
133
158
|
}
|
|
134
159
|
if (!href || href === "#") {
|
|
@@ -150,12 +175,7 @@ function RTE_Plugin_LinkChecker() {
|
|
|
150
175
|
// breakage because headings get retitled and ids change.
|
|
151
176
|
if (href.charAt(0) === "#") {
|
|
152
177
|
var id = href.substring(1);
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
target = editable.querySelector("#" + id.replace(/["\\\]\[]/g, "\\$&")) ||
|
|
156
|
-
editable.querySelector('[name="' + id.replace(/"/g, '\\"') + '"]');
|
|
157
|
-
} catch (e) { target = null; }
|
|
158
|
-
if (!target) add("error", "broken-anchor", "Links to #" + id + ", which does not exist in this document.");
|
|
178
|
+
if (!anchorExists(editable, id)) add("error", "broken-anchor", "Links to #" + id + ", which does not exist in this document.");
|
|
159
179
|
} else if (/^[a-z][a-z0-9+.-]*:/i.test(href) || href.indexOf("//") === 0) {
|
|
160
180
|
// Absolute URL: parse it to catch malformed ones.
|
|
161
181
|
var parsed = parseUrl(href);
|
|
@@ -207,8 +227,8 @@ function RTE_Plugin_LinkChecker() {
|
|
|
207
227
|
out.push({
|
|
208
228
|
element: group[g2].a, href: group[g2].href, text: group[g2].a.textContent.trim(),
|
|
209
229
|
severity: "warning", code: "ambiguous-text",
|
|
210
|
-
message: "Several links share the text
|
|
211
|
-
"
|
|
230
|
+
message: "Several links share the text \u201c" + group[g2].a.textContent.trim() +
|
|
231
|
+
"\u201d but point to different destinations."
|
|
212
232
|
});
|
|
213
233
|
}
|
|
214
234
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_linkchecker=RTE_Plugin_LinkChecker,typeof RTE_DefaultConfig.linkCheckResolver>"u"&&(RTE_DefaultConfig.linkCheckResolver=null),typeof RTE_DefaultConfig.linkCheckUnsafeSchemes>"u"&&(RTE_DefaultConfig.linkCheckUnsafeSchemes=["javascript:","data:","vbscript:","file:"]),typeof RTE_DefaultConfig.linkCheckMixedContent>"u"&&(RTE_DefaultConfig.linkCheckMixedContent=!0);function RTE_Plugin_LinkChecker(){var d=this,A,
|
|
1
|
+
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_linkchecker=RTE_Plugin_LinkChecker,typeof RTE_DefaultConfig.linkCheckResolver>"u"&&(RTE_DefaultConfig.linkCheckResolver=null),typeof RTE_DefaultConfig.linkCheckUnsafeSchemes>"u"&&(RTE_DefaultConfig.linkCheckUnsafeSchemes=["javascript:","data:","vbscript:","file:"]),typeof RTE_DefaultConfig.linkCheckMixedContent>"u"&&(RTE_DefaultConfig.linkCheckMixedContent=!0);function RTE_Plugin_LinkChecker(){var d=this,A,o,F=null,S=!1,p=[],w=!1;d.PluginName="LinkChecker",d.InitConfig=function(e){A=e},d.InitEditor=function(e){o=e,o.attachEvent("exec_command_checklinks",function(t){t.returnValue=!0,d.Check()}),x();try{o.attachEvent("ready",x)}catch{}try{o.attachEvent("aftersethtml",x)}catch{}setTimeout(x,0),o.checkLinks=function(){return d.Check()},o.getLinkIssues=function(){return p.slice()},o.highlightLinkIssues=function(t){return I(t!==!1)},o.clearLinkHighlights=function(){return I(!1)},o.getLinkCheckerCss=function(){return q()}};function x(){var e=R();e&&(Q(e),K(),F=e)}function R(){try{return o.getDocument()}catch{return null}}function L(){try{return o.getEditable()}catch{return null}}function D(){var e=L();if(!e)return[];for(var t=e.querySelectorAll("a"),r=[],n=0;n<t.length;n++){var a=t[n];if(a.hasAttribute("href")){r.push(a);continue}a.getAttribute("name")||a.getAttribute("id")||r.push(a)}return r}function J(e,t){var r=[t];try{var n=decodeURIComponent(t);n!==t&&r.push(n)}catch{}for(var a=e.querySelectorAll("[id], a[name]"),i=0;i<r.length;i++){if(r[i].toLowerCase()==="top")return!0;for(var u=0;u<a.length;u++)if(a[u].getAttribute("id")===r[i]||a[u].nodeName==="A"&&a[u].getAttribute("name")===r[i])return!0}return!1}function V(){var e=L(),t=[];if(!e)return t;var r=D(),n=A.linkCheckUnsafeSchemes||[],a=!1;try{a=window.location.protocol==="https:"}catch{}for(var i={},u=0;u<r.length;u++){var l=r[u],s=(l.getAttribute("href")||"").trim(),f=(l.textContent||"").trim(),c=function(W,X,Y){t.push({element:l,href:s,text:f,severity:W,code:X,message:Y})};if(!l.hasAttribute("href")){c("error","empty-href","Link has no destination \u2014 its address may have been removed for being unsafe.");continue}if(!s||s==="#"){c("error","empty-href","Link has no destination.");continue}for(var b=s.toLowerCase(),y=null,h=0;h<n.length;h++)if(b.indexOf(n[h])===0){y=n[h];break}if(y){c("error","unsafe-scheme","Link uses the "+y+" scheme, which is unsafe in published content.");continue}if(s.charAt(0)==="#"){var k=s.substring(1);J(e,k)||c("error","broken-anchor","Links to #"+k+", which does not exist in this document.")}else if(/^[a-z][a-z0-9+.-]*:/i.test(s)||s.indexOf("//")===0){var v=P(s);if(!v)c("error","malformed","Link address cannot be parsed as a URL.");else if(A.linkCheckMixedContent!==!1&&a&&v.protocol==="http:"&&c("warning","mixed-content","Insecure http:// link on a secure page; browsers may block or warn."),/^(https?:\/\/|www\.)/i.test(f)){var g=P(/^www\./i.test(f)?"http://"+f:f);g&&g.hostname&&v.hostname&&g.hostname.toLowerCase()!==v.hostname.toLowerCase()&&c("warning","deceptive-text","Link text shows "+g.hostname+" but the link goes to "+v.hostname+".")}}if(f){var M=f.toLowerCase();(i[M]=i[M]||[]).push({a:l,href:s})}else{for(var O=!1,U=l.querySelectorAll?l.querySelectorAll("img[alt]"):[],T=0;T<U.length;T++)(U[T].getAttribute("alt")||"").trim()&&(O=!0);!O&&!(l.getAttribute("aria-label")||"").trim()&&!(l.getAttribute("title")||"").trim()&&c("error","empty-text","Link has no text, image alt, aria-label or title, so it has no accessible name.")}}for(var z in i)if(i.hasOwnProperty(z)){var m=i[z];if(!(m.length<2)){for(var B={},_=0;_<m.length;_++)B[m[_].href]=!0;if(!(Object.keys(B).length<2))for(var C=0;C<m.length;C++)t.push({element:m[C].a,href:m[C].href,text:m[C].a.textContent.trim(),severity:"warning",code:"ambiguous-text",message:"Several links share the text \u201C"+m[C].a.textContent.trim()+"\u201D but point to different destinations."})}}return t}function P(e){try{var t=R()||document,r=t.createElement("a");return r.href=e,!r.protocol||r.protocol===":"?null:{protocol:r.protocol,hostname:r.hostname,pathname:r.pathname}}catch{return null}}d.Check=function(){var e=V(),t=A.linkCheckResolver;if(typeof t!="function")return p=e,E(e),typeof Promise=="function"?Promise.resolve(e.slice()):e.slice();for(var r={},n=0;n<e.length;n++)r[e[n].href]=!0;for(var a=[],i={},u=D(),l=0;l<u.length;l++){var s=(u[l].getAttribute("href")||"").trim();!s||s.charAt(0)==="#"||r[s]||i[s]||/^https?:/i.test(s)&&(i[s]=!0,a.push(s))}return a.length?Promise.resolve().then(function(){return t(a.slice())}).then(function(f){f=f||{};for(var c={},b=0;b<u.length;b++){var y=(u[b].getAttribute("href")||"").trim();(c[y]=c[y]||[]).push(u[b])}for(var h in f)if(f.hasOwnProperty(h)){var k=f[h];if(!(!k||k.ok!==!1))for(var v=c[h]||[],g=0;g<v.length;g++)e.push({element:v[g],href:h,text:(v[g].textContent||"").trim(),severity:"error",code:"unreachable",message:"Link did not resolve"+(k.status?" (HTTP "+k.status+")":"")+"."})}return p=e,E(e),e.slice()}).catch(function(){return p=e,E(e),e.slice()}):(p=e,E(e),typeof Promise=="function"?Promise.resolve(e.slice()):e.slice())};function E(e){w&&N(e);try{o.fireEvent&&o.fireEvent("linkcheck",e)}catch{}}function I(e){return w=!!e,w?N(p):H(),w}function H(){var e=L();if(e)for(var t=e.querySelectorAll("a[data-rte-link-issue]"),r=0;r<t.length;r++)t[r].removeAttribute("data-rte-link-issue"),t[r].removeAttribute("data-rte-link-issue-message")}function N(e){H();for(var t=0;t<e.length;t++){var r=e[t].element;!r||!r.setAttribute||r.getAttribute("data-rte-link-issue")!=="error"&&(r.setAttribute("data-rte-link-issue",e[t].severity),r.setAttribute("data-rte-link-issue-message",e[t].message))}}function G(){var e=L();if(!e)return function(){};for(var t=e.querySelectorAll("a[data-rte-link-issue]"),r=[],n=0;n<t.length;n++)r.push({el:t[n],sev:t[n].getAttribute("data-rte-link-issue"),msg:t[n].getAttribute("data-rte-link-issue-message")}),t[n].removeAttribute("data-rte-link-issue"),t[n].removeAttribute("data-rte-link-issue-message");return function(){for(var i=0;i<r.length;i++)r[i].el.setAttribute("data-rte-link-issue",r[i].sev),r[i].msg&&r[i].el.setAttribute("data-rte-link-issue-message",r[i].msg)}}function K(){if(!S){for(var e=["getHTMLCode","getJSON","getHTMLContent","getText"],t=!1,r=0;r<e.length;r++)(function(n){var a=o[n];if(!(typeof a!="function"||a.__rteLcWrapped)){var i=function(){var u=G();try{return a.apply(o,arguments)}finally{u()}};i.__rteLcWrapped=!0,o[n]=i,t=!0}})(e[r]);t&&(S=!0)}}function q(){return"a[data-rte-link-issue='error']{background:rgba(220,38,38,.12);box-shadow:inset 0 -2px 0 rgba(220,38,38,.65);border-radius:2px;}a[data-rte-link-issue='warning']{background:rgba(217,119,6,.12);box-shadow:inset 0 -2px 0 rgba(217,119,6,.6);border-radius:2px;}"}function Q(e){if(e){var t=e.getElementById("rte-link-checker-styles"),r=q();if(t){if(t.getAttribute("data-css")===r)return;t.parentNode&&t.parentNode.removeChild(t)}var n=e.createElement("style");n.id="rte-link-checker-styles",n.setAttribute("data-css",r),n.appendChild(e.createTextNode(r)),(e.head||e.getElementsByTagName("head")[0]||e.documentElement).appendChild(n),o&&typeof o.ensureStyleSheetLive=="function"&&o.ensureStyleSheetLive(e,n,"rte-link-checker-styles",n.textContent)}}}
|
|
@@ -38,7 +38,9 @@ function RTE_Plugin_LocalDraft() {
|
|
|
38
38
|
editor.clearLocalDraft = function () { try { store().removeItem(resolveKey()); } catch (e) {} hideBar(); return true; };
|
|
39
39
|
editor.restoreLocalDraft = function () {
|
|
40
40
|
var d = read(); if (!d) return false;
|
|
41
|
-
|
|
41
|
+
// 2026-10-03 undoable: Ctrl+Z gives back exactly the document the draft replaced
|
|
42
|
+
// (tools/import/replace-undo-plugins.mjs)
|
|
43
|
+
try { editor.setHTMLCode(d.html, { undoable: true }); } catch (e) { return false; }
|
|
42
44
|
try { if (typeof editor.fireChange === "function") editor.fireChange(); } catch (e) {}
|
|
43
45
|
hideBar();
|
|
44
46
|
return true;
|
|
@@ -92,12 +94,54 @@ function RTE_Plugin_LocalDraft() {
|
|
|
92
94
|
function intervalMs() { var n = opts && +opts.intervalMs; return (n && n > 250) ? n : 2500; }
|
|
93
95
|
function ttlMs() { var n = opts && +opts.ttlMs; return (n && n > 0) ? n : 14 * 24 * 60 * 60 * 1000; }
|
|
94
96
|
|
|
97
|
+
// 2026-10-02 The key names the EDITOR. It was the editing body's id - which the editor never
|
|
98
|
+
// sets - else the page path, so every editor on a page shared ONE draft: the last to save
|
|
99
|
+
// overwrote the other's, and after a reload Restore put one editor's text into the other (a
|
|
100
|
+
// form with a summary and a body editor lost the summary). Now: config key; else that body id
|
|
101
|
+
// (as before); else the replaced textarea's id or name; else the container's id; else the
|
|
102
|
+
// editor's place among the page's editors. The page's first editor with none of these keeps
|
|
103
|
+
// the old key (the page path), so a single editor's pending draft survives the upgrade; and
|
|
104
|
+
// when the page's only editor gets a new key, a draft under the old one moves to it (read).
|
|
105
|
+
// tools/autosave/local-draft-keys.mjs
|
|
106
|
+
var cachedKey = null;
|
|
107
|
+
function pagePath() {
|
|
108
|
+
try { return location.pathname; } catch (e) { return "default"; }
|
|
109
|
+
}
|
|
95
110
|
function resolveKey() {
|
|
96
111
|
if (opts && opts.key) return "rte-draft:" + opts.key;
|
|
112
|
+
if (cachedKey) return cachedKey;
|
|
97
113
|
var id = "";
|
|
98
114
|
try { var ed = editor.getEditable(); id = (ed && (ed.id || (ed.getAttribute && ed.getAttribute("data-rte-id")))) || ""; } catch (e) {}
|
|
99
|
-
if (
|
|
100
|
-
|
|
115
|
+
if (id) return (cachedKey = "rte-draft:" + id);
|
|
116
|
+
var name = "";
|
|
117
|
+
try {
|
|
118
|
+
var inp = editor.input;
|
|
119
|
+
if (inp) name = inp.id || inp.getAttribute("name") || "";
|
|
120
|
+
if (!name && editor.container && editor.container.id) name = editor.container.id;
|
|
121
|
+
} catch (e) {}
|
|
122
|
+
if (!name) {
|
|
123
|
+
var index = 0;
|
|
124
|
+
try {
|
|
125
|
+
var all = document.querySelectorAll(".richtexteditor");
|
|
126
|
+
for (var i = 0; i < all.length; i++) if (all[i] === editor.container) { index = i; break; }
|
|
127
|
+
} catch (e) {}
|
|
128
|
+
if (index > 0) name = "editor-" + index;
|
|
129
|
+
}
|
|
130
|
+
return (cachedKey = "rte-draft:" + pagePath() + (name ? "#" + name : ""));
|
|
131
|
+
}
|
|
132
|
+
// A draft saved under the old shared key belongs to this editor only when it is the page's
|
|
133
|
+
// only one; then it moves to this editor's key.
|
|
134
|
+
function takeLegacyDraft(k) {
|
|
135
|
+
var legacy = "rte-draft:" + pagePath();
|
|
136
|
+
if (legacy === k) return null;
|
|
137
|
+
try {
|
|
138
|
+
if (document.querySelectorAll(".richtexteditor").length !== 1) return null;
|
|
139
|
+
var raw = store().getItem(legacy);
|
|
140
|
+
if (!raw) return null;
|
|
141
|
+
store().setItem(k, raw);
|
|
142
|
+
store().removeItem(legacy);
|
|
143
|
+
return raw;
|
|
144
|
+
} catch (e) { return null; }
|
|
101
145
|
}
|
|
102
146
|
|
|
103
147
|
function store() { return window.localStorage; }
|
|
@@ -123,7 +167,7 @@ function RTE_Plugin_LocalDraft() {
|
|
|
123
167
|
|
|
124
168
|
function read() {
|
|
125
169
|
try {
|
|
126
|
-
var raw = store().getItem(resolveKey());
|
|
170
|
+
var raw = store().getItem(resolveKey()) || takeLegacyDraft(resolveKey());
|
|
127
171
|
if (!raw) return null;
|
|
128
172
|
var rec = JSON.parse(raw);
|
|
129
173
|
if (!rec || typeof rec.html !== "string") return null;
|
|
@@ -165,9 +209,9 @@ function RTE_Plugin_LocalDraft() {
|
|
|
165
209
|
bar.setAttribute("aria-live", "polite");
|
|
166
210
|
var msg = document.createElement("span");
|
|
167
211
|
msg.className = "rte-localdraft-message";
|
|
168
|
-
msg.textContent = "An unsaved draft
|
|
169
|
-
var restore = mkBtn("Restore", "primary");
|
|
170
|
-
var discard = mkBtn("Discard", "secondary");
|
|
212
|
+
msg.textContent = when ? ((typeof config !== "undefined" && config && config.text_ld_foundwhen) || "An unsaved draft from {0} was found.").split("{0}").join(when) : ((typeof config !== "undefined" && config && config.text_ld_found) || "An unsaved draft was found.");
|
|
213
|
+
var restore = mkBtn(((typeof config !== "undefined" && config && config.text_ld_restore) || "Restore"), "primary");
|
|
214
|
+
var discard = mkBtn(((typeof config !== "undefined" && config && config.text_ld_discard) || "Discard"), "secondary");
|
|
171
215
|
restore.onclick = function () { editor.restoreLocalDraft(); };
|
|
172
216
|
discard.onclick = function () { editor.clearLocalDraft(); };
|
|
173
217
|
bar.appendChild(msg); bar.appendChild(restore); bar.appendChild(discard);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_localdraft=RTE_Plugin_LocalDraft,typeof RTE_DefaultConfig.localDraft>"u"&&(RTE_DefaultConfig.localDraft=!1);function RTE_Plugin_LocalDraft(){var
|
|
1
|
+
window.RTE_DefaultConfig||(window.RTE_DefaultConfig={}),RTE_DefaultConfig.plugin_localdraft=RTE_Plugin_LocalDraft,typeof RTE_DefaultConfig.localDraft>"u"&&(RTE_DefaultConfig.localDraft=!1);function RTE_Plugin_LocalDraft(){var m=this,a,n,i=null,k=null,p=null,g="",o=null,D=!1,_=null;m.PluginName="LocalDraft",m.InitConfig=function(t){a=t},m.InitEditor=function(t){if(n=t,n.saveLocalDraft=function(){return h(!0)},n.hasLocalDraft=function(){return!!v()},n.getLocalDraft=function(){return v()},n.clearLocalDraft=function(){try{f().removeItem(l())}catch{}return L(),!0},n.restoreLocalDraft=function(){var e=v();if(!e)return!1;try{n.setHTMLCode(e.html,{undoable:!0})}catch{return!1}try{typeof n.fireChange=="function"&&n.fireChange()}catch{}return L(),!0},!!a.localDraft){i=typeof a.localDraft=="object"?a.localDraft:{},k=l();var r=function(){D||(g=N(),j(),I())};try{n.attachEvent("ready",r)}catch{}try{n.attachEvent("ready",E)}catch{}try{n.attachEvent("aftersethtml",E)}catch{}setTimeout(r,0)}};var b=function(){B()};function E(){if(!(!a||!a.localDraft)){var t=n.getDocument();if(t&&t!==_){try{t.addEventListener("input",b,!0)}catch{}_=t}}}function I(){if(!D){D=!0;try{n.attachEvent("change",b)}catch{}try{n.attachEvent("keyup",b)}catch{}E();try{window.addEventListener("beforeunload",function(){h(!1)},!1),window.addEventListener("pagehide",function(){h(!1)},!1)}catch{}}}function R(){var t=i&&+i.intervalMs;return t&&t>250?t:2500}function x(){var t=i&&+i.ttlMs;return t&&t>0?t:336*60*60*1e3}var s=null;function C(){try{return location.pathname}catch{return"default"}}function l(){if(i&&i.key)return"rte-draft:"+i.key;if(s)return s;var t="";try{var r=n.getEditable();t=r&&(r.id||r.getAttribute&&r.getAttribute("data-rte-id"))||""}catch{}if(t)return s="rte-draft:"+t;var e="";try{var u=n.input;u&&(e=u.id||u.getAttribute("name")||""),!e&&n.container&&n.container.id&&(e=n.container.id)}catch{}if(!e){var c=0;try{for(var d=document.querySelectorAll(".richtexteditor"),y=0;y<d.length;y++)if(d[y]===n.container){c=y;break}}catch{}c>0&&(e="editor-"+c)}return s="rte-draft:"+C()+(e?"#"+e:"")}function S(t){var r="rte-draft:"+C();if(r===t)return null;try{if(document.querySelectorAll(".richtexteditor").length!==1)return null;var e=f().getItem(r);return e?(f().setItem(t,e),f().removeItem(r),e):null}catch{return null}}function f(){return window.localStorage}function B(){p||(p=setTimeout(function(){p=null,h(!1)},R()))}function N(){try{return n.getHTMLCode()||""}catch{return""}}function h(t){if(!a||!a.localDraft)return!1;var r=N();if(!t&&(r===g||T(r)))return!1;var e={html:r,t:w()};try{return f().setItem(l(),JSON.stringify(e)),!0}catch{return!1}}function v(){try{var t=f().getItem(l())||S(l());if(!t)return null;var r=JSON.parse(t);if(!r||typeof r.html!="string")return null;if(r.t&&w()-r.t>x()){try{f().removeItem(l())}catch{}return null}return r}catch{return null}}function T(t){if(!t)return!0;var r=t.replace(/<[^>]*>/g,"").replace(/ /gi," ").replace(/\s+/g,"");return r.length===0}function w(){try{return Date.now()}catch{return 0}}function j(){if(!(i&&i.promptRestore===!1)){var t=v();t&&(t.html===g||T(t.html)||H(t))}}function H(t){L();var r=O();if(!(!r||!r.parentNode)){var e=P(t.t);o=document.createElement("div"),o.className="rte-localdraft-bar",o.setAttribute("data-rte-localdraft","1"),o.setAttribute("role","status"),o.setAttribute("aria-live","polite");var u=document.createElement("span");u.className="rte-localdraft-message",u.textContent=e?(typeof a<"u"&&a&&a.text_ld_foundwhen||"An unsaved draft from {0} was found.").split("{0}").join(e):typeof a<"u"&&a&&a.text_ld_found||"An unsaved draft was found.";var c=A(typeof a<"u"&&a&&a.text_ld_restore||"Restore","primary"),d=A(typeof a<"u"&&a&&a.text_ld_discard||"Discard","secondary");c.onclick=function(){n.restoreLocalDraft()},d.onclick=function(){n.clearLocalDraft()},o.appendChild(u),o.appendChild(c),o.appendChild(d),r.parentNode.insertBefore(o,r)}}function A(t,r){var e=document.createElement("button");return e.type="button",e.textContent=t,e.className="rte-localdraft-button is-"+r,e}function L(){o&&o.parentNode&&o.parentNode.removeChild(o),o=null}function O(){try{var t=n.getDocument(),r=t&&t.defaultView&&t.defaultView.frameElement;if(r){for(var e=r,u=0;u<4&&e.parentNode;u++){if(e.parentNode&&/rte[_-](outer|container|wrapper)/i.test(e.parentNode.className||""))return e.parentNode;e=e.parentNode}return r}}catch{}try{return n.getEditable()}catch{return null}}function P(t){if(!t)return"";try{var r=new Date(t),e=(w()-t)/1e3;return e<60?"just now":e<3600?Math.round(e/60)+" min ago":e<86400?Math.round(e/3600)+" hr ago":r.toLocaleString()}catch{return""}}}
|