Release notes · Updated May 2026

What’s new in RichTextEditor

A running log of releases for the RichTextEditor JavaScript library and the @@richscripts2/richtexteditor npm package. Major features, breaking changes, and migration notes are called out at the top of each release.

Latest
May 19, 2026
npm 2.2.3

Editing-experience push — 88 small-to-medium UX features added in one wave. No breaking changes; everything opt-out via config.

Smart typography while you type New

The editor now recognises five common typing patterns and substitutes the Unicode typographic glyph automatically — skipped inside <code>, <pre>, and <kbd> blocks so code samples stay verbatim.

  • Auto-link on space — URLs, www. hosts, and email addresses wrap into <a> the moment you press space. javascript:, vbscript:, and non-image data: URIs are blocked.
  • Em-dash-- becomes —.
  • Ellipsis... becomes ….
  • Smart quotes — straight "x" becomes “x”; it's becomes it’s (letter-aware apostrophe).
  • Trademarks(c), (r), (tm) become ©, ®, ™.

Opt-out master switch: config.smartTypography = false. Per-feature flags also available.

23 keyboard shortcuts at Google Docs / Word parity New

Every shortcut shows in toolbar tooltips (Mac auto-detects & uses ⌘ ⇧ ⌥). Press Ctrl+/ anywhere in the editor for the full cheat-sheet modal.

  • Headings: Ctrl+Alt+1..6, normal paragraph Ctrl+Alt+0
  • Lists: numbered Ctrl+Shift+7, bullet Ctrl+Shift+8, blockquote Ctrl+Shift+9
  • Align: Ctrl+Shift+L / E / R / J
  • Strike / Sub / Super / Clear: Ctrl+Shift+X, Ctrl+,, Ctrl+., Ctrl+\
  • Insert: link Ctrl+K, horizontal rule Ctrl+Shift+-
  • Paste plain: Ctrl+Shift+V
  • Highlight (yellow <mark>): Ctrl+Shift+H
  • Duplicate block: Ctrl+Shift+DMove block up / down: Alt+↑ / ↓
  • Cycle case (UPPER → lower → Title): Ctrl+Shift+K
  • Sort lines (alphabetical): Ctrl+Shift+Alt+S
  • Reading mode (distraction-free): Ctrl+Shift+M — persists across reloads via localStorage
  • Word count details: Ctrl+Shift+C
  • Cheat sheet: Ctrl+/

Auto-generated heading anchor IDs + copy-link on hover New

Every h1h6 automatically receives a stable slug ID derived from its text (NFKD-normalised, lower-case, hyphenated, deduped). Hover a heading and a small 🔗 chip appears; click it to copy the deep-link (current URL plus the slug) to your clipboard. TOC plugins, share-link patterns, and screen-reader navigation all work without manual ID assignment.

Smart paste from Word + Google Docs Improved

Two paste-cleanup paths landed:

  • Word internal-bookmark anchors (<a name="OLE_LINK1">, <a name="_Toc..."> etc.) are stripped on paste so the text doesn’t arrive as blue-underlined links. Anchors with a real href survive unchanged.
  • Google Docs wrapper (<b id="docs-internal-guid-..."> that makes everything bold) gets unwrapped, leaving only the genuine formatting.

When either path fires, a brief toast appears bottom-centre: “Cleaned from Word — Undo: Ctrl+Z”. Opt-out via config.smartPasteToast = false.

Restricted editing templates New

Word-style “protect document with editable regions.” Pass restrictedEditingMode: true to lock the document; mark fillable spans at runtime with editor.restrictedEditing.markSelection(). Use it for contracts, forms, and fillable templates — only the marked regions accept input. Tab between regions via goToNext() / goToPrev(); regions get a soft green outline for discoverability. Full TypeScript declarations shipped in index.d.ts.

Markdown round-trip New

Two new instance methods: editor.toMarkdown() (HTML → CommonMark subset) and editor.fromMarkdown(md, { apply }) (CommonMark → HTML). Round-trips through headings, bold / italic / strike / code, links, images, lists with proper indented nesting, blockquotes, horizontal rules, fenced code blocks, and pipe-tables. Round-trip-stable with the existing markdown-shortcut parser.

