diff --git a/.api-version b/.api-version index 9246c4f01e..9da0a092a0 100644 --- a/.api-version +++ b/.api-version @@ -1 +1 @@ -8.3.2 \ No newline at end of file +8.4.0 \ No newline at end of file diff --git a/antora.yml b/antora.yml index 19b9629b75..dd2adb93de 100644 --- a/antora.yml +++ b/antora.yml @@ -10,7 +10,7 @@ asciidoc: companyurl: https://www.tiny.cloud cdnurl: https://cdn.tiny.cloud/1/no-api-key/tinymce/8/tinymce.min.js tdcdnurl: https://cdn.tiny.cloud/1/_your_api_key_/tinydrive/8/tinydrive.min.js - tinymce_live_demo_url: https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/8/tinymce.min.js + tinymce_live_demo_url: https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/8-testing/tinymce.min.js tinydrive_live_demo_url: https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinydrive/8/tinydrive.min.js webcomponent_url: https://cdn.jsdelivr.net/npm/@tinymce/tinymce-webcomponent/dist/tinymce-webcomponent.min.js jquery_url: https://cdn.jsdelivr.net/npm/@tinymce/tinymce-jquery@2/dist/tinymce-jquery.min.js @@ -22,11 +22,13 @@ asciidoc: dockerimageexporttopdf: registry.containers.tiny.cloud/pdf-converter-tiny dockerimageexporttopdfwindows: registry.containers.tiny.cloud/pdf-converter-windows-tiny # document converter placeholder variables - exportpdf_service_url: exportpdf_service_url placeholder + exportpdf_service_url: exportpdf_service_url placeholder + # TinyMCE AI demo API key + tinymceai_demo_api_key: qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc # product variables productname: TinyMCE productmajorversion: 8 - productminorversion: '8.3' + productminorversion: '8.4' ##### product name in codeblock prodnamecode: tinymce #### more names diff --git a/modules/ROOT/examples/live-demos/custom-view/index.js b/modules/ROOT/examples/live-demos/custom-view/index.js index 98e3a4e322..58b4a3b0d2 100644 --- a/modules/ROOT/examples/live-demos/custom-view/index.js +++ b/modules/ROOT/examples/live-demos/custom-view/index.js @@ -19,7 +19,7 @@ tinymce.init({ text: 'Save code', buttonType: 'primary', onAction: () => { - const codeContent = document.querySelector('.tox-view__pane_panel').value; + const codeContent = document.querySelector('.my-textarea').value; ed.setContent(codeContent); ed.execCommand('ToggleView', false, 'code'); console.log('save'); @@ -28,12 +28,12 @@ tinymce.init({ ], onShow: (api) => { const editorContent = ed.getContent(); - api.getContainer().innerHTML = ` + const container = api.getContainer(); + container.innerHTML = `
- -
`.replace(/\s+/g, ''); + + `; + container.querySelector('.my-textarea').value = editorContent; }, onHide: (api) => { console.log('Deactivate code', api.getContainer()); diff --git a/modules/ROOT/examples/live-demos/exportpdf-v2/index.html b/modules/ROOT/examples/live-demos/exportpdf-v2/index.html new file mode 100644 index 0000000000..d016fa3b9e --- /dev/null +++ b/modules/ROOT/examples/live-demos/exportpdf-v2/index.html @@ -0,0 +1,78 @@ + diff --git a/modules/ROOT/examples/live-demos/exportpdf-v2/index.js b/modules/ROOT/examples/live-demos/exportpdf-v2/index.js new file mode 100644 index 0000000000..68fac1e295 --- /dev/null +++ b/modules/ROOT/examples/live-demos/exportpdf-v2/index.js @@ -0,0 +1,31 @@ +tinymce.init({ + selector: 'textarea#exportpdf-v2', + height: '800px', + plugins: [ + "exportpdf", "advlist", "anchor", "autolink", "charmap", "code", "codesample", "fullscreen", + "help", "image", "insertdatetime", "link", "lists", "media", + "preview", "searchreplace", "table", "visualblocks", + ], + toolbar: "undo redo | exportpdf | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", + image_caption: true, + exportpdf_converter_options: { + version: '2', + document: { + size: 'A4', + orientation: 'portrait', + margins: { + top: '1in', + right: '1in', + bottom: '1in', + left: '1in', + enable_mirror_margins: true + } + }, + metadata: { + title: 'Streamline LMS Overview', + author: 'TinyMCE', + subject: 'Learning Management System', + keywords: [ 'LMS', 'education', 'Streamline' ] + } + } +}); diff --git a/modules/ROOT/examples/live-demos/exportpdf/index.html b/modules/ROOT/examples/live-demos/exportpdf/index.html index 6dd3537e02..e7b61713bd 100644 --- a/modules/ROOT/examples/live-demos/exportpdf/index.html +++ b/modules/ROOT/examples/live-demos/exportpdf/index.html @@ -1,10 +1,13 @@ - \ No newline at end of file + + +
+

Nested format (v2)

+ +
+ diff --git a/modules/ROOT/examples/live-demos/exportpdf/index.js b/modules/ROOT/examples/live-demos/exportpdf/index.js index 04bec75035..c5de2fc6d7 100644 --- a/modules/ROOT/examples/live-demos/exportpdf/index.js +++ b/modules/ROOT/examples/live-demos/exportpdf/index.js @@ -1,5 +1,5 @@ tinymce.init({ - selector: 'textarea#exportpdf', + selector: 'textarea.exportpdf-flat', height: '800px', plugins: [ "exportpdf", "advlist", "anchor", "autolink", "charmap", "code", "codesample", "fullscreen", @@ -16,3 +16,35 @@ tinymce.init({ margin_left: '1in' } }); + +tinymce.init({ + selector: 'textarea.exportpdf-nested', + height: '800px', + plugins: [ + "exportpdf", "advlist", "anchor", "autolink", "charmap", "code", "codesample", "fullscreen", + "help", "image", "insertdatetime", "link", "lists", "media", + "preview", "searchreplace", "table", "visualblocks", + ], + toolbar: "undo redo | exportpdf | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", + image_caption: true, + exportpdf_converter_options: { + version: '2', + document: { + size: 'A4', + orientation: 'portrait', + margins: { + top: '1in', + right: '1in', + bottom: '1in', + left: '1in', + enable_mirror_margins: true + } + }, + metadata: { + title: 'Streamline LMS Overview', + author: 'TinyMCE', + subject: 'Learning Management System', + keywords: [ 'LMS', 'education', 'Streamline' ] + } + } +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-actions/example.js b/modules/ROOT/examples/live-demos/tinymceai-actions/example.js new file mode 100644 index 0000000000..ec14b3e82e --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-actions/example.js @@ -0,0 +1,51 @@ +// Step 1: Set up session - this should be part of the application's user management process. +// Open-source plugins below are only for editing the demo HTML (lists, links, tables). TinyMCE AI options are the focus. +tinymce.init({ + selector: 'textarea#tinymceai-actions', + height: '800px', + plugins: ['tinymceai', 'advlist', 'lists', 'link', 'autolink', 'table', 'wordcount'], + toolbar: 'undo redo | tinymceai-chat tinymceai-review tinymceai-quickactions | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link', + sidebar_show: 'tinymceai-chat', + tinymceai_token_provider: async () => { + return fetch('/api/tinymceai-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' }, + ] +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-actions/index.html b/modules/ROOT/examples/live-demos/tinymceai-actions/index.html new file mode 100644 index 0000000000..d87b06b4b2 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-actions/index.html @@ -0,0 +1,57 @@ + diff --git a/modules/ROOT/examples/live-demos/tinymceai-actions/index.js b/modules/ROOT/examples/live-demos/tinymceai-actions/index.js new file mode 100644 index 0000000000..9805514c6a --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-actions/index.js @@ -0,0 +1,112 @@ +// 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 })))); + +tinymce.init({ + selector: 'textarea#tinymceai-actions', + height: '800px', + 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 tinymceai-quickactions spellchecker | styles | bold italic underline forecolor backcolor casechange | link uploadcare table addcomment | align bullist numlist checklist removeformat | code fullscreen help', + quickbars_selection_toolbar: 'tinymceai-quickactions addcomment', + sidebar_show: 'tinymceai-chat', + 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_fetch: () => { + const textarea = document.querySelector('textarea#tinymceai-actions'); + 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))); + }, + revisionhistory_display_author: true, + tinymceai_token_provider: async () => { + 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' }, + ] +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-review/example.js b/modules/ROOT/examples/live-demos/tinymceai-review/example.js new file mode 100644 index 0000000000..50026f355c --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-review/example.js @@ -0,0 +1,51 @@ +// Step 1: Set up session - this should be part of the application's user management process. +// Open-source plugins below are only for editing the demo HTML (lists, links, tables). TinyMCE AI options are the focus. +tinymce.init({ + selector: 'textarea#tinymceai-review', + height: '800px', + plugins: ['tinymceai', 'advlist', 'lists', 'link', 'autolink', 'table', 'wordcount'], + toolbar: 'undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link', + sidebar_show: 'tinymceai-review', + tinymceai_token_provider: async () => { + return fetch('/api/tinymceai-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' }, + ] +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai-review/index.html b/modules/ROOT/examples/live-demos/tinymceai-review/index.html new file mode 100644 index 0000000000..700264f2ff --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-review/index.html @@ -0,0 +1,57 @@ + diff --git a/modules/ROOT/examples/live-demos/tinymceai-review/index.js b/modules/ROOT/examples/live-demos/tinymceai-review/index.js new file mode 100644 index 0000000000..97e111b5af --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai-review/index.js @@ -0,0 +1,112 @@ +// 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 })))); + +tinymce.init({ + selector: 'textarea#tinymceai-review', + height: '800px', + 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 spellchecker | styles | bold italic underline forecolor backcolor casechange | link uploadcare table addcomment | align bullist numlist checklist removeformat | code fullscreen help', + quickbars_selection_toolbar: 'tinymceai-quickactions addcomment', + sidebar_show: '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_fetch: () => { + const textarea = document.querySelector('textarea#tinymceai-review'); + 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))); + }, + revisionhistory_display_author: true, + tinymceai_token_provider: async () => { + 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' }, + ] +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai/example.js b/modules/ROOT/examples/live-demos/tinymceai/example.js new file mode 100644 index 0000000000..be2e035af6 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai/example.js @@ -0,0 +1,51 @@ +// Step 1: Set up session - this should be part of the application's user management process. +// Open-source plugins below are only for editing the demo HTML (lists, links, tables). TinyMCE AI options are the focus. +tinymce.init({ + selector: 'textarea#tinymceai', + height: '800px', + plugins: ['tinymceai', 'advlist', 'lists', 'link', 'autolink', 'table', 'wordcount'], + toolbar: 'undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link', + sidebar_show: 'tinymceai-chat', + tinymceai_token_provider: async () => { + return fetch('/api/tinymceai-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' }, + ] +}); diff --git a/modules/ROOT/examples/live-demos/tinymceai/index.html b/modules/ROOT/examples/live-demos/tinymceai/index.html new file mode 100644 index 0000000000..7fa0f378c2 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai/index.html @@ -0,0 +1,57 @@ + diff --git a/modules/ROOT/examples/live-demos/tinymceai/index.js b/modules/ROOT/examples/live-demos/tinymceai/index.js new file mode 100644 index 0000000000..a5b7ebd3a4 --- /dev/null +++ b/modules/ROOT/examples/live-demos/tinymceai/index.js @@ -0,0 +1,117 @@ +// 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 })))); + +tinymce.init({ + selector: 'textarea#tinymceai', + height: '800px', + 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 spellchecker | styles | bold italic underline forecolor backcolor casechange | link uploadcare table addcomment | align bullist numlist checklist removeformat | code fullscreen help', + quickbars_selection_toolbar: 'tinymceai-quickactions addcomment', + sidebar_show: 'tinymceai-chat', + 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_fetch: () => { + const textarea = document.querySelector('textarea#tinymceai'); + 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))); + }, + 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' }, + ] +}); diff --git a/modules/ROOT/images/icons-premium/adjust-length.svg b/modules/ROOT/images/icons-premium/adjust-length.svg new file mode 100644 index 0000000000..745ddb676f --- /dev/null +++ b/modules/ROOT/images/icons-premium/adjust-length.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/ai-assistant.svg b/modules/ROOT/images/icons-premium/ai-assistant.svg new file mode 100644 index 0000000000..a7e31873f5 --- /dev/null +++ b/modules/ROOT/images/icons-premium/ai-assistant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/ai-chat-response.svg b/modules/ROOT/images/icons-premium/ai-chat-response.svg new file mode 100644 index 0000000000..6964984d49 --- /dev/null +++ b/modules/ROOT/images/icons-premium/ai-chat-response.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/ai-model.svg b/modules/ROOT/images/icons-premium/ai-model.svg new file mode 100644 index 0000000000..c225787860 --- /dev/null +++ b/modules/ROOT/images/icons-premium/ai-model.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/ai-review.svg b/modules/ROOT/images/icons-premium/ai-review.svg new file mode 100644 index 0000000000..139cf4c603 --- /dev/null +++ b/modules/ROOT/images/icons-premium/ai-review.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/ai-translate.svg b/modules/ROOT/images/icons-premium/ai-translate.svg new file mode 100644 index 0000000000..ac7f32c7af --- /dev/null +++ b/modules/ROOT/images/icons-premium/ai-translate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/attachment.svg b/modules/ROOT/images/icons-premium/attachment.svg new file mode 100644 index 0000000000..4885951b3b --- /dev/null +++ b/modules/ROOT/images/icons-premium/attachment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/change-tone.svg b/modules/ROOT/images/icons-premium/change-tone.svg new file mode 100644 index 0000000000..e915836bd1 --- /dev/null +++ b/modules/ROOT/images/icons-premium/change-tone.svg @@ -0,0 +1,4 @@ + + + + diff --git a/modules/ROOT/images/icons-premium/chat-commands.svg b/modules/ROOT/images/icons-premium/chat-commands.svg new file mode 100644 index 0000000000..b01f4a0a03 --- /dev/null +++ b/modules/ROOT/images/icons-premium/chat-commands.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/chat-reasoning.svg b/modules/ROOT/images/icons-premium/chat-reasoning.svg new file mode 100644 index 0000000000..b56c0150f2 --- /dev/null +++ b/modules/ROOT/images/icons-premium/chat-reasoning.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/chat-send.svg b/modules/ROOT/images/icons-premium/chat-send.svg new file mode 100644 index 0000000000..f0a9cfb21d --- /dev/null +++ b/modules/ROOT/images/icons-premium/chat-send.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/chat-web-search.svg b/modules/ROOT/images/icons-premium/chat-web-search.svg new file mode 100644 index 0000000000..e20b98635c --- /dev/null +++ b/modules/ROOT/images/icons-premium/chat-web-search.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/collapse.svg b/modules/ROOT/images/icons-premium/collapse.svg new file mode 100644 index 0000000000..65ad8b182e --- /dev/null +++ b/modules/ROOT/images/icons-premium/collapse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/continue-writing.svg b/modules/ROOT/images/icons-premium/continue-writing.svg new file mode 100644 index 0000000000..d12fb72b68 --- /dev/null +++ b/modules/ROOT/images/icons-premium/continue-writing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/explain.svg b/modules/ROOT/images/icons-premium/explain.svg new file mode 100644 index 0000000000..f67923bb5a --- /dev/null +++ b/modules/ROOT/images/icons-premium/explain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/fix-grammar.svg b/modules/ROOT/images/icons-premium/fix-grammar.svg new file mode 100644 index 0000000000..a662954b3a --- /dev/null +++ b/modules/ROOT/images/icons-premium/fix-grammar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/highlight-key-points.svg b/modules/ROOT/images/icons-premium/highlight-key-points.svg new file mode 100644 index 0000000000..ac55d21952 --- /dev/null +++ b/modules/ROOT/images/icons-premium/highlight-key-points.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/improve-writing.svg b/modules/ROOT/images/icons-premium/improve-writing.svg new file mode 100644 index 0000000000..91667e17ef --- /dev/null +++ b/modules/ROOT/images/icons-premium/improve-writing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/new-chat.svg b/modules/ROOT/images/icons-premium/new-chat.svg new file mode 100644 index 0000000000..82f2efe376 --- /dev/null +++ b/modules/ROOT/images/icons-premium/new-chat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/other-actions.svg b/modules/ROOT/images/icons-premium/other-actions.svg new file mode 100644 index 0000000000..4f92bff29e --- /dev/null +++ b/modules/ROOT/images/icons-premium/other-actions.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/pin.svg b/modules/ROOT/images/icons-premium/pin.svg new file mode 100644 index 0000000000..e28175472e --- /dev/null +++ b/modules/ROOT/images/icons-premium/pin.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/reasoning.svg b/modules/ROOT/images/icons-premium/reasoning.svg new file mode 100644 index 0000000000..3e84782564 --- /dev/null +++ b/modules/ROOT/images/icons-premium/reasoning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/source-close.svg b/modules/ROOT/images/icons-premium/source-close.svg new file mode 100644 index 0000000000..894df4eb83 --- /dev/null +++ b/modules/ROOT/images/icons-premium/source-close.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/source-file.svg b/modules/ROOT/images/icons-premium/source-file.svg new file mode 100644 index 0000000000..a82a0fc0a5 --- /dev/null +++ b/modules/ROOT/images/icons-premium/source-file.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/source-image.svg b/modules/ROOT/images/icons-premium/source-image.svg new file mode 100644 index 0000000000..f250e829f7 --- /dev/null +++ b/modules/ROOT/images/icons-premium/source-image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/source-link.svg b/modules/ROOT/images/icons-premium/source-link.svg new file mode 100644 index 0000000000..4ff86432a1 --- /dev/null +++ b/modules/ROOT/images/icons-premium/source-link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/source-selection.svg b/modules/ROOT/images/icons-premium/source-selection.svg new file mode 100644 index 0000000000..8fc4eb63eb --- /dev/null +++ b/modules/ROOT/images/icons-premium/source-selection.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/stop.svg b/modules/ROOT/images/icons-premium/stop.svg new file mode 100644 index 0000000000..ac0676d46d --- /dev/null +++ b/modules/ROOT/images/icons-premium/stop.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons-premium/summarize.svg b/modules/ROOT/images/icons-premium/summarize.svg new file mode 100644 index 0000000000..2a5f83eb4b --- /dev/null +++ b/modules/ROOT/images/icons-premium/summarize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons-premium/table-properties.svg b/modules/ROOT/images/icons-premium/table-properties.svg new file mode 100644 index 0000000000..9e14616a49 --- /dev/null +++ b/modules/ROOT/images/icons-premium/table-properties.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/ROOT/images/icons-premium/unpin.svg b/modules/ROOT/images/icons-premium/unpin.svg new file mode 100644 index 0000000000..6e14e3420a --- /dev/null +++ b/modules/ROOT/images/icons-premium/unpin.svg @@ -0,0 +1,4 @@ + + + + diff --git a/modules/ROOT/images/icons-premium/web-search.svg b/modules/ROOT/images/icons-premium/web-search.svg new file mode 100644 index 0000000000..27f9630fdf --- /dev/null +++ b/modules/ROOT/images/icons-premium/web-search.svg @@ -0,0 +1,3 @@ + + + diff --git a/modules/ROOT/images/icons/add-file.svg b/modules/ROOT/images/icons/add-file.svg index 18af2d8265..feb2ac43ba 100644 --- a/modules/ROOT/images/icons/add-file.svg +++ b/modules/ROOT/images/icons/add-file.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/adjustments.svg b/modules/ROOT/images/icons/adjustments.svg index 2079d17011..75df7ea925 100644 --- a/modules/ROOT/images/icons/adjustments.svg +++ b/modules/ROOT/images/icons/adjustments.svg @@ -1,3 +1,3 @@ - - + + diff --git a/modules/ROOT/images/icons/alt-text.svg b/modules/ROOT/images/icons/alt-text.svg index 6e85a1f800..da39549dbc 100644 --- a/modules/ROOT/images/icons/alt-text.svg +++ b/modules/ROOT/images/icons/alt-text.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/modules/ROOT/images/icons/blur.svg b/modules/ROOT/images/icons/blur.svg index 0cf6893a70..9fedb5af76 100644 --- a/modules/ROOT/images/icons/blur.svg +++ b/modules/ROOT/images/icons/blur.svg @@ -1,3 +1,3 @@ - - + + diff --git a/modules/ROOT/images/icons/box.svg b/modules/ROOT/images/icons/box.svg index dce6de1685..acb4829f74 100644 --- a/modules/ROOT/images/icons/box.svg +++ b/modules/ROOT/images/icons/box.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/brightness.svg b/modules/ROOT/images/icons/brightness.svg index d76f74fd54..c56c524a6a 100644 --- a/modules/ROOT/images/icons/brightness.svg +++ b/modules/ROOT/images/icons/brightness.svg @@ -1,10 +1,4 @@ - - - - icon-brightness - Created with Sketch. - - - - - \ No newline at end of file + + + + diff --git a/modules/ROOT/images/icons/camera.svg b/modules/ROOT/images/icons/camera.svg index 21c6164636..d5991d2411 100644 --- a/modules/ROOT/images/icons/camera.svg +++ b/modules/ROOT/images/icons/camera.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/caption.svg b/modules/ROOT/images/icons/caption.svg index bbfa23cf7f..7a2e3e77f6 100644 --- a/modules/ROOT/images/icons/caption.svg +++ b/modules/ROOT/images/icons/caption.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/modules/ROOT/images/icons/color-swatch-remove-color.svg b/modules/ROOT/images/icons/color-swatch-remove-color.svg index 933194bd97..256a0b700f 100644 --- a/modules/ROOT/images/icons/color-swatch-remove-color.svg +++ b/modules/ROOT/images/icons/color-swatch-remove-color.svg @@ -1,4 +1,4 @@ - + diff --git a/modules/ROOT/images/icons/contrast.svg b/modules/ROOT/images/icons/contrast.svg index 4d1ed17ac9..913bddde3a 100644 --- a/modules/ROOT/images/icons/contrast.svg +++ b/modules/ROOT/images/icons/contrast.svg @@ -1,10 +1,3 @@ - - - - icon-contrast - Created with Sketch. - - - - - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/default-document-properties.svg b/modules/ROOT/images/icons/document-gear-properties.svg similarity index 100% rename from modules/ROOT/images/icons/default-document-properties.svg rename to modules/ROOT/images/icons/document-gear-properties.svg diff --git a/modules/ROOT/images/icons/document-properties.svg b/modules/ROOT/images/icons/document-properties.svg new file mode 100644 index 0000000000..eba5de0b3f --- /dev/null +++ b/modules/ROOT/images/icons/document-properties.svg @@ -0,0 +1,10 @@ + + + + icon-document-properties + Created with Sketch. + + + + + \ No newline at end of file diff --git a/modules/ROOT/images/icons/dropbox.svg b/modules/ROOT/images/icons/dropbox.svg index 61576ab6f5..353d816d3b 100644 --- a/modules/ROOT/images/icons/dropbox.svg +++ b/modules/ROOT/images/icons/dropbox.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/evernote.svg b/modules/ROOT/images/icons/evernote.svg index a750417723..1ba5699015 100644 --- a/modules/ROOT/images/icons/evernote.svg +++ b/modules/ROOT/images/icons/evernote.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/exposure.svg b/modules/ROOT/images/icons/exposure.svg index fda78d4caf..3141f579ea 100644 --- a/modules/ROOT/images/icons/exposure.svg +++ b/modules/ROOT/images/icons/exposure.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/fb.svg b/modules/ROOT/images/icons/fb.svg index 5503a9b4c0..5224ae3f14 100644 --- a/modules/ROOT/images/icons/fb.svg +++ b/modules/ROOT/images/icons/fb.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/flickr.svg b/modules/ROOT/images/icons/flickr.svg index 336b721bc4..029c14b819 100644 --- a/modules/ROOT/images/icons/flickr.svg +++ b/modules/ROOT/images/icons/flickr.svg @@ -1,3 +1,3 @@ - - + + diff --git a/modules/ROOT/images/icons/folder.svg b/modules/ROOT/images/icons/folder.svg index 9bd6f4a888..ae0a8ba4a0 100644 --- a/modules/ROOT/images/icons/folder.svg +++ b/modules/ROOT/images/icons/folder.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/gamma.svg b/modules/ROOT/images/icons/gamma.svg index 9d684fd2e5..4e759f265b 100644 --- a/modules/ROOT/images/icons/gamma.svg +++ b/modules/ROOT/images/icons/gamma.svg @@ -1,10 +1 @@ - - - - icon-gamma - Created with Sketch. - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/google-drive.svg b/modules/ROOT/images/icons/google-drive.svg index 3ca54f4325..7e97af4f0a 100644 --- a/modules/ROOT/images/icons/google-drive.svg +++ b/modules/ROOT/images/icons/google-drive.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/google-photos.svg b/modules/ROOT/images/icons/google-photos.svg index 33a6af34c5..12df76002f 100644 --- a/modules/ROOT/images/icons/google-photos.svg +++ b/modules/ROOT/images/icons/google-photos.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/grayscale.svg b/modules/ROOT/images/icons/grayscale.svg index 21af08f8a8..9ad6aa87d5 100644 --- a/modules/ROOT/images/icons/grayscale.svg +++ b/modules/ROOT/images/icons/grayscale.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/huddle.svg b/modules/ROOT/images/icons/huddle.svg index b4755a1247..41285ece88 100644 --- a/modules/ROOT/images/icons/huddle.svg +++ b/modules/ROOT/images/icons/huddle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/image-decorative.svg b/modules/ROOT/images/icons/image-decorative.svg index 656cb0260c..4c93b6c2d7 100644 --- a/modules/ROOT/images/icons/image-decorative.svg +++ b/modules/ROOT/images/icons/image-decorative.svg @@ -1,3 +1,3 @@ - - + + diff --git a/modules/ROOT/images/icons/image-enhancements.svg b/modules/ROOT/images/icons/image-enhancements.svg new file mode 100644 index 0000000000..c813b13aba --- /dev/null +++ b/modules/ROOT/images/icons/image-enhancements.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons/instagram.svg b/modules/ROOT/images/icons/instagram.svg index c46d3c45ec..2075c824ca 100644 --- a/modules/ROOT/images/icons/instagram.svg +++ b/modules/ROOT/images/icons/instagram.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/invert.svg b/modules/ROOT/images/icons/invert.svg index 954917e5f0..a6f612e3f2 100644 --- a/modules/ROOT/images/icons/invert.svg +++ b/modules/ROOT/images/icons/invert.svg @@ -1,10 +1 @@ - - - - icon-invert - Created with Sketch. - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/mentions.svg b/modules/ROOT/images/icons/mentions.svg new file mode 100644 index 0000000000..f8ac71642f --- /dev/null +++ b/modules/ROOT/images/icons/mentions.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons/onedrive.svg b/modules/ROOT/images/icons/onedrive.svg index 9463e3cecf..799826788e 100644 --- a/modules/ROOT/images/icons/onedrive.svg +++ b/modules/ROOT/images/icons/onedrive.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/photo-filter.svg b/modules/ROOT/images/icons/photo-filter.svg new file mode 100644 index 0000000000..b1f584a416 --- /dev/null +++ b/modules/ROOT/images/icons/photo-filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons/revert-changes.svg b/modules/ROOT/images/icons/revert-changes.svg new file mode 100644 index 0000000000..1c417c9686 --- /dev/null +++ b/modules/ROOT/images/icons/revert-changes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/icons/revert.svg b/modules/ROOT/images/icons/revert.svg deleted file mode 100644 index 68854286fc..0000000000 --- a/modules/ROOT/images/icons/revert.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/modules/ROOT/images/icons/saturation.svg b/modules/ROOT/images/icons/saturation.svg index 4ed121e860..9c34e30251 100644 --- a/modules/ROOT/images/icons/saturation.svg +++ b/modules/ROOT/images/icons/saturation.svg @@ -1,3 +1,3 @@ - - + + diff --git a/modules/ROOT/images/icons/sharpen.svg b/modules/ROOT/images/icons/sharpen.svg index 10d9c29e82..6a8e60b1da 100644 --- a/modules/ROOT/images/icons/sharpen.svg +++ b/modules/ROOT/images/icons/sharpen.svg @@ -1,10 +1,3 @@ - - - - icon-sharpen - Created with Sketch. - - - - - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/transform-image.svg b/modules/ROOT/images/icons/transform-image.svg index 15e252c9cf..c1e12833e4 100644 --- a/modules/ROOT/images/icons/transform-image.svg +++ b/modules/ROOT/images/icons/transform-image.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/vibrance.svg b/modules/ROOT/images/icons/vibrance.svg index 63f83303ab..a39d6498c2 100644 --- a/modules/ROOT/images/icons/vibrance.svg +++ b/modules/ROOT/images/icons/vibrance.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/modules/ROOT/images/icons/vk.svg b/modules/ROOT/images/icons/vk.svg index 3c24b20293..c18d91d140 100644 --- a/modules/ROOT/images/icons/vk.svg +++ b/modules/ROOT/images/icons/vk.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/modules/ROOT/images/icons/warmth.svg b/modules/ROOT/images/icons/warmth.svg index 1694549adc..3c8c37e43b 100644 --- a/modules/ROOT/images/icons/warmth.svg +++ b/modules/ROOT/images/icons/warmth.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-add-context-source-menu.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-add-context-source-menu.png new file mode 100644 index 0000000000..b5159da996 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-add-context-source-menu.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-remaining-suggestions.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-remaining-suggestions.png new file mode 100644 index 0000000000..c9fde1a94d Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-remaining-suggestions.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-single-suggestion-overlay.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-single-suggestion-overlay.png new file mode 100644 index 0000000000..4cde96277c Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-apply-single-suggestion-overlay.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-reject-suggestion-overlay.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-reject-suggestion-overlay.png new file mode 100644 index 0000000000..c2e667d7a2 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-diff-mode-reject-suggestion-overlay.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-history-sidebar-conversation-list.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-history-sidebar-conversation-list.png new file mode 100644 index 0000000000..9996ce5c23 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-history-sidebar-conversation-list.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-chat-model-selector-dropdown-open.png b/modules/ROOT/images/tinymceai/tinymce-ai-chat-model-selector-dropdown-open.png new file mode 100644 index 0000000000..32a71facee Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-chat-model-selector-dropdown-open.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-customer-portal-jwt-keys-page.png b/modules/ROOT/images/tinymceai/tinymce-ai-customer-portal-jwt-keys-page.png new file mode 100644 index 0000000000..ee821b6b48 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-customer-portal-jwt-keys-page.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-quick-actions-change-tone-flyout-submenu.png b/modules/ROOT/images/tinymceai/tinymce-ai-quick-actions-change-tone-flyout-submenu.png new file mode 100644 index 0000000000..735ad6d403 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-quick-actions-change-tone-flyout-submenu.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-review-improve-readability-suggestion-cards-and-underlines.png b/modules/ROOT/images/tinymceai/tinymce-ai-review-improve-readability-suggestion-cards-and-underlines.png new file mode 100644 index 0000000000..792d5c2bc6 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-review-improve-readability-suggestion-cards-and-underlines.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-review-mode-suggestions-underlined-in-editor-content.png b/modules/ROOT/images/tinymceai/tinymce-ai-review-mode-suggestions-underlined-in-editor-content.png new file mode 100644 index 0000000000..298fa217e0 Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-review-mode-suggestions-underlined-in-editor-content.png differ diff --git a/modules/ROOT/images/tinymceai/tinymce-ai-review-sidebar-command-categories-proofread-clarity.png b/modules/ROOT/images/tinymceai/tinymce-ai-review-sidebar-command-categories-proofread-clarity.png new file mode 100644 index 0000000000..7dd7fad25c Binary files /dev/null and b/modules/ROOT/images/tinymceai/tinymce-ai-review-sidebar-command-categories-proofread-clarity.png differ diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index a169e0e8a4..b97674f05e 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -251,12 +251,30 @@ ** Premium plugins *** xref:a11ychecker.adoc[Accessibility Checker] *** xref:advanced-typography.adoc[Advanced Typography] -*** xref:ai.adoc[AI Assistant] -**** xref:ai-openai.adoc[OpenAI ChatGPT integration guide] -**** xref:ai-azure.adoc[Azure AI integration guide] -**** xref:ai-bedrock.adoc[Amazon Bedrock integration guide] -**** xref:ai-gemini.adoc[Google Gemini integration guide] -**** xref:ai-proxy.adoc[AI proxy server reference guide] +*** TinyMCE AI +**** xref:tinymceai-introduction.adoc[Introduction] +**** xref:tinymceai-chat.adoc[Chat] +**** xref:tinymceai-review.adoc[Review] +**** xref:tinymceai-actions.adoc[Actions] +**** xref:tinymceai-models.adoc[AI Models] +**** xref:tinymceai-limits.adoc[Limits] +**** xref:tinymceai-integration-options.adoc[Integration Options] +***** xref:tinymceai.adoc[Plugin Configuration] +***** REST API +****** xref:tinymceai-api-overview.adoc[API Overview] +****** xref:tinymceai-api-quick-start.adoc[API Quick Start] +****** xref:tinymceai-streaming.adoc[Streaming] +**** xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication] +***** xref:tinymceai-permissions.adoc[Permissions] +***** Guides +****** xref:tinymceai-with-jwt-authentication-nodejs.adoc[JWT authentication (Node.js)] +****** xref:tinymceai-with-jwt-authentication-php.adoc[JWT authentication (PHP)] +**** xref:ai.adoc[AI Assistant (legacy)] +***** xref:ai-openai.adoc[OpenAI ChatGPT integration guide] +***** xref:ai-azure.adoc[Azure AI integration guide] +***** xref:ai-bedrock.adoc[Amazon Bedrock integration guide] +***** xref:ai-gemini.adoc[Google Gemini integration guide] +***** xref:ai-proxy.adoc[AI proxy server reference guide] *** xref:casechange.adoc[Case Change] *** xref:checklist.adoc[Checklist] *** Comments @@ -274,11 +292,14 @@ **** xref:mediaembed-server-config.adoc[Configure Enhanced Media Embed Server] **** xref:mediaembed-server-integration.adoc[Integrate Enhanced Media Embed Server] *** xref:advtable.adoc[Enhanced Tables] -*** xref:exportpdf.adoc[Export to PDF] -**** xref:html-to-pdf-converter-api.adoc[HTML to PDF Converter API] -**** JWT Authentication -***** xref:export-to-pdf-with-jwt-authentication-nodejs.adoc[Node.js] -***** xref:export-to-pdf-with-jwt-authentication-php.adoc[PHP] +*** Export to PDF +**** xref:exportpdf.adoc[Export to PDF] +***** xref:html-to-pdf-converter-api-v2.adoc[HTML to PDF Converter API] +***** JWT Authentication +****** xref:export-to-pdf-v2-with-jwt-authentication-nodejs.adoc[Node.js (8.4.0+)] +****** xref:export-to-pdf-v2-with-jwt-authentication-php.adoc[PHP (8.4.0+)] +****** xref:export-to-pdf-with-jwt-authentication-nodejs.adoc[Node.js (pre-8.4.0)] +****** xref:export-to-pdf-with-jwt-authentication-php.adoc[PHP (pre-8.4.0)] *** xref:exportword.adoc[Export to Word] **** xref:html-to-docx-converter-api.adoc[HTML to DOCX Converter API] **** JWT Authentication @@ -387,6 +408,17 @@ ** xref:tinymce-and-cors.adoc[Cross-Origin Resource Sharing (CORS)] * Release information ** xref:release-notes.adoc[Release notes for {productname}] +*** {productname} 8.4.0 +**** xref:8.4.0-release-notes.adoc#overview[Overview] +**** xref:8.4.0-release-notes.adoc#new-premium-plugin[New Premium plugin] +**** xref:8.4.0-release-notes.adoc#accompanying-premium-plugin-changes[Accompanying Premium Plugin changes] +**** xref:8.4.0-release-notes.adoc#accompanying-enhanced-skins-and-icon-packs-changes[Accompanying Enhanced Skins & Icon Packs changes] +**** xref:8.4.0-release-notes.adoc#improvements[Improvements] +**** xref:8.4.0-release-notes.adoc#additions[Additions] +**** xref:8.4.0-release-notes.adoc#changes[Changes] +**** xref:8.4.0-release-notes.adoc#bug-fixes[Bug fixes] +**** xref:8.4.0-release-notes.adoc#security-fixes[Security fixes] +**** xref:8.4.0-release-notes.adoc#known-issues[Known issues] *** {productname} 8.3.2 **** xref:8.3.2-release-notes.adoc#overview[Overview] **** xref:8.3.2-release-notes.adoc#accompanying-premium-plugin-changes[Accompanying Premium Plugin changes] diff --git a/modules/ROOT/pages/8.4.0-release-notes.adoc b/modules/ROOT/pages/8.4.0-release-notes.adoc new file mode 100644 index 0000000000..ac923f51dc --- /dev/null +++ b/modules/ROOT/pages/8.4.0-release-notes.adoc @@ -0,0 +1,395 @@ += {productname} {release-version} +:release-version: 8.4.0 +:navtitle: {productname} {release-version} +:description: Release notes for {productname} {release-version} +:keywords: releasenotes, new, changes, bugfixes, new features, improvements, changes, removals, deprecated, known issues +:page-toclevels: 1 + +include::partial$misc/admon-releasenotes-for-stable.adoc[] + + +[[overview]] +== Overview + +{productname} {release-version} was released for {enterpriseversion} and {cloudname} on Tuesday, March 31^st^, 2026. These release notes provide an overview of the changes for {productname} {release-version}, including: + +* xref:new-premium-plugins[New Premium plugins] +* xref:accompanying-premium-plugin-changes[Accompanying Premium plugin changes] +* 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:known-issues[Known issues] + + +[[new-premium-plugin]] +== New Premium plugin + +The following new Premium plugin was released alongside {productname} {release-version}. + +=== TinyMCE AI + +**TinyMCE AI** is the new premium AI platform for {productname}: faster drafting and stronger editing workflows with a ready-to-use AI features - now available as both a plug-and-play plugin and an API for custom integrations. + +The platform centers on three experiences that mirror what teams expect from modern AI writing tools: + +* image:icons-premium/ai-assistant.svg[Chat icon,24px] **Chat**: Contextual conversations, persistent history, and help that understands the document. +* image:icons-premium/ai-review.svg[Review icon,24px] **Review**: Proofreading and structured quality passes for longer content and editorial standards. +* image:icons/ai-prompt.svg[Quick Actions icon,24px] **Actions**: Quick, repeatable transformations for everyday tasks (tone, length, clarity, and more). + +Behind the UI sits a production-ready **TinyMCE AI API** with JWT authentication, granular permissions, and multiple models, which is also available for use in your broader application. + +**What this means for users** (the outcomes the interface is built for): + +* Move drafts forward and refine tone without leaving the editor. +* Summarize, adjust length, and improve clarity with guided flows. +* Keep brand and policy guardrails in reach through permissions and review-style workflows. + +**Documentation** for **TinyMCE AI**: + +* xref:tinymceai-introduction.adoc[Introduction to TinyMCE AI] — Capabilities, features, and how the platform fits together. +* xref:tinymceai.adoc[TinyMCE AI plugin] — Setup, configuration, and the out-of-the-box editor experience. +* xref:tinymceai-api-overview.adoc[TinyMCE AI API] — Service integration, authentication, and building beyond the editor. + +[TIP] +==== +Existing customers on paid plans can request a full featured free trial through the link:{accountpageurl}[Customer Portal]. +==== + + +[[accompanying-premium-plugin-changes]] +== Accompanying Premium plugin changes + +The following premium plugin updates were released alongside {productname} {release-version}. + +=== Comments + +The {productname} {release-version} release includes an accompanying release of the **Comments** premium plugin. + +**Comments** includes the following fixes. + +==== Errors when creating new comments made the save button stuck in a saving state. +// #TINY-12224 + +Previously, when creating or editing a comment in Comments, the save button could remain in a saving state indefinitely if the save operation failed or if the component was not replaced. The saving state had no way to reset to false except by recreating the component, which misled users into thinking the operation was still in progress. + +In {productname} {release-version}, the save logic now resets the saving state to false after the save operation completes, whether the operation succeeds or fails. The save button no longer remains stuck in a saving state. + +==== Users with an `id` that includes `@` weren't parsed correctly. +// #TINY-12235 + +Previously, the mentions parser in Comments did not treat the `@` symbol as part of a mention string. User IDs containing `@` (such as email addresses) were split incorrectly, so mentions remained as raw text instead of resolving to the display name after saving. + +In {productname} {release-version}, the Comments plugin now correctly parses mentions with `@` in user IDs. Mentions resolve to display names as expected. + +For information on the **Comments** plugin, see: xref:introduction-to-tiny-comments.adoc[Comments]. + +=== Export to PDF + +The {productname} {release-version} release includes an accompanying release of the **Export to PDF** premium plugin. + +**Export to PDF** includes the following addition. + +==== `exportpdf` supports API version 2 converter options +// #TINY-13700 + +`{productname}` `{release-version}` adds support for version `2` of the `exportpdf` API through `exportpdf_converter_options`. Version `1` remains the default for backward compatibility. The new nested structure organizes options under `document`, `headers`, `footers`, `metadata`, `security`, and `signature`, enabling per-page headers and footers, PDF metadata, password protection, and certificate-based signing. + +For information on the **Export to PDF** plugin, see xref:exportpdf.adoc[Export to PDF]. + +=== Full Page HTML + +The {productname} {release-version} release includes an accompanying release of the **Full Page HTML** premium plugin. + +**Full Page HTML** includes the following fixes. + +==== Replaced deprecated browser APIs with modern equivalents. +// #TINY-13674 + +Previously, the Full Page HTML plugin used deprecated `+escape+` and `+unescape+` JavaScript APIs for some protected content handling. Those APIs are no longer recommended for new code. + +In {productname} {release-version}, the plugin uses modern encoding APIs instead. This aligns the implementation with current browser guidance and improves reliability for protected content handling. + +==== Pasting an HTML document was vulnerable to XSS attacks +// #TINY-13673 + +A cross-site scripting (XSS) vulnerability was discovered in the Full Page HTML plugin. Previously, malicious code within the document `` was able to be executed when pasted. + +This vulnerability has been patched in {productname} {release-version} by ensuring that content in the document `` is properly encoded. + +==== New argument `fullpagehtml` to `editor.getContent()` and `editor.setContent()` APIs to only get/set the body of the content while the full page plugin is active. +// #TINY-13744 + +Previously, setting and getting the editor content while the Full Page HTML plugin was active could be troublesome due to the presence of the full HTML document on all API calls, even when not needed. Attempting to get and act only on the body content (for example, for saving) was undocumented and required workarounds. + +In {productname} {release-version}, the `fullpagehtml` option has been added to the `editor.getContent()` and `editor.setContent()` APIs. When set to `false`, this option allows getting and setting only the body content while the Full Page HTML plugin is active, without interfering with the full document structure. The document is now more resistant to accidental changes, and content can be retrieved or updated without including the full HTML document. For details, see xref:fullpagehtml.adoc#fullpagehtml-getcontent-setcontent[`fullpagehtml` option for getContent/setContent]. + +For information on the **Full Page HTML** plugin, see: xref:fullpagehtml.adoc[Full Page HTML]. + +=== Media Optimizer + +The {productname} {release-version} release includes an accompanying release of the **Media Optimizer** premium plugin. + +**Media Optimizer** includes the following additions and fixes. + +==== Toolbar button was not initialized when used with the `quickbars` plugin. +// #TINY-13731 + +Previously, when the Media Optimizer plugin was used together with the quickbars plugin, the uploadcare toolbar button was not registered at all. As a result, the button could not appear in the toolbar, even when configured. + +In {productname} {release-version}, the uploadcare button is now always registered and can be used in the toolbar alongside the quickbars plugin. To avoid duplication in the context toolbar, the plugin no longer adds the uploadcare button when the quickbars insert image button is already present. + +==== Third-party library icons appear in formats when using Media Optimiser plugin together with CSS plugin +// #TINY-13515 + +Previously, when the Media Optimiser plugin was used together with the importcss plugin, the previous version of `uc-video` required importing external styles. The importcss plugin detected these imports and added them to the format menu, causing third-party library icons to appear in the formats UI. These icons were not part of the official TinyMCE icon pack and created a confusing and inconsistent UI experience. + +In {productname} {release-version}, the `uc-video` package was upgraded to a version that has styles self-contained in the web component. The importcss plugin no longer detects `uc-video` styles, so third-party icons no longer appear in the formats UI. + +==== SVG images can now be uploaded. +// #TINY-13708 + +Previously, SVG images could not be uploaded through the Media Optimizer plugin because Uploadcare placed restrictions on SVG file handling. Users who needed to include SVG graphics in content were unable to upload them directly. + +In {productname} {release-version}, SVG images can now be uploaded through the Media Optimizer plugin. Some CDN operations may have limitations on SVG files; for details, see the link:https://uploadcare.com/docs/cdn-operations/#limits[Uploadcare documentation on CDN operation limits]. + +For information on the **Media Optimizer** plugin, see: xref:uploadcare.adoc[Media Optimizer]. + +=== Suggested Edits + +The {productname} {release-version} release includes an accompanying release of the **Suggested Edits** premium plugin. + +**Suggested Edits** includes the following improvement and fix. + +==== Document view rendering to reduce flickering when loading Suggested Edits. +// #TINY-13135 + +Previously, the document displayed in the Review Edits view relied on the deprecated browser method `document.write`, which could cause content to appear before it was fully styled. Users could briefly see partially rendered or unstyled content when opening the review interface. + +In {productname} {release-version}, the document loading process in the Review Edits view has been updated to remove the deprecated method. The document is now displayed only after it has fully loaded, improving browser compatibility and providing a smoother and more stable experience when reviewing suggested edits. + +==== Cancel button would always focus when the view opened, even when editor wasn't focused. +// #TINY-13711 + +Previously, the Cancel button in Suggested Edits was automatically focused whenever the review was opened, including when the review opened automatically on load. This could cause unexpected scrolling behaviour, such as when an editor is positioned further down the page, the browser would scroll the editor into view when the page loads. + +In {productname} {release-version}, the Cancel button is now focused only when the editor itself is already focused. When the review is opened automatically, the button is no longer focused, preventing unintended scrolling. + +For information on the **Suggested Edits** plugin, see: xref:suggestededits.adoc[Suggested Edits]. + + +[[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]. + + +[[improvements]] +== Improvements + +{productname} {release-version} also includes the following improvements: + +=== The file upload feature of `link` and `image` dialogs now provide feedback when an unsupported file type is selected +// #TINY-13420 + +In {productname} {release-version}, the dropzone in the link and image dialog upload tabs previously provided no feedback when users inserted only files with disallowed extensions. This left users unsure whether the upload had failed or the dialog had not responded. The dropzone now displays an error message when all selected files have disallowed extensions, informing users that the selected files do not have allowed extensions and prompting them to choose different files. + +=== Directionality buttons now always apply to blocks and only appear active when directionality is set +// #TINY-13337 + +Previously, the directionality buttons would not apply the directionality attribute or style when toggling to the default directionality. This could cause non-default directional content to appear in the opposite direction. + +In {productname} {release-version}, each directionality button always applies or removes the directionality attribute on the selected block, and only appears active when directionality is explicitly set on the block. + +=== Directionality of Hebrew was incorrect +// #TINY-13667 + +Previously, right-to-left (RTL) directionality was not correctly set for Hebrew in the language pack. This caused the editor to render the wrong directionality when Hebrew was set as the language. + +In {productname} {release-version}, this issue has been addressed by ensuring that the directionality is correctly set for Hebrew in the language pack. + + +[[additions]] +== Additions + +{productname} {release-version} also includes the following additions: + +=== New `table_default_header_rows` and `table_default_header_cols` options to set the default header size for new tables +// #TINY-13391 + +Previously, integrators had no way to set default header rows and columns when creating tables through the editor UI. This affected the accessibility of tables and required manual intervention for integrators aiming to meet accessibility standards. The new xref:table-options.adoc#table_default_header_rows[`+table_default_header_rows+`] and xref:table-options.adoc#table_default_header_cols[`+table_default_header_cols+`] options enable integrators to set the number of default header rows and columns for new tables created through the editor's UI, providing a supported way to meet accessibility requirements. + +=== New `errorHandler` option for `dropzone` dialog components +// #TINY-13420 + +In {productname} {release-version}, the dropzone dialog component supports a new `onInvalidFiles` callback (exposed as `errorHandler` in the changelog) that runs when all dropped or selected files have disallowed extensions. This enables custom error handling for invalid file uploads in dialogs that use dropzones, such as the link and image dialogs. + +=== The noneditable feature can now be disabled with the new `allow_noneditable` option. +// #TINY-10121 + +Previously, the noneditable plugin was converted to a feature in core in {productname} 6. The feature was always enabled with no documented way to turn it off, which was not always desirable for integrators. + +In {productname} {release-version}, a new xref:non-editable-content-options.adoc#allow_noneditable[`+allow_noneditable+`] option is available. It is enabled by default. When set to `+false+`, the noneditable feature is disabled, equivalent to disabling the plugin prior to {productname} 6. + +=== New `view_show` option to display a specified view on initialization. +// #TINY-11967 + +In {productname} {release-version}, the new xref:custom-view.adoc#view_show[`+view_show+`] option allows specifying which view to display when the editor is initialized. The option behaves similarly to `+sidebar_show+` but takes precedence for views; both sidebars and views can be configured to show on init. + +=== New `content_id` editor option for uniquely identifying the edited document +// #TINY-13379 + +Previously, there was no supported editor option for supplying a stable identifier for the document being edited in the editor configuration. + +In {productname} {release-version}, the optional `+content_id+` string option is available. Integrations can set it to a value that uniquely identifies the document (for example, a database record id). When the xref:tinymceai.adoc[TinyMCE AI] plugin is enabled, `+content_id+` scopes chat history to that document; for details, see xref:tinymceai.adoc#content_id[`+content_id+` in the TinyMCE AI options]. + + +[[changes]] +== Changes + +{productname} {release-version} also includes the following changes: + +=== The `border-color` style with multiple rgb colors would be compressed into `border` incorrectly +// #TINY-13393 + +Previously, when `border-color` used multiple rgb values (for example, for different sides of an element), the style compressor would incorrectly compress them into a single `border` shorthand. The `border` shorthand only supports one color, so this produced invalid CSS. This could affect tables and other elements with multi-colored borders. + +In {productname} {release-version}, a check was added to prevent compression when `border-color` contains multiple rgb values. The styles are no longer compressed into invalid shorthand. + +=== Element path uses WAI-ARIA group semantics and an accessible name +// #TINY-13338 + +Previously, the element path container used the `navigation` landmark role (`role="navigation"`) and had no accessible name. That did not match how the control behaves for assistive technologies. + +In {productname} {release-version}, the element path uses `role="group"` with an `aria-label` (localized; `Element Path` in English). For keyboard navigation, see xref:tinymce-and-screenreaders.adoc#navigating-element-path[Accessible navigation guide]. + + +[[bug-fixes]] +== Bug fixes + +{productname} {release-version} also includes the following bug fixes: + +=== Now `link` dialog allows uploading empty files +// #TINY-13421 + +Previously, when uploading an empty file through the link dialog's upload tab, the conversion to `BlobInfo` failed and returned a generic, cryptic error about blob and base64 encoding. As a result, users could not understand what caused the failure or how to resolve it. + +In {productname} {release-version}, empty file uploads are now handled by the link dialog itself, which displays a clear, user-friendly error message when an empty file is selected. Users receive a specific error that explains the issue instead of a generic conversion error. + +=== Bundled content CSS is now loaded into preview iframes +// #TINY-13190 + +Previously, when the editor content CSS was bundled, it was not loaded into preview iframes. This caused a visual mismatch between the editor content area and what users saw in the Preview dialog, Suggested Edits view and Revision History view. + +In {productname} {release-version}, the fix checks if the content CSS is available as a bundled resource and applies it to the Preview Iframe through style tags. Bundled content CSS is now correctly loaded in the Preview Iframe. + +=== Attempting to remove a link after a `contentEditable="false"` element would not be possible. +// #TINY-13108 + +In previous version of {productname}, attempting to remove a link positioned after a `contentEditable="false" (CEF) element could fail because the action flow created a bookmark that normalized the selection and shifted it into the CEF; once the cursor was inside a CEF, the selection check prevented the link-removal action (and other selection-based actions) from running. + +{productname} {release-version} addresses this by capturing the selection’s target before creating the bookmark, reversing the previous order so the selection is copied prior to normalization, ensuring the selection target remains valid and link removal works as expected. + +=== Some formatting was not applied to items in multilevel list. +// #TINY-13324 + +Previously, when applying formatting such as background, bold, italic, underline, or strikethrough to a multilevel list and then adding new items before the second-level list, the new items could lose some of that formatting. This occurred because creating a new line in a list item that contained a nested list sometimes trimmed the empty elements that held the applied styles. + +In {productname} {release-version}, the trim logic has been updated to avoid removing these elements when inserting a new line inside a list item that contains both an empty element (the styles) and a nested list. The formatting is now preserved as expected when adding new items to multilevel lists. + +=== Setting width via Table Properties did not apply when `table_style_by_css` was `false`. +// #TINY-12797 + +Previously, when `table_style_by_css` was set to `false`, updating the width of a table through the Table Properties dialog did not apply the width attribute. The dialog only applied width when using CSS styles, which broke the functionality for users who rely on HTML attributes for table sizing. + +In {productname} {release-version}, updating the width through the Table Properties dialog now ensures the width attribute is applied correctly when `table_style_by_css` is `false`. The table dialog behaves as expected for both attribute-based and style-based width settings. + +=== Dialogs did not retain focus when using the block/unblock API. +// #TINY-12918 + +Previously, when a dialog was blocked (for example, while loading) and then unblocked, the loading spinner disappeared without automatically focusing any other element. As a result, focus escaped the editor entirely. When using an inline editor, this caused the dialog and the rest of the editor UI to disappear. + +In {productname} {release-version}, unblocking a dialog now focuses the first focusable element automatically, the same as when opening a dialog. This prevents the dialog and the rest of the editor UI from disappearing when using an inline editor. + +=== Toggling lists cause selection issues +// #TINY-13213 + +Previously, repeatedly toggling list formatting (for example, switching between bullet and ordered lists) could cause the selection to extend unexpectedly, including content that was not initially selected. The selection would jump to adjacent lines and expand with each subsequent toggle, making it difficult to apply list changes only to the intended items. + +In {productname} {release-version}, the selection logic no longer considers the forced root block when the selection is not collapsed. This prevents the selection from expanding beyond the intended list items, so list formatting can be toggled without unintended selection changes. + +=== Tables with unitless width or height attributes could not be resized correctly. +// #TINY-12797 + +Previously, tables that used unitless width or height attributes (for example, numeric values without `px` or `%`) could not be resized correctly. Resizing handles and column operations did not behave as expected for these tables. + +In {productname} {release-version}, the table resize logic correctly handles unitless width and height attributes. Tables can now be resized and modified as expected regardless of how their dimensions are specified. + +=== Toolbars incorrectly had the role "group" instead of "toolbar". Toolbar groups incorrectly had the role "toolbar" instead of "group". +// #TINY-13339 + +Previously, toolbars were incorrectly given the role `group` instead of `toolbar`, and toolbar groups were incorrectly given the role `toolbar` instead of `group`. This resulted in misleading semantics for screen readers, as users heard multiple "toolbars" without clear grouping structure and no accessible names. + +In {productname} {release-version}, the ARIA roles have been corrected so that toolbars use `role="toolbar"` and toolbar groups use `role="group"`. This improves accessibility and screen reader behavior. + +=== Dropdown menus with `matchWidth: true` would be located to the left of their parent if the content was sufficiently long +// #TINY-4531 + +Previously, dropdown menus with `matchWidth: true` could sit to the left of the input when the field value overflowed past the right edge of the viewport, such as when pasting a long URL into the image dialog source field. Misalignment ranged from a slight offset to the menu sitting flush against the left edge of the viewport. The dropdown width was constrained to match the input, but the menu was not repositioned after that constraint, so the list no longer lined up with the field and looked disconnected. + +In {productname} {release-version}, the positioning logic now triggers a repositioning whenever the dropdown width is constrained. The dropdown remains aligned with the input as expected. + +=== Certain deletion keyboard events in lists could not be prevented +// #TINY-13276 + +In {productname} {release-version}, an issue was identified where certain deletion keyboard events within lists could not be prevented due to the key handler being registered before the editor setup phase and without verifying whether the event had already been prevented. As a result, attempts to intercept and prevent selection deletion were ineffective, limiting customization and control over list behavior. + +{productname} {release-version} addresses this by updating the key handler registration to occur during the `init` phase, and additional checks now ensure that previously prevented events are respected. + + + +[[security-fixes]] +== Security fixes + +{productname} {release-version} includes one fix for the following security issue: + +=== Attribute sanitization bypass in rawtext contexts +// #TINY-14180 + +A link:https://owasp.org/www-community/attacks/xss/[cross-site scripting] (XSS) vulnerability was discovered in link:https://www.npmjs.com/package/dompurify[DOMPurify] that affects versions of {productname} prior to {release-version}. The issue was a result of DOMPurify allowing attackers to bypass attribute sanitization in certain rawtext contexts, which could lead to improper sanitization when sanitized output was placed inside those contexts. + +=== Affected Versions + +* DOMPurify `3.1.3` through `3.3.1` +* DOMPurify `2.5.3` through `2.5.8` + +=== Vulnerabilities + +* **Attribute sanitization bypass in rawtext contexts** (link:https://www.cve.org/CVERecord?id=CVE-2026-0540[CVE-2026-0540]): Allowed attackers to bypass attribute sanitization by exploiting missing rawtext elements in the `SAFE_FOR_XML` regex. + +GHSA: link:https://github.com/advisories/GHSA-v2wj-7wpq-c8vv[GitHub Advisory] + +CVE: link:https://nvd.nist.gov/vuln/detail/CVE-2026-0540[CVE-2026-0540] + + +[[known-issues]] +== Known issues + +This section describes issues that users of {productname} {release-version} may encounter and possible workarounds for these issues. + +The following known issues affect {productname} {release-version}. + +=== +// #TINY-vwxyz1 + +// CCFR here. diff --git a/modules/ROOT/pages/advcode.adoc b/modules/ROOT/pages/advcode.adoc index 98a54d8663..fa011b0034 100644 --- a/modules/ROOT/pages/advcode.adoc +++ b/modules/ROOT/pages/advcode.adoc @@ -69,6 +69,8 @@ include::partial$configuration/advcode_prettify_getcontent.adoc[leveloffset=+1] include::partial$configuration/advcode_prettify_editor.adoc[leveloffset=+1] +include::partial$plugins/advcode-open-view.adoc[] + include::partial$misc/advcode-shortcuts.adoc[] include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] diff --git a/modules/ROOT/pages/available-menu-items.adoc b/modules/ROOT/pages/available-menu-items.adoc index 65d7edf122..de4614995d 100644 --- a/modules/ROOT/pages/available-menu-items.adoc +++ b/modules/ROOT/pages/available-menu-items.adoc @@ -25,26 +25,14 @@ include::partial$menu-item-ids/core-menu-items.adoc[] :plugincode: a11ychecker include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] -:plugincategory: opensource -:pluginname: Accordion -:plugincode: accordion -include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] - :plugincategory: premium -:pluginname: Enhanced Code Editor -:plugincode: advcode -:altplugincode: code +:pluginname: AI Assistant +:plugincode: ai include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] -:!altplugincode: :plugincategory: opensource -:pluginname: List Styles -:plugincode: advlist -include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] - -:plugincategory: premium -:pluginname: Enhanced Tables -:plugincode: advtable +:pluginname: Accordion +:plugincode: accordion include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :plugincategory: premium @@ -53,11 +41,6 @@ include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :pluginpage: advanced-typography.adoc include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] -:plugincategory: premium -:pluginname: AI Assistant -:plugincode: ai -include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] - :plugincategory: opensource :pluginname: Anchor :plugincode: anchor @@ -106,9 +89,15 @@ include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :plugincategory: premium -:pluginname: Full Page HTML -:plugincode: fullpagehtml -:pluginpage: fullpagehtml.adoc +:pluginname: Enhanced Code Editor +:plugincode: advcode +:altplugincode: code +include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] +:!altplugincode: + +:plugincategory: premium +:pluginname: Enhanced Tables +:plugincode: advtable include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :plugincategory: premium @@ -126,6 +115,12 @@ include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :plugincode: footnotes include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] +:plugincategory: premium +:pluginname: Full Page HTML +:plugincode: fullpagehtml +:pluginpage: fullpagehtml.adoc +include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] + :plugincategory: opensource :pluginname: Full Screen :plugincode: fullscreen @@ -156,6 +151,11 @@ include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :plugincode: link include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] +:plugincategory: opensource +:pluginname: List Styles +:plugincode: advlist +include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] + :plugincategory: opensource :pluginname: Lists :plugincode: lists @@ -240,6 +240,12 @@ include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] :!pluginpage: +:plugincategory: premium +:pluginname: TinyMCE AI +:plugincode: tinymceai +:pluginpage: tinymceai.adoc +include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] + :plugincategory: opensource :pluginname: Visual Blocks :plugincode: visualblocks diff --git a/modules/ROOT/pages/available-toolbar-buttons.adoc b/modules/ROOT/pages/available-toolbar-buttons.adoc index 065e97ac95..fa62ebcb2c 100644 --- a/modules/ROOT/pages/available-toolbar-buttons.adoc +++ b/modules/ROOT/pages/available-toolbar-buttons.adoc @@ -35,6 +35,12 @@ include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] :plugincode: ai include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] +:plugincategory: premium +:pluginname: TinyMCE AI +:plugincode: tinymceai +:pluginpage: tinymceai.adoc +include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] + :plugincategory: premium :pluginname: Enhanced Code Editor :plugincode: advcode diff --git a/modules/ROOT/pages/changelog.adoc b/modules/ROOT/pages/changelog.adoc index 522a819921..0f3ed76a53 100644 --- a/modules/ROOT/pages/changelog.adoc +++ b/modules/ROOT/pages/changelog.adoc @@ -4,6 +4,51 @@ 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.4.0-release-notes.adoc[8.4.0 - 2026-02-04] + +### Added +* New `view_show` option to display a specified view on initialization. +// #TINY-11967 +* New `errorHandler` option for `dropzone` dialog components. +// #TINY-13420 +* The noneditable feature can now be disabled with the new `allow_noneditable` option. #TINY-10121 +* Editor option `content_id` for uniquely identifying the edited document. +// #TINY-13379 +* New `table_default_header_rows` and `table_default_header_cols` options to set the default header size for new tables. +// #TINY-13391 + +### Improved +* The file upload feature of `link` and `image` dialogs now provide feedback when an unsupported file type is selected. +// #TINY-13420 +* Directionality buttons now only appear active when directionality is set on the selected block. +// #TINY-13337 +* Directionality buttons now always toggle the directionality attribute on selected blocks. +// #TINY-13337 + +### Changed +* The `border-color` style with multiple rgb colors would be compressed into `border` incorrectly. +// #TINY-13393 +* Element Path now uses the ARIA-role "group" with an aria-label. +// #TINY-13338 + +### Fixed +* The `link` dialog now allows uploading empty files. +// #TINY-13421 +* Bundled content CSS is now loaded into preview iframes. +// #TINY-13190 +* Attempting to remove a link after a `contentEditable="false"` element was not possible. +// #TINY-13108 +* Some formatting was not applied to items in multilevel list. +// #TINY-13324 +* Dialogs did not retain focus when using the block/unblock API. +// #TINY-12918 +* Setting width via Table Properties did not apply when `table_style_by_css` was `false`. +// #TINY-12797 + +### Security +* Updated DOMPurify version to 3.3.2. +// #TINY-14180 + == xref:8.3.2-release-notes.adoc[8.3.2 - 2026-01-14] * `uc-video` elements are not refreshed on undo/redo actions. diff --git a/modules/ROOT/pages/custom-view.adoc b/modules/ROOT/pages/custom-view.adoc index 2cb4d7555b..7df476776f 100644 --- a/modules/ROOT/pages/custom-view.adoc +++ b/modules/ROOT/pages/custom-view.adoc @@ -57,6 +57,10 @@ To query the state of the custom view (whether it is currently visible or hidden editor.queryCommandValue('ToggleView') == 'myCustomView'; ---- +== Options + +include::partial$configuration/view_show.adoc[leveloffset=+1] + == Interactive example This example shows how to integrate a custom view using the `addView` API. diff --git a/modules/ROOT/pages/editor-command-identifiers.adoc b/modules/ROOT/pages/editor-command-identifiers.adoc index 134b326630..8bc611c259 100644 --- a/modules/ROOT/pages/editor-command-identifiers.adoc +++ b/modules/ROOT/pages/editor-command-identifiers.adoc @@ -117,6 +117,7 @@ tinymce.activeEditor.execCommand('Redo'); tinymce.activeEditor.execCommand('Undo'); ---- +[[miscellaneous-core-commands]] ==== Miscellaneous Core Commands The commands in the following table are provided by the {productname} editor and provide additional functionality that does not require any plugins to be enabled. @@ -215,6 +216,7 @@ Commands are available for the following plugins: * xref:advancedlists[Advanced Lists] * xref:Enhanced Tables[Enhanced Tables] * xref:anchor[Anchor] +* xref:tinymceai[TinyMCE AI] * xref:autoresize[Autoresize] * xref:casechange[Case Change] * xref:charactermap[Character Map] @@ -525,6 +527,13 @@ The following commands require the xref:tableofcontents.adoc[Table of Contents ( include::partial$commands/tableofcontents-cmds.adoc[leveloffset=+3] +[[tinymceai]] +==== TinyMCE AI + +The xref:tinymceai.adoc[TinyMCE AI (`+tinymceai+`)] plugin registers AI Chat and AI Review sidebars. The following subsection describes how to open and close them using a core editor command. + +include::partial$commands/tinymceai-cmds.adoc[leveloffset=+3] + [[advtemplate]] ==== Templates diff --git a/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-nodejs.adoc b/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-nodejs.adoc new file mode 100644 index 0000000000..e5ad951ee4 --- /dev/null +++ b/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-nodejs.adoc @@ -0,0 +1,82 @@ += {pluginname} with JWT authentication (Node.js) Guide +:plugincode: exportpdf +:pluginname: Export to PDF +:navtitle: JWT Authentication setup for {pluginname} +:description: Guide on how to set up JWT authentication for exporting PDF files with {pluginname} using Node.js +:keywords: jwt, authentication, exportpdf, pdf, node.js + + +include::partial$auth/document-converters/nodejs/intro-and-prerequisites.adoc[] + +[NOTE] +==== +This guide uses the nested format (`version: '2'`) for `exportpdf_converter_options`. Requires {productname} 8.4.0 or newer. For full option documentation, see xref:exportpdf.adoc[Export to PDF]. For integrators on older versions, see xref:export-to-pdf-with-jwt-authentication-nodejs.adoc[JWT Authentication setup for Export to PDF (Node.js) – flat format]. +==== + +include::partial$auth/document-converters/nodejs/initial-project-setup.adoc[] + +== Setup + +=== Generate a Public/Private Key Pair + +include::partial$auth/document-converters/jwt-setup-document-converters.adoc[leveloffset=+2] + +include::partial$auth/document-converters/nodejs/server-setup-jwt.adoc[] + +=== Web Page (public/index.html) + +Inside the `public` folder where you created the `index.html` file add the HTML setup code. + +[source,html] +---- + + + + TinyMCE with Export to PDF + + + + +

TinyMCE Export to PDF Demo

+ + + +---- + +include::partial$auth/document-converters/nodejs/configuration-steps.adoc[] + +== Further configuration + +For additional options such as per-page headers and footers, PDF metadata, and security settings, see the xref:exportpdf.adoc#exportpdf-converter-options[`exportpdf_converter_options`] section on the Export to PDF plugin page. diff --git a/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-php.adoc b/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-php.adoc new file mode 100644 index 0000000000..de705f2e2e --- /dev/null +++ b/modules/ROOT/pages/export-to-pdf-v2-with-jwt-authentication-php.adoc @@ -0,0 +1,80 @@ += {pluginname} with JWT authentication (PHP) Guide +:pluginname: Export to PDF +:plugincode: exportpdf +:navtitle: JWT Authentication setup for {pluginname} +:description: Guide on how to set up JWT authentication for exporting PDF files with {pluginname} using PHP +:keywords: jwt, authentication, exportpdf, pdf, php + +include::partial$auth/document-converters/php/intro-and-prerequisites.adoc[] + +[NOTE] +==== +This guide uses the nested format (`version: '2'`) for `exportpdf_converter_options`. Requires {productname} 8.4.0 or newer. For full option documentation, see xref:exportpdf.adoc[Export to PDF]. For integrators on older versions, see xref:export-to-pdf-with-jwt-authentication-php.adoc[JWT Authentication setup for Export to PDF (PHP) – flat format]. +==== + +include::partial$auth/document-converters/php/initial-project-setup.adoc[] + +== Setup + +=== Generate a Public/Private Key Pair + +include::partial$auth/document-converters/jwt-setup-document-converters.adoc[leveloffset=+2] + +include::partial$auth/document-converters/php/server-setup-php.adoc[] + +=== Web Page Setup (index.html) + +Inside the `public` folder where you created the `index.html` file add the HTML setup code. + +[source,html] +---- + + + + TinyMCE with Export to PDF + + + + +

TinyMCE Export to PDF Demo

+ + + +---- + +include::partial$auth/document-converters/php/configuration-steps.adoc[] + +== Further configuration + +For additional options such as per-page headers and footers, PDF metadata, and security settings, see the xref:exportpdf.adoc#exportpdf-converter-options[`exportpdf_converter_options`] section on the Export to PDF plugin page. diff --git a/modules/ROOT/pages/exportpdf.adoc b/modules/ROOT/pages/exportpdf.adoc index 05dfce125f..21220d83db 100644 --- a/modules/ROOT/pages/exportpdf.adoc +++ b/modules/ROOT/pages/exportpdf.adoc @@ -2,7 +2,7 @@ :plugincode: exportpdf :pluginname: Export to PDF :pluginfilename: export-to-pdf -:navtitle: {pluginname} +:navtitle: Export to PDF :description: The {pluginname} feature provides the ability to generate a PDF file directly from the editor. :description_short: Generate a PDF file directly from the editor. :keywords: plugin, {plugincode}, {pluginname} @@ -13,6 +13,15 @@ include::partial$misc/admon-export-pdf-paid-addon-pricing.adoc[] The {pluginname} feature collects the HTML generated with the `tinymce.editor.getContent()` method and combines it with the default editor content styles along with the styles provided in the plugin configuration. The combined content and styles are then processed by the included server-side converter service, which can be either self-hosted or cloud-based. Following this processing, a PDF file is generated, which is subsequently returned to the user's browser, enabling them to save it onto their disk or drive. +== Backwards compatibility and conversion + +The plugin always uses the v2 API endpoint (`/v2/convert/html-pdf`). Two option formats are supported: + +* **Flat format** – Top-level properties such as `format`, `margin_top`, `header_html`, and `footer_html`. Existing integrations using this format continue to work without changes. The plugin converts flat options to the nested structure automatically before the request. +* **Nested format** – Set `version: '2'` to use the nested structure and access features such as per-page headers and footers, PDF metadata, security, and digital signatures. + +Both formats produce equivalent output when configured for the same result. Requires {productname} 8.4.0 or newer for v2 API support and automatic conversion. + == Interactive example liveDemo::exportpdf[] @@ -41,7 +50,6 @@ tinymce.init({ include::partial$misc/bundling-guide-link.adoc[] - For more infomation on the exportpdf_token_provider option, see xref:exportpdf.adoc#exportpdf-token-provider[exportpdf_token_provider]. include::partial$misc/admon-jwt-authentication-requirements.adoc[] @@ -64,7 +72,7 @@ tinymce.init({ [IMPORTANT] ==== -The `exportpdf_service_url` option automatically appends `/v1/convert` to the URL provided, so only the base URL is required. For example, if the service is hosted at `http://localhost:8080/v1/convert`, the `exportpdf_service_url` option should be set to `http://localhost:8080/`. When using in production, ensure that `exportpdf_service_url` is updated to the production URL such as `https://myserver.com/`. +The `exportpdf_service_url` option automatically appends `/v2/convert/html-pdf` to the URL provided, so only the base URL is required. For example, if the service is hosted at `http://localhost:8080/v2/convert/html-pdf`, the `exportpdf_service_url` option should be set to `http://localhost:8080/`. When using in production, ensure that `exportpdf_service_url` is updated to the production URL such as `https://myserver.com/`. ==== == Additional Configuration @@ -79,7 +87,7 @@ include::partial$configuration/exportpdf_service_url.adoc[leveloffset=+1] include::partial$configuration/exportpdf_token_provider.adoc[leveloffset=+1] -include::partial$configuration/exportpdf_converter_options.adoc[leveloffset=+1] +include::partial$configuration/exportpdf_converter_options_combined.adoc[leveloffset=+1] include::partial$configuration/exportpdf_converter_style.adoc[leveloffset=+1] @@ -95,4 +103,4 @@ include::partial$commands/{plugincode}-cmds.adoc[] == API Reference -> Explore the comprehensive API documentation for the {pluginname} Premium plugin at https://exportpdf.api.tiny.cloud/v1/convert/docs[{pluginname} API Reference Documentation.^] +> Explore the comprehensive API documentation for the {pluginname} Premium plugin at https://exportpdf.api.tiny.cloud/v2/convert/docs[{pluginname} API Reference Documentation.^] diff --git a/modules/ROOT/pages/fullpagehtml.adoc b/modules/ROOT/pages/fullpagehtml.adoc index 2d96f53856..b89d4dc369 100644 --- a/modules/ROOT/pages/fullpagehtml.adoc +++ b/modules/ROOT/pages/fullpagehtml.adoc @@ -112,6 +112,8 @@ include::partial$configuration/fullpagehtml-default-body-style.adoc[leveloffset= include::partial$configuration/fullpagehtml-hide-in-source-view.adoc[leveloffset=+1] +include::partial$configuration/fullpagehtml-getcontent-setcontent.adoc[leveloffset=+1] + include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] include::partial$toolbar-button-ids/{plugincode}-toolbar-buttons.adoc[leveloffset=+1] diff --git a/modules/ROOT/pages/html-to-pdf-converter-api-v2.adoc b/modules/ROOT/pages/html-to-pdf-converter-api-v2.adoc new file mode 100644 index 0000000000..ba9bbf49c2 --- /dev/null +++ b/modules/ROOT/pages/html-to-pdf-converter-api-v2.adoc @@ -0,0 +1,45 @@ += HTML to PDF Converter API +:navtitle: HTML to PDF Converter API +:description: The HTML to PDF Converter API service provides the ability to generate PDF files directly without the need for an editor. +:description_short: Generate a .pdf file directly from any application. +:keywords: service, exportpdf, export to pdf, HTML to PDF Converter API +:pluginname: Export to PDF +:servicename: HTML to PDF Converter API + +[NOTE] +This is a premium feature. link:https://www.tiny.cloud/contact/[Contact us] to purchase a license or to learn more about our tailored offers. Note that any documents generated without authentication will be watermarked. + +== Overview + +The {servicename} is a powerful tool that seamlessly integrates advanced document conversion capabilities into developers workflows. This API allows for the efficient conversion of HTML content into PDF documents, catering to a wide range of use cases. + +The API uses a nested configuration structure and supports per-page headers and footers, PDF metadata, security, and digital signatures. + +=== Key Features + +* **Versatile Document Conversion**: Convert HTML content into high-quality PDF documents, providing flexibility for various document needs. +* **Preprocessing Capabilities**: Pre-process content before conversion, such as resolving merge tags, ensuring fully customized and ready-to-use PDF documents. +* **Customizable Output**: Tailor the appearance and structure of the converted PDFs with customizable output xref:html-to-pdf-converter-api-v2.adoc#options[options], including page sizes, margins, and formatting. +* **Scalability**: Handle large volumes of PDF documents with consistent performance and reliability, supporting business growth and varying demands. +* **Ease of Integration**: Integrate the API into existing workflows easily with comprehensive documentation and straightforward API endpoints. +* **Security and Compliance**: Ensure secure document conversion processes that adhere to data protection standards and industry regulations, crucial for handling sensitive information. + +[[options]] +== Flexible Configuration Options + +Tailor your PDF documents to suit your needs: + +* **Custom CSS Styling:** Apply link:https://exportpdf.api.tiny.cloud/v2/convert/docs#section/General/CSS[custom CSS^] styles to your PDFs for brand consistency and enhanced presentation. +* **Header and Footer Options:** Add link:https://exportpdf.api.tiny.cloud/v2/convert/docs#section/Export-to-PDF-(v2)/Headers-and-footers[headers and footers^], and other branding elements to your PDF documents for a professional touch. +* **Page Formatting:** Control page settings such as orientation, link:https://exportpdf.api.tiny.cloud/v2/convert/docs#section/Export-to-PDF-(v2)/Document[document^] (margins, size), and link:https://exportpdf.api.tiny.cloud/v2/convert/docs#section/Export-to-PDF-(v2)/Metadata[metadata^] to optimize readability. + +== Ideal for Various Use Cases + +* **Aggregating Content from Multiple Sources**: Combine content from various editors into a single cohesive PDF document, simplifying content management for organizations using multiple tools. +* **Centralized Document Management**: Store generated PDF documents centrally for better organization and accessibility, facilitating team collaboration and efficient document retrieval. +* **Preprocessing and Customization**: Pre-process content to resolve merge tags and customize PDF document formatting, ensuring that the final output meets specific requirements and is ready for immediate use. +* **Large-Scale Document Processing**: Utilize the API's scalability to handle large volumes of PDF documents, maintaining consistent performance and reliability, essential for growing businesses. + +== PDF Converter API Reference + +> Explore the comprehensive API documentation at link:https://exportpdf.api.tiny.cloud/v2/convert/docs[PDF Converter API Reference documentation.^] diff --git a/modules/ROOT/pages/non-editable-content-options.adoc b/modules/ROOT/pages/non-editable-content-options.adoc index b8a4c15512..b4bb8f75ec 100644 --- a/modules/ROOT/pages/non-editable-content-options.adoc +++ b/modules/ROOT/pages/non-editable-content-options.adoc @@ -13,6 +13,9 @@ liveDemo::editable-class-and-editable-root[] [NOTE] Visit xref:ie-template-creation.adoc[Template creation example] for a practical example of multi-root editing. +// allow_noneditable +include::partial$configuration/allow_noneditable.adoc[] + // noneditable_class include::partial$configuration/noneditable_class.adoc[] diff --git a/modules/ROOT/pages/release-notes.adoc b/modules/ROOT/pages/release-notes.adoc index 5e43e257b7..30c8e84d5a 100644 --- a/modules/ROOT/pages/release-notes.adoc +++ b/modules/ROOT/pages/release-notes.adoc @@ -8,6 +8,12 @@ This section lists the releases for {productname} {productmajorversion} and the [cols="1,1"] |=== +a| +[.lead] +xref:8.4.0-release-notes.adoc#overview[{productname} 8.4.0] + +Release notes for {productname} 8.4.0 + a| [.lead] xref:8.3.2-release-notes.adoc#overview[{productname} 8.3.2] diff --git a/modules/ROOT/pages/revisionhistory.adoc b/modules/ROOT/pages/revisionhistory.adoc index a8a2dbac99..2aaa4390f7 100644 --- a/modules/ROOT/pages/revisionhistory.adoc +++ b/modules/ROOT/pages/revisionhistory.adoc @@ -124,6 +124,8 @@ include::partial$configuration/revisionhistory_css_url.adoc[leveloffset=+1] include::partial$configuration/revisionhistory_diff_classes.adoc[leveloffset=+1] +include::partial$plugins/revisionhistory-open-view.adoc[] + include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] diff --git a/modules/ROOT/pages/suggestededits.adoc b/modules/ROOT/pages/suggestededits.adoc index b7a9d9bb6e..ebf771135e 100644 --- a/modules/ROOT/pages/suggestededits.adoc +++ b/modules/ROOT/pages/suggestededits.adoc @@ -129,6 +129,8 @@ include::partial$configuration/suggestededits_access.adoc[leveloffset=+1] include::partial$configuration/suggestededits_auto_approve.adoc[leveloffset=+1] +include::partial$plugins/suggestededits-open-view.adoc[] + include::partial$configuration/user_id.adoc[leveloffset=+1] include::partial$configuration/fetch_users.adoc[leveloffset=+1] diff --git a/modules/ROOT/pages/table-options.adoc b/modules/ROOT/pages/table-options.adoc index f2a826e75a..96006bef9d 100644 --- a/modules/ROOT/pages/table-options.adoc +++ b/modules/ROOT/pages/table-options.adoc @@ -20,6 +20,10 @@ include::partial$configuration/table_default_attributes.adoc[leveloffset=+1] include::partial$configuration/table_default_styles.adoc[leveloffset=+1] +include::partial$configuration/table_default_header_rows.adoc[leveloffset=+1] + +include::partial$configuration/table_default_header_cols.adoc[leveloffset=+1] + == Interacting with tables include::partial$configuration/table_clone_elements.adoc[leveloffset=+1] diff --git a/modules/ROOT/pages/tinydrive-getting-started.adoc b/modules/ROOT/pages/tinydrive-getting-started.adoc index 0bdbb540bc..22a1a69531 100644 --- a/modules/ROOT/pages/tinydrive-getting-started.adoc +++ b/modules/ROOT/pages/tinydrive-getting-started.adoc @@ -25,7 +25,7 @@ The steps required for setting up {cloudfilemanager} are: If you do not have a {cloudname} API key, you can sign up for a trial or purchase a subscription on the link:{pricingpage}/[{companyname} pricing page]. -include::partial$auth/private-public-key-pairs-for-tiny-cloud-services.adoc[leveloffset=+1] +include::partial$auth/private-public-key-pairs-for-tiny-cloud-services.adoc[] [[set-up-a-json-web-token-jwt-provider-endpoint]] == 3. Set up a JSON Web Token (JWT) Provider endpoint diff --git a/modules/ROOT/pages/tinymce-and-screenreaders.adoc b/modules/ROOT/pages/tinymce-and-screenreaders.adoc index 7d16a59194..31310d8c6b 100644 --- a/modules/ROOT/pages/tinymce-and-screenreaders.adoc +++ b/modules/ROOT/pages/tinymce-and-screenreaders.adoc @@ -43,6 +43,11 @@ To focus on the editor toolbars, press *Alt+F10* (or *⌥+F10*); which moves the To open submenus or grid selections on toolbar buttons, use the *Enter*, *Return*, *Spacebar*, or *Down Arrow* keys. To close submenus or grids, use the *Esc* key. Some toolbar buttons with menus will present a grid of options rather than a menu, such as the background color selector. These grids can be navigated with the arrow keys and closed using the *Esc* key. +[[navigating-element-path]] +=== Navigating the element path + +To focus on the element path in the status bar, press *Alt+F11* (or *⌥+F11*). The element path is exposed as a WAI-ARIA `group` with a localized accessible name (`Element Path` in English). Use the *Left Arrow* and *Right Arrow* keys to move between segments. To return focus to the content area, use the *Esc* key. + === Navigating dialogs Dialogs such as *Insert/Edit Image* are opened from either a menu item or a toolbar button. Some dialogs contain multiple tabs or pages of options. To change tabs or pages, use the arrow keys; the highlighted tab will become active immediately. Use the *Tab* key to navigate between the dialog options on the selected dialog tab. The *Save* dialog button stores the changes, and the *Cancel* dialog button or the *Esc* key discards changes. diff --git a/modules/ROOT/pages/tinymceai-actions.adoc b/modules/ROOT/pages/tinymceai-actions.adoc new file mode 100644 index 0000000000..6edd282493 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-actions.adoc @@ -0,0 +1,300 @@ += TinyMCE AI Quick Actions +:navtitle: Quick Actions +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: Quick actions feature for TinyMCE AI plugin +:description_short: quick actions feature +:keywords: AI, quick actions, actions, tinymceai +:page-role: -toc + +Quick actions simplify routine content transformations by offering one-click AI-powered suggestions directly within the editor. This feature enhances speed, relevance, and usability, particularly for repeatable or simple tasks. For suggestions that change the document, the editor shows a preview and applies changes only after each suggestion is accepted or rejected. For actions that only open Chat with a pre-filled prompt, see xref:tinymceai-chat.adoc[Chat]. The API includes the ability to call default and optimized system actions, or to define your own. + +[[stateless-actions]] +Preview transformations and Actions API calls are **stateless**: each invocation is independent and does not retain prior interactions, unlike ongoing xref:tinymceai-chat.adoc[Chat] conversations. Quick Actions that open Chat with a pre-filled prompt hand off to the Conversations API instead. + +The Quick Actions feature is available as part of the `+tinymceai+` plugin for {productname} and through the Actions API. This page covers both: + +* Plugin sections describe user-facing features and configuration (xref:tinymceai.adoc#options-quickactions[Quick Actions configuration]). +* API sections cover REST API access (starting at xref:tinymceai-actions.adoc#actions-api[Actions API]). + +[[demo]] +== Demo + +The live demo loads the full {productname} example with Chat, Quick Actions, and Review on the toolbar. + +liveDemo::tinymceai-actions[] + +[[quick-actions-and-review]] +== Quick Actions and Review + +Quick Actions fit transforming a selection or section (for example grammar fixes, translation, or tone). Review fits whole-document quality analysis with suggestions in the Review sidebar and the document. + +Both Quick Actions and Review can propose edits that apply only after acceptance or rejection. The main differences are scope and where the work happens in the editor: + +* *Quick Actions*: Operate on a selection or section (including the full document when the scope includes it). The Quick Actions menu runs one-off operations such as Chat with a pre-filled prompt, preview transformations, translation, and custom actions. +* *Review*: Always analyzes the entire document in read-only Review mode. Suggestions appear in the Review sidebar and in the document. See xref:tinymceai-review.adoc[Review] for details. + +[[integration]] +== Integration + +To start using the Quick Actions feature, first load the {pluginname} plugin in the editor configuration. See xref:tinymceai.adoc[Plugin Reference] for installation and enabling AI features. + +Enabling the `+tinymceai+` plugin registers Chat, Quick Actions, and Review toolbar controls. Those controls appear on the main toolbar only when the xref:toolbar-configuration-options.adoc#toolbar[`+toolbar+`] configuration includes them: the default toolbar (when `+toolbar+` is omitted or `+true+`) adds `+tinymceai-chat+`, `+tinymceai-quickactions+` image:icons/ai-prompt.svg[Quick Actions icon,24px], `+tinymceai-review+`, and related items; with a custom `+toolbar+` value, each control must be listed or it remains hidden. + +To show Quick Actions on the Quickbars selection toolbar, add the desired identifiers to the xref:quickbars.adoc#quickbars_selection_toolbar[`+quickbars_selection_toolbar+`] option. + +image::tinymceai/tinymce-ai-quick-actions-change-tone-flyout-submenu.png[{pluginname} Quick Actions dropdown in the toolbar,width=80%] + + +Finally, individual Quick Actions can also be added to the toolbar as shortcuts for easier access. + +For example, add the `ai-quickactions-improve-writing` image:icons-premium/improve-writing.svg[Improve Writing icon,24px] button, or the `ai-chat-explain` image:icons-premium/explain.svg[Explain icon,24px] button (find it in the demo above). Whole categories can be added to the toolbar as well. Learn more about xref:tinymceai-actions.adoc#default-actions[available actions]. + +The final example configuration looks as follows: + +[source,js] +---- +tinymce.init({ + selector: '#editor', + plugins: 'tinymceai', + toolbar: 'undo redo tinymceai-chat tinymceai-quickactions tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image', + tinymceai_quickactions_menu: [ + 'ai-quickactions-chat-prompts', + 'ai-quickactions-improve-writing', + 'ai-quickactions-continue-writing', + 'ai-quickactions-check-grammar', + 'ai-quickactions-change-length', + 'ai-quickactions-change-tone', + 'ai-quickactions-translate' + ], + + // Configure a sub-menu (e.g., chat commands) + tinymceai_quickactions_chat_prompts: [ + 'ai-chat-explain', + 'ai-chat-summarize', + 'ai-chat-highlight-key-points' + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- + +[NOTE] +==== +AI controls are not added to the xref:quickbars.adoc#quickbars_selection_toolbar[`+quickbars_selection_toolbar+`] automatically; add the desired toolbar button identifiers to that option when they should appear there. + +For example: + +[source,js] +---- +tinymce.init({ + selector: 'textarea#editor', + plugins: 'quickbars tinymceai', + quickbars_selection_toolbar: 'tinymceai-quickactions bold italic', +}); +---- +==== + +[[types-of-actions]] +== Types of actions + +There are two types of actions available in the quick actions feature: + +* Chat actions, such as "Explain" or "Summarize", open the xref:tinymceai-chat.adoc[Chat] interface with the selected text added as context and automatically start the conversation with a pre-filled prompt. + +* Preview actions such as _Continue writing_, _Make shorter_, _Improve writing_, and _Fix grammar_ show a preview of your document where suggested edits appear so you can review them and apply or skip each change. + +Custom actions let integrators define whether each action opens Chat or shows a preview. See xref:tinymceai-actions.adoc#custom-actions[Custom Actions]. + +[[default-actions]] +== Default Actions + +By default, the Quick Actions feature includes several built-in actions that speed up the content editing process. All Quick Actions can be accessed through the menu button image:icons/ai-prompt.svg[Quick Actions icon,24px] (`tinymceai-quickactions`) or individually when selected by the integrator in the xref:toolbar-configuration-options.adoc[editor toolbar configuration]. Whole action categories can be added to the toolbar as well. + +Custom actions can be added to the list, and default actions can be removed or reordered by configuring `tinymceai_quickactions_menu`. See xref:tinymceai-actions.adoc#configuring-quick-actions-menu[Configuring Quick Actions menu]. + +[[quick-actions-reference-table]] +The following table lists built-in Quick Actions. + +* The **Editor** column is the label in the Quick Actions menu when that action is available in the editor. +* The **Menu or control ID** column lists values for `tinymceai_quickactions_menu`, `tinymceai_quickactions_chat_prompts`, `tinymceai_quickactions_change_tone_menu`, and the toolbar when adding individual controls (see xref:tinymceai-actions.adoc#configuring-quick-actions-menu[Configuring Quick Actions menu]). +* The **System `actionName` or quick-action prompt id** column is the service identifier. Preview actions use a system `actionName` with the xref:tinymceai-actions.adoc#actions-api[Actions API]. Chat actions use a quick-action prompt id and xref:tinymceai-chat.adoc[Chat] with a pre-filled prompt, not the system actions API. + +[cols="1,3,2,3,1,1",options="header"] +|=== +|Editor |Menu or control ID |System `actionName` |Description |Editor UI |API + +|**Explain** |`ai-chat-explain` |`explain` |Opens Chat with the selected text and a pre-filled prompt. Uses the Conversations API, not the system actions path. |✓ |— + +|**Summarize** |`ai-chat-summarize` |`summarize` |Opens Chat with a summarize prompt. Uses the Conversations API, not the system actions path. |✓ |— + +|**Highlight key points** |`ai-chat-highlight-key-points` |`highlight-key-points` |Opens Chat with a key-points prompt. Uses the Conversations API, not the system actions path. |✓ |— + +|**Improve Writing** |`ai-quickactions-improve-writing` |`improve-writing` |Enhance clarity, word choice, and sentence structure. |✓ |✓ + +|**Continue Writing** |`ai-quickactions-continue-writing` |`continue` |Complete unfinished sentences, paragraphs, or entire documents. |✓ |✓ + +|**Fix Grammar** |`ai-quickactions-check-grammar` |`fix-grammar` |Correct grammar, spelling, and punctuation errors. |✓ |✓ + +|**Adjust length** |`ai-quickactions-change-length` |`make-shorter`, `make-longer` |Shorten or lengthen the selection. Each option is its own system action. |✓ |✓ + +|**Adjust Tone** +a| +`ai-quickactions-change-tone` + +`ai-quickactions-tone-casual` + +`ai-quickactions-tone-direct` + +`ai-quickactions-tone-friendly` + +`ai-quickactions-tone-confident` + +`ai-quickactions-tone-professional` +a| +`make-tone-casual` + +`make-tone-direct` + +`make-tone-friendly` + +`make-tone-confident` + +`make-tone-professional` +|Change writing style; each menu option maps to its own system action. |✓ |✓ + +|**Translate** +a| +`ai-quickactions-translate` + +`ai-quickactions-translate-english` + +`ai-quickactions-translate-spanish` + +`ai-quickactions-translate-russian` + +`ai-quickactions-translate-swedish` + +`ai-quickactions-translate-german` + +`ai-quickactions-translate-japanese` + +`ai-quickactions-translate-portuguese` + +`ai-quickactions-translate-korean` + +`ai-quickactions-translate-italian` + +`ai-quickactions-translate-chinese` +a| +`translate` +|Convert content between languages. Request body uses `args: { language: string }` with values such as `english`, `spanish`, `russian`, `swedish`, `german`, `japanese`, `portuguese`, `korean`, `italian`, or `chinese`. Configure the editor submenu with `tinymceai_languages`. |✓ |✓ +|=== + +[NOTE] +==== +* A checkmark in the **Editor UI** column means the action can appear when included in `tinymceai_quickactions_menu` (and related sub-menu options such as `tinymceai_quickactions_chat_prompts`). +* A checkmark in the **API** column means the action is invoked through the system Actions API path `+/v1/actions/system/{actionName}/calls+`. An em dash means the command is Chat-based and uses the Conversations API instead. +==== + +For system action endpoints, schemas, and streaming details, see the https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] reference. + +[[custom-actions]] +== Custom Actions + +The `tinymceai_quickactions_custom` configuration property allows adding new commands to the Quick actions feature. The items can be of type `action` (a quick action that shows a preview of the editor content with AI suggestions so changes can be reviewed before applying) or type `chat` (which opens the chat interface for a conversation related to the prompt and selection). The `title` is used in the menu items, while the `prompt` is what is actually sent to the AI. The `model` is required for `action` type commands. Learn more about xref:tinymceai-actions.adoc#types-of-actions[types of actions]. + +[source,js] +---- +tinymce.init({ + selector: '#editor', + plugins: 'tinymceai', + toolbar: 'tinymceai-quickactions', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + }, + tinymceai_quickactions_custom: [ + { + title: 'Add a quote from a famous person', + prompt: 'Add a quote from a known person, which would make sense in the context of the selected text.', + type: 'action', + model: 'gemini-2-5-flash' + }, + { + title: 'Summarize in 5 bullet points', + prompt: 'Summarize the selected text in 5 bullet points.', + type: 'chat' + }, + { + title: 'Rewrite adding more sarcasm', + prompt: 'Rewrite using a sarcastic tone.', + type: 'action', + model: 'gemini-2-5-flash' + } + ] +}); +---- + +[[configuring-quick-actions-menu]] +== Configuring Quick Actions menu + +Which actions appear in the Quick Actions menu can be configured by specifying the list of actions to include. The `tinymceai_quickactions_menu` configuration option controls the main menu items. + +Sub-menus have their own configuration options: + +* `tinymceai_quickactions_chat_prompts`: Controls items in the **"Chat commands"** sub-menu +* `tinymceai_quickactions_change_tone_menu`: Controls items in the **"Change tone"** sub-menu +* `tinymceai_languages`: Controls languages in the **"Translate"** sub-menu + +[source,js] +---- +tinymce.init({ + selector: '#editor', + plugins: 'tinymceai', + toolbar: 'tinymceai-quickactions', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + }, + // Configure the main Quick Actions menu + tinymceai_quickactions_menu: [ + 'ai-quickactions-chat-prompts', + 'ai-quickactions-improve-writing', + 'ai-quickactions-continue-writing', + 'ai-quickactions-check-grammar', + 'ai-quickactions-change-length', + 'ai-quickactions-change-tone', + 'ai-quickactions-translate', + 'ai-quickactions-custom' + ], + // Configure a sub-menu (e.g., chat commands) + tinymceai_quickactions_chat_prompts: [ + 'ai-chat-explain', + 'ai-chat-summarize', + 'ai-chat-highlight-key-points' + ] +}); +---- + +[[actions-api]] +== Actions API + +The Quick Actions plugin feature is built on top of the Actions API, which provides REST API access to action functionality. Actions are fast, stateless operations—each request is independent, as described under xref:tinymceai-actions.adoc#stateless-actions[Stateless actions]. For suggestions that change the document, the preview flow applies edits only after each suggestion is accepted or rejected. Actions that only open Chat with a pre-filled prompt use the Conversations API; see xref:tinymceai-chat.adoc[Chat]. + +Actions use streaming output with Server-Sent Events for real-time feedback as results are generated. + +[[actions-system-actions-api]] +=== System Actions + +Built-in Quick Actions—including identifiers, descriptions, and whether each command uses the system Actions API or Chat (Conversations API)—are summarized in xref:tinymceai-actions.adoc#quick-actions-reference-table[Default Actions]. + +For endpoint details, request and response schemas, authentication, and streaming behavior for system `actionName` calls, see https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API]. + +[[actions-custom-actions-api]] +=== Custom Actions through the API + +In addition to system actions, custom actions can be created for specific use cases through the API. Custom actions allow specialized content transformations using custom prompts to control AI behavior. + +Unlike system actions that use default identifiers, custom actions use a unified endpoint where the transformation behavior is defined through a prompt parameter. See https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] for the custom actions endpoint and implementation details. + +Custom actions require the `ai:actions:custom` permission in the JWT token. + +[[actions-streaming]] +=== Streaming Responses + +Actions use Server-Sent Events (SSE) for real-time streaming results. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information. + +[[actions-api-reference]] +=== API Reference + +The https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] reference (interactive OpenAPI documentation) is the full source for system and custom action endpoints, request and response schemas, authentication, worked examples, and streaming action responses. + +[[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. diff --git a/modules/ROOT/pages/tinymceai-api-overview.adoc b/modules/ROOT/pages/tinymceai-api-overview.adoc new file mode 100644 index 0000000000..3246fa4e08 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-api-overview.adoc @@ -0,0 +1,41 @@ += TinyMCE AI API Overview + +:navtitle: API Overview +:description: Overview of TinyMCE AI service features and capabilities +:description_short: API Overview +:keywords: AI, API, AI service, overview, tinymceai + +The TinyMCE AI REST API enables AI integration within your application using the same infrastructure as the TinyMCE AI plugin, but without being tied to the editor. Integrate with multiple AI agents via one API, accessing all functionality from the Chat, Review, and Quick Actions features, with your own custom UI and workflows. + +[NOTE] +==== +**API Reference**: The complete API documentation with all endpoints, parameters, request/response schemas, and interactive examples is available at link:https://tinymceai.api.tiny.cloud/docs[TinyMCE AI API Documentation] +==== + +[[getting-started]] +== Getting Started + +New to TinyMCE AI? Start with the xref:tinymceai-api-quick-start.adoc[Quick Start] guide to set up the environment, generate access credentials, and make the first API call. + +[[tinymce-ai-features]] +== TinyMCE AI features + +* xref:tinymceai-chat.adoc[**Chat**]: Interactive AI chats with history and persistent context. +* xref:tinymceai-review.adoc[**Review**]: Content analysis and proofreading, optimized for larger content. +* xref:tinymceai-actions.adoc[**Quick Actions**]: Fast, stateless operations for specific tasks. + +[[architecture]] +== Architecture + +The following pages cover the AI service architecture and configuration. + +* xref:tinymceai-models.adoc[**Models**]: AI model selection, capabilities, and configuration. +* xref:tinymceai-streaming.adoc[**Streaming**]: Real-time streaming of AI-generated responses. +* xref:tinymceai-permissions.adoc[**Permissions**]: How to control user access to features. +* xref:tinymceai-limits.adoc[**Limits**]: Rate limits, context size limits, and file restrictions. + +[[resources-and-support]] +== Resources and Support + +* **API Documentation**: link:https://tinymceai.api.tiny.cloud/docs[Complete API reference for TinyMCE AI]. +* **Customer Support**: link:https://www.tiny.cloud/contact/[Contact us] to get help from the support team or speak with sales. diff --git a/modules/ROOT/pages/tinymceai-api-quick-start.adoc b/modules/ROOT/pages/tinymceai-api-quick-start.adoc new file mode 100644 index 0000000000..28c35d7327 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-api-quick-start.adoc @@ -0,0 +1,95 @@ += TinyMCE AI API Quick Start + +:navtitle: API Quick Start +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: Quick start guide for TinyMCE AI service +:description_short: API quick start guide +:keywords: AI, quick start, API, AI service, tinymceai, setup + +This guide helps users get up and running with the {pluginname} service. + +[TIP] +==== +Sign up for the link:{accountsignup}[{productname} Premium Features 14-day free trial] to test this feature first. + +The {productname} Premium Features free trial allows for testing SaaS services. For on-premises solutions, link:{contactpage}[contact us]. +==== + +== Getting Started + +Every request to the {pluginname} APIs must include a JWT signed with a keypair from the Customer Portal. Signing must run on the application server so private keys are never exposed to the browser. The editor supplies each token by calling xref:tinymceai.adoc#tinymceai_token_provider[+tinymceai_token_provider+], which is typically implemented as a `fetch` to a backend URL that returns a signed JWT for the signed-in user. + +To start using the service: + +* Sign up for one of the link:{pricingpage}[self-service plans], or link:{contactpage}[contact us] to purchase the {pluginname} license. +* Generate access credentials in the link:{accountpageurl}[Customer Portal]. +* During a {cloudname} trial, the xref:tinymceai-jwt-authentication-intro.adoc#trial-demo-identity-service[demo identity service] can issue JWTs (JSON Web Tokens) for testing without a custom token endpoint. See xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. +* For production, add <>: a backend HTTPS route that signs short-lived JWTs with the portal keypair for each authorized end user. See xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication] for the full flow and code examples. + +All steps are explained in detail below. + +[[get-the-tinymce-ai-license]] +== Get the {pluginname} license + +{pluginname} can be purchased as a plugin for selected tiers of the self-service plans. Details are available on the link:{pricingpage}[pricing page]. + +For custom plans, link:{contactpage}[contact us] directly. + +For testing purposes, sign up for the link:{accountsignup}[free trial]. + +After signing up, access to the link:{accountpageurl}[customer dashboard (Customer Portal)] is provided. + +[[log-in-to-the-customer-portal]] +== Log in to the Customer Portal + +Log in to the link:{accountpageurl}[Customer Portal] and navigate to link:{accountjwturl}["JWT Keys"]. + +image::tinymceai/tinymce-ai-customer-portal-jwt-keys-page.png[JWT Keys page showing Secure Keys List, Generate New Keypair, and Import Public Key sections,width=100%] + +For trial setup without a custom token endpoint, see xref:tinymceai-jwt-authentication-intro.adoc#trial-demo-identity-service[Trial: demo identity service] in xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. + +[[create-token-endpoint]] +== Create token endpoint + +The next step for production is to create a security token endpoint in the application backend. That endpoint securely authorizes end users to use {pluginname} features based on their permissions and access rights. The editor calls this endpoint through xref:tinymceai.adoc#tinymceai_token_provider[+tinymceai_token_provider+] in xref:tinymceai.adoc[Plugin Reference]. API integrations use the same JWT when calling `https://tinymceai.api.tiny.cloud`; see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication] for request details. + +[[writing-your-own-token-endpoint]] +=== Writing your own token endpoint + +To create a custom security token endpoint, generate a keypair in the link:{accountjwturl}[JWT Keys] area of the Customer Portal. In the "Generate New Keypair" section, enter a description, select the key length, and click "Add Key". Alternatively, use "Import Public Key" to add an existing key. + +Once the keypair is created, use it to sign JWTs in the token endpoint. For step-by-step implementation instructions with complete code examples, see: + +* xref:tinymceai-with-jwt-authentication-nodejs.adoc[JWT authentication (Node.js)]: Complete Node.js implementation guide +* xref:tinymceai-with-jwt-authentication-php.adoc[JWT authentication (PHP)]: Complete PHP implementation guide + +[[api-integration]] +== API Integration + +All features are accessible through the API at `https://tinymceai.api.tiny.cloud` with xref:tinymceai-jwt-authentication-intro.adoc[JWT authentication]. + +For an overview of all API features, see xref:tinymceai-api-overview.adoc[API Overview]. + +For feature documentation and API access information, see: + +* xref:tinymceai-chat.adoc#conversations-api[Chat]: Interactive AI discussions and document analysis through the Conversations API. +* xref:tinymceai-review.adoc#reviews-api[Review]: Content improvement and quality analysis through the Reviews API. +* xref:tinymceai-actions.adoc#actions-api[Quick Actions]: Content transformation through the Actions API. +* xref:tinymceai-streaming.adoc[Streaming]: Real-time AI interactions with code examples. + +link:https://tinymceai.api.tiny.cloud/docs[Complete API Documentation]: Full API reference with interactive examples for all endpoints. + +[[next-steps]] +== Next Steps + +After setting up the JWT endpoint, continue with: + +* xref:tinymceai-models.adoc[AI Models]: Choose the right model for your use case. +* xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verify model limits]: Match the configured model id to `GET /v1/models/{version}` and read `limits` and `capabilities`. +* xref:tinymceai-permissions.adoc[Permissions]: Set up user access control for production. +* xref:tinymceai-streaming.adoc[Streaming]: Learn how to handle real-time streaming responses. +* xref:tinymceai-chat.adoc#conversations-api[Chat API]: Start with interactive AI discussions. +* xref:tinymceai-review.adoc#reviews-api[Review API]: Add content improvement features. +* xref:tinymceai-actions.adoc#actions-api[Quick Actions API]: Implement content transformation. +* xref:tinymceai-api-overview.adoc[API Overview]: Optional high-level map of Chat, Review, Quick Actions, and related resources. diff --git a/modules/ROOT/pages/tinymceai-chat.adoc b/modules/ROOT/pages/tinymceai-chat.adoc new file mode 100644 index 0000000000..133c94430a --- /dev/null +++ b/modules/ROOT/pages/tinymceai-chat.adoc @@ -0,0 +1,246 @@ += TinyMCE AI Chat +:navtitle: Chat +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: AI Chat feature for TinyMCE AI plugin +:description_short: AI Chat feature +:keywords: AI, chat, conversations, tinymceai +:page-role: -toc + +The {pluginname} Chat is a conversational AI feature that facilitates rich, multi-turn interactions between users and an AI Assistant. It provides context setting, model selection, chat history, and capabilities for web search and reasoning. + +The Chat feature is available as part of the `+tinymceai+` plugin for {productname} and through the https://tinymceai.api.tiny.cloud/docs#tag/Conversations[Conversations API]. This page covers both: + +* Plugin sections describe built-in user-facing features and configuration (xref:tinymceai.adoc#options-chat[Chat configuration]). +* API sections cover REST API access (starting at xref:tinymceai-chat.adoc#conversations-api[Conversations API]). + +[[demo]] +== Demo + +liveDemo::tinymceai[] + +[[using-chat]] +== Using Chat + +The <> above shows the Chat sidebar open beside the document. The following sections describe how Chat behaves in the editor. + +[[working-with-the-document]] +=== Working with the document + +{pluginname} operates directly within the context of the document. Users can ask questions about specific sections, request a full-document proofreading, and more. + +By enabling image:icons-premium/web-search.svg[Web search icon,24px] xref:tinymceai-chat.adoc#web-search[Web search] or image:icons-premium/reasoning.svg[Reasoning icon,24px] xref:tinymceai-chat.adoc#reasoning[Reasoning], the chat capabilities can be extended, allowing the chat to look up information online and tackle complex tasks step by step. + +[[making-changes-to-the-content]] +=== Making changes to the content + +Users can chat with the AI and use it to introduce changes to the document. Ask it to _"Summarize the document"_, _"Turn this report into a one-page executive summary"_, or _"Suggest better section titles and subheadings"_. The AI will then propose a series of changes to the document that can be xref:tinymceai-chat.adoc#previewing-changes[reviewed] and xref:tinymceai-chat.adoc#applying-changes[accepted or discarded one by one]. {pluginname} works directly on the content instead of requiring copy-paste of chat transcripts. + +[[brainstorming]] +=== Brainstorming + +The chat feature accelerates the creative process. Begin with a blank document and ask the AI for ideas. Build content step by step by chatting and applying changes. Then review or have the AI rewrite the final draft for best results, all in one place. + +[[integration]] +== Integration + +To start using the Chat feature, add `+tinymceai+` to the plugins option. This will automatically add the image:icons-premium/ai-assistant.svg[Chat icon,24px] Chat toolbar button and menu item to the default {productname} toolbar and menu. + +See xref:tinymceai.adoc[Plugin Reference] for more information regarding installation and enabling AI features. + +[[available-models]] +== Available models + +Users can select the desired AI model for their conversation from a dropdown at the bottom of the chat. + +image::tinymceai/tinymce-ai-chat-model-selector-dropdown-open.png[{pluginname} Chat available models dropdown,width=80%] + +The model can be changed at any time using the same dropdown. Messages sent after a change use the newly selected model. + +[[model-selection-configuration]] +=== Configuration + +Model selection for AI chat can be configured using these options: + +* `tinymceai_default_model`: Sets the default model for new chat sessions. The value is a **model configuration id** (for example `+agent-1+`, `+gpt-5.4+`, or `+claude-4-5-haiku+`) that must be among the models allowed by the JWT and subscription. The xref:tinymceai-models.adoc#supported-models-table[Supported Models] table lists the documented names and ids. For the list the service returns for a given environment, use `GET /v1/models/{version}` or the in-editor model selector when xref:tinymceai.adoc#tinymceai_allow_model_selection[+tinymceai_allow_model_selection+] is enabled; see xref:tinymceai-models.adoc#checking-compatibility[Checking compatibility]. +* `tinymceai_allow_model_selection`: When `true`, users can pick from models the service exposes in the UI; when `false`, the default model is used without a selector (defaults to `true`). + +[source,js] +---- +tinymce.init({ + selector: '#editor', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_default_model: 'claude-4-5-haiku', + tinymceai_allow_model_selection: true, + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- + +[[web-search]] +=== Web search + +Web search in Chat allows the AI to access and retrieve real-time information from the internet. Instead of relying only on pre-trained knowledge, the model can search the web to find up-to-date facts, verify details, and provide more accurate, current answers. + +Some models use web search automatically, while others may require manual activation. Whether the "Enable web search" button image:icons-premium/web-search.svg[Web search icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support web search, use the toggle button to enable it. + +[[reasoning]] +=== Reasoning + +Reasoning in Chat models turns on the ability to think through problems, draw logical conclusions, and make sense of complex information. It enables the model to analyze context, connect ideas, and produce well-structured, coherent answers beyond simple pattern matching. + +Some models use reasoning automatically, while others may require manual activation. Whether the "Enable reasoning" button image:icons-premium/reasoning.svg[Reasoning icon,24px] below the prompt input needs to be toggled depends on the model and sometimes even how the prompt is worded. For models that support reasoning, use the toggle button to enable it. + +[[adding-context-to-conversations]] +== Adding context to conversations + +The AI chat can work with the document and beyond. Use the "Add context" image:icons/plus.svg[Add context icon,24px] button below the prompt input to add URLs, files, and external resources to the conversation. + +Uploaded files can include PDF, DOCX, common image formats, Markdown, HTML, and plain text. Per-file size limits, attachment counts, and similar caps depend on the selected model; see xref:tinymceai-models.adoc#file-processing-limits[File processing limits]. + +image::tinymceai/tinymce-ai-chat-add-context-source-menu.png[{pluginname} Chat add context user interface,width=80%] + +Ask the AI about specific resources, for instance, _"Describe the attached image"_ or _"Summarize the key points from the attached Word document"_. The AI will analyze those resources and provide information that can be easily used in the document. + +External resources enable seamless integration of knowledge bases and other centralized data into AI chat conversations. Instead of uploading documents each time, they can be selected from a list and referenced during the conversation. + +[[context-configuration]] +=== Adding custom context sources + +Built-in options for adding the current document, URLs, and files to the conversation context are always available to users. There is no configuration option to enable or disable these built-in options. + +To add custom external sources for users to select from, configure: + +* `tinymceai_chat_fetch_sources`: Supplies the list of sources shown in the menu (for example from a database or API). +* `tinymceai_chat_fetch_source`: Loads the content for a selected source ID so it can be sent to the model as context. + +Full schemas, return types, and examples are documented under xref:tinymceai.adoc#tinymceai_chat_fetch_sources[Chat configuration options]. + +[source,js] +---- +tinymce.init({ + selector: '#editor', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_chat_fetch_sources: async () => [ + { + label: 'My Documents', + sources: [ + { id: 'doc-1', label: 'Document 1', type: 'file' }, + { id: 'url-1', label: 'Web Page', type: 'web-resource' } + ] + } + ], + tinymceai_chat_fetch_source: async (id) => { + const res = await fetch(`/api/documents/\$\{id\}`); + const blob = await res.blob(); + const filename = `\$\{id\}.pdf`; + return { type: 'file', file: new File([blob], filename, { type: blob.type }) }; + }, + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- + +[[working-with-ai-generated-changes]] +== Working with AI-generated changes + +When asking the AI for changes to the document, for instance, _"Bold key facts in the document"_, the AI proposes a series of changes. The changes are displayed directly in the document content, making it easy to see what will be modified. + +When the AI response in the chat panel includes modification history, that block appears in a collapsible section. **Expand** shows the full history when the default preview is truncated. + +[[previewing-changes]] +=== Previewing changes + +A review bar appears at the bottom of the editor with **Diff mode** and **Preview** tabs. Toggle between them to show proposed changes inline (with markers for additions, removals, and formatting) or to preview the final result. When Diff mode is enabled, the proposed changes are highlighted in the document with markers indicating additions (green), removals (red), and formatting changes (blue). Use the arrows in the suggestion overlay to navigate through the changes. The overlay automatically follows the corresponding document sections as each suggestion is selected. + +[[applying-changes]] +=== Applying changes + +Click the checkmark image:icons/checkmark.svg[Accept suggestion icon,24px] in the suggestion overlay to accept the current change. Use the arrow buttons to move between suggestions. + +image::tinymceai/tinymce-ai-chat-diff-mode-apply-single-suggestion-overlay.png[{pluginname} Chat apply changes,width=80%] + +Click **Apply remaining** in the review bar at the bottom of the editor to apply all remaining suggestions at once. The button shows the number of remaining suggestions, for example, "Apply remaining (11)". + +image::tinymceai/tinymce-ai-chat-diff-mode-apply-remaining-suggestions.png[{pluginname} Chat apply all changes,width=80%] + +[[rejecting-suggestions]] +=== Rejecting suggestions + +Click the image:icons/close.svg[Reject suggestion icon,24px] in the suggestion overlay to reject the current suggestion. Click **Skip remaining** in the review bar at the bottom of the editor to skip all remaining suggestions. + +image::tinymceai/tinymce-ai-chat-diff-mode-reject-suggestion-overlay.png[{pluginname} Chat reject button,width=80%] + + +[[chat-history]] +== Chat history + +All past conversations appear in the Chat history. Click the image:icons/restore-draft.svg[Chat history icon,24px] button in the chat header to open the list. Click a conversation to reopen it, or use the menu on each entry to pin, rename, or delete it. Click **Go to AI Chat** to return from the history view to the active conversation. + +Conversations are grouped by date to help navigate the history. Conversations can be filtered by name using the search field at the top of the user interface. + +image::tinymceai/tinymce-ai-chat-history-sidebar-conversation-list.png[AI Chat history,width=80%] + +[NOTE] +==== +Any conversation from the chat history can be continued as long as the AI model used for that conversation is xref:tinymceai-models.adoc#supported-models[still supported] by the feature. Click the conversation in the history to load it in the Chat interface. +==== + +[NOTE] +==== +After a full page load or new browser session, reopening Chat does not automatically reconnect the editor to pending suggestions from an older conversation. Open that conversation again from Chat history so pending suggestions are linked to the current editor session before accepting or dismissing them. +==== + +[[conversations-api]] +== Conversations API + +The Chat plugin feature is built on top of the https://tinymceai.api.tiny.cloud/docs#tag/Conversations[Conversations API], which provides REST access to the same conversation functionality described in xref:tinymceai-api-overview.adoc[API Overview]. Conversations support multiple messages with shared context, optional files and web resources, and suggestions that can update editor content. + +For endpoint listings and request or response schemas, start with xref:tinymceai-api-overview.adoc[API Overview] and xref:tinymceai-api-quick-start.adoc[API Quick Start], then use the https://tinymceai.api.tiny.cloud/docs[interactive API documentation] (for example the https://tinymceai.api.tiny.cloud/docs#tag/Conversations[Conversations] operations). + +[[conversations-key-features]] +=== Key Features + +The API supports uploading PDFs, Word docs, and images for the AI to read and understand. Ask questions about specific sections and get intelligent answers. The AI extracts text while preserving structure from PDFs, maintains formatting context from Word documents, parses web content from HTML files, and processes images with OCR and object recognition. + +Each conversation builds on previous messages, so the AI keeps track of the entire discussion and any files that have been shared. Documents, images, web links, and text can be mixed in one conversation, and the AI connects information across all formats. + +[[example-product-launch-workflow]] +=== Example: Product Launch Workflow + +. **Upload product spec** → _"What are the key features for marketing?"_ +. **Add competitor analysis** → _"How do we compare to competitors?"_ +. **Reference blog post** → _"Write a press release using this blog post and our competitive advantages"_ +. **Include brand guidelines** → _"Match our brand voice and key messaging"_ + +The AI remembers everything that has been shared and builds on it throughout the conversation. + +[[conversations-api-capabilities]] +=== API Capabilities + +When using the Conversations API directly, advanced capabilities can be configured: + +* **Web Search**: Enable real-time web search to access current information during conversations. Configure using the `webSearch` capability in API requests. See https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources[Conversation Web Resources API] for endpoint details. +* **Reasoning**: Enable step-by-step reasoning to see the AI's problem-solving process. Configure using the `reasoning` capability in API requests. See https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages[Conversation Messages API] for endpoint details. + +[[conversations-streaming]] +=== Streaming Responses + +Conversations use Server-Sent Events (SSE) for real-time streaming responses. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information and code examples. + +[[conversations-api-reference]] +=== API Reference + +The https://tinymceai.api.tiny.cloud/docs[interactive API documentation] lists every conversation endpoint, parameter, schema, and example. In that UI, related operations are grouped under tags such as https://tinymceai.api.tiny.cloud/docs#tag/Conversations[Conversations], https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Documents[Conversation Documents], https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Files[Conversation Files], https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Web-Resources[Conversation Web Resources], and https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages[Conversation Messages] (including streaming, web search, and reasoning options where applicable). + +[[related-features]] +== Related Features + +* 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-integration-options.adoc b/modules/ROOT/pages/tinymceai-integration-options.adoc new file mode 100644 index 0000000000..bf51b4a2b4 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-integration-options.adoc @@ -0,0 +1,33 @@ += TinyMCE AI Integration Options + +:navtitle: Integration Options +:pluginname: TinyMCE AI +:description: Choose how to integrate TinyMCE AI with applications +:description_short: Integration options for TinyMCE AI +:keywords: AI, integration, plugin, API, AI service, tinymceai + +{pluginname} can be integrated with applications through two methods: + +[cols=2*a] +|=== + +| +[.lead] +xref:tinymceai.adoc[**Plugin Configuration**] + +Integrate {pluginname} features directly into the {productname} editor interface out of the box. Works with the {cloudname} CDN or self-hosted {productname}; both use the hosted AI service with JWT authentication. + +| +[.lead] +xref:tinymceai-api-overview.adoc[**AI service**] + +Use the AI service API to build custom integrations and workflows. Suitable for server-side processing, custom UI implementations, and advanced use cases. Start with the xref:tinymceai-api-quick-start.adoc[API Quick Start] guide. + +| +[.lead] +**On-Premises Deployment** + +include::partial$misc/tinymceai-on-premises-early-access-note.adoc[] + +a| +|=== \ No newline at end of file diff --git a/modules/ROOT/pages/tinymceai-introduction.adoc b/modules/ROOT/pages/tinymceai-introduction.adoc new file mode 100644 index 0000000000..d411fcfd74 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-introduction.adoc @@ -0,0 +1,92 @@ += TinyMCE AI Introduction +:navtitle: Introduction +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: Introduction to TinyMCE AI features and capabilities +:description_short: TinyMCE AI introduction +:keywords: AI, introduction, tinymceai +:page-role: -toc + +Integrate real-time AI writing assistance into your application with TinyMCE AI, with ready-to-go editor features available via the TinyMCE plugin, and custom functionality available via the API -- even outside the editor. Speed up content creation and enhance editorial workflows across a wide range of use cases, from productivity boosts and proof-reading to content quality and consistency. All with your choice of LLM -- including your own. + +[[demo]] +== Demo + +liveDemo::tinymceai[] + +[[what-is-tinymce-ai]] +== What is {pluginname} + +{pluginname} is an AI-powered writing assistant platform with two core components: + +* **xref:tinymceai.adoc[{pluginname} plugin]**: Integrates the AI directly into {productname}, providing instant text rewriting, summarization, correction, and contextual chat help based on organizational style guides. It includes automated review tools and enterprise-ready functionality that integrates with existing systems without requiring custom infrastructure. +* **xref:tinymceai-api-overview.adoc[TinyMCE AI API]**: A state-of-the-art back-end AI engine that incorporates multiple models and delivers high-quality content. Any functionality available in the plugin is also available in the API, plus more, and the API can be used anywhere in your application -- not just in {productname}. *The hosted AI service is currently available in Cloud setup only.* + +These components enable teams to implement a full suite of AI writing tools quickly, delivering efficient content workflows that maintain brand consistency and integrate smoothly with document management systems. In addition, the plugin and API use the same authorisation mechanisms and share conversation history, enabling ease of integration with your application's broader content authoring workflow -- not just within {productname}. + +Both components support multiple AI models, enabling a unified UI and API across the models your application needs. See xref:tinymceai-models.adoc[AI Models] for more information. + +include::partial$misc/tinymceai-on-premises-early-access-note.adoc[] + +[[features]] +== {pluginname} features + +There are three main features of {pluginname}. + +* xref:tinymceai-chat.adoc[**Chat**]: Interactive AI chats with history and persistent context. +* xref:tinymceai-review.adoc[**Review**]: Content analysis and proofreading, optimized for larger content. +* xref:tinymceai-actions.adoc[**Actions**]: Fast, stateless operations for specific tasks. + +[NOTE] +Existing customers on paid plans can request a full featured free trial through the link:{accountpageurl}[Customer Portal]. + +[[integration-options]] +== Integration Options + +{pluginname} can be integrated with applications through two methods: the plugin (for out-of-the-box editor features) or the AI service API (for custom integrations). See xref:tinymceai-integration-options.adoc[Integration Options] for details. + +[[permissions]] +== Permissions + +Developers can control access to AI features, models, and capabilities based on user roles, subscription tiers, and organizational requirements. Learn more about the xref:tinymceai-permissions.adoc[permissions system]. + +[[privacy-and-data-handling]] +== Privacy and data handling + +[[regional-data-storage]] +=== Regional Data Storage + +All data stored by Tiny for {pluginname} is handled in the US region. + +Data sent to LLM providers for processing is currently handled in the US region. {productname} does not offer separate LLM processing regions to choose from. + +[[data-retention-policy]] +=== Data Retention Policy + +Conversation data is automatically deleted after 12 months of inactivity, including: + +* all conversation messages and history, +* attached documents, files, and web resources, +* conversation metadata and settings. + +[[security]] +=== Security + +All data is encrypted in transit and at rest with end-to-end encryption. Conversations and attachments are stored in secure cloud infrastructure with fine-grained access control and comprehensive permission systems. + +[[on-premises-deployment]] +== On-Premises Deployment + +On-premises deployment allows the AI service to run within an organization's infrastructure, giving teams more control over data and infrastructure. + +include::partial$misc/tinymceai-on-premises-early-access-note.adoc[] + +[[next-steps]] +== Next steps + +* xref:tinymceai.adoc[Plugin Reference]: Install the `tinymceai` plugin, configure authentication, and enable Chat, Review, and Quick Actions. +* xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]: Issue tokens for the hosted `{pluginname}` service. +* xref:tinymceai-models.adoc[AI Models]: Review supported models, compatibility versions, and limits. +* xref:tinymceai-api-overview.adoc[API Overview]: Call the REST API from application code outside the editor. +* xref:tinymceai-api-quick-start.adoc[API Quick Start]: Obtain API credentials and connect to the service. +* xref:tinymceai-integration-options.adoc[Integration Options]: Compare plugin-first and API-first integration paths. diff --git a/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc b/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc new file mode 100644 index 0000000000..8c09352e26 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-jwt-authentication-intro.adoc @@ -0,0 +1,325 @@ += TinyMCE AI JWT Authentication + +:navtitle: JWT Authentication +:description: JWT authentication requirements and permissions for TinyMCE AI +:description_short: JWT Authentication +:keywords: AI, JWT, authentication, permissions, tinymceai +:pluginname: TinyMCE AI +:plugincode: tinymceai + +{pluginname} requires JWT (JSON Web Token) authentication when using the {cloudname} service. JWT authentication provides secure, user-specific access to {pluginname} features. Each JWT token contains claims that identify the user and specify which AI features they can access. + +{productname} recommends using the libraries listed on link:https://www.jwt.io/libraries[jwt.io/libraries] to create JWT tokens. These libraries support the algorithms required by {pluginname}. For details on supported algorithms, see xref:#supported-algorithms[Supported Algorithms]. + +[[trial-demo-identity-service]] +== Trial: demo identity service + +During a {cloudname} trial, a demo identity service is available for the {pluginname} plugin. This allows trying the plugin without setting up a custom token endpoint, for the duration of the trial. The demo service assigns a random session and user ID to the end user, then generates a JWT for that user. This prevents users from viewing each other's conversation history. + +[[trial-quick-start]] +=== Quick start + +The following is the simplest way to use the demo identity service. Replace `{apiKey}` with the trial API key from the link:{accountpageurl}[Customer Portal]. + +[NOTE] +==== +In production, the user session should be scoped to the page, not a specific TinyMCE instance. This example places it in the `tinymceai_token_provider` option for ease of use. If there are multiple TinyMCE instances on the page, this may cause unexpected behavior regarding users. In that case, run the session fetch only once per page. +==== + +[source,js] +---- +tinymce.init({ + selector: "textarea", + plugins: "tinymceai", + toolbar: "tinymceai-chat tinymceai-review tinymceai-quickactions", + sidebar_show: 'aichat', + tinymceai_token_provider: async () => { + await fetch(`https://demo.api.tiny.cloud/1/no-api-key/auth/random`, { method: "POST", credentials: "include" }); + return await fetch(`https://demo.api.tiny.cloud/1/no-api-key/jwt/tinymceai`, { credentials: "include" }) + .then(resp => resp.text()) + .then(token => ({ token })) + } +}); +---- + +[[trial-realistic-usage]] +=== Realistic usage + +In production, user and session management typically happens at the page level. This example gives a more realistic pattern for using the demo identity service's two endpoints: + +[source,js] +---- +// Establish a session with the demo identity service (cookies sent on same-site requests). +const isLoggedIn = fetch(`https://demo.api.tiny.cloud/1/no-api-key/auth/random`, { method: "POST", credentials: "include" }); + +tinymce.init({ + selector: "textarea", + plugins: "tinymceai", + toolbar: "tinymceai-chat tinymceai-review tinymceai-quickactions", + sidebar_show: 'aichat', + tinymceai_token_provider: async () => { + // Wait for the session request so the JWT endpoint receives the session cookie. + await isLoggedIn; + // Return a JWT string in the shape the AI plugin expects: { token }. + return await fetch(`https://demo.api.tiny.cloud/1/no-api-key/jwt/tinymceai`, { credentials: "include" }) + .then(resp => resp.text()) + .then(token => ({ token })) + } +}); +---- + +[[trial-moving-to-production]] +=== Moving to production + +To move from the demo identity service to a production system: + +. Replace the session call with your own user management. If there is no concept of users, generate a randomized identifier per session or page so end users do not share conversation history. +. Set up a JWT endpoint that creates JWTs as described in this guide. Replace the JWT fetch with a call to your endpoint. See xref:tinymceai-with-jwt-authentication-nodejs.adoc[Node.js] or xref:tinymceai-with-jwt-authentication-php.adoc[PHP] for implementation guides. + +[[token-endpoint-overview]] +== Token Endpoint Overview + +To connect {productname} with {pluginname}, a token endpoint must be created in the application backend. This guide outlines the principles required to create that endpoint. + +[[how-tinymce-ai-uses-tokens]] +== How {pluginname} Uses Tokens + +To authenticate users, {pluginname} uses tokens. The purpose of tokens is to inform the AI service that the user has access to AI features and which API key the user should connect to. The authenticity of tokens is provided by a digital signature. + +*The token endpoint* is where {productname} makes a request to get the token. It is required to return the token only if the user proves their identity. It should be placed inside the system, not exposed as a public endpoint without proper authentication. + +The following diagram shows how {pluginname} uses tokens: + +image::JWT-flow.svg[JSON Web Token Call Flow,title="JSON Web Token Call Flow"] + +[[jwt-specification]] +== The JSON Web Tokens Specification + +{pluginname} tokens are represented as JSON Web Tokens (JWT). JWT is an open link:https://datatracker.ietf.org/doc/html/rfc7519[standard] (RFC 7519) for transmitting digitally signed information. Using it ensures that the data comes from a trusted source and has not been tampered with. + +A JWT consists of three parts separated by dots `.` + +* **Header**: Contains metadata about the token, including the signing algorithm +* **Payload**: Contains the claims (user information, permissions, and similar) +* **Signature**: Used to verify the token's authenticity + +[source,json] +---- +{header}.{payload}.{signature} +---- + +.Example: +[source,json] +---- +eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQ4NzI5IiwibmFtZSI6Ikplc3NpY2EgV2lsbGlhbXMiLCJpYXQiOjE3Mjg0NzM2NDJ9.kX9mP2qL8vN4rT7wY3zA5bC6dE1fG2hI3jK4lM5nO6pQ7rS8tU9vW0xY1zA2b +---- + +[[jwt-header]] +=== Header + +The JWT header identifies the token type and specifies the cryptographic algorithm used to sign the token. For {pluginname}, the header must be a JSON object containing: + +* `alg`: The signing algorithm used to create the token signature. See xref:#supported-algorithms[Supported Algorithms] for the list of supported algorithms. {companyname} recommends using `RS256`. +* `typ`: The token type identifier, which must always be `JWT` + +The header is Base64URL-encoded to form the first part of the JWT token. + +.Example header +[source,json] +---- +{ + "alg": "RS256", + "typ": "JWT" +} +---- + +[[jwt-payload]] +=== Payload + +The JWT payload is a JSON object containing claims that identify the user, specify their AI permissions, and control token validity. The payload is Base64URL-encoded to form the second part of the JWT token. + +[[payload-properties]] +==== Payload Properties + +The following properties **must** be included in the payload: + +* `aud`: The API key that has entitlements to use {pluginname}. +* `sub`: The user ID. This should be a unique identifier for the user making the request. This identifier is used to lock down conversation history, AI-generated content, and other user-specific data to individual users, ensuring privacy and data isolation. +* `iat`: "Issued at". Ensure `iat` is present and contains a correct time stated in seconds. Some JWT implementations do not include it by default. Sometimes the system time may also be invalid, causing issues. +* `exp`: Token expiration time. Identifies the expiration time after which the JWT will not be accepted. {pluginname} only accepts tokens no older than 24 hours. This field can be used to shorten the token validity time. +* `auth`: The `auth.ai.permissions` array inside is required. This defines which AI features the user can access. See xref:#permissions[Permissions] below for details. + +The properties that are optional: + +* `user`: User information. Providing `name` and `email` is recommended for better user experience and debugging. + +[[example-token-payload]] +==== Example Token Payload + +The example below presents a complete token payload with access to all AI features: + +[source,json] +---- +{ + "aud": "no-api-key", + "iat": 1511963669, + "exp": 1511967269, + "sub": "user-123", + "user": { + "email": "user@example.com", + "name": "John Doe" + }, + "auth": { + "ai": { + "permissions": [ + "ai:conversations:read", + "ai:conversations:write", + "ai:models:agent", + "ai:actions:system:*", + "ai:reviews:system:*" + ] + } + } +} +---- + +[[permissions]] +==== Permissions + +Permissions are specified in the `auth.ai.permissions` array within the JWT token and control which AI features, models, and capabilities users can access. + +For a complete list of available permissions, permission examples, and best practices, see xref:tinymceai-permissions.adoc[Permissions]. + +For complete details on all required claims, including types, formats, and implementation examples, see: + +* xref:tinymceai-with-jwt-authentication-nodejs.adoc#required-jwt-claims-for-tinymce-ai[Node.js guide - Required JWT claims] +* xref:tinymceai-with-jwt-authentication-php.adoc#required-jwt-claims-for-tinymce-ai[PHP guide - Required JWT claims] + +[[jwt-signature]] +=== Signature + +The signature is created by encoding the header and payload using Base64URL, then signing them with the private key using the specified algorithm. The {pluginname} service verifies the signature using the corresponding public key stored in the {accountpage}. + +[[supported-algorithms]] +=== Supported Algorithms + +{productname} does not support symmetrical encryption algorithms, such as `HS256`. {companyname} recommends using the `RS256` algorithm. The following algorithms are supported: + +* RS256 +* RS384 +* RS512 +* PS256 +* PS384 +* PS512 + +For details on each of these algorithms, visit: link:https://tools.ietf.org/html/rfc7518#section-3[RFC 7518, JSON Web Algorithms (JWA) Section 3 - Cryptographic Algorithms for Digital Signatures and MACs]. + +[[token-requests]] +== Requests to the Token Endpoint + +The token for {pluginname} is requested by the {pluginname} plugin. The easiest way to configure this is to set the `tinymceai_token_provider` option to a function that fetches the token from the endpoint. + +The token endpoint will be requested: + +* At editor initialization +* Periodically to refresh the token (typically every hour) + +[[simple-token-request]] +=== Simple Usage + +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_token_provider: () => { + return fetch('http://localhost:3000/jwt', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + }).then(response => response.json()); + }, +}); +---- + +[TIP] +==== +The editor will not be ready to use until the first token is obtained from the token endpoint. If an error occurs during the initial request, the editor will not start correctly. +==== + +[[token-responses]] +== Responses from the Token Endpoint + +The token provider must return an object with a `+token+` property: `+{ token: string }+`. The endpoint may respond in either format: + +* **JSON response**: Endpoint returns `+{ "token": "eyJ..." }+`. Use `+response.json()+` and return `+{ token: data.token }+`. +* **Plain text response**: Endpoint returns the raw JWT string. Use `+response.text()+` and return `+{ token }+`. + +.Example: JSON response +[source,json] +---- +{ + "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." +} +---- + +.Example: Plain text response +[source,text] +---- +eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9... +---- + +[[quick-setup]] +== Quick Setup + +To set up JWT authentication for {pluginname}: + +. Generate a public/private key pair and add the public key to the {accountpage} using link:{accountjwturl}[{accountpage} - JWT Keys]. +. Set up a JWT endpoint that generates tokens with the required claims. +. Configure {productname} to use the JWT endpoint through the `tinymceai_token_provider` option. + +For step-by-step implementation instructions with complete code examples, see: + +* xref:tinymceai-with-jwt-authentication-nodejs.adoc[JWT authentication (Node.js)]: Complete Node.js implementation guide +* xref:tinymceai-with-jwt-authentication-php.adoc[JWT authentication (PHP)]: Complete PHP implementation guide + +[[tools]] +== Tools + +JWT tokens can be validated and debugged using the link:https://jwt.io/[jwt.io debugger]. + +[[troubleshooting]] +== Troubleshooting + +[[invalid-token-error]] +=== Invalid token + +If an error message indicates an invalid token: + +* Verify that the token was created in accordance with the required claims and format +* Ensure the API key in the `aud` claim is correct and valid +* Verify that the token is signed with one of the xref:#supported-algorithms[supported algorithms] +* Check that the public key in the {accountpage} matches the private key used to sign the token +* Validate the token structure using the link:https://jwt.io/[jwt.io debugger] +* Ensure the `iat` (issued at) timestamp is correct and not in the future +* Verify that system time is accurate (time drift can cause token validation issues) + +[[insufficient-permissions-error]] +=== Insufficient permissions + +If an error indicates insufficient permissions: + +* Verify that the token includes the `auth.ai.permissions` array with the required permissions +* Check that the permissions match the AI features being accessed +* Review the xref:tinymceai-permissions.adoc[Permissions] guide for the correct permission format +* Ensure permissions are specified correctly (for example, `ai:conversations:read`, `ai:conversations:write`) + +[[related-features]] +== Related Features + +* xref:tinymceai-permissions.adoc[Permissions]: Complete permissions reference and examples. +* xref:tinymceai-models.adoc[AI Models]: Model selection and capabilities. +* xref:tinymceai-chat.adoc[Chat]: Interactive AI discussions. +* xref:tinymceai-review.adoc[Review]: Content improvement. +* xref:tinymceai-actions.adoc[Quick Actions]: Content transformation. +* link:https://tinymceai.api.tiny.cloud/docs[API Documentation]: Complete API reference for {pluginname}. diff --git a/modules/ROOT/pages/tinymceai-limits.adoc b/modules/ROOT/pages/tinymceai-limits.adoc new file mode 100644 index 0000000000..c4a7c098cd --- /dev/null +++ b/modules/ROOT/pages/tinymceai-limits.adoc @@ -0,0 +1,49 @@ += TinyMCE AI Limits + +:navtitle: Limits +:description: Usage limits configuration for TinyMCE AI +:description_short: Usage limits configuration +:keywords: AI, limits, configuration, tinymceai +:pluginname: TinyMCE AI + +[[overview]] +== Overview + +{pluginname} applies limits on API requests, context and attachments, models, and files to ensure fair usage, optimal performance, and cost control. The sections below describe rate limits, context limits, model-specific constraints, and file restrictions. + +[[rate-limits]] +== Rate Limits + +Rate limits control the frequency of requests to prevent abuse and ensure service stability. These limits apply to both plugin usage and direct API calls, as the plugin uses the API under the hood. The service implements limits on requests, token usage, web search, and web scraping requests per minute. All rate limits are applied at both organization level (higher limits) and individual user level (lower limits) to ensure fair usage. + +NOTE: Specific rate limit values are subject to change and may vary based on the subscription tier. For current rate limit details for the environment, link:{contactpage}[contact {supportname}]. + +[[context-limits]] +== Context Limits + +Context limits control how much content can be attached to conversations to ensure AI models can process all information effectively. These limits vary by model based on their specific capabilities and processing requirements. + +[[file-limits]] +=== File Limits + +Supported attachment types include PDF, DOCX, PNG, JPEG, Markdown, HTML, and plain text. Exact per-file, per-conversation, and PDF page limits depend on the model in use. Read the `limits` object for that model from `GET /v1/models/{version}` (see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] and xref:tinymceai-models.adoc#model-information[Model Information]). For schema details, see the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. + +[[context-optimization-tips]] +=== Context Optimization Tips + +Compress images and split large documents into smaller sections. Use text formats (TXT or MD) over PDF when possible for better processing. Attach only relevant files to conversations and provide document summaries for very large files. + +[[model-specific-limits]] +== Model-Specific Limits + +Different AI models have varying capabilities and limitations that affect context processing. Each model exposes numeric caps and capability flags in the `GET /v1/models/{version}` response: find the object in `items` whose `id` matches the model in use, then read `limits` (for example context length and file size ceilings, often in bytes) and `capabilities`. See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. + +Models also have response timeouts, file processing timeouts, web resource timeouts, and streaming response limits. All models include content moderation for inappropriate content, safety checks, and moderation response time limits. + +[[next-steps]] +== Next Steps + +* xref:tinymceai-models.adoc#model-information[Model Information] documents the `GET /v1/models/{version}` request; each item in the response includes `limits` and capabilities for that model. +* xref:tinymceai-permissions.adoc[Set up Permissions] to control user access. +* xref:tinymceai-chat.adoc[Explore Chat] for context management. +* https://tinymceai.api.tiny.cloud/docs[API Documentation]: Complete API reference for TinyMCE AI. diff --git a/modules/ROOT/pages/tinymceai-models.adoc b/modules/ROOT/pages/tinymceai-models.adoc new file mode 100644 index 0000000000..6cb99845ab --- /dev/null +++ b/modules/ROOT/pages/tinymceai-models.adoc @@ -0,0 +1,399 @@ += TinyMCE AI Models + +:navtitle: AI Models +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: AI model configuration for TinyMCE AI +:description_short: AI model configuration +:keywords: AI, models, configuration, tinymceai + +{pluginname} supports multiple AI models from different providers. Which models may be used is determined by xref:tinymceai-permissions.adoc#model-permissions[model permissions] in the JWT; the plugin configuration UI, REST API request bodies, and per-action options (for example xref:tinymceai-actions.adoc[Quick Actions] custom items) then select which allowed model applies in each situation. This page covers model capabilities, configuration options, and limitations that apply to both plugin and API usage. + +[[recommended-agent-models]] +== Recommended: Agent Models + +The `agent-1` model automatically selects the best AI model for requests based on speed, quality, and cost. It is the recommended choice for most use cases as it optimizes performance and cost automatically. + +[[available-models]] +== Available Models + +{pluginname} supports multiple AI models from different providers. Each model has unique capabilities, performance characteristics, and cost profiles. By default, the automatically selected model (`agent-1`) will be used for optimal cost and performance. + +[[supported-models-table]] +=== Supported Models + +The following is a detailed list of available models with their capabilities: + +[cols="1,2,1,1,2"] +|=== +|Model |Description |xref:tinymceai-chat.adoc#web-search[Web Search] |xref:tinymceai-chat.adoc#reasoning[Reasoning] |Configuration id + +|**Auto (default)** +|Automatically selects best model for speed, quality, and cost. +|Yes +|Yes +|`'auto'` (also `'agent-1'`, learn more about xref:tinymceai-models.adoc#model-compatibility-versions[compatibility versions]) + +|**GPT-5.4** +|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks +|Yes +|Yes +|`'gpt-5.4'` + +|**GPT-5.2** +|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks +|Yes +|Yes +|`'gpt-5.2'` + +|**GPT-5.1** +|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks +|Yes +|Yes +|`'gpt-5.1'` + +|**GPT-5** +|OpenAI's flagship model for advanced reasoning, creativity, and complex tasks +|Yes +|Yes +|`'gpt-5'` + +|**GPT-4.1** +|OpenAI's model for reliable reasoning, speed, and versatility +|Yes +|No +|`'gpt-4.1'` + +|**GPT-5 Mini** +|A lightweight version of GPT-5 for faster, more cost-efficient responses +|Yes +|Yes +|`'gpt-5-mini'` + +|**GPT-4.1 Mini** +|A lighter variant of GPT-4.1 that balances speed and cost while maintaining solid accuracy +|Yes +|No +|`'gpt-4.1-mini'` + +|**Claude 4.6 Sonnet** +|Advanced model with improved creativity, reliability, and reasoning +|Yes +|Yes +|`'claude-4-6-sonnet'` + +|**Claude 4.5 Sonnet** +|Advanced model with improved creativity, reliability, and reasoning +|Yes +|Yes +|`'claude-4-5-sonnet'` + +|**Claude 4.5 Haiku** +|Cost-efficient model for quick interactions with improved reasoning +|Yes +|Yes +|`'claude-4-5-haiku'` + +|**Gemini 3.1 Pro** +|Google's advanced model for versatile problem-solving and research +|Yes +|Yes +|`'gemini-3-1-pro'` + +|**Gemini 2.5 Flash** +|Lightweight Gemini model for fast, cost-efficient interactions +|Yes +|Yes +|`'gemini-2-5-flash'` + +|**Gemini 3 Flash** +|Lightweight Gemini model for fast, cost-efficient interactions +|Yes +|Yes +|`'gemini-3-flash'` +|=== + +[[limitations]] +=== Limitations + +Model availability depends on the subscription tier and service compatibility version. Some models may have specific limitations or requirements. + +[[how-model-selection-works]] +== How Model Selection Works + +The agent model (`agent-1`) automatically selects the best underlying model based on: + +* **Request complexity**: Simple queries use faster, cost-effective models +* **Content size**: Larger content uses models with better context windows +* **Required capabilities**: Web search and reasoning require compatible models +* **Cost optimization**: Balances quality with cost efficiency + +[[model-configuration]] +=== Model Configuration + +The JWT `auth.ai.permissions` array includes xref:tinymceai-permissions.adoc#model-permissions[model permissions] that define which models are allowed for the token. That allowed set applies to both the plugin and the REST API. + +Plugin configuration, API parameters, and per-feature options do not grant access to models that the JWT disallows; they only choose which *allowed* model to use in a given context: + +* **JWT model permissions**: Set `ai:models:*`, `ai:models:agent`, `ai:models::*`, or `ai:models::` as required. See xref:tinymceai-permissions.adoc#model-permissions[Model permissions] and xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. +* **Plugin configuration**: `tinymceai_default_model` sets the default model, and `tinymceai_allow_model_selection` controls whether end users can choose among allowed models in the UI. See xref:tinymceai.adoc#options-chat[Chat configuration options]. +* **API requests**: The `model` field in request bodies selects the model for that call. See xref:tinymceai-models.adoc#api-examples[API Examples] below. +* **Custom Quick Actions and similar**: Per-item options such as the `model` property on xref:tinymceai-actions.adoc#custom-actions[custom Quick Actions] select a model for that action; the value must be among the models allowed by the JWT. + +[NOTE] +==== +The set of models and capabilities can change between major {productname} releases. That kind of change is not treated as a breaking change for the editor. Use the plugin's model selection dropdown or `GET /v1/models/{version}` to see what the environment offers and the model limitations. +==== + +.Example: Set default model in plugin configuration +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_default_model: 'gemini-2-5-flash', + tinymceai_allow_model_selection: true, + tinymceai_token_provider: () => fetch('/api/token').then(r => r.text()).then(token => ({ token })) +}); +---- + +[[model-compatibility-versions]] +== Model Compatibility Versions + +Models are organized by compatibility versions to ensure API stability. When new models are introduced or existing models are updated, they may be added to a new compatibility version. + +[[how-it-works]] +=== How It Works + +Compatibility versions allow {pluginname} to introduce new models and capabilities without breaking existing integrations. Each version maintains a stable set of models and capabilities. + +[[checking-compatibility]] +=== Checking Compatibility + +To see available models for a compatibility version: + +* **Through the plugin**: Available models are shown in the model selection dropdown when `tinymceai_allow_model_selection` is enabled. See xref:tinymceai.adoc#tinymceai_allow_model_selection[`tinymceai_allow_model_selection`] for configuration. +* **Through the API**: Check the `GET /v1/models/{version}` endpoint. The API response includes model capabilities, limits, and availability. See xref:tinymceai-models.adoc#model-information[Model Information] for an example. + +[[verifying-model-limits-for-integration]] +=== Verifying limits for a configured model + +Follow these steps to read limits and capabilities for the model the integration uses with {pluginname}: + +* *Align base URL and credentials* +** Call the same HTTP base URL the editor uses for {pluginname} requests. If the base URL and JWT do not belong to the same environment, the response is an authorization error rather than model metadata. +* *List models for the compatibility version* +** Request `GET /v1/models/{version}` with the compatibility version the integration targets (often `1`). Use the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI definition to confirm `{version}` when unsure. +* *Pick the matching `items[]` entry* +** In the JSON `items` array, select the object whose `id` matches the model in configuration (`tinymceai_default_model`) or in API bodies (`model`). +* *Read `limits` and `capabilities`* +** Inspect `limits` for numeric caps (sizes are usually in bytes). Inspect `capabilities` for `webSearch` and `reasoning`, using `enabled` and `allowed`. Compare with the example response under xref:tinymceai-models.adoc#model-information[Model Information]. +* *Interpret availability flags* +** Treat `allowed: false` as “model not available for this token or subscription.” The `recommended` field guides default selection in the UI; it does not alter `limits`. + +[TIP] +==== +Ready-to-run `fetch` (browser console) and `curl` examples appear under xref:tinymceai-models.adoc#model-information[Model Information]. For field names and schema changes over time, use the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI document. +==== + +[[model-capabilities]] +== Model Capabilities + +Different models support different capabilities (such as web search and reasoning). Check the model information through the API endpoint or the plugin model selection UI to see which capabilities are available for each model. + +[[web-search]] +=== Web Search + +Enable real-time web search to access current information during conversations. Not all models support web search. Check model capabilities to see which models support this feature. + +[[reasoning]] +=== Reasoning + +Enable step-by-step reasoning to see the AI's problem-solving process. Some models have reasoning always enabled and cannot be turned off. + +**Always-on reasoning models:** + +* Reasoning is always active during inference. +* Reasoning cannot be turned off through the API. + +To determine if a model has always-on reasoning, check the API response when listing models or refer to the model capabilities in the plugin UI. Models with mandatory reasoning will indicate this in their capability structure. + +NOTE: Model names such as `gpt-5`, `claude-4-sonnet`, and similar are examples. Actual available models depend on the service compatibility version. Use the `/v1/models` API endpoint or check the plugin model selection dropdown to see current available models for the environment. + +[[web-scraping]] +=== Web Scraping + +Web scraping extracts and processes content from web pages so the AI can analyze and summarize it. When users add web resources as context in xref:tinymceai-chat.adoc#adding-context-to-conversations[Chat], the service fetches and parses the page content for the AI to use. Web scraping supports standard web pages and is subject to xref:tinymceai-limits.adoc#rate-limits[rate limits] for web resource requests. + +[[model-limitations]] +== Model Limitations + +Per-model caps (context length, attachment sizes, PDF page totals, and similar) are returned in the `limits` object for each entry in `GET /v1/models/{version}`. Those values are **the limits the service applies at runtime** and can differ by model (for example stricter `maxImageSize` than `maxFileSize` for some providers). See xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model] for how to match the integration’s model id to the correct `items[]` entry. + +The sections below cover moderation, descriptions, and deprecation. Attachment limits are documented only under xref:tinymceai-models.adoc#file-processing-limits[File processing limits], using the live models API so values stay aligned with the service. + +[[file-processing-limits]] +=== File Processing Limits + +{pluginname} supports common attachment types in Chat conversations, including PDF, DOCX, images, Markdown, HTML, and plain text. Per-file and per-conversation ceilings—including maximum sizes, attachment counts, and PDF page totals—are returned per model in the `limits` object from `GET /v1/models/{version}`. Those numbers are **the current limits the service applies**; they can change with the service and vary by model, so read the `limits` object from that response at runtime for each model the integration uses. Field names, units, and schema updates are defined in the https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] OpenAPI documentation. + +For the request flow and how to match a configured model id to the correct `items[]` entry, see xref:tinymceai-models.adoc#verifying-model-limits-for-integration[Verifying limits for a configured model]. Typical `limits` keys include `maxFileSize`, `maxImageSize`, `maxFiles`, `maxTotalFileSize`, and `maxTotalPdfFilePages`. + +[[content-moderation]] +=== Content Moderation + +All models include moderation for inappropriate content, harmful instructions, personal information, copyrighted material, misinformation, sensitive topics, and security threats. Requests containing content that triggers moderation may be rejected with an error response. Moderation is applied automatically and cannot be disabled. + +[[model-descriptions]] +=== Model Descriptions + +Model descriptions returned by the API are provided in English and may be updated over time to reflect model improvements or capability changes. For applications that require translated model descriptions, see xref:tinymceai-models.adoc#translation-and-localization[Translation and Localization] below. + +[[translation-and-localization]] +=== Translation and Localization + +NOTE: Back-end translation handling for model descriptions is planned in a future release. Until then, use the approach described below. + +If the application requires translated model descriptions (the text returned by the API for each model), maintain a translation map in the code keyed by `model.id`, with fallback to the English description from the API for unknown models. This allows new models to work immediately while translations are added at a custom pace. + +[[model-deprecation]] +=== Model Deprecation + +Models scheduled for removal will include a `removal` field with an ISO 8601 date (for example, `"removal": "2025-11-17T00:00:00.000Z"`). When a model is removed, API requests will fail with error code `MODEL_NOT_FOUND` and the models endpoint will stop returning that particular model. + +[[api-examples]] +== API Examples + +The following examples show how to configure models when using the REST API directly. For plugin configuration, see xref:tinymceai-chat.adoc#model-selection-configuration[Chat model configuration]. + +[[model-selection]] +=== Model Selection + +[source,http] +---- +POST /v1/conversations/my-conversation-123/messages +Content-Type: application/json +Authorization: Bearer + +{ + "prompt": "Analyze this document and provide insights", + "model": "agent-1", + "content": [ + { + "type": "document", + "id": "doc-1234567890123" + } + ] +} +---- + +[[capability-configuration]] +=== Capability Configuration + +[source,http] +---- +POST /v1/conversations/my-conversation-123/messages +Content-Type: application/json +Authorization: Bearer + +{ + "prompt": "Research the latest developments in AI", + "model": "gpt-5.1", + "capabilities": { + "webSearch": {}, + "reasoning": {} + } +} +---- + +[[model-information]] +=== Model Information + +Get all available models for compatibility version `1`. + +Replace `` with a JWT from xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. Use the same TinyMCE AI API base URL the integration uses for requests. For {cloudname} production deployments, that URL is `https://tinymceai.api.tiny.cloud`. A JWT is valid only for the API host and credentials it was issued for. + +To try the request from a **browser DevTools console** (JavaScript), substitute a real token string for `''` and use the same base URL as in the application. The `fetch` and `curl` examples below use `https://tinymceai.api.tiny.cloud`. + +[source,javascript] +---- +fetch('https://tinymceai.api.tiny.cloud/v1/models/1', { + headers: { Authorization: 'Bearer ' + '' } +}).then((r) => r.json()).then(console.log); +---- + +From a **terminal**, use curl (do not paste curl into the browser console—only `fetch` belongs there): + +[source,bash] +---- +curl -sS 'https://tinymceai.api.tiny.cloud/v1/models/1' \ + -H 'Authorization: Bearer ' +---- + +Equivalent HTTP request: + +[source,http] +---- +GET /v1/models/1 +Authorization: Bearer +---- + +NOTE: If `fetch` fails with a CORS error in the console, run the curl example from a terminal instead, or call the API from the application backend. + +Response (shape illustrated; field names and numeric limits follow the live service and https://tinymceai.api.tiny.cloud/docs#tag/Models[OpenAPI] for the environment): + +[source,json] +---- +{ + "items": [ + { + "id": "agent-1", + "name": "Agent", + "description": "Automatically selects best model for speed, quality, and cost.", + "provider": "Agent", + "recommended": true, + "allowed": true, + "limits": { + "maxContextLength": 256000, + "maxFiles": 100, + "maxFileSize": 25000000, + "maxImageSize": 5000000, + "maxTotalFileSize": 30000000, + "maxTotalPdfFilePages": 100 + }, + "capabilities": { + "reasoning": { + "enabled": true, + "allowed": true + }, + "webSearch": { + "enabled": true, + "allowed": true + } + } + } + ] +} +---- + +* **`id`**: Model identifier for `tinymceai_default_model` and API `model` fields. +* **`allowed`**: Whether the model can be used with the current token or subscription. +* **`recommended`**: Service hint for default or highlighted models in UIs. +* **`limits`**: Per-model numeric caps (sizes are typically bytes; `maxContextLength` is the context budget for that model in the service). +* **`capabilities`**: Whether `webSearch` and `reasoning` are available (`allowed`) and on by default (`enabled`) for that model. + +After xref:tinymceai-models.adoc#verifying-model-limits-for-integration[locating the entry for the configured `id`], use these fields to validate integrations (for example before uploading large attachments or enabling reasoning in API calls). + +[[api-reference]] +== API Reference + +The https://tinymceai.api.tiny.cloud/docs#tag/Models[Models API] section of the https://tinymceai.api.tiny.cloud/docs[interactive API documentation] covers model listing, compatibility versions, and capability schemas, along with the rest of the {pluginname} endpoints. + +[[related-features]] +== Related Features + +* xref:tinymceai-chat.adoc[Chat]: Use models in interactive AI discussions and configure model selection. +* xref:tinymceai-review.adoc[Review]: Apply models to content analysis and improvement. +* xref:tinymceai-actions.adoc[Quick Actions]: Use models for content transformation tasks. +* xref:tinymceai.adoc[Plugin Reference]: Complete plugin configuration options including model settings. \ No newline at end of file diff --git a/modules/ROOT/pages/tinymceai-permissions.adoc b/modules/ROOT/pages/tinymceai-permissions.adoc new file mode 100644 index 0000000000..3f691bcae2 --- /dev/null +++ b/modules/ROOT/pages/tinymceai-permissions.adoc @@ -0,0 +1,265 @@ += TinyMCE AI JWT Permissions + +:navtitle: Permissions +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: JWT permissions system for TinyMCE AI +:description_short: JWT Permissions +:keywords: AI, JWT, permissions, authentication, tinymceai + +{pluginname} uses a permission-based access control system to manage user access to AI features. Permissions are specified in JWT tokens and control which features, models, and capabilities users can access. + +For information about JWT authentication setup and required claims, see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. + +[[quick-reference]] +== Quick Reference + +[cols="2,3"] +|=== +|Category |Permissions + +|Admin +|`ai:admin` + +|Models +|`ai:models:*`, `ai:models::*`, `ai:models::`, `ai:models:agent` + +|Conversations +|`ai:conversations:*`, `ai:conversations:read`, `ai:conversations:write`, `ai:conversations:websearch`, `ai:conversations:reasoning` + +|Context +|`ai:conversations:context:*`, `ai:conversations:context:files:*`, `ai:conversations:context:files:`, `ai:conversations:context:urls` + +|Actions +|`ai:actions:*`, `ai:actions:custom`, `ai:actions:system:*`, `ai:actions:system:` + +|Reviews +|`ai:reviews:*`, `ai:reviews:custom`, `ai:reviews:system:*`, `ai:reviews:system:` +|=== + +[[use-cases]] +== Use Cases + +* **Role-based access**: Different user roles have different AI capabilities +* **Cost control**: Limit access to expensive models or features +* **Feature gating**: Enable specific AI features for premium users +* **Security**: Restrict access to sensitive AI operations + +[[permission-format]] +== Permission Format + +Permissions follow a hierarchical format: `ai:::` + +[[admin-permissions]] +== Admin Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:admin` +|Grants full access to all {pluginname} features, models, and capabilities. Use with caution in production environments. +|=== + +[[model-permissions]] +== Model Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:models:*` +|Access to all available AI models. Use with caution as this includes access to new models that may be more expensive. + +|`ai:models::*` +|Access to all models from a specific provider (for example, `ai:models:openai:*`, `ai:models:anthropic:*`). + +|`ai:models::` +|Access to a specific model (for example, `ai:models:openai:gpt-4o`, `ai:models:anthropic:claude-3-sonnet`). + +|`ai:models:agent` ⭐ Recommended +|Access to the agent model which automatically selects the best model for each request. This is the recommended permission for most use cases. +|=== + +[[conversation-permissions]] +== Conversation Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:conversations:*` +|Full access to all conversation features including read, write, web search, and reasoning. + +|`ai:conversations:read` +|Ability to read and list conversations. + +|`ai:conversations:write` +|Ability to create and send messages in conversations. + +|`ai:conversations:websearch` +|Ability to use web search capability in conversations. + +|`ai:conversations:reasoning` +|Ability to use reasoning capability in conversations. +|=== + +[[context-permissions]] +== Context Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:conversations:context:*` +|Access to all context types (files and URLs). + +|`ai:conversations:context:files:*` +|Access to all file types for context. + +|`ai:conversations:context:files:` +|Access to specific file formats (for example, `ai:conversations:context:files:pdf`, `ai:conversations:context:files:docx`). + +|`ai:conversations:context:urls` +|Ability to use web URLs as context sources. +|=== + +[[actions-permissions]] +== Actions Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:actions:*` +|Access to all action types, including custom and system actions. + +|`ai:actions:custom` +|Ability to run custom actions with free-form prompts. + +|`ai:actions:system:*` +|Access to all pre-defined system actions. + +|`ai:actions:system:` +|Access to specific system actions. Examples: `ai:actions:system:improve-writing`, `ai:actions:system:fix-grammar`, `ai:actions:system:translate` +|=== + +[[reviews-permissions]] +== Reviews Permissions + +[cols="2,3"] +|=== +|Permission |Description + +|`ai:reviews:*` +|Access to all review types, including custom and system reviews. + +|`ai:reviews:custom` +|Ability to run custom reviews with free-form prompts. + +|`ai:reviews:system:*` +|Access to all pre-defined system reviews. + +|`ai:reviews:system:` +|Access to specific system reviews. Examples: `ai:reviews:system:correctness`, `ai:reviews:system:clarity`, `ai:reviews:system:make-tone-professional` +|=== + +[[permission-examples]] +== Permission Examples + +[[basic-user]] +=== Basic User + +[source,json] +---- +{ + "auth": { + "ai": { + "permissions": [ + "ai:conversations:read", + "ai:conversations:write", + "ai:models:agent", + "ai:conversations:context:files:pdf", + "ai:conversations:context:files:docx" + ] + } + } +} +---- + +[[premium-user]] +=== Premium User + +[source,json] +---- +{ + "auth": { + "ai": { + "permissions": [ + "ai:conversations:*", + "ai:models:*", + "ai:actions:system:*", + "ai:reviews:system:*" + ] + } + } +} +---- + +[[enterprise-admin]] +=== Enterprise Admin + +[source,json] +---- +{ + "auth": { + "ai": { + "permissions": [ + "ai:admin" + ] + } + } +} +---- + +[[restricted-user-review-only]] +=== Restricted User (Review Only) + +[source,json] +---- +{ + "auth": { + "ai": { + "permissions": [ + "ai:reviews:system:correctness", + "ai:reviews:system:clarity", + "ai:models:gpt-4.1-mini" + ] + } + } +} +---- + +[[best-practices]] +== Best Practices + +[[permission-design]] +=== Permission Design + +Begin with minimal, specific permissions based on actual requirements. Use wildcards only for testing environments and power users who need comprehensive access. Gradually expand permissions based on user needs and usage patterns. + +Avoid `ai:models:*` in production to prevent unexpected access to new expensive models. Use provider-specific permissions like `ai:models:openai:*` for better control, or specify exact models for maximum control. Start with common formats (PDF, DOCX, TXT, PNG, JPEG) and add specialized formats only when needed. + +[[error-handling]] +== Error Handling + +When a user lacks required permissions, the API returns a `403 Forbidden` error with the message "No permissions to the resource". Common issues include missing model permissions, file type restrictions, feature access without permission, and action/review access without permission. + +[[related-features]] +== Related Features + +* xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]: JWT authentication setup and required claims. +* xref:tinymceai-models.adoc[AI Models]: Model selection and capabilities. +* xref:tinymceai-chat.adoc[Chat]: Interactive AI discussions. +* xref:tinymceai-review.adoc[Review]: Content improvement. +* xref:tinymceai-actions.adoc[Quick Actions]: Content transformation. diff --git a/modules/ROOT/pages/tinymceai-review.adoc b/modules/ROOT/pages/tinymceai-review.adoc new file mode 100644 index 0000000000..8a6b307bae --- /dev/null +++ b/modules/ROOT/pages/tinymceai-review.adoc @@ -0,0 +1,128 @@ += TinyMCE AI Review +:navtitle: Review +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: AI Review feature for TinyMCE AI plugin +:description_short: AI Review feature +:keywords: AI, review, reviews, tinymceai +:page-role: -toc + +The Review feature provides AI-powered quality assurance for content by running checks for grammar, style, clarity, tone, and more. Review always analyzes the entire document. For AI shortcuts on a selection or range, see xref:tinymceai-actions.adoc[Quick Actions]. The editor enters read-only Review mode until the review completes or is dismissed. Suggestions appear in the Review sidebar and in the document; each change applies only after acceptance or rejection. The plugin introduces an intuitive interface for reviewing and managing AI-suggested edits directly within the document, ensuring content meets professional standards with minimal manual effort. The API offers the same functionality with flexible integration. + +The Review feature is available as a plugin UI and through the Reviews API. This page covers both: + +* Plugin sections describe user-facing features and configuration (xref:tinymceai.adoc#options-review[Review configuration]). +* API sections cover REST API access (starting at xref:tinymceai-review.adoc#reviews-api[Reviews API]). + +[[demo]] +== Demo + +The interactive demo below loads the editor with the Review feature. Use the Review toolbar button to open the Review sidebar and run the built-in reviews. + +liveDemo::tinymceai-review[] + +=== Review sidebar and built-in reviews + +The figure below is a static screenshot of the Review sidebar in Review mode before any suggestions are returned. Built-in reviews are grouped by category (Proofread, Improve clarity, Improve readability, Change length, Adjust tone and style). Expand a category to read the description and select **Run** to analyze the whole document. In this example, **Improve readability** is expanded. + +image::tinymceai/tinymce-ai-review-sidebar-command-categories-proofread-clarity.png[Review sidebar showing review categories with Improve readability expanded and Run available,width=80%] + +[[integration]] +== Integration + +To start using the Review feature, add `+tinymceai+` to the plugins option. This will automatically add the image:icons-premium/ai-review.svg[Review icon,24px] Review toolbar button and menu item to the default {productname} toolbar and menu. + +See xref:tinymceai.adoc[Plugin Reference] for more information regarding installation and enabling AI features. + +After picking one of the available reviews in the Review Mode tab, the AI will analyze the document and propose a series of suggestions: + +image::tinymceai/tinymce-ai-review-mode-suggestions-underlined-in-editor-content.png[{pluginname} Review suggestion in content,width=80%] + +While in the Review Mode, the editor remains read-only and allows browsing suggestions. Suggestions can be clicked in the sidebar or selected in the editor content (underlined): + +image::tinymceai/tinymce-ai-review-improve-readability-suggestion-cards-and-underlines.png[{pluginname} Review sidebar with suggestions,width=80%] + +Review suggestions can be individually skipped or applied by clicking the corresponding buttons. Changes that were accepted or dismissed become greyed out in the interface. The "Complete" button in the top of the sidebar enables actions such as: + +- Skipping or applying the remaining suggestions in bulk +- Completing the review with the currently applied suggestions (and skipping the rest) +- Aborting the review and exiting (with all applied changes reverted) + +[[built-in-reviews]] +== Built-in reviews + +Built-in system reviews are listed below. The **Editor** column is the label in the Review sidebar when that review is available in the editor. The **API review** column is the system review name used in the https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API]. + +[cols="1,1,3,^,^",options="header"] +|=== +|Editor |API review |Description |Editor UI |API + +|**Proofread** |Correctness |Check grammar, spelling, and punctuation; the correctness API review also addresses factual errors. |✓ |✓ + +|**Improve clarity** |Clarity |Improve logical structure, precision, sentence structure, word choice, and flow. |✓ |✓ + +|**Improve readability** |Readability |Improve readability through sentence structure, paragraph structure, transitions, word choice, and reading level. |✓ |✓ + +|**Adjust length** |Length Optimization |Shorten or lengthen the text while preserving key information. The editor offers _Longer_ and _Shorter_ options. |✓ |✓ + +|**Adjust tone and style** |Tone Adjustment |Adjust tone and style. The editor includes _Casual_, _Direct_, _Friendly_, _Confident_, and _Professional_ options. |✓ |✓ + +| |Translation |Translate between languages with cultural adaptation. | |✓ +|=== + +[NOTE] +==== +* A checkmark in the Editor UI column means that review type can appear in the Review sidebar when it is listed in xref:tinymceai.adoc#tinymceai_reviews[`tinymceai_reviews`]. +* Custom reviews (analysis defined with a prompt) are available through the xref:tinymceai-review.adoc#reviews-custom-reviews[Custom reviews (API)]. _Note: The same capability in the Review sidebar is coming soon._ +* Translation Review is API-only (not listed in the Review sidebar); see the xref:tinymceai-review.adoc#built-in-reviews[Translation row] in the table above. For translation from the editor, see **Translate** in xref:tinymceai-actions.adoc#quick-actions-reference-table[Quick Actions reference table]. +==== + +[[review-configuration]] +== Configuration + +Which built-in reviews appear in the Review sidebar can be configured using the `tinymceai_reviews` option. See xref:tinymceai.adoc#tinymceai_reviews[`tinymceai_reviews`] in the Plugin Reference for details. + +[[reviews-api]] +== Reviews API + +The Review plugin feature is built on top of the Reviews API, which provides REST API access to review functionality. Reviews run a whole-document workflow: the editor analyzes the full document, streams suggestions, and applies changes only after acceptance or rejection in the Review sidebar. xref:tinymceai-actions.adoc[Quick Actions] are shortcuts to discrete AI operations on a selection or range (for example previewing a transformation, translation, or chat with context)—not the same end-to-end review flow. + +**Reviews compared with Quick Actions:** Reviews coordinate document-wide analysis and tracked suggestions in Review mode. Quick Actions expose individual AI capabilities from the Quick Actions menu without entering that workflow. See xref:tinymceai-actions.adoc[Quick Actions] for the available shortcuts and behavior. + +Reviews use streaming output with Server-Sent Events for real-time feedback as suggestions are generated. Each review type is optimized for specific improvement tasks, providing consistent, high-quality analysis of text structure, style, and quality. Reviews provide specific, actionable recommendations for content improvement. + +[[reviews-system-reviews-api]] +=== System Reviews + +System reviews are default review operations for common use cases, which each use the AI agent most suitable for their functionality. The API includes one endpoint for running system reviews, which is passed the review name. + +Built-in system reviews including API names, descriptions, and whether each type is available in the Review sidebar or only through the API—are summarized in xref:tinymceai-review.adoc#built-in-reviews[Built-in reviews]. + +For endpoint details, request and response schemas, authentication, and streaming behavior, see https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API]. + +[[reviews-custom-reviews]] +=== Custom reviews (API) + +Integrators can also define custom reviews using the Custom Review API endpoint, which returns a output in a similar manner to system reviews but which takes a custom prompt to define the analysis behavior. Custom reviews can be as simple as checking for specific words or phrases, or as complex as applying a company style guide that includes business logic, specific terminology, and more. + + See https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] for the endpoint, parameters, and examples. + +The Review sidebar only exposes those built-in types for now; sidebar support for custom reviews is coming soon. + +Custom reviews require the `ai:reviews:custom` permission in the JWT token. + +[[reviews-streaming]] +=== Streaming Responses + +Reviews use Server-Sent Events (SSE) for real-time streaming results. See the xref:tinymceai-streaming.adoc[Streaming Responses guide] for detailed implementation information. + +[[reviews-api-reference]] +=== API Reference + +The https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] reference (interactive OpenAPI documentation) is the full source for endpoints, request and response schemas, authentication, system and custom review calls, worked examples, and streaming review responses. + +[[related-features]] +== Related Features + +* 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). diff --git a/modules/ROOT/pages/tinymceai-streaming.adoc b/modules/ROOT/pages/tinymceai-streaming.adoc new file mode 100644 index 0000000000..ac661ac76c --- /dev/null +++ b/modules/ROOT/pages/tinymceai-streaming.adoc @@ -0,0 +1,122 @@ += TinyMCE AI Streaming + +:navtitle: Streaming +:pluginname: TinyMCE AI +:plugincode: tinymceai +:description: Streaming configuration for TinyMCE AI +:description_short: Streaming configuration +:keywords: AI, streaming, configuration, tinymceai + +Real-time AI interactions using Server-Sent Events (SSE) for immediate feedback and progressive content generation. + +[[overview]] +== Overview + +{pluginname} services use Server-Sent Events (SSE) to provide real-time streaming responses. This allows users to see AI-generated content as it is being created, providing immediate feedback and enabling interactive experiences. + +[[sse-event-types]] +== SSE Event Types + +Conversations, Reviews, and Actions each use different event names and JSON payloads in the SSE stream. Those payloads are documented on each streaming operation in the https://tinymceai.api.tiny.cloud/docs[interactive API documentation], not on the feature overview pages (which only summarize that SSE is used). + +Use the API reference for the operation being called—for example: + +* https://tinymceai.api.tiny.cloud/docs#tag/Conversation-Messages[Conversation Messages] and related Conversation tags for chat streaming, sources, and reasoning. +* https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] for review streaming responses. +* https://tinymceai.api.tiny.cloud/docs#tag/Actions[Actions API] for action streaming responses. + +The shared wire format and client-side parsing are covered in <> and <> on this page. + +[[sse-wire-format]] +== SSE wire format + +The response body is a text stream in https://html.spec.whatwg.org/multipage/server-sent-events.html[Server-Sent Events] format. Events are separated by blank lines. Each event can include an `+event:+` line (event name) and one or more `+data:+` lines (payload; long payloads may be split across several `+data:+` lines). For example: + +.... +event: +data: + +event: +data: +.... + +Parsing this format correctly (including chunk boundaries, multi-line `+data:+` fields, and comments) is easy to get wrong in hand-written loops. For production code, use a maintained SSE parser such as the https://www.npmjs.com/package/eventsource-parser[`eventsource-parser`] package. + +[[basic-implementation]] +== Basic Implementation + +After obtaining a streaming `+Response+` from `+fetch+`, pass the byte stream through an SSE parser. The following example uses https://www.npmjs.com/package/eventsource-parser[`eventsource-parser`] to turn raw chunks into parsed events; application code then inspects each event payload (for example JSON with an `+event+` field and `+data+` for {pluginname} services): + +[source,javascript] +---- +import { createParser } from 'eventsource-parser'; + +const response = await fetch('/v1/your-endpoint', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + // Request payload + }) +}); + +const parser = createParser({ + onEvent: (event) => { + // event.event is the SSE event name (if present) + // event.data is the reassembled data string for this event + const data = JSON.parse(event.data); + + switch (data.event) { + case 'error': + console.error('Error:', data.data.message); + break; + default: + // Handle all other events — event names vary by API; see + // https://tinymceai.api.tiny.cloud/docs for each operation's schema. + // Examples: Conversations (text-delta, source, reasoning, modification-delta), + // Reviews (review-delta, review-metadata), Actions (modification-delta, action-metadata) + console.log('Event:', data.event, data.data); + } + } +}); + +const reader = response.body.getReader(); +const decoder = new TextDecoder(); + +while (true) { + const { done, value } = await reader.read(); + if (done) break; + parser.feed(decoder.decode(value, { stream: true })); +} +---- + +[[error-handling]] +== Error Handling + +Always handle errors gracefully: + +[source,javascript] +---- +if (data.event === 'error') { + const error = data.data; + console.error('Streaming error:', error.message); +} +---- + +[[progress-tracking]] +== Progress Tracking + +Use metadata events to show progress. Event names and fields for review streaming are defined in the https://tinymceai.api.tiny.cloud/docs#tag/Reviews[Reviews API] operations that return SSE responses, not in the Review plugin overview. + +[[api-reference]] +== API Reference + +The https://tinymceai.api.tiny.cloud/docs[interactive API documentation] describes streaming endpoints, event shapes, and errors for each feature area. + +[[next-steps]] +== Next Steps + +* xref:tinymceai-chat.adoc[Chat], xref:tinymceai-review.adoc[Review], and xref:tinymceai-actions.adoc[Quick Actions] for product behavior and editor integration. +* xref:tinymceai-models.adoc[AI Models] for model configuration and limits. diff --git a/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc b/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc new file mode 100644 index 0000000000..5f1ed39c1b --- /dev/null +++ b/modules/ROOT/pages/tinymceai-with-jwt-authentication-nodejs.adoc @@ -0,0 +1,235 @@ += {pluginname} with JWT authentication (Node.js) Guide +:plugincode: tinymceai +:pluginname: TinyMCE AI +:navtitle: JWT Authentication setup for TinyMCE AI +:description: Guide on how to setup JWT Authentication with Node.js for TinyMCE AI with TinyMCE +:keywords: jwt, authentication, tinymceai, ai, node.js + +include::partial$auth/tinymceai/nodejs/intro-and-prerequisites.adoc[] + +include::partial$auth/tinymceai/nodejs/initial-project-setup.adoc[] + +== Generate a Public/Private Key Pair + +include::partial$auth/private-public-key-pairs-for-tiny-cloud-services.adoc[] + +== JWT Configuration Requirements + +This section explains what needs to be configured for JWT authentication, whether using a managed service (such as AWS or Azure JWT services) or setting up a manual endpoint. + +For complete information about JWT requirements, claims, and permissions, see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. + +include::partial$auth/how-jwts-are-used.adoc[] + +=== JWT endpoint requirements + +A JSON Web Token (JWT) endpoint for {pluginname} requires: + +* The endpoint or server accepts a JSON HTTP POST request. +* User authentication: A method of verifying the user, and that they should have access to the {pluginname}. +* The JWTs are generated (signed) using the _private_ key that pairs with the _public_ key provided to link:{accountjwturl}[{accountpage} - JWT Keys]. +* The endpoint or server produces a JSON response with the token. {pluginname} will submit the token with requests to the AI service. + +=== Required JWT claims for {pluginname} + +JSON Web Tokens produced by the JWT endpoint must include the following claims: + +`+aud+` _(required)_:: +*Type:* `+String+` ++ +The `aud` is a case-sensitive string that must match a valid API key that has the {pluginname} plugin enabled. + +`+sub+` _(required)_:: +*Type:* `+String+` ++ +The `sub` claim identifies the user. This should be a unique identifier for the user making the request. + +`+iat+` _(required)_:: +*Type:* `+Number+` ++ +The `iat` represents the issue timestamp, specified as the number of seconds. For example, to set the issue time to the current timestamp, calculate the issue time as the current timestamp divided by 1000. + +.Example +[source,json] +---- +iat: Math.floor(Date.now() / 1000), // Issue timestamp +---- + +`+exp+` _(required)_:: +*Type:* `+Number+` ++ +The `exp` represents the expiration timestamp, specified as the number of seconds. For example, to set a validity period of 10 minutes, calculate the expiration time as the current timestamp plus 600 seconds. + +.Example +[source,json] +---- +exp: Math.floor(Date.now() / 1000) + (60 * 10) // Expiration time (10 minutes) +---- + +`+auth+` _(required)_:: +*Type:* `+Object+` ++ +The `auth` object contains AI-specific permissions that control which features the user can access. + +The following example grants access to conversations, the recommended agent model, and system actions and reviews. See xref:tinymceai-permissions.adoc[Permissions] for the full list of available permissions. + +.Example +[source,json] +---- +auth: { + ai: { + permissions: [ + "ai:conversations:read", + "ai:conversations:write", + "ai:models:agent", + "ai:actions:system:*", + "ai:reviews:system:*" + ] + } +} +---- + +[NOTE] +==== +See xref:tinymceai-permissions.adoc[Permissions] for a complete list of available permissions and best practices for configuring user access. +==== + +== Set up JWT Endpoint + +The following section shows how to create a JWT endpoint manually. If using a managed JWT service (such as AWS or Azure), configure it according to the requirements above and skip to the xref:#configure-tinymce[Configure {productname}] section. + +=== Server Setup (jwt.js) + +In the root directory, copy and paste the server setup code into the `jwt.js` file. + +[source,javascript] +---- +const express = require('express'); // Sets up the web server. +const jwt = require('jsonwebtoken'); // Generates and signs JWTs. +const cors = require('cors'); // Allows cross-origin requests. +const path = require('path'); // Handles file paths. + +const app = express(); +app.use(cors()); + +// Private key (Replace this with the actual key) +const privateKey = ` +-----BEGIN PRIVATE KEY----- +{Your private PKCS8 key goes here} +-----END PRIVATE KEY----- +`; + +app.use(express.static(path.join(__dirname, 'public'))); + +// JWT token generation endpoint +app.post('/jwt', (req, res) => { + const payload = { + aud: 'no-api-key', // Replace with the actual API key + sub: 'user-id', // Replace with actual user identifier + iat: Math.floor(Date.now() / 1000), // Issue timestamp + exp: Math.floor(Date.now() / 1000) + (60 * 10), // Expiration time (10 minutes) + // Permissions control which AI features the user can access. See the Permissions page for full details. + auth: { + ai: { + permissions: [ + 'ai:conversations:read', + 'ai:conversations:write', + 'ai:models:agent', + 'ai:actions:system:*', + 'ai:reviews:system:*' + ] + } + } + }; + + try { + // Tokens are signed with the RS256 algorithm using the private key + const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' }); + res.json({ token }); + } catch (error) { + res.status(500).send('Failed to generate JWT token.'); + console.error(error.message); + } +}); + +const PORT = 3000; +app.listen(PORT, () => { + console.log(`Server running at http://localhost:${PORT}`); +}); +---- + +[NOTE] +==== +The JWT payload includes an `auth.ai.permissions` array that defines what AI features the user can access. Adjust these permissions based on requirements. See xref:tinymceai-permissions.adoc[Permissions] for more details on available permissions. +==== + +== Configure {productname} + +[[configure-tinymce-nodejs]] +=== Web Page (public/index.html) + +Inside the `public` folder where the `index.html` file was created, add the HTML setup code. + +[source,html] +---- + + + + {productname} with {pluginname} + + + + +

{pluginname} Demo

+ + + +---- + +[[model-configuration]] +=== Model configuration + +Model selection can be configured using `tinymceai_default_model` and `tinymceai_allow_model_selection`. See xref:tinymceai-chat.adoc#model-selection-configuration[Chat model configuration] for details. Model access is controlled by JWT permissions; see xref:tinymceai-permissions.adoc#model-permissions[Model permissions] for available model permissions and xref:tinymceai-models.adoc[AI Models] for the list of available models. + +.Example: Adding model options to the JWT setup +[source,html] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_default_model: 'agent-1', + tinymceai_allow_model_selection: true, + // This demo does not verify user session; it simulates an already-authenticated user. Integrate with your auth before returning tokens. + tinymceai_token_provider: () => { + return fetch('http://localhost:3000/jwt', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + }).then(response => response.json()); + }, +}); +---- + +== Configuration and Running + +include::partial$auth/tinymceai/nodejs/configuration-steps.adoc[] diff --git a/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc b/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc new file mode 100644 index 0000000000..c79f6a694a --- /dev/null +++ b/modules/ROOT/pages/tinymceai-with-jwt-authentication-php.adoc @@ -0,0 +1,238 @@ += {pluginname} with JWT authentication (PHP) Guide +:navtitle: JWT Authentication setup for TinyMCE AI +:description: Guide on how to setup JWT Authentication with PHP for TinyMCE AI with TinyMCE +:keywords: jwt, authentication, tinymceai, ai, php +:pluginname: TinyMCE AI +:plugincode: tinymceai + +include::partial$auth/tinymceai/php/intro-and-prerequisites.adoc[] + +include::partial$auth/tinymceai/php/initial-project-setup.adoc[] + +== Generate a Public/Private Key Pair + +include::partial$auth/private-public-key-pairs-for-tiny-cloud-services.adoc[] + +== JWT Configuration Requirements + +This section explains what needs to be configured for JWT authentication, whether using a managed service (such as AWS or Azure JWT services) or setting up a manual endpoint. + +For complete information about JWT requirements, claims, and permissions, see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. + +include::partial$auth/how-jwts-are-used.adoc[] + +=== JWT endpoint requirements + +A JSON Web Token (JWT) endpoint for {pluginname} requires: + +* The endpoint or server accepts a JSON HTTP POST request. +* User authentication: A method of verifying the user, and that they should have access to the {pluginname}. +* The JWTs are generated (signed) using the _private_ key that pairs with the _public_ key provided to link:{accountjwturl}[{accountpage} - JWT Keys]. +* The endpoint or server produces a JSON response with the token. {pluginname} will submit the token with requests to the AI service. + +=== Required JWT claims for {pluginname} + +JSON Web Tokens produced by the JWT endpoint must include the following claims: + +`+aud+` _(required)_:: +*Type:* `+String+` ++ +The `aud` is a case-sensitive string that must match a valid API key that has the {pluginname} plugin enabled. + +`+sub+` _(required)_:: +*Type:* `+String+` ++ +The `sub` claim identifies the user. This should be a unique identifier for the user making the request. + +`+iat+` _(required)_:: +*Type:* `+Number+` ++ +The `iat` represents the issue timestamp, specified as the number of seconds. For example, to set the issue time to the current timestamp, calculate the issue time as the current timestamp divided by 1000. + +.Example +[source,php] +---- +"iat" => time(), // Issue timestamp +---- + +`+exp+` _(required)_:: +*Type:* `+Number+` ++ +The `exp` represents the expiration timestamp, specified as the number of seconds. For example, to set a validity period of 10 minutes, calculate the expiration time as the current timestamp plus 600 seconds. + +.Example +[source,php] +---- +"exp" => time() + (60 * 10), // Expiration time (10 minutes) +---- + +`+auth+` _(required)_:: +*Type:* `+Object+` ++ +The `auth` object contains AI-specific permissions that control which features the user can access. + +The following example grants access to conversations, the recommended agent model, and system actions and reviews. See xref:tinymceai-permissions.adoc[Permissions] for the full list of available permissions. + +.Example +[source,json] +---- +auth: { + ai: { + permissions: [ + "ai:conversations:read", + "ai:conversations:write", + "ai:models:agent", + "ai:actions:system:*", + "ai:reviews:system:*" + ] + } +} +---- + +[NOTE] +==== +See xref:tinymceai-permissions.adoc[Permissions] for a complete list of available permissions and best practices for configuring user access. +==== + +== Set up JWT Endpoint + +The following section shows how to create a JWT endpoint manually. If using a managed JWT service (such as AWS or Azure), configure it according to the requirements above and skip to the xref:#configure-tinymce[Configure {productname}] section. + +=== Server Setup (jwt.php) + +In the root directory, copy and paste the server setup code into the `jwt.php` file. + +[source,php] +---- + "JWT auth failed: " . $message))); +} + +// Check for OpenSSL extension +if (!extension_loaded('openssl')) { + fatalError('The openssl extension must be enabled in php.ini.'); +} + +// Enable CORS +header("Access-Control-Allow-Origin: *"); +header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); + +// JWT payload +$payload = array( + "aud" => "no-api-key", // Replace with the actual API key + "sub" => "user-id", // Replace with actual user identifier + "iat" => time(), // Issue timestamp + "exp" => time() + 60 * 10, // Expiration time (10 minutes) + // Permissions control which AI features the user can access. See the Permissions page for full details. + "auth" => array( + "ai" => array( + "permissions" => array( + "ai:conversations:read", + "ai:conversations:write", + "ai:models:agent", + "ai:actions:system:*", + "ai:reviews:system:*" + ) + ) + ) +); + +try { + // Tokens are signed with the RS256 algorithm using the private key + $privateKey = <<<'EOD' +-----BEGIN PRIVATE KEY----- +{Your private PKCS8 key goes here} +-----END PRIVATE KEY----- +EOD; + $token = JWT::encode($payload, $privateKey, 'RS256'); + + http_response_code(200); + header('Content-Type: application/json'); + echo json_encode(array("token" => $token)); +} catch (Exception $e) { + fatalError($e->getMessage()); +} +?> +---- + +[NOTE] +==== +The JWT payload includes an `auth.ai.permissions` array that defines what AI features the user can access. Adjust these permissions based on requirements. See xref:tinymceai-permissions.adoc[Permissions] for more details on available permissions. +==== + +== Configure {productname} + +[[configure-tinymce-php]] +=== Web Page (index.html) + +Inside the root directory where the `index.html` file was created, add the HTML setup code. + +[source,html] +---- + + + + {productname} with {pluginname} + + + + +

{pluginname} Demo

+ + + +---- + +[[model-configuration]] +=== Model configuration + +Model selection can be configured using `tinymceai_default_model` and `tinymceai_allow_model_selection`. See xref:tinymceai-chat.adoc#model-selection-configuration[Chat model configuration] for details. Model access is controlled by JWT permissions; see xref:tinymceai-permissions.adoc#model-permissions[Model permissions] for available model permissions and xref:tinymceai-models.adoc[AI Models] for the list of available models. + +.Example: Adding model options to the JWT setup +[source,html] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_default_model: 'agent-1', + tinymceai_allow_model_selection: true, + // This demo does not verify user session; it simulates an already-authenticated user. Integrate with your auth before returning tokens. + tinymceai_token_provider: () => { + return fetch('http://localhost:3000/jwt.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + }).then(response => response.json()); + }, +}); +---- + +== Configuration and Running + +include::partial$auth/tinymceai/php/configuration-steps.adoc[] diff --git a/modules/ROOT/pages/tinymceai.adoc b/modules/ROOT/pages/tinymceai.adoc new file mode 100644 index 0000000000..3abdad0039 --- /dev/null +++ b/modules/ROOT/pages/tinymceai.adoc @@ -0,0 +1,143 @@ += TinyMCE AI Plugin +:navtitle: TinyMCE AI +:description: AI-powered features for TinyMCE AI including AI chat, AI review, and quick actions +:description_short: AI-powered features for {productname} +:keywords: AI, artificial intelligence, chat, review, quick actions, tinymceai +:pluginname: TinyMCE AI +:plugincode: tinymceai +:pluginminimumplan: enterpriseplan +:plugincategory: premium +:page-role: -toc + +include::partial$misc/admon-premium-plugin.adoc[] + +The {pluginname} plugin integrates AI-assisted authoring with rich-text editing. Users can interact through Actions, Reviews, or Conversations that can use relevant context from multiple sources. + +[[interactive-example]] +== Interactive example + +liveDemo::{plugincode}[] + +[[basic-setup]] +== Basic setup + +To set up the {pluginname} plugin in {productname}: + +* add `{plugincode}` to the `plugins` option in the editor configuration; +* configure the `tinymceai_token_provider` option to provide authentication tokens (must return `+{ token: string }+`). During a {cloudname} trial, the xref:tinymceai-jwt-authentication-intro.adoc#trial-demo-identity-service[demo identity service] can supply JWTs so a custom token endpoint is not required; +* when the `toolbar` option is omitted or left at the default, the Silver theme toolbar already includes the AI toolbar buttons once the plugin is enabled: `+tinymceai-chat+` image:icons-premium/ai-assistant.svg[Chat icon,24px], `+tinymceai-quickactions+` image:icons/ai-prompt.svg[Quick Actions icon,24px], and `+tinymceai-review+` image:icons-premium/ai-review.svg[Review icon,24px]. When a custom `toolbar` string is set, add those button ids to the string explicitly. + +[[minimal-setup]] +=== Minimal setup + +The following configuration enables the plugin and token provider and relies on the default toolbar, which includes the AI buttons. If the `toolbar` option is set to a custom string, add `+tinymceai-chat+`, `+tinymceai-quickactions+`, and `+tinymceai-review+` to that string. + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[complete-setup]] +=== Complete setup example + +The following example sets a custom `toolbar` string. To use the default toolbar instead (which already includes the AI buttons), omit the `toolbar` option. + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + content_id: 'document-123', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + }, + tinymceai_default_model: 'agent-1', + tinymceai_allow_model_selection: true, + tinymceai_chat_fetch_sources: async () => [ + { + label: 'My Documents', + sources: [ + { id: 'doc-1', label: 'Document 1', type: 'file' }, + { id: 'url-1', label: 'Web Page', type: 'web-resource' } + ] + } + ], + tinymceai_chat_fetch_source: async (id) => { + const res = await fetch(`/api/documents/\$\{id\}`); + const blob = await res.blob(); + const filename = `\$\{id\}.pdf`; + return { type: 'file', file: new File([blob], filename, { type: blob.type }) }; + }, + tinymceai_quickactions_custom: [ + { title: 'Explain like I am five', prompt: 'Explain the following text in simple terms.', type: 'chat' } + ] +}); +---- + +[[options]] +== Options + +The following configuration options affect the behavior of the {pluginname} plugin. + +include::partial$configuration/tinymceai_options.adoc[leveloffset=+1] + +include::partial$misc/plugin-toolbar-button-id-boilerplate.adoc[] + +include::partial$misc/plugin-menu-item-id-boilerplate.adoc[] + +[[sidebars]] +== Sidebars + +The chat and review interfaces open as sidebars. From the toolbar or menu, clicking `+tinymceai-chat+` image:icons-premium/ai-assistant.svg[Chat icon,24px] opens the chat sidebar; clicking again minimizes it (chat history is preserved). Clicking `+tinymceai-review+` image:icons-premium/ai-review.svg[Review icon,24px] opens the review sidebar. + +To toggle sidebars programmatically, use the core `+ToggleSidebar+` command: + +[source,js] +---- +editor.execCommand('ToggleSidebar', false, 'tinymceai-chat'); +editor.execCommand('ToggleSidebar', false, 'tinymceai-review'); +---- + +[[keyboard-shortcuts]] +=== Keyboard shortcuts + +The following keyboard shortcuts are available for the AI sidebars: + +[cols="2,1,1",options="header"] +|=== +|Action |Windows |macOS +|Open or Close the AI Chat sidebar |Ctrl+J |Cmd+J +|=== + +To show the chat sidebar on load: + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to the HTML + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + sidebar_show: 'tinymceai-chat', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[commands]] +== Commands + +The {pluginname} plugin provides the following {productname} commands. + +include::partial$commands/{plugincode}-cmds.adoc[] + + diff --git a/modules/ROOT/pages/uploadcare-image.adoc b/modules/ROOT/pages/uploadcare-image.adoc index 300e424134..ff0ad939a0 100644 --- a/modules/ROOT/pages/uploadcare-image.adoc +++ b/modules/ROOT/pages/uploadcare-image.adoc @@ -214,7 +214,7 @@ This icon will only appear when the `a11y_advanced_options` configuration option | Revert | -| image:icons/revert.svg[revert.svg] +| image:icons/revert-changes.svg[revert.svg] | Restores the image to its original state by undoing all edits. |=== diff --git a/modules/ROOT/partials/auth/how-jwts-are-used.adoc b/modules/ROOT/partials/auth/how-jwts-are-used.adoc index 5b50ac1b35..811b1a5e6f 100644 --- a/modules/ROOT/partials/auth/how-jwts-are-used.adoc +++ b/modules/ROOT/partials/auth/how-jwts-are-used.adoc @@ -11,4 +11,33 @@ ifeval::["{plugincode}" == "tinydrive"] . If your JWT endpoint authorizes the user, your JWT endpoint will send a JWT to {pluginname}, certifying the user. . When the user makes a request (such as adding or deleting a file), the JWT will be sent with the request to show that the user is authorized. This JWT is verified using the _public_ key stored on the {cloudname} Server. . The {cloudname} Server sends a response, indicating that content submission was successful (or unauthorized if necessary). +endif::[] + +ifeval::["{plugincode}" == "tinymceai"] +. {pluginname} requests a signed JWT on behalf of the user. +. If your JWT endpoint authorizes the user, your JWT endpoint will send a JWT to {pluginname}, certifying the user. +. The JWT includes a `sub` (subject) claim that identifies the user. This user identifier is used to lock down conversation history, AI-generated content, and other user-specific data to individual users, ensuring privacy and data isolation. +. When the user makes a request (such as starting a chat conversation, requesting AI actions, or submitting reviews), the JWT will be sent with the request to show that the user is authorized. This JWT is verified using the _public_ key stored on the AI service. +. The AI service sends a response, indicating that the request was successful (or unauthorized if necessary). +endif::[] + +ifeval::["{plugincode}" == "importword"] +. {pluginname} requests a signed JWT on behalf of the user. +. If your JWT endpoint authorizes the user, your JWT endpoint will send a JWT to {pluginname}, certifying the user. +. When the user makes a request (such as importing a document), the JWT will be sent with the request to show that the user is authorized. This JWT is verified using the _public_ key stored on the {pluginname} Server. +. The {pluginname} Server sends a response, indicating that content submission was successful (or unauthorized if necessary). +endif::[] + +ifeval::["{plugincode}" == "exportword"] +. {pluginname} requests a signed JWT on behalf of the user. +. If your JWT endpoint authorizes the user, your JWT endpoint will send a JWT to {pluginname}, certifying the user. +. When the user makes a request (such as exporting a document), the JWT will be sent with the request to show that the user is authorized. This JWT is verified using the _public_ key stored on the {pluginname} Server. +. The {pluginname} Server sends a response, indicating that content submission was successful (or unauthorized if necessary). +endif::[] + +ifeval::["{plugincode}" == "exportpdf"] +. {pluginname} requests a signed JWT on behalf of the user. +. If your JWT endpoint authorizes the user, your JWT endpoint will send a JWT to {pluginname}, certifying the user. +. When the user makes a request (such as exporting a document), the JWT will be sent with the request to show that the user is authorized. This JWT is verified using the _public_ key stored on the {pluginname} Server. +. The {pluginname} Server sends a response, indicating that content submission was successful (or unauthorized if necessary). endif::[] \ No newline at end of file diff --git a/modules/ROOT/partials/auth/private-public-key-pairs-for-tiny-cloud-services.adoc b/modules/ROOT/partials/auth/private-public-key-pairs-for-tiny-cloud-services.adoc index 5e4b309b95..456d573004 100644 --- a/modules/ROOT/partials/auth/private-public-key-pairs-for-tiny-cloud-services.adoc +++ b/modules/ROOT/partials/auth/private-public-key-pairs-for-tiny-cloud-services.adoc @@ -1,16 +1,20 @@ -The **{pluginname}** Server requires a _public_ key generated from the same _private_ key that will be used on your JSON Web Token (JWT) provider endpoint. The public key(s) stored on the {pluginname} Server are used to ensure that content is sent by authorized users. +The **{pluginname}** Server requires a _public_ key generated from the same _private_ key that will be used on the JSON Web Token (JWT) provider endpoint. The public key(s) stored on the {pluginname} Server are used to ensure that content is sent by authorized users. -There are two methods for generating and adding a public key in the JWT Keys section of your account portal: +There are two methods for generating and adding a public key in the JWT Keys section of the account portal: . Generate New Keypair at link:{accountjwturl}[{accountpage} - JWT Keys] (recommended). . Generate a key pair locally and Import Public Key at link:{accountjwturl}[{accountpage} - JWT Keys]. -== Generate a key pair using the {accountpage} JWT Keys page +=== Generate a key pair using the {accountpage} JWT Keys page The link:{accountjwturl}[{accountpage} - JWT Keys] page provides a "Generate New Keypair" option, providing a quick and secure way of generating the required keys. This will store a copy of the _public_ key, and provide a downloadable file for both the public and private keys. {companyname} does **not store** the _private_ key and the key pair **cannot** be retrieved later. +=== Generate a key pair locally and add it to the account + +This method involves two steps: generating the key pair locally, then adding the public key to the account portal. + [[generate-a-key-pair-locally]] -== Generate a key pair locally +==== Generate a key pair locally When generating a key pair locally, use one of the supported algorithms. include::partial$auth/jwt-supported-algorithms.adoc[] @@ -19,11 +23,11 @@ For instructions on generating a key pair locally, see: xref:generate-rsa-key-pa [[add-a-public-key-to-the-tiny-cloud-api-key]] ifeval::[{numberedHeading} == true] -= 2. Add a public key in the JWT Keys section of your account portal +==== 2. Add a public key in the JWT Keys section of the account portal endif::[] ifeval::[{numberedHeading} != true] -== Add a public key in the JWT Keys section of your account portal +==== Add a public key in the JWT Keys section of the account portal endif::[] -Once a public key has been generated locally, use the "Import Public Key" option in the JWT Keys section of your account portal at: link:{accountjwturl}[{accountpage} - JWT Keys]. +Once a public key has been generated locally, use the "Import Public Key" option in the JWT Keys section of the account portal at: link:{accountjwturl}[{accountpage} - JWT Keys]. diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc new file mode 100644 index 0000000000..89580518d4 --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/configuration-steps.adoc @@ -0,0 +1,36 @@ +== Configuration Steps + +=== Add API Key + +* Replace `no-api-key` in both files with the actual {productname} API key +* The API key should be the same in both the HTML script source and the JWT payload + +=== Add Private Key + +* Replace the private key placeholder in `jwt.js` with the actual private key +* Make sure it's in `PKCS8` format +* Keep this key secure and never share it publicly + +=== Configure AI Permissions + +* Adjust the `auth.ai.permissions` array in the JWT payload based on requirements +* See xref:tinymceai-permissions.adoc[Permissions] for available permissions and best practices + +=== Configure model selection (optional) + +* Add `tinymceai_default_model` and `tinymceai_allow_model_selection` to the editor config if needed +* See xref:tinymceai-with-jwt-authentication-nodejs.adoc#model-configuration[Model configuration] for details + +=== Running the Project + +. Start the server: ++ +[source,bash] +---- +node jwt.js +---- + +. Open the browser to: `http://localhost:3000` +. The following should be visible: +* The {productname} editor +* AI feature buttons in the toolbar (tinymceai-chat, tinymceai-quickactions, tinymceai-review) diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc new file mode 100644 index 0000000000..51213d134e --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/initial-project-setup.adoc @@ -0,0 +1,41 @@ +== Quick Start Guide + +If a Node.js project is not already set up, follow the steps below to create a basic environment for integrating TinyMCE AI with JWT authentication. If a project is already configured, skip this section and proceed to the xref:tinymceai-with-jwt-authentication-nodejs.adoc#jwt-configuration-requirements[JWT Configuration Requirements] section. + +=== Project Setup + +[source,bash] +---- +# Create and enter project directory +mkdir tinymce-my-app +cd tinymce-my-app + +# Initialize project +npm init -y + +# Install required packages +npm install express cors jsonwebtoken +---- + +Verify that the `package.json` file now includes the required dependencies. + +=== Create Project Structure + +[source,bash] +---- +# Create the public folder for web files +mkdir public +touch public/index.html +touch jwt.js +---- + +The project should look like this: + +[source] +---- +/tinymce-my-app + /public + index.html (TinyMCE webpage) + jwt.js (Server code) + package.json (Project configuration) +---- diff --git a/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc b/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc new file mode 100644 index 0000000000..61af3cafc1 --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/nodejs/intro-and-prerequisites.adoc @@ -0,0 +1,31 @@ +== Introduction + +{pluginname} requires setting up JSON Web Token (JWT) authentication to maintain control over AI feature access. A JWT endpoint generates and provides authorization tokens that verify users are authorized to use AI features, preventing unauthorized access. As a standard web services authorization solution, JWT is documented extensively at link:https://jwt.io/[https://jwt.io/]. {productname} recommends using the libraries listed on link:https://www.jwt.io/libraries[jwt.io/libraries] to create JWT tokens. + +This guide provides a comprehensive walkthrough for integrating {pluginname} with {productname}, including {pluginname} functionality, by using a Node.js server for JWT token generation. It covers project setup, server configuration, and {productname} customization. + +=== What Will Be Built + +Before diving into the technical details, here is what will be achieved with this guide: + +* A working {productname} editor running the {pluginname} plugin +* A secure authentication system using JWT tokens +* A simple Node.js server to handle the authentication + +[TIP] +==== +This guide is designed for developers new to JWT authentication and {productname} integration. +==== + +=== Prerequisites + +Before starting, ensure you have: + +* Node.js installed on the computer (to check, run `node -v` in the terminal) +* A {productname} API key with TinyMCE AI enabled (get one from link:https://www.tiny.cloud/signup[TinyMCE's website]) +* Basic familiarity with the command line + +[IMPORTANT] +==== +Ensure the API key is ready before starting. It will be needed for both the server and client configuration. +==== diff --git a/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc b/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc new file mode 100644 index 0000000000..ea07404a7b --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/php/configuration-steps.adoc @@ -0,0 +1,36 @@ +== Configuration Steps + +=== Add API Key + +* Replace `no-api-key` in both files with the actual {productname} API key +* The API key should be the same in both the HTML script source and the JWT payload + +=== Add Private Key + +* Replace the private key placeholder in `jwt.php` with the actual private key +* Make sure it's in `PKCS8` format +* Keep this key secure and never share it publicly + +=== Configure AI Permissions + +* Adjust the `auth.ai.permissions` array in the JWT payload based on requirements +* See xref:tinymceai-permissions.adoc[Permissions] for available permissions and best practices + +=== Configure model selection (optional) + +* Add `tinymceai_default_model` and `tinymceai_allow_model_selection` to the editor config if needed +* See xref:tinymceai-with-jwt-authentication-php.adoc#model-configuration[Model configuration] for details + +=== Running the Project + +. Start the server: ++ +[source,bash] +---- +php -S localhost:3000 +---- + +. Open the browser to: `http://localhost:3000` +. The following should be visible: +* The {productname} editor +* AI feature buttons in the toolbar (tinymceai-chat, tinymceai-quickactions, tinymceai-review) diff --git a/modules/ROOT/partials/auth/tinymceai/php/initial-project-setup.adoc b/modules/ROOT/partials/auth/tinymceai/php/initial-project-setup.adoc new file mode 100644 index 0000000000..b8f8f89a3c --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/php/initial-project-setup.adoc @@ -0,0 +1,53 @@ +== Update PHP Configuration File + +Use the following command to locate the PHP configuration file: + +[source,bash] +---- +php --ini +---- + +Open the configuration file in a text editor and ensure the following settings are enabled: + +[source,ini] +---- +extension=openssl +extension_dir='ext' +---- + +[TIP] +The path to the extension directory may vary depending on the system. + +== Quick Start Guide + +=== Project Setup + +[source,bash] +---- +# Create and enter project directory +mkdir tinymce-app +cd tinymce-app +# Initialize Composer +composer require firebase/php-jwt +---- + +=== Create Project Structure + +[source,bash] +---- +# Create the public folder for web files +touch index.html +touch jwt.php +---- + +The project should look like this: + +[source] +---- +/tinymce-app + index.html (TinyMCE webpage) + jwt.php (Server code) + composer.json + composer.lock + vendor +---- diff --git a/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc b/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc new file mode 100644 index 0000000000..8b2d27940c --- /dev/null +++ b/modules/ROOT/partials/auth/tinymceai/php/intro-and-prerequisites.adoc @@ -0,0 +1,33 @@ +== Introduction + +{pluginname} requires setting up JSON Web Token (JWT) authentication to maintain control over AI feature access. A JWT endpoint generates and provides authorization tokens that verify users are authorized to use AI features, preventing unauthorized access. As a standard web services authorization solution, JWT is documented extensively at link:https://jwt.io/[https://jwt.io/]. {productname} recommends using the libraries listed on link:https://www.jwt.io/libraries[jwt.io/libraries] to create JWT tokens. + +This guide provides a comprehensive walkthrough for integrating {pluginname} with {productname}, including {pluginname} functionality, by using a PHP server for JWT token generation. It covers project setup, server configuration, and {productname} customization. + +=== What Will Be Built + +Before diving into the technical details, here is what will be achieved with this guide: + +* A working {productname} editor running the {pluginname} plugin +* A secure authentication system using JWT tokens +* A simple PHP server to handle the authentication + +[TIP] +==== +This guide is designed for developers new to JWT authentication and {productname} integration. +==== + +=== Prerequisites + +Before starting, ensure you have: + +* PHP installed on the computer (to check, run `php -v` in the terminal) +* OpenSSL installed on the computer (to check, run `openssl version` in the terminal) +* Composer installed on the computer (to check, run `composer -v` in the terminal) +* A {productname} API key with TinyMCE AI enabled (get one from link:https://www.tiny.cloud/signup[TinyMCE's website]) +* Basic familiarity with the command line + +[IMPORTANT] +==== +Ensure the API key is ready before starting. It will be needed for both the server and client configuration. +==== diff --git a/modules/ROOT/partials/commands/tinymceai-cmds.adoc b/modules/ROOT/partials/commands/tinymceai-cmds.adoc new file mode 100644 index 0000000000..b1cfe6b3f2 --- /dev/null +++ b/modules/ROOT/partials/commands/tinymceai-cmds.adoc @@ -0,0 +1,20 @@ +[[tinymceai-toggling-sidebars]] +.Toggling the AI Chat and AI Review sidebars + +AI Chat and AI Review use sidebars registered by the plugin. To show or hide them programmatically, use the core `+ToggleSidebar+` command (listed in the xref:editor-command-identifiers.adoc#miscellaneous-core-commands[Miscellaneous Core Commands] table), not a command defined by the TinyMCE AI plugin. Pass the sidebar identifier as the third argument: + +* `+'tinymceai-chat'+` — AI Chat +* `+'tinymceai-review'+` — AI Review + +.Examples +[source,js] +---- +// Open the AI Chat sidebar +tinymce.activeEditor.execCommand('ToggleSidebar', false, 'tinymceai-chat'); + +// Close the current sidebar (pass the same ID again to toggle off) +tinymce.activeEditor.execCommand('ToggleSidebar', false, 'tinymceai-chat'); + +// Open the AI Review sidebar +tinymce.activeEditor.execCommand('ToggleSidebar', false, 'tinymceai-review'); +---- diff --git a/modules/ROOT/partials/configuration/allow_noneditable.adoc b/modules/ROOT/partials/configuration/allow_noneditable.adoc new file mode 100644 index 0000000000..597ac1cab3 --- /dev/null +++ b/modules/ROOT/partials/configuration/allow_noneditable.adoc @@ -0,0 +1,18 @@ +[[allow_noneditable]] +== `+allow_noneditable+` + +This option controls whether the non-editable content feature is enabled. When set to `+false+`, the non-editable feature is disabled entirely, equivalent to disabling the `noneditable` plugin prior to {productname} 6. + +*Type:* `+Boolean+` + +*Default value:* `+true+` + +=== Example: using `+allow_noneditable+` + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + allow_noneditable: false +}); +---- diff --git a/modules/ROOT/partials/configuration/elementpath.adoc b/modules/ROOT/partials/configuration/elementpath.adoc index 3c88dbeb83..ced99d9363 100644 --- a/modules/ROOT/partials/configuration/elementpath.adoc +++ b/modules/ROOT/partials/configuration/elementpath.adoc @@ -9,6 +9,8 @@ For example: If a paragraph element within a table is selected, the element path Selecting elements from the element path allows users to perform operations on blocks, such as applying formatting or copying an entire block. +For assistive technologies, the element path container uses `role="group"` with an `aria-label` (localized; `Element Path` in English). For keyboard access from the content area, see xref:tinymce-and-screenreaders.adoc#navigating-element-path[Accessible navigation guide]. + *Type:* `+Boolean+` *Default value:* `+true+` diff --git a/modules/ROOT/partials/configuration/exportpdf_converter_options.adoc b/modules/ROOT/partials/configuration/exportpdf_converter_options.adoc deleted file mode 100644 index 667d77a730..0000000000 --- a/modules/ROOT/partials/configuration/exportpdf_converter_options.adoc +++ /dev/null @@ -1,42 +0,0 @@ -[[exportpdf-converter-options]] -== `exportpdf_converter_options` - -This option allows the editor to download a PDF document containing its content, along with the specified options defined in the `exportpdf_converter_options`. - -**Type:** `+Object+` - -[NOTE] -As of {productname} 7.5.0, the `exportpdf_converter_options` setting now comes with a default value set to the following: - -.**Default value:** -[source,js] ----- -{ - format: 'Letter', - margin_top: '1in', - margin_right: '1in', - margin_bottom: '1in', - margin_left: '1in' -} ----- - -=== Example: using `exportpdf_converter_options` - -[source,js] ----- -tinymce.init({ - selector: 'textarea', - plugins: 'exportpdf', - toolbar: 'exportpdf', - exportpdf_service_url: '', // required if using On-premises service - exportpdf_converter_options: { - header_html: '

HEADER

', // example - header_and_footer_css: 'p { color: blue }', // example - }, -}) ----- - -[NOTE] -The `exportpdf_service_url` option must be configured for the {pluginname} plugin to work. - -> For comprehensive details regarding the `exportpdf_converter_options`, please refer to the https://exportpdf.api.tiny.cloud/v1/convert/docs[API documentation^] available for the {pluginname} Premium plugin. \ No newline at end of file diff --git a/modules/ROOT/partials/configuration/exportpdf_converter_options_combined.adoc b/modules/ROOT/partials/configuration/exportpdf_converter_options_combined.adoc new file mode 100644 index 0000000000..fe17afa27f --- /dev/null +++ b/modules/ROOT/partials/configuration/exportpdf_converter_options_combined.adoc @@ -0,0 +1,152 @@ +[[exportpdf-converter-options]] +== `exportpdf_converter_options` + +Configures page layout, headers, footers, and other PDF output options. The editor sends this configuration to the converter service when exporting. + +**Type:** `+Object+` + +[TIP] +==== +**Which format to use** + +* **Flat format** – Use for existing integrations (no changes required) or when a simple structure is preferred. Properties such as `format`, `margin_top`, `header_html` at the top level. +* **Nested format** – Use for new integrations or when per-page headers, PDF metadata, security, or digital signatures are needed. Set `version: '2'` and organize options under `document`, `headers`, `footers`, `metadata`. +==== + +Both formats use the same API endpoint. Flat-format options are converted to the nested structure automatically before the request. + +[NOTE] +==== +Requires {productname} 8.4.0 or newer. On-premises deployments require a Docker image version that supports the v2 API. +==== + +=== Flat format + +Top-level properties: `format`, `margin_top`, `margin_right`, `margin_bottom`, `margin_left`, `header_html`, `footer_html`, `header_and_footer_css`, `page_orientation`, `wait_for_network`, `wait_time`, `base_url`, `extra_http_headers`. Supported for backward compatibility. + +[NOTE] +As of {productname} 7.5.0, the `exportpdf_converter_options` setting now comes with a default value set to the following: + +.**Default value (flat format):** +[source,js] +---- +{ + format: 'Letter', + margin_top: '1in', + margin_right: '1in', + margin_bottom: '1in', + margin_left: '1in' +} +---- + +.Example: flat format +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'exportpdf', + toolbar: 'exportpdf', + exportpdf_service_url: '', // required if using On-premises service + exportpdf_converter_options: { + header_html: '

HEADER

', // example + header_and_footer_css: 'p { color: blue }', // example + }, +}) +---- + +=== Nested format + +Set `version: '2'` to use the nested structure. Access per-page headers and footers, PDF metadata, security, and digital signatures. + +.**Default value (nested format):** +[source,js] +---- +{ + version: '2', + document: { + size: 'Letter', + margins: { + top: '1in', + right: '1in', + bottom: '1in', + left: '1in' + } + } +} +---- + +**Main option groups:** + +[cols="1,3",options="header"] +|=== +| Option | Description +| `document` | Page size, orientation, and margins +| `headers` / `footers` | Per-page headers and footers (`default`, `first`, `odd`, `even`) with `html` and `css` +| `metadata` | PDF metadata (`title`, `author`, `subject`, `keywords` array, `custom_fields`) +|=== + +**Additional options:** + +* `rendering` – `wait_for_network`, `wait_time` +* `security` – `owner_password` (password protection) +* `signature` – `certificate`, `certificate_password` (digital signing; cannot be used with `security`) +* `base_url`, `extra_http_headers`, `disable_compression` + +For full details, see the https://exportpdf.api.tiny.cloud/v2/convert/docs#section/Export-to-PDF-(v2)/Configuration[PDF Converter API documentation^]. + +.Example: per-page headers and footers +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'exportpdf', + toolbar: 'exportpdf', + exportpdf_service_url: '', + exportpdf_converter_options: { + version: '2', + document: { + size: 'Letter', + orientation: 'portrait', + margins: { + top: '2cm', + bottom: '2cm', + left: '1cm', + right: '3cm', + enable_mirror_margins: true + } + }, + headers: { + default: { html: '

HEADER

', css: 'p { color: blue }' }, + first: { html: '

FIRST PAGE

', css: 'p { font-weight: bold }' } + }, + footers: { + default: { html: '

FOOTER

', css: 'p { color: green }' } + } + }, +}); +---- + +.Example: metadata +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'exportpdf', + toolbar: 'exportpdf', + exportpdf_converter_options: { + version: '2', + metadata: { + title: 'My Document', + author: 'John Doe', + subject: 'Quarterly Report', + keywords: [ 'report', '2024', 'sales' ], + custom_fields: { 'Department': 'Sales' } + } + } +}); +---- + +[NOTE] +The `exportpdf_service_url` option must be configured for the {pluginname} plugin to work. + +> For comprehensive details, see the https://exportpdf.api.tiny.cloud/v2/convert/docs[PDF Converter API documentation^]. For migration guidance from flat to nested format, see the https://exportpdf.api.tiny.cloud/v2/convert/docs#section/Export-to-PDF-(v2)/Migration-guide-from-v1-to-v2[migration guide^]. diff --git a/modules/ROOT/partials/configuration/exportpdf_converter_style.adoc b/modules/ROOT/partials/configuration/exportpdf_converter_style.adoc index bab144bf40..c7cc600390 100644 --- a/modules/ROOT/partials/configuration/exportpdf_converter_style.adoc +++ b/modules/ROOT/partials/configuration/exportpdf_converter_style.adoc @@ -1,7 +1,7 @@ [[exportpdf-converter-style]] == `exportpdf_converter_style` -The `exportpdf_converter_style` option allow for customization of the styles applied to the exported PDF document, providing flexibility in controlling its appearance. +The `exportpdf_converter_style` option allows customization of the styles applied to the exported PDF document, providing flexibility in controlling its appearance. *Type:* `+String+` @@ -17,19 +17,20 @@ tinymce.init({ toolbar: 'exportpdf', exportpdf_service_url: '', // required if using On-premises service exportpdf_converter_options: { // required to support "exportpdf_converter_style" - header: [ - { - html: '

First page header.

', //example - css: 'h1 { font-size: 30px; }', //example - } - ], + header_html: '

First page header.

', + header_and_footer_css: 'h1 { font-size: 30px; }' }, exportpdf_converter_style: 'p { color: cyan !important }' // requires both "exportpdf_converter_style" and "exportpdf_service_url" to be set. }); ---- [TIP] -Watermarks can be added to exported PDF documents using CSS. Add the watermark styles to the `exportpdf_converter_style` option, targeting `body::after` instead of `#tinymce::after` for proper rendering. For more information see: link:https://exportpdf.converter.tiny.cloud/docs#section/General/CSS[General/CSS]. +==== +Watermarks can be added to exported PDF documents using CSS. + +* Add the watermark styles to the `exportpdf_converter_style` option, targeting **`body::after`** instead of **`#tinymce::after`** for proper rendering. +* For more information see: link:https://exportpdf.converter.tiny.cloud/docs#section/General/CSS[General/CSS]. +==== === Example: Adding watermarks to exported PDF documents diff --git a/modules/ROOT/partials/configuration/exportpdf_service_url.adoc b/modules/ROOT/partials/configuration/exportpdf_service_url.adoc index 1348e22c2b..13424b60d8 100644 --- a/modules/ROOT/partials/configuration/exportpdf_service_url.adoc +++ b/modules/ROOT/partials/configuration/exportpdf_service_url.adoc @@ -5,6 +5,11 @@ The {pluginname} plugin uses an HTML-to-PDF converter service to generate `docum This option is **required** when configuring the {pluginname} plugin for `on-premise` setups. If you require access to this feature, please link:https://www.tiny.cloud/contact/[contact us]. For detailed instructions on deploying the {pluginname} service server-side component using Docker, refer to the xref:individual-export-to-pdf-on-premises.adoc[on-premises documentation]. +[IMPORTANT] +==== +On-premises deployments require a Docker image version that supports the v2 API (`/v2/convert/html-pdf`). Upgrade to the latest image or a v2-compatible version to use {productname} 8.4.0 or newer with the Export to PDF plugin. +==== + [TIP] When using a custom host, set the `exportpdf_service_url` option in your {productname} configuration to match your host. For example, if your custom host is `mycustomhost.com`, set the URL to `https://mycustomhost.com/`. diff --git a/modules/ROOT/partials/configuration/fullpagehtml-getcontent-setcontent.adoc b/modules/ROOT/partials/configuration/fullpagehtml-getcontent-setcontent.adoc new file mode 100644 index 0000000000..7551bec2f6 --- /dev/null +++ b/modules/ROOT/partials/configuration/fullpagehtml-getcontent-setcontent.adoc @@ -0,0 +1,22 @@ +[[fullpagehtml-getcontent-setcontent]] +== `+fullpagehtml+` option for `+getContent()+` and `+setContent()+` + +When the {pluginname} plugin is active, `editor.getContent()` and `editor.setContent()` return and accept the full HTML document by default. The `fullpagehtml` option allows getting and setting only the body content when needed. + +Pass `fullpagehtml: false` in the options object to bypass full-page processing and work with body content only: + +* `editor.getContent({ fullpagehtml: false })` — Returns only the `` content. +* `editor.setContent(content, { fullpagehtml: false })` — Sets only the body content without modifying the document head. + +This option is useful when saving or loading body content separately (for example, when storing content in a database or when integrating with systems that expect body-only HTML). Unlike `fullpagehtml_hide_in_source_view`, which affects only the source code view display, the `fullpagehtml` option affects API behavior and requires no configuration. + +=== Example: getting and setting body content + +[source,js] +---- +// Get only the body content for saving +const bodyContent = editor.getContent({ fullpagehtml: false }); + +// Set only the body content (preserves document head) +editor.setContent(newBodyContent, { format: 'html', fullpagehtml: false }); +---- diff --git a/modules/ROOT/partials/configuration/icon_list.adoc b/modules/ROOT/partials/configuration/icon_list.adoc index 17901d0db6..8ef810d54b 100644 --- a/modules/ROOT/partials/configuration/icon_list.adoc +++ b/modules/ROOT/partials/configuration/icon_list.adoc @@ -19,6 +19,7 @@ | `+alt-text+` | image:icons/alt-text.svg[alt-text.svg] | `+alt-text.svg+` | `+arrow-left+` | image:icons/arrow-left.svg[arrow-left.svg] | `+arrow-left.svg+` | `+arrow-right+` | image:icons/arrow-right.svg[arrow-right.svg] | `+arrow-right.svg+` +| `+auto-image-enhancement+` | image:icons/auto-image-enhancement.svg[auto-image-enhancement.svg] | `+auto-image-enhancement.svg+` | `+blur+` | image:icons/blur.svg[blur.svg] | `+blur.svg+` | `+bold+` | image:icons/bold.svg[bold.svg] | `+bold.svg+` | `+bookmark+` | image:icons/bookmark.svg[bookmark.svg] | `+bookmark.svg+` @@ -36,14 +37,14 @@ | `+character-count+` | image:icons/character-count.svg[character-count.svg] | `+character-count.svg+` | `+checklist-rtl+` | image:icons/checklist-rtl.svg[checklist-rtl.svg] | `+checklist-rtl.svg+` | `+checklist+` | image:icons/checklist.svg[checklist.svg] | `+checklist.svg+` -| `+checkmark+` | image:icons/checkmark.svg[checkmark.svg] | `+checkmark.svg+` | `+checkmark-filled+` | image:icons/checkmark-filled.svg[checkmark-filled.svg] | `+checkmark-filled.svg+` +| `+checkmark+` | image:icons/checkmark.svg[checkmark.svg] | `+checkmark.svg+` | `+chevron-down+` | image:icons/chevron-down.svg[chevron-down.svg] | `+chevron-down.svg+` | `+chevron-left+` | image:icons/chevron-left.svg[chevron-left.svg] | `+chevron-left.svg+` | `+chevron-right+` | image:icons/chevron-right.svg[chevron-right.svg] | `+chevron-right.svg+` | `+chevron-up+` | image:icons/chevron-up.svg[chevron-up.svg] | `+chevron-up.svg+` -| `+close+` | image:icons/close.svg[close.svg] | `+close.svg+` | `+close-filled+` | image:icons/close-filled.svg[close-filled.svg] | `+close-filled.svg+` +| `+close+` | image:icons/close.svg[close.svg] | `+close.svg+` | `+code-sample+` | image:icons/code-sample.svg[code-sample.svg] | `+code-sample.svg+` | `+color-levels+` | image:icons/color-levels.svg[color-levels.svg] | `+color-levels.svg+` | `+color-picker+` | image:icons/color-picker.svg[color-picker.svg] | `+color-picker.svg+` @@ -57,7 +58,8 @@ | `+cut-column+` | image:icons/cut-column.svg[cut-column.svg] | `+cut-column.svg+` | `+cut-row+` | image:icons/cut-row.svg[cut-row.svg] | `+cut-row.svg+` | `+cut+` | image:icons/cut.svg[cut.svg] | `+cut.svg+` -| `+default-document-properties+` | image:icons/default-document-properties.svg[default-document-properties.svg] | `+default-document-properties.svg+` +| `+document-gear-properties+` | image:icons/document-gear-properties.svg[document-gear-properties.svg] | `+document-gear-properties.svg+` +| `+document-properties+` | image:icons/document-properties.svg[document-properties.svg] | `+document-properties.svg+` | `+drag+` | image:icons/drag.svg[drag.svg] | `+drag.svg+` | `+dropbox+` | image:icons/dropbox.svg[dropbox.svg] | `+dropbox.svg+` | `+duplicate-column+` | image:icons/duplicate-column.svg[duplicate-column.svg] | `+duplicate-column.svg+` @@ -71,6 +73,7 @@ | `+evernote+` | image:icons/evernote.svg[evernote.svg] | `+evernote.svg+` | `+export-pdf+` | image:icons/export-pdf.svg[export-pdf.svg] | `+export-pdf.svg+` | `+export-word+` | image:icons/export-word.svg[export-word.svg] | `+export-word.svg+` +| `+export+` | image:icons/export.svg[export.svg] | `+export.svg+` | `+exposure+` | image:icons/exposure.svg[exposure.svg] | `+exposure.svg+` | `+fb+` | image:icons/fb.svg[fb.svg] | `+fb.svg+` | `+feedback+` | image:icons/feedback.svg[feedback.svg] | `+feedback.svg+` @@ -95,7 +98,7 @@ | `+horizontal-rule+` | image:icons/horizontal-rule.svg[horizontal-rule.svg] | `+horizontal-rule.svg+` | `+huddle+` | image:icons/huddle.svg[huddle.svg] | `+huddle.svg+` | `+image-decorative+` | image:icons/image-decorative.svg[image-decorative.svg] | `+image-decorative.svg+` -| `+auto-image-enhancement+` | image:icons/auto-image-enhancement.svg[auto-image-enhancement.svg] | `+auto-image-enhancement.svg+` +| `+image-enhancements+` | image:icons/image-enhancements.svg[image-enhancements.svg] | `+image-enhancements.svg+` | `+image-options+` | image:icons/image-options.svg[image-options.svg] | `+image-options.svg+` | `+image+` | image:icons/image.svg[image.svg] | `+image.svg+` | `+import-word+` | image:icons/import-word.svg[import-word.svg] | `+import-word.svg+` @@ -110,10 +113,10 @@ | `+line-height+` | image:icons/line-height.svg[line-height.svg] | `+line-height.svg+` | `+line+` | image:icons/line.svg[line.svg] | `+line.svg+` | `+link+` | image:icons/link.svg[link.svg] | `+link.svg+` -| `+list-bull-default+` | image:icons/list-bull-default.svg[list-bull-default.svg] | `+list-bull-default.svg+` | `+list-bull-circle+` | image:icons/list-bull-circle.svg[list-bull-circle.svg] | `+list-bull-circle.svg+` -| `+list-bull-square+` | image:icons/list-bull-square.svg[list-bull-square.svg] | `+list-bull-square.svg+` +| `+list-bull-default+` | image:icons/list-bull-default.svg[list-bull-default.svg] | `+list-bull-default.svg+` | `+list-bull-disc+` | image:icons/list-bull-disc.svg[list-bull-disc.svg] | `+list-bull-disc.svg+` +| `+list-bull-square+` | image:icons/list-bull-square.svg[list-bull-square.svg] | `+list-bull-square.svg+` | `+list-num-default-rtl+` | image:icons/list-num-default-rtl.svg[list-num-default-rtl.svg] | `+list-num-default-rtl.svg+` | `+list-num-default+` | image:icons/list-num-default.svg[list-num-default.svg] | `+list-num-default.svg+` | `+list-num-lower-alpha-rtl+` | image:icons/list-num-lower-alpha-rtl.svg[list-num-lower-alpha-rtl.svg] | `+list-num-lower-alpha-rtl.svg+` @@ -128,7 +131,8 @@ | `+list-num-upper-roman+` | image:icons/list-num-upper-roman.svg[list-num-upper-roman.svg] | `+list-num-upper-roman.svg+` | `+lock+` | image:icons/lock.svg[lock.svg] | `+lock.svg+` | `+ltr+` | image:icons/ltr.svg[ltr.svg] | `+ltr.svg+` -| `+math+` | image:icons/math-equation.svg[math-equation.svg] | `+math-equation.svg+` +| `+math-equation+` | image:icons/math-equation.svg[math-equation.svg] | `+math-equation.svg+` +| `+mentions+` | image:icons/mentions.svg[mentions.svg] | `+mentions.svg+` | `+minus+` | image:icons/minus.svg[minus.svg] | `+minus.svg+` | `+more-drawer+` | image:icons/more-drawer.svg[more-drawer.svg] | `+more-drawer.svg+` | `+new-document+` | image:icons/new-document.svg[new-document.svg] | `+new-document.svg+` @@ -149,6 +153,7 @@ | `+paste-text+` | image:icons/paste-text.svg[paste-text.svg] | `+paste-text.svg+` | `+paste+` | image:icons/paste.svg[paste.svg] | `+paste.svg+` | `+permanent-pen+` | image:icons/permanent-pen.svg[permanent-pen.svg] | `+permanent-pen.svg+` +| `+photo-filter+` | image:icons/photo-filter.svg[photo-filter.svg] | `+photo-filter.svg+` | `+plus+` | image:icons/plus.svg[plus.svg] | `+plus.svg+` | `+preferences+` | image:icons/preferences.svg[preferences.svg] | `+preferences.svg+` | `+preview+` | image:icons/preview.svg[preview.svg] | `+preview.svg+` @@ -161,7 +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+` | image:icons/revert.svg[revert.svg] | `+revert.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+` | `+rotate-right+` | image:icons/rotate-right.svg[rotate-right.svg] | `+rotate-right.svg+` @@ -178,9 +183,9 @@ | `+spell-check+` | image:icons/spell-check.svg[spell-check.svg] | `+spell-check.svg+` | `+strike-through+` | image:icons/strike-through.svg[strike-through.svg] | `+strike-through.svg+` | `+subscript+` | image:icons/subscript.svg[subscript.svg] | `+subscript.svg+` -| `+superscript+` | image:icons/superscript.svg[superscript.svg] | `+superscript.svg+` -| `+suggestededits+` | image:icons/suggestededits.svg[suggestededits.svg] | `+suggestededits.svg+` | `+suggestededits-badge+` | image:icons/suggestededits-badge.svg[suggestededits-badge.svg] | `+suggestededits-badge.svg+` +| `+suggestededits+` | image:icons/suggestededits.svg[suggestededits.svg] | `+suggestededits.svg+` +| `+superscript+` | image:icons/superscript.svg[superscript.svg] | `+superscript.svg+` | `+table-caption+` | image:icons/table-caption.svg[table-caption.svg] | `+table-caption.svg+` | `+table-cell-classes+` | image:icons/table-cell-classes.svg[table-cell-classes.svg] | `+table-cell-classes.svg+` | `+table-cell-properties+` | image:icons/table-cell-properties.svg[table-cell-properties.svg] | `+table-cell-properties.svg+` @@ -218,9 +223,9 @@ | `+unlock+` | image:icons/unlock.svg[unlock.svg] | `+unlock.svg+` | `+unordered-list+` | image:icons/unordered-list.svg[unordered-list.svg] | `+unordered-list.svg+` | `+unselected+` | image:icons/unselected.svg[unselected.svg] | `+unselected.svg+` -| `+upload+` | image:icons/upload.svg[upload.svg] | `+upload.svg+` | `+upload-from-device+` | image:icons/upload-from-device.svg[upload-from-device.svg] | `+upload-from-device.svg+` | `+upload-from-link+` | image:icons/upload-from-link.svg[upload-from-link.svg] | `+upload-from-link.svg+` +| `+upload+` | image:icons/upload.svg[upload.svg] | `+upload.svg+` | `+user+` | image:icons/user.svg[user.svg] | `+user.svg+` | `+vertical-align+` | image:icons/vertical-align.svg[vertical-align.svg] | `+vertical-align.svg+` | `+vibrance+` | image:icons/vibrance.svg[vibrance.svg] | `+vibrance.svg+` @@ -231,4 +236,4 @@ | `+warning+` | image:icons/warning.svg[warning.svg] | `+warning.svg+` | `+zoom-in+` | image:icons/zoom-in.svg[zoom-in.svg] | `+zoom-in.svg+` | `+zoom-out+` | image:icons/zoom-out.svg[zoom-out.svg] | `+zoom-out.svg+` -|=== \ No newline at end of file +|=== diff --git a/modules/ROOT/partials/configuration/table_default_header_cols.adoc b/modules/ROOT/partials/configuration/table_default_header_cols.adoc new file mode 100644 index 0000000000..e070653202 --- /dev/null +++ b/modules/ROOT/partials/configuration/table_default_header_cols.adoc @@ -0,0 +1,18 @@ +[[table_default_header_cols]] +== `+table_default_header_cols+` + +The `+table_default_header_cols+` option sets the number of default header columns for new tables created through the editor UI (for example, via the table picker or insert table dialog). This helps integrators meet accessibility standards by ensuring new tables have header columns by default without manual intervention. + +*Type:* `+Number+` + +*Default value:* `+0+` + +=== Example: using `+table_default_header_cols+` + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + table_default_header_cols: 1 +}); +---- diff --git a/modules/ROOT/partials/configuration/table_default_header_rows.adoc b/modules/ROOT/partials/configuration/table_default_header_rows.adoc new file mode 100644 index 0000000000..812d519e96 --- /dev/null +++ b/modules/ROOT/partials/configuration/table_default_header_rows.adoc @@ -0,0 +1,18 @@ +[[table_default_header_rows]] +== `+table_default_header_rows+` + +The `+table_default_header_rows+` option sets the number of default header rows for new tables created through the editor UI (for example, via the table picker or insert table dialog). This helps integrators meet accessibility standards by ensuring new tables have header rows by default without manual intervention. + +*Type:* `+Number+` + +*Default value:* `+0+` + +=== Example: using `+table_default_header_rows+` + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + table_default_header_rows: 1 +}); +---- diff --git a/modules/ROOT/partials/configuration/tinymceai_options.adoc b/modules/ROOT/partials/configuration/tinymceai_options.adoc new file mode 100644 index 0000000000..cc862a84af --- /dev/null +++ b/modules/ROOT/partials/configuration/tinymceai_options.adoc @@ -0,0 +1,527 @@ +Configuration options are grouped by the feature they configure. Options in the General section apply to the plugin as a whole or to multiple features. + +[[options-general]] +== General options + +These options apply to the plugin overall or to multiple AI features (Chat, Quick Actions, Review). + +[TIP] +==== +For context toolbar use cases (a toolbar that appears when text is selected), use the xref:quickbars.adoc[Quick Toolbars] plugin and configure `+quickbars_selection_toolbar+` with the desired control identifiers. +==== + +[[content_id]] +=== `+content_id+` + +A unique identifier for the document or content being edited. When set, the chat history shown for the user is scoped to this ID, allowing conversations to be preserved and associated with the specific document across sessions. When not set, all conversations for the user are shown regardless of document. + +*Type:* `+String+` + +*Default value:* `+undefined+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + content_id: 'document-123', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_token_provider]] +=== `+tinymceai_token_provider+` + +A function that returns a Promise resolving to an object with a `+token+` property containing the signed JWT token for authenticating with the {pluginname} service. + +*Type:* `+Function+` (`+() => Promise<{ token: string }>+`) + +*Default value:* `+undefined+` + +The JWT payload must include these required claims: + +* `+iat+`: Issued at time (provided by JWT libraries) +* `+exp+`: Expiration time (tokens cannot exceed 24 hours; 5-15 minutes recommended) +* `+aud+`: The {productname} API key +* `+auth+`: Authentication object +* `+sub+`: Unique user ID + +For more information about JWT setup, required claims, and the authentication object, see xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication]. + +[NOTE] +==== +During a {cloudname} trial, a xref:tinymceai-jwt-authentication-intro.adoc#trial-demo-identity-service[demo identity service] is available so `tinymceai_token_provider` can obtain JWTs without implementing a custom token endpoint. See xref:tinymceai-jwt-authentication-intro.adoc[JWT Authentication] for setup and examples. +==== + +The function must return the token value within an object with a `+token+` property. Ensure the response from the token endpoint is handled correctly, based on the response format: + +* **JSON response**: Endpoint returns `+{ "token": "eyJ..." }+`. Use `+fetch(url).then(r => r.json())+`. +* **Plain text response**: Endpoint returns the raw JWT string. Use `+fetch(url).then(r => r.text()).then(token => ({ token }))+`. + +.Example: JSON response from custom endpoint +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_token_provider: () => { + return fetch('/api/tinymceai-token').then(r => r.json()); + } +}); +---- + +.Example: Plain text response from custom endpoint +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.text()).then(token => ({ token })); + } +}); +---- + +[[tinymceai_sidebar_type]] +=== `+tinymceai_sidebar_type+` + +Controls how the AI sidebar is displayed. With `+static+`, the sidebar renders inside the editor. With `+floating+`, it renders in a separate container outside the editor and can be dragged on the page. + +*Type:* `+String+` + +*Possible Values:* `+'static'+`, `+'floating'+` + +*Default value:* `+'static'+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + 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.json()); + } +}); +---- + +[NOTE] +==== +Changing this property dynamically (after the editor has been initialized) is not supported and can result in unpredictable behavior. +==== + +[[tinymceai_default_model]] +=== `+tinymceai_default_model+` + +The default AI model to use when no model is explicitly selected by the user. If undefined, the AI service will select the best model for speed, quality, and cost. + +*Type:* `+String+` + +*Default value:* `+undefined+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_default_model: 'gemini-2-5-flash', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_allow_model_selection]] +=== `+tinymceai_allow_model_selection+` + +Whether users can select a different AI model from the chat interface. + +*Type:* `+Boolean+` + +*Possible Values:* `+true+`, `+false+` + +*Default value:* `+true+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_allow_model_selection: false, + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[options-chat]] +== Options for Chat + +These options configure the AI Chat sidebar, where users have interactive conversations with the AI and can add external sources for context. + +[[tinymceai_chat_fetch_sources]] +=== `+tinymceai_chat_fetch_sources+` + +Populates the sources menu with submenus of files and web resources. Users can select these sources as additional context for chat conversations. + +Takes a function that returns a Promise resolving to an array of additional context source groups. Each group has `+label+`, optional `+icon+`, and `+sources+` array. Each source has `+id+`, `+label+`, and `+type+` (`+'web-resource'+` or `+'file'+`). A source's `+id+` is used to fetch its content via xref:tinymceai.adoc#tinymceai_chat_fetch_source[`tinymceai_chat_fetch_source`]. + +*Type:* `+Function+` (`+() => Promise+`) + +*Possible Values:* For source `+type+` property: `+'web-resource'+`, `+'file'+` + +*Default value:* `+() => Promise.resolve([])+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_chat_fetch_sources: async () => [ + { + label: 'My Documents', + icon: 'folder', + sources: [ + { id: 'doc-1', label: 'Document 1', type: 'file' }, + { id: 'url-1', label: 'Web Page', type: 'web-resource' } + ] + } + ], + tinymceai_chat_fetch_source: async (id) => { + const res = await fetch(`/api/documents/\$\{id\}`); + const blob = await res.blob(); + const filename = `\$\{id\}.pdf`; + return { type: 'file', file: new File([blob], filename, { type: blob.type }) }; + }, + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_chat_fetch_source]] +=== `+tinymceai_chat_fetch_source+` + +A function that fetches the content for an additional source by ID. Receives the source `+id+` and returns a Promise resolving to the source content (either `+{ type: 'file', file: File }+` or `+{ type: 'web-resource', url: string }+`). The content is passed to the AI agent as additional context for the chat conversation. + +*Type:* `+Function+` (`+(id: string) => Promise+`) + +*Possible Values:* For return object `+type+` property: `+'file'+`, `+'web-resource'+` + +*Default value:* `+(id) => Promise.resolve(\`Should fetch additional source with given \$\{id\}\`)+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_chat_fetch_sources: async () => [ + { label: 'Docs', sources: [{ id: 'doc-1', label: 'Document 1', type: 'file' }] } + ], + tinymceai_chat_fetch_source: async (id) => { + const res = await fetch(`/api/documents/\$\{id\}`); + const blob = await res.blob(); + const filename = `\$\{id\}.pdf`; + return { type: 'file', file: new File([blob], filename, { type: blob.type }) }; + }, + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_chat_welcome_message]] +=== `+tinymceai_chat_welcome_message+` + +Customises the welcome message displayed in the Chat sidebar when starting a new conversation. + +*Type:* `+String+` + +*Default value:* A default message introducing the AI assistant and its capabilities. + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_chat_welcome_message: '

Welcome! How can I help you today?

', + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[options-quickactions]] +== Options for Quick Actions + +These options configure the Quick Actions menu, which provides one-click AI transformations such as writing and grammar improvements, translation, and tone changes. + +[[tinymceai_quickactions_menu]] +=== `+tinymceai_quickactions_menu+` + +Array of control IDs that define the order of items in the Quick Actions menu. The default value includes all default items, including `+ai-quickactions-custom+` which adds a submenu of custom actions defined by `+tinymceai_quickactions_custom+`. + +*Type:* `+Array+` of `+String+` + +*Default value:* +[source,js] +---- +[ + 'ai-quickactions-chat-prompts', + 'ai-quickactions-improve-writing', + 'ai-quickactions-continue-writing', + 'ai-quickactions-check-grammar', + 'ai-quickactions-change-length', + 'ai-quickactions-change-tone', + 'ai-quickactions-translate', + 'ai-quickactions-custom' +] +---- + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_quickactions_menu: [ + 'ai-quickactions-improve-writing', + 'ai-quickactions-check-grammar', + 'ai-quickactions-custom' + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_quickactions_chat_prompts]] +=== `+tinymceai_quickactions_chat_prompts+` + +Array of control IDs for the Chat Commands submenu within the AI Quick Actions menu. + +*Type:* `+Array+` of `+String+` + +*Default value:* `+['ai-chat-explain', 'ai-chat-summarize', 'ai-chat-highlight-key-points']+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_quickactions_chat_prompts: [ + 'ai-chat-explain', + 'ai-chat-summarize', + 'ai-chat-highlight-key-points' + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_quickactions_change_tone_menu]] +=== `+tinymceai_quickactions_change_tone_menu+` + +Array of control IDs for the Change Tone submenu within the AI Quick Actions menu. + +*Type:* `+Array+` of `+String+` + +*Default value:* +[source,js] +---- +[ + 'ai-quickactions-tone-casual', + 'ai-quickactions-tone-direct', + 'ai-quickactions-tone-friendly', + 'ai-quickactions-tone-confident', + 'ai-quickactions-tone-professional' +] +---- + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_quickactions_change_tone_menu: [ + 'ai-quickactions-tone-casual', + 'ai-quickactions-tone-professional' + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_languages]] +=== `+tinymceai_languages+` + +Array of language options for the Translate submenu within the AI Quick Actions menu. Each item has `+title+` (displayed in the menu) and `+language+` (language name or label sent to the API, for example `+'english'+`, `+'chinese'+`). + +The `+language+` string is passed to the API as the target language description. Values are not limited to the built-in examples: any clear label the model can interpret can be used (including informal or regional phrasing). + +*Type:* `+Array+` of `+Object+` + +*Default value:* +[source,js] +---- +[ + { 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: 'Korean', language: 'korean' }, + { title: 'Italian', language: 'italian' }, + { title: 'Russian', language: 'russian' } +] +---- + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_languages: [ + { title: 'English', language: 'english' }, + { title: 'French', language: 'french' }, + { title: 'German', language: 'german' } + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[tinymceai_quickactions_custom]] +=== `+tinymceai_quickactions_custom+` + +Array of custom actions rendered in the Custom submenu within the AI Quick Actions menu. Each item can be type `+action+` (quick action with immediate preview) or type `+chat+` (opens in chat). + +* `+title+`: Text shown in the menu and chat history +* `+prompt+`: The prompt sent to the AI +* `+type+`: `+'action'+` or `+'chat'+` +* `+model+`: Required for `+action+` type only + +*Type:* `+Array+` of `+Object+` + +*Possible Values:* For `+type+` property: `+'action'+`, `+'chat'+` + +*Default value:* `+[]+` + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_quickactions_custom: [ + { + title: 'Add a quote from a famous person', + prompt: 'Add a quote from a known person, which would make sense in the context of the selected text.', + type: 'action', + model: 'gemini-2-5-flash' + }, + { + title: 'Summarize in 5 bullet points', + prompt: 'Summarize the selected text in 5 bullet points.', + type: 'chat' + } + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + +[[options-review]] +== Options for Review + +These options configure the AI Review sidebar, which provides content quality analysis and improvement suggestions. + +[[tinymceai_reviews]] +=== `+tinymceai_reviews+` + +Array of review command IDs that define which review types appear in the Review sidebar and their order. Only the listed reviews are available to users. + +*Type:* `+Array+` of `+String+` + +*Valid values:* + +* `+'ai-reviews-proofread'+`: Check grammar, spelling, and punctuation +* `+'ai-reviews-improve-clarity'+`: Improve logical structure and precision +* `+'ai-reviews-improve-readability'+`: Adjust sentence structure and word choice +* `+'ai-reviews-change-length'+`: Shorten or lengthen text +* `+'ai-reviews-change-tone'+`: Modify tone and style + +*Default value:* +[source,js] +---- +[ + 'ai-reviews-proofread', + 'ai-reviews-improve-clarity', + 'ai-reviews-improve-readability', + 'ai-reviews-change-length', + 'ai-reviews-change-tone' +] +---- + +.Example +[source,js] +---- +tinymce.init({ + selector: 'textarea', + plugins: 'tinymceai', + toolbar: 'tinymceai-chat tinymceai-quickactions tinymceai-review', + tinymceai_reviews: [ + 'ai-reviews-proofread', + 'ai-reviews-improve-clarity', + 'ai-reviews-change-tone' + ], + // Required for authentication + tinymceai_token_provider: () => { + return fetch('/api/token').then(r => r.json()); + } +}); +---- + diff --git a/modules/ROOT/partials/configuration/view_show.adoc b/modules/ROOT/partials/configuration/view_show.adoc new file mode 100644 index 0000000000..ce630a8d84 --- /dev/null +++ b/modules/ROOT/partials/configuration/view_show.adoc @@ -0,0 +1,61 @@ +[[view_show]] +== `+view_show+` + +This option allows the specified view to be displayed on editor initialization. It behaves similarly to xref:customsidebar.adoc#sidebar_show[`+sidebar_show+`] but applies to views and takes precedence when both are configured. Views and sidebars can both be set to show on init, with the sidebar shown once the view is closed. + +The value must match the name of a registered view. Premium plugins that register views include: + +* xref:suggestededits.adoc[Suggested Edits] (`+suggestededits+`) +* xref:revisionhistory.adoc[Revision History] (`+revision+`) +* xref:advcode.adoc[Enhanced Code Editor] (`+code+`) + +Custom views registered via xref:custom-view.adoc[`+addView+`] can also be specified. + +include::partial$misc/admon-iframe-only.adoc[] + +*Type:* `+String+` + +=== Example: using `+view_show+` with a premium plugin + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + plugins: 'suggestededits', + toolbar: 'suggestededits', + view_show: 'suggestededits', + // ... other Suggested Edits options (suggestededits_model, user_id, fetch_users) +}); +---- + +=== Example: using `+view_show+` with a custom view + +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + menubar: false, + toolbar: 'view', + view_show: 'view', + setup: (editor) => { + const toggleView = () => editor.execCommand('ToggleView', false, 'view'); + editor.ui.registry.addView('view', { + onShow: (api) => { + api.getContainer().innerHTML = '

You opened the view!

'; + }, + onHide: (api) => { + api.getContainer().innerHTML = ''; + }, + buttons: [{ + type: 'button', + text: 'Close', + onAction: toggleView + }] + }); + editor.ui.registry.addButton('view', { + text: 'Open view', + onAction: toggleView + }); + } +}); +---- diff --git a/modules/ROOT/partials/index-pages/premium-plugins.adoc b/modules/ROOT/partials/index-pages/premium-plugins.adoc index 8f1777535e..de1b794c83 100644 --- a/modules/ROOT/partials/index-pages/premium-plugins.adoc +++ b/modules/ROOT/partials/index-pages/premium-plugins.adoc @@ -1,5 +1,7 @@ This section lists the premium plugins provided by {productname}. +include::partial$misc/admon-plugins-tinymce-ai-feature.adoc[] + [cols="1,1"] |=== @@ -17,9 +19,9 @@ Replace common typewriter-style characters with their professional typesetter eq a| [.lead] -xref:ai.adoc[AI Assistant] +xref:ai.adoc[AI Assistant (legacy)] -Send queries to registered AI APIs and set the results in the current document. +Earlier plugin for sending queries to registered AI APIs and inserting results into the document. New integrations are documented under xref:tinymceai-introduction.adoc[TinyMCE AI]. a| [.lead] diff --git a/modules/ROOT/partials/individually-licensed-components/export-to-pdf/export-to-pdf-overview.adoc b/modules/ROOT/partials/individually-licensed-components/export-to-pdf/export-to-pdf-overview.adoc index faa4fa789c..42dff818cd 100644 --- a/modules/ROOT/partials/individually-licensed-components/export-to-pdf/export-to-pdf-overview.adoc +++ b/modules/ROOT/partials/individually-licensed-components/export-to-pdf/export-to-pdf-overview.adoc @@ -3,6 +3,11 @@ The On-Premises version of the {pluginname} Converter is an application that can be installed and run on the customer’s in-house servers and computing infrastructure, including a private cloud. It contains all the features of the {pluginname} Converter available as SaaS. +[IMPORTANT] +==== +To use {productname} 8.4.0 or newer with the Export to PDF plugin, the on-premises Docker image must support the v2 API (`/v2/convert/html-pdf`). Use the latest image or a v2-compatible version. See the link:https://registry.containers.tiny.cloud/api/changelogs/pdf-converter-tiny[changelog^] for version details. +==== + A valid license key is required in order to install {pluginname} Converter On-Premises. You will also need an access token to access the {companyname} Cloud Docker registry and pull the Docker image. To get started, link:https://www.tiny.cloud/contact/[Contact Tiny Support] for a trial license key and Docker access token. diff --git a/modules/ROOT/partials/menu-item-ids/tinymceai-menu-items.adoc b/modules/ROOT/partials/menu-item-ids/tinymceai-menu-items.adoc new file mode 100644 index 0000000000..6746f9af5f --- /dev/null +++ b/modules/ROOT/partials/menu-item-ids/tinymceai-menu-items.adoc @@ -0,0 +1,10 @@ +[cols="1,1,2",options="header"] +|=== +|Menu item identifier |Default Menu Location |Description + +|image:icons-premium/ai-assistant.svg[Chat icon,24px] `+tinymceai-chat+` |Tools |Opens the AI Chat sidebar. +|image:icons/ai-prompt.svg[Quick Actions icon,24px] `+tinymceai-quickactions+` |Tools |Opens the AI Quick Actions menu. +|image:icons-premium/ai-review.svg[Review icon,24px] `+tinymceai-review+` |Tools |Opens the AI Review sidebar. +|=== + +For submenu and individual menu item identifiers (for example, `+ai-quickactions-improve-writing+`, `+ai-chat-explain+`), see xref:tinymceai-actions.adoc#configuring-quick-actions-menu[Configuring Quick Actions menu]. diff --git a/modules/ROOT/partials/misc/admon-plugins-tinymce-ai-feature.adoc b/modules/ROOT/partials/misc/admon-plugins-tinymce-ai-feature.adoc new file mode 100644 index 0000000000..13a5b740e7 --- /dev/null +++ b/modules/ROOT/partials/misc/admon-plugins-tinymce-ai-feature.adoc @@ -0,0 +1,47 @@ +// Premium plugins index — TinyMCE AI feature advert. Single passthrough (markup then +++++ diff --git a/modules/ROOT/partials/misc/supported-versions.adoc b/modules/ROOT/partials/misc/supported-versions.adoc index 9ca7ecd657..0b12df3564 100644 --- a/modules/ROOT/partials/misc/supported-versions.adoc +++ b/modules/ROOT/partials/misc/supported-versions.adoc @@ -6,6 +6,7 @@ Supported versions of {productname}: [cols="^,^,^",options="header"] |=== |Version |Release Date |End of Premium Support +|8.4 |2026-03-31 |2027-09-30 |8.3 |2025-12-10 |2027-06-10 |8.2 |2025-10-22 |2027-04-22 |8.1 |2025-09-17 |2027-03-17 diff --git a/modules/ROOT/partials/misc/tinymceai-on-premises-early-access-note.adoc b/modules/ROOT/partials/misc/tinymceai-on-premises-early-access-note.adoc new file mode 100644 index 0000000000..0ed30266ff --- /dev/null +++ b/modules/ROOT/partials/misc/tinymceai-on-premises-early-access-note.adoc @@ -0,0 +1,4 @@ +[NOTE] +==== +⭐️ On-premises deployment for the AI service is available in early access; link:{contactpage}[Contact {supportname}] for details. +==== \ No newline at end of file diff --git a/modules/ROOT/partials/plugins/advcode-open-view.adoc b/modules/ROOT/partials/plugins/advcode-open-view.adoc new file mode 100644 index 0000000000..d4e899a68f --- /dev/null +++ b/modules/ROOT/partials/plugins/advcode-open-view.adoc @@ -0,0 +1,14 @@ +== Show view on editor load + +The xref:custom-view.adoc#view_show[`+view_show+`] option can be used to show the {pluginname} view when the editor is loaded. + +.For example: +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + plugins: 'advcode', + toolbar: 'code', + view_show: 'code', +}); +---- diff --git a/modules/ROOT/partials/plugins/revisionhistory-open-view.adoc b/modules/ROOT/partials/plugins/revisionhistory-open-view.adoc new file mode 100644 index 0000000000..98a16364e9 --- /dev/null +++ b/modules/ROOT/partials/plugins/revisionhistory-open-view.adoc @@ -0,0 +1,15 @@ +== Show view on editor load + +The xref:custom-view.adoc#view_show[`+view_show+`] option can be used to show the {pluginname} view when the editor is loaded. + +.For example: +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + plugins: 'revisionhistory', + toolbar: 'revisionhistory', + view_show: 'revision', + revisionhistory_fetch: () => Promise.resolve([]), // Replace with API request to get saved revisions +}); +---- diff --git a/modules/ROOT/partials/plugins/suggestededits-open-view.adoc b/modules/ROOT/partials/plugins/suggestededits-open-view.adoc new file mode 100644 index 0000000000..1885c66f11 --- /dev/null +++ b/modules/ROOT/partials/plugins/suggestededits-open-view.adoc @@ -0,0 +1,15 @@ +== Show view on editor load + +The xref:custom-view.adoc#view_show[`+view_show+`] option can be used to show the {pluginname} view when the editor is loaded. + +.For example: +[source,js] +---- +tinymce.init({ + selector: 'textarea', // change this value according to your HTML + plugins: 'suggestededits', + toolbar: 'suggestededits', + view_show: 'suggestededits', + // ... other Suggested Edits options (e.g. suggestededits_model, user_id, fetch_users) +}); +---- diff --git a/modules/ROOT/partials/toolbar-button-ids/tinymceai-toolbar-buttons.adoc b/modules/ROOT/partials/toolbar-button-ids/tinymceai-toolbar-buttons.adoc new file mode 100644 index 0000000000..b19b5cf42c --- /dev/null +++ b/modules/ROOT/partials/toolbar-button-ids/tinymceai-toolbar-buttons.adoc @@ -0,0 +1,10 @@ +[cols="2,3",options="header"] +|=== +|Toolbar button identifier |Description + +|image:icons-premium/ai-assistant.svg[Chat icon,24px] `+tinymceai-chat+` |Opens the AI Chat sidebar for conversations with the AI agent. +|image:icons/ai-prompt.svg[Quick Actions icon,24px] `+tinymceai-quickactions+` |Opens the AI Quick Actions menu (improve writing, fix grammar, translate, and similar). +|image:icons-premium/ai-review.svg[Review icon,24px] `+tinymceai-review+` |Opens the AI Review sidebar for running content review workflows. +|=== + +For submenu and individual action identifiers (for example, `+ai-quickactions-improve-writing+`, `+ai-chat-explain+`), see xref:tinymceai-actions.adoc#configuring-quick-actions-menu[Configuring Quick Actions menu].