@a3s-lab/office 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +117 -3
  2. package/dist/{0~7043.js → 0~4808.js} +347 -2
  3. package/dist/0~5050.js +10 -1
  4. package/dist/{0~5093.js → 0~7240.js} +465 -55
  5. package/dist/0~document-editor.js +1694 -187
  6. package/dist/0~spreadsheet-editor.js +183 -34
  7. package/dist/0~work-docx-export.js +507 -31
  8. package/dist/0~work-docx-import.js +41 -7
  9. package/dist/0~work-office-diagnostics.js +146 -5
  10. package/dist/1544.js +13 -1
  11. package/dist/4104.js +29 -6
  12. package/dist/4121.js +2340 -1
  13. package/dist/6282.js +1072 -1148
  14. package/dist/internal/features/work/editors/document-command-catalog.d.ts +45 -0
  15. package/dist/internal/features/work/editors/document-dom-selection.d.ts +7 -0
  16. package/dist/internal/features/work/editors/document-editor-support.d.ts +1 -0
  17. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +5 -2
  18. package/dist/internal/features/work/editors/document-font-dialog-run-shading-model.d.ts +23 -0
  19. package/dist/internal/features/work/editors/document-font-dialog-run-shading-section.d.ts +8 -0
  20. package/dist/internal/features/work/editors/document-index-dialog.d.ts +10 -0
  21. package/dist/internal/features/work/editors/document-index-entry-dialog.d.ts +10 -0
  22. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  23. package/dist/internal/features/work/editors/document-proofing-dialog-model.d.ts +22 -0
  24. package/dist/internal/features/work/editors/document-proofing-dialog.d.ts +7 -0
  25. package/dist/internal/features/work/editors/document-references-ribbon.d.ts +19 -0
  26. package/dist/internal/features/work/editors/document-table-of-contents-dialog.d.ts +10 -0
  27. package/dist/internal/features/work/editors/document-toolbar.d.ts +6 -1
  28. package/dist/internal/features/work/editors/spreadsheet-data-validation.d.ts +7 -1
  29. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +5 -0
  30. package/dist/internal/features/work/work-document-character-formatting.d.ts +8 -0
  31. package/dist/internal/features/work/work-document-format-changes.d.ts +6 -0
  32. package/dist/internal/features/work/work-document-highlight.d.ts +9 -0
  33. package/dist/internal/features/work/work-document-index-fields.d.ts +19 -0
  34. package/dist/internal/features/work/work-document-index-nodes.d.ts +32 -0
  35. package/dist/internal/features/work/work-document-index.d.ts +63 -0
  36. package/dist/internal/features/work/work-document-outline.d.ts +1 -0
  37. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +6 -0
  38. package/dist/internal/features/work/work-document-proofing.d.ts +19 -0
  39. package/dist/internal/features/work/work-document-run-shading.d.ts +12 -0
  40. package/dist/internal/features/work/work-document-table-of-contents-node.d.ts +18 -0
  41. package/dist/internal/features/work/work-document-table-of-contents.d.ts +51 -0
  42. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +3 -0
  43. package/dist/internal/features/work/work-docx-field-instructions.d.ts +1 -1
  44. package/dist/internal/features/work/work-docx-import.d.ts +5 -1
  45. package/dist/internal/features/work/work-docx-index-export.d.ts +14 -0
  46. package/dist/internal/features/work/work-docx-index-import.d.ts +23 -0
  47. package/dist/internal/features/work/work-docx-proofing-diagnostics.d.ts +3 -0
  48. package/dist/internal/features/work/work-docx-proofing.d.ts +38 -0
  49. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +7 -0
  50. package/dist/internal/features/work/work-docx-run-shading-diagnostics.d.ts +3 -0
  51. package/dist/internal/features/work/work-docx-run-shading-export.d.ts +17 -0
  52. package/dist/internal/features/work/work-docx-run-shading.d.ts +20 -0
  53. package/dist/internal/features/work/work-docx-table-of-contents-export.d.ts +11 -0
  54. package/dist/internal/features/work/work-docx-table-of-contents-import.d.ts +15 -0
  55. package/dist/internal/features/work/work-spreadsheet-data-validation.d.ts +7 -0
  56. package/dist/internal/features/work/work-types.d.ts +9 -0
  57. package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -0
  58. package/dist/office-kernel.wasm +0 -0
  59. package/dist/styles.css +607 -4
  60. package/docs/latest/en/browser-editor-architecture.md +64 -1
  61. package/package.json +15 -2
