diff --git a/.api-version b/.api-version index 214d4b7db8..e1f080d710 100644 --- a/.api-version +++ b/.api-version @@ -1 +1 @@ -8.9.2 \ No newline at end of file +8.10.0 \ No newline at end of file diff --git a/antora.yml b/antora.yml index d481503d6e..bafd9ca548 100644 --- a/antora.yml +++ b/antora.yml @@ -31,7 +31,7 @@ asciidoc: # product variables productname: TinyMCE productmajorversion: 8 - productminorversion: '8.9' + productminorversion: '8.10' ##### product name in codeblock prodnamecode: tinymce #### more names diff --git a/modules/ROOT/examples/live-demos/suggestededits-access-feedback/index.html b/modules/ROOT/examples/live-demos/suggestededits-access-feedback/index.html index 86d97711ad..e7a3865087 100644 --- a/modules/ROOT/examples/live-demos/suggestededits-access-feedback/index.html +++ b/modules/ROOT/examples/live-demos/suggestededits-access-feedback/index.html @@ -1,9 +1,9 @@ - + +

Native integration (shares the AI sidebar of group 1)

+ + +
+

Group 2: article-analysis

+

Workflow comparison (hosts the AI sidebar of group 2)

+ + +

Adoption challenges (shares the AI sidebar of group 2)

+ +
+ diff --git a/modules/ROOT/examples/live-demos/tinymceai-multi-editor-groups/index.js b/modules/ROOT/examples/live-demos/tinymceai-multi-editor-groups/index.js new file mode 100644 index 0000000000..5eec82ad4b --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-multi-editor-groups/index.js @@ -0,0 +1,165 @@ +// Step 1: Set up session - this should be part of the application's user management process. We simulate that here by creating a session for a random user. +const apiKey = '{{tinymceai_demo_api_key}}'; +const isLoggedIn = fetch(`https://demo.api.tiny.cloud/1/${apiKey}/auth/random`, { method: "POST", credentials: "include" }); + +const mentions_fetch = async (query, success) => { + const searchPhrase = query.term.toLowerCase(); + await fetch(`https://demouserdirectory.tiny.cloud/v1/users?q=${encodeURIComponent(searchPhrase)}`) + .then((response) => response.json()) + .then((users) => success(users.data.map((userInfo) => ({ + id: userInfo.id, + name: userInfo.name, + image: userInfo.avatar, + description: userInfo.custom.role + })))) + .catch(() => {}); +}; + +const fetch_users = (userIds) => Promise.all(userIds.map((userId) => fetch(`https://demouserdirectory.tiny.cloud/v1/users/${userId}`).then((response) => response.json()).catch(() => ({ id: userId })))); + +// Each editor seeds its revision history from its own textarea. +const createRevisionHistoryFetch = (selector) => () => { + const textarea = document.querySelector(selector); + const initialContent = textarea ? textarea.value : ''; + const revisions = [ + { + revisionId: '1', + createdAt: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 1, 14, 32, 0).getTime(), + author: { + id: 'jade-scott', + name: 'Jade Scott', + avatar: 'https://sneak-preview.tiny.cloud/demouserdirectory/images/employee_jade-scott_128_515dc6a1.jpg', + }, + content: initialContent + }, + { + revisionId: '0', + createdAt: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 1, 14, 32, 0).getTime(), + author: { + id: 'jade-scott', + name: 'Jade Scott', + avatar: 'https://sneak-preview.tiny.cloud/demouserdirectory/images/employee_jade-scott_128_515dc6a1.jpg', + }, + content: '' + } + ]; + return Promise.resolve(revisions.sort((a, b) => (new Date(a.createdAt) < new Date(b.createdAt) ? -1 : 1))); +}; + +// Share one TinyMCE AI configuration between every editor. Each editor sets its own group, so the page holds two independent groups. +const sharedSettings = { + height: '400px', + plugins: [ + 'autolink', 'link', 'emoticons', 'lists', 'table', 'advlist', 'searchreplace', 'wordcount', 'autocorrect', 'tinymcespellchecker', 'charmap', 'fullscreen', 'advcode', 'accordion', 'anchor', 'footnotes', 'powerpaste', 'importword', 'exportpdf', 'exportword', 'markdown', 'a11ychecker', 'typography', 'casechange', 'checklist', 'advtable', 'formatpainter', 'permanentpen', 'tableofcontents', 'help', 'math', 'linkchecker', 'media', 'mediaembed', + 'quickbars', 'tinymceai', 'tinycomments', 'mentions', 'revisionhistory', 'suggestededits', 'uploadcare' + ], + toolbar: 'undo redo | tinymceai-chat tinymceai-review ai-quickactions-translate | styles | bold italic | bullist numlist | link', + tinymceai_sidebar_type: 'floating', + quickbars_selection_toolbar: 'tinymceai-quickactions addcomment', + tinymceai_chat_welcome_message: '

Welcome to TinyMCE AI. Pick an action below or type your own prompt.

