@hmg-report-editor/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor/ReportEditorCore.d.ts +137 -0
- package/dist/editor/createReportEditor.d.ts +3 -0
- package/dist/extensions/DropdownFieldNode.d.ts +15 -0
- package/dist/extensions/FontSizeExtension.d.ts +11 -0
- package/dist/extensions/HiddenParagraphExtension.d.ts +11 -0
- package/dist/extensions/IndentationExtension.d.ts +13 -0
- package/dist/extensions/LineHeightExtension.d.ts +12 -0
- package/dist/extensions/PageBreakNode.d.ts +11 -0
- package/dist/extensions/ReportNumberedBlockNode.d.ts +10 -0
- package/dist/extensions/StructuredFieldNode.d.ts +15 -0
- package/dist/extensions/TextColorExtension.d.ts +11 -0
- package/dist/extensions/VisibilityGroupMark.d.ts +6 -0
- package/dist/extensions/index.d.ts +29 -0
- package/dist/group/ReportEditorGroupManager.d.ts +45 -0
- package/dist/history/SharedHistoryManager.d.ts +96 -0
- package/dist/identity/ControlIdentityService.d.ts +48 -0
- package/dist/identity/PageBreakIdentityService.d.ts +29 -0
- package/dist/identity/VisibilityGroupIdentityService.d.ts +24 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +5326 -0
- package/dist/nodeViews/BaseControlNodeView.d.ts +82 -0
- package/dist/nodeViews/ControlClipboard.d.ts +10 -0
- package/dist/nodeViews/ControlInputAutosize.d.ts +2 -0
- package/dist/nodeViews/DropdownFieldNodeView.d.ts +57 -0
- package/dist/nodeViews/FieldNodeViews.d.ts +4 -0
- package/dist/nodeViews/PageBreakNodeView.d.ts +20 -0
- package/dist/nodeViews/StructuredFieldNodeView.d.ts +24 -0
- package/dist/plugins/ControlGapCursor.d.ts +21 -0
- package/dist/plugins/ControlSelectionLifecycle.d.ts +3 -0
- package/dist/plugins/ControlShortcuts.d.ts +40 -0
- package/dist/plugins/ControlTransactionMeta.d.ts +10 -0
- package/dist/plugins/NumberingPlugin.d.ts +15 -0
- package/dist/plugins/NumberingService.d.ts +29 -0
- package/dist/plugins/PasteSanitizer.d.ts +32 -0
- package/dist/registry/ReportFeatureRegistry.d.ts +16 -0
- package/dist/registry/builtinReportNodes.d.ts +19 -0
- package/dist/selection/SelectionManager.d.ts +18 -0
- package/dist/serializer/ReportSerializer.d.ts +57 -0
- package/dist/serializer/VisibilityGroupResolver.d.ts +20 -0
- package/dist/template/ReportTemplateEngine.d.ts +41 -0
- package/dist/types/index.d.ts +401 -0
- package/dist/utils/ReportErrorDispatcher.d.ts +13 -0
- package/dist/utils/controlAttrs.d.ts +10 -0
- package/dist/utils/controlTextSegments.d.ts +15 -0
- package/dist/utils/html.d.ts +33 -0
- package/dist/utils/reportDocument.d.ts +11 -0
- package/dist/utils/reportDocumentValidation.d.ts +16 -0
- package/package.json +37 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/** 报告编辑器 core facade,封装 Tiptap 实例和业务命令。 */
|
|
2
|
+
import { Editor } from '@tiptap/core';
|
|
3
|
+
import type { HtmlOutputMode, ReportControlAttrs, ReportControlSnapshot, ReportDocument, ReportEditorInstance, ReportEditorOptions, ReportPageBreakSnapshot, ReportPlainTextOptions, ReportTemplate, StructuredFieldValue } from '../types/index.js';
|
|
4
|
+
/** 将模板、序列化、选择、编号和控件身份服务组合成统一编辑器实例。 */
|
|
5
|
+
export declare class ReportEditorCore implements ReportEditorInstance {
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly editor;
|
|
8
|
+
private readonly registry;
|
|
9
|
+
private readonly errors;
|
|
10
|
+
private readonly serializer;
|
|
11
|
+
private readonly templateEngine;
|
|
12
|
+
private readonly selectionManager;
|
|
13
|
+
private readonly identity;
|
|
14
|
+
private readonly pageBreakIdentity;
|
|
15
|
+
private readonly pasteSanitizer;
|
|
16
|
+
private readonly numberingService;
|
|
17
|
+
private readonly editorId;
|
|
18
|
+
private readonly controlPlugins;
|
|
19
|
+
private readonly controlPluginContext;
|
|
20
|
+
private readonly documentVersion;
|
|
21
|
+
private controlSnapshots;
|
|
22
|
+
private controlSnapshotsDirty;
|
|
23
|
+
private currentOperationBatchId;
|
|
24
|
+
private initializing;
|
|
25
|
+
/** 初始化 Tiptap 编辑器并注入报告扩展和回调。 */
|
|
26
|
+
constructor(options?: ReportEditorOptions);
|
|
27
|
+
/** 返回底层 Tiptap editor,供高级集成场景直接调用。 */
|
|
28
|
+
getTiptapEditor(): Editor;
|
|
29
|
+
/** 将焦点移动到编辑器。 */
|
|
30
|
+
focus(): void;
|
|
31
|
+
/** 销毁底层编辑器实例并释放事件监听。 */
|
|
32
|
+
destroy(): void;
|
|
33
|
+
/** 执行当前编辑器的撤销命令。 */
|
|
34
|
+
undo(): boolean;
|
|
35
|
+
/** 执行当前编辑器的重做命令。 */
|
|
36
|
+
redo(): boolean;
|
|
37
|
+
/** 导出报告 JSON 文档。 */
|
|
38
|
+
getJSON(): ReportDocument;
|
|
39
|
+
/** 按指定模式导出报告 HTML。 */
|
|
40
|
+
getHTML(mode?: HtmlOutputMode): string;
|
|
41
|
+
/** 导出报告纯文本内容。 */
|
|
42
|
+
getPlainText(options?: ReportPlainTextOptions): string;
|
|
43
|
+
/** 用报告 JSON 或 HTML 字符串替换当前内容。 */
|
|
44
|
+
setContent(content: ReportDocument | string): void;
|
|
45
|
+
/** 清空当前内容并保留编辑器文档版本。 */
|
|
46
|
+
clearContent(): void;
|
|
47
|
+
/** 将模板替换为当前文档内容。 */
|
|
48
|
+
applyTemplate(template: ReportTemplate): boolean;
|
|
49
|
+
/** 将模板追加到当前选区之后,并在成功后把选区放到新增内容末端。 */
|
|
50
|
+
appendTemplate(template: ReportTemplate): boolean;
|
|
51
|
+
/** 插入已注册的结构化控件节点。 */
|
|
52
|
+
insertControl(nodeType: string, attrs: ReportControlAttrs): boolean;
|
|
53
|
+
/** 按 controlId 更新单个控件的属性。 */
|
|
54
|
+
updateControlAttrs(controlId: string, attrs: Partial<ReportControlAttrs>): boolean;
|
|
55
|
+
/** 返回编辑器实例 ID。 */
|
|
56
|
+
getEditorId(): string;
|
|
57
|
+
/** 返回当前文档中的结构化控件快照。 */
|
|
58
|
+
getControls(): ReportControlSnapshot[];
|
|
59
|
+
/** 按 controlId 返回结构化控件快照。 */
|
|
60
|
+
getControl(controlId: string): ReportControlSnapshot | undefined;
|
|
61
|
+
/** 按 controlId 更新单个控件的业务值。 */
|
|
62
|
+
updateControlValue(controlId: string, value: StructuredFieldValue): boolean;
|
|
63
|
+
/** 按 fieldName 批量更新所有同名控件的业务值。 */
|
|
64
|
+
updateControlValueByFieldName(fieldName: string, value: StructuredFieldValue): boolean;
|
|
65
|
+
/** 在当前有效编辑位置插入手动分页符。 */
|
|
66
|
+
insertPageBreak(): boolean;
|
|
67
|
+
/** 删除指定 ID 或当前选中的手动分页符。 */
|
|
68
|
+
deletePageBreak(id?: string): boolean;
|
|
69
|
+
/** 返回当前文档中的分页符 ID 和位置。 */
|
|
70
|
+
getPageBreaks(): ReportPageBreakSnapshot[];
|
|
71
|
+
/** 切换当前段落在预览和打印模式下的隐藏状态。 */
|
|
72
|
+
toggleHiddenParagraph(): boolean;
|
|
73
|
+
/** 明确设置当前段落隐藏状态。 */
|
|
74
|
+
setParagraphHidden(hidden: boolean): boolean;
|
|
75
|
+
/** 按编号块索引移动块并重新计算自动编号。 */
|
|
76
|
+
moveNumberedBlock(fromIndex: number, toIndex: number): boolean;
|
|
77
|
+
/** 切换编辑器可编辑状态。 */
|
|
78
|
+
setEditable(editable: boolean): void;
|
|
79
|
+
/** Tiptap transaction 后同步控件生命周期插件。 */
|
|
80
|
+
private readonly handleControlTransaction;
|
|
81
|
+
/** 创建插件上下文。 */
|
|
82
|
+
private createControlPluginContext;
|
|
83
|
+
/** 初始化插件并注册初始文档中的控件。 */
|
|
84
|
+
private initializeControlPlugins;
|
|
85
|
+
/** 销毁插件并反注册当前控件。 */
|
|
86
|
+
private destroyControlPlugins;
|
|
87
|
+
/** 对比当前文档和上次快照,派发控件生命周期变更。 */
|
|
88
|
+
private syncControlPlugins;
|
|
89
|
+
/** Updates snapshots for validated attrs-only transactions without rescanning the document. */
|
|
90
|
+
private syncChangedControlSnapshots;
|
|
91
|
+
/** Ensures public control snapshot reads observe the current document state. */
|
|
92
|
+
private ensureControlSnapshots;
|
|
93
|
+
/** Collects the structured control snapshots in the current document. */
|
|
94
|
+
private collectControlSnapshots;
|
|
95
|
+
/** 判断规则相关元数据是否发生变化。 */
|
|
96
|
+
private isSameControlMetadata;
|
|
97
|
+
/** 捕获插件异常,避免插件破坏编辑器事务。 */
|
|
98
|
+
private notifyControlPlugin;
|
|
99
|
+
/** 在一次编辑器操作内复用同一批次 ID。 */
|
|
100
|
+
private runWithOperationBatch;
|
|
101
|
+
/** Separates high-level content operations from adjacent local ProseMirror history events. */
|
|
102
|
+
private closeLocalHistoryEvent;
|
|
103
|
+
/** 从插件读取外层共享批次。 */
|
|
104
|
+
private getPluginBatchId;
|
|
105
|
+
/** 为当前操作创建批次号。 */
|
|
106
|
+
private createOperationBatchId;
|
|
107
|
+
/** 创建编辑器实例 ID。 */
|
|
108
|
+
private createEditorId;
|
|
109
|
+
/** 比较普通值或 JSON 兼容对象是否一致。 */
|
|
110
|
+
private isSameValue;
|
|
111
|
+
/** 解析初始化内容,优先使用显式 content,其次使用模板。 */
|
|
112
|
+
private resolveInitialContent;
|
|
113
|
+
/** 解析初始化内容,失败时降级为空文档。 */
|
|
114
|
+
private resolveInitialTiptapContent;
|
|
115
|
+
/** 将输入内容解析为严格校验后的 Tiptap JSON。 */
|
|
116
|
+
private resolveTiptapContent;
|
|
117
|
+
/** 归一化传入文档并修复控件实例 ID。 */
|
|
118
|
+
private normalizeContent;
|
|
119
|
+
/** 将 HTML 输入解析为报告文档,随后仍走统一文档校验。 */
|
|
120
|
+
private parseHTMLContent;
|
|
121
|
+
/** 将输入校验错误派发给业务方。 */
|
|
122
|
+
private reportContentError;
|
|
123
|
+
/** 初始化事务只更新最终文档,不得提前派发对外 change。 */
|
|
124
|
+
private handleEditorUpdate;
|
|
125
|
+
/** 向外派发同步后的 JSON、HTML 和 Tiptap 实例。 */
|
|
126
|
+
private emitChange;
|
|
127
|
+
/** 阻止只读状态下的变更命令。 */
|
|
128
|
+
private ensureEditable;
|
|
129
|
+
/** 调用节点描述符上的属性校验逻辑。 */
|
|
130
|
+
private validateControlAttrs;
|
|
131
|
+
/** 在文档树中按 controlId 查找控件并更新节点属性。 */
|
|
132
|
+
private updateNodeAttrsByControlId;
|
|
133
|
+
/** 在文档树中按 fieldName 查找控件并批量更新节点属性。 */
|
|
134
|
+
private updateNodeAttrsByFieldName;
|
|
135
|
+
/** Checks whether an attrs update preserves the identity invariants needed by the fast path. */
|
|
136
|
+
private isStableControlIdentity;
|
|
137
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
import type { DropdownFieldAttrs } from '../types/index.js';
|
|
3
|
+
import { type ReportControlShortcutRuntime } from '../plugins/ControlShortcuts.js';
|
|
4
|
+
declare module '@tiptap/core' {
|
|
5
|
+
interface Commands<ReturnType> {
|
|
6
|
+
dropdownField: {
|
|
7
|
+
insertDropdownField: (attrs: DropdownFieldAttrs) => ReturnType;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export type DropdownFieldNodeOptions = {
|
|
12
|
+
controlShortcutRuntime: ReportControlShortcutRuntime;
|
|
13
|
+
};
|
|
14
|
+
/** Tiptap 下拉控件节点定义。 */
|
|
15
|
+
export declare const DropdownFieldNode: Node<DropdownFieldNodeOptions, any>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
fontSize: {
|
|
5
|
+
setFontSize: (fontSize: string) => ReturnType;
|
|
6
|
+
unsetFontSize: () => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Tiptap 字号扩展,将 fontSize 挂到 textStyle mark。 */
|
|
11
|
+
export declare const FontSizeExtension: Extension<any, any>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
hiddenParagraph: {
|
|
5
|
+
toggleHiddenParagraph: () => ReturnType;
|
|
6
|
+
setParagraphHidden: (hidden: boolean) => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Tiptap 隐藏段落扩展,支持预览和打印时过滤段落。 */
|
|
11
|
+
export declare const HiddenParagraphExtension: Extension<any, any>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
indentation: {
|
|
5
|
+
increaseIndent: () => ReturnType;
|
|
6
|
+
decreaseIndent: () => ReturnType;
|
|
7
|
+
setIndent: (value: number) => ReturnType;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** 创建可配置目标节点的缩进扩展。 */
|
|
12
|
+
export declare function createIndentationExtension(targets?: string[]): Extension<any, any>;
|
|
13
|
+
export declare const IndentationExtension: Extension<any, any>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
lineHeight: {
|
|
5
|
+
setLineHeight: (value: string) => ReturnType;
|
|
6
|
+
unsetLineHeight: () => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** 创建可配置目标节点的行高扩展。 */
|
|
11
|
+
export declare function createLineHeightExtension(targets?: string[]): Extension<any, any>;
|
|
12
|
+
export declare const LineHeightExtension: Extension<any, any>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
pageBreak: {
|
|
5
|
+
insertPageBreak: () => ReturnType;
|
|
6
|
+
deletePageBreak: (id?: string) => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Tiptap 手动分页符节点。 */
|
|
11
|
+
export declare const PageBreakNode: Node<any, any>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
reportNumberedBlock: {
|
|
5
|
+
insertNumberedBlock: (text?: string) => ReturnType;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Tiptap 报告编号块节点定义。 */
|
|
10
|
+
export declare const ReportNumberedBlockNode: Node<any, any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
import type { StructuredFieldAttrs } from '../types/index.js';
|
|
3
|
+
import { type ReportControlShortcutRuntime } from '../plugins/ControlShortcuts.js';
|
|
4
|
+
declare module '@tiptap/core' {
|
|
5
|
+
interface Commands<ReturnType> {
|
|
6
|
+
structuredField: {
|
|
7
|
+
insertStructuredField: (attrs: StructuredFieldAttrs) => ReturnType;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export type StructuredFieldNodeOptions = {
|
|
12
|
+
controlShortcutRuntime: ReportControlShortcutRuntime;
|
|
13
|
+
};
|
|
14
|
+
/** Tiptap 结构化输入控件节点定义。 */
|
|
15
|
+
export declare const StructuredFieldNode: Node<StructuredFieldNodeOptions, any>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
textColor: {
|
|
5
|
+
setTextColor: (color: string) => ReturnType;
|
|
6
|
+
unsetTextColor: () => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Tiptap 文字颜色扩展,将 color 挂到 textStyle mark。 */
|
|
11
|
+
export declare const TextColorExtension: Extension<any, any>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Extensions } from '@tiptap/core';
|
|
2
|
+
import { DropdownFieldNode } from './DropdownFieldNode.js';
|
|
3
|
+
import { FontSizeExtension } from './FontSizeExtension.js';
|
|
4
|
+
import { HiddenParagraphExtension } from './HiddenParagraphExtension.js';
|
|
5
|
+
import { IndentationExtension } from './IndentationExtension.js';
|
|
6
|
+
import { LineHeightExtension } from './LineHeightExtension.js';
|
|
7
|
+
import { PageBreakNode } from './PageBreakNode.js';
|
|
8
|
+
import { ReportNumberedBlockNode } from './ReportNumberedBlockNode.js';
|
|
9
|
+
import { StructuredFieldNode } from './StructuredFieldNode.js';
|
|
10
|
+
import { VisibilityGroupMark } from './VisibilityGroupMark.js';
|
|
11
|
+
import { type InvalidControlAttrsHandler, type InvalidVisibilityGroupHandler } from '../plugins/PasteSanitizer.js';
|
|
12
|
+
import type { ReportEditorGroupManager } from '../group/ReportEditorGroupManager.js';
|
|
13
|
+
import type { ReportControlShortcutOptions, ReportFeatureRegistry } from '../types/index.js';
|
|
14
|
+
/** 根据 feature 注册表创建报告编辑器所需的 Tiptap 扩展集合。 */
|
|
15
|
+
export declare class ReportExtensionFactory {
|
|
16
|
+
private readonly registry;
|
|
17
|
+
private readonly controlShortcuts?;
|
|
18
|
+
private readonly editorGroup?;
|
|
19
|
+
private readonly getCurrentBatchId?;
|
|
20
|
+
private readonly onInvalidControlAttrs?;
|
|
21
|
+
private readonly onInvalidVisibilityGroup?;
|
|
22
|
+
/** 绑定 feature 注册表、快捷键配置和编辑器分组。 */
|
|
23
|
+
constructor(registry?: ReportFeatureRegistry, controlShortcuts?: ReportControlShortcutOptions | undefined, editorGroup?: ReportEditorGroupManager | undefined, getCurrentBatchId?: (() => string | undefined) | undefined, onInvalidControlAttrs?: InvalidControlAttrsHandler | undefined, onInvalidVisibilityGroup?: InvalidVisibilityGroupHandler | undefined);
|
|
24
|
+
/** 创建包含内置、业务扩展和运行时插件的扩展数组。 */
|
|
25
|
+
create(): Extensions;
|
|
26
|
+
/** 创建默认配置下的扩展数组。 */
|
|
27
|
+
createDefault(): Extensions;
|
|
28
|
+
}
|
|
29
|
+
export { DropdownFieldNode, FontSizeExtension, HiddenParagraphExtension, IndentationExtension, LineHeightExtension, PageBreakNode, ReportNumberedBlockNode, StructuredFieldNode, VisibilityGroupMark };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ReportEditorInstance } from '../types/index.js';
|
|
2
|
+
/** 编辑器分组中的单个注册项。 */
|
|
3
|
+
export type ReportEditorGroupEntry = {
|
|
4
|
+
editorId: string;
|
|
5
|
+
editor: ReportEditorInstance;
|
|
6
|
+
};
|
|
7
|
+
/** 编辑器分组状态变更 payload。 */
|
|
8
|
+
export type ReportEditorGroupChangePayload = {
|
|
9
|
+
editorIds: string[];
|
|
10
|
+
activeEditorId?: string;
|
|
11
|
+
};
|
|
12
|
+
/** 编辑器分组管理器配置。 */
|
|
13
|
+
export type ReportEditorGroupManagerOptions = {
|
|
14
|
+
onChange?: (payload: ReportEditorGroupChangePayload) => void;
|
|
15
|
+
};
|
|
16
|
+
/** 管理多个编辑器实例及当前活跃编辑器。 */
|
|
17
|
+
export declare class ReportEditorGroupManager {
|
|
18
|
+
private readonly options;
|
|
19
|
+
private readonly editors;
|
|
20
|
+
private activeEditorId;
|
|
21
|
+
/** 创建编辑器分组管理器。 */
|
|
22
|
+
constructor(options?: ReportEditorGroupManagerOptions);
|
|
23
|
+
/** 注册编辑器并将其设为活跃编辑器。 */
|
|
24
|
+
register(editorId: string, editor: ReportEditorInstance): void;
|
|
25
|
+
/** 注销编辑器并清理活跃状态。 */
|
|
26
|
+
unregister(editorId: string): void;
|
|
27
|
+
/** 判断指定编辑器是否已注册。 */
|
|
28
|
+
has(editorId: string): boolean;
|
|
29
|
+
/** 按 ID 获取编辑器实例。 */
|
|
30
|
+
get(editorId: string): ReportEditorInstance | undefined;
|
|
31
|
+
/** 返回所有注册编辑器条目。 */
|
|
32
|
+
entries(): ReportEditorGroupEntry[];
|
|
33
|
+
/** 返回所有注册编辑器 ID。 */
|
|
34
|
+
getEditorIds(): string[];
|
|
35
|
+
/** 返回所有编辑器根 DOM,用于限定快捷键导航范围。 */
|
|
36
|
+
getEditorElements(): HTMLElement[];
|
|
37
|
+
/** 设置当前活跃编辑器。 */
|
|
38
|
+
setActiveEditor(editorId: string): boolean;
|
|
39
|
+
/** 获取当前活跃编辑器 ID。 */
|
|
40
|
+
getActiveEditorId(): string | undefined;
|
|
41
|
+
/** 获取当前分组状态快照。 */
|
|
42
|
+
getState(): ReportEditorGroupChangePayload;
|
|
43
|
+
/** 派发分组状态变化。 */
|
|
44
|
+
private emitChange;
|
|
45
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ReportEditorInstance, SharedHistoryChangePayload, SharedHistoryEntry, SharedHistoryManagerOptions } from '../types/index.js';
|
|
2
|
+
import { ReportEditorGroupManager } from '../group/ReportEditorGroupManager.js';
|
|
3
|
+
type SharedHistoryEntryInput = Omit<SharedHistoryEntry, 'timestamp'> & {
|
|
4
|
+
timestamp?: number;
|
|
5
|
+
};
|
|
6
|
+
type SynchronousResult<T> = T extends PromiseLike<unknown> ? never : T;
|
|
7
|
+
/** Maintains shared undo/redo history across multiple editors. */
|
|
8
|
+
export declare class SharedHistoryManager {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private static readonly DEFAULT_MAX_DEPTH;
|
|
11
|
+
private static readonly MAX_DEPTH_LIMIT;
|
|
12
|
+
private readonly editorGroup;
|
|
13
|
+
private readonly registeredEditors;
|
|
14
|
+
private readonly undoStack;
|
|
15
|
+
private readonly redoStack;
|
|
16
|
+
private readonly maxDepth;
|
|
17
|
+
private isCaptureSuppressed;
|
|
18
|
+
private readonly pendingCaptureEditorIds;
|
|
19
|
+
private pendingCaptureActiveEditorIdBefore?;
|
|
20
|
+
private pendingCaptureScheduled;
|
|
21
|
+
private pendingCaptureToken;
|
|
22
|
+
/** Creates a shared history manager and initializes its editor group. */
|
|
23
|
+
constructor(options?: SharedHistoryManagerOptions);
|
|
24
|
+
/** Registers an editor and stores its initial document snapshot. */
|
|
25
|
+
register(editorId: string, editor: ReportEditorInstance): void;
|
|
26
|
+
/** Unregisters an editor and removes its history entries. */
|
|
27
|
+
unregister(editorId: string): void;
|
|
28
|
+
/** Sets the active editor for shared history operations. */
|
|
29
|
+
setActiveEditor(editorId: string): boolean;
|
|
30
|
+
/** Returns the editor group used by shared history. */
|
|
31
|
+
getEditorGroup(): ReportEditorGroupManager;
|
|
32
|
+
/** Binds editor events so content changes are captured automatically. */
|
|
33
|
+
track(editorId: string, editor: ReportEditorInstance): () => void;
|
|
34
|
+
/** Captures the current content change for one registered editor. */
|
|
35
|
+
capture(editorId: string, label?: string): boolean;
|
|
36
|
+
/** Wraps one editor operation and records one shared history item. */
|
|
37
|
+
run<T>(editorId: string, operation: () => SynchronousResult<T>, label?: string): boolean;
|
|
38
|
+
/** Wraps a multi-editor operation and records it as one undo/redo item. */
|
|
39
|
+
runBatch<T>(editorIds: Iterable<string>, operation: () => SynchronousResult<T>, label?: string): boolean;
|
|
40
|
+
/** Manually records a single-editor shared history entry. */
|
|
41
|
+
record(entry: SharedHistoryEntryInput): boolean;
|
|
42
|
+
/** Undoes the latest shared history item. */
|
|
43
|
+
undo(): boolean;
|
|
44
|
+
/** Redoes the latest undone shared history item. */
|
|
45
|
+
redo(): boolean;
|
|
46
|
+
/** Clears all history or only the entries associated with one editor. */
|
|
47
|
+
clear(editorId?: string): void;
|
|
48
|
+
/** Returns whether undo is currently available. */
|
|
49
|
+
canUndo(): boolean;
|
|
50
|
+
/** Returns whether redo is currently available. */
|
|
51
|
+
canRedo(): boolean;
|
|
52
|
+
/** Returns the undo stack depth. */
|
|
53
|
+
getUndoDepth(): number;
|
|
54
|
+
/** Returns the redo stack depth. */
|
|
55
|
+
getRedoDepth(): number;
|
|
56
|
+
/** Returns the current active editor ID. */
|
|
57
|
+
getActiveEditorId(): string | undefined;
|
|
58
|
+
/** Returns a snapshot of shared history state. */
|
|
59
|
+
getState(): SharedHistoryChangePayload;
|
|
60
|
+
/** Coalesces synchronous tracked updates, including cross-editor plugin effects, into one history item. */
|
|
61
|
+
private queueCapture;
|
|
62
|
+
/** Flushes one event-loop turn of automatically tracked editor updates. */
|
|
63
|
+
private flushPendingCaptures;
|
|
64
|
+
/** Captures the current snapshot of every registered editor. */
|
|
65
|
+
private snapshotAllRegisteredEditors;
|
|
66
|
+
/** Builds changed entries and synchronizes every registered last snapshot after an operation. */
|
|
67
|
+
private collectChangedEntries;
|
|
68
|
+
/** Stores a single changed editor directly or promotes synchronous multi-editor effects to a batch. */
|
|
69
|
+
private pushOperationEntries;
|
|
70
|
+
private pushSingleEntry;
|
|
71
|
+
private pushBatchEntry;
|
|
72
|
+
private restore;
|
|
73
|
+
private restoreSingle;
|
|
74
|
+
private restoreBatch;
|
|
75
|
+
/** Notifies consumers only after documents and history stacks are fully committed. */
|
|
76
|
+
private notifyRestore;
|
|
77
|
+
private collectRegisteredTargets;
|
|
78
|
+
private setActiveEditorIfAvailable;
|
|
79
|
+
private removeEntriesForEditor;
|
|
80
|
+
private removeFromStack;
|
|
81
|
+
private trimStack;
|
|
82
|
+
private emitChange;
|
|
83
|
+
private createStatePayload;
|
|
84
|
+
/** Checks whether the latest automatically flushed item already contains a manual record. */
|
|
85
|
+
private latestEntryMatches;
|
|
86
|
+
/** Makes the next tracked update start from the editor's actual current document. */
|
|
87
|
+
private synchronizeRegisteredSnapshot;
|
|
88
|
+
/** Synchronizes snapshots for editors changed synchronously as a side effect of a restore. */
|
|
89
|
+
private synchronizeRegisteredSnapshots;
|
|
90
|
+
private snapshotFromEditor;
|
|
91
|
+
private createSnapshot;
|
|
92
|
+
private cloneSnapshotDocument;
|
|
93
|
+
private isSameSnapshot;
|
|
94
|
+
private toPublicEntry;
|
|
95
|
+
}
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Slice, type Node as ProseMirrorNode } from '@tiptap/pm/model';
|
|
2
|
+
import type { ReportControlAttrs, ReportDocument, ReportFeatureRegistry } from '../types/index.js';
|
|
3
|
+
/** 控件身份修复时需要写回的位置和新 ID。 */
|
|
4
|
+
export type ControlIdentityUpdate = {
|
|
5
|
+
pos: number;
|
|
6
|
+
controlId: string;
|
|
7
|
+
batchId: string;
|
|
8
|
+
};
|
|
9
|
+
/** 控件身份服务,确保每个控件实例都有唯一 controlId。 */
|
|
10
|
+
export declare class ControlIdentityService {
|
|
11
|
+
private readonly registry;
|
|
12
|
+
/** 绑定 feature 注册表以识别控件节点。 */
|
|
13
|
+
constructor(registry?: ReportFeatureRegistry);
|
|
14
|
+
/** 创建不与已有集合冲突的新 controlId。 */
|
|
15
|
+
createId(existing?: Set<string>): string;
|
|
16
|
+
/** 创建新的控件批次 ID。 */
|
|
17
|
+
createBatchId(): string;
|
|
18
|
+
/** 为控件 attrs 写入新的 controlId,并在缺失时补齐 batchId。 */
|
|
19
|
+
withFreshControlId<TAttrs extends ReportControlAttrs>(attrs: TAttrs, existing?: Set<string>, batchId?: string): TAttrs;
|
|
20
|
+
/** 归一化报告文档中的缺失或重复 controlId,并补齐 batchId。 */
|
|
21
|
+
normalizeDocument(document: ReportDocument, batchId?: string): ReportDocument;
|
|
22
|
+
/** 收集报告文档中已有的控件 ID。 */
|
|
23
|
+
collectIds(document: ReportDocument): Set<string>;
|
|
24
|
+
/** 收集 ProseMirror 文档中需要修复 controlId 或 batchId 的节点。 */
|
|
25
|
+
collectTransactionUpdates(doc: ProseMirrorNode, batchId?: string): ControlIdentityUpdate[];
|
|
26
|
+
/** 为粘贴 slice 中的控件重新分配 controlId 和批次 ID。 */
|
|
27
|
+
assignFreshControlIdsToSlice(slice: Slice, batchId?: string): Slice;
|
|
28
|
+
/** 递归处理 fragment 中的子节点。 */
|
|
29
|
+
private assignFreshControlIdsToFragment;
|
|
30
|
+
/** 为单个 ProseMirror 节点及其子树刷新控件 ID。 */
|
|
31
|
+
private assignFreshControlIdsToNode;
|
|
32
|
+
/** 递归归一化报告节点数组。 */
|
|
33
|
+
private normalizeReportNodes;
|
|
34
|
+
/** 归一化单个报告节点的 controlId 和 batchId。 */
|
|
35
|
+
private normalizeReportNode;
|
|
36
|
+
/** 深度优先遍历报告节点。 */
|
|
37
|
+
private visitReportNodes;
|
|
38
|
+
/** 判断节点类型是否为控件。 */
|
|
39
|
+
private isControlNode;
|
|
40
|
+
/** 从 attrs 中读取非空 controlId。 */
|
|
41
|
+
private getControlId;
|
|
42
|
+
/** 从 attrs 中读取非空 batchId。 */
|
|
43
|
+
private getBatchId;
|
|
44
|
+
/** 保留已有 batchId,缺失时使用传入批次或新批次。 */
|
|
45
|
+
private resolveBatchId;
|
|
46
|
+
/** 生成原始 controlId 字符串。 */
|
|
47
|
+
private createRawId;
|
|
48
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/core';
|
|
2
|
+
import { Slice, type Node as ProseMirrorNode } from '@tiptap/pm/model';
|
|
3
|
+
import type { ReportDocument } from '../types/index.js';
|
|
4
|
+
export declare const PAGE_BREAK_NODE_NAME = "pageBreak";
|
|
5
|
+
export type PageBreakIdentityUpdate = {
|
|
6
|
+
pos: number;
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
9
|
+
/** 创建分页符唯一 ID。 */
|
|
10
|
+
export declare function createPageBreakId(existing?: Set<string>): string;
|
|
11
|
+
/** 维护分页符 ID,确保加载、粘贴和直接事务后的文档仍可稳定定位。 */
|
|
12
|
+
export declare class PageBreakIdentityService {
|
|
13
|
+
/** 归一化报告 JSON 中缺失或重复的分页符 ID。 */
|
|
14
|
+
normalizeDocument(document: ReportDocument): ReportDocument;
|
|
15
|
+
/** 收集 ProseMirror 文档中需要修复的分页符。 */
|
|
16
|
+
collectTransactionUpdates(doc: ProseMirrorNode): PageBreakIdentityUpdate[];
|
|
17
|
+
/** 为粘贴或复制式拖拽进入文档的分页符分配新 ID。 */
|
|
18
|
+
assignFreshIdsToSlice(slice: Slice): Slice;
|
|
19
|
+
/** 修复已创建编辑器中的分页符 ID,不写入撤销历史。 */
|
|
20
|
+
applyToEditor(editor: Editor): boolean;
|
|
21
|
+
/** 递归归一化报告节点。 */
|
|
22
|
+
private normalizeReportNodes;
|
|
23
|
+
/** 递归刷新 fragment 中的分页符 ID。 */
|
|
24
|
+
private assignFreshIdsToFragment;
|
|
25
|
+
/** 刷新单个节点及其子树中的分页符 ID。 */
|
|
26
|
+
private assignFreshIdsToNode;
|
|
27
|
+
/** 从 attrs 中读取可用 ID。 */
|
|
28
|
+
private getId;
|
|
29
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Slice, type Mark } from '@tiptap/pm/model';
|
|
2
|
+
export declare const VISIBILITY_GROUP_MARK_NAME = "visibilityGroup";
|
|
3
|
+
export declare const DEFAULT_VISIBILITY_GROUP_CONDITION = "all-controls-empty";
|
|
4
|
+
/** 校验运行时 visibilityGroup mark 的必要身份和唯一受支持条件。 */
|
|
5
|
+
export declare function assertVisibilityGroupMarkAttrs(attrs: Record<string, unknown>): void;
|
|
6
|
+
/** 为一次模板展开、粘贴或复制式拖拽创建新的分组身份。 */
|
|
7
|
+
export declare function createVisibilityGroupId(): string;
|
|
8
|
+
/**
|
|
9
|
+
* 维护 visibilityGroup 的复制身份。
|
|
10
|
+
*
|
|
11
|
+
* 普通加载、移动和历史事务不经过本服务,因而保留原 ID;只有复制语义显式调用
|
|
12
|
+
* assignFreshIdsToSlice,并在同一个 slice 内按“旧 ID → 新 ID”映射。
|
|
13
|
+
*/
|
|
14
|
+
export declare class VisibilityGroupIdentityService {
|
|
15
|
+
/** 刷新 slice 中的所有分组 ID,同时保留副本内部原有的分组关系。 */
|
|
16
|
+
assignFreshIdsToSlice(slice: Slice): Slice;
|
|
17
|
+
/** 从 slice 中移除指定分组;省略 IDs 时移除全部 visibilityGroup mark。 */
|
|
18
|
+
removeMarksFromSlice(slice: Slice, groupIds?: ReadonlySet<string>): Slice;
|
|
19
|
+
/** 移除 mark 数组中的 visibilityGroup,同时保留 bold/textStyle 等格式 mark。 */
|
|
20
|
+
static withoutVisibilityGroupMarks(marks: readonly Mark[]): Mark[];
|
|
21
|
+
private refreshMarks;
|
|
22
|
+
private mapFragment;
|
|
23
|
+
private mapNode;
|
|
24
|
+
}
|