### Install and Initialize AIEditor Source: https://context7.com/aieditor-team/aieditor/llms.txt Install AIEditor via npm and initialize it with basic configuration options like element, placeholder, initial content, theme, and auto-save settings. ```typescript // Install: npm i aieditor import {AiEditor} from "aieditor"; import "aieditor/dist/style.css" const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", content: 'AiEditor is an Open Source Rich Text Editor Designed for AI.', theme: "light", // or "dark" contentRetention: true, // Auto-save to localStorage contentRetentionKey: 'ai-editor-content', draggable: true, // Allow resize by dragging }) ``` -------------------------------- ### Install AiEditor Source: https://github.com/aieditor-team/aieditor/blob/main/docs/getting-started.md Install the AiEditor package using npm. This command is for a Node.js environment. ```shell npm i aieditor ``` -------------------------------- ### System Prompt Example in API Request Source: https://github.com/aieditor-team/aieditor/blob/main/docs/ai/chat.md This JSON structure illustrates how a system prompt is included in an API request to an AI model. It shows the roles and content for system and user messages. ```json { "model": "gpt-4o", "stream": true, "messages": [ { "role": "system", "content": "Your name is AIEditor Editorial Assistant, and you are good at text creation and content optimization." }, { "role": "user", "content": "hello" } ] } ``` -------------------------------- ### Using the AIEditor Component in an Example Source: https://github.com/aieditor-team/aieditor/blob/main/docs/aieditor-with-react.md Demonstrates how to use the `AIEditor` component within a React application, managing its state with `useState` and handling changes via the `onChange` callback. ```jsx const [value, setValue] = useState(""); setValue(val)} /> ``` -------------------------------- ### Configure AI Menu Prompts in AIEditor Source: https://github.com/aieditor-team/aieditor/blob/main/docs/ai/prompt.md Example of configuring AI menus with custom icons, names, and prompts. This setup is used when a user selects text and interacts with an AI feature. ```typescript new AiEditor({ element: "#aiEditor", ai:{ // models:{...] menus:[ { icon: ``, name: "AI Continuation", prompt: "Please help me expand on this passage.", text: "focusBefore", }, { icon: ``, name: "AI Optimization", prompt: "Please help me optimize the content of this text and return the results", text: "selected", }, ] }, }) ``` -------------------------------- ### Server-Side URL Signing for Secure AI Requests Source: https://context7.com/aieditor-team/aieditor/llms.txt Implement secure AI API calls by signing URLs on the server. This example shows how to fetch a signed URL and track token consumption. ```typescript new AiEditor({ element: "#aiEditor", ai: { models: { spark: { appId: "your-app-id", } }, onCreateClientUrl: (modelName, modelConfig, startFn) => { // Fetch signed URL from your backend fetch("/api/ai/get-signed-url?appId=" + modelConfig.appId) .then(resp => resp.json()) .then(json => { startFn(json.url) // Start AI request with signed URL }) }, onTokenConsume(modelName, modelConfig, count) { // Track token usage for billing/monitoring fetch("/api/ai/track-tokens", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: modelName, tokens: count }) }) } }, }) ``` -------------------------------- ### Initialize AiEditor in Svelte Component Source: https://github.com/aieditor-team/aieditor/blob/main/docs/aieditor-with-svelte.md This snippet shows the basic setup for using AiEditor in a Svelte component. It imports necessary modules, initializes the editor on component mount, and cleans it up on destroy. Ensure the 'aieditor' package is installed. ```html AIEditor Demo for Svelte

AIEditor Demo for Svelte

