Skip to content

feat: Improve AI functionality - #297

Merged
kagol merged 1 commit into
opentiny:mainfrom
chenxi-20:feat/ai-tool-200250731
Jul 31, 2025
Merged

feat: Improve AI functionality#297
kagol merged 1 commit into
opentiny:mainfrom
chenxi-20:feat/ai-tool-200250731

Conversation

@chenxi-20

@chenxi-20 chenxi-20 commented Jul 31, 2025

Copy link
Copy Markdown
Contributor

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Enhanced AI editing interface with new menus, tooltips, and interactive UI elements.
    • Added configurable text length limit for AI-generated content.
    • Introduced a selection bubble for quick AI actions on selected text.
    • Added new icons and menu options for AI operations.
  • Style

    • Comprehensive redesign and improvement of AI-related UI components with new animations, hover effects, and structured layouts.
    • Updated icon styles and added a speech bubble to the AI icon.
  • Documentation

    • Updated interface documentation to include new configuration options and default values.
  • Refactor

    • Modularized and reorganized AI module code for better maintainability and clarity.
  • Chores

    • Added new constants and TypeScript interfaces for AI menu items and configuration.

@github-actions github-actions Bot added the enhancement New feature or request label Jul 31, 2025
@coderabbitai

coderabbitai Bot commented Jul 31, 2025

Copy link
Copy Markdown

Walkthrough

This update introduces a comprehensive overhaul of the AI module in the Fluent Editor, adding new UI elements, constants, icons, and TypeScript types. It refactors the AI integration for improved modularity, richer user interactions, and enhanced styling. Documentation and demo files are updated to reflect new configuration options and interface changes.

Changes

Cohort / File(s) Change Summary
AI Module Refactor & Feature Expansion
packages/fluent-editor/src/modules/ai/index.ts
Major refactor: modularizes AI UI, adds selection bubble, operation/result menus, streaming, new state variables, event handling, and richer user interactions. Updates constructor, methods, and UI logic.
AI Module Constants & Menus
packages/fluent-editor/src/modules/ai/constants.ts
Adds exported string constants for UI text, menu data for editor/tone/adjust categories, and menu ID mapping for AI features.
AI Module SVG Icons
packages/fluent-editor/src/modules/ai/icons.ts
Adds exported SVG icon constants for all AI UI elements and actions.
AI Module TypeScript Types
packages/fluent-editor/src/modules/ai/types.ts
Adds interfaces for AI options, operation/result menu items, and config typing.
AI Demo & Documentation
packages/docs/fluent-editor/demos/ai.vue, packages/docs/fluent-editor/docs/demo/ai.md
Demo: Updates toolbar config, adds contentMaxLength to AI config, and revises template content. Docs: Adds comments for AI options and documents new contentMaxLength property.
AI UI Styling
packages/fluent-editor/src/assets/ai.scss
Major style overhaul: new containers, tooltips, hover effects, flex layouts, animations, and menu/result panel styling for AI UI.
Toolbar & Common Styling
packages/fluent-editor/src/assets/common.scss, packages/fluent-editor/src/assets/toolbar.scss
Common: Excludes .ql-ai-icon from toolbar SVG color mixin. Toolbar: Adds rotate keyframes animation.
AI Icon UI Wrapper
packages/fluent-editor/src/ui/icons.config.ts
Changes AI_ICON export from SVG-only to a div-wrapped HTML structure with tooltip bubble, text, and decorative SVGs.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Editor
    participant AI_Module
    participant AI_API

    User->>Editor: Selects text or clicks AI icon
    Editor->>AI_Module: Triggers AI input panel
    AI_Module->>User: Shows input box, menus, selection bubble
    User->>AI_Module: Enters prompt / selects menu / clicks send
    AI_Module->>AI_API: Sends prompt (with streaming)
    AI_API-->>AI_Module: Streams response chunks
    AI_Module->>Editor: Updates result popup live
    User->>AI_Module: Clicks insert/replace/copy/regenerate
    AI_Module->>Editor: Performs action (insert/replace/copy)
    User->>AI_Module: Closes panel or continues interaction
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

A rabbit hops through code anew,
With menus bright and icons too,
AI now sparkles, sleek and spry,
Tooltips and bubbles catch the eye.
Types and constants join the dance,
Styling gives the UI a chance—
Let’s nibble through this change, advanced! 🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🔭 Outside diff range comments (3)
packages/fluent-editor/src/modules/ai/icons.ts (1)

1-334: Fix formatting violations: Replace tab characters with spaces.

The file contains extensive tab character violations that are causing linting failures. All tab characters must be replaced with spaces to comply with the project's ESLint configuration.

Apply this fix to replace all tab characters with spaces:

# Use sed to replace all tabs with spaces (assuming 2-space indentation)
sed -i 's/\t/  /g' packages/fluent-editor/src/modules/ai/icons.ts

Alternatively, configure your editor to use spaces instead of tabs and reformat the file.

The SVG icon definitions themselves look comprehensive and well-structured for the AI functionality.

packages/fluent-editor/src/modules/ai/index.ts (2)

679-683: Improve error handling with user feedback

The current error handling only logs to console without informing users or resetting the UI state.

Enhance error handling:

   } catch (error) {
     console.error('AI查询失败:', error)
-    return 'AI查询失败,请重试'
+    this.isThinking = false
+    this.showResultPopupEl = false
+    
+    // Show user-friendly error message
+    const errorMessage = error.message.includes('401') 
+      ? 'API密钥无效,请检查配置'
+      : error.message.includes('network')
+      ? '网络连接失败,请检查网络'
+      : 'AI查询失败,请重试'
+    
+    this.showAlert(errorMessage)
+    return ''
   }

38-807: Consider splitting the AI class into smaller, focused modules

The AI class has grown to 800+ lines handling multiple responsibilities, making it difficult to maintain and test.

Consider refactoring into separate modules:

// ai/AIService.ts - Handle API communication
export class AIService {
  async query(prompt: string, options: AIOptions): Promise<string> { }
}

// ai/AIUIBuilder.ts - Handle UI creation
export class AIUIBuilder {
  createInputPanel(): HTMLElement { }
  createResultPanel(): HTMLElement { }
  createMenus(): HTMLElement { }
}

// ai/AIStateManager.ts - Handle state
export class AIStateManager {
  private state = {
    isThinking: false,
    showResults: false,
    // etc
  }
}

// ai/AI.ts - Orchestrate the modules
export class AI {
  constructor(
    private service: AIService,
    private uiBuilder: AIUIBuilder,
    private stateManager: AIStateManager
  ) {}
}

This separation would improve testability and maintainability.

🧹 Nitpick comments (4)
packages/docs/fluent-editor/demos/ai.vue (1)

10-10: Fix missing trailing commas for consistency.

Add trailing commas to maintain consistent code style and comply with ESLint rules.

Apply these fixes:

-  ['clean']
+  ['clean'],
-          container: TOOLBAR_CONFIG
+          container: TOOLBAR_CONFIG,
-          contentMaxLength: 1000
-        }
-      }
+          contentMaxLength: 1000,
+        },
+      },

Also applies to: 22-22, 28-30

packages/fluent-editor/src/modules/ai/types.ts (2)

1-18: Fix style issues: semicolons and EOF newline

The file has inconsistent delimiter style and is missing a newline at the end.

Apply this diff to match the project's style guide:

 export interface OperationMenuItem {
-  id: string;
-  text: string;
-  icon?: string;
+  id: string
+  text: string
+  icon?: string
 }

 export interface ResultMenuItem {
-  text: string;
-  icon: string;
-  selectText?: string;
+  text: string
+  icon: string
+  selectText?: string
 }

 export interface AIOptions {
-  host?: string;
-  apiKey: string;
-  model?: string;
-  contentMaxLength?: number;
-}
+  host?: string
+  apiKey: string
+  model?: string
+  contentMaxLength?: number
+}
+

7-11: Consider adding JSDoc comments for unclear fields

The selectText field's purpose is not immediately clear from its name.

Consider adding documentation:

 export interface ResultMenuItem {
   text: string
   icon: string
+  /** Alternative text to display when in selection mode */
   selectText?: string
 }
packages/fluent-editor/src/modules/ai/index.ts (1)

3-36: Clean up imports and fix ordering

There are unused imports and ordering issues.

Fix the imports:

 import type TypeToolbar from 'quill/modules/toolbar'
 import type FluentEditor from '../../core/fluent-editor'
+import type { AIOptions, OperationMenuItem, ResultMenuItem } from './types'
+import {
+  CLOSE,
+  INPUT_PLACEHOLDER,
+  INSERT_SUB_CONTENT_TEXT,
+  INSERT_TEXT,
+  MENU_ID_MAP,
+  MENU_TITLE_DATA,
+  REGENERATE,
+  REPLACE_SELECT,
+  RESULT_HEADER_TEXT,
+  SELECT_PLACEHOLDER,
+  STOP_ANSWER,
+  THINK_TEXT,
+} from './constants'
 import {
   ADJUST_ICON,
   AI_ICON,
   CALL_ICON,
   CLOSE_ICON,
   COPY_ICON,
   EDITOR_ICON,
   INSERT_ICON,
   MENU_CLOSE_ICON,
   REBUILD_ICON,
   REFRESH_ICON,
   REPLACE_SELECT_ICON,
   RIGHT_ARROW_ICON,
   SEND_BTN_ICON,
   STOP_ICON,
   THINK_ICON,
-  SHARE_ICON,
-  VOICE_ICON
 } from './icons'
-import {
-  INPUT_PLACEHOLDER,
-  // ... rest of constants
-} from './constants'
-import type { ResultMenuItem, OperationMenuItem, AIOptions } from './types'
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53fb899 and 11775ef.

📒 Files selected for processing (10)
  • packages/docs/fluent-editor/demos/ai.vue (2 hunks)
  • packages/docs/fluent-editor/docs/demo/ai.md (1 hunks)
  • packages/fluent-editor/src/assets/ai.scss (4 hunks)
  • packages/fluent-editor/src/assets/common.scss (1 hunks)
  • packages/fluent-editor/src/assets/toolbar.scss (1 hunks)
  • packages/fluent-editor/src/modules/ai/constants.ts (1 hunks)
  • packages/fluent-editor/src/modules/ai/icons.ts (1 hunks)
  • packages/fluent-editor/src/modules/ai/index.ts (4 hunks)
  • packages/fluent-editor/src/modules/ai/types.ts (1 hunks)
  • packages/fluent-editor/src/ui/icons.config.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/fluent-editor/src/modules/ai/constants.ts (1)
packages/fluent-editor/src/modules/ai/icons.ts (4)
  • RICH_CONTENT_ICON (247-255)
  • STREAMLINE_CONTENT_ICON (258-264)
  • SYMBOL_ICON (267-273)
  • TRANSLATE_ICON (276-319)
packages/fluent-editor/src/ui/icons.config.ts (1)
packages/fluent-editor/src/modules/ai/icons.ts (1)
  • AI_ICON (321-333)
packages/fluent-editor/src/modules/ai/icons.ts (1)
packages/fluent-editor/src/ui/icons.config.ts (1)
  • AI_ICON (318-361)
🪛 ESLint
packages/docs/fluent-editor/demos/ai.vue

[error] 10-11: Missing trailing comma.

(style/comma-dangle)


[error] 10-11: Missing trailing comma.

(comma-dangle)


[error] 22-23: Missing trailing comma.

(style/comma-dangle)


[error] 22-23: Missing trailing comma.

(comma-dangle)


[error] 28-29: Missing trailing comma.

(style/comma-dangle)


[error] 28-29: Missing trailing comma.

(comma-dangle)


[error] 29-30: Missing trailing comma.

(style/comma-dangle)


