@a3s-lab/office 0.3.0 → 0.4.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/COLLABORATION_ROADMAP.md +426 -0
- package/README.md +635 -9
- package/dist/0~1403.js +1 -1
- package/dist/0~2805.js +1279 -0
- package/dist/{0~use-office-draft.js → 0~345.js} +30 -1
- package/dist/0~3539.js +1 -1
- package/dist/0~3557.js +1 -1
- package/dist/0~3635.js +1 -1
- package/dist/0~4595.js +7 -2
- package/dist/0~4980.js +154 -0
- package/dist/{0~9512.js → 0~6090.js} +539 -3
- package/dist/0~7048.js +92 -66
- package/dist/0~7614.js +2 -1
- package/dist/0~7754.js +5653 -0
- package/dist/0~9445.js +1 -1
- package/dist/0~document-editor.js +1815 -1553
- package/dist/0~markdown-editor.js +250 -44
- package/dist/0~pdf-viewer.js +1016 -24
- package/dist/0~presentation-editor.js +179 -8
- package/dist/0~spreadsheet-editor.js +3371 -578
- package/dist/0~work-docx-export.js +6801 -658
- package/dist/0~work-docx-import.js +1388 -795
- package/dist/0~work-office-diagnostics.js +524 -30
- package/dist/0~work-pptx-export.js +2 -1
- package/dist/0~work-pptx-import.js +1 -2
- package/dist/0~work-presentation-charts.js +1 -1
- package/dist/2591.js +197 -0
- package/dist/3818.js +1090 -0
- package/dist/4104.js +970 -60
- package/dist/432.js +171 -14
- package/dist/4476.js +2008 -0
- package/dist/4560.js +674 -0
- package/dist/4650.js +70 -0
- package/dist/{1134.js → 5184.js} +183 -1
- package/dist/6489.js +18 -18
- package/dist/7060.js +132 -0
- package/dist/8715.js +2 -136
- package/dist/8928.js +16778 -0
- package/dist/9787.js +209 -0
- package/dist/core.d.ts +29 -9
- package/dist/core.js +10 -2
- package/dist/index.js +13 -3
- package/dist/internal/collaboration/office-collaboration-flat-json.d.ts +13 -0
- package/dist/internal/collaboration/office-collaboration-json.d.ts +4 -0
- package/dist/internal/collaboration/office-collaboration-presence.d.ts +86 -0
- package/dist/internal/collaboration/office-collaboration-transport.d.ts +42 -0
- package/dist/internal/collaboration/office-collaboration.d.ts +85 -0
- package/dist/internal/collaboration/office-document-collaboration-bibliography.d.ts +7 -0
- package/dist/internal/collaboration/office-document-collaboration-claims.d.ts +9 -0
- package/dist/internal/collaboration/office-document-collaboration-comments.d.ts +7 -0
- package/dist/internal/collaboration/office-document-collaboration-sidecar-utils.d.ts +27 -0
- package/dist/internal/collaboration/office-document-collaboration-sidecars.d.ts +16 -0
- package/dist/internal/collaboration/office-document-collaboration.d.ts +45 -0
- package/dist/internal/collaboration/office-markdown-collaboration.d.ts +31 -0
- package/dist/internal/collaboration/office-pdf-collaboration-claims.d.ts +4 -0
- package/dist/internal/collaboration/office-pdf-collaboration-conflicts.d.ts +2 -0
- package/dist/internal/collaboration/office-pdf-collaboration-model.d.ts +26 -0
- package/dist/internal/collaboration/office-pdf-collaboration-records.d.ts +21 -0
- package/dist/internal/collaboration/office-pdf-collaboration-types.d.ts +91 -0
- package/dist/internal/collaboration/office-pdf-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-pdf-collaboration.d.ts +35 -0
- package/dist/internal/collaboration/office-presentation-collaboration-model.d.ts +25 -0
- package/dist/internal/collaboration/office-presentation-collaboration-records.d.ts +22 -0
- package/dist/internal/collaboration/office-presentation-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-presentation-collaboration.d.ts +32 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-cells.d.ts +13 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-claims.d.ts +4 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-conflicts.d.ts +2 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-flat-json.d.ts +10 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-model.d.ts +31 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +17 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration.d.ts +32 -0
- package/dist/internal/features/work/components/work-document-page-border.d.ts +6 -0
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +9 -0
- package/dist/internal/features/work/editors/document-editor-focus.d.ts +1 -1
- package/dist/internal/features/work/editors/document-editor.d.ts +7 -1
- package/dist/internal/features/work/editors/document-external-content.d.ts +14 -0
- package/dist/internal/features/work/editors/document-page-stack.d.ts +10 -1
- package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +2 -0
- package/dist/internal/features/work/editors/document-pagination-run-coordinator.d.ts +26 -0
- package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +20 -1
- package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +4 -1
- package/dist/internal/features/work/editors/document-toolbar.d.ts +8 -1
- package/dist/internal/features/work/editors/markdown-editor-focus.d.ts +1 -1
- package/dist/internal/features/work/editors/markdown-editor.d.ts +5 -1
- package/dist/internal/features/work/editors/markdown-toolbar.d.ts +2 -1
- package/dist/internal/features/work/editors/office-collaboration-participants.d.ts +3 -0
- package/dist/internal/features/work/editors/office-collaboration-presence-context.d.ts +17 -0
- package/dist/internal/features/work/editors/office-collaboration-presence-ui.d.ts +25 -0
- package/dist/internal/features/work/editors/office-editor-focus-handoff.d.ts +27 -0
- package/dist/internal/features/work/editors/pdf-annotation-controller.d.ts +5 -0
- package/dist/internal/features/work/editors/pdf-collaboration-presence.d.ts +3 -0
- package/dist/internal/features/work/editors/pdf-collaboration-projection.d.ts +10 -0
- package/dist/internal/features/work/editors/pdf-evidence-contract.d.ts +36 -0
- package/dist/internal/features/work/editors/pdf-evidence-overlay.d.ts +37 -0
- package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
- package/dist/internal/features/work/editors/pdf-viewer-controller.d.ts +7 -1
- package/dist/internal/features/work/editors/pdf-viewer.d.ts +11 -1
- package/dist/internal/features/work/editors/presentation-collaboration-presence.d.ts +5 -0
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +3 -2
- package/dist/internal/features/work/editors/presentation-editor-types.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-editor.d.ts +1 -1
- package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-clear.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-merge.d.ts +12 -0
- package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +3 -7
- package/dist/internal/features/work/editors/spreadsheet-collaboration-presence.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +464 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +45 -9
- package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +2 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +9 -28
- package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +8 -2
- package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +27 -0
- package/dist/internal/features/work/editors/spreadsheet-freeze-panes.d.ts +14 -0
- package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +3 -2
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -1
- package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +28 -0
- package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +21 -0
- package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +27 -0
- package/dist/internal/features/work/editors/use-spreadsheet-format-painter.d.ts +18 -0
- package/dist/internal/features/work/work-document-bookmark-references.d.ts +37 -0
- package/dist/internal/features/work/work-document-bookmarks.d.ts +29 -0
- package/dist/internal/features/work/work-document-caption-nodes.d.ts +4 -1
- package/dist/internal/features/work/work-document-comments.d.ts +1 -1
- package/dist/internal/features/work/work-document-equations.d.ts +513 -0
- package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
- package/dist/internal/features/work/work-document-field-identity.d.ts +2 -0
- package/dist/internal/features/work/work-document-field-node.d.ts +2 -2
- package/dist/internal/features/work/work-document-fields.d.ts +7 -0
- package/dist/internal/features/work/work-document-image-identity.d.ts +30 -0
- package/dist/internal/features/work/work-document-image-layout.d.ts +46 -1
- package/dist/internal/features/work/work-document-image-wrap-contour.d.ts +16 -0
- package/dist/internal/features/work/work-document-incremental-layout.d.ts +2 -2
- package/dist/internal/features/work/work-document-model-codec.d.ts +4 -1
- package/dist/internal/features/work/work-document-note-integrity.d.ts +2 -0
- package/dist/internal/features/work/work-document-page-borders.d.ts +25 -0
- package/dist/internal/features/work/work-document-page-capture.d.ts +8 -0
- package/dist/internal/features/work/work-document-page-frames.d.ts +15 -0
- package/dist/internal/features/work/work-document-page-margins.d.ts +56 -0
- package/dist/internal/features/work/work-document-page-size.d.ts +47 -0
- package/dist/internal/features/work/work-document-pagination-measurement.d.ts +1 -2
- package/dist/internal/features/work/work-document-pagination-types.d.ts +7 -2
- package/dist/internal/features/work/work-document-pagination.d.ts +2 -2
- package/dist/internal/features/work/work-document-paragraph-borders.d.ts +32 -0
- package/dist/internal/features/work/work-document-paragraph-identity.d.ts +26 -0
- package/dist/internal/features/work/work-document-paragraph-shading.d.ts +18 -0
- package/dist/internal/features/work/work-document-review-conflicts.d.ts +35 -0
- package/dist/internal/features/work/work-document-section.d.ts +4 -0
- package/dist/internal/features/work/work-document-snapshot.d.ts +19 -0
- package/dist/internal/features/work/work-document-source.d.ts +23 -0
- package/dist/internal/features/work/work-document-table-column-widths.d.ts +7 -0
- package/dist/internal/features/work/work-document-table-property-changes.d.ts +3 -0
- package/dist/internal/features/work/work-document-table-row-identity.d.ts +15 -0
- package/dist/internal/features/work/work-document-table-sizing.d.ts +3 -0
- package/dist/internal/features/work/work-document-text-layout.d.ts +3 -1
- package/dist/internal/features/work/work-document-word-line-metrics.d.ts +2 -0
- package/dist/internal/features/work/work-docx-bookmark-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-bookmark-import.d.ts +24 -0
- package/dist/internal/features/work/work-docx-bookmarks.d.ts +17 -0
- package/dist/internal/features/work/work-docx-comment-durable-id-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-comment-export.d.ts +3 -0
- package/dist/internal/features/work/work-docx-comment-metadata.d.ts +2 -0
- package/dist/internal/features/work/work-docx-drawing-extension-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-equation-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-equation-export.d.ts +14 -0
- package/dist/internal/features/work/work-docx-equation-import.d.ts +30 -0
- package/dist/internal/features/work/work-docx-equation-story.d.ts +9 -0
- package/dist/internal/features/work/work-docx-export-formatting.d.ts +3 -1
- package/dist/internal/features/work/work-docx-export-image.d.ts +5 -1
- package/dist/internal/features/work/work-docx-export.d.ts +1 -1
- package/dist/internal/features/work/work-docx-field-instructions.d.ts +8 -0
- package/dist/internal/features/work/work-docx-font-table-preservation.d.ts +3 -0
- package/dist/internal/features/work/work-docx-ignorable-extension-preservation.d.ts +15 -0
- package/dist/internal/features/work/work-docx-image-crop.d.ts +12 -0
- package/dist/internal/features/work/work-docx-image-identity.d.ts +17 -0
- package/dist/internal/features/work/work-docx-image-layer.d.ts +12 -0
- package/dist/internal/features/work/work-docx-image-layout-import.d.ts +14 -2
- package/dist/internal/features/work/work-docx-image-wrap.d.ts +15 -0
- package/dist/internal/features/work/work-docx-import.d.ts +13 -3
- package/dist/internal/features/work/work-docx-list-export.d.ts +18 -0
- package/dist/internal/features/work/work-docx-list-import.d.ts +14 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-block-preservation.d.ts +18 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-model.d.ts +47 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-properties.d.ts +17 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-table-model.d.ts +17 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-xml.d.ts +14 -0
- package/dist/internal/features/work/work-docx-note-comment-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-content.d.ts +40 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-preservation.d.ts +5 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-relationships.d.ts +35 -0
- package/dist/internal/features/work/work-docx-note-comment-identity.d.ts +15 -0
- package/dist/internal/features/work/work-docx-note-comment-run-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-note-comment-run-properties.d.ts +2 -0
- package/dist/internal/features/work/work-docx-note-image-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-note-image-relationships.d.ts +1 -0
- package/dist/internal/features/work/work-docx-numbering-extension-preservation.d.ts +6 -0
- package/dist/internal/features/work/work-docx-numbering.d.ts +1 -0
- package/dist/internal/features/work/work-docx-page-borders-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-borders-import.d.ts +10 -0
- package/dist/internal/features/work/work-docx-page-margins-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-margins-import.d.ts +18 -0
- package/dist/internal/features/work/work-docx-page-size-diagnostics.d.ts +2 -0
- package/dist/internal/features/work/work-docx-page-size-import.d.ts +17 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-export.d.ts +18 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +24 -0
- package/dist/internal/features/work/work-docx-paragraph-default-collapsed.d.ts +19 -0
- package/dist/internal/features/work/work-docx-paragraph-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-paragraph-identity-import.d.ts +10 -0
- package/dist/internal/features/work/work-docx-paragraph-identity.d.ts +18 -0
- package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +6 -1
- package/dist/internal/features/work/work-docx-paragraph-shading-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-paragraph-shading-export.d.ts +5 -0
- package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +18 -0
- package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +3 -0
- package/dist/internal/features/work/work-docx-settings-preservation.d.ts +10 -0
- package/dist/internal/features/work/work-docx-settings-xml.d.ts +16 -0
- package/dist/internal/features/work/work-docx-style-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-cell-export.d.ts +2 -1
- package/dist/internal/features/work/work-docx-table-cell-import.d.ts +3 -0
- package/dist/internal/features/work/work-docx-table-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-row-import.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-theme-reference.d.ts +23 -0
- package/dist/internal/features/work/work-docx-theme.d.ts +4 -1
- package/dist/internal/features/work/work-docx-twips.d.ts +12 -0
- package/dist/internal/features/work/work-file-contract.d.ts +1 -0
- package/dist/internal/features/work/work-file-io.d.ts +1 -1
- package/dist/internal/features/work/work-markdown-extensions.d.ts +4 -1
- package/dist/internal/features/work/work-ooxml-package-preservation.d.ts +12 -0
- package/dist/internal/features/work/work-ooxml-package-security.d.ts +6 -0
- package/dist/internal/features/work/work-ooxml-relationship-preservation.d.ts +10 -0
- package/dist/internal/features/work/work-ooxml-xml.d.ts +2 -0
- package/dist/internal/features/work/work-pdf-export.d.ts +10 -0
- package/dist/internal/features/work/work-repository.d.ts +2 -0
- package/dist/internal/features/work/work-types.d.ts +15 -2
- package/dist/internal/kernel/office-kernel-client-types.d.ts +1 -0
- package/dist/internal/kernel/office-kernel-protocol.d.ts +7 -0
- package/dist/internal/kernel/office-kernel-version.d.ts +1 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +93 -41
- package/dist/react.d.ts +18 -12
- package/dist/react.js +1 -1
- package/dist/styles.css +1153 -14
- package/dist/vue.d.ts +48 -5
- package/dist/vue.js +42 -3
- package/dist/web-component.d.ts +24 -2
- package/dist/web-component.js +101 -2
- package/docs/latest/en/browser-editor-architecture.md +231 -49
- package/package.json +19 -4
- package/dist/0~152.js +0 -94
- package/dist/0~2582.js +0 -485
- package/dist/0~4750.js +0 -939
- package/dist/0~5861.js +0 -596
- package/dist/0~work-document-extensions.js +0 -3045
- package/dist/0~work-document-model-codec.js +0 -42
- package/dist/0~work-docx-bibliography.js +0 -347
- package/dist/0~work-docx-page-color.js +0 -42
- package/dist/2881.js +0 -1455
- package/dist/8728.js +0 -723
|
@@ -3,12 +3,12 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import extension_placeholder from "@tiptap/extension-placeholder";
|
|
4
4
|
import { EditorContent, useEditor } from "@tiptap/react";
|
|
5
5
|
import { Fragment as external_react_Fragment, forwardRef, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
6
|
-
import { Extension } from "@tiptap/core";
|
|
6
|
+
import { Extension, createNodeFromContent } from "@tiptap/core";
|
|
7
7
|
import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
|
|
8
8
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
9
|
-
import { AArrowDown, AArrowUp, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, FileDiff, FilePlus2, FileText, Globe2, Grid2X2, Hash, Highlighter, Image, IndentDecrease, IndentIncrease, Italic, Link2, List, ListChecks, ListOrdered, MessageSquarePlus, MessageSquareReply, MessagesSquare, MoveVertical, Paintbrush, Palette, PanelBottom, PanelBottomOpen, PanelLeftOpen, PanelTop, PanelTopOpen, Pilcrow, PilcrowLeft, PilcrowRight, Plus, Quote, Redo2, RefreshCw, Replace, ReplaceAll, RotateCcw, Rows3, Ruler, Scan, Search, Settings2, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, TextWrap, Trash2, Underline, Undo2, Unlink, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
|
|
9
|
+
import { AArrowDown, AArrowUp, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Bookmark, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, FileDiff, FilePlus2, FileText, Globe2, Grid2X2, Hash, Highlighter, Image, IndentDecrease, IndentIncrease, Italic, Link2, List, ListChecks, ListOrdered, MessageSquarePlus, MessageSquareReply, MessagesSquare, MoveVertical, Paintbrush, Palette, PanelBottom, PanelBottomOpen, PanelLeftOpen, PanelTop, PanelTopOpen, Pilcrow, PilcrowLeft, PilcrowRight, Plus, Quote, Redo2, RefreshCw, Replace, ReplaceAll, RotateCcw, Rows3, Ruler, Scan, Search, Settings2, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, TextWrap, Trash2, TriangleAlert, Underline, Undo2, Unlink, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
|
|
10
|
+
import { Node as model_Node } from "@tiptap/pm/model";
|
|
10
11
|
import extension_color from "@tiptap/extension-color";
|
|
11
|
-
import extension_image from "@tiptap/extension-image";
|
|
12
12
|
import { TableKit } from "@tiptap/extension-table";
|
|
13
13
|
import extension_text_align from "@tiptap/extension-text-align";
|
|
14
14
|
import { TextStyle } from "@tiptap/extension-text-style";
|
|
@@ -16,27 +16,49 @@ 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 { nextDocumentTabAlignment, normalizedTabPosition, documentParagraphTabStops, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, documentImageLayoutOptions, documentImageProperties, normalizeDocumentTabStops } from "./0~4750.js";
|
|
20
|
-
import { documentTableRowRepeats, documentTableRowOptions, documentTableCellFormat, activeDocumentTableStyle, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, documentTableRowCantSplit, documentTableHorizontalAlignment, DOCUMENT_TABLE_STYLE_OPTIONS, canSetDocumentTableRowRepeatHeader } from "./0~2582.js";
|
|
21
|
-
import { normalizeDocumentHtml, documentInitialSectionLayout, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, mountWorkLiveDocumentCapture, resolveWorkDocumentEditorInput, createDocumentBibliography, syncDocumentContentFromHtml, clampDocumentMargin, documentMargins, millimetersToPixels as work_document_layout_millimetersToPixels, documentCitationStyleDetails, updateDocumentPageChromeVariant, normalizeDocumentColumns, documentPageChromeLegacyFields, resolveDocumentPageChrome, setCustomDocumentColumns, documentCitationStyle, normalizeDocumentPageChrome, createWorkDocumentModel, documentSectionLayoutFromNodeAttributes, updateDocumentColumnWidth } from "./2881.js";
|
|
22
19
|
import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, useOfficeDialog, useOfficeTaskPaneModal, CommittedOfficeNumberField, officeFontFamilyLabel, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField } from "./0~7048.js";
|
|
23
|
-
import { office_text_field_OfficeTextArea, Popover, officeOverlayPortalRoot, button_Button, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom, office_text_field_OfficeFileInput } from "./0~
|
|
20
|
+
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";
|
|
24
21
|
import { WorkOfficePreviewBar, isWorkspaceContextMenuKeyboardEvent, Tabs, WorkOfficeZoomControls, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton } from "./0~4595.js";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
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, measureDocumentLayoutBlocks, 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, createWorkDocumentExtensions } from "./8928.js";
|
|
23
|
+
import { createOfficeId as createWorkId } from "./5184.js";
|
|
27
24
|
import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
|
|
28
25
|
import { OfficeColorPicker, isOfficeShortcutBlocked } from "./0~3635.js";
|
|
29
26
|
import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
|
|
30
|
-
import { documentParagraphSpacing, normalizeDocumentParagraphIndent, documentParagraphDirection, documentParagraphPagination, documentParagraphIndent, canChangeDocumentIndent } from "./0~5861.js";
|
|
31
27
|
import { mergeOfficeTiptapExtensions, documentTextStatistics, documentCurrentPage, documentPageCount, documentAgentMenuItems, createWorkDocumentSelectionSnapshot, documentPlainTextAsHtml, createWorkDocumentSelectionAction, documentCustomSelectionMenuItems } from "./0~5050.js";
|
|
32
|
-
import { OFFICE_DOCUMENT_LAYOUT_HEBREW_FONT_ID,
|
|
33
|
-
import { useOfficeDraft } from "./0~
|
|
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
|
+
import { useOfficeDraft, InlineNotice } from "./0~345.js";
|
|
34
30
|
import { documentPageColor, normalizeDocumentPageColor } from "./0~work-document-page-color.js";
|
|
35
31
|
var document_editor_namespaceObject = {};
|
|
36
32
|
__webpack_require__.r(document_editor_namespaceObject);
|
|
37
33
|
__webpack_require__.d(document_editor_namespaceObject, {
|
|
38
34
|
DocumentEditor: ()=>DocumentEditor
|
|
39
35
|
});
|
|
36
|
+
function documentPageSurfaceGeometry(pages, fallback, requestedPageCount = pages.length) {
|
|
37
|
+
const pageCount = Math.max(1, Math.trunc(requestedPageCount));
|
|
38
|
+
const metrics = Array.from({
|
|
39
|
+
length: pageCount
|
|
40
|
+
}, (_, pageIndex)=>pages[pageIndex] ?? fallback);
|
|
41
|
+
const width = Math.max(1, ...metrics.map((page)=>page.width));
|
|
42
|
+
let top = 0;
|
|
43
|
+
const frames = metrics.map((page, pageIndex)=>{
|
|
44
|
+
const frame = {
|
|
45
|
+
height: page.height,
|
|
46
|
+
left: (width - page.width) / 2,
|
|
47
|
+
page,
|
|
48
|
+
pageIndex,
|
|
49
|
+
top,
|
|
50
|
+
width: page.width
|
|
51
|
+
};
|
|
52
|
+
top += page.height;
|
|
53
|
+
if (pageIndex + 1 < metrics.length) top += page.pageGap;
|
|
54
|
+
return frame;
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
frames,
|
|
58
|
+
height: Math.max(1, top),
|
|
59
|
+
width
|
|
60
|
+
};
|
|
61
|
+
}
|
|
40
62
|
function pageBreakDecorations(pageBreak) {
|
|
41
63
|
const tableBreak = pageBreak.tableBreak;
|
|
42
64
|
if (tableBreak?.cellBreaks?.length) {
|
|
@@ -149,14 +171,19 @@ function documentTableRepeatedHeaderElement(tableBreak, extraClassName = '') {
|
|
|
149
171
|
}
|
|
150
172
|
function applyDocumentPageBreakVariables(element, pageBreak) {
|
|
151
173
|
element.style.setProperty('--work-document-page-spacer-height', `${pageBreak.spacerHeight}px`);
|
|
152
|
-
element.style.setProperty('--work-document-page-gap-offset', `${pageBreak.remainingBodyHeight + pageBreak.
|
|
153
|
-
element.style.setProperty('--work-document-page-gap-height', `${pageBreak.
|
|
174
|
+
element.style.setProperty('--work-document-page-gap-offset', `${pageBreak.remainingBodyHeight + pageBreak.previousPage.marginBottom}px`);
|
|
175
|
+
element.style.setProperty('--work-document-page-gap-height', `${pageBreak.previousPage.pageGap}px`);
|
|
154
176
|
element.style.setProperty('--work-document-previous-page-footer-top', `${pageBreak.remainingBodyHeight}px`);
|
|
155
|
-
element.style.setProperty('--work-document-next-page-header-top', `${pageBreak.remainingBodyHeight + pageBreak.
|
|
156
|
-
element.style.setProperty('--work-document-page-header-height', `${pageBreak.
|
|
157
|
-
element.style.setProperty('--work-document-page-footer-height', `${pageBreak.
|
|
158
|
-
element.style.setProperty('--work-document-page-margin-left', `${pageBreak.
|
|
159
|
-
element.style.setProperty('--work-document-page-margin-right', `${pageBreak.
|
|
177
|
+
element.style.setProperty('--work-document-next-page-header-top', `${pageBreak.remainingBodyHeight + pageBreak.previousPage.marginBottom + pageBreak.previousPage.pageGap}px`);
|
|
178
|
+
element.style.setProperty('--work-document-page-header-height', `${pageBreak.nextPage.headerHeight}px`);
|
|
179
|
+
element.style.setProperty('--work-document-page-footer-height', `${pageBreak.previousPage.footerHeight}px`);
|
|
180
|
+
element.style.setProperty('--work-document-page-margin-left', `${pageBreak.nextPage.marginLeft}px`);
|
|
181
|
+
element.style.setProperty('--work-document-page-margin-right', `${pageBreak.nextPage.marginRight}px`);
|
|
182
|
+
const previousPageOffset = (pageBreak.nextPage.width - pageBreak.previousPage.width) / 2;
|
|
183
|
+
element.style.setProperty('--work-document-previous-page-margin-left', `${previousPageOffset + pageBreak.previousPage.marginLeft}px`);
|
|
184
|
+
element.style.setProperty('--work-document-previous-page-margin-right', `${previousPageOffset + pageBreak.previousPage.marginRight}px`);
|
|
185
|
+
element.style.setProperty('--work-document-next-page-margin-left', `${pageBreak.nextPage.marginLeft}px`);
|
|
186
|
+
element.style.setProperty('--work-document-next-page-margin-right', `${pageBreak.nextPage.marginRight}px`);
|
|
160
187
|
element.style.setProperty('--work-document-break-inline-offset-left', `${pageBreak.inlineOffsetLeft}px`);
|
|
161
188
|
element.style.setProperty('--work-document-break-inline-offset-right', `${pageBreak.inlineOffsetRight}px`);
|
|
162
189
|
}
|
|
@@ -263,1273 +290,6 @@ function documentPaginationState(state) {
|
|
|
263
290
|
revision: 0
|
|
264
291
|
};
|
|
265
292
|
}
|
|
266
|
-
function reusableDocumentLayoutBlocks(previous, blockId, element, nodeTo, dirtyFrom) {
|
|
267
|
-
if (nodeTo > dirtyFrom) return [];
|
|
268
|
-
return previous.filter((candidate)=>candidate.block.id === blockId || candidate.block.flowId === blockId).map((candidate)=>({
|
|
269
|
-
...candidate,
|
|
270
|
-
block: {
|
|
271
|
-
...candidate.block
|
|
272
|
-
},
|
|
273
|
-
element
|
|
274
|
-
}));
|
|
275
|
-
}
|
|
276
|
-
function isDocumentListNode(node) {
|
|
277
|
-
return 'bulletList' === node.type.name || 'orderedList' === node.type.name;
|
|
278
|
-
}
|
|
279
|
-
function documentListChildId(listId, itemIndex, node, childIndex, nestedList = isDocumentListNode(node)) {
|
|
280
|
-
const kind = nestedList ? 'list' : node.type.name;
|
|
281
|
-
return `${listId}-item-${itemIndex}-${kind}-${childIndex}`;
|
|
282
|
-
}
|
|
283
|
-
function verticalBlockStart(style) {
|
|
284
|
-
return nonNegativePixels(style.marginTop) + nonNegativePixels(style.paddingTop) + nonNegativePixels(style.borderTopWidth);
|
|
285
|
-
}
|
|
286
|
-
function verticalBlockEnd(style) {
|
|
287
|
-
return nonNegativePixels(style.marginBottom) + nonNegativePixels(style.paddingBottom) + nonNegativePixels(style.borderBottomWidth);
|
|
288
|
-
}
|
|
289
|
-
function documentInlineOffsets(editor, element) {
|
|
290
|
-
const elementRect = element.getBoundingClientRect();
|
|
291
|
-
const editorRect = editor.view.dom.getBoundingClientRect();
|
|
292
|
-
const scaleX = editor.view.dom.offsetWidth > 0 ? editorRect.width / editor.view.dom.offsetWidth : 1;
|
|
293
|
-
return {
|
|
294
|
-
inlineOffsetLeft: Math.max(0, (elementRect.left - editorRect.left) / Math.max(scaleX, 0.01)),
|
|
295
|
-
inlineOffsetRight: Math.max(0, (editorRect.right - elementRect.right) / Math.max(scaleX, 0.01))
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
function documentNodeParagraphPagination(node) {
|
|
299
|
-
return {
|
|
300
|
-
keepLines: directNodeBoolean(node, 'keepLines') ?? false,
|
|
301
|
-
keepWithNext: directNodeBoolean(node, 'keepWithNext') ?? 'heading' === node.type.name,
|
|
302
|
-
pageBreakBefore: directNodeBoolean(node, 'pageBreakBefore') ?? false,
|
|
303
|
-
widowControl: directNodeBoolean(node, 'widowControl') ?? true
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
function directNodeBoolean(node, attribute) {
|
|
307
|
-
const value = node.attrs[attribute];
|
|
308
|
-
return 'boolean' == typeof value ? value : null;
|
|
309
|
-
}
|
|
310
|
-
function measuredDocumentBlock({ block, element, from, to }) {
|
|
311
|
-
return {
|
|
312
|
-
block,
|
|
313
|
-
element,
|
|
314
|
-
from,
|
|
315
|
-
to,
|
|
316
|
-
inlineOffsetLeft: 0,
|
|
317
|
-
inlineOffsetRight: 0,
|
|
318
|
-
observeResize: true
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
function shouldKeepDocumentBlockTogether(node) {
|
|
322
|
-
return 'table' === node.type.name || 'blockquote' === node.type.name || 'codeBlock' === node.type.name || 'image' === node.type.name || 'documentNote' === node.type.name;
|
|
323
|
-
}
|
|
324
|
-
function documentPaginationLayoutKey(layout) {
|
|
325
|
-
return JSON.stringify({
|
|
326
|
-
margins: layout.margins,
|
|
327
|
-
orientation: layout.orientation,
|
|
328
|
-
pageSize: layout.pageSize
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
function documentBlockId(sectionPosition, index, position) {
|
|
332
|
-
return `section-${sectionPosition}-block-${index}-${position}`;
|
|
333
|
-
}
|
|
334
|
-
function work_document_pagination_dom_outerHeight(element) {
|
|
335
|
-
if (!element) return 0;
|
|
336
|
-
const style = getComputedStyle(element);
|
|
337
|
-
return element.offsetHeight + nonNegativePixels(style.marginTop) + nonNegativePixels(style.marginBottom);
|
|
338
|
-
}
|
|
339
|
-
function nonNegativePixels(value) {
|
|
340
|
-
const parsed = Number.parseFloat(value);
|
|
341
|
-
return Number.isFinite(parsed) ? Math.max(0, parsed) : 0;
|
|
342
|
-
}
|
|
343
|
-
function positivePixels(value) {
|
|
344
|
-
const parsed = Number.parseFloat(value);
|
|
345
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
346
|
-
}
|
|
347
|
-
function finitePixels(value) {
|
|
348
|
-
const parsed = Number.parseFloat(value);
|
|
349
|
-
return Number.isFinite(parsed) ? parsed : 0;
|
|
350
|
-
}
|
|
351
|
-
function elementForNode(editor, position) {
|
|
352
|
-
const node = editor.view.nodeDOM(position);
|
|
353
|
-
if (!node || node.nodeType !== Node.ELEMENT_NODE) return null;
|
|
354
|
-
return node;
|
|
355
|
-
}
|
|
356
|
-
const MAX_DOCUMENT_TEXT_LAYOUT_PARAGRAPHS = 1024;
|
|
357
|
-
const MAX_DOCUMENT_TEXT_LAYOUT_RUNS = 16384;
|
|
358
|
-
const MAX_DOCUMENT_TEXT_LAYOUT_BYTES = 1048576;
|
|
359
|
-
const MAX_DOCUMENT_TEXT_LAYOUT_RUNS_PER_PARAGRAPH = 4096;
|
|
360
|
-
const MAX_DOCUMENT_TEXT_LAYOUT_FONTS_PER_RUN = 8;
|
|
361
|
-
function collectDocumentTextLayoutParagraphs(editor, fonts, loadedFontIds, previous = null, dirtyFrom = 0) {
|
|
362
|
-
const paragraphs = [];
|
|
363
|
-
if (!fonts.length || 0 === loadedFontIds.size) return {
|
|
364
|
-
paragraphs
|
|
365
|
-
};
|
|
366
|
-
let runCount = 0;
|
|
367
|
-
let textBytes = 0;
|
|
368
|
-
const collectParagraph = (node, element, id, position)=>{
|
|
369
|
-
if (paragraphs.length >= MAX_DOCUMENT_TEXT_LAYOUT_PARAGRAPHS) return;
|
|
370
|
-
if (reusableDocumentLayoutBlocks(previous?.blocks ?? [], id, element, position + node.nodeSize, dirtyFrom).length) return;
|
|
371
|
-
const paragraph = documentTextLayoutParagraph(node, element, id, fonts, loadedFontIds);
|
|
372
|
-
if (!paragraph) return;
|
|
373
|
-
const paragraphBytes = utf8ByteLength(paragraph.text);
|
|
374
|
-
if (runCount + paragraph.runs.length > MAX_DOCUMENT_TEXT_LAYOUT_RUNS || textBytes + paragraphBytes > MAX_DOCUMENT_TEXT_LAYOUT_BYTES) return;
|
|
375
|
-
runCount += paragraph.runs.length;
|
|
376
|
-
textBytes += paragraphBytes;
|
|
377
|
-
paragraphs.push(paragraph);
|
|
378
|
-
};
|
|
379
|
-
editor.state.doc.forEach((section, sectionPosition)=>{
|
|
380
|
-
if ('documentSection' !== section.type.name) return;
|
|
381
|
-
let requiresBrowserLineMeasurement = false;
|
|
382
|
-
section.forEach((node, offset, index)=>{
|
|
383
|
-
if (paragraphs.length >= MAX_DOCUMENT_TEXT_LAYOUT_PARAGRAPHS) return;
|
|
384
|
-
if (isFloatingSquareDocumentImage(node)) {
|
|
385
|
-
requiresBrowserLineMeasurement = true;
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
if (requiresBrowserLineMeasurement) return;
|
|
389
|
-
const position = sectionPosition + offset + 1;
|
|
390
|
-
const element = elementForNode(editor, position);
|
|
391
|
-
if (!element) return;
|
|
392
|
-
const id = documentBlockId(sectionPosition, index, position);
|
|
393
|
-
if (isDocumentListNode(node)) return void collectDocumentListTextLayoutParagraphs(editor, node, position, id, collectParagraph);
|
|
394
|
-
collectParagraph(node, element, id, position);
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
return {
|
|
398
|
-
paragraphs
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
function isFloatingSquareDocumentImage(node) {
|
|
402
|
-
return 'image' === node.type.name && 'square' === node.attrs.layout && ('left' === node.attrs.alignment || 'right' === node.attrs.alignment);
|
|
403
|
-
}
|
|
404
|
-
function collectDocumentListTextLayoutParagraphs(editor, list, listPosition, listId, collectParagraph) {
|
|
405
|
-
list.forEach((item, itemOffset, itemIndex)=>{
|
|
406
|
-
if ('listItem' !== item.type.name) return;
|
|
407
|
-
const itemPosition = listPosition + itemOffset + 1;
|
|
408
|
-
item.forEach((node, offset, index)=>{
|
|
409
|
-
const position = itemPosition + offset + 1;
|
|
410
|
-
const nestedList = isDocumentListNode(node);
|
|
411
|
-
const id = documentListChildId(listId, itemIndex, node, index, nestedList);
|
|
412
|
-
if (nestedList) return void collectDocumentListTextLayoutParagraphs(editor, node, position, id, collectParagraph);
|
|
413
|
-
const element = elementForNode(editor, position);
|
|
414
|
-
if (element) collectParagraph(node, element, id, position);
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
function utf8ByteLength(value) {
|
|
419
|
-
let bytes = 0;
|
|
420
|
-
for(let index = 0; index < value.length; index += 1){
|
|
421
|
-
const code = value.charCodeAt(index);
|
|
422
|
-
if (code <= 0x7f) bytes += 1;
|
|
423
|
-
else if (code <= 0x7ff) bytes += 2;
|
|
424
|
-
else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length && value.charCodeAt(index + 1) >= 0xdc00 && value.charCodeAt(index + 1) <= 0xdfff) {
|
|
425
|
-
bytes += 4;
|
|
426
|
-
index += 1;
|
|
427
|
-
} else bytes += 3;
|
|
428
|
-
}
|
|
429
|
-
return bytes;
|
|
430
|
-
}
|
|
431
|
-
function documentTextLayoutParagraph(node, element, id, fonts, loadedFontIds) {
|
|
432
|
-
const text = documentTextLayoutContent(node);
|
|
433
|
-
if (!isDocumentLineFragmentNode(node) || null === text || text.length < 2 || text.includes('\u00ad') || element.querySelector('img,br,table,[data-document-note],[contenteditable="false"]:not(.work-document-auto-page-break):not([data-document-tab])')) return null;
|
|
434
|
-
const style = getComputedStyle(element);
|
|
435
|
-
const paragraphStyle = documentTextParagraphStyle(style);
|
|
436
|
-
const hasTabs = text.includes('\t');
|
|
437
|
-
if (!paragraphStyle || hasTabs && 'ltr' !== paragraphStyle.direction) return null;
|
|
438
|
-
const runs = collectDocumentTextLayoutRuns(element, text, fonts, loadedFontIds, paragraphStyle);
|
|
439
|
-
if (!runs) return null;
|
|
440
|
-
const width = element.clientWidth || element.offsetWidth || positivePixels(style.width);
|
|
441
|
-
const maxWidth = width - nonNegativePixels(style.paddingLeft) - nonNegativePixels(style.paddingRight);
|
|
442
|
-
if (maxWidth <= 1) return null;
|
|
443
|
-
const textIndent = finitePixels(style.textIndent);
|
|
444
|
-
return {
|
|
445
|
-
id,
|
|
446
|
-
text,
|
|
447
|
-
runs,
|
|
448
|
-
maxWidth,
|
|
449
|
-
firstLineMaxWidth: Math.max(1, maxWidth - textIndent),
|
|
450
|
-
direction: paragraphStyle.direction,
|
|
451
|
-
whiteSpace: paragraphStyle.whiteSpace,
|
|
452
|
-
...hasTabs ? {
|
|
453
|
-
tabLayout: {
|
|
454
|
-
origin: nonNegativePixels(style.marginLeft),
|
|
455
|
-
firstLineIndent: textIndent,
|
|
456
|
-
defaultInterval: 48,
|
|
457
|
-
stops: normalizeDocumentTabStops(node.attrs.tabStops).map(({ position, alignment })=>({
|
|
458
|
-
position,
|
|
459
|
-
alignment
|
|
460
|
-
}))
|
|
461
|
-
}
|
|
462
|
-
} : {}
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
function isDocumentLineFragmentNode(node) {
|
|
466
|
-
return 'paragraph' === node.type.name || 'heading' === node.type.name;
|
|
467
|
-
}
|
|
468
|
-
function documentTextLayoutContent(node) {
|
|
469
|
-
const content = [];
|
|
470
|
-
let supported = true;
|
|
471
|
-
node.forEach((child)=>{
|
|
472
|
-
if (child.isText) content.push(child.text ?? '');
|
|
473
|
-
else if ('documentTab' === child.type.name) content.push('\t');
|
|
474
|
-
else supported = false;
|
|
475
|
-
});
|
|
476
|
-
return supported ? content.join('') : null;
|
|
477
|
-
}
|
|
478
|
-
function collectDocumentTextLayoutRuns(element, expectedText, fonts, loadedFontIds, paragraphStyle = documentTextParagraphStyle(getComputedStyle(element))) {
|
|
479
|
-
if (!paragraphStyle) return null;
|
|
480
|
-
const tokens = documentTextLayoutDomTokens(element);
|
|
481
|
-
if (!tokens) return null;
|
|
482
|
-
const text = [];
|
|
483
|
-
const runs = [];
|
|
484
|
-
let utf16Offset = 0;
|
|
485
|
-
for (const token of tokens){
|
|
486
|
-
const runStyle = documentTextLayoutRunStyle(getComputedStyle(token.styleElement), fonts, loadedFontIds, paragraphStyle, token.styleElement === element);
|
|
487
|
-
if (!runStyle) return null;
|
|
488
|
-
const startUtf16 = utf16Offset;
|
|
489
|
-
utf16Offset += token.text.length;
|
|
490
|
-
text.push(token.text);
|
|
491
|
-
const previous = runs.at(-1);
|
|
492
|
-
if (previous && previous.endUtf16 === startUtf16 && documentTextLayoutRunStyleKey(previous) === documentTextLayoutRunStyleKey(runStyle)) previous.endUtf16 = utf16Offset;
|
|
493
|
-
else runs.push({
|
|
494
|
-
startUtf16,
|
|
495
|
-
endUtf16: utf16Offset,
|
|
496
|
-
...runStyle
|
|
497
|
-
});
|
|
498
|
-
if (runs.length > MAX_DOCUMENT_TEXT_LAYOUT_RUNS_PER_PARAGRAPH) return null;
|
|
499
|
-
}
|
|
500
|
-
return text.join('') === expectedText && runs.length ? runs : null;
|
|
501
|
-
}
|
|
502
|
-
function documentTextLayoutDomTokens(element) {
|
|
503
|
-
const tokens = [];
|
|
504
|
-
const visit = (node)=>{
|
|
505
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
506
|
-
const textNode = node;
|
|
507
|
-
if (!textNode.data.length) return true;
|
|
508
|
-
const parent = textNode.parentElement;
|
|
509
|
-
if (!parent) return false;
|
|
510
|
-
tokens.push({
|
|
511
|
-
text: textNode.data,
|
|
512
|
-
styleElement: parent
|
|
513
|
-
});
|
|
514
|
-
return true;
|
|
515
|
-
}
|
|
516
|
-
if (node.nodeType !== Node.ELEMENT_NODE) return true;
|
|
517
|
-
const child = node;
|
|
518
|
-
if (child.classList.contains('work-document-auto-page-break')) return true;
|
|
519
|
-
if (child.matches('[data-document-tab]')) {
|
|
520
|
-
tokens.push({
|
|
521
|
-
text: '\t',
|
|
522
|
-
styleElement: child.parentElement ?? element
|
|
523
|
-
});
|
|
524
|
-
return true;
|
|
525
|
-
}
|
|
526
|
-
if ('false' === child.contentEditable) return true;
|
|
527
|
-
return Array.from(child.childNodes).every(visit);
|
|
528
|
-
};
|
|
529
|
-
return Array.from(element.childNodes).every(visit) ? tokens : null;
|
|
530
|
-
}
|
|
531
|
-
function documentTextParagraphStyle(style) {
|
|
532
|
-
if (!cssValueIs(style.whiteSpace, 'normal', 'break-spaces') || !cssValueIs(style.overflowWrap, 'normal', 'anywhere', 'break-word') || !cssValueIs(style.wordBreak, 'normal') || !cssValueIs(style.hyphens, 'manual', 'none') || !cssValueIs(style.textTransform, 'none') || !cssValueIs(style.unicodeBidi, 'normal', 'isolate')) return null;
|
|
533
|
-
return {
|
|
534
|
-
direction: 'rtl' === style.direction ? 'rtl' : 'ltr',
|
|
535
|
-
whiteSpace: 'break-spaces' === style.whiteSpace ? 'breakSpaces' : 'normal'
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
function documentTextLayoutRunStyle(style, fonts, loadedFontIds, paragraphStyle, paragraphRoot) {
|
|
539
|
-
const direction = 'rtl' === style.direction ? 'rtl' : 'ltr';
|
|
540
|
-
const whiteSpace = 'break-spaces' === style.whiteSpace ? 'breakSpaces' : 'normal';
|
|
541
|
-
if (direction !== paragraphStyle.direction || whiteSpace !== paragraphStyle.whiteSpace || !cssValueIs(style.whiteSpace, 'normal', 'break-spaces') || !cssValueIs(style.overflowWrap, 'normal', 'anywhere', 'break-word') || !cssValueIs(style.wordBreak, 'normal') || !cssValueIs(style.hyphens, 'manual', 'none') || !cssValueIs(style.wordSpacing, 'normal', '0', '0px') || !cssValueIs(style.textTransform, 'none') || !cssValueIs(style.fontVariationSettings, 'normal') || !cssValueIs(style.fontVariantCaps, 'normal') || !cssValueIs(style.fontVariantEastAsian, 'normal') || !cssValueIs(style.fontVariantNumeric, 'normal') || !cssValueIs(style.fontVariantPosition, 'normal') || !cssValueIs(style.fontStretch, 'normal', '100%') || !cssValueIs(style.verticalAlign, 'baseline') || !cssValueIs(style.unicodeBidi, 'normal') && !(paragraphRoot && 'isolate' === style.unicodeBidi)) return null;
|
|
542
|
-
const fontStyle = style.fontStyle && 'normal' !== style.fontStyle ? 'italic' === style.fontStyle ? 'italic' : null : 'normal';
|
|
543
|
-
if (!fontStyle) return null;
|
|
544
|
-
const families = cssFontFamilies(style.fontFamily);
|
|
545
|
-
if (!families?.length) return null;
|
|
546
|
-
const weight = cssFontWeight(style.fontWeight);
|
|
547
|
-
const matchedFonts = [];
|
|
548
|
-
for (const family of families){
|
|
549
|
-
if (isGenericCssFontFamily(family)) break;
|
|
550
|
-
const font = matchingDocumentLayoutFont(fonts, loadedFontIds, family, weight, fontStyle);
|
|
551
|
-
if (!font) return null;
|
|
552
|
-
if (!matchedFonts.some((candidate)=>candidate.id === font.id)) matchedFonts.push(font);
|
|
553
|
-
if (matchedFonts.length > MAX_DOCUMENT_TEXT_LAYOUT_FONTS_PER_RUN) return null;
|
|
554
|
-
}
|
|
555
|
-
const [font, ...fallbackFonts] = matchedFonts;
|
|
556
|
-
if (!font) return null;
|
|
557
|
-
const fontSize = positivePixels(style.fontSize);
|
|
558
|
-
const lineHeight = positivePixels(style.lineHeight) || Math.max(1, 1.2 * fontSize);
|
|
559
|
-
if (fontSize <= 0 || fontSize > 512 || lineHeight <= 0 || lineHeight > 2048) return null;
|
|
560
|
-
const ligatures = cssLigatures(style);
|
|
561
|
-
const kerning = cssKerning(style.fontKerning);
|
|
562
|
-
if (null === ligatures || null === kerning) return null;
|
|
563
|
-
const letterSpacing = style.letterSpacing && 'normal' !== style.letterSpacing ? finitePixels(style.letterSpacing) : 0;
|
|
564
|
-
if (letterSpacing < -100 || letterSpacing > 100) return null;
|
|
565
|
-
return {
|
|
566
|
-
fontId: font.id,
|
|
567
|
-
...fallbackFonts.length ? {
|
|
568
|
-
fallbackFontIds: fallbackFonts.map((candidate)=>candidate.id)
|
|
569
|
-
} : {},
|
|
570
|
-
fontSize,
|
|
571
|
-
lineHeight,
|
|
572
|
-
letterSpacing,
|
|
573
|
-
ligatures,
|
|
574
|
-
kerning
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
function matchingDocumentLayoutFont(fonts, loadedFontIds, family, requestedWeight, requestedStyle) {
|
|
578
|
-
const candidates = fonts.filter((font)=>loadedFontIds.has(font.id) && font.family === family && (font.style ?? 'normal') === requestedStyle);
|
|
579
|
-
const exact = candidates.find((font)=>(font.weight ?? 400) === requestedWeight);
|
|
580
|
-
if (exact) return exact;
|
|
581
|
-
const weights = Array.from(new Set(candidates.map((font)=>font.weight ?? 400))).sort((left, right)=>left - right);
|
|
582
|
-
const matchedWeight = cssFontWeightSearchOrder(weights, requestedWeight)[0];
|
|
583
|
-
return void 0 === matchedWeight ? void 0 : candidates.find((font)=>(font.weight ?? 400) === matchedWeight);
|
|
584
|
-
}
|
|
585
|
-
function cssFontWeightSearchOrder(weights, requestedWeight) {
|
|
586
|
-
if (requestedWeight < 400) return [
|
|
587
|
-
...weights.filter((weight)=>weight <= requestedWeight).sort((left, right)=>right - left),
|
|
588
|
-
...weights.filter((weight)=>weight > requestedWeight).sort((left, right)=>left - right)
|
|
589
|
-
];
|
|
590
|
-
if (requestedWeight <= 500) return [
|
|
591
|
-
...weights.filter((weight)=>weight >= requestedWeight && weight <= 500).sort((left, right)=>left - right),
|
|
592
|
-
...weights.filter((weight)=>weight < requestedWeight).sort((left, right)=>right - left),
|
|
593
|
-
...weights.filter((weight)=>weight > 500).sort((left, right)=>left - right)
|
|
594
|
-
];
|
|
595
|
-
return [
|
|
596
|
-
...weights.filter((weight)=>weight >= requestedWeight).sort((left, right)=>left - right),
|
|
597
|
-
...weights.filter((weight)=>weight < requestedWeight).sort((left, right)=>right - left)
|
|
598
|
-
];
|
|
599
|
-
}
|
|
600
|
-
function documentTextLayoutRunStyleKey(style) {
|
|
601
|
-
return [
|
|
602
|
-
style.fontId,
|
|
603
|
-
(style.fallbackFontIds ?? []).join('\u0002'),
|
|
604
|
-
style.fontSize,
|
|
605
|
-
style.lineHeight,
|
|
606
|
-
style.letterSpacing ?? 0,
|
|
607
|
-
style.ligatures ?? true,
|
|
608
|
-
style.kerning ?? true
|
|
609
|
-
].join('\u0000');
|
|
610
|
-
}
|
|
611
|
-
function cssValueIs(value, ...supported) {
|
|
612
|
-
return !value || supported.includes(value);
|
|
613
|
-
}
|
|
614
|
-
function cssLigatures(style) {
|
|
615
|
-
const variant = style.fontVariantLigatures;
|
|
616
|
-
if (variant && 'normal' !== variant && 'none' !== variant) return null;
|
|
617
|
-
const features = style.fontFeatureSettings;
|
|
618
|
-
if (!features || 'normal' === features) return 'none' !== variant;
|
|
619
|
-
if (/^["']?liga["']?\s+(?:0|off)$/i.test(features.trim())) return false;
|
|
620
|
-
return null;
|
|
621
|
-
}
|
|
622
|
-
function cssKerning(value) {
|
|
623
|
-
if (!value || 'auto' === value || 'normal' === value) return true;
|
|
624
|
-
if ('none' === value) return false;
|
|
625
|
-
return null;
|
|
626
|
-
}
|
|
627
|
-
function cssFontFamilies(value) {
|
|
628
|
-
const families = [];
|
|
629
|
-
let current = '';
|
|
630
|
-
let quote = null;
|
|
631
|
-
let escaped = false;
|
|
632
|
-
const pushCurrent = ()=>{
|
|
633
|
-
const family = current.trim();
|
|
634
|
-
current = '';
|
|
635
|
-
if (!family) return false;
|
|
636
|
-
families.push(family);
|
|
637
|
-
return true;
|
|
638
|
-
};
|
|
639
|
-
for (const character of value){
|
|
640
|
-
if (escaped) {
|
|
641
|
-
current += character;
|
|
642
|
-
escaped = false;
|
|
643
|
-
continue;
|
|
644
|
-
}
|
|
645
|
-
if ('\\' === character) {
|
|
646
|
-
escaped = true;
|
|
647
|
-
continue;
|
|
648
|
-
}
|
|
649
|
-
if (quote) {
|
|
650
|
-
if (character === quote) quote = null;
|
|
651
|
-
else current += character;
|
|
652
|
-
continue;
|
|
653
|
-
}
|
|
654
|
-
if ('"' === character || "'" === character) {
|
|
655
|
-
if (current.trim()) return null;
|
|
656
|
-
quote = character;
|
|
657
|
-
continue;
|
|
658
|
-
}
|
|
659
|
-
if (',' === character) {
|
|
660
|
-
if (!pushCurrent()) return null;
|
|
661
|
-
continue;
|
|
662
|
-
}
|
|
663
|
-
current += character;
|
|
664
|
-
}
|
|
665
|
-
if (escaped || quote || !pushCurrent()) return null;
|
|
666
|
-
return families;
|
|
667
|
-
}
|
|
668
|
-
function isGenericCssFontFamily(family) {
|
|
669
|
-
return CSS_GENERIC_FONT_FAMILIES.has(family.toLowerCase());
|
|
670
|
-
}
|
|
671
|
-
const CSS_GENERIC_FONT_FAMILIES = new Set([
|
|
672
|
-
'cursive',
|
|
673
|
-
'emoji',
|
|
674
|
-
'fangsong',
|
|
675
|
-
'fantasy',
|
|
676
|
-
'math',
|
|
677
|
-
'monospace',
|
|
678
|
-
'sans-serif',
|
|
679
|
-
'serif',
|
|
680
|
-
'system-ui',
|
|
681
|
-
'ui-monospace',
|
|
682
|
-
'ui-rounded',
|
|
683
|
-
'ui-sans-serif',
|
|
684
|
-
'ui-serif'
|
|
685
|
-
]);
|
|
686
|
-
function cssFontWeight(value) {
|
|
687
|
-
if ('normal' === value) return 400;
|
|
688
|
-
if ('bold' === value) return 700;
|
|
689
|
-
const parsed = Number.parseInt(value, 10);
|
|
690
|
-
return Number.isFinite(parsed) ? parsed : 400;
|
|
691
|
-
}
|
|
692
|
-
function createDocumentLineFragments(lines, outerTop, outerBottom, scale = 1) {
|
|
693
|
-
const normalizedScale = Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
694
|
-
return lines.flatMap((line, index)=>{
|
|
695
|
-
const next = lines[index + 1];
|
|
696
|
-
const start = 0 === index ? outerTop : line.top;
|
|
697
|
-
const end = next?.top ?? outerBottom;
|
|
698
|
-
const from = line.position;
|
|
699
|
-
const to = next?.position ?? from + 1;
|
|
700
|
-
if (end <= start || to <= from) return [];
|
|
701
|
-
return [
|
|
702
|
-
{
|
|
703
|
-
from,
|
|
704
|
-
to,
|
|
705
|
-
height: Math.max(1, (end - start) / normalizedScale)
|
|
706
|
-
}
|
|
707
|
-
];
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
function measureParagraphLineFragments(editor, node, element, id, from, to, pagination, shapedLayout) {
|
|
711
|
-
const text = documentTextLayoutContent(node);
|
|
712
|
-
if (!isDocumentLineFragmentNode(node) || (text ?? node.textContent).length < 2 || element.querySelector('img,table,[data-document-note],[contenteditable="false"]:not(.work-document-auto-page-break):not([data-document-tab])')) return [];
|
|
713
|
-
if (null !== text && shapedLayout?.missingGlyphCount === 0) {
|
|
714
|
-
const shaped = measureShapedParagraphLineFragments(editor, element, id, from, to, pagination, shapedLayout);
|
|
715
|
-
if (shaped.length > 1) return shaped;
|
|
716
|
-
}
|
|
717
|
-
const range = element.ownerDocument.createRange();
|
|
718
|
-
if ('function' != typeof range.getClientRects) return [];
|
|
719
|
-
range.selectNodeContents(element);
|
|
720
|
-
const rects = groupDocumentLineRects(Array.from(range.getClientRects()).filter((rect)=>rect.height > 0 && rect.width > 0).map((rect)=>({
|
|
721
|
-
top: rect.top,
|
|
722
|
-
right: rect.right,
|
|
723
|
-
bottom: rect.bottom,
|
|
724
|
-
left: rect.left
|
|
725
|
-
})));
|
|
726
|
-
range.detach();
|
|
727
|
-
if (rects.length < 2) return [];
|
|
728
|
-
const textNodes = measureDocumentTextNodes(element);
|
|
729
|
-
const lines = rects.flatMap((rect, index)=>{
|
|
730
|
-
if (0 === index) return [
|
|
731
|
-
{
|
|
732
|
-
...rect,
|
|
733
|
-
position: from
|
|
734
|
-
}
|
|
735
|
-
];
|
|
736
|
-
const position = documentPositionAtMeasuredLineStart(editor, textNodes, rect) ?? documentPositionAtPoint(editor, element, rect);
|
|
737
|
-
const previous = rects[index - 1];
|
|
738
|
-
if (null === position || position <= from || position >= to || rect.top <= previous.top) return [];
|
|
739
|
-
return [
|
|
740
|
-
{
|
|
741
|
-
...rect,
|
|
742
|
-
position
|
|
743
|
-
}
|
|
744
|
-
];
|
|
745
|
-
});
|
|
746
|
-
const uniqueLines = lines.filter((line, index)=>0 === index || line.position > lines[index - 1].position);
|
|
747
|
-
if (uniqueLines.length !== rects.length) return [];
|
|
748
|
-
const elementRect = element.getBoundingClientRect();
|
|
749
|
-
const style = getComputedStyle(element);
|
|
750
|
-
const scaleY = element.offsetHeight > 0 ? elementRect.height / element.offsetHeight : 1;
|
|
751
|
-
const outerTop = elementRect.top - nonNegativePixels(style.marginTop) * scaleY;
|
|
752
|
-
const outerBottom = elementRect.bottom + nonNegativePixels(style.marginBottom) * scaleY;
|
|
753
|
-
const fragments = createDocumentLineFragments(uniqueLines, outerTop, outerBottom, scaleY);
|
|
754
|
-
if (fragments.length !== uniqueLines.length) return [];
|
|
755
|
-
const editorRect = editor.view.dom.getBoundingClientRect();
|
|
756
|
-
const scaleX = editor.view.dom.offsetWidth > 0 ? editorRect.width / editor.view.dom.offsetWidth : 1;
|
|
757
|
-
const inlineOffsetLeft = Math.max(0, (elementRect.left - editorRect.left) / Math.max(scaleX, 0.01));
|
|
758
|
-
const inlineOffsetRight = Math.max(0, (editorRect.right - elementRect.right) / Math.max(scaleX, 0.01));
|
|
759
|
-
const minimumFragmentsPerPage = pagination.widowControl ? Math.min(2, fragments.length) : 1;
|
|
760
|
-
return fragments.map((fragment, flowIndex)=>({
|
|
761
|
-
block: {
|
|
762
|
-
id: `${id}-line-${flowIndex}`,
|
|
763
|
-
height: fragment.height,
|
|
764
|
-
breakBefore: 0 === flowIndex && pagination.pageBreakBefore,
|
|
765
|
-
keepTogether: 0 === flowIndex && pagination.keepLines,
|
|
766
|
-
keepWithNext: flowIndex + 1 === fragments.length && pagination.keepWithNext,
|
|
767
|
-
flowId: id,
|
|
768
|
-
flowIndex,
|
|
769
|
-
flowCount: fragments.length,
|
|
770
|
-
minimumFragmentsPerPage
|
|
771
|
-
},
|
|
772
|
-
element,
|
|
773
|
-
from: fragment.from,
|
|
774
|
-
to: flowIndex + 1 < fragments.length ? fragment.to : to,
|
|
775
|
-
inlineOffsetLeft: 0 === flowIndex ? 0 : inlineOffsetLeft,
|
|
776
|
-
inlineOffsetRight: 0 === flowIndex ? 0 : inlineOffsetRight,
|
|
777
|
-
observeResize: false
|
|
778
|
-
}));
|
|
779
|
-
}
|
|
780
|
-
function measureShapedParagraphLineFragments(editor, element, id, from, to, pagination, layout) {
|
|
781
|
-
if (layout.lines.length < 2) return [];
|
|
782
|
-
const style = getComputedStyle(element);
|
|
783
|
-
const fragments = createShapedDocumentLineFragments(layout.lines, from, to, verticalBlockStart(style), verticalBlockEnd(style));
|
|
784
|
-
if (fragments.length !== layout.lines.length) return [];
|
|
785
|
-
const { inlineOffsetLeft, inlineOffsetRight } = documentInlineOffsets(editor, element);
|
|
786
|
-
const minimumFragmentsPerPage = pagination.widowControl ? Math.min(2, fragments.length) : 1;
|
|
787
|
-
return fragments.map((fragment, flowIndex)=>({
|
|
788
|
-
block: {
|
|
789
|
-
id: `${id}-line-${flowIndex}`,
|
|
790
|
-
height: fragment.height,
|
|
791
|
-
breakBefore: 0 === flowIndex && pagination.pageBreakBefore,
|
|
792
|
-
keepTogether: 0 === flowIndex && pagination.keepLines,
|
|
793
|
-
keepWithNext: flowIndex + 1 === fragments.length && pagination.keepWithNext,
|
|
794
|
-
flowId: id,
|
|
795
|
-
flowIndex,
|
|
796
|
-
flowCount: fragments.length,
|
|
797
|
-
minimumFragmentsPerPage
|
|
798
|
-
},
|
|
799
|
-
element,
|
|
800
|
-
from: fragment.from,
|
|
801
|
-
to: fragment.to,
|
|
802
|
-
inlineOffsetLeft: 0 === flowIndex ? 0 : inlineOffsetLeft,
|
|
803
|
-
inlineOffsetRight: 0 === flowIndex ? 0 : inlineOffsetRight,
|
|
804
|
-
observeResize: false
|
|
805
|
-
}));
|
|
806
|
-
}
|
|
807
|
-
function createShapedDocumentLineFragments(lines, nodeFrom, nodeTo, blockStart, blockEnd) {
|
|
808
|
-
const fragments = [];
|
|
809
|
-
for (const [index, line] of lines.entries()){
|
|
810
|
-
const next = lines[index + 1];
|
|
811
|
-
const from = 0 === index ? nodeFrom : nodeFrom + 1 + Math.max(0, line.startUtf16);
|
|
812
|
-
const to = next ? nodeFrom + 1 + Math.max(0, next.startUtf16) : nodeTo;
|
|
813
|
-
if (line.endUtf16 < line.startUtf16 || next && next.startUtf16 < line.endUtf16 || !Number.isSafeInteger(from) || !Number.isSafeInteger(to) || to <= from || from < nodeFrom || to > nodeTo) return [];
|
|
814
|
-
fragments.push({
|
|
815
|
-
from,
|
|
816
|
-
to,
|
|
817
|
-
height: line.height + (0 === index ? blockStart : 0) + (index + 1 === lines.length ? blockEnd : 0)
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
return fragments;
|
|
821
|
-
}
|
|
822
|
-
function groupDocumentLineRects(rects) {
|
|
823
|
-
const lines = [];
|
|
824
|
-
for (const rect of [
|
|
825
|
-
...rects
|
|
826
|
-
].sort((left, right)=>left.top - right.top || left.left - right.left)){
|
|
827
|
-
const line = lines.find((candidate)=>verticallyOverlaps(candidate, rect));
|
|
828
|
-
if (line) {
|
|
829
|
-
line.top = Math.min(line.top, rect.top);
|
|
830
|
-
line.right = Math.max(line.right, rect.right);
|
|
831
|
-
line.bottom = Math.max(line.bottom, rect.bottom);
|
|
832
|
-
line.left = Math.min(line.left, rect.left);
|
|
833
|
-
} else lines.push({
|
|
834
|
-
...rect
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
return lines.sort((left, right)=>left.top - right.top);
|
|
838
|
-
}
|
|
839
|
-
function verticallyOverlaps(left, right) {
|
|
840
|
-
const overlap = Math.min(left.bottom, right.bottom) - Math.max(left.top, right.top);
|
|
841
|
-
const minimumHeight = Math.min(left.bottom - left.top, right.bottom - right.top);
|
|
842
|
-
return overlap > Math.max(1, 0.2 * minimumHeight);
|
|
843
|
-
}
|
|
844
|
-
function measureDocumentTextNodes(element) {
|
|
845
|
-
const measurements = [];
|
|
846
|
-
const showText = element.ownerDocument.defaultView?.NodeFilter.SHOW_TEXT ?? 4;
|
|
847
|
-
const walker = element.ownerDocument.createTreeWalker(element, showText);
|
|
848
|
-
let current = walker.nextNode();
|
|
849
|
-
while(current){
|
|
850
|
-
const node = current;
|
|
851
|
-
if (node.data.length > 0 && !node.parentElement?.closest('.work-document-auto-page-break, [contenteditable="false"]')) {
|
|
852
|
-
const range = element.ownerDocument.createRange();
|
|
853
|
-
range.selectNodeContents(node);
|
|
854
|
-
const rects = Array.from(range.getClientRects()).filter((rect)=>rect.height > 0 && rect.width > 0).map((rect)=>({
|
|
855
|
-
top: rect.top,
|
|
856
|
-
right: rect.right,
|
|
857
|
-
bottom: rect.bottom,
|
|
858
|
-
left: rect.left
|
|
859
|
-
}));
|
|
860
|
-
range.detach();
|
|
861
|
-
if (rects.length) measurements.push({
|
|
862
|
-
node,
|
|
863
|
-
rects
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
current = walker.nextNode();
|
|
867
|
-
}
|
|
868
|
-
return measurements;
|
|
869
|
-
}
|
|
870
|
-
function documentPositionAtMeasuredLineStart(editor, textNodes, line) {
|
|
871
|
-
for (const measurement of textNodes){
|
|
872
|
-
if (!measurement.rects.some((rect)=>verticallyOverlaps(rect, line))) continue;
|
|
873
|
-
const range = measurement.node.ownerDocument.createRange();
|
|
874
|
-
const offset = findDocumentLineStartOffset(measurement.node.data.length, line, (candidate)=>{
|
|
875
|
-
range.setStart(measurement.node, candidate);
|
|
876
|
-
range.setEnd(measurement.node, candidate + 1);
|
|
877
|
-
const rectangle = Array.from(range.getClientRects()).find((rect)=>rect.height > 0 && rect.width > 0);
|
|
878
|
-
return rectangle ? {
|
|
879
|
-
top: rectangle.top,
|
|
880
|
-
bottom: rectangle.bottom
|
|
881
|
-
} : null;
|
|
882
|
-
});
|
|
883
|
-
range.detach();
|
|
884
|
-
if (null !== offset) try {
|
|
885
|
-
return editor.view.posAtDOM(measurement.node, offset);
|
|
886
|
-
} catch {}
|
|
887
|
-
}
|
|
888
|
-
return null;
|
|
889
|
-
}
|
|
890
|
-
function findDocumentLineStartOffset(textLength, line, rectangleAt) {
|
|
891
|
-
if (!Number.isSafeInteger(textLength) || textLength <= 0) return null;
|
|
892
|
-
let lower = 0;
|
|
893
|
-
let upper = textLength;
|
|
894
|
-
while(lower < upper){
|
|
895
|
-
const middle = Math.floor((lower + upper) / 2);
|
|
896
|
-
const rectangle = rectangleAt(middle);
|
|
897
|
-
if (!rectangle || rectangle.bottom <= line.top) lower = middle + 1;
|
|
898
|
-
else upper = middle;
|
|
899
|
-
}
|
|
900
|
-
const searchStart = Math.max(0, lower - 4);
|
|
901
|
-
const searchEnd = Math.min(textLength, lower + 5);
|
|
902
|
-
for(let offset = searchStart; offset < searchEnd; offset += 1){
|
|
903
|
-
const rectangle = rectangleAt(offset);
|
|
904
|
-
if (rectangle && rectangle.bottom > line.top && rectangle.top < line.bottom) return offset;
|
|
905
|
-
}
|
|
906
|
-
return null;
|
|
907
|
-
}
|
|
908
|
-
function documentPositionAtPoint(editor, element, line) {
|
|
909
|
-
const ownerDocument = element.ownerDocument;
|
|
910
|
-
const style = getComputedStyle(element);
|
|
911
|
-
const x = 'rtl' === style.direction ? line.right - 0.5 : line.left + 0.5;
|
|
912
|
-
const y = line.top + (line.bottom - line.top) / 2;
|
|
913
|
-
const caretPosition = ownerDocument.caretPositionFromPoint?.(x, y);
|
|
914
|
-
const offsetNode = caretPosition?.offsetNode ?? ownerDocument.caretRangeFromPoint?.(x, y)?.startContainer;
|
|
915
|
-
const offset = caretPosition?.offset ?? ownerDocument.caretRangeFromPoint?.(x, y)?.startOffset;
|
|
916
|
-
if (!offsetNode || void 0 === offset || offsetNode !== element && !element.contains(offsetNode)) return null;
|
|
917
|
-
try {
|
|
918
|
-
return editor.view.posAtDOM(offsetNode, offset);
|
|
919
|
-
} catch {
|
|
920
|
-
return null;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
const MAX_DOCUMENT_TABLE_ROW_FRAGMENTS = 256;
|
|
924
|
-
function createDocumentTableRowFragmentPlan(cells, rowHeight, maximumFragmentedRowHeight) {
|
|
925
|
-
const height = Math.max(1, rowHeight);
|
|
926
|
-
const atomic = ()=>[
|
|
927
|
-
{
|
|
928
|
-
height,
|
|
929
|
-
cellRanges: cells.flatMap((cell)=>cell.to > cell.from ? [
|
|
930
|
-
{
|
|
931
|
-
from: cell.from,
|
|
932
|
-
to: cell.to
|
|
933
|
-
}
|
|
934
|
-
] : [])
|
|
935
|
-
}
|
|
936
|
-
];
|
|
937
|
-
if (!cells.length || !Number.isFinite(maximumFragmentedRowHeight) || maximumFragmentedRowHeight <= 0) return atomic();
|
|
938
|
-
const candidates = normalizedDocumentTableBreakCoordinates(cells.flatMap((cell)=>cell.boundaries.slice(1, -1).map((boundary)=>boundary.y).filter((y)=>y > 0.5 && y < height - 0.5))).slice(0, MAX_DOCUMENT_TABLE_ROW_FRAGMENTS - 1);
|
|
939
|
-
if (!candidates.length) return atomic();
|
|
940
|
-
const coordinates = [
|
|
941
|
-
0,
|
|
942
|
-
...candidates,
|
|
943
|
-
height
|
|
944
|
-
];
|
|
945
|
-
const positions = coordinates.map((coordinate, coordinateIndex)=>cells.map((cell)=>{
|
|
946
|
-
if (0 === coordinateIndex) return {
|
|
947
|
-
position: cell.from,
|
|
948
|
-
y: 0
|
|
949
|
-
};
|
|
950
|
-
if (coordinateIndex + 1 === coordinates.length) return {
|
|
951
|
-
position: cell.to,
|
|
952
|
-
y: height
|
|
953
|
-
};
|
|
954
|
-
return documentTableBoundaryAtOrBefore(cell, coordinate);
|
|
955
|
-
}));
|
|
956
|
-
const fragments = coordinates.slice(0, -1).flatMap((coordinate, index)=>{
|
|
957
|
-
const nextCoordinate = coordinates[index + 1];
|
|
958
|
-
const cellRanges = cells.flatMap((_cell, cellIndex)=>{
|
|
959
|
-
const from = positions[index]?.[cellIndex]?.position;
|
|
960
|
-
const to = positions[index + 1]?.[cellIndex]?.position;
|
|
961
|
-
return void 0 !== from && void 0 !== to && to > from ? [
|
|
962
|
-
{
|
|
963
|
-
from,
|
|
964
|
-
to
|
|
965
|
-
}
|
|
966
|
-
] : [];
|
|
967
|
-
});
|
|
968
|
-
if (!cellRanges.length) return [];
|
|
969
|
-
const cellBreaks = 0 === index ? void 0 : cells.map((cell, cellIndex)=>{
|
|
970
|
-
const boundary = positions[index]?.[cellIndex] ?? {
|
|
971
|
-
position: cell.from,
|
|
972
|
-
y: 0
|
|
973
|
-
};
|
|
974
|
-
return {
|
|
975
|
-
cellIndex: cell.cellIndex,
|
|
976
|
-
position: boundary.position,
|
|
977
|
-
alignmentOffset: Math.max(0, coordinate - boundary.y),
|
|
978
|
-
...void 0 === cell.tableOffsetLeft ? {} : {
|
|
979
|
-
tableOffsetLeft: cell.tableOffsetLeft
|
|
980
|
-
},
|
|
981
|
-
...void 0 === cell.outerWidth ? {} : {
|
|
982
|
-
outerWidth: cell.outerWidth
|
|
983
|
-
},
|
|
984
|
-
...void 0 === cell.contentOffsetLeft ? {} : {
|
|
985
|
-
contentOffsetLeft: cell.contentOffsetLeft
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
});
|
|
989
|
-
return [
|
|
990
|
-
{
|
|
991
|
-
height: Math.max(1, nextCoordinate - coordinate),
|
|
992
|
-
cellRanges,
|
|
993
|
-
...cellBreaks ? {
|
|
994
|
-
cellBreaks
|
|
995
|
-
} : {}
|
|
996
|
-
}
|
|
997
|
-
];
|
|
998
|
-
});
|
|
999
|
-
return fragments.length > 1 ? fragments : atomic();
|
|
1000
|
-
}
|
|
1001
|
-
function normalizedDocumentTableBreakCoordinates(coordinates) {
|
|
1002
|
-
const result = [];
|
|
1003
|
-
for (const coordinate of [
|
|
1004
|
-
...coordinates
|
|
1005
|
-
].sort((left, right)=>left - right)){
|
|
1006
|
-
if (!Number.isFinite(coordinate)) continue;
|
|
1007
|
-
const normalized = Math.round(4 * coordinate) / 4;
|
|
1008
|
-
if (0 === result.length || normalized - result.at(-1) >= 1) result.push(normalized);
|
|
1009
|
-
}
|
|
1010
|
-
return result;
|
|
1011
|
-
}
|
|
1012
|
-
function documentTableBoundaryAtOrBefore(cell, coordinate) {
|
|
1013
|
-
let result = cell.boundaries[0] ?? {
|
|
1014
|
-
position: cell.from,
|
|
1015
|
-
y: 0
|
|
1016
|
-
};
|
|
1017
|
-
for (const boundary of cell.boundaries){
|
|
1018
|
-
if (boundary.y > coordinate + 0.5) break;
|
|
1019
|
-
result = boundary;
|
|
1020
|
-
}
|
|
1021
|
-
return result;
|
|
1022
|
-
}
|
|
1023
|
-
function measureDocumentTableRows(editor, tableNode, tableElement, tableId, tableFrom, maximumFragmentedRowHeight) {
|
|
1024
|
-
const rows = [];
|
|
1025
|
-
let complete = true;
|
|
1026
|
-
tableNode.forEach((row, offset)=>{
|
|
1027
|
-
const from = tableFrom + offset + 1;
|
|
1028
|
-
const element = elementForNode(editor, from);
|
|
1029
|
-
if ('tableRow' !== row.type.name || !element || 'tr' !== element.tagName.toLowerCase()) {
|
|
1030
|
-
complete = false;
|
|
1031
|
-
return;
|
|
1032
|
-
}
|
|
1033
|
-
rows.push({
|
|
1034
|
-
node: row,
|
|
1035
|
-
element,
|
|
1036
|
-
from,
|
|
1037
|
-
to: from + row.nodeSize,
|
|
1038
|
-
height: Math.max(1, work_document_pagination_dom_outerHeight(element))
|
|
1039
|
-
});
|
|
1040
|
-
});
|
|
1041
|
-
if (!complete || rows.length !== tableNode.childCount || !rows.length) return [];
|
|
1042
|
-
let leadingHeaderRowCount = 0;
|
|
1043
|
-
for (const row of rows){
|
|
1044
|
-
if (!documentTableRowRepeats(row.node)) break;
|
|
1045
|
-
leadingHeaderRowCount += 1;
|
|
1046
|
-
}
|
|
1047
|
-
const repeatHeaderCount = leadingHeaderRowCount < rows.length ? leadingHeaderRowCount : 0;
|
|
1048
|
-
const rowHeight = rows.reduce((sum, row)=>sum + row.height, 0);
|
|
1049
|
-
const tableStyle = getComputedStyle(tableElement);
|
|
1050
|
-
const blockStart = verticalBlockStart(tableStyle);
|
|
1051
|
-
const blockEnd = verticalBlockEnd(tableStyle);
|
|
1052
|
-
const unassignedHeight = Math.max(0, work_document_pagination_dom_outerHeight(tableElement) - rowHeight - blockStart - blockEnd);
|
|
1053
|
-
const repeatHeaderHeight = repeatHeaderCount > 0 ? rows.slice(0, repeatHeaderCount).reduce((sum, row)=>sum + row.height, 0) : 0;
|
|
1054
|
-
const tableBreak = documentTablePaginationBreak(tableElement, tableNode, tableId, rows, repeatHeaderCount, repeatHeaderHeight);
|
|
1055
|
-
const { inlineOffsetLeft, inlineOffsetRight } = documentInlineOffsets(editor, tableElement);
|
|
1056
|
-
const continuationRowHeight = Math.max(1, maximumFragmentedRowHeight - repeatHeaderHeight);
|
|
1057
|
-
const rowPlans = rows.map((row, rowIndex)=>{
|
|
1058
|
-
const cells = measureDocumentTableCellFragments(editor, row);
|
|
1059
|
-
const canSplit = rowIndex >= leadingHeaderRowCount && !documentTableRowCantSplit(row.node);
|
|
1060
|
-
return createDocumentTableRowFragmentPlan(cells, row.height, canSplit ? continuationRowHeight : 0);
|
|
1061
|
-
});
|
|
1062
|
-
const flowCount = rowPlans.reduce((count, fragments)=>count + fragments.length, 0);
|
|
1063
|
-
const repeatHeaderFragmentCount = repeatHeaderCount > 0 ? rowPlans.slice(0, repeatHeaderCount).reduce((count, fragments)=>count + fragments.length, 0) : 0;
|
|
1064
|
-
const result = [];
|
|
1065
|
-
let flowIndex = 0;
|
|
1066
|
-
for (const [rowIndex, row] of rows.entries()){
|
|
1067
|
-
const fragments = rowPlans[rowIndex] ?? [];
|
|
1068
|
-
for (const [fragmentIndex, fragment] of fragments.entries()){
|
|
1069
|
-
const first = 0 === flowIndex;
|
|
1070
|
-
const last = flowIndex + 1 === flowCount;
|
|
1071
|
-
const repeatsHeader = repeatHeaderFragmentCount > 0 && flowIndex >= repeatHeaderFragmentCount;
|
|
1072
|
-
result.push({
|
|
1073
|
-
block: {
|
|
1074
|
-
id: fragments.length > 1 ? `${tableId}-row-${rowIndex}-fragment-${fragmentIndex}` : `${tableId}-row-${rowIndex}`,
|
|
1075
|
-
height: fragment.height + (first ? blockStart : 0) + (last ? blockEnd + unassignedHeight : 0),
|
|
1076
|
-
...flowCount > 1 ? {
|
|
1077
|
-
flowId: tableId,
|
|
1078
|
-
flowIndex,
|
|
1079
|
-
flowCount,
|
|
1080
|
-
minimumFragmentsPerPage: 1
|
|
1081
|
-
} : {},
|
|
1082
|
-
...flowCount > 1 && repeatHeaderFragmentCount > 0 ? {
|
|
1083
|
-
repeatHeaderCount: repeatHeaderFragmentCount,
|
|
1084
|
-
repeatHeaderHeight
|
|
1085
|
-
} : {}
|
|
1086
|
-
},
|
|
1087
|
-
element: tableElement,
|
|
1088
|
-
from: row.from,
|
|
1089
|
-
to: row.to,
|
|
1090
|
-
inlineOffsetLeft,
|
|
1091
|
-
inlineOffsetRight,
|
|
1092
|
-
observeResize: false,
|
|
1093
|
-
selectionRanges: fragment.cellRanges,
|
|
1094
|
-
tableBreak: {
|
|
1095
|
-
...tableBreak,
|
|
1096
|
-
repeatedHeaderRowsHtml: repeatsHeader ? tableBreak.repeatedHeaderRowsHtml : [],
|
|
1097
|
-
repeatedHeaderOverlayHtml: repeatsHeader ? tableBreak.repeatedHeaderOverlayHtml : '',
|
|
1098
|
-
...fragment.cellBreaks ? {
|
|
1099
|
-
cellBreaks: fragment.cellBreaks
|
|
1100
|
-
} : {}
|
|
1101
|
-
}
|
|
1102
|
-
});
|
|
1103
|
-
flowIndex += 1;
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
return result;
|
|
1107
|
-
}
|
|
1108
|
-
function measureDocumentTableCellFragments(editor, row) {
|
|
1109
|
-
const rowRect = row.element.getBoundingClientRect();
|
|
1110
|
-
const tableElement = row.element.closest('table');
|
|
1111
|
-
const tableRect = tableElement?.getBoundingClientRect();
|
|
1112
|
-
const scaleX = tableElement && tableElement.offsetWidth > 0 && tableRect ? tableRect.width / tableElement.offsetWidth : 1;
|
|
1113
|
-
const scaleY = row.element.offsetHeight > 0 ? rowRect.height / row.element.offsetHeight : 1;
|
|
1114
|
-
const result = [];
|
|
1115
|
-
row.node.forEach((cell, cellOffset, cellIndex)=>{
|
|
1116
|
-
const from = row.from + cellOffset + 2;
|
|
1117
|
-
const to = row.from + cellOffset + cell.nodeSize;
|
|
1118
|
-
const element = elementForNode(editor, from - 1);
|
|
1119
|
-
const boundaries = [];
|
|
1120
|
-
cell.forEach((_block, blockOffset, blockIndex)=>{
|
|
1121
|
-
const position = from + blockOffset;
|
|
1122
|
-
const blockElement = elementForNode(editor, position);
|
|
1123
|
-
if (!blockElement) return;
|
|
1124
|
-
const rect = blockElement.getBoundingClientRect();
|
|
1125
|
-
const style = getComputedStyle(blockElement);
|
|
1126
|
-
const y = Math.max(0, (rect.top - rowRect.top) / Math.max(scaleY, 0.01) - nonNegativePixels(style.marginTop));
|
|
1127
|
-
if (0 === blockIndex) boundaries.push({
|
|
1128
|
-
position: from,
|
|
1129
|
-
y
|
|
1130
|
-
});
|
|
1131
|
-
else boundaries.push({
|
|
1132
|
-
position,
|
|
1133
|
-
y
|
|
1134
|
-
});
|
|
1135
|
-
});
|
|
1136
|
-
const cellStyle = element ? getComputedStyle(element) : null;
|
|
1137
|
-
const cellRect = element?.getBoundingClientRect();
|
|
1138
|
-
const contentStart = boundaries[0]?.y ?? (cellRect ? (cellRect.top - rowRect.top) / Math.max(scaleY, 0.01) + nonNegativePixels(cellStyle?.borderTopWidth ?? '') + nonNegativePixels(cellStyle?.paddingTop ?? '') : 0);
|
|
1139
|
-
if (!boundaries.length) boundaries.push({
|
|
1140
|
-
position: from,
|
|
1141
|
-
y: contentStart
|
|
1142
|
-
});
|
|
1143
|
-
boundaries[0] = {
|
|
1144
|
-
position: from,
|
|
1145
|
-
y: contentStart
|
|
1146
|
-
};
|
|
1147
|
-
const contentEnd = cellRect ? (cellRect.bottom - rowRect.top) / Math.max(scaleY, 0.01) - nonNegativePixels(cellStyle?.borderBottomWidth ?? '') - nonNegativePixels(cellStyle?.paddingBottom ?? '') : row.height;
|
|
1148
|
-
boundaries.push({
|
|
1149
|
-
position: to,
|
|
1150
|
-
y: Math.max(contentStart, Math.min(row.height, contentEnd))
|
|
1151
|
-
});
|
|
1152
|
-
result.push({
|
|
1153
|
-
cellIndex,
|
|
1154
|
-
from,
|
|
1155
|
-
to,
|
|
1156
|
-
boundaries,
|
|
1157
|
-
...cellRect && tableRect ? {
|
|
1158
|
-
tableOffsetLeft: Math.max(0, (cellRect.left - tableRect.left) / Math.max(scaleX, 0.01)),
|
|
1159
|
-
outerWidth: Math.max(1, element?.offsetWidth || cellRect.width / Math.max(scaleX, 0.01)),
|
|
1160
|
-
contentOffsetLeft: nonNegativePixels(cellStyle?.borderLeftWidth ?? '') + nonNegativePixels(cellStyle?.paddingLeft ?? '')
|
|
1161
|
-
} : {}
|
|
1162
|
-
});
|
|
1163
|
-
});
|
|
1164
|
-
return result;
|
|
1165
|
-
}
|
|
1166
|
-
function documentTablePaginationBreak(tableElement, tableNode, tableId, rows, repeatHeaderCount, repeatHeaderHeight) {
|
|
1167
|
-
const table = 'table' === tableElement.tagName.toLowerCase() ? tableElement : Array.from(tableElement.children).find((child)=>'table' === child.tagName.toLowerCase());
|
|
1168
|
-
const colgroup = Array.from(table?.children ?? []).find((child)=>'colgroup' === child.tagName.toLowerCase());
|
|
1169
|
-
const tableRect = table?.getBoundingClientRect();
|
|
1170
|
-
const scaleX = table instanceof HTMLElement && table.offsetWidth > 0 && tableRect ? tableRect.width / table.offsetWidth : 1;
|
|
1171
|
-
const scaleY = table instanceof HTMLElement && table.offsetHeight > 0 && tableRect ? tableRect.height / table.offsetHeight : 1;
|
|
1172
|
-
const columnCount = logicalDocumentTableColumnCount(tableNode);
|
|
1173
|
-
const tableWidth = table instanceof HTMLElement ? table.offsetWidth || (tableRect?.width ?? 0) / Math.max(scaleX, 0.01) : tableElement.offsetWidth;
|
|
1174
|
-
const repeatedHeaderRows = rows.slice(0, repeatHeaderCount);
|
|
1175
|
-
const leadingCell = rows[0]?.element.querySelector(':scope > th:first-child, :scope > td:first-child');
|
|
1176
|
-
const leadingCellRect = leadingCell?.getBoundingClientRect();
|
|
1177
|
-
const leadingCellStyle = leadingCell ? getComputedStyle(leadingCell) : null;
|
|
1178
|
-
return {
|
|
1179
|
-
tableId,
|
|
1180
|
-
columnCount,
|
|
1181
|
-
colgroupHtml: colgroup instanceof HTMLElement ? colgroup.outerHTML : '',
|
|
1182
|
-
repeatHeaderHeight,
|
|
1183
|
-
tableWidth,
|
|
1184
|
-
leadingCellOffsetLeft: leadingCellRect && tableRect ? (leadingCellRect.left - tableRect.left) / Math.max(scaleX, 0.01) + nonNegativePixels(leadingCellStyle?.borderLeftWidth ?? '') + nonNegativePixels(leadingCellStyle?.paddingLeft ?? '') : 0,
|
|
1185
|
-
repeatedHeaderRowsHtml: repeatedHeaderRows.map((row)=>repeatedDocumentTableRowHtml(row.element)),
|
|
1186
|
-
repeatedHeaderOverlayHtml: repeatedDocumentTableHeaderOverlayHtml(repeatedHeaderRows, tableRect, scaleX, scaleY, tableWidth, columnCount)
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
function logicalDocumentTableColumnCount(table) {
|
|
1190
|
-
let maximum = 1;
|
|
1191
|
-
table.forEach((row)=>{
|
|
1192
|
-
let columns = 0;
|
|
1193
|
-
row.forEach((cell)=>{
|
|
1194
|
-
const colspan = Number(cell.attrs.colspan);
|
|
1195
|
-
columns += Number.isSafeInteger(colspan) && colspan > 0 ? colspan : 1;
|
|
1196
|
-
});
|
|
1197
|
-
maximum = Math.max(maximum, columns);
|
|
1198
|
-
});
|
|
1199
|
-
return maximum;
|
|
1200
|
-
}
|
|
1201
|
-
function repeatedDocumentTableRowHtml(row) {
|
|
1202
|
-
const clone = row.cloneNode(true);
|
|
1203
|
-
sanitizeRepeatedDocumentTableElement(clone);
|
|
1204
|
-
return clone.outerHTML;
|
|
1205
|
-
}
|
|
1206
|
-
function repeatedDocumentTableHeaderOverlayHtml(rows, tableRect, scaleX, scaleY, tableWidth, columnCount) {
|
|
1207
|
-
const container = document.createElement('div');
|
|
1208
|
-
const originTop = rows[0]?.element.getBoundingClientRect().top ?? 0;
|
|
1209
|
-
let fallbackTop = 0;
|
|
1210
|
-
for (const row of rows){
|
|
1211
|
-
const rowRect = row.element.getBoundingClientRect();
|
|
1212
|
-
const rowTop = rowRect.height > 0 ? Math.max(0, (rowRect.top - originTop) / Math.max(scaleY, 0.01)) : fallbackTop;
|
|
1213
|
-
const cells = Array.from(row.element.children).filter((element)=>element instanceof HTMLElement && [
|
|
1214
|
-
'td',
|
|
1215
|
-
'th'
|
|
1216
|
-
].includes(element.tagName.toLowerCase()));
|
|
1217
|
-
let fallbackColumn = 0;
|
|
1218
|
-
for (const source of cells){
|
|
1219
|
-
const colspan = Math.max(1, Number.parseInt(source.getAttribute('colspan') ?? '1', 10) || 1);
|
|
1220
|
-
const cellRect = source.getBoundingClientRect();
|
|
1221
|
-
const fallbackLeft = fallbackColumn / Math.max(1, columnCount) * tableWidth;
|
|
1222
|
-
const fallbackWidth = colspan / Math.max(1, columnCount) * tableWidth;
|
|
1223
|
-
const left = tableRect && cellRect.width > 0 ? (cellRect.left - tableRect.left) / Math.max(scaleX, 0.01) : fallbackLeft;
|
|
1224
|
-
const width = cellRect.width > 0 ? source.offsetWidth || cellRect.width / Math.max(scaleX, 0.01) : fallbackWidth;
|
|
1225
|
-
const height = cellRect.height > 0 ? source.offsetHeight || cellRect.height / Math.max(scaleY, 0.01) : row.height;
|
|
1226
|
-
container.append(repeatedDocumentTableHeaderCellElement(source, left, rowTop, width, height));
|
|
1227
|
-
fallbackColumn += colspan;
|
|
1228
|
-
}
|
|
1229
|
-
fallbackTop += row.height;
|
|
1230
|
-
}
|
|
1231
|
-
return container.innerHTML;
|
|
1232
|
-
}
|
|
1233
|
-
function repeatedDocumentTableHeaderCellElement(source, left, top, width, height) {
|
|
1234
|
-
const sourceClone = source.cloneNode(true);
|
|
1235
|
-
sanitizeRepeatedDocumentTableElement(sourceClone);
|
|
1236
|
-
const cell = document.createElement('div');
|
|
1237
|
-
cell.className = 'work-document-table-repeated-header-cell';
|
|
1238
|
-
cell.dataset.sourceCell = source.tagName.toLowerCase();
|
|
1239
|
-
cell.innerHTML = sourceClone.innerHTML;
|
|
1240
|
-
const computed = getComputedStyle(source);
|
|
1241
|
-
for (const property of REPEATED_TABLE_HEADER_STYLE_PROPERTIES){
|
|
1242
|
-
const value = computed.getPropertyValue(property);
|
|
1243
|
-
if (value) cell.style.setProperty(property, value);
|
|
1244
|
-
}
|
|
1245
|
-
cell.style.left = `${left}px`;
|
|
1246
|
-
cell.style.top = `${top}px`;
|
|
1247
|
-
cell.style.width = `${Math.max(1, width)}px`;
|
|
1248
|
-
cell.style.height = `${Math.max(1, height)}px`;
|
|
1249
|
-
return cell;
|
|
1250
|
-
}
|
|
1251
|
-
const REPEATED_TABLE_HEADER_STYLE_PROPERTIES = [
|
|
1252
|
-
'background-color',
|
|
1253
|
-
'border-top',
|
|
1254
|
-
'border-right',
|
|
1255
|
-
'border-bottom',
|
|
1256
|
-
'border-left',
|
|
1257
|
-
'color',
|
|
1258
|
-
'font-family',
|
|
1259
|
-
'font-size',
|
|
1260
|
-
'font-style',
|
|
1261
|
-
'font-weight',
|
|
1262
|
-
'letter-spacing',
|
|
1263
|
-
'line-height',
|
|
1264
|
-
'padding-top',
|
|
1265
|
-
'padding-right',
|
|
1266
|
-
'padding-bottom',
|
|
1267
|
-
'padding-left',
|
|
1268
|
-
'text-align',
|
|
1269
|
-
'white-space'
|
|
1270
|
-
];
|
|
1271
|
-
function sanitizeRepeatedDocumentTableElement(clone) {
|
|
1272
|
-
clone.removeAttribute('contenteditable');
|
|
1273
|
-
clone.removeAttribute('data-node-view-content-react');
|
|
1274
|
-
clone.classList.remove('selectedCell');
|
|
1275
|
-
for (const descendant of clone.querySelectorAll('*')){
|
|
1276
|
-
descendant.removeAttribute('contenteditable');
|
|
1277
|
-
descendant.removeAttribute('data-node-view-content-react');
|
|
1278
|
-
descendant.classList.remove('selectedCell');
|
|
1279
|
-
descendant.classList.remove('ProseMirror-selectednode');
|
|
1280
|
-
}
|
|
1281
|
-
clone.querySelectorAll(".work-document-auto-page-break,.work-document-table-page-break,.work-document-table-cell-page-break,.work-document-table-repeated-header").forEach((pageBreak)=>{
|
|
1282
|
-
pageBreak.remove();
|
|
1283
|
-
});
|
|
1284
|
-
}
|
|
1285
|
-
function measureDocumentLayoutBlocks(editor, previous = null, dirtyFrom = 0, textLayouts = new Map(), maximumFragmentedTableRowHeight = 1000000) {
|
|
1286
|
-
const blocks = [];
|
|
1287
|
-
const counts = {
|
|
1288
|
-
measured: 0,
|
|
1289
|
-
reused: 0
|
|
1290
|
-
};
|
|
1291
|
-
let unsupportedLayout = false;
|
|
1292
|
-
let firstLayoutKey = null;
|
|
1293
|
-
editor.state.doc.forEach((section, sectionPosition, sectionIndex)=>{
|
|
1294
|
-
if ('documentSection' !== section.type.name) return;
|
|
1295
|
-
const layout = documentSectionLayoutFromNodeAttributes(section.attrs);
|
|
1296
|
-
const layoutKey = documentPaginationLayoutKey(layout);
|
|
1297
|
-
firstLayoutKey ??= layoutKey;
|
|
1298
|
-
if (layout.columns.count > 1 || layoutKey !== firstLayoutKey) unsupportedLayout = true;
|
|
1299
|
-
measureSectionBlocks(editor, section, sectionPosition, sectionIndex, layout, previous?.blocks ?? [], dirtyFrom, textLayouts, maximumFragmentedTableRowHeight, counts, blocks);
|
|
1300
|
-
});
|
|
1301
|
-
return {
|
|
1302
|
-
blocks,
|
|
1303
|
-
measuredBlockCount: counts.measured,
|
|
1304
|
-
reusedBlockCount: counts.reused,
|
|
1305
|
-
unsupportedLayout
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
function documentPageMetrics(layout) {
|
|
1309
|
-
const portrait = 'letter' === layout.pageSize ? {
|
|
1310
|
-
width: 816,
|
|
1311
|
-
height: 1056
|
|
1312
|
-
} : {
|
|
1313
|
-
width: work_document_layout_millimetersToPixels(210),
|
|
1314
|
-
height: work_document_layout_millimetersToPixels(297)
|
|
1315
|
-
};
|
|
1316
|
-
const landscape = 'landscape' === layout.orientation;
|
|
1317
|
-
return {
|
|
1318
|
-
width: landscape ? portrait.height : portrait.width,
|
|
1319
|
-
height: landscape ? portrait.width : portrait.height,
|
|
1320
|
-
marginTop: work_document_layout_millimetersToPixels(layout.margins.top),
|
|
1321
|
-
marginRight: work_document_layout_millimetersToPixels(layout.margins.right),
|
|
1322
|
-
marginBottom: work_document_layout_millimetersToPixels(layout.margins.bottom),
|
|
1323
|
-
marginLeft: work_document_layout_millimetersToPixels(layout.margins.left),
|
|
1324
|
-
headerHeight: 0,
|
|
1325
|
-
footerHeight: 0,
|
|
1326
|
-
pageGap: 28
|
|
1327
|
-
};
|
|
1328
|
-
}
|
|
1329
|
-
function documentPageBodyHeight(page) {
|
|
1330
|
-
return Math.max(1, page.height - page.marginTop - page.marginBottom);
|
|
1331
|
-
}
|
|
1332
|
-
function documentPaginationSurfaceHeight(pageCount, page) {
|
|
1333
|
-
const count = Math.max(1, Math.trunc(pageCount));
|
|
1334
|
-
return page.height * count + page.pageGap * (count - 1);
|
|
1335
|
-
}
|
|
1336
|
-
function documentPageChromeHeights(editor) {
|
|
1337
|
-
const page = editor.view.dom.closest('.work-document-page');
|
|
1338
|
-
return {
|
|
1339
|
-
headerHeight: work_document_pagination_dom_outerHeight(page?.querySelector('.work-document-page-header') ?? null),
|
|
1340
|
-
footerHeight: work_document_pagination_dom_outerHeight(page?.querySelector('.work-document-page-footer') ?? null)
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
function measureSectionBlocks(editor, section, sectionPosition, sectionIndex, layout, previous, dirtyFrom, textLayouts, maximumFragmentedTableRowHeight, counts, result) {
|
|
1344
|
-
const sectionBlocks = [];
|
|
1345
|
-
section.forEach((node, offset, index)=>{
|
|
1346
|
-
const position = sectionPosition + offset + 1;
|
|
1347
|
-
const element = elementForNode(editor, position);
|
|
1348
|
-
if (!element) return;
|
|
1349
|
-
const id = documentBlockId(sectionPosition, index, position);
|
|
1350
|
-
const paragraphPagination = documentNodeParagraphPagination(node);
|
|
1351
|
-
if (isDocumentListNode(node)) {
|
|
1352
|
-
const reused = reusableDocumentListLayoutBlocks(previous, id, position + node.nodeSize, dirtyFrom);
|
|
1353
|
-
if (reused.length) {
|
|
1354
|
-
counts.reused += reused.length;
|
|
1355
|
-
sectionBlocks.push(...reused);
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
const listBlocks = measureDocumentListBlocks(editor, node, element, id, position, textLayouts, maximumFragmentedTableRowHeight);
|
|
1359
|
-
if (listBlocks.length) {
|
|
1360
|
-
counts.measured += listBlocks.length;
|
|
1361
|
-
sectionBlocks.push(...listBlocks);
|
|
1362
|
-
return;
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
const reused = reusableDocumentLayoutBlocks(previous, id, element, position + node.nodeSize, dirtyFrom);
|
|
1366
|
-
if (reused.length) {
|
|
1367
|
-
counts.reused += reused.length;
|
|
1368
|
-
sectionBlocks.push(...reused);
|
|
1369
|
-
return;
|
|
1370
|
-
}
|
|
1371
|
-
if ('table' === node.type.name) {
|
|
1372
|
-
const tableRows = measureDocumentTableRows(editor, node, element, id, position, maximumFragmentedTableRowHeight);
|
|
1373
|
-
if (tableRows.length) {
|
|
1374
|
-
counts.measured += tableRows.length;
|
|
1375
|
-
sectionBlocks.push(...tableRows);
|
|
1376
|
-
return;
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
const lineFragments = measureParagraphLineFragments(editor, node, element, id, position, position + node.nodeSize, paragraphPagination, textLayouts.get(id));
|
|
1380
|
-
if (lineFragments.length > 1) {
|
|
1381
|
-
counts.measured += lineFragments.length;
|
|
1382
|
-
sectionBlocks.push(...lineFragments);
|
|
1383
|
-
return;
|
|
1384
|
-
}
|
|
1385
|
-
counts.measured += 1;
|
|
1386
|
-
sectionBlocks.push(measuredDocumentBlock({
|
|
1387
|
-
block: {
|
|
1388
|
-
id,
|
|
1389
|
-
height: Math.max(1, work_document_pagination_dom_outerHeight(element)),
|
|
1390
|
-
breakBefore: paragraphPagination.pageBreakBefore,
|
|
1391
|
-
breakAfter: 'pageBreak' === node.type.name,
|
|
1392
|
-
keepTogether: paragraphPagination.keepLines || shouldKeepDocumentBlockTogether(node),
|
|
1393
|
-
keepWithNext: paragraphPagination.keepWithNext
|
|
1394
|
-
},
|
|
1395
|
-
element,
|
|
1396
|
-
from: position,
|
|
1397
|
-
to: position + node.nodeSize
|
|
1398
|
-
}));
|
|
1399
|
-
});
|
|
1400
|
-
const last = sectionBlocks.at(-1);
|
|
1401
|
-
if (last && 'continuous' !== layout.breakAfter && 'nextColumn' !== layout.breakAfter) last.block.breakAfter = true;
|
|
1402
|
-
const sectionMetadata = {
|
|
1403
|
-
id: 'string' == typeof section.attrs.id && section.attrs.id ? section.attrs.id : `document-section-${sectionIndex + 1}`,
|
|
1404
|
-
index: sectionIndex,
|
|
1405
|
-
position: sectionPosition,
|
|
1406
|
-
layout
|
|
1407
|
-
};
|
|
1408
|
-
for (const block of sectionBlocks)block.section = sectionMetadata;
|
|
1409
|
-
result.push(...sectionBlocks);
|
|
1410
|
-
}
|
|
1411
|
-
function measureDocumentListBlocks(editor, list, listElement, listId, listPosition, textLayouts, maximumFragmentedTableRowHeight) {
|
|
1412
|
-
const blocks = [];
|
|
1413
|
-
let complete = true;
|
|
1414
|
-
list.forEach((item, itemOffset, itemIndex)=>{
|
|
1415
|
-
if ('listItem' !== item.type.name) {
|
|
1416
|
-
complete = false;
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
const itemPosition = listPosition + itemOffset + 1;
|
|
1420
|
-
const itemElement = elementForNode(editor, itemPosition);
|
|
1421
|
-
if (!itemElement || 'li' !== itemElement.tagName.toLowerCase()) {
|
|
1422
|
-
complete = false;
|
|
1423
|
-
return;
|
|
1424
|
-
}
|
|
1425
|
-
const itemBlocks = [];
|
|
1426
|
-
item.forEach((node, offset, index)=>{
|
|
1427
|
-
const position = itemPosition + offset + 1;
|
|
1428
|
-
const element = elementForNode(editor, position);
|
|
1429
|
-
if (!element) {
|
|
1430
|
-
complete = false;
|
|
1431
|
-
return;
|
|
1432
|
-
}
|
|
1433
|
-
const nestedList = isDocumentListNode(node);
|
|
1434
|
-
const id = documentListChildId(listId, itemIndex, node, index, nestedList);
|
|
1435
|
-
if (nestedList) {
|
|
1436
|
-
const nestedBlocks = measureDocumentListBlocks(editor, node, element, id, position, textLayouts, maximumFragmentedTableRowHeight);
|
|
1437
|
-
if (!nestedBlocks.length) {
|
|
1438
|
-
complete = false;
|
|
1439
|
-
return;
|
|
1440
|
-
}
|
|
1441
|
-
itemBlocks.push(...nestedBlocks);
|
|
1442
|
-
return;
|
|
1443
|
-
}
|
|
1444
|
-
itemBlocks.push(...measureDocumentListItemBlock(editor, node, element, id, position, textLayouts.get(id), maximumFragmentedTableRowHeight));
|
|
1445
|
-
});
|
|
1446
|
-
if (!itemBlocks.length) {
|
|
1447
|
-
complete = false;
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
fitDocumentBlocksToContainer(itemBlocks, itemElement);
|
|
1451
|
-
blocks.push(...itemBlocks);
|
|
1452
|
-
});
|
|
1453
|
-
if (!complete || !blocks.length) return [];
|
|
1454
|
-
fitDocumentBlocksToContainer(blocks, listElement);
|
|
1455
|
-
return blocks;
|
|
1456
|
-
}
|
|
1457
|
-
function measureDocumentListItemBlock(editor, node, element, id, position, shapedLayout, maximumFragmentedTableRowHeight) {
|
|
1458
|
-
if ('table' === node.type.name) {
|
|
1459
|
-
const rows = measureDocumentTableRows(editor, node, element, id, position, maximumFragmentedTableRowHeight);
|
|
1460
|
-
if (rows.length) return rows;
|
|
1461
|
-
}
|
|
1462
|
-
const pagination = documentNodeParagraphPagination(node);
|
|
1463
|
-
const lineFragments = measureParagraphLineFragments(editor, node, element, id, position, position + node.nodeSize, pagination, shapedLayout);
|
|
1464
|
-
const { inlineOffsetLeft, inlineOffsetRight } = documentInlineOffsets(editor, element);
|
|
1465
|
-
if (lineFragments.length > 1) return lineFragments.map((fragment)=>({
|
|
1466
|
-
...fragment,
|
|
1467
|
-
inlineOffsetLeft,
|
|
1468
|
-
inlineOffsetRight
|
|
1469
|
-
}));
|
|
1470
|
-
return [
|
|
1471
|
-
{
|
|
1472
|
-
...measuredDocumentBlock({
|
|
1473
|
-
block: {
|
|
1474
|
-
id,
|
|
1475
|
-
height: Math.max(1, work_document_pagination_dom_outerHeight(element)),
|
|
1476
|
-
breakBefore: pagination.pageBreakBefore,
|
|
1477
|
-
breakAfter: 'pageBreak' === node.type.name,
|
|
1478
|
-
keepTogether: pagination.keepLines || shouldKeepDocumentBlockTogether(node),
|
|
1479
|
-
keepWithNext: pagination.keepWithNext
|
|
1480
|
-
},
|
|
1481
|
-
element,
|
|
1482
|
-
from: position,
|
|
1483
|
-
to: position + node.nodeSize
|
|
1484
|
-
}),
|
|
1485
|
-
inlineOffsetLeft,
|
|
1486
|
-
inlineOffsetRight
|
|
1487
|
-
}
|
|
1488
|
-
];
|
|
1489
|
-
}
|
|
1490
|
-
function fitDocumentBlocksToContainer(blocks, container) {
|
|
1491
|
-
const target = work_document_pagination_dom_outerHeight(container);
|
|
1492
|
-
if (!(target > 0) || 0 === blocks.length) return;
|
|
1493
|
-
const measured = blocks.reduce((height, candidate)=>height + candidate.block.height, 0);
|
|
1494
|
-
let difference = target - measured;
|
|
1495
|
-
if (Math.abs(difference) < 0.01) return;
|
|
1496
|
-
const first = blocks[0];
|
|
1497
|
-
const last = blocks.at(-1);
|
|
1498
|
-
if (difference > 0) {
|
|
1499
|
-
const style = getComputedStyle(container);
|
|
1500
|
-
const start = Math.min(difference, verticalBlockStart(style));
|
|
1501
|
-
first.block.height += start;
|
|
1502
|
-
difference -= start;
|
|
1503
|
-
const end = Math.min(difference, verticalBlockEnd(style));
|
|
1504
|
-
last.block.height += end;
|
|
1505
|
-
difference -= end;
|
|
1506
|
-
last.block.height += difference;
|
|
1507
|
-
return;
|
|
1508
|
-
}
|
|
1509
|
-
let remaining = -difference;
|
|
1510
|
-
const candidates = Array.from(new Set([
|
|
1511
|
-
last,
|
|
1512
|
-
first,
|
|
1513
|
-
...blocks.slice(1, -1).reverse()
|
|
1514
|
-
]));
|
|
1515
|
-
for (const candidate of candidates){
|
|
1516
|
-
if (remaining <= 0) break;
|
|
1517
|
-
const removable = Math.max(0, candidate.block.height - 1);
|
|
1518
|
-
const amount = Math.min(removable, remaining);
|
|
1519
|
-
candidate.block.height -= amount;
|
|
1520
|
-
remaining -= amount;
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
function reusableDocumentListLayoutBlocks(previous, listId, nodeTo, dirtyFrom) {
|
|
1524
|
-
if (nodeTo > dirtyFrom) return [];
|
|
1525
|
-
const prefix = `${listId}-item-`;
|
|
1526
|
-
return previous.filter(({ block })=>block.id.startsWith(prefix) || block.flowId?.startsWith(prefix)).map((candidate)=>({
|
|
1527
|
-
...candidate,
|
|
1528
|
-
block: {
|
|
1529
|
-
...candidate.block
|
|
1530
|
-
}
|
|
1531
|
-
}));
|
|
1532
|
-
}
|
|
1533
293
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_THRESHOLD = 48;
|
|
1534
294
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_LIMIT = 32;
|
|
1535
295
|
const DOCUMENT_NAVIGATION_COLLECTION_WINDOW_OVERSCAN = 4;
|
|
@@ -3872,8 +2632,8 @@ function formatCommentDate(value) {
|
|
|
3872
2632
|
}).format(time);
|
|
3873
2633
|
}
|
|
3874
2634
|
const DOCUMENT_EDITOR_FOCUS_RETRY_FRAMES = 4;
|
|
3875
|
-
function restoreDocumentEditorFocus(getTarget) {
|
|
3876
|
-
const commandTrigger =
|
|
2635
|
+
function restoreDocumentEditorFocus(getTarget, focusOrigin = document.activeElement) {
|
|
2636
|
+
const commandTrigger = focusOrigin;
|
|
3877
2637
|
let remainingFrames = DOCUMENT_EDITOR_FOCUS_RETRY_FRAMES;
|
|
3878
2638
|
const restore = ()=>{
|
|
3879
2639
|
if (remainingFrames <= 0) return;
|
|
@@ -3900,9 +2660,43 @@ function fallbackPaginationPageDescriptor(sectionId, sectionIndex, layout, physi
|
|
|
3900
2660
|
sectionId: sectionId ?? 'document-section-1',
|
|
3901
2661
|
sectionIndex: sectionIndex ?? 0,
|
|
3902
2662
|
layout,
|
|
3903
|
-
pageChrome: resolveDocumentPageChrome(layout, sectionPage, sectionPage)
|
|
2663
|
+
pageChrome: resolveDocumentPageChrome(layout, sectionPage, sectionPage),
|
|
2664
|
+
page: documentPageMetrics(layout)
|
|
3904
2665
|
};
|
|
3905
2666
|
}
|
|
2667
|
+
function shouldPublishDocumentUpdate(transaction) {
|
|
2668
|
+
return !transaction.getMeta('preventUpdate') && false !== transaction.getMeta('addToHistory');
|
|
2669
|
+
}
|
|
2670
|
+
function applyExternalDocumentContent(editor, content) {
|
|
2671
|
+
let nextDocument;
|
|
2672
|
+
try {
|
|
2673
|
+
nextDocument = createNodeFromContent(content, editor.schema, {
|
|
2674
|
+
errorOnInvalidContent: true,
|
|
2675
|
+
slice: false
|
|
2676
|
+
});
|
|
2677
|
+
} catch {
|
|
2678
|
+
return 'unsupported';
|
|
2679
|
+
}
|
|
2680
|
+
if (!(nextDocument instanceof model_Node)) return 'unsupported';
|
|
2681
|
+
const currentDocument = editor.state.doc;
|
|
2682
|
+
const start = currentDocument.content.findDiffStart(nextDocument.content);
|
|
2683
|
+
if (null === start) return 'unchanged';
|
|
2684
|
+
const end = currentDocument.content.findDiffEnd(nextDocument.content);
|
|
2685
|
+
let currentEnd = end?.a ?? currentDocument.content.size;
|
|
2686
|
+
let nextEnd = end?.b ?? nextDocument.content.size;
|
|
2687
|
+
const overlap = start - Math.min(currentEnd, nextEnd);
|
|
2688
|
+
if (overlap > 0) {
|
|
2689
|
+
currentEnd += overlap;
|
|
2690
|
+
nextEnd += overlap;
|
|
2691
|
+
}
|
|
2692
|
+
try {
|
|
2693
|
+
const transaction = editor.state.tr.replace(start, currentEnd, nextDocument.slice(start, nextEnd)).setMeta('addToHistory', false).setMeta('preventUpdate', true);
|
|
2694
|
+
editor.view.dispatch(transaction);
|
|
2695
|
+
return 'applied';
|
|
2696
|
+
} catch {
|
|
2697
|
+
return 'unsupported';
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
3906
2700
|
const SEARCH_CONTEXT_LENGTH = 34;
|
|
3907
2701
|
function documentTextMatches(document1, rawQuery) {
|
|
3908
2702
|
const query = rawQuery.toLocaleLowerCase();
|
|
@@ -4520,7 +3314,11 @@ const documentFormatBlockAttributeNames = [
|
|
|
4520
3314
|
'keepWithNext',
|
|
4521
3315
|
'pageBreakBefore',
|
|
4522
3316
|
'widowControl',
|
|
3317
|
+
'contextualSpacing',
|
|
3318
|
+
'outlineLevel',
|
|
4523
3319
|
'paragraphDirection',
|
|
3320
|
+
'paragraphBorders',
|
|
3321
|
+
'paragraphShading',
|
|
4524
3322
|
'tabStops'
|
|
4525
3323
|
];
|
|
4526
3324
|
function documentFormatBlockAtSelection(editor) {
|
|
@@ -4890,21 +3688,29 @@ function createDocumentPageChromeEditorExtensions(placeholder = '输入页眉或
|
|
|
4890
3688
|
resizable: false
|
|
4891
3689
|
}
|
|
4892
3690
|
}),
|
|
4893
|
-
|
|
3691
|
+
DocumentImage.configure({
|
|
4894
3692
|
allowBase64: true,
|
|
4895
3693
|
inline: true
|
|
4896
3694
|
}),
|
|
3695
|
+
DocumentEquation,
|
|
4897
3696
|
TextStyle,
|
|
4898
3697
|
extension_color,
|
|
4899
3698
|
extension_underline,
|
|
4900
3699
|
DocumentSubscript,
|
|
4901
3700
|
DocumentSuperscript,
|
|
4902
3701
|
DocumentPageChromeCommands,
|
|
3702
|
+
DocumentParagraphFormatting,
|
|
4903
3703
|
extension_text_align.configure({
|
|
4904
3704
|
types: [
|
|
4905
3705
|
'paragraph'
|
|
4906
3706
|
]
|
|
4907
3707
|
}),
|
|
3708
|
+
DocumentParagraphIdentity.configure({
|
|
3709
|
+
types: [
|
|
3710
|
+
'paragraph'
|
|
3711
|
+
]
|
|
3712
|
+
}),
|
|
3713
|
+
DocumentTableRowIdentity,
|
|
4908
3714
|
DocumentPageChromeWpsShortcuts,
|
|
4909
3715
|
extension_placeholder.configure({
|
|
4910
3716
|
placeholder
|
|
@@ -5080,6 +3886,7 @@ function emptyPageChrome(content) {
|
|
|
5080
3886
|
function DocumentLayoutPanel({ layout, activeTab: controlledActiveTab, sectionIndex, sectionCount, onActiveTabChange, onChange, onInsertSection, onMergeSection, onClose }) {
|
|
5081
3887
|
const tabsId = useId();
|
|
5082
3888
|
const [internalActiveTab, setInternalActiveTab] = useState('page');
|
|
3889
|
+
const [customPaperSelected, setCustomPaperSelected] = useState('custom' === layout.pageSize);
|
|
5083
3890
|
const activeTab = controlledActiveTab ?? internalActiveTab;
|
|
5084
3891
|
const changeActiveTab = (tab)=>{
|
|
5085
3892
|
if (void 0 === controlledActiveTab) setInternalActiveTab(tab);
|
|
@@ -5103,6 +3910,17 @@ function DocumentLayoutPanel({ layout, activeTab: controlledActiveTab, sectionIn
|
|
|
5103
3910
|
'左'
|
|
5104
3911
|
]
|
|
5105
3912
|
];
|
|
3913
|
+
const pageMargins = documentPageMarginsForLayout(layout);
|
|
3914
|
+
const exactPageGeometry = normalizeDocumentPageGeometry(layout.pageGeometry);
|
|
3915
|
+
const resolvedPageSize = resolveDocumentPageSize(layout);
|
|
3916
|
+
const customPageDimensions = exactPageGeometry ? {
|
|
3917
|
+
width: pageTwipsToMillimeters(exactPageGeometry.width),
|
|
3918
|
+
height: pageTwipsToMillimeters(exactPageGeometry.height)
|
|
3919
|
+
} : {
|
|
3920
|
+
width: resolvedPageSize.width,
|
|
3921
|
+
height: resolvedPageSize.height
|
|
3922
|
+
};
|
|
3923
|
+
const gutterPosition = pageMargins.gutterAtTop ? 'top' : pageMargins.gutterOnRight ? 'right' : 'left';
|
|
5106
3924
|
const update = (patch)=>onChange({
|
|
5107
3925
|
...layout,
|
|
5108
3926
|
...patch
|
|
@@ -5169,20 +3987,42 @@ function DocumentLayoutPanel({ layout, activeTab: controlledActiveTab, sectionIn
|
|
|
5169
3987
|
}),
|
|
5170
3988
|
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
5171
3989
|
ariaLabel: "纸张大小",
|
|
5172
|
-
value: layout.pageSize,
|
|
3990
|
+
value: customPaperSelected ? 'custom' : layout.pageSize,
|
|
5173
3991
|
options: [
|
|
3992
|
+
{
|
|
3993
|
+
value: 'a3',
|
|
3994
|
+
label: 'A3'
|
|
3995
|
+
},
|
|
5174
3996
|
{
|
|
5175
3997
|
value: 'a4',
|
|
5176
3998
|
label: 'A4'
|
|
5177
3999
|
},
|
|
4000
|
+
{
|
|
4001
|
+
value: 'a5',
|
|
4002
|
+
label: 'A5'
|
|
4003
|
+
},
|
|
5178
4004
|
{
|
|
5179
4005
|
value: 'letter',
|
|
5180
4006
|
label: 'Letter'
|
|
4007
|
+
},
|
|
4008
|
+
{
|
|
4009
|
+
value: 'legal',
|
|
4010
|
+
label: 'Legal'
|
|
4011
|
+
},
|
|
4012
|
+
{
|
|
4013
|
+
value: 'tabloid',
|
|
4014
|
+
label: 'Tabloid'
|
|
4015
|
+
},
|
|
4016
|
+
{
|
|
4017
|
+
value: 'custom',
|
|
4018
|
+
label: '自定义'
|
|
5181
4019
|
}
|
|
5182
4020
|
],
|
|
5183
|
-
onValueChange: (pageSize)=>
|
|
5184
|
-
|
|
5185
|
-
|
|
4021
|
+
onValueChange: (pageSize)=>{
|
|
4022
|
+
if ('custom' === pageSize) return void setCustomPaperSelected(true);
|
|
4023
|
+
setCustomPaperSelected(false);
|
|
4024
|
+
onChange(updateDocumentPaperSizePreset(layout, pageSize));
|
|
4025
|
+
}
|
|
5186
4026
|
})
|
|
5187
4027
|
]
|
|
5188
4028
|
}),
|
|
@@ -5205,13 +4045,46 @@ function DocumentLayoutPanel({ layout, activeTab: controlledActiveTab, sectionIn
|
|
|
5205
4045
|
label: '横向'
|
|
5206
4046
|
}
|
|
5207
4047
|
],
|
|
5208
|
-
onValueChange: (orientation)=>
|
|
5209
|
-
orientation
|
|
5210
|
-
})
|
|
4048
|
+
onValueChange: (orientation)=>onChange(updateDocumentPageOrientation(layout, orientation))
|
|
5211
4049
|
})
|
|
5212
4050
|
]
|
|
5213
4051
|
})
|
|
5214
4052
|
]
|
|
4053
|
+
}),
|
|
4054
|
+
(customPaperSelected || 'custom' === layout.pageSize) && /*#__PURE__*/ jsx("div", {
|
|
4055
|
+
className: "work-document-layout-paired-fields",
|
|
4056
|
+
children: [
|
|
4057
|
+
[
|
|
4058
|
+
'width',
|
|
4059
|
+
'宽度'
|
|
4060
|
+
],
|
|
4061
|
+
[
|
|
4062
|
+
'height',
|
|
4063
|
+
'高度'
|
|
4064
|
+
]
|
|
4065
|
+
].map(([dimension, label])=>/*#__PURE__*/ jsxs("div", {
|
|
4066
|
+
className: "work-office-field",
|
|
4067
|
+
children: [
|
|
4068
|
+
/*#__PURE__*/ jsxs("span", {
|
|
4069
|
+
children: [
|
|
4070
|
+
label,
|
|
4071
|
+
"(毫米)"
|
|
4072
|
+
]
|
|
4073
|
+
}),
|
|
4074
|
+
/*#__PURE__*/ jsx(CommittedOfficeNumberField, {
|
|
4075
|
+
min: 25.4,
|
|
4076
|
+
max: 558.8,
|
|
4077
|
+
step: 0.1,
|
|
4078
|
+
ariaLabel: `纸张${label}`,
|
|
4079
|
+
value: customPageDimensions[dimension],
|
|
4080
|
+
normalizeValue: normalizeDocumentPageDimensionInput,
|
|
4081
|
+
onValueCommit: (value)=>{
|
|
4082
|
+
setCustomPaperSelected(false);
|
|
4083
|
+
onChange(updateDocumentCustomPageMillimeters(layout, dimension, value));
|
|
4084
|
+
}
|
|
4085
|
+
})
|
|
4086
|
+
]
|
|
4087
|
+
}, dimension))
|
|
5215
4088
|
})
|
|
5216
4089
|
]
|
|
5217
4090
|
}),
|
|
@@ -5227,24 +4100,167 @@ function DocumentLayoutPanel({ layout, activeTab: controlledActiveTab, sectionIn
|
|
|
5227
4100
|
className: "work-office-field",
|
|
5228
4101
|
children: [
|
|
5229
4102
|
/*#__PURE__*/ jsx("span", {
|
|
5230
|
-
children: label
|
|
4103
|
+
children: label
|
|
4104
|
+
}),
|
|
4105
|
+
/*#__PURE__*/ jsx(CommittedOfficeNumberField, {
|
|
4106
|
+
min: 5,
|
|
4107
|
+
max: 60,
|
|
4108
|
+
step: 1,
|
|
4109
|
+
ariaLabel: `${label}页边距`,
|
|
4110
|
+
value: layout.margins[side],
|
|
4111
|
+
normalizeValue: normalizeDocumentMarginInput,
|
|
4112
|
+
onValueCommit: (value)=>onChange(updateDocumentPageMarginMillimeters(layout, side, value))
|
|
4113
|
+
})
|
|
4114
|
+
]
|
|
4115
|
+
}, side))
|
|
4116
|
+
})
|
|
4117
|
+
]
|
|
4118
|
+
}),
|
|
4119
|
+
/*#__PURE__*/ jsxs("section", {
|
|
4120
|
+
className: "work-document-layout-group",
|
|
4121
|
+
"aria-label": "高级页边距",
|
|
4122
|
+
children: [
|
|
4123
|
+
/*#__PURE__*/ jsx("h3", {
|
|
4124
|
+
children: "高级页边距"
|
|
4125
|
+
}),
|
|
4126
|
+
/*#__PURE__*/ jsx("div", {
|
|
4127
|
+
className: "work-document-layout-margin-grid",
|
|
4128
|
+
children: [
|
|
4129
|
+
[
|
|
4130
|
+
'header',
|
|
4131
|
+
'页眉距顶端'
|
|
4132
|
+
],
|
|
4133
|
+
[
|
|
4134
|
+
'footer',
|
|
4135
|
+
'页脚距底端'
|
|
4136
|
+
],
|
|
4137
|
+
[
|
|
4138
|
+
'gutter',
|
|
4139
|
+
'装订线'
|
|
4140
|
+
]
|
|
4141
|
+
].map(([key, label])=>/*#__PURE__*/ jsxs("div", {
|
|
4142
|
+
className: "work-office-field",
|
|
4143
|
+
children: [
|
|
4144
|
+
/*#__PURE__*/ jsx("span", {
|
|
4145
|
+
children: label
|
|
4146
|
+
}),
|
|
4147
|
+
/*#__PURE__*/ jsx(CommittedOfficeNumberField, {
|
|
4148
|
+
min: 0,
|
|
4149
|
+
max: 60,
|
|
4150
|
+
step: 0.1,
|
|
4151
|
+
ariaLabel: label,
|
|
4152
|
+
value: work_document_page_margins_twipsToMillimeters(pageMargins[key]),
|
|
4153
|
+
normalizeValue: normalizeDocumentPageOffsetInput,
|
|
4154
|
+
onValueCommit: (value)=>onChange(updateDocumentPageMarginMillimeters(layout, key, value))
|
|
4155
|
+
})
|
|
4156
|
+
]
|
|
4157
|
+
}, key))
|
|
4158
|
+
}),
|
|
4159
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4160
|
+
className: "work-document-layout-paired-fields",
|
|
4161
|
+
children: [
|
|
4162
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4163
|
+
className: "work-office-field",
|
|
4164
|
+
children: [
|
|
4165
|
+
/*#__PURE__*/ jsx("span", {
|
|
4166
|
+
children: "上边距规则"
|
|
4167
|
+
}),
|
|
4168
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4169
|
+
ariaLabel: "上边距与页眉关系",
|
|
4170
|
+
value: pageMargins.top < 0 ? 'fromPageEdge' : 'clearChrome',
|
|
4171
|
+
options: [
|
|
4172
|
+
{
|
|
4173
|
+
value: 'clearChrome',
|
|
4174
|
+
label: '避让页眉'
|
|
4175
|
+
},
|
|
4176
|
+
{
|
|
4177
|
+
value: 'fromPageEdge',
|
|
4178
|
+
label: '允许重叠'
|
|
4179
|
+
}
|
|
4180
|
+
],
|
|
4181
|
+
onValueChange: (mode)=>onChange(updateDocumentPageMarginMode(layout, 'top', mode))
|
|
4182
|
+
})
|
|
4183
|
+
]
|
|
4184
|
+
}),
|
|
4185
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4186
|
+
className: "work-office-field",
|
|
4187
|
+
children: [
|
|
4188
|
+
/*#__PURE__*/ jsx("span", {
|
|
4189
|
+
children: "下边距规则"
|
|
4190
|
+
}),
|
|
4191
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4192
|
+
ariaLabel: "下边距与页脚关系",
|
|
4193
|
+
value: pageMargins.bottom < 0 ? 'fromPageEdge' : 'clearChrome',
|
|
4194
|
+
options: [
|
|
4195
|
+
{
|
|
4196
|
+
value: 'clearChrome',
|
|
4197
|
+
label: '避让页脚'
|
|
4198
|
+
},
|
|
4199
|
+
{
|
|
4200
|
+
value: 'fromPageEdge',
|
|
4201
|
+
label: '允许重叠'
|
|
4202
|
+
}
|
|
4203
|
+
],
|
|
4204
|
+
onValueChange: (mode)=>onChange(updateDocumentPageMarginMode(layout, 'bottom', mode))
|
|
4205
|
+
})
|
|
4206
|
+
]
|
|
4207
|
+
})
|
|
4208
|
+
]
|
|
4209
|
+
}),
|
|
4210
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4211
|
+
className: "work-document-layout-paired-fields",
|
|
4212
|
+
children: [
|
|
4213
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4214
|
+
className: "work-office-field",
|
|
4215
|
+
children: [
|
|
4216
|
+
/*#__PURE__*/ jsx("span", {
|
|
4217
|
+
children: "多页方式"
|
|
4218
|
+
}),
|
|
4219
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4220
|
+
ariaLabel: "镜像页边距",
|
|
4221
|
+
value: pageMargins.mirrorMargins ? 'mirrored' : 'normal',
|
|
4222
|
+
options: [
|
|
4223
|
+
{
|
|
4224
|
+
value: 'normal',
|
|
4225
|
+
label: '普通'
|
|
4226
|
+
},
|
|
4227
|
+
{
|
|
4228
|
+
value: 'mirrored',
|
|
4229
|
+
label: '镜像页边距'
|
|
4230
|
+
}
|
|
4231
|
+
],
|
|
4232
|
+
onValueChange: (value)=>onChange(updateDocumentMirrorMargins(layout, 'mirrored' === value))
|
|
4233
|
+
})
|
|
4234
|
+
]
|
|
4235
|
+
}),
|
|
4236
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4237
|
+
className: "work-office-field",
|
|
4238
|
+
children: [
|
|
4239
|
+
/*#__PURE__*/ jsx("span", {
|
|
4240
|
+
children: "装订线位置"
|
|
5231
4241
|
}),
|
|
5232
|
-
/*#__PURE__*/ jsx(
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
4242
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4243
|
+
ariaLabel: "装订线位置",
|
|
4244
|
+
value: gutterPosition,
|
|
4245
|
+
options: [
|
|
4246
|
+
{
|
|
4247
|
+
value: 'left',
|
|
4248
|
+
label: '左侧'
|
|
4249
|
+
},
|
|
4250
|
+
{
|
|
4251
|
+
value: 'right',
|
|
4252
|
+
label: '右侧'
|
|
4253
|
+
},
|
|
4254
|
+
{
|
|
4255
|
+
value: 'top',
|
|
4256
|
+
label: '顶部'
|
|
4257
|
+
}
|
|
4258
|
+
],
|
|
4259
|
+
onValueChange: (position)=>onChange(updateDocumentGutterPosition(layout, position))
|
|
5245
4260
|
})
|
|
5246
4261
|
]
|
|
5247
|
-
}
|
|
4262
|
+
})
|
|
4263
|
+
]
|
|
5248
4264
|
})
|
|
5249
4265
|
]
|
|
5250
4266
|
})
|
|
@@ -5373,6 +4389,16 @@ function normalizeDocumentMarginInput(value) {
|
|
|
5373
4389
|
const number = Number(value);
|
|
5374
4390
|
return Number.isFinite(number) ? clampDocumentMargin(number) : null;
|
|
5375
4391
|
}
|
|
4392
|
+
function normalizeDocumentPageOffsetInput(value) {
|
|
4393
|
+
if (!value.trim()) return null;
|
|
4394
|
+
const number = Number(value);
|
|
4395
|
+
return Number.isFinite(number) ? Math.min(60, Math.max(0, Math.round(10 * number) / 10)) : null;
|
|
4396
|
+
}
|
|
4397
|
+
function normalizeDocumentPageDimensionInput(value) {
|
|
4398
|
+
if (!value.trim()) return null;
|
|
4399
|
+
const number = Number(value);
|
|
4400
|
+
return Number.isFinite(number) ? Math.min(558.8, Math.max(25.4, Math.round(10 * number) / 10)) : null;
|
|
4401
|
+
}
|
|
5376
4402
|
function normalizeDocumentPageNumberInput(value) {
|
|
5377
4403
|
if (!value.trim()) return null;
|
|
5378
4404
|
const number = Number(value);
|
|
@@ -5564,6 +4590,7 @@ function DocumentPageThumbnail({ backgroundColor, fallbackText, orientation, pag
|
|
|
5564
4590
|
const sourceMutation = useThumbnailSourceMutation(source, captureActive);
|
|
5565
4591
|
const [image, setImage] = useState(null);
|
|
5566
4592
|
const [state, setState] = useState(source ? 'loading' : 'idle');
|
|
4593
|
+
const sourcePage = source ? thumbnailSourcePage(source, pageIndex) : null;
|
|
5567
4594
|
useEffect(()=>{
|
|
5568
4595
|
if (!source || !captureActive) {
|
|
5569
4596
|
setImage(null);
|
|
@@ -5605,6 +4632,10 @@ function DocumentPageThumbnail({ backgroundColor, fallbackText, orientation, pag
|
|
|
5605
4632
|
source?.pageGap,
|
|
5606
4633
|
source?.pageHeight,
|
|
5607
4634
|
source?.pageWidth,
|
|
4635
|
+
sourcePage?.height,
|
|
4636
|
+
sourcePage?.left,
|
|
4637
|
+
sourcePage?.top,
|
|
4638
|
+
sourcePage?.width,
|
|
5608
4639
|
source?.revision,
|
|
5609
4640
|
sourceMutation
|
|
5610
4641
|
]);
|
|
@@ -5616,7 +4647,7 @@ function DocumentPageThumbnail({ backgroundColor, fallbackText, orientation, pag
|
|
|
5616
4647
|
"data-thumbnail-state": state,
|
|
5617
4648
|
"aria-hidden": "true",
|
|
5618
4649
|
style: {
|
|
5619
|
-
aspectRatio: source ? `${source.pageWidth} / ${source.pageHeight}` : void 0,
|
|
4650
|
+
aspectRatio: source ? `${sourcePage?.width ?? source.pageWidth} / ${sourcePage?.height ?? source.pageHeight}` : void 0,
|
|
5620
4651
|
backgroundColor
|
|
5621
4652
|
},
|
|
5622
4653
|
children: image ? /*#__PURE__*/ jsx("img", {
|
|
@@ -5634,23 +4665,32 @@ async function renderDocumentPageThumbnail(source, pageIndex, targetPixelWidth,
|
|
|
5634
4665
|
if (!Number.isSafeInteger(pageIndex) || pageIndex < 0 || pageIndex >= source.pageCount) throw new Error('The requested document thumbnail page is out of range.');
|
|
5635
4666
|
const capture = mountWorkLiveDocumentCapture(source, pageIndex);
|
|
5636
4667
|
try {
|
|
5637
|
-
const
|
|
4668
|
+
const page = thumbnailSourcePage(source, pageIndex);
|
|
4669
|
+
const scale = Math.max(0.1, Math.min(1, targetPixelWidth / page.width));
|
|
5638
4670
|
const canvas = await renderCanvas(capture.viewport, {
|
|
5639
4671
|
backgroundColor: capture.backgroundColor,
|
|
5640
4672
|
fontReadyTimeout: 0,
|
|
5641
|
-
height:
|
|
4673
|
+
height: page.height,
|
|
5642
4674
|
logging: false,
|
|
5643
4675
|
scale,
|
|
5644
4676
|
useCORS: true,
|
|
5645
|
-
width:
|
|
5646
|
-
windowHeight: Math.ceil(
|
|
5647
|
-
windowWidth: Math.ceil(
|
|
4677
|
+
width: page.width,
|
|
4678
|
+
windowHeight: Math.ceil(page.height),
|
|
4679
|
+
windowWidth: Math.ceil(page.width)
|
|
5648
4680
|
});
|
|
5649
4681
|
return canvas.toDataURL('image/png');
|
|
5650
4682
|
} finally{
|
|
5651
4683
|
capture.host.remove();
|
|
5652
4684
|
}
|
|
5653
4685
|
}
|
|
4686
|
+
function thumbnailSourcePage(source, pageIndex) {
|
|
4687
|
+
return source.pages?.[pageIndex] ?? {
|
|
4688
|
+
height: source.pageHeight,
|
|
4689
|
+
left: 0,
|
|
4690
|
+
top: pageIndex * (source.pageHeight + source.pageGap),
|
|
4691
|
+
width: source.pageWidth
|
|
4692
|
+
};
|
|
4693
|
+
}
|
|
5654
4694
|
async function renderDocumentPageCanvas(element, options) {
|
|
5655
4695
|
const { default: html2canvas } = await import("html2canvas");
|
|
5656
4696
|
return html2canvas(element, options);
|
|
@@ -5762,7 +4802,8 @@ function DocumentPageNavigation({ currentPage, pages, thumbnailSource, onSelectP
|
|
|
5762
4802
|
const itemHeights = useMemo(()=>pages.map((page)=>estimatedDocumentPageItemHeight(page, thumbnailSource)), [
|
|
5763
4803
|
pages,
|
|
5764
4804
|
thumbnailSource?.pageHeight,
|
|
5765
|
-
thumbnailSource?.pageWidth
|
|
4805
|
+
thumbnailSource?.pageWidth,
|
|
4806
|
+
thumbnailSource?.pages
|
|
5766
4807
|
]);
|
|
5767
4808
|
const pageStarts = useMemo(()=>documentNavigationItemStarts(itemHeights, DOCUMENT_PAGE_ITEM_GAP), [
|
|
5768
4809
|
itemHeights
|
|
@@ -5953,7 +4994,8 @@ function documentPageIndex(pages, physicalPage) {
|
|
|
5953
4994
|
}
|
|
5954
4995
|
function estimatedDocumentPageItemHeight(page, source) {
|
|
5955
4996
|
const width = 'landscape' === page.orientation ? DOCUMENT_PAGE_LANDSCAPE_WIDTH : DOCUMENT_PAGE_PORTRAIT_WIDTH;
|
|
5956
|
-
const
|
|
4997
|
+
const sourcePage = source?.pages?.[page.physicalPage - 1];
|
|
4998
|
+
const sourceRatio = sourcePage && sourcePage.width > 0 && sourcePage.height > 0 ? sourcePage.height / sourcePage.width : source && source.pageWidth > 0 && source.pageHeight > 0 ? source.pageHeight / source.pageWidth : null;
|
|
5957
4999
|
const fallbackRatio = 'landscape' === page.orientation ? 210 / 297 : 297 / 210;
|
|
5958
5000
|
return Math.ceil(width * (sourceRatio ?? fallbackRatio) + DOCUMENT_PAGE_BUTTON_CHROME_HEIGHT);
|
|
5959
5001
|
}
|
|
@@ -6323,25 +5365,135 @@ function runWithInstantDocumentScroll(editor, run) {
|
|
|
6323
5365
|
else restore();
|
|
6324
5366
|
}
|
|
6325
5367
|
}
|
|
6326
|
-
function
|
|
5368
|
+
function WorkDocumentPageBorder({ layout, physicalPage = 1, sectionPage }) {
|
|
5369
|
+
const source = normalizeDocumentPageBorders(layout.pageBorders);
|
|
5370
|
+
if (!source || !documentPageBordersVisible(source, sectionPage)) return null;
|
|
5371
|
+
const resolved = resolveDocumentPageBorders(source, resolveDocumentPageMargins(layout, physicalPage).body);
|
|
5372
|
+
if (!resolved) return null;
|
|
5373
|
+
const visibleEdges = DOCUMENT_PAGE_BORDER_EDGES.filter((edge)=>(resolved.edges[edge]?.width ?? 0) > 0);
|
|
5374
|
+
if (!visibleEdges.length) return null;
|
|
5375
|
+
const shadow = visibleEdges.map((edge)=>source.edges[edge]).find((border)=>border?.shadow);
|
|
5376
|
+
const shadowColor = shadow ? resolved.edges[visibleEdges.find((edge)=>source.edges[edge] === shadow) ?? 'top']?.color ?? '#000000' : null;
|
|
5377
|
+
const art = visibleEdges.some((edge)=>{
|
|
5378
|
+
const border = source.edges[edge];
|
|
5379
|
+
return border && isDocumentParagraphArtBorderStyle(border.style);
|
|
5380
|
+
});
|
|
5381
|
+
const frame = visibleEdges.some((edge)=>source.edges[edge]?.frame);
|
|
5382
|
+
return /*#__PURE__*/ jsx("div", {
|
|
5383
|
+
className: `work-document-page-border ${resolved.zOrder}`,
|
|
5384
|
+
"data-document-page-border-art": String(art),
|
|
5385
|
+
"data-document-page-border-display": resolved.display,
|
|
5386
|
+
"data-document-page-border-frame": String(frame),
|
|
5387
|
+
"data-document-page-border-offset-from": resolved.offsetFrom,
|
|
5388
|
+
"data-document-page-border-z-order": resolved.zOrder,
|
|
5389
|
+
"aria-hidden": "true",
|
|
5390
|
+
style: {
|
|
5391
|
+
top: resolved.insets.top,
|
|
5392
|
+
right: resolved.insets.right,
|
|
5393
|
+
bottom: resolved.insets.bottom,
|
|
5394
|
+
left: resolved.insets.left,
|
|
5395
|
+
...Object.fromEntries(DOCUMENT_PAGE_BORDER_EDGES.flatMap((edge)=>{
|
|
5396
|
+
const border = resolved.edges[edge];
|
|
5397
|
+
if (!border || border.width <= 0) return [];
|
|
5398
|
+
const property = `border${edge[0]?.toUpperCase()}${edge.slice(1)}`;
|
|
5399
|
+
return [
|
|
5400
|
+
[
|
|
5401
|
+
property,
|
|
5402
|
+
`${formatPixels(border.width)}px ${border.style} ${border.color}`
|
|
5403
|
+
]
|
|
5404
|
+
];
|
|
5405
|
+
})),
|
|
5406
|
+
...shadowColor ? {
|
|
5407
|
+
filter: `drop-shadow(2px 2px 0 ${shadowColor})`
|
|
5408
|
+
} : {}
|
|
5409
|
+
}
|
|
5410
|
+
});
|
|
5411
|
+
}
|
|
5412
|
+
function formatPixels(value) {
|
|
5413
|
+
return Number(value.toFixed(3)).toString();
|
|
5414
|
+
}
|
|
5415
|
+
function DocumentPageStack({ pageColor, pageCount, pageGap, pageHeight, pageWidth = 794, pages = [] }) {
|
|
6327
5416
|
const count = Math.max(1, Math.trunc(pageCount));
|
|
6328
5417
|
const gap = Math.max(0, pageGap);
|
|
6329
5418
|
const height = Math.max(1, pageHeight);
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
5419
|
+
const fallbackPage = {
|
|
5420
|
+
width: Math.max(1, pageWidth),
|
|
5421
|
+
height,
|
|
5422
|
+
marginTop: 0,
|
|
5423
|
+
marginRight: 0,
|
|
5424
|
+
marginBottom: 0,
|
|
5425
|
+
marginLeft: 0,
|
|
5426
|
+
headerHeight: 0,
|
|
5427
|
+
footerHeight: 0,
|
|
5428
|
+
pageGap: gap
|
|
5429
|
+
};
|
|
5430
|
+
const geometry = documentPageSurfaceGeometry(pages.map((page)=>page.page ?? fallbackPage), fallbackPage, count);
|
|
5431
|
+
const descriptors = geometry.frames.map((frame)=>({
|
|
5432
|
+
frame,
|
|
5433
|
+
page: pages[frame.pageIndex]
|
|
5434
|
+
}));
|
|
5435
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
5436
|
+
children: [
|
|
5437
|
+
/*#__PURE__*/ jsx("div", {
|
|
5438
|
+
className: "work-document-page-stack",
|
|
5439
|
+
"data-page-count": count,
|
|
5440
|
+
"data-page-surface-height": geometry.height,
|
|
5441
|
+
"data-page-surface-width": geometry.width,
|
|
5442
|
+
"aria-hidden": "true",
|
|
5443
|
+
children: descriptors.map(({ frame, page })=>{
|
|
5444
|
+
const resolvedPageSize = page ? resolveDocumentPageSize(page.layout) : null;
|
|
5445
|
+
return /*#__PURE__*/ jsx("div", {
|
|
5446
|
+
className: "work-document-page-sheet",
|
|
5447
|
+
"data-work-document-page-sheet": "",
|
|
5448
|
+
"data-page-index": frame.pageIndex + 1,
|
|
5449
|
+
"data-page-top": frame.top,
|
|
5450
|
+
"data-page-left": frame.left,
|
|
5451
|
+
"data-page-width": frame.width,
|
|
5452
|
+
"data-page-height": frame.height,
|
|
5453
|
+
"data-pdf-orientation": resolvedPageSize?.orientation,
|
|
5454
|
+
"data-pdf-page-size": resolvedPageSize?.preset,
|
|
5455
|
+
"data-pdf-page-width-points": resolvedPageSize?.widthPoints ?? 72 * frame.width / 96,
|
|
5456
|
+
"data-pdf-page-height-points": resolvedPageSize?.heightPoints ?? 72 * frame.height / 96,
|
|
5457
|
+
style: {
|
|
5458
|
+
backgroundColor: pageColor,
|
|
5459
|
+
height: frame.height,
|
|
5460
|
+
left: frame.left,
|
|
5461
|
+
top: frame.top,
|
|
5462
|
+
width: frame.width
|
|
5463
|
+
}
|
|
5464
|
+
}, frame.pageIndex);
|
|
5465
|
+
})
|
|
5466
|
+
}),
|
|
5467
|
+
[
|
|
5468
|
+
'back',
|
|
5469
|
+
'front'
|
|
5470
|
+
].map((zOrder)=>/*#__PURE__*/ jsx("div", {
|
|
5471
|
+
className: `work-document-page-border-stack ${zOrder}`,
|
|
5472
|
+
"data-document-page-border-stack": zOrder,
|
|
5473
|
+
"aria-hidden": "true",
|
|
5474
|
+
children: descriptors.flatMap(({ frame, page })=>{
|
|
5475
|
+
const resolved = page ? resolveDocumentPageBorders(page.layout.pageBorders, resolveDocumentPageMargins(page.layout, page.physicalPage ?? frame.pageIndex + 1).body) : null;
|
|
5476
|
+
if (!page || resolved?.zOrder !== zOrder) return [];
|
|
5477
|
+
return [
|
|
5478
|
+
/*#__PURE__*/ jsx("div", {
|
|
5479
|
+
className: "work-document-page-border-surface",
|
|
5480
|
+
"data-page-index": frame.pageIndex + 1,
|
|
5481
|
+
style: {
|
|
5482
|
+
height: frame.height,
|
|
5483
|
+
left: frame.left,
|
|
5484
|
+
top: frame.top,
|
|
5485
|
+
width: frame.width
|
|
5486
|
+
},
|
|
5487
|
+
children: /*#__PURE__*/ jsx(WorkDocumentPageBorder, {
|
|
5488
|
+
layout: page.layout,
|
|
5489
|
+
physicalPage: page.physicalPage ?? frame.pageIndex + 1,
|
|
5490
|
+
sectionPage: page.sectionPage
|
|
5491
|
+
})
|
|
5492
|
+
}, frame.pageIndex)
|
|
5493
|
+
];
|
|
5494
|
+
})
|
|
5495
|
+
}, zOrder))
|
|
5496
|
+
]
|
|
6345
5497
|
});
|
|
6346
5498
|
}
|
|
6347
5499
|
function DocumentRulerTabStops({ marginLeft, pageWidth, rulerRef, tabStops, textWidth, onChange }) {
|
|
@@ -6751,21 +5903,10 @@ function DocumentRulerHandle({ kind, label, maximum, minimum, position, value, v
|
|
|
6751
5903
|
});
|
|
6752
5904
|
}
|
|
6753
5905
|
function documentRulerPageWidth(layout) {
|
|
6754
|
-
|
|
6755
|
-
return 'landscape' === layout.orientation ? portrait.height : portrait.width;
|
|
5906
|
+
return resolveDocumentPageSize(layout).widthPixels;
|
|
6756
5907
|
}
|
|
6757
5908
|
function documentRulerPageHeight(layout) {
|
|
6758
|
-
|
|
6759
|
-
return 'landscape' === layout.orientation ? portrait.width : portrait.height;
|
|
6760
|
-
}
|
|
6761
|
-
function documentRulerPortraitPage(layout) {
|
|
6762
|
-
return 'letter' === layout.pageSize ? {
|
|
6763
|
-
width: 816,
|
|
6764
|
-
height: 1056
|
|
6765
|
-
} : {
|
|
6766
|
-
width: work_document_layout_millimetersToPixels(210),
|
|
6767
|
-
height: work_document_layout_millimetersToPixels(297)
|
|
6768
|
-
};
|
|
5909
|
+
return resolveDocumentPageSize(layout).heightPixels;
|
|
6769
5910
|
}
|
|
6770
5911
|
function documentRulerTicks(layout, pageWidth) {
|
|
6771
5912
|
const left = work_document_layout_millimetersToPixels(layout.margins.left);
|
|
@@ -7780,6 +6921,15 @@ const documentCommandCatalog = {
|
|
|
7780
6921
|
]
|
|
7781
6922
|
}
|
|
7782
6923
|
},
|
|
6924
|
+
bookmark: {
|
|
6925
|
+
id: 'insert.bookmark',
|
|
6926
|
+
label: '添加书签',
|
|
6927
|
+
location: {
|
|
6928
|
+
area: 'ribbon',
|
|
6929
|
+
tab: 'insert',
|
|
6930
|
+
group: 'links'
|
|
6931
|
+
}
|
|
6932
|
+
},
|
|
7783
6933
|
spelling: {
|
|
7784
6934
|
id: 'review.spelling',
|
|
7785
6935
|
label: '拼写检查',
|
|
@@ -9604,9 +8754,7 @@ function DocumentPageLayoutRibbon({ editor, layout, layoutOpen, pageColor, onLay
|
|
|
9604
8754
|
label: '横向'
|
|
9605
8755
|
}
|
|
9606
8756
|
],
|
|
9607
|
-
onValueChange: (orientation)=>
|
|
9608
|
-
orientation
|
|
9609
|
-
})
|
|
8757
|
+
onValueChange: (orientation)=>onLayoutChange(updateDocumentPageOrientation(layout, orientation))
|
|
9610
8758
|
})
|
|
9611
8759
|
]
|
|
9612
8760
|
}),
|
|
@@ -9620,18 +8768,39 @@ function DocumentPageLayoutRibbon({ editor, layout, layoutOpen, pageColor, onLay
|
|
|
9620
8768
|
ariaLabel: "纸张大小",
|
|
9621
8769
|
value: layout.pageSize,
|
|
9622
8770
|
options: [
|
|
8771
|
+
{
|
|
8772
|
+
value: 'a3',
|
|
8773
|
+
label: 'A3'
|
|
8774
|
+
},
|
|
9623
8775
|
{
|
|
9624
8776
|
value: 'a4',
|
|
9625
8777
|
label: 'A4'
|
|
9626
8778
|
},
|
|
8779
|
+
{
|
|
8780
|
+
value: 'a5',
|
|
8781
|
+
label: 'A5'
|
|
8782
|
+
},
|
|
9627
8783
|
{
|
|
9628
8784
|
value: 'letter',
|
|
9629
8785
|
label: 'Letter'
|
|
8786
|
+
},
|
|
8787
|
+
{
|
|
8788
|
+
value: 'legal',
|
|
8789
|
+
label: 'Legal'
|
|
8790
|
+
},
|
|
8791
|
+
{
|
|
8792
|
+
value: 'tabloid',
|
|
8793
|
+
label: 'Tabloid'
|
|
8794
|
+
},
|
|
8795
|
+
{
|
|
8796
|
+
value: 'custom',
|
|
8797
|
+
label: '自定义'
|
|
9630
8798
|
}
|
|
9631
8799
|
],
|
|
9632
|
-
onValueChange: (pageSize)=>
|
|
9633
|
-
|
|
9634
|
-
|
|
8800
|
+
onValueChange: (pageSize)=>{
|
|
8801
|
+
if ('custom' === pageSize) return void onOpenLayout('page');
|
|
8802
|
+
onLayoutChange(updateDocumentPaperSizePreset(layout, pageSize));
|
|
8803
|
+
}
|
|
9635
8804
|
})
|
|
9636
8805
|
]
|
|
9637
8806
|
}),
|
|
@@ -9742,9 +8911,11 @@ const FALLBACK_IMAGE_HEIGHT_PIXELS = 180;
|
|
|
9742
8911
|
const MINIMUM_IMAGE_SIZE_CENTIMETERS = 0.01;
|
|
9743
8912
|
const MAXIMUM_IMAGE_SIZE_CENTIMETERS = 55.87;
|
|
9744
8913
|
const MAXIMUM_WRAP_DISTANCE_MILLIMETERS = 25;
|
|
8914
|
+
const MAXIMUM_IMAGE_OFFSET_MILLIMETERS = 558.7;
|
|
9745
8915
|
function createDocumentPicturePropertiesDraft(source) {
|
|
9746
8916
|
const width = effectiveDimension(source.properties.width, source.renderedWidth, FALLBACK_IMAGE_WIDTH_PIXELS);
|
|
9747
8917
|
const height = effectiveDimension(source.properties.height, source.renderedHeight, FALLBACK_IMAGE_HEIGHT_PIXELS);
|
|
8918
|
+
const layer = normalizeDocumentImageLayer(source.properties.layer ?? {});
|
|
9748
8919
|
return {
|
|
9749
8920
|
width: document_picture_properties_dialog_model_centimeters(width),
|
|
9750
8921
|
height: document_picture_properties_dialog_model_centimeters(height),
|
|
@@ -9753,7 +8924,22 @@ function createDocumentPicturePropertiesDraft(source) {
|
|
|
9753
8924
|
layout: source.properties.layout,
|
|
9754
8925
|
alignment: source.properties.alignment,
|
|
9755
8926
|
wrapDistance: formatNumber(source.properties.wrapDistance),
|
|
9756
|
-
|
|
8927
|
+
wrapSide: normalizeDocumentImageWrapSide(source.properties.wrapSide),
|
|
8928
|
+
alternativeText: source.properties.alternativeText,
|
|
8929
|
+
precisePosition: Boolean(source.properties.position),
|
|
8930
|
+
horizontalOffset: formatNumber(source.properties.position?.horizontalOffset ?? 0),
|
|
8931
|
+
verticalOffset: formatNumber(source.properties.position?.verticalOffset ?? 0),
|
|
8932
|
+
horizontalReference: source.properties.position?.horizontalReference ?? 'column',
|
|
8933
|
+
verticalReference: source.properties.position?.verticalReference ?? 'paragraph',
|
|
8934
|
+
cropTop: formatNumber(source.properties.crop?.top ?? 0),
|
|
8935
|
+
cropRight: formatNumber(source.properties.crop?.right ?? 0),
|
|
8936
|
+
cropBottom: formatNumber(source.properties.crop?.bottom ?? 0),
|
|
8937
|
+
cropLeft: formatNumber(source.properties.crop?.left ?? 0),
|
|
8938
|
+
relativeHeight: String(layer.relativeHeight),
|
|
8939
|
+
behindDocument: layer.behindDocument,
|
|
8940
|
+
allowOverlap: layer.allowOverlap,
|
|
8941
|
+
layoutInCell: layer.layoutInCell,
|
|
8942
|
+
lockAnchor: layer.lockAnchor
|
|
9757
8943
|
};
|
|
9758
8944
|
}
|
|
9759
8945
|
function withDocumentPictureDimension(draft, dimension, value) {
|
|
@@ -9789,11 +8975,15 @@ function documentPicturePropertiesErrors(draft) {
|
|
|
9789
8975
|
return {
|
|
9790
8976
|
width: imageDimensionError(draft.width),
|
|
9791
8977
|
height: imageDimensionError(draft.height),
|
|
9792
|
-
wrapDistance: 'inline' === draft.layout || validNumber(draft.wrapDistance, 0, MAXIMUM_WRAP_DISTANCE_MILLIMETERS) ? null : '请输入 0 到 25 之间的毫米数。'
|
|
8978
|
+
wrapDistance: 'inline' === draft.layout || 'none' === draft.layout || validNumber(draft.wrapDistance, 0, MAXIMUM_WRAP_DISTANCE_MILLIMETERS) ? null : '请输入 0 到 25 之间的毫米数。',
|
|
8979
|
+
horizontalOffset: !draft.precisePosition || validSignedNumber(draft.horizontalOffset, MAXIMUM_IMAGE_OFFSET_MILLIMETERS) ? null : '请输入 -558.7 到 558.7 之间的毫米数。',
|
|
8980
|
+
verticalOffset: !draft.precisePosition || validSignedNumber(draft.verticalOffset, MAXIMUM_IMAGE_OFFSET_MILLIMETERS) ? null : '请输入 -558.7 到 558.7 之间的毫米数。',
|
|
8981
|
+
crop: imageCropError(draft),
|
|
8982
|
+
relativeHeight: 'inline' === draft.layout || validInteger(draft.relativeHeight, 0, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT) ? null : `请输入 0 到 ${MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT} 之间的整数。`
|
|
9793
8983
|
};
|
|
9794
8984
|
}
|
|
9795
8985
|
function hasDocumentPicturePropertiesErrors(errors) {
|
|
9796
|
-
return Boolean(errors.width || errors.height || errors.wrapDistance);
|
|
8986
|
+
return Boolean(errors.width || errors.height || errors.wrapDistance || errors.horizontalOffset || errors.verticalOffset || errors.crop || errors.relativeHeight);
|
|
9797
8987
|
}
|
|
9798
8988
|
function documentPicturePropertyChanges(initial, current) {
|
|
9799
8989
|
const errors = documentPicturePropertiesErrors(current);
|
|
@@ -9805,8 +8995,31 @@ function documentPicturePropertyChanges(initial, current) {
|
|
|
9805
8995
|
if (initial.layout !== current.layout) changes.layout = current.layout;
|
|
9806
8996
|
if (initial.alignment !== current.alignment) changes.alignment = current.alignment;
|
|
9807
8997
|
if (!sameDraftNumber(initial.wrapDistance, current.wrapDistance)) changes.wrapDistance = Number(current.wrapDistance);
|
|
8998
|
+
if (initial.wrapSide !== current.wrapSide) changes.wrapSide = current.wrapSide;
|
|
9808
8999
|
const alternativeText = current.alternativeText.trim();
|
|
9809
9000
|
if (initial.alternativeText.trim() !== alternativeText) changes.alternativeText = alternativeText;
|
|
9001
|
+
if (initial.precisePosition !== current.precisePosition || current.precisePosition && (!sameDraftNumber(initial.horizontalOffset, current.horizontalOffset) || !sameDraftNumber(initial.verticalOffset, current.verticalOffset) || initial.horizontalReference !== current.horizontalReference || initial.verticalReference !== current.verticalReference)) changes.position = current.precisePosition ? {
|
|
9002
|
+
horizontalOffset: Number(current.horizontalOffset),
|
|
9003
|
+
verticalOffset: Number(current.verticalOffset),
|
|
9004
|
+
horizontalReference: current.horizontalReference,
|
|
9005
|
+
verticalReference: current.verticalReference
|
|
9006
|
+
} : null;
|
|
9007
|
+
if (!sameDraftNumber(initial.cropTop, current.cropTop) || !sameDraftNumber(initial.cropRight, current.cropRight) || !sameDraftNumber(initial.cropBottom, current.cropBottom) || !sameDraftNumber(initial.cropLeft, current.cropLeft)) {
|
|
9008
|
+
const crop = {
|
|
9009
|
+
top: Number(current.cropTop),
|
|
9010
|
+
right: Number(current.cropRight),
|
|
9011
|
+
bottom: Number(current.cropBottom),
|
|
9012
|
+
left: Number(current.cropLeft)
|
|
9013
|
+
};
|
|
9014
|
+
changes.crop = Object.values(crop).some((edge)=>edge > 0) ? crop : null;
|
|
9015
|
+
}
|
|
9016
|
+
if (!sameDraftNumber(initial.relativeHeight, current.relativeHeight) || initial.behindDocument !== current.behindDocument || initial.allowOverlap !== current.allowOverlap || initial.layoutInCell !== current.layoutInCell || initial.lockAnchor !== current.lockAnchor) changes.layer = normalizeDocumentImageLayer({
|
|
9017
|
+
relativeHeight: current.relativeHeight,
|
|
9018
|
+
behindDocument: current.behindDocument,
|
|
9019
|
+
allowOverlap: current.allowOverlap,
|
|
9020
|
+
layoutInCell: current.layoutInCell,
|
|
9021
|
+
lockAnchor: current.lockAnchor
|
|
9022
|
+
});
|
|
9810
9023
|
return Object.keys(changes).length ? changes : null;
|
|
9811
9024
|
}
|
|
9812
9025
|
function effectiveDimension(explicit, rendered, fallback) {
|
|
@@ -9821,6 +9034,27 @@ function validNumber(value, minimum, maximum) {
|
|
|
9821
9034
|
const number = numericDraft(value);
|
|
9822
9035
|
return null !== number && number >= minimum && number <= maximum;
|
|
9823
9036
|
}
|
|
9037
|
+
function validSignedNumber(value, maximumMagnitude) {
|
|
9038
|
+
if (!value.trim()) return false;
|
|
9039
|
+
const number = Number(value);
|
|
9040
|
+
return Number.isFinite(number) && Math.abs(number) <= maximumMagnitude;
|
|
9041
|
+
}
|
|
9042
|
+
function validInteger(value, minimum, maximum) {
|
|
9043
|
+
if (!value.trim()) return false;
|
|
9044
|
+
const number = Number(value);
|
|
9045
|
+
return Number.isInteger(number) && number >= minimum && number <= maximum;
|
|
9046
|
+
}
|
|
9047
|
+
function imageCropError(draft) {
|
|
9048
|
+
const edges = [
|
|
9049
|
+
draft.cropTop,
|
|
9050
|
+
draft.cropRight,
|
|
9051
|
+
draft.cropBottom,
|
|
9052
|
+
draft.cropLeft
|
|
9053
|
+
].map(numericDraft);
|
|
9054
|
+
if (edges.some((edge)=>null === edge || edge > 99.99)) return '请输入 0 到 99.99 之间的裁剪百分比。';
|
|
9055
|
+
const [top = 0, right = 0, bottom = 0, left = 0] = edges;
|
|
9056
|
+
return left + right < 100 && top + bottom < 100 ? null : '相对两边的裁剪量之和必须小于 100%。';
|
|
9057
|
+
}
|
|
9824
9058
|
function numericDraft(value) {
|
|
9825
9059
|
if (!value.trim()) return null;
|
|
9826
9060
|
const number = Number(value);
|
|
@@ -9854,10 +9088,25 @@ const document_picture_properties_dialog_layoutOptions = [
|
|
|
9854
9088
|
label: '四周环绕',
|
|
9855
9089
|
icon: TextWrap
|
|
9856
9090
|
},
|
|
9091
|
+
{
|
|
9092
|
+
value: 'tight',
|
|
9093
|
+
label: '紧密环绕',
|
|
9094
|
+
icon: TextWrap
|
|
9095
|
+
},
|
|
9096
|
+
{
|
|
9097
|
+
value: 'through',
|
|
9098
|
+
label: '穿越环绕',
|
|
9099
|
+
icon: TextWrap
|
|
9100
|
+
},
|
|
9857
9101
|
{
|
|
9858
9102
|
value: 'topBottom',
|
|
9859
9103
|
label: '上下环绕',
|
|
9860
9104
|
icon: Rows3
|
|
9105
|
+
},
|
|
9106
|
+
{
|
|
9107
|
+
value: 'none',
|
|
9108
|
+
label: '自由浮动',
|
|
9109
|
+
icon: TextWrap
|
|
9861
9110
|
}
|
|
9862
9111
|
];
|
|
9863
9112
|
const alignmentOptions = [
|
|
@@ -9877,6 +9126,52 @@ const alignmentOptions = [
|
|
|
9877
9126
|
icon: AlignRight
|
|
9878
9127
|
}
|
|
9879
9128
|
];
|
|
9129
|
+
const wrapSideOptions = [
|
|
9130
|
+
{
|
|
9131
|
+
value: 'bothSides',
|
|
9132
|
+
label: '两侧'
|
|
9133
|
+
},
|
|
9134
|
+
{
|
|
9135
|
+
value: 'left',
|
|
9136
|
+
label: '仅左侧'
|
|
9137
|
+
},
|
|
9138
|
+
{
|
|
9139
|
+
value: 'right',
|
|
9140
|
+
label: '仅右侧'
|
|
9141
|
+
},
|
|
9142
|
+
{
|
|
9143
|
+
value: 'largest',
|
|
9144
|
+
label: '较宽一侧'
|
|
9145
|
+
}
|
|
9146
|
+
];
|
|
9147
|
+
const horizontalReferenceOptions = [
|
|
9148
|
+
{
|
|
9149
|
+
value: 'column',
|
|
9150
|
+
label: '栏'
|
|
9151
|
+
},
|
|
9152
|
+
{
|
|
9153
|
+
value: 'margin',
|
|
9154
|
+
label: '页边距'
|
|
9155
|
+
},
|
|
9156
|
+
{
|
|
9157
|
+
value: 'page',
|
|
9158
|
+
label: '页面'
|
|
9159
|
+
}
|
|
9160
|
+
];
|
|
9161
|
+
const verticalReferenceOptions = [
|
|
9162
|
+
{
|
|
9163
|
+
value: 'paragraph',
|
|
9164
|
+
label: '段落'
|
|
9165
|
+
},
|
|
9166
|
+
{
|
|
9167
|
+
value: 'margin',
|
|
9168
|
+
label: '页边距'
|
|
9169
|
+
},
|
|
9170
|
+
{
|
|
9171
|
+
value: 'page',
|
|
9172
|
+
label: '页面'
|
|
9173
|
+
}
|
|
9174
|
+
];
|
|
9880
9175
|
function DocumentPicturePropertiesControl({ editor }) {
|
|
9881
9176
|
const [source, setSource] = useState(null);
|
|
9882
9177
|
const triggerRef = useRef(null);
|
|
@@ -9967,6 +9262,17 @@ function DocumentPicturePropertiesDialog({ editor, source, restoreFocusTarget, o
|
|
|
9967
9262
|
}),
|
|
9968
9263
|
/*#__PURE__*/ jsx(PictureAlignmentSection, {
|
|
9969
9264
|
draft: draft,
|
|
9265
|
+
errors: errors,
|
|
9266
|
+
onDraftChange: setDraft
|
|
9267
|
+
}),
|
|
9268
|
+
/*#__PURE__*/ jsx(PictureLayerSection, {
|
|
9269
|
+
draft: draft,
|
|
9270
|
+
errors: errors,
|
|
9271
|
+
onDraftChange: setDraft
|
|
9272
|
+
}),
|
|
9273
|
+
/*#__PURE__*/ jsx(PictureCropSection, {
|
|
9274
|
+
draft: draft,
|
|
9275
|
+
errors: errors,
|
|
9970
9276
|
onDraftChange: setDraft
|
|
9971
9277
|
}),
|
|
9972
9278
|
/*#__PURE__*/ jsxs("label", {
|
|
@@ -10082,6 +9388,24 @@ function PictureLayoutSection({ draft, onDraftChange }) {
|
|
|
10082
9388
|
}, option.value);
|
|
10083
9389
|
})
|
|
10084
9390
|
}),
|
|
9391
|
+
/*#__PURE__*/ jsxs("div", {
|
|
9392
|
+
className: "work-document-picture-properties-wrap-side",
|
|
9393
|
+
children: [
|
|
9394
|
+
/*#__PURE__*/ jsx("span", {
|
|
9395
|
+
children: "环绕侧"
|
|
9396
|
+
}),
|
|
9397
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
9398
|
+
ariaLabel: "图片文字环绕侧",
|
|
9399
|
+
value: draft.wrapSide,
|
|
9400
|
+
options: wrapSideOptions,
|
|
9401
|
+
disabled: 'inline' === draft.layout || 'topBottom' === draft.layout || 'none' === draft.layout,
|
|
9402
|
+
onValueChange: (wrapSide)=>onDraftChange((current)=>({
|
|
9403
|
+
...current,
|
|
9404
|
+
wrapSide
|
|
9405
|
+
}))
|
|
9406
|
+
})
|
|
9407
|
+
]
|
|
9408
|
+
}),
|
|
10085
9409
|
/*#__PURE__*/ jsx(PictureNumberRow, {
|
|
10086
9410
|
label: "文字距离",
|
|
10087
9411
|
ariaLabel: "图片与文字距离(毫米)",
|
|
@@ -10090,7 +9414,7 @@ function PictureLayoutSection({ draft, onDraftChange }) {
|
|
|
10090
9414
|
min: 0,
|
|
10091
9415
|
max: 25,
|
|
10092
9416
|
step: 0.5,
|
|
10093
|
-
disabled: 'inline' === draft.layout,
|
|
9417
|
+
disabled: 'inline' === draft.layout || 'none' === draft.layout,
|
|
10094
9418
|
invalid: Boolean(errors.wrapDistance),
|
|
10095
9419
|
onValueChange: (wrapDistance)=>onDraftChange((current)=>({
|
|
10096
9420
|
...current,
|
|
@@ -10104,7 +9428,7 @@ function PictureLayoutSection({ draft, onDraftChange }) {
|
|
|
10104
9428
|
]
|
|
10105
9429
|
});
|
|
10106
9430
|
}
|
|
10107
|
-
function PictureAlignmentSection({ draft, onDraftChange }) {
|
|
9431
|
+
function PictureAlignmentSection({ draft, errors, onDraftChange }) {
|
|
10108
9432
|
return /*#__PURE__*/ jsxs("fieldset", {
|
|
10109
9433
|
className: "work-document-picture-properties-section position",
|
|
10110
9434
|
children: [
|
|
@@ -10139,6 +9463,203 @@ function PictureAlignmentSection({ draft, onDraftChange }) {
|
|
|
10139
9463
|
]
|
|
10140
9464
|
}, option.value);
|
|
10141
9465
|
})
|
|
9466
|
+
}),
|
|
9467
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
9468
|
+
ariaLabel: "使用精确图片位置",
|
|
9469
|
+
checked: draft.precisePosition,
|
|
9470
|
+
disabled: 'inline' === draft.layout,
|
|
9471
|
+
onCheckedChange: (precisePosition)=>onDraftChange((current)=>({
|
|
9472
|
+
...current,
|
|
9473
|
+
precisePosition
|
|
9474
|
+
})),
|
|
9475
|
+
children: "使用精确位置"
|
|
9476
|
+
}),
|
|
9477
|
+
/*#__PURE__*/ jsxs("div", {
|
|
9478
|
+
className: "work-document-picture-properties-position-grid",
|
|
9479
|
+
children: [
|
|
9480
|
+
/*#__PURE__*/ jsx(PictureNumberRow, {
|
|
9481
|
+
label: "水平偏移",
|
|
9482
|
+
ariaLabel: "图片水平偏移(毫米)",
|
|
9483
|
+
value: draft.horizontalOffset,
|
|
9484
|
+
unit: "毫米",
|
|
9485
|
+
min: -558.7,
|
|
9486
|
+
max: 558.7,
|
|
9487
|
+
step: 0.5,
|
|
9488
|
+
disabled: 'inline' === draft.layout || !draft.precisePosition,
|
|
9489
|
+
invalid: Boolean(errors.horizontalOffset),
|
|
9490
|
+
onValueChange: (horizontalOffset)=>onDraftChange((current)=>({
|
|
9491
|
+
...current,
|
|
9492
|
+
horizontalOffset
|
|
9493
|
+
}))
|
|
9494
|
+
}),
|
|
9495
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
9496
|
+
ariaLabel: "水平相对于",
|
|
9497
|
+
value: draft.horizontalReference,
|
|
9498
|
+
options: horizontalReferenceOptions,
|
|
9499
|
+
disabled: 'inline' === draft.layout || !draft.precisePosition,
|
|
9500
|
+
onValueChange: (horizontalReference)=>onDraftChange((current)=>({
|
|
9501
|
+
...current,
|
|
9502
|
+
horizontalReference
|
|
9503
|
+
}))
|
|
9504
|
+
}),
|
|
9505
|
+
/*#__PURE__*/ jsx(PictureNumberRow, {
|
|
9506
|
+
label: "垂直偏移",
|
|
9507
|
+
ariaLabel: "图片垂直偏移(毫米)",
|
|
9508
|
+
value: draft.verticalOffset,
|
|
9509
|
+
unit: "毫米",
|
|
9510
|
+
min: -558.7,
|
|
9511
|
+
max: 558.7,
|
|
9512
|
+
step: 0.5,
|
|
9513
|
+
disabled: 'inline' === draft.layout || !draft.precisePosition,
|
|
9514
|
+
invalid: Boolean(errors.verticalOffset),
|
|
9515
|
+
onValueChange: (verticalOffset)=>onDraftChange((current)=>({
|
|
9516
|
+
...current,
|
|
9517
|
+
verticalOffset
|
|
9518
|
+
}))
|
|
9519
|
+
}),
|
|
9520
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
9521
|
+
ariaLabel: "垂直相对于",
|
|
9522
|
+
value: draft.verticalReference,
|
|
9523
|
+
options: verticalReferenceOptions,
|
|
9524
|
+
disabled: 'inline' === draft.layout || !draft.precisePosition,
|
|
9525
|
+
onValueChange: (verticalReference)=>onDraftChange((current)=>({
|
|
9526
|
+
...current,
|
|
9527
|
+
verticalReference
|
|
9528
|
+
}))
|
|
9529
|
+
})
|
|
9530
|
+
]
|
|
9531
|
+
}),
|
|
9532
|
+
errors.horizontalOffset && /*#__PURE__*/ jsx("p", {
|
|
9533
|
+
role: "alert",
|
|
9534
|
+
children: errors.horizontalOffset
|
|
9535
|
+
}),
|
|
9536
|
+
errors.verticalOffset && /*#__PURE__*/ jsx("p", {
|
|
9537
|
+
role: "alert",
|
|
9538
|
+
children: errors.verticalOffset
|
|
9539
|
+
})
|
|
9540
|
+
]
|
|
9541
|
+
});
|
|
9542
|
+
}
|
|
9543
|
+
function PictureLayerSection({ draft, errors, onDraftChange }) {
|
|
9544
|
+
const disabled = 'inline' === draft.layout;
|
|
9545
|
+
return /*#__PURE__*/ jsxs("fieldset", {
|
|
9546
|
+
className: "work-document-picture-properties-section layer",
|
|
9547
|
+
children: [
|
|
9548
|
+
/*#__PURE__*/ jsx("legend", {
|
|
9549
|
+
children: "图层与锚点"
|
|
9550
|
+
}),
|
|
9551
|
+
/*#__PURE__*/ jsx(PictureNumberRow, {
|
|
9552
|
+
label: "层级顺序",
|
|
9553
|
+
ariaLabel: "图片绘图层级顺序",
|
|
9554
|
+
value: draft.relativeHeight,
|
|
9555
|
+
unit: "序号",
|
|
9556
|
+
min: 0,
|
|
9557
|
+
max: MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT,
|
|
9558
|
+
step: 1,
|
|
9559
|
+
disabled: disabled,
|
|
9560
|
+
invalid: Boolean(errors.relativeHeight),
|
|
9561
|
+
onValueChange: (relativeHeight)=>onDraftChange((current)=>({
|
|
9562
|
+
...current,
|
|
9563
|
+
relativeHeight
|
|
9564
|
+
}))
|
|
9565
|
+
}),
|
|
9566
|
+
errors.relativeHeight && /*#__PURE__*/ jsx("p", {
|
|
9567
|
+
role: "alert",
|
|
9568
|
+
children: errors.relativeHeight
|
|
9569
|
+
}),
|
|
9570
|
+
/*#__PURE__*/ jsxs("div", {
|
|
9571
|
+
className: "work-document-picture-properties-layer-options",
|
|
9572
|
+
children: [
|
|
9573
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
9574
|
+
ariaLabel: "图片衬于文字下方",
|
|
9575
|
+
checked: draft.behindDocument,
|
|
9576
|
+
disabled: disabled,
|
|
9577
|
+
onCheckedChange: (behindDocument)=>onDraftChange((current)=>({
|
|
9578
|
+
...current,
|
|
9579
|
+
behindDocument
|
|
9580
|
+
})),
|
|
9581
|
+
children: "衬于文字下方"
|
|
9582
|
+
}),
|
|
9583
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
9584
|
+
ariaLabel: "允许图片重叠",
|
|
9585
|
+
checked: draft.allowOverlap,
|
|
9586
|
+
disabled: disabled,
|
|
9587
|
+
onCheckedChange: (allowOverlap)=>onDraftChange((current)=>({
|
|
9588
|
+
...current,
|
|
9589
|
+
allowOverlap
|
|
9590
|
+
})),
|
|
9591
|
+
children: "允许对象重叠"
|
|
9592
|
+
}),
|
|
9593
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
9594
|
+
ariaLabel: "图片随表格单元格布局",
|
|
9595
|
+
checked: draft.layoutInCell,
|
|
9596
|
+
disabled: disabled,
|
|
9597
|
+
onCheckedChange: (layoutInCell)=>onDraftChange((current)=>({
|
|
9598
|
+
...current,
|
|
9599
|
+
layoutInCell
|
|
9600
|
+
})),
|
|
9601
|
+
children: "随单元格布局"
|
|
9602
|
+
}),
|
|
9603
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
9604
|
+
ariaLabel: "锁定图片锚点",
|
|
9605
|
+
checked: draft.lockAnchor,
|
|
9606
|
+
disabled: disabled,
|
|
9607
|
+
onCheckedChange: (lockAnchor)=>onDraftChange((current)=>({
|
|
9608
|
+
...current,
|
|
9609
|
+
lockAnchor
|
|
9610
|
+
})),
|
|
9611
|
+
children: "锁定锚点"
|
|
9612
|
+
})
|
|
9613
|
+
]
|
|
9614
|
+
})
|
|
9615
|
+
]
|
|
9616
|
+
});
|
|
9617
|
+
}
|
|
9618
|
+
function PictureCropSection({ draft, errors, onDraftChange }) {
|
|
9619
|
+
const fields = [
|
|
9620
|
+
{
|
|
9621
|
+
key: 'cropTop',
|
|
9622
|
+
label: '上方裁剪'
|
|
9623
|
+
},
|
|
9624
|
+
{
|
|
9625
|
+
key: 'cropRight',
|
|
9626
|
+
label: '右侧裁剪'
|
|
9627
|
+
},
|
|
9628
|
+
{
|
|
9629
|
+
key: 'cropBottom',
|
|
9630
|
+
label: '下方裁剪'
|
|
9631
|
+
},
|
|
9632
|
+
{
|
|
9633
|
+
key: 'cropLeft',
|
|
9634
|
+
label: '左侧裁剪'
|
|
9635
|
+
}
|
|
9636
|
+
];
|
|
9637
|
+
return /*#__PURE__*/ jsxs("fieldset", {
|
|
9638
|
+
className: "work-document-picture-properties-section crop",
|
|
9639
|
+
children: [
|
|
9640
|
+
/*#__PURE__*/ jsx("legend", {
|
|
9641
|
+
children: "裁剪"
|
|
9642
|
+
}),
|
|
9643
|
+
/*#__PURE__*/ jsx("div", {
|
|
9644
|
+
className: "work-document-picture-properties-crop-grid",
|
|
9645
|
+
children: fields.map((field)=>/*#__PURE__*/ jsx(PictureNumberRow, {
|
|
9646
|
+
label: field.label,
|
|
9647
|
+
ariaLabel: `图片${field.label}(百分比)`,
|
|
9648
|
+
value: draft[field.key],
|
|
9649
|
+
unit: "%",
|
|
9650
|
+
min: 0,
|
|
9651
|
+
max: 99.99,
|
|
9652
|
+
step: 1,
|
|
9653
|
+
invalid: Boolean(errors.crop),
|
|
9654
|
+
onValueChange: (value)=>onDraftChange((current)=>({
|
|
9655
|
+
...current,
|
|
9656
|
+
[field.key]: value
|
|
9657
|
+
}))
|
|
9658
|
+
}, field.key))
|
|
9659
|
+
}),
|
|
9660
|
+
errors.crop && /*#__PURE__*/ jsx("p", {
|
|
9661
|
+
role: "alert",
|
|
9662
|
+
children: errors.crop
|
|
10142
9663
|
})
|
|
10143
9664
|
]
|
|
10144
9665
|
});
|
|
@@ -10229,10 +9750,28 @@ function DocumentPictureRibbon({ editor }) {
|
|
|
10229
9750
|
})
|
|
10230
9751
|
}),
|
|
10231
9752
|
/*#__PURE__*/ jsx(PictureButton, {
|
|
10232
|
-
label: "四周环绕",
|
|
10233
|
-
active: 'square' === image.layout,
|
|
9753
|
+
label: "四周环绕",
|
|
9754
|
+
active: 'square' === image.layout,
|
|
9755
|
+
disabled: !imageSelected,
|
|
9756
|
+
onClick: ()=>updateLayout('square'),
|
|
9757
|
+
children: /*#__PURE__*/ jsx(TextWrap, {
|
|
9758
|
+
size: 18
|
|
9759
|
+
})
|
|
9760
|
+
}),
|
|
9761
|
+
/*#__PURE__*/ jsx(PictureButton, {
|
|
9762
|
+
label: "紧密环绕",
|
|
9763
|
+
active: 'tight' === image.layout,
|
|
9764
|
+
disabled: !imageSelected,
|
|
9765
|
+
onClick: ()=>updateLayout('tight'),
|
|
9766
|
+
children: /*#__PURE__*/ jsx(TextWrap, {
|
|
9767
|
+
size: 18
|
|
9768
|
+
})
|
|
9769
|
+
}),
|
|
9770
|
+
/*#__PURE__*/ jsx(PictureButton, {
|
|
9771
|
+
label: "穿越环绕",
|
|
9772
|
+
active: 'through' === image.layout,
|
|
10234
9773
|
disabled: !imageSelected,
|
|
10235
|
-
onClick: ()=>updateLayout('
|
|
9774
|
+
onClick: ()=>updateLayout('through'),
|
|
10236
9775
|
children: /*#__PURE__*/ jsx(TextWrap, {
|
|
10237
9776
|
size: 18
|
|
10238
9777
|
})
|
|
@@ -10245,6 +9784,15 @@ function DocumentPictureRibbon({ editor }) {
|
|
|
10245
9784
|
children: /*#__PURE__*/ jsx(Rows3, {
|
|
10246
9785
|
size: 18
|
|
10247
9786
|
})
|
|
9787
|
+
}),
|
|
9788
|
+
/*#__PURE__*/ jsx(PictureButton, {
|
|
9789
|
+
label: "自由浮动",
|
|
9790
|
+
active: 'none' === image.layout,
|
|
9791
|
+
disabled: !imageSelected,
|
|
9792
|
+
onClick: ()=>updateLayout('none'),
|
|
9793
|
+
children: /*#__PURE__*/ jsx(TextWrap, {
|
|
9794
|
+
size: 18
|
|
9795
|
+
})
|
|
10248
9796
|
})
|
|
10249
9797
|
]
|
|
10250
9798
|
}),
|
|
@@ -10286,7 +9834,7 @@ function DocumentPictureRibbon({ editor }) {
|
|
|
10286
9834
|
ariaLabel: "图片与文字距离",
|
|
10287
9835
|
value: wrapDistanceValue,
|
|
10288
9836
|
options: imageWrapDistanceOptionsForValue(wrapDistanceValue),
|
|
10289
|
-
disabled: !imageSelected || 'inline' === image.layout,
|
|
9837
|
+
disabled: !imageSelected || 'inline' === image.layout || 'none' === image.layout,
|
|
10290
9838
|
onValueChange: (value)=>editor.commands.setDocumentImageLayoutOptions({
|
|
10291
9839
|
wrapDistance: Number(value)
|
|
10292
9840
|
})
|
|
@@ -10529,7 +10077,8 @@ function createDocumentTablePropertiesDraft(source) {
|
|
|
10529
10077
|
repeatHeader: source.rowOptions.repeatHeader
|
|
10530
10078
|
},
|
|
10531
10079
|
column: {
|
|
10532
|
-
|
|
10080
|
+
widthType: source.sizing.columnWidthType,
|
|
10081
|
+
width: 'percent' === source.sizing.columnWidthType ? document_table_properties_dialog_model_formatNumber(source.sizing.columnWidth ?? 100) : document_table_properties_dialog_model_centimeters(source.renderedColumnWidth ?? source.sizing.columnWidth ?? FALLBACK_COLUMN_WIDTH_CENTIMETERS * document_table_properties_dialog_model_PIXELS_PER_CENTIMETER)
|
|
10533
10082
|
},
|
|
10534
10083
|
cell: {
|
|
10535
10084
|
verticalAlign: source.cellFormat.verticalAlign,
|
|
@@ -10547,7 +10096,7 @@ function documentTablePropertiesErrors(draft) {
|
|
|
10547
10096
|
tableWidth: tableWidthError(draft),
|
|
10548
10097
|
tableIndent: tableIndentError(draft),
|
|
10549
10098
|
rowHeight: draft.row.heightEnabled ? dimensionError(draft.row.height) : null,
|
|
10550
|
-
columnWidth: dimensionError(draft.column.width),
|
|
10099
|
+
columnWidth: 'percent' === draft.column.widthType ? percentageError(draft.column.width) : dimensionError(draft.column.width),
|
|
10551
10100
|
cellMargins
|
|
10552
10101
|
};
|
|
10553
10102
|
}
|
|
@@ -10566,6 +10115,17 @@ function draftForTableWidthType(current, widthType, renderedTableWidth) {
|
|
|
10566
10115
|
}
|
|
10567
10116
|
};
|
|
10568
10117
|
}
|
|
10118
|
+
function draftForColumnWidthType(current, widthType, source) {
|
|
10119
|
+
if (widthType === current.column.widthType) return current;
|
|
10120
|
+
const width = 'percent' === widthType ? document_table_properties_dialog_model_formatNumber('percent' === source.sizing.columnWidthType ? source.sizing.columnWidth ?? 100 : source.renderedColumnWidth && source.renderedTableWidth ? source.renderedColumnWidth / source.renderedTableWidth * 100 : 100 / Math.max(1, source.sizing.selectedColumnCount)) : document_table_properties_dialog_model_centimeters(source.renderedColumnWidth ?? ('pixels' === source.sizing.columnWidthType ? source.sizing.columnWidth : null) ?? FALLBACK_COLUMN_WIDTH_CENTIMETERS * document_table_properties_dialog_model_PIXELS_PER_CENTIMETER);
|
|
10121
|
+
return {
|
|
10122
|
+
...current,
|
|
10123
|
+
column: {
|
|
10124
|
+
widthType,
|
|
10125
|
+
width
|
|
10126
|
+
}
|
|
10127
|
+
};
|
|
10128
|
+
}
|
|
10569
10129
|
function documentTablePropertyChanges(initial, current, source) {
|
|
10570
10130
|
const errors = documentTablePropertiesErrors(current);
|
|
10571
10131
|
if (hasDocumentTablePropertiesErrors(errors)) return null;
|
|
@@ -10581,9 +10141,11 @@ function documentTablePropertyChanges(initial, current, source) {
|
|
|
10581
10141
|
repeatHeader: current.row.repeatHeader
|
|
10582
10142
|
} : {}
|
|
10583
10143
|
};
|
|
10584
|
-
if (!document_table_properties_dialog_model_sameDraftNumber(initial.column.width, current.column.width)) changes.column = {
|
|
10585
|
-
|
|
10586
|
-
|
|
10144
|
+
if (initial.column.widthType !== current.column.widthType || !document_table_properties_dialog_model_sameDraftNumber(initial.column.width, current.column.width)) changes.column = {
|
|
10145
|
+
type: current.column.widthType,
|
|
10146
|
+
width: 'percent' === current.column.widthType ? document_table_properties_dialog_model_rounded(Number(current.column.width)) : document_table_properties_dialog_model_rounded(Number(current.column.width) * document_table_properties_dialog_model_PIXELS_PER_CENTIMETER),
|
|
10147
|
+
renderedColumnWidths: source.renderedColumnWidths,
|
|
10148
|
+
renderedTableWidth: source.renderedTableWidth
|
|
10587
10149
|
};
|
|
10588
10150
|
const marginsChanged = initial.cell.useTableMargins !== current.cell.useTableMargins || !current.cell.useTableMargins && marginSides.some((side)=>!document_table_properties_dialog_model_sameDraftNumber(initial.cell.margins[side], current.cell.margins[side]));
|
|
10589
10151
|
if (initial.cell.verticalAlign !== current.cell.verticalAlign || marginsChanged) changes.cell = {
|
|
@@ -10648,6 +10210,9 @@ function tableIndentError(draft) {
|
|
|
10648
10210
|
function dimensionError(value) {
|
|
10649
10211
|
return document_table_properties_dialog_model_validNumber(value, 0.5, 30) ? null : '请输入 0.5 到 30 之间的厘米数。';
|
|
10650
10212
|
}
|
|
10213
|
+
function percentageError(value) {
|
|
10214
|
+
return document_table_properties_dialog_model_validNumber(value, 1, 100) ? null : '请输入 1 到 100 之间的百分比。';
|
|
10215
|
+
}
|
|
10651
10216
|
function document_table_properties_dialog_model_validNumber(value, minimum, maximum) {
|
|
10652
10217
|
if (!value.trim()) return false;
|
|
10653
10218
|
const numeric = Number(value);
|
|
@@ -10698,6 +10263,16 @@ const widthOptions = [
|
|
|
10698
10263
|
label: '厘米'
|
|
10699
10264
|
}
|
|
10700
10265
|
];
|
|
10266
|
+
const columnWidthOptions = [
|
|
10267
|
+
{
|
|
10268
|
+
value: 'pixels',
|
|
10269
|
+
label: '厘米'
|
|
10270
|
+
},
|
|
10271
|
+
{
|
|
10272
|
+
value: 'percent',
|
|
10273
|
+
label: '百分比'
|
|
10274
|
+
}
|
|
10275
|
+
];
|
|
10701
10276
|
const document_table_properties_dialog_sections_alignmentOptions = [
|
|
10702
10277
|
{
|
|
10703
10278
|
value: 'left',
|
|
@@ -11026,25 +10601,43 @@ function RowSection({ draft, setDraft, errors, source }) {
|
|
|
11026
10601
|
]
|
|
11027
10602
|
});
|
|
11028
10603
|
}
|
|
11029
|
-
function ColumnSection({ draft, setDraft, errors }) {
|
|
10604
|
+
function ColumnSection({ draft, setDraft, errors, source }) {
|
|
11030
10605
|
return /*#__PURE__*/ jsxs("fieldset", {
|
|
11031
10606
|
className: "work-document-table-properties-section",
|
|
11032
10607
|
children: [
|
|
11033
10608
|
/*#__PURE__*/ jsx("legend", {
|
|
11034
10609
|
children: "当前列尺寸"
|
|
11035
10610
|
}),
|
|
10611
|
+
/*#__PURE__*/ jsx("div", {
|
|
10612
|
+
className: "work-document-table-properties-choice-grid width",
|
|
10613
|
+
children: columnWidthOptions.map((option)=>/*#__PURE__*/ jsxs("label", {
|
|
10614
|
+
children: [
|
|
10615
|
+
/*#__PURE__*/ jsx("input", {
|
|
10616
|
+
type: "radio",
|
|
10617
|
+
name: "table-properties-column-width-type",
|
|
10618
|
+
value: option.value,
|
|
10619
|
+
checked: draft.column.widthType === option.value,
|
|
10620
|
+
onChange: ()=>setDraft((current)=>draftForColumnWidthType(current, option.value, source))
|
|
10621
|
+
}),
|
|
10622
|
+
/*#__PURE__*/ jsx("span", {
|
|
10623
|
+
children: option.label
|
|
10624
|
+
})
|
|
10625
|
+
]
|
|
10626
|
+
}, option.value))
|
|
10627
|
+
}),
|
|
11036
10628
|
/*#__PURE__*/ jsx(NumberRow, {
|
|
11037
10629
|
label: "列宽",
|
|
11038
|
-
ariaLabel:
|
|
10630
|
+
ariaLabel: 'percent' === draft.column.widthType ? '当前列宽(百分比)' : '当前列宽(厘米)',
|
|
11039
10631
|
value: draft.column.width,
|
|
11040
|
-
unit:
|
|
11041
|
-
min: 0.5,
|
|
11042
|
-
max: 30,
|
|
11043
|
-
step: 0.1,
|
|
10632
|
+
unit: 'percent' === draft.column.widthType ? '%' : '厘米',
|
|
10633
|
+
min: 'percent' === draft.column.widthType ? 1 : 0.5,
|
|
10634
|
+
max: 'percent' === draft.column.widthType ? 100 : 30,
|
|
10635
|
+
step: 'percent' === draft.column.widthType ? 1 : 0.1,
|
|
11044
10636
|
invalid: Boolean(errors.columnWidth),
|
|
11045
10637
|
onValueChange: (width)=>setDraft((current)=>({
|
|
11046
10638
|
...current,
|
|
11047
10639
|
column: {
|
|
10640
|
+
...current.column,
|
|
11048
10641
|
width
|
|
11049
10642
|
}
|
|
11050
10643
|
}))
|
|
@@ -12067,12 +11660,13 @@ function headingLevelForShortcut(code, key) {
|
|
|
12067
11660
|
if ('3' === value) return 3;
|
|
12068
11661
|
return null;
|
|
12069
11662
|
}
|
|
12070
|
-
function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigationOpen, pageColor, showPageNumbers, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onLayoutChange, onOpenLayout, onToggleNavigation, onTogglePageNumbers, onToggleRulers, onPageColorChange, onToggleSpellcheck, onViewModeChange, onZoomChange, onZoomFit, onInsertSection, onInsertNote, onInsertCaption, onInsertCrossReference, citationsOpen, citationSourceCount, onToggleCitations, onInsertField, onRefreshFields, canInsertComment, onInsertComment, commentsOpen, commentCount, onToggleComments, trackChanges, changesOpen, changeCount, findReplaceMode, fileActions, onRibbonTabChange, onToggleTrackChanges, onToggleChanges, onOpenWordCount, onOpenFindReplace }) {
|
|
11663
|
+
function DocumentToolbar({ editor, defaultRibbonCollapsed = false, history, layoutOpen, layout, layoutFonts = [], navigationOpen, pageColor, showPageNumbers, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onLayoutChange, onOpenLayout, onToggleNavigation, onTogglePageNumbers, onToggleRulers, onPageColorChange, onToggleSpellcheck, onViewModeChange, onZoomChange, onZoomFit, onInsertSection, onInsertNote, onInsertCaption, onInsertCrossReference, citationsOpen, citationSourceCount, onToggleCitations, onInsertField, onRefreshFields, canInsertComment, onInsertComment, commentsOpen, commentCount, onToggleComments, trackChanges, changesOpen, changeCount, findReplaceMode, fileActions, onRibbonTabChange, onToggleTrackChanges, onToggleChanges, onOpenWordCount, onOpenFindReplace }) {
|
|
12071
11664
|
const [activeTab, setActiveTab] = useState('home');
|
|
12072
11665
|
const officeDialog = useOfficeDialog();
|
|
12073
11666
|
const prompt = officeDialog.prompt;
|
|
12074
11667
|
const imageSelected = editor.isActive('image');
|
|
12075
11668
|
const tableSelected = editor.isActive('table');
|
|
11669
|
+
const activeBookmark = activeDocumentBookmark(editor);
|
|
12076
11670
|
const hasRefreshableFields = documentHasRefreshableFields(editor);
|
|
12077
11671
|
const documentChanges = collectDocumentChanges(editor.state.doc);
|
|
12078
11672
|
const previousChangeIndex = adjacentDocumentChangeIndex(documentChanges, editor.state.selection, -1);
|
|
@@ -12098,7 +11692,7 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12098
11692
|
if (editor.isActive('link')) return void editor.chain().focus().unsetLink().run();
|
|
12099
11693
|
const href = await prompt({
|
|
12100
11694
|
title: '添加链接',
|
|
12101
|
-
description: '
|
|
11695
|
+
description: '输入网页、邮箱地址,或使用 #书签名称 跳转到文档内位置。',
|
|
12102
11696
|
fieldLabel: '链接地址',
|
|
12103
11697
|
initialValue: editor.getAttributes('link').href ?? 'https://',
|
|
12104
11698
|
placeholder: 'https://',
|
|
@@ -12117,6 +11711,26 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12117
11711
|
editor,
|
|
12118
11712
|
prompt
|
|
12119
11713
|
]);
|
|
11714
|
+
const toggleBookmark = useCallback(async ()=>{
|
|
11715
|
+
if (activeBookmark) return void editor.chain().focus().deleteDocumentBookmark(activeBookmark.id).run();
|
|
11716
|
+
const name = await prompt({
|
|
11717
|
+
title: '添加书签',
|
|
11718
|
+
description: '为当前光标位置或选中内容创建文档内链接目标。',
|
|
11719
|
+
fieldLabel: '书签名称',
|
|
11720
|
+
initialValue: '',
|
|
11721
|
+
placeholder: '例如 Architecture_2',
|
|
11722
|
+
confirmLabel: '添加书签',
|
|
11723
|
+
required: '请输入书签名称。',
|
|
11724
|
+
validate: (value)=>validateDocumentBookmarkName(value) ?? (documentBookmarkNameExists(editor, value) ? DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE : null),
|
|
11725
|
+
restoreFocusTarget: ()=>editor.view.dom
|
|
11726
|
+
});
|
|
11727
|
+
if (null === name || editor.isDestroyed) return;
|
|
11728
|
+
editor.chain().focus().insertDocumentBookmark(name.trim()).run();
|
|
11729
|
+
}, [
|
|
11730
|
+
activeBookmark,
|
|
11731
|
+
editor,
|
|
11732
|
+
prompt
|
|
11733
|
+
]);
|
|
12120
11734
|
useEffect(()=>{
|
|
12121
11735
|
setActiveTab((current)=>{
|
|
12122
11736
|
if (pageChromeEditor) return 'pageChrome';
|
|
@@ -12149,12 +11763,18 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12149
11763
|
const documentHistoryTarget = insideEditor || !isDocumentNativeTextUndoTarget(event.target);
|
|
12150
11764
|
if (documentHistoryTarget && 'z' === key) {
|
|
12151
11765
|
event.preventDefault();
|
|
11766
|
+
if (history) {
|
|
11767
|
+
if (event.shiftKey) history.redo();
|
|
11768
|
+
else history.undo();
|
|
11769
|
+
return;
|
|
11770
|
+
}
|
|
12152
11771
|
const command = event.shiftKey ? editor.chain().focus().redo() : editor.chain().focus().undo();
|
|
12153
11772
|
command.run();
|
|
12154
11773
|
return;
|
|
12155
11774
|
}
|
|
12156
11775
|
if (documentHistoryTarget && 'y' === key && !event.shiftKey) {
|
|
12157
11776
|
event.preventDefault();
|
|
11777
|
+
if (history) return void history.redo();
|
|
12158
11778
|
editor.chain().focus().redo().run();
|
|
12159
11779
|
return;
|
|
12160
11780
|
}
|
|
@@ -12205,6 +11825,7 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12205
11825
|
canInsertComment,
|
|
12206
11826
|
editor,
|
|
12207
11827
|
hasRefreshableFields,
|
|
11828
|
+
history,
|
|
12208
11829
|
onInsertComment,
|
|
12209
11830
|
onOpenFindReplace,
|
|
12210
11831
|
onOpenWordCount,
|
|
@@ -12267,8 +11888,9 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12267
11888
|
}),
|
|
12268
11889
|
shortcut: undoCommand.shortcut?.label,
|
|
12269
11890
|
ariaKeyShortcuts: undoCommand.shortcut?.aria,
|
|
12270
|
-
disabled: editor.isDestroyed || !editor.can().chain().undo().run(),
|
|
11891
|
+
disabled: editor.isDestroyed || (history ? !history.canUndo : !editor.can().chain().undo().run()),
|
|
12271
11892
|
onSelect: ()=>{
|
|
11893
|
+
if (history) return void history.undo();
|
|
12272
11894
|
editor.chain().focus().undo().run();
|
|
12273
11895
|
}
|
|
12274
11896
|
},
|
|
@@ -12280,12 +11902,14 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12280
11902
|
}),
|
|
12281
11903
|
shortcut: redoCommand.shortcut?.label,
|
|
12282
11904
|
ariaKeyShortcuts: redoCommand.shortcut?.aria,
|
|
12283
|
-
disabled: editor.isDestroyed || !editor.can().chain().redo().run(),
|
|
11905
|
+
disabled: editor.isDestroyed || (history ? !history.canRedo : !editor.can().chain().redo().run()),
|
|
12284
11906
|
onSelect: ()=>{
|
|
11907
|
+
if (history) return void history.redo();
|
|
12285
11908
|
editor.chain().focus().redo().run();
|
|
12286
11909
|
}
|
|
12287
11910
|
}
|
|
12288
11911
|
],
|
|
11912
|
+
defaultCollapsed: defaultRibbonCollapsed,
|
|
12289
11913
|
className: "work-document-ribbon",
|
|
12290
11914
|
toolbarClassName: "document-toolbar",
|
|
12291
11915
|
panels: {
|
|
@@ -12331,20 +11955,31 @@ function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts = [], navigat
|
|
|
12331
11955
|
})
|
|
12332
11956
|
})
|
|
12333
11957
|
}),
|
|
12334
|
-
/*#__PURE__*/
|
|
11958
|
+
/*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
|
|
12335
11959
|
label: "链接",
|
|
12336
11960
|
priority: "low",
|
|
12337
|
-
children:
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
11961
|
+
children: [
|
|
11962
|
+
/*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
|
|
11963
|
+
label: editor.isActive('link') ? '取消链接' : '添加链接',
|
|
11964
|
+
shortcut: "Cmd/Ctrl+K",
|
|
11965
|
+
ariaKeyShortcuts: "Control+K Meta+K",
|
|
11966
|
+
displayLabel: true,
|
|
11967
|
+
active: editor.isActive('link'),
|
|
11968
|
+
onClick: ()=>void toggleLink(),
|
|
11969
|
+
children: /*#__PURE__*/ jsx(Link2, {
|
|
11970
|
+
size: 19
|
|
11971
|
+
})
|
|
11972
|
+
}),
|
|
11973
|
+
/*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
|
|
11974
|
+
label: activeBookmark ? '删除书签' : '添加书签',
|
|
11975
|
+
displayLabel: true,
|
|
11976
|
+
active: Boolean(activeBookmark),
|
|
11977
|
+
onClick: ()=>void toggleBookmark(),
|
|
11978
|
+
children: /*#__PURE__*/ jsx(Bookmark, {
|
|
11979
|
+
size: 19
|
|
11980
|
+
})
|
|
12346
11981
|
})
|
|
12347
|
-
|
|
11982
|
+
]
|
|
12348
11983
|
}),
|
|
12349
11984
|
/*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
|
|
12350
11985
|
label: "页眉和页脚",
|
|
@@ -13070,7 +12705,7 @@ function useDocumentComments({ contentRef, editor, onBeforeDraft }) {
|
|
|
13070
12705
|
toggleResolved
|
|
13071
12706
|
};
|
|
13072
12707
|
}
|
|
13073
|
-
function useDocumentInsertCommands({ contentRef, editor }) {
|
|
12708
|
+
function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext }) {
|
|
13074
12709
|
const officeDialog = useOfficeDialog();
|
|
13075
12710
|
const [insertDialog, setInsertDialog] = useState(null);
|
|
13076
12711
|
const invokerRef = useRef(null);
|
|
@@ -13129,15 +12764,21 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13129
12764
|
]);
|
|
13130
12765
|
const insertCrossReference = useCallback(()=>{
|
|
13131
12766
|
if (!editor) return;
|
|
13132
|
-
const targets =
|
|
12767
|
+
const targets = [
|
|
12768
|
+
...editorDocumentCaptionTargets(editor).map((target)=>({
|
|
12769
|
+
...target,
|
|
12770
|
+
type: 'caption'
|
|
12771
|
+
})),
|
|
12772
|
+
...editorDocumentBookmarkReferenceTargets(editor)
|
|
12773
|
+
];
|
|
13133
12774
|
if (!targets.length) return void officeDialog.notice({
|
|
13134
|
-
title: '
|
|
13135
|
-
description: '
|
|
12775
|
+
title: '还没有可引用目标',
|
|
12776
|
+
description: '请先插入图片或表格题注,或在正文中添加书签。'
|
|
13136
12777
|
});
|
|
13137
12778
|
rememberInvoker();
|
|
13138
12779
|
setInsertDialog({
|
|
13139
12780
|
kind: 'crossReference',
|
|
13140
|
-
|
|
12781
|
+
selectedKey: targets[0] ? referenceTargetKey(targets[0]) : '',
|
|
13141
12782
|
targets
|
|
13142
12783
|
});
|
|
13143
12784
|
}, [
|
|
@@ -13148,14 +12789,21 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13148
12789
|
const insertField = useCallback((kind)=>{
|
|
13149
12790
|
if (!editor) return;
|
|
13150
12791
|
if (!editor.chain().focus().insertDocumentField(kind).run()) return;
|
|
13151
|
-
editor.commands.refreshDocumentFields(contentRef.current
|
|
12792
|
+
editor.commands.refreshDocumentFields(contentRef.current, {
|
|
12793
|
+
resolveContext: resolveFieldContext ?? void 0,
|
|
12794
|
+
addToHistory: false
|
|
12795
|
+
});
|
|
13152
12796
|
}, [
|
|
13153
12797
|
contentRef,
|
|
13154
|
-
editor
|
|
12798
|
+
editor,
|
|
12799
|
+
resolveFieldContext
|
|
13155
12800
|
]);
|
|
13156
|
-
const refreshFields = useCallback(()=>editor?.commands.refreshDocumentFields(contentRef.current
|
|
12801
|
+
const refreshFields = useCallback(()=>editor?.commands.refreshDocumentFields(contentRef.current, {
|
|
12802
|
+
resolveContext: resolveFieldContext ?? void 0
|
|
12803
|
+
}) ?? false, [
|
|
13157
12804
|
contentRef,
|
|
13158
|
-
editor
|
|
12805
|
+
editor,
|
|
12806
|
+
resolveFieldContext
|
|
13159
12807
|
]);
|
|
13160
12808
|
const submitCaption = ()=>{
|
|
13161
12809
|
if (!editor || insertDialog?.kind !== 'caption') return;
|
|
@@ -13166,7 +12814,7 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13166
12814
|
};
|
|
13167
12815
|
const submitCrossReference = ()=>{
|
|
13168
12816
|
if (!editor || insertDialog?.kind !== 'crossReference') return;
|
|
13169
|
-
const target = insertDialog.targets.find((candidate)=>candidate
|
|
12817
|
+
const target = insertDialog.targets.find((candidate)=>referenceTargetKey(candidate) === insertDialog.selectedKey);
|
|
13170
12818
|
if (!target) return;
|
|
13171
12819
|
const inserted = editor.chain().focus().insertDocumentCrossReference(target).run();
|
|
13172
12820
|
if (!inserted) return;
|
|
@@ -13187,11 +12835,12 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13187
12835
|
event.stopPropagation();
|
|
13188
12836
|
const target = insertDialog.targets[nextIndex];
|
|
13189
12837
|
if (!target) return;
|
|
12838
|
+
const targetKey = referenceTargetKey(target);
|
|
13190
12839
|
setInsertDialog({
|
|
13191
12840
|
...insertDialog,
|
|
13192
|
-
|
|
12841
|
+
selectedKey: targetKey
|
|
13193
12842
|
});
|
|
13194
|
-
requestAnimationFrame(()=>referenceInputRefs.current.get(
|
|
12843
|
+
requestAnimationFrame(()=>referenceInputRefs.current.get(targetKey)?.focus({
|
|
13195
12844
|
preventScroll: true
|
|
13196
12845
|
}));
|
|
13197
12846
|
};
|
|
@@ -13247,7 +12896,7 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13247
12896
|
}),
|
|
13248
12897
|
insertDialog?.kind === 'crossReference' && /*#__PURE__*/ jsx(Dialog, {
|
|
13249
12898
|
title: "插入交叉引用",
|
|
13250
|
-
description: "
|
|
12899
|
+
description: "选择正文中已有的图片、表格题注或书签。",
|
|
13251
12900
|
className: "work-document-reference-dialog",
|
|
13252
12901
|
restoreFocusTarget: ()=>invokerRef.current,
|
|
13253
12902
|
onClose: ()=>setInsertDialog(null),
|
|
@@ -13260,7 +12909,7 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13260
12909
|
}),
|
|
13261
12910
|
/*#__PURE__*/ jsx(button_Button, {
|
|
13262
12911
|
tone: "primary",
|
|
13263
|
-
disabled: !insertDialog.
|
|
12912
|
+
disabled: !insertDialog.selectedKey,
|
|
13264
12913
|
onClick: submitCrossReference,
|
|
13265
12914
|
children: "插入引用"
|
|
13266
12915
|
})
|
|
@@ -13269,35 +12918,38 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13269
12918
|
children: /*#__PURE__*/ jsx("div", {
|
|
13270
12919
|
className: "work-document-reference-list",
|
|
13271
12920
|
role: "radiogroup",
|
|
13272
|
-
"aria-label": "
|
|
13273
|
-
children: insertDialog.targets.map((target, index)
|
|
12921
|
+
"aria-label": "可引用目标",
|
|
12922
|
+
children: insertDialog.targets.map((target, index)=>{
|
|
12923
|
+
const targetKey = referenceTargetKey(target);
|
|
12924
|
+
return /*#__PURE__*/ jsxs("label", {
|
|
13274
12925
|
onDoubleClick: submitCrossReference,
|
|
13275
12926
|
children: [
|
|
13276
12927
|
/*#__PURE__*/ jsx("input", {
|
|
13277
12928
|
ref: (element)=>{
|
|
13278
|
-
if (element) referenceInputRefs.current.set(
|
|
13279
|
-
else referenceInputRefs.current.delete(
|
|
12929
|
+
if (element) referenceInputRefs.current.set(targetKey, element);
|
|
12930
|
+
else referenceInputRefs.current.delete(targetKey);
|
|
13280
12931
|
},
|
|
13281
12932
|
type: "radio",
|
|
13282
12933
|
name: "document-cross-reference",
|
|
13283
|
-
value:
|
|
13284
|
-
checked:
|
|
13285
|
-
"data-autofocus":
|
|
13286
|
-
tabIndex:
|
|
12934
|
+
value: targetKey,
|
|
12935
|
+
checked: targetKey === insertDialog.selectedKey,
|
|
12936
|
+
"data-autofocus": targetKey === insertDialog.selectedKey ? '' : void 0,
|
|
12937
|
+
tabIndex: targetKey === insertDialog.selectedKey ? 0 : -1,
|
|
13287
12938
|
onChange: ()=>setInsertDialog({
|
|
13288
12939
|
...insertDialog,
|
|
13289
|
-
|
|
12940
|
+
selectedKey: targetKey
|
|
13290
12941
|
}),
|
|
13291
12942
|
onKeyDown: (event)=>moveReferenceSelection(event, index)
|
|
13292
12943
|
}),
|
|
13293
12944
|
/*#__PURE__*/ jsx("strong", {
|
|
13294
|
-
children: target.display
|
|
12945
|
+
children: 'bookmark' === target.type ? `书签 ${target.name}` : target.display
|
|
13295
12946
|
}),
|
|
13296
12947
|
/*#__PURE__*/ jsx("span", {
|
|
13297
|
-
children: target.title || '(无题注文字)'
|
|
12948
|
+
children: target.title || ('bookmark' === target.type ? '(空书签)' : '(无题注文字)')
|
|
13298
12949
|
})
|
|
13299
12950
|
]
|
|
13300
|
-
},
|
|
12951
|
+
}, targetKey);
|
|
12952
|
+
})
|
|
13301
12953
|
})
|
|
13302
12954
|
})
|
|
13303
12955
|
]
|
|
@@ -13312,6 +12964,9 @@ function useDocumentInsertCommands({ contentRef, editor }) {
|
|
|
13312
12964
|
refreshFields
|
|
13313
12965
|
};
|
|
13314
12966
|
}
|
|
12967
|
+
function referenceTargetKey(target) {
|
|
12968
|
+
return `${target.type}:${target.id}`;
|
|
12969
|
+
}
|
|
13315
12970
|
const browserFontRegistrations = new Map();
|
|
13316
12971
|
function useDocumentLayoutFonts(fonts) {
|
|
13317
12972
|
const key = documentLayoutFontKey(fonts);
|
|
@@ -13533,13 +13188,13 @@ function planIncrementalDocumentLayout(previous, next, dirtyFrom) {
|
|
|
13533
13188
|
}
|
|
13534
13189
|
return fullLayout();
|
|
13535
13190
|
}
|
|
13536
|
-
function mergeIncrementalDocumentLayout(previous, partial
|
|
13191
|
+
function mergeIncrementalDocumentLayout(previous, partial) {
|
|
13537
13192
|
if (0 === partial.startPageIndex) return partial;
|
|
13538
13193
|
const startPageIndex = partial.startPageIndex;
|
|
13539
13194
|
const prefixPages = previous.pages.slice(0, startPageIndex);
|
|
13540
13195
|
if (prefixPages.length !== startPageIndex || partial.pages[0]?.index !== startPageIndex) throw new Error('Incremental document layout has an invalid page prefix.');
|
|
13541
13196
|
const prefixBreaks = previous.breaks.filter((pageBreak)=>pageBreak.pageIndex < startPageIndex);
|
|
13542
|
-
const boundaryBreak = incrementalBoundaryBreak(prefixPages.at(-1), partial.pages[0]
|
|
13197
|
+
const boundaryBreak = incrementalBoundaryBreak(prefixPages.at(-1), partial.pages[0]);
|
|
13543
13198
|
return {
|
|
13544
13199
|
...partial,
|
|
13545
13200
|
startPageIndex: 0,
|
|
@@ -13583,9 +13238,9 @@ function prefixMatches(pages, startPageIndex, previousBlockById, next, startBloc
|
|
|
13583
13238
|
});
|
|
13584
13239
|
}
|
|
13585
13240
|
function sameLayoutBlock(left, right) {
|
|
13586
|
-
return left.id === right.id && left.height === right.height && 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;
|
|
13241
|
+
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;
|
|
13587
13242
|
}
|
|
13588
|
-
function incrementalBoundaryBreak(previous, next
|
|
13243
|
+
function incrementalBoundaryBreak(previous, next) {
|
|
13589
13244
|
const beforeBlockId = next?.placements[0]?.blockId;
|
|
13590
13245
|
if (!previous || !next || !beforeBlockId) return null;
|
|
13591
13246
|
const remainingBodyHeight = Math.max(0, previous.availableHeight - previous.usedHeight);
|
|
@@ -13593,14 +13248,78 @@ function incrementalBoundaryBreak(previous, next, page) {
|
|
|
13593
13248
|
beforeBlockId,
|
|
13594
13249
|
pageIndex: next.index,
|
|
13595
13250
|
remainingBodyHeight,
|
|
13596
|
-
spacerHeight: remainingBodyHeight + page.marginBottom + page.pageGap + page.marginTop
|
|
13251
|
+
spacerHeight: remainingBodyHeight + previous.page.marginBottom + previous.page.pageGap + next.page.marginTop
|
|
13252
|
+
};
|
|
13253
|
+
}
|
|
13254
|
+
function createDocumentPaginationRunCoordinator({ cancelFrame, onAbort, onCoalescedRequest, onError, onRunFinish, onRunStart, requestFrame, run }) {
|
|
13255
|
+
let activeController = null;
|
|
13256
|
+
let disposed = false;
|
|
13257
|
+
let frame = 0;
|
|
13258
|
+
let rerunRequested = false;
|
|
13259
|
+
let running = false;
|
|
13260
|
+
const queue = ()=>{
|
|
13261
|
+
if (disposed || frame || running) return;
|
|
13262
|
+
frame = requestFrame(()=>{
|
|
13263
|
+
if (disposed) return;
|
|
13264
|
+
frame = requestFrame(()=>{
|
|
13265
|
+
frame = 0;
|
|
13266
|
+
if (!disposed) execute();
|
|
13267
|
+
});
|
|
13268
|
+
});
|
|
13269
|
+
};
|
|
13270
|
+
const execute = async ()=>{
|
|
13271
|
+
if (disposed || running) return;
|
|
13272
|
+
running = true;
|
|
13273
|
+
const controller = new AbortController();
|
|
13274
|
+
activeController = controller;
|
|
13275
|
+
onRunStart?.();
|
|
13276
|
+
try {
|
|
13277
|
+
await run(controller.signal);
|
|
13278
|
+
} catch (error) {
|
|
13279
|
+
if (!controller.signal.aborted) onError(error);
|
|
13280
|
+
} finally{
|
|
13281
|
+
if (activeController === controller) activeController = null;
|
|
13282
|
+
running = false;
|
|
13283
|
+
onRunFinish?.(controller.signal.aborted);
|
|
13284
|
+
if (!disposed && rerunRequested) {
|
|
13285
|
+
rerunRequested = false;
|
|
13286
|
+
queue();
|
|
13287
|
+
}
|
|
13288
|
+
}
|
|
13289
|
+
};
|
|
13290
|
+
const request = ({ invalidateActive = false } = {})=>{
|
|
13291
|
+
if (disposed) return;
|
|
13292
|
+
if (!running) return void queue();
|
|
13293
|
+
rerunRequested = true;
|
|
13294
|
+
onCoalescedRequest?.();
|
|
13295
|
+
if (invalidateActive && activeController && !activeController.signal.aborted) {
|
|
13296
|
+
onAbort?.('invalidation');
|
|
13297
|
+
activeController.abort();
|
|
13298
|
+
}
|
|
13299
|
+
};
|
|
13300
|
+
const dispose = ()=>{
|
|
13301
|
+
if (disposed) return;
|
|
13302
|
+
disposed = true;
|
|
13303
|
+
rerunRequested = false;
|
|
13304
|
+
if (frame) {
|
|
13305
|
+
cancelFrame(frame);
|
|
13306
|
+
frame = 0;
|
|
13307
|
+
}
|
|
13308
|
+
if (activeController && !activeController.signal.aborted) {
|
|
13309
|
+
onAbort?.('disposal');
|
|
13310
|
+
activeController.abort();
|
|
13311
|
+
}
|
|
13312
|
+
activeController = null;
|
|
13313
|
+
};
|
|
13314
|
+
return {
|
|
13315
|
+
dispose,
|
|
13316
|
+
request
|
|
13597
13317
|
};
|
|
13598
13318
|
}
|
|
13599
13319
|
function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, page, selectionVersion, wasmUrl, layoutFonts, loadedLayoutFontIds }) {
|
|
13600
13320
|
const client = useOfficeKernelClient(wasmUrl, layoutFonts);
|
|
13601
13321
|
const editorMounted = useEditorMounted(editor);
|
|
13602
13322
|
const revision = useRef(0);
|
|
13603
|
-
const activeRequest = useRef(null);
|
|
13604
13323
|
const measurementCache = useRef(null);
|
|
13605
13324
|
const paginationCache = useRef(null);
|
|
13606
13325
|
const measurementEditor = useRef(null);
|
|
@@ -13628,8 +13347,6 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13628
13347
|
}
|
|
13629
13348
|
if (!editor || !editorMounted || editor.isDestroyed || !enabled || !client) {
|
|
13630
13349
|
const nextRevision = ++revision.current;
|
|
13631
|
-
activeRequest.current?.abort();
|
|
13632
|
-
activeRequest.current = null;
|
|
13633
13350
|
if (editor && editorMounted && !editor.isDestroyed) {
|
|
13634
13351
|
const editorDom = editor.view.dom;
|
|
13635
13352
|
editor.commands.clearDocumentPagination(nextRevision);
|
|
@@ -13654,6 +13371,17 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13654
13371
|
delete editorDom.dataset.paginationTextEngine;
|
|
13655
13372
|
delete editorDom.dataset.paginationTextRuns;
|
|
13656
13373
|
delete editorDom.dataset.paginationUnsupportedText;
|
|
13374
|
+
delete editorDom.dataset.paginationAborts;
|
|
13375
|
+
delete editorDom.dataset.paginationActive;
|
|
13376
|
+
delete editorDom.dataset.paginationAssetTriggers;
|
|
13377
|
+
delete editorDom.dataset.paginationCoalescedRequests;
|
|
13378
|
+
delete editorDom.dataset.paginationDocumentTriggers;
|
|
13379
|
+
delete editorDom.dataset.paginationFontTriggers;
|
|
13380
|
+
delete editorDom.dataset.paginationResizeTriggers;
|
|
13381
|
+
delete editorDom.dataset.paginationRuns;
|
|
13382
|
+
delete editorDom.dataset.paginationTextBatch;
|
|
13383
|
+
delete editorDom.dataset.paginationTextBatches;
|
|
13384
|
+
delete editorDom.dataset.paginationViewportTriggers;
|
|
13657
13385
|
}
|
|
13658
13386
|
}
|
|
13659
13387
|
if (!enabled) {
|
|
@@ -13666,10 +13394,26 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13666
13394
|
}
|
|
13667
13395
|
const editorDom = editor.view.dom;
|
|
13668
13396
|
let disposed = false;
|
|
13669
|
-
let frame = 0;
|
|
13670
13397
|
let observedElements = [];
|
|
13671
13398
|
const observedHeights = new Map();
|
|
13399
|
+
let observedBlockPositions = new Map();
|
|
13400
|
+
let observingExternalLayout = false;
|
|
13401
|
+
const diagnosticCounts = {
|
|
13402
|
+
aborts: 0,
|
|
13403
|
+
assetTriggers: 0,
|
|
13404
|
+
coalescedRequests: 0,
|
|
13405
|
+
documentTriggers: 0,
|
|
13406
|
+
fontTriggers: 0,
|
|
13407
|
+
resizeTriggers: 0,
|
|
13408
|
+
runs: 0,
|
|
13409
|
+
viewportTriggers: 0
|
|
13410
|
+
};
|
|
13411
|
+
const updateDiagnostic = (name, datasetName)=>{
|
|
13412
|
+
diagnosticCounts[name] += 1;
|
|
13413
|
+
editorDom.dataset[datasetName] = String(diagnosticCounts[name]);
|
|
13414
|
+
};
|
|
13672
13415
|
const observer = "u" < typeof ResizeObserver ? null : new ResizeObserver((entries)=>{
|
|
13416
|
+
if (!observingExternalLayout) return;
|
|
13673
13417
|
let earliestChangedBlock = 1 / 0;
|
|
13674
13418
|
let changed = false;
|
|
13675
13419
|
for (const entry of entries){
|
|
@@ -13680,27 +13424,32 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13680
13424
|
const resized = void 0 !== previous && previous !== next;
|
|
13681
13425
|
changed ||= resized;
|
|
13682
13426
|
if (resized) {
|
|
13683
|
-
|
|
13427
|
+
const blockPosition = observedBlockPositions.get(element);
|
|
13428
|
+
if (void 0 !== blockPosition) earliestChangedBlock = Math.min(earliestChangedBlock, blockPosition);
|
|
13684
13429
|
}
|
|
13685
13430
|
}
|
|
13686
13431
|
if (changed) {
|
|
13432
|
+
updateDiagnostic('resizeTriggers', 'paginationResizeTriggers');
|
|
13687
13433
|
markDirty(Number.isFinite(earliestChangedBlock) ? earliestChangedBlock : 0);
|
|
13688
13434
|
schedule();
|
|
13689
13435
|
}
|
|
13690
13436
|
});
|
|
13691
|
-
const
|
|
13437
|
+
const stopObservingBlocks = ()=>{
|
|
13438
|
+
observingExternalLayout = false;
|
|
13692
13439
|
observer?.disconnect();
|
|
13693
|
-
|
|
13440
|
+
};
|
|
13441
|
+
const observeBlocks = (blocks)=>{
|
|
13442
|
+
stopObservingBlocks();
|
|
13443
|
+
observedBlockPositions = documentResizeObservationPositions(blocks);
|
|
13444
|
+
observedElements = Array.from(observedBlockPositions.keys());
|
|
13694
13445
|
observedHeights.clear();
|
|
13695
|
-
for (const element of observedElements)observer?.observe(element);
|
|
13696
13446
|
for (const element of observedElements)observedHeights.set(element, element.offsetHeight);
|
|
13447
|
+
observingExternalLayout = true;
|
|
13448
|
+
for (const element of observedElements)observer?.observe(element);
|
|
13697
13449
|
};
|
|
13698
|
-
const run = async ()=>{
|
|
13699
|
-
|
|
13450
|
+
const run = async (signal)=>{
|
|
13451
|
+
stopObservingBlocks();
|
|
13700
13452
|
const nextRevision = ++revision.current;
|
|
13701
|
-
activeRequest.current?.abort();
|
|
13702
|
-
const controller = new AbortController();
|
|
13703
|
-
activeRequest.current = controller;
|
|
13704
13453
|
editor.commands.clearDocumentPagination(nextRevision);
|
|
13705
13454
|
editorDom.dataset.paginationState = 'measuring';
|
|
13706
13455
|
editorDom.dataset.paginationReusedPageChrome = '0';
|
|
@@ -13716,36 +13465,44 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13716
13465
|
if (textLayoutCollection.paragraphs.length) {
|
|
13717
13466
|
editorDom.dataset.paginationState = 'shaping';
|
|
13718
13467
|
try {
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13468
|
+
let textLayoutEngine = '';
|
|
13469
|
+
let unsupportedTextLayoutCount = 0;
|
|
13470
|
+
const textLayoutBatches = documentTextLayoutBatches(textLayoutCollection.paragraphs);
|
|
13471
|
+
editorDom.dataset.paginationTextBatches = String(textLayoutBatches.length);
|
|
13472
|
+
for (const [batchIndex, paragraphs] of textLayoutBatches.entries()){
|
|
13473
|
+
editorDom.dataset.paginationTextBatch = String(batchIndex + 1);
|
|
13474
|
+
const textLayout = await client.textLayout({
|
|
13475
|
+
revision: nextRevision,
|
|
13476
|
+
documentRevision,
|
|
13477
|
+
paragraphs
|
|
13478
|
+
}, signal);
|
|
13479
|
+
if (disposed || signal.aborted || nextRevision !== revision.current || editor.isDestroyed) return;
|
|
13480
|
+
textLayoutEngine ||= textLayout.engine;
|
|
13481
|
+
unsupportedTextLayoutCount += textLayout.unsupportedParagraphIds.length + textLayout.layouts.filter((layout)=>layout.missingGlyphCount > 0).length;
|
|
13482
|
+
for (const layout of textLayout.layouts)if (0 === layout.missingGlyphCount) {
|
|
13483
|
+
textLayouts.set(layout.id, layout);
|
|
13484
|
+
fallbackGlyphCount += layout.fallbackGlyphCount;
|
|
13485
|
+
}
|
|
13728
13486
|
}
|
|
13729
|
-
editorDom.dataset.paginationTextEngine =
|
|
13730
|
-
editorDom.dataset.paginationUnsupportedText = String(
|
|
13487
|
+
editorDom.dataset.paginationTextEngine = textLayoutEngine;
|
|
13488
|
+
editorDom.dataset.paginationUnsupportedText = String(unsupportedTextLayoutCount);
|
|
13731
13489
|
} catch (error) {
|
|
13732
|
-
if (
|
|
13490
|
+
if (signal.aborted || error instanceof DOMException && 'AbortError' === error.name) return;
|
|
13491
|
+
textLayouts.clear();
|
|
13492
|
+
fallbackGlyphCount = 0;
|
|
13733
13493
|
editorDom.dataset.paginationTextEngine = 'dom';
|
|
13734
13494
|
editorDom.dataset.paginationUnsupportedText = String(textLayoutCollection.paragraphs.length);
|
|
13735
13495
|
}
|
|
13736
13496
|
} else {
|
|
13737
13497
|
editorDom.dataset.paginationTextEngine = 'dom';
|
|
13738
13498
|
editorDom.dataset.paginationUnsupportedText = '0';
|
|
13499
|
+
editorDom.dataset.paginationTextBatch = '0';
|
|
13500
|
+
editorDom.dataset.paginationTextBatches = '0';
|
|
13739
13501
|
}
|
|
13740
13502
|
editorDom.dataset.paginationShapedParagraphs = String(textLayouts.size);
|
|
13741
13503
|
editorDom.dataset.paginationFallbackGlyphs = String(fallbackGlyphCount);
|
|
13742
13504
|
editorDom.dataset.paginationShapedRuns = String(textLayoutCollection.paragraphs.reduce((count, paragraph)=>count + (textLayouts.has(paragraph.id) ? paragraph.runs.length : 0), 0));
|
|
13743
|
-
const
|
|
13744
|
-
...page,
|
|
13745
|
-
...documentPageChromeHeights(editor)
|
|
13746
|
-
};
|
|
13747
|
-
const availablePageHeight = documentPageBodyHeight(effectivePage);
|
|
13748
|
-
const snapshot = measureDocumentLayoutBlocks(editor, measurementCache.current, measurementStart, textLayouts, availablePageHeight);
|
|
13505
|
+
const snapshot = measureDocumentLayoutBlocks(editor, measurementCache.current, measurementStart, textLayouts);
|
|
13749
13506
|
measurementCache.current = snapshot;
|
|
13750
13507
|
editorDom.dataset.paginationBlocks = String(snapshot.blocks.length);
|
|
13751
13508
|
editorDom.dataset.paginationFlows = String(new Set(snapshot.blocks.flatMap((block)=>block.block.flowId ? [
|
|
@@ -13753,8 +13510,8 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13753
13510
|
] : [])).size);
|
|
13754
13511
|
editorDom.dataset.paginationMeasuredBlocks = String(snapshot.measuredBlockCount);
|
|
13755
13512
|
editorDom.dataset.paginationReusedBlocks = String(snapshot.reusedBlockCount);
|
|
13756
|
-
observeBlocks(snapshot.blocks);
|
|
13757
13513
|
if (snapshot.unsupportedLayout || !snapshot.blocks.length) {
|
|
13514
|
+
observeBlocks(snapshot.blocks);
|
|
13758
13515
|
editorDom.dataset.paginationState = snapshot.unsupportedLayout ? 'unsupported' : 'empty';
|
|
13759
13516
|
setPagination(null);
|
|
13760
13517
|
paginationCache.current = null;
|
|
@@ -13770,11 +13527,12 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13770
13527
|
revision: nextRevision,
|
|
13771
13528
|
documentRevision,
|
|
13772
13529
|
startPageIndex: layoutPlan.startPageIndex,
|
|
13773
|
-
page
|
|
13530
|
+
page,
|
|
13531
|
+
pageStyles: snapshot.pageStyles,
|
|
13774
13532
|
blocks: layoutPlan.blocks
|
|
13775
|
-
},
|
|
13776
|
-
if (disposed ||
|
|
13777
|
-
const layout = previousPagination && layoutPlan.startPageIndex > 0 ? mergeIncrementalDocumentLayout(previousPagination.layout, partialLayout
|
|
13533
|
+
}, signal);
|
|
13534
|
+
if (disposed || signal.aborted || nextRevision !== revision.current || editor.isDestroyed) return;
|
|
13535
|
+
const layout = previousPagination && layoutPlan.startPageIndex > 0 ? mergeIncrementalDocumentLayout(previousPagination.layout, partialLayout) : partialLayout;
|
|
13778
13536
|
const blockById = new Map(snapshot.blocks.map((block)=>[
|
|
13779
13537
|
block.block.id,
|
|
13780
13538
|
block
|
|
@@ -13792,7 +13550,8 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13792
13550
|
return block ? [
|
|
13793
13551
|
{
|
|
13794
13552
|
...pageBreak,
|
|
13795
|
-
|
|
13553
|
+
previousPage: pageByIndex.get(pageBreak.pageIndex - 1)?.page ?? layout.pages[pageBreak.pageIndex - 1]?.page ?? page,
|
|
13554
|
+
nextPage: pageByIndex.get(pageBreak.pageIndex)?.page ?? layout.pages[pageBreak.pageIndex]?.page ?? page,
|
|
13796
13555
|
position: block.from,
|
|
13797
13556
|
inlineOffsetLeft: block.inlineOffsetLeft,
|
|
13798
13557
|
inlineOffsetRight: block.inlineOffsetRight,
|
|
@@ -13802,6 +13561,7 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13802
13561
|
}
|
|
13803
13562
|
] : [];
|
|
13804
13563
|
}));
|
|
13564
|
+
observeBlocks(snapshot.blocks);
|
|
13805
13565
|
editorDom.dataset.paginationEngine = layout.engine;
|
|
13806
13566
|
editorDom.dataset.paginationDocumentRevision = String(layout.documentRevision);
|
|
13807
13567
|
editorDom.dataset.paginationPages = String(layout.pages.length);
|
|
@@ -13819,7 +13579,7 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13819
13579
|
paginationCache.current = nextPagination;
|
|
13820
13580
|
setPagination(nextPagination);
|
|
13821
13581
|
} catch (error) {
|
|
13822
|
-
if (disposed ||
|
|
13582
|
+
if (disposed || signal.aborted || error instanceof DOMException && 'AbortError' === error.name) return;
|
|
13823
13583
|
editorDom.dataset.paginationState = 'error';
|
|
13824
13584
|
editorDom.dataset.paginationError = error instanceof Error ? `${error.name}: ${error.message}` : 'UnknownError';
|
|
13825
13585
|
editor.commands.clearDocumentPagination(nextRevision);
|
|
@@ -13827,30 +13587,54 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13827
13587
|
setPagination(null);
|
|
13828
13588
|
}
|
|
13829
13589
|
};
|
|
13830
|
-
const
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13590
|
+
const coordinator = createDocumentPaginationRunCoordinator({
|
|
13591
|
+
cancelFrame: cancelAnimationFrame,
|
|
13592
|
+
onAbort: ()=>updateDiagnostic('aborts', 'paginationAborts'),
|
|
13593
|
+
onCoalescedRequest: ()=>updateDiagnostic('coalescedRequests', 'paginationCoalescedRequests'),
|
|
13594
|
+
onError: (error)=>{
|
|
13595
|
+
if (disposed || editor.isDestroyed) return;
|
|
13596
|
+
editorDom.dataset.paginationState = 'error';
|
|
13597
|
+
editorDom.dataset.paginationError = error instanceof Error ? `${error.name}: ${error.message}` : 'UnknownError';
|
|
13598
|
+
paginationCache.current = null;
|
|
13599
|
+
setPagination(null);
|
|
13600
|
+
},
|
|
13601
|
+
onRunFinish: ()=>{
|
|
13602
|
+
if (!disposed) editorDom.dataset.paginationActive = 'false';
|
|
13603
|
+
},
|
|
13604
|
+
onRunStart: ()=>{
|
|
13605
|
+
editorDom.dataset.paginationActive = 'true';
|
|
13606
|
+
updateDiagnostic('runs', 'paginationRuns');
|
|
13607
|
+
},
|
|
13608
|
+
requestFrame: requestAnimationFrame,
|
|
13609
|
+
run
|
|
13610
|
+
});
|
|
13611
|
+
const schedule = (invalidateActive = false)=>{
|
|
13612
|
+
coordinator.request({
|
|
13613
|
+
invalidateActive
|
|
13834
13614
|
});
|
|
13835
13615
|
};
|
|
13836
13616
|
const markDirty = (position)=>{
|
|
13837
13617
|
dirtyMeasurementFrom.current = Math.min(dirtyMeasurementFrom.current, Math.max(0, position));
|
|
13838
13618
|
};
|
|
13839
13619
|
const handleDocumentUpdate = ({ transaction })=>{
|
|
13620
|
+
updateDiagnostic('documentTriggers', 'paginationDocumentTriggers');
|
|
13840
13621
|
markDirty(earliestChangedPosition(transaction));
|
|
13841
|
-
schedule();
|
|
13622
|
+
schedule(true);
|
|
13842
13623
|
};
|
|
13843
13624
|
const handleLoadedAsset = (event)=>{
|
|
13625
|
+
updateDiagnostic('assetTriggers', 'paginationAssetTriggers');
|
|
13844
13626
|
const target = event.target;
|
|
13845
13627
|
const block = measurementCache.current?.blocks.find((candidate)=>target instanceof Node && (candidate.element === target || candidate.element.contains(target)));
|
|
13846
13628
|
markDirty(block?.from ?? 0);
|
|
13847
13629
|
schedule();
|
|
13848
13630
|
};
|
|
13849
13631
|
const handleFontLoading = ()=>{
|
|
13632
|
+
updateDiagnostic('fontTriggers', 'paginationFontTriggers');
|
|
13850
13633
|
markDirty(0);
|
|
13851
13634
|
schedule();
|
|
13852
13635
|
};
|
|
13853
13636
|
const handleWindowResize = ()=>{
|
|
13637
|
+
updateDiagnostic('viewportTriggers', 'paginationViewportTriggers');
|
|
13854
13638
|
markDirty(0);
|
|
13855
13639
|
schedule();
|
|
13856
13640
|
};
|
|
@@ -13862,14 +13646,12 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13862
13646
|
schedule();
|
|
13863
13647
|
return ()=>{
|
|
13864
13648
|
disposed = true;
|
|
13865
|
-
|
|
13866
|
-
observer?.disconnect();
|
|
13649
|
+
stopObservingBlocks();
|
|
13867
13650
|
editor.off('update', handleDocumentUpdate);
|
|
13868
13651
|
editorDom.removeEventListener('load', handleLoadedAsset, true);
|
|
13869
13652
|
fonts?.removeEventListener('loadingdone', handleFontLoading);
|
|
13870
13653
|
window.removeEventListener('resize', handleWindowResize);
|
|
13871
|
-
|
|
13872
|
-
activeRequest.current = null;
|
|
13654
|
+
coordinator.dispose();
|
|
13873
13655
|
};
|
|
13874
13656
|
}, [
|
|
13875
13657
|
client,
|
|
@@ -13884,6 +13666,9 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13884
13666
|
loadedLayoutFontIds,
|
|
13885
13667
|
pageKey
|
|
13886
13668
|
]);
|
|
13669
|
+
const resolveFieldContext = useMemo(()=>pagination ? createDocumentFieldPaginationContextResolver(pagination) : null, [
|
|
13670
|
+
pagination
|
|
13671
|
+
]);
|
|
13887
13672
|
return useMemo(()=>{
|
|
13888
13673
|
const currentPage = pagination ? pageForPosition(pagination, editor?.state.selection.from ?? 0) : null;
|
|
13889
13674
|
return {
|
|
@@ -13891,15 +13676,54 @@ function useDocumentPagination({ editor, documentRevision, enabled, layoutKey, p
|
|
|
13891
13676
|
currentPageDescriptor: null === currentPage ? null : pagination?.pages.find((page)=>page.physicalPage === currentPage) ?? null,
|
|
13892
13677
|
pageCount: pagination ? Math.max(1, pagination.layout.pages.length) : null,
|
|
13893
13678
|
pages: pagination?.pages ?? [],
|
|
13894
|
-
paginating: enabled && null === pagination
|
|
13679
|
+
paginating: enabled && null === pagination,
|
|
13680
|
+
resolveFieldContext
|
|
13895
13681
|
};
|
|
13896
13682
|
}, [
|
|
13897
13683
|
editor,
|
|
13898
13684
|
enabled,
|
|
13899
13685
|
pagination,
|
|
13686
|
+
resolveFieldContext,
|
|
13900
13687
|
selectionVersion
|
|
13901
13688
|
]);
|
|
13902
13689
|
}
|
|
13690
|
+
function createDocumentFieldPaginationContextResolver(pagination) {
|
|
13691
|
+
const pagesByPhysicalNumber = new Map(pagination.pages.map((page)=>[
|
|
13692
|
+
page.physicalPage,
|
|
13693
|
+
page
|
|
13694
|
+
]));
|
|
13695
|
+
const sectionPhysicalPages = new Map();
|
|
13696
|
+
for (const block of pagination.blocks){
|
|
13697
|
+
const sectionId = block.section?.id;
|
|
13698
|
+
const physicalPage = pagination.pageByBlockId.get(block.block.id);
|
|
13699
|
+
if (!sectionId || !physicalPage) continue;
|
|
13700
|
+
const pages = sectionPhysicalPages.get(sectionId) ?? new Set();
|
|
13701
|
+
pages.add(physicalPage);
|
|
13702
|
+
sectionPhysicalPages.set(sectionId, pages);
|
|
13703
|
+
}
|
|
13704
|
+
return (position)=>{
|
|
13705
|
+
const block = blockForPosition(pagination.blocks, position);
|
|
13706
|
+
const section = block?.section;
|
|
13707
|
+
const physicalPage = block ? pagination.pageByBlockId.get(block.block.id) : void 0;
|
|
13708
|
+
const page = physicalPage ? pagesByPhysicalNumber.get(physicalPage) : void 0;
|
|
13709
|
+
if (!section || !page) return null;
|
|
13710
|
+
return {
|
|
13711
|
+
pageNumber: page.pageNumber,
|
|
13712
|
+
totalPages: Math.max(1, pagination.layout.pages.length),
|
|
13713
|
+
sectionNumber: section.index + 1,
|
|
13714
|
+
sectionPages: Math.max(1, sectionPhysicalPages.get(section.id)?.size ?? 0)
|
|
13715
|
+
};
|
|
13716
|
+
};
|
|
13717
|
+
}
|
|
13718
|
+
function documentResizeObservationPositions(blocks) {
|
|
13719
|
+
const positions = new Map();
|
|
13720
|
+
for (const block of blocks){
|
|
13721
|
+
if (!block.observeResize) continue;
|
|
13722
|
+
const previous = positions.get(block.element);
|
|
13723
|
+
positions.set(block.element, void 0 === previous ? block.from : Math.min(previous, block.from));
|
|
13724
|
+
}
|
|
13725
|
+
return positions;
|
|
13726
|
+
}
|
|
13903
13727
|
function deriveDocumentPaginationPageDescriptors(layout, blocks, documentNode, previousPages = [], requestedReusedPageCount = 0) {
|
|
13904
13728
|
const blockById = new Map(blocks.map((candidate)=>[
|
|
13905
13729
|
candidate.block.id,
|
|
@@ -13942,7 +13766,7 @@ function deriveDocumentPaginationPageDescriptors(layout, blocks, documentNode, p
|
|
|
13942
13766
|
const firstSectionPage = 1 === sectionPage;
|
|
13943
13767
|
const pageNumber = firstSectionPage && void 0 !== section.layout.pageNumberStart ? section.layout.pageNumberStart : Math.max(1, previousPageNumber + 1);
|
|
13944
13768
|
const previousPage = previousPageByIndex.get(page.index);
|
|
13945
|
-
if (reuseOpen && page.index < reusablePhysicalPageCount && previousPage && reusableDocumentPageDescriptor(previousPage, physicalPage, pageNumber, sectionPage, section.id, section.index, section.layout)) {
|
|
13769
|
+
if (reuseOpen && page.index < reusablePhysicalPageCount && previousPage && reusableDocumentPageDescriptor(previousPage, physicalPage, pageNumber, sectionPage, section.id, section.index, section.layout, page.page)) {
|
|
13946
13770
|
descriptors.push(previousPage);
|
|
13947
13771
|
reusedPageCount += 1;
|
|
13948
13772
|
continue;
|
|
@@ -13958,7 +13782,8 @@ function deriveDocumentPaginationPageDescriptors(layout, blocks, documentNode, p
|
|
|
13958
13782
|
sectionId: section.id,
|
|
13959
13783
|
sectionIndex: section.index,
|
|
13960
13784
|
layout: section.layout,
|
|
13961
|
-
pageChrome: resolveDocumentPageChrome(section.layout, sectionPage, physicalPage)
|
|
13785
|
+
pageChrome: resolveDocumentPageChrome(section.layout, sectionPage, physicalPage),
|
|
13786
|
+
page: documentPageMetrics(section.layout, physicalPage)
|
|
13962
13787
|
});
|
|
13963
13788
|
}
|
|
13964
13789
|
return {
|
|
@@ -13967,8 +13792,8 @@ function deriveDocumentPaginationPageDescriptors(layout, blocks, documentNode, p
|
|
|
13967
13792
|
derivedPageCount: descriptors.length - reusedPageCount
|
|
13968
13793
|
};
|
|
13969
13794
|
}
|
|
13970
|
-
function reusableDocumentPageDescriptor(candidate, physicalPage, pageNumber, sectionPage, sectionId, sectionIndex, layout) {
|
|
13971
|
-
return candidate.pageIndex === physicalPage - 1 && candidate.physicalPage === physicalPage && candidate.pageNumber === pageNumber && candidate.sectionPage === sectionPage && candidate.sectionId === sectionId && candidate.sectionIndex === sectionIndex && JSON.stringify(candidate.layout) === JSON.stringify(layout);
|
|
13795
|
+
function reusableDocumentPageDescriptor(candidate, physicalPage, pageNumber, sectionPage, sectionId, sectionIndex, layout, page) {
|
|
13796
|
+
return candidate.pageIndex === physicalPage - 1 && candidate.physicalPage === physicalPage && candidate.pageNumber === pageNumber && candidate.sectionPage === sectionPage && candidate.sectionId === sectionId && candidate.sectionIndex === sectionIndex && pageMetricsKey(candidate.page) === pageMetricsKey(page) && JSON.stringify(candidate.layout) === JSON.stringify(layout);
|
|
13972
13797
|
}
|
|
13973
13798
|
function documentPagePreviewText(blocks, documentNode) {
|
|
13974
13799
|
const measuredText = documentNode ? documentPageTextRanges(blocks).reduce((preview, range)=>{
|
|
@@ -14043,20 +13868,24 @@ function useOfficeKernelClient(wasmUrl, fonts) {
|
|
|
14043
13868
|
return client;
|
|
14044
13869
|
}
|
|
14045
13870
|
function pageForPosition(pagination, position) {
|
|
14046
|
-
const
|
|
14047
|
-
|
|
13871
|
+
const block = blockForPosition(pagination.blocks, position);
|
|
13872
|
+
return block ? pagination.pageByBlockId.get(block.block.id) ?? 1 : 1;
|
|
13873
|
+
}
|
|
13874
|
+
function blockForPosition(blocks, position) {
|
|
13875
|
+
const rangedBlock = blocks.find((block)=>block.selectionRanges?.some((range)=>range.from <= position && position < range.to));
|
|
13876
|
+
if (rangedBlock) return rangedBlock;
|
|
14048
13877
|
let lower = 0;
|
|
14049
|
-
let upper =
|
|
14050
|
-
let containing =
|
|
13878
|
+
let upper = blocks.length - 1;
|
|
13879
|
+
let containing = blocks[0];
|
|
14051
13880
|
while(lower <= upper){
|
|
14052
13881
|
const middle = Math.floor((lower + upper) / 2);
|
|
14053
|
-
const candidate =
|
|
13882
|
+
const candidate = blocks[middle];
|
|
14054
13883
|
if (candidate.from <= position) {
|
|
14055
13884
|
containing = candidate;
|
|
14056
13885
|
lower = middle + 1;
|
|
14057
13886
|
} else upper = middle - 1;
|
|
14058
13887
|
}
|
|
14059
|
-
return containing
|
|
13888
|
+
return containing;
|
|
14060
13889
|
}
|
|
14061
13890
|
function pageMetricsKey(page) {
|
|
14062
13891
|
return [
|
|
@@ -14078,6 +13907,204 @@ function earliestChangedPosition(transaction) {
|
|
|
14078
13907
|
});
|
|
14079
13908
|
return Number.isFinite(earliest) ? earliest : 0;
|
|
14080
13909
|
}
|
|
13910
|
+
function collectDocumentReviewSnapshot(document1) {
|
|
13911
|
+
return {
|
|
13912
|
+
comments: collectDocumentCommentAnchors(document1),
|
|
13913
|
+
changes: collectDocumentChanges(document1)
|
|
13914
|
+
};
|
|
13915
|
+
}
|
|
13916
|
+
function reconcileDocumentReviewConflicts({ active, before, after, comments }) {
|
|
13917
|
+
const commentIds = new Set(comments.map((comment)=>comment.id.trim()).filter(Boolean));
|
|
13918
|
+
const afterComments = new Map(after.comments.map((comment)=>[
|
|
13919
|
+
comment.id,
|
|
13920
|
+
comment
|
|
13921
|
+
]));
|
|
13922
|
+
const afterChanges = new Map(after.changes.map((change)=>[
|
|
13923
|
+
work_document_review_conflicts_changeKey(change),
|
|
13924
|
+
change
|
|
13925
|
+
]));
|
|
13926
|
+
const surviving = active.filter((conflict)=>conflictStillApplies(conflict, commentIds, afterComments, afterChanges));
|
|
13927
|
+
const detected = detectDocumentReviewConflicts(before, after, commentIds, afterComments, afterChanges);
|
|
13928
|
+
const activeKeys = new Set(active.map(documentReviewConflictKey));
|
|
13929
|
+
const newlyDetected = detected.filter((conflict)=>!activeKeys.has(documentReviewConflictKey(conflict)));
|
|
13930
|
+
const byKey = new Map(surviving.map((conflict)=>[
|
|
13931
|
+
documentReviewConflictKey(conflict),
|
|
13932
|
+
conflict
|
|
13933
|
+
]));
|
|
13934
|
+
for (const conflict of detected){
|
|
13935
|
+
const key = documentReviewConflictKey(conflict);
|
|
13936
|
+
if (!activeKeys.has(key)) byKey.set(key, conflict);
|
|
13937
|
+
}
|
|
13938
|
+
return {
|
|
13939
|
+
active: Array.from(byKey.values()),
|
|
13940
|
+
detected: newlyDetected
|
|
13941
|
+
};
|
|
13942
|
+
}
|
|
13943
|
+
function detectDocumentReviewConflicts(before, after, commentIds, afterComments, afterChanges) {
|
|
13944
|
+
const conflicts = [];
|
|
13945
|
+
for (const previous of before.comments){
|
|
13946
|
+
const next = afterComments.get(previous.id);
|
|
13947
|
+
if (!commentIds.has(previous.id)) {
|
|
13948
|
+
if (next) conflicts.push({
|
|
13949
|
+
id: previous.id,
|
|
13950
|
+
kind: 'comment',
|
|
13951
|
+
reason: 'record-removed',
|
|
13952
|
+
previousText: previous.anchorText,
|
|
13953
|
+
nextText: next.anchorText
|
|
13954
|
+
});
|
|
13955
|
+
continue;
|
|
13956
|
+
}
|
|
13957
|
+
if (next) {
|
|
13958
|
+
if (next.anchorText !== previous.anchorText) conflicts.push({
|
|
13959
|
+
id: previous.id,
|
|
13960
|
+
kind: 'comment',
|
|
13961
|
+
reason: 'text-changed',
|
|
13962
|
+
previousText: previous.anchorText,
|
|
13963
|
+
nextText: next.anchorText
|
|
13964
|
+
});
|
|
13965
|
+
} else conflicts.push({
|
|
13966
|
+
id: previous.id,
|
|
13967
|
+
kind: 'comment',
|
|
13968
|
+
reason: 'removed',
|
|
13969
|
+
previousText: previous.anchorText
|
|
13970
|
+
});
|
|
13971
|
+
}
|
|
13972
|
+
const afterChangesById = new Map();
|
|
13973
|
+
for (const change of after.changes){
|
|
13974
|
+
const candidates = afterChangesById.get(change.id) ?? [];
|
|
13975
|
+
candidates.push(change);
|
|
13976
|
+
afterChangesById.set(change.id, candidates);
|
|
13977
|
+
}
|
|
13978
|
+
for (const previous of before.changes){
|
|
13979
|
+
const next = afterChanges.get(work_document_review_conflicts_changeKey(previous));
|
|
13980
|
+
if (next) {
|
|
13981
|
+
if (next.text !== previous.text) conflicts.push({
|
|
13982
|
+
id: previous.id,
|
|
13983
|
+
kind: previous.kind,
|
|
13984
|
+
reason: 'text-changed',
|
|
13985
|
+
previousText: previous.text,
|
|
13986
|
+
nextText: next.text
|
|
13987
|
+
});
|
|
13988
|
+
continue;
|
|
13989
|
+
}
|
|
13990
|
+
const changedKind = afterChangesById.get(previous.id)?.[0];
|
|
13991
|
+
conflicts.push(changedKind ? {
|
|
13992
|
+
id: previous.id,
|
|
13993
|
+
kind: previous.kind,
|
|
13994
|
+
reason: 'kind-changed',
|
|
13995
|
+
previousText: previous.text,
|
|
13996
|
+
nextKind: changedKind.kind,
|
|
13997
|
+
nextText: changedKind.text
|
|
13998
|
+
} : {
|
|
13999
|
+
id: previous.id,
|
|
14000
|
+
kind: previous.kind,
|
|
14001
|
+
reason: 'removed',
|
|
14002
|
+
previousText: previous.text
|
|
14003
|
+
});
|
|
14004
|
+
}
|
|
14005
|
+
return conflicts;
|
|
14006
|
+
}
|
|
14007
|
+
function conflictStillApplies(conflict, commentIds, comments, changes) {
|
|
14008
|
+
if ('comment' === conflict.kind) {
|
|
14009
|
+
if (!commentIds.has(conflict.id)) return comments.has(conflict.id);
|
|
14010
|
+
return comments.get(conflict.id)?.anchorText !== conflict.previousText;
|
|
14011
|
+
}
|
|
14012
|
+
return changes.get(`${conflict.kind}:${conflict.id}`)?.text !== conflict.previousText;
|
|
14013
|
+
}
|
|
14014
|
+
function work_document_review_conflicts_changeKey(change) {
|
|
14015
|
+
return `${change.kind}:${change.id}`;
|
|
14016
|
+
}
|
|
14017
|
+
function documentReviewConflictKey(conflict) {
|
|
14018
|
+
return 'comment' === conflict.kind ? `comment:${conflict.id}` : `change:${conflict.id}`;
|
|
14019
|
+
}
|
|
14020
|
+
function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, artifactId, content, editor, editorInput, normalizedContent, onReviewConflict, publishedDocumentRef, reconcileControlledUpdates = true }) {
|
|
14021
|
+
const appliedArtifactIdRef = useRef(artifactId);
|
|
14022
|
+
const onReviewConflictRef = useRef(onReviewConflict);
|
|
14023
|
+
const [visibleConflicts, setVisibleConflicts] = useState([]);
|
|
14024
|
+
onReviewConflictRef.current = onReviewConflict;
|
|
14025
|
+
useEffect(()=>{
|
|
14026
|
+
if (!editor || !reconcileControlledUpdates) return;
|
|
14027
|
+
const artifactChanged = appliedArtifactIdRef.current !== artifactId;
|
|
14028
|
+
const sourceChanged = appliedSourceKeyRef.current !== editorInput.sourceKey;
|
|
14029
|
+
appliedArtifactIdRef.current = artifactId;
|
|
14030
|
+
if (artifactChanged) {
|
|
14031
|
+
activeConflictsRef.current = [];
|
|
14032
|
+
setVisibleConflicts([]);
|
|
14033
|
+
}
|
|
14034
|
+
const before = collectDocumentReviewSnapshot(editor.state.doc);
|
|
14035
|
+
if (sourceChanged) {
|
|
14036
|
+
const currentContent = normalizeDocumentHtml({
|
|
14037
|
+
...content,
|
|
14038
|
+
html: editor.getHTML()
|
|
14039
|
+
});
|
|
14040
|
+
const canReuseCurrentDocument = 'string' == typeof editorInput.source && currentContent === normalizedContent;
|
|
14041
|
+
appliedSourceKeyRef.current = editorInput.sourceKey;
|
|
14042
|
+
if (!canReuseCurrentDocument) {
|
|
14043
|
+
const result = applyExternalDocumentContent(editor, editorInput.source);
|
|
14044
|
+
if ('unsupported' === result) editor.chain().setMeta('addToHistory', false).setContent(editorInput.source, {
|
|
14045
|
+
emitUpdate: false
|
|
14046
|
+
}).run();
|
|
14047
|
+
}
|
|
14048
|
+
publishedDocumentRef.current = editor.state.doc;
|
|
14049
|
+
}
|
|
14050
|
+
if (artifactChanged || !sourceChanged && 0 === activeConflictsRef.current.length) return;
|
|
14051
|
+
const reconciled = reconcileDocumentReviewConflicts({
|
|
14052
|
+
active: activeConflictsRef.current,
|
|
14053
|
+
before,
|
|
14054
|
+
after: collectDocumentReviewSnapshot(editor.state.doc),
|
|
14055
|
+
comments: content.comments ?? []
|
|
14056
|
+
});
|
|
14057
|
+
activeConflictsRef.current = reconciled.active;
|
|
14058
|
+
setVisibleConflicts((visible)=>{
|
|
14059
|
+
if (reconciled.detected.length) return reconciled.active;
|
|
14060
|
+
const visibleKeys = new Set(visible.map(documentReviewConflictKey));
|
|
14061
|
+
return reconciled.active.filter((conflict)=>visibleKeys.has(documentReviewConflictKey(conflict)));
|
|
14062
|
+
});
|
|
14063
|
+
if (reconciled.detected.length) onReviewConflictRef.current?.({
|
|
14064
|
+
artifactId,
|
|
14065
|
+
conflicts: reconciled.detected.map((conflict)=>({
|
|
14066
|
+
...conflict
|
|
14067
|
+
}))
|
|
14068
|
+
});
|
|
14069
|
+
}, [
|
|
14070
|
+
activeConflictsRef,
|
|
14071
|
+
appliedSourceKeyRef,
|
|
14072
|
+
artifactId,
|
|
14073
|
+
content,
|
|
14074
|
+
editor,
|
|
14075
|
+
editorInput,
|
|
14076
|
+
normalizedContent,
|
|
14077
|
+
publishedDocumentRef,
|
|
14078
|
+
reconcileControlledUpdates
|
|
14079
|
+
]);
|
|
14080
|
+
return {
|
|
14081
|
+
dismiss: ()=>setVisibleConflicts([]),
|
|
14082
|
+
visibleConflicts
|
|
14083
|
+
};
|
|
14084
|
+
}
|
|
14085
|
+
function DocumentReviewConflictNotice({ conflicts, onDismiss }) {
|
|
14086
|
+
if (!conflicts.length) return null;
|
|
14087
|
+
return /*#__PURE__*/ jsxs(InlineNotice, {
|
|
14088
|
+
className: "work-document-review-conflict",
|
|
14089
|
+
icon: /*#__PURE__*/ jsx(TriangleAlert, {}),
|
|
14090
|
+
role: "alert",
|
|
14091
|
+
title: "审阅内容与外部更新冲突",
|
|
14092
|
+
tone: "warning",
|
|
14093
|
+
actions: /*#__PURE__*/ jsx(button_Button, {
|
|
14094
|
+
"aria-label": "关闭审阅冲突提示",
|
|
14095
|
+
size: "compact",
|
|
14096
|
+
tone: "quiet",
|
|
14097
|
+
onClick: onDismiss,
|
|
14098
|
+
children: "关闭"
|
|
14099
|
+
}),
|
|
14100
|
+
children: [
|
|
14101
|
+
"外部版本已应用,其中 ",
|
|
14102
|
+
conflicts.length,
|
|
14103
|
+
' ',
|
|
14104
|
+
"个批注或修订范围发生变化。请检查后再继续审阅。"
|
|
14105
|
+
]
|
|
14106
|
+
});
|
|
14107
|
+
}
|
|
14081
14108
|
const EMPTY_DOCUMENT_LAYOUT_FONTS = [];
|
|
14082
14109
|
const EMPTY_DOCUMENT_EXTENSIONS = [];
|
|
14083
14110
|
function createTrackedDocumentChange(_kind) {
|
|
@@ -14087,29 +14114,100 @@ function createTrackedDocumentChange(_kind) {
|
|
|
14087
14114
|
date: new Date().toISOString()
|
|
14088
14115
|
};
|
|
14089
14116
|
}
|
|
14090
|
-
function DocumentEditor(
|
|
14117
|
+
function DocumentEditor(props) {
|
|
14118
|
+
if (!props.collaboration) return /*#__PURE__*/ jsx(DocumentEditorSurface, {
|
|
14119
|
+
...props
|
|
14120
|
+
});
|
|
14121
|
+
return /*#__PURE__*/ jsx(CollaborativeDocumentEditor, {
|
|
14122
|
+
...props,
|
|
14123
|
+
collaboration: props.collaboration
|
|
14124
|
+
});
|
|
14125
|
+
}
|
|
14126
|
+
function CollaborativeDocumentEditor(props) {
|
|
14127
|
+
const { collaboration, extensions = EMPTY_DOCUMENT_EXTENSIONS } = props;
|
|
14128
|
+
const collaborationRef = useRef(collaboration);
|
|
14129
|
+
const extensionsRef = useRef(extensions);
|
|
14130
|
+
if (collaborationRef.current !== collaboration) throw new Error('DocumentEditor collaboration sessions cannot be replaced while mounted. Remount the editor for another shared document.');
|
|
14131
|
+
if (extensionsRef.current !== extensions) throw new Error('DocumentEditor extensions cannot be replaced while a collaboration session is mounted. Remount the editor to change its schema.');
|
|
14132
|
+
const initial = useRef(null);
|
|
14133
|
+
if (!initial.current) initial.current = readWorkOfficeDocumentCollaboration(collaboration);
|
|
14134
|
+
const bridge = useRef({
|
|
14135
|
+
getContent: ()=>initial.current,
|
|
14136
|
+
isTracking: ()=>Boolean(initial.current?.trackChanges),
|
|
14137
|
+
onContentChange: ()=>void 0,
|
|
14138
|
+
onTrackingChange: ()=>void 0
|
|
14139
|
+
});
|
|
14140
|
+
const [binding, setBinding] = useState();
|
|
14141
|
+
const bindingRef = useRef(void 0);
|
|
14142
|
+
const disposeTokenRef = useRef(void 0);
|
|
14143
|
+
useEffect(()=>{
|
|
14144
|
+
disposeTokenRef.current = void 0;
|
|
14145
|
+
const current = bindingRef.current ?? createWorkOfficeDocumentCollaborationBinding(collaboration, {
|
|
14146
|
+
additionalExtensions: extensionsRef.current,
|
|
14147
|
+
workExtensions: {
|
|
14148
|
+
getContent: ()=>bridge.current.getContent(),
|
|
14149
|
+
isTracking: ()=>bridge.current.isTracking(),
|
|
14150
|
+
createChange: createTrackedDocumentChange,
|
|
14151
|
+
onContentChange: (content)=>bridge.current.onContentChange(content),
|
|
14152
|
+
onTrackingChange: (enabled)=>bridge.current.onTrackingChange(enabled)
|
|
14153
|
+
}
|
|
14154
|
+
});
|
|
14155
|
+
bindingRef.current = current;
|
|
14156
|
+
setBinding(current);
|
|
14157
|
+
return ()=>{
|
|
14158
|
+
const token = {};
|
|
14159
|
+
disposeTokenRef.current = token;
|
|
14160
|
+
queueMicrotask(()=>{
|
|
14161
|
+
if (disposeTokenRef.current !== token) return;
|
|
14162
|
+
if (bindingRef.current === current) bindingRef.current = void 0;
|
|
14163
|
+
current.destroy();
|
|
14164
|
+
});
|
|
14165
|
+
};
|
|
14166
|
+
}, [
|
|
14167
|
+
collaboration
|
|
14168
|
+
]);
|
|
14169
|
+
if (!binding) return /*#__PURE__*/ jsx(WorkEditorLoadingState, {
|
|
14170
|
+
title: "正在准备协作文档"
|
|
14171
|
+
});
|
|
14172
|
+
return /*#__PURE__*/ jsx(DocumentEditorSurface, {
|
|
14173
|
+
...props,
|
|
14174
|
+
collaborationBinding: binding,
|
|
14175
|
+
collaborationBridge: bridge,
|
|
14176
|
+
collaborationInitialContent: initial.current
|
|
14177
|
+
});
|
|
14178
|
+
}
|
|
14179
|
+
function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, collaborationBinding, collaborationBridge, collaborationInitialContent, content, extensions = EMPTY_DOCUMENT_EXTENSIONS, preview: requestedPreview, defaultRibbonCollapsed = false, saveStatus = '已自动保存', kernelWasmUrl, layoutFonts = EMPTY_DOCUMENT_LAYOUT_FONTS, fileActions, getSelectionMenuItems, onChange, onAgentRequest, onReviewConflict }) {
|
|
14180
|
+
const collaborationEditable = !collaboration || 'edit' === collaboration.mode;
|
|
14181
|
+
const preview = requestedPreview || !collaborationEditable;
|
|
14182
|
+
const readOnly = preview;
|
|
14183
|
+
const initialContentRef = useRef(collaborationInitialContent ?? content);
|
|
14184
|
+
const effectiveContent = collaboration ? initialContentRef.current : content;
|
|
14091
14185
|
const imageInputRef = useRef(null);
|
|
14092
14186
|
const pageHeaderRef = useRef(null);
|
|
14093
14187
|
const pageFooterRef = useRef(null);
|
|
14094
14188
|
const workspaceRef = useRef(null);
|
|
14095
14189
|
const reviewSurfaceRef = useRef(null);
|
|
14096
14190
|
const pageSurfaceRef = useRef(null);
|
|
14191
|
+
const editableSurfaceRef = useRef(null);
|
|
14097
14192
|
const taskPaneInvokerRef = useRef(null);
|
|
14098
14193
|
const commentsDraftFocusRef = useRef(null);
|
|
14099
14194
|
const citationsDraftFocusRef = useRef(null);
|
|
14100
14195
|
const statisticsInvokerRef = useRef(null);
|
|
14101
|
-
const contentRef = useRef(
|
|
14196
|
+
const contentRef = useRef(effectiveContent);
|
|
14102
14197
|
const onChangeRef = useRef(onChange);
|
|
14103
|
-
const trackChangesRef = useRef(Boolean(
|
|
14104
|
-
const
|
|
14105
|
-
|
|
14198
|
+
const trackChangesRef = useRef(Boolean(effectiveContent.trackChanges));
|
|
14199
|
+
const collaborationBindingRef = useRef(collaborationBinding);
|
|
14200
|
+
const normalizedContent = useMemo(()=>normalizeDocumentHtml(effectiveContent), [
|
|
14201
|
+
effectiveContent
|
|
14106
14202
|
]);
|
|
14107
|
-
const editorInput = useMemo(()=>resolveWorkDocumentEditorInput(
|
|
14108
|
-
|
|
14203
|
+
const editorInput = useMemo(()=>resolveWorkDocumentEditorInput(effectiveContent, normalizedContent), [
|
|
14204
|
+
effectiveContent,
|
|
14109
14205
|
normalizedContent
|
|
14110
14206
|
]);
|
|
14111
|
-
const
|
|
14207
|
+
const initialEditorSourceRef = useRef(editorInput.source);
|
|
14112
14208
|
const appliedSourceKeyRef = useRef(editorInput.sourceKey);
|
|
14209
|
+
const activeReviewConflictsRef = useRef([]);
|
|
14210
|
+
const publishedDocumentRef = useRef(null);
|
|
14113
14211
|
const [taskPane, setTaskPane] = useState(null);
|
|
14114
14212
|
const [layoutPanelTab, setLayoutPanelTab] = useState('page');
|
|
14115
14213
|
const [findReplaceFocusRequest, setFindReplaceFocusRequest] = useState(0);
|
|
@@ -14130,17 +14228,36 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14130
14228
|
const [selectionVersion, setSelectionVersion] = useState(0);
|
|
14131
14229
|
const [statisticsOpen, setStatisticsOpen] = useState(false);
|
|
14132
14230
|
const loadedLayoutFontIds = useDocumentLayoutFonts(layoutFonts);
|
|
14133
|
-
contentRef.current = content;
|
|
14231
|
+
if (!collaboration) contentRef.current = content;
|
|
14134
14232
|
onChangeRef.current = onChange;
|
|
14135
|
-
trackChangesRef.current = Boolean(
|
|
14233
|
+
trackChangesRef.current = Boolean(contentRef.current.trackChanges);
|
|
14234
|
+
const commitContentChange = useCallback((next)=>{
|
|
14235
|
+
const previous = contentRef.current;
|
|
14236
|
+
const binding = collaborationBindingRef.current;
|
|
14237
|
+
binding?.updateSidecars(previous, next);
|
|
14238
|
+
contentRef.current = next;
|
|
14239
|
+
if (!binding) onChangeRef.current(next);
|
|
14240
|
+
}, []);
|
|
14241
|
+
collaborationBindingRef.current = collaborationBinding;
|
|
14242
|
+
if (collaborationBridge) collaborationBridge.current = {
|
|
14243
|
+
getContent: ()=>contentRef.current,
|
|
14244
|
+
isTracking: ()=>trackChangesRef.current,
|
|
14245
|
+
onContentChange: (next)=>commitContentChange(next),
|
|
14246
|
+
onTrackingChange: (trackChanges)=>{
|
|
14247
|
+
trackChangesRef.current = trackChanges;
|
|
14248
|
+
commitContentChange({
|
|
14249
|
+
...contentRef.current,
|
|
14250
|
+
trackChanges
|
|
14251
|
+
});
|
|
14252
|
+
}
|
|
14253
|
+
};
|
|
14136
14254
|
const editorExtensions = useMemo(()=>mergeOfficeTiptapExtensions('DocumentEditor', [
|
|
14137
|
-
...createWorkDocumentExtensions({
|
|
14255
|
+
...collaborationBinding?.extensions ?? createWorkDocumentExtensions({
|
|
14138
14256
|
getContent: ()=>contentRef.current,
|
|
14139
14257
|
isTracking: ()=>trackChangesRef.current,
|
|
14140
14258
|
createChange: createTrackedDocumentChange,
|
|
14141
14259
|
onContentChange: (next)=>{
|
|
14142
|
-
|
|
14143
|
-
onChangeRef.current(next);
|
|
14260
|
+
commitContentChange(next);
|
|
14144
14261
|
},
|
|
14145
14262
|
onTrackingChange: (trackChanges)=>{
|
|
14146
14263
|
trackChangesRef.current = trackChanges;
|
|
@@ -14148,15 +14265,17 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14148
14265
|
...contentRef.current,
|
|
14149
14266
|
trackChanges
|
|
14150
14267
|
};
|
|
14151
|
-
|
|
14152
|
-
onChangeRef.current(next);
|
|
14268
|
+
commitContentChange(next);
|
|
14153
14269
|
}
|
|
14154
14270
|
}),
|
|
14155
14271
|
extension_placeholder.configure({
|
|
14156
14272
|
placeholder: '在这里开始输入…'
|
|
14157
14273
|
}),
|
|
14158
14274
|
DocumentPagination
|
|
14159
|
-
], extensions), [
|
|
14275
|
+
], collaboration ? EMPTY_DOCUMENT_EXTENSIONS : extensions), [
|
|
14276
|
+
collaboration,
|
|
14277
|
+
collaborationBinding,
|
|
14278
|
+
commitContentChange,
|
|
14160
14279
|
extensions
|
|
14161
14280
|
]);
|
|
14162
14281
|
const editorProps = useMemo(()=>({
|
|
@@ -14169,33 +14288,123 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14169
14288
|
}), []);
|
|
14170
14289
|
const editor = useEditor({
|
|
14171
14290
|
extensions: editorExtensions,
|
|
14172
|
-
content:
|
|
14173
|
-
editable: !
|
|
14291
|
+
content: collaboration ? void 0 : initialEditorSourceRef.current,
|
|
14292
|
+
editable: !readOnly,
|
|
14174
14293
|
editorProps,
|
|
14175
|
-
|
|
14294
|
+
onCreate: ({ editor: current })=>{
|
|
14295
|
+
publishedDocumentRef.current = current.state.doc;
|
|
14296
|
+
},
|
|
14297
|
+
onUpdate: ({ editor: current, transaction })=>{
|
|
14298
|
+
if (!shouldPublishDocumentUpdate(transaction)) {
|
|
14299
|
+
publishedDocumentRef.current = current.state.doc;
|
|
14300
|
+
return;
|
|
14301
|
+
}
|
|
14302
|
+
if (!publishedDocumentRef.current) {
|
|
14303
|
+
publishedDocumentRef.current = current.state.doc;
|
|
14304
|
+
return;
|
|
14305
|
+
}
|
|
14306
|
+
if (publishedDocumentRef.current.eq(current.state.doc)) return;
|
|
14307
|
+
publishedDocumentRef.current = current.state.doc;
|
|
14176
14308
|
const anchors = collectDocumentCommentAnchors(current.state.doc);
|
|
14309
|
+
const retainedCommentIds = new Set(activeReviewConflictsRef.current.filter((conflict)=>'comment' === conflict.kind).map((conflict)=>conflict.id));
|
|
14177
14310
|
const synchronized = syncDocumentContentFromHtml(contentRef.current, current.getHTML());
|
|
14178
14311
|
const model = createWorkDocumentModel(synchronized.html, current.getJSON(), contentRef.current.model);
|
|
14179
14312
|
const next = {
|
|
14180
14313
|
...synchronized,
|
|
14181
14314
|
model,
|
|
14182
|
-
comments: retainAnchoredDocumentComments(contentRef.current.comments ?? [], anchors)
|
|
14315
|
+
comments: retainAnchoredDocumentComments(contentRef.current.comments ?? [], anchors, retainedCommentIds)
|
|
14183
14316
|
};
|
|
14184
14317
|
appliedSourceKeyRef.current = `model:${model.revision}:${model.htmlFingerprint}`;
|
|
14185
|
-
|
|
14186
|
-
|
|
14318
|
+
if (!collaborationBinding) {
|
|
14319
|
+
contentRef.current = next;
|
|
14320
|
+
onChangeRef.current(next);
|
|
14321
|
+
}
|
|
14187
14322
|
},
|
|
14188
14323
|
onSelectionUpdate: ()=>setSelectionVersion((value)=>value + 1)
|
|
14189
14324
|
});
|
|
14325
|
+
const documentPresenceLocation = useMemo(()=>{
|
|
14326
|
+
if (!editor || editor.isDestroyed) return null;
|
|
14327
|
+
const { anchor, head } = editor.state.selection;
|
|
14328
|
+
return {
|
|
14329
|
+
kind: 'document',
|
|
14330
|
+
anchor,
|
|
14331
|
+
head
|
|
14332
|
+
};
|
|
14333
|
+
}, [
|
|
14334
|
+
editor,
|
|
14335
|
+
selectionVersion
|
|
14336
|
+
]);
|
|
14337
|
+
useOfficePublishPresenceLocation(documentPresenceLocation);
|
|
14338
|
+
const navigateToDocumentParticipant = useCallback((participant)=>{
|
|
14339
|
+
const location = participant.location;
|
|
14340
|
+
if (!editor || editor.isDestroyed || location?.kind !== 'document') return false;
|
|
14341
|
+
const maximum = editor.state.doc.content.size;
|
|
14342
|
+
if (location.anchor > maximum || location.head > maximum) return false;
|
|
14343
|
+
const from = Math.min(location.anchor, location.head);
|
|
14344
|
+
const to = Math.max(location.anchor, location.head);
|
|
14345
|
+
return editor.chain().focus().setTextSelection({
|
|
14346
|
+
from,
|
|
14347
|
+
to
|
|
14348
|
+
}).scrollIntoView().run();
|
|
14349
|
+
}, [
|
|
14350
|
+
editor
|
|
14351
|
+
]);
|
|
14352
|
+
useOfficeCollaborationLocationNavigator(navigateToDocumentParticipant);
|
|
14353
|
+
const reviewConflicts = useDocumentReviewConflicts({
|
|
14354
|
+
activeConflictsRef: activeReviewConflictsRef,
|
|
14355
|
+
appliedSourceKeyRef,
|
|
14356
|
+
artifactId,
|
|
14357
|
+
content: collaboration ? contentRef.current : content,
|
|
14358
|
+
editor,
|
|
14359
|
+
editorInput,
|
|
14360
|
+
normalizedContent,
|
|
14361
|
+
onReviewConflict,
|
|
14362
|
+
publishedDocumentRef,
|
|
14363
|
+
reconcileControlledUpdates: !collaboration
|
|
14364
|
+
});
|
|
14190
14365
|
const documentComments = useDocumentComments({
|
|
14191
14366
|
contentRef,
|
|
14192
14367
|
editor,
|
|
14193
14368
|
onBeforeDraft: ()=>setTaskPane(null)
|
|
14194
14369
|
});
|
|
14195
|
-
const
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14370
|
+
const [collaborationVersion, setCollaborationVersion] = useState(0);
|
|
14371
|
+
const handledCollaborationVersionRef = useRef(0);
|
|
14372
|
+
const pendingCollaborationContentRef = useRef(void 0);
|
|
14373
|
+
useEffect(()=>{
|
|
14374
|
+
if (!collaborationBinding) return;
|
|
14375
|
+
const unsubscribeChange = collaborationBinding.subscribe((change)=>{
|
|
14376
|
+
pendingCollaborationContentRef.current = change.content;
|
|
14377
|
+
contentRef.current = change.content;
|
|
14378
|
+
trackChangesRef.current = Boolean(change.content.trackChanges);
|
|
14379
|
+
setCollaborationVersion((value)=>value + 1);
|
|
14380
|
+
});
|
|
14381
|
+
const unsubscribeError = collaborationBinding.subscribeError((error)=>{
|
|
14382
|
+
queueMicrotask(()=>{
|
|
14383
|
+
throw error;
|
|
14384
|
+
});
|
|
14385
|
+
});
|
|
14386
|
+
const unsubscribeHistory = collaborationBinding.subscribeHistory(()=>{
|
|
14387
|
+
setCollaborationVersion((value)=>value + 1);
|
|
14388
|
+
});
|
|
14389
|
+
return ()=>{
|
|
14390
|
+
unsubscribeChange();
|
|
14391
|
+
unsubscribeError();
|
|
14392
|
+
unsubscribeHistory();
|
|
14393
|
+
};
|
|
14394
|
+
}, [
|
|
14395
|
+
collaborationBinding
|
|
14396
|
+
]);
|
|
14397
|
+
useEffect(()=>{
|
|
14398
|
+
if (collaborationVersion === handledCollaborationVersionRef.current || !pendingCollaborationContentRef.current) return;
|
|
14399
|
+
handledCollaborationVersionRef.current = collaborationVersion;
|
|
14400
|
+
const next = pendingCollaborationContentRef.current;
|
|
14401
|
+
pendingCollaborationContentRef.current = void 0;
|
|
14402
|
+
contentRef.current = next;
|
|
14403
|
+
trackChangesRef.current = Boolean(next.trackChanges);
|
|
14404
|
+
onChangeRef.current(next);
|
|
14405
|
+
}, [
|
|
14406
|
+
collaborationVersion
|
|
14407
|
+
]);
|
|
14199
14408
|
const rememberTaskPaneInvoker = useCallback(()=>{
|
|
14200
14409
|
const active = document.activeElement;
|
|
14201
14410
|
if (active instanceof HTMLElement && active.isConnected) taskPaneInvokerRef.current = active;
|
|
@@ -14370,6 +14579,11 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14370
14579
|
}, [
|
|
14371
14580
|
editor
|
|
14372
14581
|
]);
|
|
14582
|
+
useOfficeEditorInitialFocus({
|
|
14583
|
+
enabled: autoFocus && !readOnly && Boolean(editor && !editor.isDestroyed),
|
|
14584
|
+
getTarget: ()=>!editor || editor.isDestroyed ? null : editor.view.dom,
|
|
14585
|
+
isTargetReady: (target)=>'true' === target.getAttribute('contenteditable')
|
|
14586
|
+
});
|
|
14373
14587
|
const replaceDocumentText = useCallback((from, to, replacement)=>{
|
|
14374
14588
|
if (!editor) return false;
|
|
14375
14589
|
if (trackChangesRef.current) return editor.commands.replaceDocumentTextWithTrackedChange(from, to, replacement);
|
|
@@ -14384,7 +14598,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14384
14598
|
if (!editor) return;
|
|
14385
14599
|
const applyEditableState = ()=>{
|
|
14386
14600
|
if (editor.isDestroyed) return;
|
|
14387
|
-
editor.setEditable(!
|
|
14601
|
+
editor.setEditable(!readOnly);
|
|
14388
14602
|
const editorDom = editor.view.dom;
|
|
14389
14603
|
editorDom.setAttribute('role', preview ? 'document' : 'textbox');
|
|
14390
14604
|
if (preview) editorDom.removeAttribute('aria-multiline');
|
|
@@ -14397,7 +14611,8 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14397
14611
|
};
|
|
14398
14612
|
}, [
|
|
14399
14613
|
editor,
|
|
14400
|
-
preview
|
|
14614
|
+
preview,
|
|
14615
|
+
readOnly
|
|
14401
14616
|
]);
|
|
14402
14617
|
useEffect(()=>{
|
|
14403
14618
|
if (!editor) return;
|
|
@@ -14413,33 +14628,12 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14413
14628
|
editor,
|
|
14414
14629
|
spellcheckEnabled
|
|
14415
14630
|
]);
|
|
14416
|
-
useEffect(()=>{
|
|
14417
|
-
if (!editor || appliedSourceKeyRef.current === editorInput.sourceKey) return;
|
|
14418
|
-
const currentContent = normalizeDocumentHtml({
|
|
14419
|
-
...content,
|
|
14420
|
-
html: editor.getHTML()
|
|
14421
|
-
});
|
|
14422
|
-
if ('string' == typeof editorInput.source && currentContent === normalizedContent) {
|
|
14423
|
-
appliedSourceKeyRef.current = editorInput.sourceKey;
|
|
14424
|
-
return;
|
|
14425
|
-
}
|
|
14426
|
-
appliedSourceKeyRef.current = editorInput.sourceKey;
|
|
14427
|
-
editor.chain().setMeta('addToHistory', false).setContent(editorInput.source, {
|
|
14428
|
-
emitUpdate: false
|
|
14429
|
-
}).run();
|
|
14430
|
-
}, [
|
|
14431
|
-
content,
|
|
14432
|
-
editor,
|
|
14433
|
-
editorInput,
|
|
14434
|
-
normalizedContent
|
|
14435
|
-
]);
|
|
14436
14631
|
const section = editor ? activeDocumentSection(editor) : null;
|
|
14437
|
-
const
|
|
14438
|
-
const
|
|
14439
|
-
|
|
14440
|
-
|
|
14441
|
-
|
|
14442
|
-
});
|
|
14632
|
+
const currentContent = contentRef.current;
|
|
14633
|
+
const layout = section?.layout ?? documentInitialSectionLayout(currentContent);
|
|
14634
|
+
const resolvedPageSize = resolveDocumentPageSize(layout);
|
|
14635
|
+
const resolvedMargins = resolveDocumentPageMargins(layout, 1);
|
|
14636
|
+
const margins = resolvedMargins.body;
|
|
14443
14637
|
const marginPixels = {
|
|
14444
14638
|
top: work_document_layout_millimetersToPixels(margins.top),
|
|
14445
14639
|
right: work_document_layout_millimetersToPixels(margins.right),
|
|
@@ -14453,6 +14647,8 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14453
14647
|
layout.margins.right,
|
|
14454
14648
|
layout.margins.top,
|
|
14455
14649
|
layout.orientation,
|
|
14650
|
+
JSON.stringify(layout.pageGeometry),
|
|
14651
|
+
JSON.stringify(layout.pageMargins),
|
|
14456
14652
|
layout.pageSize
|
|
14457
14653
|
]);
|
|
14458
14654
|
const pagination = useDocumentPagination({
|
|
@@ -14465,7 +14661,9 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14465
14661
|
layout.columns.spacing,
|
|
14466
14662
|
layout.columns.separator,
|
|
14467
14663
|
layoutOpen,
|
|
14468
|
-
JSON.stringify(pageChrome)
|
|
14664
|
+
JSON.stringify(pageChrome),
|
|
14665
|
+
JSON.stringify(layout.pageBorders),
|
|
14666
|
+
JSON.stringify(layout.pageMargins)
|
|
14469
14667
|
].join(':'),
|
|
14470
14668
|
page: kernelPage,
|
|
14471
14669
|
selectionVersion,
|
|
@@ -14473,12 +14671,33 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14473
14671
|
layoutFonts,
|
|
14474
14672
|
loadedLayoutFontIds
|
|
14475
14673
|
});
|
|
14674
|
+
const documentInsert = useDocumentInsertCommands({
|
|
14675
|
+
contentRef,
|
|
14676
|
+
editor,
|
|
14677
|
+
resolveFieldContext: pagination.resolveFieldContext
|
|
14678
|
+
});
|
|
14679
|
+
useEffect(()=>{
|
|
14680
|
+
if (!editor || !pagination.resolveFieldContext) return;
|
|
14681
|
+
editor.commands.refreshDocumentFields(contentRef.current, {
|
|
14682
|
+
resolveContext: pagination.resolveFieldContext,
|
|
14683
|
+
addToHistory: false,
|
|
14684
|
+
updateClock: false
|
|
14685
|
+
});
|
|
14686
|
+
}, [
|
|
14687
|
+
contentRef,
|
|
14688
|
+
editor,
|
|
14689
|
+
pagination.resolveFieldContext
|
|
14690
|
+
]);
|
|
14476
14691
|
const pageCount = editor ? pagination.pageCount ?? documentPageCount(editor) : 1;
|
|
14477
|
-
const
|
|
14692
|
+
const paginationGeometry = pagination.pageCount ? documentPageSurfaceGeometry(pagination.pages.map((page)=>page.page), kernelPage, pagination.pageCount) : null;
|
|
14478
14693
|
const currentPage = editor ? Math.min(pageCount, pagination.currentPage ?? documentCurrentPage(editor)) : 1;
|
|
14479
14694
|
const currentPageDescriptor = pagination.currentPageDescriptor ?? fallbackPaginationPageDescriptor(section?.id, section?.index, layout, currentPage);
|
|
14480
14695
|
const firstPageDescriptor = pagination.pages[0] ?? fallbackPaginationPageDescriptor(section?.id, section?.index, layout, 1);
|
|
14481
14696
|
const lastPageDescriptor = pagination.pages.at(-1) ?? currentPageDescriptor;
|
|
14697
|
+
const firstPageFrame = paginationGeometry?.frames[0];
|
|
14698
|
+
const lastPageFrame = paginationGeometry?.frames.at(-1);
|
|
14699
|
+
const firstPageMargins = resolveDocumentPageMargins(firstPageDescriptor.layout, firstPageDescriptor.physicalPage);
|
|
14700
|
+
const lastPageMargins = resolveDocumentPageMargins(lastPageDescriptor.layout, lastPageDescriptor.physicalPage);
|
|
14482
14701
|
const { chromeEditor: pageChromeEditor, close: closePageChrome, edit: editPageChrome, editing: pageChromeEditing, footerChrome, headerChrome, reset: resetPageChrome, setChromeEditor: setPageChromeEditor, togglePageNumber: toggleVisiblePageNumber, update: updateVisiblePageChrome, visibleChrome } = useDocumentPageChrome({
|
|
14483
14702
|
editor,
|
|
14484
14703
|
enabled: !preview && 'page' === viewMode,
|
|
@@ -14542,8 +14761,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14542
14761
|
...contentRef.current,
|
|
14543
14762
|
pageColor
|
|
14544
14763
|
};
|
|
14545
|
-
|
|
14546
|
-
onChangeRef.current(next);
|
|
14764
|
+
commitContentChange(next);
|
|
14547
14765
|
}
|
|
14548
14766
|
restoreDocumentBodyFocus();
|
|
14549
14767
|
};
|
|
@@ -14562,8 +14780,8 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14562
14780
|
if (!viewport) return;
|
|
14563
14781
|
const style = getComputedStyle(viewport);
|
|
14564
14782
|
setZoom(documentZoomForFit(fit, {
|
|
14565
|
-
pageHeight:
|
|
14566
|
-
pageWidth:
|
|
14783
|
+
pageHeight: currentPageDescriptor.page.height,
|
|
14784
|
+
pageWidth: currentPageDescriptor.page.width,
|
|
14567
14785
|
viewportHeight: viewport.clientHeight,
|
|
14568
14786
|
viewportWidth: viewport.clientWidth,
|
|
14569
14787
|
viewportPadding: {
|
|
@@ -14633,12 +14851,19 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14633
14851
|
className: "work-document-ribbon"
|
|
14634
14852
|
}) : /*#__PURE__*/ jsx(DocumentToolbar, {
|
|
14635
14853
|
editor: editor,
|
|
14854
|
+
defaultRibbonCollapsed: defaultRibbonCollapsed,
|
|
14855
|
+
history: collaborationBinding ? {
|
|
14856
|
+
canRedo: collaborationBinding.canRedo(),
|
|
14857
|
+
canUndo: collaborationBinding.canUndo(),
|
|
14858
|
+
redo: ()=>collaborationBinding.redo(),
|
|
14859
|
+
undo: ()=>collaborationBinding.undo()
|
|
14860
|
+
} : void 0,
|
|
14636
14861
|
fileActions: fileActions,
|
|
14637
14862
|
layout: layout,
|
|
14638
14863
|
layoutFonts: layoutFonts,
|
|
14639
14864
|
layoutOpen: layoutOpen,
|
|
14640
14865
|
navigationOpen: navigationOpen,
|
|
14641
|
-
pageColor: documentPageColor(
|
|
14866
|
+
pageColor: documentPageColor(currentContent.pageColor),
|
|
14642
14867
|
showPageNumbers: visibleChrome.showPageNumber,
|
|
14643
14868
|
showRulers: showRulers,
|
|
14644
14869
|
spellcheckEnabled: spellcheckEnabled,
|
|
@@ -14670,7 +14895,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14670
14895
|
onInsertCaption: documentInsert.insertCaption,
|
|
14671
14896
|
onInsertCrossReference: documentInsert.insertCrossReference,
|
|
14672
14897
|
citationsOpen: citationsOpen,
|
|
14673
|
-
citationSourceCount:
|
|
14898
|
+
citationSourceCount: currentContent.bibliography?.sources.length ?? 0,
|
|
14674
14899
|
onToggleCitations: ()=>void toggleTaskPane('citations'),
|
|
14675
14900
|
onInsertField: documentInsert.insertField,
|
|
14676
14901
|
onRefreshFields: refreshDocumentFields,
|
|
@@ -14679,7 +14904,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14679
14904
|
commentsOpen: documentComments.open,
|
|
14680
14905
|
commentCount: documentComments.comments.length,
|
|
14681
14906
|
onToggleComments: ()=>void toggleCommentsPanel(),
|
|
14682
|
-
trackChanges: Boolean(
|
|
14907
|
+
trackChanges: Boolean(currentContent.trackChanges),
|
|
14683
14908
|
changesOpen: changesOpen,
|
|
14684
14909
|
changeCount: changes.length,
|
|
14685
14910
|
findReplaceMode: findReplaceMode,
|
|
@@ -14695,6 +14920,10 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14695
14920
|
onOpenWordCount: openDocumentStatistics,
|
|
14696
14921
|
onOpenFindReplace: openFindReplace
|
|
14697
14922
|
}),
|
|
14923
|
+
!preview && /*#__PURE__*/ jsx(DocumentReviewConflictNotice, {
|
|
14924
|
+
conflicts: reviewConflicts.visibleConflicts,
|
|
14925
|
+
onDismiss: reviewConflicts.dismiss
|
|
14926
|
+
}),
|
|
14698
14927
|
/*#__PURE__*/ jsxs("div", {
|
|
14699
14928
|
ref: workspaceRef,
|
|
14700
14929
|
className: `work-document-workspace${!preview && taskPane ? ' task-pane-open' : ''}`,
|
|
@@ -14710,12 +14939,13 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14710
14939
|
pageGap: kernelPage.pageGap,
|
|
14711
14940
|
pageHeight: kernelPage.height,
|
|
14712
14941
|
pageWidth: kernelPage.width,
|
|
14942
|
+
pages: paginationGeometry?.frames,
|
|
14713
14943
|
revision: editorInput.sourceKey
|
|
14714
14944
|
} : void 0,
|
|
14715
14945
|
pages: (pagination.pages.length ? pagination.pages : [
|
|
14716
14946
|
firstPageDescriptor
|
|
14717
14947
|
]).map((page)=>({
|
|
14718
|
-
backgroundColor: documentPageColor(
|
|
14948
|
+
backgroundColor: documentPageColor(currentContent.pageColor),
|
|
14719
14949
|
orientation: page.layout.orientation,
|
|
14720
14950
|
pageNumber: page.pageNumber,
|
|
14721
14951
|
physicalPage: page.physicalPage,
|
|
@@ -14765,29 +14995,49 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14765
14995
|
"data-pdf-page-gap": artifactId && pagination.pageCount ? kernelPage.pageGap : void 0,
|
|
14766
14996
|
"data-pdf-page-height": artifactId && pagination.pageCount ? kernelPage.height : void 0,
|
|
14767
14997
|
"data-pdf-page-size": artifactId && pagination.pageCount ? layout.pageSize : void 0,
|
|
14998
|
+
"data-pdf-page-width-points": artifactId && pagination.pageCount ? resolvedPageSize.widthPoints : void 0,
|
|
14999
|
+
"data-pdf-page-height-points": artifactId && pagination.pageCount ? resolvedPageSize.heightPoints : void 0,
|
|
14768
15000
|
"data-pdf-page-width": artifactId && pagination.pageCount ? kernelPage.width : void 0,
|
|
15001
|
+
"data-document-page-gutter-position": resolvedMargins.gutterPosition,
|
|
15002
|
+
"data-document-page-margins-bounded": String(resolvedMargins.bounded),
|
|
15003
|
+
"data-document-page-mirror-margins": String(resolvedMargins.mirrorMargins),
|
|
15004
|
+
"data-document-page-top-margin-mode": resolvedMargins.topMode,
|
|
15005
|
+
"data-document-page-bottom-margin-mode": resolvedMargins.bottomMode,
|
|
14769
15006
|
"aria-label": preview ? '文字预览' : '文字页面',
|
|
14770
15007
|
style: {
|
|
14771
|
-
padding: `${marginPixels.top}px ${marginPixels.right}px ${marginPixels.bottom}px ${marginPixels.left}px`,
|
|
14772
|
-
backgroundColor: documentPageColor(
|
|
14773
|
-
|
|
14774
|
-
'
|
|
15008
|
+
padding: paginationGeometry ? `${firstPageDescriptor.page.marginTop}px 0 ${lastPageDescriptor.page.marginBottom}px` : `${marginPixels.top}px ${marginPixels.right}px ${marginPixels.bottom}px ${marginPixels.left}px`,
|
|
15009
|
+
backgroundColor: documentPageColor(currentContent.pageColor),
|
|
15010
|
+
width: 'page' === viewMode ? paginationGeometry?.width ?? kernelPage.width : void 0,
|
|
15011
|
+
minHeight: 'page' === viewMode ? paginationGeometry?.height ?? kernelPage.height : void 0,
|
|
15012
|
+
'--work-document-page-color': documentPageColor(currentContent.pageColor),
|
|
14775
15013
|
'--work-document-page-margin-left': `${marginPixels.left}px`,
|
|
14776
15014
|
'--work-document-page-margin-right': `${marginPixels.right}px`,
|
|
14777
15015
|
'--work-document-page-margin-top': `${marginPixels.top}px`,
|
|
14778
|
-
'--work-document-page-margin-bottom': `${marginPixels.bottom}px
|
|
15016
|
+
'--work-document-page-margin-bottom': `${marginPixels.bottom}px`,
|
|
15017
|
+
'--work-document-page-header-distance': `${work_document_layout_millimetersToPixels(resolvedMargins.headerDistance)}px`,
|
|
15018
|
+
'--work-document-page-footer-distance': `${work_document_layout_millimetersToPixels(resolvedMargins.footerDistance)}px`,
|
|
15019
|
+
'--work-document-page-header-height': `${Math.max(0, marginPixels.top - work_document_layout_millimetersToPixels(resolvedMargins.headerDistance))}px`,
|
|
15020
|
+
'--work-document-page-footer-height': `${Math.max(0, marginPixels.bottom - work_document_layout_millimetersToPixels(resolvedMargins.footerDistance))}px`
|
|
14779
15021
|
},
|
|
14780
15022
|
children: [
|
|
14781
15023
|
'page' === viewMode && pagination.pageCount && /*#__PURE__*/ jsx(DocumentPageStack, {
|
|
14782
|
-
pageColor: documentPageColor(
|
|
15024
|
+
pageColor: documentPageColor(currentContent.pageColor),
|
|
14783
15025
|
pageCount: pagination.pageCount,
|
|
14784
15026
|
pageGap: kernelPage.pageGap,
|
|
14785
|
-
pageHeight: kernelPage.height
|
|
15027
|
+
pageHeight: kernelPage.height,
|
|
15028
|
+
pageWidth: kernelPage.width,
|
|
15029
|
+
pages: pagination.pages
|
|
14786
15030
|
}),
|
|
14787
15031
|
'page' === viewMode && (!preview || Boolean(headerChrome.headerHtml)) && /*#__PURE__*/ jsx("header", {
|
|
14788
15032
|
ref: pageHeaderRef,
|
|
14789
15033
|
className: `work-document-page-header${!preview && pageChromeEditing?.part === 'header' ? ' editing' : ''}`,
|
|
14790
15034
|
"data-document-page-chrome": firstPageDescriptor.pageChrome.variant,
|
|
15035
|
+
style: firstPageFrame && paginationGeometry ? {
|
|
15036
|
+
height: firstPageDescriptor.page.headerHeight,
|
|
15037
|
+
left: firstPageFrame.left + firstPageDescriptor.page.marginLeft,
|
|
15038
|
+
right: paginationGeometry.width - firstPageFrame.left - firstPageFrame.width + firstPageDescriptor.page.marginRight,
|
|
15039
|
+
top: work_document_layout_millimetersToPixels(firstPageMargins.headerDistance)
|
|
15040
|
+
} : void 0,
|
|
14791
15041
|
onDoubleClick: preview ? void 0 : (event)=>{
|
|
14792
15042
|
if (pageChromeEditing?.part === 'header') return;
|
|
14793
15043
|
event.preventDefault();
|
|
@@ -14812,6 +15062,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14812
15062
|
}, `${pageChromeEditing.sectionId}-${pageChromeEditing.variant}-header`)
|
|
14813
15063
|
}),
|
|
14814
15064
|
/*#__PURE__*/ jsxs("section", {
|
|
15065
|
+
ref: editableSurfaceRef,
|
|
14815
15066
|
className: `work-document-editable ${viewMode}`,
|
|
14816
15067
|
"aria-label": "文档内容编辑区域",
|
|
14817
15068
|
onDoubleClick: ()=>{
|
|
@@ -14826,6 +15077,11 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14826
15077
|
/*#__PURE__*/ jsx(EditorContent, {
|
|
14827
15078
|
editor: editor
|
|
14828
15079
|
}),
|
|
15080
|
+
/*#__PURE__*/ jsx(OfficeTiptapPresenceLayer, {
|
|
15081
|
+
containerRef: editableSurfaceRef,
|
|
15082
|
+
editor: editor,
|
|
15083
|
+
kind: "document"
|
|
15084
|
+
}),
|
|
14829
15085
|
!preview && /*#__PURE__*/ jsx(DocumentSelectionToolbar, {
|
|
14830
15086
|
editor: editor,
|
|
14831
15087
|
canInsertComment: documentComments.canInsert,
|
|
@@ -14838,6 +15094,12 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14838
15094
|
ref: pageFooterRef,
|
|
14839
15095
|
className: `work-document-page-footer${!preview && pageChromeEditing?.part === 'footer' ? ' editing' : ''}`,
|
|
14840
15096
|
"data-document-page-chrome": lastPageDescriptor.pageChrome.variant,
|
|
15097
|
+
style: lastPageFrame && paginationGeometry ? {
|
|
15098
|
+
bottom: work_document_layout_millimetersToPixels(lastPageMargins.footerDistance),
|
|
15099
|
+
height: lastPageDescriptor.page.footerHeight,
|
|
15100
|
+
left: lastPageFrame.left + lastPageDescriptor.page.marginLeft,
|
|
15101
|
+
right: paginationGeometry.width - lastPageFrame.left - lastPageFrame.width + lastPageDescriptor.page.marginRight
|
|
15102
|
+
} : void 0,
|
|
14841
15103
|
onDoubleClick: preview ? void 0 : (event)=>{
|
|
14842
15104
|
if (pageChromeEditing?.part === 'footer') return;
|
|
14843
15105
|
event.preventDefault();
|
|
@@ -14898,14 +15160,14 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14898
15160
|
}),
|
|
14899
15161
|
!preview && citationsOpen && /*#__PURE__*/ jsx(DocumentCitationsPanel, {
|
|
14900
15162
|
editor: editor,
|
|
14901
|
-
content:
|
|
15163
|
+
content: currentContent,
|
|
14902
15164
|
onClose: closeTaskPane,
|
|
14903
15165
|
onDirtyChange: setCitationsDirty
|
|
14904
15166
|
}),
|
|
14905
15167
|
!preview && changesOpen && /*#__PURE__*/ jsx(DocumentChangesPanel, {
|
|
14906
15168
|
editor: editor,
|
|
14907
15169
|
changes: changes,
|
|
14908
|
-
trackChanges: Boolean(
|
|
15170
|
+
trackChanges: Boolean(currentContent.trackChanges),
|
|
14909
15171
|
onTrackChangesChange: (enabled)=>editor.commands.setDocumentTrackChanges(enabled),
|
|
14910
15172
|
onClose: closeTaskPane
|
|
14911
15173
|
}),
|
|
@@ -14949,7 +15211,7 @@ function DocumentEditor({ artifactId, content, extensions = EMPTY_DOCUMENT_EXTEN
|
|
|
14949
15211
|
})
|
|
14950
15212
|
]
|
|
14951
15213
|
}) : /*#__PURE__*/ jsx(DocumentStatusBar, {
|
|
14952
|
-
bibliographyCount:
|
|
15214
|
+
bibliographyCount: currentContent.bibliography?.sources.length ?? 0,
|
|
14953
15215
|
citationCount: citationCount,
|
|
14954
15216
|
currentPage: currentPage,
|
|
14955
15217
|
pageCount: pageCount,
|