@stll/folio-core 0.54.2 → 0.56.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/apply.js +185 -33
- package/dist/ai-edits/headless.js +3 -2
- package/dist/ai-edits/types.d.ts +7 -1
- package/dist/compare/compare.js +1 -0
- package/dist/compare/content-types.d.ts +3 -15
- package/dist/compare/reproducible-package.d.ts +0 -17
- package/dist/compare/reproducible-package.js +12 -18
- package/dist/controller/canonicalClipboard.d.ts +23 -0
- package/dist/controller/canonicalClipboard.js +476 -0
- package/dist/controller/canonicalClipboardResources.d.ts +21 -0
- package/dist/controller/canonicalClipboardResources.js +382 -0
- package/dist/controller/canonicalComposition.d.ts +53 -0
- package/dist/controller/canonicalComposition.js +296 -0
- package/dist/controller/canonicalInlineProjection.d.ts +113 -0
- package/dist/controller/canonicalInlineProjection.js +393 -0
- package/dist/controller/canonicalInput.d.ts +54 -0
- package/dist/controller/canonicalInput.js +377 -0
- package/dist/controller/canonicalInputTimer.d.ts +7 -0
- package/dist/controller/canonicalInputTimer.js +11 -0
- package/dist/controller/canonicalOperations.d.ts +22 -0
- package/dist/controller/canonicalOperations.js +85 -0
- package/dist/controller/canonicalPublicOperations.d.ts +48 -0
- package/dist/controller/canonicalPublicOperations.js +556 -0
- package/dist/controller/canonicalReview.d.ts +12 -0
- package/dist/controller/canonicalReview.js +19 -0
- package/dist/controller/canonicalSession.d.ts +167 -0
- package/dist/controller/canonicalSession.js +1186 -0
- package/dist/controller/canonicalStoryEditor.d.ts +36 -0
- package/dist/controller/canonicalStoryEditor.js +87 -0
- package/dist/controller/canonicalStructure.d.ts +16 -0
- package/dist/controller/canonicalStructure.js +322 -0
- package/dist/controller/canonicalTocSelection.d.ts +11 -0
- package/dist/controller/canonicalTocSelection.js +43 -0
- package/dist/controller/folioEditor.d.ts +3 -10
- package/dist/controller/folioEditor.js +14 -4
- package/dist/controller/headerFooterEditorManager.d.ts +5 -0
- package/dist/controller/headerFooterEditorManager.js +72 -3
- package/dist/controller/hiddenEditorApi.d.ts +45 -0
- package/dist/controller/hiddenEditorApi.js +29 -8
- package/dist/controller/hiddenEditorManager.d.ts +13 -2
- package/dist/controller/hiddenEditorManager.js +639 -31
- package/dist/controller/layoutPipeline.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +2 -0
- package/dist/controller/noteEditorManager.d.ts +5 -0
- package/dist/controller/noteEditorManager.js +114 -15
- package/dist/document-operations.d.ts +8 -1
- package/dist/document-operations.js +6 -4
- package/dist/docx/attributeRemainder.js +1 -0
- package/dist/docx/blockPlainText.d.ts +1 -1
- package/dist/docx/blockPlainText.js +11 -3
- package/dist/docx/canonicalResourceSave.d.ts +16 -0
- package/dist/docx/canonicalResourceSave.js +27 -0
- package/dist/docx/canonicalSave.d.ts +29 -0
- package/dist/docx/canonicalSave.js +101 -0
- package/dist/docx/canonicalSessionInput.d.ts +11 -0
- package/dist/docx/canonicalSessionInput.js +27 -0
- package/dist/docx/canonicalStoryRepack.d.ts +10 -0
- package/dist/docx/canonicalStoryRepack.js +74 -0
- package/dist/docx/contentTypeRegistry.d.ts +8 -0
- package/dist/docx/contentTypeRegistry.js +64 -0
- package/dist/docx/documentParser.d.ts +1 -13
- package/dist/docx/documentParser.js +1 -47
- package/dist/docx/ensureParaIds.d.ts +7 -1
- package/dist/docx/ensureParaIds.js +173 -215
- package/dist/docx/foldedListNumberFields.d.ts +85 -0
- package/dist/docx/foldedListNumberFields.js +267 -0
- package/dist/docx/footnoteParser.d.ts +1 -11
- package/dist/docx/footnoteParser.js +1 -16
- package/dist/docx/headerFooterParser.d.ts +1 -9
- package/dist/docx/headerFooterParser.js +1 -12
- package/dist/docx/headerFooterVerbatim.d.ts +39 -1
- package/dist/docx/headerFooterVerbatim.js +173 -2
- package/dist/docx/imageParser.d.ts +13 -1
- package/dist/docx/imageParser.js +20 -11
- package/dist/docx/metadataPrivacy.js +6 -1
- package/dist/docx/noteIds.d.ts +5 -0
- package/dist/docx/noteIds.js +6 -2
- package/dist/docx/noteReferenceMark.d.ts +3 -1
- package/dist/docx/noteReferenceMark.js +15 -14
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +17 -3
- package/dist/docx/packageParts.d.ts +3 -1
- package/dist/docx/packageParts.js +74 -19
- package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
- package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
- package/dist/docx/paragraphParser.js +101 -53
- package/dist/docx/paragraphPropertySource.d.ts +15 -1
- package/dist/docx/paragraphPropertySource.js +77 -22
- package/dist/docx/parser.js +3 -1
- package/dist/docx/removeHeaderFooterParts.js +17 -6
- package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
- package/dist/docx/reviewHistoryNamespace.js +4 -0
- package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
- package/dist/docx/reviewResolutionProvenance.js +153 -0
- package/dist/docx/rezip.d.ts +54 -6
- package/dist/docx/rezip.js +835 -257
- package/dist/docx/runConsolidator.d.ts +2 -58
- package/dist/docx/runConsolidator.js +3 -175
- package/dist/docx/runParser.d.ts +2 -1
- package/dist/docx/runParser.js +156 -116
- package/dist/docx/saveDiagnostics.d.ts +22 -0
- package/dist/docx/saveDiagnostics.js +0 -0
- package/dist/docx/selectiveSave.d.ts +3 -1
- package/dist/docx/selectiveSave.js +36 -4
- package/dist/docx/selectiveXmlPatch.d.ts +16 -8
- package/dist/docx/selectiveXmlPatch.js +81 -7
- package/dist/docx/serializer/documentSerializer.d.ts +9 -2
- package/dist/docx/serializer/documentSerializer.js +29 -10
- package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
- package/dist/docx/serializer/headerFooterSerializer.js +19 -11
- package/dist/docx/serializer/noteSerializer.d.ts +2 -2
- package/dist/docx/serializer/noteSerializer.js +24 -8
- package/dist/docx/serializer/paragraphSerializer.js +41 -4
- package/dist/docx/serializer/partNamespaces.js +2 -1
- package/dist/docx/serializer/runSerializer.js +3 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
- package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
- package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
- package/dist/docx/settingsParser.d.ts +1 -2
- package/dist/docx/settingsParser.js +5 -6
- package/dist/docx/storyBlockReplay.d.ts +31 -0
- package/dist/docx/storyBlockReplay.js +471 -0
- package/dist/docx/storyPlainText.d.ts +20 -0
- package/dist/docx/storyPlainText.js +23 -0
- package/dist/docx/streamingXmlParser.d.ts +22 -1
- package/dist/docx/streamingXmlParser.js +49 -3
- package/dist/docx/structuralXmlPatch.js +18 -23
- package/dist/docx/styleParser.d.ts +5 -1
- package/dist/docx/styleParser.js +1 -1
- package/dist/docx/tableParser.d.ts +1 -8
- package/dist/docx/tableParser.js +1 -28
- package/dist/docx/textBoxParser.d.ts +1 -5
- package/dist/docx/textBoxParser.js +1 -20
- package/dist/docx/unzip.js +6 -1
- package/dist/docx/verbatimCapture.d.ts +3 -1
- package/dist/docx/verbatimCapture.js +49 -6
- package/dist/i18n/messages/ar.gen.d.ts +5 -0
- package/dist/i18n/messages/ar.gen.js +656 -0
- package/dist/i18n/messages/cs.gen.d.ts +5 -0
- package/dist/i18n/messages/cs.gen.js +656 -0
- package/dist/i18n/messages/de.gen.d.ts +5 -0
- package/dist/i18n/messages/de.gen.js +656 -0
- package/dist/i18n/messages/en.gen.d.ts +5 -0
- package/dist/i18n/messages/en.gen.js +656 -0
- package/dist/i18n/messages/es.gen.d.ts +5 -0
- package/dist/i18n/messages/es.gen.js +656 -0
- package/dist/i18n/messages/et.gen.d.ts +5 -0
- package/dist/i18n/messages/et.gen.js +656 -0
- package/dist/i18n/messages/fr.gen.d.ts +5 -0
- package/dist/i18n/messages/fr.gen.js +656 -0
- package/dist/i18n/messages/he.gen.d.ts +5 -0
- package/dist/i18n/messages/he.gen.js +656 -0
- package/dist/i18n/messages/hi.gen.d.ts +5 -0
- package/dist/i18n/messages/hi.gen.js +656 -0
- package/dist/i18n/messages/hu.gen.d.ts +5 -0
- package/dist/i18n/messages/hu.gen.js +656 -0
- package/dist/i18n/messages/locales.d.ts +5 -0
- package/dist/i18n/messages/locales.js +22 -0
- package/dist/i18n/messages/lt.gen.d.ts +5 -0
- package/dist/i18n/messages/lt.gen.js +656 -0
- package/dist/i18n/messages/lv.gen.d.ts +5 -0
- package/dist/i18n/messages/lv.gen.js +656 -0
- package/dist/i18n/messages/pl.gen.d.ts +5 -0
- package/dist/i18n/messages/pl.gen.js +656 -0
- package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
- package/dist/i18n/messages/pt-BR.gen.js +656 -0
- package/dist/i18n/messages/sk.gen.d.ts +5 -0
- package/dist/i18n/messages/sk.gen.js +656 -0
- package/dist/i18n/messages/tr.gen.d.ts +5 -0
- package/dist/i18n/messages/tr.gen.js +656 -0
- package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
- package/dist/i18n/messages/zh-CN.gen.js +656 -0
- package/dist/i18n/messages.d.ts +2 -3
- package/dist/i18n/messages.js +1 -19
- package/dist/internal/acceptedBlockProjection.d.ts +12 -0
- package/dist/internal/acceptedBlockProjection.js +45 -0
- package/dist/internal/noteMarkerAttrs.d.ts +8 -0
- package/dist/internal/noteMarkerAttrs.js +16 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
- package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
- package/dist/internal/prosemirrorAttrBoundary.js +50 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
- package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
- package/dist/layout-bridge/convert/noteReferences.js +1 -6
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
- package/dist/managers/DocumentLoaderManager.d.ts +1 -0
- package/dist/managers/DocumentLoaderManager.js +9 -1
- package/dist/markdown/escape.d.ts +3 -1
- package/dist/markdown/escape.js +9 -2
- package/dist/markdown/renderBlock.js +20 -121
- package/dist/markdown/renderParagraph.js +13 -15
- package/dist/markdown/renderRuns.d.ts +7 -1
- package/dist/markdown/renderRuns.js +35 -15
- package/dist/markdown/renderTable.js +2 -0
- package/dist/markdown/types.d.ts +3 -9
- package/dist/prosemirror/attrs/index.d.ts +2 -12
- package/dist/prosemirror/attrs/index.js +22 -48
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/canonicalCommands.d.ts +121 -0
- package/dist/prosemirror/canonicalCommands.js +35 -0
- package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
- package/dist/prosemirror/canonicalSelectionRange.js +15 -0
- package/dist/prosemirror/clipboardIntent.d.ts +7 -0
- package/dist/prosemirror/clipboardIntent.js +9 -0
- package/dist/prosemirror/commands/pageBreak.js +15 -1
- package/dist/prosemirror/commands/pastePlainText.js +2 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
- package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
- package/dist/prosemirror/conversion/toProseDoc.js +55 -14
- package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
- package/dist/prosemirror/executeEditorCommand.js +26 -0
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
- package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
- package/dist/prosemirror/insertOperations.js +2 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +16 -7
- package/dist/prosemirror/listNumbering.js +26 -5
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/markupViewNotes.js +3 -2
- package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
- package/dist/prosemirror/noteReferenceReview.js +5 -3
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
- package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
- package/dist/prosemirror/plugins/suggestionMode.js +57 -7
- package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
- package/dist/prosemirror/runFormattingFromMarks.js +15 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
- package/dist/prosemirror/schema/marks.d.ts +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +10 -2
- package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
- package/dist/prosemirror/textInput.js +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +2 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
- package/dist/prosemirror/validation.js +4 -0
- package/dist/types/canonicalCapabilities.d.ts +215 -0
- package/dist/types/canonicalCapabilities.js +212 -0
- package/dist/types/canonicalSave.d.ts +11 -0
- package/dist/types/canonicalSave.js +0 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/types/docxSerialization.d.ts +14 -0
- package/dist/types/docxSerialization.js +7 -0
- package/dist/utils/createDocument.js +2 -2
- package/package.json +16 -4
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/storyPlainText.d.ts
|
|
3
|
+
/** Read the document body with pending revisions accepted. */
|
|
4
|
+
declare const getDocumentText: (body: document_d_exports.DocumentBody) => string;
|
|
5
|
+
/** Approximate word count of the accepted body text. */
|
|
6
|
+
declare const getWordCount: (body: document_d_exports.DocumentBody) => number;
|
|
7
|
+
/** Character count of the accepted body text. */
|
|
8
|
+
declare const getCharacterCount: (body: document_d_exports.DocumentBody) => number;
|
|
9
|
+
/** Read an accepted table, including nested blocks and tracked structure. */
|
|
10
|
+
declare const getTableText: (table: document_d_exports.Table) => string;
|
|
11
|
+
/** Read accepted text-box content for search and indexing. */
|
|
12
|
+
declare const getTextBoxText: (textBox: document_d_exports.TextBox) => string;
|
|
13
|
+
/** Read an accepted header or footer through the same walk as body and notes. */
|
|
14
|
+
declare const getHeaderFooterText: (headerFooter: document_d_exports.HeaderFooter) => string;
|
|
15
|
+
/** Read accepted footnote content, including nested blocks. */
|
|
16
|
+
declare const getFootnoteText: (footnote: document_d_exports.Footnote) => string;
|
|
17
|
+
/** Read accepted endnote content, including nested blocks. */
|
|
18
|
+
declare const getEndnoteText: (endnote: document_d_exports.Endnote) => string;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { getCharacterCount, getDocumentText, getEndnoteText, getFootnoteText, getHeaderFooterText, getTableText, getTextBoxText, getWordCount };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { blockPlainText } from "./blockPlainText.js";
|
|
2
|
+
//#region src/docx/storyPlainText.ts
|
|
3
|
+
/** Read the document body with pending revisions accepted. */
|
|
4
|
+
const getDocumentText = (body) => blockPlainText(body.content);
|
|
5
|
+
/** Approximate word count of the accepted body text. */
|
|
6
|
+
const getWordCount = (body) => {
|
|
7
|
+
const words = getDocumentText(body).trim().split(/\s+/u);
|
|
8
|
+
return words.length > 0 && words[0] !== "" ? words.length : 0;
|
|
9
|
+
};
|
|
10
|
+
/** Character count of the accepted body text. */
|
|
11
|
+
const getCharacterCount = (body) => getDocumentText(body).length;
|
|
12
|
+
/** Read an accepted table, including nested blocks and tracked structure. */
|
|
13
|
+
const getTableText = (table) => blockPlainText([table]);
|
|
14
|
+
/** Read accepted text-box content for search and indexing. */
|
|
15
|
+
const getTextBoxText = (textBox) => blockPlainText(textBox.content);
|
|
16
|
+
/** Read an accepted header or footer through the same walk as body and notes. */
|
|
17
|
+
const getHeaderFooterText = (headerFooter) => blockPlainText(headerFooter.content);
|
|
18
|
+
/** Read accepted footnote content, including nested blocks. */
|
|
19
|
+
const getFootnoteText = (footnote) => blockPlainText(footnote.content);
|
|
20
|
+
/** Read accepted endnote content, including nested blocks. */
|
|
21
|
+
const getEndnoteText = (endnote) => blockPlainText(endnote.content);
|
|
22
|
+
//#endregion
|
|
23
|
+
export { getCharacterCount, getDocumentText, getEndnoteText, getFootnoteText, getHeaderFooterText, getTableText, getTextBoxText, getWordCount };
|
|
@@ -6,6 +6,12 @@ type ParseXmlResult = {
|
|
|
6
6
|
} | {
|
|
7
7
|
status: "unsupported";
|
|
8
8
|
};
|
|
9
|
+
type XmlSourceRange = {
|
|
10
|
+
readonly start: number;
|
|
11
|
+
readonly end: number;
|
|
12
|
+
};
|
|
13
|
+
/** Exact element source ranges, available only from the opt-in source-range reader. */
|
|
14
|
+
declare const getXmlSourceRange: (element: XmlElement) => XmlSourceRange | undefined;
|
|
9
15
|
/**
|
|
10
16
|
* Parse ordinary OOXML into Folio's existing element representation in one
|
|
11
17
|
* pass. Unsupported or malformed constructs return a sentinel so callers can
|
|
@@ -17,11 +23,20 @@ type AttributeValueSpan = {
|
|
|
17
23
|
};
|
|
18
24
|
type OpenTagVisitor = (element: XmlElement, attributeValueSpans: ReadonlyMap<string, AttributeValueSpan>) => ReadonlyMap<string, string> | null;
|
|
19
25
|
type OpenTagScanVisitor = (...args: Parameters<OpenTagVisitor>) => null;
|
|
26
|
+
type ElementScanOptions = {
|
|
27
|
+
element: XmlElement;
|
|
28
|
+
attributeValueSpans: ReadonlyMap<string, AttributeValueSpan>;
|
|
29
|
+
nameEnd: number;
|
|
30
|
+
parent: XmlElement | undefined;
|
|
31
|
+
};
|
|
32
|
+
type ElementScanVisitor = (options: ElementScanOptions) => void;
|
|
20
33
|
/**
|
|
21
34
|
* @param inheritedNamespaceScope the bindings in scope around `xml`, for a
|
|
22
35
|
* fragment captured out of a part whose root declared them.
|
|
23
36
|
*/
|
|
24
37
|
declare const parseStreamingXml: (xml: string, inheritedNamespaceScope?: XmlNamespaceScope) => ParseXmlResult;
|
|
38
|
+
/** Retain source spans for every element without changing the parsed namespace tree. */
|
|
39
|
+
declare const parseStreamingXmlWithSourceRanges: (xml: string, inheritedNamespaceScope?: XmlNamespaceScope) => ParseXmlResult;
|
|
25
40
|
/** Retain the body tree while collecting identities for import repair. */
|
|
26
41
|
declare const parseStreamingXmlWithIdentityVisitor: (xml: string, visitOpenTag: OpenTagScanVisitor) => ParseXmlResult;
|
|
27
42
|
/** Rewrite selected decimal attribute values while preserving every other source byte. */
|
|
@@ -37,5 +52,11 @@ declare const scanStreamingXmlNumericIdAttributes: (xml: string, visitOpenTag: O
|
|
|
37
52
|
} | {
|
|
38
53
|
status: "scanned";
|
|
39
54
|
};
|
|
55
|
+
/** Visit namespace-resolved start tags and source spans without building a tree. */
|
|
56
|
+
declare const scanStreamingXmlElements: (xml: string, visitElement: ElementScanVisitor) => {
|
|
57
|
+
status: "unsupported";
|
|
58
|
+
} | {
|
|
59
|
+
status: "scanned";
|
|
60
|
+
};
|
|
40
61
|
//#endregion
|
|
41
|
-
export { parseStreamingXml, parseStreamingXmlWithIdentityVisitor, rewriteStreamingXmlDecimalAttributes, scanStreamingXmlNumericIdAttributes };
|
|
62
|
+
export { getXmlSourceRange, parseStreamingXml, parseStreamingXmlWithIdentityVisitor, parseStreamingXmlWithSourceRanges, rewriteStreamingXmlDecimalAttributes, scanStreamingXmlElements, scanStreamingXmlNumericIdAttributes };
|
|
@@ -2,6 +2,9 @@ import { EMPTY_NAMESPACE_SCOPE, attachXmlNamespaceContext } from "./xmlNamespace
|
|
|
2
2
|
import { FOLIO_XML_RESOURCE_LIMITS } from "./xmlResourceLimits.js";
|
|
3
3
|
import { isOoxmlNumericIdAttributeName } from "@stll/docx-core";
|
|
4
4
|
//#region src/docx/streamingXmlParser.ts
|
|
5
|
+
const sourceRanges = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
/** Exact element source ranges, available only from the opt-in source-range reader. */
|
|
7
|
+
const getXmlSourceRange = (element) => sourceRanges.get(element);
|
|
5
8
|
const BUILT_IN_ENTITIES = {
|
|
6
9
|
amp: "&",
|
|
7
10
|
apos: "'",
|
|
@@ -14,6 +17,7 @@ const parseStreamingXmlInternal = (options) => {
|
|
|
14
17
|
const visitOpenTag = options.visitOpenTag;
|
|
15
18
|
let spanMode = "none";
|
|
16
19
|
if (visitOpenTag !== void 0) spanMode = options.mode === "tree" ? "identities" : "all";
|
|
20
|
+
if (options.visitElement !== void 0) spanMode = "all";
|
|
17
21
|
const openTagOptions = {
|
|
18
22
|
xml,
|
|
19
23
|
start: 0,
|
|
@@ -67,6 +71,10 @@ const parseStreamingXmlInternal = (options) => {
|
|
|
67
71
|
const name = xml.slice(open + 2, close).trim();
|
|
68
72
|
const frame = stack.pop();
|
|
69
73
|
if (!frame || frame.name !== name) return { status: "unsupported" };
|
|
74
|
+
if (frame.start !== void 0) sourceRanges.set(frame.element, {
|
|
75
|
+
start: frame.start,
|
|
76
|
+
end: close + 1
|
|
77
|
+
});
|
|
70
78
|
cursor = close + 1;
|
|
71
79
|
mergeAdjacentText = false;
|
|
72
80
|
continue;
|
|
@@ -79,6 +87,12 @@ const parseStreamingXmlInternal = (options) => {
|
|
|
79
87
|
const scope = parent?.namespaceScope ?? inheritedNamespaceScope;
|
|
80
88
|
if (options.mode === "attributes" && options.retainAttribute !== void 0 && parsedTag.element.attributes === void 0) parsedTag.element.namespaceScope = scope;
|
|
81
89
|
else attachXmlNamespaceContext(parsedTag.element, scope);
|
|
90
|
+
options.visitElement?.({
|
|
91
|
+
element: parsedTag.element,
|
|
92
|
+
attributeValueSpans: parsedTag.attributeValueSpans ?? /* @__PURE__ */ new Map(),
|
|
93
|
+
nameEnd: parsedTag.nameEnd,
|
|
94
|
+
parent
|
|
95
|
+
});
|
|
82
96
|
const rewritten = (options.mode === "tree" ? parsedTag.attributeValueSpans !== void 0 : options.retainAttribute === void 0 || parsedTag.element.attributes !== void 0) ? visitOpenTag?.(parsedTag.element, parsedTag.attributeValueSpans ?? /* @__PURE__ */ new Map()) : null;
|
|
83
97
|
if (rewritten) for (const [attributeName, value] of rewritten) {
|
|
84
98
|
const span = parsedTag.attributeValueSpans?.get(attributeName);
|
|
@@ -91,11 +105,18 @@ const parseStreamingXmlInternal = (options) => {
|
|
|
91
105
|
if (options.mode === "tree") appendElement(parent ?? root, parsedTag.element);
|
|
92
106
|
if (!parsedTag.selfClosing) {
|
|
93
107
|
if (stack.length >= FOLIO_XML_RESOURCE_LIMITS.maxDepth) return { status: "unsupported" };
|
|
94
|
-
stack.push({
|
|
108
|
+
stack.push(options.mode === "tree" && options.sourceRanges === "tracked" ? {
|
|
109
|
+
element: parsedTag.element,
|
|
110
|
+
name: parsedTag.name,
|
|
111
|
+
start: open
|
|
112
|
+
} : {
|
|
95
113
|
element: parsedTag.element,
|
|
96
114
|
name: parsedTag.name
|
|
97
115
|
});
|
|
98
|
-
}
|
|
116
|
+
} else if (options.mode === "tree" && options.sourceRanges === "tracked") sourceRanges.set(parsedTag.element, {
|
|
117
|
+
start: open,
|
|
118
|
+
end: close + 1
|
|
119
|
+
});
|
|
99
120
|
cursor = close + 1;
|
|
100
121
|
mergeAdjacentText = false;
|
|
101
122
|
}
|
|
@@ -121,6 +142,19 @@ const parseStreamingXml = (xml, inheritedNamespaceScope = EMPTY_NAMESPACE_SCOPE)
|
|
|
121
142
|
value: parsed.value
|
|
122
143
|
} : { status: "unsupported" };
|
|
123
144
|
};
|
|
145
|
+
/** Retain source spans for every element without changing the parsed namespace tree. */
|
|
146
|
+
const parseStreamingXmlWithSourceRanges = (xml, inheritedNamespaceScope = EMPTY_NAMESPACE_SCOPE) => {
|
|
147
|
+
const parsed = parseStreamingXmlInternal({
|
|
148
|
+
xml,
|
|
149
|
+
mode: "tree",
|
|
150
|
+
inheritedNamespaceScope,
|
|
151
|
+
sourceRanges: "tracked"
|
|
152
|
+
});
|
|
153
|
+
return parsed.status === "parsed" ? {
|
|
154
|
+
status: "parsed",
|
|
155
|
+
value: parsed.value
|
|
156
|
+
} : { status: "unsupported" };
|
|
157
|
+
};
|
|
124
158
|
/** Retain the body tree while collecting identities for import repair. */
|
|
125
159
|
const parseStreamingXmlWithIdentityVisitor = (xml, visitOpenTag) => {
|
|
126
160
|
const parsed = parseStreamingXmlInternal({
|
|
@@ -170,12 +204,23 @@ const scanStreamingXmlNumericIdAttributes = (xml, visitOpenTag) => {
|
|
|
170
204
|
});
|
|
171
205
|
return parsed.status === "parsed" ? { status: "scanned" } : parsed;
|
|
172
206
|
};
|
|
207
|
+
/** Visit namespace-resolved start tags and source spans without building a tree. */
|
|
208
|
+
const scanStreamingXmlElements = (xml, visitElement) => {
|
|
209
|
+
const parsed = parseStreamingXmlInternal({
|
|
210
|
+
xml,
|
|
211
|
+
mode: "attributes",
|
|
212
|
+
visitOpenTag: () => null,
|
|
213
|
+
visitElement
|
|
214
|
+
});
|
|
215
|
+
return parsed.status === "parsed" ? { status: "scanned" } : parsed;
|
|
216
|
+
};
|
|
173
217
|
const parseOpenTag = ({ xml, start, close, spanMode, retainAttribute }) => {
|
|
174
218
|
let cursor = skipWhitespace(xml, start, close);
|
|
175
219
|
const nameStart = cursor;
|
|
176
220
|
cursor = scanName(xml, cursor, close);
|
|
177
221
|
if (cursor === nameStart) return { status: "unsupported" };
|
|
178
222
|
const name = xml.slice(nameStart, cursor);
|
|
223
|
+
const nameEnd = cursor;
|
|
179
224
|
if (isUnsafePropertyName(name)) return { status: "unsupported" };
|
|
180
225
|
let attributes;
|
|
181
226
|
let attributeValueSpans;
|
|
@@ -232,6 +277,7 @@ const parseOpenTag = ({ xml, start, close, spanMode, retainAttribute }) => {
|
|
|
232
277
|
status: "parsed",
|
|
233
278
|
element,
|
|
234
279
|
name,
|
|
280
|
+
nameEnd,
|
|
235
281
|
selfClosing,
|
|
236
282
|
attributeValueSpans
|
|
237
283
|
};
|
|
@@ -358,4 +404,4 @@ const isUnsafePropertyName = (name) => {
|
|
|
358
404
|
}
|
|
359
405
|
};
|
|
360
406
|
//#endregion
|
|
361
|
-
export { parseStreamingXml, parseStreamingXmlWithIdentityVisitor, rewriteStreamingXmlDecimalAttributes, scanStreamingXmlNumericIdAttributes };
|
|
407
|
+
export { getXmlSourceRange, parseStreamingXml, parseStreamingXmlWithIdentityVisitor, parseStreamingXmlWithSourceRanges, rewriteStreamingXmlDecimalAttributes, scanStreamingXmlElements, scanStreamingXmlNumericIdAttributes };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
2
2
|
import { parseDocumentBody } from "./documentParser.js";
|
|
3
3
|
import { paraIdAttribute } from "./paraIdAttribute.js";
|
|
4
|
-
import { spliceXml } from "./selectiveXmlPatch.js";
|
|
5
|
-
import {
|
|
4
|
+
import { spliceSupportsRootNamespaces, spliceXml } from "./selectiveXmlPatch.js";
|
|
5
|
+
import { materializeReplayFragment } from "./storyBlockReplay.js";
|
|
6
6
|
import { NAMESPACES, WORDPROCESSINGML_NAMESPACE_URIS, getChildElements, getLocalName, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
|
|
7
7
|
//#region src/docx/structuralXmlPatch.ts
|
|
8
8
|
/** Conservative body-paragraph splices; source offsets never come from reserialization. */
|
|
@@ -111,21 +111,6 @@ const paragraphIds = (root) => {
|
|
|
111
111
|
}
|
|
112
112
|
return ids;
|
|
113
113
|
};
|
|
114
|
-
/** Bind fragment prefixes locally: the source root may use entirely different aliases. */
|
|
115
|
-
const paragraphFragment = ({ xml, block, bindings }) => {
|
|
116
|
-
const fragment = xml.slice(block.start, block.end);
|
|
117
|
-
const openEnd = fragment.indexOf(">");
|
|
118
|
-
const name = block.element.name ?? "w:p";
|
|
119
|
-
const selfClosing = fragment[openEnd - 1] === "/";
|
|
120
|
-
return serializePartElement({
|
|
121
|
-
partPath: "word/document.xml",
|
|
122
|
-
rootName: name,
|
|
123
|
-
rootAttributes: fragment.slice(name.length + 1, selfClosing ? openEnd - 1 : openEnd).trim(),
|
|
124
|
-
baselinePrefixes: [],
|
|
125
|
-
sourceBindings: bindings,
|
|
126
|
-
body: selfClosing ? "" : fragment.slice(openEnd + 1, fragment.lastIndexOf("</"))
|
|
127
|
-
});
|
|
128
|
-
};
|
|
129
114
|
/**
|
|
130
115
|
* Insert/delete direct body paragraphs between surviving paragraph/table anchors.
|
|
131
116
|
* Tables are opaque barriers: their modeled content and order must stay identical.
|
|
@@ -168,11 +153,11 @@ const buildStructuralDocumentPatch = ({ originalXml, serializedXml, changedIds }
|
|
|
168
153
|
const survivingBefore = [...before.keys()].filter((key) => after.has(key));
|
|
169
154
|
const survivingAfter = [...after.keys()].filter((key) => before.has(key));
|
|
170
155
|
if (canonicalJson(survivingBefore) !== canonicalJson(survivingAfter)) return null;
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
156
|
+
const fragmentFor = (block) => materializeReplayFragment({
|
|
157
|
+
xml: serializedXml.slice(block.start, block.end),
|
|
158
|
+
element: block.element,
|
|
159
|
+
sourceNamespace: getNamespaceUri(source.root) ?? "",
|
|
160
|
+
generatedRoot: current.root
|
|
176
161
|
});
|
|
177
162
|
const splices = [];
|
|
178
163
|
for (const [key, block] of before) if (!after.has(key)) splices.push({
|
|
@@ -186,11 +171,14 @@ const buildStructuralDocumentPatch = ({ originalXml, serializedXml, changedIds }
|
|
|
186
171
|
if (!original) {
|
|
187
172
|
const id = paraIdAttribute(block.element)?.toUpperCase();
|
|
188
173
|
if (!id || allSourceIds.has(id)) return null;
|
|
189
|
-
|
|
174
|
+
const fragment = fragmentFor(block);
|
|
175
|
+
if (fragment === null) return null;
|
|
176
|
+
pending.push(fragment);
|
|
190
177
|
continue;
|
|
191
178
|
}
|
|
192
179
|
const id = paraIdAttribute(block.element)?.toUpperCase();
|
|
193
180
|
const replacement = id !== void 0 && changed.has(id) ? fragmentFor(block) : originalXml.slice(original.start, original.end);
|
|
181
|
+
if (replacement === null) return null;
|
|
194
182
|
if (pending.length > 0 || replacement !== originalXml.slice(original.start, original.end)) splices.push({
|
|
195
183
|
start: original.start,
|
|
196
184
|
end: original.end,
|
|
@@ -203,6 +191,13 @@ const buildStructuralDocumentPatch = ({ originalXml, serializedXml, changedIds }
|
|
|
203
191
|
end: source.bodyEnd,
|
|
204
192
|
newXml: pending.join("")
|
|
205
193
|
});
|
|
194
|
+
if (!spliceSupportsRootNamespaces({
|
|
195
|
+
originalXml,
|
|
196
|
+
serializedXml,
|
|
197
|
+
fragments: splices.map(({ newXml }) => newXml).filter(Boolean),
|
|
198
|
+
originalRoot: source.root,
|
|
199
|
+
serializedRoot: current.root
|
|
200
|
+
})) return null;
|
|
206
201
|
return spliceXml(originalXml, splices);
|
|
207
202
|
};
|
|
208
203
|
//#endregion
|
|
@@ -8,6 +8,10 @@ type ParsedStylesPackage = {
|
|
|
8
8
|
styleDefinitions: document_d_exports.StyleDefinitions;
|
|
9
9
|
styles: StyleMap;
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolve style inheritance chain
|
|
13
|
+
*/
|
|
14
|
+
declare function resolveStyleInheritance(style: document_d_exports.Style, styleMap: StyleMap, visited?: Set<string>): document_d_exports.Style;
|
|
11
15
|
/**
|
|
12
16
|
* Parse styles.xml content
|
|
13
17
|
*
|
|
@@ -46,4 +50,4 @@ declare function getDefaultCharacterStyle(styleMap: StyleMap): document_d_export
|
|
|
46
50
|
*/
|
|
47
51
|
declare function getStylesByType(styleMap: StyleMap, type: document_d_exports.StyleType): document_d_exports.Style[];
|
|
48
52
|
//#endregion
|
|
49
|
-
export { ParsedStylesPackage, StyleMap, getDefaultCharacterStyle, getDefaultParagraphStyle, getResolvedStyle, getStylesByType, parseStyleDefinitions, parseStyles, parseStylesPackage };
|
|
53
|
+
export { ParsedStylesPackage, StyleMap, getDefaultCharacterStyle, getDefaultParagraphStyle, getResolvedStyle, getStylesByType, parseStyleDefinitions, parseStyles, parseStylesPackage, resolveStyleInheritance };
|
package/dist/docx/styleParser.js
CHANGED
|
@@ -554,4 +554,4 @@ function getStylesByType(styleMap, type) {
|
|
|
554
554
|
return result;
|
|
555
555
|
}
|
|
556
556
|
//#endregion
|
|
557
|
-
export { getDefaultCharacterStyle, getDefaultParagraphStyle, getResolvedStyle, getStylesByType, parseStyleDefinitions, parseStyles, parseStylesPackage };
|
|
557
|
+
export { getDefaultCharacterStyle, getDefaultParagraphStyle, getResolvedStyle, getStylesByType, parseStyleDefinitions, parseStyles, parseStylesPackage, resolveStyleInheritance };
|
|
@@ -342,13 +342,6 @@ declare function isCellMergeStart(cell: document_d_exports.TableCell): boolean;
|
|
|
342
342
|
* @returns true if cell spans multiple columns
|
|
343
343
|
*/
|
|
344
344
|
declare function isCellHorizontallyMerged(cell: document_d_exports.TableCell): boolean;
|
|
345
|
-
/**
|
|
346
|
-
* Get the plain text content of a table
|
|
347
|
-
*
|
|
348
|
-
* @param table - The table to extract text from
|
|
349
|
-
* @returns Plain text content
|
|
350
|
-
*/
|
|
351
|
-
declare function getTableText(table: document_d_exports.Table): string;
|
|
352
345
|
/**
|
|
353
346
|
* Check if table has header row
|
|
354
347
|
*
|
|
@@ -371,4 +364,4 @@ declare function getHeaderRows(table: document_d_exports.Table): document_d_expo
|
|
|
371
364
|
*/
|
|
372
365
|
declare function isFloatingTable(table: document_d_exports.Table): boolean;
|
|
373
366
|
//#endregion
|
|
374
|
-
export { CELL_CONTENT_HANDLERS, MAX_TABLE_COLUMNS, ROW_CONTENT_HANDLERS, TABLE_CONTENT_HANDLERS, getHeaderRows, getTableColumnCount, getTableRowCount,
|
|
367
|
+
export { CELL_CONTENT_HANDLERS, MAX_TABLE_COLUMNS, ROW_CONTENT_HANDLERS, TABLE_CONTENT_HANDLERS, getHeaderRows, getTableColumnCount, getTableRowCount, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, isTableCellMergeRevisionContinuation, isTableCellMergeRevisionValue, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTablePropertyExceptions, parseTableRow, parseTableRowProperties };
|
package/dist/docx/tableParser.js
CHANGED
|
@@ -1406,33 +1406,6 @@ function isCellHorizontallyMerged(cell) {
|
|
|
1406
1406
|
return (cell.formatting?.gridSpan ?? 1) > 1;
|
|
1407
1407
|
}
|
|
1408
1408
|
/**
|
|
1409
|
-
* Get the plain text content of a table
|
|
1410
|
-
*
|
|
1411
|
-
* @param table - The table to extract text from
|
|
1412
|
-
* @returns Plain text content
|
|
1413
|
-
*/
|
|
1414
|
-
function getTableText(table) {
|
|
1415
|
-
const rows = [];
|
|
1416
|
-
for (const row of table.rows) {
|
|
1417
|
-
const cells = [];
|
|
1418
|
-
for (const cell of row.cells) {
|
|
1419
|
-
const cellText = cell.content.filter((c) => c.type === "paragraph").map((p) => getParagraphText(p)).join("\n");
|
|
1420
|
-
cells.push(cellText);
|
|
1421
|
-
}
|
|
1422
|
-
rows.push(cells.join(" "));
|
|
1423
|
-
}
|
|
1424
|
-
return rows.join("\n");
|
|
1425
|
-
}
|
|
1426
|
-
/**
|
|
1427
|
-
* Helper to get paragraph text (simplified)
|
|
1428
|
-
*/
|
|
1429
|
-
function getParagraphText(para) {
|
|
1430
|
-
return para.content.filter((c) => "content" in c).flatMap((run) => {
|
|
1431
|
-
if (!("content" in run) || !Array.isArray(run.content)) return [];
|
|
1432
|
-
return run.content.filter((c) => typeof c === "object" && c !== null && "type" in c && c.type === "text" && "text" in c).map((c) => c.text);
|
|
1433
|
-
}).join("");
|
|
1434
|
-
}
|
|
1435
|
-
/**
|
|
1436
1409
|
* Check if table has header row
|
|
1437
1410
|
*
|
|
1438
1411
|
* @param table - The table to check
|
|
@@ -1461,4 +1434,4 @@ function isFloatingTable(table) {
|
|
|
1461
1434
|
return table.formatting?.floating !== void 0;
|
|
1462
1435
|
}
|
|
1463
1436
|
//#endregion
|
|
1464
|
-
export { CELL_CONTENT_HANDLERS, MAX_TABLE_COLUMNS, ROW_CONTENT_HANDLERS, TABLE_CONTENT_HANDLERS, getHeaderRows, getTableColumnCount, getTableRowCount,
|
|
1437
|
+
export { CELL_CONTENT_HANDLERS, MAX_TABLE_COLUMNS, ROW_CONTENT_HANDLERS, TABLE_CONTENT_HANDLERS, getHeaderRows, getTableColumnCount, getTableRowCount, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, isTableCellMergeRevisionContinuation, isTableCellMergeRevisionValue, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTablePropertyExceptions, parseTableRow, parseTableRowProperties };
|
|
@@ -103,10 +103,6 @@ declare function hasTextBoxOutline(textBox: document_d_exports.TextBox): boolean
|
|
|
103
103
|
* Check if text box has content
|
|
104
104
|
*/
|
|
105
105
|
declare function hasTextBoxContent(textBox: document_d_exports.TextBox): boolean;
|
|
106
|
-
/**
|
|
107
|
-
* Get plain text from text box (helper for search/indexing)
|
|
108
|
-
*/
|
|
109
|
-
declare function getTextBoxText(textBox: document_d_exports.TextBox): string;
|
|
110
106
|
/**
|
|
111
107
|
* Resolve fill color to CSS color string
|
|
112
108
|
*/
|
|
@@ -151,4 +147,4 @@ type ScanRunForTextBoxDrawingsOptions = {
|
|
|
151
147
|
};
|
|
152
148
|
declare const scanRunForTextBoxDrawings: ({ xmlRun, claimedByRunParser }: ScanRunForTextBoxDrawingsOptions) => TextBoxRunScan;
|
|
153
149
|
//#endregion
|
|
154
|
-
export { ParagraphParserFn, ScanRunForTextBoxDrawingsOptions, TableParserFn, TextBoxDrawing, TextBoxRunScan, extractTextBoxContentElements, getTextBoxContentElement, getTextBoxDimensionsPx, getTextBoxHeightPx, getTextBoxMarginsPx, getTextBoxOutlineWidthPx,
|
|
150
|
+
export { ParagraphParserFn, ScanRunForTextBoxDrawingsOptions, TableParserFn, TextBoxDrawing, TextBoxRunScan, extractTextBoxContentElements, getTextBoxContentElement, getTextBoxDimensionsPx, getTextBoxHeightPx, getTextBoxMarginsPx, getTextBoxOutlineWidthPx, getTextBoxWidthPx, hasTextBoxContent, hasTextBoxFill, hasTextBoxOutline, isFloatingTextBox, isShapeTextBox, isTextBoxDrawing, parseTextBox, parseTextBoxContent, parseTextBoxFromShape, resolveTextBoxFillColor, resolveTextBoxOutlineColor, scanRunForTextBoxDrawings };
|
|
@@ -285,25 +285,6 @@ function hasTextBoxContent(textBox) {
|
|
|
285
285
|
return textBox.content.length > 0;
|
|
286
286
|
}
|
|
287
287
|
/**
|
|
288
|
-
* Get plain text from text box (helper for search/indexing)
|
|
289
|
-
*/
|
|
290
|
-
function getTextBoxText(textBox) {
|
|
291
|
-
return textBox.content.map(getTextBoxBlockText).join("\n");
|
|
292
|
-
}
|
|
293
|
-
const getTextBoxBlockText = (block) => {
|
|
294
|
-
if (block.type === "paragraph") {
|
|
295
|
-
const runTexts = [];
|
|
296
|
-
for (const item of block.content) {
|
|
297
|
-
if (item.type !== "run") continue;
|
|
298
|
-
for (const content of item.content) if (content.type === "text") runTexts.push(content.text);
|
|
299
|
-
}
|
|
300
|
-
return runTexts.join("");
|
|
301
|
-
}
|
|
302
|
-
if (block.type === "table") return block.rows.map((row) => row.cells.map((cell) => cell.content.map(getTextBoxBlockText).join("\n")).join(" ")).join("\n");
|
|
303
|
-
if (block.type !== "blockSdt" && block.type !== "blockCustomXml") return "";
|
|
304
|
-
return block.content.map(getTextBoxBlockText).join("\n");
|
|
305
|
-
};
|
|
306
|
-
/**
|
|
307
288
|
* Resolve fill color to CSS color string
|
|
308
289
|
*/
|
|
309
290
|
function resolveTextBoxFillColor(textBox) {
|
|
@@ -380,4 +361,4 @@ const scanRunForTextBoxDrawings = ({ xmlRun, claimedByRunParser }) => {
|
|
|
380
361
|
};
|
|
381
362
|
};
|
|
382
363
|
//#endregion
|
|
383
|
-
export { extractTextBoxContentElements, getTextBoxContentElement, getTextBoxDimensionsPx, getTextBoxHeightPx, getTextBoxMarginsPx, getTextBoxOutlineWidthPx,
|
|
364
|
+
export { extractTextBoxContentElements, getTextBoxContentElement, getTextBoxDimensionsPx, getTextBoxHeightPx, getTextBoxMarginsPx, getTextBoxOutlineWidthPx, getTextBoxWidthPx, hasTextBoxContent, hasTextBoxFill, hasTextBoxOutline, isFloatingTextBox, isShapeTextBox, isTextBoxDrawing, parseTextBox, parseTextBoxContent, parseTextBoxFromShape, resolveTextBoxFillColor, resolveTextBoxOutlineColor, scanRunForTextBoxDrawings };
|
package/dist/docx/unzip.js
CHANGED
|
@@ -5,6 +5,7 @@ import { openDocxBuffer } from "./encryption/openEncryptedDocx.js";
|
|
|
5
5
|
import { RASTER_MIME_TYPES, detectRasterMimeType } from "./rasterMime.js";
|
|
6
6
|
import { decodeXmlBytes } from "./xmlEncoding.js";
|
|
7
7
|
import { FOLIO_XML_RESOURCE_LIMITS, assertXmlResourceLimits, createXmlPackageBudget } from "./xmlResourceLimits.js";
|
|
8
|
+
import { writeZipPart } from "@stll/docx-core/zip";
|
|
8
9
|
import JSZip from "jszip";
|
|
9
10
|
//#region src/docx/unzip.ts
|
|
10
11
|
/**
|
|
@@ -282,7 +283,11 @@ const replaceRawDocxXmlParts = async (content, parts) => {
|
|
|
282
283
|
lowerPath: path.toLowerCase(),
|
|
283
284
|
content: xmlContent
|
|
284
285
|
});
|
|
285
|
-
|
|
286
|
+
writeZipPart({
|
|
287
|
+
zip: content.originalZip,
|
|
288
|
+
path,
|
|
289
|
+
data: xmlContent
|
|
290
|
+
});
|
|
286
291
|
identitiesChanged = true;
|
|
287
292
|
}
|
|
288
293
|
if (identitiesChanged) content.originalBuffer = await content.originalZip.generateAsync({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
1
2
|
import { XmlElement, XmlNamespaceScope } from "./xmlParser.js";
|
|
2
3
|
//#region src/docx/verbatimCapture.d.ts
|
|
3
4
|
declare const UntranslatableStrictNamespaceError_base: import("better-result").TaggedErrorClass<"UntranslatableStrictNamespaceError">;
|
|
@@ -29,5 +30,6 @@ declare const isSafeCapturedXmlDocument: (xml: string) => boolean;
|
|
|
29
30
|
* must therefore depend on nothing but the element they are given.
|
|
30
31
|
*/
|
|
31
32
|
declare const createCapturedXmlSanitizer: (options: SanitizeCapturedXmlOptions) => ((xml: string | undefined) => string | null);
|
|
33
|
+
declare const captureSourceProfileXml: (element: XmlElement, conformance: document_d_exports.DocxConformanceClass | undefined) => string;
|
|
32
34
|
//#endregion
|
|
33
|
-
export { UntranslatableStrictNamespaceError, captureVerbatimXml, createCapturedXmlSanitizer, isSafeCapturedXmlDocument };
|
|
35
|
+
export { UntranslatableStrictNamespaceError, captureSourceProfileXml, captureVerbatimXml, createCapturedXmlSanitizer, isSafeCapturedXmlDocument };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { TRANSITIONAL_NAMESPACE_BY_STRICT_URI } from "./strictValueEncodings.gen.js";
|
|
2
2
|
import { NUMBERS_PER_PERCENT, isStrictNamespaceUri, percentageSpelling, toTransitionalNamespaceUri, transitionalSlotEncoding } from "./transitionalSpelling.js";
|
|
3
3
|
import { roundHalfAwayFromZero, universalMeasureAs } from "./universalMeasure.js";
|
|
4
|
-
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, cloneElement, elementToXml, getChildElements, getLocalName, getNamespacePrefix, parseXml } from "./xmlParser.js";
|
|
4
|
+
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, elementToXml, getAttributeByNamespaceUri, getChildElements, getLocalName, getNamespacePrefix, parseXml, resolveAttributeNamespaceUri } from "./xmlParser.js";
|
|
5
5
|
import { assertXmlResourceLimits } from "./xmlResourceLimits.js";
|
|
6
6
|
import { getDocxXmlSafetyIssue } from "./xmlSafety.js";
|
|
7
|
-
import { TaggedError } from "better-result";
|
|
7
|
+
import { TaggedError, panic } from "better-result";
|
|
8
|
+
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
8
9
|
//#region src/docx/verbatimCapture.ts
|
|
9
10
|
/**
|
|
10
11
|
* The one way to turn parsed markup into a string a rebuilt part replays.
|
|
@@ -75,14 +76,22 @@ const originOf = (element, inherited) => {
|
|
|
75
76
|
});
|
|
76
77
|
return TRANSITIONAL_URIS.has(uri) ? "transitional" : inherited;
|
|
77
78
|
};
|
|
78
|
-
|
|
79
|
+
/** A same-local-name extension attribute is not a slot in the element's vocabulary. */
|
|
80
|
+
const attributeSlotEncoding = (element, name) => {
|
|
81
|
+
if (getNamespacePrefix(name) !== null) {
|
|
82
|
+
const attributeUri = resolveAttributeNamespaceUri(element, name);
|
|
83
|
+
if (attributeUri === void 0 || element.namespaceUri === void 0 || toTransitionalNamespaceUri(attributeUri) !== toTransitionalNamespaceUri(element.namespaceUri)) return void 0;
|
|
84
|
+
}
|
|
85
|
+
return transitionalSlotEncoding(element.namespaceUri, getLocalName(element.name), getLocalName(name));
|
|
86
|
+
};
|
|
87
|
+
const convertAttributes = (element, namespaceUri, convertValues) => {
|
|
79
88
|
const attributes = element.attributes ?? {};
|
|
80
89
|
let converted;
|
|
81
90
|
for (const [name, raw] of Object.entries(attributes)) {
|
|
82
91
|
if (typeof raw !== "string") continue;
|
|
83
92
|
let next = raw;
|
|
84
93
|
if (name === "xmlns" || name.startsWith("xmlns:")) next = toTransitionalNamespaceUri(raw);
|
|
85
|
-
else if (convertValues) next = transitionalValue(raw, namespaceUri,
|
|
94
|
+
else if (convertValues) next = transitionalValue(raw, namespaceUri, attributeSlotEncoding(element, name));
|
|
86
95
|
if (next === raw) continue;
|
|
87
96
|
converted ??= { ...attributes };
|
|
88
97
|
converted[name] = next;
|
|
@@ -99,7 +108,7 @@ const toTransitional = (element, inherited) => {
|
|
|
99
108
|
const namespaceUri = element.namespaceUri === void 0 ? "" : toTransitionalNamespaceUri(element.namespaceUri);
|
|
100
109
|
const localName = getLocalName(element.name);
|
|
101
110
|
const textEncoding = transitionalSlotEncoding(element.namespaceUri, localName);
|
|
102
|
-
const attributes = element.attributes ? convertAttributes(element, namespaceUri,
|
|
111
|
+
const attributes = element.attributes ? convertAttributes(element, namespaceUri, origin === "strict") : void 0;
|
|
103
112
|
let elements;
|
|
104
113
|
for (const [index, child] of (element.elements ?? []).entries()) {
|
|
105
114
|
const next = origin === "strict" && child.type === "text" && typeof child.text === "string" ? childWithValue(child, transitionalValue(child.text, namespaceUri, textEncoding)) : toTransitional(child, origin);
|
|
@@ -363,5 +372,39 @@ const createCapturedXmlSanitizer = (options) => {
|
|
|
363
372
|
return sanitized;
|
|
364
373
|
};
|
|
365
374
|
};
|
|
375
|
+
const STRICT_BY_TRANSITIONAL = new Map([...TRANSITIONAL_NAMESPACE_BY_STRICT_URI].map(([strict, transitional]) => [transitional, strict]));
|
|
376
|
+
const strictPercentage = (value, unit) => /^-?\d+(?:\.\d+)?$/u.test(value) ? `${Number(value) / NUMBERS_PER_PERCENT[unit]}%` : value;
|
|
377
|
+
/** Translate generated markup by namespace/slot, never by a user-text replacement. */
|
|
378
|
+
const strictElement = (element) => {
|
|
379
|
+
const localName = getLocalName(element.name);
|
|
380
|
+
for (const [name, value] of Object.entries(element.attributes ?? {})) {
|
|
381
|
+
if (typeof value !== "string") continue;
|
|
382
|
+
if (name === "xmlns" || name.startsWith("xmlns:")) {
|
|
383
|
+
element.attributes[name] = STRICT_BY_TRANSITIONAL.get(value) ?? value;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (localName === "graphicData" && toTransitionalNamespaceUri(element.namespaceUri ?? "") === NAMESPACES.a && name === "uri") {
|
|
387
|
+
element.attributes[name] = STRICT_BY_TRANSITIONAL.get(value) ?? value;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
const encoding = attributeSlotEncoding(element, name);
|
|
391
|
+
if (encoding?.percent && (!encoding.measure || getAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, "type") === "pct")) element.attributes[name] = strictPercentage(value, encoding.percent);
|
|
392
|
+
}
|
|
393
|
+
const encoding = transitionalSlotEncoding(element.namespaceUri, localName);
|
|
394
|
+
for (const child of element.elements ?? []) if (child.type === "element") strictElement(child);
|
|
395
|
+
else if (child.type === "text" && typeof child.text === "string" && encoding?.percent) child.text = strictPercentage(child.text, encoding.percent);
|
|
396
|
+
};
|
|
397
|
+
/** Serialize a generated, scope-bound block in the source part's profile. */
|
|
398
|
+
const cloneSourceProfileTree = (element) => cloneElement(element, {
|
|
399
|
+
...element.attributes === void 0 ? {} : { attributes: { ...element.attributes } },
|
|
400
|
+
...element.elements === void 0 ? {} : { elements: element.elements.map(cloneSourceProfileTree) }
|
|
401
|
+
});
|
|
402
|
+
const captureSourceProfileXml = (element, conformance) => {
|
|
403
|
+
const owned = cloneSourceProfileTree(element);
|
|
404
|
+
if (conformance === DOCX_CONFORMANCE_CLASSES.STRICT) strictElement(owned);
|
|
405
|
+
const xml = elementToXml(owned);
|
|
406
|
+
if (!isSafeCapturedXmlDocument(xml)) panic("Generated source-profile markup is unsafe.");
|
|
407
|
+
return xml;
|
|
408
|
+
};
|
|
366
409
|
//#endregion
|
|
367
|
-
export { UntranslatableStrictNamespaceError, captureVerbatimXml, createCapturedXmlSanitizer, isSafeCapturedXmlDocument };
|
|
410
|
+
export { UntranslatableStrictNamespaceError, captureSourceProfileXml, captureVerbatimXml, createCapturedXmlSanitizer, isSafeCapturedXmlDocument };
|