Smart-find live highlight + match count New

editor.openFindDialog() shows a small floating panel with a live count badge (“3 of 12”), Prev / Next navigation that auto-scrolls to the active hit, Replace single + Replace all. Every match is wrapped in <mark class="rte-find-hit"> so you can see the matches at a glance. Programmatic: editor.findHighlight(query, { caseSensitive }) returns { matches }.

Auto-save with status New

Pass config.autoSave = { onSave: function(html) {...} } and the editor debounces saves, hashes content to skip no-op writes, and renders “Saving…” → “✓ Saved at HH:MM” in the status bar. Promise-aware (waits for your save to resolve before flipping to ✓); failure-aware (shows ⚠ on rejected promise / thrown error). Programmatic: editor.autoSave.trigger(), isDirty(), lastSavedAt().

Auto-grow, sticky toolbar, reading mode, block drag handles New

Four composable mode switches for layout flexibility.

  • config.autoGrow = true — editor expands to fit content, no inner scrollbar.
  • config.stickyToolbar = true — toolbar sticks to top of viewport on long pages.
  • editor.toggleReadingMode() + Ctrl+Shift+M — distraction-free, hides chrome.
  • config.blockDragHandles = true — Notion-style ⁞ handle appears on hover; drag to reorder paragraphs/lists/tables.

Editing-flow fixes that just match expectations UX

  • Enter on an empty <li> exits the list (no more chains of empty bullets).
  • Enter on an empty blockquote line exits the blockquote.
  • Backspace at column 0 of an <li> outdents one level instead of merging into the previous paragraph.
  • Backspace at column 0 of a blockquote exits the blockquote.
  • Tab in a list nests; Shift+Tab outdents.
  • Image upload inserts inline at the caret — no more forced centring.
  • Insert table defaults to width:100%; cells get visible borders (dotted in toggle-border mode) and minimum dimensions so empty tables don’t vanish.
  • Snippets: type :date / :time / :datetime / :hr + Tab; register your own with editor.snippets.register(":sig", "<p>...</p>", { isHtml: true }).

Selection chrome polish UX

  • Inline link URL preview — clickable URL appears in the float toolbar when caret is in an <a>; opens in a new tab safely with rel="noopener noreferrer".
  • Image hover quick-action bar — floating Alt / Replace / × chips appear when hovering an <img>; Replace opens a file picker, × deletes the image.
  • Inline alt-text editor — images missing alt get a dashed amber outline; click to open an inline popup that sets the alt attribute.
  • Video (IFRAME) float toolbar — gets the same handles + action chips as images.
  • Table column & row resize handles — hover near a border, cursor changes to resize, drag to resize.
  • Float toolbar icons enlarged 22 → 30 px button / 14 → 18 px SVG, all toolbars.

Print preview + PDF export New

editor.printPreview() opens a clean print-ready window; editor.exportPdf({ title }) additionally auto-triggers the print dialog so the user can pick “Save as PDF” as the destination — browser-native, no library required. A @media print stylesheet hides all toolbar / chrome / handles so only the document content prints.

Math markup hook New

editor.applyMathMarkup() wraps every $x^2$ run in <span class="rte-math-inline" data-tex="x^2">; editor.renderMath() additionally detects KaTeX or MathJax v3+ on the host page and dispatches to it. No bundling — you bring your own renderer, the editor provides stable markup.

Right-click “Ask AI” context menu AI

When a text selection is non-empty and the AI Toolkit plugin is wired, right-click shows a compact menu: ✨ Ask AI to explain, ✏️ Rewrite, 📝 Summarize, 🌐 Translate. Each entry calls editor.aiToolkit.openDialog({ mode }). Disable with config.aiContextMenu = false.

DOCX import endpoint Server

