snapshot of https://github.com/dream-num/univer.git (dev, 2026-09-16; blobs > 131072B omitted)
Some checks failed
📦 Build / build (push) Has been cancelled
🧪 CI Test / test shard (1/4) (push) Has been cancelled
🧪 CI Test / test shard (2/4) (push) Has been cancelled
🧪 CI Test / test shard (3/4) (push) Has been cancelled
🧪 CI Test / test shard (4/4) (push) Has been cancelled
🧪 CI Test / test (push) Has been cancelled
🧪 CI Test / eslint (push) Has been cancelled
🧪 CI Test / typecheck (push) Has been cancelled
🔫 Sync to Pro / dispatch-sync (push) Has been cancelled
🔮 Sync Mirror / sync (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-16 05:09:45 +05:00
commit bcf6ef63ad
7118 changed files with 1236854 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# @univerjs/docs-thread-comment
`@univerjs/docs-thread-comment` provides model commands and Facade APIs for comments anchored to fixed document text ranges. It has no UI or rendering dependency and can be used in Node environments.
## Package Overview
| Package | UMD global | CSS | Locales | Facade entry |
| --- | --- | :---: | :---: | :---: |
| `@univerjs/docs-thread-comment` | `UniverDocsThreadComment` | No | No | Yes |
## Installation
```sh
pnpm add @univerjs/docs-thread-comment
# or
npm install @univerjs/docs-thread-comment
```
Keep all `@univerjs/*` packages on the same version.
## Usage
```ts
import { UniverDocsThreadCommentPlugin } from '@univerjs/docs-thread-comment';
import '@univerjs/docs-thread-comment/facade';
univer.registerPlugin(UniverDocsThreadCommentPlugin);
const range = univerAPI.getActiveDocument()?.getTextRange(0, 12);
await range?.createCommentAsync('Verify this introduction.', { id: 'review-intro' });
```
Use `@univerjs/docs-thread-comment-ui` separately when menus, canvas decorations, or the shared side panel are required.
## Resources
- [Documentation](https://docs.univer.ai)
- [NPM package](https://npmjs.com/package/@univerjs/docs-thread-comment)
- [GitHub repository](https://github.com/dream-num/univer)

View File

@@ -0,0 +1,87 @@
{
"name": "@univerjs/docs-thread-comment",
"version": "1.0.0-rc.0",
"private": false,
"description": "Thread comment model integration and Facade APIs for Univer Docs.",
"author": "DreamNum Co., Ltd. <developer@univer.ai>",
"license": "Apache-2.0",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/univer"
},
"homepage": "https://univer.ai",
"repository": {
"type": "git",
"url": "https://github.com/dream-num/univer"
},
"bugs": {
"url": "https://github.com/dream-num/univer/issues"
},
"keywords": [
"univer",
"docs",
"comment",
"thread-comment"
],
"exports": {
".": "./src/index.ts",
"./facade": "./src/facade/index.ts",
"./*": "./src/*"
},
"main": "./src/index.ts",
"types": "./lib/types/index.d.ts",
"publishConfig": {
"access": "public",
"main": "./lib/es/index.js",
"module": "./lib/es/index.js",
"exports": {
".": {
"import": "./lib/es/index.js",
"require": "./lib/cjs/index.js",
"types": "./lib/types/index.d.ts"
},
"./*": {
"import": "./lib/es/*",
"require": "./lib/cjs/*",
"types": "./lib/types/index.d.ts"
},
"./facade": {
"import": "./lib/es/facade.js",
"require": "./lib/cjs/facade.js",
"types": "./lib/types/facade/index.d.ts"
},
"./lib/facade": {
"import": "./lib/es/facade.js",
"require": "./lib/cjs/facade.js",
"types": "./lib/types/facade/index.d.ts"
},
"./lib/*": "./lib/*"
}
},
"directories": {
"lib": "lib"
},
"files": [
"lib"
],
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"coverage": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"build:bundle": "univer-cli build",
"build:types": "tsc -p tsconfig.node.json",
"build": "pnpm run build:bundle && pnpm run build:types"
},
"dependencies": {
"@univerjs/core": "workspace:*",
"@univerjs/docs": "workspace:*",
"@univerjs/thread-comment": "workspace:*"
},
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.2",
"typescript": "^6.0.3",
"vitest": "^5.0.0"
}
}

View File

@@ -0,0 +1,113 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { DocumentDataModel, IDocumentData } from '@univerjs/core';
import {
ICommandService,
IUniverInstanceService,
Univer,
UniverInstanceType,
} from '@univerjs/core';
import { FDocument } from '@univerjs/docs/facade';
import {
AddCommentMutation,
IThreadCommentDataSourceService,
ThreadCommentDataSourceService,
ThreadCommentFacadeService,
ThreadCommentModel,
} from '@univerjs/thread-comment';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { DEFAULT_DOC_SUBUNIT_ID } from '../../../common/const';
import {
AddDocCommentDecorationMutation,
CreateDocTextRangeCommentCommand,
} from '../create-doc-text-range-comment.command';
import '@univerjs/docs-thread-comment/facade';
const DOC_ID = 'headless-doc-comment-test';
function createDocData(): IDocumentData {
return {
id: DOC_ID,
body: {
dataStream: 'Hello world\r\n',
textRuns: [],
paragraphs: [],
sectionBreaks: [],
customBlocks: [],
customDecorations: [],
},
documentStyle: {
pageSize: { width: 594.3, height: 840.51 },
marginTop: 72,
marginBottom: 72,
marginRight: 90,
marginLeft: 90,
},
};
}
describe('CreateDocTextRangeCommentCommand', () => {
let univer: Univer;
beforeEach(() => {
univer = new Univer();
const injector = univer.__getInjector();
injector.add([IThreadCommentDataSourceService, { useClass: ThreadCommentDataSourceService }]);
injector.add([ThreadCommentModel]);
injector.add([ThreadCommentFacadeService]);
univer.createUnit(UniverInstanceType.UNIVER_DOC, createDocData());
const commandService = injector.get(ICommandService);
commandService.registerCommand(CreateDocTextRangeCommentCommand);
commandService.registerCommand(AddCommentMutation);
commandService.registerCommand(AddDocCommentDecorationMutation);
});
afterEach(() => univer.dispose());
it('creates and queries a fixed text comment without UI services', async () => {
const injector = univer.__getInjector();
const commandService = injector.get(ICommandService);
await expect(commandService.executeCommand(CreateDocTextRangeCommentCommand.id, {
unitId: DOC_ID,
range: { startOffset: 0, endOffset: 5 },
content: 'Check the greeting.',
id: 'agent-comment-1',
personId: 'agent-user-1',
})).resolves.toBe(true);
const documentModel = injector.get(IUniverInstanceService)
.getUnit<DocumentDataModel>(DOC_ID, UniverInstanceType.UNIVER_DOC);
if (!documentModel) {
throw new Error('Test document was not created.');
}
const range = injector.createInstance(FDocument, documentModel).getTextRange(0, 5);
expect(range.getComments()).toHaveLength(1);
expect(injector.get(ThreadCommentModel).getThread(
DOC_ID,
DEFAULT_DOC_SUBUNIT_ID,
'agent-comment-1'
)?.root).toMatchObject({
ref: 'Hello',
startOffset: 0,
endOffset: 5,
personId: 'agent-user-1',
});
});
});

View File

@@ -0,0 +1,206 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { DocumentDataModel, IAccessor, ICommand, IMutation, IMutationInfo, ITextRangeParam, JSONXActions } from '@univerjs/core';
import type { IThreadComment, ThreadCommentContent } from '@univerjs/thread-comment';
import {
BuildTextUtils,
CommandType,
CustomDecorationType,
generateRandomId,
ICommandService,
IUniverInstanceService,
JSONX,
sequenceExecute,
UniverInstanceType,
UserManagerService,
} from '@univerjs/core';
import {
AddCommentMutation,
getDT,
IThreadCommentDataSourceService,
normalizeThreadCommentContent,
} from '@univerjs/thread-comment';
import { DEFAULT_DOC_SUBUNIT_ID } from '../../common/const';
export interface IAddDocTextRangeCommentParams {
unitId: string;
comment: IThreadComment;
range: ITextRangeParam;
}
/** Parameters accepted by the document text-range Facade. */
export interface ICreateDocTextRangeCommentParams {
unitId: string;
range: ITextRangeParam;
content: ThreadCommentContent;
attachments?: string[];
id?: string;
threadId?: string;
personId?: string;
dateTime?: Date;
}
interface IValidTextRange extends ITextRangeParam {
startOffset: number;
endOffset: number;
}
export interface IPreparedDocTextRangeComment {
comment: IThreadComment;
commentMutation: IMutationInfo;
decorationMutationParams: IDocCommentDecorationMutationParams;
}
export interface IDocCommentDecorationMutationParams {
unitId: string;
actions: JSONXActions;
segmentId?: string;
}
/** Applies document comment decoration actions without render or selection services. */
export const AddDocCommentDecorationMutation: IMutation<
IDocCommentDecorationMutationParams,
IDocCommentDecorationMutationParams | false
> = {
id: 'docs-thread-comment.mutation.add-decoration',
type: CommandType.MUTATION,
handler(accessor, params) {
if (!params || JSONX.isNoop(params.actions)) {
return false;
}
const document = accessor.get(IUniverInstanceService)
.getUnit<DocumentDataModel>(params.unitId, UniverInstanceType.UNIVER_DOC);
if (!document) {
return false;
}
const undoActions = JSONX.invertWithDoc(params.actions, document.getSnapshot());
document.apply(params.actions);
return { ...params, actions: undoActions };
},
};
function getValidRange(accessor: IAccessor, unitId: string, range: ITextRangeParam): IValidTextRange | null {
const { startOffset, endOffset } = range;
if (!Number.isInteger(startOffset) || !Number.isInteger(endOffset) || startOffset < 0 || endOffset <= startOffset) {
return null;
}
const document = accessor.get(IUniverInstanceService).getUnit<DocumentDataModel>(unitId, UniverInstanceType.UNIVER_DOC);
const body = document?.getSelfOrHeaderFooterModel(range.segmentId)?.getBody();
if (!body || endOffset > body.dataStream.length) {
return null;
}
return { ...range, startOffset, endOffset, collapsed: false };
}
/** Builds the model mutations shared by headless and UI document comment commands. */
export async function prepareDocTextRangeComment(
accessor: IAccessor,
params: IAddDocTextRangeCommentParams
): Promise<IPreparedDocTextRangeComment | null> {
const range = getValidRange(accessor, params.unitId, params.range);
if (!range) {
return null;
}
const savedComment = await accessor.get(IThreadCommentDataSourceService).addComment(params.comment);
const comment: IThreadComment = {
...params.comment,
...savedComment,
unitId: params.unitId,
subUnitId: DEFAULT_DOC_SUBUNIT_ID,
startOffset: range.startOffset,
endOffset: range.endOffset,
segmentId: range.segmentId,
collapsed: false,
};
const textX = BuildTextUtils.customDecoration.add({
ranges: [range],
id: comment.id,
type: CustomDecorationType.COMMENT,
});
const decorationMutationParams: IDocCommentDecorationMutationParams = {
unitId: params.unitId,
actions: JSONX.getInstance().editOp(textX.serialize()),
segmentId: range.segmentId,
};
return {
comment,
commentMutation: {
id: AddCommentMutation.id,
params: { unitId: params.unitId, subUnitId: DEFAULT_DOC_SUBUNIT_ID, comment },
},
decorationMutationParams,
};
}
/**
* Creates a root comment and document decoration for an explicit text range.
* This model command is safe to execute without loading document UI packages.
*/
export const CreateDocTextRangeCommentCommand: ICommand<ICreateDocTextRangeCommentParams> = {
id: 'docs.command.create-text-range-comment',
type: CommandType.COMMAND,
async handler(accessor, params) {
if (!params) {
return false;
}
const range = getValidRange(accessor, params.unitId, params.range);
if (!range) {
return false;
}
const document = accessor.get(IUniverInstanceService).getUnit<DocumentDataModel>(params.unitId, UniverInstanceType.UNIVER_DOC);
const body = document?.getSelfOrHeaderFooterModel(range.segmentId)?.getBody();
if (!body) {
return false;
}
const id = params.id ?? generateRandomId();
const comment: IThreadComment = {
id,
threadId: params.threadId ?? id,
unitId: params.unitId,
subUnitId: DEFAULT_DOC_SUBUNIT_ID,
ref: BuildTextUtils.transform.getPlainText(body.dataStream.slice(range.startOffset, range.endOffset)),
text: normalizeThreadCommentContent(params.content),
attachments: params.attachments ?? [],
dT: getDT(params.dateTime),
personId: params.personId ?? accessor.get(UserManagerService).getCurrentUser().userID,
startOffset: range.startOffset,
endOffset: range.endOffset,
segmentId: range.segmentId,
collapsed: false,
};
const prepared = await prepareDocTextRangeComment(accessor, { unitId: params.unitId, range, comment });
if (!prepared) {
return false;
}
return (await sequenceExecute([
prepared.commentMutation,
{ id: AddDocCommentDecorationMutation.id, params: prepared.decorationMutationParams },
], accessor.get(ICommandService))).result;
},
};

View File

@@ -0,0 +1,20 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** Stable subunit used by document text comments. */
export const DEFAULT_DOC_SUBUNIT_ID = 'default_doc';
export const DOCS_THREAD_COMMENT_PLUGIN_NAME = 'DOC_THREAD_COMMENT_PLUGIN';

View File

@@ -0,0 +1,24 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const DOCS_THREAD_COMMENT_PLUGIN_CONFIG_KEY = 'docs-thread-comment.config';
export const configSymbol = Symbol(DOCS_THREAD_COMMENT_PLUGIN_CONFIG_KEY);
export interface IUniverDocsThreadCommentConfig {
}
export const defaultPluginConfig: IUniverDocsThreadCommentConfig = {};

View File

@@ -0,0 +1,41 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Disposable, Inject, IResourceManagerService, UniverInstanceType } from '@univerjs/core';
import {
createThreadCommentResourceHook,
IThreadCommentDataSourceService,
TC_PLUGIN_NAME,
ThreadCommentModel,
} from '@univerjs/thread-comment';
export const DOC_UNIVER_THREAD_COMMENT_PLUGIN = `DOC_${TC_PLUGIN_NAME}`;
export class DocsThreadCommentResourceController extends Disposable {
constructor(
@IResourceManagerService private readonly _resourceManagerService: IResourceManagerService,
@Inject(ThreadCommentModel) private readonly _threadCommentModel: ThreadCommentModel,
@IThreadCommentDataSourceService private readonly _threadCommentDataSourceService: IThreadCommentDataSourceService
) {
super();
this.disposeWithMe(this._resourceManagerService.registerPluginResource(createThreadCommentResourceHook(
this._threadCommentModel,
this._threadCommentDataSourceService,
DOC_UNIVER_THREAD_COMMENT_PLUGIN,
[UniverInstanceType.UNIVER_DOC]
)));
}
}

