+` items into `++` paragraphs, it reused the original element IDs. The diffing logic treated the reused IDs as updates to the nested elements, so some prompts intermittently removed the content instead of unwrapping it. A reused ID is now treated as an existing block only when it points to a top-level element; otherwise it is processed as a new element. Edits that unwrap nested elements now apply reliably and preserve content.
+
+==== Switching back to an earlier conversation now continues that conversation
+// #TINY-14487
-For information on the **** plugin, see: xref:.adoc[].
+Previously, a regression prevented earlier conversations from loading correctly in the Chat sidebar. After starting a new chat, returning to an earlier conversation and sending a prompt began a disconnected exchange instead of continuing the original thread. Switching to an existing conversation now restores its conversation ID, so later prompts continue the selected conversation.
+==== Image edits now target the correct image in content with multiple images
+// #TINY-14454
-[[accompanying-premium-plugin-end-of-life-announcement]]
-== Accompanying Premium plugin end-of-life announcement
+Previously, images sent to the model were not uniquely identified, so a prompt referencing a specific image could mistake one image for another and apply changes, such as alt text updates, to the wrong image. **TinyMCE AI** now uniquely tags each `+img+` elements so they are less likely to be mistaken. Image edits now apply to the intended image, even when the content contains multiple images.
-The following Premium plugin has been announced as reaching its end-of-life:
+==== Integrators can now add custom AI reviews using the `+tinymceai_reviews+` option
+// #TINY-14200
-===
+Previously, the Review sidebar supported only a fixed set of built-in reviews, selected by ID through the `+tinymceai_reviews+` option. There was no supported way for integrators to add named reviews, parameterized prompts, or menus that mixed built-in and custom reviews. Integrators had to rely on generic flows, such as Custom review, instead of dedicated review actions in the Review sidebar.
-{productname}’s xref:.adoc[] plugin will be deactivated on , , and is no longer available for purchase.
+In {productname} {release-version}, the `+tinymceai_reviews+` option also accepts integrator-defined review objects alongside the existing built-in string IDs. Integrators can define `+simple+`, `+list+`, and `+input+` review types, each with a custom name, description, and prompt. For the full schema and examples, see the xref:tinymceai.adoc#tinymceai_reviews[`+tinymceai_reviews+`] option.
+==== The AI suggestions preview no longer shows deleted text when content has been replaced
+// #TINY-14364
-[[accompanying-open-source-plugin-end-of-life-announcement]]
-== Accompanying open source plugin end-of-life announcement
+Previously, when reviewing AI suggestions, the preview displayed both the deleted text and the inserted text side by side for replacements. This made the preview cluttered and harder to read, because the original and new content had to be parsed at the same time, especially when a document contained multiple replacements.
-The following open source plugin has been announced as reaching its end-of-life:
+In {productname} {release-version}, the preview hides the deleted text for replacements and shows only the new content. When a replacement is selected, the inserted content is shown and highlighted while the removed text stays hidden. Standalone deletions continue to show the removed text when selected, so pure deletions remain fully visible. This makes the preview cleaner and easier to read when reviewing AI-generated changes.
-===
+==== The AI preview did not match the editor content structure, causing style rendering differences
+// #TINY-14328
-{productname}’s xref:.adoc[] plugin will be deactivated on , , and is no longer available for purchase.
+Previously, the AI suggestions preview rendered content inside a wrapper element within the preview iframe body, rather than directly into the iframe body as the editor does. Because the preview and editor had different structures, injected styles could render differently. Absolutely positioned elements and body-level CSS rules did not always apply the same way, which could cause glitches such as misaligned table headers and footers.
+In {productname} {release-version}, the preview inserts content directly into the iframe body so that its structure mirrors the editor. Injected styles now produce the same visual result in both, and the preview renders consistently with the editor.
-[[accompanying-enhanced-skins-and-icon-packs-changes]]
-== Accompanying Enhanced Skins & Icon Packs changes
+==== Bulk action buttons when reviewing AI suggestions now reflect the current progress
+// #TINY-14228
-The {productname} {release-version} release includes an accompanying release of the **Enhanced Skins & Icon Packs**.
+Previously, when reviewing AI suggestions, the bulk action buttons always showed **Skip remaining** and **Apply remaining**, even before any suggestion had been applied or skipped. This was confusing because no decisions had been made yet.
-=== Enhanced Skins & Icon Packs
+In {productname} {release-version}, the bulk action buttons reflect the current progress. They show **Skip all** and **Apply all** before the first decision, then switch to **Skip remaining** and **Apply remaining** after at least one suggestion has been applied or skipped. This behavior is consistent across the Chat and Quick Actions flows.
-The **Enhanced Skins & Icon Packs** release includes the following updates:
+==== Some tooltips now appear only when the content is too long to display
+// #TINY-14072
-The **Enhanced Skins & Icon Packs** were rebuilt to pull in the changes also incorporated into the default {productname} {release-version} skin, Oxide.
+Previously, some tooltips in the TinyMCE AI interface were shown whenever their trigger condition was met, even when the content was already fully visible. This added unnecessary visual clutter.
-For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-and-icon-packs.adoc[Enhanced Skins & Icon Packs].
+In {productname} {release-version}, these tooltips appear only when the content is truncated because it is too long to display in full. This reduces unnecessary tooltips and keeps the interface less cluttered.
+
+==== White space in user prompts was not rendered correctly in the AI Chat history
+// #TINY-14448
+
+Previously, user prompts shown in the AI Chat history collapsed consecutive spaces and line breaks. A multi-line prompt was displayed as a single run-on line, so the message in the chat thread did not match what was typed.
+
+In {productname} {release-version}, user prompts in the AI Chat history preserve their original line breaks and spacing, while long lines still wrap within the message. Prompts now display as they were typed.
+
+==== Replaced the icon-only buttons in the AI suggestion preview with labeled Apply and Skip buttons
+// #TINY-14369
+
+Previously, the AI suggestion preview used icon-only accept and reject buttons, so the meaning of each action relied on the icon and its tooltip. This made the actions ambiguous and harder to discover.
+
+In {productname} {release-version}, the AI suggestion preview uses labeled buttons: a primary **Apply** button to accept a suggestion and a secondary **Skip** button to reject it. The clearer labels make each action obvious and improve accessibility.
+
+==== The AI suggestions diff overlay did not always maintain alignment when resizing the browser window
+// #TINY-14366
+
+Previously, after the AI Chat generated new content, resizing the browser window could leave the AI suggestions diff overlay misaligned with the underlying text. On some layouts the highlights became detached from the content they marked, which made the suggestions preview look broken.
+
+In {productname} {release-version}, the preview overlay tracks a wider set of size changes when the window is resized. The diff overlay now stays aligned with the generated content, which keeps the AI suggestions preview accurate.
+
+==== Reduced the spacing in the AI review suggestion cards
+// #TINY-14279
+
+Previously, the review suggestion cards in the AI Review sidebar used more padding than intended, which made the card layout look inconsistent with the design.
+
+In {productname} {release-version}, the spacing between the card header and body has been reduced to match the design. The review suggestion cards now have a more compact and consistent appearance.
+
+==== Editor content was visible through the AI suggestions preview when using the premium snow skin
+// #TINY-14189
+
+Previously, when using the premium Snow skin, the AI suggestions preview overlay had a transparent background. The underlying editor content showed through the preview, which made it difficult to read and evaluate AI-generated suggestions.
+
+In {productname} {release-version}, the AI suggestions preview uses a solid white background in the Snow skin. Suggestions now appear on a clean, unobstructed background.
+
+==== Keyboard navigation in the preview footer now focuses the currently active view mode instead of always the first one
+// #TINY-14272
+
+Previously, moving keyboard focus to the preview footer in the AI Chat always landed on the first view mode option rather than the one that was currently active. This made keyboard navigation between the Diff mode and Preview tabs less predictable.
+
+In {productname} {release-version}, focus moves to the currently active view mode in the preview footer. Keyboard navigation now reflects the active selection.
+
+==== A confirmation dialog now appears before navigating away from unresolved suggestions, such as when switching to another sidebar or opening a sidebar during quick actions
+// #TINY-14236
+
+Previously, switching between the AI Chat and Review sidebars, or opening a sidebar during quick actions, while AI suggestions were still unresolved discarded those suggestions and any applied changes permanently. A single accidental click could cause lost progress.
+
+In {productname} {release-version}, a confirmation dialog appears before navigating away from unresolved suggestions. The action proceeds only after it is confirmed, which prevents the accidental loss of in-progress changes.
+
+==== Two tooltips were shown at the same time when hovering over context sources or conversation titles that were shortened with an ellipsis in Safari
+// #TINY-14032
+
+Previously, in Safari, hovering over text that was shortened with an ellipsis, such as AI Chat conversation titles or context sources, could display two tooltips at once: the browser's native tooltip and the plugin's custom tooltip.
+
+In {productname} {release-version}, only the native tooltip is shown for these elements in Safari. A single tooltip now appears on hover as expected.
+
+==== An error could be reported when aborting and starting a new conversation
+// #TINY-14381
+
+Previously, aborting a streamed AI response and starting a new conversation could report an error. Aborting the response triggered a document delete operation that sometimes failed.
+
+In {productname} {release-version}, the document is no longer deleted when an AI request is aborted. Aborting a response and starting a new conversation no longer reports this error.
+
+==== AI response HTML is now filtered through the editor's content pipeline before being displayed in preview
+// #TINY-14344
+
+Previously, content shown in the AI preview was not filtered by the editor's content rules until it was applied. With a strict schema configuration, a change could appear in the preview, be accepted, and then be removed when applied to the editor, so the final result did not match the preview.
+
+In {productname} {release-version}, AI response HTML is filtered through the editor's content pipeline before it is shown in the preview. The preview now reflects what will be added to the editor, and if filtering removes all of the content the user is notified.
+
+==== AI Chat state was lost if the sidebar was closed before the model started responding
+// #TINY-14222
+
+Previously, the state of an AI Chat conversation could be lost if the Chat sidebar was closed before the model began responding to a prompt. The plugin recorded which sidebar started a response only once the response began, so closing the sidebar beforehand left no record. Reopening the sidebar then reset the conversation and any pending preview.
+
+In {productname} {release-version}, the sidebar is recorded as soon as the prompt is sent. Closing and reopening the Chat sidebar before the response is ready no longer resets the conversation.
+
+For information on the **TinyMCE AI** plugin, see: xref:tinymceai.adoc[TinyMCE AI].
[[improvements]]
@@ -111,18 +361,50 @@ For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-a
{productname} {release-version} also includes the following improvement:
-===
+// ===
// #TINY-vwxyz1
// CCFR here.
+=== Removed the 300-item limit on the emoticons dialog All tab
+// #TINY-7552
+
+Previously, the emoticons dialog limited the **All** tab to 300 items. This limit was a workaround, because rendering all of the available emoticons (over 1,200) caused performance issues and a laggy experience.
+
+In {productname} {release-version}, the render performance of the emoticons dialog has been optimized and the 300-item limit on the **All** tab has been removed. All available emoticons are now displayed.
+
+=== Pressing Tab or Shift+Tab on an open menu now closes it and moves focus to the next or previous focusable element
+// #TINY-13341
+
+Previously, pressing Tab or Shift+Tab inside an open dropdown menu cycled focus through the menu items instead of closing the menu. This behavior did not align with accessibility guidelines, which recommend that the Tab key close the menu and move focus to the next or previous element in the tab order. As a result, keyboard navigation through menus was less predictable for users who rely on the keyboard or assistive technologies.
+
+In {productname} {release-version}, pressing Tab or Shift+Tab on an open menu now closes the menu and moves focus to the next or previous focusable element in the tab order. This makes keyboard navigation more predictable and aligns dropdown menu behavior with accessibility guidelines.
+
+=== The editor resize handle now uses browser pointer events for more reliable behavior across different integration environments
+// #TINY-14241
+
+Previously, the editor resize handle relied on an overlay element to capture pointer movement, which required raising the editor's stacking order. This caused the editor to appear on top of the floating sidebar used by the TinyMCE AI plugin while the editor was being resized.
+
+In {productname} {release-version}, the resize handle uses modern browser pointer events instead. This removes the need for the overlay element and the raised stacking order, providing more reliable resizing across different integration environments and resolving the overlap with the floating sidebar.
+
[[additions]]
== Additions
{productname} {release-version} also includes the following addition:
-===
+=== New `tinymce.dom.AriaAnnouncer` API for screen reader announcements
+// #TINY-12791
+
+{productname} {release-version} adds the `+tinymce.dom.AriaAnnouncer+` API for sending messages to screen readers through an `+aria-live+` region without shifting focus. The `+announce+` method accepts a message and an optional `+{ assertive }+` setting. Integrators can use it to announce formatting changes, for example by listening to the `+FormatApply+` and `+FormatRemove+` events.
+
+[source,js]
+----
+tinymce.dom.AriaAnnouncer.announce('Bold on');
+tinymce.dom.AriaAnnouncer.announce('Error occurred', { assertive: true });
+----
+
+// ===
// #TINY-vwxyz1
// CCFR here.
@@ -133,7 +415,7 @@ For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-a
{productname} {release-version} also includes the following change:
-===
+// ===
// #TINY-vwxyz1
// CCFR here.
@@ -144,7 +426,7 @@ For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-a
{productname} {release-version} also includes the following removal:
-===
+// ===
// #TINY-vwxyz1
// CCFR here.
@@ -155,18 +437,101 @@ For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-a
{productname} {release-version} also includes the following bug fix:
-===
+=== Block formatting now targets the correct element across a table cell selection
+// #TINY-14385
+
+Previously, when multiple table cells were selected, the check for whether a block could be renamed did not inspect nested elements. For example, with a blockquote containing a heading, applying a new heading format changed the blockquote instead of the heading.
+
+In {productname} {release-version}, the check inspects nested elements, so block formatting is applied to the correct element.
+
+=== Block formats can now be applied when a non-editable inline element is selected
+// #TINY-13333
+
+Previously, selecting an inline `+contenteditable="false"+` element, such as an iframe wrapped by the Media plugin, and applying a block-level format, such as a custom class or heading style, failed silently and had no effect.
+
+In {productname} {release-version}, block formats are applied to the nearest editable parent block in this case, including adding classes and styles and changing block tags.
+
+=== Indentation is now applied to all selected table cells
+// #TINY-14370
+
+Previously, applying indentation with multiple table cells selected affected only the cell where the pointer was released. The action used the browser's native selection rather than the editor's cell selection, so the remaining selected cells were left unchanged.
+
+In {productname} {release-version}, indentation is applied to every cell in the selection.
+
+// ===
// #TINY-vwxyz1
// CCFR here.
+=== Dragging and dropping or copying and pasting an image didn't add `width` and `height` to the tag.
+// #TINYMCE-14411
+
+Previously, {productname} inserted an `img` tag without `width` and `height` attributes when a user dragged and dropped or copied and pasted an image into the editor. The inserted `img` tag lacked the dimension attributes that the image dialog adds.
+
+In {productname} {release-version}, the editor reads the dimensions of a dropped or pasted image and adds the `width` and `height` attributes to the `img` tag. A dropped or pasted image now includes the same `width` and `height` attributes that the image dialog adds.
+
+=== Tooltips were clipped when the editor was hosted in a shadow DOM and its parent element had `overflow:scroll`.
+// #TINYMCE-14384
+
+Previously, when {productname} ran in a shadow DOM, such as a web component, and a parent element of the host used `overflow: scroll`, that element clipped a tooltip that extended past the host element boundary. The clipped tooltip could become unreadable.
+
+{productname} {release-version} restricts tooltip positioning to the bounds of the host element. A tooltip now repositions to stay within the host element and remains visible when {productname} runs in a shadow DOM.
+
+=== Deleting a newline within a list item would delete the list item.
+// #TINYMCE-13292
+
+Previously, pressing `Backspace` to delete a newline (`
`) inside an otherwise empty list item removed the entire list item instead of only the newline. The issue affected lists created with `Shift + Enter`, including nested lists, and deleted content without warning.
+
+In {productname} {release-version}, `Backspace` removes only the newline and leaves the empty list item in place.
+
+=== CSS custom property names and color values in the style attribute were lowercased when parsed
+// #TINY-11524
+
+Previously, the {productname} style parser lowercased CSS custom property names (such as `--MyColor`) and `color` and `background-color` values when reading the `style` attribute. This altered case-sensitive values, including CSS custom properties, template placeholders such as `{{FooBar}}`, and hex colors such as `#AABBCC`, so the affected styling sometimes did not render as authored.
+
+In {productname} {release-version}, the style parser preserves the original case of CSS custom property names and `color` and `background-color` values. Standard property names are still lowercased, and other processing, such as RGB-to-hex conversion, shorthand merging, and security filtering, is unchanged. Case-sensitive colors and custom properties now stay exactly as authored.
+
+=== Focused links in dark mode had the same text color as the background
+// #TINY-14264
+
+Previously, in dark mode, a focused or selected link was displayed with the same text color as the background. This made the link text impossible to read while it was selected.
+
+In {productname} {release-version}, selected link text in dark mode is displayed in white. Links remain readable when focused, which improves accessibility in dark mode.
+
+=== Context toolbar with position 'line' was not repositioning to the opposite side when overflowing the viewport
+// #TINY-14376
+
+Previously, a context toolbar configured with `position: 'line'`, such as a quickbar, was not repositioned when it overflowed the edge of the viewport. Under these conditions the toolbar could be cut off, which prevented users from clicking its buttons.
+
+In {productname} {release-version}, a context toolbar that uses `position: 'line'` now flips to the opposite side when there is not enough space. The toolbar remains fully visible and usable in constrained layouts.
+
+=== Some annotated text was hidden when printed even though it should have been visible
+// #TINY-14296
+
+Previously, text marked by annotation features, such as spelling indicators, could be hidden when a page was printed. The annotations were wrapped in internal placeholder elements that were hidden during printing, which also hid the text inside them.
+
+In {productname} {release-version}, placeholder elements that act only as wrappers now hide their styling rather than their contents when printing. Annotation highlights remain hidden in the printed output, while the underlying text is printed as expected.
+
+=== Worked around a Chromium bug where clicking on the right of an `li` could fail
+// #TINY-13886
+
+Previously, clicking to the right of the content in a list item could place the cursor at the start of the item instead of at the location that was clicked. This was caused by a Chromium browser bug that moved the caret to an incorrect position.
+
+In {productname} {release-version}, a targeted workaround detects this case and corrects the caret position. Clicking to the right of a list item now places the cursor where expected.
+
+=== Using the undo keyboard shortcut did not restore editor selection correctly
+// #TINY-14255
+
+Previously, pressing the undo keyboard shortcut (Ctrl+Z, or Cmd+Z on macOS) after deleting a selection could leave the cursor in the wrong position. An earlier change registered an extra undo step whenever Ctrl or Cmd was pressed, so the step was recorded before the deleted content was restored.
+
+In {productname} {release-version}, {productname} registers that undo step only when Ctrl or Cmd is pressed together with Backspace or Delete, rather than on every Ctrl or Cmd key press. Undoing the deletion of a selection now restores both the content and the original selection correctly.
[[security-fixes]]
== Security fixes
{productname} {release-version} includes :
-===
+// ===
// #TINY-vwxyz1
// CCFR here.
@@ -177,7 +542,7 @@ For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-a
{productname} {release-version} includes the following deprecation:
-=== The `` configuration property, ``, has been deprecated
+// === The `` configuration property, ``, has been deprecated
// placeholder here.
@@ -189,7 +554,7 @@ This section describes issues that users of {productname} {release-version} may
There known issue in {productname} {release-version}.
-===
+// ===
// #TINY-vwxyz1
// CCFR here.
diff --git a/modules/ROOT/pages/exportpdf.adoc b/modules/ROOT/pages/exportpdf.adoc
index 0455a28ab7..6f2772734f 100644
--- a/modules/ROOT/pages/exportpdf.adoc
+++ b/modules/ROOT/pages/exportpdf.adoc
@@ -1,6 +1,7 @@
= {pluginname} plugin
:plugincode: exportpdf
:pluginname: Export to PDF
+:export-type: pdf
:page-aliases: export.adoc
:pluginfilename: export-to-pdf
:navtitle: Export to PDF
@@ -81,6 +82,8 @@ The `exportpdf_service_url` option automatically appends `/v2/convert/html-pdf`
include::partial$misc/pagebreak-export-note.adoc[]
+include::partial$misc/export-specific-content-filtering.adoc[]
+
== Options
The following configuration options affect the behavior of the {pluginname} plugin.
diff --git a/modules/ROOT/pages/exportword.adoc b/modules/ROOT/pages/exportword.adoc
index f4444b888a..bcceb97682 100644
--- a/modules/ROOT/pages/exportword.adoc
+++ b/modules/ROOT/pages/exportword.adoc
@@ -1,6 +1,7 @@
= {pluginname} plugin
:plugincode: exportword
:pluginname: Export to Word
+:export-type: word
:pluginfilename: export-to-word
:navtitle: {pluginname}
:description: The {pluginname} feature lets you generate a .docx (Microsoft Word document) file directly from the editor.
@@ -80,6 +81,8 @@ The `exportword_service_url` option automatically appends `/v2/convert/html-docx
include::partial$misc/pagebreak-export-note.adoc[]
+include::partial$misc/export-specific-content-filtering.adoc[]
+
== Options
The following configuration options affect the behavior of the {pluginname} plugin.
diff --git a/modules/ROOT/pages/revisionhistory.adoc b/modules/ROOT/pages/revisionhistory.adoc
index 2aaa4390f7..a95900379d 100644
--- a/modules/ROOT/pages/revisionhistory.adoc
+++ b/modules/ROOT/pages/revisionhistory.adoc
@@ -87,6 +87,7 @@ The revision is an `+Object+` that contains the following fields:
| `+createdAt+` | `+string+` | required | A UTC datetime string in ISO-8061 format.
| `+content+` | `+string+` | optional | HTML string of the revision content. Empty string is considered as valid content.
| `+author+` | xref:#author[Author] `+Object+` | optional | The author of the revision.
+| `+metadata+` | xref:#metadata[Metadata] `+Object+` | optional | Additional information about the revision, such as whether it was AI-assisted.
|===
=== Author
@@ -101,6 +102,72 @@ The author is an `+Object+` that represents the author or creator of a revision.
| `+avatar+` | `+string+` | optional | The URL of the author's avatar image. If not provided or invalid, the {pluginname} will use a generated avatar using the author's initials.
|===
+=== Metadata
+
+The metadata is an `+Object+` that holds additional information about a revision. It contains the following fields:
+
+[cols="1,1,1,3",options="header"]
+|===
+| Field | Type | Required? | Description
+| `+source+` | `+string+` | optional | The origin of the revision's content. A value of `+'ai'+` marks the revision as AI-assisted and, when xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] is enabled, displays an AI badge on the revision card.
+|===
+
+== Attributing AI-assisted revisions
+
+A revision is identified as AI-assisted through the `+source+` field of its xref:#metadata[`+metadata+`] object. When `+metadata.source+` is `+'ai'+` and the xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] option is enabled, an AI badge appears on that revision card.
+
+The {pluginname} plugin does not set this marker automatically. The xref:tinymceai.adoc[{productname} AI] plugin sets `+ai+` to `+true+` on the `+SetContent+` event for any content it inserts. Detecting that signal and recording it as `+metadata.source+` when saving a revision is the responsibility of the application. There are three steps to keep attribution accurate:
+
+. **Detect**: Listen for the `+SetContent+` event and record when its `+ai+` property is `+true+`.
+. **Save**: When saving a revision, set `+metadata.source+` to `+'ai'+` if AI contributed since the last save.
+. **Restore**: When a revision is restored, carry its marker forward so later revisions remain correctly attributed.
+
+[NOTE]
+The AI badge appears only on `+saved+` revisions. The `+draft+` and `+initial+` revisions are generated from the editor's current content and do not carry `+metadata+`, so they never display the badge, even when that content was AI-assisted. See xref:#understanding-revision-types[Understanding revision types].
+
+=== Saving an AI-assisted revision
+
+The application is responsible for saving revisions and returns them through the xref:revisionhistory_fetch[`+revisionhistory_fetch+`] option. The following example tracks AI involvement from the `+SetContent+` event and attaches the `+metadata+` marker when saving a snapshot:
+
+[source,js]
+----
+let aiAssisted = false;
+
+// The TinyMCE AI plugin sets `ai: true` on the SetContent event for content it inserts.
+editor.on('SetContent', (e) => {
+ if (e.ai) {
+ aiAssisted = true;
+ }
+});
+
+// Call this when saving a snapshot of the current content as a revision.
+const saveRevision = () => {
+ const revision = {
+ revisionId: createRevisionId(), // Replace with your ID generation
+ createdAt: new Date().toISOString(),
+ content: editor.getContent(),
+ // Mark the revision as AI-assisted if AI contributed since the last save.
+ ...(aiAssisted ? { metadata: { source: 'ai' } } : {})
+ };
+
+ saveToStorage(revision); // Replace with your storage call
+ aiAssisted = false; // Reset state of AI assistance for new content
+};
+----
+
+=== Restoring an AI-assisted revision
+
+Restoring a revision sets its content back into the editor and fires the `+VersionRestored+` event. The restored content is not flagged as AI-assisted, so look up the restored revision and carry its marker forward to the next save:
+
+[source,js]
+----
+editor.on('VersionRestored', (e) => {
+ const restored = getFromStorage(e.revisionId); // Replace with your storage lookup
+ // Preserve attribution so the next saved revision reflects the restored content.
+ aiAssisted = restored?.metadata?.source === 'ai';
+});
+----
+
== Options
@@ -120,6 +187,8 @@ include::partial$configuration/revisionhistory_author.adoc[leveloffset=+1]
include::partial$configuration/revisionhistory_display_author.adoc[leveloffset=+1]
+include::partial$configuration/revisionhistory_ai_attribution.adoc[leveloffset=+1]
+
include::partial$configuration/revisionhistory_css_url.adoc[leveloffset=+1]
include::partial$configuration/revisionhistory_diff_classes.adoc[leveloffset=+1]
diff --git a/modules/ROOT/pages/suggestededits.adoc b/modules/ROOT/pages/suggestededits.adoc
index d55ba3ef10..f083384601 100644
--- a/modules/ROOT/pages/suggestededits.adoc
+++ b/modules/ROOT/pages/suggestededits.adoc
@@ -27,7 +27,7 @@ The {pluginname} plugin keeps track of every edit made to the document by the cu
The {pluginname} model is a JSON object representing the document along with all unreviewed edits and feedback. The model must be kept in sync with the editor content and loaded into the editor at the same time as the content.
-The structure of the model is not documented and should not be relied upon.
+The structure of the model is not documented and should not be relied upon. Models saved by earlier versions of the plugin continue to load and are upgraded automatically.
The model can be retrieved from the plugin using the xref:#get_model[`+getModel+`] API, saved externally alongside the document, and loaded into the editor with the xref:#suggestededits_model[`+suggestededits_model+`] option. This ensures that the document and the model are in sync and every user's contributions are tracked correctly. If the model and content are out of sync when the editor loads, the difference between them will be included in the next edit by the current user. If a model is not provided in the editor configuration or is set to `+undefined+`, the plugin will generate a new model from the initial content.
@@ -59,6 +59,8 @@ Replaced content is represented as both added and removed content, and indicates
Each suggested edit is listed as a card in the sidebar and color coded by the type of change. Each card shows a contextual description of the content, along with the user who made the suggestion, when the edit was made, and any feedback provided on that suggestion.
+Edits made with the xref:tinymceai.adoc[{productname} AI] plugin are recorded as AI-assisted. When the xref:#suggestededits_ai_attribution[`+suggestededits_ai_attribution+`] option is enabled, an AI badge appears on their cards.
+
When selected, a suggestion can be handled in the following ways:
* Accept: Resolves the suggestion, applying the edit to the document when the review is completed.
@@ -129,6 +131,8 @@ include::partial$configuration/suggestededits_access.adoc[leveloffset=+1]
include::partial$configuration/suggestededits_auto_approve.adoc[leveloffset=+1]
+include::partial$configuration/suggestededits_ai_attribution.adoc[leveloffset=+1]
+
include::partial$plugins/suggestededits-open-view.adoc[leveloffset=+1]
include::partial$configuration/user_id.adoc[leveloffset=+1]
diff --git a/modules/ROOT/pages/tinymceai-models.adoc b/modules/ROOT/pages/tinymceai-models.adoc
index 6cb99845ab..01a4d3d8fa 100644
--- a/modules/ROOT/pages/tinymceai-models.adoc
+++ b/modules/ROOT/pages/tinymceai-models.adoc
@@ -34,6 +34,12 @@ The following is a detailed list of available models with their capabilities:
|Yes
|`'auto'` (also `'agent-1'`, learn more about xref:tinymceai-models.adoc#model-compatibility-versions[compatibility versions])
+|**GPT-5.5**
+|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks
+|Yes
+|Yes
+|`'gpt-5.5'`
+
|**GPT-5.4**
|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks
|Yes
@@ -70,12 +76,30 @@ The following is a detailed list of available models with their capabilities:
|Yes
|`'gpt-5-mini'`
+|**GPT-5.4 Mini**
+|A lighter variant of GPT-5.4 that balances speed and cost while maintaining solid accuracy
+|Yes
+|Yes
+|`'gpt-5.4-mini'`
+
|**GPT-4.1 Mini**
|A lighter variant of GPT-4.1 that balances speed and cost while maintaining solid accuracy
|Yes
|No
|`'gpt-4.1-mini'`
+|**Claude Opus 4.8**
+|Anthropic's most capable model for extended reasoning and complex tasks
+|Yes
+|Yes
+|`'claude-opus-4-8'`
+
+|**Claude Opus 4.7**
+|Anthropic's most capable model for extended reasoning and complex tasks
+|Yes
+|Yes
+|`'claude-opus-4-7'`
+
|**Claude 4.6 Sonnet**
|Advanced model with improved creativity, reliability, and reasoning
|Yes
@@ -111,6 +135,12 @@ The following is a detailed list of available models with their capabilities:
|Yes
|Yes
|`'gemini-3-flash'`
+
+|**Gemini 3.5 Flash**
+|Lightweight Gemini model for fast, cost-efficient interactions
+|Yes
+|Yes
+|`'gemini-3-5-flash'`
|===
[[limitations]]
diff --git a/modules/ROOT/partials/commands/suggestededits-cmds.adoc b/modules/ROOT/partials/commands/suggestededits-cmds.adoc
index 5ac738e8ff..4a6f353caf 100644
--- a/modules/ROOT/partials/commands/suggestededits-cmds.adoc
+++ b/modules/ROOT/partials/commands/suggestededits-cmds.adoc
@@ -2,10 +2,14 @@
|===
|Command |Description
|suggestededits |Toggles the Suggested Edits view.
+|suggestededitsToggleTracking |Toggles the tracking of suggested edits.
|===
.Example
[source,js]
----
tinymce.activeEditor.execCommand('suggestededits');
+tinymce.activeEditor.execCommand('suggestededitsToggleTracking');
+
+tinymce.activeEditor.queryCommandState('suggestededitsToggleTracking'); // Returns true if tracking of suggested edits is enabled, otherwise false.
----
diff --git a/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc b/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc
new file mode 100644
index 0000000000..5b567fadf1
--- /dev/null
+++ b/modules/ROOT/partials/configuration/revisionhistory_ai_attribution.adoc
@@ -0,0 +1,23 @@
+[[revisionhistory_ai_attribution]]
+== `revisionhistory_ai_attribution`
+
+This option controls the display of the AI badge on revision cards. When set to `+true+`, an AI badge appears on each revision whose xref:revisionhistory.adoc#metadata[`+metadata+`] has `+source+` set to `+'ai'+`. For details on attributing revisions to AI, see xref:revisionhistory.adoc#attributing-ai-assisted-revisions[Attributing AI-assisted revisions].
+
+*Type:* `+Boolean+`
+
+*Default value:* `+false+`
+
+*Possible values:* `+true+`, `+false+`
+
+=== Example: using `revisionhistory_ai_attribution`
+
+[source,js]
+----
+tinymce.init({
+ selector: 'textarea', // Change this value according to your HTML
+ plugins: 'revisionhistory',
+ toolbar: 'revisionhistory',
+ revisionhistory_fetch: () => Promise.resolve([]),
+ revisionhistory_ai_attribution: true
+});
+----
diff --git a/modules/ROOT/partials/configuration/suggestededits_ai_attribution.adoc b/modules/ROOT/partials/configuration/suggestededits_ai_attribution.adoc
new file mode 100644
index 0000000000..b8ca748839
--- /dev/null
+++ b/modules/ROOT/partials/configuration/suggestededits_ai_attribution.adoc
@@ -0,0 +1,22 @@
+[[suggestededits_ai_attribution]]
+== `suggestededits_ai_attribution`
+
+This option controls the display of the AI badge on suggestion cards. When set to `+true+`, an AI badge appears on the cards of edits made with the xref:tinymceai.adoc[{productname} AI] plugin.
+
+NOTE: AI-assisted suggestions are always recorded in the model. This option controls only whether the AI badge is displayed.
+
+*Type:* `+Boolean+`
+
+*Default value:* `+false+`
+
+=== Example: using `suggestededits_ai_attribution`
+
+[source,js]
+----
+tinymce.init({
+ selector: 'textarea', // Change this value according to your HTML
+ plugins: 'suggestededits',
+ toolbar: 'suggestededits',
+ suggestededits_ai_attribution: true
+});
+----
diff --git a/modules/ROOT/partials/configuration/suggestededits_auto_approve.adoc b/modules/ROOT/partials/configuration/suggestededits_auto_approve.adoc
index 928ddd7358..f9b560aa40 100644
--- a/modules/ROOT/partials/configuration/suggestededits_auto_approve.adoc
+++ b/modules/ROOT/partials/configuration/suggestededits_auto_approve.adoc
@@ -8,6 +8,7 @@ When set to:
* `false`: All edits require manual approval before being applied.
* `true`: All new edits are automatically approved and applied.
+NOTE: In {productname} 8.7, this option controls the default state of the `suggestededits-tracking` toolbar button and menu item. When set to `false`, the `suggestededits-tracking` button will be active by default and edits will appear in the review. When set to `true`, the button will be inactive by default, meaning edits will not appear in the review. Toggling the button or menu item will override the default state set by this option for the current session.
*Type:* `+Boolean+`
@@ -19,7 +20,7 @@ When set to:
tinymce.init({
selector: 'textarea#suggestededits', // Change this value according to your HTML
plugins: 'suggestededits',
- toolbar: 'suggestededits',
+ toolbar: 'suggestededits suggestededits-tracking',
suggestededits_auto_approve: true, // Change this value to auto-approve suggested edits
});
----
diff --git a/modules/ROOT/partials/configuration/tinymceai_options.adoc b/modules/ROOT/partials/configuration/tinymceai_options.adoc
index fb0b72ba71..380d002084 100644
--- a/modules/ROOT/partials/configuration/tinymceai_options.adoc
+++ b/modules/ROOT/partials/configuration/tinymceai_options.adoc
@@ -516,9 +516,9 @@ These options configure the AI Review sidebar, which provides content quality an
[[tinymceai_reviews]]
=== `+tinymceai_reviews+`
-Array of review command IDs that define which review types appear in the Review sidebar and their order. Only the listed reviews are available to users.
+Array that defines which reviews appear in the Review sidebar and their order. Only the listed reviews are available to users. Each item is either a built-in review command ID (a string) or an xref:#integrator-defined-reviews[integrator-defined review] (an object).
-*Type:* `+Array+` of `+String+`
+*Type:* `+Array+` of `+String+` or `+Object+`
*Valid values:*
@@ -563,3 +563,145 @@ tinymce.init({
});
----
+[[tinymceai_reviews_change_tone_menu]]
+=== `+tinymceai_reviews_change_tone_menu+`
+
+Array of tone IDs that define which tone options appear in the Change Tone review and their order. Only the listed tones appear in the menu.
+
+This option applies only when `+'ai-reviews-change-tone'+` is included in the xref:tinymceai.adoc#tinymceai_reviews[`+tinymceai_reviews+`] option.
+
+*Type:* `+Array+` of `+String+`
+
+*Valid values:*
+
+* `+'ai-reviews-tone-casual'+`: Casual tone
+* `+'ai-reviews-tone-direct'+`: Direct tone
+* `+'ai-reviews-tone-friendly'+`: Friendly tone
+* `+'ai-reviews-tone-confident'+`: Confident tone
+* `+'ai-reviews-tone-professional'+`: Professional tone
+
+Duplicate IDs are removed, and the menu displays tones in the configured order. If the option includes an invalid tone ID, the configuration is rejected and the default tones are used. An empty array (`+[]+`) is accepted, but {productname} logs a console warning. To remove the Change Tone review entirely, omit `+'ai-reviews-change-tone'+` from the xref:tinymceai.adoc#tinymceai_reviews[`+tinymceai_reviews+`] option.
+
+*Default value:*
+[source,js]
+----
+[
+ 'ai-reviews-tone-casual',
+ 'ai-reviews-tone-direct',
+ 'ai-reviews-tone-friendly',
+ 'ai-reviews-tone-confident',
+ 'ai-reviews-tone-professional'
+]
+----
+
+.Example
+[source,js]
+----
+tinymce.init({
+ selector: 'textarea',
+ plugins: 'tinymceai',
+ toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review',
+ tinymceai_reviews_change_tone_menu: [
+ 'ai-reviews-tone-professional',
+ 'ai-reviews-tone-friendly'
+ ],
+ // Required for authentication
+ tinymceai_token_provider: () => {
+ return fetch('/api/token').then(r => r.json());
+ }
+});
+
+[[integrator-defined-reviews]]
+==== Integrator-defined reviews
+
+In addition to the built-in review command IDs, the `+tinymceai_reviews+` option accepts integrator-defined review objects. These objects can be interleaved with the built-in string IDs, allowing integrators to add named reviews to the Review sidebar.
+
+Each integrator-defined review object has a `+type+` of `+'simple'+`, `+'list'+`, or `+'input'+`, and shares the following properties:
+
+* `+type+`: The review type. One of `+'simple'+`, `+'list'+`, or `+'input'+`.
+* `+id+`: A unique identifier for the review. It must not reuse a built-in review command ID.
+* `+name+`: The review name shown in the Review sidebar.
+* `+description+`: A short description shown beneath the name.
+* `+prompt+`: The prompt sent to the model when the review runs.
+* `+model+` (optional): The model used for the review. The value must be a model ID that the configured AI service exposes (see xref:tinymceai-models.adoc[AI Models]). When omitted, the editor default model set by xref:tinymceai.adoc#tinymceai_default_model[`+tinymceai_default_model+`] is used.
+
+A `+list+` review adds an `+options+` array, and an `+input+` review adds an optional `+inputPlaceholder+`:
+
+* `+options+` (`+list+` only): An array of `+{ label, value }+` objects. The selected `+value+` is substituted into the prompt wherever `+{value}+` appears.
+* `+inputPlaceholder+` (`+input+`, optional): Placeholder text for the input field. {productname} substitutes the text entered by the end user into the prompt wherever `+{input}+` appears.
+
+If an integrator-defined review is invalid, for example, if it reuses a built-in review command ID or does not match the expected schema, {productname} falls back to the default reviews list in the Review sidebar.
+
+NOTE: The `+model+` ID used in the following examples (`+agent-1+`) selects the recommended automatic model. The available model IDs depend on the configured AI service. See xref:tinymceai-models.adoc[AI Models] for the supported models and how to confirm which are available in an environment.
+
+.Simple integrator-defined review
+[source,js]
+----
+tinymceai_reviews: [
+ {
+ type: 'simple',
+ id: 'integrator-simple-review',
+ name: 'Simple Integrator Review',
+ description: 'This is a simple integrator review',
+ prompt: 'Review this document',
+ model: 'agent-1'
+ }
+]
+----
+
+.List integrator-defined review
+[source,js]
+----
+tinymceai_reviews: [
+ {
+ type: 'list',
+ id: 'integrator-list-review',
+ name: 'Translate Document',
+ description: 'Translate the document to a selected language.',
+ prompt: 'Translate this document to {value}',
+ model: 'agent-1',
+ options: [
+ { label: 'English', value: 'english' },
+ { label: 'Swedish', value: 'swedish' }
+ ]
+ }
+]
+----
+
+.Input integrator-defined review
+[source,js]
+----
+tinymceai_reviews: [
+ {
+ type: 'input',
+ id: 'integrator-input-review',
+ name: 'Custom Instruction',
+ description: 'Apply a custom instruction.',
+ prompt: 'Apply the following instruction {input}',
+ model: 'agent-1',
+ inputPlaceholder: 'Enter an instruction here...'
+ }
+]
+----
+
+.Built-in and integrator-defined reviews combined
+[source,js]
+----
+tinymceai_reviews: [
+ // Built-in reviews
+ 'ai-reviews-proofread',
+ 'ai-reviews-improve-clarity',
+ 'ai-reviews-change-tone',
+ 'ai-reviews-custom',
+ // Integrator-defined review
+ {
+ type: 'simple',
+ id: 'integrator-simple-review',
+ name: 'Simple Integrator Review',
+ description: 'This is a simple integrator review',
+ prompt: 'Review this document',
+ model: 'agent-1'
+ }
+]
+----
+
diff --git a/modules/ROOT/partials/events/suggestededits-events.adoc b/modules/ROOT/partials/events/suggestededits-events.adoc
index 094c76c1fc..48233cabc1 100644
--- a/modules/ROOT/partials/events/suggestededits-events.adoc
+++ b/modules/ROOT/partials/events/suggestededits-events.adoc
@@ -7,4 +7,5 @@ The following events are provided by the xref:{plugincode}.adoc[{pluginname} plu
|SuggestedEditsReviewComplete |N/A |A review in the Suggested Edits view has been completed.
|SuggestedEditsReviewCancelled |N/A |A review in the Suggested Edits view was cancelled.
|SuggestedEditsHasChangesUpdate |`+hasChanges+` |The Suggested Edits model is updated. The `+hasChanges+` data is a boolean value indicating whether there are suggestions to review.
+|SuggestedEditsTrackingToggle |`+tracking+` |The tracking state of suggested edits has changed. The `+tracking+` data is a boolean value indicating whether edits are being tracked.
|===
\ No newline at end of file
diff --git a/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc b/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc
index d45e2420b5..f6c9324b04 100644
--- a/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc
+++ b/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc
@@ -3,4 +3,5 @@
|Menu item identifier |xref:menus-configuration-options.adoc#example-the-tinymce-default-menu-items[Default Menu Location] |Description
|`suggestededits` |View |Opens the Suggested Edits view.
+|`suggestededits-tracking` |_Not Applicable_ |Toggles the tracking of suggested edits.
|===
\ No newline at end of file
diff --git a/modules/ROOT/partials/misc/export-specific-content-filtering.adoc b/modules/ROOT/partials/misc/export-specific-content-filtering.adoc
new file mode 100644
index 0000000000..32ed0acf7c
--- /dev/null
+++ b/modules/ROOT/partials/misc/export-specific-content-filtering.adoc
@@ -0,0 +1,26 @@
+[[export-specific-content-filtering]]
+== Export-specific content filtering
+
+To generate content for export, the {pluginname} plugin calls the `tinymce.editor.getContent()` method with an `export` property set to `{export-type}`. {productname} adds this `export` property to the data for the xref:events.adoc#editor-core-events[`+GetContent+` event] and for serializer node filters. A serializer node filter or a `GetContent` event handler can read the `export` property to filter content during a {pluginname} export only, without changing the result of a standard `tinymce.editor.getContent()` call.
+
+The following serializer node filter removes `footer` elements during a {pluginname} export:
+
+[source,js,subs="+attributes"]
+----
+editor.serializer.addNodeFilter('footer', (nodes, name, args) => {
+ if (args.export === '{export-type}') {
+ nodes.forEach((node) => node.remove());
+ }
+});
+----
+
+A `GetContent` event handler can read the same `export` property:
+
+[source,js,subs="+attributes"]
+----
+editor.on('GetContent', (e) => {
+ if (e.export === '{export-type}') {
+ e.content = removeFooterFromHtml(e.content);
+ }
+});
+----
diff --git a/modules/ROOT/partials/toolbar-button-ids/suggestededits-toolbar-buttons.adoc b/modules/ROOT/partials/toolbar-button-ids/suggestededits-toolbar-buttons.adoc
index 83f8b4fb4c..7d766a3c2b 100644
--- a/modules/ROOT/partials/toolbar-button-ids/suggestededits-toolbar-buttons.adoc
+++ b/modules/ROOT/partials/toolbar-button-ids/suggestededits-toolbar-buttons.adoc
@@ -4,4 +4,5 @@
|`+suggestededits+` |Opens the Review edits view.
|`+suggestededits-label+` |Opens the Review edits view (this button uses text instead of an icon).
+|`+suggestededits-tracking+` |Toggles the tracking of suggested edits.
|===
\ No newline at end of file