@@ -6,7 +6,7 @@ import { Fragment as external_react_Fragment, forwardRef, useCallback, useEffect
6
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, ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Bookmark, CaseUpper, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, Eye, 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, Square, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, TextWrap, Trash2, TriangleAlert, Type, Underline, Undo2, Unlink, Unlink2, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
9
+ import { AArrowDown, AArrowUp, ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Bookmark, CaseUpper, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, Eye, FileDiff, FilePlus2, FileText, Globe2, Grid2X2, Hash, Highlighter, Image, IndentDecrease, IndentIncrease, Italic, Languages, Link2, List, ListChecks, ListOrdered, ListTree, 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, Square, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, Tags, TextWrap, Trash2, TriangleAlert, Type, Underline, Undo2, Unlink, Unlink2, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
10
10
  import { Node as model_Node } from "@tiptap/pm/model";
11
11
  import extension_color from "@tiptap/extension-color";
12
12
  import { TableKit } from "@tiptap/extension-table";
@@ -15,15 +15,15 @@ import font_size from "@tiptap/extension-text-style/font-size";
15
15
  import starter_kit from "@tiptap/starter-kit";
16
16
  import { BubbleMenu } from "@tiptap/react/menus";
17
17
  import { TableMap, isInTable, selectedRect } from "@tiptap/pm/tables";
18
- import { documentTableSizing, transferChangedDocumentTextStatistics, documentPageBordersVisible, documentUnderlineStyle, DOCUMENT_PAGE_BORDER_EDGES, documentScriptFontDirectFamily, normalizeDocumentColumns, clampDocumentMargin, materializeLazyDocumentEditorRoot, patchDocumentScriptFonts, documentKerningThresholdPoints, nextDocumentTabAlignment, documentTableRowOptions, normalizedTabPosition, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, documentCitationCount, resolveDocumentPageBorders, documentLazyHtmlChunkFragment, DocumentFontFamily, normalizeDocumentHiddenText, documentLegacyTextEffectsConflict, DOCUMENT_CHUNK_VISIBLE_IDS_META, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, documentCharacterPositionPoints, documentBulletListStyle, collectDocumentTextLayoutParagraphs, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, normalizeDocumentCharacterScalePercent, documentOrderedListState, normalizeDocumentPageChrome, documentTextStatistics, documentPageMarginsForLayout, invalidateDocumentLazyHtmlProjection, documentTableCellFormat, normalizeDocumentPageGeometry, normalizeDocumentImageLayer, documentImageProperties, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, parseDocumentScriptFonts, DocumentParagraphFormatting, activeDocumentSection, normalizeDocumentHtml, documentInitialSectionLayout, documentModelHasTrustedInitialIntegrityFeatures, documentParagraphDirection, documentParagraphPagination, documentModelUsesWindowing, documentPageChromeLegacyFields, documentChunkMountedIds, collectDocumentCommentAnchors, documentTextCaseKeyboardShortcuts, DocumentTextStyle, canChangeDocumentIndent, cssDocumentFontFamily, documentCharacterSpacingPoints, documentKerningIsEffective, DocumentSuperscript, documentSectionById, activeDocumentBookmark, DocumentEquation, documentLazyHtmlProjectionFingerprint, documentLazyHtmlProjection, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, DocumentStrike, mountWorkLiveDocumentCapture, registerDocumentPageSurfaceGeometry, documentHiddenTextKeyboardShortcut, syncDocumentContentFromHtml, documentLegacyTextEffectsCss, documentScriptFontSlotFromHint, editorDocumentCaptionTargets, resolveDocumentPageChrome, documentScriptFontFamilyForRendering, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, editorDocumentBookmarkReferenceTargets, serializeWorkDocumentNode, DOCUMENT_CHUNK_PAGINATION_META, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, documentModelForContent, documentLegacyTextEffectsFromTextStyleAttributes, normalizeDocumentEmphasisMark, selectedDocumentChunkId, documentCommentViews, documentParagraphSpacing, normalizeDocumentTabStops, patchDocumentLazyHtmlProjection, normalizeDocumentTextCase, serializeDocumentScriptFonts, documentUnderlineColor, documentBookmarkNameExists, collectDocumentChanges, DocumentImage, resolveDocumentPageMargins, updateDocumentPageMarginMode, canSetDocumentTableRowRepeatHeader, normalizeDocumentCharacterSpacingTwips, DocumentCharacterFormatting, millimetersToPixels as work_document_layout_millimetersToPixels, DOCUMENT_CHUNK_HYDRATION_META, documentTabLeaderLabel, createSchemaDerivedWorkDocumentModel, updateDocumentCustomPageMillimeters, DocumentUnderline, documentCommentDraftRange, documentParagraphTabStops, documentScriptFontSegments, documentUnderlineKeyboardShortcuts, documentParagraphIndent, documentFontNameFromCssFamily, DocumentScriptFontFormatting, canInsertDocumentComment, documentTableHorizontalAlignment, documentTextLayoutBatches, normalizeDocumentImageWrapSide, updateDocumentPageOrientation, documentCitationStyleDetails, validateDocumentBookmarkName, setCustomDocumentColumns, updateDocumentPageMarginMillimeters, documentCitationStyle, normalizeDocumentCharacterPositionHalfPoints, documentTransactionsOnlyHydrateChunks, normalizeDocumentKerningThresholdHalfPoints, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, documentPageMetrics, documentStrikeStyle, createDocumentBibliography, DocumentSubscript, DocumentParagraphIdentity, updateDocumentPageChromeVariant, updateDocumentMirrorMargins, activeDocumentTableStyle, normalizeDocumentScriptFontSlot, measureDocumentLayoutBlocksIncrementally, documentWordLineHeightFactor, normalizeDocumentLegacyTextEffect, createWorkDocumentExtensions } from "./6282.js";
18
+ import { documentTableSizing, transferChangedDocumentTextStatistics, documentPageBordersVisible, documentUnderlineStyle, DOCUMENT_PAGE_BORDER_EDGES, documentTableRowOptions, normalizeDocumentColumns, clampDocumentMargin, materializeLazyDocumentEditorRoot, documentKerningThresholdPoints, selectedDocumentIndexOptions, nextDocumentTabAlignment, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, normalizedTabPosition, documentCitationCount, resolveDocumentPageBorders, documentLazyHtmlChunkFragment, DocumentFontFamily, normalizeDocumentHiddenText, documentLegacyTextEffectsConflict, DOCUMENT_CHUNK_VISIBLE_IDS_META, selectedDocumentIndexDraft, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, documentCharacterPositionPoints, documentBulletListStyle, collectDocumentTextLayoutParagraphs, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, normalizeDocumentCharacterScalePercent, documentOrderedListState, normalizeDocumentPageChrome, documentTextStatistics, documentPageMarginsForLayout, invalidateDocumentLazyHtmlProjection, documentTableCellFormat, normalizeDocumentPageGeometry, normalizeDocumentImageLayer, documentImageProperties, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, activeDocumentSection, DocumentParagraphFormatting, normalizeDocumentHtml, documentInitialSectionLayout, documentModelHasTrustedInitialIntegrityFeatures, documentModelUsesWindowing, documentParagraphDirection, documentParagraphPagination, documentPageChromeLegacyFields, documentChunkMountedIds, collectDocumentCommentAnchors, documentTextCaseKeyboardShortcuts, DocumentTextStyle, canChangeDocumentIndent, documentCharacterSpacingPoints, documentKerningIsEffective, DocumentSuperscript, documentSectionById, activeDocumentBookmark, DocumentEquation, documentLazyHtmlProjectionFingerprint, documentLazyHtmlProjection, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, DocumentStrike, mountWorkLiveDocumentCapture, registerDocumentPageSurfaceGeometry, documentHiddenTextKeyboardShortcut, documentHasIndex, syncDocumentContentFromHtml, documentLegacyTextEffectsCss, editorDocumentCaptionTargets, resolveDocumentPageChrome, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, editorDocumentBookmarkReferenceTargets, serializeWorkDocumentNode, DOCUMENT_CHUNK_PAGINATION_META, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, documentModelForContent, documentLegacyTextEffectsFromTextStyleAttributes, normalizeDocumentEmphasisMark, selectedDocumentChunkId, documentCommentViews, documentParagraphSpacing, normalizeDocumentTabStops, patchDocumentLazyHtmlProjection, normalizeDocumentTextCase, documentUnderlineColor, documentBookmarkNameExists, collectDocumentChanges, DocumentImage, selectedDocumentTableOfContentsOptions, resolveDocumentPageMargins, updateDocumentPageMarginMode, canSetDocumentTableRowRepeatHeader, normalizeDocumentCharacterSpacingTwips, DocumentCharacterFormatting, millimetersToPixels as work_document_layout_millimetersToPixels, DOCUMENT_CHUNK_HYDRATION_META, documentTabLeaderLabel, createSchemaDerivedWorkDocumentModel, updateDocumentCustomPageMillimeters, DocumentUnderline, documentCommentDraftRange, documentParagraphTabStops, documentTableHorizontalAlignment, documentUnderlineKeyboardShortcuts, documentParagraphIndent, DocumentScriptFontFormatting, canInsertDocumentComment, documentHasTableOfContents, documentTextLayoutBatches, normalizeDocumentImageWrapSide, updateDocumentPageOrientation, documentCitationStyleDetails, validateDocumentBookmarkName, setCustomDocumentColumns, updateDocumentPageMarginMillimeters, documentCitationStyle, normalizeDocumentCharacterPositionHalfPoints, documentTransactionsOnlyHydrateChunks, normalizeDocumentKerningThresholdHalfPoints, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, documentPageMetrics, documentStrikeStyle, DocumentHighlight, createDocumentBibliography, DocumentSubscript, selectedDocumentIndexEntry, updateDocumentPageChromeVariant, updateDocumentMirrorMargins, activeDocumentTableStyle, measureDocumentLayoutBlocksIncrementally, documentWordLineHeightFactor, normalizeDocumentLegacyTextEffect, createWorkDocumentExtensions } from "./6282.js";
19
19
  import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, useOfficeDialog, useOfficeTaskPaneModal, CommittedOfficeNumberField, officeFontFamilyLabel, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField } from "./0~7048.js";
20
20
  import { moveOfficeMenuFocus, office_text_field_OfficeTextArea, Popover, officeOverlayPortalRoot, button_Button, useOfficePublishPresenceLocation, OfficeTiptapPresenceLayer, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom, office_text_field_OfficeFileInput } from "./0~6090.js";
21
21
  import { WorkOfficePreviewBar, isWorkspaceContextMenuKeyboardEvent, Tabs, WorkOfficeZoomControls, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton } from "./0~4595.js";
22
- import { documentBorderPresentation, normalizeDocumentRunBorder, parseDocumentRunBorder, DOCUMENT_RUN_BORDER_STYLES, isDocumentParagraphArtBorderStyle, serializeDocumentRunBorder, createOfficeId as createWorkId, documentRunBorderIsVisible } from "./4121.js";
22
+ import { documentFontNameFromCssFamily, normalizeDocumentRunBorder, parseDocumentScriptFonts, parseDocumentRunShading, DOCUMENT_RUN_BORDER_STYLES, serializeDocumentRunBorder, documentScriptFontDirectFamily, serializeDocumentRunShading, patchDocumentScriptFonts, serializeDocumentScriptFonts, documentRunBorderIsVisible, cssDocumentFontFamily, isDocumentParagraphArtBorderStyle, visibleWorkDocumentOutlineItems, DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS, createOfficeId as createWorkId, DEFAULT_DOCUMENT_INDEX_OPTIONS, normalizeDocumentLanguageTag, currentWorkDocumentOutlineItem, normalizeDocumentNoProof, parseDocumentRunBorder, DocumentParagraphIdentity, parseDocumentProofingLanguages, collectWorkDocumentOutline, documentScriptFontSlotFromHint, documentBorderPresentation, documentScriptFontFamilyForRendering, normalizeDocumentRunShading, normalizeDocumentScriptFontSlot, documentScriptFontSegments, patchDocumentProofingLanguages, serializeDocumentProofingLanguages, documentRunShadingDomAttributes } from "./4121.js";
23
23
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
24
24
  import { OfficeColorPicker, isOfficeShortcutBlocked } from "./0~3635.js";
25
25
  import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
26
- import { mergeOfficeTiptapExtensions, documentCurrentPage, documentPageCount, documentAgentMenuItems, createWorkDocumentSelectionSnapshot, documentPlainTextAsHtml, documentCustomSelectionMenuItems, createWorkDocumentSelectionAction } from "./0~5050.js";
26
+ import { mergeOfficeTiptapExtensions, documentHasRefreshableFields, documentCurrentPage, documentAgentMenuItems, documentPageCount, createWorkDocumentSelectionSnapshot, documentPlainTextAsHtml, createWorkDocumentSelectionAction, documentCustomSelectionMenuItems } from "./0~5050.js";
27
27
  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";
28
28
  import { useOfficeDraft, InlineNotice } from "./0~345.js";
29
29
  import { documentPageColor, normalizeDocumentPageColor } from "./0~work-document-page-color.js";
@@ -4087,6 +4087,9 @@ function createDocumentPageChromeEditorExtensions(placeholder = '输入页眉或
4087
4087
  DocumentFontFamily,
4088
4088
  font_size,
4089
4089
  extension_color,
4090
+ DocumentHighlight.configure({
4091
+ multicolor: true
4092
+ }),
4090
4093
  DocumentUnderline,
4091
4094
  DocumentStrike,
4092
4095
  DocumentCharacterFormatting,
@@ -4804,65 +4807,6 @@ function normalizeDocumentPageNumberInput(value) {
4804
4807
  const number = Number(value);
4805
4808
  return Number.isFinite(number) ? Math.min(9999, Math.max(1, Math.round(number))) : null;
4806
4809
  }
4807
- function collectWorkDocumentOutline(document1) {
4808
- const items = [];
4809
- const hierarchy = [];
4810
- document1.descendants((node, position)=>{
4811
- if ('heading' !== node.type.name) return;
4812
- const level = documentHeadingLevel(node.attrs.level);
4813
- while((hierarchy.at(-1)?.level ?? 0) >= level)hierarchy.pop();
4814
- const parent = hierarchy.at(-1);
4815
- const from = position + 1;
4816
- const item = {
4817
- id: `heading-${position}`,
4818
- text: normalizedDocumentHeadingText(node.textContent),
4819
- level,
4820
- depth: hierarchy.length,
4821
- from,
4822
- to: from + node.content.size,
4823
- ...parent ? {
4824
- parentId: parent.id
4825
- } : {}
4826
- };
4827
- items.push(item);
4828
- hierarchy.push(item);
4829
- });
4830
- return items.map((item, index)=>({
4831
- ...item,
4832
- hasChildren: (items[index + 1]?.depth ?? -1) > item.depth
4833
- }));
4834
- }
4835
- function currentWorkDocumentOutlineItem(items, position) {
4836
- let current = null;
4837
- for (const item of items){
4838
- if (item.from > position) break;
4839
- current = item;
4840
- }
4841
- return current;
4842
- }
4843
- function visibleWorkDocumentOutlineItems(items, collapsedIds, rawQuery) {
4844
- const query = normalizedDocumentOutlineQuery(rawQuery);
4845
- if (query) return items.filter((item)=>normalizedDocumentOutlineQuery(item.text).includes(query));
4846
- const visible = [];
4847
- let hiddenBelowDepth = null;
4848
- for (const item of items){
4849
- if (null !== hiddenBelowDepth && item.depth <= hiddenBelowDepth) hiddenBelowDepth = null;
4850
- if (null === hiddenBelowDepth) {
4851
- visible.push(item);
4852
- if (item.hasChildren && collapsedIds.has(item.id)) hiddenBelowDepth = item.depth;
4853
- }
4854
- }
4855
- return visible;
4856
- }
4857
- function documentHeadingLevel(value) {
4858
- return 'number' == typeof value && Number.isInteger(value) && value >= 1 && value <= 6 ? value : 1;
4859
- }
4860
- function normalizedDocumentHeadingText(value) {
4861
- return value.replace(/\s+/g, ' ').trim() || '未命名标题';
4862
- }
4863
- function normalizedDocumentOutlineQuery(value) {
4864
- return value.normalize('NFKC').trim().toLocaleLowerCase();
4865
- }
4866
4810
  const DOCUMENT_OUTLINE_ITEM_HEIGHT = 31;
4867
4811
  const DOCUMENT_OUTLINE_LIST_PADDING_TOP = 6;
4868
4812
  const document_outline_navigation_DocumentOutlineNavigation = /*#__PURE__*/ forwardRef(function({ activeItemId, collapsedIds, items, rovingId, onNavigate, onRovingIdChange, onToggleCollapsed }, ref) {
@@ -7521,6 +7465,51 @@ const documentCommandCatalog = {
7521
7465
  ]
7522
7466
  }
7523
7467
  },
7468
+ tableOfContents: {
7469
+ id: 'references.tableOfContents',
7470
+ label: '插入或自定义目录',
7471
+ location: {
7472
+ area: 'ribbon',
7473
+ tab: 'references',
7474
+ group: 'tableOfContents'
7475
+ }
7476
+ },
7477
+ refreshTableOfContents: {
7478
+ id: 'references.refreshTableOfContents',
7479
+ label: '更新目录',
7480
+ location: {
7481
+ area: 'ribbon',
7482
+ tab: 'references',
7483
+ group: 'tableOfContents'
7484
+ }
7485
+ },
7486
+ markIndexEntry: {
7487
+ id: 'references.markIndexEntry',
7488
+ label: '标记索引项',
7489
+ location: {
7490
+ area: 'ribbon',
7491
+ tab: 'references',
7492
+ group: 'index'
7493
+ }
7494
+ },
7495
+ index: {
7496
+ id: 'references.index',
7497
+ label: '插入或自定义索引',
7498
+ location: {
7499
+ area: 'ribbon',
7500
+ tab: 'references',
7501
+ group: 'index'
7502
+ }
7503
+ },
7504
+ refreshIndex: {
7505
+ id: 'references.refreshIndex',
7506
+ label: '更新索引',
7507
+ location: {
7508
+ area: 'ribbon',
7509
+ tab: 'references',
7510
+ group: 'index'
7511
+ }
7512
+ },
7524
7513
  refreshFields: {
7525
7514
  id: 'references.refreshFields',
7526
7515
  label: '更新域',
@@ -8107,6 +8096,450 @@ function DocumentStatusBar({ bibliographyCount, citationCount, currentPage, page
8107
8096
  ]
8108
8097
  });
8109
8098
  }
8099
+ function synchronizeDocumentEditorSelectionFromDom(editor) {
8100
+ if (editor.isDestroyed) return false;
8101
+ const { view } = editor;
8102
+ const domSelection = view.dom.ownerDocument.getSelection();
8103
+ if (!domSelection || domSelection.isCollapsed || 1 !== domSelection.rangeCount) return false;
8104
+ const range = domSelection.getRangeAt(0);
8105
+ if (!view.dom.contains(range.startContainer) || !view.dom.contains(range.endContainer)) return false;
8106
+ let from;
8107
+ let to;
8108
+ try {
8109
+ from = view.posAtDOM(range.startContainer, range.startOffset, 1);
8110
+ to = view.posAtDOM(range.endContainer, range.endOffset, -1);
8111
+ } catch {
8112
+ return false;
8113
+ }
8114
+ const maximum = editor.state.doc.content.size;
8115
+ if (from < 0 || to <= from || to > maximum) return false;
8116
+ const nextSelection = TextSelection.between(editor.state.doc.resolve(from), editor.state.doc.resolve(to), 1);
8117
+ if (nextSelection.empty || nextSelection.eq(editor.state.selection)) return false;
8118
+ view.dispatch(editor.state.tr.setSelection(nextSelection).setMeta('addToHistory', false));
8119
+ return true;
8120
+ }
8121
+ const proofingStateOptions = [
8122
+ {
8123
+ value: 'mixed',
8124
+ label: '混合(保持不变)',
8125
+ disabled: true
8126
+ },
8127
+ {
8128
+ value: 'inherit',
8129
+ label: '跟随样式'
8130
+ },
8131
+ {
8132
+ value: 'check',
8133
+ label: '检查拼写和语法'
8134
+ },
8135
+ {
8136
+ value: 'skip',
8137
+ label: '不检查拼写或语法'
8138
+ }
8139
+ ];
8140
+ const proofingLanguageSuggestions = [
8141
+ 'en-US',
8142
+ 'en-GB',
8143
+ 'zh-CN',
8144
+ 'zh-TW',
8145
+ 'ja-JP',
8146
+ 'ko-KR',
8147
+ 'ar-SA',
8148
+ 'he-IL',
8149
+ 'fr-FR',
8150
+ 'de-DE',
8151
+ 'es-ES',
8152
+ 'x-none'
8153
+ ];
8154
+ function DocumentProofingDialog({ source, restoreFocusTarget, onApply, onClose }) {
8155
+ const [draft, setDraft] = useState(()=>({
8156
+ latin: source.latin.value ?? '',
8157
+ eastAsia: source.eastAsia.value ?? '',
8158
+ bidi: source.bidi.value ?? '',
8159
+ noProof: proofingStateDraft(source)
8160
+ }));
8161
+ const [touched, setTouched] = useState({
8162
+ latin: false,
8163
+ eastAsia: false,
8164
+ bidi: false,
8165
+ noProof: false
8166
+ });
8167
+ const formId = useId();
8168
+ const datalistId = useId();
8169
+ const error = proofingDialogError(draft, touched);
8170
+ const patch = proofingDialogPatch(source, draft, touched);
8171
+ const hasChanges = Object.keys(patch).length > 0;
8172
+ const submit = (event)=>{
8173
+ event?.preventDefault();
8174
+ if (!hasChanges || error) return;
8175
+ if (onApply(patch)) onClose();
8176
+ };
8177
+ return /*#__PURE__*/ jsx(Dialog, {
8178
+ title: "设置校对语言",
8179
+ description: source.selectedCharacters ? `为选中的 ${source.selectedCharacters} 个字符分别设置拉丁、东亚和双向文字校对语言。` : '设置当前位置后续输入文字的校对语言。',
8180
+ className: "work-document-proofing-dialog",
8181
+ restoreFocusTarget: restoreFocusTarget,
8182
+ onClose: onClose,
8183
+ footer: /*#__PURE__*/ jsxs(Fragment, {
8184
+ children: [
8185
+ /*#__PURE__*/ jsx(button_Button, {
8186
+ tone: "quiet",
8187
+ onClick: onClose,
8188
+ children: "取消"
8189
+ }),
8190
+ /*#__PURE__*/ jsx(button_Button, {
8191
+ tone: "primary",
8192
+ type: "submit",
8193
+ form: formId,
8194
+ disabled: !hasChanges || Boolean(error),
8195
+ children: "应用"
8196
+ })
8197
+ ]
8198
+ }),
8199
+ children: /*#__PURE__*/ jsxs("form", {
8200
+ id: formId,
8201
+ onSubmit: submit,
8202
+ children: [
8203
+ /*#__PURE__*/ jsxs("fieldset", {
8204
+ children: [
8205
+ /*#__PURE__*/ jsx("legend", {
8206
+ children: "按文字系统设置语言"
8207
+ }),
8208
+ /*#__PURE__*/ jsx(ProofingLanguageField, {
8209
+ label: "拉丁文字",
8210
+ languageKey: "latin",
8211
+ value: draft.latin,
8212
+ mixed: source.latin.mixed && !touched.latin,
8213
+ list: datalistId,
8214
+ initialFocus: true,
8215
+ error: touched.latin && !validLanguageDraft(draft.latin),
8216
+ onChange: (value)=>{
8217
+ setDraft((current)=>({
8218
+ ...current,
8219
+ latin: value
8220
+ }));
8221
+ setTouched((current)=>({
8222
+ ...current,
8223
+ latin: true
8224
+ }));
8225
+ }
8226
+ }),
8227
+ /*#__PURE__*/ jsx(ProofingLanguageField, {
8228
+ label: "东亚文字",
8229
+ languageKey: "eastAsia",
8230
+ value: draft.eastAsia,
8231
+ mixed: source.eastAsia.mixed && !touched.eastAsia,
8232
+ list: datalistId,
8233
+ error: touched.eastAsia && !validLanguageDraft(draft.eastAsia),
8234
+ onChange: (value)=>{
8235
+ setDraft((current)=>({
8236
+ ...current,
8237
+ eastAsia: value
8238
+ }));
8239
+ setTouched((current)=>({
8240
+ ...current,
8241
+ eastAsia: true
8242
+ }));
8243
+ }
8244
+ }),
8245
+ /*#__PURE__*/ jsx(ProofingLanguageField, {
8246
+ label: "双向文字",
8247
+ languageKey: "bidi",
8248
+ value: draft.bidi,
8249
+ mixed: source.bidi.mixed && !touched.bidi,
8250
+ list: datalistId,
8251
+ error: touched.bidi && !validLanguageDraft(draft.bidi),
8252
+ onChange: (value)=>{
8253
+ setDraft((current)=>({
8254
+ ...current,
8255
+ bidi: value
8256
+ }));
8257
+ setTouched((current)=>({
8258
+ ...current,
8259
+ bidi: true
8260
+ }));
8261
+ }
8262
+ }),
8263
+ /*#__PURE__*/ jsx("datalist", {
8264
+ id: datalistId,
8265
+ children: proofingLanguageSuggestions.map((language)=>/*#__PURE__*/ jsx("option", {
8266
+ value: language
8267
+ }, language))
8268
+ })
8269
+ ]
8270
+ }),
8271
+ /*#__PURE__*/ jsxs("div", {
8272
+ className: "work-document-proofing-dialog-state",
8273
+ children: [
8274
+ /*#__PURE__*/ jsx("span", {
8275
+ className: "work-document-proofing-dialog-state-label",
8276
+ "aria-hidden": "true",
8277
+ children: "校对行为"
8278
+ }),
8279
+ /*#__PURE__*/ jsx(OfficeSelect, {
8280
+ ariaLabel: "校对行为",
8281
+ value: draft.noProof,
8282
+ options: proofingStateOptions,
8283
+ onValueChange: (noProof)=>{
8284
+ setDraft((current)=>({
8285
+ ...current,
8286
+ noProof
8287
+ }));
8288
+ setTouched((current)=>({
8289
+ ...current,
8290
+ noProof: true
8291
+ }));
8292
+ }
8293
+ }),
8294
+ source.noProof.mixed && !touched.noProof && /*#__PURE__*/ jsx("p", {
8295
+ role: "status",
8296
+ children: "当前选区包含不同的校对行为,保持不变。"
8297
+ })
8298
+ ]
8299
+ }),
8300
+ /*#__PURE__*/ jsxs("p", {
8301
+ className: "work-document-proofing-dialog-help",
8302
+ children: [
8303
+ "使用 BCP 47 语言标记,例如 ",
8304
+ /*#__PURE__*/ jsx("code", {
8305
+ children: "en-US"
8306
+ }),
8307
+ "、",
8308
+ /*#__PURE__*/ jsx("code", {
8309
+ children: "zh-CN"
8310
+ }),
8311
+ " 或",
8312
+ ' ',
8313
+ /*#__PURE__*/ jsx("code", {
8314
+ children: "ar-SA"
8315
+ }),
8316
+ "。留空或选择“跟随样式”会移除直接格式。"
8317
+ ]
8318
+ }),
8319
+ error && /*#__PURE__*/ jsx("p", {
8320
+ className: "work-document-proofing-dialog-error",
8321
+ role: "alert",
8322
+ children: error
8323
+ })
8324
+ ]
8325
+ })
8326
+ });
8327
+ }
8328
+ function ProofingLanguageField({ label, languageKey, value, mixed, list, initialFocus = false, error, onChange }) {
8329
+ return /*#__PURE__*/ jsxs("div", {
8330
+ className: "work-document-proofing-dialog-language",
8331
+ children: [
8332
+ /*#__PURE__*/ jsx("label", {
8333
+ htmlFor: `work-document-proofing-${languageKey}`,
8334
+ children: label
8335
+ }),
8336
+ /*#__PURE__*/ jsxs("div", {
8337
+ children: [
8338
+ /*#__PURE__*/ jsx(office_text_field_OfficeTextField, {
8339
+ id: `work-document-proofing-${languageKey}`,
8340
+ "aria-label": `${label}校对语言`,
8341
+ "aria-invalid": error || void 0,
8342
+ "data-autofocus": initialFocus ? 'true' : void 0,
8343
+ list: list,
8344
+ value: value,
8345
+ placeholder: mixed ? '混合(保持不变)' : '跟随样式',
8346
+ spellCheck: false,
8347
+ onChange: (event)=>onChange(event.currentTarget.value)
8348
+ }),
8349
+ /*#__PURE__*/ jsx(button_Button, {
8350
+ tone: "quiet",
8351
+ type: "button",
8352
+ "aria-label": `${label}跟随样式`,
8353
+ onClick: ()=>onChange(''),
8354
+ children: "跟随样式"
8355
+ })
8356
+ ]
8357
+ }),
8358
+ mixed && /*#__PURE__*/ jsxs("p", {
8359
+ role: "status",
8360
+ children: [
8361
+ "当前选区包含不同的",
8362
+ label,
8363
+ "校对语言,输入后才会统一修改。"
8364
+ ]
8365
+ })
8366
+ ]
8367
+ });
8368
+ }
8369
+ function proofingStateDraft(source) {
8370
+ if (source.noProof.mixed) return 'mixed';
8371
+ if (null === source.noProof.value) return 'inherit';
8372
+ return source.noProof.value ? 'skip' : 'check';
8373
+ }
8374
+ function proofingDialogPatch(source, draft, touched) {
8375
+ const languages = {};
8376
+ for (const key of [
8377
+ 'latin',
8378
+ 'eastAsia',
8379
+ 'bidi'
8380
+ ]){
8381
+ if (!touched[key] || !validLanguageDraft(draft[key])) continue;
8382
+ const value = draft[key] || null;
8383
+ if (source[key].mixed || source[key].value !== value) languages[key] = value;
8384
+ }
8385
+ const patch = {};
8386
+ if (Object.keys(languages).length) patch.languages = languages;
8387
+ if (touched.noProof && 'mixed' !== draft.noProof) {
8388
+ const noProof = 'inherit' === draft.noProof ? null : 'skip' === draft.noProof;
8389
+ if (source.noProof.mixed || source.noProof.value !== noProof) patch.noProof = noProof;
8390
+ }
8391
+ return patch;
8392
+ }
8393
+ function proofingDialogError(draft, touched) {
8394
+ for (const key of [
8395
+ 'latin',
8396
+ 'eastAsia',
8397
+ 'bidi'
8398
+ ])if (touched[key] && !validLanguageDraft(draft[key])) return '请输入有效的 BCP 47 语言标记;不能包含空格、下划线或控制字符。';
8399
+ return null;
8400
+ }
8401
+ function validLanguageDraft(value) {
8402
+ return '' === value || null !== normalizeDocumentLanguageTag(value);
8403
+ }
8404
+ const PROOFING_LANGUAGE_SLOTS = [
8405
+ 'latin',
8406
+ 'eastAsia',
8407
+ 'bidi'
8408
+ ];
8409
+ const PROOFING_LANGUAGE_SLOT_SET = new Set(PROOFING_LANGUAGE_SLOTS);
8410
+ function documentProofingDialogSource(editor) {
8411
+ const latin = new Map();
8412
+ const eastAsia = new Map();
8413
+ const bidi = new Map();
8414
+ const noProof = new Map();
8415
+ const { doc, selection } = editor.state;
8416
+ const addValues = (attributes)=>{
8417
+ const languages = parseDocumentProofingLanguages(attributes.proofingLanguages);
8418
+ addSelectedValue(latin, languages?.latin ?? null);
8419
+ addSelectedValue(eastAsia, languages?.eastAsia ?? null);
8420
+ addSelectedValue(bidi, languages?.bidi ?? null);
8421
+ addSelectedValue(noProof, normalizeDocumentNoProof(attributes.noProof));
8422
+ };
8423
+ if (selection.empty) addValues(editor.getAttributes('textStyle'));
8424
+ else doc.nodesBetween(selection.from, selection.to, (node, position)=>{
8425
+ if (!node.isText || position >= selection.to || position + node.nodeSize <= selection.from) return;
8426
+ const textStyle = node.marks.find((mark)=>'textStyle' === mark.type.name);
8427
+ addValues(textStyle?.attrs ?? {});
8428
+ });
8429
+ if (!latin.size) addValues(editor.getAttributes('textStyle'));
8430
+ const selectedText = selection.empty ? '' : doc.textBetween(selection.from, selection.to, '', '');
8431
+ return {
8432
+ latin: selectedValue(latin),
8433
+ eastAsia: selectedValue(eastAsia),
8434
+ bidi: selectedValue(bidi),
8435
+ noProof: selectedValue(noProof),
8436
+ selectedCharacters: Array.from(selectedText).length
8437
+ };
8438
+ }
8439
+ function applyDocumentProofingDialogPatch(editor, selection, patch) {
8440
+ if (!validDocumentProofingDialogPatch(patch) || editor.isDestroyed) return false;
8441
+ const maximum = editor.state.doc.content.size;
8442
+ if (!Number.isSafeInteger(selection.from) || !Number.isSafeInteger(selection.to) || selection.from < 0 || selection.to < selection.from || selection.to > maximum) return false;
8443
+ const textStyle = editor.state.schema.marks.textStyle;
8444
+ if (!textStyle) return false;
8445
+ const transaction = editor.state.tr;
8446
+ try {
8447
+ transaction.setSelection(TextSelection.create(transaction.doc, selection.from, selection.to));
8448
+ } catch {
8449
+ return false;
8450
+ }
8451
+ if (selection.from === selection.to) {
8452
+ const marks = transaction.selection.$from.marks();
8453
+ const current = marks.find((mark)=>mark.type === textStyle);
8454
+ const attributes = patchedProofingAttributes(current, patch);
8455
+ if (!attributes) return false;
8456
+ const retained = marks.filter((mark)=>mark.type !== textStyle);
8457
+ if (textStyleAttributesHaveValue(attributes)) retained.push(textStyle.create(attributes));
8458
+ transaction.setStoredMarks(retained);
8459
+ transaction.scrollIntoView();
8460
+ editor.view.dispatch(transaction);
8461
+ editor.view.focus();
8462
+ return true;
8463
+ }
8464
+ const updates = [];
8465
+ transaction.doc.nodesBetween(selection.from, selection.to, (node, position)=>{
8466
+ if (!node.isText || !node.text) return;
8467
+ const from = Math.max(selection.from, position);
8468
+ const to = Math.min(selection.to, position + node.nodeSize);
8469
+ if (to <= from) return;
8470
+ const current = node.marks.find((mark)=>mark.type === textStyle);
8471
+ const attributes = patchedProofingAttributes(current, patch);
8472
+ if (attributes) updates.push({
8473
+ from,
8474
+ to,
8475
+ current,
8476
+ attributes
8477
+ });
8478
+ });
8479
+ for (const update of updates){
8480
+ if (update.current) transaction.removeMark(update.from, update.to, update.current);
8481
+ if (textStyleAttributesHaveValue(update.attributes)) transaction.addMark(update.from, update.to, textStyle.create(update.attributes));
8482
+ }
8483
+ if (!transaction.docChanged) return false;
8484
+ editor.view.dispatch(transaction.scrollIntoView());
8485
+ editor.view.focus();
8486
+ return true;
8487
+ }
8488
+ function patchedProofingAttributes(current, patch) {
8489
+ const attributes = {
8490
+ ...current?.attrs ?? {}
8491
+ };
8492
+ let changed = false;
8493
+ if (patch.languages) {
8494
+ const currentLanguages = parseDocumentProofingLanguages(current?.attrs.proofingLanguages);
8495
+ const nextLanguages = patchDocumentProofingLanguages(currentLanguages, patch.languages);
8496
+ const currentSerialized = serializeDocumentProofingLanguages(currentLanguages) ?? null;
8497
+ const nextSerialized = serializeDocumentProofingLanguages(nextLanguages) ?? null;
8498
+ if (currentSerialized !== nextSerialized) {
8499
+ attributes.proofingLanguages = nextSerialized;
8500
+ changed = true;
8501
+ }
8502
+ }
8503
+ if (void 0 !== patch.noProof) {
8504
+ const currentNoProof = normalizeDocumentNoProof(current?.attrs.noProof);
8505
+ if (currentNoProof !== patch.noProof) {
8506
+ attributes.noProof = patch.noProof;
8507
+ changed = true;
8508
+ }
8509
+ }
8510
+ return changed ? attributes : null;
8511
+ }
8512
+ function validDocumentProofingDialogPatch(patch) {
8513
+ if (!isRecord(patch)) return false;
8514
+ const keys = Object.keys(patch);
8515
+ if (!keys.length || keys.some((key)=>'languages' !== key && 'noProof' !== key)) return false;
8516
+ if (void 0 !== patch.noProof && null !== patch.noProof && null === normalizeDocumentNoProof(patch.noProof)) return false;
8517
+ if (void 0 !== patch.languages) {
8518
+ if (!isRecord(patch.languages)) return false;
8519
+ const languageEntries = Object.entries(patch.languages);
8520
+ if (!languageEntries.length || languageEntries.some(([slot, language])=>!PROOFING_LANGUAGE_SLOT_SET.has(slot) || null !== language && null === normalizeDocumentLanguageTag(language))) return false;
8521
+ }
8522
+ return void 0 !== patch.languages || void 0 !== patch.noProof;
8523
+ }
8524
+ function addSelectedValue(values, value) {
8525
+ values.set(null === value ? 'inherited' : String(value), value);
8526
+ }
8527
+ function selectedValue(values) {
8528
+ if (1 !== values.size) return {
8529
+ mixed: true,
8530
+ value: null
8531
+ };
8532
+ return {
8533
+ mixed: false,
8534
+ value: values.values().next().value ?? null
8535
+ };
8536
+ }
8537
+ function textStyleAttributesHaveValue(attributes) {
8538
+ return Object.values(attributes).some((value)=>null != value && '' !== value);
8539
+ }
8540
+ function isRecord(source) {
8541
+ return 'object' == typeof source && null !== source && !Array.isArray(source);
8542
+ }
8110
8543
  function DocumentFormatTools({ editor }) {
8111
8544
  const hasFormat = useSyncExternalStore(subscribeDocumentFormatClipboard, hasDocumentFormatClipboard, hasDocumentFormatClipboard);
8112
8545
  const [formatPainterActive, setFormatPainterActive] = useState(false);
@@ -9194,7 +9627,7 @@ function applyDocumentScriptFontPatch(editor, selection, scalarPatch, scriptFont
9194
9627
  const current = marks.find((mark)=>mark.type === textStyle);
9195
9628
  const attributes = patchedTextStyleAttributes(current, scalarPatch, scriptFontPatch, normalizeDocumentScriptFontSlot(current?.attrs.scriptFontSlot) ?? documentScriptFontSlotFromHint(parseDocumentScriptFonts(current?.attrs.scriptFonts)?.hint));
9196
9629
  const retained = marks.filter((mark)=>mark.type !== textStyle);
9197
- if (textStyleAttributesHaveValue(attributes)) retained.push(textStyle.create(attributes));
9630
+ if (document_font_dialog_script_font_model_textStyleAttributesHaveValue(attributes)) retained.push(textStyle.create(attributes));
9198
9631
  transaction.setStoredMarks(retained);
9199
9632
  transaction.scrollIntoView();
9200
9633
  editor.view.dispatch(transaction);
@@ -9221,7 +9654,7 @@ function applyDocumentScriptFontPatch(editor, selection, scalarPatch, scriptFont
9221
9654
  });
9222
9655
  for (const update of updates){
9223
9656
  if (update.current) transaction.removeMark(update.from, update.to, update.current);
9224
- if (textStyleAttributesHaveValue(update.attributes)) transaction.addMark(update.from, update.to, textStyle.create(update.attributes));
9657
+ if (document_font_dialog_script_font_model_textStyleAttributesHaveValue(update.attributes)) transaction.addMark(update.from, update.to, textStyle.create(update.attributes));
9225
9658
  }
9226
9659
  if (!transaction.docChanged) return false;
9227
9660
  editor.view.dispatch(transaction.scrollIntoView());
@@ -9250,7 +9683,7 @@ function patchedTextStyleAttributes(current, scalarPatch, scriptFontPatch, slot,
9250
9683
  attributes.wordLineHeightFactor = family ? documentWordLineHeightFactor(family) : null;
9251
9684
  return attributes;
9252
9685
  }
9253
- function textStyleAttributesHaveValue(attributes) {
9686
+ function document_font_dialog_script_font_model_textStyleAttributesHaveValue(attributes) {
9254
9687
  return Object.values(attributes).some((value)=>null != value && '' !== value);
9255
9688
  }
9256
9689
  function validScriptFontPatch(patch) {
@@ -9343,7 +9776,88 @@ function runBorderSpaceFromDraft(draft) {
9343
9776
  function formatPoints(value) {
9344
9777
  return Number(value.toFixed(3)).toString();
9345
9778
  }
9346
- function documentFontDialogSource(editor) {
9779
+ function addDocumentFontDialogRunShadingValue(values, source) {
9780
+ const shading = parseDocumentRunShading(source);
9781
+ const serialized = serializeDocumentRunShading(shading);
9782
+ values.set(serialized ?? 'inherited', shading);
9783
+ }
9784
+ function selectedDocumentFontDialogRunShadingValue(values) {
9785
+ return 1 === values.size ? {
9786
+ mixed: false,
9787
+ value: values.values().next().value ?? null
9788
+ } : {
9789
+ mixed: true,
9790
+ value: null
9791
+ };
9792
+ }
9793
+ function createDocumentFontDialogRunShadingDraft(source) {
9794
+ const shading = source.value;
9795
+ return {
9796
+ runShadingMode: source.mixed ? 'mixed' : shading ? 'nil' === shading.pattern ? 'none' : 'value' : 'inherit',
9797
+ runShadingPattern: shading && 'nil' !== shading.pattern ? shading.pattern : 'clear',
9798
+ runShadingColor: shading?.color?.value ?? 'auto',
9799
+ runShadingFill: shading?.fill?.value ?? 'auto'
9800
+ };
9801
+ }
9802
+ function documentFontDialogRunShadingDraftError(draft) {
9803
+ if ('value' !== draft.runShadingMode) return null;
9804
+ if (!validColor(draft.runShadingColor)) return '请选择有效的字符底纹前景色。';
9805
+ if (!validColor(draft.runShadingFill)) return '请选择有效的字符底纹背景色。';
9806
+ return null;
9807
+ }
9808
+ function documentFontDialogRunShadingPatch(source, draft, touched) {
9809
+ if (!touched || 'mixed' === draft.runShadingMode) return {};
9810
+ if ('inherit' === draft.runShadingMode) return source.mixed || source.value ? {
9811
+ runShading: null
9812
+ } : {};
9813
+ const shading = 'none' === draft.runShadingMode ? {
9814
+ pattern: 'nil'
9815
+ } : documentFontDialogRunShadingFromDraft(source, draft);
9816
+ if (!shading) return {};
9817
+ return serializeDocumentRunShading(source.value) === serializeDocumentRunShading(shading) ? {} : {
9818
+ runShading: shading
9819
+ };
9820
+ }
9821
+ function documentFontDialogRunShadingFromDraft(source, draft) {
9822
+ if ('none' === draft.runShadingMode) return {
9823
+ pattern: 'nil'
9824
+ };
9825
+ if ('value' !== draft.runShadingMode) return source.value;
9826
+ return normalizeDocumentRunShading({
9827
+ pattern: draft.runShadingPattern,
9828
+ ...shadingColorPatch('color', draft.runShadingColor, source.value?.color),
9829
+ ...shadingColorPatch('fill', draft.runShadingFill, source.value?.fill)
9830
+ });
9831
+ }
9832
+ function documentFontDialogRunShadingPreviewStyle(source, draft) {
9833
+ const shading = documentFontDialogRunShadingFromDraft(source, draft);
9834
+ const cssText = documentRunShadingDomAttributes(shading).style;
9835
+ if (!cssText) return {};
9836
+ const probe = document.createElement('span');
9837
+ probe.style.cssText = cssText;
9838
+ return {
9839
+ backgroundColor: probe.style.backgroundColor || void 0,
9840
+ backgroundImage: probe.style.backgroundImage || void 0,
9841
+ backgroundSize: probe.style.backgroundSize || void 0,
9842
+ boxDecorationBreak: 'clone',
9843
+ WebkitBoxDecorationBreak: 'clone'
9844
+ };
9845
+ }
9846
+ function shadingColorPatch(name, value, source) {
9847
+ if (!source && 'auto' === value) return {};
9848
+ return {
9849
+ [name]: {
9850
+ value,
9851
+ ...source?.theme && source.value === value ? {
9852
+ theme: source.theme
9853
+ } : {}
9854
+ }
9855
+ };
9856
+ }
9857
+ function validColor(value) {
9858
+ return 'auto' === value || /^#[0-9a-f]{6}$/i.test(value);
9859
+ }
9860
+ function documentFontDialogSource(editor) {
9347
9861
  const { doc, selection } = editor.state;
9348
9862
  const scaleValues = new Map();
9349
9863
  const positionValues = new Map();
@@ -9356,6 +9870,7 @@ function documentFontDialogSource(editor) {
9356
9870
  const legacyTextEmbossValues = new Map();
9357
9871
  const legacyTextImprintValues = new Map();
9358
9872
  const runBorderValues = new Map();
9873
+ const runShadingValues = new Map();
9359
9874
  const latinFontValues = new Map();
9360
9875
  const eastAsiaFontValues = new Map();
9361
9876
  const complexScriptFontValues = new Map();
@@ -9371,6 +9886,7 @@ function documentFontDialogSource(editor) {
9371
9886
  addLegacyTextEffectValue(legacyTextEmbossValues, attributes.legacyTextEmboss);
9372
9887
  addLegacyTextEffectValue(legacyTextImprintValues, attributes.legacyTextImprint);
9373
9888
  addDocumentFontDialogRunBorderValue(runBorderValues, attributes.runBorder);
9889
+ addDocumentFontDialogRunShadingValue(runShadingValues, attributes.runShading);
9374
9890
  addDocumentScriptFontValues(latinFontValues, eastAsiaFontValues, complexScriptFontValues, attributes);
9375
9891
  };
9376
9892
  if (selection.empty) addValues(editor.getAttributes('textStyle'));
@@ -9379,21 +9895,22 @@ function documentFontDialogSource(editor) {
9379
9895
  const textStyle = node.marks.find((mark)=>'textStyle' === mark.type.name);
9380
9896
  addValues(textStyle?.attrs ?? {});
9381
9897
  });
9382
- if (!scaleValues.size || !spacingValues.size || !positionValues.size || !kerningValues.size || !emphasisValues.size || !hiddenTextValues.size || !legacyTextOutlineValues.size || !legacyTextShadowValues.size || !legacyTextEmbossValues.size || !legacyTextImprintValues.size || !runBorderValues.size || !latinFontValues.size || !eastAsiaFontValues.size || !complexScriptFontValues.size) addValues(editor.getAttributes('textStyle'));
9383
- const characterScale = selectedValue(scaleValues);
9384
- const characterPosition = selectedValue(positionValues);
9385
- const characterSpacing = selectedValue(spacingValues);
9386
- const kerningThreshold = selectedValue(kerningValues);
9387
- const emphasisMark = selectedValue(emphasisValues);
9388
- const hiddenText = selectedValue(hiddenTextValues);
9389
- const legacyTextOutline = selectedValue(legacyTextOutlineValues);
9390
- const legacyTextShadow = selectedValue(legacyTextShadowValues);
9391
- const legacyTextEmboss = selectedValue(legacyTextEmbossValues);
9392
- const legacyTextImprint = selectedValue(legacyTextImprintValues);
9898
+ if (!scaleValues.size || !spacingValues.size || !positionValues.size || !kerningValues.size || !emphasisValues.size || !hiddenTextValues.size || !legacyTextOutlineValues.size || !legacyTextShadowValues.size || !legacyTextEmbossValues.size || !legacyTextImprintValues.size || !runBorderValues.size || !runShadingValues.size || !latinFontValues.size || !eastAsiaFontValues.size || !complexScriptFontValues.size) addValues(editor.getAttributes('textStyle'));
9899
+ const characterScale = document_font_dialog_model_selectedValue(scaleValues);
9900
+ const characterPosition = document_font_dialog_model_selectedValue(positionValues);
9901
+ const characterSpacing = document_font_dialog_model_selectedValue(spacingValues);
9902
+ const kerningThreshold = document_font_dialog_model_selectedValue(kerningValues);
9903
+ const emphasisMark = document_font_dialog_model_selectedValue(emphasisValues);
9904
+ const hiddenText = document_font_dialog_model_selectedValue(hiddenTextValues);
9905
+ const legacyTextOutline = document_font_dialog_model_selectedValue(legacyTextOutlineValues);
9906
+ const legacyTextShadow = document_font_dialog_model_selectedValue(legacyTextShadowValues);
9907
+ const legacyTextEmboss = document_font_dialog_model_selectedValue(legacyTextEmbossValues);
9908
+ const legacyTextImprint = document_font_dialog_model_selectedValue(legacyTextImprintValues);
9393
9909
  const runBorder = selectedDocumentFontDialogRunBorderValue(runBorderValues);
9394
- const latinFont = selectedValue(latinFontValues);
9395
- const eastAsiaFont = selectedValue(eastAsiaFontValues);
9396
- const complexScriptFont = selectedValue(complexScriptFontValues);
9910
+ const runShading = selectedDocumentFontDialogRunShadingValue(runShadingValues);
9911
+ const latinFont = document_font_dialog_model_selectedValue(latinFontValues);
9912
+ const eastAsiaFont = document_font_dialog_model_selectedValue(eastAsiaFontValues);
9913
+ const complexScriptFont = document_font_dialog_model_selectedValue(complexScriptFontValues);
9397
9914
  const textStyle = editor.getAttributes('textStyle');
9398
9915
  const selectedText = selection.empty ? '' : doc.textBetween(selection.from, selection.to, ' ', ' ').replace(/\s+/g, ' ').trim();
9399
9916
  return {
@@ -9408,6 +9925,7 @@ function documentFontDialogSource(editor) {
9408
9925
  legacyTextEmboss,
9409
9926
  legacyTextImprint,
9410
9927
  runBorder,
9928
+ runShading,
9411
9929
  latinFont,
9412
9930
  eastAsiaFont,
9413
9931
  complexScriptFont,
@@ -9440,6 +9958,7 @@ function createDocumentFontDialogDraft(source) {
9440
9958
  legacyTextEmboss: source.legacyTextEmboss.value ?? false,
9441
9959
  legacyTextImprint: source.legacyTextImprint.value ?? false,
9442
9960
  ...createDocumentFontDialogRunBorderDraft(source.runBorder),
9961
+ ...createDocumentFontDialogRunShadingDraft(source.runShading),
9443
9962
  latinFont: documentFontFamilyDraftValue(source.latinFont),
9444
9963
  eastAsiaFont: documentFontFamilyDraftValue(source.eastAsiaFont),
9445
9964
  complexScriptFont: documentFontFamilyDraftValue(source.complexScriptFont)
@@ -9448,6 +9967,8 @@ function createDocumentFontDialogDraft(source) {
9448
9967
  function documentFontDialogDraftError(draft) {
9449
9968
  const runBorderError = documentFontDialogRunBorderDraftError(draft);
9450
9969
  if (runBorderError) return runBorderError;
9970
+ const runShadingError = documentFontDialogRunShadingDraftError(draft);
9971
+ if (runShadingError) return runShadingError;
9451
9972
  if ('mixed' !== draft.characterScaleMode && null === characterScalePercentFromDraft(draft)) return "请输入 1 至 600 的整数缩放比例。";
9452
9973
  if ('mixed' !== draft.characterSpacingMode && 'normal' !== draft.characterSpacingMode && null === characterSpacingTwipsFromDraft(draft)) return "请输入 0.05 至 1584 磅的间距。";
9453
9974
  if ('mixed' !== draft.characterPositionMode && 'normal' !== draft.characterPositionMode && null === characterPositionHalfPointsFromDraft(draft)) return "请输入 0.5 至 1584 磅、以 0.5 磅递增的位置值。";
@@ -9483,6 +10004,7 @@ function documentFontDialogPatch(source, draft, touched) {
9483
10004
  if (touched.hiddenText && (source.hiddenText.mixed || source.hiddenText.value !== draft.hiddenText)) patch.hiddenText = draft.hiddenText;
9484
10005
  appendLegacyTextEffectPatch(patch, 'legacyTextOutline', source.legacyTextOutline, draft.legacyTextOutline, touched.legacyTextOutline);
9485
10006
  Object.assign(patch, documentFontDialogRunBorderPatch(source.runBorder, draft, touched.runBorder));
10007
+ Object.assign(patch, documentFontDialogRunShadingPatch(source.runShading, draft, touched.runShading));
9486
10008
  appendLegacyTextEffectPatch(patch, 'legacyTextShadow', source.legacyTextShadow, draft.legacyTextShadow, touched.legacyTextShadow);
9487
10009
  appendLegacyTextEffectPatch(patch, 'legacyTextEmboss', source.legacyTextEmboss, draft.legacyTextEmboss, touched.legacyTextEmboss);
9488
10010
  appendLegacyTextEffectPatch(patch, 'legacyTextImprint', source.legacyTextImprint, draft.legacyTextImprint, touched.legacyTextImprint);
@@ -9503,6 +10025,7 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9503
10025
  const hasLegacyTextEmboss = void 0 !== patch.legacyTextEmboss;
9504
10026
  const hasLegacyTextImprint = void 0 !== patch.legacyTextImprint;
9505
10027
  const hasRunBorder = void 0 !== patch.runBorder;
10028
+ const hasRunShading = void 0 !== patch.runShading;
9506
10029
  const hasLegacyTextEffects = hasLegacyTextOutline || hasLegacyTextShadow || hasLegacyTextEmboss || hasLegacyTextImprint;
9507
10030
  const scriptFontPatch = {
9508
10031
  ...void 0 !== patch.latinFont ? {
@@ -9522,8 +10045,9 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9522
10045
  const kerningThreshold = hasKerning && null !== patch.kerningThresholdHalfPoints ? normalizeDocumentKerningThresholdHalfPoints(patch.kerningThresholdHalfPoints) : null;
9523
10046
  const emphasisMark = hasEmphasis && null !== patch.emphasisMark ? normalizeDocumentEmphasisMark(patch.emphasisMark) : null;
9524
10047
  const runBorder = hasRunBorder && null !== patch.runBorder ? normalizeDocumentRunBorder(patch.runBorder) : null;
10048
+ const runShading = hasRunShading && null !== patch.runShading ? normalizeDocumentRunShading(patch.runShading) : null;
9525
10049
  const maximum = editor.state.doc.content.size;
9526
- if (editor.isDestroyed || !hasScale && !hasPosition && !hasSpacing && !hasKerning && !hasEmphasis && !hasHiddenText && !hasLegacyTextEffects && !hasRunBorder && !hasScriptFonts || hasScale && null === scale || hasPosition && null === position || hasSpacing && null === spacing || hasKerning && null !== patch.kerningThresholdHalfPoints && null === kerningThreshold || hasEmphasis && null !== patch.emphasisMark && null === emphasisMark || hasRunBorder && null !== patch.runBorder && null === runBorder || hasHiddenText && 'boolean' != typeof patch.hiddenText || hasLegacyTextOutline && null === normalizeDocumentLegacyTextEffect(patch.legacyTextOutline) || hasLegacyTextShadow && null === normalizeDocumentLegacyTextEffect(patch.legacyTextShadow) || hasLegacyTextEmboss && null === normalizeDocumentLegacyTextEffect(patch.legacyTextEmboss) || hasLegacyTextImprint && null === normalizeDocumentLegacyTextEffect(patch.legacyTextImprint) || !Number.isSafeInteger(selection.from) || !Number.isSafeInteger(selection.to) || selection.from < 0 || selection.to < selection.from || selection.to > maximum || hasLegacyTextEffects && !documentFontDialogLegacyTextEffectsAreSafe(editor, selection, patch)) return false;
10050
+ if (editor.isDestroyed || !hasScale && !hasPosition && !hasSpacing && !hasKerning && !hasEmphasis && !hasHiddenText && !hasLegacyTextEffects && !hasRunBorder && !hasRunShading && !hasScriptFonts || hasScale && null === scale || hasPosition && null === position || hasSpacing && null === spacing || hasKerning && null !== patch.kerningThresholdHalfPoints && null === kerningThreshold || hasEmphasis && null !== patch.emphasisMark && null === emphasisMark || hasRunBorder && null !== patch.runBorder && null === runBorder || hasRunShading && null !== patch.runShading && null === runShading || hasHiddenText && 'boolean' != typeof patch.hiddenText || hasLegacyTextOutline && null === normalizeDocumentLegacyTextEffect(patch.legacyTextOutline) || hasLegacyTextShadow && null === normalizeDocumentLegacyTextEffect(patch.legacyTextShadow) || hasLegacyTextEmboss && null === normalizeDocumentLegacyTextEffect(patch.legacyTextEmboss) || hasLegacyTextImprint && null === normalizeDocumentLegacyTextEffect(patch.legacyTextImprint) || !Number.isSafeInteger(selection.from) || !Number.isSafeInteger(selection.to) || selection.from < 0 || selection.to < selection.from || selection.to > maximum || hasLegacyTextEffects && !documentFontDialogLegacyTextEffectsAreSafe(editor, selection, patch)) return false;
9527
10051
  const attributes = {};
9528
10052
  if (null !== scale) attributes.characterScalePercent = scale;
9529
10053
  if (null !== position) attributes.characterPositionHalfPoints = position;
@@ -9536,6 +10060,7 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9536
10060
  if (hasLegacyTextEmboss) attributes.legacyTextEmboss = patch.legacyTextEmboss ?? false;
9537
10061
  if (hasLegacyTextImprint) attributes.legacyTextImprint = patch.legacyTextImprint ?? false;
9538
10062
  if (hasRunBorder) attributes.runBorder = null === patch.runBorder ? null : serializeDocumentRunBorder(runBorder) ?? null;
10063
+ if (hasRunShading) attributes.runShading = null === patch.runShading ? null : serializeDocumentRunShading(runShading) ?? null;
9539
10064
  if (hasScriptFonts) return applyDocumentScriptFontPatch(editor, selection, attributes, scriptFontPatch);
9540
10065
  return editor.chain().setTextSelection(selection).setMark('textStyle', attributes).removeEmptyTextStyle().focus().scrollIntoView().run();
9541
10066
  }
@@ -9633,7 +10158,7 @@ function kerningThresholdHalfPointsFromDraft(draft) {
9633
10158
  if (!Number.isFinite(points) || points < 0 || points > 1638.5 || !Number.isSafeInteger(halfPoints)) return null;
9634
10159
  return normalizeDocumentKerningThresholdHalfPoints(halfPoints);
9635
10160
  }
9636
- function selectedValue(values) {
10161
+ function document_font_dialog_model_selectedValue(values) {
9637
10162
  const mixed = values.size > 1;
9638
10163
  return {
9639
10164
  mixed,
@@ -9941,6 +10466,231 @@ function documentFontDialogRunBorderPreviewStyle(source, draft) {
9941
10466
  } : {}
9942
10467
  };
9943
10468
  }
10469
+ const shadingModes = [
10470
+ {
10471
+ value: 'mixed',
10472
+ label: '混合(保持不变)',
10473
+ disabled: true
10474
+ },
10475
+ {
10476
+ value: 'inherit',
10477
+ label: '跟随样式'
10478
+ },
10479
+ {
10480
+ value: 'none',
10481
+ label: '无(显式重置)'
10482
+ },
10483
+ {
10484
+ value: 'value',
10485
+ label: '底纹'
10486
+ }
10487
+ ];
10488
+ const shadingPatterns = [
10489
+ {
10490
+ value: 'clear',
10491
+ label: '清除(背景色)',
10492
+ group: '基本'
10493
+ },
10494
+ {
10495
+ value: 'solid',
10496
+ label: '实心(前景色)',
10497
+ group: '基本'
10498
+ },
10499
+ {
10500
+ value: 'horzStripe',
10501
+ label: '水平条纹',
10502
+ group: '条纹'
10503
+ },
10504
+ {
10505
+ value: 'vertStripe',
10506
+ label: '垂直条纹',
10507
+ group: '条纹'
10508
+ },
10509
+ {
10510
+ value: 'reverseDiagStripe',
10511
+ label: '反向对角条纹',
10512
+ group: '条纹'
10513
+ },
10514
+ {
10515
+ value: 'diagStripe',
10516
+ label: '对角条纹',
10517
+ group: '条纹'
10518
+ },
10519
+ {
10520
+ value: 'horzCross',
10521
+ label: '水平交叉',
10522
+ group: '交叉'
10523
+ },
10524
+ {
10525
+ value: 'diagCross',
10526
+ label: '对角交叉',
10527
+ group: '交叉'
10528
+ },
10529
+ {
10530
+ value: 'thinHorzStripe',
10531
+ label: '细水平条纹',
10532
+ group: '细线'
10533
+ },
10534
+ {
10535
+ value: 'thinVertStripe',
10536
+ label: '细垂直条纹',
10537
+ group: '细线'
10538
+ },
10539
+ {
10540
+ value: 'thinReverseDiagStripe',
10541
+ label: '细反向对角条纹',
10542
+ group: '细线'
10543
+ },
10544
+ {
10545
+ value: 'thinDiagStripe',
10546
+ label: '细对角条纹',
10547
+ group: '细线'
10548
+ },
10549
+ {
10550
+ value: 'thinHorzCross',
10551
+ label: '细水平交叉',
10552
+ group: '细线'
10553
+ },
10554
+ {
10555
+ value: 'thinDiagCross',
10556
+ label: '细对角交叉',
10557
+ group: '细线'
10558
+ },
10559
+ ...[
10560
+ 5,
10561
+ 10,
10562
+ 12,
10563
+ 15,
10564
+ 20,
10565
+ 25,
10566
+ 30,
10567
+ 35,
10568
+ 37,
10569
+ 40,
10570
+ 45,
10571
+ 50,
10572
+ 55,
10573
+ 60,
10574
+ 62,
10575
+ 65,
10576
+ 70,
10577
+ 75,
10578
+ 80,
10579
+ 85,
10580
+ 87,
10581
+ 90,
10582
+ 95
10583
+ ].map((percentage)=>({
10584
+ value: `pct${percentage}`,
10585
+ label: `${percentage}%`,
10586
+ group: '密度'
10587
+ }))
10588
+ ];
10589
+ function DocumentFontDialogRunShadingSection({ source, draft, touched, onDraftChange, onTouched }) {
10590
+ const enabled = 'value' === draft.runShadingMode;
10591
+ const update = (patch)=>{
10592
+ onDraftChange(patch);
10593
+ onTouched();
10594
+ };
10595
+ return /*#__PURE__*/ jsxs("fieldset", {
10596
+ className: "work-document-font-dialog-run-shading",
10597
+ "aria-label": "字符底纹设置",
10598
+ children: [
10599
+ /*#__PURE__*/ jsx("legend", {
10600
+ children: "字符底纹"
10601
+ }),
10602
+ /*#__PURE__*/ jsxs("div", {
10603
+ className: "work-document-font-dialog-field",
10604
+ children: [
10605
+ /*#__PURE__*/ jsx("span", {
10606
+ children: "应用方式"
10607
+ }),
10608
+ /*#__PURE__*/ jsx(OfficeSelect, {
10609
+ ariaLabel: "字符底纹",
10610
+ value: draft.runShadingMode,
10611
+ options: shadingModes,
10612
+ onValueChange: (runShadingMode)=>update({
10613
+ runShadingMode
10614
+ })
10615
+ })
10616
+ ]
10617
+ }),
10618
+ /*#__PURE__*/ jsxs("div", {
10619
+ className: "work-document-font-dialog-field",
10620
+ children: [
10621
+ /*#__PURE__*/ jsx("span", {
10622
+ children: "图案"
10623
+ }),
10624
+ /*#__PURE__*/ jsx(OfficeSelect, {
10625
+ ariaLabel: "字符底纹图案",
10626
+ value: draft.runShadingPattern,
10627
+ options: shadingPatterns,
10628
+ disabled: !enabled,
10629
+ onValueChange: (runShadingPattern)=>update({
10630
+ runShadingMode: 'value',
10631
+ runShadingPattern
10632
+ })
10633
+ })
10634
+ ]
10635
+ }),
10636
+ /*#__PURE__*/ jsxs("div", {
10637
+ className: "work-document-font-dialog-field",
10638
+ children: [
10639
+ /*#__PURE__*/ jsx("span", {
10640
+ children: "前景色"
10641
+ }),
10642
+ /*#__PURE__*/ jsx(OfficeColorPicker, {
10643
+ ariaLabel: "字符底纹前景色",
10644
+ value: 'auto' === draft.runShadingColor ? '#000000' : draft.runShadingColor,
10645
+ disabled: !enabled,
10646
+ resetAction: {
10647
+ kind: 'automatic',
10648
+ label: '自动前景色',
10649
+ onSelect: ()=>update({
10650
+ runShadingMode: 'value',
10651
+ runShadingColor: 'auto'
10652
+ })
10653
+ },
10654
+ onValueChange: (runShadingColor)=>update({
10655
+ runShadingMode: 'value',
10656
+ runShadingColor: runShadingColor
10657
+ })
10658
+ })
10659
+ ]
10660
+ }),
10661
+ /*#__PURE__*/ jsxs("div", {
10662
+ className: "work-document-font-dialog-field",
10663
+ children: [
10664
+ /*#__PURE__*/ jsx("span", {
10665
+ children: "背景色"
10666
+ }),
10667
+ /*#__PURE__*/ jsx(OfficeColorPicker, {
10668
+ ariaLabel: "字符底纹背景色",
10669
+ value: 'auto' === draft.runShadingFill ? '#ffffff' : draft.runShadingFill,
10670
+ disabled: !enabled,
10671
+ resetAction: {
10672
+ kind: 'automatic',
10673
+ label: '自动背景色',
10674
+ onSelect: ()=>update({
10675
+ runShadingMode: 'value',
10676
+ runShadingFill: 'auto'
10677
+ })
10678
+ },
10679
+ onValueChange: (runShadingFill)=>update({
10680
+ runShadingMode: 'value',
10681
+ runShadingFill: runShadingFill
10682
+ })
10683
+ })
10684
+ ]
10685
+ }),
10686
+ source.mixed && !touched ? /*#__PURE__*/ jsx("p", {
10687
+ className: "work-document-font-dialog-mixed",
10688
+ role: "status",
10689
+ children: "当前选区包含不同的字符底纹。选择一种应用方式后才会统一修改。"
10690
+ }) : null
10691
+ ]
10692
+ });
10693
+ }
9944
10694
  const characterSpacingModes = [
9945
10695
  {
9946
10696
  value: 'mixed',
@@ -10023,6 +10773,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10023
10773
  const [legacyTextEmbossTouched, setLegacyTextEmbossTouched] = useState(false);
10024
10774
  const [legacyTextImprintTouched, setLegacyTextImprintTouched] = useState(false);
10025
10775
  const [runBorderTouched, setRunBorderTouched] = useState(false);
10776
+ const [runShadingTouched, setRunShadingTouched] = useState(false);
10026
10777
  const [latinFontTouched, setLatinFontTouched] = useState(false);
10027
10778
  const [eastAsiaFontTouched, setEastAsiaFontTouched] = useState(false);
10028
10779
  const [complexScriptFontTouched, setComplexScriptFontTouched] = useState(false);
@@ -10041,6 +10792,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10041
10792
  legacyTextEmboss: legacyTextEmbossTouched,
10042
10793
  legacyTextImprint: legacyTextImprintTouched,
10043
10794
  runBorder: runBorderTouched,
10795
+ runShading: runShadingTouched,
10044
10796
  kerning: kerningTouched,
10045
10797
  latinFont: latinFontTouched
10046
10798
  });
@@ -10057,6 +10809,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10057
10809
  imprint: draft.legacyTextImprint
10058
10810
  });
10059
10811
  const previewRunBorder = documentFontDialogRunBorderPreviewStyle(source.runBorder, draft);
10812
+ const previewRunShading = documentFontDialogRunShadingPreviewStyle(source.runShading, draft);
10060
10813
  const submit = (event)=>{
10061
10814
  event?.preventDefault();
10062
10815
  if (!hasChanges || error) return;
@@ -10506,6 +11259,16 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10506
11259
  })),
10507
11260
  onTouched: ()=>setRunBorderTouched(true)
10508
11261
  }),
11262
+ /*#__PURE__*/ jsx(DocumentFontDialogRunShadingSection, {
11263
+ source: source.runShading,
11264
+ draft: draft,
11265
+ touched: runShadingTouched,
11266
+ onDraftChange: (runShadingDraft)=>setDraft((current)=>({
11267
+ ...current,
11268
+ ...runShadingDraft
11269
+ })),
11270
+ onTouched: ()=>setRunShadingTouched(true)
11271
+ }),
10509
11272
  source.characterScale.mixed && !characterScaleTouched && /*#__PURE__*/ jsx("p", {
10510
11273
  className: "work-document-font-dialog-mixed",
10511
11274
  role: "status",
@@ -10541,7 +11304,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10541
11304
  role: "status",
10542
11305
  children: "当前选区包含不同的空心、阴影、阳文或阴文设置。勾选或取消对应选项后才会统一修改。"
10543
11306
  }),
10544
- (characterScaleTouched || characterSpacingTouched || characterPositionTouched || kerningTouched || emphasisTouched || hiddenTextTouched || legacyTextOutlineTouched || legacyTextShadowTouched || legacyTextEmbossTouched || legacyTextImprintTouched || runBorderTouched) && error && /*#__PURE__*/ jsx("p", {
11307
+ (characterScaleTouched || characterSpacingTouched || characterPositionTouched || kerningTouched || emphasisTouched || hiddenTextTouched || legacyTextOutlineTouched || legacyTextShadowTouched || legacyTextEmbossTouched || legacyTextImprintTouched || runBorderTouched || runShadingTouched) && error && /*#__PURE__*/ jsx("p", {
10545
11308
  className: "work-document-font-dialog-error",
10546
11309
  role: "alert",
10547
11310
  children: error
@@ -10568,6 +11331,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
10568
11331
  verticalAlign: `${previewPosition}pt`,
10569
11332
  ...previewEmphasis,
10570
11333
  ...previewLegacyTextEffects,
11334
+ ...previewRunShading,
10571
11335
  ...previewRunBorder,
10572
11336
  ...draft.hiddenText ? {
10573
11337
  textDecorationColor: 'currentColor',
@@ -10648,7 +11412,7 @@ function previewScriptFontFamily(value, fallback) {
10648
11412
  function fontDialogDescription(source) {
10649
11413
  return source.selectedCharacters ? `分别设置当前选中内容的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号、隐藏文字、空心、阴影、阳文和阴文(${source.selectedCharacters} 个字符)。` : '分别设置当前位置后续输入文字的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号、隐藏文字、空心、阴影、阳文和阴文。';
10650
11414
  }
10651
- function DocumentPageChromeRibbon({ editor, editingPart, showPageNumber, onEditingPartChange, onTogglePageNumber, onOpenFontDialog, onClose }) {
11415
+ function DocumentPageChromeRibbon({ editor, editingPart, showPageNumber, onEditingPartChange, onTogglePageNumber, onOpenFontDialog, onOpenProofingDialog, onClose }) {
10652
11416
  const imageInputRef = useRef(null);
10653
11417
  const [, setRevision] = useState(0);
10654
11418
  const officeDialog = useOfficeDialog();
@@ -10806,6 +11570,13 @@ function DocumentPageChromeRibbon({ editor, editingPart, showPageNumber, onEditi
10806
11570
  ariaLabel: "页眉页脚文字颜色",
10807
11571
  value: pickerColor(state.color),
10808
11572
  onValueChange: (color)=>editor.chain().focus().setColor(color).run()
11573
+ }),
11574
+ onOpenProofingDialog && /*#__PURE__*/ jsx(PageChromeRibbonButton, {
11575
+ label: "页眉页脚校对语言",
11576
+ onClick: onOpenProofingDialog,
11577
+ children: /*#__PURE__*/ jsx(Languages, {
11578
+ size: 16
11579
+ })
10809
11580
  })
10810
11581
  ]
10811
11582
  }),
@@ -12415,6 +13186,158 @@ function PictureButton({ label, active = false, disabled = false, onClick, child
12415
13186
  children: children
12416
13187
  });
12417
13188
  }
13189
+ function DocumentReferencesRibbon({ editor, citationsOpen, citationSourceCount, onInsertNote, onInsertCaption, onInsertCrossReference, onOpenTableOfContents, onRefreshTableOfContents, onOpenIndexEntry, onOpenIndex, onRefreshIndex, onToggleCitations, onRefreshFields }) {
13190
+ const hasTableOfContents = documentHasTableOfContents(editor);
13191
+ const hasIndex = documentHasIndex(editor);
13192
+ const canMarkIndexEntry = Boolean(selectedDocumentIndexDraft(editor));
13193
+ const hasRefreshableFields = documentHasRefreshableFields(editor);
13194
+ const refreshFieldsCommand = getDocumentCommandDefinition('refreshFields');
13195
+ return /*#__PURE__*/ jsxs(Fragment, {
13196
+ children: [
13197
+ /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
13198
+ label: "目录",
13199
+ priority: "high",
13200
+ children: [
13201
+ /*#__PURE__*/ jsx(ReferencesButton, {
13202
+ label: "插入或自定义目录",
13203
+ onClick: onOpenTableOfContents,
13204
+ children: /*#__PURE__*/ jsx(ListTree, {
13205
+ size: 19
13206
+ })
13207
+ }),
13208
+ /*#__PURE__*/ jsx(ReferencesButton, {
13209
+ label: "更新目录",
13210
+ disabled: !hasTableOfContents,
13211
+ title: hasTableOfContents ? '根据当前标题和页码更新目录' : '文档中没有可更新的目录',
13212
+ onClick: onRefreshTableOfContents,
13213
+ children: /*#__PURE__*/ jsx(RefreshCw, {
13214
+ size: 19
13215
+ })
13216
+ })
13217
+ ]
13218
+ }),
13219
+ /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
13220
+ label: "脚注",
13221
+ priority: "high",
13222
+ children: [
13223
+ /*#__PURE__*/ jsx(ReferencesButton, {
13224
+ label: "插入脚注",
13225
+ onClick: ()=>onInsertNote('footnote'),
13226
+ children: /*#__PURE__*/ jsx("span", {
13227
+ className: "work-ribbon-glyph",
13228
+ children: "\xb9"
13229
+ })
13230
+ }),
13231
+ /*#__PURE__*/ jsx(ReferencesButton, {
13232
+ label: "插入尾注",
13233
+ onClick: ()=>onInsertNote('endnote'),
13234
+ children: /*#__PURE__*/ jsx("span", {
13235
+ className: "work-ribbon-glyph",
13236
+ children: "ⅰ"
13237
+ })
13238
+ })
13239
+ ]
13240
+ }),
13241
+ /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
13242
+ label: "题注",
13243
+ children: [
13244
+ /*#__PURE__*/ jsx(ReferencesButton, {
13245
+ label: "插入图片题注",
13246
+ onClick: ()=>onInsertCaption('figure'),
13247
+ children: /*#__PURE__*/ jsx(Image, {
13248
+ size: 19
13249
+ })
13250
+ }),
13251
+ /*#__PURE__*/ jsx(ReferencesButton, {
13252
+ label: "插入表格题注",
13253
+ onClick: ()=>onInsertCaption('table'),
13254
+ children: /*#__PURE__*/ jsx(Table2, {
13255
+ size: 19
13256
+ })
13257
+ }),
13258
+ /*#__PURE__*/ jsx(ReferencesButton, {
13259
+ label: "插入交叉引用",
13260
+ onClick: onInsertCrossReference,
13261
+ children: /*#__PURE__*/ jsx(Link2, {
13262
+ size: 19
13263
+ })
13264
+ })
13265
+ ]
13266
+ }),
13267
+ /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
13268
+ label: "引文和书目",
13269
+ priority: "high",
13270
+ children: /*#__PURE__*/ jsx(ReferencesButton, {
13271
+ label: `文献库${citationSourceCount ? `(${citationSourceCount})` : ''}`,
13272
+ active: citationsOpen,
13273
+ onClick: onToggleCitations,
13274
+ children: /*#__PURE__*/ jsx(BookOpen, {
13275
+ size: 19
13276
+ })
13277
+ })
13278
+ }),
13279
+ /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
13280
+ label: "索引",
13281
+ priority: "high",
13282
+ children: [
13283
+ /*#__PURE__*/ jsx(ReferencesButton, {
13284
+ label: "标记索引项",
13285
+ disabled: !canMarkIndexEntry,
13286
+ title: canMarkIndexEntry ? '把当前选中文字标记为索引项' : '请先选择正文文字或已有索引项',
13287
+ onClick: onOpenIndexEntry,
13288
+ children: /*#__PURE__*/ jsx(Tags, {
13289
+ size: 19
13290
+ })
13291
+ }),
13292
+ /*#__PURE__*/ jsx(ReferencesButton, {
13293
+ label: "插入或自定义索引",
13294
+ onClick: onOpenIndex,
13295
+ children: /*#__PURE__*/ jsx(ListOrdered, {
13296
+ size: 19
13297
+ })
13298
+ }),
13299
+ /*#__PURE__*/ jsx(ReferencesButton, {
13300
+ label: "更新索引",
13301
+ disabled: !hasIndex,
13302
+ title: hasIndex ? '根据当前索引项和页码更新索引' : '文档中没有可更新的索引',
13303
+ onClick: onRefreshIndex,
13304
+ children: /*#__PURE__*/ jsx(RefreshCw, {
13305
+ size: 19
13306
+ })
13307
+ })
13308
+ ]
13309
+ }),
13310
+ /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
13311
+ label: "更新",
13312
+ priority: "low",
13313
+ children: /*#__PURE__*/ jsx(ReferencesButton, {
13314
+ label: "更新页码和日期",
13315
+ shortcut: refreshFieldsCommand.shortcut?.label,
13316
+ ariaKeyShortcuts: refreshFieldsCommand.shortcut?.aria,
13317
+ disabled: !hasRefreshableFields,
13318
+ title: hasRefreshableFields ? `更新页码和日期(${refreshFieldsCommand.shortcut?.label})` : '文档中没有可更新的页码或日期',
13319
+ onClick: onRefreshFields,
13320
+ children: /*#__PURE__*/ jsx(RefreshCw, {
13321
+ size: 19
13322
+ })
13323
+ })
13324
+ })
13325
+ ]
13326
+ });
13327
+ }
13328
+ function ReferencesButton({ label, title, shortcut, ariaKeyShortcuts, active = false, disabled = false, onClick, children }) {
13329
+ return /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
13330
+ label: label,
13331
+ visibleLabel: label.replace(/(\d+)$/, ''),
13332
+ title: title ?? (shortcut ? `${label}(${shortcut})` : label),
13333
+ "aria-keyshortcuts": ariaKeyShortcuts,
13334
+ active: active,
13335
+ displayLabel: true,
13336
+ disabled: disabled,
13337
+ onClick: onClick,
13338
+ children: children
13339
+ });
13340
+ }
12418
13341
  function selectedDocumentChangeIndex(changes, selection) {
12419
13342
  const index = changes.findIndex((change)=>selection.from === selection.to ? change.from <= selection.from && selection.from <= change.to : change.from < selection.to && change.to > selection.from);
12420
13343
  return index >= 0 ? index : null;
@@ -14220,9 +15143,10 @@ function headingLevelForShortcut(code, key) {
14220
15143
  if ('3' === value) return 3;
14221
15144
  return null;
14222
15145
  }
14223
- function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly = false, suggestionOnly = false, history, layoutOpen, layout, layoutFonts = [], navigationOpen, pageColor, showPageNumbers, showHiddenText, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onLayoutChange, onOpenLayout, onToggleNavigation, onTogglePageNumbers, onToggleHiddenText, 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, onDecideChange, onOpenWordCount, onOpenFindReplace }) {
15146
+ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly = false, suggestionOnly = false, history, layoutOpen, layout, layoutFonts = [], navigationOpen, pageColor, showPageNumbers, showHiddenText, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onLayoutChange, onOpenLayout, onToggleNavigation, onTogglePageNumbers, onToggleHiddenText, onToggleRulers, onPageColorChange, onToggleSpellcheck, onViewModeChange, onZoomChange, onZoomFit, onInsertSection, onInsertNote, onInsertCaption, onInsertCrossReference, onOpenTableOfContents, onOpenIndexEntry, onOpenIndex, citationsOpen, citationSourceCount, onToggleCitations, onInsertField, onRefreshFields, onRefreshIndex, onRefreshTableOfContents, canInsertComment, onInsertComment, commentsOpen, commentCount, onToggleComments, trackChanges, changesOpen, changeCount, findReplaceMode, fileActions, onRibbonTabChange, onToggleTrackChanges, onToggleChanges, onDecideChange, onOpenWordCount, onOpenFindReplace }) {
14224
15147
  const [activeTab, setActiveTab] = useState(reviewOnly ? 'review' : 'home');
14225
15148
  const [fontDialogRequest, setFontDialogRequest] = useState(null);
15149
+ const [proofingDialogRequest, setProofingDialogRequest] = useState(null);
14226
15150
  const officeDialog = useOfficeDialog();
14227
15151
  const prompt = officeDialog.prompt;
14228
15152
  const imageSelected = editor.isActive('image');
@@ -14235,12 +15159,12 @@ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly =
14235
15159
  const actionableChangeIndex = actionableDocumentChangeIndex(documentChanges, editor.state.selection);
14236
15160
  const undoCommand = getDocumentCommandDefinition('undo');
14237
15161
  const redoCommand = getDocumentCommandDefinition('redo');
14238
- const refreshFieldsCommand = getDocumentCommandDefinition('refreshFields');
14239
15162
  const spellingCommand = getDocumentCommandDefinition('spelling');
14240
15163
  const insertCommentCommand = getDocumentCommandDefinition('insertComment');
14241
15164
  const trackChangesCommand = getDocumentCommandDefinition('trackChanges');
14242
15165
  const openFontDialog = useCallback((target)=>{
14243
15166
  if (target.isDestroyed) return;
15167
+ synchronizeDocumentEditorSelectionFromDom(target);
14244
15168
  const { from, to } = target.state.selection;
14245
15169
  setFontDialogRequest({
14246
15170
  editor: target,
@@ -14251,6 +15175,19 @@ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly =
14251
15175
  source: documentFontDialogSource(target)
14252
15176
  });
14253
15177
  }, []);
15178
+ const openProofingDialog = useCallback((target)=>{
15179
+ if (target.isDestroyed) return;
15180
+ synchronizeDocumentEditorSelectionFromDom(target);
15181
+ const { from, to } = target.state.selection;
15182
+ setProofingDialogRequest({
15183
+ editor: target,
15184
+ selection: {
15185
+ from,
15186
+ to
15187
+ },
15188
+ source: documentProofingDialogSource(target)
15189
+ });
15190
+ }, []);
14254
15191
  const ribbonTabs = reviewOnly ? documentRibbonTabs.filter(({ id })=>'review' === id || 'view' === id) : pageChromeEditor ? [
14255
15192
  ...documentRibbonTabs,
14256
15193
  documentPageChromeRibbonTab
@@ -14624,109 +15561,48 @@ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly =
14624
15561
  onPageColorChange: onPageColorChange,
14625
15562
  onInsertSection: onInsertSection
14626
15563
  }),