View File

@@ -0,0 +1,130 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { Injector } from '@univerjs/core';
import { CustomDecorationType, ICommandService } from '@univerjs/core';
import * as DocsThreadComment from '@univerjs/docs-thread-comment';
import * as DocsFacade from '@univerjs/docs/facade';
import * as ThreadComment from '@univerjs/thread-comment';
export type IDocumentTextRangeCommentCreateOptions = Omit<
DocsThreadComment.ICreateDocTextRangeCommentParams,
'unitId' | 'range' | 'content'
>;
/** Comment methods added to a fixed document text range. */
export interface IFDocumentTextRangeThreadCommentMixin {
/**
* Creates a comment on this text range.
* @param content Plain text or a Univer document body for rich comment content.
* @param [options] Optional stable IDs, author, attachments, and creation time.
* @returns {Promise<boolean>} `true` when the create command succeeds; otherwise, `false`.
* @throws {TypeError} If the content is empty.
* @example
* ```ts
* const range = univerAPI.getActiveDocument()?.getTextRange(0, 12);
* await range?.createCommentAsync('Verify this introduction.', { id: 'review-intro' });
* ```
*/
createCommentAsync(
content: ThreadComment.ThreadCommentContent,
options?: IDocumentTextRangeCommentCreateOptions
): Promise<boolean>;
/**
* Returns locally loaded comments whose comment decorations overlap this text range.
* @returns Matching comment threads. The returned anchors use `DOC_TEXT_RANGE`.
* @example
* ```ts
* const range = univerAPI.getActiveDocument()?.getTextRange(0, 12);
* const comments = range?.getComments() ?? [];
* comments.forEach(({ root, children }) => console.log(root.id, children.length));
* ```
*/
getComments(): ThreadComment.IFacadeThreadCommentInfo[];
/**
* Synchronizes known document threads and returns comments whose decorations overlap this text range.
* @returns {Promise<ThreadComment.IFacadeThreadCommentInfo[]>} A promise resolving to the synchronized matching comment threads.
* @example
* ```ts
* const range = univerAPI.getActiveDocument()?.getTextRange(0, 12);
* const comments = range ? await range.listCommentsAsync() : [];
* console.log(comments.length);
* ```
*/
listCommentsAsync(): Promise<ThreadComment.IFacadeThreadCommentInfo[]>;
}
export class FDocumentTextRangeThreadCommentMixin extends DocsFacade.FDocumentTextRange implements IFDocumentTextRangeThreadCommentMixin {
declare private _threadCommentCommandService: ICommandService;
declare private _threadCommentFacadeService: ThreadComment.ThreadCommentFacadeService;
override _initialize(injector: Injector): void {
this._threadCommentCommandService = injector.get(ICommandService);
let commentService: ThreadComment.ThreadCommentFacadeService | undefined;
Object.defineProperty(this, '_threadCommentFacadeService', {
get: () => commentService ??= injector.get(ThreadComment.ThreadCommentFacadeService),
});
}
/** @inheritdoc */
override createCommentAsync(
content: ThreadComment.ThreadCommentContent,
options: IDocumentTextRangeCommentCreateOptions = {}
): Promise<boolean> {
return this._threadCommentCommandService.executeCommand(DocsThreadComment.CreateDocTextRangeCommentCommand.id, {
...options,
unitId: this._document.getId(),
range: { ...this.getRange(), collapsed: false },
content,
});
}
/** @inheritdoc */
override getComments(): ThreadComment.IFacadeThreadCommentInfo[] {
const range = this.getRange();
const commentIds = this._getOverlappingCommentIds(range);
return this._threadCommentFacadeService.getComments({
unitIds: [this._document.getId()],
subUnitIds: [DocsThreadComment.DEFAULT_DOC_SUBUNIT_ID],
anchorKinds: [ThreadComment.ThreadCommentAnchorKind.DOC_TEXT_RANGE],
}).filter((comment) => commentIds.has(comment.root.id));
}
/** @inheritdoc */
override async listCommentsAsync(): Promise<ThreadComment.IFacadeThreadCommentInfo[]> {
const range = this.getRange();
const commentIds = this._getOverlappingCommentIds(range);
const comments = await this._threadCommentFacadeService.listCommentsAsync({
unitIds: [this._document.getId()],
subUnitIds: [DocsThreadComment.DEFAULT_DOC_SUBUNIT_ID],
anchorKinds: [ThreadComment.ThreadCommentAnchorKind.DOC_TEXT_RANGE],
});
return comments.filter((comment) => commentIds.has(comment.root.id));
}
private _getOverlappingCommentIds(range: DocsFacade.IFDocumentTextRange): Set<string> {
const decorations = this._document.getBody(range.segmentId).customDecorations ?? [];
return new Set(decorations.filter((decoration) => decoration.type === CustomDecorationType.COMMENT
&& decoration.startIndex < range.endOffset
&& decoration.endIndex >= range.startOffset).map((decoration) => decoration.id));
}
}
DocsFacade.FDocumentTextRange.extend(FDocumentTextRangeThreadCommentMixin);
declare module '@univerjs/docs/facade' {
interface FDocumentTextRange extends IFDocumentTextRangeThreadCommentMixin {}
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import './f-document-text-range';
export type {
IDocumentTextRangeCommentCreateOptions,
IFDocumentTextRangeThreadCommentMixin,
} from './f-document-text-range';

View File

@@ -0,0 +1,30 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export {
AddDocCommentDecorationMutation,
CreateDocTextRangeCommentCommand,
prepareDocTextRangeComment,
} from './commands/commands/create-doc-text-range-comment.command';
export type {
IAddDocTextRangeCommentParams,
ICreateDocTextRangeCommentParams,
IDocCommentDecorationMutationParams,
IPreparedDocTextRangeComment,
} from './commands/commands/create-doc-text-range-comment.command';
export { DEFAULT_DOC_SUBUNIT_ID } from './common/const';
export type { IUniverDocsThreadCommentConfig } from './config/config';
export { UniverDocsThreadCommentPlugin } from './plugin';

View File

@@ -0,0 +1,68 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { IUniverDocsThreadCommentConfig } from './config/config';
import {
DependentOn,
ICommandService,
IConfigService,
Inject,
Injector,
merge,
Plugin,
UniverInstanceType,
} from '@univerjs/core';
import { UniverDocsPlugin } from '@univerjs/docs';
import { UniverThreadCommentPlugin } from '@univerjs/thread-comment';
import pkg from '../package.json';
import {
AddDocCommentDecorationMutation,
CreateDocTextRangeCommentCommand,
} from './commands/commands/create-doc-text-range-comment.command';
import { DOCS_THREAD_COMMENT_PLUGIN_NAME } from './common/const';
import { defaultPluginConfig, DOCS_THREAD_COMMENT_PLUGIN_CONFIG_KEY } from './config/config';
import { DocsThreadCommentResourceController } from './controllers/docs-thread-comment-resource.controller';
@DependentOn(UniverDocsPlugin, UniverThreadCommentPlugin)
export class UniverDocsThreadCommentPlugin extends Plugin {
static override pluginName = DOCS_THREAD_COMMENT_PLUGIN_NAME;
static override packageName = pkg.name;
static override version = pkg.version;
static override type = UniverInstanceType.UNIVER_DOC;
constructor(
private readonly _config: Partial<IUniverDocsThreadCommentConfig> = defaultPluginConfig,
@Inject(Injector) protected override _injector: Injector,
@IConfigService private readonly _configService: IConfigService,
@ICommandService private readonly _commandService: ICommandService
) {
super();
const { ...rest } = merge(
{},
defaultPluginConfig,
this._config
);
this._configService.setConfig(DOCS_THREAD_COMMENT_PLUGIN_CONFIG_KEY, rest);
}
override onStarting(): void {
this._injector.add([DocsThreadCommentResourceController]);
this._injector.get(DocsThreadCommentResourceController);
this.disposeWithMe(this._commandService.registerCommand(CreateDocTextRangeCommentCommand));
this.disposeWithMe(this._commandService.registerCommand(AddDocCommentDecorationMutation));
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "@univerjs-infra/shared/tsconfigs/base",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib/types"
},
"include": ["src"]
}

View File

@@ -0,0 +1,18 @@
{
"extends": "@univerjs-infra/shared/tsconfigs/node",
"compilerOptions": {
"rootDir": "src",
"declaration": true,
"emitDeclarationOnly": true,
"noEmit": false,
"outDir": "lib/types"
},
"include": [
"src"
],
"exclude": [
"src/**/__tests__/**",
"src/**/*.spec.ts",
"src/**/*.test.ts"
]
}

View File

@@ -0,0 +1,3 @@
import createConfig from '@univerjs-infra/shared/vitest';
export default createConfig();