@stll/folio-core 0.42.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compat/eigenpal.d.ts +2 -2
- package/dist/controller/layoutPipeline.d.ts +2 -1
- package/dist/controller/layoutPipeline.js +5 -2
- package/dist/controller/layoutSession.d.ts +2 -1
- package/dist/controller/layoutSession.js +1 -0
- package/dist/docx/blockContentParser.js +2 -1
- package/dist/docx/commentIdNormalization.d.ts +8 -0
- package/dist/docx/commentIdNormalization.js +16 -0
- package/dist/docx/defaultParagraphStyle.d.ts +22 -0
- package/dist/docx/defaultParagraphStyle.js +32 -0
- package/dist/docx/footnoteParser.js +2 -0
- package/dist/docx/headerFooterRefParser.d.ts +12 -1
- package/dist/docx/headerFooterRefParser.js +9 -2
- package/dist/docx/numberingParser.js +2 -1
- package/dist/docx/numberingReference.d.ts +21 -0
- package/dist/docx/numberingReference.js +21 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +11 -2
- package/dist/docx/numberingReferenceNormalization.js +32 -9
- package/dist/docx/paragraphParser.js +3 -2
- package/dist/docx/parser.js +10 -2
- package/dist/docx/rezip.js +22 -5
- package/dist/docx/server/createBilingualDocument.js +5 -4
- package/dist/docx/styleParser.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +7 -5
- package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +19 -11
- package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
- package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
- package/dist/prosemirror/commands/pageBreak.js +12 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +2 -1
- package/dist/prosemirror/conversion/toProseDoc.js +27 -12
- package/dist/prosemirror/extensions/features/ListExtension.js +42 -4
- package/dist/prosemirror/listMarker.js +2 -1
- package/dist/prosemirror/numberedRefFields.js +2 -1
- package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
- package/dist/prosemirror/pageBreakRunProjection.js +16 -8
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +42 -1
- package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -1
- package/dist/prosemirror/styles/styleResolver.js +3 -6
- package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
- package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
- package/dist/style-engine/styleEngine.d.ts +1 -1
- package/dist/style-sets/extract.js +57 -11
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ import { getFolioCaretViewportRect, getFolioSelectionViewportRect } from "./page
|
|
|
30
30
|
import { AICitationRange, createAICitationDecorationsPlugin, setAICitationsMeta, setActiveCitationMeta } from "./prosemirror/plugins/aiCitationDecorations.js";
|
|
31
31
|
import { AnonymizationMatch, AnonymizationTerm, anonymizationDecorationsKey, getAnonymizationMatches, setAnonymizationTermsMeta } from "./prosemirror/plugins/anonymizationDecorations.js";
|
|
32
32
|
import { DirectiveKind, DirectiveRange, getTemplateDirectives, scanDirectives } from "./prosemirror/plugins/templateDirectives.js";
|
|
33
|
-
import { TemplatePreviewSpan, TemplatePreviewValue, TemplatePreviewValues, setTemplatePreviewValues } from "./prosemirror/plugins/templatePreviewValues.js";
|
|
33
|
+
import { TemplatePreviewHiddenRange, TemplatePreviewSpan, TemplatePreviewValue, TemplatePreviewValues, setTemplatePreviewValues } from "./prosemirror/plugins/templatePreviewValues.js";
|
|
34
34
|
import { TemplateSlashMenuKeyAction, TemplateSlashMenuState, clearTemplateSlashMenu, consumeTemplateSlashQuery, getTemplateSlashMenu, resetTemplateSlashQuery, templateSlashMenuKey } from "./prosemirror/plugins/templateSlashMenu.js";
|
|
35
35
|
import { AcceptAutocompleteResult, AutocompleteSuggestionPluginOptions, AutocompleteSuggestionState, AutocompleteSuggestionStatus, AutocompleteTriggerCheck, AutocompleteTriggerOptions, AutocompleteTriggerSkipReason, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, acceptAutocompleteSuggestion, acceptAutocompleteWord, appendAutocompleteToken, autocompleteSuggestionKey, autocompleteSuggestionPlugin, clearAutocompleteSuggestion, finishAutocompleteSuggestion, getAutocompleteSuggestion, shouldTriggerAutocomplete, startAutocompleteSuggestion } from "./prosemirror/plugins/autocompleteSuggestion.js";
|
|
36
36
|
import { ImageMeta, ImageRef, MarkdownOptions, MarkdownResult } from "./markdown/types.js";
|
|
@@ -41,4 +41,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
|
|
|
41
41
|
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
42
42
|
type Document = document_d_exports.Document;
|
|
43
43
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
44
|
-
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
44
|
+
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
@@ -2,6 +2,8 @@ import { document_d_exports } from "../types/document.js";
|
|
|
2
2
|
//#region src/internal/pageBreakRunSourceDescendantIndex.d.ts
|
|
3
3
|
type PageBreakRunSourceDescendantIndex = {
|
|
4
4
|
containsPageBreakRun: (content: readonly document_d_exports.BlockContent[]) => boolean;
|
|
5
|
+
/** The same question about one block, so a caller can ask it per sibling. */
|
|
6
|
+
blockContainsPageBreakRun: (block: document_d_exports.BlockContent) => boolean;
|
|
5
7
|
paragraphFeatures: (paragraph: document_d_exports.Paragraph) => PageBreakRunSourceParagraphFeatures;
|
|
6
8
|
};
|
|
7
9
|
type PageBreakRunSourceParagraphFeatures = {
|
|
@@ -105,12 +105,14 @@ const buildPageBreakRunSourceDescendantIndex = (rootContent) => {
|
|
|
105
105
|
return flags;
|
|
106
106
|
}
|
|
107
107
|
inspectBlocks(rootContent);
|
|
108
|
+
const indexedFlags = (node) => {
|
|
109
|
+
const flags = flagsByObject.get(node);
|
|
110
|
+
if (flags === void 0) panic("Page-break source ownership was queried outside its conversion index");
|
|
111
|
+
return flags;
|
|
112
|
+
};
|
|
108
113
|
return {
|
|
109
|
-
containsPageBreakRun: (content) =>
|
|
110
|
-
|
|
111
|
-
if (flags === void 0) panic("Page-break source ownership was queried outside its conversion index");
|
|
112
|
-
return hasFlag(flags, SOURCE_FLAGS.containsPageBreak);
|
|
113
|
-
},
|
|
114
|
+
containsPageBreakRun: (content) => hasFlag(indexedFlags(content), SOURCE_FLAGS.containsPageBreak),
|
|
115
|
+
blockContainsPageBreakRun: (block) => hasFlag(indexedFlags(block), SOURCE_FLAGS.containsPageBreak),
|
|
114
116
|
paragraphFeatures: (paragraph) => {
|
|
115
117
|
const flags = flagsByObject.get(paragraph);
|
|
116
118
|
if (flags === void 0) panic("Page-break paragraph ownership was queried outside its conversion index");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TemplatePreviewValue } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
1
|
+
import { TemplatePreviewHiddenRange, TemplatePreviewValue } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
2
2
|
import { FlowBlock } from "../../layout-engine/types.js";
|
|
3
3
|
//#region src/layout-bridge/convert/templatePreviewFlow.d.ts
|
|
4
4
|
/** One marker→value substitution, in PM doc positions. */
|
|
@@ -10,27 +10,35 @@ type TemplatePreviewFlowEntry = {
|
|
|
10
10
|
/** The typed value displayed in place of the marker. */
|
|
11
11
|
value: TemplatePreviewValue;
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
/** What the preview substitutes and what it hides, as the flow stage sees it. */
|
|
14
|
+
type TemplatePreviewFlowState = {
|
|
14
15
|
entries: readonly TemplatePreviewFlowEntry[];
|
|
16
|
+
/** Conditional spans a `false` condition hides, in PM doc positions. */
|
|
17
|
+
hidden: readonly TemplatePreviewHiddenRange[];
|
|
18
|
+
};
|
|
19
|
+
type TemplatePreviewFlowOptions = TemplatePreviewFlowState & {
|
|
15
20
|
/** `highlighted` marks substituted runs for the accent-chip CSS. */
|
|
16
21
|
mode: "highlighted" | "plain";
|
|
17
22
|
};
|
|
18
23
|
/**
|
|
19
24
|
* Replace each entry's marker range with its preview value across the given
|
|
20
|
-
* flow blocks (recursing into table cells and text boxes)
|
|
21
|
-
*
|
|
25
|
+
* flow blocks (recursing into table cells and text boxes), and drop the blocks
|
|
26
|
+
* a hidden conditional span swallows whole. Returns the input array unchanged
|
|
27
|
+
* when there is nothing to substitute and nothing to hide.
|
|
22
28
|
*/
|
|
23
|
-
declare function applyTemplatePreviewToBlocks(blocks: FlowBlock[], { entries, mode }: TemplatePreviewFlowOptions): FlowBlock[];
|
|
29
|
+
declare function applyTemplatePreviewToBlocks(blocks: FlowBlock[], { entries, hidden, mode }: TemplatePreviewFlowOptions): FlowBlock[];
|
|
24
30
|
/**
|
|
25
|
-
* PM range covering every substitution
|
|
26
|
-
* states (changed, added, or removed
|
|
27
|
-
*
|
|
31
|
+
* PM range covering every substitution and every hidden span that differs
|
|
32
|
+
* between two preview states (changed, added, or removed), or `null` when the
|
|
33
|
+
* flow content both produce is identical. Feeds the layout pipeline's
|
|
28
34
|
* dirty-range invalidation so typing a value re-measures only the blocks
|
|
29
|
-
* hosting the affected markers.
|
|
35
|
+
* hosting the affected markers. A hidden span that appears or disappears also
|
|
36
|
+
* changes the block count, which sends the measure path down its full-remeasure
|
|
37
|
+
* branch regardless of how wide this range is.
|
|
30
38
|
*/
|
|
31
|
-
declare function templatePreviewDirtyRange(previous:
|
|
39
|
+
declare function templatePreviewDirtyRange(previous: TemplatePreviewFlowState, next: TemplatePreviewFlowState): {
|
|
32
40
|
from: number;
|
|
33
41
|
to: number;
|
|
34
42
|
} | null;
|
|
35
43
|
//#endregion
|
|
36
|
-
export { TemplatePreviewFlowEntry, TemplatePreviewFlowOptions, applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
44
|
+
export { TemplatePreviewFlowEntry, TemplatePreviewFlowOptions, TemplatePreviewFlowState, applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
@@ -1,16 +1,41 @@
|
|
|
1
|
-
import { templatePreviewValueFingerprint } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
1
|
+
import { templatePreviewHidesWholeBlock, templatePreviewValueFingerprint } from "../../prosemirror/plugins/templatePreviewValues.js";
|
|
2
2
|
//#region src/layout-bridge/convert/templatePreviewFlow.ts
|
|
3
3
|
/**
|
|
4
|
+
* A top-level block a hidden span swallows whole, which therefore leaves the
|
|
5
|
+
* flow. A block the span only partly covers stays: its text is authored content
|
|
6
|
+
* outside the conditional, and dropping the block would take that text with it.
|
|
7
|
+
*
|
|
8
|
+
* A block carrying no PM positions stays too. That is every section break,
|
|
9
|
+
* which is the safe answer rather than an accident: a section break sets the
|
|
10
|
+
* page geometry that follows it, so hiding text must not take it out of the
|
|
11
|
+
* flow. `SectionBreakBlock` is the one `FlowBlock` variant without the fields,
|
|
12
|
+
* hence the `in` test, matching `findDirtyBlockIndexes`.
|
|
13
|
+
*/
|
|
14
|
+
const isHiddenWholeBlock = (block, hidden) => {
|
|
15
|
+
const pmStart = "pmStart" in block ? block.pmStart : void 0;
|
|
16
|
+
const pmEnd = "pmEnd" in block ? block.pmEnd : void 0;
|
|
17
|
+
if (pmStart === void 0 || pmEnd === void 0) return false;
|
|
18
|
+
return hidden.some((range) => templatePreviewHidesWholeBlock(range, {
|
|
19
|
+
pmStart,
|
|
20
|
+
pmEnd
|
|
21
|
+
}));
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
4
24
|
* Replace each entry's marker range with its preview value across the given
|
|
5
|
-
* flow blocks (recursing into table cells and text boxes)
|
|
6
|
-
*
|
|
25
|
+
* flow blocks (recursing into table cells and text boxes), and drop the blocks
|
|
26
|
+
* a hidden conditional span swallows whole. Returns the input array unchanged
|
|
27
|
+
* when there is nothing to substitute and nothing to hide.
|
|
7
28
|
*/
|
|
8
|
-
function applyTemplatePreviewToBlocks(blocks, { entries, mode }) {
|
|
9
|
-
if (entries.length === 0) return blocks;
|
|
29
|
+
function applyTemplatePreviewToBlocks(blocks, { entries, hidden, mode }) {
|
|
30
|
+
if (entries.length === 0 && hidden.length === 0) return blocks;
|
|
10
31
|
const sorted = [...entries].sort((a, b) => a.from - b.from);
|
|
11
32
|
let changed = false;
|
|
12
33
|
const next = [];
|
|
13
34
|
for (const block of blocks) {
|
|
35
|
+
if (isHiddenWholeBlock(block, hidden)) {
|
|
36
|
+
changed = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
14
39
|
const transformed = transformBlock(block, sorted, mode);
|
|
15
40
|
changed ||= transformed !== block;
|
|
16
41
|
next.push(transformed);
|
|
@@ -117,60 +142,100 @@ function sliceTextRun(run, base, from, to) {
|
|
|
117
142
|
pmEnd: to
|
|
118
143
|
};
|
|
119
144
|
}
|
|
145
|
+
/** Every newline form a host value may carry; `\r\n` counts once. */
|
|
146
|
+
const VALUE_LINE_BREAK_RE = /\r\n|[\n\r]/u;
|
|
147
|
+
/**
|
|
148
|
+
* Push one span of value text, breaking its lines the way the editor does: each
|
|
149
|
+
* newline becomes a `lineBreak` run, which is the `w:br` the measurer starts a
|
|
150
|
+
* new line on. Consecutive newlines emit consecutive breaks, so a blank line
|
|
151
|
+
* stays a blank line; an empty segment contributes no text run of its own.
|
|
152
|
+
*
|
|
153
|
+
* A rich value's spans are one text stream, so a `\r\n` the host split across a
|
|
154
|
+
* formatting boundary is still one break: `pendingCr` carries a `\r` that ended
|
|
155
|
+
* the previous span, and the returned flag carries this span's. Without it the
|
|
156
|
+
* halves would count as two breaks and the value would gain a blank line.
|
|
157
|
+
*/
|
|
158
|
+
function pushValueSpan(out, valueRun, pendingCr) {
|
|
159
|
+
const text = pendingCr && valueRun.text.startsWith("\n") ? valueRun.text.slice(1) : valueRun.text;
|
|
160
|
+
const segments = text.split(VALUE_LINE_BREAK_RE);
|
|
161
|
+
for (const [index, segment] of segments.entries()) {
|
|
162
|
+
if (index > 0) out.push({
|
|
163
|
+
kind: "lineBreak",
|
|
164
|
+
pmStart: valueRun.pmStart,
|
|
165
|
+
pmEnd: valueRun.pmEnd
|
|
166
|
+
});
|
|
167
|
+
if (segment !== "") out.push({
|
|
168
|
+
...valueRun,
|
|
169
|
+
text: segment
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return text.endsWith("\r");
|
|
173
|
+
}
|
|
120
174
|
/**
|
|
121
175
|
* The value run(s) replacing a marker. A plain value is one run carrying the
|
|
122
176
|
* host run's formatting; a rich value emits one run per span, each layering
|
|
123
177
|
* its own bold/italic over the host formatting (host bold stays bold, a
|
|
124
|
-
* span's flags OR in).
|
|
125
|
-
*
|
|
178
|
+
* span's flags OR in). A newline in either splits its span around a line
|
|
179
|
+
* break run. Every run keeps the marker's full PM range so click-to-position
|
|
180
|
+
* keeps resolving into the marker.
|
|
126
181
|
*/
|
|
127
182
|
function buildValueRuns(host, entry, mode) {
|
|
128
|
-
|
|
183
|
+
const runs = [];
|
|
184
|
+
const base = {
|
|
129
185
|
...host,
|
|
130
|
-
text: entry.value,
|
|
131
186
|
pmStart: entry.from,
|
|
132
187
|
pmEnd: entry.to,
|
|
133
188
|
templatePreview: mode
|
|
134
|
-
}
|
|
135
|
-
|
|
189
|
+
};
|
|
190
|
+
if (typeof entry.value === "string") {
|
|
191
|
+
pushValueSpan(runs, {
|
|
192
|
+
...base,
|
|
193
|
+
text: entry.value
|
|
194
|
+
}, false);
|
|
195
|
+
return runs;
|
|
196
|
+
}
|
|
197
|
+
let pendingCr = false;
|
|
198
|
+
for (const span of entry.value.runs) {
|
|
136
199
|
const valueRun = {
|
|
137
|
-
...
|
|
138
|
-
text: span.text
|
|
139
|
-
pmStart: entry.from,
|
|
140
|
-
pmEnd: entry.to,
|
|
141
|
-
templatePreview: mode
|
|
200
|
+
...base,
|
|
201
|
+
text: span.text
|
|
142
202
|
};
|
|
143
203
|
if (span.bold === true) valueRun.bold = true;
|
|
144
204
|
if (span.italic === true) valueRun.italic = true;
|
|
145
|
-
|
|
146
|
-
}
|
|
205
|
+
pendingCr = pushValueSpan(runs, valueRun, pendingCr);
|
|
206
|
+
}
|
|
207
|
+
return runs;
|
|
147
208
|
}
|
|
148
209
|
const entryKey = (entry) => `${entry.from}:${entry.to}:${templatePreviewValueFingerprint(entry.value)}`;
|
|
210
|
+
const hiddenKey = (range) => `${range.from}:${range.to}:${range.expr}`;
|
|
211
|
+
/** Widen `bounds` over every range whose key is absent from `known`. */
|
|
212
|
+
const growOverUnknown = (ranges, key, known, bounds) => {
|
|
213
|
+
for (const range of ranges) {
|
|
214
|
+
if (known.has(key(range))) continue;
|
|
215
|
+
bounds.from = Math.min(bounds.from, range.from);
|
|
216
|
+
bounds.to = Math.max(bounds.to, range.to);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
149
219
|
/**
|
|
150
|
-
* PM range covering every substitution
|
|
151
|
-
* states (changed, added, or removed
|
|
152
|
-
*
|
|
220
|
+
* PM range covering every substitution and every hidden span that differs
|
|
221
|
+
* between two preview states (changed, added, or removed), or `null` when the
|
|
222
|
+
* flow content both produce is identical. Feeds the layout pipeline's
|
|
153
223
|
* dirty-range invalidation so typing a value re-measures only the blocks
|
|
154
|
-
* hosting the affected markers.
|
|
224
|
+
* hosting the affected markers. A hidden span that appears or disappears also
|
|
225
|
+
* changes the block count, which sends the measure path down its full-remeasure
|
|
226
|
+
* branch regardless of how wide this range is.
|
|
155
227
|
*/
|
|
156
228
|
function templatePreviewDirtyRange(previous, next) {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
let to = Number.NEGATIVE_INFINITY;
|
|
161
|
-
for (const entry of previous) if (!nextKeys.has(entryKey(entry))) {
|
|
162
|
-
from = Math.min(from, entry.from);
|
|
163
|
-
to = Math.max(to, entry.to);
|
|
164
|
-
}
|
|
165
|
-
for (const entry of next) if (!previousKeys.has(entryKey(entry))) {
|
|
166
|
-
from = Math.min(from, entry.from);
|
|
167
|
-
to = Math.max(to, entry.to);
|
|
168
|
-
}
|
|
169
|
-
if (from === Number.POSITIVE_INFINITY) return null;
|
|
170
|
-
return {
|
|
171
|
-
from,
|
|
172
|
-
to
|
|
229
|
+
const bounds = {
|
|
230
|
+
from: Number.POSITIVE_INFINITY,
|
|
231
|
+
to: Number.NEGATIVE_INFINITY
|
|
173
232
|
};
|
|
233
|
+
growOverUnknown(previous.entries, entryKey, new Set(next.entries.map(entryKey)), bounds);
|
|
234
|
+
growOverUnknown(next.entries, entryKey, new Set(previous.entries.map(entryKey)), bounds);
|
|
235
|
+
growOverUnknown(previous.hidden, hiddenKey, new Set(next.hidden.map(hiddenKey)), bounds);
|
|
236
|
+
growOverUnknown(next.hidden, hiddenKey, new Set(previous.hidden.map(hiddenKey)), bounds);
|
|
237
|
+
if (bounds.from === Number.POSITIVE_INFINITY) return null;
|
|
238
|
+
return bounds;
|
|
174
239
|
}
|
|
175
240
|
//#endregion
|
|
176
241
|
export { applyTemplatePreviewToBlocks, templatePreviewDirtyRange };
|
|
@@ -1175,6 +1175,15 @@ const runIsZeroWidthBoundaryMarker = (run) => {
|
|
|
1175
1175
|
default: return run;
|
|
1176
1176
|
}
|
|
1177
1177
|
};
|
|
1178
|
+
/** Every page-break run under a node, nested tables and text boxes included. */
|
|
1179
|
+
const countPageBreakRuns = (node) => {
|
|
1180
|
+
let count = node.type.name === "pageBreakRun" ? 1 : 0;
|
|
1181
|
+
node.descendants((descendant) => {
|
|
1182
|
+
if (descendant.type.name === "pageBreakRun") count += 1;
|
|
1183
|
+
return true;
|
|
1184
|
+
});
|
|
1185
|
+
return count;
|
|
1186
|
+
};
|
|
1178
1187
|
/** Decide leading-break eligibility from the exact projected runs consumed by layout. */
|
|
1179
1188
|
const hasSingleLeadingProjectedPageBreak = (runs, pageBreaks) => {
|
|
1180
1189
|
if (pageBreaks.length !== 1) return false;
|
|
@@ -1348,12 +1357,12 @@ function convertTableCell(node, startPos, options, tableCellMargins) {
|
|
|
1348
1357
|
const blocks = [];
|
|
1349
1358
|
let offset = startPos + 1;
|
|
1350
1359
|
const authoredPageBreakPosition = options.firstPageBreakRunPosition(node);
|
|
1351
|
-
const
|
|
1352
|
-
if (authoredPageBreakPosition !== void 0 &&
|
|
1360
|
+
const leadingParagraph = node.firstChild?.type.name === "paragraph" ? node.firstChild : void 0;
|
|
1361
|
+
if (authoredPageBreakPosition !== void 0 && (leadingParagraph === void 0 || countPageBreakRuns(node) !== 1 || options.firstPageBreakRunPosition(leadingParagraph) !== authoredPageBreakPosition)) panic(`An explicit page-break run at ${String(authoredPageBreakPosition)} cannot be projected inside a table cell`);
|
|
1353
1362
|
const pageBreaks = [];
|
|
1354
1363
|
node.forEach((child) => {
|
|
1355
1364
|
if (child.type.name === "paragraph") {
|
|
1356
|
-
const block = convertParagraph(child, offset, options, child ===
|
|
1365
|
+
const block = convertParagraph(child, offset, options, child === leadingParagraph ? pageBreaks : void 0);
|
|
1357
1366
|
blocks.push(block);
|
|
1358
1367
|
} else if (child.type.name === "table") blocks.push(convertTable(child, offset, options));
|
|
1359
1368
|
else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child, offset, options));
|
|
@@ -5,6 +5,17 @@ const UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS = /* @__PURE__ */ new Set([
|
|
|
5
5
|
"tableHeader",
|
|
6
6
|
"textBox"
|
|
7
7
|
]);
|
|
8
|
+
const hasTextBoxAnchorAtOrAfter = (paragraph, contentStart, position) => {
|
|
9
|
+
let found = false;
|
|
10
|
+
paragraph.descendants((descendant, offset) => {
|
|
11
|
+
if (descendant.type.name === "textBoxAnchor" && contentStart + offset >= position) {
|
|
12
|
+
found = true;
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return !found;
|
|
16
|
+
});
|
|
17
|
+
return found;
|
|
18
|
+
};
|
|
8
19
|
/**
|
|
9
20
|
* Insert a page-break run at the current text cursor.
|
|
10
21
|
*
|
|
@@ -18,7 +29,7 @@ const insertPageBreak = (state, dispatch) => {
|
|
|
18
29
|
const { $from } = state.selection;
|
|
19
30
|
if (!pageBreakRunType || !state.selection.empty || !$from.parent.isTextblock) return false;
|
|
20
31
|
for (let depth = $from.depth; depth >= 0; depth--) if (UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS.has($from.node(depth).type.name)) return false;
|
|
21
|
-
if ($from.parent.type.name !== "paragraph" || pageBreakRunParagraphProjectionDisposition($from.parent).status === "unsupported") return false;
|
|
32
|
+
if ($from.parent.type.name !== "paragraph" || pageBreakRunParagraphProjectionDisposition($from.parent).status === "unsupported" || hasTextBoxAnchorAtOrAfter($from.parent, $from.start(), $from.pos)) return false;
|
|
22
33
|
if (dispatch) {
|
|
23
34
|
const pageBreak = pageBreakRunType.create();
|
|
24
35
|
dispatch(state.tr.replaceSelectionWith(pageBreak).scrollIntoView());
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
|
|
2
|
+
import { isNumberingReference } from "../../docx/numberingReference.js";
|
|
2
3
|
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
|
|
3
4
|
import { visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
|
|
4
5
|
import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
|
|
@@ -689,7 +690,7 @@ function removeTextBoxAnchorFromBlocks(blocks, marker) {
|
|
|
689
690
|
*/
|
|
690
691
|
function listRenderingFromAttrs(attrs) {
|
|
691
692
|
const numId = attrs.numPr?.numId;
|
|
692
|
-
if (numId
|
|
693
|
+
if (!isNumberingReference(numId)) return;
|
|
693
694
|
if (!(attrs.listMarker != null || attrs.listIsBullet || attrs.listNumFmt != null)) return;
|
|
694
695
|
return listRenderingFromAttrs$1({
|
|
695
696
|
attrs,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
|
|
2
|
+
import { isNumberingReference } from "../../docx/numberingReference.js";
|
|
2
3
|
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
3
4
|
import { buildPageBreakRunSourceDescendantIndex } from "../../internal/pageBreakRunSourceDescendantIndex.js";
|
|
4
5
|
import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
@@ -453,7 +454,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
453
454
|
if (formatting?.spaceBefore === void 0 && tableParagraphOverlay?.spaceBefore === void 0 && paragraphStyle?.pPr?.spaceBefore === void 0 && docDefaultSpacing?.spaceBefore !== void 0) spacingFromDocDefaults.before = true;
|
|
454
455
|
if (formatting?.spaceAfter === void 0 && tableParagraphOverlay?.spaceAfter === void 0 && paragraphStyle?.pPr?.spaceAfter === void 0 && docDefaultSpacing?.spaceAfter !== void 0) spacingFromDocDefaults.after = true;
|
|
455
456
|
if (spacingFromDocDefaults.before || spacingFromDocDefaults.after) attrs.spacingFromDocDefaults = spacingFromDocDefaults;
|
|
456
|
-
const effectiveIndent = mergeParagraphFormatting(formatting?.numPr?.numId === 0 && stylePpr?.numPr
|
|
457
|
+
const effectiveIndent = mergeParagraphFormatting(formatting?.numPr?.numId === 0 && isNumberingReference(stylePpr?.numPr?.numId) ? void 0 : stylePpr, formatting);
|
|
457
458
|
set("indentLeft", effectiveIndent?.indentLeft);
|
|
458
459
|
set("indentRight", formatting?.indentRight ?? stylePpr?.indentRight);
|
|
459
460
|
set("indentFirstLine", effectiveIndent?.indentFirstLine);
|
|
@@ -473,7 +474,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
473
474
|
set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
|
|
474
475
|
set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
|
|
475
476
|
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 && (styleId === void 0 || paragraph.content.length === 0) }));
|
|
476
|
-
if (stylePpr?.numPr && formatting?.numPr?.numId === void 0 && stylePpr.numPr.numId
|
|
477
|
+
if (stylePpr?.numPr && formatting?.numPr?.numId === void 0 && isNumberingReference(stylePpr.numPr.numId)) {
|
|
477
478
|
attrs.numPr = {
|
|
478
479
|
...stylePpr.numPr,
|
|
479
480
|
...formatting?.numPr
|
|
@@ -1216,19 +1217,27 @@ const PAGE_BREAK_PARAGRAPH_OWNERS = {
|
|
|
1216
1217
|
};
|
|
1217
1218
|
function assertSourceContainerHasNoPageBreakRun(content, owner, sourceDescendants) {
|
|
1218
1219
|
if (!sourceDescendants.containsPageBreakRun(content)) return;
|
|
1219
|
-
if (owner === "table-cell" && hasSingleLeadingTableCellPageBreak(content)) return;
|
|
1220
|
+
if (owner === "table-cell" && hasSingleLeadingTableCellPageBreak(content, sourceDescendants)) return;
|
|
1220
1221
|
throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1221
1222
|
message: `${PAGE_BREAK_CONTAINER_DESCRIPTIONS[owner]} cannot be represented in the editor model`,
|
|
1222
1223
|
owner,
|
|
1223
1224
|
contentType: "break"
|
|
1224
1225
|
});
|
|
1225
1226
|
}
|
|
1226
|
-
/**
|
|
1227
|
-
*
|
|
1228
|
-
*
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1227
|
+
/**
|
|
1228
|
+
* A page break opening a cell advances the whole row during pagination.
|
|
1229
|
+
*
|
|
1230
|
+
* Word writes this shape routinely and the row's own `breakBefore` projects it
|
|
1231
|
+
* losslessly, so what follows the break inside the cell rides along: the row
|
|
1232
|
+
* moves as a unit. The break has to be the cell's only one and has to open its
|
|
1233
|
+
* first paragraph; an interior break still requires table-fragment ownership,
|
|
1234
|
+
* which cell-local flow cannot model. `convertTableCell` in the layout bridge
|
|
1235
|
+
* decides the same question over the projected runs.
|
|
1236
|
+
*/
|
|
1237
|
+
function hasSingleLeadingTableCellPageBreak(content, sourceDescendants) {
|
|
1238
|
+
const first = content.at(0);
|
|
1239
|
+
if (first?.type !== "paragraph" || !hasSingleLeadingParagraphPageBreak(first)) return false;
|
|
1240
|
+
return !content.slice(1).some((block) => sourceDescendants.blockContainsPageBreakRun(block));
|
|
1232
1241
|
}
|
|
1233
1242
|
const scanLeadingPageBreakRun = (run, scan) => {
|
|
1234
1243
|
for (const content of run.content) {
|
|
@@ -1237,6 +1246,7 @@ const scanLeadingPageBreakRun = (run, scan) => {
|
|
|
1237
1246
|
scan.pageBreaks += 1;
|
|
1238
1247
|
continue;
|
|
1239
1248
|
}
|
|
1249
|
+
if (content.type === "shape" && content.shape.textBody && scan.pageBreaks > 0) scan.textBoxShapeAfterBreak = true;
|
|
1240
1250
|
if (scan.pageBreaks === 0) scan.contentBeforeBreak = true;
|
|
1241
1251
|
}
|
|
1242
1252
|
};
|
|
@@ -1276,12 +1286,17 @@ const scanLeadingPageBreakContent = (content, scan) => {
|
|
|
1276
1286
|
default: return content;
|
|
1277
1287
|
}
|
|
1278
1288
|
};
|
|
1279
|
-
const
|
|
1289
|
+
const scanParagraphPageBreaks = (paragraph) => {
|
|
1280
1290
|
const scan = {
|
|
1281
1291
|
contentBeforeBreak: false,
|
|
1282
|
-
pageBreaks: 0
|
|
1292
|
+
pageBreaks: 0,
|
|
1293
|
+
textBoxShapeAfterBreak: false
|
|
1283
1294
|
};
|
|
1284
1295
|
for (const content of paragraph.content) scanLeadingPageBreakContent(content, scan);
|
|
1296
|
+
return scan;
|
|
1297
|
+
};
|
|
1298
|
+
const hasSingleLeadingParagraphPageBreak = (paragraph) => {
|
|
1299
|
+
const scan = scanParagraphPageBreaks(paragraph);
|
|
1285
1300
|
return !scan.contentBeforeBreak && scan.pageBreaks === 1;
|
|
1286
1301
|
};
|
|
1287
1302
|
function assertParagraphPageBreakCanBeProjected({ paragraph, attrs, effectiveFrame, sourceDescendants }) {
|
|
@@ -1290,7 +1305,7 @@ function assertParagraphPageBreakCanBeProjected({ paragraph, attrs, effectiveFra
|
|
|
1290
1305
|
const disposition = pageBreakRunParagraphProjectionDispositionForFeatures({
|
|
1291
1306
|
attrs,
|
|
1292
1307
|
effectiveFrame,
|
|
1293
|
-
|
|
1308
|
+
textBoxAnchorAfterPageBreak: sourceFeatures.hasTextBoxShape && !sourceFeatures.pageBreakSharesTextBoxShape && scanParagraphPageBreaks(paragraph).textBoxShapeAfterBreak
|
|
1294
1309
|
});
|
|
1295
1310
|
if (disposition.status === "supported") return;
|
|
1296
1311
|
if (disposition.reason !== "textBoxAnchor" && hasSingleLeadingParagraphPageBreak(paragraph)) return;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNumberingReference } from "../../../docx/numberingReference.js";
|
|
1
2
|
import { expectParagraphAttrs } from "../../attrs/index.js";
|
|
2
3
|
import { PPR_CHANGE_SCOPED_ATTR_KEYS, hasSerializableParagraphPropertyChange } from "../../commands/propertyChangeScope.js";
|
|
3
4
|
import { CLEARED_LIST_RENDERING_ATTRS } from "../../listMarker.js";
|
|
@@ -9,6 +10,7 @@ import { createExtension } from "../create.js";
|
|
|
9
10
|
import { goToNextCell, goToPrevCell } from "../nodes/TableExtension.js";
|
|
10
11
|
import { Priority } from "../types.js";
|
|
11
12
|
import { panic } from "better-result";
|
|
13
|
+
import { InputRule, inputRules, undoInputRule } from "prosemirror-inputrules";
|
|
12
14
|
//#region src/prosemirror/extensions/features/ListExtension.ts
|
|
13
15
|
/**
|
|
14
16
|
* List Extension — list commands + keymaps
|
|
@@ -48,9 +50,9 @@ function getPreviousListFormatting(attrs) {
|
|
|
48
50
|
}
|
|
49
51
|
function clearListAttrs(attrs) {
|
|
50
52
|
const styleNumPr = attrs.numPrFromStyle;
|
|
51
|
-
const numPr = styleNumPr?.numId
|
|
53
|
+
const numPr = isNumberingReference(styleNumPr?.numId) ? {
|
|
52
54
|
numId: 0,
|
|
53
|
-
ilvl: attrs.numPr?.ilvl ?? styleNumPr
|
|
55
|
+
ilvl: attrs.numPr?.ilvl ?? styleNumPr?.ilvl ?? 0
|
|
54
56
|
} : null;
|
|
55
57
|
return {
|
|
56
58
|
...attrs,
|
|
@@ -59,7 +61,7 @@ function clearListAttrs(attrs) {
|
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
function hasActiveListNumbering(attrs) {
|
|
62
|
-
return attrs.numPr?.numId
|
|
64
|
+
return isNumberingReference(attrs.numPr?.numId);
|
|
63
65
|
}
|
|
64
66
|
function toggleList(numId) {
|
|
65
67
|
return (state, dispatch) => {
|
|
@@ -293,11 +295,47 @@ function insertTab() {
|
|
|
293
295
|
return true;
|
|
294
296
|
};
|
|
295
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Word's as-you-type markers. Each ends in the space that triggers the rule.
|
|
300
|
+
* `1.` starts a numbered list at one, like the toolbar button; another typed
|
|
301
|
+
* number stays text rather than being silently renumbered.
|
|
302
|
+
*/
|
|
303
|
+
const BULLET_AUTOFORMAT = /^[-*] $/u;
|
|
304
|
+
const NUMBERED_AUTOFORMAT = /^1\. $/u;
|
|
305
|
+
const captureTransaction = (command, state) => {
|
|
306
|
+
const captured = { transaction: null };
|
|
307
|
+
command(state, (transaction) => {
|
|
308
|
+
captured.transaction = transaction;
|
|
309
|
+
});
|
|
310
|
+
return captured.transaction;
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Replace a typed marker with the list the toolbar button produces. Running the
|
|
314
|
+
* command itself (rather than writing `numPr` here) keeps an autoformatted list
|
|
315
|
+
* identical to a clicked one, down to what the document saves.
|
|
316
|
+
*/
|
|
317
|
+
const listAutoformat = (marker, toggleCommand) => new InputRule(marker, (state, _match, start, end) => {
|
|
318
|
+
const { $from } = state.selection;
|
|
319
|
+
if ($from.parent.type.name !== "paragraph") return null;
|
|
320
|
+
if (start !== $from.start()) return null;
|
|
321
|
+
if (expectParagraphAttrs($from.parent).numPr?.numId) return null;
|
|
322
|
+
if (makeRevisionInfo(state)) return null;
|
|
323
|
+
const toggled = captureTransaction(toggleCommand, state);
|
|
324
|
+
if (!toggled) return null;
|
|
325
|
+
const tr = state.tr.delete(start, end);
|
|
326
|
+
for (const step of toggled.steps) {
|
|
327
|
+
const mapped = step.map(tr.mapping);
|
|
328
|
+
if (mapped) tr.step(mapped);
|
|
329
|
+
}
|
|
330
|
+
return tr;
|
|
331
|
+
});
|
|
332
|
+
const listAutoformatRules = () => inputRules({ rules: [listAutoformat(BULLET_AUTOFORMAT, toggleBulletList), listAutoformat(NUMBERED_AUTOFORMAT, toggleNumberedList)] });
|
|
296
333
|
const ListExtension = createExtension({
|
|
297
334
|
name: "list",
|
|
298
335
|
priority: Priority.High,
|
|
299
336
|
onSchemaReady() {
|
|
300
337
|
return {
|
|
338
|
+
plugins: [listAutoformatRules()],
|
|
301
339
|
commands: {
|
|
302
340
|
toggleBulletList: () => toggleBulletList,
|
|
303
341
|
toggleNumberedList: () => toggleNumberedList,
|
|
@@ -310,7 +348,7 @@ const ListExtension = createExtension({
|
|
|
310
348
|
"Shift-Tab": chainCommands(goToPrevCell(), decreaseListIndent()),
|
|
311
349
|
"Shift-Enter": () => false,
|
|
312
350
|
Enter: chainCommands(exitListOnEmptyEnter(), splitListItem()),
|
|
313
|
-
Backspace: backspaceExitList()
|
|
351
|
+
Backspace: chainCommands(undoInputRule, backspaceExitList())
|
|
314
352
|
}
|
|
315
353
|
};
|
|
316
354
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { convertBulletToUnicode } from "../docx/bulletMarkers.js";
|
|
2
|
+
import { isNumberingReference } from "../docx/numberingReference.js";
|
|
2
3
|
import { formatOoxmlCounter } from "../docx/ooxmlCounterFormatter.js";
|
|
3
4
|
import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
|
|
4
5
|
//#region src/prosemirror/listMarker.ts
|
|
@@ -179,7 +180,7 @@ function advanceListMarker(attrs, state) {
|
|
|
179
180
|
const level = attrs.numPr?.ilvl ?? 0;
|
|
180
181
|
if (!Number.isInteger(level) || level < 0 || level > 8) return null;
|
|
181
182
|
const numId = attrs.numPr?.numId;
|
|
182
|
-
if (numId
|
|
183
|
+
if (!isNumberingReference(numId)) {
|
|
183
184
|
let marker = null;
|
|
184
185
|
if (markerTemplate?.includes("%") && !attrs.listIsBullet) {
|
|
185
186
|
const counters = getLastListCounters(state);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNumberingReference } from "../docx/numberingReference.js";
|
|
1
2
|
import { expectFieldAttrs, expectParagraphAttrs } from "./attrs/index.js";
|
|
2
3
|
import { expectBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
|
|
3
4
|
import { advanceVisibleListMarker, createListCounterState, resolveListTemplateWithComponents } from "./listMarker.js";
|
|
@@ -79,7 +80,7 @@ function numberTargetForParagraph(node, contextStreams, streams) {
|
|
|
79
80
|
}
|
|
80
81
|
function numberTargetForAdvancedMarker(attrs, resolvedMarker, state, contexts) {
|
|
81
82
|
const numId = attrs.numPr?.numId;
|
|
82
|
-
if (numId
|
|
83
|
+
if (!isNumberingReference(numId) || attrs.listIsBullet || attrs.listMarkerHidden || attrs.listNumFmt === "none" || !resolvedMarker) return null;
|
|
83
84
|
const marker = attrs.listMarkerAllCaps ? resolvedMarker.toLocaleUpperCase() : resolvedMarker;
|
|
84
85
|
const level = attrs.numPr?.ilvl ?? 0;
|
|
85
86
|
if (!Number.isInteger(level) || level < 0 || level > 8) return null;
|
|
@@ -6,7 +6,7 @@ declare const PAGE_BREAK_RUN_PARAGRAPH_PROJECTION_MESSAGES: {
|
|
|
6
6
|
readonly borders: "A bordered paragraph containing an explicit page-break run cannot be projected";
|
|
7
7
|
readonly frame: "A framed paragraph containing an explicit page-break run cannot be projected";
|
|
8
8
|
readonly outline: "An outline paragraph containing an explicit page-break run cannot be projected";
|
|
9
|
-
readonly textBoxAnchor: "A paragraph
|
|
9
|
+
readonly textBoxAnchor: "A paragraph whose text-box anchor follows an explicit page-break run cannot be projected";
|
|
10
10
|
};
|
|
11
11
|
type PageBreakRunParagraphProjectionReason = keyof typeof PAGE_BREAK_RUN_PARAGRAPH_PROJECTION_MESSAGES;
|
|
12
12
|
type PageBreakRunParagraphProjectionDisposition = {
|
|
@@ -19,10 +19,18 @@ type PageBreakRunParagraphProjectionDisposition = {
|
|
|
19
19
|
type PageBreakRunParagraphFeatures = {
|
|
20
20
|
attrs: ParagraphAttrs;
|
|
21
21
|
effectiveFrame: document_d_exports.ParagraphFormatting["frame"];
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* A text-box anchor that the paragraph's first page break precedes.
|
|
24
|
+
*
|
|
25
|
+
* Layout splits such a paragraph into fragments at its breaks, and only the
|
|
26
|
+
* first fragment keeps the paragraph's block id, which is what an anchor
|
|
27
|
+
* resolves its host through. An anchor before the first break is therefore
|
|
28
|
+
* projected faithfully; one after it would lose its host.
|
|
29
|
+
*/
|
|
30
|
+
textBoxAnchorAfterPageBreak: boolean;
|
|
23
31
|
};
|
|
24
32
|
/** Keep source-import and ProseMirror-layout ownership decisions on one predicate. */
|
|
25
|
-
declare const pageBreakRunParagraphProjectionDispositionForFeatures: ({ attrs, effectiveFrame,
|
|
33
|
+
declare const pageBreakRunParagraphProjectionDispositionForFeatures: ({ attrs, effectiveFrame, textBoxAnchorAfterPageBreak }: PageBreakRunParagraphFeatures) => PageBreakRunParagraphProjectionDisposition;
|
|
26
34
|
declare const pageBreakRunParagraphProjectionDisposition: (paragraph: Node) => PageBreakRunParagraphProjectionDisposition;
|
|
27
35
|
//#endregion
|
|
28
36
|
export { PageBreakRunParagraphProjectionDisposition, PageBreakRunParagraphProjectionReason, pageBreakRunParagraphProjectionDisposition, pageBreakRunParagraphProjectionDispositionForFeatures };
|