[error] 29-30: Missing trailing comma.

(comma-dangle)


[error] 30-31: Missing trailing comma.

(style/comma-dangle)


[error] 30-31: Missing trailing comma.

(comma-dangle)

packages/fluent-editor/src/modules/ai/constants.ts

[error] 1-2: Too many blank lines at the beginning of file. Max of 0 allowed.

(style/no-multiple-empty-lines)


[error] 3-3: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 4-4: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 5-5: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 6-6: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 7-7: Expected indentation of 0 spaces but found 2.

(style/indent)


[error] 9-9: Extra semicolon.

(style/semi)


[error] 10-10: Extra semicolon.

(style/semi)


[error] 11-11: Extra semicolon.

(style/semi)


[error] 12-12: Extra semicolon.

(style/semi)


[error] 13-13: Extra semicolon.

(style/semi)


[error] 14-14: Extra semicolon.

(style/semi)


[error] 15-15: Extra semicolon.

(style/semi)


[error] 16-16: Extra semicolon.

(style/semi)


[error] 17-17: Extra semicolon.

(style/semi)


[error] 18-18: Extra semicolon.

(style/semi)


[error] 21-21: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 22-22: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 23-23: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 24-24: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 25-25: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 26-26: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 27-27: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 28-28: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 29-29: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 30-30: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 31-31: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 32-32: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 33-33: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 34-34: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 35-35: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 36-36: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 37-37: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 37-38: Missing trailing comma.

(style/comma-dangle)


[error] 37-38: Missing trailing comma.

(comma-dangle)


[error] 38-38: Extra semicolon.

(style/semi)


[error] 41-41: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 42-42: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 43-43: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 44-44: Extra semicolon.

(style/semi)


[error] 44-44: Newline required at end of file but not found.

(style/eol-last)


[error] 44-44: Newline required at end of file but not found.

(eol-last)

packages/fluent-editor/src/modules/ai/types.ts

[error] 2-2: Unexpected separator (;).

(style/member-delimiter-style)


[error] 3-3: Unexpected separator (;).

(style/member-delimiter-style)


[error] 4-4: Unexpected separator (;).

(style/member-delimiter-style)


[error] 8-8: Unexpected separator (;).

(style/member-delimiter-style)


[error] 9-9: Unexpected separator (;).

(style/member-delimiter-style)


[error] 10-10: Unexpected separator (;).

(style/member-delimiter-style)


[error] 14-14: Unexpected separator (;).

(style/member-delimiter-style)


[error] 15-15: Unexpected separator (;).

(style/member-delimiter-style)


[error] 16-16: Unexpected separator (;).

(style/member-delimiter-style)


[error] 17-17: Unexpected separator (;).

(style/member-delimiter-style)


[error] 18-18: Newline required at end of file but not found.

(style/eol-last)


[error] 18-18: Newline required at end of file but not found.

(eol-last)

packages/fluent-editor/src/ui/icons.config.ts

[error] 320-320: Unexpected tab character.

(style/no-tabs)


[error] 321-321: Unexpected tab character.

(style/no-tabs)


[error] 322-322: Unexpected tab character.

(style/no-tabs)


[error] 323-323: Unexpected tab character.

(style/no-tabs)


[error] 324-324: Unexpected tab character.

(style/no-tabs)


[error] 325-325: Unexpected tab character.

(style/no-tabs)


[error] 326-326: Unexpected tab character.

(style/no-tabs)


[error] 327-327: Unexpected tab character.

(style/no-tabs)


[error] 328-328: Unexpected tab character.

(style/no-tabs)


[error] 329-329: Unexpected tab character.

(style/no-tabs)


[error] 330-330: Unexpected tab character.

(style/no-tabs)

packages/fluent-editor/src/modules/ai/icons.ts

[error] 3-3: Unexpected tab character.

(style/no-tabs)


[error] 4-4: Unexpected tab character.

(style/no-tabs)


[error] 5-5: Unexpected tab character.

(style/no-tabs)


[error] 6-6: Unexpected tab character.

(style/no-tabs)


[error] 7-7: Unexpected tab character.

(style/no-tabs)


[error] 8-8: Unexpected tab character.

(style/no-tabs)


[error] 13-13: Unexpected tab character.

(style/no-tabs)


[error] 14-14: Unexpected tab character.

(style/no-tabs)


[error] 15-15: Unexpected tab character.

(style/no-tabs)


[error] 16-16: Unexpected tab character.

(style/no-tabs)


[error] 17-17: Unexpected tab character.

(style/no-tabs)


[error] 18-18: Unexpected tab character.

(style/no-tabs)


[error] 19-19: Unexpected tab character.

(style/no-tabs)


[error] 20-20: Unexpected tab character.

(style/no-tabs)


[error] 26-26: Unexpected tab character.

(style/no-tabs)


[error] 27-27: Unexpected tab character.

(style/no-tabs)


[error] 28-28: Unexpected tab character.

(style/no-tabs)


[error] 29-29: Unexpected tab character.

(style/no-tabs)


[error] 30-30: Unexpected tab character.

(style/no-tabs)


[error] 35-35: Unexpected tab character.

(style/no-tabs)


[error] 36-36: Unexpected tab character.

(style/no-tabs)


[error] 37-37: Unexpected tab character.

(style/no-tabs)


[error] 38-38: Unexpected tab character.

(style/no-tabs)


[error] 39-39: Unexpected tab character.

(style/no-tabs)


[error] 40-40: Unexpected tab character.

(style/no-tabs)


[error] 41-41: Unexpected tab character.

(style/no-tabs)


[error] 42-42: Unexpected tab character.

(style/no-tabs)


[error] 43-43: Unexpected tab character.

(style/no-tabs)


[error] 44-44: Unexpected tab character.

(style/no-tabs)


[error] 45-45: Unexpected tab character.

(style/no-tabs)


[error] 46-46: Unexpected tab character.

(style/no-tabs)


[error] 47-47: Unexpected tab character.

(style/no-tabs)


[error] 48-48: Unexpected tab character.

(style/no-tabs)


[error] 49-49: Unexpected tab character.

(style/no-tabs)


[error] 50-50: Unexpected tab character.

(style/no-tabs)


[error] 51-51: Unexpected tab character.

(style/no-tabs)


[error] 52-52: Unexpected tab character.

(style/no-tabs)


[error] 53-53: Unexpected tab character.

(style/no-tabs)


[error] 54-54: Unexpected tab character.

(style/no-tabs)


[error] 55-55: Unexpected tab character.

(style/no-tabs)


[error] 56-56: Unexpected tab character.

(style/no-tabs)


[error] 57-57: Unexpected tab character.

(style/no-tabs)


[error] 58-58: Unexpected tab character.

(style/no-tabs)


[error] 59-59: Unexpected tab character.

(style/no-tabs)


[error] 60-60: Unexpected tab character.

(style/no-tabs)


[error] 61-61: Unexpected tab character.

(style/no-tabs)


[error] 62-62: Unexpected tab character.

(style/no-tabs)


[error] 63-63: Unexpected tab character.

(style/no-tabs)


[error] 68-68: Unexpected tab character.

(style/no-tabs)


[error] 69-69: Unexpected tab character.

(style/no-tabs)


[error] 70-70: Unexpected tab character.

(style/no-tabs)


[error] 71-71: Unexpected tab character.

(style/no-tabs)


[error] 72-72: Unexpected tab character.

(style/no-tabs)


[error] 73-73: Unexpected tab character.

(style/no-tabs)


[error] 74-74: Unexpected tab character.

(style/no-tabs)


[error] 79-79: Unexpected tab character.

(style/no-tabs)


[error] 80-80: Unexpected tab character.

(style/no-tabs)


[error] 81-81: Unexpected tab character.

(style/no-tabs)


[error] 82-82: Unexpected tab character.

(style/no-tabs)


[error] 83-83: Unexpected tab character.

(style/no-tabs)


[error] 84-84: Unexpected tab character.

(style/no-tabs)


[error] 85-85: Unexpected tab character.

(style/no-tabs)


[error] 86-86: Unexpected tab character.

(style/no-tabs)


[error] 87-87: Unexpected tab character.

(style/no-tabs)


[error] 88-88: Unexpected tab character.

(style/no-tabs)


[error] 89-89: Unexpected tab character.

(style/no-tabs)


[error] 90-90: Unexpected tab character.

(style/no-tabs)


[error] 91-91: Unexpected tab character.

(style/no-tabs)


[error] 92-92: Unexpected tab character.

(style/no-tabs)


[error] 93-93: Unexpected tab character.

(style/no-tabs)


[error] 94-94: Unexpected tab character.

(style/no-tabs)


[error] 95-95: Unexpected tab character.

(style/no-tabs)


[error] 100-100: Unexpected tab character.

(style/no-tabs)


[error] 101-101: Unexpected tab character.

(style/no-tabs)


[error] 105-105: Unexpected tab character.

(style/no-tabs)


[error] 106-106: Unexpected tab character.

(style/no-tabs)


[error] 107-107: Unexpected tab character.

(style/no-tabs)


[error] 108-108: Unexpected tab character.

(style/no-tabs)


[error] 109-109: Unexpected tab character.

(style/no-tabs)


[error] 114-114: Unexpected tab character.

(style/no-tabs)


[error] 115-115: Unexpected tab character.

(style/no-tabs)


[error] 116-116: Unexpected tab character.

(style/no-tabs)


[error] 117-117: Unexpected tab character.

(style/no-tabs)


[error] 118-118: Unexpected tab character.

(style/no-tabs)


[error] 119-119: Unexpected tab character.

(style/no-tabs)


[error] 120-120: Unexpected tab character.

(style/no-tabs)


[error] 121-121: Unexpected tab character.

(style/no-tabs)


[error] 122-122: Unexpected tab character.

(style/no-tabs)


[error] 123-123: Unexpected tab character.

(style/no-tabs)


[error] 124-124: Unexpected tab character.

(style/no-tabs)


[error] 125-125: Unexpected tab character.

(style/no-tabs)


[error] 126-126: Unexpected tab character.

(style/no-tabs)


[error] 127-127: Unexpected tab character.

(style/no-tabs)


[error] 128-128: Unexpected tab character.

(style/no-tabs)


[error] 129-129: Unexpected tab character.

(style/no-tabs)


[error] 134-134: Unexpected tab character.

(style/no-tabs)


[error] 135-135: Unexpected tab character.

(style/no-tabs)


[error] 136-136: Unexpected tab character.

(style/no-tabs)


[error] 137-137: Unexpected tab character.

(style/no-tabs)


[error] 138-138: Unexpected tab character.

(style/no-tabs)


[error] 139-139: Unexpected tab character.

(style/no-tabs)


[error] 140-140: Unexpected tab character.

(style/no-tabs)


[error] 141-141: Unexpected tab character.

(style/no-tabs)


[error] 142-142: Unexpected tab character.

(style/no-tabs)


[error] 143-143: Unexpected tab character.

(style/no-tabs)


[error] 144-144: Unexpected tab character.

(style/no-tabs)


[error] 145-145: Unexpected tab character.

(style/no-tabs)


[error] 146-146: Unexpected tab character.

(style/no-tabs)


[error] 151-151: Unexpected tab character.

(style/no-tabs)


[error] 152-152: Unexpected tab character.

(style/no-tabs)


[error] 153-153: Unexpected tab character.

(style/no-tabs)


[error] 154-154: Unexpected tab character.

(style/no-tabs)


[error] 155-155: Unexpected tab character.

(style/no-tabs)


[error] 156-156: Unexpected tab character.

(style/no-tabs)


[error] 157-157: Unexpected tab character.

(style/no-tabs)


[error] 158-158: Unexpected tab character.

(style/no-tabs)


