@stll/folio-core 0.59.0 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -1
- package/dist/ai-edits/apply.js +139 -32
- package/dist/ai-edits/headless.d.ts +3 -0
- package/dist/ai-edits/headless.js +57 -63
- package/dist/ai-edits/note-story-inventory.d.ts +7 -0
- package/dist/ai-edits/note-story-inventory.js +11 -0
- package/dist/ai-edits/read.js +16 -9
- package/dist/ai-edits/revisionStretches.js +52 -1
- package/dist/ai-edits/table-row-column-mutations.js +6 -1
- package/dist/compare/reproducible-package.js +2 -1
- package/dist/compare/verification.js +1 -0
- package/dist/compat/eigenpal.d.ts +4 -2
- package/dist/compat/eigenpal.js +2 -2
- package/dist/controller/canonicalClipboard.js +2 -1
- package/dist/controller/canonicalListRendering.d.ts +4 -6
- package/dist/controller/canonicalListRendering.js +3 -157
- package/dist/controller/canonicalSession.js +3 -2
- package/dist/controller/canonicalStructure.js +10 -7
- package/dist/controller/fontReadiness.js +1 -1
- package/dist/controller/headerFooterEditorManager.d.ts +1 -0
- package/dist/controller/headerFooterEditorManager.js +11 -0
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +3 -1
- package/dist/controller/layoutPipeline.d.ts +3 -1
- package/dist/controller/layoutPipeline.js +19 -4
- package/dist/controller/layoutSession.d.ts +4 -1
- package/dist/display-list/build/fontTable.js +7 -5
- package/dist/display-list/build/furniture.d.ts +1 -0
- package/dist/display-list/build/furniture.js +1 -0
- package/dist/display-list/build/imagePrimitives.js +3 -6
- package/dist/display-list/build/watermarkPrimitives.d.ts +2 -1
- package/dist/display-list/build/watermarkPrimitives.js +9 -3
- package/dist/display-list/editor/pageRenderer.js +1 -0
- package/dist/docx/bookmarkIdNormalization.d.ts +10 -0
- package/dist/docx/bookmarkIdNormalization.js +100 -0
- package/dist/docx/bookmarkParser.js +4 -2
- package/dist/docx/canonicalStoryRepack.js +3 -2
- package/dist/docx/commentTextParagraph.d.ts +6 -0
- package/dist/docx/commentTextParagraph.js +15 -0
- package/dist/docx/conformance.js +6 -1
- package/dist/docx/diagramPreview.js +2 -1
- package/dist/docx/documentParser.d.ts +13 -1
- package/dist/docx/documentParser.js +1 -1
- package/dist/docx/encryption/compoundFile.d.ts +0 -8
- package/dist/docx/encryption/compoundFile.js +2 -1
- package/dist/docx/encryption/cryptoBytes.d.ts +2 -2
- package/dist/docx/encryption/cryptoBytes.js +3 -18
- package/dist/docx/encryption/encryptionInfo.d.ts +0 -5
- package/dist/docx/encryption/encryptionInfo.js +2 -1
- package/dist/docx/ensureParaIds.js +2 -1
- package/dist/docx/groupDrawingParser.js +6 -1
- package/dist/docx/importedIdCollisions.d.ts +136 -0
- package/dist/docx/importedIdCollisions.js +215 -0
- package/dist/docx/listModelNormalization.d.ts +10 -0
- package/dist/docx/listModelNormalization.js +166 -0
- package/dist/docx/metadataPrivacy.js +3 -2
- package/dist/docx/metafileRaster.js +2 -1
- package/dist/docx/numberingParser.js +2 -2
- package/dist/docx/packageParts.js +6 -5
- package/dist/docx/paragraphParser.js +6 -4
- package/dist/docx/paragraphPropertySource.js +1 -2
- package/dist/docx/parseContext.d.ts +2 -1
- package/dist/docx/parseContext.js +1 -0
- package/dist/docx/parseWarningMessage.js +1 -0
- package/dist/docx/parser.js +10 -5
- package/dist/docx/preservedRunContent.js +11 -2
- package/dist/docx/relsParser.js +1 -1
- package/dist/docx/removeHeaderFooterParts.js +8 -7
- package/dist/docx/replyToComment.js +3 -13
- package/dist/docx/rezip.js +90 -90
- package/dist/docx/runParser.js +12 -6
- package/dist/docx/runPropertyPresence.d.ts +11 -0
- package/dist/docx/runPropertyPresence.js +14 -0
- package/dist/docx/selectedXmlIdentityScan.d.ts +10 -0
- package/dist/docx/selectedXmlIdentityScan.js +36 -0
- package/dist/docx/selectiveSave.js +19 -17
- package/dist/docx/selectiveXmlPatch.js +44 -52
- package/dist/docx/serializer/commentSerializer.d.ts +3 -1
- package/dist/docx/serializer/commentSerializer.js +11 -2
- package/dist/docx/serializer/runSerializer.js +5 -4
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +1 -3
- package/dist/docx/serializer/trackedChangeAttributes.js +1 -11
- package/dist/docx/server/applyDocxXmlPatchProposal.js +2 -2
- package/dist/docx/server/boundedArchive.js +2 -1
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +2 -1
- package/dist/docx/server/inspectDocxPackage.js +5 -1
- package/dist/docx/server/validateDocxConformance.js +2 -1
- package/dist/docx/tableParser.js +7 -4
- package/dist/docx/tableRowPropertyPresence.d.ts +9 -0
- package/dist/docx/tableRowPropertyPresence.js +15 -0
- package/dist/docx/unzip.js +2 -1
- package/dist/docx/xmlEncoding.js +6 -5
- package/dist/fonts/embeddedFontFingerprint.d.ts +5 -0
- package/dist/fonts/embeddedFontFingerprint.js +18 -0
- package/dist/fonts/embeddedFonts.d.ts +1 -1
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/fonts/fontsourceFaces.js +2 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/fonts/sfnt/parse.js +6 -9
- package/dist/fonts/sfnt/subset.js +2 -1
- package/dist/fonts/sfnt/tables.js +2 -3
- package/dist/fonts/sfnt/woff.js +2 -1
- package/dist/headless-layout.js +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -2
- package/dist/internal/revisionResolutionInline.d.ts +2 -1
- package/dist/internal/revisionResolutionInline.js +22 -1
- package/dist/internal/wholeStoryRevisionResolution.js +24 -7
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +4 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +5 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +16 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +6 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +13 -14
- package/dist/layout-bridge/convert/paragraphConversion.js +8 -1
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +25 -1
- package/dist/layout-engine/measure/cache.js +39 -7
- package/dist/layout-engine/measure/crossRunWords.js +12 -2
- package/dist/layout-engine/measure/lineTypography.js +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +1 -0
- package/dist/layout-engine/measure/measureContainer.js +3 -4
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -9
- package/dist/layout-engine/measure/measureHelpers.js +21 -18
- package/dist/layout-engine/measure/measureParagraph.js +2 -0
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -0
- package/dist/layout-engine/types.d.ts +4 -1
- package/dist/layout-painter/renderPage.d.ts +1 -0
- package/dist/layout-painter/renderPage.js +11 -3
- package/dist/layout-painter/renderParagraph.js +13 -3
- package/dist/layout-painter/renderWatermark.d.ts +1 -0
- package/dist/layout-painter/renderWatermark.js +7 -3
- package/dist/managers/AutoSaveManager.js +2 -1
- package/dist/managers/EditorModeManager.d.ts +10 -1
- package/dist/managers/EditorModeManager.js +15 -1
- package/dist/managers/TableSelectionManager.d.ts +1 -1
- package/dist/managers/autoSaveCodec.js +2 -6
- package/dist/managers/editorShortcuts.d.ts +2 -1
- package/dist/managers/editorShortcuts.js +2 -1
- package/dist/managers/reviewDisplayMode.d.ts +8 -0
- package/dist/managers/reviewDisplayMode.js +15 -0
- package/dist/paged-layout/pageText.d.ts +11 -2
- package/dist/paged-layout/pageText.js +8 -3
- package/dist/pdf/fonts.js +5 -14
- package/dist/pdf/images.js +3 -2
- package/dist/pdf/objects.d.ts +0 -11
- package/dist/pdf/objects.js +7 -9
- package/dist/pdf/writePdf.js +2 -1
- package/dist/prosemirror/canonicalSelectionRange.d.ts +4 -1
- package/dist/prosemirror/canonicalSelectionRange.js +9 -3
- package/dist/prosemirror/commands/comments.js +51 -13
- package/dist/prosemirror/containerFinalParagraph.d.ts +8 -8
- package/dist/prosemirror/containerFinalParagraph.js +8 -8
- package/dist/prosemirror/conversion/fromProseDoc.js +9 -4
- package/dist/prosemirror/conversion/toProseDoc.js +4 -4
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +39 -3
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ImageDragExtension.js +4 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +9 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +6 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +11 -3
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +1 -1
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +16 -2
- package/dist/prosemirror/findReplaceSelection.d.ts +11 -1
- package/dist/prosemirror/findReplaceSelection.js +15 -1
- package/dist/prosemirror/markupViewProjection.d.ts +10 -1
- package/dist/prosemirror/markupViewProjection.js +21 -3
- package/dist/prosemirror/pluginKeyOwner.d.ts +13 -0
- package/dist/prosemirror/pluginKeyOwner.js +35 -0
- package/dist/prosemirror/plugins/aiCitationDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiCitationDecorations.js +16 -3
- package/dist/prosemirror/plugins/aiSuggestionDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiSuggestionDecorations.js +18 -3
- package/dist/prosemirror/plugins/anonymizationDecorations.d.ts +11 -11
- package/dist/prosemirror/plugins/anonymizationDecorations.js +23 -13
- package/dist/prosemirror/plugins/autocompleteSuggestion.d.ts +8 -2
- package/dist/prosemirror/plugins/autocompleteSuggestion.js +27 -5
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +8 -2
- package/dist/prosemirror/plugins/contentControlWidgets.js +4 -3
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +6 -5
- package/dist/prosemirror/plugins/createDocScanPlugin.js +1 -1
- package/dist/prosemirror/plugins/documentNumbering.js +5 -3
- package/dist/prosemirror/plugins/documentStyleState.d.ts +8 -2
- package/dist/prosemirror/plugins/documentStyleState.js +2 -2
- package/dist/prosemirror/plugins/documentStyles.js +1 -1
- package/dist/prosemirror/plugins/selectionTracker.d.ts +8 -2
- package/dist/prosemirror/plugins/selectionTracker.js +4 -3
- package/dist/prosemirror/plugins/suggestionMode.d.ts +8 -2
- package/dist/prosemirror/plugins/suggestionMode.js +4 -3
- package/dist/prosemirror/plugins/templateDirectives.d.ts +8 -2
- package/dist/prosemirror/plugins/templateDirectives.js +19 -4
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +8 -2
- package/dist/prosemirror/plugins/templatePreviewValues.js +27 -5
- package/dist/prosemirror/plugins/templateSlashMenu.d.ts +8 -2
- package/dist/prosemirror/plugins/templateSlashMenu.js +23 -5
- package/dist/prosemirror/plugins/transactionInvariants.js +29 -4
- package/dist/prosemirror/replacedAnnotations.d.ts +15 -1
- package/dist/prosemirror/replacedAnnotations.js +71 -12
- package/dist/prosemirror/runFormattingReconciliation.d.ts +3 -1
- package/dist/prosemirror/runFormattingReconciliation.js +10 -2
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +5 -7
- package/dist/prosemirror/runIdentityAcrossRevisions.js +66 -38
- package/dist/prosemirror/runPropertyChangeResolution.js +13 -1
- package/dist/utils/base64.d.ts +1 -31
- package/dist/utils/base64.js +19 -33
- package/dist/utils/clipboard.js +5 -4
- package/dist/utils/colorResolver.js +11 -2
- package/dist/utils/findReplace.d.ts +5 -0
- package/dist/utils/fontLoader.d.ts +2 -2
- package/dist/utils/fontLoader.js +2 -7
- package/dist/utils/fontResolver.d.ts +7 -3
- package/dist/utils/fontResolver.js +6 -8
- package/dist/utils/replaceText.js +21 -4
- package/dist/utils/sliceText.d.ts +2 -0
- package/dist/utils/sliceText.js +2 -0
- package/dist/utils/textEncoding.d.ts +2 -0
- package/dist/utils/textEncoding.js +2 -0
- package/dist/utils/tiffConverter.d.ts +0 -9
- package/dist/utils/tiffConverter.js +2 -4
- package/package.json +73 -31
|
@@ -42,7 +42,7 @@ const formatEndnoteTexts = (numbers, formatNumber) => {
|
|
|
42
42
|
for (const [id, displayNumber] of numbers) texts.set(id, formatNumber(displayNumber));
|
|
43
43
|
return texts;
|
|
44
44
|
};
|
|
45
|
-
const sameMeasureInputs = (left, right) => left.styles === right.styles && left.theme === right.theme && left.defaultTabStop === right.defaultTabStop && left.pageContentHeight === right.pageContentHeight && left.fontSet === right.fontSet && left.fontAlternates.size === right.fontAlternates.size && [...left.fontAlternates].every(([name, alternate]) => right.fontAlternates.get(name) === alternate) && left.markupView === right.markupView;
|
|
45
|
+
const sameMeasureInputs = (left, right) => left.embeddedFontFamilyMap === right.embeddedFontFamilyMap && left.styles === right.styles && left.theme === right.theme && left.defaultTabStop === right.defaultTabStop && left.pageContentHeight === right.pageContentHeight && left.fontSet === right.fontSet && left.fontAlternates.size === right.fontAlternates.size && [...left.fontAlternates].every(([name, alternate]) => right.fontAlternates.get(name) === alternate) && left.markupView === right.markupView && left.showCommentHighlights === right.showCommentHighlights;
|
|
46
46
|
/**
|
|
47
47
|
* The range an incremental pass re-measures, or `null` for a full measure: the
|
|
48
48
|
* committed measures must come from the same measure inputs, and the range is
|
|
@@ -136,7 +136,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
136
136
|
return result;
|
|
137
137
|
}
|
|
138
138
|
function runLayoutPipelineMeasured(deps, state, options) {
|
|
139
|
-
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, readFontSetSignature, buildFootnoteRenderItems, describeInvalidHighlightMarks, pageRenderer = PAGE_RENDERER.legacy, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES, emptyTemplatePreviewHidden: EMPTY_TEMPLATE_PREVIEW_HIDDEN, markupView } = deps;
|
|
139
|
+
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, readFontSetSignature, buildFootnoteRenderItems, describeInvalidHighlightMarks, pageRenderer = PAGE_RENDERER.legacy, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES, emptyTemplatePreviewHidden: EMPTY_TEMPLATE_PREVIEW_HIDDEN, markupView, showCommentHighlights = true } = deps;
|
|
140
140
|
let outcome = {};
|
|
141
141
|
let pendingArtifacts;
|
|
142
142
|
let pendingTemplatePreview;
|
|
@@ -154,16 +154,22 @@ function runLayoutPipelineMeasured(deps, state, options) {
|
|
|
154
154
|
let phaseStartedAt = performance.now();
|
|
155
155
|
const pageContentHeight = pageSize.h - margins.top - margins.bottom;
|
|
156
156
|
const fontAlternates = buildFontAlternates(document?.package.fontTable);
|
|
157
|
+
const displayCommentHighlights = showCommentHighlights && markupView !== "no-markup" && markupView !== "original";
|
|
158
|
+
const embeddedFontFamilies = session.embeddedFontFamilyMap ? { embeddedFontFamilyMap: session.embeddedFontFamilyMap } : {};
|
|
157
159
|
const measureInputs = {
|
|
160
|
+
...embeddedFontFamilies,
|
|
158
161
|
styles,
|
|
159
162
|
theme: _theme,
|
|
160
163
|
defaultTabStop,
|
|
161
164
|
pageContentHeight,
|
|
162
165
|
fontSet,
|
|
163
166
|
fontAlternates,
|
|
164
|
-
markupView
|
|
167
|
+
markupView,
|
|
168
|
+
showCommentHighlights: displayCommentHighlights
|
|
165
169
|
};
|
|
166
170
|
const flowOpts = {
|
|
171
|
+
showCommentHighlights: displayCommentHighlights,
|
|
172
|
+
...embeddedFontFamilies,
|
|
167
173
|
pageContentHeight,
|
|
168
174
|
fontAlternates,
|
|
169
175
|
...styles ? { styles } : {},
|
|
@@ -243,11 +249,14 @@ function runLayoutPipelineMeasured(deps, state, options) {
|
|
|
243
249
|
const buildHfOptions = (pageCount, fieldInputs) => {
|
|
244
250
|
const hfMeasureBlocks = (hfBlocks, hfWidth) => measureBlocks(hfBlocks, hfWidth, void 0, void 0, buildHeaderFooterFieldValues(hfBlocks, pageCount, hfClock, fieldInputs), { allowEndTabOverflow: true });
|
|
245
251
|
return {
|
|
252
|
+
markupView,
|
|
253
|
+
showCommentHighlights: displayCommentHighlights,
|
|
246
254
|
...flowOpts.styles ? { styles: flowOpts.styles } : {},
|
|
247
255
|
...document?.package.numbering === void 0 ? {} : { numbering: document.package.numbering },
|
|
248
256
|
...flowOpts.defaultSize === void 0 ? {} : { defaultSize: flowOpts.defaultSize },
|
|
249
257
|
..._theme !== void 0 ? { theme: _theme } : {},
|
|
250
258
|
fontAlternates,
|
|
259
|
+
...embeddedFontFamilies,
|
|
251
260
|
measureBlocks: hfMeasureBlocks,
|
|
252
261
|
...defaultTabStop !== void 0 ? { defaultTabStopTwips: defaultTabStop } : {},
|
|
253
262
|
...flowOpts.lineBreakRules ? { lineBreakRules: flowOpts.lineBreakRules } : {},
|
|
@@ -374,12 +383,17 @@ function runLayoutPipelineMeasured(deps, state, options) {
|
|
|
374
383
|
outcome.measures = newMeasures;
|
|
375
384
|
recordPhaseDuration("measure-blocks", phaseStartedAt);
|
|
376
385
|
const buildNoteOptions = () => {
|
|
377
|
-
const noteOptions = {
|
|
386
|
+
const noteOptions = {
|
|
387
|
+
measureBlocks,
|
|
388
|
+
showCommentHighlights: displayCommentHighlights,
|
|
389
|
+
markupView
|
|
390
|
+
};
|
|
378
391
|
if (flowOpts.styles) noteOptions.styles = flowOpts.styles;
|
|
379
392
|
if (flowOpts.defaultSize !== void 0) noteOptions.defaultSize = flowOpts.defaultSize;
|
|
380
393
|
if (_theme !== void 0) noteOptions.theme = _theme;
|
|
381
394
|
if (document?.package.numbering !== void 0) noteOptions.numbering = document.package.numbering;
|
|
382
395
|
noteOptions.fontAlternates = fontAlternates;
|
|
396
|
+
if (session.embeddedFontFamilyMap) noteOptions.embeddedFontFamilyMap = session.embeddedFontFamilyMap;
|
|
383
397
|
if (defaultTabStop !== void 0) noteOptions.defaultTabStopTwips = defaultTabStop;
|
|
384
398
|
if (flowOpts.lineBreakRules) noteOptions.lineBreakRules = flowOpts.lineBreakRules;
|
|
385
399
|
if (flowOpts.justificationCompatibility) noteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
|
|
@@ -579,6 +593,7 @@ function runLayoutPipelineMeasured(deps, state, options) {
|
|
|
579
593
|
outcome.blockLookup = blockLookup;
|
|
580
594
|
const footnotesByPage = hasFootnotes ? buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, document) : void 0;
|
|
581
595
|
const renderOpts = {
|
|
596
|
+
...embeddedFontFamilies,
|
|
582
597
|
pageGap,
|
|
583
598
|
showShadow: true,
|
|
584
599
|
blockLookup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { TemplatePreviewEntry, TemplatePreviewHiddenRange, TemplatePreviewValues } from "../prosemirror/plugins/templatePreviewValues.js";
|
|
3
|
-
import { FlowBlock, Measure } from "../layout-engine/types.js";
|
|
4
3
|
import { DisplayMode } from "../managers/EditorModeManager.js";
|
|
4
|
+
import { FlowBlock, Measure } from "../layout-engine/types.js";
|
|
5
5
|
import { FontAlternates } from "../fonts/fontAlternates.js";
|
|
6
6
|
import { EditorState } from "prosemirror-state";
|
|
7
7
|
//#region src/controller/layoutSession.d.ts
|
|
@@ -23,6 +23,7 @@ type LayoutTemplatePreview = {
|
|
|
23
23
|
* that changes how text measures brings new styles or font alternates.
|
|
24
24
|
*/
|
|
25
25
|
type LayoutMeasureInputs = {
|
|
26
|
+
embeddedFontFamilyMap?: ReadonlyMap<string, string>;
|
|
26
27
|
styles: document_d_exports.StyleDefinitions | null | undefined;
|
|
27
28
|
theme: document_d_exports.Theme | null | undefined;
|
|
28
29
|
defaultTabStop: number | undefined;
|
|
@@ -35,8 +36,10 @@ type LayoutMeasureInputs = {
|
|
|
35
36
|
fontAlternates: FontAlternates;
|
|
36
37
|
/** The review view: each lays out different text, so a measure is reusable only within one. */
|
|
37
38
|
markupView: DisplayMode;
|
|
39
|
+
showCommentHighlights?: boolean;
|
|
38
40
|
};
|
|
39
41
|
type LayoutSession = {
|
|
42
|
+
embeddedFontFamilyMap?: ReadonlyMap<string, string>;
|
|
40
43
|
artifacts: LayoutArtifacts | null;
|
|
41
44
|
lastEditorState: EditorState | null;
|
|
42
45
|
lastPmDoc: EditorState["doc"] | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ptToPx } from "../../layout-engine/measure/measureHelpers.js";
|
|
2
2
|
import { getFontMetrics } from "../../layout-engine/measure/measureProvider.js";
|
|
3
|
-
import { resolveFontFamily } from "../../utils/fontResolver.js";
|
|
3
|
+
import { parseFontFamilyList, resolveFontFamily } from "../../utils/fontResolver.js";
|
|
4
4
|
//#region src/display-list/build/fontTable.ts
|
|
5
5
|
const CSS_NORMAL_WEIGHT = 400;
|
|
6
6
|
const CSS_BOLD_WEIGHT = 700;
|
|
@@ -12,7 +12,6 @@ const GENERIC_FAMILIES = {
|
|
|
12
12
|
fantasy: "fantasy"
|
|
13
13
|
};
|
|
14
14
|
const DEFAULT_GENERIC = "sans-serif";
|
|
15
|
-
const splitFallbackStack = (cssFallback) => cssFallback.split(",").map((entry) => entry.trim().replace(/^["']|["']$/gu, ""));
|
|
16
15
|
/**
|
|
17
16
|
* The category `resolveFontFamily` chose. It is the last CSS generic in the
|
|
18
17
|
* stack it built, which is where `detectFontCategory` puts it; reading it back
|
|
@@ -30,8 +29,8 @@ const faceKey = (family, weight, italic) => `${family.toLowerCase()} ${weight} $
|
|
|
30
29
|
* Package faces keyed by every family name a run can resolve to.
|
|
31
30
|
*
|
|
32
31
|
* `resolveFontFamily` substitutes the scoped `folio-embedded-{nonce}-{name}`
|
|
33
|
-
* family
|
|
34
|
-
* that
|
|
32
|
+
* family when the run carries its document-owned embedded-family map; a build
|
|
33
|
+
* without that context resolves the same run to the authored name. Both
|
|
35
34
|
* names therefore key the same face, and the bytes are interned by id so one
|
|
36
35
|
* face's binary appears once however many names reach it.
|
|
37
36
|
*/
|
|
@@ -64,7 +63,10 @@ var FontTable = class {
|
|
|
64
63
|
this.embeddedByKey = indexEmbeddedFonts(embeddedFonts);
|
|
65
64
|
}
|
|
66
65
|
intern({ fontFamily, alternateFontFamily, bold, italic, measureStyle }) {
|
|
67
|
-
const stack =
|
|
66
|
+
const stack = parseFontFamilyList(resolveFontFamily(fontFamily, {
|
|
67
|
+
alternateFontName: alternateFontFamily,
|
|
68
|
+
embeddedFontFamilyMap: measureStyle.embeddedFontFamilyMap
|
|
69
|
+
}).cssFallback);
|
|
68
70
|
const family = stack.at(0) ?? fontFamily;
|
|
69
71
|
const weight = bold ? CSS_BOLD_WEIGHT : CSS_NORMAL_WEIGHT;
|
|
70
72
|
const isItalic = italic === true;
|
|
@@ -12,6 +12,7 @@ import { PageComposer } from "./regions.js";
|
|
|
12
12
|
* caller's `documentFeatures` shows the document had one.
|
|
13
13
|
*/
|
|
14
14
|
type PageFurnitureInputs = {
|
|
15
|
+
embeddedFontFamilyMap?: ReadonlyMap<string, string>;
|
|
15
16
|
/**
|
|
16
17
|
* `w:pgBorders` for the section. Absent: no border is painted, and the gap is
|
|
17
18
|
* reported unless `documentFeatures` says the document has none.
|
|
@@ -61,6 +61,7 @@ const paintPageFurniture = ({ page, furniture, context }) => {
|
|
|
61
61
|
const watermark = !suppliesWatermark(furniture) || selected.watermark === void 0 ? [] : paintWatermark({
|
|
62
62
|
page,
|
|
63
63
|
watermark: selected.watermark,
|
|
64
|
+
...furniture.embeddedFontFamilyMap ? { embeddedFontFamilyMap: furniture.embeddedFontFamilyMap } : {},
|
|
64
65
|
...furniture.watermarkImageSrc === void 0 ? {} : { imageSrc: furniture.watermarkImageSrc },
|
|
65
66
|
context
|
|
66
67
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseRotationDegrees } from "../../utils/rotationBoundingBox.js";
|
|
2
2
|
import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
|
|
3
|
+
import { base64ToBytes } from "../../utils/textEncoding.js";
|
|
3
4
|
import { paintPreview } from "./previewPrimitives.js";
|
|
4
5
|
import { resolveBorderStroke } from "./strokes.js";
|
|
5
6
|
import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
|
|
@@ -21,12 +22,8 @@ const DATA_URL_PATTERN = /^data:([^;,]*)(;base64)?,(.*)$/su;
|
|
|
21
22
|
* document the builder reports, not an exception that aborts the build.
|
|
22
23
|
*/
|
|
23
24
|
const decodeBase64 = (encoded) => {
|
|
24
|
-
const decoded = Result.try(() =>
|
|
25
|
-
|
|
26
|
-
const binary = decoded.value;
|
|
27
|
-
const bytes = new Uint8Array(binary.length);
|
|
28
|
-
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
29
|
-
return bytes;
|
|
25
|
+
const decoded = Result.try(() => base64ToBytes(encoded));
|
|
26
|
+
return decoded.isOk() ? decoded.value : void 0;
|
|
30
27
|
};
|
|
31
28
|
const readUint32BE = (bytes, offset) => bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3];
|
|
32
29
|
const readUint16BE = (bytes, offset) => bytes[offset] << 8 | bytes[offset + 1];
|
|
@@ -4,12 +4,13 @@ import { DisplayPrimitive } from "../types.js";
|
|
|
4
4
|
import { BuildContext } from "./buildContext.js";
|
|
5
5
|
//#region src/display-list/build/watermarkPrimitives.d.ts
|
|
6
6
|
type WatermarkPaintOptions = {
|
|
7
|
+
embeddedFontFamilyMap?: ReadonlyMap<string, string> | undefined;
|
|
7
8
|
readonly page: Page;
|
|
8
9
|
readonly watermark: document_d_exports.Watermark;
|
|
9
10
|
/** Resolved `data:` source for a picture watermark; absent means unresolved. */
|
|
10
11
|
readonly imageSrc?: string;
|
|
11
12
|
readonly context: BuildContext;
|
|
12
13
|
};
|
|
13
|
-
declare const paintWatermark: ({ page, watermark, imageSrc, context }: WatermarkPaintOptions) => readonly DisplayPrimitive[];
|
|
14
|
+
declare const paintWatermark: ({ page, watermark, imageSrc, context, embeddedFontFamilyMap }: WatermarkPaintOptions) => readonly DisplayPrimitive[];
|
|
14
15
|
//#endregion
|
|
15
16
|
export { WatermarkPaintOptions, paintWatermark };
|
|
@@ -29,9 +29,10 @@ const TEXT_DEFAULT_OPACITY = .5;
|
|
|
29
29
|
const TEXT_DIAGONAL_DEGREES = -45;
|
|
30
30
|
const PICTURE_NATIVE_SCALE = 1;
|
|
31
31
|
const PICTURE_WASHOUT_OPACITY = .18;
|
|
32
|
-
const paintTextWatermark = (watermark, page, context) => {
|
|
32
|
+
const paintTextWatermark = ({ watermark, page, context, embeddedFontFamilyMap }) => {
|
|
33
33
|
if (watermark.text.length === 0) return [];
|
|
34
34
|
const style = {
|
|
35
|
+
...embeddedFontFamilyMap ? { embeddedFontFamilyMap } : {},
|
|
35
36
|
fontFamily: watermark.font ?? TEXT_DEFAULT_FONT,
|
|
36
37
|
fontSize: pxToPt(TEXT_FONT_SIZE_PX),
|
|
37
38
|
bold: true
|
|
@@ -129,9 +130,14 @@ const paintPictureWatermark = (watermark, page, imageSrc, context) => {
|
|
|
129
130
|
opacity: watermark.washout === false ? 1 : PICTURE_WASHOUT_OPACITY
|
|
130
131
|
}];
|
|
131
132
|
};
|
|
132
|
-
const paintWatermark = ({ page, watermark, imageSrc, context }) => {
|
|
133
|
+
const paintWatermark = ({ page, watermark, imageSrc, context, embeddedFontFamilyMap }) => {
|
|
133
134
|
switch (watermark.kind) {
|
|
134
|
-
case "text": return paintTextWatermark(
|
|
135
|
+
case "text": return paintTextWatermark({
|
|
136
|
+
watermark,
|
|
137
|
+
page,
|
|
138
|
+
context,
|
|
139
|
+
embeddedFontFamilyMap
|
|
140
|
+
});
|
|
135
141
|
case "picture": return paintPictureWatermark(watermark, page, imageSrc, context);
|
|
136
142
|
default: return [];
|
|
137
143
|
}
|
|
@@ -17,6 +17,7 @@ const isPageRendererName = (value) => value === PAGE_RENDERER.legacy || value ==
|
|
|
17
17
|
* which header a page carries.
|
|
18
18
|
*/
|
|
19
19
|
const displayListFurnitureFrom = (options) => ({
|
|
20
|
+
...options.embeddedFontFamilyMap ? { embeddedFontFamilyMap: options.embeddedFontFamilyMap } : {},
|
|
20
21
|
...options.pageBorders === void 0 ? {} : { pageBorders: options.pageBorders },
|
|
21
22
|
...options.theme === void 0 ? {} : { theme: options.theme },
|
|
22
23
|
...options.watermark === void 0 ? {} : { watermark: options.watermark },
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/docx/bookmarkIdNormalization.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Give repeated bookmark ranges independent identities before editor pairing.
|
|
4
|
+
* The first range keeps its id. Ends close starts in encounter order, including
|
|
5
|
+
* overlapping ambiguous ranges. Only colliding ids are repaired: those require
|
|
6
|
+
* unique XML ids for a valid save. Every other source byte stays verbatim.
|
|
7
|
+
*/
|
|
8
|
+
declare const normalizeBookmarkIdsInXmlParts: (parts: ReadonlyMap<string, string>) => ReadonlyMap<string, string>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { normalizeBookmarkIdsInXmlParts };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { scanSelectedStreamingXmlElements } from "./selectedXmlIdentityScan.js";
|
|
2
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, findAttributeByNamespaceUri, getLocalName, getNamespaceUri } from "./xmlParser.js";
|
|
3
|
+
import { panic } from "better-result";
|
|
4
|
+
//#region src/docx/bookmarkIdNormalization.ts
|
|
5
|
+
const bookmarkIdentity = (element) => {
|
|
6
|
+
if (!WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(element) ?? "")) return null;
|
|
7
|
+
const name = getLocalName(element.name);
|
|
8
|
+
if (name !== "bookmarkStart" && name !== "bookmarkEnd") return null;
|
|
9
|
+
const attribute = findAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, "id");
|
|
10
|
+
if (!attribute) return null;
|
|
11
|
+
const id = Number(attribute.value);
|
|
12
|
+
if (!Number.isSafeInteger(id) || id < 0) return null;
|
|
13
|
+
return {
|
|
14
|
+
name,
|
|
15
|
+
attribute: attribute.name,
|
|
16
|
+
id
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Give repeated bookmark ranges independent identities before editor pairing.
|
|
21
|
+
* The first range keeps its id. Ends close starts in encounter order, including
|
|
22
|
+
* overlapping ambiguous ranges. Only colliding ids are repaired: those require
|
|
23
|
+
* unique XML ids for a valid save. Every other source byte stays verbatim.
|
|
24
|
+
*/
|
|
25
|
+
const normalizeBookmarkIdsInXmlParts = (parts) => {
|
|
26
|
+
const candidates = [...parts].filter(([, xml]) => /bookmark(?:Start|End)/u.test(xml));
|
|
27
|
+
const reserved = /* @__PURE__ */ new Set();
|
|
28
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
29
|
+
const markersByPart = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const [path, xml] of candidates) {
|
|
31
|
+
const starts = /* @__PURE__ */ new Set();
|
|
32
|
+
const markers = [];
|
|
33
|
+
if (scanSelectedStreamingXmlElements(xml, ({ element, attributeValueSpans }) => {
|
|
34
|
+
const marker = bookmarkIdentity(element);
|
|
35
|
+
if (!marker) return;
|
|
36
|
+
const span = attributeValueSpans.get(marker.attribute);
|
|
37
|
+
if (!span) panic("Missing bookmark identity source span");
|
|
38
|
+
markers.push({
|
|
39
|
+
marker,
|
|
40
|
+
...span
|
|
41
|
+
});
|
|
42
|
+
reserved.add(marker.id);
|
|
43
|
+
if (marker.name === "bookmarkStart") {
|
|
44
|
+
if (starts.has(marker.id)) repeated.add(path);
|
|
45
|
+
starts.add(marker.id);
|
|
46
|
+
}
|
|
47
|
+
}).status === "unsupported") {
|
|
48
|
+
repeated.delete(path);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
markersByPart.set(path, markers);
|
|
52
|
+
}
|
|
53
|
+
if (repeated.size === 0) return parts;
|
|
54
|
+
let next = 0;
|
|
55
|
+
const allocate = () => {
|
|
56
|
+
while (reserved.has(next)) next += 1;
|
|
57
|
+
const id = next++;
|
|
58
|
+
reserved.add(id);
|
|
59
|
+
return id;
|
|
60
|
+
};
|
|
61
|
+
const normalized = new Map(parts);
|
|
62
|
+
for (const [path, xml] of candidates) {
|
|
63
|
+
if (!repeated.has(path)) continue;
|
|
64
|
+
const seen = /* @__PURE__ */ new Set();
|
|
65
|
+
const open = /* @__PURE__ */ new Map();
|
|
66
|
+
const chunks = [];
|
|
67
|
+
let cursor = 0;
|
|
68
|
+
for (const { marker, start, end } of markersByPart.get(path) ?? []) {
|
|
69
|
+
let id = marker.id;
|
|
70
|
+
if (marker.name === "bookmarkStart") {
|
|
71
|
+
if (seen.has(id)) id = allocate();
|
|
72
|
+
seen.add(marker.id);
|
|
73
|
+
let queue = open.get(marker.id);
|
|
74
|
+
if (!queue) {
|
|
75
|
+
queue = {
|
|
76
|
+
ids: [],
|
|
77
|
+
cursor: 0
|
|
78
|
+
};
|
|
79
|
+
open.set(marker.id, queue);
|
|
80
|
+
}
|
|
81
|
+
queue.ids.push(id);
|
|
82
|
+
} else {
|
|
83
|
+
const queue = open.get(marker.id);
|
|
84
|
+
const paired = queue?.ids.at(queue.cursor);
|
|
85
|
+
if (paired !== void 0 && queue) {
|
|
86
|
+
id = paired;
|
|
87
|
+
queue.cursor += 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (id === marker.id) continue;
|
|
91
|
+
chunks.push(xml.slice(cursor, start), String(id));
|
|
92
|
+
cursor = end;
|
|
93
|
+
}
|
|
94
|
+
chunks.push(xml.slice(cursor));
|
|
95
|
+
normalized.set(path, chunks.join(""));
|
|
96
|
+
}
|
|
97
|
+
return normalized;
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
100
|
+
export { normalizeBookmarkIdsInXmlParts };
|
|
@@ -31,8 +31,10 @@ function createBookmarkMap() {
|
|
|
31
31
|
* @param bookmark - The bookmark start to add
|
|
32
32
|
*/
|
|
33
33
|
function addBookmark(map, bookmark) {
|
|
34
|
-
map.byId.set(bookmark.id, bookmark);
|
|
35
|
-
if (bookmark.name)
|
|
34
|
+
if (!map.byId.has(bookmark.id)) map.byId.set(bookmark.id, bookmark);
|
|
35
|
+
if (bookmark.name) {
|
|
36
|
+
if (!map.byName.has(bookmark.name)) map.byName.set(bookmark.name, bookmark);
|
|
37
|
+
}
|
|
36
38
|
map.bookmarks.push(bookmark);
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { withTrackedSectionEndpointRemoval } from "../internal/sectionEndpointResolution.js";
|
|
2
2
|
import { withSectionReferenceResolution } from "../internal/sectionReferenceResolution.js";
|
|
3
|
+
import { decodeText, encodeUtf8 } from "../utils/textEncoding.js";
|
|
3
4
|
import { readDocumentSectionFacts } from "./documentSectionFacts.js";
|
|
4
5
|
import { parseDocx } from "./parser.js";
|
|
5
6
|
import { assertSectionCarriersMatchModel } from "./rezip.js";
|
|
@@ -9,7 +10,7 @@ import JSZip from "jszip";
|
|
|
9
10
|
/** Canonical snapshots own explicit section references; the PM projection does not. */
|
|
10
11
|
const referenceKey = ({ element, type, rId }) => `${element}:${type}:${rId}`;
|
|
11
12
|
const xmlFingerprint = async (xml) => {
|
|
12
|
-
const digest = await crypto.subtle.digest("SHA-256",
|
|
13
|
+
const digest = await crypto.subtle.digest("SHA-256", encodeUtf8(xml));
|
|
13
14
|
let fingerprint = "";
|
|
14
15
|
for (const byte of new Uint8Array(digest)) fingerprint += byte.toString(16).padStart(2, "0");
|
|
15
16
|
return fingerprint;
|
|
@@ -18,7 +19,7 @@ const xmlFingerprint = async (xml) => {
|
|
|
18
19
|
const repackWithCanonicalStoryRemovals = async ({ document, repack }) => {
|
|
19
20
|
const originalBuffer = document.originalBuffer;
|
|
20
21
|
if (!originalBuffer) return repack();
|
|
21
|
-
const xml = await (await JSZip.loadAsync(originalBuffer)).file("word/document.xml")?.async("
|
|
22
|
+
const xml = await (await JSZip.loadAsync(originalBuffer)).file("word/document.xml")?.async("uint8array").then((bytes) => decodeText(bytes, { ignoreBOM: true }));
|
|
22
23
|
if (!xml) return repack();
|
|
23
24
|
const before = readDocumentSectionFacts(xml);
|
|
24
25
|
const serializedXml = serializeDocument(document);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/commentTextParagraph.d.ts
|
|
3
|
+
/** Plain comment text has no authored paragraph formatting. */
|
|
4
|
+
declare const commentTextParagraph: (text: string) => document_d_exports.Paragraph;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { commentTextParagraph };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/docx/commentTextParagraph.ts
|
|
2
|
+
/** Plain comment text has no authored paragraph formatting. */
|
|
3
|
+
const commentTextParagraph = (text) => ({
|
|
4
|
+
type: "paragraph",
|
|
5
|
+
content: [{
|
|
6
|
+
type: "run",
|
|
7
|
+
formatting: {},
|
|
8
|
+
content: [{
|
|
9
|
+
type: "text",
|
|
10
|
+
text
|
|
11
|
+
}]
|
|
12
|
+
}]
|
|
13
|
+
});
|
|
14
|
+
//#endregion
|
|
15
|
+
export { commentTextParagraph };
|
package/dist/docx/conformance.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sliceText } from "../utils/sliceText.js";
|
|
1
2
|
import { getLocalName, getNamespacePrefix, parseXmlDocument } from "./xmlParser.js";
|
|
2
3
|
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
3
4
|
//#region src/docx/conformance.ts
|
|
@@ -62,7 +63,11 @@ function scanRootStartTag(scanTarget) {
|
|
|
62
63
|
}
|
|
63
64
|
const detectDocxConformanceClass = (documentXml) => {
|
|
64
65
|
if (documentXml === null) return DOCX_CONFORMANCE_CLASSES.UNKNOWN;
|
|
65
|
-
const rootStartTag = scanRootStartTag(documentXml.length <= ROOT_START_TAG_SCAN_LIMIT ? documentXml :
|
|
66
|
+
const rootStartTag = scanRootStartTag(documentXml.length <= ROOT_START_TAG_SCAN_LIMIT ? documentXml : sliceText({
|
|
67
|
+
text: documentXml,
|
|
68
|
+
units: "codeUnits",
|
|
69
|
+
end: ROOT_START_TAG_SCAN_LIMIT
|
|
70
|
+
}));
|
|
66
71
|
const root = (rootStartTag === void 0 ? null : parseXmlDocument(rootStartTag.endsWith("/>") ? rootStartTag : `${rootStartTag.slice(0, -1)}/>`)) ?? parseXmlDocument(documentXml);
|
|
67
72
|
return detectDocxConformanceClassFromRoot(root);
|
|
68
73
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeText } from "../utils/textEncoding.js";
|
|
1
2
|
import { resolveRelationshipIdOfType, resolveRelativePath } from "./relsParser.js";
|
|
2
3
|
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, findChildByNamespaceUri, getAttribute, getAttributeByNamespaceUri, getLocalName, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
3
4
|
//#region src/docx/diagramPreview.ts
|
|
@@ -31,7 +32,7 @@ const partByRelationshipId = ({ rels, media, rId, type, cache }) => {
|
|
|
31
32
|
const cached = cache.get(path);
|
|
32
33
|
if (cached !== void 0) return cached;
|
|
33
34
|
const file = media.get(path);
|
|
34
|
-
const parsed = file?.data ? parseXmlDocument(new
|
|
35
|
+
const parsed = file?.data ? parseXmlDocument(decodeText(new Uint8Array(file.data))) : null;
|
|
35
36
|
cache.set(path, parsed);
|
|
36
37
|
return parsed;
|
|
37
38
|
};
|
|
@@ -19,6 +19,18 @@ declare function extractTemplateVariables(text: string): string[];
|
|
|
19
19
|
* @returns Array of unique variable names
|
|
20
20
|
*/
|
|
21
21
|
declare function extractAllTemplateVariables(content: document_d_exports.BlockContent[]): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Build sections from content based on section properties in paragraphs
|
|
24
|
+
*
|
|
25
|
+
* In OOXML, sections are delimited by:
|
|
26
|
+
* 1. w:pPr/w:sectPr within a paragraph (marks end of a section)
|
|
27
|
+
* 2. w:body/w:sectPr (final section properties)
|
|
28
|
+
*
|
|
29
|
+
* @param content - All block content
|
|
30
|
+
* @param finalSectPr - Final section properties from body
|
|
31
|
+
* @returns Array of sections
|
|
32
|
+
*/
|
|
33
|
+
declare function buildSections(content: document_d_exports.BlockContent[], finalSectPr: document_d_exports.SectionProperties | undefined): document_d_exports.Section[];
|
|
22
34
|
/**
|
|
23
35
|
* Parse document.xml body content
|
|
24
36
|
*
|
|
@@ -67,4 +79,4 @@ declare function getSectionCount(body: document_d_exports.DocumentBody): number;
|
|
|
67
79
|
*/
|
|
68
80
|
declare function hasTemplateVariables(body: document_d_exports.DocumentBody): boolean;
|
|
69
81
|
//#endregion
|
|
70
|
-
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|
|
82
|
+
export { buildSections, extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|
|
@@ -257,4 +257,4 @@ function hasTemplateVariables(body) {
|
|
|
257
257
|
return extractAllTemplateVariables(body.content).length > 0;
|
|
258
258
|
}
|
|
259
259
|
//#endregion
|
|
260
|
-
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|
|
260
|
+
export { buildSections, extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
//#region src/docx/encryption/compoundFile.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Read-only MS-CFB compound file access for encrypted OOXML packages.
|
|
4
|
-
*
|
|
5
|
-
* Encrypted `.docx` files store `EncryptionInfo` and `EncryptedPackage` streams
|
|
6
|
-
* at the compound-file root. This reader implements only what MS-OFFCRYPTO needs.
|
|
7
|
-
*
|
|
8
|
-
* @see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/
|
|
9
|
-
*/
|
|
10
2
|
type CompoundFileReader = {
|
|
11
3
|
readStream: (absolutePath: string) => Uint8Array | null;
|
|
12
4
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeText } from "../../utils/textEncoding.js";
|
|
1
2
|
import { joinBytes } from "./cryptoBytes.js";
|
|
2
3
|
//#region src/docx/encryption/compoundFile.ts
|
|
3
4
|
/**
|
|
@@ -39,7 +40,7 @@ const u64 = (view, offset) => {
|
|
|
39
40
|
return BigInt(view.getUint32(offset + 4, true)) << 32n | low;
|
|
40
41
|
};
|
|
41
42
|
const decodeName = (nameBytes) => {
|
|
42
|
-
const decoded =
|
|
43
|
+
const decoded = decodeText(nameBytes, { encoding: "utf-16le" });
|
|
43
44
|
let end = decoded.length;
|
|
44
45
|
while (end > 0 && decoded.charCodeAt(end - 1) === 0) end--;
|
|
45
46
|
return decoded.slice(0, end);
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/** Byte helpers shared by MS-CFB and MS-OFFCRYPTO agile decryption. */
|
|
3
3
|
declare const joinBytes: (parts: readonly Uint8Array[]) => Uint8Array;
|
|
4
4
|
declare const writeUint32Le: (value: number) => Uint8Array;
|
|
5
|
-
declare const passwordToUtf16Le: (
|
|
5
|
+
declare const passwordToUtf16Le: (text: string) => Uint8Array<ArrayBuffer>;
|
|
6
6
|
declare const bytesEqual: (left: Uint8Array, right: Uint8Array) => boolean;
|
|
7
7
|
declare const toArrayBuffer: (bytes: Uint8Array) => ArrayBuffer;
|
|
8
|
-
declare const decodeBase64: (
|
|
8
|
+
declare const decodeBase64: (text: string) => Uint8Array<ArrayBuffer>;
|
|
9
9
|
declare const padToBlock: (bytes: Uint8Array, blockSize: number, padByte?: number) => Uint8Array;
|
|
10
10
|
//#endregion
|
|
11
11
|
export { bytesEqual, decodeBase64, joinBytes, padToBlock, passwordToUtf16Le, toArrayBuffer, writeUint32Le };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { base64ToBytes, encodeUtf16LE } from "../../utils/textEncoding.js";
|
|
1
2
|
//#region src/docx/encryption/cryptoBytes.ts
|
|
2
3
|
/** Byte helpers shared by MS-CFB and MS-OFFCRYPTO agile decryption. */
|
|
3
4
|
const joinBytes = (parts) => {
|
|
@@ -19,15 +20,7 @@ const writeUint32Le = (value) => {
|
|
|
19
20
|
out[3] = value >>> 24 & 255;
|
|
20
21
|
return out;
|
|
21
22
|
};
|
|
22
|
-
const passwordToUtf16Le =
|
|
23
|
-
const out = new Uint8Array(password.length * 2);
|
|
24
|
-
for (let i = 0; i < password.length; i++) {
|
|
25
|
-
const code = password.charCodeAt(i);
|
|
26
|
-
out[i * 2] = code & 255;
|
|
27
|
-
out[i * 2 + 1] = code >> 8;
|
|
28
|
-
}
|
|
29
|
-
return out;
|
|
30
|
-
};
|
|
23
|
+
const passwordToUtf16Le = encodeUtf16LE;
|
|
31
24
|
const bytesEqual = (left, right) => {
|
|
32
25
|
if (left.length !== right.length) return false;
|
|
33
26
|
let mismatch = 0;
|
|
@@ -38,15 +31,7 @@ const toArrayBuffer = (bytes) => {
|
|
|
38
31
|
if (bytes.buffer instanceof ArrayBuffer && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength) return bytes.buffer;
|
|
39
32
|
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
40
33
|
};
|
|
41
|
-
const decodeBase64 =
|
|
42
|
-
if (typeof atob === "function") {
|
|
43
|
-
const binary = atob(encoded);
|
|
44
|
-
const out = new Uint8Array(binary.length);
|
|
45
|
-
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
|
|
46
|
-
return out;
|
|
47
|
-
}
|
|
48
|
-
return new Uint8Array(Buffer.from(encoded, "base64"));
|
|
49
|
-
};
|
|
34
|
+
const decodeBase64 = base64ToBytes;
|
|
50
35
|
const padToBlock = (bytes, blockSize, padByte = 54) => {
|
|
51
36
|
if (bytes.length >= blockSize) return bytes.subarray(0, blockSize);
|
|
52
37
|
const out = new Uint8Array(blockSize);
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
//#region src/docx/encryption/encryptionInfo.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Parse the EncryptionInfo stream for Agile Encryption (Office 2010+).
|
|
4
|
-
*
|
|
5
|
-
* @see https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/87020a34-e73f-4139-99bc-bbdf6cf6fa55
|
|
6
|
-
*/
|
|
7
2
|
type AgileKeyMaterial = {
|
|
8
3
|
packageSalt: Uint8Array;
|
|
9
4
|
packageKeyBits: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeText } from "../../utils/textEncoding.js";
|
|
1
2
|
import { decodeBase64 } from "./cryptoBytes.js";
|
|
2
3
|
import { DOCX_ENCRYPTION_ERROR_CODES, DocxEncryptionError } from "./errors.js";
|
|
3
4
|
//#region src/docx/encryption/encryptionInfo.ts
|
|
@@ -85,7 +86,7 @@ const requireSpinCount = (attrs, element) => {
|
|
|
85
86
|
return spinCount;
|
|
86
87
|
};
|
|
87
88
|
const parseAgileXml = (xmlBytes) => {
|
|
88
|
-
const xml =
|
|
89
|
+
const xml = decodeText(xmlBytes, { encoding: "utf-8" });
|
|
89
90
|
const keyDataTag = findElement(xml, "keyData");
|
|
90
91
|
const integrityTag = findElement(xml, "dataIntegrity");
|
|
91
92
|
const encryptedKeyTag = findElement(xml, "encryptedKey");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { deterministicHexId } from "../utils/hexId.js";
|
|
2
|
+
import { encodeUtf8 } from "../utils/textEncoding.js";
|
|
2
3
|
import { resolvePackageRelationshipTarget } from "./packageParts.js";
|
|
3
4
|
import { spliceXml } from "./selectiveXmlPatch.js";
|
|
4
5
|
import { loadDocxArchive } from "./server/boundedArchive.js";
|
|
@@ -390,7 +391,7 @@ const ensureParaIdsInternal = async (docx, options) => {
|
|
|
390
391
|
writeZipPart({
|
|
391
392
|
zip,
|
|
392
393
|
path: partPath,
|
|
393
|
-
data: content,
|
|
394
|
+
data: encodeUtf8(content),
|
|
394
395
|
options: {
|
|
395
396
|
compression: "DEFLATE",
|
|
396
397
|
compressionOptions: { level: 6 },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sliceText } from "../utils/sliceText.js";
|
|
1
2
|
import { emuToPixels } from "../utils/units.js";
|
|
2
3
|
import { collectGroupTextBoxes, readTransform } from "./drawingGroupChildren.js";
|
|
3
4
|
import { parseImage, resolveImageData } from "./imageParser.js";
|
|
@@ -142,7 +143,11 @@ const renderTextBox = (wsp, unitScale) => {
|
|
|
142
143
|
const color = colorFrom(findAllDeep(wsp, "w", "color").at(0) ?? null, DEFAULT_TEXT_COLOR);
|
|
143
144
|
const fontSize = halfPoints * HALF_POINT_TO_EMU / unitScale;
|
|
144
145
|
const maxCharacters = Math.max(1, Math.floor(width / (fontSize * .38)));
|
|
145
|
-
const lines = paragraphs.flatMap((paragraph) => wrapLine(
|
|
146
|
+
const lines = paragraphs.flatMap((paragraph) => wrapLine(sliceText({
|
|
147
|
+
text: getTextContent(paragraph),
|
|
148
|
+
units: "codeUnits",
|
|
149
|
+
end: MAX_TEXT_CHARACTERS
|
|
150
|
+
}), maxCharacters)).map(escapeXmlText);
|
|
146
151
|
if (lines.length === 0) return "";
|
|
147
152
|
const lineHeight = fontSize * 1.15;
|
|
148
153
|
const svgFontSize = 1e3;
|