New: POST /richtextbox/import/docx on the ASP.NET Core RichTextBox.AspNetCore package. Accepts multipart/form-data with a .docx file; returns { html, mode, fileName }. Client wrapper: editor.aiToolkit.importDocx({ url, file, mode }) — opens a file picker if file is omitted, then applies via insertHTML or setHTMLCode. Uses DocumentFormat.OpenXml; conservative HTML subset (p, strong, em, u, h1–h6, ul / ol / li, br, table / tr / td) that round-trips with the existing DOCX export.

Robustness fixes Bug fix

Five real-world regressions resolved this wave:

  • Chrome iframe document-swap recovery. Chrome fires a deferred about:blank load AFTER our synchronous contentDocument.open/write/close, replacing the document. Closure refs (editdoc / editable / editsel) now reseat to the live document; all 18 iframe listeners re-bind. Fixes “editor renders but typing does nothing” on multi-editor pages.
  • Toolbar null-guard. A single unknown button command in the toolbar config no longer crashes the toolbar build half-way through, leaving the editor visually-rendered-but-non-editable.
  • Image insertion at caret. Persistent __lastInEditorRange tracker ensures the file-picker flow inserts the upload at the original caret position even if focus shifted in between (reported by Nathan Allen / Kenneth Chen).
  • Plugin-button crash on empty selection. _editsel_getRange() synthesises a collapsed range at end-of-content when callers (emoji panel, gallery, image dialog) fire from outside the iframe and the editor has never been focused.
  • NuGet DocumentFormat.OpenXml now declared as a PackageReference in the generated demo csproj so trial download bundles include the dependency (reported by Kenneth Chen).
Stable
April 29, 2026
npm 2.2.0

RichTextBox.AspNetCore: bundled plugins/crdt-engine.min.js auto-injected via the <richtextbox> tag helper.

Per-node Yjs CRDT engine New

The big one. Pass textSync: "crdt" to editor.collab.attach() to activate a per-paragraph Yjs binding with character-level merge resolution. Two users editing the same paragraph at the same time produce non-conflicting Yjs operations — no last-write-wins, no caret jumps under normal load.

  • Per-author undo manager: Ctrl-Z undoes only your edits, never your collaborator’s. Standard Y.UndoManager with trackedOrigins: { LOCAL_ORIGIN }.
  • Presence cursors via Y.RelativePosition: stable identifiers that survive concurrent inserts / deletes, so peer cursors stay in the right place after the surrounding text changes.
  • Subtree-aware mutation handling: mid-tree childList changes (lists, tables, mid-paragraph image insert) trigger surgical subtree rebuilds instead of coarse whole-doc resyncs.
  • One-shot HTML migration helper: htmlToYFragment() converts existing HTML into the per-node Y tree for customers upgrading from textSync: true.

Bundle: ships separately as richtexteditor/plugins/crdt-engine.min.js (~88 KB minified) so customers who don’t use collab don’t pay the download cost. Auto-injected by the ASP.NET Core <richtextbox> tag helper. Architecture & integration docs · Live demo

Back-compat: the legacy textSync: true snapshot mode keeps working unchanged. Customers opt into the new path explicitly. Default flips in a future release; legacy mode supported through 2027.

Auto-injected AI Toolkit stylesheet Bug fix

aitoolkit.js now auto-injects a <link rel="stylesheet" href="aitoolkit.css"> if the host page doesn’t already include it. Closes a class of bugs where the Ask AI menu, AI Chat dock, or AI Review drawer rendered with viewport-sized inline SVG icons because the matching CSS file was missing. Skips gracefully if a link to aitoolkit.css is already in the document. Opt-out via RTE_DefaultConfig.aitoolkit_skip_auto_css = true.

Remove Style now strips <td> backgrounds Bug fix

The Remove Style toolbar button used to leave inline backgrounds, borders, fonts, and colors set directly on table cells, paragraphs, divs, and other block-level elements (the browser’s native execCommand("removeformat") only touches inline runs). Now it actively strips presentational style properties (background*, color, font*, border*, outline*, box-shadow, text-decoration*, text-shadow, text-transform, text-indent, letter-spacing, word-spacing, line-height, opacity, filter) from non-SPAN elements while preserving layout properties (width, height, padding, margin, vertical-align, text-align). Word-pasted cell colours / borders / fonts now wipe cleanly; cell sizing survives.

