github xdan/jodit 4.12.22

14 hours ago

πŸ› Bug Fix

  • Clipboard (copy/cut inside the editor): copying or cutting a selection that sat entirely inside the text of a formatted element (e.g. selecting part of a bold-italic word with the mouse) put the bare text into the clipboard β€” the <strong>/<em>/… context was lost, so pasting it elsewhere dropped the formatting. Native browser copy keeps that context, but Jodit intercepts copy/cut and serialized only the range contents. The copied fragment is now wrapped in shallow clones of the selection's inline ancestors, like browsers do. Fixes #1202.
  • Source mode / multiple editors: switching an editor into source mode focused its code mirror unconditionally β€” when the switch happened programmatically (e.g. a Vue/React wrapper re-initializing the editor) it pulled the focus out of the editor the user was typing in. The mirror is now focused only when the focus is not already inside another editor or control. Fixes #1356 (follow-up to #1313).
  • Limit (limitChars + countTextSpaces): the character limiter never counted spaces β€” even with countTextSpaces: true the limit applied to non-space characters only (limitChars: 10 allowed I am only 8 because only 8 visible characters were counted), while the status-bar counter showed the space-inclusive number. With countTextSpaces: true the limiter now counts characters the same way as the counter β€” including spaces. Fixes #1144.
  • Value assignment re-requested images (jodit-react): every editor.value = … assignment parsed the HTML into a helper element of the live document to sanitize it, so the browser issued a network request for every <img> in the value β€” with wrappers that sync the value on each change (e.g. jodit-react onChange), the image URLs were re-requested on every click/keystroke. The sanitize sandbox is now an inert document (implementation.createHTMLDocument), which never loads sub-resources; Dom.isElement/Dom.isHTMLElement no longer require a browsing context (defaultView), so the sanitizer keeps working on inert nodes. The internal safeHTML hook is now fired as an event for extensibility. Fixes #1237.
  • Inline toolbar (toolbarInlineForSelection): clicking a button in the selection toolbar (e.g. Bold) applied the command but closed the toolbar, even though the selection was still active β€” applying several formats required re-selecting the same text again and again. After a command fired from inside the popup, the selection toolbar is now reopened while the selection is not collapsed. Fixes #1238.
  • Clean HTML (allowTags): when cleanHTML.allowTags was configured as a map with per-tag attribute rules (e.g. {p: true, a: {href: true}}) and the content contained a tag outside the list that had attributes (e.g. <meta charset="utf-8"> from pasted e-mail HTML), the cleanup worker threw TypeError: Cannot read properties of undefined on every pass β€” the editor "crashed" on the first click and disallowed tags were never removed. The attribute filter now skips tags that are not in the allow list (the tags filter removes them). Fixes #1224.
  • Paste (plain text): pasting plain text containing a stray < (e.g. TD}gy{<KMj3ScW1[efbi) lost everything after the bracket β€” the clipboard text was inserted through the HTML path, so <KMj3… was parsed as an unclosed tag and swallowed the rest of the string. When the clipboard contains only text/plain (and it is not actual HTML), special characters are now escaped before insertion, so <, > and & survive as literal text; the nl2brInPlainText line-break conversion still applies after escaping. Fixes #1227.
  • i18n (Turkish): the Word/Excel paste prompt ("The pasted content is coming from a Microsoft Word/Excel document…") was shown in German when the editor language was set to Turkish β€” langs/tr.js contained a copy of the German translation for that key. Replaced with the proper Turkish text. Fixes #1245.
  • Dialog: a dialog (e.g. Paste as HTML) could be resized by its corner handle to a size smaller than its own header, content and footer, so the footer buttons ended up rendered outside the dialog box. Interactive resizing is now clamped to a minimum size: dialog.minWidth/dialog.minHeight options when set, otherwise the sum of the header, the content's CSS min-height and the footer (and the footer buttons' row width). Fixes #1262.
  • Resize handler / Iframe: resizing the editor itself by the statusbar handle was jerky in iframe mode β€” while dragging, the editor height jumped between two values. Same root cause as the image-resizer fix below: mousemove events proxied from the editor's iframe carry iframe-viewport coordinates and were mixed as-is with host-window ones; they are now shifted into the host coordinate space (checked via e.view). Fixes #1287.
  • Resizer / Iframe: resizing an image (or table) by its handles was jerky in iframe mode (e.g. with editHTMLDocumentMode) β€” the size jumped while dragging, making it impossible to set precisely. During a drag, mousemove events arrive both from the host window (pointer over the resize frame) and proxied from the editor's iframe (pointer over the content), but the iframe-viewport coordinate correction was applied to all of them, so host-window events were shifted by the workplace offset. The correction is now applied only to events that originate from the iframe window (e.view). Fixes #1264.

🏠 Internal

  • Popup tests: added a regression test asserting that with allowTabNavigation: true an inner popup (a dropdown opened from a button inside another popup β€” e.g. the image Horizontal align list) is positioned next to its trigger button. With that option the inner popup is appended into the button inside the outer popup, whose CSS transform shifts position: fixed coordinates; covers #1265 (already fixed in 4.12.8 by the getFixedPositionOffset containing-block compensation from #1350).
  • Shadow DOM tests: added regression tests asserting that with the shadowRoot option the image resizer frame, the image properties dialog (double click) and the inline popup all open correctly inside the shadow root. Covers the scenario from #1109, which does not reproduce with a vanilla Shadow DOM.
  • Tooltip tests: added a regression test asserting that buttons inside the table-cell inline popup show their tooltip on hover. Covers #1141, fixed back in 4.2.40.
  • Image-processor tests: added regression tests asserting that a base64 (data:) image is replaced with a blob: URL only in the view and never leaks into editor.value, the source element, the controlled-value loop (value re-assigned on every change, as jodit-react does) or the value left after destruct() (React remount). Covers the scenario from #1244, which does not reproduce in the core editor.
  • Selection tests: added a regression test asserting that editor.selection.insertHTML() called after the editor lost focus (e.g. from a click handler on a non-focusable page element) inserts at the previously saved caret position instead of the start of the editor. Covers the scenario from #1239, which does not reproduce on the current version in Chrome or Firefox.
  • Color tests: added a regression test asserting that applying a font color over a selection that includes a whole table recolors the text in every cell β€” including cells whose color sits on the <td> itself (as Word produces) rather than on inner spans. Covers the scenario from #1221, which does not reproduce on the current version.
  • Select-cells tests: added a regression test asserting that the table cells popup stays open after a fast drag-select β€” including a pending trailing throttled mousemove, the Firefox redraw-hack cleanup, debounced history changes and the browser's click dispatched on the common TR ancestor. Covers the scenario from #1174, which does not reproduce on the current version in Chrome or Firefox.
  • Paste tests: added regression tests asserting that Word's inter-word spaces placed in their own spans (<span style="letter-spacing:-.5pt"> </span>) survive pasting in every mode (keep, clean, text). Covers the scenario from #1230, which does not reproduce on the current version (verified with the full table HTML from the issue).
  • Resizer tests: added a regression test asserting that in iframe: true + editHTMLDocumentMode: true mode the image resize frame is hidden when the iframe content is scrolled (the iframe plugin proxies the inner window's scroll event into the main window, where the resizer plugin listens). Covers the scenario from #1266, which does not reproduce on the current version.

Don't miss a new jodit release

NewReleases is sending notifications on new releases.