14627
- references: reviewOnly ? null : /*#__PURE__*/ jsxs(Fragment, {
15564
+ references: reviewOnly ? null : /*#__PURE__*/ jsx(DocumentReferencesRibbon, {
15565
+ editor: editor,
15566
+ citationsOpen: citationsOpen,
15567
+ citationSourceCount: citationSourceCount,
15568
+ onInsertNote: onInsertNote,
15569
+ onInsertCaption: onInsertCaption,
15570
+ onInsertCrossReference: onInsertCrossReference,
15571
+ onOpenTableOfContents: onOpenTableOfContents,
15572
+ onRefreshTableOfContents: onRefreshTableOfContents,
15573
+ onOpenIndexEntry: onOpenIndexEntry,
15574
+ onOpenIndex: onOpenIndex,
15575
+ onRefreshIndex: onRefreshIndex,
15576
+ onToggleCitations: onToggleCitations,
15577
+ onRefreshFields: onRefreshFields
15578
+ }),
15579
+ review: /*#__PURE__*/ jsxs(Fragment, {
14628
15580
  children: [
14629
- /*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
14630
- label: "脚注",
15581
+ !reviewOnly && /*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
15582
+ label: "校对",
14631
15583
  priority: "high",
14632
15584
  children: [
14633
15585
  /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14634
- label: "插入脚注",
15586
+ label: "拼写检查",
14635
15587
  displayLabel: true,
14636
- onClick: ()=>onInsertNote('footnote'),
14637
- children: /*#__PURE__*/ jsx("span", {
14638
- className: "work-ribbon-glyph",
14639
- children: "\xb9"
15588
+ shortcut: spellingCommand.shortcut?.label,
15589
+ ariaKeyShortcuts: spellingCommand.shortcut?.aria,
15590
+ active: spellcheckEnabled,
15591
+ onClick: onToggleSpellcheck,
15592
+ children: /*#__PURE__*/ jsx(CheckCheck, {
15593
+ size: 19
14640
15594
  })
14641
15595
  }),
14642
15596
  /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14643
- label: "插入尾注",
15597
+ label: "设置校对语言",
14644
15598
  displayLabel: true,
14645
- onClick: ()=>onInsertNote('endnote'),
14646
- children: /*#__PURE__*/ jsx("span", {
14647
- className: "work-ribbon-glyph",
14648
- children: "ⅰ"
15599
+ onClick: ()=>openProofingDialog(editor),
15600
+ children: /*#__PURE__*/ jsx(Languages, {
15601
+ size: 19
14649
15602
  })
14650
15603
  })
14651
15604
  ]
14652
15605
  }),
14653
- /*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
14654
- label: "题注",
14655
- children: [
14656
- /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14657
- label: "插入图片题注",
14658
- displayLabel: true,
14659
- onClick: ()=>onInsertCaption('figure'),
14660
- children: /*#__PURE__*/ jsx(Image, {
14661
- size: 19
14662
- })
14663
- }),
14664
- /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14665
- label: "插入表格题注",
14666
- displayLabel: true,
14667
- onClick: ()=>onInsertCaption('table'),
14668
- children: /*#__PURE__*/ jsx(Table2, {
14669
- size: 19
14670
- })
14671
- }),
14672
- /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14673
- label: "插入交叉引用",
14674
- displayLabel: true,
14675
- onClick: onInsertCrossReference,
14676
- children: /*#__PURE__*/ jsx(Link2, {
14677
- size: 19
14678
- })
14679
- })
14680
- ]
14681
- }),
14682
- /*#__PURE__*/ jsx(document_toolbar_RibbonGroup, {
14683
- label: "引文和书目",
14684
- priority: "high",
14685
- children: /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14686
- label: `文献库${citationSourceCount ? `(${citationSourceCount})` : ''}`,
14687
- displayLabel: true,
14688
- active: citationsOpen,
14689
- onClick: onToggleCitations,
14690
- children: /*#__PURE__*/ jsx(BookOpen, {
14691
- size: 19
14692
- })
14693
- })
14694
- }),
14695
- /*#__PURE__*/ jsx(document_toolbar_RibbonGroup, {
14696
- label: "更新",
14697
- priority: "low",
14698
- children: /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14699
- label: "更新页码和日期",
14700
- displayLabel: true,
14701
- shortcut: refreshFieldsCommand.shortcut?.label,
14702
- ariaKeyShortcuts: refreshFieldsCommand.shortcut?.aria,
14703
- disabled: !hasRefreshableFields,
14704
- title: hasRefreshableFields ? `更新页码和日期(${refreshFieldsCommand.shortcut?.label})` : '文档中没有可更新的页码或日期',
14705
- onClick: onRefreshFields,
14706
- children: /*#__PURE__*/ jsx(RefreshCw, {
14707
- size: 19
14708
- })
14709
- })
14710
- })
14711
- ]
14712
- }),
14713
- review: /*#__PURE__*/ jsxs(Fragment, {
14714
- children: [
14715
- !reviewOnly && /*#__PURE__*/ jsx(document_toolbar_RibbonGroup, {
14716
- label: "校对",
14717
- priority: "high",
14718
- children: /*#__PURE__*/ jsx(document_toolbar_ToolbarButton, {
14719
- label: "拼写检查",
14720
- displayLabel: true,
14721
- shortcut: spellingCommand.shortcut?.label,
14722
- ariaKeyShortcuts: spellingCommand.shortcut?.aria,
14723
- active: spellcheckEnabled,
14724
- onClick: onToggleSpellcheck,
14725
- children: /*#__PURE__*/ jsx(CheckCheck, {
14726
- size: 19
14727
- })
14728
- })
14729
- }),
14730
15606
  !suggestionOnly && /*#__PURE__*/ jsxs(document_toolbar_RibbonGroup, {
14731
15607
  label: "批注",
14732
15608
  priority: "high",
@@ -14956,6 +15832,7 @@ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly =
14956
15832
  onEditingPartChange: onPageChromeEditingPartChange,
14957
15833
  onTogglePageNumber: onTogglePageChromePageNumber,
14958
15834
  onOpenFontDialog: ()=>openFontDialog(pageChromeEditor),
15835
+ onOpenProofingDialog: ()=>openProofingDialog(pageChromeEditor),
14959
15836
  onClose: onClosePageChrome
14960
15837
  }) : null
14961
15838
  }
@@ -14976,6 +15853,21 @@ function DocumentToolbar({ editor, defaultRibbonCollapsed = false, reviewOnly =
14976
15853
  });
14977
15854
  }
14978
15855
  }),
