@a3s-lab/office 0.10.0 → 0.12.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.
Files changed (47) hide show
  1. package/COLLABORATION_ROADMAP.md +22 -12
  2. package/README.md +40 -15
  3. package/dist/{0~4705.js → 0~5093.js} +959 -10
  4. package/dist/0~document-editor.js +1 -0
  5. package/dist/0~spreadsheet-editor.js +189 -104
  6. package/dist/0~work-docx-export.js +225 -6
  7. package/dist/0~work-docx-import.js +26 -755
  8. package/dist/0~work-office-diagnostics.js +12 -8
  9. package/dist/0~work-pptx-import.js +2 -2
  10. package/dist/4104.js +330 -122
  11. package/dist/4476.js +82 -65
  12. package/dist/8715.js +41 -3
  13. package/dist/8928.js +448 -137
  14. package/dist/9356.js +126 -8
  15. package/dist/core.d.ts +1 -0
  16. package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +1 -0
  17. package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +2 -1
  18. package/dist/internal/features/work/spreadsheet-sparse.d.ts +5 -0
  19. package/dist/internal/features/work/work-document-file-io.d.ts +2 -1
  20. package/dist/internal/features/work/work-document-format-change-tracking.d.ts +1 -1
  21. package/dist/internal/features/work/work-document-paragraph-format-change-tracking.d.ts +7 -0
  22. package/dist/internal/features/work/work-document-paragraph-format-changes.d.ts +8 -0
  23. package/dist/internal/features/work/work-docx-import.d.ts +5 -2
  24. package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +1 -0
  25. package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +1 -0
  26. package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +1 -0
  27. package/dist/internal/features/work/work-docx-paragraph-format-change-export.d.ts +13 -0
  28. package/dist/internal/features/work/work-docx-paragraph-format-change-import.d.ts +17 -0
  29. package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +1 -0
  30. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +1 -0
  31. package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +1 -0
  32. package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +1 -0
  33. package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +1 -0
  34. package/dist/internal/features/work/work-file-data.d.ts +7 -1
  35. package/dist/internal/features/work/work-file-import.d.ts +28 -0
  36. package/dist/internal/features/work/work-file-io.d.ts +2 -1
  37. package/dist/internal/features/work/work-markdown-file-io.d.ts +2 -1
  38. package/dist/internal/features/work/work-office-diagnostics.d.ts +3 -2
  39. package/dist/internal/features/work/work-pptx-import.d.ts +1 -1
  40. package/dist/internal/features/work/work-presentation-file-io.d.ts +2 -1
  41. package/dist/internal/features/work/work-spreadsheet-protection.d.ts +2 -0
  42. package/dist/internal/features/work/work-types.d.ts +23 -1
  43. package/dist/internal/features/work/work-xlsx-interop.d.ts +4 -14
  44. package/dist/office-kernel.wasm +0 -0
  45. package/dist/styles.css +8 -0
  46. package/docs/latest/en/browser-editor-architecture.md +18 -0
  47. package/package.json +10 -4
