@stll/folio-core 0.47.6 → 0.48.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/ai-edits/word-diff.d.ts +25 -6
- package/dist/ai-edits/word-diff.js +210 -38
- package/dist/controller/fontReadiness.js +3 -3
- package/dist/controller/hyphenationReadiness.d.ts +19 -0
- package/dist/controller/hyphenationReadiness.js +47 -0
- package/dist/controller/layoutPipeline.d.ts +3 -0
- package/dist/controller/layoutPipeline.js +59 -17
- package/dist/display-list/build/buildDisplayList.js +39 -12
- package/dist/display-list/build/pageFurniture.d.ts +7 -1
- package/dist/display-list/build/pageFurniture.js +21 -8
- package/dist/display-list/build/paragraphPrimitives.js +5 -4
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +77 -62
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +57 -45
- package/dist/docx/containerChildren.d.ts +21 -8
- package/dist/docx/containerChildren.js +39 -9
- package/dist/docx/documentParser.d.ts +5 -1
- package/dist/docx/documentParser.js +8 -5
- package/dist/docx/documentSectionFacts.d.ts +22 -0
- package/dist/docx/documentSectionFacts.js +43 -0
- package/dist/docx/fieldParser.d.ts +8 -1
- package/dist/docx/fieldParser.js +47 -3
- package/dist/docx/fontTableParser.js +34 -27
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +15 -12
- package/dist/docx/groupDrawingParser.d.ts +2 -1
- package/dist/docx/groupDrawingParser.js +3 -6
- package/dist/docx/headerFooterParser.d.ts +7 -2
- package/dist/docx/headerFooterParser.js +15 -5
- package/dist/docx/hyperlinkParser.d.ts +48 -36
- package/dist/docx/hyperlinkParser.js +97 -82
- package/dist/docx/numberingParser.js +108 -84
- package/dist/docx/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +381 -362
- package/dist/docx/paragraphProperties.js +123 -109
- package/dist/docx/paragraphPropertySource.d.ts +6 -1
- package/dist/docx/paragraphPropertySource.js +9 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +17 -6
- package/dist/docx/parser.d.ts +7 -1
- package/dist/docx/parser.js +33 -16
- package/dist/docx/previewBudget.d.ts +55 -33
- package/dist/docx/previewBudget.js +59 -65
- package/dist/docx/relsParser.js +9 -1
- package/dist/docx/rezip.js +41 -58
- package/dist/docx/runParser.d.ts +4 -1
- package/dist/docx/runParser.js +172 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/serializer/paragraphSerializer.js +42 -38
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -0
- package/dist/docx/streamingXmlParser.d.ts +6 -2
- package/dist/docx/streamingXmlParser.js +12 -7
- package/dist/docx/styleParser.js +34 -8
- package/dist/docx/tableParser.d.ts +21 -12
- package/dist/docx/tableParser.js +518 -441
- package/dist/docx/textBoxParser.d.ts +8 -3
- package/dist/docx/textBoxParser.js +3 -3
- package/dist/docx/verbatimCapture.d.ts +10 -8
- package/dist/docx/verbatimCapture.js +45 -2
- package/dist/docx/vmlImageParser.d.ts +15 -13
- package/dist/docx/vmlImageParser.js +75 -60
- package/dist/docx/vmlPreview.d.ts +3 -3
- package/dist/docx/vmlPreview.js +3 -4
- package/dist/docx/xmlNamespaceContext.d.ts +9 -0
- package/dist/docx/xmlNamespaceContext.js +54 -0
- package/dist/docx/xmlParser.d.ts +6 -3
- package/dist/docx/xmlParser.js +11 -41
- package/dist/docx/xmlResourceLimits.d.ts +2 -1
- package/dist/docx/xmlResourceLimits.js +4 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/headless-layout.d.ts +11 -2
- package/dist/headless-layout.js +153 -107
- package/dist/internal/paragraphFormattingSerialization.js +3 -3
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
- package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
- package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
- package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
- package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +258 -35
- package/dist/layout-bridge/engine/hitTest.js +5 -3
- package/dist/layout-bridge/engine/selectionRects.js +5 -3
- package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
- package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +70 -11
- package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
- package/dist/layout-engine/justificationCompatibility.js +9 -5
- package/dist/layout-engine/keep-together.d.ts +11 -5
- package/dist/layout-engine/keep-together.js +39 -16
- package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
- package/dist/layout-engine/layoutInstrumentation.js +8 -1
- package/dist/layout-engine/measure/advanceComposition.js +4 -7
- package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
- package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
- package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
- package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
- package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
- package/dist/layout-engine/measure/lineBreaks.js +10 -3
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
- package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
- package/dist/layout-engine/measure/measureBlocks.js +42 -8
- package/dist/layout-engine/measure/measureContainer.js +5 -5
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +21 -5
- package/dist/layout-engine/measure/measureParagraph.js +109 -30
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
- package/dist/layout-engine/measure/tabCalculator.js +2 -1
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +51 -19
- package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
- package/dist/layout-engine/measure/tableCellGrid.js +45 -5
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
- package/dist/layout-engine/noteAreaFlow.js +83 -0
- package/dist/layout-engine/paginator.d.ts +10 -1
- package/dist/layout-engine/paginator.js +13 -1
- package/dist/layout-engine/tableRowBreak.js +3 -1
- package/dist/layout-engine/types.d.ts +89 -3
- package/dist/layout-engine/types.js +96 -1
- package/dist/layout-painter/index.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +32 -83
- package/dist/layout-painter/renderParagraph.d.ts +6 -1
- package/dist/layout-painter/renderParagraph.js +34 -22
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +43 -11
- package/dist/prosemirror/conversion/fromProseDoc.js +8 -1
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +77 -41
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +2 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +2 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +13 -1
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- package/dist/utils/createDocument.js +10 -1
- package/dist/utils/scriptSegments.d.ts +33 -4
- package/dist/utils/scriptSegments.js +39 -6
- package/dist/utils/textFormattingMerge.d.ts +17 -3
- package/dist/utils/textFormattingMerge.js +18 -12
- package/dist/utils/trailingText.d.ts +22 -0
- package/dist/utils/trailingText.js +32 -0
- package/package.json +2 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { calculateColumnWidths } from "../../layout-engine/paginator.js";
|
|
2
|
+
import { resolveEffectiveParagraphSpacingTree } from "../../layout-engine/paragraphSpacing.js";
|
|
3
|
+
import { stripFlowBlockPmAnchors } from "../../layout-engine/types.js";
|
|
4
|
+
import { getMargins, getPageSize } from "../../paged-layout/sectionGeometry.js";
|
|
5
|
+
import { getColumns } from "../sectionColumns.js";
|
|
6
|
+
import { collectEndnoteRefs, convertFootnoteToContent, convertNoteStoryToFlowBlocks } from "./footnoteLayout.js";
|
|
7
|
+
import { panic } from "better-result";
|
|
8
|
+
//#region src/layout-bridge/convert/endnoteLayout.ts
|
|
9
|
+
/**
|
|
10
|
+
* Endnote areas (ECMA-376 §17.11).
|
|
11
|
+
*
|
|
12
|
+
* Endnotes are not reserved per page the way footnotes are. `w:pos` puts them
|
|
13
|
+
* after the last body block of the document (`docEnd`, the default) or of each
|
|
14
|
+
* section (`sectEnd`), where they paginate as body content does: they are
|
|
15
|
+
* spliced into the body's block list and the same measure and paginate path
|
|
16
|
+
* places them. Each area opens with the `w:separator` endnote story, and every
|
|
17
|
+
* page it continues onto opens with the `w:continuationSeparator` story. The
|
|
18
|
+
* parsed model keeps only normal notes, so both stories are the ones a package
|
|
19
|
+
* is written with: one paragraph, no space after, single line spacing, holding
|
|
20
|
+
* the separator mark.
|
|
21
|
+
*
|
|
22
|
+
* A note's blocks carry positions in the note's own document, so they are
|
|
23
|
+
* stripped of them before joining the body flow: a click, a caret or a
|
|
24
|
+
* selection in the body must never resolve into a note. The painted note is
|
|
25
|
+
* addressed by its story instead, which is what the note editor opens.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* The separator story a notes part is written with (folio writes it too):
|
|
29
|
+
* `<w:p><w:pPr><w:spacing w:after="0" w:line="240" w:lineRule="auto"/></w:pPr>`
|
|
30
|
+
* around the mark run, in the document's default paragraph style.
|
|
31
|
+
*/
|
|
32
|
+
const SEPARATOR_STORY = [{
|
|
33
|
+
type: "paragraph",
|
|
34
|
+
formatting: {
|
|
35
|
+
spaceAfter: 0,
|
|
36
|
+
lineSpacing: 240,
|
|
37
|
+
lineSpacingRule: "auto"
|
|
38
|
+
},
|
|
39
|
+
content: []
|
|
40
|
+
}];
|
|
41
|
+
/**
|
|
42
|
+
* Convert and measure every referenced endnote into the areas `w:pos` asks
|
|
43
|
+
* for. `undefined` when no reference names a note, so a document without
|
|
44
|
+
* endnotes lays out exactly as it did before.
|
|
45
|
+
*/
|
|
46
|
+
function prepareEndnoteAreas(input) {
|
|
47
|
+
const notesById = /* @__PURE__ */ new Map();
|
|
48
|
+
for (const note of input.endnotes ?? []) if (note.noteType === "normal") notesById.set(note.id, note);
|
|
49
|
+
if (notesById.size === 0 || input.displayNumbers.size === 0) return;
|
|
50
|
+
const finalSection = countSectionBreaks(input.blocks);
|
|
51
|
+
const referenceSection = firstReferenceSections(input.blocks);
|
|
52
|
+
const notesBySection = /* @__PURE__ */ new Map();
|
|
53
|
+
for (const noteId of input.displayNumbers.keys()) {
|
|
54
|
+
if (!notesById.has(noteId)) continue;
|
|
55
|
+
const section = input.position === "sectEnd" ? collectingSection(referenceSection.get(noteId) ?? finalSection, finalSection, input) : finalSection;
|
|
56
|
+
const noteIds = notesBySection.get(section) ?? [];
|
|
57
|
+
noteIds.push(noteId);
|
|
58
|
+
notesBySection.set(section, noteIds);
|
|
59
|
+
}
|
|
60
|
+
const separatorBlockIds = /* @__PURE__ */ new Map();
|
|
61
|
+
const contentBlockIds = /* @__PURE__ */ new Set();
|
|
62
|
+
const noteStoryByBlockId = /* @__PURE__ */ new Map();
|
|
63
|
+
const areas = [];
|
|
64
|
+
for (const [section, noteIds] of [...notesBySection].sort(([left], [right]) => left - right)) {
|
|
65
|
+
const width = endnoteAreaWidth(section === finalSection ? input.sections.at(-1) : input.sections[section]);
|
|
66
|
+
const separator = convertSeparatorStory(`${`endnote-area-${String(section)}`}-separator`, width, input.options);
|
|
67
|
+
const blocks = [{
|
|
68
|
+
...separator.block,
|
|
69
|
+
attrs: {
|
|
70
|
+
...separator.block.attrs,
|
|
71
|
+
keepNext: true
|
|
72
|
+
}
|
|
73
|
+
}];
|
|
74
|
+
const measures = [separator.measure];
|
|
75
|
+
separatorBlockIds.set(String(separator.block.id), "separator");
|
|
76
|
+
for (const noteId of noteIds) {
|
|
77
|
+
const content = convertFootnoteToContent(notesById.get(noteId), input.displayNumbers.get(noteId) ?? 0, width, {
|
|
78
|
+
...input.options,
|
|
79
|
+
displayText: input.displayTexts.get(noteId) ?? String(noteId)
|
|
80
|
+
});
|
|
81
|
+
for (const [index, block] of content.blocks.entries()) {
|
|
82
|
+
const id = `endnote-${String(noteId)}-${String(index)}`;
|
|
83
|
+
blocks.push(withId(stripFlowBlockPmAnchors(block), id));
|
|
84
|
+
measures.push(content.measures[index]);
|
|
85
|
+
contentBlockIds.add(id);
|
|
86
|
+
noteStoryByBlockId.set(id, {
|
|
87
|
+
kind: "endnote",
|
|
88
|
+
noteId
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
areas.push({
|
|
93
|
+
beforeSectionBreak: section === finalSection ? null : section,
|
|
94
|
+
blocks: resolveEffectiveParagraphSpacingTree(blocks),
|
|
95
|
+
measures
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const continuationSeparator = convertSeparatorStory("endnote-continuation-separator", endnoteAreaWidth(input.sections.at(-1)), input.options);
|
|
99
|
+
separatorBlockIds.set(String(continuationSeparator.block.id), "continuationSeparator");
|
|
100
|
+
return {
|
|
101
|
+
areas,
|
|
102
|
+
noteAreas: {
|
|
103
|
+
separatorBlockIds,
|
|
104
|
+
contentBlockIds,
|
|
105
|
+
continuationSeparator
|
|
106
|
+
},
|
|
107
|
+
noteStoryByBlockId
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The body blocks with each endnote area in place: before the section break
|
|
112
|
+
* that ends the section it follows, or after the last body block.
|
|
113
|
+
*/
|
|
114
|
+
function spliceEndnoteAreas(blocks, measures, prepared) {
|
|
115
|
+
if (prepared === void 0 || prepared.areas.length === 0) return {
|
|
116
|
+
blocks,
|
|
117
|
+
measures
|
|
118
|
+
};
|
|
119
|
+
const areasByBreak = /* @__PURE__ */ new Map();
|
|
120
|
+
let documentEndArea;
|
|
121
|
+
for (const area of prepared.areas) if (area.beforeSectionBreak === null) documentEndArea = area;
|
|
122
|
+
else areasByBreak.set(area.beforeSectionBreak, area);
|
|
123
|
+
const splicedBlocks = [];
|
|
124
|
+
const splicedMeasures = [];
|
|
125
|
+
let sectionBreakIndex = 0;
|
|
126
|
+
for (const [index, block] of blocks.entries()) {
|
|
127
|
+
if (block.kind === "sectionBreak") {
|
|
128
|
+
const area = areasByBreak.get(sectionBreakIndex);
|
|
129
|
+
if (area !== void 0) {
|
|
130
|
+
splicedBlocks.push(...area.blocks);
|
|
131
|
+
splicedMeasures.push(...area.measures);
|
|
132
|
+
}
|
|
133
|
+
sectionBreakIndex += 1;
|
|
134
|
+
}
|
|
135
|
+
splicedBlocks.push(block);
|
|
136
|
+
splicedMeasures.push(measures[index]);
|
|
137
|
+
}
|
|
138
|
+
if (documentEndArea !== void 0) {
|
|
139
|
+
splicedBlocks.push(...documentEndArea.blocks);
|
|
140
|
+
splicedMeasures.push(...documentEndArea.measures);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
blocks: splicedBlocks,
|
|
144
|
+
measures: splicedMeasures
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The endnotes a `docEnd` area collects after the body's last block, for
|
|
149
|
+
* `toFlowBlocks`' `trailingEndnoteIds`. Empty for `sectEnd`, whose final area
|
|
150
|
+
* depends on where the references fall.
|
|
151
|
+
*/
|
|
152
|
+
function trailingEndnoteIds(endnotes, position) {
|
|
153
|
+
if (position !== "docEnd") return /* @__PURE__ */ new Set();
|
|
154
|
+
return new Set((endnotes ?? []).flatMap((note) => note.noteType === "normal" ? [note.id] : []));
|
|
155
|
+
}
|
|
156
|
+
/** `w:pos` for the document: the settings value, else the final section's. */
|
|
157
|
+
function resolveEndnotePosition(settingsPosition, finalSection) {
|
|
158
|
+
return settingsPosition ?? finalSection?.endnotePr?.position ?? "docEnd";
|
|
159
|
+
}
|
|
160
|
+
/** The first column's width in a section: what an endnote area there wraps to. */
|
|
161
|
+
function endnoteAreaWidth(section) {
|
|
162
|
+
const pageSize = getPageSize(section);
|
|
163
|
+
const margins = getMargins(section);
|
|
164
|
+
const [firstColumn] = calculateColumnWidths(pageSize.w, margins.left, margins.right, getColumns(section) ?? {
|
|
165
|
+
count: 1,
|
|
166
|
+
gap: 0
|
|
167
|
+
});
|
|
168
|
+
return firstColumn ?? pageSize.w - margins.left - margins.right;
|
|
169
|
+
}
|
|
170
|
+
function countSectionBreaks(blocks) {
|
|
171
|
+
let count = 0;
|
|
172
|
+
for (const block of blocks) if (block.kind === "sectionBreak") count += 1;
|
|
173
|
+
return count;
|
|
174
|
+
}
|
|
175
|
+
/** The section each endnote is first referenced in. */
|
|
176
|
+
function firstReferenceSections(blocks) {
|
|
177
|
+
const sections = /* @__PURE__ */ new Map();
|
|
178
|
+
let section = 0;
|
|
179
|
+
for (const block of blocks) {
|
|
180
|
+
if (block.kind === "sectionBreak") {
|
|
181
|
+
section += 1;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
for (const { endnoteId } of collectEndnoteRefs([block])) if (!sections.has(endnoteId)) sections.set(endnoteId, section);
|
|
185
|
+
}
|
|
186
|
+
return sections;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The section whose end collects a note referenced in `section`: a section
|
|
190
|
+
* with `w:noEndnote` passes its endnotes on to the next section that shows
|
|
191
|
+
* them, and the document's end collects whatever is left.
|
|
192
|
+
*/
|
|
193
|
+
function collectingSection(section, finalSection, input) {
|
|
194
|
+
let target = section;
|
|
195
|
+
while (target < finalSection && input.sections[target]?.noEndnote === true) target += 1;
|
|
196
|
+
return target;
|
|
197
|
+
}
|
|
198
|
+
/** A separator story's paragraph, converted and measured as a note's text is. */
|
|
199
|
+
function convertSeparatorStory(id, width, options) {
|
|
200
|
+
const converted = convertNoteStoryToFlowBlocks(SEPARATOR_STORY, options).flowBlocks.at(0);
|
|
201
|
+
const block = converted?.kind === "paragraph" ? {
|
|
202
|
+
...converted,
|
|
203
|
+
id
|
|
204
|
+
} : {
|
|
205
|
+
kind: "paragraph",
|
|
206
|
+
id,
|
|
207
|
+
runs: [{
|
|
208
|
+
kind: "text",
|
|
209
|
+
text: ""
|
|
210
|
+
}]
|
|
211
|
+
};
|
|
212
|
+
const [measure] = options.measureBlocks([block], width);
|
|
213
|
+
if (measure?.kind !== "paragraph") panic("An endnote separator paragraph must measure as a paragraph");
|
|
214
|
+
const { pmStart: _pmStart, pmEnd: _pmEnd, ...detached } = block;
|
|
215
|
+
return {
|
|
216
|
+
block: detached,
|
|
217
|
+
measure
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function withId(block, id) {
|
|
221
|
+
return {
|
|
222
|
+
...block,
|
|
223
|
+
id
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
227
|
+
export { endnoteAreaWidth, prepareEndnoteAreas, resolveEndnotePosition, spliceEndnoteAreas, trailingEndnoteIds };
|
|
@@ -15,6 +15,12 @@ type ConvertFootnoteOptions = {
|
|
|
15
15
|
justificationCompatibility?: ToFlowBlocksOptions["justificationCompatibility"];
|
|
16
16
|
tableIndentCompatibility?: ToFlowBlocksOptions["tableIndentCompatibility"];
|
|
17
17
|
automaticHyphenation?: ToFlowBlocksOptions["automaticHyphenation"];
|
|
18
|
+
/**
|
|
19
|
+
* The note's reference text, when it is not the plain display number: an
|
|
20
|
+
* endnote's number in its `w:numFmt` (`i`, `ii`, …). The note shows the same
|
|
21
|
+
* text as its reference mark in the body.
|
|
22
|
+
*/
|
|
23
|
+
displayText?: string;
|
|
18
24
|
};
|
|
19
25
|
/**
|
|
20
26
|
* Scan FlowBlocks for runs with footnoteRefId set.
|
|
@@ -82,8 +88,18 @@ declare function mapFootnotesToPages(pages: Page[], footnoteRefs: {
|
|
|
82
88
|
* Convert a Footnote's content paragraphs to FlowBlocks suitable for rendering.
|
|
83
89
|
* Prepends the display number to the first run of the first paragraph.
|
|
84
90
|
*/
|
|
85
|
-
declare function convertFootnoteToContent(footnote: document_d_exports.Footnote, displayNumber: number, contentWidth: number, options?: ConvertFootnoteOptions): FootnoteContent;
|
|
86
|
-
|
|
91
|
+
declare function convertFootnoteToContent(footnote: document_d_exports.Footnote | document_d_exports.Endnote, displayNumber: number, contentWidth: number, options?: ConvertFootnoteOptions): FootnoteContent;
|
|
92
|
+
/**
|
|
93
|
+
* A note story's content as flow blocks, through the same projection and
|
|
94
|
+
* conversion a note's text takes. `referenceMarkText` is what the story's own
|
|
95
|
+
* `w:footnoteRef`/`w:endnoteRef` mark shows; a story without one (a separator
|
|
96
|
+
* story) is converted as authored.
|
|
97
|
+
*/
|
|
98
|
+
declare function convertNoteStoryToFlowBlocks(content: document_d_exports.Footnote["content"], options: ConvertFootnoteOptions, referenceMarkText?: string): {
|
|
99
|
+
flowBlocks: FlowBlock[];
|
|
100
|
+
hasReferenceMark: boolean;
|
|
101
|
+
};
|
|
102
|
+
declare function applyFootnotePresentation(blocks: FlowBlock[], displayNumber: number | string): FlowBlock[];
|
|
87
103
|
/**
|
|
88
104
|
* Build footnote content for all footnotes referenced in the document.
|
|
89
105
|
* Returns a Map<footnoteId, FootnoteContent>.
|
|
@@ -99,4 +115,4 @@ declare function calculateFootnoteReservedHeights(pageFootnoteMap: Map<number, n
|
|
|
99
115
|
height: number;
|
|
100
116
|
}>): Map<number, number>;
|
|
101
117
|
//#endregion
|
|
102
|
-
export { ConvertFootnoteOptions, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, MeasureBlocksFn, NoteDisplayNumberMaps, applyFootnotePresentation, buildFootnoteContentMap, calculateFootnoteReservedHeights, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, convertFootnoteToContent, mapFootnotesToPages, remapNoteMarkerText };
|
|
118
|
+
export { ConvertFootnoteOptions, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, MeasureBlocksFn, NoteDisplayNumberMaps, applyFootnotePresentation, buildFootnoteContentMap, calculateFootnoteReservedHeights, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, convertFootnoteToContent, convertNoteStoryToFlowBlocks, mapFootnotesToPages, remapNoteMarkerText };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { measureParagraph } from "../../layout-engine/measure/measureParagraph.js";
|
|
2
2
|
import { layoutTextBoxContent } from "../../layout-engine/measure/textBoxParagraphLayout.js";
|
|
3
3
|
import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, isFloatingImageRun, resolveTableWidthPx } from "../../layout-engine/types.js";
|
|
4
|
+
import { expectPreservedXmlAttrs } from "../../prosemirror/attrs/index.js";
|
|
4
5
|
import { footnoteToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
|
|
5
|
-
import { toFlowBlocks } from "./toFlowBlocks.js";
|
|
6
|
+
import { collectNoteRefs, isNoteReferenceMarkXml, toFlowBlocks } from "./toFlowBlocks.js";
|
|
6
7
|
//#region src/layout-bridge/convert/footnoteLayout.ts
|
|
7
8
|
/** Default footnote font size in points */
|
|
8
9
|
const FOOTNOTE_FONT_SIZE = 8;
|
|
@@ -32,23 +33,6 @@ function collectEndnoteRefs(blocks) {
|
|
|
32
33
|
pmPos
|
|
33
34
|
}));
|
|
34
35
|
}
|
|
35
|
-
function collectNoteRefs(blocks, idKey) {
|
|
36
|
-
const refs = [];
|
|
37
|
-
const walk = (containerBlocks) => {
|
|
38
|
-
for (const block of containerBlocks) if (block.kind === "paragraph") for (const run of block.runs) {
|
|
39
|
-
if (run.kind !== "text") continue;
|
|
40
|
-
const noteId = run[idKey];
|
|
41
|
-
if (noteId !== void 0) refs.push({
|
|
42
|
-
noteId,
|
|
43
|
-
pmPos: run.pmStart ?? 0
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
else if (block.kind === "table") for (const row of block.rows) for (const cell of row.cells) walk(cell.blocks);
|
|
47
|
-
else if (block.kind === "textBox") walk(block.content);
|
|
48
|
-
};
|
|
49
|
-
walk(blocks);
|
|
50
|
-
return refs;
|
|
51
|
-
}
|
|
52
36
|
/**
|
|
53
37
|
* Assign sequential display numbers (1, 2, 3, …) to notes in order of first
|
|
54
38
|
* reference. Word numbers footnotes/endnotes by reference order, not by their
|
|
@@ -192,10 +176,33 @@ function mapFootnotesToPages(pages, footnoteRefs) {
|
|
|
192
176
|
* Prepends the display number to the first run of the first paragraph.
|
|
193
177
|
*/
|
|
194
178
|
function convertFootnoteToContent(footnote, displayNumber, contentWidth, options = {}) {
|
|
179
|
+
const displayText = options.displayText ?? String(displayNumber);
|
|
180
|
+
const { flowBlocks, hasReferenceMark } = convertNoteStoryToFlowBlocks(footnote.content, options, displayText);
|
|
181
|
+
const blocks = hasReferenceMark ? flowBlocks.map(applyFootnoteBlockPresentation) : applyFootnotePresentation(flowBlocks, displayText);
|
|
182
|
+
const measures = options.measureBlocks ? options.measureBlocks(blocks, contentWidth) : measureFootnoteBlocks(blocks, contentWidth);
|
|
183
|
+
let totalHeight = 0;
|
|
184
|
+
for (const measure of measures) if (measure.kind === "paragraph") totalHeight += measure.totalHeight;
|
|
185
|
+
else if (measure.kind === "table") totalHeight += measure.totalHeight;
|
|
186
|
+
else if (measure.kind === "image" || measure.kind === "textBox") totalHeight += measure.height;
|
|
187
|
+
return {
|
|
188
|
+
id: footnote.id,
|
|
189
|
+
displayNumber,
|
|
190
|
+
blocks,
|
|
191
|
+
measures,
|
|
192
|
+
height: totalHeight
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* A note story's content as flow blocks, through the same projection and
|
|
197
|
+
* conversion a note's text takes. `referenceMarkText` is what the story's own
|
|
198
|
+
* `w:footnoteRef`/`w:endnoteRef` mark shows; a story without one (a separator
|
|
199
|
+
* story) is converted as authored.
|
|
200
|
+
*/
|
|
201
|
+
function convertNoteStoryToFlowBlocks(content, options, referenceMarkText) {
|
|
195
202
|
const proseOptions = {};
|
|
196
203
|
if (options.styles) proseOptions.styles = options.styles;
|
|
197
204
|
if (options.theme !== void 0) proseOptions.theme = options.theme;
|
|
198
|
-
const pmDoc = footnoteToProseDoc(
|
|
205
|
+
const pmDoc = footnoteToProseDoc(content, proseOptions);
|
|
199
206
|
const flowOptions = {};
|
|
200
207
|
if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
|
|
201
208
|
if (options.styles) flowOptions.styles = options.styles;
|
|
@@ -206,20 +213,22 @@ function convertFootnoteToContent(footnote, displayNumber, contentWidth, options
|
|
|
206
213
|
if (options.justificationCompatibility) flowOptions.justificationCompatibility = options.justificationCompatibility;
|
|
207
214
|
if (options.tableIndentCompatibility) flowOptions.tableIndentCompatibility = options.tableIndentCompatibility;
|
|
208
215
|
if (options.automaticHyphenation) flowOptions.automaticHyphenation = options.automaticHyphenation;
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
let totalHeight = 0;
|
|
212
|
-
for (const measure of measures) if (measure.kind === "paragraph") totalHeight += measure.totalHeight;
|
|
213
|
-
else if (measure.kind === "table") totalHeight += measure.totalHeight;
|
|
214
|
-
else if (measure.kind === "image" || measure.kind === "textBox") totalHeight += measure.height;
|
|
216
|
+
const hasReferenceMark = containsNoteReferenceMark(pmDoc);
|
|
217
|
+
if (hasReferenceMark && referenceMarkText !== void 0) flowOptions.noteReferenceMarkText = referenceMarkText;
|
|
215
218
|
return {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
blocks,
|
|
219
|
-
measures,
|
|
220
|
-
height: totalHeight
|
|
219
|
+
flowBlocks: preserveAuthoredFootnoteTerminalParagraph(toFlowBlocks(pmDoc, flowOptions)),
|
|
220
|
+
hasReferenceMark
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
+
function containsNoteReferenceMark(doc) {
|
|
224
|
+
let found = false;
|
|
225
|
+
doc.descendants((node) => {
|
|
226
|
+
if (found) return false;
|
|
227
|
+
if (node.type.name === "preservedXml" && isNoteReferenceMarkXml(expectPreservedXmlAttrs(node).xml)) found = true;
|
|
228
|
+
return !found;
|
|
229
|
+
});
|
|
230
|
+
return found;
|
|
231
|
+
}
|
|
223
232
|
/** Restore an authored footnote line that the body-only terminal-table policy collapsed. */
|
|
224
233
|
function preserveAuthoredFootnoteTerminalParagraph(blocks) {
|
|
225
234
|
const finalBlock = blocks.at(-1);
|
|
@@ -488,4 +497,4 @@ function calculateFootnoteReservedHeights(pageFootnoteMap, footnoteContentMap) {
|
|
|
488
497
|
return reserved;
|
|
489
498
|
}
|
|
490
499
|
//#endregion
|
|
491
|
-
export { FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyFootnotePresentation, buildFootnoteContentMap, calculateFootnoteReservedHeights, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, convertFootnoteToContent, mapFootnotesToPages, remapNoteMarkerText };
|
|
500
|
+
export { FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyFootnotePresentation, buildFootnoteContentMap, calculateFootnoteReservedHeights, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, convertFootnoteToContent, convertNoteStoryToFlowBlocks, mapFootnotesToPages, remapNoteMarkerText };
|
|
@@ -13,12 +13,6 @@ type HeaderFooterMetrics = {
|
|
|
13
13
|
margins: PageMargins;
|
|
14
14
|
};
|
|
15
15
|
declare function normalizeHeaderFooterMeasureBlocks(blocks: FlowBlock[], section?: HeaderFooterMetrics["section"]): FlowBlock[];
|
|
16
|
-
/**
|
|
17
|
-
* Header/footer auto-fit tables use `w:tblGrid` as a provisional ratio, not a
|
|
18
|
-
* license to paint beyond the page furniture frame. Scale an oversized grid
|
|
19
|
-
* for measurement while leaving the authored block untouched for round trips.
|
|
20
|
-
*/
|
|
21
|
-
declare function fitHeaderFooterTablesToContentWidth(blocks: FlowBlock[], contentWidth: number): FlowBlock[];
|
|
22
16
|
declare function resolveHeaderFooterPositionedVisualTop(position: ImageRunPosition | undefined, elementHeight: number, sourceY: number, flowHeight: number, metrics: HeaderFooterMetrics): number;
|
|
23
17
|
declare function resolveHeaderFooterVisualTop(run: ImageRun, paragraphY: number, flowHeight: number, metrics: HeaderFooterMetrics): number;
|
|
24
18
|
declare function calculateHeaderFooterVisualBounds(blocks: FlowBlock[], measures: Measure[], flowHeight: number, metrics: HeaderFooterMetrics): {
|
|
@@ -103,4 +97,4 @@ type ReserveHeaderFooterFullWidthWrapBandsOptions = {
|
|
|
103
97
|
};
|
|
104
98
|
declare function reserveHeaderFooterFullWidthWrapBands({ blocks, measures, contentWidth, metrics }: ReserveHeaderFooterFullWidthWrapBandsOptions): Measure[];
|
|
105
99
|
//#endregion
|
|
106
|
-
export { ConvertHeaderFooterOptions, HeaderFooterMetrics, calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent,
|
|
100
|
+
export { ConvertHeaderFooterOptions, HeaderFooterMetrics, calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, reserveHeaderFooterFullWidthWrapBands, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cloneParagraphWithPropertySource } from "../../docx/paragraphPropertySource.js";
|
|
2
|
-
import { isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun
|
|
2
|
+
import { isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun } from "../../layout-engine/types.js";
|
|
3
3
|
import { headerFooterToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
|
|
4
4
|
import { emuToPixels } from "../../utils/units.js";
|
|
5
5
|
import { toFlowBlocks } from "./toFlowBlocks.js";
|
|
@@ -33,23 +33,6 @@ function preservesInheritedSpacing(block) {
|
|
|
33
33
|
function normalizeHeaderFooterMeasureBlocks(blocks, section = "header") {
|
|
34
34
|
return normalizeFlowBlockArray(blocks, { suppressTrailingEmptyAfterTable: section === "header" });
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
37
|
-
* Header/footer auto-fit tables use `w:tblGrid` as a provisional ratio, not a
|
|
38
|
-
* license to paint beyond the page furniture frame. Scale an oversized grid
|
|
39
|
-
* for measurement while leaving the authored block untouched for round trips.
|
|
40
|
-
*/
|
|
41
|
-
function fitHeaderFooterTablesToContentWidth(blocks, contentWidth) {
|
|
42
|
-
return blocks.map((block) => {
|
|
43
|
-
if (block.kind !== "table" || block.floating !== void 0 || tableColumnsArePinned(block) || block.columnWidths === void 0) return block;
|
|
44
|
-
const totalWidth = block.columnWidths.reduce((sum, width) => sum + width, 0);
|
|
45
|
-
if (totalWidth <= contentWidth || totalWidth <= 0) return block;
|
|
46
|
-
const scale = contentWidth / totalWidth;
|
|
47
|
-
return {
|
|
48
|
-
...block,
|
|
49
|
-
columnWidths: block.columnWidths.map((width) => width * scale)
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
36
|
function normalizeFlowBlockArray(blocks, normalization) {
|
|
54
37
|
const trailingEmptyAfterTable = /* @__PURE__ */ new Set();
|
|
55
38
|
const lastIndex = blocks.length - 1;
|
|
@@ -433,7 +416,7 @@ function reserveHeaderFooterFullWidthWrapBands({ blocks, measures, contentWidth,
|
|
|
433
416
|
}
|
|
434
417
|
function finalizeHeaderFooterContent(blocks, contentWidth, metrics, options) {
|
|
435
418
|
if (blocks.length === 0) return;
|
|
436
|
-
const blocksForMeasure =
|
|
419
|
+
const blocksForMeasure = normalizeHeaderFooterMeasureBlocks(blocks, metrics.section);
|
|
437
420
|
const measures = reserveHeaderFooterFullWidthWrapBands({
|
|
438
421
|
blocks,
|
|
439
422
|
measures: options.measureBlocks(blocksForMeasure, contentWidth),
|
|
@@ -547,6 +530,7 @@ function serializeParagraphAttrs(attrs) {
|
|
|
547
530
|
"listMarkerFormatting",
|
|
548
531
|
"listMarkerAlignment",
|
|
549
532
|
"listMarkerSuffix",
|
|
533
|
+
"listLevelTabs",
|
|
550
534
|
"tabs"
|
|
551
535
|
];
|
|
552
536
|
const out = {};
|
|
@@ -575,6 +559,7 @@ function serializeRunFmt(run) {
|
|
|
575
559
|
"alternateFontFamily",
|
|
576
560
|
"eastAsiaFontFamily",
|
|
577
561
|
"eastAsiaAlternateFontFamily",
|
|
562
|
+
"eastAsiaHint",
|
|
578
563
|
"complexScriptFontFamily",
|
|
579
564
|
"complexScriptAlternateFontFamily",
|
|
580
565
|
"complexScriptFontSize",
|
|
@@ -594,4 +579,4 @@ function serializeRunFmt(run) {
|
|
|
594
579
|
return JSON.stringify(out);
|
|
595
580
|
}
|
|
596
581
|
//#endregion
|
|
597
|
-
export { calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent,
|
|
582
|
+
export { calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, reserveHeaderFooterFullWidthWrapBands, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
import { ParagraphAttrs } from "../../prosemirror/schema/nodes.js";
|
|
3
|
+
import { RunStyleResolver } from "../../prosemirror/runStyleFormatting.js";
|
|
4
|
+
//#region src/layout-bridge/convert/paragraphMarkFormatting.d.ts
|
|
5
|
+
/** The mark's own properties: its `w:rStyle` character style under its direct `w:rPr`. */
|
|
6
|
+
declare const resolveParagraphMarkOwnFormatting: (mark: document_d_exports.TextFormatting | undefined, styleResolver: RunStyleResolver) => document_d_exports.TextFormatting | undefined;
|
|
7
|
+
/** The paragraph mark's fully resolved run properties. */
|
|
8
|
+
declare const resolveParagraphMarkFormatting: (pmAttrs: ParagraphAttrs, styleResolver: RunStyleResolver) => document_d_exports.TextFormatting | undefined;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { resolveParagraphMarkFormatting, resolveParagraphMarkOwnFormatting };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { resolveParagraphBodyRunFormatting } from "../../prosemirror/runStyleFormatting.js";
|
|
2
|
+
import { cascadeStyleTextFormatting } from "../../prosemirror/styles/styleToggleCascade.js";
|
|
3
|
+
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
4
|
+
//#region src/layout-bridge/convert/paragraphMarkFormatting.ts
|
|
5
|
+
/**
|
|
6
|
+
* Run properties of a paragraph mark (ECMA-376 §17.3.1.29 `w:pPr/w:rPr`).
|
|
7
|
+
*
|
|
8
|
+
* The mark resolves like any run of its paragraph: document defaults, the
|
|
9
|
+
* table style, the paragraph style chain, then a character style the mark
|
|
10
|
+
* names in `w:rStyle` (whose toggles combine per §17.7.3), then the mark's
|
|
11
|
+
* direct properties. The default character style is not applied to the mark.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The properties of the character style a mark names in `w:rStyle`. An id that
|
|
15
|
+
* is missing or names a style of another type contributes nothing.
|
|
16
|
+
*/
|
|
17
|
+
const markCharacterStyleFormatting = (mark, styleResolver) => {
|
|
18
|
+
const styleId = mark?.styleId;
|
|
19
|
+
if (styleId === void 0 || styleResolver.getStyle(styleId)?.type !== "character") return;
|
|
20
|
+
return styleResolver.getRunStyleOwnProperties(styleId);
|
|
21
|
+
};
|
|
22
|
+
/** The mark's own properties: its `w:rStyle` character style under its direct `w:rPr`. */
|
|
23
|
+
const resolveParagraphMarkOwnFormatting = (mark, styleResolver) => {
|
|
24
|
+
const characterStyle = markCharacterStyleFormatting(mark, styleResolver);
|
|
25
|
+
if (characterStyle === void 0) return mark;
|
|
26
|
+
return cascadeStyleTextFormatting([{
|
|
27
|
+
formatting: characterStyle,
|
|
28
|
+
type: "style"
|
|
29
|
+
}, {
|
|
30
|
+
formatting: mark,
|
|
31
|
+
type: "direct"
|
|
32
|
+
}]).formatting;
|
|
33
|
+
};
|
|
34
|
+
/** The paragraph mark's fully resolved run properties. */
|
|
35
|
+
const resolveParagraphMarkFormatting = (pmAttrs, styleResolver) => {
|
|
36
|
+
const mark = pmAttrs._originalFormatting?.runProperties;
|
|
37
|
+
const { baseFormatting, baseToggleCascade } = resolveParagraphBodyRunFormatting({
|
|
38
|
+
styleId: pmAttrs.styleId ?? void 0,
|
|
39
|
+
styleResolver,
|
|
40
|
+
tableRunFormatting: pmAttrs._tableRunFormatting
|
|
41
|
+
});
|
|
42
|
+
const characterStyle = markCharacterStyleFormatting(mark, styleResolver);
|
|
43
|
+
return cascadeStyleTextFormatting([
|
|
44
|
+
{
|
|
45
|
+
cascade: baseToggleCascade,
|
|
46
|
+
type: "carried"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
formatting: characterStyle,
|
|
50
|
+
type: "style"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
formatting: mark,
|
|
54
|
+
type: "direct"
|
|
55
|
+
}
|
|
56
|
+
], { ordinaryFormatting: mergeTextFormatting(mergeTextFormatting(baseFormatting, characterStyle), mark) }).formatting;
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { resolveParagraphMarkFormatting, resolveParagraphMarkOwnFormatting };
|
|
@@ -64,11 +64,39 @@ type ToFlowBlocksOptions = {
|
|
|
64
64
|
justificationCompatibility?: NonNullable<ParagraphAttrs["justificationCompatibility"]>;
|
|
65
65
|
/** Document-generation policy for where `w:tblInd` is measured from. */
|
|
66
66
|
tableIndentCompatibility?: NonNullable<TableBlock["indentCompatibility"]>;
|
|
67
|
+
/**
|
|
68
|
+
* When set, every table-cell anchor lays out inside its cell regardless of
|
|
69
|
+
* an authored `wp:anchor/@layoutInCell="0"`. Compatibility mode 15 and
|
|
70
|
+
* above ignore that opt-out; see `resolveAnchorLayoutInCellCompatibility`.
|
|
71
|
+
*/
|
|
72
|
+
forceAnchorLayoutInCell?: boolean;
|
|
67
73
|
/** Document-wide automatic hyphenation policy. */
|
|
68
74
|
automaticHyphenation?: NonNullable<ParagraphAttrs["automaticHyphenation"]>;
|
|
69
75
|
/** Line pitch for the final body section, whose properties live outside the PM body. */
|
|
70
76
|
finalSectionDocumentGridLinePitchTwips?: number;
|
|
77
|
+
/**
|
|
78
|
+
* The number a note story's `w:footnoteRef`/`w:endnoteRef` marks show. The
|
|
79
|
+
* mark stands for its note's reference number and shows it where it sits
|
|
80
|
+
* among the story's runs, in that run's formatting.
|
|
81
|
+
*/
|
|
82
|
+
noteReferenceMarkText?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Endnotes laid out after the body's last block (`w:pos="docEnd"`). A body
|
|
85
|
+
* that references one ends in its endnote area, so its final paragraph is no
|
|
86
|
+
* longer the document's last and keeps its height.
|
|
87
|
+
*/
|
|
88
|
+
trailingEndnoteIds?: ReadonlySet<number>;
|
|
71
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* Runs with `idKey` set, in document order: the note references a block list
|
|
92
|
+
* makes, through table cells (and tables within cells) and text boxes.
|
|
93
|
+
*/
|
|
94
|
+
declare function collectNoteRefs(blocks: readonly FlowBlock[], idKey: "footnoteRefId" | "endnoteRefId"): {
|
|
95
|
+
noteId: number;
|
|
96
|
+
pmPos: number;
|
|
97
|
+
}[];
|
|
98
|
+
/** Whether captured run-child markup is a note story's `w:footnoteRef`/`w:endnoteRef`. */
|
|
99
|
+
declare function isNoteReferenceMarkXml(xml: string): boolean;
|
|
72
100
|
/**
|
|
73
101
|
* Word's layout fallback when an imported OOXML style hierarchy never supplies
|
|
74
102
|
* `w:sz`. ECMA-376 deliberately leaves that terminal fallback to the consumer;
|
|
@@ -101,4 +129,4 @@ declare function convertBorderSpecToLayout(border: ConvertibleBorder, theme?: do
|
|
|
101
129
|
*/
|
|
102
130
|
declare function toFlowBlocks(doc: Node, options?: ToFlowBlocksOptions): FlowBlock[];
|
|
103
131
|
//#endregion
|
|
104
|
-
export { ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, convertBorderSpecToLayout, formatCounter, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|
|
132
|
+
export { ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|