diff --git a/-scripts/README-llm-files.md b/-scripts/README-llm-files.md
index 9d1b1c3387..32216b49fe 100644
--- a/-scripts/README-llm-files.md
+++ b/-scripts/README-llm-files.md
@@ -81,7 +81,7 @@ The files are generated in `modules/ROOT/attachments/`:
**Post-build:** Files are moved to the root directory (handled in separate PR) and accessible at:
- `https://www.tiny.cloud/docs/tinymce/latest/llms.txt`
-- `https://www.tiny.cloud/docs/tinymce/latest/llms-full.txt`
+- `https://www.tiny.cloud/docs/llms-full.txt`
## How It Works
diff --git a/-scripts/generate-llm-files.js b/-scripts/generate-llm-files.js
index 014b307f11..5eafb7c8cc 100755
--- a/-scripts/generate-llm-files.js
+++ b/-scripts/generate-llm-files.js
@@ -16,6 +16,7 @@ const http = require('http');
const sanitizeHtml = require('sanitize-html');
const BASE_URL = 'https://www.tiny.cloud/docs/tinymce/latest';
+const DOCS_ROOT_URL = 'https://www.tiny.cloud/docs';
const OUTPUT_DIR = path.join(__dirname, '../modules/ROOT/attachments');
// Fetch sitemap from URL or file
@@ -1187,7 +1188,7 @@ function App() {
## Complete Documentation
-For a complete list of all ${urls.length} documentation pages, see [llms-full.txt](${BASE_URL}/llms-full.txt).
+For a complete list of all ${urls.length} documentation pages, see [llms-full.txt](${DOCS_ROOT_URL}/llms-full.txt).
`;
}
diff --git a/antora.yml b/antora.yml
index bd5735dda8..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,7 +22,9 @@ 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
diff --git a/modules/ROOT/attachments/llms.txt b/modules/ROOT/attachments/llms.txt
index 7b81de7981..b1857d5fb3 100644
--- a/modules/ROOT/attachments/llms.txt
+++ b/modules/ROOT/attachments/llms.txt
@@ -101,5 +101,5 @@ function App() {
## Complete Documentation
-For a complete list of all 395 documentation pages, see [llms-full.txt](https://www.tiny.cloud/docs/tinymce/latest/llms-full.txt).
+For a complete list of all 395 documentation pages, see [llms-full.txt](https://www.tiny.cloud/docs/llms-full.txt).
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..a4772e8160
--- /dev/null
+++ b/modules/ROOT/examples/live-demos/tinymceai-actions/example.js
@@ -0,0 +1,50 @@
+// Step 1: Set up session - this should be part of the application's user management process.
+tinymce.init({
+ selector: 'textarea#tinymceai-actions',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ 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_token_provider: async () => {
+ // Step 2: Check we have a session then fetch JWT from your backend
+ 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..6e38f3adfd
--- /dev/null
+++ b/modules/ROOT/examples/live-demos/tinymceai-actions/index.js
@@ -0,0 +1,51 @@
+// 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" });
+
+tinymce.init({
+ selector: 'textarea#tinymceai-actions',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ toolbar: "undo redo | tinymceai-chat tinymceai-quickactions tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
+ sidebar_show: 'tinymceai-chat',
+ 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..637ff1270b
--- /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.
+tinymce.init({
+ selector: 'textarea#tinymceai-review',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ toolbar: "undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
+ sidebar_show: 'tinymceai-review',
+ tinymceai_token_provider: async () => {
+ // Step 2: Check we have a session then fetch JWT from your backend
+ 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..50c210fc22
--- /dev/null
+++ b/modules/ROOT/examples/live-demos/tinymceai-review/index.js
@@ -0,0 +1,51 @@
+// 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" });
+
+tinymce.init({
+ selector: 'textarea#tinymceai-review',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ toolbar: "undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
+ sidebar_show: 'tinymceai-review',
+ 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..d51457a280
--- /dev/null
+++ b/modules/ROOT/examples/live-demos/tinymceai/example.js
@@ -0,0 +1,50 @@
+// Step 1: Set up session - this should be part of the application's user management process.
+tinymce.init({
+ selector: 'textarea#tinymceai',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ toolbar: "undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
+ tinymceai_token_provider: async () => {
+ // Step 2: Check we have a session then fetch JWT from your backend
+ 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..1a03053e79
--- /dev/null
+++ b/modules/ROOT/examples/live-demos/tinymceai/index.js
@@ -0,0 +1,56 @@
+// 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" });
+
+tinymce.init({
+ selector: 'textarea#tinymceai',
+ height: '610px',
+ plugins: ["tinymceai", "advlist", "anchor", "autolink", "charmap", "code"],
+ toolbar: "undo redo | tinymceai-chat ai-quickactions-translate tinymceai-review | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
+ sidebar_show: 'tinymceai-chat',
+ 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 @@
-