package/dist/9356.js CHANGED
@@ -1,10 +1,128 @@
1
- async function materializeWorkFile(file) {
2
- const bytes = await file.arrayBuffer();
3
- return new File([
4
- bytes
5
- ], file.name, {
6
- lastModified: file.lastModified,
7
- type: file.type
1
+ const stageRanges = {
2
+ reading: [
3
+ 0,
4
+ 0.2
5
+ ],
6
+ parsing: [
7
+ 0.2,
8
+ 0.75
9
+ ],
10
+ analyzing: [
11
+ 0.75,
12
+ 0.95
13
+ ],
14
+ finalizing: [
15
+ 0.95,
16
+ 1
17
+ ]
18
+ };
19
+ class WorkFileImportController {
20
+ options;
21
+ totalBytes;
22
+ progress = 0;
23
+ constructor(options, totalBytes){
24
+ this.options = options;
25
+ this.totalBytes = totalBytes;
26
+ }
27
+ get signal() {
28
+ return this.options.signal;
29
+ }
30
+ throwIfAborted() {
31
+ if (!this.signal?.aborted) return;
32
+ throw workFileImportAbortError(this.signal.reason);
33
+ }
34
+ report(stage, stageProgress, bytesRead = this.totalBytes) {
35
+ this.throwIfAborted();
36
+ const boundedStageProgress = Math.max(0, Math.min(1, stageProgress));
37
+ const [start, end] = stageRanges[stage];
38
+ this.progress = Math.max(this.progress, start + (end - start) * boundedStageProgress);
39
+ this.options.onProgress?.({
40
+ stage,
41
+ stageProgress: boundedStageProgress,
42
+ progress: this.progress,
43
+ bytesRead: Math.max(0, Math.min(this.totalBytes, bytesRead)),
44
+ totalBytes: this.totalBytes
45
+ });
46
+ this.throwIfAborted();
47
+ }
48
+ async checkpoint(stage, stageProgress) {
49
+ this.report(stage, stageProgress);
50
+ await this.yieldToMainThread();
51
+ }
52
+ async yieldToMainThread() {
53
+ this.throwIfAborted();
54
+ await new Promise((resolve)=>setTimeout(resolve, 0));
55
+ this.throwIfAborted();
56
+ }
57
+ complete() {
58
+ this.report('finalizing', 1);
59
+ }
60
+ }
61
+ function workFileImportAbortError(reason) {
62
+ if (reason instanceof Error && 'AbortError' === reason.name) return reason;
63
+ if ("u" > typeof DOMException) return new DOMException('Office file import was cancelled.', 'AbortError');
64
+ const error = new Error('Office file import was cancelled.');
65
+ error.name = 'AbortError';
66
+ return error;
67
+ }
68
+ const WORK_FILE_READ_CHUNK_BYTES = 4194304;
69
+ async function materializeWorkFile(file, controller = new WorkFileImportController({}, file.size)) {
70
+ return (await materializeWorkFileSource(file, controller)).file;
71
+ }
72
+ async function materializeWorkFileSource(file, controller) {
73
+ const bytes = await readWorkFileBytes(file, controller);
74
+ return {
75
+ bytes,
76
+ file: new File([
77
+ bytes
78
+ ], file.name, {
79
+ lastModified: file.lastModified,
80
+ type: file.type
81
+ })
82
+ };
83
+ }
84
+ async function readWorkFileBytes(file, controller) {
85
+ controller.report('reading', 0, 0);
86
+ if (file.size <= WORK_FILE_READ_CHUNK_BYTES) {
87
+ const bytes = await abortableArrayBuffer(file.arrayBuffer(), controller);
88
+ controller.report('reading', 1, bytes.byteLength);
89
+ return bytes;
90
+ }
91
+ const bytes = new Uint8Array(file.size);
92
+ for(let offset = 0; offset < file.size; offset += WORK_FILE_READ_CHUNK_BYTES){
93
+ controller.throwIfAborted();
94
+ const end = Math.min(file.size, offset + WORK_FILE_READ_CHUNK_BYTES);
95
+ const chunk = await abortableArrayBuffer(file.slice(offset, end).arrayBuffer(), controller);
96
+ bytes.set(new Uint8Array(chunk), offset);
97
+ controller.report('reading', end / file.size, end);
98
+ if (end < file.size) await controller.yieldToMainThread();
99
+ }
100
+ return bytes.buffer;
101
+ }
102
+ async function abortableArrayBuffer(pending, controller) {
103
+ controller.throwIfAborted();
104
+ const signal = controller.signal;
105
+ if (!signal) return pending;
106
+ return new Promise((resolve, reject)=>{
107
+ const abort = ()=>{
108
+ cleanup();
109
+ try {
110
+ controller.throwIfAborted();
111
+ } catch (error) {
112
+ reject(error);
113
+ }
114
+ };
115
+ const cleanup = ()=>signal.removeEventListener('abort', abort);
116
+ signal.addEventListener('abort', abort, {
117
+ once: true
118
+ });
119
+ pending.then((bytes)=>{
120
+ cleanup();
121
+ resolve(bytes);
122
+ }, (error)=>{
123
+ cleanup();
124
+ reject(error);
125
+ });
8
126
  });
9
127
  }
10
- export { materializeWorkFile };
128
+ export { WorkFileImportController, materializeWorkFile, materializeWorkFileSource };
package/dist/core.d.ts CHANGED
@@ -21,6 +21,7 @@ export type { WorkEditorAgentRequest as EditorAgentRequest } from './internal/fe
21
21
  export type { WorkDocumentReviewConflict as DocumentReviewConflict, WorkDocumentReviewConflictEvent as DocumentReviewConflictEvent, WorkDocumentReviewConflictReason as DocumentReviewConflictReason, WorkDocumentReviewKind as DocumentReviewKind, } from './internal/features/work/work-document-review-conflicts';
22
22
  export type { WorkDocumentSelectionCommandFailure as DocumentSelectionCommandFailure, WorkDocumentSelectionCommandResult as DocumentSelectionCommandResult, WorkDocumentSelectionCommands as DocumentSelectionCommands, WorkDocumentSelectionContext as DocumentSelectionContext, WorkDocumentSelectionMenuIcon as DocumentSelectionMenuIcon, WorkDocumentSelectionMenuItem as DocumentSelectionMenuItem, WorkDocumentSelectionSnapshot as DocumentSelectionSnapshot, WorkGetDocumentSelectionMenuItems as GetDocumentSelectionMenuItems, } from './internal/features/work/work-document-selection-menu';
23
23
  export type { WorkArtifactExportOptions as ArtifactExportOptions } from './internal/features/work/work-file-io';
24
+ export type { WorkFileImportOptions as OfficeFileImportOptions, WorkFileImportProgress as OfficeFileImportProgress, WorkFileImportStage as OfficeFileImportStage, } from './internal/features/work/work-file-import';
24
25
  export { createWorkArtifactBlob as createArtifactBlob, exportWorkArtifact as downloadArtifact, importWorkFile as importOfficeFile, WORK_IMPORT_ACCEPT as OFFICE_FILE_ACCEPT, workKindForFile as officeKindForFile, } from './internal/features/work/work-file-io';
25
26
  export { decodeWorkDocumentSnapshot as decodeDocumentSnapshot, encodeWorkDocumentSnapshot as encodeDocumentSnapshot, WORK_DOCUMENT_SNAPSHOT_MEDIA_TYPE as DOCUMENT_SNAPSHOT_MEDIA_TYPE, WORK_DOCUMENT_SNAPSHOT_SCHEMA as DOCUMENT_SNAPSHOT_SCHEMA, WORK_DOCUMENT_SNAPSHOT_VERSION as DOCUMENT_SNAPSHOT_VERSION, type WorkDocumentSnapshot as DocumentSnapshot, } from './internal/features/work/work-document-snapshot';
26
27
  export { applyWorkDocumentSource as applyDocumentSource, projectWorkDocumentSource as projectDocumentSource, WORK_DOCUMENT_SOURCE_MEDIA_TYPE as DOCUMENT_SOURCE_MEDIA_TYPE, WORK_DOCUMENT_SOURCE_SCHEMA as DOCUMENT_SOURCE_SCHEMA, WORK_DOCUMENT_SOURCE_VERSION as DOCUMENT_SOURCE_VERSION, type WorkDocumentSource as DocumentSource, } from './internal/features/work/work-document-source';
@@ -21,6 +21,7 @@ export declare function spreadsheetFontSizeOptions(current: number | undefined):
21
21
  export declare function spreadsheetFontFamilyOptions(current: string | undefined): OfficeSelectOption[];
22
22
  export declare function spreadsheetSheetsWithFiniteSelections(sheets: WorkSpreadsheetContent['sheets']): WorkSpreadsheetContent['sheets'];
23
23
  export declare function spreadsheetSheetsForFortune(sheets: WorkSpreadsheetContent['sheets']): WorkSpreadsheetContent['sheets'];
24
+ export declare function spreadsheetSheetsFromFortune(sheets: WorkSpreadsheetContent['sheets'], sourceSheets: WorkSpreadsheetContent['sheets']): WorkSpreadsheetContent['sheets'];
24
25
  export declare function finiteSpreadsheetSelection(selection: Selection | undefined): Selection;
25
26
  export declare function sameSpreadsheetWorkbookState(changed: WorkSpreadsheetContent['sheets'], rendered: WorkSpreadsheetContent['sheets']): boolean;
26
27
  export declare function sameSpreadsheetHistoryContent(left: WorkSpreadsheetContent, right: WorkSpreadsheetContent): boolean;
@@ -8,7 +8,7 @@ export interface SpreadsheetCollaborationHistory {
8
8
  undo: () => boolean;
9
9
  }
10
10
  export interface SpreadsheetCollaborationViewController {
11
- activateSheet: (sheetId: string) => void;
11
+ activateSheet: (sheetId: string) => boolean;
12
12
  select: (sheetId: string, selection: Selection) => void;
13
13
  setZoom: (sheetId: string, zoomRatio: number) => void;
14
14
  }
@@ -21,6 +21,7 @@ export declare function useSpreadsheetCollaboration({ initialContent, onChange,
21
21
  content: WorkSpreadsheetContent;
22
22
  history: SpreadsheetCollaborationHistory;
23
23
  onChange: (next: WorkSpreadsheetContent) => void;
24
+ onDerivedChange: (next: WorkSpreadsheetContent) => void;
24
25
  readOnly: boolean;
25
26
  view: SpreadsheetCollaborationViewController;
26
27
  };
@@ -0,0 +1,5 @@
1
+ import type { CellMatrix } from '@fortune-sheet/core';
2
+ export declare function sparseArrayIndexes(values: readonly unknown[] | undefined): number[];
3
+ export declare function sparseArrayEntries<T>(values: readonly T[] | undefined): Array<[number, T]>;
4
+ export declare function sparseMatrixColumnCount(matrix: CellMatrix | undefined): number;
5
+ export declare function cloneSparseMatrix(source: CellMatrix | undefined): CellMatrix;
@@ -1,4 +1,5 @@
1
+ import type { WorkFileImportContext } from './work-file-import';
1
2
  import type { WorkArtifact } from './work-types';
2
- export declare function importWorkDocumentFile(file: File, extension: string): Promise<WorkArtifact>;
3
+ export declare function importWorkDocumentFile(file: File, extension: string, context?: WorkFileImportContext): Promise<WorkArtifact>;
3
4
  export declare function exportWorkDocumentArtifact(artifact: WorkArtifact): Promise<void>;
4
5
  export declare function createWorkDocumentBlob(artifact: WorkArtifact): Promise<Blob>;
@@ -3,7 +3,7 @@ import type { EditorState, PluginKey, Transaction } from '@tiptap/pm/state';
3
3
  import type { WorkDocumentChangeIdentity } from './work-document-changes';
4
4
  interface DocumentFormattingChangeTrackingOptions {
5
5
  isTracking: () => boolean;
6
- createChange: () => WorkDocumentChangeIdentity;
6
+ createChange: (kind: 'formatting' | 'paragraph-formatting') => WorkDocumentChangeIdentity;
7
7
  }
8
8
  export declare function trackDocumentFormattingTransaction(transaction: Transaction, state: EditorState, type: ProseMirrorMark['type'], options: DocumentFormattingChangeTrackingOptions, pluginKey: PluginKey): void;
9
9
  export {};
@@ -0,0 +1,7 @@
1
+ import type { EditorState, Transaction } from '@tiptap/pm/state';
2
+ import type { WorkDocumentChangeIdentity } from './work-document-changes';
3
+ interface DocumentParagraphFormattingTrackingOptions {
4
+ createChange: () => WorkDocumentChangeIdentity;
5
+ }
6
+ export declare function trackDocumentParagraphFormattingTransaction(transaction: Transaction, state: EditorState, options: DocumentParagraphFormattingTrackingOptions): boolean;
7
+ export {};
@@ -0,0 +1,8 @@
1
+ export declare const DOCUMENT_PARAGRAPH_CHANGE_ATTRIBUTES: readonly ["paragraphChangeKind", "paragraphChangeId", "paragraphChangeActorId", "paragraphChangeAuthor", "paragraphChangeDate", "paragraphChangeBefore"];
2
+ export declare const DOCUMENT_PARAGRAPH_FORMAT_ATTRIBUTES: readonly ["textAlign", "paragraphDirection", "indentLevel", "rightIndent", "firstLineIndent", "spaceBefore", "spaceAfter", "lineHeight", "lineRule", "autoLineHeight", "keepLines", "keepWithNext", "pageBreakBefore", "widowControl", "contextualSpacing", "outlineLevel", "tabStops", "paragraphBorders", "paragraphShading", "defaultCollapsed"];
3
+ export type DocumentParagraphFormatAttribute = (typeof DOCUMENT_PARAGRAPH_FORMAT_ATTRIBUTES)[number];
4
+ export type DocumentParagraphFormattingSnapshot = Record<DocumentParagraphFormatAttribute, unknown>;
5
+ export declare function serializeDocumentParagraphFormatting(attributes: Record<string, unknown>): string;
6
+ export declare function parseDocumentParagraphFormatting(value: unknown): DocumentParagraphFormattingSnapshot | null;
7
+ export declare function restoredDocumentParagraphAttributes(attributes: Record<string, unknown>, serialized: unknown): Record<string, unknown> | null;
8
+ export declare function clearDocumentParagraphChangeAttributes(attributes: Record<string, unknown>): Record<string, unknown>;
@@ -10,6 +10,7 @@ import { type ImportedDocxListMarkers } from './work-docx-list-import';
10
10
  import { type ImportedDocxParagraphAlignmentMarkers } from './work-docx-paragraph-alignment-import';
11
11
  import { type ImportedDocxParagraphDirectionMarkers } from './work-docx-paragraph-direction-import';
12
12
  import { type ImportedDocxParagraphIdentityMarkers } from './work-docx-paragraph-identity-import';
13
+ import { type ImportedDocxParagraphFormattingChangeMarkers } from './work-docx-paragraph-format-change-import';
13
14
  import { type ImportedDocxParagraphIndentMarkers } from './work-docx-paragraph-indent-import';
14
15
  import { type ImportedDocxParagraphPaginationMarkers } from './work-docx-paragraph-pagination-import';
15
16
  import { type ImportedDocxParagraphBorderMarkers } from './work-docx-paragraph-borders-import';
@@ -20,6 +21,7 @@ import { type ImportedDocxParagraphTabStopMarkers } from './work-docx-tab-stop-i
20
21
  import { type ImportedDocxTableCellMarkers } from './work-docx-table-cell-import';
21
22
  import { type ImportedDocxTableRowMarkers } from './work-docx-table-row-import';
22
23
  import { type ImportedDocxTableSizingMarkers } from './work-docx-table-sizing-import';
24
+ import { OoxmlPackage } from './work-ooxml-package';
23
25
  import type { WorkDocumentContent, WorkDocumentSectionLayout } from './work-types';
24
26
  type ImportedDocumentLayout = Omit<WorkDocumentContent, 'type' | 'html'>;
25
27
  export interface PreparedDocxImport {
@@ -39,6 +41,7 @@ export interface PreparedDocxImport {
39
41
  listMarkers: ImportedDocxListMarkers;
40
42
  imageLayoutMarkers: ImportedDocxImageLayoutMarkers;
41
43
  paragraphIdentityMarkers: ImportedDocxParagraphIdentityMarkers;
44
+ paragraphFormattingChangeMarkers: ImportedDocxParagraphFormattingChangeMarkers;
42
45
  paragraphAlignmentMarkers: ImportedDocxParagraphAlignmentMarkers;
43
46
  paragraphDirectionMarkers: ImportedDocxParagraphDirectionMarkers;
44
47
  paragraphIndentMarkers: ImportedDocxParagraphIndentMarkers;
@@ -54,7 +57,7 @@ export interface PreparedDocxImport {
54
57
  bibliography?: WorkDocumentContent['bibliography'];
55
58
  trackChanges: boolean;
56
59
  }
57
- export declare function prepareDocxImport(buffer: ArrayBuffer): Promise<PreparedDocxImport>;
58
- export declare function applyDocxSectionsToHtml(html: string, sections: PreparedDocxImport['sections'], captionMarkers?: ImportedDocxCaptionMarkers, bookmarkMarkers?: ImportedDocxBookmarkMarkers, changeMarkers?: ImportedDocxChangeMarkers, commentMarkers?: ImportedDocxCommentMarkers, fieldMarkers?: ImportedDocxFieldMarkers, equationMarkers?: ImportedDocxEquationMarkers, citationMarkers?: ImportedDocxCitationMarkers, listMarkers?: ImportedDocxListMarkers, imageLayoutMarkers?: ImportedDocxImageLayoutMarkers, paragraphIdentityMarkers?: ImportedDocxParagraphIdentityMarkers, paragraphAlignmentMarkers?: ImportedDocxParagraphAlignmentMarkers, runFormattingMarkers?: ImportedDocxRunFormattingMarkers, paragraphDirectionMarkers?: ImportedDocxParagraphDirectionMarkers, paragraphIndentMarkers?: ImportedDocxParagraphIndentMarkers, paragraphSpacingMarkers?: ImportedDocxParagraphSpacingMarkers, paragraphBorderMarkers?: ImportedDocxParagraphBorderMarkers, paragraphShadingMarkers?: ImportedDocxParagraphShadingMarkers, paragraphPaginationMarkers?: ImportedDocxParagraphPaginationMarkers, bibliography?: WorkDocumentContent['bibliography'], tabStopMarkers?: ImportedDocxParagraphTabStopMarkers, tableCellMarkers?: ImportedDocxTableCellMarkers, tableRowMarkers?: ImportedDocxTableRowMarkers, tableSizingMarkers?: ImportedDocxTableSizingMarkers): string;
60
+ export declare function prepareDocxImport(buffer: ArrayBuffer, sourcePackage?: OoxmlPackage): Promise<PreparedDocxImport>;
61
+ export declare function applyDocxSectionsToHtml(html: string, sections: PreparedDocxImport['sections'], captionMarkers?: ImportedDocxCaptionMarkers, bookmarkMarkers?: ImportedDocxBookmarkMarkers, changeMarkers?: ImportedDocxChangeMarkers, commentMarkers?: ImportedDocxCommentMarkers, fieldMarkers?: ImportedDocxFieldMarkers, equationMarkers?: ImportedDocxEquationMarkers, citationMarkers?: ImportedDocxCitationMarkers, listMarkers?: ImportedDocxListMarkers, imageLayoutMarkers?: ImportedDocxImageLayoutMarkers, paragraphIdentityMarkers?: ImportedDocxParagraphIdentityMarkers, paragraphFormattingChangeMarkers?: ImportedDocxParagraphFormattingChangeMarkers, paragraphAlignmentMarkers?: ImportedDocxParagraphAlignmentMarkers, runFormattingMarkers?: ImportedDocxRunFormattingMarkers, paragraphDirectionMarkers?: ImportedDocxParagraphDirectionMarkers, paragraphIndentMarkers?: ImportedDocxParagraphIndentMarkers, paragraphSpacingMarkers?: ImportedDocxParagraphSpacingMarkers, paragraphBorderMarkers?: ImportedDocxParagraphBorderMarkers, paragraphShadingMarkers?: ImportedDocxParagraphShadingMarkers, paragraphPaginationMarkers?: ImportedDocxParagraphPaginationMarkers, bibliography?: WorkDocumentContent['bibliography'], tabStopMarkers?: ImportedDocxParagraphTabStopMarkers, tableCellMarkers?: ImportedDocxTableCellMarkers, tableRowMarkers?: ImportedDocxTableRowMarkers, tableSizingMarkers?: ImportedDocxTableSizingMarkers): string;
59
62
  export declare function readDocxLayout(buffer: ArrayBuffer): Promise<ImportedDocumentLayout>;
60
63
  export {};
@@ -11,3 +11,4 @@ export interface ImportedDocxParagraphAlignmentMarkers {
11
11
  export declare function markDocxParagraphAlignments(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphAlignmentMarkers;
12
12
  export declare function applyImportedDocxParagraphAlignmentMarkers(document: Document, markers: ImportedDocxParagraphAlignmentMarkers): void;
13
13
  export declare function hasImportedDocxParagraphAlignmentMarkers(markers: ImportedDocxParagraphAlignmentMarkers): boolean;
14
+ export declare function resolveDocxParagraphAlignment(propertySources: readonly Element[]): ImportedDocxParagraphAlignment | null;
@@ -18,6 +18,7 @@ export interface ResolvedDocxParagraphBorders {
18
18
  }
19
19
  export declare function markDocxParagraphBorders(document: Document, styleSource?: DocxParagraphStyleSource, themeSource?: DocxThemeSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphBorderMarkers;
20
20
  export declare function resolveDocxParagraphBordersForParagraph(paragraph: Element, styleSource?: DocxParagraphStyleSource, themeSource?: DocxThemeSource, tableStyleSource?: DocxTableStyleSource): ResolvedDocxParagraphBorders;
21
+ export declare function resolveDocxParagraphBordersFromSources(propertySources: readonly Element[], themeSource?: DocxThemeSource): ResolvedDocxParagraphBorders;
21
22
  export declare function applyImportedDocxParagraphBorderMarkers(document: Document, markers: ImportedDocxParagraphBorderMarkers): void;
22
23
  export declare function hasImportedDocxParagraphBorderMarkers(markers: ImportedDocxParagraphBorderMarkers): boolean;
23
24
  export declare function parseDirectDocxParagraphBorders(properties: Element, themeSource?: DocxThemeSource): DocumentParagraphBorders | null | undefined;
@@ -11,3 +11,4 @@ export interface ImportedDocxParagraphDirectionMarkers {
11
11
  export declare function markDocxParagraphDirections(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphDirectionMarkers;
12
12
  export declare function applyImportedDocxParagraphDirectionMarkers(document: Document, markers: ImportedDocxParagraphDirectionMarkers): void;
13
13
  export declare function hasImportedDocxParagraphDirectionMarkers(markers: ImportedDocxParagraphDirectionMarkers): boolean;
14
+ export declare function resolveDocxParagraphDirection(propertySources: readonly Element[]): DocumentParagraphDirection | null;
@@ -0,0 +1,13 @@
1
+ interface DocxParagraphFormattingChangePatch {
2
+ marker: string;
3
+ id: number;
4
+ author: string;
5
+ date: string;
6
+ before: string;
7
+ }
8
+ export declare class DocxParagraphFormattingChangePatchCollector {
9
+ readonly patches: DocxParagraphFormattingChangePatch[];
10
+ register(element: HTMLElement, id: number): string | null;
11
+ }
12
+ export declare function patchDocxParagraphFormattingChanges(buffer: ArrayBuffer, patches: readonly DocxParagraphFormattingChangePatch[]): Promise<ArrayBuffer>;
13
+ export {};
@@ -0,0 +1,17 @@
1
+ import { type DocxParagraphStyleSource } from './work-docx-paragraph-styles';
2
+ import { type DocxTableStyleSource } from './work-docx-table-styles';
3
+ import { type DocxThemeSource } from './work-docx-theme';
4
+ export interface ImportedDocxParagraphFormattingChangeMarker {
5
+ marker: string;
6
+ id: string;
7
+ author: string;
8
+ date: string;
9
+ before: string;
10
+ }
11
+ export interface ImportedDocxParagraphFormattingChangeMarkers {
12
+ paragraphs: ImportedDocxParagraphFormattingChangeMarker[];
13
+ }
14
+ export declare function markDocxParagraphFormattingChanges(document: Document, styleSource?: DocxParagraphStyleSource, themeSource?: DocxThemeSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphFormattingChangeMarkers;
15
+ export declare function applyImportedDocxParagraphFormattingChangeMarkers(document: Document, markers: ImportedDocxParagraphFormattingChangeMarkers): void;
16
+ export declare function hasImportedDocxParagraphFormattingChangeMarkers(markers: ImportedDocxParagraphFormattingChangeMarkers): boolean;
17
+ export declare function isSupportedDocxParagraphFormattingChange(change: Element): boolean;
@@ -11,3 +11,4 @@ export interface ImportedDocxParagraphIndentMarkers {
11
11
  export declare function markDocxParagraphIndents(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphIndentMarkers;
12
12
  export declare function applyImportedDocxParagraphIndentMarkers(document: Document, markers: ImportedDocxParagraphIndentMarkers): void;
13
13
  export declare function hasImportedDocxParagraphIndentMarkers(markers: ImportedDocxParagraphIndentMarkers): boolean;
14
+ export declare function resolveDocxParagraphIndent(propertySources: readonly Element[]): DocumentParagraphIndent;
@@ -16,3 +16,4 @@ export interface ImportedDocxParagraphPaginationMarkers {
16
16
  export declare function markDocxParagraphPagination(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphPaginationMarkers;
17
17
  export declare function applyImportedDocxParagraphPaginationMarkers(document: Document, markers: ImportedDocxParagraphPaginationMarkers): void;
18
18
  export declare function hasImportedDocxParagraphPaginationMarkers(markers: ImportedDocxParagraphPaginationMarkers): boolean;
19
+ export declare function resolveDocxParagraphPagination(sources: readonly Element[]): ImportedDocxParagraphPagination;
@@ -16,3 +16,4 @@ export declare function applyImportedDocxParagraphShadingMarkers(document: Docum
16
16
  export declare function hasImportedDocxParagraphShadingMarkers(markers: ImportedDocxParagraphShadingMarkers): boolean;
17
17
  export declare function parseDocxParagraphShadingElement(element: Element, themeSource?: DocxThemeSource): DocumentParagraphShading | null;
18
18
  export declare function parseDirectDocxParagraphShading(properties: Element, themeSource?: DocxThemeSource): DocumentParagraphShading | null | undefined;
19
+ export declare function resolveDocxParagraphShadingFromSources(propertySources: readonly Element[], themeSource?: DocxThemeSource): DocumentParagraphShading | null;
@@ -11,3 +11,4 @@ export interface ImportedDocxParagraphSpacingMarkers {
11
11
  export declare function markDocxParagraphSpacing(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphSpacingMarkers;
12
12
  export declare function applyImportedDocxParagraphSpacingMarkers(document: Document, markers: ImportedDocxParagraphSpacingMarkers): void;
13
13
  export declare function hasImportedDocxParagraphSpacingMarkers(markers: ImportedDocxParagraphSpacingMarkers): boolean;
14
+ export declare function resolveDocxParagraphSpacing(propertySources: readonly Element[]): Partial<DocumentParagraphSpacing>;
@@ -12,3 +12,4 @@ export interface ImportedDocxParagraphTabStopMarkers {
12
12
  export declare function markDocxParagraphTabStops(document: Document, styleSource?: DocxParagraphStyleSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxParagraphTabStopMarkers;
13
13
  export declare function applyImportedDocxParagraphTabStopMarkers(document: Document, markers: ImportedDocxParagraphTabStopMarkers): void;
14
14
  export declare function hasImportedDocxParagraphTabStopMarkers(markers: ImportedDocxParagraphTabStopMarkers): boolean;
15
+ export declare function resolveDocxParagraphTabStops(sources: readonly Element[]): DocumentTabStop[];
@@ -1 +1,7 @@
1
- export declare function materializeWorkFile(file: File): Promise<File>;
1
+ import { WorkFileImportController } from './work-file-import';
2
+ export interface MaterializedWorkFile {
3
+ bytes: ArrayBuffer;
4
+ file: File;
5
+ }
6
+ export declare function materializeWorkFile(file: File, controller?: WorkFileImportController): Promise<File>;
7
+ export declare function materializeWorkFileSource(file: File, controller: WorkFileImportController): Promise<MaterializedWorkFile>;
@@ -0,0 +1,28 @@
1
+ export type WorkFileImportStage = 'reading' | 'parsing' | 'analyzing' | 'finalizing';
2
+ export interface WorkFileImportProgress {
3
+ stage: WorkFileImportStage;
4
+ stageProgress: number;
5
+ progress: number;
6
+ bytesRead: number;
7
+ totalBytes: number;
8
+ }
9
+ export interface WorkFileImportOptions {
10
+ signal?: AbortSignal;
11
+ onProgress?: (progress: WorkFileImportProgress) => void;
12
+ }
13
+ export interface WorkFileImportContext {
14
+ bytes: ArrayBuffer;
15
+ controller: WorkFileImportController;
16
+ }
17
+ export declare class WorkFileImportController {
18
+ private readonly options;
19
+ readonly totalBytes: number;
20
+ private progress;
21
+ constructor(options: WorkFileImportOptions, totalBytes: number);
22
+ get signal(): AbortSignal | undefined;
23
+ throwIfAborted(): void;
24
+ report(stage: WorkFileImportStage, stageProgress: number, bytesRead?: number): void;
25
+ checkpoint(stage: WorkFileImportStage, stageProgress: number): Promise<void>;
26
+ yieldToMainThread(): Promise<void>;
27
+ complete(): void;
28
+ }
@@ -1,8 +1,9 @@
1
1
  export { WORK_IMPORT_ACCEPT } from './work-file-contract';
2
+ import { type WorkFileImportOptions } from './work-file-import';
2
3
  import { type WorkPresentationExportOptions } from './work-presentation-file-io';
3
4
  import { type WorkArtifact, type WorkArtifactKind } from './work-types';
4
5
  export type WorkArtifactExportOptions = WorkPresentationExportOptions;
5
- export declare function importWorkFile(file: File): Promise<WorkArtifact>;
6
+ export declare function importWorkFile(file: File, options?: WorkFileImportOptions): Promise<WorkArtifact>;
6
7
  export declare function exportWorkArtifact(artifact: WorkArtifact, options?: WorkArtifactExportOptions): Promise<void>;
7
8
  export declare function createWorkArtifactBlob(artifact: WorkArtifact, options?: WorkArtifactExportOptions): Promise<Blob>;
8
9
  export declare function workKindForFile(file: File): WorkArtifactKind | null;
@@ -1,3 +1,4 @@
1
+ import type { WorkFileImportContext } from './work-file-import';
1
2
  import type { WorkArtifact } from './work-types';
2
- export declare function importWorkMarkdownFile(file: File): Promise<WorkArtifact>;
3
+ export declare function importWorkMarkdownFile(file: File, context?: WorkFileImportContext): Promise<WorkArtifact>;
3
4
  export declare function createWorkMarkdownBlob(artifact: WorkArtifact): Blob;
@@ -1,9 +1,10 @@
1
1
  import type { WorkBook } from 'xlsx';
2
+ import { OoxmlPackage } from './work-ooxml-package';
2
3
  import type { WorkCompatibilityReport } from './work-types';
3
4
  interface ConversionMessage {
4
5
  type: string;
5
6
  message: string;
6
7
  }
7
- export declare function analyzeDocxCompatibility(file: File, messages: ConversionMessage[]): Promise<WorkCompatibilityReport>;
8
- export declare function analyzeSpreadsheetCompatibility(file: File, extension: string, workbook: WorkBook): Promise<WorkCompatibilityReport | null>;
8
+ export declare function analyzeDocxCompatibility(file: File, messages: ConversionMessage[], sourcePackage?: OoxmlPackage | null): Promise<WorkCompatibilityReport>;
9
+ export declare function analyzeSpreadsheetCompatibility(file: File, extension: string, workbook: WorkBook, sourcePackage?: OoxmlPackage | null): Promise<WorkCompatibilityReport | null>;
9
10
  export {};
@@ -3,4 +3,4 @@ export interface PptxImportResult {
3
3
  content: WorkPresentationContent;
4
4
  compatibility: WorkCompatibilityReport;
5
5
  }
6
- export declare function importPptxPresentation(file: File): Promise<PptxImportResult>;
6
+ export declare function importPptxPresentation(file: File, sourceBytes?: ArrayBuffer): Promise<PptxImportResult>;
@@ -1,3 +1,4 @@
1
+ import type { WorkFileImportContext } from './work-file-import';
1
2
  import type { WorkArtifact } from './work-types';
2
3
  type PptxConstructor = typeof import('pptxgenjs').default;
3
4
  declare global {
@@ -9,7 +10,7 @@ export interface WorkPresentationExportOptions {
9
10
  pptxRuntimeUrl?: string;
10
11
  }
11
12
  export declare const defaultPptxRuntimeUrl: string;
12
- export declare function importWorkPresentationFile(file: File): Promise<WorkArtifact>;
13
+ export declare function importWorkPresentationFile(file: File, context?: WorkFileImportContext): Promise<WorkArtifact>;
13
14
  export declare function exportWorkPresentationArtifact(artifact: WorkArtifact, options?: WorkPresentationExportOptions): Promise<void>;
14
15
  export declare function createWorkPresentationBlob(artifact: WorkArtifact, options?: WorkPresentationExportOptions): Promise<Blob>;
15
16
  export {};
@@ -27,6 +27,7 @@ export interface FortuneSheetProtectionAuthority {
27
27
  hintText: string;
28
28
  defaultSheetHintText: string;
29
29
  allowRangeList: FortuneSheetEditableRange[];
30
+ cellProtectionRanges: SpreadsheetCellProtectionRange[];
30
31
  xlsxAttributes?: Record<string, string>;
31
32
  }
32
33
  export interface SpreadsheetCellProtectionRange {
@@ -37,6 +38,7 @@ export interface SpreadsheetCellProtectionRange {
37
38
  export declare function defaultSheetProtectionAuthority(enabled?: boolean): FortuneSheetProtectionAuthority;
38
39
  export declare function sheetProtectionAuthority(sheet: Sheet): FortuneSheetProtectionAuthority;
39
40
  export declare function normalizeSheetProtectionAuthority(source: unknown): FortuneSheetProtectionAuthority;
41
+ export declare function importedSheetProtectionAuthority(authority: FortuneSheetProtectionAuthority | undefined, cellProtectionRanges: SpreadsheetCellProtectionRange[]): FortuneSheetProtectionAuthority | undefined;
40
42
  export declare function withSheetProtection(sheet: Sheet, enabled: boolean): Sheet;
41
43
  export declare function withSheetSelectionPermissions(sheet: Sheet, permissions: {
42
44
  selectLockedCells?: boolean;
@@ -106,7 +106,7 @@ export interface WorkDocumentContent {
106
106
  comments?: WorkDocumentComment[];
107
107
  bibliography?: WorkDocumentBibliography;
108
108
  }
109
- export type WorkDocumentChangeKind = 'insertion' | 'deletion' | 'formatting';
109
+ export type WorkDocumentChangeKind = 'insertion' | 'deletion' | 'formatting' | 'paragraph-formatting';
110
110
  export type WorkDocumentChangeDecisionAction = 'accept' | 'reject';
111
111
  /**
112
112
  * Immutable audit record created when an editor accepts or rejects one
@@ -192,11 +192,33 @@ export interface WorkSpreadsheetContent {
192
192
  pageBreaks?: WorkSpreadsheetPageBreaks[];
193
193
  pageSetups?: WorkSpreadsheetPageSetup[];
194
194
  }
195
+ export interface WorkSpreadsheetCellRange {
196
+ row: [number, number];
197
+ column: [number, number];
198
+ }
199
+ export interface WorkSpreadsheetDataValidationItem {
200
+ type: string;
201
+ type2: string;
202
+ rangeTxt: string;
203
+ value1: string;
204
+ value2: string;
205
+ validity: string;
206
+ remote: boolean;
207
+ prohibitInput: boolean;
208
+ hintShow: boolean;
209
+ hintValue: string;
210
+ checked?: boolean;
211
+ }
212
+ export interface WorkSpreadsheetDataValidationRange {
213
+ ranges: WorkSpreadsheetCellRange[];
214
+ item: WorkSpreadsheetDataValidationItem;
215
+ }
195
216
  export type WorkSpreadsheetSheet = Omit<Sheet, 'images'> & {
196
217
  images?: WorkSpreadsheetImage[];
197
218
  charts?: WorkSpreadsheetChart[];
198
219
  pivotTables?: WorkSpreadsheetPivotTable[];
199
220
  formulaMetadata?: WorkSpreadsheetFormulaMetadata;
221
+ dataValidationRanges?: WorkSpreadsheetDataValidationRange[];
200
222
  };
201
223
  export type WorkSpreadsheetPivotAggregation = 'sum' | 'count' | 'counta' | 'average' | 'max' | 'min' | 'product' | 'stdDev' | 'stdDevP' | 'var' | 'varP';
202
224
  export interface WorkSpreadsheetPivotValue {
@@ -1,11 +1,12 @@
1
1
  import type { Sheet } from '@fortune-sheet/core';
2
+ import { OoxmlPackage } from './work-ooxml-package';
2
3
  import { type FortuneConditionalFormatRule } from './work-xlsx-conditional-format';
3
4
  import { type XlsxProtectionFeatures } from './work-xlsx-protection';
4
5
  import { type XlsxManualPageBreaks } from './work-xlsx-page-breaks';
5
6
  import { type XlsxWorksheetChart } from './work-xlsx-charts';
6
7
  import { type XlsxWorksheetImage } from './work-xlsx-images';
7
8
  import { type XlsxPageSetup } from './work-xlsx-page-setup';
8
- import type { WorkSpreadsheetContent } from './work-types';
9
+ import type { WorkSpreadsheetContent, WorkSpreadsheetDataValidationItem } from './work-types';
9
10
  type FrozenPane = NonNullable<Sheet['frozen']>;
10
11
  export interface XlsxDataValidation {
11
12
  references: string[];
@@ -21,19 +22,8 @@ export interface XlsxSheetFeatures {
21
22
  images: XlsxWorksheetImage[];
22
23
  charts: XlsxWorksheetChart[];
23
24
  }
24
- export interface FortuneDataValidationItem {
25
- type: string;
26
- type2: string;
27
- rangeTxt: string;
28
- value1: string;
29
- value2: string;
30
- validity: string;
31
- remote: boolean;
32
- prohibitInput: boolean;
33
- hintShow: boolean;
34
- hintValue: string;
35
- checked?: boolean;
36
- }
25
+ export type FortuneDataValidationItem = WorkSpreadsheetDataValidationItem;
37
26
  export declare function readXlsxSheetFeatures(buffer: ArrayBuffer): Promise<Map<string, XlsxSheetFeatures>>;
27
+ export declare function readXlsxSheetFeaturesFromPackage(archive: OoxmlPackage): Promise<Map<string, XlsxSheetFeatures>>;
38
28
  export declare function patchXlsxSheetFeatures(buffer: ArrayBuffer, content: WorkSpreadsheetContent): Promise<ArrayBuffer>;
39
29
  export {};
Binary file
package/dist/styles.css CHANGED
@@ -9082,6 +9082,10 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
9082
9082
  text-decoration: none;
9083
9083
  }
9084
9084
 
9085
+ .work-document-editor :is(p, h1, h2, h3, h4, h5, h6)[data-document-change][data-change-kind="paragraph-formatting"], .work-pdf-export-page.document :is(p, h1, h2, h3, h4, h5, h6)[data-document-change][data-change-kind="paragraph-formatting"] {
9086
+ box-shadow: inset 3px 0 #8b5cf6;
9087
+ }
9088
+
9085
9089
  .work-document-list-tools {
9086
9090
  align-items: center;
9087
9091
  gap: 2px;
@@ -12039,6 +12043,10 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
12039
12043
  border-left: 3px solid #6d5bd0;
12040
12044
  }
12041
12045
 
12046
+ .work-document-change-decisions li[data-document-change-kind="paragraph-formatting"] {
12047
+ border-left: 3px solid #8b5cf6;
12048
+ }
12049
+
12042
12050
  .work-document-change-decisions li > strong {
12043
12051
  text-overflow: ellipsis;
12044
12052
  white-space: nowrap;
@@ -222,6 +222,18 @@ rejecting every revision requires confirmation, and an empty revision pane does
222
222
  not retain disabled bulk controls. Deleting a comment confirms that its thread
223
223
  and any unsent reply will also be removed.
224
224
 
225
+ Paragraph formatting is a node-level review concern rather than an inline
226
+ mark. When tracking is active, one formatting transaction compares the complete
227
+ canonical paragraph-property set before and after each affected paragraph or
228
+ heading. A changed set receives one shared `paragraph-formatting` identity and
229
+ the first complete prior snapshot; later edits retain that original review
230
+ baseline. Accept clears only the revision attributes. Reject restores the
231
+ validated snapshot without changing child content. Both decisions are atomic
232
+ across every node with the same identity and have their own undo boundary.
233
+ DOCX import/export maps that model to strict or transitional `w:pPrChange`,
234
+ while Yjs stores the same node attributes and immutable decision audit without a
235
+ parallel transport model.
236
+
225
237
  Selected document text has a typed host-owned context-menu boundary.
226
238
  `getSelectionMenuItems` receives an immutable snapshot containing the selected
227
239
  plain text and structured fragment, bounded adjacent text, synchronized HTML,
@@ -350,6 +362,12 @@ real DOCX with 120 native OOXML insertions and proves bounded mounting,
350
362
  first/last focus, the 120-to-119 decision transition, spacer geometry, and zero
351
363
  console or page errors.
352
364
 
365
+ The public formatting fixture also exercises the non-windowed review boundary
366
+ with independent character- and paragraph-formatting cards. Focused A3S Test
367
+ suites reject each kind separately, verify that text and the other revision
368
+ remain intact, and prove full paragraph alignment, indentation, spacing, and
369
+ line-height restoration with clean browser diagnostics.
370
+
353
371
  Spreadsheet now uses a persistent browser Rust/WASM calculation session. The
354
372
  editor initializes it with a sparse workbook replacement, sends bounded cell
355
373
  patches from stable Fortune cell operations, and requests only the dirty