@a3s-lab/office 0.11.0 → 0.13.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/README.md +121 -6
- package/dist/0~1403.js +20 -12
- package/dist/0~2805.js +241 -241
- package/dist/0~4980.js +1 -1
- package/dist/0~5050.js +1 -20
- package/dist/0~5093.js +547 -547
- package/dist/0~7048.js +31 -29
- package/dist/0~document-editor.js +694 -90
- package/dist/0~pdf-viewer.js +41 -10
- package/dist/0~presentation-editor.js +8 -6
- package/dist/0~spreadsheet-editor.js +4272 -2753
- package/dist/0~work-document-import-worker-client.js +237 -0
- package/dist/0~work-docx-export.js +1 -1
- package/dist/0~work-docx-import.js +3 -3
- package/dist/0~work-docx-large-document-import.js +559 -0
- package/dist/0~work-office-diagnostics.js +51 -35
- package/dist/0~work-pptx-import.js +2 -2
- package/dist/4104.js +4127 -3037
- package/dist/432.js +51 -7
- package/dist/4476.js +280 -69
- package/dist/5184.js +24 -2
- package/dist/{8928.js → 6282.js} +2338 -93
- package/dist/8715.js +1201 -1156
- package/dist/9356.js +128 -8
- package/dist/core.d.ts +1 -0
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/features/work/editors/document-editor-support.d.ts +1 -9
- package/dist/internal/features/work/editors/document-external-content.d.ts +1 -1
- package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +3 -1
- package/dist/internal/features/work/editors/presentation-slide-thumbnail.d.ts +3 -2
- package/dist/internal/features/work/editors/presentation-thumbnail-rail.d.ts +2 -1
- package/dist/internal/features/work/editors/presentation-workspace.d.ts +2 -1
- package/dist/internal/features/work/editors/spreadsheet-border-ribbon.d.ts +5 -0
- package/dist/internal/features/work/editors/spreadsheet-calculation-projection.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border.d.ts +14 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-fill-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-fill.d.ts +12 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-range.d.ts +14 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +159 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +8 -4
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +8 -1
- package/dist/internal/features/work/editors/spreadsheet-home-format-ribbon.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-in-place-workbook-sync.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-operation-projection.d.ts +14 -0
- package/dist/internal/features/work/editors/spreadsheet-structure-selection.d.ts +7 -0
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +5 -0
- package/dist/internal/features/work/editors/use-presentation-design-commands.d.ts +2 -1
- package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +2 -1
- package/dist/internal/features/work/editors/use-spreadsheet-workbook-sync.d.ts +2 -1
- package/dist/internal/features/work/spreadsheet-history-value.d.ts +1 -0
- package/dist/internal/features/work/spreadsheet-sparse.d.ts +10 -0
- package/dist/internal/features/work/work-document-chunk-geometry.d.ts +28 -0
- package/dist/internal/features/work/work-document-chunk-node.d.ts +23 -0
- package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
- package/dist/internal/features/work/work-document-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-document-html-fingerprint.d.ts +15 -0
- package/dist/internal/features/work/work-document-import-worker-client.d.ts +13 -0
- package/dist/internal/features/work/work-document-import-worker-protocol.d.ts +36 -0
- package/dist/internal/features/work/work-document-import.worker.d.ts +1 -0
- package/dist/internal/features/work/work-document-incremental-layout.d.ts +1 -1
- package/dist/internal/features/work/work-document-integrity-index.d.ts +14 -0
- package/dist/internal/features/work/work-document-lazy-block.d.ts +3 -0
- package/dist/internal/features/work/work-document-lazy-html.d.ts +21 -0
- package/dist/internal/features/work/work-document-lazy-model.d.ts +29 -0
- package/dist/internal/features/work/work-document-lazy-pagination-measurement.d.ts +3 -0
- package/dist/internal/features/work/work-document-lazy-preview.d.ts +21 -0
- package/dist/internal/features/work/work-document-lazy-update.d.ts +14 -0
- package/dist/internal/features/work/work-document-model.d.ts +18 -2
- package/dist/internal/features/work/work-document-page-surface-registry.d.ts +16 -0
- package/dist/internal/features/work/work-document-pagination-dom.d.ts +1 -0
- package/dist/internal/features/work/work-document-pagination-types.d.ts +1 -0
- package/dist/internal/features/work/work-document-pagination.d.ts +1 -1
- package/dist/internal/features/work/work-document-text-statistics.d.ts +25 -0
- package/dist/internal/features/work/work-document-windowing.d.ts +23 -0
- package/dist/internal/features/work/work-docx-import.d.ts +2 -1
- package/dist/internal/features/work/work-docx-large-document-import.d.ts +35 -0
- package/dist/internal/features/work/work-docx-large-document-parser.d.ts +29 -0
- package/dist/internal/features/work/work-file-data.d.ts +7 -1
- package/dist/internal/features/work/work-file-import.d.ts +33 -0
- package/dist/internal/features/work/work-file-io.d.ts +5 -4
- package/dist/internal/features/work/work-file-kind.d.ts +5 -0
- package/dist/internal/features/work/work-markdown-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-office-diagnostics.d.ts +12 -2
- package/dist/internal/features/work/work-ooxml-package.d.ts +8 -0
- package/dist/internal/features/work/work-pptx-import.d.ts +1 -1
- package/dist/internal/features/work/work-presentation-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-presentation-layouts.d.ts +7 -1
- package/dist/internal/features/work/work-repository.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-compatibility-summary.d.ts +10 -0
- package/dist/internal/features/work/work-spreadsheet-file-export.d.ts +2 -0
- package/dist/internal/features/work/work-spreadsheet-file-import.d.ts +3 -0
- package/dist/internal/features/work/work-spreadsheet-import-diagnostics.d.ts +2 -0
- package/dist/internal/features/work/work-spreadsheet-import-worker-client.d.ts +6 -0
- package/dist/internal/features/work/work-spreadsheet-import-worker-protocol.d.ts +32 -0
- package/dist/internal/features/work/work-spreadsheet-import.worker.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-matrix-profile.d.ts +64 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan-worker-client.d.ts +6 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan-worker-protocol.d.ts +49 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan.worker.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-protection.d.ts +2 -0
- package/dist/internal/features/work/work-types.d.ts +22 -0
- package/dist/internal/features/work/work-xlsx-formula-diagnostics.d.ts +3 -1
- package/dist/internal/features/work/work-xlsx-formulas.d.ts +2 -1
- package/dist/internal/features/work/work-xlsx-interop.d.ts +8 -17
- package/dist/internal/features/work/work-xlsx-pivot-diagnostics.d.ts +2 -1
- package/dist/internal/features/work/work-xlsx-plain-fast-path.d.ts +54 -0
- package/dist/internal/features/work/work-xlsx-style-gate.d.ts +1 -0
- package/dist/internal/features/work/work-xlsx-worksheet-scan.d.ts +12 -0
- package/dist/internal/features/work/work-xlsx-worksheet.d.ts +12 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +31 -29
- package/dist/react.d.ts +7 -1
- package/dist/styles.css +440 -3
- package/dist/work-document-import.worker.js +558 -0
- package/dist/work-spreadsheet-import.worker.js +24745 -0
- package/dist/work-spreadsheet-import.worker.js.LICENSE.txt +3 -0
- package/dist/work-spreadsheet-package-scan.worker.js +4157 -0
- package/dist/work-spreadsheet-package-scan.worker.js.LICENSE.txt +11 -0
- package/docs/latest/en/browser-editor-architecture.md +351 -15
- package/package.json +26 -4
|
@@ -16,15 +16,15 @@ import extension_underline from "@tiptap/extension-underline";
|
|
|
16
16
|
import starter_kit from "@tiptap/starter-kit";
|
|
17
17
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
18
18
|
import { TableMap, isInTable, selectedRect } from "@tiptap/pm/tables";
|
|
19
|
+
import { documentTableSizing, transferChangedDocumentTextStatistics, documentPageBordersVisible, DOCUMENT_PAGE_BORDER_EDGES, documentTableRowOptions, normalizeDocumentColumns, clampDocumentMargin, materializeLazyDocumentEditorRoot, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, documentCitationCount, nextDocumentTabAlignment, normalizedTabPosition, isDocumentParagraphArtBorderStyle, resolveDocumentPageBorders, documentLazyHtmlChunkFragment, DOCUMENT_CHUNK_VISIBLE_IDS_META, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, collectDocumentTextLayoutParagraphs, documentBulletListStyle, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, documentOrderedListState, normalizeDocumentPageChrome, documentTextStatistics, documentPageMarginsForLayout, invalidateDocumentLazyHtmlProjection, documentTableCellFormat, normalizeDocumentPageGeometry, normalizeDocumentImageLayer, documentImageProperties, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, activeDocumentSection, DocumentParagraphFormatting, normalizeDocumentHtml, documentInitialSectionLayout, documentModelHasTrustedInitialIntegrityFeatures, documentModelUsesWindowing, documentParagraphDirection, documentParagraphPagination, documentPageChromeLegacyFields, documentChunkMountedIds, collectDocumentCommentAnchors, canChangeDocumentIndent, DocumentSuperscript, documentSectionById, activeDocumentBookmark, DocumentEquation, documentLazyHtmlProjectionFingerprint, documentLazyHtmlProjection, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, mountWorkLiveDocumentCapture, registerDocumentPageSurfaceGeometry, syncDocumentContentFromHtml, editorDocumentCaptionTargets, resolveDocumentPageChrome, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, editorDocumentBookmarkReferenceTargets, serializeWorkDocumentNode, DOCUMENT_CHUNK_PAGINATION_META, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, documentModelForContent, selectedDocumentChunkId, documentCommentViews, documentParagraphSpacing, normalizeDocumentTabStops, patchDocumentLazyHtmlProjection, documentBookmarkNameExists, collectDocumentChanges, DocumentImage, resolveDocumentPageMargins, updateDocumentPageMarginMode, canSetDocumentTableRowRepeatHeader, millimetersToPixels as work_document_layout_millimetersToPixels, DOCUMENT_CHUNK_HYDRATION_META, documentTabLeaderLabel, createSchemaDerivedWorkDocumentModel, updateDocumentCustomPageMillimeters, documentCommentDraftRange, documentParagraphTabStops, documentTableHorizontalAlignment, documentParagraphIndent, canInsertDocumentComment, documentTextLayoutBatches, normalizeDocumentImageWrapSide, updateDocumentPageOrientation, documentCitationStyleDetails, validateDocumentBookmarkName, setCustomDocumentColumns, updateDocumentPageMarginMillimeters, documentCitationStyle, documentTransactionsOnlyHydrateChunks, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, documentPageMetrics, createDocumentBibliography, DocumentSubscript, DocumentParagraphIdentity, updateDocumentPageChromeVariant, updateDocumentMirrorMargins, activeDocumentTableStyle, measureDocumentLayoutBlocksIncrementally, createWorkDocumentExtensions } from "./6282.js";
|
|
19
20
|
import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, useOfficeDialog, useOfficeTaskPaneModal, CommittedOfficeNumberField, officeFontFamilyLabel, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField } from "./0~7048.js";
|
|
20
21
|
import { office_text_field_OfficeTextArea, Popover, officeOverlayPortalRoot, button_Button, useOfficePublishPresenceLocation, OfficeTiptapPresenceLayer, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom, office_text_field_OfficeFileInput } from "./0~6090.js";
|
|
21
22
|
import { WorkOfficePreviewBar, isWorkspaceContextMenuKeyboardEvent, Tabs, WorkOfficeZoomControls, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton } from "./0~4595.js";
|
|
22
|
-
import { documentTableSizing, documentTableRowOptions, documentCommentViews, documentParagraphSpacing, documentPageBordersVisible, DOCUMENT_PAGE_BORDER_EDGES, normalizeDocumentColumns, clampDocumentMargin, normalizeDocumentTabStops, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, createWorkDocumentModel, nextDocumentTabAlignment, documentBookmarkNameExists, normalizedTabPosition, DocumentImage, collectDocumentChanges, documentCitationCount, isDocumentParagraphArtBorderStyle, resolveDocumentPageMargins, updateDocumentPageMarginMode, resolveDocumentPageBorders, canSetDocumentTableRowRepeatHeader, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, collectDocumentTextLayoutParagraphs, millimetersToPixels as work_document_layout_millimetersToPixels, documentBulletListStyle, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, documentTabLeaderLabel, documentOrderedListState, normalizeDocumentPageChrome, documentPageMarginsForLayout, documentTableCellFormat, updateDocumentCustomPageMillimeters, documentCommentDraftRange, normalizeDocumentPageGeometry, documentParagraphTabStops, normalizeDocumentImageLayer, documentImageProperties, documentParagraphIndent, documentTableHorizontalAlignment, isValidDocumentCitationTag, canInsertDocumentComment, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, DocumentParagraphFormatting, activeDocumentSection, documentTextLayoutBatches, normalizeDocumentImageWrapSide, normalizeDocumentHtml, documentParagraphDirection, documentParagraphPagination, updateDocumentPageOrientation, documentCitationStyleDetails, documentInitialSectionLayout, documentPageChromeLegacyFields, setCustomDocumentColumns, collectDocumentCommentAnchors, documentCitationStyle, updateDocumentPageMarginMillimeters, canChangeDocumentIndent, validateDocumentBookmarkName, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DocumentSuperscript, documentSectionById, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, DocumentEquation, documentPageMetrics, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, mountWorkLiveDocumentCapture, activeDocumentBookmark, createDocumentBibliography, DocumentSubscript, DocumentParagraphIdentity, syncDocumentContentFromHtml, updateDocumentPageChromeVariant, editorDocumentCaptionTargets, resolveDocumentPageChrome, updateDocumentMirrorMargins, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, activeDocumentTableStyle, editorDocumentBookmarkReferenceTargets, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, measureDocumentLayoutBlocksIncrementally, createWorkDocumentExtensions } from "./8928.js";
|
|
23
23
|
import { createOfficeId as createWorkId } from "./5184.js";
|
|
24
24
|
import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
|
|
25
25
|
import { OfficeColorPicker, isOfficeShortcutBlocked } from "./0~3635.js";
|
|
26
26
|
import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
|
|
27
|
-
import { mergeOfficeTiptapExtensions,
|
|
27
|
+
import { mergeOfficeTiptapExtensions, documentCurrentPage, documentPageCount, documentAgentMenuItems, createWorkDocumentSelectionSnapshot, documentPlainTextAsHtml, documentCustomSelectionMenuItems, createWorkDocumentSelectionAction } from "./0~5050.js";
|
|
28
28
|
import { WorkEditorLoadingState, documentLayoutFontKey, useOfficeCollaborationLocationNavigator, OFFICE_DOCUMENT_LAYOUT_HEBREW_FONT_ID, useOfficeEditorInitialFocus, OFFICE_DOCUMENT_LAYOUT_FONT_ID, OFFICE_DOCUMENT_LAYOUT_ARABIC_FONT_ID, OFFICE_DOCUMENT_LAYOUT_LATIN_FONT_ID } from "./432.js";
|
|
29
29
|
import { useOfficeDraft, InlineNotice } from "./0~345.js";
|
|
30
30
|
import { documentPageColor, normalizeDocumentPageColor } from "./0~work-document-page-color.js";
|
|
@@ -33,6 +33,128 @@ __webpack_require__.r(document_editor_namespaceObject);
|
|
|
33
33
|
__webpack_require__.d(document_editor_namespaceObject, {
|
|
34
34
|
DocumentEditor: ()=>DocumentEditor
|
|
35
35
|
});
|
|
36
|
+
function materializeLazyDocumentUpdate(previousDocument, nextDocument, compactRoot, model) {
|
|
37
|
+
const root = materializeLazyDocumentEditorRoot(compactRoot, model);
|
|
38
|
+
const projection = documentLazyHtmlProjection(model);
|
|
39
|
+
const changed = changedLazyDocumentChunks(previousDocument, nextDocument);
|
|
40
|
+
if (!projection || !changed?.length || changed.some(({ after, before })=>!documentChunkOnlyChangesText(before, after))) {
|
|
41
|
+
invalidateDocumentLazyHtmlProjection(model);
|
|
42
|
+
return {
|
|
43
|
+
html: null,
|
|
44
|
+
htmlFingerprint: null,
|
|
45
|
+
root
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const replacements = new Map();
|
|
50
|
+
for (const { id } of changed){
|
|
51
|
+
const range = projection.ranges.get(id);
|
|
52
|
+
const isolated = isolatedDocumentChunk(root, id);
|
|
53
|
+
if (!range || !isolated) throw new Error('Lazy chunk is not indexed.');
|
|
54
|
+
const serialized = serializeWorkDocumentNode(isolated);
|
|
55
|
+
const sectionOpen = serialized.indexOf('>') + 1;
|
|
56
|
+
const sectionClose = serialized.lastIndexOf('</section>');
|
|
57
|
+
if (sectionOpen <= 0 || sectionClose < sectionOpen) throw new Error('Lazy chunk serialization has no section boundary.');
|
|
58
|
+
const fragment = documentLazyHtmlChunkFragment(serialized.slice(sectionOpen, sectionClose), range.tablePart);
|
|
59
|
+
if (null === fragment) throw new Error('Lazy table chunk serialization is malformed.');
|
|
60
|
+
replacements.set(id, fragment);
|
|
61
|
+
}
|
|
62
|
+
const html = patchDocumentLazyHtmlProjection(projection, replacements);
|
|
63
|
+
if (null === html) throw new Error('Lazy HTML patch could not be applied.');
|
|
64
|
+
const htmlFingerprint = documentLazyHtmlProjectionFingerprint(projection);
|
|
65
|
+
if (!htmlFingerprint) throw new Error('Lazy HTML fingerprint could not be updated.');
|
|
66
|
+
return {
|
|
67
|
+
html,
|
|
68
|
+
htmlFingerprint,
|
|
69
|
+
root
|
|
70
|
+
};
|
|
71
|
+
} catch {
|
|
72
|
+
invalidateDocumentLazyHtmlProjection(model);
|
|
73
|
+
return {
|
|
74
|
+
html: null,
|
|
75
|
+
htmlFingerprint: null,
|
|
76
|
+
root
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function transferLazyDocumentTextStatistics(previousDocument, nextDocument) {
|
|
81
|
+
const changed = changedLazyDocumentChunks(previousDocument, nextDocument);
|
|
82
|
+
if (!changed?.length || changed.some(({ after, before })=>!documentChunkOnlyChangesText(before, after))) return false;
|
|
83
|
+
return transferChangedDocumentTextStatistics(previousDocument, nextDocument, changed);
|
|
84
|
+
}
|
|
85
|
+
function changedLazyDocumentChunks(before, after) {
|
|
86
|
+
const changed = [];
|
|
87
|
+
const visit = (previous, next)=>{
|
|
88
|
+
if (previous === next || previous.eq(next)) return true;
|
|
89
|
+
if (previous.type !== next.type) return false;
|
|
90
|
+
if ('documentChunk' === previous.type.name && true !== previous.attrs.windowContainer && true !== next.attrs.windowContainer) {
|
|
91
|
+
const previousId = documentChunkId(previous);
|
|
92
|
+
const nextId = documentChunkId(next);
|
|
93
|
+
if (!previousId || previousId !== nextId) return false;
|
|
94
|
+
changed.push({
|
|
95
|
+
after: next,
|
|
96
|
+
before: previous,
|
|
97
|
+
id: nextId
|
|
98
|
+
});
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (!previous.sameMarkup(next) || previous.childCount !== next.childCount) return false;
|
|
102
|
+
for(let index = 0; index < previous.childCount; index += 1){
|
|
103
|
+
const previousChild = previous.child(index);
|
|
104
|
+
const nextChild = next.child(index);
|
|
105
|
+
if (!visit(previousChild, nextChild)) return false;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
};
|
|
109
|
+
return visit(before, after) ? changed : null;
|
|
110
|
+
}
|
|
111
|
+
function documentChunkOnlyChangesText(before, after) {
|
|
112
|
+
let textChanged = false;
|
|
113
|
+
const visit = (previous, next)=>{
|
|
114
|
+
if (previous.type !== next.type || !previous.sameMarkup(next) || previous.childCount !== next.childCount) return false;
|
|
115
|
+
if (previous.isText || next.isText) {
|
|
116
|
+
if (!previous.isText || !next.isText) return false;
|
|
117
|
+
if (previous.text !== next.text) textChanged = true;
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
for(let index = 0; index < previous.childCount; index += 1)if (!visit(previous.child(index), next.child(index))) return false;
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
return visit(before, after) && textChanged;
|
|
124
|
+
}
|
|
125
|
+
function isolatedDocumentChunk(root, id) {
|
|
126
|
+
let section = null;
|
|
127
|
+
let chunk = null;
|
|
128
|
+
const visit = (node, activeSection)=>{
|
|
129
|
+
if (chunk) return;
|
|
130
|
+
const nextSection = 'documentSection' === node.type ? node : activeSection;
|
|
131
|
+
if ('documentChunk' === node.type && node.attrs?.windowContainer !== true && node.attrs?.id === id) {
|
|
132
|
+
section = nextSection;
|
|
133
|
+
chunk = node;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
for (const child of node.content ?? [])visit(child, nextSection);
|
|
137
|
+
};
|
|
138
|
+
visit(root, null);
|
|
139
|
+
const foundSection = section;
|
|
140
|
+
const foundChunk = chunk;
|
|
141
|
+
if (!foundSection || !foundChunk) return null;
|
|
142
|
+
return {
|
|
143
|
+
type: 'doc',
|
|
144
|
+
content: [
|
|
145
|
+
{
|
|
146
|
+
...foundSection,
|
|
147
|
+
content: [
|
|
148
|
+
foundChunk
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function documentChunkId(node) {
|
|
155
|
+
const id = node.attrs.id;
|
|
156
|
+
return 'string' == typeof id && id ? id : null;
|
|
157
|
+
}
|
|
36
158
|
function documentPageSurfaceGeometry(pages, fallback, requestedPageCount = pages.length) {
|
|
37
159
|
const pageCount = Math.max(1, Math.trunc(requestedPageCount));
|
|
38
160
|
const metrics = Array.from({
|
|
@@ -217,10 +339,14 @@ const DocumentPagination = Extension.create({
|
|
|
217
339
|
name: 'documentPagination',
|
|
218
340
|
addCommands () {
|
|
219
341
|
return {
|
|
220
|
-
applyDocumentPagination: (revision, breaks)=>({ tr })=>{
|
|
342
|
+
applyDocumentPagination: (revision, breaks)=>({ state, tr })=>{
|
|
221
343
|
tr.setMeta(documentPaginationPluginKey, {
|
|
222
344
|
kind: 'apply',
|
|
223
345
|
revision,
|
|
346
|
+
breaks,
|
|
347
|
+
visibleIds: documentChunkMountedIds(state) ?? []
|
|
348
|
+
});
|
|
349
|
+
tr.setMeta(DOCUMENT_CHUNK_PAGINATION_META, {
|
|
224
350
|
breaks
|
|
225
351
|
});
|
|
226
352
|
tr.setMeta('addToHistory', false);
|
|
@@ -228,11 +354,14 @@ const DocumentPagination = Extension.create({
|
|
|
228
354
|
},
|
|
229
355
|
clearDocumentPagination: (revision)=>({ state, tr })=>{
|
|
230
356
|
const current = documentPaginationState(state);
|
|
231
|
-
if (!current.
|
|
357
|
+
if (!current.breaks.length && current.revision === revision) return false;
|
|
232
358
|
tr.setMeta(documentPaginationPluginKey, {
|
|
233
359
|
kind: 'clear',
|
|
234
360
|
revision
|
|
235
361
|
});
|
|
362
|
+
tr.setMeta(DOCUMENT_CHUNK_PAGINATION_META, {
|
|
363
|
+
breaks: []
|
|
364
|
+
});
|
|
236
365
|
tr.setMeta('addToHistory', false);
|
|
237
366
|
return true;
|
|
238
367
|
}
|
|
@@ -244,34 +373,54 @@ const DocumentPagination = Extension.create({
|
|
|
244
373
|
key: documentPaginationPluginKey,
|
|
245
374
|
state: {
|
|
246
375
|
init: ()=>({
|
|
376
|
+
breakIndex: emptyDocumentPaginationBreakIndex(),
|
|
377
|
+
breaks: [],
|
|
247
378
|
decorations: DecorationSet.empty,
|
|
248
|
-
revision: 0
|
|
379
|
+
revision: 0,
|
|
380
|
+
visibleIds: []
|
|
249
381
|
}),
|
|
250
382
|
apply: (transaction, current, _previous, next)=>{
|
|
251
383
|
const meta = transaction.getMeta(documentPaginationPluginKey);
|
|
384
|
+
const visibleMeta = transaction.getMeta(DOCUMENT_CHUNK_VISIBLE_IDS_META);
|
|
385
|
+
const hydrationMeta = transaction.getMeta(DOCUMENT_CHUNK_HYDRATION_META);
|
|
252
386
|
if (meta?.kind === 'clear') return {
|
|
387
|
+
breakIndex: emptyDocumentPaginationBreakIndex(),
|
|
388
|
+
breaks: [],
|
|
253
389
|
decorations: DecorationSet.empty,
|
|
254
|
-
revision: meta.revision
|
|
255
|
-
|
|
256
|
-
if (meta?.kind === 'apply') return {
|
|
257
|
-
decorations: DecorationSet.create(next.doc, (meta.breaks ?? []).flatMap(pageBreakDecorations)),
|
|
258
|
-
revision: meta.revision
|
|
390
|
+
revision: meta.revision,
|
|
391
|
+
visibleIds: documentChunkMountedIds(next) ?? []
|
|
259
392
|
};
|
|
393
|
+
if (meta?.kind === 'apply') return createDocumentPaginationPluginState(next, meta.breaks ?? [], meta.revision, meta.visibleIds);
|
|
394
|
+
if (transaction.docChanged && hydrationMeta) {
|
|
395
|
+
const visibleIds = visibleMeta?.visibleIds ?? documentChunkMountedIds(next) ?? current.visibleIds;
|
|
396
|
+
return {
|
|
397
|
+
...current,
|
|
398
|
+
decorations: documentPaginationDecorationSet(next.doc, current.breakIndex, visibleIds),
|
|
399
|
+
visibleIds: [
|
|
400
|
+
...visibleIds
|
|
401
|
+
]
|
|
402
|
+
};
|
|
403
|
+
}
|
|
260
404
|
if (transaction.docChanged) {
|
|
261
405
|
const appendedTo = transaction.getMeta('appendedTransaction');
|
|
262
406
|
const sourceMeta = appendedTo?.getMeta(documentPaginationPluginKey);
|
|
263
|
-
if (sourceMeta?.kind === 'apply') return
|
|
264
|
-
...current,
|
|
265
|
-
decorations: current.decorations.map(transaction.mapping, next.doc)
|
|
266
|
-
};
|
|
407
|
+
if (sourceMeta?.kind === 'apply') return createDocumentPaginationPluginState(next, mapDocumentPaginationBreaks(current.breaks, transaction.mapping), current.revision);
|
|
267
408
|
return {
|
|
409
|
+
breakIndex: emptyDocumentPaginationBreakIndex(),
|
|
410
|
+
breaks: [],
|
|
268
411
|
decorations: DecorationSet.empty,
|
|
269
|
-
revision: current.revision
|
|
412
|
+
revision: current.revision,
|
|
413
|
+
visibleIds: documentChunkMountedIds(next) ?? []
|
|
270
414
|
};
|
|
271
415
|
}
|
|
416
|
+
const visibleIds = visibleMeta?.visibleIds ?? (transaction.selectionSet ? withSelectedDocumentChunk(current.visibleIds, next) : current.visibleIds);
|
|
417
|
+
if (arraysEqual(visibleIds, current.visibleIds)) return current;
|
|
272
418
|
return {
|
|
273
419
|
...current,
|
|
274
|
-
decorations:
|
|
420
|
+
decorations: documentPaginationDecorationSet(next.doc, current.breakIndex, visibleIds),
|
|
421
|
+
visibleIds: [
|
|
422
|
+
...visibleIds
|
|
423
|
+
]
|
|
275
424
|
};
|
|
276
425
|
}
|
|
277
426
|
},
|
|
@@ -279,6 +428,21 @@ const DocumentPagination = Extension.create({
|
|
|
279
428
|
decorations (state) {
|
|
280
429
|
return documentPaginationState(state).decorations;
|
|
281
430
|
}
|
|
431
|
+
},
|
|
432
|
+
view: (initialView)=>{
|
|
433
|
+
const publishDiagnostics = (state)=>{
|
|
434
|
+
const pagination = documentPaginationState(state);
|
|
435
|
+
initialView.dom.dataset.paginationVisualBreaks = String(pagination.breaks.length);
|
|
436
|
+
initialView.dom.dataset.paginationVisibleBreaks = String(visibleDocumentPaginationBreakCount(pagination.breakIndex, pagination.visibleIds));
|
|
437
|
+
initialView.dom.dataset.paginationVisibleDecorations = String(pagination.decorations.find().length);
|
|
438
|
+
initialView.dom.dataset.paginationIndexedChunks = String(pagination.breakIndex.byChunkId.size);
|
|
439
|
+
};
|
|
440
|
+
publishDiagnostics(initialView.state);
|
|
441
|
+
return {
|
|
442
|
+
update (nextView) {
|
|
443
|
+
publishDiagnostics(nextView.state);
|
|
444
|
+
}
|
|
445
|
+
};
|
|
282
446
|
}
|
|
283
447
|
})
|
|
284
448
|
];
|
|
@@ -286,10 +450,117 @@ const DocumentPagination = Extension.create({
|
|
|
286
450
|
});
|
|
287
451
|
function documentPaginationState(state) {
|
|
288
452
|
return documentPaginationPluginKey.getState(state) ?? {
|
|
453
|
+
breakIndex: emptyDocumentPaginationBreakIndex(),
|
|
454
|
+
breaks: [],
|
|
289
455
|
decorations: DecorationSet.empty,
|
|
290
|
-
revision: 0
|
|
456
|
+
revision: 0,
|
|
457
|
+
visibleIds: []
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function createDocumentPaginationPluginState(state, breaks, revision, requestedVisibleIds) {
|
|
461
|
+
const visibleIds = requestedVisibleIds ?? documentChunkMountedIds(state) ?? [];
|
|
462
|
+
const breakIndex = indexDocumentPaginationBreaks(state.doc, breaks);
|
|
463
|
+
return {
|
|
464
|
+
breakIndex,
|
|
465
|
+
breaks: [
|
|
466
|
+
...breaks
|
|
467
|
+
],
|
|
468
|
+
decorations: documentPaginationDecorationSet(state.doc, breakIndex, visibleIds),
|
|
469
|
+
revision,
|
|
470
|
+
visibleIds
|
|
291
471
|
};
|
|
292
472
|
}
|
|
473
|
+
function indexDocumentPaginationBreaks(document1, breaks) {
|
|
474
|
+
if (!breaks.length) return emptyDocumentPaginationBreakIndex();
|
|
475
|
+
const chunks = [];
|
|
476
|
+
document1.descendants((node, position)=>{
|
|
477
|
+
if ('documentChunk' !== node.type.name) return true;
|
|
478
|
+
if (true === node.attrs.windowContainer) return true;
|
|
479
|
+
chunks.push({
|
|
480
|
+
from: position,
|
|
481
|
+
id: 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
482
|
+
to: position + node.nodeSize
|
|
483
|
+
});
|
|
484
|
+
return false;
|
|
485
|
+
});
|
|
486
|
+
if (!chunks.length) return {
|
|
487
|
+
byChunkId: new Map(),
|
|
488
|
+
outsideChunks: [
|
|
489
|
+
...breaks
|
|
490
|
+
]
|
|
491
|
+
};
|
|
492
|
+
const byChunkId = new Map();
|
|
493
|
+
const outsideChunks = [];
|
|
494
|
+
const orderedBreaks = [
|
|
495
|
+
...breaks
|
|
496
|
+
].sort(compareDocumentPaginationBreaks);
|
|
497
|
+
let chunkIndex = 0;
|
|
498
|
+
for (const pageBreak of orderedBreaks){
|
|
499
|
+
while(chunkIndex < chunks.length && pageBreak.position >= (chunks[chunkIndex]?.to ?? 1 / 0))chunkIndex += 1;
|
|
500
|
+
const chunk = chunks[chunkIndex];
|
|
501
|
+
if (chunk && pageBreak.position > chunk.from && pageBreak.position < chunk.to) {
|
|
502
|
+
const chunkBreaks = byChunkId.get(chunk.id) ?? [];
|
|
503
|
+
chunkBreaks.push(pageBreak);
|
|
504
|
+
byChunkId.set(chunk.id, chunkBreaks);
|
|
505
|
+
} else outsideChunks.push(pageBreak);
|
|
506
|
+
}
|
|
507
|
+
return {
|
|
508
|
+
byChunkId,
|
|
509
|
+
outsideChunks
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function documentPaginationDecorationSet(document1, breakIndex, visibleIds) {
|
|
513
|
+
const visibleBreaks = [
|
|
514
|
+
...breakIndex.outsideChunks
|
|
515
|
+
];
|
|
516
|
+
for (const id of visibleIds){
|
|
517
|
+
const chunkBreaks = breakIndex.byChunkId.get(id);
|
|
518
|
+
if (chunkBreaks) visibleBreaks.push(...chunkBreaks);
|
|
519
|
+
}
|
|
520
|
+
visibleBreaks.sort(compareDocumentPaginationBreaks);
|
|
521
|
+
return DecorationSet.create(document1, visibleBreaks.flatMap(pageBreakDecorations));
|
|
522
|
+
}
|
|
523
|
+
function visibleDocumentPaginationBreakCount(breakIndex, visibleIds) {
|
|
524
|
+
let count = breakIndex.outsideChunks.length;
|
|
525
|
+
for (const id of visibleIds)count += breakIndex.byChunkId.get(id)?.length ?? 0;
|
|
526
|
+
return count;
|
|
527
|
+
}
|
|
528
|
+
function emptyDocumentPaginationBreakIndex() {
|
|
529
|
+
return {
|
|
530
|
+
byChunkId: new Map(),
|
|
531
|
+
outsideChunks: []
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function compareDocumentPaginationBreaks(left, right) {
|
|
535
|
+
return left.position - right.position || left.pageIndex - right.pageIndex;
|
|
536
|
+
}
|
|
537
|
+
function mapDocumentPaginationBreaks(breaks, mapping) {
|
|
538
|
+
return breaks.map((pageBreak)=>({
|
|
539
|
+
...pageBreak,
|
|
540
|
+
position: mapping.map(pageBreak.position, -1),
|
|
541
|
+
...pageBreak.tableBreak?.cellBreaks ? {
|
|
542
|
+
tableBreak: {
|
|
543
|
+
...pageBreak.tableBreak,
|
|
544
|
+
cellBreaks: pageBreak.tableBreak.cellBreaks.map((cellBreak)=>({
|
|
545
|
+
...cellBreak,
|
|
546
|
+
position: mapping.map(cellBreak.position, -1)
|
|
547
|
+
}))
|
|
548
|
+
}
|
|
549
|
+
} : {}
|
|
550
|
+
}));
|
|
551
|
+
}
|
|
552
|
+
function arraysEqual(left, right) {
|
|
553
|
+
if (left.length !== right.length) return false;
|
|
554
|
+
for(let index = 0; index < left.length; index += 1)if (left[index] !== right[index]) return false;
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
function withSelectedDocumentChunk(visibleIds, state) {
|
|
558
|
+
const selected = selectedDocumentChunkId(state);
|
|
559
|
+
return selected && !visibleIds.includes(selected) ? [
|
|
560
|
+
...visibleIds,
|
|
561
|
+
selected
|
|
562
|
+
] : visibleIds;
|
|
563
|
+
}
|
|
293
564
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_THRESHOLD = 48;
|
|
294
565
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_LIMIT = 32;
|
|
295
566
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_OVERSCAN = 4;
|
|
@@ -2753,10 +3024,28 @@ function fallbackPaginationPageDescriptor(sectionId, sectionIndex, layout, physi
|
|
|
2753
3024
|
page: documentPageMetrics(layout)
|
|
2754
3025
|
};
|
|
2755
3026
|
}
|
|
2756
|
-
function shouldPublishDocumentUpdate(transaction) {
|
|
2757
|
-
return
|
|
3027
|
+
function shouldPublishDocumentUpdate(transaction, appendedTransactions = []) {
|
|
3028
|
+
return [
|
|
3029
|
+
transaction,
|
|
3030
|
+
...appendedTransactions
|
|
3031
|
+
].some((candidate)=>candidate.docChanged && !candidate.getMeta('preventUpdate') && false !== candidate.getMeta('addToHistory'));
|
|
2758
3032
|
}
|
|
2759
3033
|
function applyExternalDocumentContent(editor, content) {
|
|
3034
|
+
const startedAt = externalContentNow();
|
|
3035
|
+
const finish = (result)=>{
|
|
3036
|
+
const finishedAt = externalContentNow();
|
|
3037
|
+
editor.view.dom.dataset.documentExternalApplyMs = String(Math.round((finishedAt - startedAt) * 10) / 10);
|
|
3038
|
+
try {
|
|
3039
|
+
globalThis.performance?.measure('a3s-office.document.external-content-apply', {
|
|
3040
|
+
detail: {
|
|
3041
|
+
result
|
|
3042
|
+
},
|
|
3043
|
+
end: finishedAt,
|
|
3044
|
+
start: startedAt
|
|
3045
|
+
});
|
|
3046
|
+
} catch {}
|
|
3047
|
+
return result;
|
|
3048
|
+
};
|
|
2760
3049
|
let nextDocument;
|
|
2761
3050
|
try {
|
|
2762
3051
|
nextDocument = createNodeFromContent(content, editor.schema, {
|
|
@@ -2764,12 +3053,12 @@ function applyExternalDocumentContent(editor, content) {
|
|
|
2764
3053
|
slice: false
|
|
2765
3054
|
});
|
|
2766
3055
|
} catch {
|
|
2767
|
-
return 'unsupported';
|
|
3056
|
+
return finish('unsupported');
|
|
2768
3057
|
}
|
|
2769
|
-
if (!(nextDocument instanceof model_Node)) return 'unsupported';
|
|
3058
|
+
if (!(nextDocument instanceof model_Node)) return finish('unsupported');
|
|
2770
3059
|
const currentDocument = editor.state.doc;
|
|
2771
3060
|
const start = currentDocument.content.findDiffStart(nextDocument.content);
|
|
2772
|
-
if (null === start) return 'unchanged';
|
|
3061
|
+
if (null === start) return finish('unchanged');
|
|
2773
3062
|
const end = currentDocument.content.findDiffEnd(nextDocument.content);
|
|
2774
3063
|
let currentEnd = end?.a ?? currentDocument.content.size;
|
|
2775
3064
|
let nextEnd = end?.b ?? nextDocument.content.size;
|
|
@@ -2781,11 +3070,14 @@ function applyExternalDocumentContent(editor, content) {
|
|
|
2781
3070
|
try {
|
|
2782
3071
|
const transaction = editor.state.tr.replace(start, currentEnd, nextDocument.slice(start, nextEnd)).setMeta('addToHistory', false).setMeta('preventUpdate', true);
|
|
2783
3072
|
editor.view.dispatch(transaction);
|
|
2784
|
-
return 'applied';
|
|
3073
|
+
return finish('applied');
|
|
2785
3074
|
} catch {
|
|
2786
|
-
return 'unsupported';
|
|
3075
|
+
return finish('unsupported');
|
|
2787
3076
|
}
|
|
2788
3077
|
}
|
|
3078
|
+
function externalContentNow() {
|
|
3079
|
+
return globalThis.performance?.now?.() ?? Date.now();
|
|
3080
|
+
}
|
|
2789
3081
|
const SEARCH_CONTEXT_LENGTH = 34;
|
|
2790
3082
|
function documentTextMatches(document1, rawQuery) {
|
|
2791
3083
|
const query = rawQuery.toLocaleLowerCase();
|
|
@@ -5501,33 +5793,120 @@ function WorkDocumentPageBorder({ layout, physicalPage = 1, sectionPage }) {
|
|
|
5501
5793
|
function formatPixels(value) {
|
|
5502
5794
|
return Number(value.toFixed(3)).toString();
|
|
5503
5795
|
}
|
|
5504
|
-
|
|
5796
|
+
const EMPTY_DOCUMENT_PAGE_DESCRIPTORS = [];
|
|
5797
|
+
const document_page_stack_DOCUMENT_PAGE_WINDOW_THRESHOLD = 24;
|
|
5798
|
+
const DOCUMENT_PAGE_INITIAL_WINDOW_SIZE = 8;
|
|
5799
|
+
const document_page_stack_DOCUMENT_PAGE_WINDOW_OVERSCAN = 3;
|
|
5800
|
+
function DocumentPageStack({ pageColor, pageCount, pageGap, pageHeight, pageWidth = 794, pages = EMPTY_DOCUMENT_PAGE_DESCRIPTORS }) {
|
|
5505
5801
|
const count = Math.max(1, Math.trunc(pageCount));
|
|
5506
5802
|
const gap = Math.max(0, pageGap);
|
|
5507
5803
|
const height = Math.max(1, pageHeight);
|
|
5508
|
-
const fallbackPage = {
|
|
5509
|
-
|
|
5804
|
+
const fallbackPage = useMemo(()=>({
|
|
5805
|
+
width: Math.max(1, pageWidth),
|
|
5806
|
+
height,
|
|
5807
|
+
marginTop: 0,
|
|
5808
|
+
marginRight: 0,
|
|
5809
|
+
marginBottom: 0,
|
|
5810
|
+
marginLeft: 0,
|
|
5811
|
+
headerHeight: 0,
|
|
5812
|
+
footerHeight: 0,
|
|
5813
|
+
pageGap: gap
|
|
5814
|
+
}), [
|
|
5815
|
+
gap,
|
|
5510
5816
|
height,
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
const
|
|
5520
|
-
const
|
|
5817
|
+
pageWidth
|
|
5818
|
+
]);
|
|
5819
|
+
const geometry = useMemo(()=>documentPageSurfaceGeometry(pages.map((page)=>page.page ?? fallbackPage), fallbackPage, count), [
|
|
5820
|
+
count,
|
|
5821
|
+
fallbackPage,
|
|
5822
|
+
pages
|
|
5823
|
+
]);
|
|
5824
|
+
const windowed = count > document_page_stack_DOCUMENT_PAGE_WINDOW_THRESHOLD;
|
|
5825
|
+
const stackRef = useRef(null);
|
|
5826
|
+
const [requestedWindow, setRequestedWindow] = useState(()=>initialDocumentPageWindow(count));
|
|
5827
|
+
const pageWindow = windowed ? clampDocumentPageWindow(requestedWindow, count) : {
|
|
5828
|
+
start: 0,
|
|
5829
|
+
end: count
|
|
5830
|
+
};
|
|
5831
|
+
const descriptors = geometry.frames.slice(pageWindow.start, pageWindow.end).map((frame)=>({
|
|
5521
5832
|
frame,
|
|
5522
5833
|
page: pages[frame.pageIndex]
|
|
5523
5834
|
}));
|
|
5835
|
+
useLayoutEffect(()=>{
|
|
5836
|
+
const stack = stackRef.current;
|
|
5837
|
+
if (!stack) return;
|
|
5838
|
+
return registerDocumentPageSurfaceGeometry(stack, ()=>{
|
|
5839
|
+
if (pages.length < count) return [];
|
|
5840
|
+
return geometry.frames.map((frame)=>{
|
|
5841
|
+
const descriptor = pages[frame.pageIndex];
|
|
5842
|
+
const pageSize = descriptor ? resolveDocumentPageSize(descriptor.layout) : null;
|
|
5843
|
+
return {
|
|
5844
|
+
height: frame.height,
|
|
5845
|
+
left: frame.left,
|
|
5846
|
+
orientation: pageSize?.orientation ?? 'portrait',
|
|
5847
|
+
pageHeightPoints: pageSize?.heightPoints ?? 72 * frame.height / 96,
|
|
5848
|
+
pageIndex: frame.pageIndex,
|
|
5849
|
+
pageSize: pageSize?.preset && 'custom' !== pageSize.preset ? pageSize.preset : 'a4',
|
|
5850
|
+
pageWidthPoints: pageSize?.widthPoints ?? 72 * frame.width / 96,
|
|
5851
|
+
top: frame.top,
|
|
5852
|
+
width: frame.width
|
|
5853
|
+
};
|
|
5854
|
+
});
|
|
5855
|
+
});
|
|
5856
|
+
}, [
|
|
5857
|
+
count,
|
|
5858
|
+
geometry.frames,
|
|
5859
|
+
pages
|
|
5860
|
+
]);
|
|
5861
|
+
useLayoutEffect(()=>{
|
|
5862
|
+
const stack = stackRef.current;
|
|
5863
|
+
if (!stack || !windowed) return;
|
|
5864
|
+
const root = stack.closest('.work-document-scroll');
|
|
5865
|
+
if (!root) {
|
|
5866
|
+
const next = initialDocumentPageWindow(count);
|
|
5867
|
+
setRequestedWindow((current)=>documentPageWindowsEqual(current, next) ? current : next);
|
|
5868
|
+
return;
|
|
5869
|
+
}
|
|
5870
|
+
let animationFrame = 0;
|
|
5871
|
+
const update = ()=>{
|
|
5872
|
+
animationFrame = 0;
|
|
5873
|
+
const next = documentPageWindowForViewport(geometry.frames, stack, root);
|
|
5874
|
+
setRequestedWindow((current)=>documentPageWindowsEqual(current, next) ? current : next);
|
|
5875
|
+
};
|
|
5876
|
+
const schedule = ()=>{
|
|
5877
|
+
if (animationFrame) return;
|
|
5878
|
+
animationFrame = requestAnimationFrame(update);
|
|
5879
|
+
};
|
|
5880
|
+
const resizeObserver = "u" < typeof ResizeObserver ? null : new ResizeObserver(schedule);
|
|
5881
|
+
root.addEventListener('scroll', schedule, {
|
|
5882
|
+
passive: true
|
|
5883
|
+
});
|
|
5884
|
+
globalThis.addEventListener('resize', schedule);
|
|
5885
|
+
resizeObserver?.observe(root);
|
|
5886
|
+
resizeObserver?.observe(stack);
|
|
5887
|
+
update();
|
|
5888
|
+
return ()=>{
|
|
5889
|
+
if (animationFrame) cancelAnimationFrame(animationFrame);
|
|
5890
|
+
resizeObserver?.disconnect();
|
|
5891
|
+
root.removeEventListener('scroll', schedule);
|
|
5892
|
+
globalThis.removeEventListener('resize', schedule);
|
|
5893
|
+
};
|
|
5894
|
+
}, [
|
|
5895
|
+
count,
|
|
5896
|
+
geometry.frames,
|
|
5897
|
+
windowed
|
|
5898
|
+
]);
|
|
5524
5899
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
5525
5900
|
children: [
|
|
5526
5901
|
/*#__PURE__*/ jsx("div", {
|
|
5902
|
+
ref: stackRef,
|
|
5527
5903
|
className: "work-document-page-stack",
|
|
5528
5904
|
"data-page-count": count,
|
|
5529
5905
|
"data-page-surface-height": geometry.height,
|
|
5530
5906
|
"data-page-surface-width": geometry.width,
|
|
5907
|
+
"data-page-window-end": pageWindow.end,
|
|
5908
|
+
"data-page-window-start": pageWindow.start + 1,
|
|
5909
|
+
"data-page-windowed": String(windowed),
|
|
5531
5910
|
"aria-hidden": "true",
|
|
5532
5911
|
children: descriptors.map(({ frame, page })=>{
|
|
5533
5912
|
const resolvedPageSize = page ? resolveDocumentPageSize(page.layout) : null;
|
|
@@ -5585,6 +5964,69 @@ function DocumentPageStack({ pageColor, pageCount, pageGap, pageHeight, pageWidt
|
|
|
5585
5964
|
]
|
|
5586
5965
|
});
|
|
5587
5966
|
}
|
|
5967
|
+
function initialDocumentPageWindow(pageCount) {
|
|
5968
|
+
return {
|
|
5969
|
+
start: 0,
|
|
5970
|
+
end: Math.min(pageCount, DOCUMENT_PAGE_INITIAL_WINDOW_SIZE)
|
|
5971
|
+
};
|
|
5972
|
+
}
|
|
5973
|
+
function clampDocumentPageWindow(pageWindow, pageCount) {
|
|
5974
|
+
const start = Math.max(0, Math.min(pageCount - 1, pageWindow.start));
|
|
5975
|
+
const end = Math.max(start + 1, Math.min(pageCount, pageWindow.end));
|
|
5976
|
+
return {
|
|
5977
|
+
start,
|
|
5978
|
+
end
|
|
5979
|
+
};
|
|
5980
|
+
}
|
|
5981
|
+
function documentPageWindowForViewport(frames, stack, root) {
|
|
5982
|
+
if (!frames.length) return {
|
|
5983
|
+
start: 0,
|
|
5984
|
+
end: 1
|
|
5985
|
+
};
|
|
5986
|
+
const stackRect = stack.getBoundingClientRect();
|
|
5987
|
+
const rootRect = root.getBoundingClientRect();
|
|
5988
|
+
if (!(stackRect.width > 0) || !(rootRect.height > 0)) return initialDocumentPageWindow(frames.length);
|
|
5989
|
+
const scale = Math.max(0.01, stackRect.width / Math.max(1, stack.offsetWidth));
|
|
5990
|
+
const viewportTop = Math.max(0, (rootRect.top - stackRect.top) / scale);
|
|
5991
|
+
const viewportBottom = Math.max(viewportTop, (rootRect.bottom - stackRect.top) / scale);
|
|
5992
|
+
const firstVisible = firstDocumentPageEndingAfter(frames, viewportTop);
|
|
5993
|
+
const lastVisible = lastDocumentPageStartingBefore(frames, viewportBottom);
|
|
5994
|
+
return {
|
|
5995
|
+
start: Math.max(0, firstVisible - document_page_stack_DOCUMENT_PAGE_WINDOW_OVERSCAN),
|
|
5996
|
+
end: Math.min(frames.length, Math.max(firstVisible + 1, lastVisible + 1) + document_page_stack_DOCUMENT_PAGE_WINDOW_OVERSCAN)
|
|
5997
|
+
};
|
|
5998
|
+
}
|
|
5999
|
+
function firstDocumentPageEndingAfter(frames, offset) {
|
|
6000
|
+
let lower = 0;
|
|
6001
|
+
let upper = frames.length - 1;
|
|
6002
|
+
let result = upper;
|
|
6003
|
+
while(lower <= upper){
|
|
6004
|
+
const middle = Math.floor((lower + upper) / 2);
|
|
6005
|
+
const frame = frames[middle];
|
|
6006
|
+
if (frame && frame.top + frame.height >= offset) {
|
|
6007
|
+
result = middle;
|
|
6008
|
+
upper = middle - 1;
|
|
6009
|
+
} else lower = middle + 1;
|
|
6010
|
+
}
|
|
6011
|
+
return result;
|
|
6012
|
+
}
|
|
6013
|
+
function lastDocumentPageStartingBefore(frames, offset) {
|
|
6014
|
+
let lower = 0;
|
|
6015
|
+
let upper = frames.length - 1;
|
|
6016
|
+
let result = 0;
|
|
6017
|
+
while(lower <= upper){
|
|
6018
|
+
const middle = Math.floor((lower + upper) / 2);
|
|
6019
|
+
const frame = frames[middle];
|
|
6020
|
+
if (frame && frame.top <= offset) {
|
|
6021
|
+
result = middle;
|
|
6022
|
+
lower = middle + 1;
|
|
6023
|
+
} else upper = middle - 1;
|
|
6024
|
+
}
|
|
6025
|
+
return result;
|
|
6026
|
+
}
|
|
6027
|
+
function documentPageWindowsEqual(left, right) {
|
|
6028
|
+
return left.start === right.start && left.end === right.end;
|
|
6029
|
+
}
|
|
5588
6030
|
function DocumentRulerTabStops({ marginLeft, pageWidth, rulerRef, tabStops, textWidth, onChange }) {
|
|
5589
6031
|
const normalized = constrainRulerTabStops(tabStops, textWidth);
|
|
5590
6032
|
const positionFromClientX = (clientX)=>{
|
|
@@ -13262,7 +13704,7 @@ function useDocumentPageChrome({ editor, enabled, firstPage, footerRef, headerRe
|
|
|
13262
13704
|
visibleChrome
|
|
13263
13705
|
};
|
|
13264
13706
|
}
|
|
13265
|
-
function planIncrementalDocumentLayout(previous, next, dirtyFrom) {
|
|
13707
|
+
function planIncrementalDocumentLayout(previous, next, dirtyFrom, reusedPrefixBlockCount = 0) {
|
|
13266
13708
|
const fullLayout = ()=>({
|
|
13267
13709
|
blocks: next.map(({ block })=>block),
|
|
13268
13710
|
reusedPageCount: 0,
|
|
@@ -13270,7 +13712,8 @@ function planIncrementalDocumentLayout(previous, next, dirtyFrom) {
|
|
|
13270
13712
|
startPageIndex: 0
|
|
13271
13713
|
});
|
|
13272
13714
|
if (!previous || !Number.isFinite(dirtyFrom) || dirtyFrom <= 0 || 0 !== previous.layout.startPageIndex || previous.layout.pages.length < 3) return fullLayout();
|
|
13273
|
-
const
|
|
13715
|
+
const stablePrefixBlockCount = Math.max(0, Math.min(Math.trunc(reusedPrefixBlockCount), previous.blocks.length, next.length));
|
|
13716
|
+
const affectedBlockIndex = earliestAffectedBlockIndex(previous.blocks, next, dirtyFrom, stablePrefixBlockCount);
|
|
13274
13717
|
const pageByBlockId = new Map(previous.layout.pages.flatMap((page)=>page.placements.map((placement)=>[
|
|
13275
13718
|
placement.blockId,
|
|
13276
13719
|
page.index
|
|
@@ -13288,10 +13731,6 @@ function planIncrementalDocumentLayout(previous, next, dirtyFrom) {
|
|
|
13288
13731
|
block.id,
|
|
13289
13732
|
index
|
|
13290
13733
|
]));
|
|
13291
|
-
const previousBlockById = new Map(previous.blocks.map(({ block })=>[
|
|
13292
|
-
block.id,
|
|
13293
|
-
block
|
|
13294
|
-
]));
|
|
13295
13734
|
let startPageIndex = affectedPageIndex - 1;
|
|
13296
13735
|
while(startPageIndex > 0){
|
|
13297
13736
|
const startBlockId = previous.layout.pages[startPageIndex]?.placements[0]?.blockId;
|
|
@@ -13313,7 +13752,7 @@ function planIncrementalDocumentLayout(previous, next, dirtyFrom) {
|
|
|
13313
13752
|
startPageIndex -= 1;
|
|
13314
13753
|
continue;
|
|
13315
13754
|
}
|
|
13316
|
-
if (!prefixMatches(previous.layout.pages, startPageIndex,
|
|
13755
|
+
if (!prefixMatches(previous.layout.pages, startPageIndex, previous.blocks, next, startBlockIndex, stablePrefixBlockCount)) {
|
|
13317
13756
|
startPageIndex -= 1;
|
|
13318
13757
|
continue;
|
|
13319
13758
|
}
|
|
@@ -13349,13 +13788,22 @@ function mergeIncrementalDocumentLayout(previous, partial) {
|
|
|
13349
13788
|
]
|
|
13350
13789
|
};
|
|
13351
13790
|
}
|
|
13352
|
-
function earliestAffectedBlockIndex(previous, next, dirtyFrom) {
|
|
13353
|
-
|
|
13791
|
+
function earliestAffectedBlockIndex(previous, next, dirtyFrom, stablePrefixBlockCount) {
|
|
13792
|
+
let lower = 0;
|
|
13793
|
+
let upper = next.length;
|
|
13794
|
+
while(lower < upper){
|
|
13795
|
+
const middle = Math.floor((lower + upper) / 2);
|
|
13796
|
+
if (next[middle].to <= dirtyFrom) lower = middle + 1;
|
|
13797
|
+
else upper = middle;
|
|
13798
|
+
}
|
|
13799
|
+
const positionIndex = lower < next.length ? lower : -1;
|
|
13354
13800
|
const sharedLength = Math.min(previous.length, next.length);
|
|
13355
|
-
let divergentIndex = -1;
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13801
|
+
let divergentIndex = stablePrefixBlockCount > 0 && stablePrefixBlockCount < sharedLength ? stablePrefixBlockCount : -1;
|
|
13802
|
+
if (0 === stablePrefixBlockCount) {
|
|
13803
|
+
for(let index = 0; index < sharedLength; index += 1)if (!sameLayoutBlock(previous[index].block, next[index].block)) {
|
|
13804
|
+
divergentIndex = index;
|
|
13805
|
+
break;
|
|
13806
|
+
}
|
|
13359
13807
|
}
|
|
13360
13808
|
if (divergentIndex < 0 && previous.length !== next.length) divergentIndex = sharedLength;
|
|
13361
13809
|
const candidates = [
|
|
@@ -13366,14 +13814,18 @@ function earliestAffectedBlockIndex(previous, next, dirtyFrom) {
|
|
|
13366
13814
|
Math.max(0, next.length - 1)
|
|
13367
13815
|
]);
|
|
13368
13816
|
}
|
|
13369
|
-
function prefixMatches(pages, startPageIndex,
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13817
|
+
function prefixMatches(pages, startPageIndex, previous, next, startBlockIndex, stablePrefixBlockCount) {
|
|
13818
|
+
let blockIndex = 0;
|
|
13819
|
+
for(let pageIndex = 0; pageIndex < startPageIndex; pageIndex += 1)for (const placement of pages[pageIndex]?.placements ?? []){
|
|
13820
|
+
if (blockIndex >= startBlockIndex) return false;
|
|
13821
|
+
if (blockIndex >= stablePrefixBlockCount) {
|
|
13822
|
+
const previousBlock = previous[blockIndex]?.block;
|
|
13823
|
+
const nextBlock = next[blockIndex]?.block;
|
|
13824
|
+
if (previousBlock?.id !== placement.blockId || nextBlock?.id !== placement.blockId || !sameLayoutBlock(previousBlock, nextBlock)) return false;
|
|
13825
|
+
}
|
|
13826
|
+
blockIndex += 1;
|
|
13827
|
+
}
|
|
13828
|
+
return blockIndex === startBlockIndex;
|
|
13377
13829
|
}
|
|
13378
13830
|
function sameLayoutBlock(left, right) {
|
|
13379
13831
|
return left.id === right.id && left.height === right.height && left.pageStyleId === right.pageStyleId && left.breakBefore === right.breakBefore && left.breakAfter === right.breakAfter && left.keepTogether === right.keepTogether && left.keepWithNext === right.keepWithNext && left.flowId === right.flowId && left.flowIndex === right.flowIndex && left.flowCount === right.flowCount && left.minimumFragmentsPerPage === right.minimumFragmentsPerPage && left.repeatHeaderCount === right.repeatHeaderCount && left.repeatHeaderHeight === right.repeatHeaderHeight;
|
|
@@ -13492,6 +13944,7 @@ function createDocumentPaginationRunCoordinator({ cancelFrame, onAbort, onCoales
|
|
|
13492
13944
|
request
|
|
13493
13945
|
};
|
|
13494
13946
|
}
|
|
13947
|
+
const MAX_DOCUMENT_BLOCK_RESIZE_OBSERVATIONS = 4096;
|
|
13495
13948
|
function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, page, selectionVersion, wasmUrl, layoutFonts, loadedLayoutFontIds }) {
|
|
13496
13949
|
const client = useOfficeKernelClient(wasmUrl, layoutFonts);
|
|
13497
13950
|
const editorMounted = useEditorMounted(editor);
|
|
@@ -13537,6 +13990,7 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13537
13990
|
delete editorDom.dataset.paginationFallbackGlyphs;
|
|
13538
13991
|
delete editorDom.dataset.paginationFlows;
|
|
13539
13992
|
delete editorDom.dataset.paginationMeasuredBlocks;
|
|
13993
|
+
delete editorDom.dataset.paginationObservedBlocks;
|
|
13540
13994
|
delete editorDom.dataset.paginationLaidOutBlocks;
|
|
13541
13995
|
delete editorDom.dataset.paginationPages;
|
|
13542
13996
|
delete editorDom.dataset.paginationReusedBlocks;
|
|
@@ -13556,6 +14010,7 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13556
14010
|
delete editorDom.dataset.paginationDocumentTriggers;
|
|
13557
14011
|
delete editorDom.dataset.paginationFontTriggers;
|
|
13558
14012
|
delete editorDom.dataset.paginationResizeTriggers;
|
|
14013
|
+
delete editorDom.dataset.paginationResizeScope;
|
|
13559
14014
|
delete editorDom.dataset.paginationRuns;
|
|
13560
14015
|
delete editorDom.dataset.paginationTextBatch;
|
|
13561
14016
|
delete editorDom.dataset.paginationTextBatches;
|
|
@@ -13618,7 +14073,10 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13618
14073
|
};
|
|
13619
14074
|
const observeBlocks = (blocks)=>{
|
|
13620
14075
|
stopObservingBlocks();
|
|
13621
|
-
|
|
14076
|
+
const observation = documentResizeObservationTargets(editorDom, blocks);
|
|
14077
|
+
editorDom.dataset.paginationObservedBlocks = String(observation.observedBlockCount);
|
|
14078
|
+
editorDom.dataset.paginationResizeScope = observation.scope;
|
|
14079
|
+
observedBlockPositions = observation.positions;
|
|
13622
14080
|
observedElements = Array.from(observedBlockPositions.keys());
|
|
13623
14081
|
observedHeights.clear();
|
|
13624
14082
|
for (const element of observedElements)observedHeights.set(element, element.offsetHeight);
|
|
@@ -13700,7 +14158,7 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13700
14158
|
return;
|
|
13701
14159
|
}
|
|
13702
14160
|
const previousPagination = paginationCache.current;
|
|
13703
|
-
const layoutPlan = planIncrementalDocumentLayout(previousPagination, snapshot.blocks, measurementStart);
|
|
14161
|
+
const layoutPlan = planIncrementalDocumentLayout(previousPagination, snapshot.blocks, measurementStart, snapshot.reusedPrefixBlockCount);
|
|
13704
14162
|
editorDom.dataset.paginationLaidOutBlocks = String(layoutPlan.blocks.length);
|
|
13705
14163
|
editorDom.dataset.paginationReusedPages = String(layoutPlan.reusedPageCount);
|
|
13706
14164
|
try {
|
|
@@ -13806,7 +14264,11 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13806
14264
|
const markDirty = (position)=>{
|
|
13807
14265
|
measurementRange.invalidate(position);
|
|
13808
14266
|
};
|
|
13809
|
-
const handleDocumentUpdate = ({ transaction })=>{
|
|
14267
|
+
const handleDocumentUpdate = ({ appendedTransactions, transaction })=>{
|
|
14268
|
+
if (documentTransactionsOnlyHydrateChunks([
|
|
14269
|
+
transaction,
|
|
14270
|
+
...appendedTransactions ?? []
|
|
14271
|
+
])) return;
|
|
13810
14272
|
updateDiagnostic('documentTriggers', 'paginationDocumentTriggers');
|
|
13811
14273
|
markDirty(earliestChangedPosition(transaction));
|
|
13812
14274
|
schedule(true);
|
|
@@ -13914,6 +14376,24 @@ function documentResizeObservationPositions(blocks) {
|
|
|
13914
14376
|
}
|
|
13915
14377
|
return positions;
|
|
13916
14378
|
}
|
|
14379
|
+
function documentResizeObservationTargets(editorDom, blocks) {
|
|
14380
|
+
const positions = documentResizeObservationPositions(blocks);
|
|
14381
|
+
if (positions.size <= MAX_DOCUMENT_BLOCK_RESIZE_OBSERVATIONS) return {
|
|
14382
|
+
observedBlockCount: positions.size,
|
|
14383
|
+
positions,
|
|
14384
|
+
scope: 'blocks'
|
|
14385
|
+
};
|
|
14386
|
+
return {
|
|
14387
|
+
observedBlockCount: positions.size,
|
|
14388
|
+
positions: new Map([
|
|
14389
|
+
[
|
|
14390
|
+
editorDom,
|
|
14391
|
+
0
|
|
14392
|
+
]
|
|
14393
|
+
]),
|
|
14394
|
+
scope: 'document'
|
|
14395
|
+
};
|
|
14396
|
+
}
|
|
13917
14397
|
function deriveDocumentPaginationPageDescriptors(layout, blocks, documentNode, previousPages = [], requestedReusedPageCount = 0) {
|
|
13918
14398
|
const blockById = new Map(blocks.map((candidate)=>[
|
|
13919
14399
|
candidate.block.id,
|
|
@@ -14062,20 +14542,25 @@ function pageForPosition(pagination, position) {
|
|
|
14062
14542
|
return block ? pagination.pageByBlockId.get(block.block.id) ?? 1 : 1;
|
|
14063
14543
|
}
|
|
14064
14544
|
function blockForPosition(blocks, position) {
|
|
14065
|
-
|
|
14066
|
-
if (rangedBlock) return rangedBlock;
|
|
14545
|
+
if (!blocks.length) return;
|
|
14067
14546
|
let lower = 0;
|
|
14068
14547
|
let upper = blocks.length - 1;
|
|
14069
|
-
let
|
|
14548
|
+
let containingIndex = 0;
|
|
14070
14549
|
while(lower <= upper){
|
|
14071
14550
|
const middle = Math.floor((lower + upper) / 2);
|
|
14072
14551
|
const candidate = blocks[middle];
|
|
14073
14552
|
if (candidate.from <= position) {
|
|
14074
|
-
|
|
14553
|
+
containingIndex = middle;
|
|
14075
14554
|
lower = middle + 1;
|
|
14076
14555
|
} else upper = middle - 1;
|
|
14077
14556
|
}
|
|
14078
|
-
|
|
14557
|
+
let overlappingFrom = containingIndex;
|
|
14558
|
+
while(overlappingFrom > 0 && blocks[overlappingFrom - 1].to > position)overlappingFrom -= 1;
|
|
14559
|
+
for(let index = overlappingFrom; index <= containingIndex; index += 1){
|
|
14560
|
+
const candidate = blocks[index];
|
|
14561
|
+
if (candidate.selectionRanges?.some((range)=>range.from <= position && position < range.to)) return candidate;
|
|
14562
|
+
}
|
|
14563
|
+
return blocks[containingIndex];
|
|
14079
14564
|
}
|
|
14080
14565
|
function pageMetricsKey(page) {
|
|
14081
14566
|
return [
|
|
@@ -14395,20 +14880,29 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
|
|
|
14395
14880
|
const citationsDraftFocusRef = useRef(null);
|
|
14396
14881
|
const statisticsInvokerRef = useRef(null);
|
|
14397
14882
|
const contentRef = useRef(effectiveContent);
|
|
14883
|
+
const editorMountStartedAtRef = useRef(documentEditorNow());
|
|
14884
|
+
const editorBeforeCreateAtRef = useRef(null);
|
|
14885
|
+
const editorDetachedMountAtRef = useRef(null);
|
|
14398
14886
|
const onChangeRef = useRef(onChange);
|
|
14399
14887
|
const trackChangesRef = useRef(suggestionOnly || Boolean(effectiveContent.trackChanges));
|
|
14400
14888
|
const collaborationBindingRef = useRef(collaborationBinding);
|
|
14401
|
-
const
|
|
14889
|
+
const validatedModel = useMemo(()=>documentModelForContent(effectiveContent), [
|
|
14402
14890
|
effectiveContent
|
|
14403
14891
|
]);
|
|
14404
|
-
const
|
|
14892
|
+
const normalizedContent = useMemo(()=>validatedModel ? effectiveContent.html : normalizeDocumentHtml(effectiveContent), [
|
|
14405
14893
|
effectiveContent,
|
|
14406
|
-
|
|
14894
|
+
validatedModel
|
|
14895
|
+
]);
|
|
14896
|
+
const editorInput = useMemo(()=>resolveWorkDocumentEditorInput(effectiveContent, normalizedContent, validatedModel), [
|
|
14897
|
+
effectiveContent,
|
|
14898
|
+
normalizedContent,
|
|
14899
|
+
validatedModel
|
|
14407
14900
|
]);
|
|
14408
14901
|
const initialEditorSourceRef = useRef(editorInput.source);
|
|
14409
14902
|
const appliedSourceKeyRef = useRef(editorInput.sourceKey);
|
|
14410
14903
|
const activeReviewConflictsRef = useRef([]);
|
|
14411
14904
|
const publishedDocumentRef = useRef(null);
|
|
14905
|
+
const pendingLazyPublicationRef = useRef(null);
|
|
14412
14906
|
const [taskPane, setTaskPane] = useState(null);
|
|
14413
14907
|
const [layoutPanelTab, setLayoutPanelTab] = useState('page');
|
|
14414
14908
|
const [findReplaceFocusRequest, setFindReplaceFocusRequest] = useState(0);
|
|
@@ -14453,7 +14947,10 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
|
|
|
14453
14947
|
});
|
|
14454
14948
|
}
|
|
14455
14949
|
};
|
|
14456
|
-
const
|
|
14950
|
+
const trustInitialIntegrityFeatures = documentModelHasTrustedInitialIntegrityFeatures(editorInput.model);
|
|
14951
|
+
const editorExtensions = useMemo(()=>{
|
|
14952
|
+
const startedAt = documentEditorNow();
|
|
14953
|
+
const merged = mergeOfficeTiptapExtensions('DocumentEditor', [
|
|
14457
14954
|
...collaborationBinding?.extensions ?? createWorkDocumentExtensions({
|
|
14458
14955
|
getContent: ()=>contentRef.current,
|
|
14459
14956
|
isTracking: ()=>trackChangesRef.current,
|
|
@@ -14469,17 +14966,22 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
|
|
|
14469
14966
|
trackChanges
|
|
14470
14967
|
};
|
|
14471
14968
|
commitContentChange(next);
|
|
14472
|
-
}
|
|
14969
|
+
},
|
|
14970
|
+
trustInitialIntegrityFeatures
|
|
14473
14971
|
}),
|
|
14474
14972
|
extension_placeholder.configure({
|
|
14475
14973
|
placeholder: '在这里开始输入…'
|
|
14476
14974
|
}),
|
|
14477
14975
|
DocumentPagination
|
|
14478
|
-
], collaboration ? EMPTY_DOCUMENT_EXTENSIONS : extensions)
|
|
14976
|
+
], collaboration ? EMPTY_DOCUMENT_EXTENSIONS : extensions);
|
|
14977
|
+
recordDocumentEditorMeasure('a3s-office.document.editor-extensions', startedAt, documentEditorNow());
|
|
14978
|
+
return merged;
|
|
14979
|
+
}, [
|
|
14479
14980
|
collaboration,
|
|
14480
14981
|
collaborationBinding,
|
|
14481
14982
|
commitContentChange,
|
|
14482
|
-
extensions
|
|
14983
|
+
extensions,
|
|
14984
|
+
trustInitialIntegrityFeatures
|
|
14483
14985
|
]);
|
|
14484
14986
|
const editorProps = useMemo(()=>({
|
|
14485
14987
|
attributes: {
|
|
@@ -14492,16 +14994,107 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
|
|
|
14492
14994
|
}), [
|
|
14493
14995
|
commentOnly
|
|
14494
14996
|
]);
|
|
14997
|
+
const publishDocumentUpdate = useCallback((current, previousDocument)=>{
|
|
14998
|
+
if (current.isDestroyed || previousDocument.eq(current.state.doc)) return;
|
|
14999
|
+
const publishStartedAt = documentEditorNow();
|
|
15000
|
+
const previousContent = contentRef.current;
|
|
15001
|
+
const previousModel = previousContent.model;
|
|
15002
|
+
const compactRoot = current.getJSON();
|
|
15003
|
+
const materialized = previousModel && documentLazyHtmlProjection(previousModel) ? materializeLazyDocumentUpdate(previousDocument, current.state.doc, compactRoot, previousModel) : {
|
|
15004
|
+
html: null,
|
|
15005
|
+
htmlFingerprint: null,
|
|
15006
|
+
root: materializeLazyDocumentEditorRoot(compactRoot, previousModel)
|
|
15007
|
+
};
|
|
15008
|
+
const anchors = collectDocumentCommentAnchors(current.state.doc);
|
|
15009
|
+
const retainedCommentIds = new Set(activeReviewConflictsRef.current.filter((conflict)=>'comment' === conflict.kind).map((conflict)=>conflict.id));
|
|
15010
|
+
const synchronized = null === materialized.html ? syncDocumentContentFromHtml(previousContent, documentModelUsesWindowing(materialized.root) ? serializeWorkDocumentNode(materialized.root) : current.getHTML()) : {
|
|
15011
|
+
...previousContent,
|
|
15012
|
+
html: materialized.html
|
|
15013
|
+
};
|
|
15014
|
+
const model = createSchemaDerivedWorkDocumentModel(synchronized.html, materialized.root, previousModel, materialized.htmlFingerprint ?? void 0);
|
|
15015
|
+
const next = {
|
|
15016
|
+
...synchronized,
|
|
15017
|
+
model,
|
|
15018
|
+
comments: retainAnchoredDocumentComments(previousContent.comments ?? [], anchors, retainedCommentIds)
|
|
15019
|
+
};
|
|
15020
|
+
appliedSourceKeyRef.current = `model:${model.revision}:${model.htmlFingerprint}`;
|
|
15021
|
+
if (!collaborationBindingRef.current) {
|
|
15022
|
+
contentRef.current = next;
|
|
15023
|
+
onChangeRef.current(next);
|
|
15024
|
+
}
|
|
15025
|
+
const publishEndedAt = documentEditorNow();
|
|
15026
|
+
const publishCount = Number(current.view.dom.dataset.documentControlledPublishCount) || 0;
|
|
15027
|
+
current.view.dom.dataset.documentControlledPublishCount = String(publishCount + 1);
|
|
15028
|
+
current.view.dom.dataset.documentControlledPublishMode = null === materialized.html ? 'full' : 'lazy-chunk';
|
|
15029
|
+
current.view.dom.dataset.documentControlledPublishMs = String(Math.round((publishEndedAt - publishStartedAt) * 10) / 10);
|
|
15030
|
+
recordDocumentEditorMeasure('a3s-office.document.controlled-publish', publishStartedAt, publishEndedAt, {
|
|
15031
|
+
mode: current.view.dom.dataset.documentControlledPublishMode
|
|
15032
|
+
});
|
|
15033
|
+
}, []);
|
|
15034
|
+
const queueLazyDocumentPublication = useCallback((current, previousDocument)=>{
|
|
15035
|
+
const pending = pendingLazyPublicationRef.current;
|
|
15036
|
+
if (pending) {
|
|
15037
|
+
pending.editor = current;
|
|
15038
|
+
return;
|
|
15039
|
+
}
|
|
15040
|
+
const flush = ()=>{
|
|
15041
|
+
const queued = pendingLazyPublicationRef.current;
|
|
15042
|
+
pendingLazyPublicationRef.current = null;
|
|
15043
|
+
if (queued) publishDocumentUpdate(queued.editor, queued.before);
|
|
15044
|
+
};
|
|
15045
|
+
pendingLazyPublicationRef.current = {
|
|
15046
|
+
before: previousDocument,
|
|
15047
|
+
cancel: scheduleDocumentEditorFrame(flush),
|
|
15048
|
+
editor: current
|
|
15049
|
+
};
|
|
15050
|
+
}, [
|
|
15051
|
+
publishDocumentUpdate
|
|
15052
|
+
]);
|
|
15053
|
+
useEffect(()=>()=>{
|
|
15054
|
+
const pending = pendingLazyPublicationRef.current;
|
|
15055
|
+
pendingLazyPublicationRef.current = null;
|
|
15056
|
+
if (!pending) return;
|
|
15057
|
+
pending.cancel();
|
|
15058
|
+
publishDocumentUpdate(pending.editor, pending.before);
|
|
15059
|
+
}, [
|
|
15060
|
+
publishDocumentUpdate
|
|
15061
|
+
]);
|
|
14495
15062
|
const editor = useEditor({
|
|
15063
|
+
immediatelyRender: false,
|
|
14496
15064
|
extensions: editorExtensions,
|
|
14497
15065
|
content: collaboration ? void 0 : initialEditorSourceRef.current,
|
|
14498
15066
|
editable: !readOnly,
|
|
14499
15067
|
editorProps,
|
|
15068
|
+
onBeforeCreate: ()=>{
|
|
15069
|
+
const beforeCreateAt = documentEditorNow();
|
|
15070
|
+
editorBeforeCreateAtRef.current = beforeCreateAt;
|
|
15071
|
+
recordDocumentEditorMeasure('a3s-office.document.editor-before-create', editorMountStartedAtRef.current, beforeCreateAt);
|
|
15072
|
+
},
|
|
15073
|
+
onMount: ()=>{
|
|
15074
|
+
const mountedAt = documentEditorNow();
|
|
15075
|
+
editorDetachedMountAtRef.current = mountedAt;
|
|
15076
|
+
const beforeCreateAt = editorBeforeCreateAtRef.current;
|
|
15077
|
+
if (null !== beforeCreateAt) recordDocumentEditorMeasure('a3s-office.document.editor-state-view', beforeCreateAt, mountedAt);
|
|
15078
|
+
},
|
|
14500
15079
|
onCreate: ({ editor: current })=>{
|
|
14501
15080
|
publishedDocumentRef.current = current.state.doc;
|
|
15081
|
+
const mountedAt = documentEditorNow();
|
|
15082
|
+
const detachedMountAt = editorDetachedMountAtRef.current;
|
|
15083
|
+
if (null !== detachedMountAt) recordDocumentEditorMeasure('a3s-office.document.editor-create-dispatch', detachedMountAt, mountedAt);
|
|
15084
|
+
current.view.dom.dataset.documentEditorMountMs = String(Math.round((mountedAt - editorMountStartedAtRef.current) * 10) / 10);
|
|
15085
|
+
recordDocumentEditorMeasure('a3s-office.document.editor-mount', editorMountStartedAtRef.current, mountedAt, {
|
|
15086
|
+
source: editorInput.model ? 'model' : 'html',
|
|
15087
|
+
windowed: Boolean(editorInput.model && documentModelUsesWindowing(editorInput.model.root))
|
|
15088
|
+
});
|
|
15089
|
+
},
|
|
15090
|
+
onTransaction: ({ appendedTransactions, editor: current, transaction })=>{
|
|
15091
|
+
if (documentTransactionsOnlyHydrateChunks([
|
|
15092
|
+
transaction,
|
|
15093
|
+
...appendedTransactions
|
|
15094
|
+
])) publishedDocumentRef.current = current.state.doc;
|
|
14502
15095
|
},
|
|
14503
|
-
onUpdate: ({ editor: current, transaction })=>{
|
|
14504
|
-
if (!shouldPublishDocumentUpdate(transaction)) {
|
|
15096
|
+
onUpdate: ({ appendedTransactions, editor: current, transaction })=>{
|
|
15097
|
+
if (!shouldPublishDocumentUpdate(transaction, appendedTransactions ?? [])) {
|
|
14505
15098
|
publishedDocumentRef.current = current.state.doc;
|
|
14506
15099
|
return;
|
|
14507
15100
|
}
|
|
@@ -14509,22 +15102,13 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
|
|
|
14509
15102
|
publishedDocumentRef.current = current.state.doc;
|
|
14510
15103
|
return;
|
|
14511
15104
|
}
|
|
14512
|
-
|
|
15105
|
+
const previousDocument = publishedDocumentRef.current;
|
|
15106
|
+
if (previousDocument.eq(current.state.doc)) return;
|
|
15107
|
+
const lazyProjection = documentLazyHtmlProjection(contentRef.current.model);
|
|
15108
|
+
if (lazyProjection) transferLazyDocumentTextStatistics(previousDocument, current.state.doc);
|
|
14513
15109
|
publishedDocumentRef.current = current.state.doc;
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
const synchronized = syncDocumentContentFromHtml(contentRef.current, current.getHTML());
|
|
14517
|
-
const model = createWorkDocumentModel(synchronized.html, current.getJSON(), contentRef.current.model);
|
|
14518
|
-
const next = {
|
|
14519
|
-
...synchronized,
|
|
14520
|
-
model,
|
|
14521
|
-
comments: retainAnchoredDocumentComments(contentRef.current.comments ?? [], anchors, retainedCommentIds)
|
|
14522
|
-
};
|
|
14523
|
-
appliedSourceKeyRef.current = `model:${model.revision}:${model.htmlFingerprint}`;
|
|
14524
|
-
if (!collaborationBinding) {
|
|
14525
|
-
contentRef.current = next;
|
|
14526
|
-
onChangeRef.current(next);
|
|
14527
|
-
}
|
|
15110
|
+
if (lazyProjection) queueLazyDocumentPublication(current, previousDocument);
|
|
15111
|
+
else publishDocumentUpdate(current, previousDocument);
|
|
14528
15112
|
},
|
|
14529
15113
|
onSelectionUpdate: ()=>setSelectionVersion((value)=>value + 1)
|
|
14530
15114
|
});
|
|
@@ -15478,4 +16062,24 @@ function cssPixelValue(value) {
|
|
|
15478
16062
|
const parsed = Number.parseFloat(value);
|
|
15479
16063
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
15480
16064
|
}
|
|
16065
|
+
function scheduleDocumentEditorFrame(callback) {
|
|
16066
|
+
if ('function' == typeof requestAnimationFrame) {
|
|
16067
|
+
const frame = requestAnimationFrame(callback);
|
|
16068
|
+
return ()=>cancelAnimationFrame(frame);
|
|
16069
|
+
}
|
|
16070
|
+
const timeout = setTimeout(callback, 0);
|
|
16071
|
+
return ()=>clearTimeout(timeout);
|
|
16072
|
+
}
|
|
16073
|
+
function documentEditorNow() {
|
|
16074
|
+
return globalThis.performance?.now?.() ?? Date.now();
|
|
16075
|
+
}
|
|
16076
|
+
function recordDocumentEditorMeasure(name, start, end, detail) {
|
|
16077
|
+
try {
|
|
16078
|
+
globalThis.performance?.measure(name, {
|
|
16079
|
+
detail,
|
|
16080
|
+
end,
|
|
16081
|
+
start
|
|
16082
|
+
});
|
|
16083
|
+
} catch {}
|
|
16084
|
+
}
|
|
15481
16085
|
export { document_editor_namespaceObject };
|