15856
+ proofingDialogRequest && /*#__PURE__*/ jsx(DocumentProofingDialog, {
15857
+ source: proofingDialogRequest.source,
15858
+ restoreFocusTarget: ()=>proofingDialogRequest.editor.isDestroyed ? null : proofingDialogRequest.editor.view.dom,
15859
+ onApply: (patch)=>applyDocumentProofingDialogPatch(proofingDialogRequest.editor, proofingDialogRequest.selection, patch),
15860
+ onClose: ()=>{
15861
+ const { editor: dialogEditor, selection } = proofingDialogRequest;
15862
+ setProofingDialogRequest(null);
15863
+ requestAnimationFrame(()=>{
15864
+ if (dialogEditor.isDestroyed) return;
15865
+ dialogEditor.chain().setTextSelection(selection).focus(null, {
15866
+ scrollIntoView: false
15867
+ }).run();
15868
+ });
15869
+ }
15870
+ }),
14979
15871
  officeDialog.dialog
14980
15872
  ]
14981
15873
  });
@@ -15052,15 +15944,6 @@ function DocumentFieldSelect({ onInsertField }) {
15052
15944
  }
15053
15945
  });
15054
15946
  }
15055
- function documentHasRefreshableFields(editor) {
15056
- let found = false;
15057
- editor.state.doc.descendants((node)=>{
15058
- if ('documentField' !== node.type.name) return !found;
15059
- found = true;
15060
- return false;
15061
- });
15062
- return found;
15063
- }
15064
15947
  function DocumentVerticalRuler({ layout, onLayoutChange }) {
15065
15948
  const rulerRef = useRef(null);
15066
15949
  const pageHeight = documentRulerPageHeight(layout);
@@ -15360,6 +16243,496 @@ function commentActor(actor) {
15360
16243
  author: CURRENT_COMMENT_AUTHOR
15361
16244
  };
15362
16245
  }