``` -------------------------------- ### Initialize AIEditor with Light Theme Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/theme.md Initializes AIEditor using the default light theme. No specific theme configuration is needed as 'light' is the default. ```typescript new AiEditor({ element: "#aiEditor", placeholder: "Click to enter content...", content: 'AiEditor is an open source rich text editor for AI. ', // theme: "light", }) ``` -------------------------------- ### Vue3 Composition API Integration Source: https://github.com/aieditor-team/aieditor/blob/main/docs/aieditor-with-vue3.md Integrate AiEditor using Vue3's Composition API with `setup`. This example demonstrates using `ref` for element referencing and `onMounted`/`onUnmounted` for lifecycle management. Remember to import the CSS. ```vue ``` -------------------------------- ### AI Prompt with {content} Placeholder Source: https://github.com/aieditor-team/aieditor/blob/main/docs/ai/prompt.md Demonstrates using the {content} placeholder in a prompt to dynamically insert user-selected text. This ensures clarity and accuracy when the selected text might conflict with a simple prompt. ```plaintext Please help me optimize the text content and return the result. The text content is: “{content}” Note that only English content can be returned, not Chinese content. ``` -------------------------------- ### Configure Video Upload Source: https://context7.com/aieditor-team/aieditor/llms.txt Set up custom video upload handling, including URL, form name, headers, and event callbacks for pre-upload checks, success, and failure. ```typescript new AiEditor({ element: "#aiEditor", video: { uploadUrl: "https://your-domain.com/api/video/upload", uploadFormName: "video", uploadHeaders: () => ({ "Authorization": "Bearer " + getAuthToken(), }), uploaderEvent: { onUploadBefore: (file, uploadUrl, headers) => { if (file.size > 100 * 1024 * 1024) { alert("Video file too large (max 100MB)"); return false; // Abort upload } }, onSuccess: (file, response) => { // Transform response if needed return { errorCode: 0, data: { src: response.videoUrl, poster: response.thumbnailUrl, width: "100%", controls: "true" } }; }, onFailed: (file, response) => { alert("Video upload failed: " + response.message); }, } }, }) ``` -------------------------------- ### Get HTML Content from AiEditor Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Retrieves the current content of the editor as an HTML string. Ensure the editor is initialized before calling this method. ```typescript const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", }) //Get the editing content and read it as an HTML string. const html = aiEditor.getHtml(); console.log(html) ``` -------------------------------- ### Handle Editor Creation Event Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Executes a callback function immediately after the AiEditor instance has been successfully created. Useful for initial setup or logging. ```typescript const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", onCreated:(aiEditor)=>{ console.log("AIEditor instance created....") } }) ``` -------------------------------- ### Initialize AiEditor with Mention Query Callback Source: https://github.com/aieditor-team/aieditor/blob/main/docs/zh/config/mention.md Configure the AiEditor instance to handle mention queries. The `onMentionQuery` callback receives user input and should return a list of matching user suggestions. ```typescript new AiEditor({ element: "#aiEditor", onMentionQuery: (query: string) => { return [ 'Lea Thompson', 'Cyndi Lauper', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder', 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John', 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey', 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet', ] .filter(item => item.toLowerCase().startsWith(query.toLowerCase())) .slice(0, 5) }, }) ``` -------------------------------- ### Get Editor Outline Structure Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Retrieves the outline of the editor's content, providing a structured array of headings with their properties. This is useful for navigation or generating a table of contents. ```json [ { "id":"aie-heading-1", "text":"Installation", "level":2, "pos":1203, "size":4 }, { "id":"aie-heading-2", "text":"Usage", "level":2, "pos":1229, "size":4 }, { "id":"aie-heading-3", "text":"Configuration", "level":2, "pos":2744, "size":4 } ] ``` -------------------------------- ### Handle Editor Focus Event Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Executes a callback function when the editor gains focus. This is useful for triggering actions or UI updates when the user starts interacting with the editor. ```typescript const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", onFocus:(aiEditor)=>{ console.log("get the focus....") } }) ``` -------------------------------- ### Configure AiEditor Video Settings Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/video.md Initialize AiEditor with custom video configurations, including upload URL, headers, and custom upload logic. ```typescript new AiEditor({ element: "#aiEditor", video: { customMenuInvoke: (editor: AiEditor) => { }, uploadUrl: "https://your-domain/video/upload", uploadFormName: "video", //Upload File Form Name uploadHeaders: { "jwt": "xxxxx", "other": "xxxx", }, uploader: (file, uploadUrl, headers, formName) => { //Customizable video Upload Logic }, uploaderEvent: { onUploadBefore: (file, uploadUrl, headers) => { //Listen for the video upload before it happens. This method can be left without returning any content, but if it returns false, the upload will be aborted. }, onSuccess: (file, response) => { //Listen for Video Upload Success //Note: // 1. If this method returns false, the Video will not be inserted into the editor. // 2.You can return a new JSON object to the editor here. }, onFailed: (file, response) => { //Listen for Video Upload Failure, or if the returned JSON information is incorrect. }, onError: (file, error) => { //Listen for Video Upload Errors, such as network timeouts, etc. } } }, }) ``` -------------------------------- ### Initialize AiEditor with AI Configuration Source: https://github.com/aieditor-team/aieditor/blob/main/docs/ai/codeblock.md Use this configuration to set up AI functionalities for code comments and code explanation. Specify the target element and AI model prompts. ```typescript new AiEditor({ element: "#aiEditor", ai:{ codeBlock: { codeComments: { model:"auto", prompt:"Help me add some comments to this code, and return the code with comments added. Only return the code.", }, codeExplain: { model:"auto", prompt:"Help me explain this code, providing an explanation of what the code does. Note that there's no need to explain the comments in the code.", } } }, }) ``` -------------------------------- ### Initialize AiEditor with Basic Configuration Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/base.md Use this snippet to initialize AiEditor with essential settings like element, placeholder, theme, and content. Ensure all required parameters are provided for proper editor functionality. ```typescript new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", theme: "light", content: 'AiEditor is an Open Source Rich Text Editor Designed for AI. ', contentIsMarkdown: false, contentRetention: true, contentRetentionKey: 'ai-editor-content', draggable: true, pasteAsText: false, textCounter: (text: string) => number, ai: { models: { spark: { appId: "***", apiKey: "***", apiSecret: "***", } } } }) ``` -------------------------------- ### Initialize AiEditor with Comment Functionality Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/comment.md Initializes the AiEditor component with comment features enabled, configuring LocalStorage for data persistence. This setup includes defining callbacks for comment creation, deletion, updates, and retrieval. ```typescript const colors = ['#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#92cddc', '#fac08f']; new AiEditor({ element: "#aiEditor", comment: { enable: true, floatable: false, enableWithEditDisable: true, onCommentActivated: (_commentId) => { // console.log("onCommentActivated---->", commentId) }, queryAllComments: () => { const allCommentsString = localStorage.getItem("all-comments"); const allCommentIds = allCommentsString ? JSON.parse(allCommentsString) : []; const allComments = [] as any[]; allCommentIds.forEach((commentId: any) => { const contentJSON = localStorage.getItem(commentId); if (contentJSON) allComments.push(JSON.parse(contentJSON)); }) return allComments; }, queryCommentsByIds: (commentIds) => { const allComments = [] as any[]; if (commentIds) commentIds.forEach((commentId: any) => { const contentJSON = localStorage.getItem("comment-" + commentId); if (contentJSON) allComments.push(JSON.parse(contentJSON)); }) return allComments; }, onCommentCreate: (comment) => { console.log("onCommentCreate---->", comment) comment = { ...comment, account: "张三", // avatar: Math.floor(Math.random() * 10) > 3 ? "https://aieditor.dev/assets/image/logo.png" : undefined, mainColor: colors[Math.floor(Math.random() * colors.length)], createdAt: "05-26 10:23", } as CommentInfo; localStorage.setItem("comment-" + comment.id, JSON.stringify(comment)); const allCommentsString = localStorage.getItem("all-comments"); const allComments = allCommentsString ? JSON.parse(allCommentsString) : []; if (comment.pid) { const parentCommentJSON = localStorage.getItem("comment-" + comment.pid); if (parentCommentJSON) { const parentComment = JSON.parse(parentCommentJSON); if (parentComment.children) { parentComment.children.unshift(comment) } else { parentComment.children = [comment] } localStorage.setItem("comment-" + comment.pid, JSON.stringify(parentComment)); } } else { allComments.push("comment-" + comment.id) } localStorage.setItem("all-comments", JSON.stringify(allComments)); // return callback(comment); return new Promise((resolve) => { resolve(comment) }) // return comment; }, onCommentDeleteConfirm: (comment) => { console.log("onCommentDeleteConfirm---->", comment) return confirm("确认要删除吗"); }, onCommentDelete: (commentId) => { console.log("onCommentDelete---->", commentId) const commentInfo = JSON.parse(localStorage.getItem("comment-" + commentId)!); if (commentInfo.pid) { const parentCommentJSON = localStorage.getItem("comment-" + commentInfo.pid); if (parentCommentJSON) { const parentComment = JSON.parse(parentCommentJSON); if (parentComment.children) { parentComment.children = parentComment.children.filter((item: any) => item.id !== commentId) localStorage.setItem("comment-" + commentInfo.pid, JSON.stringify(parentComment)); } } } localStorage.removeItem("comment-" + commentId); return true; }, onCommentUpdate: (commentId, content) => { console.log("onCommentUpdate---->", commentId, content) const commentInfo = JSON.parse(localStorage.getItem("comment-" + commentId)!); commentInfo.content = content localStorage.setItem("comment-" + commentId, JSON.stringify(commentInfo)) return true } }, }) ``` -------------------------------- ### Configure Gitee AI with Advanced Parameters Source: https://github.com/aieditor-team/aieditor/blob/main/docs/ai/llm.md Extended configuration for Gitee AI, including parameters like max_tokens, temperature, top_p, and top_k for fine-tuning responses. ```typescript new AiEditor({ element: "#aiEditor", ai: { models: { gitee:{ endpoint:"https://ai.gitee.com/api/inference/serverless/KGHCVOPBV7GY/chat/completions", apiKey:"***", max_tokens: 512, temperature: 0.7, top_p: 0.7, top_k: 50, } } }, }) ``` -------------------------------- ### Vue3 SSR Integration with Dynamic Import Source: https://github.com/aieditor-team/aieditor/blob/main/docs/aieditor-with-vue3.md Example of integrating AiEditor in a Vue3 SSR environment using dynamic import within `onMounted`. This ensures the editor is loaded only on the client-side. CSS import is necessary. ```vue ``` -------------------------------- ### Configure AI Bubble Menu (Pro Version) Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/bubbleMenu.md Configure AI-specific menu items for the bubble menu, available only in the Pro version. Use `type: "ai"` and provide a `prompt`. This configuration will trigger an AI dialogue upon clicking. ```typescript new AiEditor({ element: "#aiEditor", placeholder: "Click to enter content...", content: 'AiEditor is an open source rich text editor for AI.', textSelectionBubbleMenu: { enable: true, items: ["ai", "Bold", "Italic", { id:"translate", icon:" ", type:"ai", prompt:"Help me translate the following content into English: {content}" }], }, }) ``` -------------------------------- ### Instantiate AiEditor in Vue2 Source: https://github.com/aieditor-team/aieditor/blob/main/docs/zh/aieditor-with-vue2.md Integrate AiEditor into a Vue2 component by using the `ref` attribute to get a DOM element reference and then instantiating `AiEditor` with configuration options. Ensure the element has a defined height for proper rendering. ```html ``` -------------------------------- ### Initialize AI Editor with Commands Source: https://github.com/aieditor-team/aieditor/blob/main/docs/zh/ai/command.md Use this to initialize the AI Editor with OpenAI model configuration and define custom AI commands. Ensure the element ID and API key are correctly set. ```typescript new AiEditor({ element: "#aiEditor", ai:{ models:{ openai: { apiKey: "sk-alQ96zbDn*****", model:"gpt-4o", } }, commands:[ { name: "AI 续写", prompt: "请帮我继续扩展一些这段话的内容", }, { name: "AI 提问", prompt: "...", }, ] }, }) ``` -------------------------------- ### Initialize AiEditor with Comment Feature Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/comment.md Use this snippet to enable the comment functionality when initializing AiEditor. Configure various aspects like floatable comments, custom class names, and user information. This setup is crucial for integrating comment features into your application. ```typescript new AiEditor({ element: "#aiEditor", comment: { enable: true, floatable: false, containerClassName: "comment-container", // currentAccountAvatar: "https://aieditor.com.cn/logo.png", currentAccount:"Miachel Yang", currentAccountId: "1", enableWithEditDisable: true, onCommentActivated: (commentIds) => { // When the comment area gets focus }, queryAllComments: () => { // Query all comments of the current document and return CommentInfo[] or Promise }, queryMyComments: () => { // Query "My Comments", return CommentInfo[] or Promise }, queryCommentsByIds: (commentIds) => { // Query multiple comments based on multiple document IDs and return CommentInfo[] or Promise }, onCommentCreate: (comment) => { // When a comment is created, returns CommentInfo or Promise }, onCommentDeleteConfirm:(comment)=>{ // When a comment is deleted, a confirmation box pops up and returns boolean or Promise; }, onCommentDelete: (commentId) => { // When the comment is deleted, returns boolean or Promise; }, onCommentUpdate: (commentId, content) => { // When the comment is modified, returns a boolean or Promise; }, }, }) ``` -------------------------------- ### Initialize AiEditor Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Initializes the AiEditor with a target element and placeholder text. This is the first step to using the editor. ```typescript const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", }) ``` -------------------------------- ### Initialize AiEditor with Mention Query Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/mention.md Configure the AiEditor to handle mention suggestions by providing an `onMentionQuery` callback. This callback receives user input and returns a filtered list of names. ```typescript new AiEditor({ element: "#aiEditor", onMentionQuery:(query:string)=>{ return [ 'Lea Thompson', 'Cyndi Lauper', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder', 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John', 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey', 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet', ] .filter(item => item.toLowerCase().startsWith(query.toLowerCase())) .slice(0, 5) }, }) ``` -------------------------------- ### 配置 AI 翻译默认语言和菜单项 Source: https://github.com/aieditor-team/aieditor/blob/main/docs/zh/ai/translate.md 通过配置 `ai.translate` 选项来设置 AI 翻译的 prompt 和菜单项。`prompt` 函数用于生成发送给大模型的翻译指令,`translateMenuItems` 数组定义了菜单中显示的翻译选项及其对应的语言。 ```typescript new AiEditor({ element: "#aiEditor", ai: { translate: { prompt: (lang, selectedText) => { return `请帮我把以下内容翻译为: ${lang},并返回翻译结果。 您需要翻译的内容是: ${selectedText}` }, translateMenuItems: [ {title: '英语', language:'英语'}, {title: '中文'}, {title: '日语'}, {title: '法语'}, {title: '德语'}, {title: '葡萄牙语'}, {title: '西班牙语'}, ], } }, }) ``` -------------------------------- ### Initialize AiEditor Pro with Comment Functionality Source: https://github.com/aieditor-team/aieditor/blob/main/docs/zh/config/comment.md Initializes AiEditor Pro with comments enabled, configuring various comment-related options. Uses local storage for persistence. ```typescript const colors = ['#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#92cddc', '#fac08f']; new AiEditorPro({ element: "#aiEditor", comment: { enable: true, // floatable: false, containerClassName: "comment-container", // currentAccountAvatar: "https://aieditor.com.cn/logo.png", currentAccount: "杨福海", currentAccountId: "1", enableWithEditDisable: true, // commentCreateDisable: true, // commentUpdateDisable: true, // commentDeleteDisable: true, // commentReplyDisable: true, onCommentActivated: (_commentIds) => { // console.log("onCommentActivated---->", commentId) }, // 注意: queryAllComments 只有在设置 `floatable = false` 是配置才有意义 queryAllComments: () => { const allCommentsString = localStorage.getItem("all-comments"); const allCommentIds = allCommentsString ? JSON.parse(allCommentsString) : []; const allComments = [] as any[]; allCommentIds.forEach((commentId: any) => { const contentJSON = localStorage.getItem(commentId); if (contentJSON) allComments.push(JSON.parse(contentJSON)); }) return allComments; }, queryCommentsByIds: (commentIds) => { const allComments = [] as any[]; if (commentIds) commentIds.forEach((commentId: any) => { const contentJSON = localStorage.getItem("comment-" + commentId); if (contentJSON) allComments.push(JSON.parse(contentJSON)); }) return new Promise((resolve) => { setTimeout(() => { resolve(allComments); }, 200) }); }, onCommentCreate: (comment) => { console.log("onCommentCreate---->", comment) comment = { ...comment, account: "杨福海", // avatar: Math.floor(Math.random() * 10) > 3 ? "https://aieditor.dev/assets/image/logo.png" : undefined, mainColor: colors[Math.floor(Math.random() * colors.length)], createdAt: "05-26 10:23", } as CommentInfo; localStorage.setItem("comment-" + comment.id, JSON.stringify(comment)); const allCommentsString = localStorage.getItem("all-comments"); const allComments = allCommentsString ? JSON.parse(allCommentsString) : []; if (comment.pid) { const parentCommentJSON = localStorage.getItem("comment-" + comment.pid); if (parentCommentJSON) { const parentComment = JSON.parse(parentCommentJSON); if (parentComment.children) { parentComment.children.unshift(comment) } else { parentComment.children = [comment] } localStorage.setItem("comment-" + comment.pid, JSON.stringify(parentComment)); } } else { allComments.push("comment-" + comment.id) } localStorage.setItem("all-comments", JSON.stringify(allComments)); return new Promise((resolve) => { setTimeout(() => { resolve(comment); }, 200); }); // return new Promise((resolve) => { // resolve(comment) // }) }, onCommentDeleteConfirm: (comment) => { console.log("onCommentDeleteConfirm---->", comment) // return confirm("确认要删除吗"); return new Promise((resolve) => { setTimeout(() => { resolve(confirm("确认要删除吗")); }, 200) }); }, onCommentDelete: (commentId) => { console.log("onCommentDelete---->", commentId) const commentInfo = JSON.parse(localStorage.getItem("comment-" + commentId)!); if (commentInfo.pid) { const parentCommentJSON = localStorage.getItem("comment-" + commentInfo.pid); if (parentCommentJSON) { const parentComment = JSON.parse(parentCommentJSON); if (parentComment.children) { parentComment.children = parentComment.children.filter((item: any) => item.id !== commentId) localStorage.setItem("comment-" + commentInfo.pid, JSON.stringify(parentComment)); } } } localStorage.removeItem("comment-" + commentId); // return true; return new Promise((resolve) => { setTimeout(() => { resolve(true); }, 200) }); }, } }); ``` -------------------------------- ### AiEditor Initialization Source: https://github.com/aieditor-team/aieditor/blob/main/docs/api/aieditor.md Initialize the AiEditor with custom element and placeholder. ```APIDOC ## Initialize AiEditor AiEditor is the core class of the entire editor, and its initialization code is as follows: ### Request Example ```typescript const aiEditor = new AiEditor({ element: "#aiEditor", placeholder: "Click to Input Content...", }) ``` ``` -------------------------------- ### Enable Basic Bubble Menu Source: https://github.com/aieditor-team/aieditor/blob/main/docs/config/bubbleMenu.md Configure the bubble menu to appear on text selection with a predefined list of items. Ensure 'enable' is set to true. Note that 'comment' item is Pro version only. ```typescript new AiEditor({ element: "#aiEditor", content: 'AiEditor is an open source rich text editor for AI.', textSelectionBubbleMenu: { enable: true, items: ["ai", "Bold", "Italic", "Underline", "Strike", "code", "comment"], }, }) ```