[error] 159-159: Unexpected tab character.

(style/no-tabs)


[error] 160-160: Unexpected tab character.

(style/no-tabs)


[error] 161-161: Unexpected tab character.

(style/no-tabs)


[error] 162-162: Unexpected tab character.

(style/no-tabs)


[error] 163-163: Unexpected tab character.

(style/no-tabs)


[error] 168-168: Unexpected tab character.

(style/no-tabs)


[error] 169-169: Unexpected tab character.

(style/no-tabs)


[error] 170-170: Unexpected tab character.

(style/no-tabs)


[error] 171-171: Unexpected tab character.

(style/no-tabs)


[error] 172-172: Unexpected tab character.

(style/no-tabs)


[error] 173-173: Unexpected tab character.

(style/no-tabs)


[error] 174-174: Unexpected tab character.

(style/no-tabs)


[error] 175-175: Unexpected tab character.

(style/no-tabs)


[error] 176-176: Unexpected tab character.

(style/no-tabs)


[error] 177-177: Unexpected tab character.

(style/no-tabs)


[error] 178-178: Unexpected tab character.

(style/no-tabs)


[error] 179-179: Unexpected tab character.

(style/no-tabs)


[error] 180-180: Unexpected tab character.

(style/no-tabs)


[error] 181-181: Unexpected tab character.

(style/no-tabs)


[error] 182-182: Unexpected tab character.

(style/no-tabs)


[error] 183-183: Unexpected tab character.

(style/no-tabs)


[error] 188-188: Unexpected tab character.

(style/no-tabs)


[error] 189-189: Unexpected tab character.

(style/no-tabs)


[error] 190-190: Unexpected tab character.

(style/no-tabs)


[error] 191-191: Unexpected tab character.

(style/no-tabs)


[error] 192-192: Unexpected tab character.

(style/no-tabs)


[error] 193-193: Unexpected tab character.

(style/no-tabs)


[error] 194-194: Unexpected tab character.

(style/no-tabs)


[error] 195-195: Unexpected tab character.

(style/no-tabs)


[error] 196-196: Unexpected tab character.

(style/no-tabs)


[error] 197-197: Unexpected tab character.

(style/no-tabs)


[error] 198-198: Unexpected tab character.

(style/no-tabs)


[error] 199-199: Unexpected tab character.

(style/no-tabs)


[error] 200-200: Unexpected tab character.

(style/no-tabs)


[error] 201-201: Unexpected tab character.

(style/no-tabs)


[error] 202-202: Unexpected tab character.

(style/no-tabs)


[error] 203-203: Unexpected tab character.

(style/no-tabs)


[error] 204-204: Unexpected tab character.

(style/no-tabs)


[error] 205-205: Unexpected tab character.

(style/no-tabs)


[error] 206-206: Unexpected tab character.

(style/no-tabs)


[error] 207-207: Unexpected tab character.

(style/no-tabs)


[error] 208-208: Unexpected tab character.

(style/no-tabs)


[error] 209-209: Unexpected tab character.

(style/no-tabs)


[error] 210-210: Unexpected tab character.

(style/no-tabs)


[error] 211-211: Unexpected tab character.

(style/no-tabs)


[error] 212-212: Unexpected tab character.

(style/no-tabs)


[error] 213-213: Unexpected tab character.

(style/no-tabs)


[error] 218-218: Unexpected tab character.

(style/no-tabs)


[error] 219-219: Unexpected tab character.

(style/no-tabs)


[error] 224-224: Unexpected tab character.

(style/no-tabs)


[error] 225-225: Unexpected tab character.

(style/no-tabs)


[error] 226-226: Unexpected tab character.

(style/no-tabs)


[error] 231-231: Unexpected tab character.

(style/no-tabs)


[error] 232-232: Unexpected tab character.

(style/no-tabs)


[error] 233-233: Unexpected tab character.

(style/no-tabs)


[error] 234-234: Unexpected tab character.

(style/no-tabs)


[error] 235-235: Unexpected tab character.

(style/no-tabs)


[error] 236-236: Unexpected tab character.

(style/no-tabs)


[error] 237-237: Unexpected tab character.

(style/no-tabs)


[error] 238-238: Unexpected tab character.

(style/no-tabs)


[error] 239-239: Unexpected tab character.

(style/no-tabs)


[error] 240-240: Unexpected tab character.

(style/no-tabs)


[error] 241-241: Unexpected tab character.

(style/no-tabs)


[error] 242-242: Unexpected tab character.

(style/no-tabs)


[error] 248-248: Unexpected tab character.

(style/no-tabs)


[error] 249-249: Unexpected tab character.

(style/no-tabs)


[error] 250-250: Unexpected tab character.

(style/no-tabs)


[error] 251-251: Unexpected tab character.

(style/no-tabs)


[error] 252-252: Unexpected tab character.

(style/no-tabs)


[error] 253-253: Unexpected tab character.

(style/no-tabs)


[error] 254-254: Unexpected tab character.

(style/no-tabs)


[error] 259-259: Unexpected tab character.

(style/no-tabs)


[error] 260-260: Unexpected tab character.

(style/no-tabs)


[error] 261-261: Unexpected tab character.

(style/no-tabs)


[error] 262-262: Unexpected tab character.

(style/no-tabs)


[error] 263-263: Unexpected tab character.

(style/no-tabs)


[error] 268-268: Unexpected tab character.

(style/no-tabs)


[error] 269-269: Unexpected tab character.

(style/no-tabs)


[error] 270-270: Unexpected tab character.

(style/no-tabs)


[error] 271-271: Unexpected tab character.

(style/no-tabs)


[error] 272-272: Unexpected tab character.

(style/no-tabs)


[error] 277-277: Unexpected tab character.

(style/no-tabs)


[error] 278-278: Unexpected tab character.

(style/no-tabs)


[error] 279-279: Unexpected tab character.

(style/no-tabs)


[error] 280-280: Unexpected tab character.

(style/no-tabs)


[error] 281-281: Unexpected tab character.

(style/no-tabs)


[error] 282-282: Unexpected tab character.

(style/no-tabs)


[error] 283-283: Unexpected tab character.

(style/no-tabs)


[error] 284-284: Unexpected tab character.

(style/no-tabs)


[error] 285-285: Unexpected tab character.

(style/no-tabs)


[error] 286-286: Unexpected tab character.

(style/no-tabs)


[error] 287-287: Unexpected tab character.

(style/no-tabs)


[error] 288-288: Unexpected tab character.

(style/no-tabs)


[error] 289-289: Unexpected tab character.

(style/no-tabs)


[error] 290-290: Unexpected tab character.

(style/no-tabs)


[error] 291-291: Unexpected tab character.

(style/no-tabs)


[error] 292-292: Unexpected tab character.

(style/no-tabs)


[error] 293-293: Unexpected tab character.

(style/no-tabs)


[error] 294-294: Unexpected tab character.

(style/no-tabs)


[error] 295-295: Unexpected tab character.

(style/no-tabs)


[error] 296-296: Unexpected tab character.

(style/no-tabs)


[error] 297-297: Unexpected tab character.

(style/no-tabs)


[error] 298-298: Unexpected tab character.

(style/no-tabs)


[error] 299-299: Unexpected tab character.

(style/no-tabs)


[error] 300-300: Unexpected tab character.

(style/no-tabs)


[error] 301-301: Unexpected tab character.

(style/no-tabs)


[error] 302-302: Unexpected tab character.

(style/no-tabs)


[error] 303-303: Unexpected tab character.

(style/no-tabs)


[error] 304-304: Unexpected tab character.

(style/no-tabs)


[error] 305-305: Unexpected tab character.

(style/no-tabs)


[error] 306-306: Unexpected tab character.

(style/no-tabs)


[error] 307-307: Unexpected tab character.

(style/no-tabs)


[error] 308-308: Unexpected tab character.

(style/no-tabs)


[error] 309-309: Unexpected tab character.

(style/no-tabs)


[error] 310-310: Unexpected tab character.

(style/no-tabs)


[error] 311-311: Unexpected tab character.

(style/no-tabs)


[error] 312-312: Unexpected tab character.

(style/no-tabs)


[error] 313-313: Unexpected tab character.

(style/no-tabs)


[error] 314-314: Unexpected tab character.

(style/no-tabs)


[error] 315-315: Unexpected tab character.

(style/no-tabs)


[error] 316-316: Unexpected tab character.

(style/no-tabs)


[error] 317-317: Unexpected tab character.

(style/no-tabs)


[error] 318-318: Unexpected tab character.

(style/no-tabs)


[error] 322-322: Unexpected tab character.

(style/no-tabs)


[error] 323-323: Unexpected tab character.

(style/no-tabs)


[error] 324-324: Unexpected tab character.

(style/no-tabs)


[error] 325-325: Unexpected tab character.

(style/no-tabs)


[error] 326-326: Unexpected tab character.

(style/no-tabs)


[error] 327-327: Unexpected tab character.

(style/no-tabs)


[error] 328-328: Unexpected tab character.

(style/no-tabs)


[error] 329-329: Unexpected tab character.

(style/no-tabs)


[error] 330-330: Unexpected tab character.

(style/no-tabs)


[error] 331-331: Unexpected tab character.

(style/no-tabs)


[error] 332-332: Unexpected tab character.

(style/no-tabs)

packages/fluent-editor/src/modules/ai/index.ts

[error] 19-19: Expected "SHARE_ICON" to come before "THINK_ICON".

(perfectionist/sort-named-imports)


[error] 19-19: 'SHARE_ICON' is defined but never used.

(unused-imports/no-unused-imports)


[error] 20-20: 'VOICE_ICON' is defined but never used.

(unused-imports/no-unused-imports)


[error] 20-21: Missing trailing comma.

(style/comma-dangle)


[error] 20-21: Missing trailing comma.

(comma-dangle)


[error] 22-35: Expected "./constants" to come before "./icons".

(perfectionist/sort-imports)


[error] 26-26: Expected "REPLACE_SELECT" to come before "STOP_ANSWER".

(perfectionist/sort-named-imports)


[error] 27-27: Expected "INSERT_TEXT" to come before "REPLACE_SELECT".

(perfectionist/sort-named-imports)


[error] 28-28: Expected "INSERT_SUB_CONTENT_TEXT" to come before "INSERT_TEXT".

(perfectionist/sort-named-imports)


[error] 30-30: Expected "CLOSE" to come before "REGENERATE".

(perfectionist/sort-named-imports)


[error] 32-32: Expected "RESULT_HEADER_TEXT" to come before "THINK_TEXT".

(perfectionist/sort-named-imports)


[error] 33-33: Expected "MENU_TITLE_DATA" to come before "RESULT_HEADER_TEXT".

(perfectionist/sort-named-imports)


[error] 34-34: Expected "MENU_ID_MAP" to come before "MENU_TITLE_DATA".

(perfectionist/sort-named-imports)


[error] 34-35: Missing trailing comma.

(style/comma-dangle)


[error] 34-35: Missing trailing comma.

(comma-dangle)


[error] 36-36: Expected "./types" (sibling-type) to come before "./constants" (sibling).

(perfectionist/sort-imports)


[error] 36-36: Expected "OperationMenuItem" to come before "ResultMenuItem".

(perfectionist/sort-named-imports)


[error] 36-36: Expected "AIOptions" to come before "OperationMenuItem".

(perfectionist/sort-named-imports)


[error] 92-93: Missing trailing comma.

(style/comma-dangle)


[error] 92-93: Missing trailing comma.

(comma-dangle)


[error] 112-113: Missing trailing comma.

(style/comma-dangle)


[error] 112-113: Missing trailing comma.

(comma-dangle)


[error] 118-119: Missing trailing comma.

(style/comma-dangle)