16246
+ function DocumentTableOfContentsDialog({ editing, options, restoreFocusTarget, onCancel, onOptionsChange, onSubmit }) {
16247
+ const updateOptions = (update)=>onOptionsChange({
16248
+ ...options,
16249
+ ...update
16250
+ });
16251
+ return /*#__PURE__*/ jsxs(Dialog, {
16252
+ title: editing ? '自定义目录' : '插入目录',
16253
+ description: "从文档标题生成可更新目录,并保留原生 DOCX 目录域。",
16254
+ className: "work-document-table-of-contents-dialog",
16255
+ restoreFocusTarget: restoreFocusTarget,
16256
+ onClose: onCancel,
16257
+ footer: /*#__PURE__*/ jsxs(Fragment, {
16258
+ children: [
16259
+ /*#__PURE__*/ jsx(button_Button, {
16260
+ tone: "quiet",
16261
+ onClick: onCancel,
16262
+ children: "取消"
16263
+ }),
16264
+ /*#__PURE__*/ jsx(button_Button, {
16265
+ tone: "primary",
16266
+ onClick: onSubmit,
16267
+ children: editing ? '应用' : '插入目录'
16268
+ })
16269
+ ]
16270
+ }),
16271
+ children: [
16272
+ /*#__PURE__*/ jsxs("div", {
16273
+ className: "work-document-table-of-contents-dialog-grid",
16274
+ children: [
16275
+ /*#__PURE__*/ jsxs("div", {
16276
+ className: "work-document-table-of-contents-dialog-field",
16277
+ children: [
16278
+ /*#__PURE__*/ jsx("span", {
16279
+ children: "起始标题级别"
16280
+ }),
16281
+ /*#__PURE__*/ jsx(OfficeSelect, {
16282
+ initialFocus: true,
16283
+ ariaLabel: "起始标题级别",
16284
+ value: String(options.minLevel),
16285
+ options: tableOfContentsLevelOptions,
16286
+ onValueChange: (value)=>{
16287
+ const minLevel = Number(value);
16288
+ updateOptions({
16289
+ minLevel,
16290
+ maxLevel: Math.max(minLevel, options.maxLevel)
16291
+ });
16292
+ }
16293
+ })
16294
+ ]
16295
+ }),
16296
+ /*#__PURE__*/ jsxs("div", {
16297
+ className: "work-document-table-of-contents-dialog-field",
16298
+ children: [
16299
+ /*#__PURE__*/ jsx("span", {
16300
+ children: "结束标题级别"
16301
+ }),
16302
+ /*#__PURE__*/ jsx(OfficeSelect, {
16303
+ ariaLabel: "结束标题级别",
16304
+ value: String(options.maxLevel),
16305
+ options: tableOfContentsLevelOptions.map((option)=>({
16306
+ ...option,
16307
+ disabled: Number(option.value) < options.minLevel
16308
+ })),
16309
+ onValueChange: (value)=>updateOptions({
16310
+ maxLevel: Number(value)
16311
+ })
16312
+ })
16313
+ ]
16314
+ })
16315
+ ]
16316
+ }),
16317
+ /*#__PURE__*/ jsxs("div", {
16318
+ className: "work-document-table-of-contents-dialog-options",
16319
+ children: [
16320
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16321
+ ariaLabel: "目录项使用超链接",
16322
+ checked: options.hyperlinks,
16323
+ onCheckedChange: (hyperlinks)=>updateOptions({
16324
+ hyperlinks
16325
+ }),
16326
+ children: "目录项使用超链接"
16327
+ }),
16328
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16329
+ ariaLabel: "显示页码",
16330
+ checked: options.showPageNumbers,
16331
+ onCheckedChange: (showPageNumbers)=>updateOptions({
16332
+ showPageNumbers,
16333
+ rightAlignPageNumbers: showPageNumbers && options.rightAlignPageNumbers
16334
+ }),
16335
+ children: "显示页码"
16336
+ }),
16337
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16338
+ ariaLabel: "页码右对齐",
16339
+ checked: options.rightAlignPageNumbers,
16340
+ disabled: !options.showPageNumbers,
16341
+ onCheckedChange: (rightAlignPageNumbers)=>updateOptions({
16342
+ rightAlignPageNumbers
16343
+ }),
16344
+ children: "页码右对齐"
16345
+ })
16346
+ ]
16347
+ }),
16348
+ /*#__PURE__*/ jsxs("div", {
16349
+ className: "work-document-table-of-contents-dialog-leader",
16350
+ children: [
16351
+ /*#__PURE__*/ jsx("span", {
16352
+ children: "前导符"
16353
+ }),
16354
+ /*#__PURE__*/ jsx(OfficeSelect, {
16355
+ ariaLabel: "目录前导符",
16356
+ value: options.leader,
16357
+ options: tableOfContentsLeaderOptions,
16358
+ disabled: !options.showPageNumbers || !options.rightAlignPageNumbers,
16359
+ onValueChange: (leader)=>updateOptions({
16360
+ leader
16361
+ })
16362
+ })
16363
+ ]
16364
+ }),
16365
+ /*#__PURE__*/ jsxs("fieldset", {
16366
+ className: "work-document-table-of-contents-dialog-preview",
16367
+ "aria-label": "目录预览",
16368
+ "data-toc-leader": options.leader,
16369
+ "data-toc-right-align-page-numbers": String(options.rightAlignPageNumbers),
16370
+ children: [
16371
+ /*#__PURE__*/ jsx("legend", {
16372
+ children: "目录"
16373
+ }),
16374
+ /*#__PURE__*/ jsxs("span", {
16375
+ children: [
16376
+ "项目概述 ",
16377
+ /*#__PURE__*/ jsx("i", {
16378
+ "aria-hidden": "true"
16379
+ }),
16380
+ options.showPageNumbers ? '1' : ''
16381
+ ]
16382
+ }),
16383
+ /*#__PURE__*/ jsxs("span", {
16384
+ className: "nested",
16385
+ children: [
16386
+ "实施计划 ",
16387
+ /*#__PURE__*/ jsx("i", {
16388
+ "aria-hidden": "true"
16389
+ }),
16390
+ options.showPageNumbers ? '3' : ''
16391
+ ]
16392
+ })
16393
+ ]
16394
+ })
16395
+ ]
16396
+ });
16397
+ }
16398
+ const tableOfContentsLevelOptions = Array.from({
16399
+ length: 9
16400
+ }, (_, index)=>({
16401
+ value: String(index + 1),
16402
+ label: `标题 ${index + 1}`
16403
+ }));
16404
+ const tableOfContentsLeaderOptions = [
16405
+ {
16406
+ value: 'dot',
16407
+ label: '点线(……)'
16408
+ },
16409
+ {
16410
+ value: 'dash',
16411
+ label: '短横线(----)'
16412
+ },
16413
+ {
16414
+ value: 'underline',
16415
+ label: '下划线(____)'
16416
+ },
16417
+ {
16418
+ value: 'none',
16419
+ label: '无'
16420
+ }
16421
+ ];
16422
+ function DocumentIndexDialog({ editing, options, restoreFocusTarget, onCancel, onOptionsChange, onSubmit }) {
16423
+ const update = (patch)=>onOptionsChange({
16424
+ ...options,
16425
+ ...patch
16426
+ });
16427
+ return /*#__PURE__*/ jsxs(Dialog, {
16428
+ title: editing ? '自定义索引' : '插入索引',
16429
+ description: "从已标记的索引项生成可更新索引,并保留原生 DOCX INDEX 域。",
16430
+ className: "work-document-index-dialog",
16431
+ restoreFocusTarget: restoreFocusTarget,
16432
+ onClose: onCancel,
16433
+ footer: /*#__PURE__*/ jsxs(Fragment, {
16434
+ children: [
16435
+ /*#__PURE__*/ jsx(button_Button, {
16436
+ tone: "quiet",
16437
+ onClick: onCancel,
16438
+ children: "取消"
16439
+ }),
16440
+ /*#__PURE__*/ jsx(button_Button, {
16441
+ tone: "primary",
16442
+ onClick: onSubmit,
16443
+ children: editing ? '应用' : '插入索引'
16444
+ })
16445
+ ]
16446
+ }),
16447
+ children: [
16448
+ /*#__PURE__*/ jsxs("div", {
16449
+ className: "work-document-index-dialog-grid",
16450
+ children: [
16451
+ /*#__PURE__*/ jsxs("div", {
16452
+ className: "work-document-index-dialog-field",
16453
+ children: [
16454
+ /*#__PURE__*/ jsx("span", {
16455
+ children: "栏数"
16456
+ }),
16457
+ /*#__PURE__*/ jsx(OfficeSelect, {
16458
+ initialFocus: true,
16459
+ ariaLabel: "索引栏数",
16460
+ value: String(options.columns),
16461
+ options: indexColumnOptions,
16462
+ onValueChange: (columns)=>update({
16463
+ columns: Number(columns)
16464
+ })
16465
+ })
16466
+ ]
16467
+ }),
16468
+ /*#__PURE__*/ jsxs("div", {
16469
+ className: "work-document-index-dialog-field",
16470
+ children: [
16471
+ /*#__PURE__*/ jsx("span", {
16472
+ children: "次索引项布局"
16473
+ }),
16474
+ /*#__PURE__*/ jsx(OfficeSelect, {
16475
+ ariaLabel: "索引布局",
16476
+ value: options.format,
16477
+ options: indexFormatOptions,
16478
+ onValueChange: (format)=>update({
16479
+ format
16480
+ })
16481
+ })
16482
+ ]
16483
+ })
16484
+ ]
16485
+ }),
16486
+ /*#__PURE__*/ jsxs("div", {
16487
+ className: "work-document-index-dialog-options",
16488
+ children: [
16489
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16490
+ ariaLabel: "页码右对齐",
16491
+ checked: options.rightAlignPageNumbers,
16492
+ onCheckedChange: (rightAlignPageNumbers)=>update({
16493
+ rightAlignPageNumbers
16494
+ }),
16495
+ children: "页码右对齐"
16496
+ }),
16497
+ /*#__PURE__*/ jsxs("div", {
16498
+ className: "work-document-index-dialog-field",
16499
+ children: [
16500
+ /*#__PURE__*/ jsx("span", {
16501
+ children: "前导符"
16502
+ }),
16503
+ /*#__PURE__*/ jsx(OfficeSelect, {
16504
+ ariaLabel: "索引前导符",
16505
+ value: options.leader,
16506
+ options: indexLeaderOptions,
16507
+ disabled: !options.rightAlignPageNumbers,
16508
+ onValueChange: (leader)=>update({
16509
+ leader
16510
+ })
16511
+ })
16512
+ ]
16513
+ })
16514
+ ]
16515
+ }),
16516
+ /*#__PURE__*/ jsxs("fieldset", {
16517
+ className: "work-document-index-dialog-preview",
16518
+ "aria-label": "索引预览",
16519
+ "data-index-format": options.format,
16520
+ "data-index-leader": options.leader,
16521
+ "data-index-right-align-page-numbers": String(options.rightAlignPageNumbers),
16522
+ children: [
16523
+ /*#__PURE__*/ jsx("legend", {
16524
+ children: "索引"
16525
+ }),
16526
+ /*#__PURE__*/ jsxs("span", {
16527
+ children: [
16528
+ "Architecture ",
16529
+ /*#__PURE__*/ jsx("i", {
16530
+ "aria-hidden": "true"
16531
+ }),
16532
+ " 1, 3"
16533
+ ]
16534
+ }),
16535
+ /*#__PURE__*/ jsxs("span", {
16536
+ className: "nested",
16537
+ children: [
16538
+ "Runtime ",
16539
+ /*#__PURE__*/ jsx("i", {
16540
+ "aria-hidden": "true"
16541
+ }),
16542
+ " 5"
16543
+ ]
16544
+ })
16545
+ ]
16546
+ })
16547
+ ]
16548
+ });
16549
+ }
16550
+ const indexColumnOptions = [
16551
+ {
16552
+ value: '1',
16553
+ label: '一栏'
16554
+ },
16555
+ {
16556
+ value: '2',
16557
+ label: '两栏'
16558
+ },
16559
+ {
16560
+ value: '3',
16561
+ label: '三栏'
16562
+ },
16563
+ {
16564
+ value: '4',
16565
+ label: '四栏'
16566
+ }
16567
+ ];
16568
+ const indexFormatOptions = [
16569
+ {
16570
+ value: 'indented',
16571
+ label: '缩进式'
16572
+ },
16573
+ {
16574
+ value: 'run-in',
16575
+ label: '连续式'
16576
+ }
16577
+ ];
16578
+ const indexLeaderOptions = [
16579
+ {
16580
+ value: 'dot',
16581
+ label: '点线(……)'
16582
+ },
16583
+ {
16584
+ value: 'dash',
16585
+ label: '短横线(----)'
16586
+ },
16587
+ {
16588
+ value: 'underline',
16589
+ label: '下划线(____)'
16590
+ },
16591
+ {
16592
+ value: 'none',
16593
+ label: '无'
16594
+ }
16595
+ ];
16596
+ function DocumentIndexEntryDialog({ editing, value, restoreFocusTarget, onCancel, onChange, onSubmit }) {
16597
+ const update = (patch)=>onChange({
16598
+ ...value,
16599
+ ...patch
16600
+ });
16601
+ const crossReferenceEnabled = Boolean(value.crossReference);
16602
+ const mainEntryId = useId();
16603
+ const subEntryId = useId();
16604
+ const crossReferenceId = useId();
16605
+ return /*#__PURE__*/ jsxs(Dialog, {
16606
+ title: editing ? '编辑索引项' : '标记索引项',
16607
+ description: "标记主索引项、次索引项或交叉引用,并保留原生 DOCX XE 域。",
16608
+ className: "work-document-index-entry-dialog",
16609
+ restoreFocusTarget: restoreFocusTarget,
16610
+ onClose: onCancel,
16611
+ footer: /*#__PURE__*/ jsxs(Fragment, {
16612
+ children: [
16613
+ /*#__PURE__*/ jsx(button_Button, {
16614
+ tone: "quiet",
16615
+ onClick: onCancel,
16616
+ children: "取消"
16617
+ }),
16618
+ /*#__PURE__*/ jsx(button_Button, {
16619
+ tone: "primary",
16620
+ disabled: !value.mainEntry.trim(),
16621
+ onClick: onSubmit,
16622
+ children: editing ? '应用' : '标记'
16623
+ })
16624
+ ]
16625
+ }),
16626
+ children: [
16627
+ /*#__PURE__*/ jsxs("div", {
16628
+ className: "work-document-index-entry-dialog-fields",
16629
+ children: [
16630
+ /*#__PURE__*/ jsxs("label", {
16631
+ htmlFor: mainEntryId,
16632
+ children: [
16633
+ /*#__PURE__*/ jsx("span", {
16634
+ children: "主索引项"
16635
+ }),
16636
+ /*#__PURE__*/ jsx(office_text_field_OfficeTextField, {
16637
+ id: mainEntryId,
16638
+ "data-autofocus": true,
16639
+ "aria-label": "主索引项",
16640
+ value: value.mainEntry,
16641
+ maxLength: 240,
16642
+ onChange: (event)=>update({
16643
+ mainEntry: event.target.value
16644
+ }),
16645
+ onKeyDown: (event)=>{
16646
+ if ('Enter' !== event.key || !value.mainEntry.trim()) return;
16647
+ event.preventDefault();
16648
+ onSubmit();
16649
+ }
16650
+ })
16651
+ ]
16652
+ }),
16653
+ /*#__PURE__*/ jsxs("label", {
16654
+ htmlFor: subEntryId,
16655
+ children: [
16656
+ /*#__PURE__*/ jsx("span", {
16657
+ children: "次索引项"
16658
+ }),
16659
+ /*#__PURE__*/ jsx(office_text_field_OfficeTextField, {
16660
+ id: subEntryId,
16661
+ "aria-label": "次索引项",
16662
+ value: value.subEntry,
16663
+ maxLength: 240,
16664
+ placeholder: "可选",
16665
+ onChange: (event)=>update({
16666
+ subEntry: event.target.value
16667
+ })
16668
+ })
16669
+ ]
16670
+ })
16671
+ ]
16672
+ }),
16673
+ /*#__PURE__*/ jsxs("div", {
16674
+ className: "work-document-index-entry-dialog-mode",
16675
+ children: [
16676
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16677
+ ariaLabel: "使用交叉引用",
16678
+ checked: crossReferenceEnabled,
16679
+ onCheckedChange: (enabled)=>update({
16680
+ crossReference: enabled ? value.crossReference || '参见' : '',
16681
+ pageBold: enabled ? false : value.pageBold,
16682
+ pageItalic: enabled ? false : value.pageItalic
16683
+ }),
16684
+ children: "使用交叉引用"
16685
+ }),
16686
+ crossReferenceEnabled && /*#__PURE__*/ jsxs("label", {
16687
+ htmlFor: crossReferenceId,
16688
+ children: [
16689
+ /*#__PURE__*/ jsx("span", {
16690
+ children: "引用目标"
16691
+ }),
16692
+ /*#__PURE__*/ jsx(office_text_field_OfficeTextField, {
16693
+ id: crossReferenceId,
16694
+ "aria-label": "交叉引用目标",
16695
+ value: value.crossReference,
16696
+ maxLength: 240,
16697
+ placeholder: "例如:Architecture",
16698
+ onChange: (event)=>update({
16699
+ crossReference: event.target.value
16700
+ })
16701
+ })
16702
+ ]
16703
+ })
16704
+ ]
16705
+ }),
16706
+ /*#__PURE__*/ jsxs("fieldset", {
16707
+ className: "work-document-index-entry-dialog-page-style",
16708
+ disabled: crossReferenceEnabled,
16709
+ children: [
16710
+ /*#__PURE__*/ jsx("legend", {
16711
+ children: "当前页码格式"
16712
+ }),
16713
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16714
+ ariaLabel: "页码加粗",
16715
+ checked: value.pageBold,
16716
+ disabled: crossReferenceEnabled,
16717
+ onCheckedChange: (pageBold)=>update({
16718
+ pageBold
16719
+ }),
16720
+ children: "页码加粗"
16721
+ }),
16722
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
16723
+ ariaLabel: "页码倾斜",
16724
+ checked: value.pageItalic,
16725
+ disabled: crossReferenceEnabled,
16726
+ onCheckedChange: (pageItalic)=>update({
16727
+ pageItalic
16728
+ }),
16729
+ children: "页码倾斜"
16730
+ })
16731
+ ]
16732
+ })
16733
+ ]
16734
+ });
16735
+ }
15363
16736
  function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext }) {
15364
16737
  const officeDialog = useOfficeDialog();
15365
16738
  const [insertDialog, setInsertDialog] = useState(null);
@@ -15453,6 +16826,50 @@ function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext })
15453
16826
  editor,
