@web-ppt/edit-core 0.5.0-beta.1
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/CHANGELOG.md +274 -0
- package/LICENSE +21 -0
- package/README.md +474 -0
- package/dist/animation-catalog.d.ts +21 -0
- package/dist/body-properties.d.ts +8 -0
- package/dist/body-property-schema.d.ts +3 -0
- package/dist/change-classification.d.ts +10 -0
- package/dist/clipboard-binary.d.ts +4 -0
- package/dist/clipboard-links.d.ts +11 -0
- package/dist/clipboard-source.d.ts +23 -0
- package/dist/clipboard.d.ts +4 -0
- package/dist/commands/add-image.d.ts +4 -0
- package/dist/commands/add-shape.d.ts +4 -0
- package/dist/commands/add-slide-identity.d.ts +8 -0
- package/dist/commands/add-slide-template.d.ts +9 -0
- package/dist/commands/add-slide.d.ts +3 -0
- package/dist/commands/add-table.d.ts +4 -0
- package/dist/commands/align-elements.d.ts +4 -0
- package/dist/commands/apply-format.d.ts +4 -0
- package/dist/commands/clipboard-types.d.ts +91 -0
- package/dist/commands/direct-format-patches.d.ts +8 -0
- package/dist/commands/dispatch.d.ts +7 -0
- package/dist/commands/duplicate-slide.d.ts +3 -0
- package/dist/commands/edit-text.d.ts +3 -0
- package/dist/commands/element-effects.d.ts +5 -0
- package/dist/commands/element-fill.d.ts +5 -0
- package/dist/commands/element-image-content.d.ts +17 -0
- package/dist/commands/element-interaction.d.ts +11 -0
- package/dist/commands/element-link.d.ts +5 -0
- package/dist/commands/element-name.d.ts +8 -0
- package/dist/commands/element-order.d.ts +7 -0
- package/dist/commands/element-stroke.d.ts +5 -0
- package/dist/commands/element-text.d.ts +6 -0
- package/dist/commands/element-transform.d.ts +5 -0
- package/dist/commands/element-tree.d.ts +8 -0
- package/dist/commands/fit-text-shape.d.ts +3 -0
- package/dist/commands/format-painter-types.d.ts +17 -0
- package/dist/commands/image-format.d.ts +7 -0
- package/dist/commands/image-resource.d.ts +4 -0
- package/dist/commands/insert-row.d.ts +3 -0
- package/dist/commands/insertion-rect.d.ts +9 -0
- package/dist/commands/paste-elements.d.ts +4 -0
- package/dist/commands/paste-resources.d.ts +18 -0
- package/dist/commands/patch.d.ts +6 -0
- package/dist/commands/remove-slide.d.ts +3 -0
- package/dist/commands/replace-image.d.ts +3 -0
- package/dist/commands/replace-text.d.ts +5 -0
- package/dist/commands/set-animations.d.ts +3 -0
- package/dist/commands/set-body-props.d.ts +3 -0
- package/dist/commands/set-crop.d.ts +3 -0
- package/dist/commands/set-effects.d.ts +3 -0
- package/dist/commands/set-fill.d.ts +3 -0
- package/dist/commands/set-flip.d.ts +4 -0
- package/dist/commands/set-link.d.ts +3 -0
- package/dist/commands/set-para-props.d.ts +3 -0
- package/dist/commands/set-run-props.d.ts +3 -0
- package/dist/commands/set-slide-properties.d.ts +7 -0
- package/dist/commands/set-stroke.d.ts +3 -0
- package/dist/commands/set-xfrm.d.ts +3 -0
- package/dist/commands/set-z.d.ts +5 -0
- package/dist/commands/slide-image.d.ts +4 -0
- package/dist/commands/slide-layout.d.ts +8 -0
- package/dist/commands/slide-notes.d.ts +8 -0
- package/dist/commands/slide-order.d.ts +7 -0
- package/dist/commands/slide-property-types.d.ts +135 -0
- package/dist/commands/slide-property.d.ts +20 -0
- package/dist/commands/slide-tree.d.ts +6 -0
- package/dist/commands/spid.d.ts +4 -0
- package/dist/commands/table-row.d.ts +5 -0
- package/dist/commands/text-target.d.ts +25 -0
- package/dist/commands/types.d.ts +509 -0
- package/dist/commands/xfrm.d.ts +8 -0
- package/dist/data-validation.d.ts +7 -0
- package/dist/document.d.ts +17 -0
- package/dist/dynamic-slide-fields.d.ts +6 -0
- package/dist/edit-core.js +5321 -0
- package/dist/editor.d.ts +38 -0
- package/dist/element-ancestry.d.ts +3 -0
- package/dist/element-name.d.ts +4 -0
- package/dist/element-order.d.ts +7 -0
- package/dist/field-text.d.ts +3 -0
- package/dist/fractional-index.d.ts +10 -0
- package/dist/history.d.ts +50 -0
- package/dist/hyperlink.d.ts +10 -0
- package/dist/image-content.d.ts +7 -0
- package/dist/image-resource-history.d.ts +6 -0
- package/dist/index-D4ZTaYOa.js +706 -0
- package/dist/index.d.ts +46 -0
- package/dist/insertion-DabLme_U.js +5471 -0
- package/dist/insertion-invariants.d.ts +5 -0
- package/dist/layout-assets.d.ts +10 -0
- package/dist/layout-projection.d.ts +24 -0
- package/dist/layout-text-rebase.d.ts +3 -0
- package/dist/model-invariants.d.ts +5 -0
- package/dist/notes-part.d.ts +2 -0
- package/dist/opc/bytes.d.ts +1 -0
- package/dist/opc/crc32.d.ts +1 -0
- package/dist/opc/index.d.ts +3 -0
- package/dist/opc/package-owner.d.ts +4 -0
- package/dist/opc/patch.d.ts +6 -0
- package/dist/opc/types.d.ts +12 -0
- package/dist/opc/zip.d.ts +28 -0
- package/dist/opc-owner-protocol.d.ts +5 -0
- package/dist/opc.js +5 -0
- package/dist/paragraph-properties.d.ts +4 -0
- package/dist/paragraph-property-schema.d.ts +4 -0
- package/dist/patch-DO8497wO.js +322 -0
- package/dist/projection.d.ts +19 -0
- package/dist/recovery-identity.d.ts +35 -0
- package/dist/recovery-types.d.ts +30 -0
- package/dist/recovery.d.ts +28 -0
- package/dist/run-links.d.ts +3 -0
- package/dist/run-properties.d.ts +4 -0
- package/dist/run-property-schema.d.ts +3 -0
- package/dist/save/animation.d.ts +6 -0
- package/dist/save/background-image.d.ts +8 -0
- package/dist/save/clipboard-parts.d.ts +11 -0
- package/dist/save/drawing-color.d.ts +2 -0
- package/dist/save/duplicate-slide-parts.d.ts +15 -0
- package/dist/save/effects.d.ts +6 -0
- package/dist/save/hyperlink.d.ts +18 -0
- package/dist/save/image-content.d.ts +4 -0
- package/dist/save/index.d.ts +5 -0
- package/dist/save/insertion.d.ts +14 -0
- package/dist/save/layout-fallback-source.d.ts +4 -0
- package/dist/save/layout-fallback.d.ts +7 -0
- package/dist/save/materialize.d.ts +5 -0
- package/dist/save/name.d.ts +5 -0
- package/dist/save/notes.d.ts +12 -0
- package/dist/save/order.d.ts +5 -0
- package/dist/save/remove-element.d.ts +4 -0
- package/dist/save/remove-slide-parts.d.ts +11 -0
- package/dist/save/shape-format.d.ts +14 -0
- package/dist/save/slide-parts.d.ts +11 -0
- package/dist/save/slide-properties.d.ts +4 -0
- package/dist/save/table.d.ts +7 -0
- package/dist/save/text-body.d.ts +4 -0
- package/dist/save/text.d.ts +6 -0
- package/dist/save/transition.d.ts +4 -0
- package/dist/save/xfrm.d.ts +22 -0
- package/dist/save/xml-element.d.ts +3 -0
- package/dist/save.js +1559 -0
- package/dist/selection-pane.d.ts +18 -0
- package/dist/selection.d.ts +11 -0
- package/dist/session-assets.d.ts +20 -0
- package/dist/shape-effects.d.ts +6 -0
- package/dist/shape-fill.d.ts +12 -0
- package/dist/shape-stroke.d.ts +9 -0
- package/dist/slide-animation.d.ts +15 -0
- package/dist/slide-background-source.d.ts +13 -0
- package/dist/slide-notes.d.ts +2 -0
- package/dist/slide-properties.d.ts +4 -0
- package/dist/slide-transition.d.ts +19 -0
- package/dist/space.d.ts +47 -0
- package/dist/table-cell.d.ts +10 -0
- package/dist/table-direct-markup.d.ts +3 -0
- package/dist/table-insertion-policy.d.ts +5 -0
- package/dist/table-row-append-validation.d.ts +3 -0
- package/dist/table-rows.d.ts +12 -0
- package/dist/text-model.d.ts +28 -0
- package/dist/text-override-projection.d.ts +8 -0
- package/dist/text-override-validation.d.ts +7 -0
- package/dist/text-position.d.ts +8 -0
- package/dist/text-search-types.d.ts +46 -0
- package/dist/text-search.d.ts +5 -0
- package/dist/transaction-validation.d.ts +5 -0
- package/dist/types.d.ts +519 -0
- package/dist/xml/index.d.ts +9 -0
- package/dist/xml/mutate.d.ts +7 -0
- package/dist/xml/namespace.d.ts +5 -0
- package/dist/xml/nodes.d.ts +22 -0
- package/dist/xml/order.d.ts +15 -0
- package/dist/xml/qname.d.ts +15 -0
- package/dist/xml/query.d.ts +10 -0
- package/dist/xml/state.d.ts +30 -0
- package/dist/xml/tree.d.ts +8 -0
- package/dist/xml/types.d.ts +46 -0
- package/dist/xml.js +19 -0
- package/package.json +67 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EditDoc, ElementRecord } from './types';
|
|
2
|
+
/** 结构 Patch 是公开 JSON seam;内嵌 OOXML 闭包不能依赖命令曾经正确地产生过它。 */
|
|
3
|
+
export declare function assertElementInsertionSource(doc: EditDoc, record: ElementRecord): void;
|
|
4
|
+
/** 每个宿主 part 只建一次索引,避免多图片页面的全局模型校验退化成 O(n²)。 */
|
|
5
|
+
export declare function assertActiveRelationshipTargets(doc: EditDoc): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Slide } from '@web-ppt/core';
|
|
2
|
+
import type { EditDoc } from './types';
|
|
3
|
+
interface LayoutAsset {
|
|
4
|
+
readonly mime: string;
|
|
5
|
+
readonly data: Uint8Array;
|
|
6
|
+
}
|
|
7
|
+
/** 只兑现 Schema 的资源槽;普通字符串即使形似内部 token 也必须逐字保留。 */
|
|
8
|
+
export declare function hydrateLayoutSlideAssets(doc: EditDoc, slide: Slide, assets: readonly LayoutAsset[]): Slide;
|
|
9
|
+
export declare function releaseLayoutAssetCache(doc: EditDoc): void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { GeomSpec, ShapeCreationDefaults, Slide, SlideElement, TableCreationDefaults, TextBody } from '@web-ppt/core';
|
|
2
|
+
import type { EditDoc, ElementId, SlideId } from './types';
|
|
3
|
+
export declare function resolvedLayoutSlide(doc: EditDoc, slideId: SlideId): Slide | null;
|
|
4
|
+
export declare function releaseLayoutProjectionCache(doc: EditDoc): void;
|
|
5
|
+
export declare function changedLayout(doc: EditDoc, slideId: SlideId): import("@web-ppt/core").SlideLayoutTemplate | undefined;
|
|
6
|
+
export declare function currentShapeDefaults(doc: EditDoc, slideId: SlideId): ShapeCreationDefaults | undefined;
|
|
7
|
+
export declare function currentTableDefaults(doc: EditDoc, slideId: SlideId): TableCreationDefaults | undefined;
|
|
8
|
+
/** 页面级 showMasterSp=false 必须继续压过新关系指向的版式/母版。 */
|
|
9
|
+
export declare function projectedLayoutElements(doc: EditDoc, slideId: SlideId): SlideElement[];
|
|
10
|
+
export declare function projectionContentIds(doc: EditDoc, slideId: SlideId): ElementId[];
|
|
11
|
+
/** 目标没有宿主且来源变换本来只靠旧版式继承时,保存必须把有效 frame 降级为页面直设。 */
|
|
12
|
+
export declare function layoutFallbackElementIds(doc: EditDoc, slideId: SlideId): ElementId[];
|
|
13
|
+
/** 预设几何可由语义重建;继承 custGeom 由保存层从来源版式逐节点复制。 */
|
|
14
|
+
export declare function layoutFallbackGeometry(record: EditDoc['elements'][string]): GeomSpec | undefined;
|
|
15
|
+
/** 整页 SVG 可混入没有 EditDoc 身份的目标版式静态节点;DOM 绑定按同一投影序列跳过它们。 */
|
|
16
|
+
export declare function projectedSlideElementIds(doc: EditDoc, slideId: SlideId): Array<ElementId | null>;
|
|
17
|
+
/** 尚无 slide 内容节点的目标占位符只供 edit interaction layer 提示,不进入业务渲染。 */
|
|
18
|
+
export declare function unboundLayoutPlaceholders(doc: EditDoc, slideId: SlideId): SlideElement[];
|
|
19
|
+
export declare function rebasedElementBase(doc: EditDoc, slideId: SlideId, record: EditDoc['elements'][string]): {
|
|
20
|
+
base: SlideElement;
|
|
21
|
+
geom?: GeomSpec;
|
|
22
|
+
};
|
|
23
|
+
/** 文字命令从当前版式的重基值起步,不能把旧版式有效值烘进首次覆盖。 */
|
|
24
|
+
export declare function rebasedTextBase(doc: EditDoc, slideId: SlideId, id: ElementId): TextBody | null;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EditDoc, ElementId } from './types';
|
|
2
|
+
/** 全局模型已在 Editor 构造时验证;事务只需重验其 patch 能影响的元素不变量。 */
|
|
3
|
+
export declare function validateEditElements(doc: EditDoc, ids: Iterable<ElementId>): void;
|
|
4
|
+
/** 在编辑会话入口验证全局结构;命令提交只需验证自己可能改变的局部不变量。 */
|
|
5
|
+
export declare function validateEditDoc(doc: EditDoc): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function equalBytes(left: Uint8Array, right: Uint8Array): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function crc32(bytes: Uint8Array): number;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { OpcPackage } from '@web-ppt/core';
|
|
2
|
+
/** 返回可释放、但仍能 structuredClone 的纯数据句柄。 */
|
|
3
|
+
export declare function createOwnedPackage(bytes: Uint8Array, parts: Readonly<Record<string, Uint8Array>>, assets?: OpcPackage['assets']): OpcPackage;
|
|
4
|
+
export declare function releaseOwnedPackage(pkg: OpcPackage): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { OpcPackage } from '@web-ppt/core';
|
|
2
|
+
import type { OpcPartChanges, OpcPatchResult } from './types';
|
|
3
|
+
/** 释放脱离 EditDoc 单独持有的保存结果;原始解析包仍由 Presentation.dispose() 释放。 */
|
|
4
|
+
export declare function disposeOpcPackage(pkg: OpcPackage): void;
|
|
5
|
+
/** 在原 OPC 包上应用 part 级修改;空修改必须保持整包字节身份。 */
|
|
6
|
+
export declare function patchOpcPackage(source: OpcPackage, changes: OpcPartChanges): OpcPatchResult;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OpcPackage } from '@web-ppt/core';
|
|
2
|
+
export type OpcPartChanges = Readonly<Record<string, Uint8Array | null>>;
|
|
3
|
+
export type OpcSaveMode = 'identity' | 'passthrough' | 'repacked';
|
|
4
|
+
export type OpcFallbackReason = 'archive-comment' | 'data-descriptor' | 'encrypted-entry' | 'legacy-filename' | 'multi-disk' | 'unsupported-compression' | 'zip64';
|
|
5
|
+
export interface OpcPatchResult {
|
|
6
|
+
readonly bytes: Uint8Array;
|
|
7
|
+
readonly package: OpcPackage;
|
|
8
|
+
readonly mode: OpcSaveMode;
|
|
9
|
+
readonly fallbackReason: OpcFallbackReason | null;
|
|
10
|
+
readonly preservedEntries: number;
|
|
11
|
+
readonly rewrittenEntries: number;
|
|
12
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { OpcFallbackReason } from './types';
|
|
2
|
+
export interface ZipEntry {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly flags: number;
|
|
5
|
+
readonly method: number;
|
|
6
|
+
readonly compressedSize: number;
|
|
7
|
+
readonly uncompressedSize: number;
|
|
8
|
+
readonly localOffset: number;
|
|
9
|
+
readonly localRaw: Uint8Array;
|
|
10
|
+
readonly centralRaw: Uint8Array;
|
|
11
|
+
}
|
|
12
|
+
export interface ZipArchive {
|
|
13
|
+
readonly entries: readonly ZipEntry[];
|
|
14
|
+
}
|
|
15
|
+
export interface RewrittenZip {
|
|
16
|
+
readonly bytes: Uint8Array;
|
|
17
|
+
readonly preservedEntries: number;
|
|
18
|
+
readonly rewrittenEntries: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class ZipPassthroughUnsupported extends Error {
|
|
21
|
+
readonly reason: OpcFallbackReason;
|
|
22
|
+
constructor(reason: OpcFallbackReason, message: string);
|
|
23
|
+
}
|
|
24
|
+
/** 读取标准单磁盘中央目录;不支持的特性后续由上层选择整包重压。 */
|
|
25
|
+
export declare function parseZipArchive(bytes: Uint8Array): ZipArchive;
|
|
26
|
+
export declare function rewriteZipArchive(archive: ZipArchive, changes: ReadonlyMap<string, Uint8Array | null>): RewrittenZip;
|
|
27
|
+
/** 不支持直通时从已解压 part 确定性重建;不复用任何可能含不兼容语义的 ZIP 元数据。 */
|
|
28
|
+
export declare function repackZipParts(parts: Readonly<Record<string, Uint8Array>>, changes: ReadonlyMap<string, Uint8Array | null>): RewrittenZip;
|
package/dist/opc.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TextRange } from './commands/types';
|
|
2
|
+
import type { EditDoc, ParagraphPropertiesState, TableCellAddress } from './types';
|
|
3
|
+
/** 工具栏只查询 headless 文档;DOM 选区只是把范围传进来。 */
|
|
4
|
+
export declare function queryParaProps(doc: EditDoc, id: string, range: TextRange, cell?: TableCellAddress): ParagraphPropertiesState;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ParagraphPropertyOverrides } from './types';
|
|
2
|
+
export declare const PARAGRAPH_PROPERTY_FIELDS: readonly ["align", "lineHeight", "spaceBefore", "spaceAfter", "marginLeft", "indent"];
|
|
3
|
+
export declare const PARAGRAPH_ALIGNMENTS: readonly ["left", "center", "right", "justify"];
|
|
4
|
+
export declare function assertParagraphPropertyOverrides(value: ParagraphPropertyOverrides, label: string): void;
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { deflateSync as j } from "fflate";
|
|
2
|
+
function N(t, n) {
|
|
3
|
+
return t.length === n.length && t.every((e, r) => e === n[r]);
|
|
4
|
+
}
|
|
5
|
+
const q = new Uint8Array(), X = Object.freeze(/* @__PURE__ */ Object.create(null)), y = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
6
|
+
function H(t, n, e = y) {
|
|
7
|
+
let r = t, o = n, s = e, i = !1;
|
|
8
|
+
const a = {
|
|
9
|
+
format: "pptx",
|
|
10
|
+
get bytes() {
|
|
11
|
+
return r;
|
|
12
|
+
},
|
|
13
|
+
get parts() {
|
|
14
|
+
return o;
|
|
15
|
+
},
|
|
16
|
+
get assets() {
|
|
17
|
+
return s;
|
|
18
|
+
},
|
|
19
|
+
get disposed() {
|
|
20
|
+
return i;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
return Object.defineProperty(a, "dispose", {
|
|
24
|
+
value: () => {
|
|
25
|
+
r = q, o = X, s = y, i = !0;
|
|
26
|
+
}
|
|
27
|
+
}), Object.freeze(a);
|
|
28
|
+
}
|
|
29
|
+
function J(t) {
|
|
30
|
+
var n;
|
|
31
|
+
(n = t.dispose) == null || n.call(t);
|
|
32
|
+
}
|
|
33
|
+
const D = new Uint32Array(256);
|
|
34
|
+
for (let t = 0; t < 256; t++) {
|
|
35
|
+
let n = t;
|
|
36
|
+
for (let e = 0; e < 8; e++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
|
|
37
|
+
D[t] = n >>> 0;
|
|
38
|
+
}
|
|
39
|
+
function _(t) {
|
|
40
|
+
let n = 4294967295;
|
|
41
|
+
for (const e of t) n = D[(n ^ e) & 255] ^ n >>> 8;
|
|
42
|
+
return (n ^ 4294967295) >>> 0;
|
|
43
|
+
}
|
|
44
|
+
const M = 33639248, C = 101010256, G = 67324752, K = 101075792, Q = 117853008, L = 1, tt = new TextDecoder("utf-8", { fatal: !0 }), et = new TextEncoder(), nt = /* @__PURE__ */ new Set([
|
|
45
|
+
"7z",
|
|
46
|
+
"aac",
|
|
47
|
+
"avi",
|
|
48
|
+
"eot",
|
|
49
|
+
"gif",
|
|
50
|
+
"gz",
|
|
51
|
+
"jpeg",
|
|
52
|
+
"jpg",
|
|
53
|
+
"m4a",
|
|
54
|
+
"m4v",
|
|
55
|
+
"mov",
|
|
56
|
+
"mp3",
|
|
57
|
+
"mp4",
|
|
58
|
+
"mpeg",
|
|
59
|
+
"mpg",
|
|
60
|
+
"ogg",
|
|
61
|
+
"otf",
|
|
62
|
+
"png",
|
|
63
|
+
"ttf",
|
|
64
|
+
"webm",
|
|
65
|
+
"webp",
|
|
66
|
+
"woff",
|
|
67
|
+
"woff2",
|
|
68
|
+
"zip"
|
|
69
|
+
]), Y = (t, n) => t < n ? -1 : t > n ? 1 : 0;
|
|
70
|
+
class p extends Error {
|
|
71
|
+
constructor(n, e) {
|
|
72
|
+
super(e), this.reason = n, this.name = "ZipPassthroughUnsupported";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const m = (t) => new DataView(t.buffer, t.byteOffset, t.byteLength);
|
|
76
|
+
function Z(t, n, e, r) {
|
|
77
|
+
if (!Number.isSafeInteger(n) || !Number.isSafeInteger(e) || n < 0 || e < 0 || n + e > t.length)
|
|
78
|
+
throw new Error(`ZIP ${r} 超出文件边界`);
|
|
79
|
+
}
|
|
80
|
+
function rt(t) {
|
|
81
|
+
if (t.length < 22) throw new Error("ZIP 缺少 EOCD");
|
|
82
|
+
const n = m(t), e = Math.max(0, t.length - 22 - 65535);
|
|
83
|
+
for (let r = t.length - 22; r >= e; r--) {
|
|
84
|
+
if (n.getUint32(r, !0) !== C) continue;
|
|
85
|
+
const o = n.getUint16(r + 20, !0);
|
|
86
|
+
if (r + 22 + o === t.length) return r;
|
|
87
|
+
}
|
|
88
|
+
throw new Error("ZIP 缺少有效 EOCD");
|
|
89
|
+
}
|
|
90
|
+
function ot(t, n) {
|
|
91
|
+
if (!(n & 2048) && t.some((e) => e >= 128))
|
|
92
|
+
throw new p("legacy-filename", "ZIP 使用非 UTF-8 文件名,不能安全映射 OPC part");
|
|
93
|
+
try {
|
|
94
|
+
return tt.decode(t);
|
|
95
|
+
} catch {
|
|
96
|
+
throw new Error("ZIP 文件名不是有效 UTF-8");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function T(t, n, e, r, o) {
|
|
100
|
+
Z(t, n, e, o);
|
|
101
|
+
const s = m(t), i = n + e;
|
|
102
|
+
let a = n;
|
|
103
|
+
for (; a < i; ) {
|
|
104
|
+
if (a + 4 > i) throw new Error(`ZIP ${o} 字段头不完整`);
|
|
105
|
+
const h = s.getUint16(a, !0), d = s.getUint16(a + 2, !0);
|
|
106
|
+
if (a + 4 + d > i) throw new Error(`ZIP ${o} 字段超出 extra 边界`);
|
|
107
|
+
if (h === r) return !0;
|
|
108
|
+
a += 4 + d;
|
|
109
|
+
}
|
|
110
|
+
return !1;
|
|
111
|
+
}
|
|
112
|
+
function st(t) {
|
|
113
|
+
const n = rt(t), e = m(t), r = e.getUint16(n + 4, !0), o = e.getUint16(n + 6, !0), s = e.getUint16(n + 8, !0), i = e.getUint16(n + 10, !0), a = e.getUint32(n + 12, !0), h = e.getUint32(n + 16, !0), d = e.getUint16(n + 20, !0);
|
|
114
|
+
if (n >= 20 && e.getUint32(n - 20, !0) === Q)
|
|
115
|
+
throw new p("zip64", "ZIP64 定位器不支持直通");
|
|
116
|
+
if (r || o || s !== i)
|
|
117
|
+
throw new p("multi-disk", "ZIP 多磁盘格式不支持直通");
|
|
118
|
+
if (i === 65535 || a === 4294967295 || h === 4294967295)
|
|
119
|
+
throw new p("zip64", "ZIP64 不支持直通");
|
|
120
|
+
if (d)
|
|
121
|
+
throw new p("archive-comment", "带存档注释的 ZIP 不支持直通");
|
|
122
|
+
Z(t, h, a, "中央目录");
|
|
123
|
+
const U = [], l = /* @__PURE__ */ new Set();
|
|
124
|
+
let c = h;
|
|
125
|
+
for (let u = 0; u < i; u++) {
|
|
126
|
+
if (Z(t, c, 46, "中央目录条目"), e.getUint32(c, !0) !== M) throw new Error("ZIP 中央目录签名错误");
|
|
127
|
+
const f = e.getUint16(c + 8, !0), w = e.getUint16(c + 10, !0), P = e.getUint32(c + 20, !0), I = e.getUint32(c + 24, !0), S = e.getUint16(c + 28, !0), R = e.getUint16(c + 30, !0), V = e.getUint16(c + 32, !0), $ = e.getUint16(c + 34, !0), g = e.getUint32(c + 42, !0), z = 46 + S + R + V;
|
|
128
|
+
if (Z(t, c, z, "中央目录条目"), P === 4294967295 || I === 4294967295 || g === 4294967295 || $ === 65535)
|
|
129
|
+
throw new p("zip64", "ZIP64 条目不支持直通");
|
|
130
|
+
if ($) throw new p("multi-disk", "跨磁盘 ZIP 条目不支持直通");
|
|
131
|
+
if (f & 1) throw new p("encrypted-entry", "ZIP 加密条目不支持直通");
|
|
132
|
+
if (f & 8)
|
|
133
|
+
throw new p("data-descriptor", "ZIP 数据描述符不支持直通");
|
|
134
|
+
if (w !== 0 && w !== 8)
|
|
135
|
+
throw new p("unsupported-compression", `ZIP 压缩方法 ${w} 不支持直通`);
|
|
136
|
+
const x = t.subarray(c + 46, c + 46 + S);
|
|
137
|
+
if (T(
|
|
138
|
+
t,
|
|
139
|
+
c + 46 + S,
|
|
140
|
+
R,
|
|
141
|
+
L,
|
|
142
|
+
`中央目录 extra ${u + 1}`
|
|
143
|
+
))
|
|
144
|
+
throw new p("zip64", "ZIP64 中央目录 extra 不支持直通");
|
|
145
|
+
const E = ot(x, f);
|
|
146
|
+
if (l.has(E)) throw new Error(`ZIP 存在重复条目:${E}`);
|
|
147
|
+
if (l.add(E), Z(t, g, 30, `本地头 ${E}`), e.getUint32(g, !0) !== G) throw new Error(`ZIP 本地头签名错误:${E}`);
|
|
148
|
+
const A = e.getUint16(g + 6, !0), O = e.getUint16(g + 8, !0);
|
|
149
|
+
if (A & 1)
|
|
150
|
+
throw new p("encrypted-entry", "ZIP 本地头声明加密,不支持直通");
|
|
151
|
+
if (A & 8)
|
|
152
|
+
throw new p("data-descriptor", "ZIP 本地头使用数据描述符,不支持直通");
|
|
153
|
+
if (O !== 0 && O !== 8)
|
|
154
|
+
throw new p(
|
|
155
|
+
"unsupported-compression",
|
|
156
|
+
`ZIP 本地头压缩方法 ${O} 不支持直通`
|
|
157
|
+
);
|
|
158
|
+
if (A !== f || O !== w || e.getUint32(g + 14, !0) !== e.getUint32(c + 16, !0) || e.getUint32(g + 18, !0) !== P || e.getUint32(g + 22, !0) !== I)
|
|
159
|
+
throw new Error(`ZIP 本地头与中央目录元数据不一致:${E}`);
|
|
160
|
+
const v = e.getUint16(g + 26, !0), b = e.getUint16(g + 28, !0);
|
|
161
|
+
if (T(
|
|
162
|
+
t,
|
|
163
|
+
g + 30 + v,
|
|
164
|
+
b,
|
|
165
|
+
L,
|
|
166
|
+
`本地头 extra ${E}`
|
|
167
|
+
))
|
|
168
|
+
throw new p("zip64", "ZIP64 本地头 extra 不支持直通");
|
|
169
|
+
const k = 30 + v + b + P;
|
|
170
|
+
Z(t, g, k, `本地条目 ${E}`);
|
|
171
|
+
const W = t.subarray(g + 30, g + 30 + v);
|
|
172
|
+
if (!N(W, x)) throw new Error(`ZIP 本地头与中央目录名称不一致:${E}`);
|
|
173
|
+
U.push({
|
|
174
|
+
name: E,
|
|
175
|
+
flags: f,
|
|
176
|
+
method: w,
|
|
177
|
+
compressedSize: P,
|
|
178
|
+
uncompressedSize: I,
|
|
179
|
+
localOffset: g,
|
|
180
|
+
localRaw: t.subarray(g, g + k),
|
|
181
|
+
centralRaw: t.subarray(c, c + z)
|
|
182
|
+
}), c += z;
|
|
183
|
+
}
|
|
184
|
+
if (c !== h + a) throw new Error("ZIP 中央目录包含未识别记录");
|
|
185
|
+
if (c !== n)
|
|
186
|
+
throw c + 4 <= t.length && e.getUint32(c, !0) === K ? new p("zip64", "ZIP64 EOCD 记录不支持直通") : new Error("ZIP 中央目录与 EOCD 之间存在未识别记录");
|
|
187
|
+
return { entries: U };
|
|
188
|
+
}
|
|
189
|
+
function B(t) {
|
|
190
|
+
const n = t.reduce((o, s) => o + s.length, 0), e = new Uint8Array(n);
|
|
191
|
+
let r = 0;
|
|
192
|
+
for (const o of t)
|
|
193
|
+
e.set(o, r), r += o.length;
|
|
194
|
+
return e;
|
|
195
|
+
}
|
|
196
|
+
function ct(t, n) {
|
|
197
|
+
if (n.length > 4294967295) throw new Error(`OPC part 过大,需要 ZIP64:${t.name}`);
|
|
198
|
+
const e = t.method === 8 ? j(n, { level: 6 }) : n;
|
|
199
|
+
if (e.length > 4294967295) throw new Error(`OPC part 压缩后过大,需要 ZIP64:${t.name}`);
|
|
200
|
+
const r = t.localRaw.length - t.compressedSize, o = new Uint8Array(r + e.length);
|
|
201
|
+
o.set(t.localRaw.subarray(0, r)), o.set(e, r);
|
|
202
|
+
const s = m(o), i = _(n);
|
|
203
|
+
return s.setUint32(14, i, !0), s.setUint32(18, e.length, !0), s.setUint32(22, n.length, !0), { bytes: o, checksum: i, compressedSize: e.length, uncompressedSize: n.length };
|
|
204
|
+
}
|
|
205
|
+
function it(t, n, e) {
|
|
206
|
+
const r = t.centralRaw.slice(), o = m(r);
|
|
207
|
+
return n && (o.setUint32(16, n.checksum, !0), o.setUint32(20, n.compressedSize, !0), o.setUint32(24, n.uncompressedSize, !0)), o.setUint32(42, e, !0), r;
|
|
208
|
+
}
|
|
209
|
+
function lt(t, n) {
|
|
210
|
+
const e = [], r = [];
|
|
211
|
+
let o = 0, s = 0, i = 0;
|
|
212
|
+
const a = new Set(t.entries.map((f) => f.name));
|
|
213
|
+
for (const f of t.entries) {
|
|
214
|
+
const w = n.get(f.name);
|
|
215
|
+
if (w === null) {
|
|
216
|
+
i++;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const P = w ? ct(f, w) : null, I = (P == null ? void 0 : P.bytes) ?? f.localRaw;
|
|
220
|
+
e.push(I), r.push(it(f, P, o)), o += I.length, w ? i++ : s++;
|
|
221
|
+
}
|
|
222
|
+
const h = [...n].filter(([f, w]) => !a.has(f) && w !== null).sort(([f], [w]) => Y(f, w));
|
|
223
|
+
for (const [f, w] of h) {
|
|
224
|
+
const P = F(f, w, o);
|
|
225
|
+
e.push(P.local), r.push(P.central), o += P.local.length, i++;
|
|
226
|
+
}
|
|
227
|
+
const d = e.length;
|
|
228
|
+
if (d > 65535) throw new Error("保存结果需要 ZIP64 条目计数,当前不支持");
|
|
229
|
+
const U = o, l = r.reduce((f, w) => f + w.length, 0);
|
|
230
|
+
if (U > 4294967295 || l > 4294967295)
|
|
231
|
+
throw new Error("保存结果需要 ZIP64 偏移,当前不支持");
|
|
232
|
+
const c = new Uint8Array(22), u = m(c);
|
|
233
|
+
return u.setUint32(0, C, !0), u.setUint16(8, d, !0), u.setUint16(10, d, !0), u.setUint32(12, l, !0), u.setUint32(16, U, !0), { bytes: B([...e, ...r, c]), preservedEntries: s, rewrittenEntries: i };
|
|
234
|
+
}
|
|
235
|
+
function ut(t, n) {
|
|
236
|
+
const e = Object.keys(t), r = new Set(e), o = e.filter((l) => n.get(l) !== null);
|
|
237
|
+
if (o.push(...[...n].filter(([l, c]) => !r.has(l) && c !== null).map(([l]) => l).sort(Y)), o.length > 65535) throw new Error("重压结果需要 ZIP64 条目计数,当前不支持");
|
|
238
|
+
const s = [], i = [];
|
|
239
|
+
let a = 0;
|
|
240
|
+
for (const l of o) {
|
|
241
|
+
const c = n.get(l) ?? t[l];
|
|
242
|
+
if (!c) throw new Error(`重压时缺少 OPC part:${l}`);
|
|
243
|
+
const u = F(l, c, a);
|
|
244
|
+
s.push(u.local), i.push(u.central), a += u.local.length;
|
|
245
|
+
}
|
|
246
|
+
const h = i.reduce((l, c) => l + c.length, 0);
|
|
247
|
+
if (a > 4294967295 || h > 4294967295) throw new Error("重压结果需要 ZIP64 偏移,当前不支持");
|
|
248
|
+
const d = new Uint8Array(22), U = m(d);
|
|
249
|
+
return U.setUint32(0, C, !0), U.setUint16(8, o.length, !0), U.setUint16(10, o.length, !0), U.setUint32(12, h, !0), U.setUint32(16, a, !0), {
|
|
250
|
+
bytes: B([...s, ...i, d]),
|
|
251
|
+
preservedEntries: 0,
|
|
252
|
+
rewrittenEntries: o.length
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function F(t, n, e) {
|
|
256
|
+
if (n.length > 4294967295) throw new Error(`OPC part 过大,需要 ZIP64:${t}`);
|
|
257
|
+
const r = et.encode(t);
|
|
258
|
+
if (r.length > 65535) throw new Error(`OPC part 路径过长:${t.slice(0, 80)}`);
|
|
259
|
+
const o = t.slice(t.lastIndexOf(".") + 1).toLowerCase(), s = nt.has(o) ? null : j(n, { level: 6 }), i = s !== null && s.length < n.length, a = i ? 8 : 0, h = i ? s : n;
|
|
260
|
+
if (h.length > 4294967295) throw new Error(`OPC part 压缩后过大,需要 ZIP64:${t}`);
|
|
261
|
+
const d = _(n), U = new Uint8Array(30 + r.length + h.length), l = m(U);
|
|
262
|
+
l.setUint32(0, G, !0), l.setUint16(4, 20, !0), l.setUint16(6, 2048, !0), l.setUint16(8, a, !0), l.setUint16(12, 33, !0), l.setUint32(14, d, !0), l.setUint32(18, h.length, !0), l.setUint32(22, n.length, !0), l.setUint16(26, r.length, !0), U.set(r, 30), U.set(h, 30 + r.length);
|
|
263
|
+
const c = new Uint8Array(46 + r.length), u = m(c);
|
|
264
|
+
return u.setUint32(0, M, !0), u.setUint16(4, 798, !0), u.setUint16(6, 20, !0), u.setUint16(8, 2048, !0), u.setUint16(10, a, !0), u.setUint16(14, 33, !0), u.setUint32(16, d, !0), u.setUint32(20, h.length, !0), u.setUint32(24, n.length, !0), u.setUint16(28, r.length, !0), u.setUint32(42, e, !0), c.set(r, 46), { local: U, central: c };
|
|
265
|
+
}
|
|
266
|
+
function at(t, n) {
|
|
267
|
+
const e = /* @__PURE__ */ new Map();
|
|
268
|
+
for (const [r, o] of Object.entries(n)) {
|
|
269
|
+
ft(r);
|
|
270
|
+
const s = t.parts[r];
|
|
271
|
+
o === null ? s && e.set(r, null) : (!s || !N(s, o)) && e.set(r, o.slice());
|
|
272
|
+
}
|
|
273
|
+
return e;
|
|
274
|
+
}
|
|
275
|
+
function ft(t) {
|
|
276
|
+
const n = t.split("/");
|
|
277
|
+
if (!t || t.startsWith("/") || t.endsWith("/") || t.includes("\\") || n.some((e) => !e || e === "." || e === ".."))
|
|
278
|
+
throw new Error(`非法 OPC part 路径:${t}`);
|
|
279
|
+
}
|
|
280
|
+
function wt(t, n, e) {
|
|
281
|
+
const r = /* @__PURE__ */ Object.create(null);
|
|
282
|
+
for (const [s, i] of Object.entries(t.parts))
|
|
283
|
+
e.get(s) !== null && (r[s] = e.get(s) ?? i);
|
|
284
|
+
for (const [s, i] of e) i !== null && (r[s] = i);
|
|
285
|
+
Object.freeze(r);
|
|
286
|
+
const o = Object.freeze(Object.fromEntries(Object.entries(t.assets ?? {}).filter(([, s]) => !!s.sourcePart && !!r[s.sourcePart] && !e.has(s.sourcePart))));
|
|
287
|
+
return H(n, r, o);
|
|
288
|
+
}
|
|
289
|
+
function gt(t) {
|
|
290
|
+
J(t);
|
|
291
|
+
}
|
|
292
|
+
function pt(t, n) {
|
|
293
|
+
if (t.disposed) throw new Error("OPC 原包已释放,不能保存");
|
|
294
|
+
const e = at(t, n);
|
|
295
|
+
if (e.size) {
|
|
296
|
+
let r, o = null;
|
|
297
|
+
try {
|
|
298
|
+
r = lt(st(t.bytes), e);
|
|
299
|
+
} catch (s) {
|
|
300
|
+
if (!(s instanceof p)) throw s;
|
|
301
|
+
o = s.reason, r = ut(t.parts, e);
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
...r,
|
|
305
|
+
package: wt(t, r.bytes, e),
|
|
306
|
+
mode: o ? "repacked" : "passthrough",
|
|
307
|
+
fallbackReason: o
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
bytes: t.bytes,
|
|
312
|
+
package: t,
|
|
313
|
+
mode: "identity",
|
|
314
|
+
fallbackReason: null,
|
|
315
|
+
preservedEntries: Object.keys(t.parts).length,
|
|
316
|
+
rewrittenEntries: 0
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
export {
|
|
320
|
+
gt as d,
|
|
321
|
+
pt as p
|
|
322
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Slide, SlideElement } from '@web-ppt/core';
|
|
2
|
+
import type { EditDoc, ElementId, ProjectionInvalidation, SlideId } from './types';
|
|
3
|
+
/** 文档换包或释放后,投影不能继续持有旧资源 URL 与整页 Schema。 */
|
|
4
|
+
export declare function releaseProjectionCache(doc: EditDoc): void;
|
|
5
|
+
export declare function effectiveElement(doc: EditDoc, id: ElementId): SlideElement;
|
|
6
|
+
export declare function toSlide(doc: EditDoc, id: SlideId): Slide;
|
|
7
|
+
export declare function slideOfElement(doc: EditDoc, id: ElementId): SlideId;
|
|
8
|
+
/** 元素变化会沿组祖先传播到所属页;无需扫描或比较整份文档。 */
|
|
9
|
+
export declare function invalidateElement(doc: EditDoc, id: ElementId): ProjectionInvalidation;
|
|
10
|
+
export declare function invalidateSlide(doc: EditDoc, id: SlideId): ProjectionInvalidation;
|
|
11
|
+
/** 备注属于页面数据但不参与 SVG;只清投影缓存,不把画布视图列为脏页。 */
|
|
12
|
+
export declare function invalidateSlideData(doc: EditDoc, id: SlideId): ProjectionInvalidation;
|
|
13
|
+
/** 页面树 patch 发生在页面存在性变化之前,不能要求目标页已经在模型中。 */
|
|
14
|
+
export declare function invalidateSlideStructure(doc: EditDoc, id: SlideId, elements: readonly ElementId[]): ProjectionInvalidation;
|
|
15
|
+
/** 页序变化只改变动态字段;沿字段父链失效,避免框架订阅者收到整段页尾的元素更新。 */
|
|
16
|
+
export declare function invalidateSlideSequence(doc: EditDoc, start: number): ProjectionInvalidation;
|
|
17
|
+
/** 结构 patch 的根可能尚不存在;以外部父节点失效并清掉整棵树的旧投影缓存。 */
|
|
18
|
+
export declare function invalidateElementStructure(doc: EditDoc, ids: readonly ElementId[], parent: SlideId | ElementId): ProjectionInvalidation;
|
|
19
|
+
export declare function invalidateAll(doc: EditDoc): ProjectionInvalidation;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Patch } from './commands/types';
|
|
2
|
+
import type { EditDoc, EditIdentity } from './types';
|
|
3
|
+
export declare function assertRecoveryIdentity(value: unknown, prefix: string, sequence: number): asserts value is EditIdentity;
|
|
4
|
+
export interface RecoveryIdentityFloor {
|
|
5
|
+
nextSlide: number;
|
|
6
|
+
nextElement: number;
|
|
7
|
+
readonly nextSpid: Map<string, number>;
|
|
8
|
+
readonly checkedSpidSources: Set<string>;
|
|
9
|
+
readonly createdParts: Set<string>;
|
|
10
|
+
readonly knownElements: Map<string, string | null>;
|
|
11
|
+
readonly owningParts: Map<string, string | null>;
|
|
12
|
+
readonly knownSlides: Map<string, string>;
|
|
13
|
+
readonly occupiedSlideParts: Set<string>;
|
|
14
|
+
readonly usedPresentationSlideIds: Set<number>;
|
|
15
|
+
readonly usedPresentationRelationships: Set<string>;
|
|
16
|
+
readonly allowedNotesBindings: Map<string, Set<string>>;
|
|
17
|
+
readonly currentNotesBindings: Map<string, string | null>;
|
|
18
|
+
readonly occupiedNotesParts: Set<string>;
|
|
19
|
+
readonly inheritedSources: Map<string, Set<string>>;
|
|
20
|
+
readonly slideIdPattern: RegExp;
|
|
21
|
+
readonly elementIdPattern: RegExp;
|
|
22
|
+
readonly rowIdPattern: RegExp;
|
|
23
|
+
nextSlidePart?: number;
|
|
24
|
+
nextNotesPart?: number;
|
|
25
|
+
nextPresentationSlideId?: number;
|
|
26
|
+
nextPresentationRelationship?: number;
|
|
27
|
+
minimumNewSlidePart?: number;
|
|
28
|
+
minimumNewPresentationSlideId?: number;
|
|
29
|
+
minimumNewPresentationRelationship?: number;
|
|
30
|
+
minimumNewNotesPart?: number;
|
|
31
|
+
checkedSlideSource: boolean;
|
|
32
|
+
checkedNotesSource: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function createRecoveryIdentityFloor(doc: EditDoc): RecoveryIdentityFloor;
|
|
35
|
+
export declare function assertRecoveryIdentityFloor(doc: EditDoc, floor: RecoveryIdentityFloor, next: EditIdentity, patches: readonly Patch[], sequence: number): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { EditIdentity } from './types';
|
|
2
|
+
import type { Patch, Selection } from './commands/types';
|
|
3
|
+
export type RecoveryFrameSource = 'transaction' | 'undo' | 'redo' | 'selection' | 'savepoint';
|
|
4
|
+
/** Patch 里的 blob URL 会被保留 token 取代;这里保存 token 可重绑的原包身份或字节。 */
|
|
5
|
+
export interface RecoveryAssetReference {
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly mime: string;
|
|
8
|
+
readonly sourcePart?: string;
|
|
9
|
+
/** 无原包 part 的派生资源才内联;普通源图片不会把字节重复写进每帧。 */
|
|
10
|
+
readonly data?: string;
|
|
11
|
+
}
|
|
12
|
+
/** 一帧只描述已经生效的结果;资源 URL 已 token 化,存储层不需要理解命令或历史内部状态。 */
|
|
13
|
+
export interface RecoveryFrame {
|
|
14
|
+
readonly version: 1;
|
|
15
|
+
readonly sequence: number;
|
|
16
|
+
readonly source: RecoveryFrameSource;
|
|
17
|
+
readonly patches: Patch[];
|
|
18
|
+
readonly assets?: readonly RecoveryAssetReference[];
|
|
19
|
+
readonly identity: EditIdentity;
|
|
20
|
+
readonly selection: Selection;
|
|
21
|
+
readonly dirty: boolean;
|
|
22
|
+
readonly label: string;
|
|
23
|
+
readonly time: number;
|
|
24
|
+
}
|
|
25
|
+
export type RecoverySubscriber = (frame: RecoveryFrame) => void;
|
|
26
|
+
export interface RecoveryRestoreResult {
|
|
27
|
+
readonly selection: Selection;
|
|
28
|
+
readonly dirty: boolean;
|
|
29
|
+
readonly sequence: number;
|
|
30
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Patch, Selection } from './commands/types';
|
|
2
|
+
import type { RecoveryFrame, RecoveryFrameSource, RecoveryRestoreResult, RecoverySubscriber } from './recovery-types';
|
|
3
|
+
import type { EditDoc, EditIdentity } from './types';
|
|
4
|
+
export declare const EDITOR_RECOVERY_VERSION: 1;
|
|
5
|
+
export declare function cloneRecoveryFrame(frame: RecoveryFrame): RecoveryFrame;
|
|
6
|
+
/** 只应在新解析文档建立 Editor 前调用;成功时一次性交换模型,失败时目标保持原样。 */
|
|
7
|
+
export declare function restoreRecoveryFrames(doc: EditDoc, frames: readonly RecoveryFrame[]): RecoveryRestoreResult;
|
|
8
|
+
interface EmitRecoveryFrame {
|
|
9
|
+
readonly source: RecoveryFrameSource;
|
|
10
|
+
readonly patches: readonly Patch[];
|
|
11
|
+
readonly doc: EditDoc;
|
|
12
|
+
readonly identity: EditIdentity;
|
|
13
|
+
readonly selection: Selection;
|
|
14
|
+
readonly dirty: boolean;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly time: number;
|
|
17
|
+
}
|
|
18
|
+
/** 序号在调用观察者前分配;同步重入编辑也不会颠倒日志因果顺序。 */
|
|
19
|
+
export declare class RecoveryJournal {
|
|
20
|
+
private readonly subscribers;
|
|
21
|
+
private readonly pending;
|
|
22
|
+
private dispatching;
|
|
23
|
+
private sequence;
|
|
24
|
+
constructor(sequence?: number);
|
|
25
|
+
subscribe(subscriber: RecoverySubscriber): () => void;
|
|
26
|
+
emit(input: EmitRecoveryFrame): void;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TextRange } from './commands/types';
|
|
2
|
+
import type { EditDoc, RunPropertiesState, TableCellAddress } from './types';
|
|
3
|
+
/** 面板与框架适配层只从 headless 文档查询,不把格式真相藏进 DOM。 */
|
|
4
|
+
export declare function queryRunProps(doc: EditDoc, id: string, range: TextRange, cell?: TableCellAddress): RunPropertiesState;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RunPropertyOverrides } from './types';
|
|
2
|
+
export declare const RUN_PROPERTY_FIELDS: readonly ["font", "size", "b", "i", "u", "strike", "link"];
|
|
3
|
+
export declare function assertRunPropertyOverrides(value: unknown, label: string, allowEmpty?: boolean): asserts value is RunPropertyOverrides;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EditAnimationStep, EditDoc, SlideRecord } from '../types';
|
|
2
|
+
import type { XmlDocument } from '../xml/types';
|
|
3
|
+
/** 删除对象必须保留式清理所有已知/未知行为和 build 对该 spid 的引用。 */
|
|
4
|
+
export declare function removeSlideAnimationTargets(document: XmlDocument, sourceSpids: readonly number[]): void;
|
|
5
|
+
/** bldLst 按 spid/grpId 描述图表/SmartArt build,不依赖 cTn id;本票只替换 tnLst。 */
|
|
6
|
+
export declare function patchSlideAnimations(document: XmlDocument, doc: EditDoc, record: SlideRecord, steps: readonly EditAnimationStep[]): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Fill } from '@web-ppt/core';
|
|
2
|
+
import type { XmlElement } from '../xml/types';
|
|
3
|
+
type ImageFill = Extract<Fill, {
|
|
4
|
+
type: 'image';
|
|
5
|
+
}>;
|
|
6
|
+
/** 已有 blipFill 原位修改,未知属性、效果和扩展不因编辑已知字段而丢失。 */
|
|
7
|
+
export declare function patchBackgroundImageFill(properties: XmlElement, image: ImageFill, relationshipId: string, preserveSourceDpi: boolean): void;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { relationshipPartFor } from '../clipboard-source';
|
|
2
|
+
import type { EditDoc, ElementInsertionRelationship, ElementInsertionResource } from '../types';
|
|
3
|
+
export interface MediaPackageParts {
|
|
4
|
+
readonly relationships: Map<string, ElementInsertionRelationship[]>;
|
|
5
|
+
readonly resources: Map<string, ElementInsertionResource>;
|
|
6
|
+
}
|
|
7
|
+
export declare function mediaPackageParts(doc: EditDoc): MediaPackageParts;
|
|
8
|
+
export declare function patchRelationshipPart(source: Uint8Array | undefined, relationships: readonly ElementInsertionRelationship[]): Uint8Array;
|
|
9
|
+
export declare function patchContentTypes(source: Uint8Array | undefined, resources: readonly ElementInsertionResource[]): Uint8Array;
|
|
10
|
+
export declare function resourceBytes(resource: ElementInsertionResource): Uint8Array;
|
|
11
|
+
export { relationshipPartFor };
|