-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
530 请问 mention 提及插件没有做集成吗 #533
The head ref may contain hidden characters: "530-\u8BF7\u95EE-mention-\u63D0\u53CA\u63D2\u4EF6\u6CA1\u6709\u505A\u96C6\u6210\u5417"
Conversation
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the WalkthroughThis pull request introduces a new mention plugin for the wangEditor editor. The changes include new documentation, package configuration, build setup, and module implementations covering type definitions, HTML conversion, and editor integration for mention functionality. The plugin intercepts the "@" input to trigger a mention selector modal and renders mention elements appropriately in the editor. Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant E as Editor
participant M as Mention Plugin
U->>E: Types "@"
E->>M: withMention intercepts input
M->>E: Calls showModal() to display mention selector
U->>M: Selects a mention option
M->>E: Inserts mention node into content
E->>M: Renders mention via renderMention
Possibly related issues
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (11)
packages/plugin-mention/src/module/index.ts (1)
1-4
: Enhance module documentation.Consider adding more detailed JSDoc documentation including:
- Purpose and functionality of the mention plugin
- Usage examples
- Configuration options
- Dependencies and requirements
/** * @description mention module entry + * @description Implements mention functionality for the editor, allowing users to tag/mention others + * @example + * ```ts + * import mentionModule from '@wangeditor-next/plugin-mention' + * // Add usage example + * ``` + * @requires @wangeditor-next/editor * @author wangfupeng */packages/plugin-mention/src/module/custom-types.ts (2)
12-12
: Consider using a more specific type forinfo
.Using
any
type reduces type safety. Consider defining a specific interface for theinfo
property to better document the expected structure and improve type checking.- info: any + info: { + id?: string | number + name?: string + [key: string]: unknown + }
13-13
: Translate Chinese comment to English for consistency.Consider translating the Chinese comment "void 元素必须有一个空 text" to English.
- children: EmptyText[] // void 元素必须有一个空 text + children: EmptyText[] // void elements must have an empty textpackages/plugin-mention/src/module/interface.ts (1)
8-13
: Add JSDoc documentation and explicit return types.Consider adding documentation for the methods and making return types explicit for better maintainability.
export interface IExtendConfig { mentionConfig: { + /** + * Called when the mention modal needs to be displayed + * @param editor The editor instance + */ - showModal: (editor: IDomEditor) => void + showModal: (editor: IDomEditor) => void + /** + * Called when the mention modal needs to be hidden + * @param editor The editor instance + */ - hideModal: (editor: IDomEditor) => void + hideModal: (editor: IDomEditor) => void } }packages/plugin-mention/rollup.config.js (1)
10-16
: Consider adding source maps for development builds.Source maps are helpful for debugging. Consider enabling them in development builds.
const esmConf = createRollupConfig({ output: { file: pkg.module, format: 'esm', name, + sourcemap: process.env.NODE_ENV === 'development' }, }) // ... similar change for umdConf
Also applies to: 21-27
packages/plugin-mention/src/module/parse-elem-html.ts (1)
28-34
: Consider using type guard instead of type assertion.Using type assertion with
as MentionElement
might hide type mismatches. Consider using a type guard to ensure type safety.- return { + const mentionElement = { type: 'mention', value, info, children: [{ text: '' }], // void node 必须有一个空白 text - } as MentionElement + } + + function isMentionElement(elem: any): elem is MentionElement { + return ( + elem.type === 'mention' && + typeof elem.value === 'string' && + Array.isArray(elem.children) && + elem.children.length === 1 && + 'text' in elem.children[0] + ) + } + + if (!isMentionElement(mentionElement)) { + throw new Error('Invalid mention element structure') + } + + return mentionElementpackages/plugin-mention/src/module/render-elem.ts (1)
14-14
: Add type validation for mention element.The type casting
as MentionElement
might hide type mismatches. Consider adding runtime type validation.- const { value = '' } = elem as MentionElement + if (elem.type !== 'mention') { + throw new Error('Invalid element type') + } + const mentionElem = elem as MentionElement + const { value = '' } = mentionElempackages/plugin-mention/README.md (2)
9-9
: Provide Alternate Text for the Demo ImageThe demo image at line 9 does not include any alt text. For better accessibility and to satisfy markdown lint rules (MD045), please add descriptive alt text.
-![](./_img/demo.png) +![Demo image showing mention plugin usage](./_img/demo.png)
61-79
: Editor Configuration and Typographical CorrectionThe configuration snippet (lines 66-76) clearly demonstrates how to integrate the mention configuration into the editor setup.
Typographical Issue:
Line 78 contains a duplicated phrase ("创建创建和工具栏"). A simple correction would improve clarity.-// 创建创建和工具栏,会用到 editorConfig 。具体查看 wangEditor 文档 +// 创建编辑器和工具栏,会用到 editorConfig 。具体查看 wangEditor 文档packages/plugin-mention/README-en.md (2)
9-9
: Add Alt Text to Demo Image for AccessibilitySimilar to the Chinese documentation, the demo image here lacks alt text. Please include descriptive alt text to ensure accessibility and compliance with markdown best practices.
-![](./_img/demo.png) +![Demo image demonstrating the mention plugin](./_img/demo.png)🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
9-9: Images should have alternate text (alt text)
null(MD045, no-alt-text)
31-60
: Modal Display and Mention Insertion Example – Minor TypoThe
showModal
function, including its innerinsertMention
implementation, is well-documented and clear. However, note a minor typo in the inline comment: “move curser” should be “move cursor.”- editor.move(1) // move curser + editor.move(1) // move cursor
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
packages/plugin-mention/_img/demo.png
is excluded by!**/*.png
📒 Files selected for processing (15)
.changeset/wise-ducks-grin.md
(1 hunks)packages/plugin-mention/README-en.md
(1 hunks)packages/plugin-mention/README.md
(1 hunks)packages/plugin-mention/package.json
(1 hunks)packages/plugin-mention/rollup.config.js
(1 hunks)packages/plugin-mention/src/index.ts
(1 hunks)packages/plugin-mention/src/module/custom-types.ts
(1 hunks)packages/plugin-mention/src/module/elem-to-html.ts
(1 hunks)packages/plugin-mention/src/module/index.ts
(1 hunks)packages/plugin-mention/src/module/interface.ts
(1 hunks)packages/plugin-mention/src/module/parse-elem-html.ts
(1 hunks)packages/plugin-mention/src/module/plugin.ts
(1 hunks)packages/plugin-mention/src/module/render-elem.ts
(1 hunks)packages/plugin-mention/src/utils/dom.ts
(1 hunks)packages/plugin-mention/tsconfig.json
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- packages/plugin-mention/src/utils/dom.ts
- packages/plugin-mention/src/index.ts
- packages/plugin-mention/tsconfig.json
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
packages/plugin-mention/README-en.md
9-9: Images should have alternate text (alt text)
null
(MD045, no-alt-text)
🔇 Additional comments (15)
packages/plugin-mention/src/module/index.ts (2)
6-11
: LGTM!The imports are well-organized, following a logical pattern with external dependencies first followed by internal modules.
20-20
: LGTM!The default export is appropriate for this module entry point.
packages/plugin-mention/rollup.config.js (1)
3-3
: Consider compatibility with older Node.js versions.The JSON import assertion syntax is relatively new and may not be supported in all environments. Consider using
require()
or dynamic import for better compatibility.✅ Verification successful
🌐 Web query:
Which Node.js versions support JSON import assertions?
💡 Result:
JSON import assertions in Node.js have evolved through different versions with changing syntax and experimental flags: ## Support Timeline **Experimental phase with `assert { type: 'json' }`:** - **Node.js ≥17.1**: Initial experimental support via flag [`--experimental-json-modules`][3][6]. - **Node.js ≥18.x**: Available experimentally but required manual flag activation[2][6]. **Syntax change to `with { type: 'json' }`:** - **Node.js ≥18.19 & ≥20.10**: Introduced new syntax (`with`) for import attributes[7][8]. - **Node.js ≥22**: Dropped support for legacy `assert` syntax; only supports new [`with` keyword][8]. ## Current Status (2025) - **Legacy behavior**: Use **`import data from './file.json' assert { type: 'json' }`** in: - **Node.js <18.19** or **<20.x** (experimental). - Requires flag [`--experimental-json-modules`][6]. - **Modern behavior**: Use **`import data from './file.json' with { type: 'json' }`** in: - **Node.js ≥18.19**, **≥20.x**, and later LTS/stable releases[7][8]. --- For example: ```javascript // Pre-v18/v20: import jsonData from './data.json' assert { type: 'json' }; // Post-v18/v20: import jsonData from './data.json' with { type: 'json' }; ``` Citations: - 1: https://v8.dev/features/import-assertions - 2: https://www.stefanjudis.com/snippets/how-to-import-json-files-in-es-modules-node-js/ - 3: https://miyauchi.dev/posts/import-assertions-json-modules/ - 4: https://www.emmanuelgautier.com/blog/node-module-import-assert-json - 5: https://www.proposals.es/proposals/Import%20Assertions - 6: https://nodejs.org/download/release/v18.11.0/docs/api/esm.html - 7: https://nodejs.org/api/esm.html - 8: https://github.com/nodejs/node/issues/51622 - 9: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
JSON Import Assertions May Hinder Compatibility on Older Node Versions
- The syntax
import pkg from './package.json' assert { type: 'json' }
is fully supported only in Node.js v17.1+ (albeit experimentally) and in later versions with appropriate flags.- For projects that need to run on Node versions earlier than v17.1 or without experimental flag usage, using
require()
or dynamic imports would provide broader compatibility..changeset/wise-ducks-grin.md (1)
1-6
: LGTM!The changeset correctly describes the feature addition and uses the appropriate version increment.
packages/plugin-mention/package.json (1)
1-48
: Package Metadata and Configuration ValidationThe package metadata for the new
@wangeditor-next/plugin-mention
is well-defined. The file correctly declares the name, version, description, module type, export fields (supporting both ESM and CommonJS), and peer dependencies. Please ensure that the path specified in the"types"
field (i.e."dist/plugin-mention/src/index.d.ts"
) matches the actual build output and that the scripts for development and build are functioning as expected.packages/plugin-mention/README.md (5)
1-4
: Clear Title and Language NavigationThe title ("# wangEditor mention 插件") and the link to the English documentation are clearly provided at the top. This is helpful for users looking for guidance in both Chinese and English.
11-16
: Installation Instructions are ClearThe installation section correctly shows the command to add the plugin using Yarn. This straightforward instruction is clear for users.
17-20
: Usage Link for Vue ExampleThe provided link to the Vue 示例源码 is useful for developers looking for a practical example of how to integrate the plugin.
21-29
: Accurate Plugin Registration ExampleThe code snippet showing how to register the mention module (lines 23-29) is accurate and clearly instructs that the registration must occur before creating the editor. This is crucial for proper integration.
30-59
: Modal Setup and Mention Insertion ExampleThe detailed example demonstrating the
showModal
function, which positions the modal based on the cursor and container positions, is well illustrated. The nestedinsertMention
function clearly shows how to construct and insert a mention node.One minor note: consider verifying that the null check on
domRange
is sufficient for all edge cases wheredocument.getSelection()
might returnnull
.packages/plugin-mention/README-en.md (5)
1-4
: Concise English Title and Language SwitchThe English documentation starts with a clear title and provides a link to the Chinese version for users who need it. This is a solid approach to support a bilingual audience.
11-16
: Clear Installation InstructionsThe installation instructions using Yarn are straightforward and correct.
21-30
: Plugin Registration Code is ClearThe code snippet (lines 23-30) demonstrates how to import and register the module before editor creation, which is clearly stated as a requirement.
67-77
: Editor Configuration is Well-OutlinedThe configuration snippet provided (lines 67-77) is straightforward and correctly shows how to integrate the mention configuration into the editor's extended configuration. This clarity will help users apply custom settings.
82-90
: HTML Rendering Example is InformativeThe HTML snippet example (lines 86-88) elegantly shows how a mention node will be rendered, including the emphasis on decoding the
data-info
attribute. This helps clarify the expected output.
const module: Partial<IModuleConf> = { | ||
editorPlugin: withMention, | ||
renderElems: [renderElemConf], | ||
elemsToHtml: [elemToHtmlConf], | ||
parseElemsHtml: [parseHtmlConf], | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify the implementation of imported configurations.
The module configuration looks well-structured. However, we should verify that all imported configurations (elemToHtmlConf
, parseHtmlConf
, renderElemConf
) are properly implemented and tested.
🏁 Script executed:
#!/bin/bash
# Check implementation of imported configurations
echo "Checking elem-to-html implementation..."
ast-grep --pattern 'const elemToHtmlConf = {
type: $_,
$$$
}'
echo "Checking parse-elem-html implementation..."
ast-grep --pattern 'const parseHtmlConf = {
selector: $_,
$$$
}'
echo "Checking render-elem implementation..."
ast-grep --pattern 'const renderElemConf = {
type: $_,
$$$
}'
Length of output: 4095
I ran a second check using a plain text search to locate the definitions of both elemToHtmlConf
and renderElemConf
. The search confirmed that while parseHtmlConf
is defined (and our previous output shows multiple definitions), neither elemToHtmlConf
nor renderElemConf
appear to be defined anywhere in the repository.
It appears that in the module configuration for the mention plugin the imported configurations for converting elements to HTML and for rendering elements are missing their implementations. You might need to confirm whether these configurations are defined elsewhere or if they should be added.
elemToHtmlConf
is not defined.renderElemConf
is not defined.
Please verify if these are intentionally omitted (for example, if the mention plugin doesn’t support these features) or if they need to be implemented.
function mentionToHtml(elem: SlateElement, _childrenHtml: string): string { | ||
const { value = '', info = {} } = elem as MentionElement | ||
const infoStr = encodeURIComponent(JSON.stringify(info)) | ||
|
||
return `<span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="${value}" data-info="${infoStr}">@${value}</span>` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation and HTML escaping to prevent XSS.
The current implementation could be vulnerable to XSS attacks. Consider:
- Validating the
value
andinfo
properties - Escaping HTML special characters in
value
- Adding error handling for JSON.stringify
+import { escapeHtml } from '@wangeditor-next/core-utils'
+
function mentionToHtml(elem: SlateElement, _childrenHtml: string): string {
const { value = '', info = {} } = elem as MentionElement
- const infoStr = encodeURIComponent(JSON.stringify(info))
+ if (typeof value !== 'string') {
+ console.warn('Invalid mention value:', value)
+ return ''
+ }
+
+ let infoStr = ''
+ try {
+ infoStr = encodeURIComponent(JSON.stringify(info))
+ } catch (err) {
+ console.error('Failed to stringify mention info:', err)
+ return ''
+ }
+
+ const escapedValue = escapeHtml(value)
- return `<span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="${value}" data-info="${infoStr}">@${value}</span>`
+ return `<span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="${escapedValue}" data-info="${infoStr}">@${escapedValue}</span>`
}
📝 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.
function mentionToHtml(elem: SlateElement, _childrenHtml: string): string { | |
const { value = '', info = {} } = elem as MentionElement | |
const infoStr = encodeURIComponent(JSON.stringify(info)) | |
return `<span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="${value}" data-info="${infoStr}">@${value}</span>` | |
} | |
import { escapeHtml } from '@wangeditor-next/core-utils' | |
function mentionToHtml(elem: SlateElement, _childrenHtml: string): string { | |
const { value = '', info = {} } = elem as MentionElement | |
if (typeof value !== 'string') { | |
console.warn('Invalid mention value:', value) | |
return '' | |
} | |
let infoStr = '' | |
try { | |
infoStr = encodeURIComponent(JSON.stringify(info)) | |
} catch (err) { | |
console.error('Failed to stringify mention info:', err) | |
return '' | |
} | |
const escapedValue = escapeHtml(value) | |
return `<span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="${escapedValue}" data-info="${infoStr}">@${escapedValue}</span>` | |
} |
const value = elem.getAttribute('data-value') || '' | ||
const rawInfo = decodeURIComponent(elem.getAttribute('data-info') || '') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for required attributes.
The function should validate that required attributes are present and handle missing attributes gracefully.
- const value = elem.getAttribute('data-value') || ''
- const rawInfo = decodeURIComponent(elem.getAttribute('data-info') || '')
+ const value = elem.getAttribute('data-value')
+ if (!value) {
+ throw new Error('Missing required attribute: data-value')
+ }
+ const rawInfoAttr = elem.getAttribute('data-info')
+ const rawInfo = rawInfoAttr ? decodeURIComponent(rawInfoAttr) : ''
📝 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.
const value = elem.getAttribute('data-value') || '' | |
const rawInfo = decodeURIComponent(elem.getAttribute('data-info') || '') | |
const value = elem.getAttribute('data-value') | |
if (!value) { | |
throw new Error('Missing required attribute: data-value') | |
} | |
const rawInfoAttr = elem.getAttribute('data-info') | |
const rawInfo = rawInfoAttr ? decodeURIComponent(rawInfoAttr) : '' |
const vnode = h( | ||
'span', | ||
{ | ||
props: { | ||
contentEditable: false, // 不可编辑 | ||
}, | ||
style: { | ||
marginLeft: '3px', | ||
marginRight: '3px', | ||
backgroundColor: 'var(--w-e-textarea-slight-bg-color)', | ||
border: selected // 选中/不选中,样式不一样 | ||
? '2px solid var(--w-e-textarea-selected-border-color)' // wangEditor 提供了 css var https://www.wangeditor.com/v5/theme.html | ||
: '2px solid transparent', | ||
borderRadius: '3px', | ||
padding: '0 3px', | ||
}, | ||
}, | ||
`@${value}`, // 如 `@张三` | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance accessibility with ARIA attributes.
Add ARIA attributes to improve accessibility for screen readers.
const vnode = h(
'span',
{
props: {
contentEditable: false, // 不可编辑
+ role: 'button',
+ 'aria-label': `Mention ${value}`,
},
style: {
marginLeft: '3px',
marginRight: '3px',
backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
border: selected
? '2px solid var(--w-e-textarea-selected-border-color)'
: '2px solid transparent',
borderRadius: '3px',
padding: '0 3px',
},
},
`@${value}`,
)
📝 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.
const vnode = h( | |
'span', | |
{ | |
props: { | |
contentEditable: false, // 不可编辑 | |
}, | |
style: { | |
marginLeft: '3px', | |
marginRight: '3px', | |
backgroundColor: 'var(--w-e-textarea-slight-bg-color)', | |
border: selected // 选中/不选中,样式不一样 | |
? '2px solid var(--w-e-textarea-selected-border-color)' // wangEditor 提供了 css var https://www.wangeditor.com/v5/theme.html | |
: '2px solid transparent', | |
borderRadius: '3px', | |
padding: '0 3px', | |
}, | |
}, | |
`@${value}`, // 如 `@张三` | |
) | |
const vnode = h( | |
'span', | |
{ | |
props: { | |
contentEditable: false, // 不可编辑 | |
role: 'button', | |
'aria-label': `Mention ${value}`, | |
}, | |
style: { | |
marginLeft: '3px', | |
marginRight: '3px', | |
backgroundColor: 'var(--w-e-textarea-slight-bg-color)', | |
border: selected | |
? '2px solid var(--w-e-textarea-selected-border-color)' | |
: '2px solid transparent', | |
borderRadius: '3px', | |
padding: '0 3px', | |
}, | |
}, | |
`@${value}`, | |
) |
function getMentionConfig(editor: IDomEditor) { | ||
const { EXTEND_CONF } = editor.getConfig() | ||
const { mentionConfig } = EXTEND_CONF as IExtendConfig | ||
|
||
return mentionConfig | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for config retrieval.
The getMentionConfig
function should handle cases where the config is missing or invalid.
function getMentionConfig(editor: IDomEditor) {
const { EXTEND_CONF } = editor.getConfig()
+ if (!EXTEND_CONF) {
+ throw new Error('Editor config is missing EXTEND_CONF')
+ }
const { mentionConfig } = EXTEND_CONF as IExtendConfig
+ if (!mentionConfig) {
+ throw new Error('Mention config is missing in EXTEND_CONF')
+ }
return mentionConfig
}
📝 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.
function getMentionConfig(editor: IDomEditor) { | |
const { EXTEND_CONF } = editor.getConfig() | |
const { mentionConfig } = EXTEND_CONF as IExtendConfig | |
return mentionConfig | |
} | |
function getMentionConfig(editor: IDomEditor) { | |
const { EXTEND_CONF } = editor.getConfig() | |
if (!EXTEND_CONF) { | |
throw new Error('Editor config is missing EXTEND_CONF') | |
} | |
const { mentionConfig } = EXTEND_CONF as IExtendConfig | |
if (!mentionConfig) { | |
throw new Error('Mention config is missing in EXTEND_CONF') | |
} | |
return mentionConfig | |
} |
setTimeout(() => { | ||
// 展示 modal (异步,以便准确获取光标位置) | ||
if (showModal) { showModal(newEditor) } | ||
|
||
// 监听,隐藏 modal(异步,等待 modal 渲染后再监听) | ||
setTimeout(() => { | ||
function hide() { | ||
if (hideModal) { hideModal(newEditor) } | ||
} | ||
newEditor.once('fullScreen', hide) | ||
newEditor.once('unFullScreen', hide) | ||
newEditor.once('scroll', hide) | ||
newEditor.once('modalOrPanelShow', hide) | ||
newEditor.once('modalOrPanelHide', hide) | ||
|
||
function hideOnChange() { | ||
if (newEditor.selection != null) { | ||
hide() | ||
newEditor.off('change', hideOnChange) // 及时解绑 | ||
} | ||
} | ||
newEditor.on('change', hideOnChange) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean up timeouts and event listeners.
The nested timeouts and event listeners should be properly cleaned up to prevent memory leaks.
+ let showModalTimeout: NodeJS.Timeout
+ let listenerTimeout: NodeJS.Timeout
+
if (t === '@') {
- setTimeout(() => {
+ showModalTimeout = setTimeout(() => {
// 展示 modal (异步,以便准确获取光标位置)
if (showModal) { showModal(newEditor) }
// 监听,隐藏 modal(异步,等待 modal 渲染后再监听)
- setTimeout(() => {
+ listenerTimeout = setTimeout(() => {
function hide() {
if (hideModal) { hideModal(newEditor) }
+ // Clean up all event listeners
+ newEditor.off('fullScreen', hide)
+ newEditor.off('unFullScreen', hide)
+ newEditor.off('scroll', hide)
+ newEditor.off('modalOrPanelShow', hide)
+ newEditor.off('modalOrPanelHide', hide)
}
newEditor.once('fullScreen', hide)
newEditor.once('unFullScreen', hide)
newEditor.once('scroll', hide)
newEditor.once('modalOrPanelShow', hide)
newEditor.once('modalOrPanelHide', hide)
function hideOnChange() {
if (newEditor.selection != null) {
hide()
newEditor.off('change', hideOnChange)
}
}
newEditor.on('change', hideOnChange)
})
})
+
+ // Clean up timeouts when editor is destroyed
+ newEditor.once('destroy', () => {
+ clearTimeout(showModalTimeout)
+ clearTimeout(listenerTimeout)
+ })
}
📝 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.
setTimeout(() => { | |
// 展示 modal (异步,以便准确获取光标位置) | |
if (showModal) { showModal(newEditor) } | |
// 监听,隐藏 modal(异步,等待 modal 渲染后再监听) | |
setTimeout(() => { | |
function hide() { | |
if (hideModal) { hideModal(newEditor) } | |
} | |
newEditor.once('fullScreen', hide) | |
newEditor.once('unFullScreen', hide) | |
newEditor.once('scroll', hide) | |
newEditor.once('modalOrPanelShow', hide) | |
newEditor.once('modalOrPanelHide', hide) | |
function hideOnChange() { | |
if (newEditor.selection != null) { | |
hide() | |
newEditor.off('change', hideOnChange) // 及时解绑 | |
} | |
} | |
newEditor.on('change', hideOnChange) | |
}) | |
}) | |
let showModalTimeout: NodeJS.Timeout | |
let listenerTimeout: NodeJS.Timeout | |
if (t === '@') { | |
showModalTimeout = setTimeout(() => { | |
// 展示 modal (异步,以便准确获取光标位置) | |
if (showModal) { showModal(newEditor) } | |
// 监听,隐藏 modal(异步,等待 modal 渲染后再监听) | |
listenerTimeout = setTimeout(() => { | |
function hide() { | |
if (hideModal) { hideModal(newEditor) } | |
// Clean up all event listeners | |
newEditor.off('fullScreen', hide) | |
newEditor.off('unFullScreen', hide) | |
newEditor.off('scroll', hide) | |
newEditor.off('modalOrPanelShow', hide) | |
newEditor.off('modalOrPanelHide', hide) | |
} | |
newEditor.once('fullScreen', hide) | |
newEditor.once('unFullScreen', hide) | |
newEditor.once('scroll', hide) | |
newEditor.once('modalOrPanelShow', hide) | |
newEditor.once('modalOrPanelHide', hide) | |
function hideOnChange() { | |
if (newEditor.selection != null) { | |
hide() | |
newEditor.off('change', hideOnChange) // 及时解绑 | |
} | |
} | |
newEditor.on('change', hideOnChange) | |
}) | |
}) | |
// Clean up timeouts when editor is destroyed | |
newEditor.once('destroy', () => { | |
clearTimeout(showModalTimeout) | |
clearTimeout(listenerTimeout) | |
}) | |
} |
Changes Overview
Implementation Approach
Testing Done
Verification Steps
Additional Notes
Checklist
Related Issues
Summary by CodeRabbit
New Features
Documentation