15454
16827
  resolveFieldContext
15455
16828
  ]);
16829
+ const openTableOfContents = useCallback(()=>{
16830
+ if (!editor) return;
16831
+ rememberInvoker();
16832
+ const selected = selectedDocumentTableOfContentsOptions(editor);
16833
+ setInsertDialog({
16834
+ kind: 'tableOfContents',
16835
+ editing: Boolean(selected),
16836
+ options: selected ?? DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS
16837
+ });
16838
+ }, [
16839
+ editor,
16840
+ rememberInvoker
16841
+ ]);
16842
+ const openIndexEntry = useCallback(()=>{
16843
+ if (!editor) return;
16844
+ const value = selectedDocumentIndexDraft(editor);
16845
+ if (!value) return void officeDialog.notice({
16846
+ title: '请选择索引文字',
16847
+ description: '请先选择要标记的正文文字,或选中一个已有索引项。'
16848
+ });
16849
+ rememberInvoker();
16850
+ setInsertDialog({
16851
+ kind: 'indexEntry',
16852
+ editing: Boolean(selectedDocumentIndexEntry(editor)),
16853
+ value
16854
+ });
16855
+ }, [
16856
+ editor,
16857
+ officeDialog,
16858
+ rememberInvoker
16859
+ ]);
16860
+ const openIndex = useCallback(()=>{
16861
+ if (!editor) return;
16862
+ rememberInvoker();
16863
+ const selected = selectedDocumentIndexOptions(editor);
16864
+ setInsertDialog({
16865
+ kind: 'index',
16866
+ editing: Boolean(selected),
16867
+ options: selected ?? DEFAULT_DOCUMENT_INDEX_OPTIONS
16868
+ });
16869
+ }, [
16870
+ editor,
16871
+ rememberInvoker
16872
+ ]);
15456
16873
  const refreshFields = useCallback(()=>editor?.commands.refreshDocumentFields(contentRef.current, {
15457
16874
  resolveContext: resolveFieldContext ?? void 0
15458
16875
  }) ?? false, [
@@ -15460,6 +16877,18 @@ function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext })
15460
16877
  editor,
