feat(editor): comment extension (#12948)

#### PR Dependency Tree


* **PR #12948** 👈
  * **PR #12980**

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Introduced inline comment functionality, allowing users to add,
resolve, and highlight comments directly within text.
  * Added a new toolbar action for inserting comments when supported.
* Inline comments are visually highlighted and can be interacted with in
the editor.

* **Enhancements**
  * Integrated a feature flag to enable or disable the comment feature.
* Improved inline manager rendering to support wrapper specs for
advanced formatting.

* **Developer Tools**
* Added mock comment provider for testing and development environments.

* **Chores**
* Updated dependencies and project references to support the new inline
comment module.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
L-Sun
2025-07-02 17:14:34 +08:00
committed by GitHub
parent a66096cdf9
commit 8ce85f708d
40 changed files with 760 additions and 14 deletions

View File

@@ -32,12 +32,29 @@ export class InlineManager<TextAttributes extends BaseTextAttributes> {
const renderer: AttributeRenderer<TextAttributes> = props => {
// Priority increases from front to back
for (const spec of this.specs.toReversed()) {
const specs = this.specs.toReversed();
const wrapperSpecs = specs.filter(spec => spec.wrapper);
const normalSpecs = specs.filter(spec => !spec.wrapper);
let result = defaultRenderer(props);
for (const spec of normalSpecs) {
if (spec.match(props.delta)) {
return spec.renderer(props);
result = spec.renderer(props);
break;
}
}
return defaultRenderer(props);
for (const spec of wrapperSpecs) {
if (spec.match(props.delta)) {
result = spec.renderer({
...props,
children: result,
});
}
}
return result;
};
return renderer;
};

View File

@@ -21,6 +21,7 @@ export type InlineSpecs<
match: (delta: DeltaInsert<TextAttributes>) => boolean;
renderer: AttributeRenderer<TextAttributes>;
embed?: boolean;
wrapper?: boolean;
};
export type InlineMarkdownMatchAction<

View File

@@ -279,7 +279,10 @@ export class InlineEditor<
this._isReadonly = isReadonly;
}
transact(fn: () => void): void {
/**
* @param withoutTransact Execute a transaction without capturing the history.
*/
transact(fn: () => void, withoutTransact = false): void {
const doc = this.yText.doc;
if (!doc) {
throw new BlockSuiteError(
@@ -288,6 +291,6 @@ export class InlineEditor<
);
}
doc.transact(fn, doc.clientID);
doc.transact(fn, withoutTransact ? null : doc.clientID);
}
}

View File

@@ -19,11 +19,16 @@ export class InlineTextService<TextAttributes extends BaseTextAttributes> {
options: {
match?: (delta: DeltaInsert, deltaInlineRange: InlineRange) => boolean;
mode?: 'replace' | 'merge';
withoutTransact?: boolean;
} = {}
): void => {
if (this.editor.isReadonly) return;
const { match = () => true, mode = 'merge' } = options;
const {
match = () => true,
mode = 'merge',
withoutTransact = false,
} = options;
const deltas = this.editor.deltaService.getDeltasByInlineRange(inlineRange);
deltas
@@ -49,7 +54,7 @@ export class InlineTextService<TextAttributes extends BaseTextAttributes> {
targetInlineRange.length,
normalizedAttributes
);
});
}, withoutTransact);
});
};

View File

@@ -12,6 +12,7 @@ export type AttributeRenderer<
startOffset: number;
endOffset: number;
lineIndex: number;
children?: TemplateResult<1>;
}) => TemplateResult<1>;
export interface InlineRange {