', + tinymceai_chat_welcome_actions: [ + { text: 'Here are some actions to get started:' }, + { title: 'Summarize the document', command: 'TinyMCEAIQuickActionsSummarize' }, + { title: 'Continue writing', command: 'TinyMCEAIQuickActionContinueWriting' }, + { title: 'Translate to Spanish', command: 'TinyMCEAIQuickActionTranslate', value: 'spanish' }, + { title: 'Review my document', command: 'ToggleSidebar', value: 'tinymceai-review' } + ], + toolbar_mode: 'sliding', + visual: false, + images_file_types: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp,svg', + user_id: 'james-wilson', + spellchecker_active: true, + spellchecker_dialog: true, + uploadcare_public_key: '630992ad50fe2291c406', + uploadcare_store_type: 'temporary', + advcode_inline: true, + tinycomments_mode: 'embedded', + suggestededits_content: 'html', + mentions_item_type: 'profile', + mentions_fetch, + fetch_users, + revisionhistory_display_author: true, + tinymceai_token_provider: async () => { + // Step 2: Check we have a session then fetch JWT + return isLoggedIn.then(() => + fetch(`https://demo.api.tiny.cloud/1/${apiKey}/jwt/tinymceai`, { credentials: "include" }) + .then(resp => resp.text()) + .then(token => ({ token })) + ); + }, + tinymceai_chat_fetch_sources: () => Promise.resolve([{ + label: 'TinyMCE resources', + sources: [ + { id: 'docs', label: 'TinyMCE Documentation', type: 'web-resource' }, + { id: 'blog', label: 'Tiny Blog', type: 'web-resource' }, + { id: 'survey-2023', label: 'State of rich text editing 2023', type: 'web-resource' }, + ] + }]), + tinymceai_chat_fetch_source: (id) => { + const urls = { + 'docs': 'https://www.tiny.cloud/docs/tinymce/latest/', + 'blog': 'https://www.tiny.cloud/blog/', + 'survey-2023': 'https://www.tiny.cloud/developer-survey-results-2023/', + }; + return Promise.resolve({ type: 'web-resource', url: urls[id] }); + }, + tinymceai_quickactions_custom: [ + { + type: 'chat', + title: 'Challenge', + prompt: 'Challenge statements, verify facts and identify assumptions' + } + ], + tinymceai_languages: [ + { title: 'English', language: 'english' }, + { title: 'Chinese (Simplified)', language: 'chinese' }, + { title: 'Spanish', language: 'spanish' }, + { title: 'German', language: 'german' }, + { title: 'Japanese', language: 'japanese' }, + { title: 'Portuguese', language: 'portuguese' }, + { title: 'Swedish', language: 'swedish' }, + { title: 'Korean', language: 'korean' }, + { title: 'Hindi (Devanagari)', language: 'hindi devanagari' }, + { title: 'Italian', language: 'italian' }, + { title: 'Klingon', language: 'klingon' }, + { title: 'Dothraki', language: 'dothraki' }, + ] +}; + +// Group 1: the Introduction and Native integration editors share one AI sidebar. +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-groups-introduction', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-groups-introduction'), + tinymceai_group: 'article-opening', + tinymceai_document_name: 'Introduction', + tinymceai_document_description: 'The introduction of the article. A title, a short paragraph that sets out the topic, and a figure.' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-groups-native-integration', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-groups-native-integration'), + tinymceai_group: 'article-opening', + tinymceai_document_name: 'Native integration', + tinymceai_document_description: 'The section on moving from external AI tools to AI built into the editor, with a bulleted list of benefits.' +}); + +// Group 2: the Workflow comparison and Adoption challenges editors share a separate AI sidebar and never see the content of group 1. +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-groups-workflow-comparison', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-groups-workflow-comparison'), + tinymceai_group: 'article-analysis', + tinymceai_document_name: 'Workflow comparison', + tinymceai_document_description: 'The section that compares traditional and AI-enhanced workflows. Keep the comparison table.' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-groups-adoption-challenges', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-groups-adoption-challenges'), + tinymceai_group: 'article-analysis', + tinymceai_document_name: 'Adoption challenges', + tinymceai_document_description: 'The closing section on adoption challenges. Two short paragraphs.' +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-multi-editor/example.js b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/example.js new file mode 100644 index 0000000000..59f9baea49 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/example.js @@ -0,0 +1,74 @@ +// Open-source plugins below are only for editing the demo HTML (lists, links, tables). TinyMCE AI options are the focus. +// Share one TinyMCE AI configuration between every editor in the group. +const sharedSettings = { + height: '400px', + plugins: ['tinymceai', 'advlist', 'lists', 'link', 'autolink', 'table', 'wordcount'], + toolbar: 'undo redo | tinymceai-chat tinymceai-review ai-quickactions-translate | styles | bold italic | bullist numlist | link', + tinymceai_sidebar_type: 'floating', + tinymceai_chat_welcome_message: '

Welcome to TinyMCE AI. Pick an action below or type your own prompt.

', + tinymceai_chat_welcome_actions: [ + { text: 'Here are some actions to get started:' }, + { title: 'Summarize the document', command: 'TinyMCEAIQuickActionsSummarize' }, + { title: 'Continue writing', command: 'TinyMCEAIQuickActionContinueWriting' }, + { title: 'Translate to Spanish', command: 'TinyMCEAIQuickActionTranslate', value: 'spanish' }, + { title: 'Review my document', command: 'ToggleSidebar', value: 'tinymceai-review' } + ], + tinymceai_token_provider: async () => { + return fetch('/api/token', { credentials: 'include' }) + .then(resp => resp.text()) + .then(token => ({ token })); + }, + tinymceai_chat_fetch_sources: () => Promise.resolve([{ + label: 'TinyMCE resources', + sources: [ + { id: 'docs', label: 'TinyMCE Documentation', type: 'web-resource' }, + { id: 'blog', label: 'Tiny Blog', type: 'web-resource' }, + { id: 'survey-2023', label: 'State of rich text editing 2023', type: 'web-resource' }, + ] + }]), + tinymceai_chat_fetch_source: (id) => { + const urls = { + 'docs': 'https://www.tiny.cloud/docs/tinymce/latest/', + 'blog': 'https://www.tiny.cloud/blog/', + 'survey-2023': 'https://www.tiny.cloud/developer-survey-results-2023/', + }; + return Promise.resolve({ type: 'web-resource', url: urls[id] }); + }, + tinymceai_quickactions_custom: [ + { + type: 'chat', + title: 'Challenge', + prompt: 'Challenge statements, verify facts and identify assumptions' + } + ], + tinymceai_languages: [ + { title: 'English', language: 'english' }, + { title: 'Chinese (Simplified)', language: 'chinese' }, + { title: 'Spanish', language: 'spanish' }, + { title: 'German', language: 'german' }, + { title: 'Japanese', language: 'japanese' }, + { title: 'Portuguese', language: 'portuguese' }, + { title: 'Swedish', language: 'swedish' }, + { title: 'Korean', language: 'korean' }, + { title: 'Hindi (Devanagari)', language: 'hindi devanagari' }, + { title: 'Italian', language: 'italian' }, + { title: 'Klingon', language: 'klingon' }, + { title: 'Dothraki', language: 'dothraki' }, + ] +}; + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-introduction', + tinymceai_group: 'article', + tinymceai_document_name: 'Introduction', + tinymceai_document_description: 'The introduction of the article. A title, a short paragraph that sets out the topic, and a figure.' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-body', + tinymceai_group: 'article', + tinymceai_document_name: 'Body', + tinymceai_document_description: 'The main body of the article. Uses h2 and h3 subheadings, short paragraphs, a bulleted list, and a comparison table.' +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.html b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.html new file mode 100644 index 0000000000..6c2a5ef576 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.html @@ -0,0 +1,62 @@ +

Introduction (first editor in the group)

+ + +

Body (shares the AI sidebar with the Introduction)

+ diff --git a/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.js b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.js new file mode 100644 index 0000000000..600056c785 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-multi-editor/index.js @@ -0,0 +1,145 @@ +// Step 1: Set up session - this should be part of the application's user management process. We simulate that here by creating a session for a random user. +const apiKey = '{{tinymceai_demo_api_key}}'; +const isLoggedIn = fetch(`https://demo.api.tiny.cloud/1/${apiKey}/auth/random`, { method: "POST", credentials: "include" }); + +const mentions_fetch = async (query, success) => { + const searchPhrase = query.term.toLowerCase(); + await fetch(`https://demouserdirectory.tiny.cloud/v1/users?q=${encodeURIComponent(searchPhrase)}`) + .then((response) => response.json()) + .then((users) => success(users.data.map((userInfo) => ({ + id: userInfo.id, + name: userInfo.name, + image: userInfo.avatar, + description: userInfo.custom.role + })))) + .catch(() => {}); +}; + +const fetch_users = (userIds) => Promise.all(userIds.map((userId) => fetch(`https://demouserdirectory.tiny.cloud/v1/users/${userId}`).then((response) => response.json()).catch(() => ({ id: userId })))); + +// Each editor seeds its revision history from its own textarea. +const createRevisionHistoryFetch = (selector) => () => { + const textarea = document.querySelector(selector); + const initialContent = textarea ? textarea.value : ''; + const revisions = [ + { + revisionId: '1', + createdAt: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 1, 14, 32, 0).getTime(), + author: { + id: 'jade-scott', + name: 'Jade Scott', + avatar: 'https://sneak-preview.tiny.cloud/demouserdirectory/images/employee_jade-scott_128_515dc6a1.jpg', + }, + content: initialContent + }, + { + revisionId: '0', + createdAt: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 1, 14, 32, 0).getTime(), + author: { + id: 'jade-scott', + name: 'Jade Scott', + avatar: 'https://sneak-preview.tiny.cloud/demouserdirectory/images/employee_jade-scott_128_515dc6a1.jpg', + }, + content: '' + } + ]; + return Promise.resolve(revisions.sort((a, b) => (new Date(a.createdAt) < new Date(b.createdAt) ? -1 : 1))); +}; + +// Share one TinyMCE AI configuration between every editor in the group. +const sharedSettings = { + height: '400px', + plugins: [ + 'autolink', 'link', 'emoticons', 'lists', 'table', 'advlist', 'searchreplace', 'wordcount', 'autocorrect', 'tinymcespellchecker', 'charmap', 'fullscreen', 'advcode', 'accordion', 'anchor', 'footnotes', 'powerpaste', 'importword', 'exportpdf', 'exportword', 'markdown', 'a11ychecker', 'typography', 'casechange', 'checklist', 'advtable', 'formatpainter', 'permanentpen', 'tableofcontents', 'help', 'math', 'linkchecker', 'media', 'mediaembed', + 'quickbars', 'tinymceai', 'tinycomments', 'mentions', 'revisionhistory', 'suggestededits', 'uploadcare' + ], + toolbar: 'undo redo | tinymceai-chat tinymceai-review ai-quickactions-translate | styles | bold italic | bullist numlist | link', + tinymceai_sidebar_type: 'floating', + quickbars_selection_toolbar: 'tinymceai-quickactions addcomment', + tinymceai_chat_welcome_message: '

Welcome to TinyMCE AI. Pick an action below or type your own prompt.

', + tinymceai_chat_welcome_actions: [ + { text: 'Here are some actions to get started:' }, + { title: 'Summarize the document', command: 'TinyMCEAIQuickActionsSummarize' }, + { title: 'Continue writing', command: 'TinyMCEAIQuickActionContinueWriting' }, + { title: 'Translate to Spanish', command: 'TinyMCEAIQuickActionTranslate', value: 'spanish' }, + { title: 'Review my document', command: 'ToggleSidebar', value: 'tinymceai-review' } + ], + toolbar_mode: 'sliding', + visual: false, + images_file_types: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp,svg', + user_id: 'james-wilson', + spellchecker_active: true, + spellchecker_dialog: true, + uploadcare_public_key: '630992ad50fe2291c406', + uploadcare_store_type: 'temporary', + advcode_inline: true, + tinycomments_mode: 'embedded', + suggestededits_content: 'html', + mentions_item_type: 'profile', + mentions_fetch, + fetch_users, + revisionhistory_display_author: true, + tinymceai_token_provider: async () => { + // Step 2: Check we have a session then fetch JWT + return isLoggedIn.then(() => + fetch(`https://demo.api.tiny.cloud/1/${apiKey}/jwt/tinymceai`, { credentials: "include" }) + .then(resp => resp.text()) + .then(token => ({ token })) + ); + }, + tinymceai_chat_fetch_sources: () => Promise.resolve([{ + label: 'TinyMCE resources', + sources: [ + { id: 'docs', label: 'TinyMCE Documentation', type: 'web-resource' }, + { id: 'blog', label: 'Tiny Blog', type: 'web-resource' }, + { id: 'survey-2023', label: 'State of rich text editing 2023', type: 'web-resource' }, + ] + }]), + tinymceai_chat_fetch_source: (id) => { + const urls = { + 'docs': 'https://www.tiny.cloud/docs/tinymce/latest/', + 'blog': 'https://www.tiny.cloud/blog/', + 'survey-2023': 'https://www.tiny.cloud/developer-survey-results-2023/', + }; + return Promise.resolve({ type: 'web-resource', url: urls[id] }); + }, + tinymceai_quickactions_custom: [ + { + type: 'chat', + title: 'Challenge', + prompt: 'Challenge statements, verify facts and identify assumptions' + } + ], + tinymceai_languages: [ + { title: 'English', language: 'english' }, + { title: 'Chinese (Simplified)', language: 'chinese' }, + { title: 'Spanish', language: 'spanish' }, + { title: 'German', language: 'german' }, + { title: 'Japanese', language: 'japanese' }, + { title: 'Portuguese', language: 'portuguese' }, + { title: 'Swedish', language: 'swedish' }, + { title: 'Korean', language: 'korean' }, + { title: 'Hindi (Devanagari)', language: 'hindi devanagari' }, + { title: 'Italian', language: 'italian' }, + { title: 'Klingon', language: 'klingon' }, + { title: 'Dothraki', language: 'dothraki' }, + ] +}; + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-introduction', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-introduction'), + tinymceai_group: 'article', + tinymceai_document_name: 'Introduction', + tinymceai_document_description: 'The introduction of the article. A title, a short paragraph that sets out the topic, and a figure.' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#tinymceai-multi-editor-body', + revisionhistory_fetch: createRevisionHistoryFetch('textarea#tinymceai-multi-editor-body'), + tinymceai_group: 'article', + tinymceai_document_name: 'Body', + tinymceai_document_description: 'The main body of the article. Uses h2 and h3 subheadings, short paragraphs, a bulleted list, and a comparison table.' +}); diff --git a/modules/ROOT/images/icons/revert-all.svg b/modules/ROOT/images/icons/revert-all.svg new file mode 100644 index 0000000000..5c73a0fe6e --- /dev/null +++ b/modules/ROOT/images/icons/revert-all.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/tinymceai/tinymceai-context-tag.png b/modules/ROOT/images/tinymceai/tinymceai-context-tag.png new file mode 100644 index 0000000000..b04ead3a52 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymceai-context-tag.png differ diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 366559b36c..9489a27130 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -258,6 +258,7 @@ **** xref:tinymceai-chat.adoc[Chat] **** xref:tinymceai-review.adoc[Review] **** xref:tinymceai-actions.adoc[Actions] +**** xref:tinymceai-multi-editor.adoc[Multi-editor mode] **** xref:tinymceai-models.adoc[AI models] **** xref:tinymceai-limits.adoc[Limits] **** xref:tinymceai-integration-options.adoc[Integration options] @@ -424,20 +425,10 @@ ** xref:release-notes.adoc[Release notes for {productname}] *** {productname} 8.10.0 **** xref:8.10.0-release-notes.adoc#overview[Overview] -**** xref:8.10.0-release-notes.adoc#new-premium-plugin[New Premium Plugin] -**** xref:8.10.0-release-notes.adoc#new-open-source-plugin[New Open Source Plugin] **** xref:8.10.0-release-notes.adoc#accompanying-premium-plugin-changes[Accompanying Premium Plugin changes] -**** xref:8.10.0-release-notes.adoc#accompanying-premium-plugin-end-of-life-announcement[Accompanying Premium Plugin end-of-life announcement] -**** xref:8.10.0-release-notes.adoc#accompanying-open-source-plugin-end-of-life-announcement[Accompanying Open Source Plugin end-of-life announcement] **** xref:8.10.0-release-notes.adoc#accompanying-enhanced-skins-and-icon-packs-changes[Accompanying Enhanced Skins & Icon Packs changes] -**** xref:8.10.0-release-notes.adoc#improvements[Improvements] **** xref:8.10.0-release-notes.adoc#additions[Additions] -**** xref:8.10.0-release-notes.adoc#changes[Changes] -**** xref:8.10.0-release-notes.adoc#removed[Removed] **** xref:8.10.0-release-notes.adoc#bug-fixes[Bug fixes] -**** xref:8.10.0-release-notes.adoc#security-fixes[Security fixes] -**** xref:8.10.0-release-notes.adoc#deprecated[Deprecated] -**** xref:8.10.0-release-notes.adoc#known-issues[Known issues] *** {productname} 8.9.3 **** xref:8.9.3-release-notes.adoc#overview[Overview] **** xref:8.9.3-release-notes.adoc#security-fixes[Security fixes] diff --git a/modules/ROOT/pages/8.10.0-release-notes.adoc b/modules/ROOT/pages/8.10.0-release-notes.adoc index fa0f879095..7c86965e4e 100644 --- a/modules/ROOT/pages/8.10.0-release-notes.adoc +++ b/modules/ROOT/pages/8.10.0-release-notes.adoc @@ -11,185 +11,420 @@ include::partial$misc/admon-releasenotes-for-stable.adoc[] [[overview]] == Overview -{productname} {release-version} was released for {enterpriseversion} and {cloudname} on ,
^^, . These release notes provide an overview of the changes for {productname} {release-version}, including: +{productname} {release-version} was released for {enterpriseversion} and {cloudname} on Wednesday, October 14^th^, 2026. These release notes provide an overview of the changes for {productname} {release-version}, including: -// Remove sections and section boilerplates as necessary. -// Pluralise as necessary or remove the placeholder plural marker. -* xref:new-premium-plugin[New Premium plugin] -* xref:new-open-source-plugin[New Open Source plugin] * xref:accompanying-premium-plugin-changes[Accompanying Premium plugin changes] -* xref:accompanying-premium-plugin-end-of-life-announcement[Accompanying Premium plugin end-of-life announcement] -* xref:accompanying-open-source-plugin-end-of-life-announcement[Accompanying open source plugin end-of-life-announcement] * xref:accompanying-enhanced-skins-and-icon-packs-changes[Accompanying Enhanced Skins & Icon Packs changes] -* xref:improvements[Improvements] * xref:additions[Additions] -* xref:changes[Changes] * xref:bug-fixes[Bug fixes] -* xref:security-fixes[Security fixes] -* xref:deprecated[Deprecated] -* xref:known-issues[Known issues] -[[new-premium-plugin]] -== New Premium plugin +[[accompanying-premium-plugin-changes]] +== Accompanying Premium plugin changes -The following new Premium plugin was released alongside {productname} {release-version}. +The following premium plugin updates were released alongside {productname} {release-version}. -=== +=== Image Editing -The new Premium plugin, **** // description here. +The {productname} {release-version} release includes an accompanying release of the **Image Editing** premium plugin. -For information on the **** plugin, see xref:.adoc[]. +**Image Editing** includes the following fix. +==== Clicking **Edit image** now shows an error notification instead of failing silently when the image cannot be loaded +// #TINYMCE-14679 -[[new-open-source-plugin]] -== New Open Source plugin +Previously, when the image proxy returned an error for an image, such as a `+404+` or `+424+` response, clicking **Edit image** did not open the Edit Image dialog and did not display a message. The **Image Editing** plugin logged an uncaught error to the browser console instead. Users received no indication that the image could not be loaded for editing. -The following new Open Source plugin was released alongside {productname} {release-version}. +In {productname} {release-version}, the **Image Editing** plugin displays an error notification when the image cannot be loaded. The plugin also displays an error notification when applying an edit from the Edit Image dialog fails. The image proxy returns a `+424+` response when it cannot retrieve the image from its source. In that case, the notification reports that the image failed to load. -=== +For information on the **Image Editing** plugin, see: xref:editimage.adoc[Image Editing]. -The new open source plugin, **** // description here. +=== Suggested Edits -For information on the **** plugin, see xref:.adoc[]. +The {productname} {release-version} release includes an accompanying release of the **Suggested Edits** premium plugin. The review interface now uses the same layout and components as the **TinyMCE AI** review. Setup and configuration of the plugin are unchanged. The class names of the suggestion cards and the review panel have changed, so custom CSS written for the previous class names must be updated. +**Suggested Edits** includes the following changes, improvements, and fixes. -[[accompanying-premium-plugin-changes]] -== Accompanying Premium plugin changes +==== The review actions moved to the sidebar header and were renamed +// #TINYMCE-14619 +// #TINYMCE-14620 +// #TINYMCE-14862 +// #TINYMCE-14618 -The following premium plugin updates were released alongside {productname} {release-version}. +Previously, the **Complete review** and **Cancel** buttons for a Suggested Edits review appeared in a header bar above the review content, apart from the sidebar that lists the suggestions. -=== +In {productname} {release-version}, the **Suggested Edits** plugin shows these actions in the sidebar header, next to the **Review edits** title. The **Save & Exit** button replaces **Complete review**. The **Exit review** button replaces **Cancel** and shows only an icon, with **Exit review** as its tooltip and accessible label. Both actions work as before. The sidebar is also wider, 440 pixels instead of 316 pixels. For more information, see xref:suggestededits.adoc#header[Header]. -The {productname} {release-version} release includes an accompanying release of the **** premium plugin. +==== Diff mode and Preview options replaced the Show edits toggle +// #TINYMCE-14610 -**** includes the following . +Previously, the **Suggested Edits** plugin placed the **Show edits** toggle in the header of the Review edits view, apart from the review content that the toggle switched. With **Show edits** turned off, the plugin also dimmed the suggestion cards, which made the cards look disabled even though their buttons still worked. -==== +In {productname} {release-version}, the **Suggested Edits** plugin replaces the **Show edits** toggle with **Diff mode** and **Preview** options in a footer below the review content. **Diff mode** shows the suggested edits and is the default view. **Preview** shows how the document reads with the suggested edits applied. The suggestion cards no longer dim in either view. The footer matches the review bar in **TinyMCE AI**, so the view switch appears in the same place in both plugins. For more information, see xref:suggestededits.adoc#footer[Footer]. -// CCFR here. +==== The review now keeps the editor menu bar and toolbar visible, makes the editor read-only, and closes when a sidebar opens +// #TINYMCE-14768 -For information on the **** plugin, see: xref:.adoc[]. +Previously, the Review edits view replaced the whole editor, including the menu bar and toolbar, so the review appeared as a separate screen. +In {productname} {release-version}, the **Suggested Edits** plugin keeps the editor menu bar and toolbar visible during a review and makes the editor content read-only. Most toolbar buttons and menu items are disabled during the review, but items that work in any editor mode, such as **Fullscreen**, **Preview**, and **Print**, remain available. Opening a sidebar closes the review. For more information, see xref:suggestededits.adoc#reviewing-edits[Reviewing edits]. -[[accompanying-premium-plugin-end-of-life-announcement]] -== Accompanying Premium plugin end-of-life announcement +==== The review now keeps the status bar visible and lets the editor be resized while suggestions are reviewed +// #TINYMCE-14920 -The following Premium plugin has been announced as reaching its end-of-life: +Previously, the Review edits view covered the editor status bar, so the editor could not be resized during a review. -=== +In {productname} {release-version}, the status bar remains visible during a review, and the editor can be resized while suggestions are reviewed. -{productname}’s xref:.adoc[] plugin will be deactivated on
, , and is no longer available for purchase. +==== Bulk accepting or rejecting suggestions no longer overwrites suggestions that were already accepted or rejected individually +// #TINYMCE-14851 +// #TINYMCE-14913 +Previously, the **Accept all** and **Reject all** bulk actions changed the status of every suggestion, including suggestions already accepted or rejected individually. Reviewers who mixed individual and bulk decisions lost their earlier decisions and had to make them again. -[[accompanying-open-source-plugin-end-of-life-announcement]] -== Accompanying open source plugin end-of-life announcement +In {productname} {release-version}, bulk accept and reject apply only to unresolved suggestions. While some suggestions are resolved and others remain unresolved, the bulk actions are labeled **Accept remaining** and **Reject remaining**. **Revert all** is unavailable until at least one suggestion is resolved, and the accept and reject actions are unavailable when no unresolved suggestions remain. For more information, see xref:suggestededits.adoc#bulk-actions[Bulk actions]. -The following open source plugin has been announced as reaching its end-of-life: +==== Suggested Edits cards now use icon-only accept and reject actions that appear on hover, with tooltips +// #TINYMCE-14607 +// #TINYMCE-14612 +// #TINYMCE-14705 -=== +Previously, each suggestion card stacked the author, a colored label for the type of change, and the date, and a selected card added a row of **Reject** and **Accept** text buttons below its details. -{productname}’s xref:.adoc[] plugin will be deactivated on
, , and is no longer available for purchase. +In {productname} {release-version}, the card header shows the author's avatar, name, and the date in one row. **Accept** and **Reject** are icon buttons with tooltips in the card header. The buttons appear when pointing to a card and stay visible while the card is selected, so more cards fit in the sidebar. +==== Suggested Edits cards now show a preview of changed text for each operation +// #TINYMCE-14828 +// #TINYMCE-14615 -[[accompanying-enhanced-skins-and-icon-packs-changes]] -== Accompanying Enhanced Skins & Icon Packs changes +Previously, suggestion cards described only the type of content that changed, such as "deleted text", so reviewers could not tell from the card alone which part of the document had changed. -The {productname} {release-version} release includes an accompanying release of the **Enhanced Skins & Icon Packs**. +In {productname} {release-version}, each card quotes the changed text, for example: Replaced "`the`" with "`them`". Long text is shortened with an ellipsis. Changes that are not text name the type of content that changed, such as an image or a table. Reviewers can see what changed, and where, from the card alone. -=== Enhanced Skins & Icon Packs +==== Suggestion cards in the sidebar are now listed in the order the changes appear in the document +// #TINYMCE-14966 -The **Enhanced Skins & Icon Packs** release includes the following updates: +Previously, suggestion cards were listed in the order the suggestions were created. For example, deleting an image near the top of the document after editing further down placed the card for the image near the bottom of the sidebar. Reviewers working from top to bottom had to move around the document. -The **Enhanced Skins & Icon Packs** were rebuilt to pull in the changes also incorporated into the default {productname} {release-version} skin, Oxide. +In {productname} {release-version}, suggestion cards are listed in the order their changes appear in the document, from top to bottom, regardless of who made each change or when. Users can work through suggestions in reading order and match each card to its change. -For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-and-icon-packs.adoc[Enhanced Skins & Icon Packs]. +==== Diff mode and Preview now make suggested changes easier to spot +// #TINYMCE-14609 +Previously, with **Show edits** turned on, the **Suggested Edits** plugin displayed unchanged content with the same emphasis as suggested edits, so the suggestions were hard to spot. With **Show edits** turned off, the plugin did not show where the suggestions were. The plugin also marked every line break in the document, not only the line breaks that changed. Reviewers had to read the whole document to find each suggestion and could miss one in a long document. -[[improvements]] -== Improvements +In {productname} {release-version}, **Diff mode** dims unchanged content while suggestions are pending, so the pending suggestions stand out. **Preview** underlines added and modified content in place, and line break markers appear only where a line break was added or removed. -{productname} {release-version} also includes the following improvement: +==== Deleted media in Diff mode now shows a red X overlay +// #TINYMCE-14611 -=== -// #TINY-vwxyz1 +Previously, a deleted image was marked only with a highlight, which could be easy to miss. -// CCFR here. +In {productname} {release-version}, **Diff mode** also marks deleted images, videos, and embedded frames with a large red X. +==== Preview now shows only the inserted text of a replaced suggestion +// #TINYMCE-14771 -[[additions]] -== Additions +In {productname} {release-version}, selecting a suggestion that replaces text in **Preview** shows and highlights only the new text, and the removed text stays hidden. **Preview** matches the content produced by accepting the suggestion. **Diff mode** continues to show both the removed and the added text. + +==== Opening the Review edits view now keeps the editor scroll position, and closing it restores the review scroll position in the editor +// #TINYMCE-14902 + +Previously, opening the Review edits view jumped to the first change, and closing it scrolled the editor back to the cursor. Each time the review opened or closed, the reader lost the current position in the document. + +In {productname} {release-version}, the Review edits view opens at the same position in the document that the editor showed, and closing the review returns the editor to the position last shown in the review. Selecting a card still scrolls to its change. + +==== The up and down arrow keys now move between suggestion cards in the sidebar and select the focused suggestion +// #TINYMCE-14844 + +Previously, the Up Arrow and Down Arrow keys did not move between suggestion cards in the sidebar, so keyboard users had to press Tab through the controls of each card to reach the next suggestion. Reviewing a document with many suggestions from the keyboard was slow. + +In {productname} {release-version}, the Up Arrow and Down Arrow keys move between suggestion cards in the sidebar and select the focused suggestion, which highlights it in the document. Pressing Enter on a card moves focus into the content of that card. For more information, see xref:suggestededits.adoc#keyboard-navigation[Keyboard navigation]. + +==== Suggestion cards now include the accepted or rejected outcome in their accessible name, and the revert button is named Revert +// #TINYMCE-14616 + +In {productname} {release-version}, screen readers announce whether a suggestion was accepted or rejected as part of the card name, and the button that reverts a decision is announced as **Revert**. + +==== Suggested Edits cards now describe elements without a friendly name as "content" instead of showing their HTML tag name +// #TINYMCE-14952 + +Previously, when a changed element did not have a friendly name, its card showed the HTML tag name of the element. For example, pasting content that contained a `+div+` element produced a card reading "Added div". Users could see technical terms that did not explain the change. + +In {productname} {release-version}, cards describe elements without a friendly name as "content", so "Added div" now reads "Added content". The card still shows the changed text, and elements that already have a friendly name, such as paragraphs, images, tables, and lists, are described as before. + +==== Long feedback text without spaces overflowed the suggested edit card and pushed the card's buttons and textbox out of alignment +// #TINYMCE-14973 + +Previously, feedback on a suggestion that contained a long string with no spaces, such as a long link, ran past the edge of the suggestion card. The overflowing text pushed the buttons and the feedback text box of the card out of alignment and made the sidebar scroll sideways. + +In {productname} {release-version}, long feedback text wraps onto new lines within the suggestion card, and the buttons and text box of the card remain aligned. + +==== Nested parts of the same suggestion showed duplicate highlights +// #TINYMCE-14358 + +Previously, when one suggestion changed both an element and the content inside it, such as the font size of a list, the Review edits view highlighted the element, then highlighted each part of the content inside it again. The Review edits view also stacked the selection styling when the suggestion was selected. The stacked styling made the change cluttered and harder to read. + +In {productname} {release-version}, the **Suggested Edits** plugin applies the highlight and selection styling once for each suggestion, on the outermost element that the suggestion changes, in both **Diff mode** and **Preview**. + +For information on the **Suggested Edits** plugin, see: xref:suggestededits.adoc[Suggested Edits]. + + +=== TinyMCE AI + +The {productname} {release-version} release includes an accompanying release of the **TinyMCE AI** premium plugin. + +**TinyMCE AI** includes the following addition, improvements, and fixes. + +==== New multi-editor support +// #TINYMCE-14817 + +Previously, the **TinyMCE AI** plugin worked with one editor at a time. When related content was split across several editors on a page, users had to run Chat, Review, and Quick Actions in each editor separately, and the AI had no context from the other editors. + +In {productname} {release-version}, the **TinyMCE AI** plugin can group editors on the same page. Editors that share a xref:tinymceai.adoc#tinymceai_group[`+tinymceai_group+`] value share one Chat sidebar and one Review sidebar. Chat, Review, and Quick Actions work across the content of every editor in the group, and the plugin previews and applies each change in the editor it belongs to. The Review sidebar groups suggestions under the name of the editor they belong to. + +The xref:tinymceai.adoc#tinymceai_document_name[`+tinymceai_document_name+`] option names the content of each editor, and the xref:tinymceai.adoc#tinymceai_document_description[`+tinymceai_document_description+`] option describes that content to the AI service. + +For information on multi-editor mode, see xref:tinymceai-multi-editor.adoc[Multi-editor mode]. + +==== Deleted media in AI preview Diff mode now shows a red X overlay +// #TINYMCE-14611 + +Previously, a deleted image in a **TinyMCE AI** preview was marked only with a highlight, which could be easy to miss. + +In {productname} {release-version}, **Diff mode** in a **TinyMCE AI** preview also marks deleted images, videos, and embedded frames with a large red X. + +==== Nested parts of the same suggestion showed duplicate highlights +// #TINYMCE-14358 + +Previously, when one suggestion changed both an element and the content inside it, such as a modified list item and its modified text, the **TinyMCE AI** plugin applied the highlight, selection, and preview highlight styling to the element and again to the content inside it. The stacked styling appeared in **Diff mode** and **Preview** for Chat, Quick Actions, and Review suggestions. It made the suggestion cluttered and harder to read. + +In {productname} {release-version}, the **TinyMCE AI** plugin applies the highlight, selection, and preview highlight styling only once for each suggestion, on the outermost element that the suggestion changes, in both **Diff mode** and **Preview**. Content inside that element no longer repeats the styling. + +==== Applying or skipping all quick action suggestions did nothing when the Review sidebar was open +// #TINYMCE-14293 + +Previously, when the Review sidebar was open but no review was in progress, the **TinyMCE AI** plugin handled a quick action preview as if it belonged to a review. Selecting **Apply all** or **Skip all** in the preview footer did not resolve the suggestions, and the editor stayed in preview mode. Users had to close the Review sidebar before they could apply or skip the result of a quick action. + +In {productname} {release-version}, the **TinyMCE AI** plugin resolves a quick action preview based on whether a review is in progress, not on whether the Review sidebar is open. While the Review sidebar is open, **Apply all** applies the suggestions, **Skip all** skips them, and the editor then leaves preview mode. + +==== Selecting an applied or skipped suggestion in Diff mode showed only part of the change, or none of it, instead of the full suggestion +// #TINYMCE-14948 + +Previously, in **Diff mode**, the **TinyMCE AI** plugin hid part or all of a change as soon as applying or skipping the suggestion removed that content from the result. This affected a skipped addition, an applied deletion, and the added part of a skipped replacement. The suggestion stayed selected, for example as a card in the Review sidebar, but the change no longer appeared in the content. Users could not check what they had just applied or skipped, so reconsidering a decision before finishing the review was harder. + +In {productname} {release-version}, the **TinyMCE AI** plugin shows the full change in **Diff mode** while an applied or skipped suggestion is selected, with removed content struck through and added content styled as an addition. The plugin hides the change when another suggestion is selected, and shows it again whenever its suggestion is selected. **Preview** still shows only the resulting content. + +==== Button text in the confirmation dialog would not be translated +// #TINYMCE-14751 + +Previously, the confirmation dialog that appeared when a user deleted a conversation from the Chat history displayed the **Yes** and **No** buttons in English, regardless of the editor language. The **TinyMCE AI** plugin translated the confirmation message but not the button text, so users of a non-English editor saw a dialog in two languages. + +In {productname} {release-version}, the **TinyMCE AI** plugin translates the **Yes** and **No** buttons into the language set by the xref:ui-localization.adoc#language[`+language+`] option. The whole confirmation dialog now appears in the configured language. + +==== Clicking outside a suggestion in the AI preview now deselects the active suggestion and dismisses its context toolbar or review card highlight +// #TINYMCE-14706 + +Previously, clicking empty space outside a suggestion in a **TinyMCE AI** preview did nothing. The last selected suggestion stayed highlighted, its context toolbar stayed on screen, and during a review the matching card in the Review sidebar stayed selected. The only way to clear the selection was to select a different suggestion. Users could not get a clear view of the proposed content, and the context toolbar could cover nearby text. + +In {productname} {release-version}, clicking anywhere in the preview outside a suggestion clears the active selection. The **TinyMCE AI** plugin closes the context toolbar and, during a review, removes the highlight from the card in the Review sidebar. + +==== Diff mode reserved an empty scrollbar gutter beside the content +// #TINYMCE-14933 + +Previously, the **TinyMCE AI** plugin reserved space for a scrollbar whenever the **Diff mode** tab displayed proposed changes, even when the content was too short to scroll. The empty gutter beside the content looked like a broken scrollbar. + +In {productname} {release-version}, the **TinyMCE AI** plugin no longer reserves space for a scrollbar in **Diff mode**. A scrollbar appears only when the content is long enough to scroll. -{productname} {release-version} also includes the following addition: +==== Starting a quick action, chat prompt, or review while another one was still running canceled both instead of keeping the new one +// #TINYMCE-14806 -=== -// #TINY-vwxyz1 +The **TinyMCE AI** plugin runs one AI task at a time, and starting a new task cancels the task in progress. Previously, when a user started a quick action, sent a chat prompt, or started a review while another task was still running, the plugin canceled both the running task and the new one. Users had to start the new task again. -// CCFR here. +In {productname} {release-version}, starting a new task while another task is running cancels only the running task. The new quick action, chat prompt, or review runs to completion. +==== The `+tinymceai_chat_fetch_sources+` option now reports a clear error when it returns sources in an unexpected format +// #TINYMCE-14802 -[[changes]] -== Changes +Previously, the **TinyMCE AI** plugin did not check the value returned by the xref:tinymceai.adoc#tinymceai_chat_fetch_sources[`+tinymceai_chat_fetch_sources+`] function. When the function resolved with a value in an unexpected format, for example a source without a `+type+` or a `+defaults+` value that was not an array, the browser console showed a generic JavaScript error that did not identify the cause. -{productname} {release-version} also includes the following change: +In {productname} {release-version}, the **TinyMCE AI** plugin checks the returned value against the formats that the option supports. When the value does not match, the browser console logs a `+DecodingError+` that includes the value the function returned. -=== -// #TINY-vwxyz1 +==== Opening an editor view now asks for confirmation before discarding AI suggestions +// #TINYMCE-14893 -// CCFR here. +Previously, while **TinyMCE AI** suggestions were displayed in the editor, for example after running a quick action, opening an editor view such as the **Suggested Edits** review discarded the suggestions without warning. Switching to the Chat sidebar or the Review sidebar already asked for confirmation, but opening a view did not. +In {productname} {release-version}, opening a view while suggestions are displayed shows the same confirmation dialog: _Leaving this AI flow will discard current suggestions and reset applied changes. Continue?_ Canceling keeps the suggestions and the current view. Confirming discards the suggestions and opens the view. + +==== Pressing Enter in the AI Chat prompt before the models loaded caused a "No model selected" error +// #TINYMCE-14827 + +Previously, when a user opened the Chat sidebar, typed a prompt, and pressed Enter before the list of AI models had loaded, the **TinyMCE AI** plugin sent the prompt without a model. An error notification appeared, and the browser console logged `+TinyMCE AI Error: No model selected+`. The send button was already disabled until a model was selected, but pressing Enter bypassed that check. + +In {productname} {release-version}, pressing Enter does nothing until a model is selected. The prompt text stays in the prompt field, no error appears, and the user can send the prompt once the models have loaded. + +==== Link sources in the AI Chat without an http or https scheme or a dotted hostname are now treated as invalid URLs +// #TINYMCE-14813 + +Previously, the **TinyMCE AI** plugin showed different errors for invalid links added with **Add context source** > **Link**. An empty value or plain text, such as `+test+`, showed _This URL isn't valid. Check the full, correct web address and try again._ A URL with an incomplete scheme or hostname, such as `+https://test+`, was sent to the AI service and failed with _Failed to add web resource "https://test": The web resource could not be scraped from the provided URL_. + +In {productname} {release-version}, the **TinyMCE AI** plugin accepts a link only when its URL uses the `+http+` or `+https+` scheme and has a hostname that contains a dot, such as `+example.com+`. Any other value shows _This URL isn't valid. Check the full, correct web address and try again._ and is not sent to the AI service. The same check applies to web resources returned by the xref:tinymceai.adoc#tinymceai_chat_fetch_source[`+tinymceai_chat_fetch_source+`] option, so URLs such as `+http://localhost+` are rejected. + +==== The chat actions button in the chat history now has an accessible name for screen readers +// #TINYMCE-14742 + +Previously, in the **TinyMCE AI** Chat history, the actions button on each conversation, which opens the **Pin**, **Rename**, and **Delete** options, had no accessible name. Screen readers announced it only as "button". + +In {productname} {release-version}, screen readers announce the button as "Chat actions", and announce each conversation in the history by its title and date. + +For information on the **TinyMCE AI** plugin, see: xref:tinymceai.adoc[TinyMCE AI]. + +=== Spell Checker + +The {productname} {release-version} release includes an accompanying release of the **Spell Checker** premium plugin. + +**Spell Checker** includes the following fixes. + +==== Moving the caret backwards with the keyboard lost its column position and jumped to the beginning of the line +// #TINYMCE-14832 + +Previously, when the **Spell Checker** plugin was active, pressing the Up Arrow key to move up through several lines could place the caret at the beginning of a line instead of keeping its column position. The same problem occurred when extending a selection upward with Shift+Up Arrow. + +In {productname} {release-version}, the **Spell Checker** plugin restores the selection only when spell checking changes the editor content. The caret keeps its column position when it moves up through lines, including when Shift+Up Arrow extends a selection. + +==== Disabling spell checking removed the misspelled word from a selection that started right before it +// #TINYMCE-14878 + +Previously, when spell checking as-you-type was enabled and a selection started or ended immediately before a misspelled word, disabling spell checking removed the misspelled word from the selection. Formatting applied to the selection afterward, such as bold, then skipped the misspelled word. + +In {productname} {release-version}, the **Spell Checker** plugin keeps the selection unchanged when spell checking is disabled. + +For information on the **Spell Checker** plugin, see: xref:introduction-to-tiny-spellchecker.adoc[Spell Checker]. + +=== PowerPaste + +The {productname} {release-version} release includes an accompanying release of the **PowerPaste** premium plugin. + +**PowerPaste** includes the following fixes. + +==== Pasting the same image more than once from HTML content, such as from another editor, created a separate blob URL for each copy instead of reusing the existing one +// #TINYMCE-11140 + +Previously, when a user pasted the same image more than once from HTML content, such as from another editor or a Microsoft Word document, the **PowerPaste** plugin created a new blob URL for each copy. The editor treated each copy as a separate image and uploaded each one. Without the **PowerPaste** plugin, copies of the same pasted image already shared one blob URL. + +In {productname} {release-version}, the **PowerPaste** plugin checks whether the editor contains an image with identical data. When the editor already contains a matching image, the plugin reuses the blob URL of that image. Copies of the same image now share one blob URL for every paste source. The editor uploads the image only once. + +==== Nested list items pasted from Google Docs with Keep formatting became bold when only the top-level list item was bold +// #TINYMCE-13282 + +Previously, when a user pasted a nested list from Google Docs and selected **Keep formatting**, the **PowerPaste** plugin made every nested list item bold, even when only the top-level list item was bold in the source document. The pasted list did not match the original document. Pasting with **Remove formatting** avoided the issue, but also removed the inline styles and classes from the pasted content. + +In {productname} {release-version}, the **PowerPaste** plugin keeps the font weight of each list item from the Google Docs content. When only the top-level list item is bold, the plugin pastes the nested list items with normal font weight, and the pasted list matches the original document. + +For information on the **PowerPaste** plugin, see: xref:introduction-to-powerpaste.adoc[PowerPaste]. + +=== Revision History + +The {productname} {release-version} release includes an accompanying release of the **Revision History** premium plugin. + +**Revision History** includes the following addition. + +==== New `+tags+` metadata field for displaying tags in revision cards +// #TINYMCE-14331 + +The revision xref:revisionhistory.adoc#metadata[`+metadata+`] object now supports an optional `+tags+` field. The `+tags+` field takes an array of xref:revisionhistory.adoc#tag[tag] objects, each with a `+label+` string. The **Revision History** plugin displays each tag as a label on the revision card, in the same style as the revision type label, such as `+DRAFT+`. The plugin displays the label text exactly as provided, without changes to capitalization. + +Integrators can use tags to mark saved revisions with a custom status, such as `+REVIEWED+` or `+Legal+`. + +For information on the **Revision History** plugin, see: xref:revisionhistory.adoc[Revision History]. + +=== Templates + +The {productname} {release-version} release includes an accompanying release of the **Templates** premium plugin. + +**Templates** includes the following fix. + +==== Bundled content CSS is now loaded in the template preview +// #TINYMCE-14363 + +Previously, when the editor content CSS was bundled, the **Templates** plugin did not load it into the template preview of the **Insert template** dialog. The preview loaded content CSS only from URLs, so it did not match the styling of the editor content. {productname} 8.4.0 fixed the same problem in the Preview dialog, the **Suggested Edits** view, and the **Revision History** view. + +In {productname} {release-version}, the **Templates** plugin adds bundled content CSS to the template preview, so the preview matches the editor content. Content CSS loaded from a URL works as before. For information on bundling content CSS, see xref:bundling-content-css.adoc[Bundling content CSS]. + +For information on the **Templates** plugin, see: xref:advanced-templates.adoc[Templates]. + + +[[accompanying-enhanced-skins-and-icon-packs-changes]] +== Accompanying Enhanced Skins & Icon Packs changes + +The {productname} {release-version} release includes an accompanying release of the **Enhanced Skins & Icon Packs**. + +=== Enhanced Skins & Icon Packs + +The **Enhanced Skins & Icon Packs** release includes the following updates: + +The **Enhanced Skins & Icon Packs** were rebuilt to pull in the changes also incorporated into the default {productname} {release-version} skin, Oxide. + +For information on using Enhanced Skins & Icon Packs, see: xref:enhanced-skins-and-icon-packs.adoc[Enhanced Skins & Icon Packs]. + + +[[additions]] +== Additions -[[removed]] -== Removed +{productname} {release-version} also includes the following addition: -{productname} {release-version} also includes the following removal: +=== Added the `+BlobInfo+` type to the public API +// #TINYMCE-14853 -=== -// #TINY-vwxyz1 +Previously, {productname} passed a `+BlobInfo+` object to the functions set for options such as xref:file-image-upload.adoc#images_upload_handler[`+images_upload_handler+`], but did not export the `+BlobInfo+` type. TypeScript integrations had to declare their own interface for the object. -// CCFR here. +In {productname} {release-version}, the `+BlobInfo+` type is part of the public {productname} API. TypeScript integrations can use it to type the functions they set for these options. [[bug-fixes]] == Bug fixes -{productname} {release-version} also includes the following bug fix: +{productname} {release-version} also includes the following bug fixes: -=== -// #TINY-vwxyz1 +=== The editor iframe was missing its `+title+` attribute on browsers other than Firefox +// #TINYMCE-13100 -// CCFR here. +Previously, {productname} set the `+title+` attribute on the editor iframe only in Firefox. In other browsers, the iframe had no `+title+`. {productname} applied the xref:accessibility.adoc#iframe_aria_text[`+iframe_aria_text+`] value as an `+aria-label+` on the `++` element inside the iframe instead. Screen readers announced the editor correctly, but accessibility checkers reported the missing iframe `+title+` as a violation of the Web Content Accessibility Guidelines (WCAG). +In {productname} {release-version}, the editor sets the `+title+` attribute of the iframe to the `+iframe_aria_text+` value in every browser. On macOS and iOS, the VoiceOver screen reader does not announce the iframe `+title+`. The editor therefore also sets the value as an `+aria-label+` on the `++` element, together with `+role="textbox"+` and `+aria-multiline="true"+`. On other operating systems, the editor no longer sets an `+aria-label+` on the `++` element. -[[security-fixes]] -== Security fixes +=== Drag selection did not work when clicking to the right of a list item in Chrome +// #TINYMCE-14855 -{productname} {release-version} includes : +Previously, in Chrome and other Chromium-based browsers, pressing the mouse button to the right of the text in a list item and dragging did not select any content. {productname} 8.7.0 added a workaround for a Chromium bug that placed the caret at the start of a list item when clicking to the right of its text. The workaround ran when the mouse button was pressed and blocked the default browser behavior, which also prevented drag selection. -=== -// #TINY-vwxyz1 +In {productname} {release-version}, the workaround runs when the click completes instead. Pressing the mouse button to the right of a list item and dragging selects content, and clicking to the right of a list item still places the caret where expected. -// CCFR here. +=== Clicking to the right of an `+ +` at the end of an element could make the selection jump when the content contained an empty formatting element +// #TINYMCE-14724 +Previously, when the content contained an empty formatting element, for example one left after a format such as a font size was applied with no text selected, clicking to the right of a line that ended in a non-breaking space (`+ +`) moved the caret away from the click position. {productname} removed the empty formatting element and placed the caret where that element had been, such as at the start of another paragraph. -[[deprecated]] -== Deprecated +In {productname} {release-version}, {productname} moves the caret only when the empty formatting element it removes is next to the selection. Clicking to the right of a line that ends in a non-breaking space places the caret at the end of that line. -{productname} {release-version} includes the following deprecation: +=== Opening or closing a view no longer scrolls the editor to the caret position +// #TINYMCE-14905 -=== The `` configuration property, ``, has been deprecated +Previously, opening or closing a view, such as a xref:custom-view.adoc[custom view] or the **Revision History** view, scrolled the editor content to the caret, even when the user had scrolled to a different part of the document. Users lost their place in the document each time a view was opened or closed, which was most noticeable when the caret was far outside the visible area. -// placeholder here. +In {productname} {release-version}, opening or closing a view keeps the editor scroll position. The editor still receives focus when a view closes, and the caret and selection do not change. +=== Clicking to the right of a list item's text in an unfocused editor scrolled the content back to the top in Chrome +// #TINYMCE-14856 -[[known-issues]] -== Known issues +Previously, in Chrome and other Chromium-based browsers, when the editor was not focused, scrolling down the editor content and clicking to the right of the text in a list item scrolled the content back to the top. The caret was placed in the list item, but the list item was no longer in view. -This section describes issues that users of {productname} {release-version} may encounter and possible workarounds for these issues. +In {productname} {release-version}, clicking to the right of the text in a list item in an unfocused editor keeps the scroll position and places the caret where the user clicked. -There known issue in {productname} {release-version}. +=== Applying a list style did not change the markers, and the toolbar showed the wrong active style, on list items that had their own inline `+list-style-type+` +// #TINYMCE-14565 -=== -// #TINY-vwxyz1 +Previously, some list items had their own inline `+list-style-type+`, for example after content was pasted from Microsoft Word with **PowerPaste**. When the selection was in such an item, choosing a style from the `+numlist+` or `+bullist+` toolbar button menu did not change the item's marker, because the item's own style overrode the style that {productname} applied to the list. The menu also showed **Default** as the active style instead of the item's actual style. -// CCFR here. +In {productname} {release-version}, the list style menu shows the style of the selected list item when the item has its own `+list-style-type+`. Applying a list style removes the inline `+list-style-type+` from the selected list items and applies the chosen style to the whole list. Other list items that have their own `+list-style-type+` keep it until they are selected and changed. diff --git a/modules/ROOT/pages/changelog.adoc b/modules/ROOT/pages/changelog.adoc index f0ee453563..1c8e3f7d7d 100644 --- a/modules/ROOT/pages/changelog.adoc +++ b/modules/ROOT/pages/changelog.adoc @@ -5,9 +5,31 @@ NOTE: This is the {productname} Community version changelog. For information about the latest {cloudname} or {enterpriseversion} Release, see: xref:release-notes.adoc[{productname} Release Notes]. -== xref:8.10.0-release-notes.adoc[8.10.0 - ] +== xref:8.10.0-release-notes.adoc[8.10.0 - 2026-10-14] -//TODO +### Added +* Added the `BlobInfo` type to the public API. +// #TINYMCE-14853 +* New `revert-all` icon. +// #TINYMCE-14851 + +### Fixed +* Applying a list style did not change the markers, and the toolbar showed the wrong active style, on list items that had their own inline `list-style-type`. +// #TINYMCE-14565 +* Clicking to the right of a list item's text in an unfocused editor scrolled the content back to the top in Chrome. +// #TINYMCE-14856 +* Drag selection wasn't working when clicking on the right of an `li` in Chrome. +// #TINYMCE-14855 +* Resizing an image would sometimes show a 0px ghost image +// #TINYMCE-14887 +* Clicking to the right of an `+ +` at the end of an element could make the selection jump if there is an empty element inside the editor. +// #TINYMCE-14724 +* Opening or closing a View no longer scrolls the editor to the caret position. +// #TINYMCE-14905 +* The editor iframe was missing its `title` attribute on browsers other than Firefox. +// #TINYMCE-13100 +* Views that keep the toolbar now also keep the statusbar visible. +// #TINYMCE-14920 == xref:8.9.3-release-notes.adoc[8.9.3 - 2026-10-06] diff --git a/modules/ROOT/pages/revisionhistory.adoc b/modules/ROOT/pages/revisionhistory.adoc index 16d0a897d8..d0f999d7c3 100644 --- a/modules/ROOT/pages/revisionhistory.adoc +++ b/modules/ROOT/pages/revisionhistory.adoc @@ -87,7 +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. +| `+metadata+` | xref:#metadata[Metadata] `+Object+` | optional | Additional information about the revision, such as whether it was AI-assisted and which tags appear on its revision card. |=== === Author @@ -110,8 +110,38 @@ The metadata is an `+Object+` that holds additional information about a revision |=== | 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 displays an AI badge on the revision card by default. Set xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] to `+false+` to hide the badge. +| `+tags+` | `+Array+` of xref:#tag[Tag] `+Object+` | optional | The tags that appear on the revision card. Each tag appears as a label in the same style as the revision type label, such as `+DRAFT+`. |=== +=== Tag + +The tag is an `+Object+` that represents a label displayed on a revision card. It contains the following fields: + +[cols="1,1,1,3",options="header"] +|=== +| Field | Type | Required? | Description +| `+label+` | `+string+` | required | The text of the tag. The plugin displays the text exactly as provided, without changes to capitalization. +|=== + +The following example defines a saved revision that has two tags: + +[source,js] +---- +const revision = { + revisionId: '3', + createdAt: '2026-10-14T10:11:21.578Z', + content: '

Approved content.

', + metadata: { + tags: [ + { label: 'REVIEWED' }, + { label: 'Legal' } + ] + } +}; +---- + +Tags appear only on `+saved+` revisions. The `+draft+` and `+initial+` revisions are generated from the editor's current content and do not carry `+metadata+`. See xref:#understanding-revision-types[Understanding revision types]. + == 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'+`, an AI badge appears on that revision card by default. Set xref:revisionhistory_ai_attribution[`+revisionhistory_ai_attribution+`] to `+false+` to hide the badge. diff --git a/modules/ROOT/pages/suggestededits.adoc b/modules/ROOT/pages/suggestededits.adoc index 569294d637..c7ecff39cd 100644 --- a/modules/ROOT/pages/suggestededits.adoc +++ b/modules/ROOT/pages/suggestededits.adoc @@ -21,7 +21,7 @@ include::partial$misc/bundling-guide-link.adoc[] == How it works -The {pluginname} plugin keeps track of every edit made to the document by the current user and stores this metadata in an internal model of the document. These suggestions can then be reviewed in the Review Edits view, where each edit is highlighted in the document, and where users can accept, reject, or provide feedback. The Review Edits view is accessible via either the `suggestededits` toolbar button or menu button within the `View` menu. +The {pluginname} plugin keeps track of every edit made to the document by the current user and stores this metadata in an internal model of the document. These suggestions can then be reviewed in the Review edits view, where each edit is highlighted in the document, and where users can accept, reject, or provide feedback. The Review edits view opens from either the `suggestededits` toolbar button or the `suggestededits` menu item in the `View` menu. == The model @@ -35,50 +35,79 @@ Alternatively the xref:#suggestededits_content[`+suggestededits_content+`] optio == Reviewing edits -The Review Edits view can be used to view and reviewing edits made by multiple authors. The available actions in this view depends on the xref:#suggestededits_access[`+suggestededits_access+` option]. +The Review edits view displays the edits made by multiple authors for review. The available actions in this view depend on the xref:#suggestededits_access[`+suggestededits_access+` option]. + +While the Review edits view is open, the editor menu bar, toolbar, and status bar remain visible, the editor content is read-only, and the editor can still be resized. Most toolbar buttons and menu items are disabled while the view is open. Items that work in any editor mode, such as Fullscreen, Preview, and Print, remain available. For details, see xref:context.adoc#built-in-contexts[Built-in contexts]. Opening a sidebar closes the Review edits view. Opening and closing the Review edits view keeps the current scroll position in the document. === Header -The view contains a few controls to manage the review process: +The header at the top of the sidebar shows the **Review edits** title and two buttons that end the review: + +* Save & Exit: Ends the review, applying resolved suggestions to the document. Unresolved suggestions remain in the document for future review. This button is disabled for users without `+full+` access. +* image:icons/close.svg[Exit review icon,24px] Exit review: Ends the review without applying resolved suggestions, and makes no change to the document. Feedback given on suggestions will be retained. + +The **Exit review** button displays only an icon. The text **Exit review** appears as a tooltip and as the accessible label of the button. + +=== Footer -* Show edits: Toggles whether suggested edits are shown. When hidden, the view shows what the document will look like if the review is completed. -* Complete review: Ends the review, applying resolved suggestions to the document. Unresolved suggestions remain in the document for future review. -* Cancel: Ignores any resolved suggestions and makes no change to the document. Feedback given on suggestions will be retained. +The footer below the document switches between two views: + +* Diff mode: Shows the suggested edits with the color coding described in xref:#document[Document]. While unresolved suggestions remain, Diff mode dims unchanged content so the unresolved suggestions stand out. Diff mode is the default view. +* Preview: Shows how the document reads with the suggested edits applied, taking accepted and rejected suggestions into account. Added and modified content is underlined, and removed content is hidden unless the suggestion is selected. === Document -The current editor document is displayed in a sandboxed iframe, with each suggested edit highlighted as they appear in the document. The following color coding is used to indicate the type of change: +The Review edits view displays the current editor document in an iframe, with each suggested edit highlighted where it appears in the document. + +In Diff mode, the following color coding is used to indicate the type of change: + +* Green: Added content. +* Blue: Modified attributes or formatting, such as bold or italic. +* Red: Removed content, shown with a strikethrough. -* Green: Added content. -* Blue: Modified attributes or formatting (e.g. bold, italic, etc.). -* Red: Removed content. +In Diff mode, removed images, videos, and embedded frames are also marked with a red X. Line break markers appear only where a line break was added or removed. -Replaced content is represented as both added and removed content, and indicates that some content was removed and replaced with new content in a single edit. When a suggestion is selected, whether in the document or in the sidebar, the corresponding highlighted suggestion in the document will be outlined in blue and scrolled into view. +Replaced content is represented as both added and removed content, and indicates that some content was removed and replaced with new content in a single edit. When a suggestion is selected, whether in the document or in the sidebar, the corresponding highlighted suggestion in the document will be outlined in blue and scrolled into view. In Diff mode, accepted and rejected suggestions show their result without highlighting, except while the suggestion is selected. Selecting anywhere outside a card or a suggestion clears the selection. === Sidebar -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. +Each suggested edit is listed as a card in the sidebar, in the order the edits appear in the document. The card header shows the user who made the suggestion and when the edit was made. Below the header, the card describes the edit and quotes the changed text, for example: Replaced "`the`" with "`them`". Long text is shortened with an ellipsis. Edits made with the xref:tinymceai.adoc[{productname} AI] plugin are recorded as AI-assisted. An AI badge appears on their cards by default. Set xref:#suggestededits_ai_attribution[`+suggestededits_ai_attribution+`] to `+false+` to hide the badge. -When selected, a suggestion can be handled in the following ways: +For users with `+full+` access, pointing to a card or selecting it shows the following buttons in the card header: * Accept: Resolves the suggestion, applying the edit to the document when the review is completed. * Reject: Resolves the suggestion, turning back the edit to the original state. -* Revert: Reverts the current "Accept" or "Reject" resolution on the suggestion. -* Provide feedback: Opens a text area for users to provide feedback on the suggestion. -Feedback is shown in chronological order beneath the card details when the card is selected. Feedback allows users to discuss suggestions before resolving them. The feedback author can edit or delete their own feedback, with the appropriate permissions in the xref:#suggestededits_access[`+suggestededits_access+`] option. +After a suggestion is accepted or rejected, the card header shows a **Revert** button with an icon that indicates the decision. Selecting **Revert** removes the decision and returns the suggestion to an unresolved state. + +When an unresolved suggestion is selected, users with `+feedback+` or `+full+` access can select **Provide feedback** to open a text area and provide feedback on the suggestion. + +Feedback is shown in chronological order beneath the card details when an unresolved card is selected. Feedback allows users to discuss suggestions before resolving them. The feedback author can edit or delete their own feedback, with the appropriate permissions in the xref:#suggestededits_access[`+suggestededits_access+`] option. + +==== Bulk actions + +Users with `+full+` access can use the **Bulk actions** menu at the top of the sidebar to resolve several suggestions at once: + +* Accept all: Accepts every unresolved suggestion. Suggestions that are already accepted or rejected keep their decision. While some suggestions are resolved and others remain unresolved, this item is labeled **Accept remaining**. +* Reject all: Rejects every unresolved suggestion. Suggestions that are already accepted or rejected keep their decision. While some suggestions are resolved and others remain unresolved, this item is labeled **Reject remaining**. +* Revert all: Returns every accepted or rejected suggestion to an unresolved state. + +The accept and reject items are unavailable when no unresolved suggestions remain. **Revert all** is unavailable until at least one suggestion is resolved. + +=== Keyboard navigation -At the top of the sidebar there is a dropdown menu to apply review actions in bulk to all suggested edits: +The Review edits view supports the following keys: -* Accept all. -* Reject all. -* Revert all. +* Tab and Shift+Tab: Move focus between the buttons in the sidebar header, the **Bulk actions** menu, and the cards. +* Up Arrow and Down Arrow: Move between cards and select the focused suggestion. +* Enter: Moves focus into the content of the focused card. +* Escape: Moves focus to the **Exit review** button. When **Exit review** already has focus, Escape ends the review. === Finishing a review -When completing a review, resolved suggestions will be applied to the document and will no longer be tracked in the model as a suggestion. Feedback on resolved suggestions is discarded. Any "accepted" edits will remain in the document, and any "rejected" edits will be reverted to the state before the suggestion was made. +When a review is completed with **Save & Exit**, resolved suggestions will be applied to the document and will no longer be tracked in the model as a suggestion. Feedback on resolved suggestions is discarded. Any "accepted" edits will remain in the document, and any "rejected" edits will be reverted to the state before the suggestion was made. Review actions will apply the following to the document: @@ -97,7 +126,7 @@ When removed content is: * Accepted: The content will be removed from the document. * Rejected: The removed content will be restored to the document. -If a review is canceled, no resolved suggestions will be applied to the document. All suggestions, including any feedback provided during that review session, will remain stored in the model. +If a review ends with **Exit review**, no resolved suggestions will be applied to the document. All suggestions, including any feedback provided during that review session, will remain stored in the model. == Initial setup diff --git a/modules/ROOT/pages/tinymceai-actions.adoc b/modules/ROOT/pages/tinymceai-actions.adoc index bad22cd5aa..5078a74be7 100644 --- a/modules/ROOT/pages/tinymceai-actions.adoc +++ b/modules/ROOT/pages/tinymceai-actions.adoc @@ -298,3 +298,4 @@ The https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] reference (in * xref:tinymceai-chat.adoc[AI Chat]: For interactive discussions with document analysis and context. * xref:tinymceai-review.adoc[AI Review]: For content quality analysis and improvement suggestions. +* xref:tinymceai-multi-editor.adoc[Multi-editor mode]: For sharing Chat, Review, and Quick Actions across several editors on one page. diff --git a/modules/ROOT/pages/tinymceai-chat.adoc b/modules/ROOT/pages/tinymceai-chat.adoc index e110299faa..ba69e993bb 100644 --- a/modules/ROOT/pages/tinymceai-chat.adoc +++ b/modules/ROOT/pages/tinymceai-chat.adoc @@ -287,3 +287,4 @@ The https://tinymceai.api.tiny.cloud/docs[interactive API documentation] lists e * xref:tinymceai-review.adoc[AI Review]: For content quality analysis and improvement suggestions. * xref:tinymceai-actions.adoc[Quick actions]: For fast, stateless content transformations. +* xref:tinymceai-multi-editor.adoc[Multi-editor mode]: For sharing Chat, Review, and Quick Actions across several editors on one page. diff --git a/modules/ROOT/pages/tinymceai-multi-editor.adoc b/modules/ROOT/pages/tinymceai-multi-editor.adoc new file mode 100644 index 0000000000..417a9fd0fd --- /dev/null +++ b/modules/ROOT/pages/tinymceai-multi-editor.adoc @@ -0,0 +1,134 @@ += TinyMCE AI multi-editor mode +:navtitle: Multi-editor mode +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: Group several editors on one page so that they share TinyMCE AI Chat, Review, and Quick Actions +:description_short: multi-editor mode +:keywords: AI, multi-editor, multiple editors, group, tinymceai + +include::partial$misc/admon-requires-8.10v.adoc[] + +Multi-editor mode groups several {productname} editors on the same page so that they share one Chat sidebar and one Review sidebar. Use multi-editor mode when a page splits related content across several editors, for example a form with separate editors for a summary and a body, or a page that edits several related articles side by side. + +In a group, Chat, Review, and Quick Actions work across the content of every editor. The {pluginname} plugin identifies the content of each editor by name, and previews and applies each change in the editor it belongs to. + +[[demo]] +== Demo + +The demo below splits an article across an Introduction editor and a Body editor in one group. Select the image:icons-premium/ai-assistant.svg[Chat icon,24px] Chat toolbar button in either editor to open the shared Chat sidebar, which the first editor hosts. Then ask the AI to change both parts of the article, or run a review over both editors. + +liveDemo::tinymceai-multi-editor[] + +include::partial$misc/admon-inline-not-supported.adoc[] + +[[how-grouped-editors-work]] +== How grouped editors work + +[[shared-sidebar]] +=== Shared sidebar + +The first editor of the group to be created hosts the shared Chat sidebar and Review sidebar. The Chat and Review toolbar buttons and menu items in every other editor of the group open, close, and focus that shared sidebar. + +[[chat]] +=== Chat + +By default, each chat prompt includes the content of every editor in the group. Each editor appears above the prompt as a context tag labeled with its xref:tinymceai.adoc#tinymceai_document_name[`+tinymceai_document_name+`] value, for example image:tinymceai/tinymceai-context-tag.png[Body context tag] for an editor named `+Body+`. + +Users can change which editors the AI works with: + +* Removing a context tag leaves the content of that editor out of the prompt, and the AI does not change that editor. +* The **Add context source** menu lists every editor in the group and adds a removed editor back. + +After a message is sent, the editors included in that message stay in the conversation and their context tags cannot be removed until the user starts a new conversation. Editors that were left out can still be added from the **Add context source** menu at any point in the conversation. + +The AI can change the content of any editor in the conversation, and the plugin previews and applies each change in the editor it belongs to. To direct a request at the content of one editor, name that content in the prompt, for example _"Shorten the Introduction"_. For more information about chat, see xref:tinymceai-chat.adoc[Chat]. + +[[review]] +=== Review + +A review analyzes the content of every editor in the group. The Review sidebar groups suggestions under the name of the editor they belong to and shows the number of pending suggestions in each group. A review always covers the whole group. For more information about reviews, see xref:tinymceai-review.adoc[Review]. + +[[quick-actions]] +=== Quick Actions + +Users can run a Quick Action from any editor in the group. What the Quick Action changes depends on whether text is selected in that editor: + +* With text selected, the Quick Action changes only the selected text in that editor. +* With no text selected, the Quick Action changes the whole content of every editor in the group and ignores any text selected in the other editors. For example, running **Translate** with no text selected translates every editor in the group. + +Chat actions, such as **Explain**, **Summarize**, and **Highlight key points**, open the shared Chat sidebar and start a conversation that includes every editor in the group, as described in xref:#chat[Chat]. For more information about Quick Actions, see xref:tinymceai-actions.adoc[Quick Actions]. + +[[previewing-and-applying-changes]] +=== Previewing and applying changes + +While the {pluginname} plugin previews changes from Chat or Quick Actions, each affected editor shows its own preview and is read-only. The whole group shares one change toolbar: + +* The change counter covers the changes in every editor of the group. +* The next and previous buttons move between changes across editors. +* Selecting a change in any editor moves the change toolbar to that change. +* Accepting or rejecting a change applies it to the editor that holds the change. + +[[discarding-suggestions]] +=== Discarding pending suggestions + +When any editor in the group has pending suggestions, the {pluginname} plugin asks for confirmation before it discards them and starts a different AI task. For example, the confirmation dialog appears when the user switches between the Chat sidebar and the Review sidebar, or runs a Quick Action while a review has pending suggestions. + +If the user confirms, the plugin discards the pending suggestions in every editor of the group and returns each editor to normal editing. If the user cancels, the plugin keeps every preview and pending suggestion. + +[[integration]] +== Integration + +To group editors, load the `+tinymceai+` plugin in each editor and set the same xref:tinymceai.adoc#tinymceai_group[`+tinymceai_group+`] value on each editor in the group. Give each editor a unique xref:tinymceai.adoc#tinymceai_document_name[`+tinymceai_document_name+`] value, and optionally a xref:tinymceai.adoc#tinymceai_document_description[`+tinymceai_document_description+`] value that describes the content to the AI. + +Multi-editor mode is supported with the floating sidebar. Set xref:tinymceai.adoc#tinymceai_sidebar_type[`+tinymceai_sidebar_type+`] to `+'floating'+` for every editor in the group. + +Use the same {pluginname} configuration for every editor in a group, for example by sharing a settings object between the `+tinymce.init+` calls: + +[source,js] +---- +const sharedSettings = { + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_sidebar_type: 'floating', + tinymceai_group: 'article', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}; + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#introduction', // change this value according to the HTML + tinymceai_document_name: 'Introduction', + tinymceai_document_description: 'The introduction of the article. A short paragraph that sets out the topic and hooks the reader.' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#body', // change this value according to the HTML + tinymceai_document_name: 'Body', + tinymceai_document_description: 'The main body of the article. Uses h2 subheadings and short paragraphs.' +}); +---- + +Grouped editors must be on the same page and use the same `+tinymce+` instance. Set xref:tinymceai.adoc#tinymceai_group[`+tinymceai_group+`] in the initial configuration of each editor. + +For information about installing the plugin and enabling AI features, see xref:tinymceai.adoc[Plugin Reference]. + +[[multiple-groups]] +=== Multiple groups on one page + +A page can contain several independent groups, each with a different xref:tinymceai.adoc#tinymceai_group[`+tinymceai_group+`] value. Each group has its own shared sidebar, and an editor in one group never receives the content of an editor in another group. For a configuration with two groups, see the xref:tinymceai.adoc#tinymceai_group[two-group example]. + +[[configuration]] +== Configuration + +For the options that configure multi-editor mode, see xref:tinymceai.adoc#options-multi-editor[Options for multi-editor mode]. + +[[related-features]] +== Related features + +* xref:tinymceai-chat.adoc[AI Chat]: For interactive discussions with document analysis and context. +* xref:tinymceai-review.adoc[AI Review]: For content quality analysis and improvement suggestions. +* xref:tinymceai-actions.adoc[Quick Actions]: For fast, stateless content transformations. diff --git a/modules/ROOT/pages/tinymceai-review.adoc b/modules/ROOT/pages/tinymceai-review.adoc index 2ceef933e9..738f1db662 100644 --- a/modules/ROOT/pages/tinymceai-review.adoc +++ b/modules/ROOT/pages/tinymceai-review.adoc @@ -134,3 +134,4 @@ The https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] reference (in * xref:tinymceai-chat.adoc[AI chat]: For interactive discussions with document analysis and context. * xref:tinymceai-actions.adoc[Quick actions]: Shortcuts to individual AI operations on a selection or range (transformations, translation, chat, and custom actions). +* xref:tinymceai-multi-editor.adoc[Multi-editor mode]: For sharing Chat, Review, and Quick Actions across several editors on one page. diff --git a/modules/ROOT/partials/commands/suggestededits-cmds.adoc b/modules/ROOT/partials/commands/suggestededits-cmds.adoc index 4a6f353caf..4ab3cf89bb 100644 --- a/modules/ROOT/partials/commands/suggestededits-cmds.adoc +++ b/modules/ROOT/partials/commands/suggestededits-cmds.adoc @@ -1,7 +1,7 @@ [cols="1,3",options="header"] |=== |Command |Description -|suggestededits |Toggles the Suggested Edits view. +|suggestededits |Opens the Review edits view, or closes it without applying resolved suggestions if it is already open. The view opens only when there are suggestions to review and the user has at least `'read'` access. |suggestededitsToggleTracking |Toggles the tracking of suggested edits. |=== diff --git a/modules/ROOT/partials/configuration/icon_list.adoc b/modules/ROOT/partials/configuration/icon_list.adoc index 8ef810d54b..95ca510ff6 100644 --- a/modules/ROOT/partials/configuration/icon_list.adoc +++ b/modules/ROOT/partials/configuration/icon_list.adoc @@ -166,6 +166,7 @@ | `+resize-handle+` | image:icons/resize-handle.svg[resize-handle.svg] | `+resize-handle.svg+` | `+resize+` | image:icons/resize.svg[resize.svg] | `+resize.svg+` | `+restore-draft+` | image:icons/restore-draft.svg[restore-draft.svg] | `+restore-draft.svg+` +| `+revert-all+` | image:icons/revert-all.svg[revert-all.svg] | `+revert-all.svg+` | `+revert-changes+` | image:icons/revert-changes.svg[revert-changes.svg] | `+revert-changes.svg+` | `+revision-history+` | image:icons/revision-history.svg[revision-history.svg] | `+revision-history.svg+` | `+rotate-left+` | image:icons/rotate-left.svg[rotate-left.svg] | `+rotate-left.svg+` diff --git a/modules/ROOT/partials/configuration/iframe_aria_text.adoc b/modules/ROOT/partials/configuration/iframe_aria_text.adoc index 6eeb7d34e6..3f6edfe34a 100644 --- a/modules/ROOT/partials/configuration/iframe_aria_text.adoc +++ b/modules/ROOT/partials/configuration/iframe_aria_text.adoc @@ -1,13 +1,21 @@ [[iframe_aria_text]] == `+iframe_aria_text+` -This option sets the accessible name for the editable content area inside the {productname} `+iframe+`. The value is read by screen readers to help users identify the editor. +This option sets the accessible name for the {productname} `+iframe+` and its editable content area. The value is read by screen readers to help users identify the editor. -On most browsers, the value is applied as an `+aria-label+` on the `++` element inside the iframe document. For example: +{productname} applies the value as follows: + +* **All operating systems**: {productname} sets the value as the `+title+` attribute of the iframe element. +* **macOS and iOS**: {productname} also sets the value as an `+aria-label+` on the `++` element inside the iframe document, together with `+role="textbox"+` and `+aria-multiline="true"+`. The VoiceOver screen reader does not announce the iframe `+title+`, so the `++` element carries the accessible name on these operating systems. + +For example, on macOS: [source,html] ---- - + ---- This option only applies to {productname} classic (iframe) mode and has no effect on xref:inline-editor-options.adoc#inline[`+inline+` editors]. @@ -26,12 +34,4 @@ tinymce.init({ selector: 'textarea', // change this value according to your HTML iframe_aria_text: 'Text Editor' }); ----- - -[NOTE] -==== -The `+iframe_aria_text+` option is applied differently depending on the browser to ensure consistent screen reader announcements: - -* **Firefox**: The `+title+` attribute is set on the iframe element. The `+aria-label+` on the body is not set. -* **Other browsers**: The `+aria-label+` is set on the body inside the iframe. The `+title+` is not set on the iframe. -==== \ No newline at end of file +---- \ No newline at end of file diff --git a/modules/ROOT/partials/configuration/suggestededits_access.adoc b/modules/ROOT/partials/configuration/suggestededits_access.adoc index af385f9974..be829e8ac0 100644 --- a/modules/ROOT/partials/configuration/suggestededits_access.adoc +++ b/modules/ROOT/partials/configuration/suggestededits_access.adoc @@ -1,14 +1,14 @@ [[suggestededits_access]] == `suggestededits_access` -The `suggestededits_access` option determines the level of access a user has to the {pluginname} view. This setting is crucial for controlling who can accept or reject suggestions, add feedback, or view suggestions in read-only mode. The `suggestededits_access` option does not control access to the editor content, however when used in conjunction with the xref:editor-important-options#readonly[`readonly`] option it allows for fine-grained control over user permissions. +The `suggestededits_access` option determines the level of access a user has to the Review edits view. This setting is crucial for controlling who can accept or reject suggestions, add feedback, or view suggestions in read-only mode. The `suggestededits_access` option does not control access to the editor content, however when used in conjunction with the xref:editor-important-options#readonly[`readonly`] option it allows for fine-grained control over user permissions. When set to: -* `'full'`: The user has full access to the {pluginname} view, with permission to accept or reject suggestions. -* `'feedback'`: The user has access to the {pluginname} view, with permission to add feedback to suggestions. -* `'read'`: The user has read-only access to the {pluginname} view. -* `'none'`: The user has no access to the {pluginname} view. +* `'full'`: The user has full access to the Review edits view, with permission to accept or reject suggestions, use the **Bulk actions** menu, and complete the review with **Save & Exit**. +* `'feedback'`: The user has access to the Review edits view, with permission to add feedback to suggestions. The **Save & Exit** button is disabled. +* `'read'`: The user has read-only access to the Review edits view. The **Save & Exit** button is disabled. +* `'none'`: The user has no access to the Review edits view. The `suggestededits` toolbar button and menu item are unavailable. *Type:* `+String+` @@ -23,7 +23,7 @@ tinymce.init({ selector: 'textarea#suggestededits', // Change this value according to your HTML plugins: 'suggestededits', toolbar: 'suggestededits', - suggestededits_access: 'feedback', // Change this value to set the {pluginname} view permissions + suggestededits_access: 'feedback', // Change this value to set the Review edits view permissions readonly: false // Set to true to restrict editing }); ---- @@ -37,7 +37,7 @@ tinymce.init({ selector: 'textarea#suggestededits', // Change this value according to your HTML plugins: 'suggestededits', toolbar: 'suggestededits', - suggestededits_access: 'read', // Change this value to set the {pluginname} view permissions + suggestededits_access: 'read', // Change this value to set the Review edits view permissions readonly: false // Set to true to restrict editing }); ---- diff --git a/modules/ROOT/partials/configuration/tinymceai_options.adoc b/modules/ROOT/partials/configuration/tinymceai_options.adoc index 73902da544..b1664d75ae 100644 --- a/modules/ROOT/partials/configuration/tinymceai_options.adoc +++ b/modules/ROOT/partials/configuration/tinymceai_options.adoc @@ -847,3 +847,136 @@ tinymceai_reviews: [ ] ---- +[[options-multi-editor]] +== Options for multi-editor mode + +These options group several editors on the same page so that they share one Chat sidebar and one Review sidebar, and Chat, Review, and Quick Actions work across the content of every editor in the group. The options also identify the content of each editor to users and to the AI service. For a description of how grouped editors work, see xref:tinymceai-multi-editor.adoc[Multi-editor mode]. + +include::partial$misc/admon-requires-8.10v.adoc[] + +[[tinymceai_group]] +=== `+tinymceai_group+` + +Adds the editor to a named group. Editors on the same page with the same `+tinymceai_group+` value share one Chat sidebar and one Review sidebar. In a group, Chat, Review, and Quick Actions work across the content of every editor. The editor created first in the group hosts the shared sidebars. + +The plugin uses the group name only to match editors, and never shows the name to users or sends it to the AI service. A page can contain several independent groups, each with a different name. Editors in one group never receive content from another group. + +An editor without this option does not belong to any group. It has its own Chat sidebar and Review sidebar, and works only with its own content, even when other editors on the same page belong to a group. + +For more details and a live demo, see xref:tinymceai-multi-editor.adoc[Multi-editor mode]. + +*Type:* `+String+` + +*Default value:* `+undefined+` + +.Example: two independent groups on one page +[source,js] +---- +const sharedSettings = { + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_sidebar_type: 'floating', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}; + +// Group "article": the introduction and body editors share one AI sidebar. +tinymce.init({ + ...sharedSettings, + selector: 'textarea#introduction', // change this value according to the HTML + tinymceai_group: 'article' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#body', // change this value according to the HTML + tinymceai_group: 'article' +}); + +// Group "notes": a separate AI sidebar that never receives the content of the "article" group. +tinymce.init({ + ...sharedSettings, + selector: 'textarea#research-notes', // change this value according to the HTML + tinymceai_group: 'notes' +}); + +tinymce.init({ + ...sharedSettings, + selector: 'textarea#review-notes', // change this value according to the HTML + tinymceai_group: 'notes' +}); +---- + +[NOTE] +==== +Set this option in the initial configuration of the editor. Changing this option after the editor initializes is not supported. +==== + +[[tinymceai_document_name]] +=== `+tinymceai_document_name+` + +The name of the content in the editor. The {pluginname} plugin uses this name to: + +* Label the content of the editor in the Chat sidebar, including the context tags of a prompt and the chat history. +* Label the group of suggestions for the editor in the Review sidebar. +* Name the content that the plugin sends to the AI service with a chat prompt, so that the AI can refer to it and tell it apart from the content of other editors. +* Match each editor to its content when a user resumes a conversation from the chat history. + +When this option is not set, the plugin uses the editor ID as the name, for example `+mce_0+` or the ID of the target element. Set a descriptive name for each editor in a group, because an editor ID does not identify the content to users or to the AI service. + +The plugin removes leading and trailing whitespace from the value. A value that is empty or longer than 255 characters is not valid. When the value is not valid, {productname} logs a warning to the browser console and the plugin uses the editor ID instead. + +*Type:* `+String+` + +*Default value:* `+undefined+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_group: 'report', + tinymceai_document_name: 'Executive summary', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- + +[IMPORTANT] +==== +Give each editor in a group a unique name, and keep each name the same across page loads. When a user resumes a conversation from the chat history, the plugin matches the stored content to editors by name. If two editors in a group share a name, the plugin can match content to the wrong editor. If a name changes, the plugin no longer matches conversations saved with the previous name to that editor. +==== + +[[tinymceai_document_description]] +=== `+tinymceai_document_description+` + +A short description of the content in the editor, such as its purpose, format, length limits, or audience. The {pluginname} plugin sends the description to the AI service with the content of the editor when a user submits a chat prompt. The AI uses the description as additional context, for example to keep a title short or to apply a change only to the relevant content. + +Users do not see the description. + +*Type:* `+String+` + +*Default value:* `+undefined+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_group: 'blog-post', + tinymceai_document_name: 'Blog post body', + tinymceai_document_description: 'The main body of the blog post. Uses h2 subheadings and short paragraphs.', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- diff --git a/modules/ROOT/partials/events/suggestededits-events.adoc b/modules/ROOT/partials/events/suggestededits-events.adoc index 48233cabc1..b217420927 100644 --- a/modules/ROOT/partials/events/suggestededits-events.adoc +++ b/modules/ROOT/partials/events/suggestededits-events.adoc @@ -3,9 +3,9 @@ The following events are provided by the xref:{plugincode}.adoc[{pluginname} plu [cols="2,1,3",options="header"] |=== |Name |Data |Description -|SuggestedEditsBeginReview |N/A |The Suggested Edits view has opened. -|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. +|SuggestedEditsBeginReview |N/A |The Review edits view has opened. +|SuggestedEditsReviewComplete |N/A |A review in the Review edits view has been completed with **Save & Exit**. +|SuggestedEditsReviewCancelled |N/A |A review in the Review edits view ended without applying resolved suggestions. This event fires when the user selects **Exit review**, when the review closes through the `suggestededits` toolbar button, menu item, or command, when a sidebar opens, and when the editor mode changes. It also fires when the `suggestededits` command runs and there are no suggestions to review. |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 f6c9324b04..b9e7045166 100644 --- a/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc +++ b/modules/ROOT/partials/menu-item-ids/suggestededits-menu-items.adoc @@ -2,6 +2,6 @@ |=== |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` |View |Opens the Review 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/admon-requires-8.10v.adoc b/modules/ROOT/partials/misc/admon-requires-8.10v.adoc new file mode 100644 index 0000000000..8cfaa251e1 --- /dev/null +++ b/modules/ROOT/partials/misc/admon-requires-8.10v.adoc @@ -0,0 +1 @@ +NOTE: This feature is only available for {productname} 8.10 and later. diff --git a/modules/ROOT/partials/misc/supported-versions.adoc b/modules/ROOT/partials/misc/supported-versions.adoc index b555fa4bd1..2bd0ee1343 100644 --- a/modules/ROOT/partials/misc/supported-versions.adoc +++ b/modules/ROOT/partials/misc/supported-versions.adoc @@ -6,7 +6,7 @@ Supported versions of {productname}: [cols="^,^,^",options="header"] |=== |Version |Release Date |End of Premium Support -|8.10 | | +|8.10 |2026-10-14 |2028-04-14 |8.9 |2026-08-31 |2028-03-01 |8.8 |2026-07-15 |2028-01-15 |8.7 |2026-06-30 |2027-12-30