15461
16878
  resolveFieldContext
15462
16879
  ]);
16880
+ const refreshTableOfContents = useCallback(()=>editor?.commands.refreshDocumentTablesOfContents({
16881
+ resolveContext: resolveFieldContext ?? void 0
16882
+ }) ?? false, [
16883
+ editor,
16884
+ resolveFieldContext
16885
+ ]);
16886
+ const refreshIndex = useCallback(()=>editor?.commands.refreshDocumentIndexes({
16887
+ resolveContext: resolveFieldContext ?? void 0
16888
+ }) ?? false, [
16889
+ editor,
16890
+ resolveFieldContext
16891
+ ]);
15463
16892
  const submitCaption = ()=>{
15464
16893
  if (!editor || insertDialog?.kind !== 'caption') return;
15465
16894
  const inserted = editor.chain().focus().insertDocumentCaption(insertDialog.captionKind, insertDialog.title.trim()).run();
@@ -15476,6 +16905,33 @@ function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext })
15476
16905
  invokerRef.current = editor.view.dom;
15477
16906
  setInsertDialog(null);
15478
16907
  };
16908
+ const submitTableOfContents = ()=>{
16909
+ if (!editor || insertDialog?.kind !== 'tableOfContents') return;
16910
+ const buildOptions = {
16911
+ resolveContext: resolveFieldContext ?? void 0
16912
+ };
16913
+ const applied = insertDialog.editing ? editor.commands.updateDocumentTableOfContents(insertDialog.options, buildOptions) : editor.commands.insertDocumentTableOfContents(insertDialog.options, buildOptions);
16914
+ if (!applied) return;
16915
+ invokerRef.current = editor.view.dom;
16916
+ setInsertDialog(null);
16917
+ };
16918
+ const submitIndexEntry = ()=>{
16919
+ if (!editor || insertDialog?.kind !== 'indexEntry') return;
16920
+ const applied = insertDialog.editing ? editor.commands.updateDocumentIndexEntry(insertDialog.value) : editor.commands.markDocumentIndexEntry(insertDialog.value);
16921
+ if (!applied) return;
16922
+ invokerRef.current = editor.view.dom;
16923
+ setInsertDialog(null);
16924
+ };
16925
+ const submitIndex = ()=>{
16926
+ if (!editor || insertDialog?.kind !== 'index') return;
16927
+ const buildOptions = {
16928
+ resolveContext: resolveFieldContext ?? void 0
16929
+ };
16930
+ const applied = insertDialog.editing ? editor.commands.updateDocumentIndex(insertDialog.options, buildOptions) : editor.commands.insertDocumentIndex(insertDialog.options, buildOptions);
16931
+ if (!applied) return;
16932
+ invokerRef.current = editor.view.dom;
16933
+ setInsertDialog(null);
16934
+ };
15479
16935
  const moveReferenceSelection = (event, currentIndex)=>{
15480
16936
  if (insertDialog?.kind !== 'crossReference') return;
15481
16937
  let nextIndex = currentIndex;
@@ -15606,6 +17062,39 @@ function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext })
15606
17062
  }, targetKey);