[error] 118-119: Missing trailing comma.

(comma-dangle)


[error] 130-130: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 176-176: Prefer .textContent over .innerText.

(unicorn/prefer-dom-node-text-content)


[error] 183-183: Prefer .textContent over .innerText.

(unicorn/prefer-dom-node-text-content)


[error] 307-307: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 333-333: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 443-443: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 447-447: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 546-546: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 572-572: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 634-634: Inconsistently quoted property 'Authorization' found.

(style/quote-props)


[error] 634-635: Missing trailing comma.

(style/comma-dangle)


[error] 634-635: Missing trailing comma.

(comma-dangle)


[error] 639-640: Missing trailing comma.

(style/comma-dangle)


[error] 639-640: Missing trailing comma.

(comma-dangle)


[error] 661-661: Unexpected parentheses around single function argument having a body with no curly braces.

(style/arrow-parens)


[error] 668-668: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 679-679: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 692-692: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)


[error] 759-759: Getter is not present for class setter 'charCount'.

(accessor-pairs)


[error] 768-768: Prefer .textContent over .innerText.

(unicorn/prefer-dom-node-text-content)


[error] 775-775: Getter is not present for class setter 'inputPlaceholder'.

(accessor-pairs)


[error] 782-782: Getter is not present for class setter 'showOperationMenu'.

(accessor-pairs)


[error] 789-789: Getter is not present for class setter 'isSelectRangeMode'.

(accessor-pairs)


[error] 796-796: Getter is not present for class setter 'isThinking'.

(accessor-pairs)


[error] 801-801: Getter is not present for class setter 'showResultPopupEl'.

(accessor-pairs)

🪛 GitHub Check: lint
packages/fluent-editor/src/modules/ai/icons.ts

[failure] 16-16:
Unexpected tab character


[failure] 15-15:
Unexpected tab character


[failure] 14-14:
Unexpected tab character


[failure] 13-13:
Unexpected tab character


[failure] 8-8:
Unexpected tab character


[failure] 7-7:
Unexpected tab character


[failure] 6-6:
Unexpected tab character


[failure] 5-5:
Unexpected tab character


[failure] 4-4:
Unexpected tab character


[failure] 3-3:
Unexpected tab character

🪛 GitHub Actions: autofix.ci
packages/fluent-editor/src/modules/ai/icons.ts

[error] 3-3: ESLint: Unexpected tab character (style/no-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (6)
packages/fluent-editor/src/assets/toolbar.scss (1)

380-387: LGTM! Clean keyframe animation implementation.

The rotate animation is properly defined and will support the AI "thinking" icon rotation functionality. The implementation follows CSS best practices with clear naming and standard rotation transform.

packages/docs/fluent-editor/docs/demo/ai.md (1)

14-22: LGTM! Helpful documentation improvements.

The addition of default value comments for host and model properties improves the developer experience by clearly showing what values will be used if not specified. The new contentMaxLength property is well-documented and aligns with the AI module enhancements.

packages/docs/fluent-editor/demos/ai.vue (2)

28-28: LGTM! Good addition of content length limit.

The contentMaxLength: 1000 configuration properly demonstrates the new AI text length limiting feature and aligns with the updated AIOptions interface.


38-38: LGTM! Simplified demo content.

The simplified demo content with a single meaningful paragraph is appropriate for demonstrating the AI functionality without unnecessary complexity.

packages/fluent-editor/src/assets/common.scss (1)

112-116: LGTM! Smart exclusion prevents styling conflicts.

The modification to exclude .ql-ai-icon from the general toolbar SVG styling is well-designed. This ensures that AI-specific icons maintain their distinct styling while preserving the existing behavior for other toolbar SVG elements.

packages/fluent-editor/src/assets/ai.scss (1)

303-329: :has() Selector – Compatibility Is Solid, Focus on Maintainability

Browser support for the CSS :has() pseudo-class is now widespread in all major browsers (Chrome, Firefox, Safari, Edge), so you can safely use it without compatibility workarounds. The only concern here is the verbosity and maintainability of these rules:

File: packages/fluent-editor/src/assets/ai.scss
Lines: 303–329

&:has(.editor) {
  .ql-ai-main-menu > .ql-ai-menu-item:first-child { … }
}
&:has(.tone) {
  .ql-ai-main-menu > .ql-ai-menu-item:nth-of-type(2) { … }
}
&:has(.adjust) {
  .ql-ai-main-menu > .ql-ai-menu-item:nth-of-type(3) { … }
}

Suggestions for cleaner code:

  • Extract the shared styles (background: #f5f5f5; and > svg:nth-of-type(2) { display: inline-block; }) into a mixin or utility class.
  • Add inline comments to explain the intent of each :has() block.
  • (Optional) Use modifier classes on the parent container (e.g. .ql-ai-menu-container--editor) instead of chaining :has(), which can simplify selectors and improve readability.

No compatibility fixes are required.

Comment on lines +1 to +56
.ql-ai-icon-box {
position: relative;

&:hover {
.ql-ai-icon-bubble {
display: block;
}
}

.ql-ai-icon-bubble {
display: none;
width: 216px;
height: 52px;
border-radius: 12px;
position: absolute;
top: 28px;
left: -26px;
z-index: 1000;
}

.ql-ai-icon-bubble-box {
margin-top: 8px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 44px;

.ql-ai-icon-bubble-text {
z-index: 1000;
font-size: 14px;
line-height: 21px;
color: #191919;
}

svg {
position: absolute;
}

.bubble-arrow-icon {
z-index: 1000;
left: 16px;
top: -8px;
width: 28px;
height: 9px;
}

.bubble-rect-icon {
top: 0;
width: 216px;
height: 44px;
z-index: 999;
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use CSS variables for consistent theming

The styles use many hard-coded colors and dimensions that should be extracted to CSS variables for consistency and theming support.

Consider creating theme variables:

:root {
  // Colors
  --ai-primary-color: #191919;
  --ai-border-color: #c2c2c2;
  --ai-background: white;
  --ai-shadow: 0 2px 28px 0px rgba(0, 0, 0, 0.1);
  --ai-hover-bg: #f5f5f5;
  --ai-scrollbar-color: #DBDBDB;
  
  // Dimensions
  --ai-border-radius-sm: 8px;
  --ai-border-radius-md: 12px;
  --ai-border-radius-lg: 24px;
  
  // Z-index layers
  --ai-z-bubble: 999;
  --ai-z-dialog: 1000;
  --ai-z-menu: 1001;
  --ai-z-alert: 9999;
}

// Then use them:
.ql-ai-icon-bubble {
  z-index: var(--ai-z-dialog);
  border-radius: var(--ai-border-radius-md);
}

Also applies to: 88-168, 170-220, 279-293

🤖 Prompt for AI Agents
In packages/fluent-editor/src/assets/ai.scss lines 1 to 56, replace hard-coded
colors, dimensions, and z-index values with CSS variables to support consistent
theming. Define these variables in a :root selector at the top of the file or a
global styles file, then update the styles to use var(--variable-name) for
colors like #191919, border-radius values like 12px, and z-index values like
1000. Apply the same approach to the other specified line ranges (88-168,
170-220, 279-293) for uniformity.

Comment on lines +31 to +35
z-index: 1000;
font-size: 14px;
line-height: 21px;
color: #191919;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add accessibility improvements

The styles lack important accessibility features.

Add focus styles and use relative units:

// Add focus styles for keyboard navigation
.ql-ai-menu-item,
.ql-ai-action-item,
.ql-ai-think-btn {
  &:focus {
    outline: 2px solid var(--ai-focus-color, #1890ff);
    outline-offset: 2px;
  }
}

// Use rem for font sizes
.ql-ai-icon-bubble-text {
  font-size: 0.875rem; // 14px
  line-height: 1.5;
}

// Ensure sufficient color contrast
.ql-ai-result-footer-text {
  color: #666; // Better contrast than #adadad
}

Also applies to: 117-119, 216-219, 389-393

🤖 Prompt for AI Agents
In packages/fluent-editor/src/assets/ai.scss around lines 31 to 35, add
accessibility improvements by including focus styles for keyboard navigation on
.ql-ai-menu-item, .ql-ai-action-item, and .ql-ai-think-btn with a visible
outline and offset. Change font sizes to use relative units (rem) instead of
pixels for .ql-ai-icon-bubble-text, and update color values to ensure sufficient
contrast, such as changing .ql-ai-result-footer-text color to #666. Apply
similar changes to lines 117-119, 216-219, and 389-393 as well.

Comment on lines +1 to +44

import {
RICH_CONTENT_ICON,
STREAMLINE_CONTENT_ICON,
SYMBOL_ICON,
TRANSLATE_ICON,
} from './icons'

export const INPUT_PLACEHOLDER = '请输入问题或"/"获取提示词';
export const SELECT_PLACEHOLDER = '向我提问/选择操作';
export const STOP_ANSWER = '停止回答';
export const REPLACE_SELECT = '替换选中内容';
export const INSERT_TEXT = '插入内容';
export const INSERT_SUB_CONTENT_TEXT = '插入内容下方';
export const REGENERATE = '重新生成';
export const CLOSE = '关闭';
export const THINK_TEXT = '正在为您分析并总结答案';
export const RESULT_HEADER_TEXT = '根据您的诉求,已为您解答,具体如下:';

export const MENU_TITLE_DATA = {
editor: [
{ id: '1-1', text: '丰富内容', icon: RICH_CONTENT_ICON },
{ id: '1-2', text: '精简内容', icon: STREAMLINE_CONTENT_ICON },
{ id: '1-3', text: '修改标点符号', icon: SYMBOL_ICON },
{ id: '1-4', text: '翻译', icon: TRANSLATE_ICON },
],
tone: [
{ id: '2-1', text: '更专业的' },
{ id: '2-2', text: '更直接的' },
{ id: '2-3', text: '更友善的' },
{ id: '2-4', text: '更口语化的' },
],
adjust: [
{ id: '3-1', text: '提炼要点' },
{ id: '3-2', text: '归纳总结' },
{ id: '3-3', text: '转写成[代码块]' },
]
};

export const MENU_ID_MAP = {
editor: 'subMenuEditorEl',
tone: 'subMenuToneEl',
adjust: 'subMenuAdjustEl',
}; No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix multiple style violations

The file has numerous style issues including extra blank lines, incorrect indentation, semicolons, and missing trailing commas.

Apply this diff to fix all style issues:

-
 import {
-    RICH_CONTENT_ICON,
-    STREAMLINE_CONTENT_ICON,
-    SYMBOL_ICON,
-    TRANSLATE_ICON,
-  } from './icons'
+  RICH_CONTENT_ICON,
+  STREAMLINE_CONTENT_ICON,
+  SYMBOL_ICON,
+  TRANSLATE_ICON,
+} from './icons'

-export const INPUT_PLACEHOLDER = '请输入问题或"/"获取提示词';
+export const INPUT_PLACEHOLDER = '请输入问题或"/"获取提示词'
 // ... (apply similar changes to all constants, removing semicolons)

 export const MENU_TITLE_DATA = {
-    editor: [
-      { id: '1-1', text: '丰富内容', icon: RICH_CONTENT_ICON },
-      { id: '1-2', text: '精简内容', icon: STREAMLINE_CONTENT_ICON },
-      { id: '1-3', text: '修改标点符号', icon: SYMBOL_ICON },
-      { id: '1-4', text: '翻译', icon: TRANSLATE_ICON },
-    ],
+  editor: [
+    { id: '1-1', text: '丰富内容', icon: RICH_CONTENT_ICON },
+    { id: '1-2', text: '精简内容', icon: STREAMLINE_CONTENT_ICON },
+    { id: '1-3', text: '修改标点符号', icon: SYMBOL_ICON },
+    { id: '1-4', text: '翻译', icon: TRANSLATE_ICON },
+  ],
   // ... (similar fixes for other properties)
-    ]
-};
+  ],
+}

 export const MENU_ID_MAP = {
-    editor: 'subMenuEditorEl',
-    tone: 'subMenuToneEl',
-    adjust: 'subMenuAdjustEl',
-};
+  editor: 'subMenuEditorEl',
+  tone: 'subMenuToneEl',
+  adjust: 'subMenuAdjustEl',
+}
+

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 ESLint

[error] 1-2: Too many blank lines at the beginning of file. Max of 0 allowed.

(style/no-multiple-empty-lines)


[error] 3-3: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 4-4: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 5-5: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 6-6: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 7-7: Expected indentation of 0 spaces but found 2.

(style/indent)


[error] 9-9: Extra semicolon.

(style/semi)


[error] 10-10: Extra semicolon.

(style/semi)


[error] 11-11: Extra semicolon.

(style/semi)


[error] 12-12: Extra semicolon.

(style/semi)


[error] 13-13: Extra semicolon.

(style/semi)


[error] 14-14: Extra semicolon.

(style/semi)


[error] 15-15: Extra semicolon.

(style/semi)


[error] 16-16: Extra semicolon.

(style/semi)


[error] 17-17: Extra semicolon.

(style/semi)


[error] 18-18: Extra semicolon.

(style/semi)


[error] 21-21: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 22-22: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 23-23: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 24-24: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 25-25: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 26-26: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 27-27: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 28-28: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 29-29: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 30-30: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 31-31: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 32-32: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 33-33: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 34-34: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 35-35: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 36-36: Expected indentation of 4 spaces but found 6.

(style/indent)


[error] 37-37: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 37-38: Missing trailing comma.

(style/comma-dangle)


[error] 37-38: Missing trailing comma.

(comma-dangle)


[error] 38-38: Extra semicolon.

(style/semi)


[error] 41-41: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 42-42: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 43-43: Expected indentation of 2 spaces but found 4.

(style/indent)


[error] 44-44: Extra semicolon.

(style/semi)


[error] 44-44: Newline required at end of file but not found.

(style/eol-last)


[error] 44-44: Newline required at end of file but not found.

(eol-last)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/modules/ai/constants.ts from lines 1 to 44, fix
multiple style violations by removing extra blank lines, correcting indentation
to be consistent, ensuring semicolons are used properly at the end of
statements, and adding missing trailing commas in object and array literals.
This will improve code readability and maintain consistent style throughout the
file.

Comment on lines +9 to +18
export const INPUT_PLACEHOLDER = '请输入问题或"/"获取提示词';
export const SELECT_PLACEHOLDER = '向我提问/选择操作';
export const STOP_ANSWER = '停止回答';
export const REPLACE_SELECT = '替换选中内容';
export const INSERT_TEXT = '插入内容';
export const INSERT_SUB_CONTENT_TEXT = '插入内容下方';
export const REGENERATE = '重新生成';
export const CLOSE = '关闭';
export const THINK_TEXT = '正在为您分析并总结答案';
export const RESULT_HEADER_TEXT = '根据您的诉求,已为您解答,具体如下:';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract all UI text for internationalization

All UI text is hardcoded in Chinese, limiting the module to Chinese-speaking users.

Consider implementing a localization system:

  1. Create a locale file structure:
// locales/zh-CN.ts
export default {
  ai: {
    inputPlaceholder: '请输入问题或"/"获取提示词',
    selectPlaceholder: '向我提问/选择操作',
    // ... other translations
  }
}

// locales/en-US.ts  
export default {
  ai: {
    inputPlaceholder: 'Enter a question or "/" for prompts',
    selectPlaceholder: 'Ask me/Select operation',
    // ... other translations
  }
}
  1. Use a localization function:
export const INPUT_PLACEHOLDER = t('ai.inputPlaceholder')

Also applies to: 21-37

🧰 Tools
🪛 ESLint

[error] 9-9: Extra semicolon.

(style/semi)


[error] 10-10: Extra semicolon.

(style/semi)


[error] 11-11: Extra semicolon.

(style/semi)


[error] 12-12: Extra semicolon.

(style/semi)


[error] 13-13: Extra semicolon.

(style/semi)


[error] 14-14: Extra semicolon.

(style/semi)


[error] 15-15: Extra semicolon.

(style/semi)


[error] 16-16: Extra semicolon.

(style/semi)


[error] 17-17: Extra semicolon.

(style/semi)


[error] 18-18: Extra semicolon.

(style/semi)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/modules/ai/constants.ts lines 9 to 18 and also
lines 21 to 37, all UI text strings are hardcoded in Chinese, which limits
localization support. Refactor by extracting these strings into separate locale
files (e.g., locales/zh-CN.ts and locales/en-US.ts) with corresponding
translations. Then replace the hardcoded constants with calls to a localization
function like t('ai.inputPlaceholder') to dynamically load the appropriate
language text.

Comment on lines +137 to 144
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
this.closeAIPanel()
this.quill.container.removeEventListener('keydown', handleKeyDown)
}
}
this.quill.container.addEventListener('keydown', handleKeyDown)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent memory leaks by cleaning up event listeners