Reported by Sushanth Sivadas (NASCO Dubai).

Comprehensive TypeScript declarations DX

index.d.ts expanded from 304 to 487 lines. Every editor instance method documented at /Docs/jsapi_AllMethods.aspx is now strongly typed: execCommand, isCommandEnabled, isCommandActive, getReadOnly, setReadOnly, setContentCssText, setPreviewCssText, insertRootParagraph, insertByTagName, surroundByTagName, insertElement, surroundElement, insertText, insertHTML, selectControl, selectDoc, collapse, delete, commitBookmark, clearHistory, notifySelectionChange, getDocument, getEditable, getSelection, getSelectedControl, getSelectionElement, getSelectedText, htmlEncode, htmlDecode, createToolbarButton, createToolbarDropDown, createDialog, closeCurrentPopup, setImageForCommand. Plus a RichTextEditorCommand string-literal union (50+ built-in commands), typed event names (change, selectionchange, exec_command, etc.), and a RichTextEditorConfig interface for the constructor’s second arg.

Pre-publish protected-bundle guard Tooling

npm prepublishOnly hook now verifies that richtexteditor/rte.js is the obfuscated production build (banner present, no source-only TODO/FIXME markers, filesize ≥ 380 KB) before any publish. Refuses with a clear error message if the unprotected source slipped in. Opt-out for emergency hotfix flow via RTE_ALLOW_UNPROTECTED=1 npm publish, with a loud warning.

Migration coverage expanded

The migration guide at /migrate.aspx now covers six source editors: TinyMCE, CKEditor 5, Froala, Quill, Lexical, and Tiptap. Each panel has a step-by-step checklist, a config cheat sheet, a plugin / extension equivalence table, behaviour-difference callouts, and a "what you gain" summary.

Breaking changes · npm 2.0.x retired

Every 2.0.x version was unpublished from the npm registry due to an unprotected-source packaging mistake in the April 2026 wave. Republishing skips straight to 2.2.0 so the leaked tags stay permanently retired. Consumers on any 2.0.x should pin to 2.2.0 or later. Public surface is unchanged; existing import statements work as-is.

Current
April 24, 2026
npm 2.0.6

RichTextBox.AspNetCore: 1.0.0-preview.12

Dictation plugin New

New plugins/dictation.js. Speech-to-text via the Web Speech API with a toolbar microphone button; interim transcripts render live under the cursor. Opt-in via config.dictationEnabled = true. JS API: editor.dictation.start() / stop() / toggle() / isListening() / isSupported().

Browser support: Chrome, Edge, Safari (macOS / iOS 14+), Opera. Firefox detects as unsupported and hides the button. · Live demo

Mobile toolbar stylesheet New

New rte_mobile.css. Add class rte-mobile to any editor container (or use the editor’s built-in config.toolbarMobile + maxWidthForMobile auto-swap) to reshape the toolbar for phones: horizontally-scrolling strip, 44×44 tap targets, sticky header, bottom-sheet dropdowns / dialogs / review drawer. Scoped behind @@media (max-width: 768px), (pointer: coarse) so desktop layouts stay unchanged.

Live demo

Paste from Word list conversion Fixed

Rewrote _ConvertWordLists in rte.js. Now correctly detects ordered vs unordered from the marker span, handles nested levels (via mso-list: l{N} level{M}), and strips actual bullet glyphs (·, , , §, ) instead of the previously ineffective character class. Numeric / alphabetic / Roman markers now round-trip as <ol> with proper nesting.

Preview
April 24, 2026
npm 2.0.5

Revision history: named versions + diff API New

Three new methods on editor.revisionHistory:

  • promptAndSnapshot(defaultLabel?) — native prompt + snapshot. Returns entry or null if cancelled.
  • rename(id, label) — rename an existing snapshot; flips its isNamed flag to true.
  • listNamed() — return only named snapshots (handy for a “milestones only” filter).
  • diff(idA, idB){ oldEntry, newEntry, oldText, newText, lines[] } for building side-by-side diff UI.

Each entry now carries an isNamed boolean. Snapshots with an auto: true metadata flag always stay unnamed.

