🐛 Bug Fix
- Security (stored XSS): the HTML sanitizer (
safeHTML) strippedon*event handlers andjavascript:links but left several executable constructs in the serialized editor value, so an application that re-renderededitor.valueas trusted HTML could execute attacker script. It now also: dropsiframe[srcdoc]; removesdata:text/html/data:application/xhtml(and SVGdata:URLs iniframe/object/embed/frame) sources; and stripsjavascript:/vbscript:/livescript:/mocha:from every URL-bearing attribute (src,data,action,formaction,poster,background,xlink:href), not just<a href>. Safedata:image/*sources (e.g. base64 PNG/SVG used in<img>) are preserved. Responsibly reported by Yuji Tounai. - Paste (Insert as Text): pasting multi-line content with the Insert as Text option lost its line breaks — the escaped text kept raw newlines that collapse to spaces when rendered. The Insert as Text path now converts newlines to
<br>(gated onnl2brInPlainText, like the plain-text paste path). Fixes #1093. - Hotkeys: the default keyboard shortcut for Insert Unordered List (
Ctrl/Cmd+Shift+8) never fired — both variants were written as a single comma-joined string'ctrl+shift+8, cmd+shift+8'instead of two separate array entries, so the combined value never matched a real keypress. Fixes #1079. - Color / Brush button: the brush (text/background color) button never reflected the color under the caret. Its
updatehandler computed the current color into the icon fill but then unconditionally reseticon.fillto an empty string on every toolbar update, discarding it — which also made the icon render invisibly against some themes (editorCssClass). The computed fill is now kept when a color is present (and only cleared when there is none). Fixes #195 and #182. - Toolbar / Selection: when a text selection was started inside the editor and the mouse button was released outside of the editable area (a drag-select that ends over the page), the editor never received the
mouseupevent, so the active state of toolbar buttons (Bold, Italic, etc.) was not recalculated and stayed stale. A document-levelmouseuplistener now re-fireschangeSelectionwhen the selection still belongs to the editor, so the toolbar updates correctly. Fixes #1251. - Media embed (YouTube & Vimeo): real-world share URLs were not converted to an embedded player. For YouTube, short links of the form
https://youtu.be/<id>?si=…(the Share button format) and?t=timestamp links were inserted as plain text — the video id sits in the path but was only read when there was no query string — and/shorts/<id>//live/<id>produced a brokenembed/shorts/<id>src. For Vimeo,?share=copytracking params andchannels/<name>/<id>/groups/<name>/videos/<id>URLs produced a brokenvideo/channels/…src.convertMediaUrlToVideoEmbednow extracts the video id (and the unlisted Vimeo hash) from the URL path, ignoring tracking params and channel/group/embed/shorts/liveprefixes, and also recognises them.youtube.com(mobile) andmusic.youtube.comhosts. Fixes #1209. - Indent / Lists: the Decrease Indent (outdent) toolbar button stayed disabled when the cursor was inside a nested list item, even though
Shift+Tabcould un-nest it. The button's enabled state only considered an inline indent margin and ignored list nesting. It is now also enabled when the cursor sits in a list whose parent is another list item (matching thetabplugin's outdent behaviour). Fixes #1247. - Uploader (base64): with
uploader.insertImageAsBase64URI = true, dropping or pasting images in formats outside the defaultimagesExtensionslist — notably.svg,.bmp,.webp— failed withNeed Url for Ajax Requestinstead of being inlined as a data URI (the file fell through to the server-upload path). The defaultimagesExtensionsnow also includeswebp,bmp,svg,tiffandavif. Fixes #1228. - Paste (Insert only Text): pasting multi-paragraph HTML with the Insert only Text option collapsed everything into a single paragraph — block boundaries became spaces, so the text could no longer be split into list items or separate blocks.
stripTagsgained an opt-inblockBrmode and the Insert only Text path now uses it (gated onnl2brInPlainText), so paragraphs are separated by<br>. The defaultstripTagsbehaviour (space-joined single-line plain text) is unchanged. Fixes #1232. - Paste from Word: list items pasted from Microsoft Word kept their auto-generated marker text — the bullet glyph or the literal item number (
1.,2., …) leaked into the content as plain text. Word emits these markers inside<span style="mso-list:Ignore">elements that are explicitly flagged as display-only; both paste paths now drop those spans entirely instead of just stripping their attributes —cleanFromWord(the Clean / As text options) andapplyStyles(the Keep / insert-as-HTML option). Fixes #948.
🏠 Internal
- Accessibility tests: added a regression test asserting that a toolbar button's
aria-labelis placed on the interactive<button>element (not only on the wrapper<span>), covering the toolbar-specific case of #1261 (already fixed in 4.9.7). - Color tests: added a regression test for applying a single font color over a selection that already contains several different colors — every part of the text must be recolored, none left without a color, covering #169 (already fixed in the v4 style engine).