Event listeners are added throughout the code without a cleanup mechanism, which will cause memory leaks when AI instances are destroyed.

Add a destroy method and track listeners:

export class AI {
  private eventListeners: Array<{ element: Element, event: string, handler: Function }> = []

  private addEventListener(element: Element, event: string, handler: Function) {
    element.addEventListener(event, handler)
    this.eventListeners.push({ element, event, handler })
  }

  destroy() {
    // Clean up all event listeners
    this.eventListeners.forEach(({ element, event, handler }) => {
      element.removeEventListener(event, handler)
    })
    this.eventListeners = []

    // Clean up DOM elements
    this.alertEl?.remove()
    this.selectionBubbleEl?.remove()
    this.dialogContainerEl?.remove()
    
    // Clear timers
    if (this.alertTimer) clearTimeout(this.alertTimer)
    if (this._debounceTimer) clearTimeout(this._debounceTimer)
  }
}

Also applies to: 416-417, 453-487

🤖 Prompt for AI Agents
In packages/fluent-editor/src/modules/ai/index.ts around lines 137 to 144, event
listeners are added without proper cleanup, risking memory leaks. Implement a
destroy method in the AI class that removes all registered event listeners,
clears timers, and removes DOM elements. Refactor event listener additions to
use a helper method that tracks each listener in an array for later removal.
Apply similar cleanup logic to the event listeners added around lines 416-417
and 453-487.