15607
17063
  })
15608
17064
  })
17065
+ }),
17066
+ insertDialog?.kind === 'tableOfContents' && /*#__PURE__*/ jsx(DocumentTableOfContentsDialog, {
17067
+ editing: insertDialog.editing,
17068
+ options: insertDialog.options,
17069
+ restoreFocusTarget: ()=>invokerRef.current,
17070
+ onCancel: ()=>setInsertDialog(null),
17071
+ onOptionsChange: (options)=>setInsertDialog({
17072
+ ...insertDialog,
17073
+ options
17074
+ }),
17075
+ onSubmit: submitTableOfContents
17076
+ }),
17077
+ insertDialog?.kind === 'indexEntry' && /*#__PURE__*/ jsx(DocumentIndexEntryDialog, {
17078
+ editing: insertDialog.editing,
17079
+ value: insertDialog.value,
17080
+ restoreFocusTarget: ()=>invokerRef.current,
17081
+ onCancel: ()=>setInsertDialog(null),
17082
+ onChange: (value)=>setInsertDialog({
17083
+ ...insertDialog,
17084
+ value
17085
+ }),
17086
+ onSubmit: submitIndexEntry
17087
+ }),
17088
+ insertDialog?.kind === 'index' && /*#__PURE__*/ jsx(DocumentIndexDialog, {
17089
+ editing: insertDialog.editing,
17090
+ options: insertDialog.options,
17091
+ restoreFocusTarget: ()=>invokerRef.current,
17092
+ onCancel: ()=>setInsertDialog(null),
17093
+ onOptionsChange: (options)=>setInsertDialog({
17094
+ ...insertDialog,
17095
+ options
17096
+ }),
17097
+ onSubmit: submitIndex
15609
17098
  })
15610
17099
  ]
15611
17100
  });
@@ -15616,7 +17105,12 @@ function useDocumentInsertCommands({ contentRef, editor, resolveFieldContext })
15616
17105
  insertField,
15617
17106
  insertImage,
15618
17107
  insertNote,
15619
- refreshFields
17108
+ openIndexEntry,
17109
+ openIndex,
17110
+ openTableOfContents,
17111
+ refreshFields,
17112
+ refreshIndex,
17113
+ refreshTableOfContents
15620
17114
  };
15621
17115
  }
15622
17116
  function referenceTargetKey(target) {
@@ -17681,6 +19175,14 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
17681
19175
  documentInsert.refreshFields();
17682
19176
  restoreDocumentBodyFocus();
17683
19177
  };
19178
+ const refreshDocumentTableOfContents = ()=>{
19179
+ documentInsert.refreshTableOfContents();
19180
+ restoreDocumentBodyFocus();
19181
+ };
19182
+ const refreshDocumentIndex = ()=>{
19183
+ documentInsert.refreshIndex();
19184
+ restoreDocumentBodyFocus();
19185
+ };
17684
19186
  const openSelectionContextMenu = (event)=>{
17685
19187
  if (!canEditDocument || !getSelectionMenuItems && !onAgentRequest) return false;
17686
19188
  const snapshot = createWorkDocumentSelectionSnapshot(editor, contentRef.current);
@@ -17777,11 +19279,16 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
17777
19279
  onInsertNote: documentInsert.insertNote,
17778
19280
  onInsertCaption: documentInsert.insertCaption,
17779
19281
  onInsertCrossReference: documentInsert.insertCrossReference,
19282
+ onOpenTableOfContents: documentInsert.openTableOfContents,
19283
+ onOpenIndexEntry: documentInsert.openIndexEntry,
19284
+ onOpenIndex: documentInsert.openIndex,
17780
19285
  citationsOpen: citationsOpen,
17781
19286
  citationSourceCount: currentContent.bibliography?.sources.length ?? 0,
17782
19287
  onToggleCitations: ()=>void toggleTaskPane('citations'),
17783
19288
  onInsertField: documentInsert.insertField,
17784
19289
  onRefreshFields: refreshDocumentFields,
19290
+ onRefreshIndex: refreshDocumentIndex,
19291
+ onRefreshTableOfContents: refreshDocumentTableOfContents,
17785
19292
  canInsertComment: documentComments.canInsert,
17786
19293
  onInsertComment: ()=>void startCommentDraft(),
17787
19294
  commentsOpen: documentComments.open,