@stll/folio-core 0.36.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -1
- package/dist/ai-edits/apply.js +545 -296
- package/dist/ai-edits/block-identity.d.ts +4 -1
- package/dist/ai-edits/block-identity.js +4 -1
- package/dist/ai-edits/blockRange.js +14 -14
- package/dist/ai-edits/clean-text.d.ts +40 -1
- package/dist/ai-edits/clean-text.js +52 -2
- package/dist/ai-edits/headless.d.ts +3 -1
- package/dist/ai-edits/headless.js +133 -71
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.js +38 -20
- package/dist/ai-edits/snapshot.d.ts +14 -6
- package/dist/ai-edits/snapshot.js +99 -19
- package/dist/ai-edits/table-cell-mutations.js +1 -1
- package/dist/ai-edits/table-row-column-mutations.js +7 -0
- package/dist/ai-edits/table-template.d.ts +11 -1
- package/dist/ai-edits/table-template.js +49 -17
- package/dist/ai-edits/types.d.ts +45 -57
- package/dist/ai-suggestions/conflict.js +1 -4
- package/dist/ai-suggestions/text-positions.d.ts +8 -0
- package/dist/ai-suggestions/text-positions.js +27 -5
- package/dist/compare/__fixtures__/body-sequence.js +3 -4
- package/dist/compare/column-alignment.d.ts +13 -13
- package/dist/compare/column-alignment.js +78 -39
- package/dist/compare/compare.d.ts +4 -3
- package/dist/compare/compare.js +41 -5
- package/dist/compare/content-alignment.d.ts +95 -0
- package/dist/compare/content-alignment.js +1450 -0
- package/dist/compare/content-types.d.ts +100 -0
- package/dist/compare/content-types.js +0 -0
- package/dist/compare/content.d.ts +209 -0
- package/dist/compare/content.js +885 -0
- package/dist/compare/formatting.d.ts +5 -5
- package/dist/compare/formatting.js +6 -4
- package/dist/compare/plan.d.ts +6 -1
- package/dist/compare/plan.js +169 -567
- package/dist/compare/scenario.d.ts +2 -2
- package/dist/compare/types.d.ts +3 -3
- package/dist/compare/verification.d.ts +2 -2
- package/dist/compare/verification.js +25 -8
- package/dist/compat/eigenpal.d.ts +5 -3
- package/dist/compat/eigenpal.js +3 -2
- package/dist/controller/headerFooterEditorManager.js +14 -6
- package/dist/controller/hiddenEditorManager.d.ts +7 -2
- package/dist/controller/hiddenEditorManager.js +15 -6
- package/dist/controller/layoutPipeline.js +5 -3
- package/dist/controller/noteEditorManager.js +12 -7
- package/dist/display-list/build/headerFooterPrimitives.js +1 -0
- package/dist/display-list/build/storyPrimitives.d.ts +5 -2
- package/dist/display-list/build/storyPrimitives.js +60 -3
- package/dist/display-list/build/tablePrimitives.js +30 -0
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/document-operations.d.ts +6 -4
- package/dist/document-operations.js +77 -12
- package/dist/docx/blockContentParser.js +6 -27
- package/dist/docx/ensureParaIds.js +9 -4
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +4 -1
- package/dist/docx/paragraphParser.js +7 -6
- package/dist/docx/paragraphTraversal.js +30 -34
- package/dist/docx/rezip.d.ts +0 -8
- package/dist/docx/rezip.js +41 -16
- package/dist/docx/runParser.js +4 -2
- package/dist/docx/serializer/paragraphSerializer.js +2 -0
- package/dist/docx/serializer/runSerializer.js +5 -3
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +3 -1
- package/dist/docx/serializer/trackedChangeAttributes.js +11 -1
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/headless-layout.js +5 -4
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/internal/headlessRevisionResolution.d.ts +23 -0
- package/dist/internal/headlessRevisionResolution.js +155 -0
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
- package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
- package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
- package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
- package/dist/internal/pageBreakRunPartition.d.ts +26 -0
- package/dist/internal/pageBreakRunPartition.js +35 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
- package/dist/internal/sectionEndpointResolution.d.ts +32 -0
- package/dist/internal/sectionEndpointResolution.js +38 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
- package/dist/layout-bridge/convert/headerFooterLayout.js +48 -5
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +379 -75
- package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
- package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
- package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
- package/dist/layout-bridge/dom/textStreamDom.js +75 -0
- package/dist/layout-bridge/headerFooterLayout.js +16 -30
- package/dist/layout-engine/index.js +12 -3
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +7 -0
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderTable.js +20 -0
- package/dist/model.d.ts +1 -1
- package/dist/paged-layout/rangeProjection.js +6 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
- package/dist/paged-layout/transactionDirtyRange.js +23 -1
- package/dist/prosemirror/attrs/index.d.ts +7 -3
- package/dist/prosemirror/attrs/index.js +113 -7
- package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
- package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
- package/dist/prosemirror/commands/comments.d.ts +10 -1
- package/dist/prosemirror/commands/comments.js +190 -59
- package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
- package/dist/prosemirror/commands/formatPainter.js +319 -63
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
- package/dist/prosemirror/commands/pageBreak.js +18 -36
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +7 -5
- package/dist/prosemirror/commands/propertyChangeScope.js +27 -18
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +7 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +809 -209
- package/dist/prosemirror/conversion/runShadingMark.js +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
- package/dist/prosemirror/conversion/toProseDoc.js +416 -283
- package/dist/prosemirror/extensions/StarterKit.js +4 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -8
- package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
- package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
- package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
- package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
- package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
- package/dist/prosemirror/findReplaceSelection.js +8 -3
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/listMarker.d.ts +26 -1
- package/dist/prosemirror/listMarker.js +108 -14
- package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
- package/dist/prosemirror/pageBreakRunProjection.js +47 -0
- package/dist/prosemirror/paraText.js +6 -0
- package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
- package/dist/prosemirror/paragraphSpacing.js +125 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
- package/dist/prosemirror/plugins/documentNumbering.js +18 -0
- package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
- package/dist/prosemirror/plugins/pmTextScan.js +14 -4
- package/dist/prosemirror/plugins/suggestionMode.js +8 -10
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
- package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
- package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
- package/dist/prosemirror/runFormattingProvenance.js +48 -0
- package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
- package/dist/prosemirror/runFormattingReconciliation.js +54 -0
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
- package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
- package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
- package/dist/prosemirror/runStyleFormatting.js +105 -0
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +82 -9
- package/dist/prosemirror/schema/marks.js +73 -1
- package/dist/prosemirror/schema/nodes.d.ts +18 -5
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +44 -23
- package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
- package/dist/prosemirror/styles/styleResolver.js +3 -3
- package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
- package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
- package/dist/prosemirror/tableGridMutation.d.ts +20 -0
- package/dist/prosemirror/tableGridMutation.js +30 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
- package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
- package/dist/prosemirror/validation.js +23 -4
- package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
- package/dist/render-dom/RenderedDomContext.js +17 -34
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/style-engine/styleEngine.d.ts +1 -1
- package/dist/utils/clipboard.js +1 -1
- package/dist/utils/findReplace.js +38 -21
- package/dist/version-comparison.d.ts +38 -44
- package/dist/version-comparison.js +270 -401
- package/package.json +3 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { computeListRendering } from "../../docx/numberingParser.js";
|
|
1
|
+
import { computeListRendering, numberingLevelHasMarkerSlot } from "../../docx/numberingParser.js";
|
|
2
2
|
import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
3
3
|
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
4
|
+
import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
|
|
4
5
|
//#region src/prosemirror/styles/resolvedStyleAttrs.ts
|
|
5
6
|
/**
|
|
6
7
|
* Shared helper for projecting a resolved paragraph style onto ProseMirror
|
|
@@ -73,42 +74,62 @@ function autospacingBaseFromResolvedParagraphFormatting(ppr) {
|
|
|
73
74
|
function listAttrsFromResolvedStyle(resolved, numbering) {
|
|
74
75
|
const numPr = resolved.paragraphFormatting?.numPr;
|
|
75
76
|
if (!numPr || numPr.numId === void 0 || numPr.numId === 0) return null;
|
|
76
|
-
const
|
|
77
|
+
const attrs = listAttrsFromNumbering({
|
|
78
|
+
numId: numPr.numId,
|
|
79
|
+
ilvl: numPr.ilvl ?? 0
|
|
80
|
+
}, numbering);
|
|
77
81
|
const level = numbering?.getLevel(numPr.numId, numPr.ilvl ?? 0);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
attrs["numPrFromStyle"] = {
|
|
83
|
+
numId: numPr.numId,
|
|
84
|
+
ilvl: numPr.ilvl ?? 0
|
|
85
|
+
};
|
|
86
|
+
const ppr = resolved.paragraphFormatting;
|
|
87
|
+
if (level?.pPr) {
|
|
88
|
+
if (ppr?.indentLeft === void 0 && level.pPr.indentLeft !== void 0) attrs["indentLeft"] = level.pPr.indentLeft;
|
|
89
|
+
if (!(ppr?.indentFirstLine !== void 0 || ppr?.hangingIndent !== void 0) && numberingLevelHasMarkerSlot(level)) {
|
|
90
|
+
if (level.pPr.indentFirstLine !== void 0) attrs["indentFirstLine"] = level.pPr.indentFirstLine;
|
|
91
|
+
if (level.pPr.hangingIndent !== void 0) attrs["hangingIndent"] = level.pPr.hangingIndent;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return attrs;
|
|
95
|
+
}
|
|
96
|
+
/** Project one resolved numbering level into the complete editor attr group. */
|
|
97
|
+
function listAttrsFromNumbering(numPr, numbering) {
|
|
98
|
+
const targetNumPr = {
|
|
99
|
+
numId: numPr.numId,
|
|
100
|
+
ilvl: numPr.ilvl
|
|
101
|
+
};
|
|
102
|
+
const rendering = numbering ? computeListRendering(targetNumPr, numbering) : null;
|
|
103
|
+
return {
|
|
104
|
+
...CLEARED_LIST_RENDERING_ATTRS,
|
|
105
|
+
numPr: targetNumPr,
|
|
87
106
|
listNumFmt: rendering?.numFmt ?? null,
|
|
88
107
|
listIsBullet: rendering?.isBullet ?? null,
|
|
89
108
|
listIsLegal: rendering?.isLegal ?? null,
|
|
90
109
|
listMarker: rendering?.marker ?? null,
|
|
110
|
+
listMarkerTemplate: rendering?.markerTemplate ?? null,
|
|
91
111
|
listMarkerHidden: rendering?.markerHidden ?? null,
|
|
92
112
|
listMarkerFormatting: rendering?.markerFormatting ?? null,
|
|
93
113
|
listMarkerAlignment: rendering?.markerAlignment ?? null,
|
|
94
114
|
listMarkerSuffix: rendering?.markerSuffix ?? null,
|
|
95
115
|
listMarkerAllCaps: rendering?.markerAllCaps ?? null,
|
|
96
|
-
listImplicitChildLevelAdvances: null,
|
|
97
|
-
listMarkerSecondSlotOffsetTwips: null,
|
|
98
116
|
listLevelNumFmts: rendering?.levelNumFmts ?? null,
|
|
99
117
|
listLevelStarts: rendering?.levelStarts ?? null,
|
|
100
118
|
listAbstractNumId: rendering?.abstractNumId ?? null,
|
|
101
119
|
listStartOverride: rendering?.startOverride ?? null
|
|
102
120
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
}
|
|
122
|
+
/** Recompute every level-dependent attr when a paragraph changes list level. */
|
|
123
|
+
function listLevelAttrPatch(attrs, numPr, numbering) {
|
|
124
|
+
const level = numbering?.getLevel(numPr.numId, numPr.ilvl);
|
|
125
|
+
const hasMarkerSlot = level ? numberingLevelHasMarkerSlot(level) : false;
|
|
126
|
+
return {
|
|
127
|
+
...listAttrsFromNumbering(numPr, numbering),
|
|
128
|
+
listImplicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? null,
|
|
129
|
+
indentLeft: level?.pPr?.indentLeft ?? null,
|
|
130
|
+
indentFirstLine: hasMarkerSlot ? level?.pPr?.indentFirstLine ?? null : null,
|
|
131
|
+
hangingIndent: hasMarkerSlot ? level?.pPr?.hangingIndent ?? null : null
|
|
132
|
+
};
|
|
112
133
|
}
|
|
113
134
|
//#endregion
|
|
114
|
-
export { listAttrsFromResolvedStyle, paragraphAttrsFromResolvedStyle };
|
|
135
|
+
export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listLevelAttrPatch, paragraphAttrsFromResolvedStyle };
|
|
@@ -10,21 +10,18 @@ type ResolvedParagraphStyle = {
|
|
|
10
10
|
runFormatting?: document_d_exports.TextFormatting;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
* Paragraph
|
|
14
|
-
*
|
|
13
|
+
* Paragraph fields sourced from the table style enclosing a cell paragraph:
|
|
14
|
+
* the table style's own `w:pPr`, then the applicable
|
|
15
15
|
* `w:tblStylePr` conditional region's `w:pPr` layered on top (already merged
|
|
16
16
|
* by the caller — see `resolveTableBaseStyle`/`resolveTableStyleConditional`
|
|
17
17
|
* in toProseDoc.ts).
|
|
18
18
|
*
|
|
19
|
-
* Deliberately narrower than the full {@link ParagraphFormatting}:
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* to `docDefaults`). Alignment, indentation, borders, etc. are out of scope
|
|
24
|
-
* here — applying the whole `pPr` would risk regressing unrelated cell
|
|
25
|
-
* layout that isn't part of this fix.
|
|
19
|
+
* Deliberately narrower than the full {@link ParagraphFormatting}: spacing
|
|
20
|
+
* affects table-row height, while `frame` participates in lossless page-break
|
|
21
|
+
* ownership checks. Other fields remain out of scope until their table-style
|
|
22
|
+
* projection is modeled end to end.
|
|
26
23
|
*/
|
|
27
|
-
type TableCellParagraphSpacingOverlay = Pick<document_d_exports.ParagraphFormatting, "spaceBefore" | "spaceAfter" | "lineSpacing" | "lineSpacingRule" | "contextualSpacing">;
|
|
24
|
+
type TableCellParagraphSpacingOverlay = Pick<document_d_exports.ParagraphFormatting, "spaceBefore" | "spaceAfter" | "lineSpacing" | "lineSpacingRule" | "contextualSpacing" | "frame">;
|
|
28
25
|
/**
|
|
29
26
|
* StyleResolver provides efficient access to resolved style properties
|
|
30
27
|
*/
|
|
@@ -52,7 +49,7 @@ declare class StyleResolver {
|
|
|
52
49
|
resolveParagraphStyle(styleId: string | undefined | null): ResolvedParagraphStyle;
|
|
53
50
|
/**
|
|
54
51
|
* Resolve paragraph style properties for a paragraph inside a table cell,
|
|
55
|
-
* layering the enclosing
|
|
52
|
+
* layering the modeled enclosing-table paragraph fields into the
|
|
56
53
|
* cascade between docDefaults and the paragraph's own style chain.
|
|
57
54
|
*
|
|
58
55
|
* Per ECMA-376 §17.7.2, a cell paragraph's properties resolve in this
|
|
@@ -68,10 +65,10 @@ declare class StyleResolver {
|
|
|
68
65
|
* paragraph style still wins over the table for any field it sets.
|
|
69
66
|
*
|
|
70
67
|
* @param styleId - The paragraph's style ID (e.g., 'Heading1', 'Normal')
|
|
71
|
-
* @param tableParagraphOverlay -
|
|
68
|
+
* @param tableParagraphOverlay - Modeled paragraph fields from the
|
|
72
69
|
* enclosing table style (base `pPr` merged with the applicable
|
|
73
70
|
* conditional region), or `undefined` when the paragraph isn't in a
|
|
74
|
-
* table cell, the table has no style, or the style sets
|
|
71
|
+
* table cell, the table has no style, or the style sets none of them.
|
|
75
72
|
* @returns Resolved paragraph and run formatting
|
|
76
73
|
*/
|
|
77
74
|
resolveParagraphStyleInTable(styleId: string | undefined | null, tableParagraphOverlay: TableCellParagraphSpacingOverlay | undefined): ResolvedParagraphStyle;
|
|
@@ -74,7 +74,7 @@ var StyleResolver = class {
|
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
76
|
* Resolve paragraph style properties for a paragraph inside a table cell,
|
|
77
|
-
* layering the enclosing
|
|
77
|
+
* layering the modeled enclosing-table paragraph fields into the
|
|
78
78
|
* cascade between docDefaults and the paragraph's own style chain.
|
|
79
79
|
*
|
|
80
80
|
* Per ECMA-376 §17.7.2, a cell paragraph's properties resolve in this
|
|
@@ -90,10 +90,10 @@ var StyleResolver = class {
|
|
|
90
90
|
* paragraph style still wins over the table for any field it sets.
|
|
91
91
|
*
|
|
92
92
|
* @param styleId - The paragraph's style ID (e.g., 'Heading1', 'Normal')
|
|
93
|
-
* @param tableParagraphOverlay -
|
|
93
|
+
* @param tableParagraphOverlay - Modeled paragraph fields from the
|
|
94
94
|
* enclosing table style (base `pPr` merged with the applicable
|
|
95
95
|
* conditional region), or `undefined` when the paragraph isn't in a
|
|
96
|
-
* table cell, the table has no style, or the style sets
|
|
96
|
+
* table cell, the table has no style, or the style sets none of them.
|
|
97
97
|
* @returns Resolved paragraph and run formatting
|
|
98
98
|
*/
|
|
99
99
|
resolveParagraphStyleInTable(styleId, tableParagraphOverlay) {
|
|
@@ -23,6 +23,13 @@ type StyleToggleCascadeOptions = {
|
|
|
23
23
|
/** Existing ordinary-property merge whose toggle fields this cascade replaces. */
|
|
24
24
|
ordinaryFormatting: document_d_exports.TextFormatting | undefined;
|
|
25
25
|
};
|
|
26
|
+
type CascadeStyleFromResolvedBaseOptions = {
|
|
27
|
+
baseFormatting: document_d_exports.TextFormatting | undefined;
|
|
28
|
+
defaultsActiveProperties: readonly StyleToggleKey[] | undefined;
|
|
29
|
+
styleFormatting: document_d_exports.TextFormatting | undefined;
|
|
30
|
+
};
|
|
31
|
+
/** Continue a style cascade from a compact resolved paragraph snapshot. */
|
|
32
|
+
declare const cascadeStyleFromResolvedBase: ({ baseFormatting, defaultsActiveProperties, styleFormatting }: CascadeStyleFromResolvedBaseOptions) => document_d_exports.TextFormatting | undefined;
|
|
26
33
|
/**
|
|
27
34
|
* Resolve run formatting across OOXML style hierarchy levels.
|
|
28
35
|
*
|
|
@@ -34,4 +41,4 @@ type StyleToggleCascadeOptions = {
|
|
|
34
41
|
*/
|
|
35
42
|
declare function cascadeStyleTextFormatting(levels: readonly StyleToggleLevel[], options?: StyleToggleCascadeOptions): StyleTextFormattingCascade;
|
|
36
43
|
//#endregion
|
|
37
|
-
export { cascadeStyleTextFormatting };
|
|
44
|
+
export { StyleToggleKey, cascadeStyleFromResolvedBase, cascadeStyleTextFormatting };
|
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import { STYLE_TOGGLE_KEYS, mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
2
2
|
//#region src/prosemirror/styles/styleToggleCascade.ts
|
|
3
|
+
/** Continue a style cascade from a compact resolved paragraph snapshot. */
|
|
4
|
+
const cascadeStyleFromResolvedBase = ({ baseFormatting, defaultsActiveProperties, styleFormatting }) => {
|
|
5
|
+
const defaultsActive = new Set(defaultsActiveProperties);
|
|
6
|
+
const toggleStates = /* @__PURE__ */ new Map();
|
|
7
|
+
for (const key of STYLE_TOGGLE_KEYS) {
|
|
8
|
+
const value = baseFormatting?.[key];
|
|
9
|
+
if (value !== void 0) toggleStates.set(key, {
|
|
10
|
+
value,
|
|
11
|
+
defaultsActive: defaultsActive.has(key)
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return cascadeStyleTextFormatting([{
|
|
15
|
+
cascade: {
|
|
16
|
+
formatting: baseFormatting,
|
|
17
|
+
toggleStates,
|
|
18
|
+
type: "styleToggleCascade"
|
|
19
|
+
},
|
|
20
|
+
type: "carried"
|
|
21
|
+
}, {
|
|
22
|
+
formatting: styleFormatting,
|
|
23
|
+
type: "style"
|
|
24
|
+
}]).formatting;
|
|
25
|
+
};
|
|
3
26
|
/**
|
|
4
27
|
* Resolve run formatting across OOXML style hierarchy levels.
|
|
5
28
|
*
|
|
@@ -49,4 +72,4 @@ function cascadeStyleTextFormatting(levels, options) {
|
|
|
49
72
|
};
|
|
50
73
|
}
|
|
51
74
|
//#endregion
|
|
52
|
-
export { cascadeStyleTextFormatting };
|
|
75
|
+
export { cascadeStyleFromResolvedBase, cascadeStyleTextFormatting };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Transaction } from "prosemirror-state";
|
|
2
|
+
import { Node } from "prosemirror-model";
|
|
3
|
+
//#region src/prosemirror/tableGridMutation.d.ts
|
|
4
|
+
type ReconcileTableGridAfterColumnRemovalOptions = {
|
|
5
|
+
tr: Transaction;
|
|
6
|
+
tablePosition: number;
|
|
7
|
+
previousTable: Node;
|
|
8
|
+
removedColumn: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Keep the editable table grid aligned with a physical column removal.
|
|
12
|
+
*
|
|
13
|
+
* `prosemirror-tables` owns cell topology, but Folio separately retains the
|
|
14
|
+
* authored `w:tblGrid` widths and source XML on the table node. A topology
|
|
15
|
+
* edit that leaves those attrs untouched serializes a new row shape against
|
|
16
|
+
* the old grid; reopening then has to interpret surviving cells as spans.
|
|
17
|
+
*/
|
|
18
|
+
declare const reconcileTableGridAfterColumnRemoval: ({ tr, tablePosition, previousTable, removedColumn }: ReconcileTableGridAfterColumnRemovalOptions) => void;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { reconcileTableGridAfterColumnRemoval };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expectTableAttrs, mergeTableAttrs } from "./attrs/index.js";
|
|
2
|
+
import { TableMap } from "prosemirror-tables";
|
|
3
|
+
//#region src/prosemirror/tableGridMutation.ts
|
|
4
|
+
/**
|
|
5
|
+
* Keep the editable table grid aligned with a physical column removal.
|
|
6
|
+
*
|
|
7
|
+
* `prosemirror-tables` owns cell topology, but Folio separately retains the
|
|
8
|
+
* authored `w:tblGrid` widths and source XML on the table node. A topology
|
|
9
|
+
* edit that leaves those attrs untouched serializes a new row shape against
|
|
10
|
+
* the old grid; reopening then has to interpret surviving cells as spans.
|
|
11
|
+
*/
|
|
12
|
+
const reconcileTableGridAfterColumnRemoval = ({ tr, tablePosition, previousTable, removedColumn }) => {
|
|
13
|
+
const previousColumnCount = TableMap.get(previousTable).width;
|
|
14
|
+
const table = tr.doc.nodeAt(tablePosition);
|
|
15
|
+
if (!table || table.type.spec["tableRole"] !== "table") return;
|
|
16
|
+
const columnCount = TableMap.get(table).width;
|
|
17
|
+
if (columnCount >= previousColumnCount) return;
|
|
18
|
+
const removedColumnCount = previousColumnCount - columnCount;
|
|
19
|
+
const previousWidths = expectTableAttrs(previousTable).columnWidths;
|
|
20
|
+
const columnWidths = previousWidths?.length === previousColumnCount ? previousWidths.toSpliced(removedColumn, removedColumnCount) : void 0;
|
|
21
|
+
const formatting = expectTableAttrs(table)._originalFormatting;
|
|
22
|
+
const originalFormatting = formatting ? { ...formatting } : void 0;
|
|
23
|
+
if (originalFormatting) delete originalFormatting.gridSourceXml;
|
|
24
|
+
tr.setNodeMarkup(tablePosition, void 0, mergeTableAttrs(table, {
|
|
25
|
+
columnWidths: columnWidths?.length === columnCount ? columnWidths : void 0,
|
|
26
|
+
_originalFormatting: originalFormatting
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { reconcileTableGridAfterColumnRemoval };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Node } from "prosemirror-model";
|
|
2
|
+
//#region src/prosemirror/trackedRunInlineAtoms.d.ts
|
|
3
|
+
type TrackedRunInlineAtomDisposition = "carry" | "field-carrier" | "outside-wrapper" | "page-break-carrier" | "text-carrier" | "transparent";
|
|
4
|
+
/**
|
|
5
|
+
* How every inline atom in the editor schema participates in an OOXML
|
|
6
|
+
* run-level tracked-change wrapper.
|
|
7
|
+
*
|
|
8
|
+
* The schema is assembled at runtime, so the fixed-point test binds this map
|
|
9
|
+
* to its complete inline-atom set. The lookup also panics on a missing entry:
|
|
10
|
+
* a new atom cannot silently lose revision ownership before that test runs.
|
|
11
|
+
*/
|
|
12
|
+
declare const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS: Readonly<{
|
|
13
|
+
readonly bookmarkBoundary: "carry";
|
|
14
|
+
readonly field: "field-carrier";
|
|
15
|
+
readonly hardBreak: "carry";
|
|
16
|
+
readonly image: "carry";
|
|
17
|
+
readonly math: "outside-wrapper";
|
|
18
|
+
readonly pageBreakRun: "page-break-carrier";
|
|
19
|
+
readonly renderedPageBreak: "transparent";
|
|
20
|
+
readonly shape: "carry";
|
|
21
|
+
readonly structuredField: "carry";
|
|
22
|
+
readonly symbol: "carry";
|
|
23
|
+
readonly tab: "carry";
|
|
24
|
+
readonly text: "text-carrier";
|
|
25
|
+
readonly textBoxAnchor: "carry";
|
|
26
|
+
}>;
|
|
27
|
+
declare const trackedRunInlineAtomDisposition: (node: Node) => TrackedRunInlineAtomDisposition | null;
|
|
28
|
+
/** Whether an editor node can own an insertion/deletion mark as one run carrier. */
|
|
29
|
+
declare const canCarryTrackedRunMark: (node: Node) => boolean;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { TRACKED_RUN_INLINE_ATOM_DISPOSITIONS, TrackedRunInlineAtomDisposition, canCarryTrackedRunMark, trackedRunInlineAtomDisposition };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
//#region src/prosemirror/trackedRunInlineAtoms.ts
|
|
3
|
+
/**
|
|
4
|
+
* How every inline atom in the editor schema participates in an OOXML
|
|
5
|
+
* run-level tracked-change wrapper.
|
|
6
|
+
*
|
|
7
|
+
* The schema is assembled at runtime, so the fixed-point test binds this map
|
|
8
|
+
* to its complete inline-atom set. The lookup also panics on a missing entry:
|
|
9
|
+
* a new atom cannot silently lose revision ownership before that test runs.
|
|
10
|
+
*/
|
|
11
|
+
const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS = Object.freeze({
|
|
12
|
+
bookmarkBoundary: "carry",
|
|
13
|
+
field: "field-carrier",
|
|
14
|
+
hardBreak: "carry",
|
|
15
|
+
image: "carry",
|
|
16
|
+
math: "outside-wrapper",
|
|
17
|
+
pageBreakRun: "page-break-carrier",
|
|
18
|
+
renderedPageBreak: "transparent",
|
|
19
|
+
shape: "carry",
|
|
20
|
+
structuredField: "carry",
|
|
21
|
+
symbol: "carry",
|
|
22
|
+
tab: "carry",
|
|
23
|
+
text: "text-carrier",
|
|
24
|
+
textBoxAnchor: "carry"
|
|
25
|
+
});
|
|
26
|
+
const dispositionsByName = new Map(Object.entries(TRACKED_RUN_INLINE_ATOM_DISPOSITIONS));
|
|
27
|
+
const trackedRunInlineAtomDisposition = (node) => {
|
|
28
|
+
if (!node.isInline || !node.isAtom) return null;
|
|
29
|
+
const disposition = dispositionsByName.get(node.type.name);
|
|
30
|
+
if (!disposition) panic(`Inline atom ${JSON.stringify(node.type.name)} has no tracked-run disposition`);
|
|
31
|
+
return disposition;
|
|
32
|
+
};
|
|
33
|
+
/** Whether an editor node can own an insertion/deletion mark as one run carrier. */
|
|
34
|
+
const canCarryTrackedRunMark = (node) => {
|
|
35
|
+
const disposition = trackedRunInlineAtomDisposition(node);
|
|
36
|
+
return disposition === "carry" || disposition === "field-carrier" || disposition === "text-carrier" || disposition === "page-break-carrier";
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { TRACKED_RUN_INLINE_ATOM_DISPOSITIONS, canCarryTrackedRunMark, trackedRunInlineAtomDisposition };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { findBodyEmptyRuns, findBodyPmSpans } from "../../layout-bridge/dom/findBodyPmSpans.js";
|
|
2
|
+
import { createTextStreamRange, descendantTextNodes, totalTextLength } from "../../layout-bridge/dom/textStreamDom.js";
|
|
1
3
|
import { findVerticalScrollParent } from "../../utils/findVerticalScrollParent.js";
|
|
2
4
|
import { TextSelection } from "prosemirror-state";
|
|
3
5
|
//#region src/prosemirror/utils/visualLineNavigation.ts
|
|
@@ -33,28 +35,21 @@ function scrollIntoViewIfNeeded(el) {
|
|
|
33
35
|
}
|
|
34
36
|
/** @internal */
|
|
35
37
|
function getCaretClientX(container, pmPos) {
|
|
36
|
-
const
|
|
37
|
-
for (const span of Array.from(spans)) {
|
|
38
|
-
const spanEl = span;
|
|
38
|
+
for (const spanEl of findBodyPmSpans(container)) {
|
|
39
39
|
const pmStart = Number(spanEl.dataset["pmStart"]);
|
|
40
40
|
const pmEnd = Number(spanEl.dataset["pmEnd"]);
|
|
41
41
|
if (spanEl.classList.contains("layout-run-tab")) {
|
|
42
42
|
if (pmPos >= pmStart && pmPos < pmEnd) return spanEl.getBoundingClientRect().left;
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
45
|
-
if (pmPos >= pmStart && pmPos <= pmEnd
|
|
46
|
-
const
|
|
47
|
-
const charIndex = Math.min(pmPos - pmStart,
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
const range = ownerDoc.createRange();
|
|
51
|
-
range.setStart(textNode, charIndex);
|
|
52
|
-
range.setEnd(textNode, charIndex);
|
|
53
|
-
return range.getBoundingClientRect().left;
|
|
45
|
+
if (pmPos >= pmStart && pmPos <= pmEnd) {
|
|
46
|
+
const textNodes = descendantTextNodes(spanEl);
|
|
47
|
+
const charIndex = Math.min(pmPos - pmStart, totalTextLength(textNodes));
|
|
48
|
+
const range = createTextStreamRange(spanEl, charIndex, charIndex);
|
|
49
|
+
if (range) return range.getBoundingClientRect().left;
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
|
-
const
|
|
57
|
-
for (const emptyRun of Array.from(emptyRuns)) {
|
|
52
|
+
for (const emptyRun of findBodyEmptyRuns(container)) {
|
|
58
53
|
const paragraph = emptyRun.closest(".layout-paragraph");
|
|
59
54
|
if (!paragraph) continue;
|
|
60
55
|
const pmStart = Number(paragraph.dataset["pmStart"]);
|
|
@@ -91,6 +86,13 @@ function findLineElementAtPosition(container, pmPos) {
|
|
|
91
86
|
/** @internal */
|
|
92
87
|
function findPositionOnLineAtClientX(lineEl, clientX) {
|
|
93
88
|
const spans = lineEl.querySelectorAll("span[data-pm-start][data-pm-end]");
|
|
89
|
+
const emptyRun = lineEl.querySelector(".layout-empty-run");
|
|
90
|
+
if (emptyRun) {
|
|
91
|
+
const emptyRunStart = emptyRun.dataset["pmStart"];
|
|
92
|
+
if (emptyRunStart !== void 0) return Number(emptyRunStart);
|
|
93
|
+
const paragraphStart = emptyRun.closest(".layout-paragraph")?.dataset["pmStart"];
|
|
94
|
+
return paragraphStart === void 0 ? null : Number(paragraphStart) + 1;
|
|
95
|
+
}
|
|
94
96
|
if (spans.length === 0) {
|
|
95
97
|
const paragraph = lineEl.closest(".layout-paragraph");
|
|
96
98
|
if (paragraph?.dataset["pmStart"]) return Number(paragraph.dataset["pmStart"]) + 1;
|
|
@@ -106,29 +108,23 @@ function findPositionOnLineAtClientX(lineEl, clientX) {
|
|
|
106
108
|
continue;
|
|
107
109
|
}
|
|
108
110
|
if (clientX >= rect.left && clientX <= rect.right) {
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
const text = textNode;
|
|
112
|
-
const ownerDoc = spanEl.ownerDocument;
|
|
113
|
-
if (!ownerDoc) return pmStart;
|
|
111
|
+
const textLength = totalTextLength(descendantTextNodes(spanEl));
|
|
112
|
+
if (textLength === 0) return pmStart;
|
|
114
113
|
let lo = 0;
|
|
115
|
-
let hi =
|
|
114
|
+
let hi = textLength;
|
|
116
115
|
while (lo < hi) {
|
|
117
116
|
const mid = Math.floor((lo + hi) / 2);
|
|
118
|
-
const r =
|
|
119
|
-
r
|
|
120
|
-
r.setEnd(text, mid);
|
|
117
|
+
const r = createTextStreamRange(spanEl, mid, mid);
|
|
118
|
+
if (!r) return pmStart;
|
|
121
119
|
if (clientX < r.getBoundingClientRect().left) hi = mid;
|
|
122
120
|
else lo = mid + 1;
|
|
123
121
|
}
|
|
124
|
-
if (lo > 0 && lo <=
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const leftX =
|
|
129
|
-
|
|
130
|
-
r.setEnd(text, Math.min(lo, text.length));
|
|
131
|
-
const rightX = r.getBoundingClientRect().left;
|
|
122
|
+
if (lo > 0 && lo <= textLength) {
|
|
123
|
+
const left = createTextStreamRange(spanEl, lo - 1, lo - 1);
|
|
124
|
+
const right = createTextStreamRange(spanEl, Math.min(lo, textLength), Math.min(lo, textLength));
|
|
125
|
+
if (!left || !right) return pmStart;
|
|
126
|
+
const leftX = left.getBoundingClientRect().left;
|
|
127
|
+
const rightX = right.getBoundingClientRect().left;
|
|
132
128
|
if (Math.abs(clientX - leftX) < Math.abs(clientX - rightX)) return pmStart + (lo - 1);
|
|
133
129
|
}
|
|
134
130
|
return pmStart + Math.min(lo, pmEnd - pmStart);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readLanguageMarkAttrs, readMathAttrs, readParagraphAttrs, readRunFormattingOverrideMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
1
|
+
import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readPageBreakRunOwnerMarkAttrs, readParagraphAttrs, readRunFormattingOverrideMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
2
2
|
import { readBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
|
|
3
3
|
import { readTextBoxAnchorAttrs } from "./textBoxAnchorAttrs.js";
|
|
4
4
|
//#region src/prosemirror/validation.ts
|
|
@@ -151,6 +151,9 @@ const validateNodeAttrs = (node, path, issues) => {
|
|
|
151
151
|
case "hardBreak":
|
|
152
152
|
appendAttrIssues(path, readHardBreakAttrs(node), issues);
|
|
153
153
|
return;
|
|
154
|
+
case "pageBreakRun":
|
|
155
|
+
appendAttrIssues(path, readPageBreakRunAttrs(node), issues);
|
|
156
|
+
return;
|
|
154
157
|
case "paragraph":
|
|
155
158
|
appendAttrIssues(path, readParagraphAttrs(node), issues);
|
|
156
159
|
return;
|
|
@@ -180,18 +183,31 @@ const validateNodeAttrs = (node, path, issues) => {
|
|
|
180
183
|
appendAttrIssues(path, fieldAttrs, issues);
|
|
181
184
|
if (fieldAttrs.ok) {
|
|
182
185
|
const hasStructuredHyperlink = node.content.content.some((child) => child.marks.some((mark) => mark.type.name === "hyperlink"));
|
|
183
|
-
|
|
186
|
+
const hasPageBreakCarrier = node.content.content.some((child) => child.type.name === "pageBreakRun");
|
|
187
|
+
if (fieldAttrs.value.fieldKind === "complex" && !hasPageBreakCarrier) issues.push({
|
|
184
188
|
path: `${path}.content`,
|
|
185
189
|
message: "Complex fields cannot contain structured result children."
|
|
186
190
|
});
|
|
187
|
-
else if (
|
|
191
|
+
else if (fieldAttrs.value.fieldKind === "complex" && hasStructuredHyperlink) issues.push({
|
|
192
|
+
path: `${path}.content`,
|
|
193
|
+
message: "Complex field results cannot contain hyperlink content."
|
|
194
|
+
});
|
|
195
|
+
else if (!hasStructuredHyperlink && !hasPageBreakCarrier) issues.push({
|
|
188
196
|
path: `${path}.content`,
|
|
189
197
|
message: "Structured simple fields require hyperlink content."
|
|
190
198
|
});
|
|
191
199
|
node.forEach((child, _offset, index) => {
|
|
192
200
|
const childPath = `${path}.content[${index}]`;
|
|
193
201
|
const hasHyperlink = child.marks.some((mark) => mark.type.name === "hyperlink");
|
|
194
|
-
if (child.type.name === "
|
|
202
|
+
if (fieldAttrs.value.fieldKind === "complex" && child.type.name === "textBoxAnchor") issues.push({
|
|
203
|
+
path: childPath,
|
|
204
|
+
message: "Complex field results cannot contain text-box anchors."
|
|
205
|
+
});
|
|
206
|
+
else if (fieldAttrs.value.fieldKind === "complex" && child.type.name === "bookmarkBoundary") issues.push({
|
|
207
|
+
path: childPath,
|
|
208
|
+
message: "Complex field results cannot contain bookmark boundaries."
|
|
209
|
+
});
|
|
210
|
+
else if (child.type.name === "bookmarkBoundary" && !hasHyperlink) issues.push({
|
|
195
211
|
path: childPath,
|
|
196
212
|
message: "Bookmark boundaries inside fields require a hyperlink parent."
|
|
197
213
|
});
|
|
@@ -289,6 +305,9 @@ const validateMarks = (marks, path, issues) => {
|
|
|
289
305
|
case "runPropertyChange":
|
|
290
306
|
appendAttrIssues(markPath, readRunPropertyChangeMarkAttrs(mark), issues);
|
|
291
307
|
continue;
|
|
308
|
+
case "pageBreakRunOwner":
|
|
309
|
+
appendAttrIssues(markPath, readPageBreakRunOwnerMarkAttrs(mark), issues);
|
|
310
|
+
continue;
|
|
292
311
|
case "runFormattingOverride":
|
|
293
312
|
appendAttrIssues(markPath, readRunFormattingOverrideMarkAttrs(mark), issues);
|
|
294
313
|
continue;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { findHfCaretSpan, findHfPmSpans } from "../layout-bridge/dom/findHfPmSpans.js";
|
|
2
|
+
import { createTextStreamRange, descendantTextNodes, totalTextLength } from "../layout-bridge/dom/textStreamDom.js";
|
|
2
3
|
//#region src/render-dom/HeaderFooterSelectionOverlay.ts
|
|
3
4
|
const CARET_CLASS = "folio-hf-selection-caret";
|
|
4
5
|
const RANGE_CLASS = "folio-hf-selection-rect";
|
|
5
6
|
const OWNED_SELECTOR = `.${CARET_CLASS}, .${RANGE_CLASS}`;
|
|
6
|
-
const TEXT_NODE_TYPE = 3;
|
|
7
7
|
const relativeRect = (rect, containerRect, zoom) => ({
|
|
8
8
|
x: (rect.left - containerRect.left) / zoom,
|
|
9
9
|
y: (rect.top - containerRect.top) / zoom,
|
|
@@ -27,17 +27,17 @@ const resolveHeaderFooterSelectionGeometry = (pagesContainer, selection, zoom) =
|
|
|
27
27
|
let height = anchorRect.height || 16;
|
|
28
28
|
const pmStart = Number.parseInt(hit.element.dataset["pmStart"] ?? "", 10);
|
|
29
29
|
const pmEnd = Number.parseInt(hit.element.dataset["pmEnd"] ?? "", 10);
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
const offset = Math.min(Math.max(0, selection.from - pmStart),
|
|
33
|
-
const range = hit.element
|
|
34
|
-
range
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
const textNodes = descendantTextNodes(hit.element);
|
|
31
|
+
if (textNodes.length > 0 && Number.isFinite(pmStart) && Number.isFinite(pmEnd)) {
|
|
32
|
+
const offset = Math.min(Math.max(0, selection.from - pmStart), totalTextLength(textNodes));
|
|
33
|
+
const range = createTextStreamRange(hit.element, offset, offset);
|
|
34
|
+
if (range) {
|
|
35
|
+
const rangeRect = range.getBoundingClientRect();
|
|
36
|
+
if (rangeRect.height > 0 || rangeRect.width > 0 || rangeRect.left > 0) {
|
|
37
|
+
left = rangeRect.left;
|
|
38
|
+
top = rangeRect.top;
|
|
39
|
+
height = rangeRect.height || height;
|
|
40
|
+
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
return {
|
|
@@ -57,17 +57,17 @@ const resolveHeaderFooterSelectionGeometry = (pagesContainer, selection, zoom) =
|
|
|
57
57
|
const spanEnd = Number.parseInt(span.dataset["pmEnd"] ?? "", 10);
|
|
58
58
|
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
|
|
59
59
|
if (spanEnd <= from || spanStart >= to) continue;
|
|
60
|
-
const
|
|
61
|
-
if (
|
|
62
|
-
const length =
|
|
60
|
+
const textNodes = descendantTextNodes(span);
|
|
61
|
+
if (textNodes.length > 0) {
|
|
62
|
+
const length = totalTextLength(textNodes);
|
|
63
63
|
const startOffset = Math.max(0, from - spanStart);
|
|
64
64
|
const endOffset = Math.min(length, to - spanStart);
|
|
65
65
|
if (startOffset < endOffset) {
|
|
66
|
-
const range = span
|
|
67
|
-
range
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
const range = createTextStreamRange(span, startOffset, endOffset);
|
|
67
|
+
if (range) {
|
|
68
|
+
for (const rect of Array.from(range.getClientRects())) ranges.push(relativeRect(rect, containerRect, zoomDivisor));
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
ranges.push(relativeRect(span.getBoundingClientRect(), containerRect, zoomDivisor));
|