@stll/folio-core 0.43.0 → 0.45.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/__fixtures__/paragraphs.js +2 -2
- package/dist/ai-edits/headless.js +7 -5
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/snapshot.js +13 -9
- package/dist/compare/content-alignment.js +94 -54
- package/dist/compare/inline-atoms.js +34 -20
- package/dist/compare/style-resources.js +6 -0
- package/dist/content-controls/mutateContentControls.js +4 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +8 -8
- package/dist/document-operations.js +14 -3
- package/dist/docx/appVersionNormalization.d.ts +0 -18
- package/dist/docx/blockContentParser.js +8 -0
- package/dist/docx/blockRangeMarkers.d.ts +36 -0
- package/dist/docx/blockRangeMarkers.js +59 -0
- package/dist/docx/bookmarkParser.d.ts +2 -20
- package/dist/docx/bookmarkParser.js +6 -30
- package/dist/docx/borderParser.d.ts +13 -0
- package/dist/docx/borderParser.js +71 -0
- package/dist/docx/builtInStyles.d.ts +165 -0
- package/dist/docx/builtInStyles.js +239 -0
- package/dist/docx/commentIdNormalization.d.ts +3 -1
- package/dist/docx/commentIdNormalization.js +18 -1
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +80 -42
- package/dist/docx/commentReferenceNormalization.d.ts +4 -1
- package/dist/docx/commentReferenceNormalization.js +23 -14
- package/dist/docx/commentThreadKey.d.ts +18 -0
- package/dist/docx/commentThreadKey.js +22 -0
- package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
- package/dist/docx/danglingRelationshipReferences.js +30 -0
- package/dist/docx/defaultParagraphStyle.d.ts +18 -1
- package/dist/docx/defaultParagraphStyle.js +23 -1
- package/dist/docx/diagramPreview.js +87 -27
- package/dist/docx/documentParser.d.ts +2 -1
- package/dist/docx/documentParser.js +2 -2
- package/dist/docx/drawingUtils.d.ts +8 -1
- package/dist/docx/drawingUtils.js +12 -3
- package/dist/docx/fieldParser.js +3 -5
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +19 -4
- package/dist/docx/groupDrawingParser.js +4 -4
- package/dist/docx/headerFooterRefParser.d.ts +4 -3
- package/dist/docx/headerFooterRefParser.js +42 -12
- package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
- package/dist/docx/headerFooterReferenceNormalization.js +5 -1
- package/dist/docx/hyperlinkParser.js +13 -17
- package/dist/docx/imageParser.d.ts +10 -2
- package/dist/docx/imageParser.js +80 -30
- package/dist/docx/imageRawXml.d.ts +14 -1
- package/dist/docx/imageRawXml.js +35 -11
- package/dist/docx/markupRangeMarker.d.ts +15 -0
- package/dist/docx/markupRangeMarker.js +44 -0
- package/dist/docx/mathToMathml.js +12 -14
- package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
- package/dist/docx/nonVisualDrawingProps.js +46 -0
- package/dist/docx/noteReferenceStyles.d.ts +29 -0
- package/dist/docx/noteReferenceStyles.js +70 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +4 -1
- package/dist/docx/numberingReferenceNormalization.js +20 -1
- package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
- package/dist/docx/paragraphParser.js +66 -99
- package/dist/docx/paragraphPropertySource.js +1 -0
- package/dist/docx/paragraphTextBoxEnrichment.js +3 -0
- package/dist/docx/paragraphTraversal.d.ts +37 -1
- package/dist/docx/paragraphTraversal.js +84 -1
- package/dist/docx/parseContext.d.ts +37 -0
- package/dist/docx/parseContext.js +67 -0
- package/dist/docx/parseWarningMessage.d.ts +6 -0
- package/dist/docx/parseWarningMessage.js +44 -0
- package/dist/docx/parser.js +83 -29
- package/dist/docx/previewBudget.d.ts +64 -0
- package/dist/docx/previewBudget.js +88 -0
- package/dist/docx/relsParser.d.ts +28 -11
- package/dist/docx/relsParser.js +26 -13
- package/dist/docx/revisionIdNormalization.js +96 -10
- package/dist/docx/rezip.js +80 -40
- package/dist/docx/runConsolidator.js +1 -2
- package/dist/docx/runParser.d.ts +8 -1
- package/dist/docx/runParser.js +30 -48
- package/dist/docx/sdtPropertiesPatch.js +24 -18
- package/dist/docx/sectionParser.d.ts +2 -1
- package/dist/docx/sectionParser.js +21 -65
- package/dist/docx/sectionReferenceHistory.js +2 -2
- package/dist/docx/selectiveSave.js +6 -6
- package/dist/docx/serializer/blockSdtSerializer.js +38 -26
- package/dist/docx/serializer/borderSerializer.d.ts +2 -3
- package/dist/docx/serializer/borderSerializer.js +13 -12
- package/dist/docx/serializer/commentSerializer.d.ts +41 -16
- package/dist/docx/serializer/commentSerializer.js +82 -72
- package/dist/docx/serializer/documentSerializer.d.ts +1 -5
- package/dist/docx/serializer/documentSerializer.js +6 -16
- package/dist/docx/serializer/fontTableSerializer.js +6 -6
- package/dist/docx/serializer/headerFooterSerializer.js +10 -5
- package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
- package/dist/docx/serializer/markupRangeAttributes.js +24 -0
- package/dist/docx/serializer/noteSerializer.js +5 -0
- package/dist/docx/serializer/numberingSerializer.js +7 -6
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
- package/dist/docx/serializer/paragraphSerializer.js +47 -52
- package/dist/docx/serializer/partNamespaces.js +2 -2
- package/dist/docx/serializer/runSerializer.js +57 -31
- package/dist/docx/serializer/sectionPropertiesSerializer.js +11 -10
- package/dist/docx/serializer/settingsSerializer.js +4 -3
- package/dist/docx/serializer/stylesSerializer.js +6 -6
- package/dist/docx/serializer/tableSerializer.js +37 -21
- package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
- package/dist/docx/serializer/textFormattingSerializer.js +29 -28
- package/dist/docx/serializer/themeSerializer.js +6 -6
- package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
- package/dist/docx/serializer/xmlUtils.d.ts +1 -2
- package/dist/docx/serializer/xmlUtils.js +1 -13
- package/dist/docx/server/boundedArchive.d.ts +12 -0
- package/dist/docx/server/boundedArchive.js +20 -1
- package/dist/docx/server/build.js +8 -1
- package/dist/docx/server/createBilingualDocument.js +10 -18
- package/dist/docx/server/extractDocxText.js +3 -4
- package/dist/docx/server/validateDocxConformance.js +22 -1
- package/dist/docx/shadingParser.d.ts +6 -0
- package/dist/docx/shadingParser.js +32 -0
- package/dist/docx/shapeParser.js +10 -8
- package/dist/docx/styleParser.js +13 -87
- package/dist/docx/styleReferenceResolution.d.ts +36 -0
- package/dist/docx/styleReferenceResolution.js +51 -0
- package/dist/docx/tableLook.d.ts +57 -0
- package/dist/docx/tableLook.js +63 -0
- package/dist/docx/tableParser.d.ts +7 -9
- package/dist/docx/tableParser.js +64 -110
- package/dist/docx/textBoxParser.js +11 -6
- package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
- package/dist/docx/trackedMoveRangeNormalization.js +11 -21
- package/dist/docx/transitionalSpelling.d.ts +13 -2
- package/dist/docx/transitionalSpelling.js +23 -1
- package/dist/docx/unzip.d.ts +23 -0
- package/dist/docx/unzip.js +32 -22
- package/dist/docx/verbatimCapture.js +5 -12
- package/dist/docx/vmlImageParser.js +5 -4
- package/dist/docx/vmlPreview.d.ts +1 -3
- package/dist/docx/vmlPreview.js +2 -30
- package/dist/docx/watermarkParser.js +2 -2
- package/dist/docx/xmlParser.d.ts +38 -33
- package/dist/docx/xmlParser.js +92 -47
- package/dist/docx/xmlResourceLimits.d.ts +89 -9
- package/dist/docx/xmlResourceLimits.js +105 -24
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
- package/dist/internal/paragraphFormattingSerialization.js +29 -8
- package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +2 -2
- package/dist/layout-engine/measure/measureBlocks.js +1 -6
- package/dist/layout-engine/types.d.ts +8 -2
- package/dist/layout-engine/types.js +35 -2
- package/dist/layout-painter/renderImage.js +4 -3
- package/dist/layout-painter/renderParagraph.js +4 -3
- package/dist/managers/autoSaveCodec.js +2 -8
- package/dist/markdown/images.js +1 -4
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/internals.d.ts +6 -1
- package/dist/markdown/internals.js +14 -1
- package/dist/markdown/renderBlock.js +35 -21
- package/dist/markdown/renderParagraph.js +14 -5
- package/dist/markdown/renderRuns.js +4 -3
- package/dist/markdown/renderTable.js +4 -3
- package/dist/markdown/trailers.js +41 -7
- package/dist/markdown/types.d.ts +3 -7
- package/dist/prosemirror/attrs/index.js +71 -5
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
- package/dist/prosemirror/commands/image.js +1 -0
- package/dist/prosemirror/commands/index.d.ts +3 -3
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +3 -3
- package/dist/prosemirror/commands/paragraph.js +2 -2
- package/dist/prosemirror/commentIdAllocator.js +2 -7
- package/dist/prosemirror/conversion/fromProseDoc.js +197 -68
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +458 -335
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +6 -1
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -2
- package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +8 -4
- package/dist/prosemirror/extensions/types.d.ts +2 -2
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/index.js +3 -3
- package/dist/prosemirror/insertOperations.d.ts +9 -2
- package/dist/prosemirror/insertOperations.js +9 -4
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +162 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +115 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
- package/dist/prosemirror/plugins/documentStyles.js +11 -1
- package/dist/prosemirror/plugins/index.d.ts +2 -2
- package/dist/prosemirror/plugins/index.js +2 -2
- package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
- package/dist/prosemirror/plugins/revisionIds.js +21 -6
- package/dist/prosemirror/runFormattingReconciliation.js +3 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +81 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
- package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
- package/dist/prosemirror/styles/styleResolver.js +12 -0
- package/dist/style-engine/styleEngine.d.ts +3 -0
- package/dist/style-engine/styleEngine.js +3 -0
- package/dist/style-sets/extract.js +1 -23
- package/dist/style-sets/stellaStyle.js +46 -39
- package/dist/style-sets/styleSetNormalization.d.ts +19 -0
- package/dist/style-sets/styleSetNormalization.js +99 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/base64.d.ts +36 -0
- package/dist/utils/base64.js +40 -0
- package/dist/utils/clipboard.js +2 -1
- package/dist/utils/createDocument.js +145 -20
- package/dist/utils/headingCollector.d.ts +8 -5
- package/dist/utils/headingCollector.js +23 -25
- package/dist/utils/tableOfContentsStyle.js +9 -2
- package/dist/utils/units.d.ts +10 -1
- package/dist/utils/units.js +12 -1
- package/dist/utils/urlSecurity.d.ts +8 -2
- package/dist/utils/urlSecurity.js +21 -3
- package/package.json +2 -2
- package/dist/docx/textWhitespace.d.ts +0 -4
- package/dist/docx/textWhitespace.js +0 -4
- package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
- package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
- package/dist/markdown/headings.d.ts +0 -13
- package/dist/markdown/headings.js +0 -20
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { applyFolioAIEditOperations, previewFolioAIEditOperations } from "./ai-edits/apply.js";
|
|
2
2
|
import { LINE_SPACING_RULE_VALUES, PARAGRAPH_ALIGNMENT_VALUES } from "./types/documentEnumValues.js";
|
|
3
3
|
import { TaggedError } from "better-result";
|
|
4
|
+
import { sanitizeXmlCharacters } from "@stll/docx-core";
|
|
4
5
|
//#region src/document-operations.ts
|
|
5
6
|
const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION = 1;
|
|
6
7
|
/** Direct paragraph-alignment values accepted by the operation contract. */
|
|
@@ -138,15 +139,25 @@ const assertAllowedKeys = (value, path, allowedKeys) => {
|
|
|
138
139
|
const unexpected = Object.keys(value).find((key) => !allowedKeys.includes(key));
|
|
139
140
|
if (unexpected !== void 0) invalidBatch(`${path}.${unexpected}`, "unexpected property");
|
|
140
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* Every string in a batch passes through here, so this is where a value an
|
|
144
|
+
* agent sent stops being able to corrupt the package it lands in: XML 1.0
|
|
145
|
+
* admits none of the C0 controls but tab, LF and CR, and no escape can carry
|
|
146
|
+
* one into a document. The batch is otherwise held to exactly what it says, so
|
|
147
|
+
* the rule is the narrowest one that keeps the request usable — drop what
|
|
148
|
+
* cannot be written, map an unpaired surrogate to U+FFFD — rather than
|
|
149
|
+
* rejecting a whole edit over a stray control character. The parsed batch is
|
|
150
|
+
* both what folio applies and what the receipt reports, so the two agree.
|
|
151
|
+
*/
|
|
141
152
|
const readString = (value, key, path) => {
|
|
142
153
|
const candidate = value[key];
|
|
143
|
-
if (typeof candidate === "string") return candidate;
|
|
154
|
+
if (typeof candidate === "string") return sanitizeXmlCharacters(candidate);
|
|
144
155
|
return invalidBatch(`${path}.${key}`, "expected a string");
|
|
145
156
|
};
|
|
146
157
|
const readOptionalString = (value, key, path) => {
|
|
147
158
|
const candidate = value[key];
|
|
148
159
|
if (candidate === void 0) return;
|
|
149
|
-
if (typeof candidate === "string") return candidate;
|
|
160
|
+
if (typeof candidate === "string") return sanitizeXmlCharacters(candidate);
|
|
150
161
|
return invalidBatch(`${path}.${key}`, "expected a string when provided");
|
|
151
162
|
};
|
|
152
163
|
const readOptionalBoolean = (value, key, path) => {
|
|
@@ -184,7 +195,7 @@ const readOptionalStringArray = (value, key, path) => {
|
|
|
184
195
|
if (candidate === void 0) return;
|
|
185
196
|
if (!Array.isArray(candidate)) return invalidBatch(`${path}.${key}`, "expected an array when provided");
|
|
186
197
|
return candidate.map((item, index) => {
|
|
187
|
-
if (typeof item === "string") return item;
|
|
198
|
+
if (typeof item === "string") return sanitizeXmlCharacters(item);
|
|
188
199
|
return invalidBatch(`${path}.${key}[${index}]`, "expected a string");
|
|
189
200
|
});
|
|
190
201
|
};
|
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
//#region src/docx/appVersionNormalization.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Keep the application version a package states about itself in the form the
|
|
4
|
-
* schema gives it.
|
|
5
|
-
*
|
|
6
|
-
* `AppVersion` in the extended-properties part is `XX.YYYY`: a one- or
|
|
7
|
-
* two-digit integer, a dot, and four digits. Producers exist that write a
|
|
8
|
-
* three-part version there instead, and folio copies `docProps/app.xml`
|
|
9
|
-
* through verbatim when it saves a document it did not create — so a package
|
|
10
|
-
* can carry a value with two dots in, and a save that copies it out hands a
|
|
11
|
-
* consumer a package it refuses to open at all.
|
|
12
|
-
*
|
|
13
|
-
* {@link appVersionInSchemaForm} is the one mapping, and it is a pure function
|
|
14
|
-
* of the value alone: it keeps the leading integer where the value opens with
|
|
15
|
-
* one the form allows, and writes the build digits the form requires. Nothing
|
|
16
|
-
* else in the part is touched, and a package that carries no extended
|
|
17
|
-
* properties keeps carrying none — synthesizing metadata a document never
|
|
18
|
-
* stated is a different decision.
|
|
19
|
-
*/
|
|
20
2
|
declare const AppVersionSchemaError_base: import("better-result").TaggedErrorClass<"AppVersionSchemaError">;
|
|
21
3
|
/**
|
|
22
4
|
* A value reached the package that the schema form does not accept.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { attachPendingRangeMarkers, attachTrailingRangeMarkers, isBlockRangeMarker } from "./blockRangeMarkers.js";
|
|
1
2
|
import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
|
|
2
3
|
import { appendBookmarkMarkerToLastParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInBlocks } from "./bookmarkPlacement.js";
|
|
3
4
|
import { convertBulletToUnicode } from "./bulletMarkers.js";
|
|
@@ -106,6 +107,7 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
106
107
|
const content = [];
|
|
107
108
|
const children = getChildElements(parent);
|
|
108
109
|
const pendingBookmarkMarkers = [];
|
|
110
|
+
const pendingRangeMarkers = [];
|
|
109
111
|
for (const child of children) {
|
|
110
112
|
const localName = getLocalName(child.name ?? "");
|
|
111
113
|
if (localName === "p") {
|
|
@@ -119,6 +121,7 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
119
121
|
restartedNumIds: state.restartedNumIds,
|
|
120
122
|
previousList: state.previousList
|
|
121
123
|
});
|
|
124
|
+
attachPendingRangeMarkers(paragraph, pendingRangeMarkers);
|
|
122
125
|
content.push(paragraph);
|
|
123
126
|
continue;
|
|
124
127
|
}
|
|
@@ -126,6 +129,7 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
126
129
|
const table = parseTable(child, styles, theme, numbering, rels, media, state.options);
|
|
127
130
|
if (!table) continue;
|
|
128
131
|
if (prependBookmarkMarkersToFirstParagraphInBlocks([table], pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
132
|
+
attachPendingRangeMarkers(table, pendingRangeMarkers);
|
|
129
133
|
content.push(table);
|
|
130
134
|
continue;
|
|
131
135
|
}
|
|
@@ -143,6 +147,7 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
143
147
|
content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), sdtContent)) : []
|
|
144
148
|
};
|
|
145
149
|
if (prependBookmarkMarkersToFirstParagraphInBlocks(blockSdt.content, pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
150
|
+
attachPendingRangeMarkers(blockSdt, pendingRangeMarkers);
|
|
146
151
|
content.push(blockSdt);
|
|
147
152
|
continue;
|
|
148
153
|
}
|
|
@@ -154,12 +159,15 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
154
159
|
if (localName === "bookmarkStart" || localName === "bookmarkEnd") {
|
|
155
160
|
const marker = parseBookmarkMarker(child, localName);
|
|
156
161
|
if (!appendBookmarkMarkerToLastParagraphInBlocks(content, marker)) pendingBookmarkMarkers.push(marker);
|
|
162
|
+
continue;
|
|
157
163
|
}
|
|
164
|
+
if (isBlockRangeMarker(localName)) pendingRangeMarkers.push(captureVerbatimXml(child));
|
|
158
165
|
}
|
|
159
166
|
if (pendingBookmarkMarkers.length > 0) content.push({
|
|
160
167
|
type: "paragraph",
|
|
161
168
|
content: [...pendingBookmarkMarkers]
|
|
162
169
|
});
|
|
170
|
+
attachTrailingRangeMarkers(content, pendingRangeMarkers);
|
|
163
171
|
return content;
|
|
164
172
|
};
|
|
165
173
|
/**
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/docx/blockRangeMarkers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Range markers that stand between two blocks.
|
|
4
|
+
*
|
|
5
|
+
* `w:body`, `w:tc`, a header and an SDT's content all admit
|
|
6
|
+
* `EG_RunLevelElts` and `EG_RangeMarkupElements` beside their paragraphs, and
|
|
7
|
+
* every block container dropped them: a `w:permStart` between two paragraphs
|
|
8
|
+
* is the whole of a document-protection range, so losing it removes the
|
|
9
|
+
* protection from the saved file without a word. folio models none of these,
|
|
10
|
+
* and their position is their meaning, so they are captured verbatim and
|
|
11
|
+
* replayed where they stood — the same treatment `w:sdt`'s sibling markers
|
|
12
|
+
* already get (MS-OE376 §2.5.2.30).
|
|
13
|
+
*
|
|
14
|
+
* Bookmarks are absent from the set on purpose: they are modelled, and the
|
|
15
|
+
* block containers already relocate them into the neighbouring paragraph.
|
|
16
|
+
*/
|
|
17
|
+
declare const isBlockRangeMarker: (localName: string) => boolean;
|
|
18
|
+
/** Hand the markers collected so far to the block they stood before. */
|
|
19
|
+
declare const attachPendingRangeMarkers: (block: {
|
|
20
|
+
rawMarkersBefore?: string;
|
|
21
|
+
}, pending: string[]) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Markers after the last block ride on it, since there is no block after them.
|
|
24
|
+
* With no block at all they are dropped: a container holding markers and no
|
|
25
|
+
* content has nothing for them to delimit.
|
|
26
|
+
*/
|
|
27
|
+
declare const attachTrailingRangeMarkers: (blocks: readonly {
|
|
28
|
+
rawMarkersAfter?: string;
|
|
29
|
+
}[], pending: string[]) => void;
|
|
30
|
+
/** Wrap a serialized block in the markup that stood around it. */
|
|
31
|
+
declare const withBlockRangeMarkers: (block: {
|
|
32
|
+
rawMarkersBefore?: string;
|
|
33
|
+
rawMarkersAfter?: string;
|
|
34
|
+
}, xml: string) => string;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { attachPendingRangeMarkers, attachTrailingRangeMarkers, isBlockRangeMarker, withBlockRangeMarkers };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//#region src/docx/blockRangeMarkers.ts
|
|
2
|
+
/**
|
|
3
|
+
* Range markers that stand between two blocks.
|
|
4
|
+
*
|
|
5
|
+
* `w:body`, `w:tc`, a header and an SDT's content all admit
|
|
6
|
+
* `EG_RunLevelElts` and `EG_RangeMarkupElements` beside their paragraphs, and
|
|
7
|
+
* every block container dropped them: a `w:permStart` between two paragraphs
|
|
8
|
+
* is the whole of a document-protection range, so losing it removes the
|
|
9
|
+
* protection from the saved file without a word. folio models none of these,
|
|
10
|
+
* and their position is their meaning, so they are captured verbatim and
|
|
11
|
+
* replayed where they stood — the same treatment `w:sdt`'s sibling markers
|
|
12
|
+
* already get (MS-OE376 §2.5.2.30).
|
|
13
|
+
*
|
|
14
|
+
* Bookmarks are absent from the set on purpose: they are modelled, and the
|
|
15
|
+
* block containers already relocate them into the neighbouring paragraph.
|
|
16
|
+
*/
|
|
17
|
+
const BLOCK_RANGE_MARKER_NAMES = /* @__PURE__ */ new Set([
|
|
18
|
+
"commentRangeEnd",
|
|
19
|
+
"commentRangeStart",
|
|
20
|
+
"customXmlDelRangeEnd",
|
|
21
|
+
"customXmlDelRangeStart",
|
|
22
|
+
"customXmlInsRangeEnd",
|
|
23
|
+
"customXmlInsRangeStart",
|
|
24
|
+
"customXmlMoveFromRangeEnd",
|
|
25
|
+
"customXmlMoveFromRangeStart",
|
|
26
|
+
"customXmlMoveToRangeEnd",
|
|
27
|
+
"customXmlMoveToRangeStart",
|
|
28
|
+
"moveFromRangeEnd",
|
|
29
|
+
"moveFromRangeStart",
|
|
30
|
+
"moveToRangeEnd",
|
|
31
|
+
"moveToRangeStart",
|
|
32
|
+
"permEnd",
|
|
33
|
+
"permStart"
|
|
34
|
+
]);
|
|
35
|
+
const isBlockRangeMarker = (localName) => BLOCK_RANGE_MARKER_NAMES.has(localName);
|
|
36
|
+
/** Hand the markers collected so far to the block they stood before. */
|
|
37
|
+
const attachPendingRangeMarkers = (block, pending) => {
|
|
38
|
+
if (pending.length === 0) return;
|
|
39
|
+
block.rawMarkersBefore = pending.join("");
|
|
40
|
+
pending.length = 0;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Markers after the last block ride on it, since there is no block after them.
|
|
44
|
+
* With no block at all they are dropped: a container holding markers and no
|
|
45
|
+
* content has nothing for them to delimit.
|
|
46
|
+
*/
|
|
47
|
+
const attachTrailingRangeMarkers = (blocks, pending) => {
|
|
48
|
+
const last = blocks.at(-1);
|
|
49
|
+
if (pending.length === 0 || last === void 0) {
|
|
50
|
+
pending.length = 0;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
last.rawMarkersAfter = pending.join("");
|
|
54
|
+
pending.length = 0;
|
|
55
|
+
};
|
|
56
|
+
/** Wrap a serialized block in the markup that stood around it. */
|
|
57
|
+
const withBlockRangeMarkers = (block, xml) => `${block.rawMarkersBefore ?? ""}${xml}${block.rawMarkersAfter ?? ""}`;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { attachPendingRangeMarkers, attachTrailingRangeMarkers, isBlockRangeMarker, withBlockRangeMarkers };
|
|
@@ -1,27 +1,9 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { XmlElement } from "./xmlParser.js";
|
|
3
3
|
//#region src/docx/bookmarkParser.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Parse a bookmark start element (w:bookmarkStart)
|
|
6
|
-
*
|
|
7
|
-
* Extracts:
|
|
8
|
-
* - id: Numeric identifier (required, matches with bookmarkEnd)
|
|
9
|
-
* - name: Bookmark name (required, used by hyperlinks)
|
|
10
|
-
* - colFirst: First column for table bookmarks (optional)
|
|
11
|
-
* - colLast: Last column for table bookmarks (optional)
|
|
12
|
-
*
|
|
13
|
-
* @param node - The w:bookmarkStart XML element
|
|
14
|
-
* @returns Parsed BookmarkStart object
|
|
15
|
-
*/
|
|
4
|
+
/** Parse a bookmark start element (w:bookmarkStart, CT_Bookmark). */
|
|
16
5
|
declare function parseBookmarkStart(node: XmlElement): document_d_exports.BookmarkStart;
|
|
17
|
-
/**
|
|
18
|
-
* Parse a bookmark end element (w:bookmarkEnd)
|
|
19
|
-
*
|
|
20
|
-
* Bookmark ends only contain an ID that matches the corresponding start marker.
|
|
21
|
-
*
|
|
22
|
-
* @param node - The w:bookmarkEnd XML element
|
|
23
|
-
* @returns Parsed BookmarkEnd object
|
|
24
|
-
*/
|
|
6
|
+
/** Parse a bookmark end element (w:bookmarkEnd, CT_MarkupRange). */
|
|
25
7
|
declare function parseBookmarkEnd(node: XmlElement): document_d_exports.BookmarkEnd;
|
|
26
8
|
/**
|
|
27
9
|
* Bookmark map for quick lookup by ID or name
|
|
@@ -1,41 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseBookmarkRangeMarker, parseMarkupRangeMarker } from "./markupRangeMarker.js";
|
|
2
2
|
//#region src/docx/bookmarkParser.ts
|
|
3
|
-
/**
|
|
4
|
-
* Parse a bookmark start element (w:bookmarkStart)
|
|
5
|
-
*
|
|
6
|
-
* Extracts:
|
|
7
|
-
* - id: Numeric identifier (required, matches with bookmarkEnd)
|
|
8
|
-
* - name: Bookmark name (required, used by hyperlinks)
|
|
9
|
-
* - colFirst: First column for table bookmarks (optional)
|
|
10
|
-
* - colLast: Last column for table bookmarks (optional)
|
|
11
|
-
*
|
|
12
|
-
* @param node - The w:bookmarkStart XML element
|
|
13
|
-
* @returns Parsed BookmarkStart object
|
|
14
|
-
*/
|
|
3
|
+
/** Parse a bookmark start element (w:bookmarkStart, CT_Bookmark). */
|
|
15
4
|
function parseBookmarkStart(node) {
|
|
16
|
-
|
|
5
|
+
return {
|
|
17
6
|
type: "bookmarkStart",
|
|
18
|
-
|
|
19
|
-
name: getAttribute(node, "w", "name") ?? ""
|
|
7
|
+
...parseBookmarkRangeMarker(node)
|
|
20
8
|
};
|
|
21
|
-
const colFirst = parseNumericAttribute(node, "w", "colFirst");
|
|
22
|
-
if (colFirst !== void 0) bookmark.colFirst = colFirst;
|
|
23
|
-
const colLast = parseNumericAttribute(node, "w", "colLast");
|
|
24
|
-
if (colLast !== void 0) bookmark.colLast = colLast;
|
|
25
|
-
return bookmark;
|
|
26
9
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Parse a bookmark end element (w:bookmarkEnd)
|
|
29
|
-
*
|
|
30
|
-
* Bookmark ends only contain an ID that matches the corresponding start marker.
|
|
31
|
-
*
|
|
32
|
-
* @param node - The w:bookmarkEnd XML element
|
|
33
|
-
* @returns Parsed BookmarkEnd object
|
|
34
|
-
*/
|
|
10
|
+
/** Parse a bookmark end element (w:bookmarkEnd, CT_MarkupRange). */
|
|
35
11
|
function parseBookmarkEnd(node) {
|
|
36
12
|
return {
|
|
37
13
|
type: "bookmarkEnd",
|
|
38
|
-
|
|
14
|
+
...parseMarkupRangeMarker(node)
|
|
39
15
|
};
|
|
40
16
|
}
|
|
41
17
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { ParseContext } from "./parseContext.js";
|
|
3
|
+
import { XmlElement } from "./xmlParser.js";
|
|
4
|
+
//#region src/docx/borderParser.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* `w:val` is `use="required"` on `CT_Border`. An element without it states no
|
|
7
|
+
* style at all, so the border is dropped rather than invented as `none`:
|
|
8
|
+
* `none` is an authored token that cancels an inherited border, and a
|
|
9
|
+
* malformed element is not evidence the author wanted that.
|
|
10
|
+
*/
|
|
11
|
+
declare function parseBorderSpec(border: XmlElement | null, context?: ParseContext): document_d_exports.BorderSpec | undefined;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { parseBorderSpec };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { BorderStyleSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
|
|
2
|
+
import { getAttribute, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
3
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
4
|
+
//#region src/docx/borderParser.ts
|
|
5
|
+
/**
|
|
6
|
+
* The one reader for `CT_Border`, shared by the paragraph (`w:pBdr`), style,
|
|
7
|
+
* table (`w:tblBorders`/`w:tcBorders`) and page (`w:pgBorders`) tiers.
|
|
8
|
+
*
|
|
9
|
+
* `w:val` is `ST_Border`, whose 193 members include two distinct "no border"
|
|
10
|
+
* tokens: `nil` and `none`. They are not interchangeable downstream, and an
|
|
11
|
+
* explicit one overrides a border inherited from the container, so the member
|
|
12
|
+
* the author wrote is preserved exactly. Members outside the model's known
|
|
13
|
+
* union survive verbatim rather than collapsing to a default, which is how the
|
|
14
|
+
* repo already treats `w:numFmt`, `w:suff` and `w:tab`.
|
|
15
|
+
*/
|
|
16
|
+
const parseBorderColor = (border) => {
|
|
17
|
+
const rgb = getAttribute(border, "w", "color");
|
|
18
|
+
const themeColor = getAttribute(border, "w", "themeColor");
|
|
19
|
+
const themeTint = getAttribute(border, "w", "themeTint");
|
|
20
|
+
const themeShade = getAttribute(border, "w", "themeShade");
|
|
21
|
+
if (rgb === null && themeColor === null && themeTint === null && themeShade === null) return;
|
|
22
|
+
const color = {};
|
|
23
|
+
if (rgb === "auto") color.auto = true;
|
|
24
|
+
else if (rgb) color.rgb = rgb;
|
|
25
|
+
const validatedThemeColor = narrowEnum(themeColor, ThemeColorSlotSchema);
|
|
26
|
+
if (validatedThemeColor) color.themeColor = validatedThemeColor;
|
|
27
|
+
if (themeTint) color.themeTint = themeTint;
|
|
28
|
+
if (themeShade) color.themeShade = themeShade;
|
|
29
|
+
return color;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* `w:val` is `use="required"` on `CT_Border`. An element without it states no
|
|
33
|
+
* style at all, so the border is dropped rather than invented as `none`:
|
|
34
|
+
* `none` is an authored token that cancels an inherited border, and a
|
|
35
|
+
* malformed element is not evidence the author wanted that.
|
|
36
|
+
*/
|
|
37
|
+
function parseBorderSpec(border, context) {
|
|
38
|
+
if (!border) return;
|
|
39
|
+
const rawStyle = getAttribute(border, "w", "val");
|
|
40
|
+
if (!rawStyle) {
|
|
41
|
+
context?.warn({
|
|
42
|
+
code: PARSE_WARNING_CODES.borderWithoutValue,
|
|
43
|
+
element: border.name ?? "border"
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const spec = { style: narrowEnum(rawStyle, BorderStyleSchema) ?? rawStyle };
|
|
48
|
+
const color = parseBorderColor(border);
|
|
49
|
+
if (color) spec.color = color;
|
|
50
|
+
const size = parseNumericAttribute(border, "w", "sz");
|
|
51
|
+
if (size !== void 0) spec.size = size;
|
|
52
|
+
const space = parseNumericAttribute(border, "w", "space");
|
|
53
|
+
if (space !== void 0) spec.space = space;
|
|
54
|
+
const shadow = parseOnOffAttribute(border, "w", "shadow");
|
|
55
|
+
if (shadow !== void 0) spec.shadow = shadow;
|
|
56
|
+
const frame = parseOnOffAttribute(border, "w", "frame");
|
|
57
|
+
if (frame !== void 0) spec.frame = frame;
|
|
58
|
+
const artRelationshipId = getAttribute(border, "r", "id")?.trim();
|
|
59
|
+
if (artRelationshipId) spec.artRelationshipId = artRelationshipId;
|
|
60
|
+
const topLeftArtRelationshipId = getAttribute(border, "r", "topLeft")?.trim();
|
|
61
|
+
if (topLeftArtRelationshipId) spec.topLeftArtRelationshipId = topLeftArtRelationshipId;
|
|
62
|
+
const topRightArtRelationshipId = getAttribute(border, "r", "topRight")?.trim();
|
|
63
|
+
if (topRightArtRelationshipId) spec.topRightArtRelationshipId = topRightArtRelationshipId;
|
|
64
|
+
const bottomLeftArtRelationshipId = getAttribute(border, "r", "bottomLeft")?.trim();
|
|
65
|
+
if (bottomLeftArtRelationshipId) spec.bottomLeftArtRelationshipId = bottomLeftArtRelationshipId;
|
|
66
|
+
const bottomRightArtRelationshipId = getAttribute(border, "r", "bottomRight")?.trim();
|
|
67
|
+
if (bottomRightArtRelationshipId) spec.bottomRightArtRelationshipId = bottomRightArtRelationshipId;
|
|
68
|
+
return spec;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { parseBorderSpec };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/builtInStyles.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The tenth `w:outlineLvl` value. 17.3.1.20: "the val attribute … can be from
|
|
5
|
+
* 0 to 9, where 9 specifically indicates that there is no outline level
|
|
6
|
+
* specifically applied to this paragraph." It is a deliberate "not a heading",
|
|
7
|
+
* not a tenth level. Every range test goes through
|
|
8
|
+
* {@link isHeadingOutlineLevel} so the reserved value keeps one meaning across
|
|
9
|
+
* the codebase.
|
|
10
|
+
*
|
|
11
|
+
* The same clause adds that an omitted element "is assumed to be 9". That
|
|
12
|
+
* default cannot be applied to a *style* definition, because 17.7.1 tells
|
|
13
|
+
* producers not to write a property "already been set by a previous level of
|
|
14
|
+
* the style hierarchy": a document that names a style `heading 1` and omits
|
|
15
|
+
* the level is inheriting the consumer's built-in definition, which carries
|
|
16
|
+
* level 0. An absent level therefore means "unspecified, ask the name", and
|
|
17
|
+
* only a written 9 means body text.
|
|
18
|
+
*/
|
|
19
|
+
declare const BODY_TEXT_OUTLINE_LEVEL = 9;
|
|
20
|
+
/** True when an outline level names a heading rather than body text. */
|
|
21
|
+
declare const isHeadingOutlineLevel: (level: number | null | undefined) => level is number;
|
|
22
|
+
/**
|
|
23
|
+
* Compare style names the way producers actually write them. The corpus shows
|
|
24
|
+
* both `heading 1` (Annex L, 94.8%) and `Heading 1` (5.2%), and LibreOffice
|
|
25
|
+
* drops the space entirely (`Heading1`, `IntenseQuote`), so case and
|
|
26
|
+
* whitespace are the tolerance. A name is otherwise matched whole: a style a
|
|
27
|
+
* Czech template calls `Nadpis 1` stays a custom style.
|
|
28
|
+
*/
|
|
29
|
+
declare const normalizeStyleName: (name: string) => string;
|
|
30
|
+
/**
|
|
31
|
+
* The `w:name` Word itself writes for each built-in, and therefore the
|
|
32
|
+
* spelling every style table folio authors must use. One owner: a style set and
|
|
33
|
+
* the classifier that reads it cannot drift apart if both name the same
|
|
34
|
+
* constant.
|
|
35
|
+
*
|
|
36
|
+
* Word is not uniformly cased and guessing gets it wrong, so each value is the
|
|
37
|
+
* spelling that dominates Microsoft Word output in the public corpus:
|
|
38
|
+
* `footnote text` 375 against 49 `Footnote Text`, `footer` 1145 against 2,
|
|
39
|
+
* `caption` 390 against 60 — but `Body Text` 424 against 2, `Title` 621
|
|
40
|
+
* against 2, and the auto-generated linked character styles (`Footnote Text
|
|
41
|
+
* Char` 248, `Endnote Text Char` 116) title-cased without exception.
|
|
42
|
+
* {@link normalizeStyleName} makes matching tolerant of all of it; this map is
|
|
43
|
+
* about what folio *writes*.
|
|
44
|
+
*/
|
|
45
|
+
declare const BUILT_IN_STYLE_NAME: {
|
|
46
|
+
/** 4,515 Word occurrences against 3 lowercase. */
|
|
47
|
+
readonly normal: "Normal";
|
|
48
|
+
readonly bodyText: "Body Text";
|
|
49
|
+
readonly title: "Title";
|
|
50
|
+
readonly subtitle: "Subtitle";
|
|
51
|
+
readonly quote: "Quote";
|
|
52
|
+
readonly intenseQuote: "Intense Quote";
|
|
53
|
+
readonly listParagraph: "List Paragraph";
|
|
54
|
+
readonly tocHeading: "TOC Heading";
|
|
55
|
+
readonly caption: "caption";
|
|
56
|
+
readonly header: "header";
|
|
57
|
+
readonly footer: "footer";
|
|
58
|
+
readonly footnoteText: "footnote text";
|
|
59
|
+
readonly commentReference: "annotation reference";
|
|
60
|
+
readonly footnoteReference: "footnote reference";
|
|
61
|
+
readonly footnoteTextChar: "Footnote Text Char";
|
|
62
|
+
readonly endnoteText: "endnote text";
|
|
63
|
+
readonly endnoteReference: "endnote reference";
|
|
64
|
+
readonly endnoteTextChar: "Endnote Text Char";
|
|
65
|
+
readonly hyperlink: "Hyperlink";
|
|
66
|
+
readonly defaultParagraphFont: "Default Paragraph Font";
|
|
67
|
+
readonly noList: "No List";
|
|
68
|
+
readonly normalTable: "Normal Table";
|
|
69
|
+
readonly tableGrid: "Table Grid";
|
|
70
|
+
};
|
|
71
|
+
type BuiltInStyleName = (typeof BUILT_IN_STYLE_NAME)[keyof typeof BUILT_IN_STYLE_NAME];
|
|
72
|
+
/**
|
|
73
|
+
* The name of a built-in heading, from its zero-based outline level.
|
|
74
|
+
* Lowercase: 1,066 Word occurrences of `heading 1` against 13 `Heading 1`, and
|
|
75
|
+
* Annex L writes the latent-style exceptions the same way.
|
|
76
|
+
*/
|
|
77
|
+
declare const builtInHeadingStyleName: (outlineLevel: number) => string;
|
|
78
|
+
/** The name of a built-in TOC entry style, from its one-based level (`toc 1`). */
|
|
79
|
+
declare const builtInTableOfContentsStyleName: (level: number) => string;
|
|
80
|
+
/**
|
|
81
|
+
* A document's styles indexed by what they *are* rather than by what they are
|
|
82
|
+
* called. Built once per document: the consumers below classify every
|
|
83
|
+
* paragraph, and rebuilding the maps per paragraph would make each of them
|
|
84
|
+
* quadratic.
|
|
85
|
+
*/
|
|
86
|
+
type BuiltInStyleIndex = {
|
|
87
|
+
/** The style's effective `w:outlineLvl`, including 9, or undefined. */
|
|
88
|
+
outlineLevelOf: (styleId: string | null | undefined) => number | undefined;
|
|
89
|
+
/** The zero-based level a built-in heading *name* implies, or undefined. */
|
|
90
|
+
headingLevelFromNameOf: (styleId: string | null | undefined) => number | undefined;
|
|
91
|
+
/** The built-in this style is, by name, or undefined for a custom style. */
|
|
92
|
+
builtInNameOf: (styleId: string | null | undefined) => BuiltInStyleName | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* The level an English built-in heading *id* implies, and only when the
|
|
95
|
+
* package defines no style under it. See {@link resolveHeadingLevel} tier 3.
|
|
96
|
+
*/
|
|
97
|
+
undefinedBuiltInHeadingLevelOf: (styleId: string | null | undefined) => number | undefined;
|
|
98
|
+
/** The document's style id for a built-in heading level (zero-based). */
|
|
99
|
+
styleIdForHeadingLevel: (level: number) => string | undefined;
|
|
100
|
+
/** The document's style id for a built-in TOC entry level (one-based, `toc 1`). */
|
|
101
|
+
styleIdForTableOfContentsLevel: (level: number) => string | undefined;
|
|
102
|
+
/** The document's style id for a named built-in, e.g. `TOC Heading`. */
|
|
103
|
+
styleIdForBuiltInName: (name: BuiltInStyleName) => string | undefined;
|
|
104
|
+
};
|
|
105
|
+
declare const createBuiltInStyleIndex: (styles: Iterable<document_d_exports.Style>, docDefaults?: document_d_exports.DocDefaults | undefined) => BuiltInStyleIndex;
|
|
106
|
+
/** An index over a document that defines no styles: every lookup misses. */
|
|
107
|
+
declare const EMPTY_BUILT_IN_STYLE_INDEX: BuiltInStyleIndex;
|
|
108
|
+
/**
|
|
109
|
+
* What a consumer knows about a paragraph: its style id and whatever
|
|
110
|
+
* `w:outlineLvl` applies to it. The ProseMirror `outlineLevel` attr already
|
|
111
|
+
* holds direct-else-style resolution, so passing it here agrees with passing
|
|
112
|
+
* direct formatting from the DOCX model.
|
|
113
|
+
*/
|
|
114
|
+
type ParagraphOutlineSource = {
|
|
115
|
+
styleId?: string | null | undefined;
|
|
116
|
+
outlineLevel?: number | null | undefined;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* The heading level a paragraph carries, zero-based (`heading 1` is 0), or
|
|
120
|
+
* undefined when it is not a heading.
|
|
121
|
+
*
|
|
122
|
+
* Precedence:
|
|
123
|
+
*
|
|
124
|
+
* 1. An effective outline level decides on its own, including
|
|
125
|
+
* {@link BODY_TEXT_OUTLINE_LEVEL}, which means "not a heading". A style
|
|
126
|
+
* named `heading 5` whose outline level is 0 is a level-1 heading; a style
|
|
127
|
+
* named `heading 3` reset to 9 is body text. The format gives the outline
|
|
128
|
+
* level to field calculation (17.3.1.20) and leaves the name to the UI
|
|
129
|
+
* (17.7.4.9), so the level is the one the document asserts.
|
|
130
|
+
* 2. Only when no outline level is set anywhere does the built-in `w:name`
|
|
131
|
+
* decide — the style is then inheriting the consumer's own built-in
|
|
132
|
+
* definition, which supplies the level.
|
|
133
|
+
* 3. Last resort, and only for a `w:pStyle` the package defines no style for:
|
|
134
|
+
* the id itself, read as the English built-in id. 17.7.4.17 makes a style
|
|
135
|
+
* without `w:customStyle` a built-in and lets an application recognise it
|
|
136
|
+
* "if the associated style ID is known", which is the one case where the id
|
|
137
|
+
* is all the information left. `defaultParagraphStyle.ts` keeps the same
|
|
138
|
+
* last tier for `Normal`. A document that defines its heading styles never
|
|
139
|
+
* reaches this, so it cannot override a name or an outline level — and a
|
|
140
|
+
* localized package never writes an English id to begin with.
|
|
141
|
+
*
|
|
142
|
+
* Two consequences of rule 1 are deliberate, not oversights.
|
|
143
|
+
*
|
|
144
|
+
* **An outline level on a style that is not a heading still makes a heading.**
|
|
145
|
+
* The corpus has 680 such occurrences across 161 files, including `Title` at
|
|
146
|
+
* level 0 (42×) and `Subtitle` at level 1 (23×), plus `H1`, `Sub-heading`,
|
|
147
|
+
* `index heading` and a `DSTOC1-1`…`DSTOC8-8` family. Setting the level is how
|
|
148
|
+
* a document asks for a paragraph to be outlined, and Word's navigation pane
|
|
149
|
+
* and a `TOC \u` field both honour it, so folio does not second-guess a
|
|
150
|
+
* document that asked. Suppressing `Title` here would mean folio deciding a
|
|
151
|
+
* document's outline differs from Word's.
|
|
152
|
+
*
|
|
153
|
+
* **An outline level that disagrees with a built-in heading name wins.** 26
|
|
154
|
+
* corpus styles do this (`heading 5` at level 0, `heading 3` at level 1, and
|
|
155
|
+
* so on), all from non-Word producers or hand-authored fixtures. The format
|
|
156
|
+
* gives the level to field calculation (17.3.1.20) and the name to the user
|
|
157
|
+
* interface (17.7.4.9), so the level is the machine-readable claim and the
|
|
158
|
+
* name is a label. This is the one rule below that was not confirmed against
|
|
159
|
+
* Word itself.
|
|
160
|
+
*/
|
|
161
|
+
declare const resolveHeadingLevel: (paragraph: ParagraphOutlineSource, index: BuiltInStyleIndex) => number | undefined;
|
|
162
|
+
/** True when the paragraph's style is Word's `Quote` or `Intense Quote`. */
|
|
163
|
+
declare const isQuoteStyle: (styleId: string | null | undefined, index: BuiltInStyleIndex) => boolean;
|
|
164
|
+
//#endregion
|
|
165
|
+
export { BODY_TEXT_OUTLINE_LEVEL, BUILT_IN_STYLE_NAME, BuiltInStyleIndex, EMPTY_BUILT_IN_STYLE_INDEX, ParagraphOutlineSource, builtInHeadingStyleName, builtInTableOfContentsStyleName, createBuiltInStyleIndex, isHeadingOutlineLevel, isQuoteStyle, normalizeStyleName, resolveHeadingLevel };
|