Comment on lines +759 to +773
set charCount(value: number) {
// 清除之前的定时器
if (this._debounceTimer) {
clearTimeout(this._debounceTimer)
}

this._debounceTimer = setTimeout(() => {
this._charCount = value
if (this.resultPopupFooterTextEl) {
this.resultPopupFooterTextEl.innerText = `${this._charCount}/${this.textNumber}`
}
clearTimeout(this._debounceTimer)
this._debounceTimer = null
}, 210)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add getters for all setter methods

ESLint correctly identifies that all setter methods lack corresponding getters, which violates the accessor-pairs rule and can cause confusion.

Add getters for all properties:

+  get charCount(): number {
+    return this._charCount
+  }
+
   set charCount(value: number) {
     // existing implementation
   }

+  get inputPlaceholder(): string {
+    return this._inputPlaceholder
+  }
+
   set inputPlaceholder(value: string) {
     // existing implementation
   }

+  get showOperationMenu(): boolean {
+    return this._showOperationMenu
+  }
+
   set showOperationMenu(value: boolean) {
     // existing implementation
   }

// Add similar getters for isSelectRangeMode, isThinking, and showResultPopupEl

Also applies to: 775-780, 782-787, 789-794, 796-799, 801-806

🧰 Tools
🪛 ESLint

[error] 759-759: Getter is not present for class setter 'charCount'.

(accessor-pairs)


[error] 768-768: Prefer .textContent over .innerText.

(unicorn/prefer-dom-node-text-content)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/modules/ai/index.ts around lines 759 to 773 and
also in lines 775-780, 782-787, 789-794, 796-799, and 801-806, there are setter
methods without corresponding getter methods, violating the accessor-pairs
ESLint rule. To fix this, add matching getter methods for each setter property
to provide consistent accessors and resolve the linting issue.

Comment on lines +318 to +361
export const AI_ICON = `<div class="ql-ai-icon-box">
<svg viewBox="0 0 24 24.0023" class="ql-ai-trigger-icon ql-ai-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24.0022736" fill="none" customFrame="#000000">
<defs>
<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
<stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
<stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
<stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
<stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
<stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<path id="矢量 54" d="M12.9196 5.92509L6.52253 12.3221C6.30963 12.5349 6.14215 12.7787 6.01959 13.0536C5.89703 13.3284 5.8277 13.6161 5.81207 13.9166L5.71637 15.7208C5.63971 17.1667 6.83308 18.3601 8.27938 18.2835L10.0831 18.188C10.3839 18.1721 10.6715 18.1029 10.9464 17.9804C11.2213 17.8579 11.465 17.6903 11.6779 17.4775L18.9079 10.2475C19.3942 10.9692 19.7898 11.7495 20.0944 12.5884C20.2961 13.1437 20.448 13.7009 20.5495 14.2597C20.6428 14.7731 20.6897 15.2605 20.6897 15.7225C20.6897 16.4805 20.4992 17.1292 20.1179 17.6686C19.7619 18.1717 19.2678 18.5486 18.6359 18.7997C17.9894 19.0561 17.2853 19.1496 16.5231 19.0801C15.7233 19.0073 14.9669 18.763 14.2545 18.3471C14.1144 18.2653 13.9557 18.2223 13.7941 18.2223C13.2819 18.2223 12.8663 18.6465 12.8663 19.1698C12.8663 19.2533 12.8771 19.3354 12.8981 19.416C12.9196 19.4967 12.9508 19.5731 12.9918 19.6453C13.0328 19.7176 13.0822 19.7831 13.1403 19.842C13.1793 19.8813 13.2208 19.9168 13.2653 19.9483L13.3336 19.9924C13.8068 20.2686 14.3029 20.4897 14.8229 20.6555C15.3239 20.8158 15.8356 20.9198 16.3586 20.9676C16.8722 21.0144 17.3776 21.0043 17.8747 20.9373C18.3771 20.8694 18.8552 20.7456 19.3078 20.5658C19.7761 20.3802 20.2024 20.1407 20.5871 19.8474C20.9904 19.5403 21.3352 19.1839 21.6223 18.7779C21.9216 18.3542 22.1496 17.8888 22.3054 17.3818C22.4656 16.8605 22.5456 16.3074 22.5456 15.7225C22.5456 15.1442 22.4885 14.5412 22.3743 13.9136C22.2532 13.2479 22.073 12.5866 21.8347 11.9295C21.5764 11.218 21.2575 10.5358 20.8786 9.88306C20.6838 9.54703 20.4743 9.22121 20.2502 8.90559L23.2864 5.86926C24.238 4.91748 24.238 3.37431 23.2864 2.42253L21.5779 0.713837C20.6257 -0.237946 19.0827 -0.237946 18.1306 0.713837L14.4083 4.43634C12.5861 3.74113 10.5411 3.39346 8.27499 3.39346C7.76229 3.39346 7.34724 3.81766 7.34724 4.34097C7.34724 4.86429 7.76229 5.28848 8.27499 5.28848C9.97178 5.28865 11.5196 5.50081 12.9196 5.92509ZM7.91903 14.0282C7.92244 13.9442 7.95418 13.8728 8.01473 13.8142L17.3937 4.43512L19.6228 6.54848L19.5256 6.64574L10.1856 15.9854C10.1271 16.0456 10.0558 16.0774 9.97178 16.0808L8.16756 16.1763C8.07039 16.1815 7.98739 16.1496 7.91903 16.0809C7.85018 16.0122 7.81844 15.9294 7.82381 15.8324L7.91903 14.0282ZM21.7942 4.37717L20.8239 5.34731L18.653 3.1759L19.6228 2.20593C19.6867 2.14209 19.7639 2.11012 19.8542 2.11012C19.8991 2.10941 19.9406 2.1169 19.9792 2.1326L20.0857 2.20593L21.7942 3.91463C21.8581 3.97856 21.8899 4.05559 21.8899 4.14589C21.8913 4.2368 21.8596 4.31389 21.7942 4.37717ZM0.381352 6.34212C-0.126954 6.2448 -0.126954 5.50148 0.381352 5.40408L0.451665 5.39062C0.521978 5.37715 0.591315 5.36131 0.660651 5.34309C0.744636 5.32089 0.827645 5.29515 0.910165 5.26588C1.06007 5.21257 1.20509 5.14813 1.34523 5.07259C1.48537 4.99702 1.61916 4.91119 1.74709 4.81508C1.87453 4.71898 1.99465 4.61366 2.10647 4.49916C2.21877 4.38464 2.3218 4.26222 2.41604 4.1319C2.4468 4.08905 2.47659 4.0455 2.50588 4.00127L2.54495 3.93964L2.57473 3.89056C2.60745 3.83527 2.6387 3.77893 2.668 3.72156C2.74222 3.57832 2.8052 3.43025 2.85745 3.27734C2.9097 3.12442 2.95023 2.96838 2.97952 2.80922L2.98733 2.76753C3.07913 2.26801 3.78226 2.27577 3.86381 2.7771C3.88969 2.93764 3.92729 3.09518 3.97709 3.24979C4.0269 3.40439 4.08793 3.5542 4.1602 3.69925C4.23198 3.84428 4.31499 3.98286 4.40776 4.11496C4.50102 4.24706 4.60307 4.37114 4.71489 4.4872C4.82671 4.60326 4.94634 4.70993 5.07378 4.80724C5.20171 4.90453 5.33599 4.99132 5.47662 5.06758C5.61724 5.14384 5.76324 5.20869 5.91363 5.26215C6.06403 5.31558 6.21784 5.35699 6.37458 5.38635L6.47516 5.4053C6.98396 5.50072 6.98396 6.24556 6.47516 6.34097L6.37458 6.35992C6.21784 6.3893 6.06403 6.43069 5.91363 6.48413C5.76324 6.53758 5.61724 6.60243 5.47662 6.6787C5.33599 6.75494 5.20171 6.84174 5.07378 6.93903C4.94634 7.03632 4.82671 7.14301 4.71489 7.25905C4.60307 7.37511 4.50102 7.49918 4.40776 7.63127C4.37749 7.67439 4.34819 7.71822 4.32036 7.76273C4.26225 7.85454 4.20903 7.94928 4.1602 8.04697C4.08793 8.19202 4.0269 8.34183 3.97709 8.49641C3.92729 8.651 3.88969 8.80856 3.86381 8.96909C3.78226 9.4706 3.07913 9.47827 2.98733 8.97874L2.97952 8.93706C2.95023 8.77789 2.9097 8.62186 2.85745 8.46895C2.8052 8.31604 2.74222 8.16797 2.668 8.02473C2.62893 7.94897 2.58694 7.87502 2.54251 7.80286C2.50247 7.7386 2.46047 7.67578 2.41604 7.6144C2.3218 7.48405 2.21877 7.36163 2.10647 7.24713C1.99465 7.13263 1.87453 7.02731 1.74709 6.9312C1.61916 6.8351 1.48537 6.74925 1.34523 6.67371C1.20509 6.59814 1.06007 6.53371 0.910165 6.48041C0.760262 6.42711 0.607428 6.38551 0.451665 6.35567L0.381352 6.34212ZM2.26418 14.218C2.62259 15.5594 3.22367 16.7893 4.06694 17.9076C4.9063 19.0207 5.92242 19.9394 7.11531 20.6639C8.34188 21.409 9.66807 21.8938 11.0953 22.1182C11.1495 22.1268 11.2028 22.1401 11.2545 22.1583C11.3068 22.1765 11.3566 22.1992 11.4049 22.2265C11.4528 22.2537 11.4982 22.2851 11.5406 22.3206C11.5836 22.3561 11.6227 22.3951 11.6583 22.4377C11.6945 22.4803 11.7262 22.5258 11.754 22.5742C11.7819 22.6226 11.8053 22.6731 11.8243 22.7258C11.8434 22.7784 11.858 22.8324 11.8678 22.8876C11.8771 22.9429 11.882 22.9986 11.882 23.0547C11.882 23.5781 11.4669 24.0023 10.9542 24.0023C10.9068 24.0023 10.86 23.9986 10.8107 23.9909C9.14804 23.7294 7.59969 23.1631 6.16608 22.2925C4.77056 21.4447 3.5806 20.3685 2.59671 19.0638C1.60402 17.7478 0.896493 16.2987 0.474126 14.7167C0.03418 13.0693 -0.0654303 11.39 0.176271 9.67772L0.192873 9.58968L0.214358 9.51338L0.254885 9.41016L0.280276 9.35857C0.306644 9.30896 0.337406 9.26216 0.372074 9.21817C0.406742 9.17416 0.445317 9.13367 0.486821 9.09666C0.528814 9.05966 0.573736 9.02673 0.6211 8.99791L0.734871 8.93944L0.770516 8.92503C0.822274 8.90529 0.875497 8.89041 0.929697 8.88037C0.984385 8.87035 1.03907 8.86533 1.09474 8.86533C1.60695 8.86533 2.02248 9.28952 2.02248 9.81284C2.02248 9.85803 2.01955 9.90323 2.0132 9.94795C1.80812 11.4 1.89211 12.8234 2.26418 14.218Z" fill="url(#paint_linear_1)" fill-rule="evenodd" />
</svg>
`
<div class="ql-ai-icon-bubble">
<div class="ql-ai-icon-bubble-box">
<div class="ql-ai-icon-bubble-text">让我帮你吧?我什么都能做~</div>
<svg class="ql-ai-icon bubble-arrow-icon" viewBox="0 0 28.4766 10.2476" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28.4765625" height="10.2475586" fill="none" customFrame="#000000">
<defs>
<linearGradient id="bubble-arrow" x1="-0.624592781" x2="25.3206978" y1="9.2897892" y2="-0.221138" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(87,190,255)" offset="0" stop-opacity="1" />
<stop stop-color="rgb(149,215,255)" offset="0.29017064" stop-opacity="1" />
<stop stop-color="rgb(253,171,255)" offset="0.666350782" stop-opacity="1" />
<stop stop-color="rgb(255,219,126)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<path id="矩形备份 46" d="M25.6167 0C16.6815 -5.46574e-13 4.76257 6.56187 1.46998 8.47962C1.14293 8.67011 0.736641 8.37674 0.820143 8.00759L1.99241 2.82518C2.2969 1.47906 1.37022 0.165056 0 0C0 0 36.0811 6.40129e-13 25.6167 0Z" fill="rgb(255,255,255)" fill-rule="evenodd" transform="matrix(-1,0,0,-1,28.3745,9.39355)" />
<path id="矩形备份 46" d="M1.51932 9.36628Q1.71643 9.32424 1.89974 9.21748Q3.71641 8.15937 5.76607 7.10493Q8.82626 5.53064 11.756 4.30875Q15.5037 2.74576 18.7568 1.88045Q22.616 0.85389 25.6167 0.85389L27.5207 0.85389Q27.8744 0.85389 28.1245 0.603792Q28.3746 0.353693 28.3746 0Q28.3746 -0.353693 28.1245 -0.603792Q27.8744 -0.85389 27.5207 -0.85389L0 -0.85389L-0.102121 0.847761Q0.0881771 0.870685 0.260977 0.938314Q0.378491 0.984306 0.487912 1.05097Q0.6038 1.12158 0.703269 1.21055Q0.827683 1.32182 0.92641 1.46181Q1.02513 1.6018 1.08819 1.75634Q1.1386 1.87991 1.16621 2.01278Q1.19228 2.13824 1.19615 2.26438Q1.20185 2.44985 1.15956 2.63679L-0.0127056 7.8192Q-0.0601339 8.02887 -0.0397504 8.23173Q-0.0215362 8.413 0.0508242 8.58883Q0.115644 8.74634 0.21512 8.87757Q0.329616 9.02863 0.490025 9.14488Q0.647674 9.25913 0.823735 9.32093Q0.980583 9.37599 1.15204 9.38942Q1.34131 9.40425 1.51932 9.36628ZM19.2234 0L0 0C0.632833 0.0762305 1.17106 0.397535 1.53708 0.85389C1.96358 1.38565 2.15627 2.10076 1.99241 2.82518L0.820143 8.00759C0.736641 8.37674 1.14293 8.67011 1.46998 8.47962C4.02868 6.98931 11.7968 2.69442 19.3259 0.85389C21.4853 0.325992 23.6251 0 25.6167 0L19.2234 0Z" fill="url(#bubble-arrow)" fill-rule="evenodd" transform="matrix(-1,0,0,-1,28.3745,9.39355)" />
</svg>
<svg class="ql-ai-icon bubble-rect-icon" viewBox="0 0 216 44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216" height="44" fill="none" customFrame="#000000">
<defs>
<linearGradient id="bubble-rect" x1="-4.8235321" x2="195.545532" y1="45.4169006" y2="-1.08105469" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(87,190,255)" offset="0" stop-opacity="1" />
<stop stop-color="rgb(149,215,255)" offset="0.29017064" stop-opacity="1" />
<stop stop-color="rgb(253,171,255)" offset="0.666350782" stop-opacity="1" />
<stop stop-color="rgb(255,219,126)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<rect id="矩形 6" width="216" height="44" x="0" y="0" rx="12" fill="rgb(255,255,255)" />
<rect id="矩形 6" width="215" height="43" x="0.5" y="0.5" rx="12" stroke="url(#bubble-rect)" stroke-width="1" />
</svg>
</div>
</div>
</div>`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider moving complex UI structure to a component file

The AI_ICON has been transformed from a simple SVG icon into a complex UI component with interactive elements. This violates the single responsibility principle for an icons configuration file.

Consider:

  1. Keep only the SVG icon definition in this file
  2. Create a separate AI component (e.g., AIIconButton.ts) that imports the icon and adds the bubble UI
  3. This would improve maintainability and allow for proper component testing

Example structure:

// icons.config.ts
export const AI_ICON = `<svg>...</svg>` // Just the icon

// components/AIIconButton.ts
import { AI_ICON } from '../ui/icons.config'
export function createAIIconButton() {
  // Build the complex UI structure here
}
🧰 Tools
🪛 ESLint

[error] 320-320: Unexpected tab character.

(style/no-tabs)


[error] 321-321: Unexpected tab character.

(style/no-tabs)


[error] 322-322: Unexpected tab character.

(style/no-tabs)


[error] 323-323: Unexpected tab character.

(style/no-tabs)


[error] 324-324: Unexpected tab character.

(style/no-tabs)


[error] 325-325: Unexpected tab character.

(style/no-tabs)


[error] 326-326: Unexpected tab character.

(style/no-tabs)


[error] 327-327: Unexpected tab character.

(style/no-tabs)


[error] 328-328: Unexpected tab character.

(style/no-tabs)


[error] 329-329: Unexpected tab character.

(style/no-tabs)


[error] 330-330: Unexpected tab character.

(style/no-tabs)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/ui/icons.config.ts between lines 318 and 361, the
AI_ICON constant includes a complex UI structure with interactive elements,
which is inappropriate for an icons configuration file. To fix this, extract
only the raw SVG icon markup into AI_ICON in this file, removing the bubble and
other UI elements. Then create a new component file (e.g., AIIconButton.ts)
where you import AI_ICON and build the full interactive UI structure including
the bubble. This separation improves maintainability and aligns with single
responsibility principles.

Comment on lines +320 to +330
<defs>
<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
<stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
<stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
<stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
<stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
<stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<path id="矢量 54" d="M12.9196 5.92509L6.52253 12.3221C6.30963 12.5349 6.14215 12.7787 6.01959 13.0536C5.89703 13.3284 5.8277 13.6161 5.81207 13.9166L5.71637 15.7208C5.63971 17.1667 6.83308 18.3601 8.27938 18.2835L10.0831 18.188C10.3839 18.1721 10.6715 18.1029 10.9464 17.9804C11.2213 17.8579 11.465 17.6903 11.6779 17.4775L18.9079 10.2475C19.3942 10.9692 19.7898 11.7495 20.0944 12.5884C20.2961 13.1437 20.448 13.7009 20.5495 14.2597C20.6428 14.7731 20.6897 15.2605 20.6897 15.7225C20.6897 16.4805 20.4992 17.1292 20.1179 17.6686C19.7619 18.1717 19.2678 18.5486 18.6359 18.7997C17.9894 19.0561 17.2853 19.1496 16.5231 19.0801C15.7233 19.0073 14.9669 18.763 14.2545 18.3471C14.1144 18.2653 13.9557 18.2223 13.7941 18.2223C13.2819 18.2223 12.8663 18.6465 12.8663 19.1698C12.8663 19.2533 12.8771 19.3354 12.8981 19.416C12.9196 19.4967 12.9508 19.5731 12.9918 19.6453C13.0328 19.7176 13.0822 19.7831 13.1403 19.842C13.1793 19.8813 13.2208 19.9168 13.2653 19.9483L13.3336 19.9924C13.8068 20.2686 14.3029 20.4897 14.8229 20.6555C15.3239 20.8158 15.8356 20.9198 16.3586 20.9676C16.8722 21.0144 17.3776 21.0043 17.8747 20.9373C18.3771 20.8694 18.8552 20.7456 19.3078 20.5658C19.7761 20.3802 20.2024 20.1407 20.5871 19.8474C20.9904 19.5403 21.3352 19.1839 21.6223 18.7779C21.9216 18.3542 22.1496 17.8888 22.3054 17.3818C22.4656 16.8605 22.5456 16.3074 22.5456 15.7225C22.5456 15.1442 22.4885 14.5412 22.3743 13.9136C22.2532 13.2479 22.073 12.5866 21.8347 11.9295C21.5764 11.218 21.2575 10.5358 20.8786 9.88306C20.6838 9.54703 20.4743 9.22121 20.2502 8.90559L23.2864 5.86926C24.238 4.91748 24.238 3.37431 23.2864 2.42253L21.5779 0.713837C20.6257 -0.237946 19.0827 -0.237946 18.1306 0.713837L14.4083 4.43634C12.5861 3.74113 10.5411 3.39346 8.27499 3.39346C7.76229 3.39346 7.34724 3.81766 7.34724 4.34097C7.34724 4.86429 7.76229 5.28848 8.27499 5.28848C9.97178 5.28865 11.5196 5.50081 12.9196 5.92509ZM7.91903 14.0282C7.92244 13.9442 7.95418 13.8728 8.01473 13.8142L17.3937 4.43512L19.6228 6.54848L19.5256 6.64574L10.1856 15.9854C10.1271 16.0456 10.0558 16.0774 9.97178 16.0808L8.16756 16.1763C8.07039 16.1815 7.98739 16.1496 7.91903 16.0809C7.85018 16.0122 7.81844 15.9294 7.82381 15.8324L7.91903 14.0282ZM21.7942 4.37717L20.8239 5.34731L18.653 3.1759L19.6228 2.20593C19.6867 2.14209 19.7639 2.11012 19.8542 2.11012C19.8991 2.10941 19.9406 2.1169 19.9792 2.1326L20.0857 2.20593L21.7942 3.91463C21.8581 3.97856 21.8899 4.05559 21.8899 4.14589C21.8913 4.2368 21.8596 4.31389 21.7942 4.37717ZM0.381352 6.34212C-0.126954 6.2448 -0.126954 5.50148 0.381352 5.40408L0.451665 5.39062C0.521978 5.37715 0.591315 5.36131 0.660651 5.34309C0.744636 5.32089 0.827645 5.29515 0.910165 5.26588C1.06007 5.21257 1.20509 5.14813 1.34523 5.07259C1.48537 4.99702 1.61916 4.91119 1.74709 4.81508C1.87453 4.71898 1.99465 4.61366 2.10647 4.49916C2.21877 4.38464 2.3218 4.26222 2.41604 4.1319C2.4468 4.08905 2.47659 4.0455 2.50588 4.00127L2.54495 3.93964L2.57473 3.89056C2.60745 3.83527 2.6387 3.77893 2.668 3.72156C2.74222 3.57832 2.8052 3.43025 2.85745 3.27734C2.9097 3.12442 2.95023 2.96838 2.97952 2.80922L2.98733 2.76753C3.07913 2.26801 3.78226 2.27577 3.86381 2.7771C3.88969 2.93764 3.92729 3.09518 3.97709 3.24979C4.0269 3.40439 4.08793 3.5542 4.1602 3.69925C4.23198 3.84428 4.31499 3.98286 4.40776 4.11496C4.50102 4.24706 4.60307 4.37114 4.71489 4.4872C4.82671 4.60326 4.94634 4.70993 5.07378 4.80724C5.20171 4.90453 5.33599 4.99132 5.47662 5.06758C5.61724 5.14384 5.76324 5.20869 5.91363 5.26215C6.06403 5.31558 6.21784 5.35699 6.37458 5.38635L6.47516 5.4053C6.98396 5.50072 6.98396 6.24556 6.47516 6.34097L6.37458 6.35992C6.21784 6.3893 6.06403 6.43069 5.91363 6.48413C5.76324 6.53758 5.61724 6.60243 5.47662 6.6787C5.33599 6.75494 5.20171 6.84174 5.07378 6.93903C4.94634 7.03632 4.82671 7.14301 4.71489 7.25905C4.60307 7.37511 4.50102 7.49918 4.40776 7.63127C4.37749 7.67439 4.34819 7.71822 4.32036 7.76273C4.26225 7.85454 4.20903 7.94928 4.1602 8.04697C4.08793 8.19202 4.0269 8.34183 3.97709 8.49641C3.92729 8.651 3.88969 8.80856 3.86381 8.96909C3.78226 9.4706 3.07913 9.47827 2.98733 8.97874L2.97952 8.93706C2.95023 8.77789 2.9097 8.62186 2.85745 8.46895C2.8052 8.31604 2.74222 8.16797 2.668 8.02473C2.62893 7.94897 2.58694 7.87502 2.54251 7.80286C2.50247 7.7386 2.46047 7.67578 2.41604 7.6144C2.3218 7.48405 2.21877 7.36163 2.10647 7.24713C1.99465 7.13263 1.87453 7.02731 1.74709 6.9312C1.61916 6.8351 1.48537 6.74925 1.34523 6.67371C1.20509 6.59814 1.06007 6.53371 0.910165 6.48041C0.760262 6.42711 0.607428 6.38551 0.451665 6.35567L0.381352 6.34212ZM2.26418 14.218C2.62259 15.5594 3.22367 16.7893 4.06694 17.9076C4.9063 19.0207 5.92242 19.9394 7.11531 20.6639C8.34188 21.409 9.66807 21.8938 11.0953 22.1182C11.1495 22.1268 11.2028 22.1401 11.2545 22.1583C11.3068 22.1765 11.3566 22.1992 11.4049 22.2265C11.4528 22.2537 11.4982 22.2851 11.5406 22.3206C11.5836 22.3561 11.6227 22.3951 11.6583 22.4377C11.6945 22.4803 11.7262 22.5258 11.754 22.5742C11.7819 22.6226 11.8053 22.6731 11.8243 22.7258C11.8434 22.7784 11.858 22.8324 11.8678 22.8876C11.8771 22.9429 11.882 22.9986 11.882 23.0547C11.882 23.5781 11.4669 24.0023 10.9542 24.0023C10.9068 24.0023 10.86 23.9986 10.8107 23.9909C9.14804 23.7294 7.59969 23.1631 6.16608 22.2925C4.77056 21.4447 3.5806 20.3685 2.59671 19.0638C1.60402 17.7478 0.896493 16.2987 0.474126 14.7167C0.03418 13.0693 -0.0654303 11.39 0.176271 9.67772L0.192873 9.58968L0.214358 9.51338L0.254885 9.41016L0.280276 9.35857C0.306644 9.30896 0.337406 9.26216 0.372074 9.21817C0.406742 9.17416 0.445317 9.13367 0.486821 9.09666C0.528814 9.05966 0.573736 9.02673 0.6211 8.99791L0.734871 8.93944L0.770516 8.92503C0.822274 8.90529 0.875497 8.89041 0.929697 8.88037C0.984385 8.87035 1.03907 8.86533 1.09474 8.86533C1.60695 8.86533 2.02248 9.28952 2.02248 9.81284C2.02248 9.85803 2.01955 9.90323 2.0132 9.94795C1.80812 11.4 1.89211 12.8234 2.26418 14.218Z" fill="url(#paint_linear_1)" fill-rule="evenodd" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace tab characters with spaces

The code uses tab characters which violate the project's style guide.

Apply this diff to fix the indentation:

-	<defs>
-		<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
-			<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
-			<stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
-			<stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
-			<stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
-			<stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
-			<stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
-		</linearGradient>
-	</defs>
+  <defs>
+    <linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
+      <stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
+      <stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
+      <stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
+      <stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
+      <stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
+      <stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
+    </linearGradient>
+  </defs>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<defs>
<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
<stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
<stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
<stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
<stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
<stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<path id="矢量 54" d="M12.9196 5.92509L6.52253 12.3221C6.30963 12.5349 6.14215 12.7787 6.01959 13.0536C5.89703 13.3284 5.8277 13.6161 5.81207 13.9166L5.71637 15.7208C5.63971 17.1667 6.83308 18.3601 8.27938 18.2835L10.0831 18.188C10.3839 18.1721 10.6715 18.1029 10.9464 17.9804C11.2213 17.8579 11.465 17.6903 11.6779 17.4775L18.9079 10.2475C19.3942 10.9692 19.7898 11.7495 20.0944 12.5884C20.2961 13.1437 20.448 13.7009 20.5495 14.2597C20.6428 14.7731 20.6897 15.2605 20.6897 15.7225C20.6897 16.4805 20.4992 17.1292 20.1179 17.6686C19.7619 18.1717 19.2678 18.5486 18.6359 18.7997C17.9894 19.0561 17.2853 19.1496 16.5231 19.0801C15.7233 19.0073 14.9669 18.763 14.2545 18.3471C14.1144 18.2653 13.9557 18.2223 13.7941 18.2223C13.2819 18.2223 12.8663 18.6465 12.8663 19.1698C12.8663 19.2533 12.8771 19.3354 12.8981 19.416C12.9196 19.4967 12.9508 19.5731 12.9918 19.6453C13.0328 19.7176 13.0822 19.7831 13.1403 19.842C13.1793 19.8813 13.2208 19.9168 13.2653 19.9483L13.3336 19.9924C13.8068 20.2686 14.3029 20.4897 14.8229 20.6555C15.3239 20.8158 15.8356 20.9198 16.3586 20.9676C16.8722 21.0144 17.3776 21.0043 17.8747 20.9373C18.3771 20.8694 18.8552 20.7456 19.3078 20.5658C19.7761 20.3802 20.2024 20.1407 20.5871 19.8474C20.9904 19.5403 21.3352 19.1839 21.6223 18.7779C21.9216 18.3542 22.1496 17.8888 22.3054 17.3818C22.4656 16.8605 22.5456 16.3074 22.5456 15.7225C22.5456 15.1442 22.4885 14.5412 22.3743 13.9136C22.2532 13.2479 22.073 12.5866 21.8347 11.9295C21.5764 11.218 21.2575 10.5358 20.8786 9.88306C20.6838 9.54703 20.4743 9.22121 20.2502 8.90559L23.2864 5.86926C24.238 4.91748 24.238 3.37431 23.2864 2.42253L21.5779 0.713837C20.6257 -0.237946 19.0827 -0.237946 18.1306 0.713837L14.4083 4.43634C12.5861 3.74113 10.5411 3.39346 8.27499 3.39346C7.76229 3.39346 7.34724 3.81766 7.34724 4.34097C7.34724 4.86429 7.76229 5.28848 8.27499 5.28848C9.97178 5.28865 11.5196 5.50081 12.9196 5.92509ZM7.91903 14.0282C7.92244 13.9442 7.95418 13.8728 8.01473 13.8142L17.3937 4.43512L19.6228 6.54848L19.5256 6.64574L10.1856 15.9854C10.1271 16.0456 10.0558 16.0774 9.97178 16.0808L8.16756 16.1763C8.07039 16.1815 7.98739 16.1496 7.91903 16.0809C7.85018 16.0122 7.81844 15.9294 7.82381 15.8324L7.91903 14.0282ZM21.7942 4.37717L20.8239 5.34731L18.653 3.1759L19.6228 2.20593C19.6867 2.14209 19.7639 2.11012 19.8542 2.11012C19.8991 2.10941 19.9406 2.1169 19.9792 2.1326L20.0857 2.20593L21.7942 3.91463C21.8581 3.97856 21.8899 4.05559 21.8899 4.14589C21.8913 4.2368 21.8596 4.31389 21.7942 4.37717ZM0.381352 6.34212C-0.126954 6.2448 -0.126954 5.50148 0.381352 5.40408L0.451665 5.39062C0.521978 5.37715 0.591315 5.36131 0.660651 5.34309C0.744636 5.32089 0.827645 5.29515 0.910165 5.26588C1.06007 5.21257 1.20509 5.14813 1.34523 5.07259C1.48537 4.99702 1.61916 4.91119 1.74709 4.81508C1.87453 4.71898 1.99465 4.61366 2.10647 4.49916C2.21877 4.38464 2.3218 4.26222 2.41604 4.1319C2.4468 4.08905 2.47659 4.0455 2.50588 4.00127L2.54495 3.93964L2.57473 3.89056C2.60745 3.83527 2.6387 3.77893 2.668 3.72156C2.74222 3.57832 2.8052 3.43025 2.85745 3.27734C2.9097 3.12442 2.95023 2.96838 2.97952 2.80922L2.98733 2.76753C3.07913 2.26801 3.78226 2.27577 3.86381 2.7771C3.88969 2.93764 3.92729 3.09518 3.97709 3.24979C4.0269 3.40439 4.08793 3.5542 4.1602 3.69925C4.23198 3.84428 4.31499 3.98286 4.40776 4.11496C4.50102 4.24706 4.60307 4.37114 4.71489 4.4872C4.82671 4.60326 4.94634 4.70993 5.07378 4.80724C5.20171 4.90453 5.33599 4.99132 5.47662 5.06758C5.61724 5.14384 5.76324 5.20869 5.91363 5.26215C6.06403 5.31558 6.21784 5.35699 6.37458 5.38635L6.47516 5.4053C6.98396 5.50072 6.98396 6.24556 6.47516 6.34097L6.37458 6.35992C6.21784 6.3893 6.06403 6.43069 5.91363 6.48413C5.76324 6.53758 5.61724 6.60243 5.47662 6.6787C5.33599 6.75494 5.20171 6.84174 5.07378 6.93903C4.94634 7.03632 4.82671 7.14301 4.71489 7.25905C4.60307 7.37511 4.50102 7.49918 4.40776 7.63127C4.37749 7.67439 4.34819 7.71822 4.32036 7.76273C4.26225 7.85454 4.20903 7.94928 4.1602 8.04697C4.08793 8.19202 4.0269 8.34183 3.97709 8.49641C3.92729 8.651 3.88969 8.80856 3.86381 8.96909C3.78226 9.4706 3.07913 9.47827 2.98733 8.97874L2.97952 8.93706C2.95023 8.77789 2.9097 8.62186 2.85745 8.46895C2.8052 8.31604 2.74222 8.16797 2.668 8.02473C2.62893 7.94897 2.58694 7.87502 2.54251 7.80286C2.50247 7.7386 2.46047 7.67578 2.41604 7.6144C2.3218 7.48405 2.21877 7.36163 2.10647 7.24713C1.99465 7.13263 1.87453 7.02731 1.74709 6.9312C1.61916 6.8351 1.48537 6.74925 1.34523 6.67371C1.20509 6.59814 1.06007 6.53371 0.910165 6.48041C0.760262 6.42711 0.607428 6.38551 0.451665 6.35567L0.381352 6.34212ZM2.26418 14.218C2.62259 15.5594 3.22367 16.7893 4.06694 17.9076C4.9063 19.0207 5.92242 19.9394 7.11531 20.6639C8.34188 21.409 9.66807 21.8938 11.0953 22.1182C11.1495 22.1268 11.2028 22.1401 11.2545 22.1583C11.3068 22.1765 11.3566 22.1992 11.4049 22.2265C11.4528 22.2537 11.4982 22.2851 11.5406 22.3206C11.5836 22.3561 11.6227 22.3951 11.6583 22.4377C11.6945 22.4803 11.7262 22.5258 11.754 22.5742C11.7819 22.6226 11.8053 22.6731 11.8243 22.7258C11.8434 22.7784 11.858 22.8324 11.8678 22.8876C11.8771 22.9429 11.882 22.9986 11.882 23.0547C11.882 23.5781 11.4669 24.0023 10.9542 24.0023C10.9068 24.0023 10.86 23.9986 10.8107 23.9909C9.14804 23.7294 7.59969 23.1631 6.16608 22.2925C4.77056 21.4447 3.5806 20.3685 2.59671 19.0638C1.60402 17.7478 0.896493 16.2987 0.474126 14.7167C0.03418 13.0693 -0.0654303 11.39 0.176271 9.67772L0.192873 9.58968L0.214358 9.51338L0.254885 9.41016L0.280276 9.35857C0.306644 9.30896 0.337406 9.26216 0.372074 9.21817C0.406742 9.17416 0.445317 9.13367 0.486821 9.09666C0.528814 9.05966 0.573736 9.02673 0.6211 8.99791L0.734871 8.93944L0.770516 8.92503C0.822274 8.90529 0.875497 8.89041 0.929697 8.88037C0.984385 8.87035 1.03907 8.86533 1.09474 8.86533C1.60695 8.86533 2.02248 9.28952 2.02248 9.81284C2.02248 9.85803 2.01955 9.90323 2.0132 9.94795C1.80812 11.4 1.89211 12.8234 2.26418 14.218Z" fill="url(#paint_linear_1)" fill-rule="evenodd" />
<defs>
<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />
<stop stop-color="rgb(249.9,102.687,1)" offset="0.349490285" stop-opacity="1" />
<stop stop-color="rgb(247,181,1)" offset="0.494946986" stop-opacity="1" />
<stop stop-color="rgb(11,184,178)" offset="0.690560162" stop-opacity="1" />
<stop stop-color="rgb(1,145,255)" offset="0.858591199" stop-opacity="1" />
<stop stop-color="rgb(182,32,224)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
🧰 Tools
🪛 ESLint

[error] 320-320: Unexpected tab character.

(style/no-tabs)


[error] 321-321: Unexpected tab character.

(style/no-tabs)


[error] 322-322: Unexpected tab character.

(style/no-tabs)


[error] 323-323: Unexpected tab character.

(style/no-tabs)


[error] 324-324: Unexpected tab character.

(style/no-tabs)


[error] 325-325: Unexpected tab character.

(style/no-tabs)


[error] 326-326: Unexpected tab character.

(style/no-tabs)


[error] 327-327: Unexpected tab character.

(style/no-tabs)


[error] 328-328: Unexpected tab character.

(style/no-tabs)


[error] 329-329: Unexpected tab character.

(style/no-tabs)


[error] 330-330: Unexpected tab character.

(style/no-tabs)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/ui/icons.config.ts around lines 320 to 330, the
code contains tab characters for indentation which violates the project's style
guide. Replace all tab characters with spaces to conform to the style guide and
ensure consistent formatting.

<svg viewBox="0 0 24 24.0023" class="ql-ai-trigger-icon ql-ai-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24.0022736" fill="none" customFrame="#000000">
<defs>
<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" x1="2.50000095" x2="12.0000048" y1="0" y2="23.9999962" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(250,100,1)" offset="0.263296664" stop-opacity="1" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent duplicate SVG gradient IDs

The gradient IDs (paint_linear_1, bubble-arrow, bubble-rect) will be duplicated if multiple AI icons are rendered on the same page, causing potential rendering issues.

Consider making the IDs unique by:

  1. Using a UUID generator
  2. Adding a timestamp or counter suffix
  3. Using CSS classes with scoped styles instead of gradients

Example approach:

-<linearGradient class="ql-ai-icon-linear" id="paint_linear_1" ...>
+<linearGradient class="ql-ai-icon-linear" id={`paint_linear_${uniqueId}`} ...>

Also applies to: 337-337, 349-349

🧰 Tools
🪛 ESLint

[error] 322-322: Unexpected tab character.

(style/no-tabs)

🤖 Prompt for AI Agents
In packages/fluent-editor/src/ui/icons.config.ts at lines 322, 337, and 349, the
SVG gradient IDs like 'paint_linear_1', 'bubble-arrow', and 'bubble-rect' are
hardcoded and will cause duplicates when multiple AI icons render on the same
page. To fix this, modify the code to generate unique IDs for these gradients
dynamically, for example by appending a UUID, timestamp, or a unique counter
suffix to each ID, and update all references to these IDs accordingly to prevent
conflicts.

`
<div class="ql-ai-icon-bubble">
<div class="ql-ai-icon-bubble-box">
<div class="ql-ai-icon-bubble-text">让我帮你吧?我什么都能做~</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract hardcoded text for localization

The bubble text is hardcoded in Chinese, which limits the component's usability for non-Chinese users.

Consider extracting this text to a localization system or at least to a constants file:

-        <div class="ql-ai-icon-bubble-text">让我帮你吧?我什么都能做~</div>
+        <div class="ql-ai-icon-bubble-text">{AI_BUBBLE_TEXT}</div>

Then define the constant in your localization system or constants file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class="ql-ai-icon-bubble-text">让我帮你吧?我什么都能做~</div>
<div class="ql-ai-icon-bubble-text">{AI_BUBBLE_TEXT}</div>
🤖 Prompt for AI Agents
In packages/fluent-editor/src/ui/icons.config.ts at line 334, the bubble text is
hardcoded in Chinese, limiting localization. Extract this text into a
localization system or a constants file by replacing the hardcoded string with a
reference to a localized constant or key. Define the corresponding text in your
localization files or constants to support multiple languages.

@kagol
kagol merged commit 2441ccf into opentiny:main Jul 31, 2025
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants