@office-open/core 0.10.15 → 0.12.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 +2 -1
- package/dist/chart/index.d.mts +2 -2
- package/dist/chart/index.mjs +2 -2
- package/dist/chart-DED4tXC9.mjs +2325 -0
- package/dist/chart-DED4tXC9.mjs.map +1 -0
- package/dist/color-mapping-CFF0vRSe.mjs +117 -0
- package/dist/color-mapping-CFF0vRSe.mjs.map +1 -0
- package/dist/data-type-CZMKVaaT.d.mts.map +1 -1
- package/dist/descriptor/index.d.mts +2 -2
- package/dist/descriptor/index.mjs +1 -1
- package/dist/{descriptor-BjNkn5jo.mjs → descriptor-BqaNZrrZ.mjs} +43 -11
- package/dist/{descriptor-BjNkn5jo.mjs.map → descriptor-BqaNZrrZ.mjs.map} +1 -1
- package/dist/drawing/index.d.mts +2 -0
- package/dist/drawing/index.mjs +2 -0
- package/dist/{drawingml-sj1J3lb0.mjs → drawing-BCAyrCCw.mjs} +4456 -3452
- package/dist/drawing-BCAyrCCw.mjs.map +1 -0
- package/dist/{converters-C_Y2QX1w.mjs → ext-uri-BHBcIrW7.mjs} +742 -45
- package/dist/ext-uri-BHBcIrW7.mjs.map +1 -0
- package/dist/index-BAxlDUQ1.d.mts +590 -0
- package/dist/index-BAxlDUQ1.d.mts.map +1 -0
- package/dist/index-BP541uS-.d.mts +489 -0
- package/dist/index-BP541uS-.d.mts.map +1 -0
- package/dist/{index-BVK2dv6C.d.mts → index-BQLIofaF.d.mts} +10 -4
- package/dist/index-BQLIofaF.d.mts.map +1 -0
- package/dist/{index-k8WKLXnA.d.mts → index-CaNwM5_e.d.mts} +19 -20
- package/dist/index-CaNwM5_e.d.mts.map +1 -0
- package/dist/index-DPkf_CtG.d.mts +1578 -0
- package/dist/index-DPkf_CtG.d.mts.map +1 -0
- package/dist/index-DcukVskh.d.mts +31 -0
- package/dist/index-DcukVskh.d.mts.map +1 -0
- package/dist/index-Di6XPdGl.d.mts +322 -0
- package/dist/index-Di6XPdGl.d.mts.map +1 -0
- package/dist/index-L6AXewfV.d.mts +872 -0
- package/dist/index-L6AXewfV.d.mts.map +1 -0
- package/dist/index.d.mts +294 -30
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1327 -112
- package/dist/index.mjs.map +1 -1
- package/dist/{output-D_G_JR_8.d.mts → output-yyxdkG0C.d.mts} +2 -3
- package/dist/output-yyxdkG0C.d.mts.map +1 -0
- package/dist/patch/index.d.mts +2 -2
- package/dist/patch/index.mjs +2 -2
- package/dist/{patch-BmRfghOo.mjs → patch-AkQY17CD.mjs} +73 -28
- package/dist/patch-AkQY17CD.mjs.map +1 -0
- package/dist/smartart/index.d.mts +2 -2
- package/dist/smartart/index.mjs +2 -2
- package/dist/smartart-n1kYJ6Jg.mjs +1650 -0
- package/dist/smartart-n1kYJ6Jg.mjs.map +1 -0
- package/dist/style-matrix-B6jhPAT3.mjs +123 -0
- package/dist/style-matrix-B6jhPAT3.mjs.map +1 -0
- package/dist/theme/index.d.mts +4 -2
- package/dist/theme/index.mjs +4 -2
- package/dist/theme-BKnXRmvn.mjs +426 -0
- package/dist/theme-BKnXRmvn.mjs.map +1 -0
- package/dist/theme-options-kO89NUEX.d.mts +109 -0
- package/dist/theme-options-kO89NUEX.d.mts.map +1 -0
- package/dist/util/index.d.mts +3 -3
- package/dist/util/index.mjs +3 -3
- package/dist/{util-Tq9PSjK0.mjs → util-ptE16MEk.mjs} +237 -459
- package/dist/util-ptE16MEk.mjs.map +1 -0
- package/dist/{values-8di32lIe.d.mts → values-BECDm4zr.d.mts} +17 -31
- package/dist/values-BECDm4zr.d.mts.map +1 -0
- package/dist/vector/index.d.mts +2 -0
- package/dist/vector/index.mjs +2 -0
- package/dist/vector-DhLGZjP5.mjs +3049 -0
- package/dist/vector-DhLGZjP5.mjs.map +1 -0
- package/package.json +16 -8
- package/dist/chart-DIGJna_6.mjs +0 -582
- package/dist/chart-DIGJna_6.mjs.map +0 -1
- package/dist/converters-C_Y2QX1w.mjs.map +0 -1
- package/dist/drawingml/index.d.mts +0 -2
- package/dist/drawingml/index.mjs +0 -2
- package/dist/drawingml-sj1J3lb0.mjs.map +0 -1
- package/dist/index-BVK2dv6C.d.mts.map +0 -1
- package/dist/index-BfHfKuKy.d.mts +0 -275
- package/dist/index-BfHfKuKy.d.mts.map +0 -1
- package/dist/index-CE53SwpZ.d.mts +0 -1463
- package/dist/index-CE53SwpZ.d.mts.map +0 -1
- package/dist/index-D6VE-MnJ.d.mts +0 -43
- package/dist/index-D6VE-MnJ.d.mts.map +0 -1
- package/dist/index-DE4CLElr.d.mts +0 -145
- package/dist/index-DE4CLElr.d.mts.map +0 -1
- package/dist/index-DlPA26cw.d.mts +0 -91
- package/dist/index-DlPA26cw.d.mts.map +0 -1
- package/dist/index-k8WKLXnA.d.mts.map +0 -1
- package/dist/output-D_G_JR_8.d.mts.map +0 -1
- package/dist/patch-BmRfghOo.mjs.map +0 -1
- package/dist/smartart-B7ukZ-Tw.mjs +0 -305
- package/dist/smartart-B7ukZ-Tw.mjs.map +0 -1
- package/dist/theme-CiNzdl-9.mjs +0 -177
- package/dist/theme-CiNzdl-9.mjs.map +0 -1
- package/dist/util-Tq9PSjK0.mjs.map +0 -1
- package/dist/values-8di32lIe.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
import {
|
|
3
|
-
import { $ as
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
1
|
+
import { A as ZIP_STORED_LEVEL, B as OoxmlMimeType, C as replaceVideoPlaceholders, D as addBinaryFile, E as randomBytes, F as strFromU8, H as hasNativeInflate, I as unzipSync, L as zipAndConvert, M as createPacker, N as createZipStream, O as compileMapping, P as levelForMediaName, R as zipSync, S as replaceSmartArtPlaceholders, T as hashPasswordAgile, U as nativeCrc32, V as convertOutput, W as nativeUnzip, _ as replaceMediaPlaceholders, a as getAudioRefs, b as replaceOlePlaceholders, c as getReferencedMedia, d as replaceAllPlaceholders, f as replaceAudioPlaceholders, g as replaceImagePlaceholders, h as replaceImageLinkPlaceholders, i as formatId, j as ZipStreamWriter, k as ZIP_DEFLATE_LEVEL, l as getVideoRefs, m as replaceHyperlinkPlaceholders, n as collectPlaceholderKeys, o as getMediaRefs, p as replaceChartPlaceholders, r as findAndReplaceImagePlaceholders, s as getOleRefs, t as addSmartArtRelationships, u as hasPlaceholders, v as replaceNumberingPlaceholders, w as derivePasswordHash, x as replacePlaceholders, y as replaceOleLinkPlaceholders, z as zipSyncAndConvert } from "./util-ptE16MEk.mjs";
|
|
2
|
+
import { _ as toJson, a as appendOverride, b as buildCorePropertiesXmlString, c as createTraverser, d as TokenNotFoundError, f as createSplitInject, g as patchSpaceAttribute, h as nextNumericId, i as appendContentType, l as createRunRenderer, m as getFirstLevelElements, n as appendRelationship, o as removeOverride, p as createTextElementContents, r as getNextRelationshipIndex, s as createReplacer, t as applyCorePropertiesOverride, u as createTokenReplacer, v as DOCX_NS, x as parseCorePropsElement, y as PPTX_NS } from "./patch-AkQY17CD.mjs";
|
|
3
|
+
import { $ as xsdDiagramDirection, $t as pointMeasureValue, A as parseAngle, At as xsdTextBuild, B as xsdAxisCrossBetween, Bt as decodeBase64, C as convertUniversalMeasureToEmu, Ct as xsdSizeRepresents, D as emitAngle, Dt as xsdTableWidthType, E as convertUniversalMeasureToTwip, Et as xsdStrikeStyle, F as xsdAnimCalcMode, Ft as xsdTrendlineType, G as xsdBlendMode, Gt as eighthPointMeasureValue, H as xsdAxisLabelAlignment, I as xsdAnimClass, It as xsdUnderlineStyle, J as xsdCompoundLine, Jt as hpsMeasureValue, K as xsdChartBuild, Kt as hexBinary, L as xsdAnimLevel, Lt as xsdVerticalMergeRev, M as parsePercentAttr, Mt as xsdTextTabAlignment, N as parseUniversalMeasure, Nt as xsdTextVerticalType, O as emitPercent, Ot as xsdTextAlign, P as invertMap, Pt as xsdTotalsRowFunction, Q as xsdDiagramBuild, Qt as percentageValue, R as xsdAnimValueType, Rt as isBase64DataURL, S as convertTwipToPoints, St as xsdShadingPattern, T as convertUniversalMeasureToPt, Tt as xsdSplitType, U as xsdAxisOrientation, Ut as dateTimeValue, V as xsdAxisCrosses, Vt as encodeBase64, W as xsdAxisPosition, Wt as decimalNumber, X as xsdDashStyle, Xt as measurementOrPercentValue, Y as xsdConsolidateFunction, Yt as longHexNumber, Z as xsdDataLabelPosition, Zt as parseOnOff, _ as convertToEmu, _t as xsdPenAlignment, a as uniqueNumericIdCreator, an as twipsMeasureValue, at as xsdIterateType, b as convertToTwip, bt as xsdRectAlignment, c as convertEmuToPixels, cn as unsignedDecimalNumber, ct as xsdLightRigDirection, d as convertInchesToEmu, dt as xsdMaterialType, en as positiveUniversalMeasureValue, et as xsdEffectContainer, f as convertInchesToTwip, ft as xsdMathStyle, g as convertPointsToTwip, gt as xsdPattern, h as convertPointsToEmu, ht as xsdPathFillMode, i as uniqueId, in as stripColorHashPrefix, it as xsdHueDirection, j as parsePercent, jt as xsdTextCaps, k as mapOptional, kt as xsdTextAnchor, l as convertEmuToPoints, lt as xsdLineCap, m as convertPixelsToEmu, mt as xsdOrient, n as imageTypeFromPath, nn as signedHpsMeasureValue, nt as xsdFontAlignment, o as uniqueUuid, on as uCharHexNumber, ot as xsdJcAlignment, p as convertMillimetersToTwip, pt as xsdOnOffStyle, q as xsdComments, qt as hexColorValue, r as hashedId, rn as signedTwipsMeasureValue, rt as xsdHierBranch, s as convertEmuToInches, sn as universalMeasureValue, st as xsdLegendPosition, t as extUriMatches, tn as shortHexNumber, tt as xsdErrorValueType, u as convertEmuToTwip, ut as xsdLineEndSize, v as convertToInch, vt as xsdPlaceholderType, w as convertUniversalMeasureToInch, wt as xsdSlideLayoutType, x as convertTwipToEmu, xt as xsdResizeHandles, y as convertToPt, yt as xsdPresetShadow, z as xsdAnimationDgmBuild, zt as toUint8Array } from "./ext-uri-BHBcIrW7.mjs";
|
|
4
|
+
import { C as stringifyDataModelOptions, D as COLOR_CATEGORIES, E as stringifyConnection, O as LAYOUT_CATEGORIES, S as stringifyDataModel, T as stringifyTransPoint, _ as parseLayoutDefinition, a as getColorXml, b as withDiagramNamespaces, c as parseStyleDefinition, d as styleDefDesc, f as colorsDefDesc, g as layoutDefDesc, h as stringifyColorDefinitionPart, i as DEFAULT_DRAWING_XML, k as STYLE_CATEGORIES, l as stringifyStyleDefinition, m as stringifyColorDefinition, n as SmartArtCollection, o as getLayoutXml, p as parseColorDefinition, r as definitionId, s as getStyleXml, t as createDataModel, u as stringifyStyleDefinitionPart, v as stringifyLayoutDefinition, w as stringifyPoint, x as parseDataModelOptions, y as stringifyLayoutDefinitionPart } from "./smartart-n1kYJ6Jg.mjs";
|
|
5
|
+
import { $ as createAdjustList, $n as createSystemColor, $t as createGroupFill, A as groupShapePropertiesDesc, An as createEffectColorList, At as createCustomGeometry, B as shapeLockingDesc, Bn as emitColorChoice, Bt as createSoftEdgeEffect, C as createBodyProperties, Cn as bevelDesc, Ct as parseTableStyleList, D as DEFAULT_SHADOW_BLUR_RADIUS, Dn as FontCollectionIndex, Dt as createBlipFill, E as DEFAULT_SHADOW_ALPHA, En as shape3DDesc, Et as stringifyStretch, F as presetGeometryDesc, Fn as createTextFillColorList, Ft as createBottomBevel, G as createDiagramRelationshipIds, Gn as presetColorDesc, Gt as createGlowEffect, H as createDiagramExtensionList, Hn as isPlainRgbColor, Ht as createPresetShadowEffect, I as connectorLockingDesc, In as createTextLineColorList, It as createScene3D, J as createLayoutDefinitionHeader, Jn as schemeColorDesc, Jt as outlineDesc, K as createColorsDefinitionHeader, Kn as rgbColorDesc, Kt as BlendMode, L as graphicFrameLockingDesc, Lt as createEffectDag, M as groupTransform2DDesc, Mn as createLineColorList, Mt as stringifyAdjustmentValues, N as transform2DDesc, Nn as createStyleLabel, Nt as createShape3D, O as DEFAULT_SHADOW_DIRECTION, Ot as createBlip, P as customGeometryDesc, Pn as createTextEffectColorList, Pt as createBevel, Q as createAdjust, Qn as SystemColor, Qt as createCustomDash, R as groupLockingDesc, Rn as createColorElement, Rt as calculateEffectExtent, S as bodyPropertiesDesc, Sn as createRgbColor, St as parseTableStyle, T as DEFAULT_OUTLINE_WIDTH, Tn as scene3DDesc, Tt as createTransform2D, U as createDiagramShape3D, Un as parseColorChoice, Ut as createOuterShadowEffect, V as effectListDesc, Vn as hslColorDesc, Vt as createReflectionEffect, W as createDiagramTextProperties, Wn as parseColorChoiceElement, Wt as createInnerShadowEffect, X as createStyleDefinitionHeader, Xn as stringifyColorChoice, Xt as createOutline, Y as createLayoutDefinitionHeaderList, Yn as solidFillDesc, Yt as stringifyLineProperties, Z as createStyleDefinitionHeaderList, Zn as systemColorDesc, Zt as createLineEnd, _ as buildHyperlinkElement, _n as stretchDesc, _t as createGroupLocking, a as textBodyDesc, an as extractBlipFillMedia, at as createPreferredChildren, b as runPropertiesDesc, bn as createScRgbColor, bt as createTableStyle, c as stringifyTextListStyleTag, cn as findFillChild, ct as stringifyNonVisualContentPartProperties, d as textStylesDesc, dn as createTileInfo, dt as stringifyNonVisualDrawingProperties, en as createPatternFill, er as SchemeColor, et as createAnimateOneByOne, f as paragraphDesc, fn as createSourceRectangle, ft as parseEndpointConnection, g as textRunDesc, gn as sourceRectangleDesc, gt as createGraphicFrameLocking, h as stringifyTextRun, hn as blipFillDesc, ht as createContentPartLocking, i as presentationLayoutVariablesDesc, in as buildFill, ir as createColorTransforms, it as createOrgChart, j as shapePropertiesDesc, jn as createFillColorList, jt as stringifyPresetGeometry, k as DEFAULT_SHADOW_DISTANCE, kn as createDiagramStyle, kt as createExtensionList, l as stringifyTextStyles, ln as gradientFillDesc, lt as parseNonVisualDrawingProperties, m as stringifyParagraphPropertiesElement, mn as blipDesc, mt as createConnectorLocking, n as diagramRelationshipIdsDesc, nn as createGradientStop, nr as PresetColor, nt as createHierBranch, o as DEFAULT_TEXT_STYLES, on as emitFillXml, ot as createPresentationLayoutVariables, p as readParagraphProperties, pn as createBlipEffects, pt as stringifyEndpointConnection, q as createColorsDefinitionHeaderList, qn as scRgbColorDesc, qt as createFillOverlayEffect, r as diagramStyleDesc, rn as createNoFill, rr as createPresetColor, rt as createMaxChildren, s as parseTextStyles, sn as fillDesc, st as parseNonVisualContentPartProperties, t as diagramExtensionListDesc, tn as createGradientFill, tr as createSchemeColor, tt as createAnimationLevel, u as textListStyleDesc, un as patternFillDesc, ut as pickNonVisualDrawingProperties, v as readHyperlink, vn as stringifyBlipEffects, vt as createPictureLocking, w as parseBodyProperties, wn as cell3DDesc, wt as createGroupTransform2D, x as stringifyRunProperties, xn as createHslColor, xt as createTableStyleList, y as registerHyperlink, yn as tileDesc, yt as createShapeLocking, z as pictureLockingDesc, zn as createSolidFill, zt as createEffectList } from "./drawing-BCAyrCCw.mjs";
|
|
6
|
+
import { a as roundTripFields, i as diffTagSets, n as findFieldSpec, o as parse, r as checkOrder, s as stringify, t as FIELD_SPECS } from "./descriptor-BqaNZrrZ.mjs";
|
|
7
|
+
import { i as stringifyShapeStyle, n as parseShapeStyle } from "./style-matrix-B6jhPAT3.mjs";
|
|
8
|
+
import { n as chartSpaceDesc, r as ChartCollection, t as userShapesDesc } from "./chart-DED4tXC9.mjs";
|
|
9
|
+
import { n as parseColorMapping, r as stringifyColorMapping, t as DEFAULT_COLOR_MAPPING } from "./color-mapping-CFF0vRSe.mjs";
|
|
10
|
+
import { $ as stringifyVmlIsComment, A as stringifyVmlPolyline, At as stringifyVmlEquationXml, B as stringifyVmlAnchorLock, Bt as VML_OFFICE_SHAPE_ATTRS, C as stringifyVmlArc, Ct as parseVmlOleObject, D as stringifyVmlImage, Dt as stringifyVmlClipPath, E as stringifyVmlGroup, Et as stringifyVmlCallout, F as stringifyVmlShapetype, Ft as stringifyVmlOleObject, G as parseVmlTextbox, Gt as stringifyVmlAttributes, H as stringifyVmlWrap, Ht as parseVmlAttributes, I as VML_BORDER_TAGS, It as stringifyVmlSignatureLine, J as stringifyVmlStroke, Jt as parseVmlShapeStyle, K as stringifyVmlTextbox, Kt as stringifyVmlTrueFalse, L as parseVmlAnchorLock, Lt as stringifyVmlSkew, M as stringifyVmlRoundRect, Mt as stringifyVmlInk, N as stringifyVmlShape, Nt as stringifyVmlLock, O as stringifyVmlLine, Ot as stringifyVmlComplex, P as stringifyVmlShapeChild, Pt as stringifyVmlOfficeFill, Q as parseVmlTextData, R as parseVmlBorder, Rt as VML_CORE_ATTRS, S as parseVmlShapetype, St as parseVmlOfficeFill, T as stringifyVmlCurve, Tt as parseVmlSkew, U as parseVmlTextPath, Ut as parseVmlTrueFalse, V as stringifyVmlBorder, Vt as VML_SHAPE_ATTRS, W as stringifyVmlTextPath, Wt as parseVmlTrueFalseBlank, X as stringifyVmlShadow, Xt as stringifyVmlStyle, Y as parseVmlShadow, Yt as parseVmlStyle, Z as parseVmlIsComment, Zt as styleToKeyMap, _ as parseVmlPolyline, _t as parseVmlDiagram, a as stringifyVmlColorMenu, at as parseVmlHandles, b as parseVmlShape, bt as parseVmlInk, c as stringifyVmlShapeLayout, ct as stringifyVmlFormulas, d as parseVmlBackground, dt as parseVmlClientData, et as stringifyVmlTextData, f as parseVmlCurve, ft as stringifyVmlClientData, g as parseVmlOval, gt as parseVmlComplex, h as parseVmlLine, ht as parseVmlClipPath, i as parseVmlShapeLayout, it as stringifyVmlImageData, j as stringifyVmlRect, jt as stringifyVmlExtrusion, k as stringifyVmlOval, kt as stringifyVmlDiagram, l as nextVmlShapeId, lt as parseVmlFill, m as parseVmlImage, mt as parseVmlCallout, n as parseVmlColorMru, nt as stringifyVmlPath, o as stringifyVmlColorMru, ot as stringifyVmlHandles, p as parseVmlGroup, pt as EXT_ATTR, q as parseVmlStroke, qt as stringifyVmlTrueFalseBlank, r as parseVmlShapeDefaults, rt as parseVmlImageData, s as stringifyVmlShapeDefaults, st as parseVmlFormulas, t as parseVmlColorMenu, tt as parseVmlPath, u as parseVmlArc, ut as stringifyVmlFill, v as parseVmlRect, vt as parseVmlEquationXml, w as stringifyVmlBackground, wt as parseVmlSignatureLine, x as parseVmlShapeChild, xt as parseVmlLock, y as parseVmlRoundRect, yt as parseVmlExtrusion, z as parseVmlWrap, zt as VML_OFFICE_CORE_ATTRS } from "./vector-DhLGZjP5.mjs";
|
|
11
|
+
import { a as buildThemeXml, i as createThemeXml, n as themeOverrideDesc, o as DEFAULT_COLORS, r as themeDesc, t as themeManagerDesc } from "./theme-BKnXRmvn.mjs";
|
|
12
|
+
import { attr, escapeXml, parse as parse$1, stringify as stringify$1, textOf } from "@office-open/xml";
|
|
13
|
+
import { strFromU8 as strFromU8$1, strToU8, unzipSync as unzipSync$1, zipSync as zipSync$1 } from "fflate";
|
|
11
14
|
//#region src/opc/relationships.ts
|
|
12
15
|
const TargetModeType = { EXTERNAL: "External" };
|
|
13
16
|
/**
|
|
@@ -26,9 +29,107 @@ var Relationships = class {
|
|
|
26
29
|
targetMode
|
|
27
30
|
});
|
|
28
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Register a relationship with an auto-allocated sequential id and return
|
|
34
|
+
* the numeric id. Prefer this over the `relationshipCount + 1` +
|
|
35
|
+
* `addRelationship` pair at every call site that wants the next id; reach
|
|
36
|
+
* for `addRelationship` directly only when the id is externally determined
|
|
37
|
+
* (a contiguous batch pre-computed from an offset, a fixed rId1, …).
|
|
38
|
+
*
|
|
39
|
+
* The id is max(existing) + 1, not count + 1 — externally-determined ids
|
|
40
|
+
* (passthrough source ids) can leave gaps, and a gap-following count-based
|
|
41
|
+
* id would collide with an existing entry (duplicate Relationship ids
|
|
42
|
+
* corrupt the package for Office applications).
|
|
43
|
+
*/
|
|
44
|
+
add(type, target, targetMode) {
|
|
45
|
+
const id = this.nextRelationshipId;
|
|
46
|
+
this.entries.push({
|
|
47
|
+
id: `rId${id}`,
|
|
48
|
+
type,
|
|
49
|
+
target,
|
|
50
|
+
targetMode
|
|
51
|
+
});
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
29
54
|
get relationshipCount() {
|
|
30
55
|
return this.entries.length;
|
|
31
56
|
}
|
|
57
|
+
/** The next free numeric id (max existing + 1) — the safe offset base when
|
|
58
|
+
* externally-determined ids (passthrough source ids) leave gaps below it. */
|
|
59
|
+
get nextRelationshipId() {
|
|
60
|
+
let max = 0;
|
|
61
|
+
for (const e of this.entries) {
|
|
62
|
+
const n = /^rId(\d+)$/.exec(e.id);
|
|
63
|
+
if (n) max = Math.max(max, Number(n[1]));
|
|
64
|
+
}
|
|
65
|
+
return max + 1;
|
|
66
|
+
}
|
|
67
|
+
/** Rename the first entry matching `type` to `newId` — used to promote a
|
|
68
|
+
* structured rel (e.g. the slide layout) to its source id when the
|
|
69
|
+
* source rId is free. No-op when the slot is taken or no match. */
|
|
70
|
+
renameEntryByType(type, newId) {
|
|
71
|
+
if (this.hasId(`rId${newId}`)) return;
|
|
72
|
+
const entry = this.entries.find((e) => e.type === type);
|
|
73
|
+
if (entry) entry.id = `rId${newId}`;
|
|
74
|
+
}
|
|
75
|
+
/** Numeric id of the first entry matching `kind` (last segment of the type
|
|
76
|
+
* URI), or undefined when none is registered. */
|
|
77
|
+
idByKind(kind) {
|
|
78
|
+
const entry = this.entries.find((e) => e.type.split("/").pop() === kind);
|
|
79
|
+
if (!entry) return void 0;
|
|
80
|
+
const m = /^rId(\d+)$/.exec(entry.id);
|
|
81
|
+
if (!m) return void 0;
|
|
82
|
+
return Number(m[1]);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Claim a captured source relationship (round-trip pre-claim). Verbatim
|
|
86
|
+
* part content references the source rIds, so re-emit the rel at its exact
|
|
87
|
+
* source id whenever that slot is still free — renumbering would dangle
|
|
88
|
+
* those references. Skips rels already registered under the same
|
|
89
|
+
* kind+target (the model absorbed them); falls back to an auto id for
|
|
90
|
+
* non-numeric source ids.
|
|
91
|
+
*/
|
|
92
|
+
claimSourceRel(rel) {
|
|
93
|
+
if (this.hasRelationship(rel.relationshipType, rel.target)) return;
|
|
94
|
+
const numeric = /^rId(\d+)$/.exec(rel.rId);
|
|
95
|
+
if (numeric && !this.hasId(rel.rId)) this.addRelationship(Number(numeric[1]), rel.relationshipType, rel.target, rel.targetMode);
|
|
96
|
+
else this.add(rel.relationshipType, rel.target, rel.targetMode);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* True when a relationship of the same kind and target is already
|
|
100
|
+
* registered. The kind compares only the relationship type's last path
|
|
101
|
+
* segment, so the transitional and strict URI forms of the same
|
|
102
|
+
* relationship compare equal — passthrough re-emission uses this to skip
|
|
103
|
+
* relationships the compiler already wired (a duplicate entry corrupts the
|
|
104
|
+
* package for Office applications).
|
|
105
|
+
*/
|
|
106
|
+
hasRelationship(type, target) {
|
|
107
|
+
const kind = type.split("/").pop();
|
|
108
|
+
return this.entries.some((e) => e.type.split("/").pop() === kind && e.target === target);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* True when any entry carries the relationship kind (last type segment).
|
|
112
|
+
* Round-trip re-emission uses this as the ownership test: a rebuilt part
|
|
113
|
+
* that already registered a rel of this kind absorbed the concept, so the
|
|
114
|
+
* captured source rel (possibly a renamed target or the ISO-strict type
|
|
115
|
+
* dual) must not be re-emitted alongside it.
|
|
116
|
+
*/
|
|
117
|
+
hasRelationshipKind(kind) {
|
|
118
|
+
return this.entries.some((e) => e.type.split("/").pop() === kind);
|
|
119
|
+
}
|
|
120
|
+
/** True when an entry already occupies this exact relationship id. */
|
|
121
|
+
hasId(id) {
|
|
122
|
+
return this.entries.some((e) => e.id === id);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The id of the entry matching kind+target (same last-path-segment equality
|
|
126
|
+
* as {@link hasRelationship}), or undefined when absent. Round-trip legs use
|
|
127
|
+
* this to point a reference element at an already-registered relationship.
|
|
128
|
+
*/
|
|
129
|
+
idOf(type, target) {
|
|
130
|
+
const kind = type.split("/").pop();
|
|
131
|
+
return this.entries.find((e) => e.type.split("/").pop() === kind && e.target === target)?.id;
|
|
132
|
+
}
|
|
32
133
|
/** Directly builds XML string — zero intermediate tree allocation. */
|
|
33
134
|
serialize() {
|
|
34
135
|
const p = ["<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"];
|
|
@@ -57,9 +158,63 @@ function optionalRelsPart(rel, xmlDeclaration, path) {
|
|
|
57
158
|
path
|
|
58
159
|
} : void 0;
|
|
59
160
|
}
|
|
161
|
+
/** Build the package root relationships shared by docx, pptx, and xlsx. */
|
|
162
|
+
function buildRootRelationships(mainPartTarget, includeCustomProperties, passthroughRelationships) {
|
|
163
|
+
const rels = new Relationships();
|
|
164
|
+
rels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", mainPartTarget);
|
|
165
|
+
rels.addRelationship(2, "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", "docProps/core.xml");
|
|
166
|
+
rels.addRelationship(3, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", "docProps/app.xml");
|
|
167
|
+
if (includeCustomProperties) rels.addRelationship(4, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties", "docProps/custom.xml");
|
|
168
|
+
for (const rel of passthroughRelationships ?? []) {
|
|
169
|
+
if (rel.source !== "") continue;
|
|
170
|
+
if (rels.hasRelationship(rel.relationshipType, rel.target)) continue;
|
|
171
|
+
rels.add(rel.relationshipType, rel.target, rel.targetMode);
|
|
172
|
+
}
|
|
173
|
+
return rels;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Derive the .rels part path for a package part:
|
|
177
|
+
* "ppt/slides/slide1.xml" → "ppt/slides/_rels/slide1.xml.rels".
|
|
178
|
+
*/
|
|
179
|
+
function partPathToRelsPath(partPath) {
|
|
180
|
+
const idx = partPath.lastIndexOf("/");
|
|
181
|
+
return `${partPath.substring(0, idx)}/_rels/${partPath.substring(idx + 1)}.rels`;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Resolve a relationship target against the referencing part's directory,
|
|
185
|
+
* segment by segment: each ".." pops one directory level. A single
|
|
186
|
+
* String.replace("../", …) only strips the first occurrence and mis-resolves
|
|
187
|
+
* deeper targets like "../../media/image.png".
|
|
188
|
+
*/
|
|
189
|
+
function resolveRelationshipTarget(partPath, target) {
|
|
190
|
+
if (target.startsWith("/")) return target.slice(1);
|
|
191
|
+
const dir = partPath.substring(0, partPath.lastIndexOf("/"));
|
|
192
|
+
const dirParts = dir ? dir.split("/") : [];
|
|
193
|
+
for (const part of target.split("/")) if (part === "..") dirParts.pop();
|
|
194
|
+
else if (part !== "." && part !== "") dirParts.push(part);
|
|
195
|
+
return dirParts.join("/");
|
|
196
|
+
}
|
|
60
197
|
//#endregion
|
|
61
198
|
//#region src/opc/media.ts
|
|
62
199
|
/**
|
|
200
|
+
* Content-deduplicated media collection for OOXML packages.
|
|
201
|
+
*
|
|
202
|
+
* Stores image entries keyed by file name. `addMedia` deduplicates by raw byte
|
|
203
|
+
* content — byte-identical images referenced N times share one file, while
|
|
204
|
+
* per-image metadata (transformation, extent, fallback) stays with each
|
|
205
|
+
* reference in its own drawing XML and is passed via the `build` callback so it
|
|
206
|
+
* never participates in the dedup key.
|
|
207
|
+
*
|
|
208
|
+
* Lookup is O(1) amortized: a `WeakMap` memoizes the resolved entry per input
|
|
209
|
+
* `Uint8Array` (the hot path — a single document reuses the same buffer object
|
|
210
|
+
* for repeated references), and a content-hash index (native CRC-32 where
|
|
211
|
+
* available, FNV-1a fallback) resolves cross-object duplicates (e.g. a
|
|
212
|
+
* freshly-decoded buffer carrying bytes already seen) with a one-time byte
|
|
213
|
+
* verification to rule out hash collisions.
|
|
214
|
+
*
|
|
215
|
+
* @module
|
|
216
|
+
*/
|
|
217
|
+
/**
|
|
63
218
|
* FNV-1a hash is a pure function of the bytes, so memoize it across
|
|
64
219
|
* {@link Media} instances — repeated `generate()` calls that reuse the same
|
|
65
220
|
* buffer objects (the common case) skip recomputation entirely.
|
|
@@ -116,16 +271,27 @@ var Media = class {
|
|
|
116
271
|
while (this.map.has(name)) name = `image${++this.counter}.${type}`;
|
|
117
272
|
return name;
|
|
118
273
|
}
|
|
119
|
-
/**
|
|
274
|
+
/**
|
|
275
|
+
* "length:hash" content key for `data`, memoized. Native CRC-32
|
|
276
|
+
* (`zlib.crc32`) on Node/Bun — ~59× faster than JS hashing on 100 MB inputs;
|
|
277
|
+
* FNV-1a fallback where no native zlib resolved. Both are 32-bit candidate
|
|
278
|
+
* keys; the byte verification in `addMedia` rules out collisions, so the
|
|
279
|
+
* weaker hash needs no collision handling of its own.
|
|
280
|
+
*/
|
|
120
281
|
contentKey(data) {
|
|
121
282
|
const cached = hashKeyCache.get(data);
|
|
122
283
|
if (cached !== void 0) return cached;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
284
|
+
const native = nativeCrc32(data);
|
|
285
|
+
let key;
|
|
286
|
+
if (native !== void 0) key = `${data.length}:${(native >>> 0).toString(16)}`;
|
|
287
|
+
else {
|
|
288
|
+
let hash = 2166136261;
|
|
289
|
+
for (const byte of data) {
|
|
290
|
+
hash ^= byte;
|
|
291
|
+
hash = Math.imul(hash, 16777619);
|
|
292
|
+
}
|
|
293
|
+
key = `${data.length}:${(hash >>> 0).toString(16)}`;
|
|
127
294
|
}
|
|
128
|
-
const key = `${data.length}:${(hash >>> 0).toString(16)}`;
|
|
129
295
|
hashKeyCache.set(data, key);
|
|
130
296
|
return key;
|
|
131
297
|
}
|
|
@@ -141,15 +307,185 @@ var Media = class {
|
|
|
141
307
|
}
|
|
142
308
|
};
|
|
143
309
|
//#endregion
|
|
144
|
-
//#region src/opc/
|
|
310
|
+
//#region src/opc/embeddings.ts
|
|
145
311
|
/**
|
|
146
|
-
*
|
|
312
|
+
* Collects OLE embeddings allocated during document generation. Each embedding
|
|
313
|
+
* is stored under a sequential `oleObjectN.bin` name, mirroring MS Office's
|
|
314
|
+
* numbering so output is deterministic and diffable.
|
|
147
315
|
*/
|
|
148
|
-
|
|
316
|
+
var EmbeddingCollection = class {
|
|
317
|
+
map = /* @__PURE__ */ new Map();
|
|
318
|
+
counter = 0;
|
|
319
|
+
/** Allocate the next sequential embedding file name (oleObject1.bin, …). */
|
|
320
|
+
nextEmbeddingName() {
|
|
321
|
+
let name = `oleObject${++this.counter}.bin`;
|
|
322
|
+
while (this.map.has(name)) name = `oleObject${++this.counter}.bin`;
|
|
323
|
+
return name;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Register embedding bytes and return the stored entry. The requested name
|
|
327
|
+
* is used when free or already claimed by identical bytes (two objects
|
|
328
|
+
* sharing one embedded part); a name claimed by different bytes falls back
|
|
329
|
+
* to a fresh sequential name — overwriting would silently drop the other
|
|
330
|
+
* object's payload.
|
|
331
|
+
*/
|
|
332
|
+
addEmbedding(data, requestedName, progId, relationshipType) {
|
|
333
|
+
const requested = requestedName ?? this.nextEmbeddingName();
|
|
334
|
+
const extras = {
|
|
335
|
+
...progId !== void 0 ? { progId } : {},
|
|
336
|
+
...relationshipType !== void 0 ? { relationshipType } : {}
|
|
337
|
+
};
|
|
338
|
+
const existing = this.map.get(requested);
|
|
339
|
+
if (existing) {
|
|
340
|
+
if (this.byteEqual(existing.data, data)) return existing;
|
|
341
|
+
const fallbackName = this.nextEmbeddingName();
|
|
342
|
+
const entry = {
|
|
343
|
+
fileName: fallbackName,
|
|
344
|
+
data,
|
|
345
|
+
...extras
|
|
346
|
+
};
|
|
347
|
+
this.map.set(fallbackName, entry);
|
|
348
|
+
return entry;
|
|
349
|
+
}
|
|
350
|
+
const entry = {
|
|
351
|
+
fileName: requested,
|
|
352
|
+
data,
|
|
353
|
+
...extras
|
|
354
|
+
};
|
|
355
|
+
this.map.set(requested, entry);
|
|
356
|
+
return entry;
|
|
357
|
+
}
|
|
358
|
+
/** All registered embeddings in insertion order. */
|
|
359
|
+
get array() {
|
|
360
|
+
return [...this.map.values()];
|
|
361
|
+
}
|
|
362
|
+
byteEqual(a, b) {
|
|
363
|
+
if (a.length !== b.length) return false;
|
|
364
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
//#endregion
|
|
369
|
+
//#region src/opc/variant-types.ts
|
|
370
|
+
/**
|
|
371
|
+
* Variant value types (vt:*) — shared vocabulary for the docProps parts.
|
|
372
|
+
*
|
|
373
|
+
* custom.xml property values and app.xml vectors (HeadingPairs,
|
|
374
|
+
* TitlesOfParts) are expressed with the vt:* element set defined in
|
|
375
|
+
* shared-documentPropertiesVariantTypes.xsd. JS values map as:
|
|
376
|
+
* string → vt:lpwstr, boolean → vt:bool, Date → vt:filetime, integers →
|
|
377
|
+
* vt:i4, other numbers → vt:r8.
|
|
378
|
+
*
|
|
379
|
+
* The two domains spell strings differently and Excel enforces the split:
|
|
380
|
+
* app.xml vectors (CT_VectorLpstr) must carry vt:lpstr — Excel refuses to
|
|
381
|
+
* open a file whose HeadingPairs/TitlesOfParts use vt:lpwstr — while
|
|
382
|
+
* custom.xml property values use vt:lpwstr, the spelling Office itself
|
|
383
|
+
* writes there.
|
|
384
|
+
*
|
|
385
|
+
* @module
|
|
386
|
+
*/
|
|
387
|
+
/** Numeric vt:* tags parsed back to a JS number. */
|
|
388
|
+
const NUMERIC_VT_TAGS = /* @__PURE__ */ new Set([
|
|
389
|
+
"vt:i1",
|
|
390
|
+
"vt:i2",
|
|
391
|
+
"vt:i4",
|
|
392
|
+
"vt:i8",
|
|
393
|
+
"vt:ui1",
|
|
394
|
+
"vt:ui2",
|
|
395
|
+
"vt:ui4",
|
|
396
|
+
"vt:ui8",
|
|
397
|
+
"vt:int",
|
|
398
|
+
"vt:uint",
|
|
399
|
+
"vt:r4",
|
|
400
|
+
"vt:r8",
|
|
401
|
+
"vt:decimal"
|
|
402
|
+
]);
|
|
403
|
+
/** Every scalar vt:* element stringifyVariantValue can emit. */
|
|
404
|
+
const VT_TAGS = /* @__PURE__ */ new Set([
|
|
405
|
+
...NUMERIC_VT_TAGS,
|
|
406
|
+
"vt:lpwstr",
|
|
407
|
+
"vt:lpstr",
|
|
408
|
+
"vt:bstr",
|
|
409
|
+
"vt:bool",
|
|
410
|
+
"vt:date",
|
|
411
|
+
"vt:filetime"
|
|
412
|
+
]);
|
|
413
|
+
/** The vt:* element the default JS mapping picks for a value. */
|
|
414
|
+
function defaultVariantTag(value) {
|
|
415
|
+
if (typeof value === "string") return "vt:lpwstr";
|
|
416
|
+
if (typeof value === "boolean") return "vt:bool";
|
|
417
|
+
if (value instanceof Date) return "vt:filetime";
|
|
418
|
+
return Number.isInteger(value) ? "vt:i4" : "vt:r8";
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Serialize a JS value as its vt:* element (stringify side, custom.xml domain).
|
|
422
|
+
*
|
|
423
|
+
* Strings stay lpwstr (the spelling Office writes for custom property
|
|
424
|
+
* values), integers become i4, other numbers r8, booleans bool, and Dates
|
|
425
|
+
* filetime (xsd:dateTime form). A `sourceTag` captured at parse overrides the
|
|
426
|
+
* default mapping so a source spelling the mapping would rewrite (an integer
|
|
427
|
+
* carried as vt:r8, an lpstr string) round-trips unchanged.
|
|
428
|
+
*/
|
|
429
|
+
function stringifyVariantValue(value, sourceTag) {
|
|
430
|
+
const tag = sourceTag !== void 0 && VT_TAGS.has(sourceTag) ? sourceTag : defaultVariantTag(value);
|
|
431
|
+
let inner;
|
|
432
|
+
if (tag === "vt:bool") inner = value ? "true" : "false";
|
|
433
|
+
else if (tag === "vt:date" || tag === "vt:filetime") inner = value instanceof Date ? value.toISOString() : String(value);
|
|
434
|
+
else if (typeof value === "string") inner = escapeXml(value);
|
|
435
|
+
else inner = String(value);
|
|
436
|
+
return `<${tag}>${inner}</${tag}>`;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Parse a vt:* scalar element back to a JS value (parse side).
|
|
440
|
+
*
|
|
441
|
+
* Lenient about unknown tags: they round-trip as their text content, the
|
|
442
|
+
* same fallback the previous string-only custom-properties parse used.
|
|
443
|
+
*/
|
|
444
|
+
function parseVariantValue(el) {
|
|
445
|
+
const text = textOf(el);
|
|
446
|
+
switch (el.name) {
|
|
447
|
+
case "vt:lpwstr":
|
|
448
|
+
case "vt:lpstr":
|
|
449
|
+
case "vt:bstr": return text;
|
|
450
|
+
case "vt:bool": return parseOnOff(text) ?? false;
|
|
451
|
+
case "vt:date":
|
|
452
|
+
case "vt:filetime": return text ? new Date(text) : void 0;
|
|
453
|
+
default:
|
|
454
|
+
if (NUMERIC_VT_TAGS.has(el.name ?? "")) return text === "" ? void 0 : Number(text);
|
|
455
|
+
return text || void 0;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
149
458
|
/**
|
|
150
|
-
*
|
|
459
|
+
* Serialize a vt:vector of lpstr entries (the TitlesOfParts shape).
|
|
460
|
+
* lpstr is required: Excel refuses to open a file whose app.xml vectors
|
|
461
|
+
* carry lpwstr (CT_VectorLpstr).
|
|
151
462
|
*/
|
|
152
|
-
|
|
463
|
+
function stringifyStringVector(values) {
|
|
464
|
+
const items = values.map((v) => `<vt:lpstr>${escapeXml(v)}</vt:lpstr>`).join("");
|
|
465
|
+
return `<vt:vector size="${values.length}" baseType="lpstr">${items}</vt:vector>`;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Serialize a vt:vector of variant entries (the HLinks shape). Each value
|
|
469
|
+
* keeps the element spelling stringifyVariantValue maps it to, wrapped in a
|
|
470
|
+
* vt:variant carrier — round-trips whatever int/string mix the source carried.
|
|
471
|
+
*/
|
|
472
|
+
function stringifyVariantVector(values) {
|
|
473
|
+
const items = values.map((v) => `<vt:variant>${stringifyVariantValue(v)}</vt:variant>`).join("");
|
|
474
|
+
return `<vt:vector size="${values.length}" baseType="variant">${items}</vt:vector>`;
|
|
475
|
+
}
|
|
476
|
+
/** Parse a vt:vector with any scalar baseType into its JS values. */
|
|
477
|
+
function parseVector(el) {
|
|
478
|
+
if (!el || el.name !== "vt:vector") return [];
|
|
479
|
+
const out = [];
|
|
480
|
+
for (const child of el.elements ?? []) {
|
|
481
|
+
if (child.type !== "element") continue;
|
|
482
|
+
const scalar = child.name === "vt:variant" ? child.elements?.find((e) => e.name?.startsWith("vt:")) : child;
|
|
483
|
+
if (!scalar) continue;
|
|
484
|
+
const value = parseVariantValue(scalar);
|
|
485
|
+
if (value !== void 0) out.push(value);
|
|
486
|
+
}
|
|
487
|
+
return out;
|
|
488
|
+
}
|
|
153
489
|
//#endregion
|
|
154
490
|
//#region src/opc/app-properties.ts
|
|
155
491
|
/**
|
|
@@ -166,46 +502,56 @@ const xsdBoolean = (value) => value ? "true" : "false";
|
|
|
166
502
|
const appPropertiesDesc = {
|
|
167
503
|
kind: "custom",
|
|
168
504
|
stringify(opts, _ctx) {
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
if (opts.
|
|
172
|
-
if (opts.
|
|
173
|
-
if (opts.
|
|
174
|
-
if (opts.
|
|
175
|
-
if (opts.
|
|
176
|
-
if (opts.
|
|
177
|
-
if (opts.
|
|
178
|
-
if (opts.
|
|
179
|
-
if (opts.
|
|
180
|
-
if (opts.
|
|
181
|
-
if (opts.
|
|
182
|
-
if (opts.
|
|
183
|
-
if (opts.
|
|
184
|
-
if (opts.
|
|
185
|
-
if (opts.
|
|
186
|
-
if (opts.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (opts.
|
|
191
|
-
if (opts.
|
|
192
|
-
p.push("
|
|
505
|
+
const t = (name) => opts.apPrefix ? `ap:${name}` : name;
|
|
506
|
+
const p = opts.apPrefix ? ["<ap:Properties xmlns:ap=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"] : ["<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"];
|
|
507
|
+
if (opts.template !== void 0) p.push(`<${t("Template")}>${escapeXml(opts.template)}</${t("Template")}>`);
|
|
508
|
+
if (opts.manager !== void 0) p.push(`<${t("Manager")}>${escapeXml(opts.manager)}</${t("Manager")}>`);
|
|
509
|
+
if (opts.company !== void 0) p.push(`<${t("Company")}>${escapeXml(opts.company)}</${t("Company")}>`);
|
|
510
|
+
if (opts.pages !== void 0) p.push(`<${t("Pages")}>${opts.pages}</${t("Pages")}>`);
|
|
511
|
+
if (opts.words !== void 0) p.push(`<${t("Words")}>${opts.words}</${t("Words")}>`);
|
|
512
|
+
if (opts.characters !== void 0) p.push(`<${t("Characters")}>${opts.characters}</${t("Characters")}>`);
|
|
513
|
+
if (opts.presentationFormat !== void 0) p.push(`<${t("PresentationFormat")}>${escapeXml(opts.presentationFormat)}</${t("PresentationFormat")}>`);
|
|
514
|
+
if (opts.lines !== void 0) p.push(`<${t("Lines")}>${opts.lines}</${t("Lines")}>`);
|
|
515
|
+
if (opts.paragraphs !== void 0) p.push(`<${t("Paragraphs")}>${opts.paragraphs}</${t("Paragraphs")}>`);
|
|
516
|
+
if (opts.slides !== void 0) p.push(`<${t("Slides")}>${opts.slides}</${t("Slides")}>`);
|
|
517
|
+
if (opts.notes !== void 0) p.push(`<${t("Notes")}>${opts.notes}</${t("Notes")}>`);
|
|
518
|
+
if (opts.totalTime !== void 0) p.push(`<${t("TotalTime")}>${opts.totalTime}</${t("TotalTime")}>`);
|
|
519
|
+
if (opts.hiddenSlides !== void 0) p.push(`<${t("HiddenSlides")}>${opts.hiddenSlides}</${t("HiddenSlides")}>`);
|
|
520
|
+
if (opts.mmClips !== void 0) p.push(`<${t("MMClips")}>${opts.mmClips}</${t("MMClips")}>`);
|
|
521
|
+
if (opts.scaleCrop !== void 0) p.push(`<${t("ScaleCrop")}>${xsdBoolean(opts.scaleCrop)}</${t("ScaleCrop")}>`);
|
|
522
|
+
if (opts.headingPairs !== void 0 && opts.headingPairs.length > 0) {
|
|
523
|
+
const items = opts.headingPairs.map((pair) => `<vt:variant><vt:lpstr>${escapeXml(pair.name)}</vt:lpstr></vt:variant><vt:variant><vt:i4>${pair.count}</vt:i4></vt:variant>`).join("");
|
|
524
|
+
p.push(`<${t("HeadingPairs")}><vt:vector size="${opts.headingPairs.length * 2}" baseType="variant">${items}</vt:vector></${t("HeadingPairs")}>`);
|
|
525
|
+
}
|
|
526
|
+
if (opts.titlesOfParts !== void 0 && opts.titlesOfParts.length > 0) p.push(`<${t("TitlesOfParts")}>${stringifyStringVector(opts.titlesOfParts)}</${t("TitlesOfParts")}>`);
|
|
527
|
+
if (opts.linksUpToDate !== void 0) p.push(`<${t("LinksUpToDate")}>${xsdBoolean(opts.linksUpToDate)}</${t("LinksUpToDate")}>`);
|
|
528
|
+
if (opts.charactersWithSpaces !== void 0) p.push(`<${t("CharactersWithSpaces")}>${opts.charactersWithSpaces}</${t("CharactersWithSpaces")}>`);
|
|
529
|
+
if (opts.sharedDoc !== void 0) p.push(`<${t("SharedDoc")}>${xsdBoolean(opts.sharedDoc)}</${t("SharedDoc")}>`);
|
|
530
|
+
if (opts.hyperlinkBase !== void 0) p.push(`<${t("HyperlinkBase")}>${escapeXml(opts.hyperlinkBase)}</${t("HyperlinkBase")}>`);
|
|
531
|
+
if (opts.hlinks !== void 0 && opts.hlinks.length > 0) p.push(`<${t("HLinks")}>${stringifyVariantVector(opts.hlinks)}</${t("HLinks")}>`);
|
|
532
|
+
if (opts.hyperlinksChanged !== void 0) p.push(`<${t("HyperlinksChanged")}>${xsdBoolean(opts.hyperlinksChanged)}</${t("HyperlinksChanged")}>`);
|
|
533
|
+
if (opts.application !== void 0) p.push(`<${t("Application")}>${escapeXml(opts.application)}</${t("Application")}>`);
|
|
534
|
+
if (opts.appVersion !== void 0) p.push(`<${t("AppVersion")}>${escapeXml(opts.appVersion)}</${t("AppVersion")}>`);
|
|
535
|
+
if (opts.docSecurity !== void 0) p.push(`<${t("DocSecurity")}>${opts.docSecurity}</${t("DocSecurity")}>`);
|
|
536
|
+
p.push(opts.apPrefix ? "</ap:Properties>" : "</Properties>");
|
|
193
537
|
return p.join("");
|
|
194
538
|
},
|
|
195
539
|
parse(el, _ctx) {
|
|
196
540
|
const result = {};
|
|
541
|
+
if (el.name === "ap:Properties") result.apPrefix = true;
|
|
197
542
|
for (const child of el.elements ?? []) {
|
|
198
543
|
if (typeof child.name !== "string") continue;
|
|
199
544
|
const text = child.elements?.[0]?.text;
|
|
200
|
-
|
|
545
|
+
const str = String(text ?? "");
|
|
546
|
+
switch (child.name.includes(":") ? child.name.slice(child.name.indexOf(":") + 1) : child.name) {
|
|
201
547
|
case "Template":
|
|
202
|
-
|
|
548
|
+
result.template = str;
|
|
203
549
|
break;
|
|
204
550
|
case "Manager":
|
|
205
|
-
|
|
551
|
+
result.manager = str;
|
|
206
552
|
break;
|
|
207
553
|
case "Company":
|
|
208
|
-
|
|
554
|
+
result.company = str;
|
|
209
555
|
break;
|
|
210
556
|
case "Pages":
|
|
211
557
|
if (typeof text === "string") result.pages = Number(text);
|
|
@@ -216,6 +562,9 @@ const appPropertiesDesc = {
|
|
|
216
562
|
case "Characters":
|
|
217
563
|
if (typeof text === "string") result.characters = Number(text);
|
|
218
564
|
break;
|
|
565
|
+
case "PresentationFormat":
|
|
566
|
+
result.presentationFormat = str;
|
|
567
|
+
break;
|
|
219
568
|
case "Lines":
|
|
220
569
|
if (typeof text === "string") result.lines = Number(text);
|
|
221
570
|
break;
|
|
@@ -237,33 +586,58 @@ const appPropertiesDesc = {
|
|
|
237
586
|
case "MMClips":
|
|
238
587
|
if (typeof text === "string") result.mmClips = Number(text);
|
|
239
588
|
break;
|
|
589
|
+
case "HeadingPairs": {
|
|
590
|
+
const vector = child.elements?.find((e) => e.name === "vt:vector");
|
|
591
|
+
const flat = parseVector(vector);
|
|
592
|
+
const pairs = [];
|
|
593
|
+
for (let i = 0; i + 1 < flat.length; i += 2) {
|
|
594
|
+
const name = flat[i];
|
|
595
|
+
const count = flat[i + 1];
|
|
596
|
+
if (typeof name === "string" && typeof count === "number") pairs.push({
|
|
597
|
+
name,
|
|
598
|
+
count
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
if (pairs.length > 0) result.headingPairs = pairs;
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
case "TitlesOfParts": {
|
|
605
|
+
const vector = child.elements?.find((e) => e.name === "vt:vector");
|
|
606
|
+
const titles = parseVector(vector).filter((v) => typeof v === "string");
|
|
607
|
+
if (titles.length > 0) result.titlesOfParts = titles;
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
240
610
|
case "ScaleCrop":
|
|
241
|
-
if (typeof text === "string") result.scaleCrop = text
|
|
611
|
+
if (typeof text === "string") result.scaleCrop = parseOnOff(text) ?? false;
|
|
242
612
|
break;
|
|
243
613
|
case "LinksUpToDate":
|
|
244
|
-
if (typeof text === "string") result.linksUpToDate = text
|
|
614
|
+
if (typeof text === "string") result.linksUpToDate = parseOnOff(text) ?? false;
|
|
245
615
|
break;
|
|
246
616
|
case "CharactersWithSpaces":
|
|
247
617
|
if (typeof text === "string") result.charactersWithSpaces = Number(text);
|
|
248
618
|
break;
|
|
249
619
|
case "SharedDoc":
|
|
250
|
-
if (typeof text === "string") result.sharedDoc = text
|
|
620
|
+
if (typeof text === "string") result.sharedDoc = parseOnOff(text) ?? false;
|
|
251
621
|
break;
|
|
252
622
|
case "HyperlinkBase":
|
|
253
|
-
|
|
623
|
+
result.hyperlinkBase = str;
|
|
624
|
+
break;
|
|
625
|
+
case "HLinks": {
|
|
626
|
+
const vector = child.elements?.find((e) => e.name === "vt:vector");
|
|
627
|
+
const values = parseVector(vector);
|
|
628
|
+
if (values.length > 0) result.hlinks = values;
|
|
254
629
|
break;
|
|
630
|
+
}
|
|
255
631
|
case "HyperlinksChanged":
|
|
256
|
-
if (typeof text === "string") result.hyperlinksChanged = text
|
|
632
|
+
if (typeof text === "string") result.hyperlinksChanged = parseOnOff(text) ?? false;
|
|
257
633
|
break;
|
|
258
634
|
case "Application":
|
|
259
|
-
|
|
635
|
+
result.application = str;
|
|
260
636
|
break;
|
|
261
637
|
case "AppVersion":
|
|
262
|
-
|
|
263
|
-
break;
|
|
264
|
-
case "DocSecurity":
|
|
265
|
-
if (typeof text === "string") result.docSecurity = Number(text);
|
|
638
|
+
result.appVersion = str;
|
|
266
639
|
break;
|
|
640
|
+
case "DocSecurity": if (typeof text === "string") result.docSecurity = Number(text);
|
|
267
641
|
}
|
|
268
642
|
}
|
|
269
643
|
return result;
|
|
@@ -285,7 +659,7 @@ const customPropertiesDesc = {
|
|
|
285
659
|
const p = ["<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">"];
|
|
286
660
|
let pid = 2;
|
|
287
661
|
for (const prop of opts.properties) {
|
|
288
|
-
p.push(`<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="${pid}" name="${escapeXml(prop.name)}"
|
|
662
|
+
p.push(`<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="${pid}" name="${escapeXml(prop.name)}">` + stringifyVariantValue(prop.value, prop.valueType) + `</property>`);
|
|
289
663
|
pid++;
|
|
290
664
|
}
|
|
291
665
|
p.push("</Properties>");
|
|
@@ -298,20 +672,262 @@ const customPropertiesDesc = {
|
|
|
298
672
|
const name = attr(child, "name");
|
|
299
673
|
if (!name) continue;
|
|
300
674
|
const valueEl = child.elements?.find((e) => e.name?.startsWith("vt:"));
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
675
|
+
if (valueEl) {
|
|
676
|
+
const value = parseVariantValue(valueEl);
|
|
677
|
+
if (value !== void 0) {
|
|
678
|
+
const prop = {
|
|
679
|
+
name,
|
|
680
|
+
value
|
|
681
|
+
};
|
|
682
|
+
if (valueEl.name && valueEl.name !== defaultVariantTag(value)) prop.valueType = valueEl.name;
|
|
683
|
+
properties.push(prop);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
306
686
|
}
|
|
307
687
|
return { properties };
|
|
308
688
|
}
|
|
309
689
|
};
|
|
310
690
|
//#endregion
|
|
691
|
+
//#region src/opc/encryption.ts
|
|
692
|
+
/** OLE2/CFB compound-file signature shared by every encrypted OOXML file. */
|
|
693
|
+
const CFB_SIGNATURE = [
|
|
694
|
+
208,
|
|
695
|
+
207,
|
|
696
|
+
17,
|
|
697
|
+
224,
|
|
698
|
+
161,
|
|
699
|
+
177,
|
|
700
|
+
26,
|
|
701
|
+
225
|
|
702
|
+
];
|
|
703
|
+
/** Whether `data` is an OLE2/CFB container — i.e. an encrypted OOXML file. */
|
|
704
|
+
function isEncryptedContainer(data) {
|
|
705
|
+
return data.length >= CFB_SIGNATURE.length && CFB_SIGNATURE.every((b, i) => data[i] === b);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Converted output for an encrypted-container file, or `undefined` when the
|
|
709
|
+
* options carry no encrypted payload (the normal compile path applies).
|
|
710
|
+
*/
|
|
711
|
+
function encryptedContainerOutput(file, type, mimeType) {
|
|
712
|
+
const { encrypted } = file;
|
|
713
|
+
if (!encrypted) return void 0;
|
|
714
|
+
return convertOutput(toUint8Array(encrypted.data), type, mimeType);
|
|
715
|
+
}
|
|
716
|
+
/** Streaming variant of {@link encryptedContainerOutput}. */
|
|
717
|
+
function encryptedContainerStream(file) {
|
|
718
|
+
const { encrypted } = file;
|
|
719
|
+
if (!encrypted) return void 0;
|
|
720
|
+
const bytes = toUint8Array(encrypted.data);
|
|
721
|
+
return new ReadableStream({ start(c) {
|
|
722
|
+
c.enqueue(bytes);
|
|
723
|
+
c.close();
|
|
724
|
+
} });
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Reject encrypted passthrough mixed with real content: generate() re-emits
|
|
728
|
+
* the encrypted bytes, so every other field would be silently dropped.
|
|
729
|
+
*
|
|
730
|
+
* `hasContent` is the package's primary content collection being non-empty
|
|
731
|
+
* (e.g. `sections.length > 0`) — callers know their own shape.
|
|
732
|
+
*/
|
|
733
|
+
function assertEncryptedExclusive(file, hasContent) {
|
|
734
|
+
if (file.encrypted && hasContent) throw new Error("Encrypted passthrough carries no editable content — clear the content fields or drop `encrypted`.");
|
|
735
|
+
}
|
|
736
|
+
//#endregion
|
|
737
|
+
//#region src/opc/namespaces.ts
|
|
738
|
+
/**
|
|
739
|
+
* Namespace URI → canonical prefix table for parse-time normalization.
|
|
740
|
+
*
|
|
741
|
+
* Producers are free to bind any prefix to a namespace (XML namespaces say
|
|
742
|
+
* the prefix is arbitrary), and real-world generators do: pandoc writes
|
|
743
|
+
* `ns0:`, ClosedXML binds the spreadsheet namespace to `x:`. Everything
|
|
744
|
+
* downstream of the parser — descriptor `findChild("w:p")` calls, registry
|
|
745
|
+
* path matching — addresses elements by the canonical prefixes this library
|
|
746
|
+
* itself emits, so non-canonical sources parsed blind.
|
|
747
|
+
*
|
|
748
|
+
* Feeding this table to the XML parser's `normalizeNamespaces` rewrites every
|
|
749
|
+
* element and attribute name onto the canonical prefix (an empty value means
|
|
750
|
+
* the canonical form is unprefixed — the sml and OPC namespaces), while
|
|
751
|
+
* unknown URIs keep their source prefix and `xmlns` declarations follow the
|
|
752
|
+
* rewrite so serialized output stays self-consistent.
|
|
753
|
+
*
|
|
754
|
+
* The table mirrors the prefixes this library's own stringify output uses —
|
|
755
|
+
* when a new namespace appears in a part template, add it here in the same
|
|
756
|
+
* change. Strict-OOXML variants (`purl.oclc.org`) are deliberately absent:
|
|
757
|
+
* mapping them would silently convert strict packages to transitional.
|
|
758
|
+
*/
|
|
759
|
+
const SCHEMAS_OPENXML = "http://schemas.openxmlformats.org";
|
|
760
|
+
const SCHEMAS_MS = "http://schemas.microsoft.com";
|
|
761
|
+
/**
|
|
762
|
+
* Obsolete namespace URIs accepted by Office and the Open XML SDK, mapped to
|
|
763
|
+
* their final standardized forms. A round-trip must normalize passthrough XML
|
|
764
|
+
* too: rebuilding modeled parts with the final URI while carrying an obsolete
|
|
765
|
+
* URI verbatim in a raw part creates a mixed-dialect package that Word rejects.
|
|
766
|
+
*
|
|
767
|
+
* Keep this aligned with Open XML SDK's OpenXmlNamespaceResolver
|
|
768
|
+
* `_extendedNamespaces` table.
|
|
769
|
+
*/
|
|
770
|
+
const OOXML_OBSOLETE_NAMESPACE_ALIASES = {
|
|
771
|
+
[`${SCHEMAS_OPENXML}/wordprocessingml/2006/3/main`]: `${SCHEMAS_OPENXML}/wordprocessingml/2006/main`,
|
|
772
|
+
[`${SCHEMAS_OPENXML}/wordprocessingml/2006/5/main`]: `${SCHEMAS_OPENXML}/wordprocessingml/2006/main`,
|
|
773
|
+
[`${SCHEMAS_OPENXML}/wordprocessingml/2006/6/main`]: `${SCHEMAS_OPENXML}/wordprocessingml/2006/main`,
|
|
774
|
+
[`${SCHEMAS_OPENXML}/spreadsheetml/2006/5/main`]: `${SCHEMAS_OPENXML}/spreadsheetml/2006/main`,
|
|
775
|
+
[`${SCHEMAS_OPENXML}/spreadsheetml/2006/7/main`]: `${SCHEMAS_OPENXML}/spreadsheetml/2006/main`,
|
|
776
|
+
[`${SCHEMAS_OPENXML}/presentationml/2006/3/main`]: `${SCHEMAS_OPENXML}/presentationml/2006/main`,
|
|
777
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/3/main`]: `${SCHEMAS_OPENXML}/drawingml/2006/main`,
|
|
778
|
+
[`${SCHEMAS_MS}/office/word/2010/11/wordml`]: `${SCHEMAS_MS}/office/word/2012/wordml`
|
|
779
|
+
};
|
|
780
|
+
/**
|
|
781
|
+
* Normalize obsolete OOXML namespace URI bytes without reparsing or
|
|
782
|
+
* reserializing the XML. Byte-level replacement preserves every other source
|
|
783
|
+
* detail (declaration, whitespace, prefix choices, attribute order, and line
|
|
784
|
+
* endings), which is required for passthrough parts.
|
|
785
|
+
*/
|
|
786
|
+
function normalizeObsoleteNamespaceAliases(data) {
|
|
787
|
+
let result = data;
|
|
788
|
+
for (const pattern of OBSOLETE_PATTERNS) result = replaceAsciiBytes(result, pattern);
|
|
789
|
+
return result;
|
|
790
|
+
}
|
|
791
|
+
function isNamespaceDeclarationValue(data, valueOffset, valueLength) {
|
|
792
|
+
const quote = data[valueOffset - 1];
|
|
793
|
+
if (quote !== 34 && quote !== 39 || data[valueOffset + valueLength] !== quote) return false;
|
|
794
|
+
let i = valueOffset - 2;
|
|
795
|
+
while (i >= 0 && (data[i] === 32 || data[i] === 9 || data[i] === 10 || data[i] === 13)) i--;
|
|
796
|
+
if (data[i] !== 61) return false;
|
|
797
|
+
i--;
|
|
798
|
+
while (i >= 0 && (data[i] === 32 || data[i] === 9 || data[i] === 10 || data[i] === 13)) i--;
|
|
799
|
+
const nameEnd = i + 1;
|
|
800
|
+
while (i >= 0 && (data[i] >= 65 && data[i] <= 90 || data[i] >= 97 && data[i] <= 122 || data[i] >= 48 && data[i] <= 57 || data[i] === 58 || data[i] === 45 || data[i] === 95)) i--;
|
|
801
|
+
const nameStart = i + 1;
|
|
802
|
+
const nameLen = nameEnd - nameStart;
|
|
803
|
+
if (nameLen < 5) return false;
|
|
804
|
+
for (let k = 0; k < 5; k++) if (data[nameStart + k] !== XMLNS_BYTES[k]) return false;
|
|
805
|
+
return nameLen === 5 || data[nameStart + 5] === 58;
|
|
806
|
+
}
|
|
807
|
+
/** "xmlns" as bytes — module constant so the hit-path compare allocates nothing. */
|
|
808
|
+
const XMLNS_BYTES = Uint8Array.from([
|
|
809
|
+
120,
|
|
810
|
+
109,
|
|
811
|
+
108,
|
|
812
|
+
110,
|
|
813
|
+
115
|
|
814
|
+
]);
|
|
815
|
+
function replaceAsciiBytes(data, pattern) {
|
|
816
|
+
const { needle, value } = pattern;
|
|
817
|
+
const positions = [];
|
|
818
|
+
const first = needle[0];
|
|
819
|
+
const lastStart = data.length - needle.length;
|
|
820
|
+
let i = data.indexOf(first);
|
|
821
|
+
while (i !== -1) {
|
|
822
|
+
if (i <= lastStart) {
|
|
823
|
+
let matches = true;
|
|
824
|
+
for (let j = 1; j < needle.length; j++) if (data[i + j] !== needle[j]) {
|
|
825
|
+
matches = false;
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
828
|
+
if (matches && isNamespaceDeclarationValue(data, i, needle.length)) {
|
|
829
|
+
positions.push(i);
|
|
830
|
+
i += needle.length - 1;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
i = data.indexOf(first, i + 1);
|
|
834
|
+
}
|
|
835
|
+
if (positions.length === 0) return data;
|
|
836
|
+
const out = new Uint8Array(data.length + positions.length * (value.length - needle.length));
|
|
837
|
+
let sourceOffset = 0;
|
|
838
|
+
let targetOffset = 0;
|
|
839
|
+
for (const position of positions) {
|
|
840
|
+
const prefix = data.subarray(sourceOffset, position);
|
|
841
|
+
out.set(prefix, targetOffset);
|
|
842
|
+
targetOffset += prefix.length;
|
|
843
|
+
out.set(value, targetOffset);
|
|
844
|
+
targetOffset += value.length;
|
|
845
|
+
sourceOffset = position + needle.length;
|
|
846
|
+
}
|
|
847
|
+
out.set(data.subarray(sourceOffset), targetOffset);
|
|
848
|
+
return out;
|
|
849
|
+
}
|
|
850
|
+
const OBSOLETE_PATTERNS = Object.entries(OOXML_OBSOLETE_NAMESPACE_ALIASES).map(([obsolete, finalUri]) => ({
|
|
851
|
+
needle: new TextEncoder().encode(obsolete),
|
|
852
|
+
value: new TextEncoder().encode(finalUri)
|
|
853
|
+
}));
|
|
854
|
+
const OOXML_CANONICAL_PREFIXES = {
|
|
855
|
+
...Object.fromEntries(Object.entries(OOXML_OBSOLETE_NAMESPACE_ALIASES).map(([oldUri, finalUri]) => [oldUri, finalUri === `${SCHEMAS_OPENXML}/spreadsheetml/2006/main` ? "" : finalUri === `${SCHEMAS_OPENXML}/presentationml/2006/main` ? "p" : finalUri === `${SCHEMAS_OPENXML}/drawingml/2006/main` ? "a" : finalUri === `${SCHEMAS_OPENXML}/wordprocessingml/2006/main` ? "w" : "w15"])),
|
|
856
|
+
[`${SCHEMAS_OPENXML}/wordprocessingml/2006/main`]: "w",
|
|
857
|
+
[`${SCHEMAS_OPENXML}/presentationml/2006/main`]: "p",
|
|
858
|
+
[`${SCHEMAS_OPENXML}/spreadsheetml/2006/main`]: "",
|
|
859
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/main`]: "a",
|
|
860
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/relationships`]: "r",
|
|
861
|
+
[`${SCHEMAS_OPENXML}/markup-compatibility/2006`]: "mc",
|
|
862
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/math`]: "m",
|
|
863
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/wordprocessingDrawing`]: "wp",
|
|
864
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/spreadsheetDrawing`]: "xdr",
|
|
865
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/chart`]: "c",
|
|
866
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/chartDrawing`]: "cdr",
|
|
867
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/diagram`]: "dgm",
|
|
868
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/lockedCanvas`]: "lc",
|
|
869
|
+
[`${SCHEMAS_OPENXML}/drawingml/2006/picture`]: "pic",
|
|
870
|
+
[`${SCHEMAS_OPENXML}/package/2006/relationships`]: "",
|
|
871
|
+
[`${SCHEMAS_OPENXML}/package/2006/content-types`]: "",
|
|
872
|
+
[`${SCHEMAS_OPENXML}/package/2006/metadata/core-properties`]: "",
|
|
873
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/extended-properties`]: "",
|
|
874
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/custom-properties`]: "",
|
|
875
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/docPropsVTypes`]: "vt",
|
|
876
|
+
[`${SCHEMAS_OPENXML}/officeDocument/2006/bibliography`]: "b",
|
|
877
|
+
"urn:schemas-microsoft-com:vml": "v",
|
|
878
|
+
"urn:schemas-microsoft-com:office:office": "o",
|
|
879
|
+
"urn:schemas-microsoft-com:office:word": "w10",
|
|
880
|
+
"urn:schemas-microsoft-com:office:excel": "x",
|
|
881
|
+
"urn:schemas-microsoft-com:office:powerpoint": "pvml",
|
|
882
|
+
[`${SCHEMAS_MS}/office/word/2006/wordml`]: "wne",
|
|
883
|
+
[`${SCHEMAS_MS}/office/word/2010/wordml`]: "w14",
|
|
884
|
+
[`${SCHEMAS_MS}/office/word/2010/11/wordml`]: "w15",
|
|
885
|
+
[`${SCHEMAS_MS}/office/word/2012/wordml`]: "w15",
|
|
886
|
+
[`${SCHEMAS_MS}/office/word/2016/wordml/cid`]: "w16cid",
|
|
887
|
+
[`${SCHEMAS_MS}/office/word/2018/wordml`]: "w16",
|
|
888
|
+
[`${SCHEMAS_MS}/office/word/2018/wordml/cex`]: "w16cex",
|
|
889
|
+
[`${SCHEMAS_MS}/office/word/2020/wordml/sdtdatahash`]: "w16sdtdh",
|
|
890
|
+
[`${SCHEMAS_MS}/office/word/2015/wordml/symex`]: "w16se",
|
|
891
|
+
[`${SCHEMAS_MS}/office/word/2010/wordprocessingDrawing`]: "wp14",
|
|
892
|
+
[`${SCHEMAS_MS}/office/word/2010/wordprocessingCanvas`]: "wpc",
|
|
893
|
+
[`${SCHEMAS_MS}/office/word/2010/wordprocessingGroup`]: "wpg",
|
|
894
|
+
[`${SCHEMAS_MS}/office/word/2010/wordprocessingInk`]: "wpi",
|
|
895
|
+
[`${SCHEMAS_MS}/office/word/2010/wordprocessingShape`]: "wps",
|
|
896
|
+
[`${SCHEMAS_MS}/office/drawing/2010/main`]: "a14",
|
|
897
|
+
[`${SCHEMAS_MS}/office/drawing/2014/main`]: "a16",
|
|
898
|
+
[`${SCHEMAS_MS}/office/drawing/2016/ink`]: "aink",
|
|
899
|
+
[`${SCHEMAS_MS}/office/drawing/2017/model3d`]: "am3d",
|
|
900
|
+
[`${SCHEMAS_MS}/office/drawing/2016/SVG/main`]: "asvg",
|
|
901
|
+
[`${SCHEMAS_MS}/office/drawing/2007/8/2/chart`]: "c14",
|
|
902
|
+
[`${SCHEMAS_MS}/office/drawing/2008/diagram`]: "dsp",
|
|
903
|
+
[`${SCHEMAS_MS}/office/drawing/2014/chartex`]: "cx",
|
|
904
|
+
[`${SCHEMAS_MS}/office/drawing/2015/9/8/chartex`]: "cx1",
|
|
905
|
+
[`${SCHEMAS_MS}/office/drawing/2015/10/21/chartex`]: "cx2",
|
|
906
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/9/chartex`]: "cx3",
|
|
907
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/10/chartex`]: "cx4",
|
|
908
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/11/chartex`]: "cx5",
|
|
909
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/12/chartex`]: "cx6",
|
|
910
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/13/chartex`]: "cx7",
|
|
911
|
+
[`${SCHEMAS_MS}/office/drawing/2016/5/14/chartex`]: "cx8",
|
|
912
|
+
[`${SCHEMAS_MS}/office/2019/extlst`]: "oel",
|
|
913
|
+
[`${SCHEMAS_MS}/office/powerpoint/2010/main`]: "p14",
|
|
914
|
+
[`${SCHEMAS_MS}/office/powerpoint/2015/main`]: "p15",
|
|
915
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2009/9/main`]: "x14",
|
|
916
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2009/9/ac`]: "x14ac",
|
|
917
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2010/11/main`]: "x15",
|
|
918
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2010/11/ac`]: "x15ac",
|
|
919
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2014/revision`]: "xr",
|
|
920
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2015/revision2`]: "xr2",
|
|
921
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2016/revision3`]: "xr3",
|
|
922
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2016/revision6`]: "xr6",
|
|
923
|
+
[`${SCHEMAS_MS}/office/spreadsheetml/2016/revision10`]: "xr10"
|
|
924
|
+
};
|
|
925
|
+
//#endregion
|
|
311
926
|
//#region src/opc/parser.ts
|
|
312
927
|
const XML_PARSE_OPTIONS = {
|
|
313
928
|
nativeTypeAttributes: true,
|
|
314
|
-
captureSpacesBetweenElements: true
|
|
929
|
+
captureSpacesBetweenElements: true,
|
|
930
|
+
normalizeNamespaces: OOXML_CANONICAL_PREFIXES
|
|
315
931
|
};
|
|
316
932
|
/**
|
|
317
933
|
* Parsed OOXML archive backed by an unzipped ZIP map.
|
|
@@ -332,11 +948,20 @@ var ParsedArchive = class {
|
|
|
332
948
|
}
|
|
333
949
|
this.zip = new Map(Object.entries(unzipped));
|
|
334
950
|
}
|
|
335
|
-
/**
|
|
336
|
-
|
|
951
|
+
/**
|
|
952
|
+
* Read an XML part as an Element tree. `parseOptions` extends the default
|
|
953
|
+
* XML parse options for this part (e.g. `deferElements` to capture a hot
|
|
954
|
+
* container's inner XML verbatim). Callers must use consistent options per
|
|
955
|
+
* path — the wrapper cache is keyed by path only.
|
|
956
|
+
*/
|
|
957
|
+
get(path, parseOptions) {
|
|
958
|
+
const opts = parseOptions ? {
|
|
959
|
+
...XML_PARSE_OPTIONS,
|
|
960
|
+
...parseOptions
|
|
961
|
+
} : XML_PARSE_OPTIONS;
|
|
337
962
|
const modData = this.modified.get(path);
|
|
338
963
|
if (modData) {
|
|
339
|
-
const wrapper =
|
|
964
|
+
const wrapper = parse$1(strFromU8$1(modData), opts);
|
|
340
965
|
this.wrapperCache.set(path, wrapper);
|
|
341
966
|
return wrapper.elements?.find((e) => e.type === "element");
|
|
342
967
|
}
|
|
@@ -344,14 +969,14 @@ var ParsedArchive = class {
|
|
|
344
969
|
if (data === void 0) return void 0;
|
|
345
970
|
const cached = this.wrapperCache.get(path);
|
|
346
971
|
if (cached) return cached.elements?.find((e) => e.type === "element");
|
|
347
|
-
const wrapper =
|
|
972
|
+
const wrapper = parse$1(strFromU8$1(data), opts);
|
|
348
973
|
this.wrapperCache.set(path, wrapper);
|
|
349
974
|
return wrapper.elements?.find((e) => e.type === "element");
|
|
350
975
|
}
|
|
351
976
|
/** Write an XML part (Element → XML string). */
|
|
352
977
|
set(path, element) {
|
|
353
978
|
const wrapper = this.wrapperCache.get(path);
|
|
354
|
-
const
|
|
979
|
+
const doc = wrapper ? {
|
|
355
980
|
...wrapper,
|
|
356
981
|
elements: [{
|
|
357
982
|
...element,
|
|
@@ -360,7 +985,8 @@ var ParsedArchive = class {
|
|
|
360
985
|
} : { elements: [{
|
|
361
986
|
...element,
|
|
362
987
|
type: "element"
|
|
363
|
-
}] }
|
|
988
|
+
}] };
|
|
989
|
+
const xml = stringify$1(doc);
|
|
364
990
|
this.modified.set(path, strToU8(xml));
|
|
365
991
|
}
|
|
366
992
|
/** Read raw binary data (images, media, etc.). */
|
|
@@ -391,34 +1017,11 @@ var ParsedArchive = class {
|
|
|
391
1017
|
/** Serialize back to a ZIP buffer, merging original zip + modifications. */
|
|
392
1018
|
save() {
|
|
393
1019
|
const files = {};
|
|
394
|
-
for (const [path, data] of this.zip) if (!this.modified.has(path)) files[path] =
|
|
395
|
-
for (const [path, data] of this.modified) files[path] =
|
|
396
|
-
return zipSync(files);
|
|
1020
|
+
for (const [path, data] of this.zip) if (!this.modified.has(path)) files[path] = [data, { level: levelForMediaName(path, 6) }];
|
|
1021
|
+
for (const [path, data] of this.modified) files[path] = [data, { level: levelForMediaName(path, 6) }];
|
|
1022
|
+
return zipSync$1(files);
|
|
397
1023
|
}
|
|
398
1024
|
};
|
|
399
|
-
/** Media file extensions that should use STORE (no compression). */
|
|
400
|
-
const MEDIA_EXTENSIONS = new Set([
|
|
401
|
-
".png",
|
|
402
|
-
".jpg",
|
|
403
|
-
".jpeg",
|
|
404
|
-
".gif",
|
|
405
|
-
".wmf",
|
|
406
|
-
".emf",
|
|
407
|
-
".tif",
|
|
408
|
-
".tiff",
|
|
409
|
-
".avi",
|
|
410
|
-
".mp4",
|
|
411
|
-
".mp3",
|
|
412
|
-
".wav"
|
|
413
|
-
]);
|
|
414
|
-
/** Check if a file path has a media extension that should use STORE (no compression). */
|
|
415
|
-
function isMediaPath(path) {
|
|
416
|
-
const dot = path.lastIndexOf(".");
|
|
417
|
-
if (dot === -1) return false;
|
|
418
|
-
return MEDIA_EXTENSIONS.has(path.slice(dot).toLowerCase());
|
|
419
|
-
}
|
|
420
|
-
/** STORE level for already-compressed media formats. */
|
|
421
|
-
const MEDIA_STORED_LEVEL = 0;
|
|
422
1025
|
/** Parse an OOXML archive (.docx, .pptx, .xlsx) into a ParsedArchive. */
|
|
423
1026
|
function parseArchive(data) {
|
|
424
1027
|
return new ParsedArchive(data);
|
|
@@ -431,13 +1034,14 @@ function parseArchive(data) {
|
|
|
431
1034
|
* Pure function operating on an already-unzipped part map. Detects the three
|
|
432
1035
|
* classes of cross-part breakage that single-part XSD validation cannot see:
|
|
433
1036
|
*
|
|
434
|
-
* - relationship integrity — dangling targets,
|
|
1037
|
+
* - relationship integrity — dangling targets, undeclared r:id references,
|
|
1038
|
+
* duplicate rIds (O3/O4/O7)
|
|
435
1039
|
* - content-type integrity — parts with no Override/Default, stale
|
|
436
1040
|
* Overrides pointing at absent parts (O5/O6)
|
|
437
1041
|
* - structural integrity — missing `always` parts, undeclared orphans
|
|
438
1042
|
* (O1/O2)
|
|
439
1043
|
*
|
|
440
|
-
* O3/O5/O6/O7 are derived directly from the ZIP + `.rels` + `[Content_Types].xml`
|
|
1044
|
+
* O3/O4/O5/O6/O7 are derived directly from the ZIP + `.rels` + `[Content_Types].xml`
|
|
441
1045
|
* and need no registry. O1/O2 consult {@link PackagePartRegistry}.
|
|
442
1046
|
*
|
|
443
1047
|
* Reference: ECMA-376 Part 2 (OPC).
|
|
@@ -446,7 +1050,7 @@ function parseArchive(data) {
|
|
|
446
1050
|
*/
|
|
447
1051
|
function rootElement(xml) {
|
|
448
1052
|
try {
|
|
449
|
-
return
|
|
1053
|
+
return parse$1(xml).elements?.find((e) => e.type === "element");
|
|
450
1054
|
} catch {
|
|
451
1055
|
return;
|
|
452
1056
|
}
|
|
@@ -526,11 +1130,25 @@ function pathMatcher(template) {
|
|
|
526
1130
|
const pattern = template.replace(/\$\{i\}/g, "\0").replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(//g, "(\\d+)");
|
|
527
1131
|
return new RegExp(`^${pattern}$`);
|
|
528
1132
|
}
|
|
529
|
-
function extensionOf(path) {
|
|
1133
|
+
function extensionOf$2(path) {
|
|
530
1134
|
const dot = path.lastIndexOf(".");
|
|
531
1135
|
return dot === -1 ? "" : path.slice(dot + 1).toLowerCase();
|
|
532
1136
|
}
|
|
533
1137
|
/**
|
|
1138
|
+
* Reference attributes in the officeDocument relationships namespace — every
|
|
1139
|
+
* one resolves against the owning part's `.rels`. Escaped text can never match
|
|
1140
|
+
* (a literal `"` in text is `"`), so hits are always real attributes.
|
|
1141
|
+
*/
|
|
1142
|
+
const REL_REF_ATTR_RE = /\br:(?:id|embed|link|dm|lo|qs|cs|pict)="([^"]*)"/g;
|
|
1143
|
+
/** `word/_rels/document.xml.rels` → `word/document.xml`; package rels → undefined. */
|
|
1144
|
+
function partOfRels(relsPath) {
|
|
1145
|
+
const slash = relsPath.lastIndexOf("/");
|
|
1146
|
+
const dir = slash === -1 ? "" : relsPath.slice(0, slash);
|
|
1147
|
+
const name = relsPath.slice(slash + 1).replace(/\.rels$/, "");
|
|
1148
|
+
if (dir === "_rels") return name === "" ? void 0 : name;
|
|
1149
|
+
if (dir.endsWith("/_rels")) return `${dir.slice(0, -6)}/${name}`;
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
534
1152
|
* Validate OPC consistency of an unzipped package.
|
|
535
1153
|
*
|
|
536
1154
|
* @param entries ZIP path → decoded XML/binary text. Binary parts (media,
|
|
@@ -576,10 +1194,35 @@ function validateOpcConsistency(entries, registry) {
|
|
|
576
1194
|
message: `relationship ${rel.id || "(no Id)"} (${rel.type}) Target "${rel.target}" resolves to absent part "${resolved}"`
|
|
577
1195
|
});
|
|
578
1196
|
}
|
|
1197
|
+
const relIdsByPart = /* @__PURE__ */ new Map();
|
|
1198
|
+
for (const rf of relsFiles) {
|
|
1199
|
+
const part = partOfRels(rf.relsPath);
|
|
1200
|
+
if (part === void 0) continue;
|
|
1201
|
+
const ids = relIdsByPart.get(part) ?? /* @__PURE__ */ new Set();
|
|
1202
|
+
for (const r of rf.entries) ids.add(r.id);
|
|
1203
|
+
relIdsByPart.set(part, ids);
|
|
1204
|
+
}
|
|
1205
|
+
for (const [path, xml] of entries) {
|
|
1206
|
+
if (path === "[Content_Types].xml" || path.endsWith(".rels") || !path.endsWith(".xml")) continue;
|
|
1207
|
+
const declared = relIdsByPart.get(path);
|
|
1208
|
+
const reported = /* @__PURE__ */ new Set();
|
|
1209
|
+
REL_REF_ATTR_RE.lastIndex = 0;
|
|
1210
|
+
for (let m = REL_REF_ATTR_RE.exec(xml); m; m = REL_REF_ATTR_RE.exec(xml)) {
|
|
1211
|
+
const ref = m[1];
|
|
1212
|
+
if (declared?.has(ref) || reported.has(ref)) continue;
|
|
1213
|
+
reported.add(ref);
|
|
1214
|
+
issues.push({
|
|
1215
|
+
code: "O4",
|
|
1216
|
+
severity: "error",
|
|
1217
|
+
part: path,
|
|
1218
|
+
message: `r:id/r:embed reference "${ref}" is not declared by the part's .rels`
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
579
1222
|
for (const path of entries.keys()) {
|
|
580
1223
|
if (path === "[Content_Types].xml" || path.endsWith(".rels")) continue;
|
|
581
1224
|
if (contentTypes.overrides.has(path)) continue;
|
|
582
|
-
const ext = extensionOf(path);
|
|
1225
|
+
const ext = extensionOf$2(path);
|
|
583
1226
|
if (ext && contentTypes.defaults.has(ext)) continue;
|
|
584
1227
|
issues.push({
|
|
585
1228
|
code: "O5",
|
|
@@ -662,6 +1305,22 @@ const DOCX_PARTS = {
|
|
|
662
1305
|
flag: "freshCompile"
|
|
663
1306
|
}
|
|
664
1307
|
},
|
|
1308
|
+
{
|
|
1309
|
+
path: "word/stylesWithEffects.xml",
|
|
1310
|
+
contentType: "application/vnd.ms-word.stylesWithEffects+xml",
|
|
1311
|
+
presence: {
|
|
1312
|
+
kind: "conditional",
|
|
1313
|
+
flag: "source carried the legacy part"
|
|
1314
|
+
}
|
|
1315
|
+
},
|
|
1316
|
+
{
|
|
1317
|
+
path: "customXml/itemProps${i}.xml",
|
|
1318
|
+
contentType: "application/vnd.openxmlformats-officedocument.customXmlProperties+xml",
|
|
1319
|
+
presence: {
|
|
1320
|
+
kind: "repeated",
|
|
1321
|
+
countFrom: "customXml items"
|
|
1322
|
+
}
|
|
1323
|
+
},
|
|
665
1324
|
{
|
|
666
1325
|
path: "word/numbering.xml",
|
|
667
1326
|
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
|
|
@@ -723,7 +1382,7 @@ const DOCX_PARTS = {
|
|
|
723
1382
|
contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
|
724
1383
|
presence: {
|
|
725
1384
|
kind: "conditional",
|
|
726
|
-
flag: "
|
|
1385
|
+
flag: "hasCustomProperties"
|
|
727
1386
|
}
|
|
728
1387
|
},
|
|
729
1388
|
{
|
|
@@ -734,6 +1393,22 @@ const DOCX_PARTS = {
|
|
|
734
1393
|
flag: "hasComments"
|
|
735
1394
|
}
|
|
736
1395
|
},
|
|
1396
|
+
{
|
|
1397
|
+
path: "word/people.xml",
|
|
1398
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml",
|
|
1399
|
+
presence: {
|
|
1400
|
+
kind: "conditional",
|
|
1401
|
+
flag: "hasPeople"
|
|
1402
|
+
}
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
path: "word/commentsExtended.xml",
|
|
1406
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml",
|
|
1407
|
+
presence: {
|
|
1408
|
+
kind: "conditional",
|
|
1409
|
+
flag: "hasCommentsExtended"
|
|
1410
|
+
}
|
|
1411
|
+
},
|
|
737
1412
|
{
|
|
738
1413
|
path: "word/header${i}.xml",
|
|
739
1414
|
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
|
|
@@ -808,12 +1483,44 @@ const DOCX_PARTS = {
|
|
|
808
1483
|
},
|
|
809
1484
|
{
|
|
810
1485
|
path: "word/glossary/document.xml",
|
|
811
|
-
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.glossary+xml",
|
|
1486
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml",
|
|
812
1487
|
presence: {
|
|
813
1488
|
kind: "conditional",
|
|
814
1489
|
flag: "hasGlossary"
|
|
815
1490
|
}
|
|
816
1491
|
},
|
|
1492
|
+
{
|
|
1493
|
+
path: "word/glossary/styles.xml",
|
|
1494
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
|
|
1495
|
+
presence: {
|
|
1496
|
+
kind: "conditional",
|
|
1497
|
+
flag: "glossary companion parts"
|
|
1498
|
+
}
|
|
1499
|
+
},
|
|
1500
|
+
{
|
|
1501
|
+
path: "word/glossary/settings.xml",
|
|
1502
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
|
|
1503
|
+
presence: {
|
|
1504
|
+
kind: "conditional",
|
|
1505
|
+
flag: "glossary companion parts"
|
|
1506
|
+
}
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
path: "word/glossary/fontTable.xml",
|
|
1510
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
|
|
1511
|
+
presence: {
|
|
1512
|
+
kind: "conditional",
|
|
1513
|
+
flag: "glossary companion parts"
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
{
|
|
1517
|
+
path: "word/glossary/webSettings.xml",
|
|
1518
|
+
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
|
|
1519
|
+
presence: {
|
|
1520
|
+
kind: "conditional",
|
|
1521
|
+
flag: "glossary companion parts"
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
817
1524
|
{
|
|
818
1525
|
path: "word/webSettings.xml",
|
|
819
1526
|
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
|
|
@@ -879,6 +1586,14 @@ const PPTX_PARTS = {
|
|
|
879
1586
|
flag: "freshCompile"
|
|
880
1587
|
}
|
|
881
1588
|
},
|
|
1589
|
+
{
|
|
1590
|
+
path: "docProps/custom.xml",
|
|
1591
|
+
contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
|
1592
|
+
presence: {
|
|
1593
|
+
kind: "conditional",
|
|
1594
|
+
flag: "has custom properties"
|
|
1595
|
+
}
|
|
1596
|
+
},
|
|
882
1597
|
{
|
|
883
1598
|
path: "ppt/theme/theme${i}.xml",
|
|
884
1599
|
contentType: "application/vnd.openxmlformats-officedocument.theme+xml",
|
|
@@ -887,6 +1602,22 @@ const PPTX_PARTS = {
|
|
|
887
1602
|
countFrom: "masters + notes/handout masters"
|
|
888
1603
|
}
|
|
889
1604
|
},
|
|
1605
|
+
{
|
|
1606
|
+
path: "ppt/theme/themeOverride${i}.xml",
|
|
1607
|
+
contentType: "application/vnd.openxmlformats-officedocument.themeOverride+xml",
|
|
1608
|
+
presence: {
|
|
1609
|
+
kind: "conditional",
|
|
1610
|
+
flag: "layout-level theme overrides"
|
|
1611
|
+
}
|
|
1612
|
+
},
|
|
1613
|
+
{
|
|
1614
|
+
path: "ppt/theme/themeManager1.xml",
|
|
1615
|
+
contentType: "application/vnd.openxmlformats-officedocument.themeManager+xml",
|
|
1616
|
+
presence: {
|
|
1617
|
+
kind: "conditional",
|
|
1618
|
+
flag: "legacy themeManager part"
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
890
1621
|
{
|
|
891
1622
|
path: "ppt/presProps.xml",
|
|
892
1623
|
contentType: "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml",
|
|
@@ -1025,7 +1756,7 @@ const PPTX_PARTS = {
|
|
|
1025
1756
|
},
|
|
1026
1757
|
{
|
|
1027
1758
|
path: "ppt/slideSyncPr/slideSyncPr${i}.xml",
|
|
1028
|
-
contentType: "application/vnd.openxmlformats-officedocument.presentationml.
|
|
1759
|
+
contentType: "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml",
|
|
1029
1760
|
presence: {
|
|
1030
1761
|
kind: "repeated",
|
|
1031
1762
|
countFrom: "slides with slideSync"
|
|
@@ -1079,6 +1810,14 @@ const XLSX_PARTS = {
|
|
|
1079
1810
|
flag: "freshCompile"
|
|
1080
1811
|
}
|
|
1081
1812
|
},
|
|
1813
|
+
{
|
|
1814
|
+
path: "docProps/custom.xml",
|
|
1815
|
+
contentType: "application/vnd.openxmlformats-officedocument.custom-properties+xml",
|
|
1816
|
+
presence: {
|
|
1817
|
+
kind: "conditional",
|
|
1818
|
+
flag: "has custom properties"
|
|
1819
|
+
}
|
|
1820
|
+
},
|
|
1082
1821
|
{
|
|
1083
1822
|
path: "xl/styles.xml",
|
|
1084
1823
|
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
|
|
@@ -1119,6 +1858,14 @@ const XLSX_PARTS = {
|
|
|
1119
1858
|
countFrom: "chartsheets.length"
|
|
1120
1859
|
}
|
|
1121
1860
|
},
|
|
1861
|
+
{
|
|
1862
|
+
path: "xl/dialogSheets/sheet${i}.xml",
|
|
1863
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
|
|
1864
|
+
presence: {
|
|
1865
|
+
kind: "repeated",
|
|
1866
|
+
countFrom: "dialogsheets.length"
|
|
1867
|
+
}
|
|
1868
|
+
},
|
|
1122
1869
|
{
|
|
1123
1870
|
path: "xl/drawings/drawing${i}.xml",
|
|
1124
1871
|
contentType: "application/vnd.openxmlformats-officedocument.drawing+xml",
|
|
@@ -1190,6 +1937,54 @@ const XLSX_PARTS = {
|
|
|
1190
1937
|
countFrom: "externalLinks.length"
|
|
1191
1938
|
}
|
|
1192
1939
|
},
|
|
1940
|
+
{
|
|
1941
|
+
path: "xl/connections.xml",
|
|
1942
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml",
|
|
1943
|
+
presence: {
|
|
1944
|
+
kind: "conditional",
|
|
1945
|
+
flag: "connections"
|
|
1946
|
+
}
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
path: "xl/queryTables/queryTable${i}.xml",
|
|
1950
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml",
|
|
1951
|
+
presence: {
|
|
1952
|
+
kind: "repeated",
|
|
1953
|
+
countFrom: "queryTables"
|
|
1954
|
+
}
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
path: "xl/metadata.xml",
|
|
1958
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml",
|
|
1959
|
+
presence: {
|
|
1960
|
+
kind: "conditional",
|
|
1961
|
+
flag: "metadata"
|
|
1962
|
+
}
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
path: "xl/xmlMaps.xml",
|
|
1966
|
+
contentType: "application/xml",
|
|
1967
|
+
presence: {
|
|
1968
|
+
kind: "conditional",
|
|
1969
|
+
flag: "xmlMaps"
|
|
1970
|
+
}
|
|
1971
|
+
},
|
|
1972
|
+
{
|
|
1973
|
+
path: "xl/volTypes.xml",
|
|
1974
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.volTypes+xml",
|
|
1975
|
+
presence: {
|
|
1976
|
+
kind: "conditional",
|
|
1977
|
+
flag: "volTypes"
|
|
1978
|
+
}
|
|
1979
|
+
},
|
|
1980
|
+
{
|
|
1981
|
+
path: "xl/tables/tableSingleCells${i}.xml",
|
|
1982
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml",
|
|
1983
|
+
presence: {
|
|
1984
|
+
kind: "repeated",
|
|
1985
|
+
countFrom: "singleXmlCells"
|
|
1986
|
+
}
|
|
1987
|
+
},
|
|
1193
1988
|
{
|
|
1194
1989
|
path: "xl/calcChain.xml",
|
|
1195
1990
|
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml",
|
|
@@ -1216,7 +2011,7 @@ const XLSX_PARTS = {
|
|
|
1216
2011
|
},
|
|
1217
2012
|
{
|
|
1218
2013
|
path: "xl/users.xml",
|
|
1219
|
-
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.
|
|
2014
|
+
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml",
|
|
1220
2015
|
presence: {
|
|
1221
2016
|
kind: "conditional",
|
|
1222
2017
|
flag: "revisionLog.users"
|
|
@@ -1232,7 +2027,7 @@ const PART_REGISTRIES = {
|
|
|
1232
2027
|
//#endregion
|
|
1233
2028
|
//#region src/opc/content-type-overrides.ts
|
|
1234
2029
|
/** Ensure a part path carries the leading slash an Override PartName requires. */
|
|
1235
|
-
function withLeadingSlash(partPath) {
|
|
2030
|
+
function withLeadingSlash$1(partPath) {
|
|
1236
2031
|
return partPath.startsWith("/") ? partPath : `/${partPath}`;
|
|
1237
2032
|
}
|
|
1238
2033
|
/**
|
|
@@ -1248,18 +2043,18 @@ function buildContentTypeOverrides(registry, facts) {
|
|
|
1248
2043
|
const presence = part.presence;
|
|
1249
2044
|
if (presence.kind === "always") {
|
|
1250
2045
|
if (!part.path.includes("${i}")) overrides.push({
|
|
1251
|
-
partName: withLeadingSlash(part.path),
|
|
2046
|
+
partName: withLeadingSlash$1(part.path),
|
|
1252
2047
|
contentType: part.contentType
|
|
1253
2048
|
});
|
|
1254
2049
|
} else if (presence.kind === "conditional") {
|
|
1255
2050
|
if (facts.get(presence.flag)) overrides.push({
|
|
1256
|
-
partName: withLeadingSlash(part.path),
|
|
2051
|
+
partName: withLeadingSlash$1(part.path),
|
|
1257
2052
|
contentType: part.contentType
|
|
1258
2053
|
});
|
|
1259
2054
|
} else {
|
|
1260
2055
|
const count = Number(facts.get(presence.countFrom) ?? 0);
|
|
1261
2056
|
for (let i = 1; i <= count; i++) overrides.push({
|
|
1262
|
-
partName: withLeadingSlash(part.path.replace("${i}", String(i))),
|
|
2057
|
+
partName: withLeadingSlash$1(part.path.replace("${i}", String(i))),
|
|
1263
2058
|
contentType: part.contentType
|
|
1264
2059
|
});
|
|
1265
2060
|
}
|
|
@@ -1267,6 +2062,426 @@ function buildContentTypeOverrides(registry, facts) {
|
|
|
1267
2062
|
return overrides;
|
|
1268
2063
|
}
|
|
1269
2064
|
//#endregion
|
|
1270
|
-
|
|
2065
|
+
//#region src/opc/content-types-input.ts
|
|
2066
|
+
const contentTypesDesc = {
|
|
2067
|
+
kind: "custom",
|
|
2068
|
+
stringify(opts, _ctx) {
|
|
2069
|
+
const p = ["<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"];
|
|
2070
|
+
const seenDefault = /* @__PURE__ */ new Set();
|
|
2071
|
+
for (const d of opts.defaults) {
|
|
2072
|
+
const key = d.extension.toLowerCase();
|
|
2073
|
+
if (seenDefault.has(key)) continue;
|
|
2074
|
+
seenDefault.add(key);
|
|
2075
|
+
p.push(`<Default Extension="${d.extension}" ContentType="${d.contentType}"/>`);
|
|
2076
|
+
}
|
|
2077
|
+
const seenOverride = /* @__PURE__ */ new Set();
|
|
2078
|
+
for (const o of opts.overrides) {
|
|
2079
|
+
const key = o.partName.toLowerCase();
|
|
2080
|
+
if (seenOverride.has(key)) continue;
|
|
2081
|
+
seenOverride.add(key);
|
|
2082
|
+
p.push(`<Override PartName="${o.partName}" ContentType="${o.contentType}"/>`);
|
|
2083
|
+
}
|
|
2084
|
+
p.push("</Types>");
|
|
2085
|
+
return p.join("");
|
|
2086
|
+
},
|
|
2087
|
+
parse(el, _ctx) {
|
|
2088
|
+
const defaults = [];
|
|
2089
|
+
const overrides = [];
|
|
2090
|
+
for (const child of el.elements ?? []) if (child.name === "Default") {
|
|
2091
|
+
const ext = child.attributes?.["Extension"];
|
|
2092
|
+
const ct = child.attributes?.["ContentType"];
|
|
2093
|
+
if (ext && ct) defaults.push({
|
|
2094
|
+
extension: String(ext),
|
|
2095
|
+
contentType: String(ct)
|
|
2096
|
+
});
|
|
2097
|
+
} else if (child.name === "Override") {
|
|
2098
|
+
const pn = child.attributes?.["PartName"];
|
|
2099
|
+
const ct = child.attributes?.["ContentType"];
|
|
2100
|
+
if (pn && ct) overrides.push({
|
|
2101
|
+
partName: String(pn),
|
|
2102
|
+
contentType: String(ct)
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
return {
|
|
2106
|
+
defaults,
|
|
2107
|
+
overrides
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
/** Convert a registry part path (with `${i}` placeholders) to an anchored RegExp. */
|
|
2112
|
+
function patternToRegExp(path) {
|
|
2113
|
+
const escaped = path.split("${i}").map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
2114
|
+
return new RegExp("^" + escaped.join("\\d+") + "$");
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* Build a path→contentType resolver from a part registry. Only the path pattern
|
|
2118
|
+
* and contentType are consulted; the presence/flag/countFrom fields are
|
|
2119
|
+
* irrelevant here because emission is driven by the files actually written, not
|
|
2120
|
+
* by a separate facts map. Any path the resolver does not recognize falls
|
|
2121
|
+
* through to extension-based Default handling (media, embeddings, .rels).
|
|
2122
|
+
*/
|
|
2123
|
+
function resolverFromRegistry(registry) {
|
|
2124
|
+
const patterns = [];
|
|
2125
|
+
for (const part of registry.parts) {
|
|
2126
|
+
if (!part.contentType) continue;
|
|
2127
|
+
patterns.push({
|
|
2128
|
+
re: patternToRegExp(part.path),
|
|
2129
|
+
contentType: part.contentType
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
return (partPath) => patterns.find((p) => p.re.test(partPath))?.contentType;
|
|
2133
|
+
}
|
|
2134
|
+
const BASE_DEFAULTS = [{
|
|
2135
|
+
extension: "rels",
|
|
2136
|
+
contentType: "application/vnd.openxmlformats-package.relationships+xml"
|
|
2137
|
+
}, {
|
|
2138
|
+
extension: "xml",
|
|
2139
|
+
contentType: "application/xml"
|
|
2140
|
+
}];
|
|
2141
|
+
function extensionOf$1(path) {
|
|
2142
|
+
const slash = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
2143
|
+
const dot = path.slice(slash + 1).lastIndexOf(".");
|
|
2144
|
+
return dot > 0 ? path.slice(slash + 1 + dot + 1) : void 0;
|
|
2145
|
+
}
|
|
2146
|
+
function withLeadingSlash(path) {
|
|
2147
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
2148
|
+
}
|
|
2149
|
+
/**
|
|
2150
|
+
* Derive [Content_Types].xml entries from the actual part paths in the package.
|
|
2151
|
+
* Each path that the resolver maps to a content type becomes an Override; every
|
|
2152
|
+
* other file contributes a Default keyed by its extension (declared once).
|
|
2153
|
+
*/
|
|
2154
|
+
function deriveContentTypes(filePaths, options) {
|
|
2155
|
+
const files = [...filePaths].filter((p) => p !== "[Content_Types].xml");
|
|
2156
|
+
const defaults = [...options.baseDefaults ?? BASE_DEFAULTS];
|
|
2157
|
+
const seenExt = new Set(defaults.map((d) => d.extension.toLowerCase()));
|
|
2158
|
+
const overrideMap = /* @__PURE__ */ new Map();
|
|
2159
|
+
const partTypes = [];
|
|
2160
|
+
for (const path of files) {
|
|
2161
|
+
const partType = options.resolve(path);
|
|
2162
|
+
if (partType) {
|
|
2163
|
+
const partName = withLeadingSlash(path);
|
|
2164
|
+
overrideMap.set(partName.toLowerCase(), {
|
|
2165
|
+
partName,
|
|
2166
|
+
contentType: partType
|
|
2167
|
+
});
|
|
2168
|
+
partTypes.push({
|
|
2169
|
+
partName,
|
|
2170
|
+
contentType: partType
|
|
2171
|
+
});
|
|
2172
|
+
continue;
|
|
2173
|
+
}
|
|
2174
|
+
const ext = extensionOf$1(path);
|
|
2175
|
+
if (!ext) continue;
|
|
2176
|
+
const key = ext.toLowerCase();
|
|
2177
|
+
const mime = options.mediaContentTypes[key];
|
|
2178
|
+
if (!seenExt.has(key) && mime) {
|
|
2179
|
+
defaults.push({
|
|
2180
|
+
extension: ext,
|
|
2181
|
+
contentType: mime
|
|
2182
|
+
});
|
|
2183
|
+
seenExt.add(key);
|
|
2184
|
+
}
|
|
2185
|
+
if (mime) partTypes.push({
|
|
2186
|
+
partName: withLeadingSlash(path),
|
|
2187
|
+
contentType: mime
|
|
2188
|
+
});
|
|
2189
|
+
}
|
|
2190
|
+
for (const extra of options.overrides ?? []) {
|
|
2191
|
+
const partName = withLeadingSlash(extra.path);
|
|
2192
|
+
overrideMap.set(partName.toLowerCase(), {
|
|
2193
|
+
partName,
|
|
2194
|
+
contentType: extra.contentType
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
if (!options.source) return {
|
|
2198
|
+
defaults,
|
|
2199
|
+
overrides: [...overrideMap.values()]
|
|
2200
|
+
};
|
|
2201
|
+
return mergeSourceContentTypes(options.source, files, defaults, overrideMap, partTypes, { verbatim: options.verbatimPaths });
|
|
2202
|
+
}
|
|
2203
|
+
/**
|
|
2204
|
+
* Merge derived declarations onto the source package's table (round-trip).
|
|
2205
|
+
*
|
|
2206
|
+
* - Source Defaults survive verbatim — extension-level entries are harmless
|
|
2207
|
+
* when unused, and dropping them (or retyping the shared .bin extension)
|
|
2208
|
+
* is what a purely derived table gets wrong.
|
|
2209
|
+
* - Source Overrides survive for parts that still exist at the same path;
|
|
2210
|
+
* media the pipeline renamed drops out.
|
|
2211
|
+
* - Derived Overrides fill only what the surviving source table leaves
|
|
2212
|
+
* uncovered: parts with no source Override whose covering source Default
|
|
2213
|
+
* disagrees with (or omits) their derived type. A part the compiler
|
|
2214
|
+
* rebuilds from its parsed source stays the same part kind, so a surviving
|
|
2215
|
+
* source Override (macro-enabled variants included) keeps the source type —
|
|
2216
|
+
* the static registry cannot know the package variant the source declared.
|
|
2217
|
+
* - A derived Default joins only when an output part of that extension is
|
|
2218
|
+
* still uncovered after Overrides — a source table that declares its .jpg
|
|
2219
|
+
* parts via per-part Overrides stays as-is.
|
|
2220
|
+
*/
|
|
2221
|
+
function mergeSourceContentTypes(source, files, derivedDefaults, derivedOverrides, partTypes, mergeOpts) {
|
|
2222
|
+
const filePaths = new Set(files.map((p) => withLeadingSlash(p).toLowerCase()));
|
|
2223
|
+
const verbatimLower = new Set([...mergeOpts.verbatim ?? []].map((p) => p.toLowerCase()));
|
|
2224
|
+
const isVerbatim = (partName) => verbatimLower.has(partName.slice(1).toLowerCase());
|
|
2225
|
+
const partExt = (partName) => {
|
|
2226
|
+
const dot = partName.lastIndexOf(".");
|
|
2227
|
+
return dot > partName.lastIndexOf("/") ? partName.slice(dot + 1) : "";
|
|
2228
|
+
};
|
|
2229
|
+
const defaultTypeByExt = /* @__PURE__ */ new Map();
|
|
2230
|
+
const derivedDefaultByExt = /* @__PURE__ */ new Map();
|
|
2231
|
+
for (const d of source.defaults) {
|
|
2232
|
+
const key = d.extension.toLowerCase();
|
|
2233
|
+
if (!defaultTypeByExt.has(key)) defaultTypeByExt.set(key, d.contentType);
|
|
2234
|
+
}
|
|
2235
|
+
for (const d of derivedDefaults) {
|
|
2236
|
+
const key = d.extension.toLowerCase();
|
|
2237
|
+
if (defaultTypeByExt.has(key)) continue;
|
|
2238
|
+
defaultTypeByExt.set(key, d.contentType);
|
|
2239
|
+
derivedDefaultByExt.set(key, d);
|
|
2240
|
+
}
|
|
2241
|
+
const overrides = [];
|
|
2242
|
+
const seenOverride = /* @__PURE__ */ new Set();
|
|
2243
|
+
const keptSourceTypeByPath = /* @__PURE__ */ new Map();
|
|
2244
|
+
for (const o of source.overrides) {
|
|
2245
|
+
const key = o.partName.toLowerCase();
|
|
2246
|
+
if (!filePaths.has(key)) continue;
|
|
2247
|
+
if (seenOverride.has(key)) continue;
|
|
2248
|
+
seenOverride.add(key);
|
|
2249
|
+
overrides.push(o);
|
|
2250
|
+
keptSourceTypeByPath.set(key, o.contentType);
|
|
2251
|
+
}
|
|
2252
|
+
for (const o of derivedOverrides.values()) {
|
|
2253
|
+
const key = o.partName.toLowerCase();
|
|
2254
|
+
if (isVerbatim(key)) continue;
|
|
2255
|
+
if (keptSourceTypeByPath.has(key)) continue;
|
|
2256
|
+
const ext = partExt(key);
|
|
2257
|
+
if ((ext ? defaultTypeByExt.get(ext) : void 0) === o.contentType) continue;
|
|
2258
|
+
seenOverride.add(key);
|
|
2259
|
+
overrides.push(o);
|
|
2260
|
+
}
|
|
2261
|
+
for (const { partName, contentType } of partTypes) {
|
|
2262
|
+
const key = partName.toLowerCase();
|
|
2263
|
+
if (derivedOverrides.has(key) || keptSourceTypeByPath.has(key)) continue;
|
|
2264
|
+
if (isVerbatim(key)) continue;
|
|
2265
|
+
const ext = partExt(key);
|
|
2266
|
+
const coveringDefault = ext ? defaultTypeByExt.get(ext) : void 0;
|
|
2267
|
+
if (coveringDefault === void 0 || coveringDefault === contentType) continue;
|
|
2268
|
+
if (seenOverride.has(key)) continue;
|
|
2269
|
+
seenOverride.add(key);
|
|
2270
|
+
overrides.push({
|
|
2271
|
+
partName,
|
|
2272
|
+
contentType
|
|
2273
|
+
});
|
|
2274
|
+
}
|
|
2275
|
+
const defaults = [];
|
|
2276
|
+
const seenDefault = /* @__PURE__ */ new Set();
|
|
2277
|
+
for (const d of source.defaults) {
|
|
2278
|
+
const key = d.extension.toLowerCase();
|
|
2279
|
+
if (seenDefault.has(key)) continue;
|
|
2280
|
+
seenDefault.add(key);
|
|
2281
|
+
defaults.push(d);
|
|
2282
|
+
}
|
|
2283
|
+
for (const [key, d] of derivedDefaultByExt) if (files.some((f) => extensionOf$1(f)?.toLowerCase() === key && !seenOverride.has(withLeadingSlash(f).toLowerCase()))) defaults.push(d);
|
|
2284
|
+
return {
|
|
2285
|
+
defaults,
|
|
2286
|
+
overrides
|
|
2287
|
+
};
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Extension → MIME for image media, shared by every format package.
|
|
2291
|
+
*
|
|
2292
|
+
* The three format compilers each declare a package-scoped media table made
|
|
2293
|
+
* of this image block plus format-specific extras (docx: odttf/bin fonts and
|
|
2294
|
+
* OLE; pptx: video/audio; xlsx: vml). Keeping the image half in one place
|
|
2295
|
+
* means a new image format lands everywhere at once.
|
|
2296
|
+
*/
|
|
2297
|
+
const IMAGE_MEDIA_CONTENT_TYPES = {
|
|
2298
|
+
png: "image/png",
|
|
2299
|
+
jpeg: "image/jpeg",
|
|
2300
|
+
jpg: "image/jpeg",
|
|
2301
|
+
bmp: "image/bmp",
|
|
2302
|
+
gif: "image/gif",
|
|
2303
|
+
tif: "image/tiff",
|
|
2304
|
+
tiff: "image/tiff",
|
|
2305
|
+
emf: "image/x-emf",
|
|
2306
|
+
wmf: "image/x-wmf",
|
|
2307
|
+
ico: "image/x-icon",
|
|
2308
|
+
svg: "image/svg+xml"
|
|
2309
|
+
};
|
|
2310
|
+
//#endregion
|
|
2311
|
+
//#region src/opc/passthrough.ts
|
|
2312
|
+
/**
|
|
2313
|
+
* Package-wide passthrough collection (SDK ExtendedPart analogue).
|
|
2314
|
+
*
|
|
2315
|
+
* The parse side of the "maximum parse" contract: every part the model did
|
|
2316
|
+
* NOT absorb is carried verbatim instead of dropped. Callers list the parts
|
|
2317
|
+
* their compiler rebuilds; everything else — unknown extensions, companion
|
|
2318
|
+
* .rels, media referenced only by passthrough parts — survives round-trip
|
|
2319
|
+
* with bytes and content-type declarations intact.
|
|
2320
|
+
*
|
|
2321
|
+
* Rebuilt parts whose source .rels referenced a passthrough part are captured
|
|
2322
|
+
* as relationship entries so the compiler can re-emit them verbatim (fresh
|
|
2323
|
+
* rId, unchanged target — passthrough paths never move).
|
|
2324
|
+
*
|
|
2325
|
+
* @module
|
|
2326
|
+
*/
|
|
2327
|
+
/** Package-level files the packer always regenerates. */
|
|
2328
|
+
const ALWAYS_REBUILT = /* @__PURE__ */ new Set(["[Content_Types].xml", "_rels/.rels"]);
|
|
2329
|
+
function extensionOf(path) {
|
|
2330
|
+
const slash = path.lastIndexOf("/");
|
|
2331
|
+
const dot = path.slice(slash + 1).lastIndexOf(".");
|
|
2332
|
+
return dot > 0 ? path.slice(slash + 1 + dot + 1) : void 0;
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* Collect passthrough parts and rebuilt→passthrough relationships.
|
|
2336
|
+
*
|
|
2337
|
+
* @param archive - Parsed source package.
|
|
2338
|
+
* @param rebuiltPaths - Parts (including their .rels) the compiler re-emits
|
|
2339
|
+
* from the model. Listing a part here without its .rels leaves the .rels
|
|
2340
|
+
* to pass through — used by docx glossary, where the document part is
|
|
2341
|
+
* rebuilt but its companion rels travel verbatim.
|
|
2342
|
+
*/
|
|
2343
|
+
function collectPassthroughParts(archive, rebuiltPaths) {
|
|
2344
|
+
const rebuilt = new Set(ALWAYS_REBUILT);
|
|
2345
|
+
for (const p of rebuiltPaths) rebuilt.add(p);
|
|
2346
|
+
let defaults = [];
|
|
2347
|
+
let overrides = [];
|
|
2348
|
+
const ctEl = archive.get("[Content_Types].xml");
|
|
2349
|
+
if (ctEl) {
|
|
2350
|
+
const parsed = contentTypesDesc.parse(ctEl, void 0);
|
|
2351
|
+
defaults = parsed.defaults;
|
|
2352
|
+
overrides = parsed.overrides;
|
|
2353
|
+
}
|
|
2354
|
+
const overrideMap = new Map(overrides.map((o) => [o.partName.toLowerCase(), o.contentType]));
|
|
2355
|
+
const defaultMap = new Map(defaults.map((d) => [d.extension.toLowerCase(), d.contentType]));
|
|
2356
|
+
const contentTypeFor = (path) => {
|
|
2357
|
+
const override = overrideMap.get(`/${path}`.toLowerCase());
|
|
2358
|
+
if (override) return override;
|
|
2359
|
+
const ext = extensionOf(path);
|
|
2360
|
+
return ext ? defaultMap.get(ext.toLowerCase()) : void 0;
|
|
2361
|
+
};
|
|
2362
|
+
const parts = [];
|
|
2363
|
+
const kept = /* @__PURE__ */ new Set();
|
|
2364
|
+
for (const path of archive.keys()) {
|
|
2365
|
+
if (path.endsWith("/") || rebuilt.has(path)) continue;
|
|
2366
|
+
const sourceData = archive.getRaw(path);
|
|
2367
|
+
if (!sourceData) continue;
|
|
2368
|
+
const data = path.endsWith(".xml") || path.endsWith(".rels") ? normalizeObsoleteNamespaceAliases(sourceData) : sourceData;
|
|
2369
|
+
kept.add(path.toLowerCase());
|
|
2370
|
+
const contentType = contentTypeFor(path);
|
|
2371
|
+
parts.push(contentType === void 0 ? {
|
|
2372
|
+
path,
|
|
2373
|
+
data
|
|
2374
|
+
} : {
|
|
2375
|
+
path,
|
|
2376
|
+
data,
|
|
2377
|
+
contentType
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
const relationships = [];
|
|
2381
|
+
const captureRels = (relsEl, source) => {
|
|
2382
|
+
if (!relsEl) return;
|
|
2383
|
+
for (const rel of relsEl.elements ?? []) {
|
|
2384
|
+
if (rel.name !== "Relationship") continue;
|
|
2385
|
+
const targetMode = attr(rel, "TargetMode");
|
|
2386
|
+
const relationshipType = attr(rel, "Type");
|
|
2387
|
+
const target = attr(rel, "Target");
|
|
2388
|
+
const rId = attr(rel, "Id");
|
|
2389
|
+
if (!relationshipType || !target || !rId) continue;
|
|
2390
|
+
if (targetMode === "External") {
|
|
2391
|
+
if (source === "") relationships.push({
|
|
2392
|
+
source,
|
|
2393
|
+
relationshipType,
|
|
2394
|
+
target,
|
|
2395
|
+
rId,
|
|
2396
|
+
targetMode
|
|
2397
|
+
});
|
|
2398
|
+
continue;
|
|
2399
|
+
}
|
|
2400
|
+
if (kept.has(resolveRelationshipTarget(source, target).toLowerCase()) || source !== "") relationships.push({
|
|
2401
|
+
source,
|
|
2402
|
+
relationshipType,
|
|
2403
|
+
target,
|
|
2404
|
+
rId
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
for (const source of rebuiltPaths) captureRels(archive.get(partPathToRelsPath(source)), source);
|
|
2409
|
+
captureRels(archive.get("_rels/.rels"), "");
|
|
2410
|
+
return {
|
|
2411
|
+
parts,
|
|
2412
|
+
relationships
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
/** Regex metacharacters in a literal target path (e.g. "." in file names). */
|
|
2416
|
+
const RE_ESCAPE = /[.*+?^${}()|[\]\\]/g;
|
|
2417
|
+
/**
|
|
2418
|
+
* Drop passthrough relationships whose target part is absent from the final
|
|
2419
|
+
* package: a dangling internal Target makes Office refuse to open the file,
|
|
2420
|
+
* and a hand-authored options JSON can reference parts it never carried in
|
|
2421
|
+
* `rawParts`. Parsed sources never produce this (their targets exist in the
|
|
2422
|
+
* source archive), so the guard only fires on the hand-authoring input face.
|
|
2423
|
+
* External and same-part `#fragment` targets are left alone.
|
|
2424
|
+
*
|
|
2425
|
+
* Runs after `compileMapping` on the assembled file map; rewrites the rebuilt
|
|
2426
|
+
* .rels part in place. Returns the number of relationships removed.
|
|
2427
|
+
*/
|
|
2428
|
+
function dropDanglingPassthroughRels(files, passthroughRelationships) {
|
|
2429
|
+
if (!passthroughRelationships || passthroughRelationships.length === 0) return 0;
|
|
2430
|
+
const paths = new Set(Object.keys(files).map((p) => p.toLowerCase()));
|
|
2431
|
+
const decoder = new TextDecoder();
|
|
2432
|
+
const encoder = new TextEncoder();
|
|
2433
|
+
let dropped = 0;
|
|
2434
|
+
for (const rel of passthroughRelationships) {
|
|
2435
|
+
if (rel.targetMode === "External" || rel.target.startsWith("#")) continue;
|
|
2436
|
+
const relsPath = rel.source === "" ? "_rels/.rels" : partPathToRelsPath(rel.source);
|
|
2437
|
+
const entry = files[relsPath];
|
|
2438
|
+
const bytes = entry instanceof Uint8Array ? entry : Array.isArray(entry) && entry[0] instanceof Uint8Array ? entry[0] : void 0;
|
|
2439
|
+
if (!bytes) continue;
|
|
2440
|
+
const xml = decoder.decode(bytes);
|
|
2441
|
+
const escaped = escapeXml(rel.target).replace(RE_ESCAPE, "\\$&");
|
|
2442
|
+
if (!escaped) continue;
|
|
2443
|
+
const match = new RegExp(`(<Relationship\\b[^>]*\\bTarget="${escaped}"[^>]*/>)`).exec(xml);
|
|
2444
|
+
if (!match) continue;
|
|
2445
|
+
const resolved = resolveRelationshipTarget(rel.source, rel.target);
|
|
2446
|
+
if (paths.has(resolved.toLowerCase())) continue;
|
|
2447
|
+
const stripped = xml.slice(0, match.index) + xml.slice(match.index + match[1].length);
|
|
2448
|
+
const rewritten = encoder.encode(stripped);
|
|
2449
|
+
files[relsPath] = Array.isArray(entry) ? [rewritten, entry[1]] : rewritten;
|
|
2450
|
+
dropped++;
|
|
2451
|
+
}
|
|
2452
|
+
return dropped;
|
|
2453
|
+
}
|
|
2454
|
+
//#endregion
|
|
2455
|
+
//#region src/connector/types.ts
|
|
2456
|
+
/**
|
|
2457
|
+
* Pick the connector base fields (cNvPr + locking + endpoint connections)
|
|
2458
|
+
* actually set on `opts`, dropping undefined. Used when bridging a package's
|
|
2459
|
+
* connector options onto the shared base during cross-format conversion.
|
|
2460
|
+
*/
|
|
2461
|
+
function pickConnectorBase(opts) {
|
|
2462
|
+
if (!opts) return {};
|
|
2463
|
+
return {
|
|
2464
|
+
...pickNonVisualDrawingProperties(opts),
|
|
2465
|
+
...opts.locking !== void 0 ? { locking: opts.locking } : {},
|
|
2466
|
+
...opts.startConnection !== void 0 ? { startConnection: opts.startConnection } : {},
|
|
2467
|
+
...opts.endConnection !== void 0 ? { endConnection: opts.endConnection } : {}
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
//#endregion
|
|
2471
|
+
//#region src/group/types.ts
|
|
2472
|
+
/**
|
|
2473
|
+
* Pick the group base fields (cNvPr + locks) actually set on `opts`, dropping
|
|
2474
|
+
* undefined. Used when bridging a package's group options onto the shared base
|
|
2475
|
+
* during cross-format conversion.
|
|
2476
|
+
*/
|
|
2477
|
+
function pickGroupBase(opts) {
|
|
2478
|
+
if (!opts) return {};
|
|
2479
|
+
return {
|
|
2480
|
+
...pickNonVisualDrawingProperties(opts),
|
|
2481
|
+
...opts.locking !== void 0 ? { locking: opts.locking } : {}
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
//#endregion
|
|
2485
|
+
export { BlendMode, COLOR_CATEGORIES, ChartCollection, DEFAULT_COLORS, DEFAULT_COLOR_MAPPING, DEFAULT_DRAWING_XML, DEFAULT_OUTLINE_WIDTH, DEFAULT_SHADOW_ALPHA, DEFAULT_SHADOW_BLUR_RADIUS, DEFAULT_SHADOW_DIRECTION, DEFAULT_SHADOW_DISTANCE, DEFAULT_TEXT_STYLES, DOCX_NS, DOCX_PARTS, EXT_ATTR, EmbeddingCollection, FIELD_SPECS, FontCollectionIndex, IMAGE_MEDIA_CONTENT_TYPES, LAYOUT_CATEGORIES, Media, OOXML_CANONICAL_PREFIXES, OoxmlMimeType, PART_REGISTRIES, PPTX_NS, PPTX_PARTS, ParsedArchive, PresetColor, Relationships, STYLE_CATEGORIES, SchemeColor, SmartArtCollection, SystemColor, TargetModeType, TokenNotFoundError, VML_BORDER_TAGS, VML_CORE_ATTRS, VML_OFFICE_CORE_ATTRS, VML_OFFICE_SHAPE_ATTRS, VML_SHAPE_ATTRS, XLSX_PARTS, ZIP_DEFLATE_LEVEL, ZIP_STORED_LEVEL, ZipStreamWriter, addBinaryFile, addSmartArtRelationships, appPropertiesDesc, appendContentType, appendOverride, appendRelationship, applyCorePropertiesOverride, assertEncryptedExclusive, bevelDesc, blipDesc, blipFillDesc, bodyPropertiesDesc, buildContentTypeOverrides, buildCorePropertiesXmlString, buildFill, buildHyperlinkElement, buildRootRelationships, buildThemeXml, calculateEffectExtent, cell3DDesc, chartSpaceDesc, checkOrder, collectPassthroughParts, collectPlaceholderKeys, colorsDefDesc, compileMapping, connectorLockingDesc, contentTypesDesc, convertEmuToInches, convertEmuToPixels, convertEmuToPoints, convertEmuToTwip, convertInchesToEmu, convertInchesToTwip, convertMillimetersToTwip, convertOutput, convertPixelsToEmu, convertPointsToEmu, convertPointsToTwip, convertToEmu, convertToInch, convertToPt, convertToTwip, convertTwipToEmu, convertTwipToPoints, convertUniversalMeasureToEmu, convertUniversalMeasureToInch, convertUniversalMeasureToPt, convertUniversalMeasureToTwip, createAdjust, createAdjustList, createAnimateOneByOne, createAnimationLevel, createBevel, createBlip, createBlipEffects, createBlipFill, createBodyProperties, createBottomBevel, createColorElement, createColorTransforms, createColorsDefinitionHeader, createColorsDefinitionHeaderList, createConnectorLocking, createContentPartLocking, createCustomDash, createCustomGeometry, createDataModel, createDiagramExtensionList, createDiagramRelationshipIds, createDiagramShape3D, createDiagramStyle, createDiagramTextProperties, createEffectColorList, createEffectDag, createEffectList, createExtensionList, createFillColorList, createFillOverlayEffect, createGlowEffect, createGradientFill, createGradientStop, createGraphicFrameLocking, createGroupFill, createGroupLocking, createGroupTransform2D, createHierBranch, createHslColor, createInnerShadowEffect, createLayoutDefinitionHeader, createLayoutDefinitionHeaderList, createLineColorList, createLineEnd, createMaxChildren, createNoFill, createOrgChart, createOuterShadowEffect, createOutline, createPacker, createPatternFill, createPictureLocking, createPreferredChildren, createPresentationLayoutVariables, createPresetColor, createPresetShadowEffect, createReflectionEffect, createReplacer, createRgbColor, createRunRenderer, createScRgbColor, createScene3D, createSchemeColor, createShape3D, createShapeLocking, createSoftEdgeEffect, createSolidFill, createSourceRectangle, createSplitInject, createStyleDefinitionHeader, createStyleDefinitionHeaderList, createStyleLabel, createSystemColor, createTableStyle, createTableStyleList, createTextEffectColorList, createTextElementContents, createTextFillColorList, createTextLineColorList, createThemeXml, createTileInfo, createTokenReplacer, createTransform2D, createTraverser, createZipStream, customGeometryDesc, customPropertiesDesc, dateTimeValue, decimalNumber, decodeBase64, definitionId, deriveContentTypes, derivePasswordHash, diagramExtensionListDesc, diagramRelationshipIdsDesc, diagramStyleDesc, diffTagSets, dropDanglingPassthroughRels, effectListDesc, eighthPointMeasureValue, emitAngle, emitColorChoice, emitFillXml, emitPercent, encodeBase64, encryptedContainerOutput, encryptedContainerStream, extUriMatches, extractBlipFillMedia, fillDesc, findAndReplaceImagePlaceholders, findFieldSpec, findFillChild, formatId, getAudioRefs, getColorXml, getFirstLevelElements, getLayoutXml, getMediaRefs, getNextRelationshipIndex, getOleRefs, getReferencedMedia, getStyleXml, getVideoRefs, gradientFillDesc, graphicFrameLockingDesc, groupLockingDesc, groupShapePropertiesDesc, groupTransform2DDesc, hasPlaceholders, hashPasswordAgile, hashedId, hexBinary, hexColorValue, hpsMeasureValue, hslColorDesc, imageTypeFromPath, invertMap, isBase64DataURL, isEncryptedContainer, isPlainRgbColor, layoutDefDesc, levelForMediaName, longHexNumber, mapOptional, measurementOrPercentValue, nextNumericId, nextVmlShapeId, optionalRelsPart, outlineDesc, paragraphDesc, parse, parseAngle, parseArchive, parseBodyProperties, parseColorChoice, parseColorChoiceElement, parseColorDefinition, parseColorMapping, parseCorePropsElement, parseDataModelOptions, parseEndpointConnection, parseLayoutDefinition, parseNonVisualContentPartProperties, parseNonVisualDrawingProperties, parseOnOff, parsePercent, parsePercentAttr, parseShapeStyle, parseStyleDefinition, parseTableStyle, parseTableStyleList, parseTextStyles, parseUniversalMeasure, parseVariantValue, parseVector, parseVmlAnchorLock, parseVmlArc, parseVmlAttributes, parseVmlBackground, parseVmlBorder, parseVmlCallout, parseVmlClientData, parseVmlClipPath, parseVmlColorMenu, parseVmlColorMru, parseVmlComplex, parseVmlCurve, parseVmlDiagram, parseVmlEquationXml, parseVmlExtrusion, parseVmlFill, parseVmlFormulas, parseVmlGroup, parseVmlHandles, parseVmlImage, parseVmlImageData, parseVmlInk, parseVmlIsComment, parseVmlLine, parseVmlLock, parseVmlOfficeFill, parseVmlOleObject, parseVmlOval, parseVmlPath, parseVmlPolyline, parseVmlRect, parseVmlRoundRect, parseVmlShadow, parseVmlShape, parseVmlShapeChild, parseVmlShapeDefaults, parseVmlShapeLayout, parseVmlShapeStyle, parseVmlShapetype, parseVmlSignatureLine, parseVmlSkew, parseVmlStroke, parseVmlStyle, parseVmlTextData, parseVmlTextPath, parseVmlTextbox, parseVmlTrueFalse, parseVmlTrueFalseBlank, parseVmlWrap, partPathToRelsPath, patchSpaceAttribute, patternFillDesc, percentageValue, pickConnectorBase, pickGroupBase, pickNonVisualDrawingProperties, pictureLockingDesc, pointMeasureValue, positiveUniversalMeasureValue, presentationLayoutVariablesDesc, presetColorDesc, presetGeometryDesc, randomBytes, readHyperlink, readParagraphProperties, registerHyperlink, removeOverride, replaceAllPlaceholders, replaceAudioPlaceholders, replaceChartPlaceholders, replaceHyperlinkPlaceholders, replaceImageLinkPlaceholders, replaceImagePlaceholders, replaceMediaPlaceholders, replaceNumberingPlaceholders, replaceOleLinkPlaceholders, replaceOlePlaceholders, replacePlaceholders, replaceSmartArtPlaceholders, replaceVideoPlaceholders, resolveRelationshipTarget, resolverFromRegistry, rgbColorDesc, roundTripFields, runPropertiesDesc, scRgbColorDesc, scene3DDesc, schemeColorDesc, shape3DDesc, shapeLockingDesc, shapePropertiesDesc, shortHexNumber, signedHpsMeasureValue, signedTwipsMeasureValue, solidFillDesc, sourceRectangleDesc, strFromU8, stretchDesc, stringify, stringifyAdjustmentValues, stringifyBlipEffects, stringifyColorChoice, stringifyColorDefinition, stringifyColorDefinitionPart, stringifyColorMapping, stringifyConnection, stringifyDataModel, stringifyDataModelOptions, stringifyEndpointConnection, stringifyLayoutDefinition, stringifyLayoutDefinitionPart, stringifyLineProperties, stringifyNonVisualContentPartProperties, stringifyNonVisualDrawingProperties, stringifyParagraphPropertiesElement, stringifyPoint, stringifyPresetGeometry, stringifyRunProperties, stringifyShapeStyle, stringifyStretch, stringifyStringVector, stringifyStyleDefinition, stringifyStyleDefinitionPart, stringifyTextListStyleTag, stringifyTextRun, stringifyTextStyles, stringifyTransPoint, stringifyVariantValue, stringifyVmlAnchorLock, stringifyVmlArc, stringifyVmlAttributes, stringifyVmlBackground, stringifyVmlBorder, stringifyVmlCallout, stringifyVmlClientData, stringifyVmlClipPath, stringifyVmlColorMenu, stringifyVmlColorMru, stringifyVmlComplex, stringifyVmlCurve, stringifyVmlDiagram, stringifyVmlEquationXml, stringifyVmlExtrusion, stringifyVmlFill, stringifyVmlFormulas, stringifyVmlGroup, stringifyVmlHandles, stringifyVmlImage, stringifyVmlImageData, stringifyVmlInk, stringifyVmlIsComment, stringifyVmlLine, stringifyVmlLock, stringifyVmlOfficeFill, stringifyVmlOleObject, stringifyVmlOval, stringifyVmlPath, stringifyVmlPolyline, stringifyVmlRect, stringifyVmlRoundRect, stringifyVmlShadow, stringifyVmlShape, stringifyVmlShapeChild, stringifyVmlShapeDefaults, stringifyVmlShapeLayout, stringifyVmlShapetype, stringifyVmlSignatureLine, stringifyVmlSkew, stringifyVmlStroke, stringifyVmlStyle, stringifyVmlTextData, stringifyVmlTextPath, stringifyVmlTextbox, stringifyVmlTrueFalse, stringifyVmlTrueFalseBlank, stringifyVmlWrap, stripColorHashPrefix, styleDefDesc, styleToKeyMap, summarizeOpcIssues, systemColorDesc, textBodyDesc, textListStyleDesc, textRunDesc, textStylesDesc, themeDesc, themeManagerDesc, themeOverrideDesc, tileDesc, toJson, toUint8Array, transform2DDesc, twipsMeasureValue, uCharHexNumber, uniqueId, uniqueNumericIdCreator, uniqueUuid, universalMeasureValue, unsignedDecimalNumber, unzipSync, userShapesDesc, validateOpcConsistency, withDiagramNamespaces, xsdAnimCalcMode, xsdAnimClass, xsdAnimLevel, xsdAnimValueType, xsdAnimationDgmBuild, xsdAxisCrossBetween, xsdAxisCrosses, xsdAxisLabelAlignment, xsdAxisOrientation, xsdAxisPosition, xsdBlendMode, xsdChartBuild, xsdComments, xsdCompoundLine, xsdConsolidateFunction, xsdDashStyle, xsdDataLabelPosition, xsdDiagramBuild, xsdDiagramDirection, xsdEffectContainer, xsdErrorValueType, xsdFontAlignment, xsdHierBranch, xsdHueDirection, xsdIterateType, xsdJcAlignment, xsdLegendPosition, xsdLightRigDirection, xsdLineCap, xsdLineEndSize, xsdMaterialType, xsdMathStyle, xsdOnOffStyle, xsdOrient, xsdPathFillMode, xsdPattern, xsdPenAlignment, xsdPlaceholderType, xsdPresetShadow, xsdRectAlignment, xsdResizeHandles, xsdShadingPattern, xsdSizeRepresents, xsdSlideLayoutType, xsdSplitType, xsdStrikeStyle, xsdTableWidthType, xsdTextAlign, xsdTextAnchor, xsdTextBuild, xsdTextCaps, xsdTextTabAlignment, xsdTextVerticalType, xsdTotalsRowFunction, xsdTrendlineType, xsdUnderlineStyle, xsdVerticalMergeRev, zipAndConvert, zipSync, zipSyncAndConvert };
|
|
1271
2486
|
|
|
1272
2487
|
//# sourceMappingURL=index.mjs.map
|