DOCX export client helper New

New editor.aiToolkit.exportDocx({ url?, fileName?, title?, html?, onError? }) builds a POST to a server DOCX endpoint and triggers a browser download via Blob + anchor. Falls back to navigator.msSaveOrOpenBlob on legacy IE/Edge. Pairs with the new DocxExporter server in RichTextBox.AspNetCore 1.0.0-preview.11.

Live demo

Yjs text sync preview (opt-in concurrent typing) Preview

editor.collab.attach({ doc, provider, textSync: true }) binds the editor’s full HTML to a shared Y.Text on the given Y.Doc. CRDT merges concurrent inserts / deletes at character level; two users typing at the same time both see each other’s edits survive.

Known tradeoffs: remote updates re-set the body (caret snaps to start), HTML character offsets don’t align with rendered caret offsets. Per-node binding (y-xml-fragment) is on the roadmap.

New config keys: collabTextSync (bool, default false) and collabTextName (string, default richtextbox.body).

Preview
April 23, 2026
npm 2.0.4

Streaming AI client helper New

New editor.aiToolkit.streamRequest({ url, body, onDelta, onResponse, onDone, onError }) consumes Server-Sent Events from a streaming AI endpoint. Returns { promise, abort() }. Browsers without fetch / ReadableStream fall back to a non-streaming XHR against the same endpoint with /stream stripped — same callback shape either way.

Works against any SSE source that follows data: / event: response / event: done framing; not tied to RichTextBox.

Live demo

Preview
April 22, 2026
npm 2.0.3

AI Toolkit polish & server-side integration New

Shipped alongside the preview.9 NuGet server release. JavaScript side exposed editor.aiToolkit surface for React / Vue / Angular integrations. Resolver contract finalized; BYOK pattern fully documented in /demos/ai-provider-settings.aspx.

Preview
April 22, 2026
npm 2.0.0–2.0.2

v2.0 Collaboration & Review plugins Major

Six plugins shipped together — the full review stack that TinyMCE 7 and CKEditor 5 gate behind their premium tiers:

  • Slash commands (plugins/slashcommand.js) — type / to insert headings, lists, tables, code blocks, AI actions; 15 built-in blocks plus any registered AI action.
  • @Mentions (plugins/mentionplugin.js) — trigger-character framework for @, #, [[wiki]]; async data sources with debounce + loading state, atomic chips.
  • Track Changes (plugins/trackedchanges.js) — Word-style human suggesting mode, per-author color, accept / reject from the Review drawer.
  • Threaded comments (plugins/comments.js) — anchored to selection ranges, with replies, resolve, delete.
  • Revision history (plugins/revisionhistory.js) — snapshot browser with LCS line diff, manual or debounced auto-snapshots, localStorage or server-POST persistence.
  • Yjs presence (plugins/yjscollab.js) — live cursors + shared review ledger via a peer-dependency Yjs provider.

All six share a single editor.reviewLedger store so AI suggestions, human tracked-change suggestions, and comments appear interleaved in the same Review drawer.

AI Toolkit Major

Three AI surfaces in one release:

  • Ask AI — toolbar dropdown with nine preset actions (proofread, rewrite, shorten, expand, summarize, translate, justify, add paragraph, add AI comment) + free-text prompt.
  • AI Chat — docked multi-turn panel with scope switcher.
  • AI Review — batch suggestions in a reviewable drawer.

Provider-agnostic via editor.aiToolkit.setResolver(fn) (client-side BYOK) or IRichTextBoxAiResolver (ASP.NET Core). Ships a demo resolver so AI works without a key out of the box. · Demo

Structured content: JSON / Markdown round-trip New

Opt-in via config.enableStructuredContent = true. Round-trip HTML ↔ JSON ↔ Markdown for apps that need a typed document model or want to render server-side. · Demo

Install or upgrade

Grab the latest via npm:

npm install @@richscripts2/richtexteditor@@latest

Need the ASP.NET Core Tag Helper wrapper? See richtextbox.com release notes.

Feedback & issues: support@@richtexteditor.com