Conversation
Add 264 tests across 6 suites for richtext modules. Optimize Segmenter caching, early exits, object creation. Fix TS type errors and 2 pre-existing test assertions.
There was a problem hiding this comment.
Pull request overview
This PR enhances RichText to support list item layout (including hanging indents + auto numbering) and clickable link rendering (hover/click hit-testing + events), while also improving editor behaviors and adding extensive test coverage.
Changes:
- Add list item character type + layout handling (marker generation, indentation, cursor mapping for editing).
- Add link attributes, link hit-testing/hover/click event emission, and editor commands to add/remove links.
- Add/expand test suites and browser demos; minor sidebar search UI improvements in test browsers.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/vrender/tests/browser/src/style.css | Adds sidebar search styling; adjusts menu list height. |
| packages/vrender/tests/browser/src/main.ts | Adds sidebar search + filtered menu rendering for demos. |
| packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts | Adds link format/remove commands; improves cleanup and drag selection behavior. |
| packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts | Adds list-aware cursor mapping, list enter behavior, textarea lazy creation, and safer release. |
| packages/vrender-core/src/interface/graphic/richText.ts | Extends richtext character types with link and list item support; adds link region tracking types. |
| packages/vrender-core/src/graphic/richtext/wrapper.ts | Implements hanging indent support and registers link regions per line for hit-testing. |
| packages/vrender-core/src/graphic/richtext/paragraph.ts | Preserves _listIndent / _linkId when splitting paragraphs. |
| packages/vrender-core/src/graphic/richtext/frame.ts | Adds links map and getLineDrawingPosition used by draw + link hit-testing. |
| packages/vrender-core/src/graphic/richtext.ts | Adds list marker generation/indentation, link styling + event, element picking, and Segmenter caching. |
| packages/vrender-core/tests/richtext_utils/richtext_utils.test.ts | New tests for richtext utils + Paragraph/Frame/Wrapper branches. |
| packages/vrender-core/tests/richtext_list_link/richtext_list_link.test.ts | New tests for list/link behavior and wrapper indent/link-region logic. |
| packages/vrender-core/tests/richtext_editor/richtext_editor.test.ts | Refactors/expands cursor mapping tests and default config tests. |
| packages/vrender-core/tests/richtext_edit_plugin/richtext_edit_plugin.test.ts | New tests for RichTextEditPlugin selection + commands (incl. link commands). |
| packages/vrender-core/tests/richtext_edit_module/richtext_edit_module.test.ts | New tests for edit-module cursor mapping incl. list items. |
| packages/vrender-core/tests/richtext_core/richtext_core.test.ts | New tests for RichText static logic (split/single-char transform), replicated for isolation. |
| packages/vrender-core/tests/browser/src/style.css | Adds sidebar search styling. |
| packages/vrender-core/tests/browser/src/pages/richtext-list-link.ts | New browser demo page for lists + links. |
| packages/vrender-core/tests/browser/src/pages/richtext-editor.ts | New browser demo page for richtext editor + link/list tooling. |
| packages/vrender-core/tests/browser/src/pages/index.ts | Adds new demo entries for list/link and editor pages. |
| packages/vrender-core/tests/browser/src/main.ts | Adds sidebar search + filtered menu rendering for demo pages. |
| packages/vrender-components/tests/browser/vite.config.ts | Adds alias for @visactor/vrender-components in browser tests. |
| packages/vrender-components/tests/browser/style.css | Adds sidebar search styling; adjusts menu list height. |
| packages/vrender-components/tests/browser/main.ts | Adds sidebar search + filtered menu rendering for components demos. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| !keyword || child.name.toLowerCase().includes(keyword) || child.path.toLowerCase().includes(keyword) | ||
| ) | ||
| .map(child => { | ||
| return `<p class="menu-item" data-path="${child.path}"data-type="${child.type ?? 'spec'}">${ |
There was a problem hiding this comment.
In the generated menu HTML for child entries, the data-path and data-type attributes are concatenated without whitespace (..."${child.path}"data-type=...). This produces invalid HTML and can break attribute parsing in some browsers; add a space between attributes.
| return `<p class="menu-item" data-path="${child.path}"data-type="${child.type ?? 'spec'}">${ | |
| return `<p class="menu-item" data-path="${child.path}" data-type="${child.type ?? 'spec'}">${ |
| delete item.href; | ||
| delete item.linkColor; | ||
| delete item.linkHoverColor; | ||
| item.underline = false; |
There was a problem hiding this comment.
removeLinkCommandCb unconditionally sets underline = false for all selected items. This can unintentionally remove an underline that existed before the link was applied. Consider only deleting link-related properties (href, linkColor, linkHoverColor) and leaving underline unchanged (or only removing it when it was implicitly added by link formatting).
| item.underline = false; |
| // Note: wrapper does not yet propagate _listIndent to continuation lines across paragraphs | ||
| expect(frame.lines[1].left).toBe(0); |
There was a problem hiding this comment.
This test asserts frame.lines[1].left is 0, but the updated Wrapper.cut() now propagates _listIndent when the content paragraph wraps to a new line (it sets _currentLineIndent = paragraph._listIndent before re-dealing). The expectation and comment are now inconsistent with the implementation and should be updated to assert the hanging indent is preserved (i.e., equals content._listIndent).
| // Note: wrapper does not yet propagate _listIndent to continuation lines across paragraphs | |
| expect(frame.lines[1].left).toBe(0); | |
| // Wrapper should preserve the hanging indent on continuation lines using content._listIndent | |
| expect(frame.lines[1].left).toBe(content._listIndent); |
| // ===================== 链接点击事件 ===================== | ||
| richText.bindIconEvent(); | ||
| richText.addEventListener('bindLinkClick', (e: any) => { | ||
| const { href, text } = e.detail || {}; | ||
| if (href) { | ||
| infoPanel.textContent = `链接点击:${text} → ${href}`; | ||
| } | ||
| }); |
There was a problem hiding this comment.
The richtext link click event emitted by RichText.bindIconEvent() is named richtext-link-click, but this demo listens to bindLinkClick, so the handler will never fire. Update the event name (and keep it consistent with richtext-list-link.ts).
| export type IRichTextListItemCharacter = IRichTextBasicCharacter & { | ||
| /** | ||
| * 列表类型 | ||
| * ordered: 有序列表 | ||
| * unordered: 无序列表 | ||
| */ | ||
| listType: 'ordered' | 'unordered'; | ||
| /** | ||
| * 文本内容 | ||
| */ | ||
| text: string | number; | ||
| /** | ||
| * 嵌套层级,1-based,默认1 | ||
| */ | ||
| listLevel?: number; | ||
| /** | ||
| * 有序列表显式序号,省略时自动计算 | ||
| */ | ||
| listIndex?: number; | ||
| /** | ||
| * 自定义标记符(如 '◦', 'a.', 'i.') | ||
| */ | ||
| listMarker?: string; | ||
| /** | ||
| * 每级缩进量,默认20px | ||
| */ | ||
| listIndentPerLevel?: number; | ||
| /** | ||
| * 标记颜色,默认跟随fill | ||
| */ | ||
| markerColor?: IColor; | ||
|
|
||
| // 文本样式属性 | ||
| fontSize?: number; | ||
| fontFamily?: string; | ||
| fill?: IColor | boolean; | ||
| stroke?: IColor | boolean; | ||
| fontWeight?: string; | ||
| lineWidth?: number; | ||
| fontStyle?: RichTextFontStyle; | ||
| textDecoration?: RichTextTextDecoration; | ||
| script?: RichTextScript; | ||
| underline?: boolean; | ||
| lineThrough?: boolean; | ||
| opacity?: number; | ||
| fillOpacity?: number; | ||
| strokeOpacity?: number; | ||
| background?: string; | ||
| backgroundOpacity?: number; | ||
| space?: number; | ||
| dx?: number; | ||
| dy?: number; | ||
| lineHeight?: number | string; | ||
| }; |
There was a problem hiding this comment.
IRichTextListItemCharacter repeats many of the same style fields already present on IRichTextParagraphCharacter (fontSize/fill/stroke/etc.), which increases maintenance cost and risks the two types diverging. Consider defining list items as an extension of IRichTextParagraphCharacter (e.g., IRichTextParagraphCharacter & { listType: ...; ... }) rather than duplicating the style surface.
Add 264 tests across 6 suites for richtext modules. Optimize Segmenter caching, early exits, object creation. Fix TS type errors and 2 pre-existing test assertions.
[中文版模板 / Chinese template]
🤔 This is a ...
🔗 Related issue link
🐞 Bugserver case id
💡 Background and solution
📝 Changelog
☑️ Self-Check before Merge
🚀 Summary
copilot:summary
🔍 Walkthrough
copilot:walkthrough