ooxml-core 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/automation/node.d.ts.map +1 -1
- package/dist/collab/broadcast-transport.d.ts.map +1 -1
- package/dist/collab/emitter.d.ts.map +1 -1
- package/dist/collab/index.cjs +3 -2
- package/dist/collab/index.mjs +3 -2
- package/dist/collab/ordering.d.ts.map +1 -1
- package/dist/crypto/detect.d.ts.map +1 -1
- package/dist/crypto/errors.d.ts +3 -3
- package/dist/crypto/errors.d.ts.map +1 -1
- package/dist/crypto/index.cjs +6 -6
- package/dist/crypto/index.mjs +6 -6
- package/dist/crypto/key-derivation.d.ts.map +1 -1
- package/dist/diagram/drawing.d.ts.map +1 -1
- package/dist/diagram/relationships.d.ts.map +1 -1
- package/dist/digest/sha512.d.ts.map +1 -1
- package/dist/docx/diagram.d.ts.map +1 -1
- package/dist/docx/docpr-ids.d.ts.map +1 -1
- package/dist/docx/field-runs.d.ts.map +1 -1
- package/dist/docx/generated/wml-simple-types.d.ts +99 -99
- package/dist/docx/generated/wml-simple-types.d.ts.map +1 -1
- package/dist/docx/heading-list-kinds.d.ts.map +1 -1
- package/dist/docx/highlight.d.ts +1 -1
- package/dist/docx/highlight.d.ts.map +1 -1
- package/dist/docx/layout/page-cursor.d.ts.map +1 -1
- package/dist/docx/ligatures.d.ts +1 -1
- package/dist/docx/ligatures.d.ts.map +1 -1
- package/dist/docx/load/index.cjs +18 -18
- package/dist/docx/load/index.mjs +18 -18
- package/dist/docx/load/legacy-doc.d.ts.map +1 -1
- package/dist/docx/paragraph-styles.d.ts +1 -1
- package/dist/docx/paragraph-styles.d.ts.map +1 -1
- package/dist/docx/relationship-allocator.d.ts.map +1 -1
- package/dist/docx/revision-commands.d.ts.map +1 -1
- package/dist/docx/simple-types.d.ts.map +1 -1
- package/dist/docx/table-of-contents.d.ts.map +1 -1
- package/dist/docx/table-of-figures.d.ts.map +1 -1
- package/dist/docx/test-support/restart-fixture.d.ts +3 -3
- package/dist/docx/test-support/restart-fixture.d.ts.map +1 -1
- package/dist/docx/validate-issues.d.ts.map +1 -1
- package/dist/docx/write-revisions.d.ts.map +1 -1
- package/dist/docx/xml.d.ts.map +1 -1
- package/dist/docx/zip-parts.d.ts.map +1 -1
- package/dist/opc/properties/types.d.ts +6 -6
- package/dist/opc/properties/types.d.ts.map +1 -1
- package/dist/opc/relationship-types.d.ts +6 -6
- package/dist/opc/relationship-types.d.ts.map +1 -1
- package/dist/opc/relationships.d.ts.map +1 -1
- package/dist/pptx/automation/index.cjs +138 -138
- package/dist/pptx/automation/index.d.ts +3 -3
- package/dist/pptx/automation/index.mjs +138 -138
- package/dist/pptx/chunks/{index-BWRd8p4y.d.ts → index-BtBj3VG1.d.ts} +3 -3
- package/dist/pptx/chunks/index-BtBj3VG1.d.ts.map +1 -0
- package/dist/pptx/chunks/{index-CT9y69AZ.d.ts → index-D0yGoLyw.d.ts} +136 -136
- package/dist/pptx/chunks/index-D0yGoLyw.d.ts.map +1 -0
- package/dist/pptx/chunks/{text-operations-2tKzrY5o.d.ts → text-operations-GuisjlbR.d.ts} +2 -2
- package/dist/pptx/chunks/{text-operations-2tKzrY5o.d.ts.map → text-operations-GuisjlbR.d.ts.map} +1 -1
- package/dist/pptx/cli/index.cjs +104 -104
- package/dist/pptx/cli/index.d.ts +1 -1
- package/dist/pptx/cli/index.mjs +104 -104
- package/dist/pptx/converter/index.d.ts +1 -1
- package/dist/pptx/index.cjs +138 -138
- package/dist/pptx/index.d.ts +3 -3
- package/dist/pptx/index.mjs +138 -138
- package/dist/teams/call.d.ts +61 -0
- package/dist/teams/call.d.ts.map +1 -0
- package/dist/teams/chat.d.ts +34 -0
- package/dist/teams/chat.d.ts.map +1 -0
- package/dist/teams/index.cjs +2207 -0
- package/dist/teams/index.d.ts +10 -0
- package/dist/teams/index.d.ts.map +1 -0
- package/dist/teams/index.mjs +2153 -0
- package/dist/teams/model.d.ts +49 -0
- package/dist/teams/model.d.ts.map +1 -0
- package/dist/teams/peer.d.ts +76 -0
- package/dist/teams/peer.d.ts.map +1 -0
- package/dist/teams/server-config.d.ts +27 -0
- package/dist/teams/server-config.d.ts.map +1 -0
- package/dist/teams/signaling.d.ts +81 -0
- package/dist/teams/signaling.d.ts.map +1 -0
- package/dist/teams/store.d.ts +113 -0
- package/dist/teams/store.d.ts.map +1 -0
- package/dist/teams/view.d.ts +77 -0
- package/dist/teams/view.d.ts.map +1 -0
- package/dist/teams/workspace.d.ts +51 -0
- package/dist/teams/workspace.d.ts.map +1 -0
- package/dist/units/units.d.ts.map +1 -1
- package/dist/visio/edit-geometry-admission.d.ts.map +1 -1
- package/dist/visio/edit-recalculate-index.d.ts.map +1 -1
- package/dist/visio/emf-admission-context.d.ts +1 -1
- package/dist/visio/emf-admission-context.d.ts.map +1 -1
- package/dist/visio/foreign-vector-types.d.ts.map +1 -1
- package/dist/visio/formula-master.d.ts +2 -2
- package/dist/visio/formula.d.ts.map +1 -1
- package/dist/visio/index.cjs +2048 -290
- package/dist/visio/index.mjs +2048 -290
- package/dist/visio/media.d.ts.map +1 -1
- package/dist/visio/package-common.d.ts.map +1 -1
- package/dist/visio/package.d.ts.map +1 -1
- package/dist/visio/sheet.d.ts.map +1 -1
- package/dist/visio/theme-color.d.ts.map +1 -1
- package/dist/xlsx/address.d.ts.map +1 -1
- package/dist/xlsx/cell-styles.d.ts.map +1 -1
- package/dist/xlsx/cells.d.ts.map +1 -1
- package/dist/xlsx/edit/calc-mode.d.ts.map +1 -1
- package/dist/xlsx/edit/clipboard-html.d.ts.map +1 -1
- package/dist/xlsx/edit/columns.d.ts.map +1 -1
- package/dist/xlsx/edit/context.d.ts.map +1 -1
- package/dist/xlsx/edit/fill-series.d.ts.map +1 -1
- package/dist/xlsx/edit/history.d.ts.map +1 -1
- package/dist/xlsx/edit/outline.d.ts.map +1 -1
- package/dist/xlsx/edit/range-math.d.ts.map +1 -1
- package/dist/xlsx/edit/session-calc.d.ts.map +1 -1
- package/dist/xlsx/edit/structure.d.ts.map +1 -1
- package/dist/xlsx/formula/area-index.d.ts.map +1 -1
- package/dist/xlsx/formula/ast.d.ts.map +1 -1
- package/dist/xlsx/formula/date-serial.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-core.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-host.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-util.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/criteria.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/dist-core.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/helpers.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/math-combin.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/registry.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/stats-core.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/text-case.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/types.d.ts.map +1 -1
- package/dist/xlsx/formula/graph-index.d.ts.map +1 -1
- package/dist/xlsx/formula/lexemes.d.ts +1 -1
- package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
- package/dist/xlsx/formula/references.d.ts.map +1 -1
- package/dist/xlsx/formula/spill.d.ts.map +1 -1
- package/dist/xlsx/formula/test-helpers.d.ts.map +1 -1
- package/dist/xlsx/formula/tokenizer.d.ts.map +1 -1
- package/dist/xlsx/formula/values.d.ts +2 -1
- package/dist/xlsx/formula/values.d.ts.map +1 -1
- package/dist/xlsx/layout/axis-metrics.d.ts.map +1 -1
- package/dist/xlsx/layout/chart-svg-util.d.ts.map +1 -1
- package/dist/xlsx/layout/colors.d.ts +1 -1
- package/dist/xlsx/layout/colors.d.ts.map +1 -1
- package/dist/xlsx/layout/tint.d.ts.map +1 -1
- package/dist/xlsx/layout/units.d.ts.map +1 -1
- package/dist/xlsx/load/errors.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +24 -24
- package/dist/xlsx/load/index.mjs +24 -24
- package/dist/xlsx/load/legacy-xls-sheet.d.ts.map +1 -1
- package/dist/xlsx/load/legacy-xls.d.ts.map +1 -1
- package/dist/xlsx/model.d.ts +1 -1
- package/dist/xlsx/model.d.ts.map +1 -1
- package/dist/xlsx/numfmt/decimal.d.ts.map +1 -1
- package/dist/xlsx/read/package.d.ts +22 -22
- package/dist/xlsx/read/package.d.ts.map +1 -1
- package/dist/xlsx/read/password-hash.d.ts.map +1 -1
- package/dist/xlsx/read/sheet-props.d.ts +7 -7
- package/dist/xlsx/read/sheet-props.d.ts.map +1 -1
- package/dist/xlsx/read/theme.d.ts +2 -2
- package/dist/xlsx/read/theme.d.ts.map +1 -1
- package/dist/xlsx/read/worksheet.d.ts +1 -1
- package/dist/xlsx/read/worksheet.d.ts.map +1 -1
- package/dist/xlsx/read/xml-util.d.ts.map +1 -1
- package/dist/xlsx/workbook.d.ts.map +1 -1
- package/dist/xlsx/write/carried-refs.d.ts.map +1 -1
- package/dist/xlsx/write/comments.d.ts.map +1 -1
- package/dist/xlsx/write/doc-props.d.ts.map +1 -1
- package/dist/xlsx/write/drawing.d.ts.map +1 -1
- package/dist/xlsx/write/dynamic-array.d.ts.map +1 -1
- package/dist/xlsx/write/metadata.d.ts.map +1 -1
- package/dist/xlsx/write/package-writer.d.ts.map +1 -1
- package/dist/xlsx/write/shared-strings.d.ts.map +1 -1
- package/dist/xlsx/write/snapshot.d.ts.map +1 -1
- package/dist/xlsx/write/style-xml.d.ts.map +1 -1
- package/dist/xlsx/write/styles.d.ts.map +1 -1
- package/dist/xlsx/write/vml-ids.d.ts.map +1 -1
- package/dist/xlsx/write/xml-out.d.ts.map +1 -1
- package/dist/xml/namespaces.d.ts +31 -31
- package/dist/xml/namespaces.d.ts.map +1 -1
- package/dist/xml/xml.d.ts.map +1 -1
- package/package.json +19 -14
- package/dist/pptx/chunks/index-BWRd8p4y.d.ts.map +0 -1
- package/dist/pptx/chunks/index-CT9y69AZ.d.ts.map +0 -1
package/dist/visio/index.mjs
CHANGED
|
@@ -2246,7 +2246,7 @@ function sanitize(root, limits) {
|
|
|
2246
2246
|
}
|
|
2247
2247
|
return { tag: data2.tag, attrs, children: data2.children };
|
|
2248
2248
|
}
|
|
2249
|
-
function
|
|
2249
|
+
function children4(value, optional = false) {
|
|
2250
2250
|
if (value === void 0 && optional) return [];
|
|
2251
2251
|
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
|
|
2252
2252
|
unsafe("Expected plain child array.");
|
|
@@ -2277,7 +2277,7 @@ function sanitize(root, limits) {
|
|
|
2277
2277
|
return target;
|
|
2278
2278
|
}
|
|
2279
2279
|
function leaf(data2) {
|
|
2280
|
-
if (
|
|
2280
|
+
if (children4(data2.children, true).length !== 0) unsafe("Path cannot contain child elements.");
|
|
2281
2281
|
return pathCommands(data2.attrs.d, limits, pathBudget);
|
|
2282
2282
|
}
|
|
2283
2283
|
function item(value, depth) {
|
|
@@ -2290,7 +2290,7 @@ function sanitize(root, limits) {
|
|
|
2290
2290
|
paint: paint(data2.attrs)
|
|
2291
2291
|
}) : Object.assign(target, {
|
|
2292
2292
|
kind: "group",
|
|
2293
|
-
items: Object.freeze(
|
|
2293
|
+
items: Object.freeze(children4(data2.children).map((child2) => item(child2, depth + 1)))
|
|
2294
2294
|
});
|
|
2295
2295
|
freezeLater.push(result);
|
|
2296
2296
|
return result;
|
|
@@ -2307,7 +2307,7 @@ function sanitize(root, limits) {
|
|
|
2307
2307
|
ids.set(id, clips.length);
|
|
2308
2308
|
const target = base(data2.attrs);
|
|
2309
2309
|
const paths = [];
|
|
2310
|
-
for (const child2 of
|
|
2310
|
+
for (const child2 of children4(data2.children)) {
|
|
2311
2311
|
const part = node(child2, depth + 1, true);
|
|
2312
2312
|
if (part.tag !== "path") unsafe("Clip content must be a path.");
|
|
2313
2313
|
const path = Object.assign(base(part.attrs), {
|
|
@@ -2332,11 +2332,11 @@ function sanitize(root, limits) {
|
|
|
2332
2332
|
if (viewBox[0] !== 0 || viewBox[1] !== 0 || viewBox[2] !== width || viewBox[3] !== height)
|
|
2333
2333
|
unsafe("Viewport differs from dimensions.");
|
|
2334
2334
|
const items = [];
|
|
2335
|
-
for (const child2 of
|
|
2335
|
+
for (const child2 of children4(data.children)) {
|
|
2336
2336
|
const peek = record(child2, ["tag", "attrs", "children"]);
|
|
2337
2337
|
if (peek.tag === "defs") {
|
|
2338
2338
|
const defs = node(child2, 1);
|
|
2339
|
-
for (const value of
|
|
2339
|
+
for (const value of children4(defs.children)) definition(value, 2);
|
|
2340
2340
|
} else items.push(item(child2, 1));
|
|
2341
2341
|
}
|
|
2342
2342
|
for (const { target, id } of pending) {
|
|
@@ -5128,7 +5128,7 @@ function getVisioPageLayers(document, pageId) {
|
|
|
5128
5128
|
return result.reverse();
|
|
5129
5129
|
}
|
|
5130
5130
|
|
|
5131
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5131
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
|
|
5132
5132
|
var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
|
|
5133
5133
|
var ENDOFCHAIN = 4294967294;
|
|
5134
5134
|
var FREESECT = 4294967295;
|
|
@@ -5146,7 +5146,7 @@ var Ole2ParseError = class extends Error {
|
|
|
5146
5146
|
}
|
|
5147
5147
|
};
|
|
5148
5148
|
|
|
5149
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5149
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
|
|
5150
5150
|
function parseOle2(buffer) {
|
|
5151
5151
|
const data = new Uint8Array(buffer);
|
|
5152
5152
|
const view2 = new DataView(buffer);
|
|
@@ -5376,7 +5376,7 @@ function parseOle2(buffer) {
|
|
|
5376
5376
|
return { entries, getStream };
|
|
5377
5377
|
}
|
|
5378
5378
|
|
|
5379
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5379
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document-base.js
|
|
5380
5380
|
var Ole2DocumentError = class extends Error {
|
|
5381
5381
|
code;
|
|
5382
5382
|
constructor(code, message) {
|
|
@@ -5441,7 +5441,7 @@ var Ole2DocumentBase = class {
|
|
|
5441
5441
|
}
|
|
5442
5442
|
};
|
|
5443
5443
|
|
|
5444
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5444
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-edit.js
|
|
5445
5445
|
var END = 4294967294;
|
|
5446
5446
|
var MAX = 4294967290;
|
|
5447
5447
|
var NIL = 4294967295;
|
|
@@ -5601,11 +5601,11 @@ function processCompoundFileStream(input, path, replacement) {
|
|
|
5601
5601
|
if (!workbook)
|
|
5602
5602
|
continue;
|
|
5603
5603
|
for (let p = 0; p + 4 <= workbook.length; ) {
|
|
5604
|
-
const
|
|
5604
|
+
const record5 = workbook[p] | workbook[p + 1] << 8;
|
|
5605
5605
|
const length = workbook[p + 2] | workbook[p + 3] << 8;
|
|
5606
|
-
if (
|
|
5606
|
+
if (record5 === 47)
|
|
5607
5607
|
return reject2();
|
|
5608
|
-
if (p + 4 + length > workbook.length ||
|
|
5608
|
+
if (p + 4 + length > workbook.length || record5 === 10)
|
|
5609
5609
|
break;
|
|
5610
5610
|
p += 4 + length;
|
|
5611
5611
|
}
|
|
@@ -5714,7 +5714,7 @@ function replaceCompoundFileStream(input, path, replacement) {
|
|
|
5714
5714
|
return processCompoundFileStream(input, path, replacement) ?? input;
|
|
5715
5715
|
}
|
|
5716
5716
|
|
|
5717
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5717
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-v4.js
|
|
5718
5718
|
var END2 = 4294967294;
|
|
5719
5719
|
var FREE = 4294967295;
|
|
5720
5720
|
var FAT = 4294967293;
|
|
@@ -5786,49 +5786,49 @@ function validateHierarchy(slots) {
|
|
|
5786
5786
|
throw new Error("Unreachable directory entries");
|
|
5787
5787
|
}
|
|
5788
5788
|
function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
5789
|
-
const
|
|
5789
|
+
const fail3 = (reason) => ({ ok: false, bytes: input, reason });
|
|
5790
5790
|
try {
|
|
5791
5791
|
if (input.length < 512 || !path.length || path.some((part) => !part))
|
|
5792
|
-
return
|
|
5792
|
+
return fail3("invalid-or-missing-stream");
|
|
5793
5793
|
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
5794
5794
|
const read = (offset) => view2.getUint32(offset, true);
|
|
5795
5795
|
const version = view2.getUint16(26, true);
|
|
5796
5796
|
if (version !== 4)
|
|
5797
|
-
return
|
|
5797
|
+
return fail3("unsupported-version");
|
|
5798
5798
|
const SECTOR3 = 4096, FAT_ENTRIES2 = SECTOR3 / 4, DIRECTORY_ENTRIES = SECTOR3 / 128;
|
|
5799
5799
|
if (read(72) !== 0 || read(44) > 109)
|
|
5800
|
-
return
|
|
5800
|
+
return fail3("unsupported-difat");
|
|
5801
5801
|
const cutoff = read(56);
|
|
5802
5802
|
if (cutoff !== 0 && cutoff !== 4096)
|
|
5803
|
-
return
|
|
5803
|
+
return fail3("unsupported-layout");
|
|
5804
5804
|
const original = readCompoundFileStream(input, path);
|
|
5805
5805
|
if (!original)
|
|
5806
|
-
return
|
|
5806
|
+
return fail3("invalid-or-missing-stream");
|
|
5807
5807
|
const name = path[path.length - 1].toLocaleLowerCase();
|
|
5808
5808
|
if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
|
|
5809
|
-
return
|
|
5809
|
+
return fail3("unsafe-edit");
|
|
5810
5810
|
if (name === "book" || name === "workbook") {
|
|
5811
5811
|
for (let offset = 0; offset + 4 <= original.length; ) {
|
|
5812
|
-
const
|
|
5812
|
+
const record5 = original[offset] | original[offset + 1] << 8;
|
|
5813
5813
|
const length = original[offset + 2] | original[offset + 3] << 8;
|
|
5814
|
-
if (
|
|
5815
|
-
return
|
|
5816
|
-
if (
|
|
5814
|
+
if (record5 === 47)
|
|
5815
|
+
return fail3("unsafe-edit");
|
|
5816
|
+
if (record5 === 10 || offset + 4 + length > original.length)
|
|
5817
5817
|
break;
|
|
5818
5818
|
offset += 4 + length;
|
|
5819
5819
|
}
|
|
5820
5820
|
}
|
|
5821
5821
|
const validated = replaceCompoundFileStream(input, path, original);
|
|
5822
5822
|
if (validated === input)
|
|
5823
|
-
return
|
|
5823
|
+
return fail3("unsafe-edit");
|
|
5824
5824
|
const sameLength = replacement.length === original.length;
|
|
5825
5825
|
if (!sameLength && original.length < cutoff)
|
|
5826
|
-
return
|
|
5826
|
+
return fail3("unsupported-mini-stream");
|
|
5827
5827
|
if (!sameLength && replacement.length < cutoff)
|
|
5828
|
-
return
|
|
5828
|
+
return fail3("unsupported-mini-transition");
|
|
5829
5829
|
const sectorCount = input.length / SECTOR3 - 1, fatCount = read(44);
|
|
5830
5830
|
if (sectorCount > fatCount * FAT_ENTRIES2)
|
|
5831
|
-
return
|
|
5831
|
+
return fail3("unsafe-edit");
|
|
5832
5832
|
const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
|
|
5833
5833
|
const fat = [];
|
|
5834
5834
|
for (const id of fatIds) {
|
|
@@ -5836,11 +5836,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5836
5836
|
fat.push(read((id + 1) * SECTOR3 + i * 4));
|
|
5837
5837
|
}
|
|
5838
5838
|
if (fatIds.some((id) => fat[id] !== FAT))
|
|
5839
|
-
return
|
|
5839
|
+
return fail3("unsafe-edit");
|
|
5840
5840
|
const slots = /* @__PURE__ */ new Map();
|
|
5841
5841
|
const directoryChain = follow(fat, read(48));
|
|
5842
5842
|
if (read(40) !== directoryChain.length)
|
|
5843
|
-
return
|
|
5843
|
+
return fail3("unsafe-edit");
|
|
5844
5844
|
for (const [block, sector] of directoryChain.entries()) {
|
|
5845
5845
|
for (let entry = 0; entry < DIRECTORY_ENTRIES; entry++) {
|
|
5846
5846
|
const offset = (sector + 1) * SECTOR3 + entry * 128, type = view2.getUint8(offset + 66);
|
|
@@ -5848,33 +5848,33 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5848
5848
|
continue;
|
|
5849
5849
|
const nameLength = view2.getUint16(offset + 64, true);
|
|
5850
5850
|
if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
|
|
5851
|
-
return
|
|
5851
|
+
return fail3("unsafe-edit");
|
|
5852
5852
|
let name2 = "";
|
|
5853
5853
|
for (let i = 0; i < nameLength - 2; i += 2)
|
|
5854
5854
|
name2 += String.fromCharCode(view2.getUint16(offset + i, true));
|
|
5855
5855
|
if (read(offset + 124) !== 0)
|
|
5856
|
-
return
|
|
5856
|
+
return fail3("unsafe-edit");
|
|
5857
5857
|
const id = block * DIRECTORY_ENTRIES + entry;
|
|
5858
5858
|
slots.set(id, { id, name: name2, type, left: read(offset + 68), right: read(offset + 72), child: read(offset + 76), start: read(offset + 116), size: read(offset + 120), offset });
|
|
5859
5859
|
}
|
|
5860
5860
|
}
|
|
5861
5861
|
if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
|
|
5862
|
-
return
|
|
5862
|
+
return fail3("unsafe-edit");
|
|
5863
5863
|
const target = findSlot(slots, path);
|
|
5864
5864
|
validateHierarchy(slots);
|
|
5865
5865
|
if (sameLength) {
|
|
5866
5866
|
const bytes = replaceCompoundFileStream(input, path, replacement);
|
|
5867
|
-
return bytes === input ?
|
|
5867
|
+
return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
|
|
5868
5868
|
}
|
|
5869
5869
|
const oldChain = follow(fat, target.start);
|
|
5870
5870
|
if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR3))
|
|
5871
|
-
return
|
|
5871
|
+
return fail3("unsafe-edit");
|
|
5872
5872
|
const payloadSectors = Math.ceil(replacement.length / SECTOR3);
|
|
5873
5873
|
let newFatCount = fatCount;
|
|
5874
5874
|
while (sectorCount + payloadSectors + newFatCount - fatCount > newFatCount * FAT_ENTRIES2)
|
|
5875
5875
|
newFatCount++;
|
|
5876
5876
|
if (newFatCount > 109)
|
|
5877
|
-
return
|
|
5877
|
+
return fail3("allocation-limit");
|
|
5878
5878
|
const totalSectors = sectorCount + payloadSectors + newFatCount - fatCount;
|
|
5879
5879
|
const output = new Uint8Array((totalSectors + 1) * SECTOR3);
|
|
5880
5880
|
output.set(input);
|
|
@@ -5898,11 +5898,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5898
5898
|
outView.setUint32(target.offset + 120, replacement.length, true);
|
|
5899
5899
|
return { ok: true, bytes: output };
|
|
5900
5900
|
} catch {
|
|
5901
|
-
return
|
|
5901
|
+
return fail3("unsafe-edit");
|
|
5902
5902
|
}
|
|
5903
5903
|
}
|
|
5904
5904
|
|
|
5905
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5905
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-allocation.js
|
|
5906
5906
|
function appendCompoundAllocations(input, existingFatIds, payloads, sectorSize = 512) {
|
|
5907
5907
|
const sectorCount = input.length / sectorSize - 1;
|
|
5908
5908
|
const entriesPerFat = sectorSize / 4;
|
|
@@ -5949,7 +5949,7 @@ function followCompoundAllocation(table, start) {
|
|
|
5949
5949
|
return ids;
|
|
5950
5950
|
}
|
|
5951
5951
|
|
|
5952
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5952
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-mini.js
|
|
5953
5953
|
var END3 = 4294967294;
|
|
5954
5954
|
var FREE2 = 4294967295;
|
|
5955
5955
|
var SECTOR = 512;
|
|
@@ -6021,7 +6021,7 @@ function resizeMiniCompoundStream(input, fat, fatIds, root, target, replacement,
|
|
|
6021
6021
|
return output.bytes;
|
|
6022
6022
|
}
|
|
6023
6023
|
|
|
6024
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6024
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize.js
|
|
6025
6025
|
var END4 = 4294967294;
|
|
6026
6026
|
var FREE3 = 4294967295;
|
|
6027
6027
|
var FAT2 = 4294967293;
|
|
@@ -6097,43 +6097,43 @@ function validateHierarchy2(slots) {
|
|
|
6097
6097
|
function resizeCompoundFileStream(input, path, replacement) {
|
|
6098
6098
|
if (input.length >= 512 && new DataView(input.buffer, input.byteOffset, input.byteLength).getUint16(26, true) === 4)
|
|
6099
6099
|
return resizeCompoundFileStreamV4(input, path, replacement);
|
|
6100
|
-
const
|
|
6100
|
+
const fail3 = (reason) => ({ ok: false, bytes: input, reason });
|
|
6101
6101
|
try {
|
|
6102
6102
|
if (input.length < SECTOR2 || !path.length || path.some((part) => !part))
|
|
6103
|
-
return
|
|
6103
|
+
return fail3("invalid-or-missing-stream");
|
|
6104
6104
|
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
6105
6105
|
const read = (offset) => view2.getUint32(offset, true);
|
|
6106
6106
|
if (view2.getUint16(26, true) !== 3)
|
|
6107
|
-
return
|
|
6107
|
+
return fail3("unsupported-version");
|
|
6108
6108
|
if (read(72) !== 0 || read(44) > 109)
|
|
6109
|
-
return
|
|
6109
|
+
return fail3("unsupported-difat");
|
|
6110
6110
|
const cutoff = read(56);
|
|
6111
6111
|
if (cutoff !== 0 && cutoff !== 4096)
|
|
6112
|
-
return
|
|
6112
|
+
return fail3("unsupported-layout");
|
|
6113
6113
|
const original = readCompoundFileStream(input, path);
|
|
6114
6114
|
if (!original)
|
|
6115
|
-
return
|
|
6115
|
+
return fail3("invalid-or-missing-stream");
|
|
6116
6116
|
const name = path[path.length - 1].toLocaleLowerCase();
|
|
6117
6117
|
if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
|
|
6118
|
-
return
|
|
6118
|
+
return fail3("unsafe-edit");
|
|
6119
6119
|
if (name === "book" || name === "workbook") {
|
|
6120
6120
|
for (let offset = 0; offset + 4 <= original.length; ) {
|
|
6121
|
-
const
|
|
6121
|
+
const record5 = original[offset] | original[offset + 1] << 8;
|
|
6122
6122
|
const length = original[offset + 2] | original[offset + 3] << 8;
|
|
6123
|
-
if (
|
|
6124
|
-
return
|
|
6125
|
-
if (
|
|
6123
|
+
if (record5 === 47)
|
|
6124
|
+
return fail3("unsafe-edit");
|
|
6125
|
+
if (record5 === 10 || offset + 4 + length > original.length)
|
|
6126
6126
|
break;
|
|
6127
6127
|
offset += 4 + length;
|
|
6128
6128
|
}
|
|
6129
6129
|
}
|
|
6130
6130
|
const validated = replaceCompoundFileStream(input, path, original);
|
|
6131
6131
|
if (validated === input)
|
|
6132
|
-
return
|
|
6132
|
+
return fail3("unsafe-edit");
|
|
6133
6133
|
const sameLength = replacement.length === original.length;
|
|
6134
6134
|
const sectorCount = input.length / SECTOR2 - 1, fatCount = read(44);
|
|
6135
6135
|
if (sectorCount > fatCount * FAT_ENTRIES)
|
|
6136
|
-
return
|
|
6136
|
+
return fail3("unsafe-edit");
|
|
6137
6137
|
const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
|
|
6138
6138
|
const fat = [];
|
|
6139
6139
|
for (const id of fatIds) {
|
|
@@ -6141,7 +6141,7 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6141
6141
|
fat.push(read((id + 1) * SECTOR2 + i * 4));
|
|
6142
6142
|
}
|
|
6143
6143
|
if (fatIds.some((id) => fat[id] !== FAT2))
|
|
6144
|
-
return
|
|
6144
|
+
return fail3("unsafe-edit");
|
|
6145
6145
|
const slots = /* @__PURE__ */ new Map();
|
|
6146
6146
|
for (const [block, sector] of follow2(fat, read(48)).entries()) {
|
|
6147
6147
|
for (let entry = 0; entry < 4; entry++) {
|
|
@@ -6150,7 +6150,7 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6150
6150
|
continue;
|
|
6151
6151
|
const nameLength = view2.getUint16(offset + 64, true);
|
|
6152
6152
|
if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
|
|
6153
|
-
return
|
|
6153
|
+
return fail3("unsafe-edit");
|
|
6154
6154
|
let name2 = "";
|
|
6155
6155
|
for (let i = 0; i < nameLength - 2; i += 2)
|
|
6156
6156
|
name2 += String.fromCharCode(view2.getUint16(offset + i, true));
|
|
@@ -6159,34 +6159,34 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6159
6159
|
}
|
|
6160
6160
|
}
|
|
6161
6161
|
if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
|
|
6162
|
-
return
|
|
6162
|
+
return fail3("unsafe-edit");
|
|
6163
6163
|
const target = findSlot2(slots, path);
|
|
6164
6164
|
validateHierarchy2(slots);
|
|
6165
6165
|
if (sameLength) {
|
|
6166
6166
|
const bytes = replaceCompoundFileStream(input, path, replacement);
|
|
6167
|
-
return bytes === input ?
|
|
6167
|
+
return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
|
|
6168
6168
|
}
|
|
6169
6169
|
if (original.length < cutoff || replacement.length < cutoff) {
|
|
6170
6170
|
const bytes = resizeMiniCompoundStream(input, fat, fatIds, slots.get(0), target, replacement, cutoff);
|
|
6171
|
-
return bytes ? { ok: true, bytes } :
|
|
6171
|
+
return bytes ? { ok: true, bytes } : fail3("allocation-limit");
|
|
6172
6172
|
}
|
|
6173
6173
|
const oldChain = follow2(fat, target.start);
|
|
6174
6174
|
if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR2))
|
|
6175
|
-
return
|
|
6175
|
+
return fail3("unsafe-edit");
|
|
6176
6176
|
const output = appendCompoundAllocations(input, fatIds, [replacement]);
|
|
6177
6177
|
if (!output)
|
|
6178
|
-
return
|
|
6178
|
+
return fail3("allocation-limit");
|
|
6179
6179
|
for (const id of oldChain)
|
|
6180
6180
|
output.writeFat(id, FREE3);
|
|
6181
6181
|
output.view.setUint32(target.offset + 116, output.chains[0][0] ?? END4, true);
|
|
6182
6182
|
output.view.setUint32(target.offset + 120, replacement.length, true);
|
|
6183
6183
|
return { ok: true, bytes: output.bytes };
|
|
6184
6184
|
} catch {
|
|
6185
|
-
return
|
|
6185
|
+
return fail3("unsafe-edit");
|
|
6186
6186
|
}
|
|
6187
6187
|
}
|
|
6188
6188
|
|
|
6189
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6189
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fib.js
|
|
6190
6190
|
var FC_LCB_INDEX = {
|
|
6191
6191
|
plcfbteChpx: 12,
|
|
6192
6192
|
plcfbtePapx: 13,
|
|
@@ -6282,7 +6282,7 @@ function patchDocFib(wordDoc, fib, patch) {
|
|
|
6282
6282
|
view2.setUint32(papxOff + 4, patch.plcfbtePapx.lcb, true);
|
|
6283
6283
|
}
|
|
6284
6284
|
|
|
6285
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6285
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cfb.js
|
|
6286
6286
|
var DocCfbRewriteError = class extends Error {
|
|
6287
6287
|
constructor(message) {
|
|
6288
6288
|
super(message);
|
|
@@ -6337,7 +6337,7 @@ function unwrapDocBytes(bytes) {
|
|
|
6337
6337
|
}
|
|
6338
6338
|
}
|
|
6339
6339
|
|
|
6340
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6340
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fkp.js
|
|
6341
6341
|
var PAGE_SIZE = 512;
|
|
6342
6342
|
function parseBteTable(tableStream, at) {
|
|
6343
6343
|
const view2 = new DataView(tableStream.buffer, tableStream.byteOffset, tableStream.byteLength);
|
|
@@ -6478,7 +6478,7 @@ function buildSingleRunChpxPage(fcStart, fcEnd, blob) {
|
|
|
6478
6478
|
return page;
|
|
6479
6479
|
}
|
|
6480
6480
|
|
|
6481
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6481
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cp1252.js
|
|
6482
6482
|
var CP1252_HIGH_BLOCK = [
|
|
6483
6483
|
8364,
|
|
6484
6484
|
129,
|
|
@@ -6546,7 +6546,7 @@ function encodeCp1252(text) {
|
|
|
6546
6546
|
return Uint8Array.from(bytes);
|
|
6547
6547
|
}
|
|
6548
6548
|
|
|
6549
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6549
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-pieces.js
|
|
6550
6550
|
var CLXT_PRC = 1;
|
|
6551
6551
|
var CLXT_PCDT = 2;
|
|
6552
6552
|
var DocResourceLimitError = class extends Error {
|
|
@@ -6758,7 +6758,7 @@ function buildClxBytes(pieces, prcBytes = new Uint8Array()) {
|
|
|
6758
6758
|
return result;
|
|
6759
6759
|
}
|
|
6760
6760
|
|
|
6761
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6761
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fields.js
|
|
6762
6762
|
var UnsupportedDocFieldEditError = class extends Error {
|
|
6763
6763
|
constructor(message) {
|
|
6764
6764
|
super(message);
|
|
@@ -6842,7 +6842,7 @@ function shiftDocMainFieldCps(table, at, body, editStart, editEnd, delta, maxFie
|
|
|
6842
6842
|
return result;
|
|
6843
6843
|
}
|
|
6844
6844
|
|
|
6845
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6845
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-editor.js
|
|
6846
6846
|
var RISKY_PLCF_INDICES = [2, 3, 4, 5, 17, 18, 19, 20, 40, 41, 42, 43, 46, 47, 48, 54, 55, 56, 57, 58, 59, 75, 76, 89, 90];
|
|
6847
6847
|
var RISKY_STTB_INDICES = [21, 22, 23];
|
|
6848
6848
|
var SAFE_EXTENDED_FC_LCB_INDICES = /* @__PURE__ */ new Set([93, 94, 113, 181, 182]);
|
|
@@ -7111,7 +7111,7 @@ function tryWriteOleDocParagraphEdit(docBytes, paragraphIndex, text, limits) {
|
|
|
7111
7111
|
}
|
|
7112
7112
|
}
|
|
7113
7113
|
|
|
7114
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7114
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-runs.js
|
|
7115
7115
|
var LIMIT = 65536;
|
|
7116
7116
|
var SAFE_OPERANDS = /* @__PURE__ */ new Set([
|
|
7117
7117
|
2101,
|
|
@@ -7139,9 +7139,12 @@ var SAFE_OPERANDS = /* @__PURE__ */ new Set([
|
|
|
7139
7139
|
26646,
|
|
7140
7140
|
26647
|
|
7141
7141
|
]);
|
|
7142
|
-
function parsePrls(word, start, end) {
|
|
7142
|
+
function parsePrls(word, start, end, budget) {
|
|
7143
7143
|
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7144
7144
|
for (let at = start; at < end; ) {
|
|
7145
|
+
if (budget.remaining <= 0)
|
|
7146
|
+
throw new Error("Formatting SPRM limit");
|
|
7147
|
+
budget.remaining--;
|
|
7145
7148
|
if (at + 2 > end)
|
|
7146
7149
|
throw new Error("Truncated SPRM");
|
|
7147
7150
|
const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
|
|
@@ -7161,9 +7164,9 @@ function parsePrls(word, start, end) {
|
|
|
7161
7164
|
function parsePhysicalRuns(word, table) {
|
|
7162
7165
|
if (table.pns.length > LIMIT)
|
|
7163
7166
|
throw new Error("Formatting page limit");
|
|
7164
|
-
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7167
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [], budget = { remaining: 262144 };
|
|
7165
7168
|
for (let bte = 0; bte < table.pns.length; bte++) {
|
|
7166
|
-
const page = table.pns[bte] * 512;
|
|
7169
|
+
const page = (table.pns[bte] & 4194303) * 512;
|
|
7167
7170
|
if (page > word.length - 512)
|
|
7168
7171
|
throw new Error("Truncated CHPX page");
|
|
7169
7172
|
const count = word[page + 511], header = (count + 1) * 4 + count;
|
|
@@ -7177,7 +7180,7 @@ function parsePhysicalRuns(word, table) {
|
|
|
7177
7180
|
if (offset && (offset < header || offset + 1 + word[page + offset] > 511))
|
|
7178
7181
|
throw new Error("Invalid CHPX blob");
|
|
7179
7182
|
const blob = offset ? page + offset : 0, blobEnd = blob ? blob + 1 + word[blob] : 0;
|
|
7180
|
-
out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd) : [] });
|
|
7183
|
+
out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd, budget) : [] });
|
|
7181
7184
|
}
|
|
7182
7185
|
}
|
|
7183
7186
|
out.sort((a, b) => a.start - b.start);
|
|
@@ -7201,7 +7204,9 @@ function inspect2(input) {
|
|
|
7201
7204
|
if (fib.plcfbteChpx.lcb > LIMIT * 8 + 4 || fib.plcfbtePapx.lcb > LIMIT * 8 + 4)
|
|
7202
7205
|
throw new Error("Formatting table limit");
|
|
7203
7206
|
const chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx), papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx);
|
|
7207
|
+
papx.pns = papx.pns.map((pn) => pn & 4194303);
|
|
7204
7208
|
const physical = parsePhysicalRuns(word, chpx), runs = [];
|
|
7209
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
7205
7210
|
for (const piece of pieces) {
|
|
7206
7211
|
if (piece.cpStart >= fib.ccpText)
|
|
7207
7212
|
break;
|
|
@@ -7228,16 +7233,24 @@ function inspect2(input) {
|
|
|
7228
7233
|
const values = row.prls.filter((p) => p.opcode === opcode);
|
|
7229
7234
|
return values.length === 1 && values[0].operand[0] <= 1 ? values[0].operand[0] === 1 : void 0;
|
|
7230
7235
|
};
|
|
7236
|
+
const underline = row.prls.filter((p) => p.opcode === 10814);
|
|
7237
|
+
const kul = underline.length === 1 ? underline[0].operand[0] : void 0;
|
|
7231
7238
|
const size = row.prls.filter((p) => p.opcode === 19011);
|
|
7232
7239
|
const halfPoints = size.length === 1 ? size[0].operand[0] + size[0].operand[1] * 256 : void 0;
|
|
7240
|
+
let sprms = snapshots.get(row);
|
|
7241
|
+
if (!sprms) {
|
|
7242
|
+
sprms = Object.freeze(row.prls.map((p) => Object.freeze({ opcode: p.opcode, operand: Object.freeze(p.operand.slice()) })));
|
|
7243
|
+
snapshots.set(row, sprms);
|
|
7244
|
+
}
|
|
7233
7245
|
runs.push({
|
|
7234
7246
|
cpStart: cp,
|
|
7235
7247
|
cpEnd: end,
|
|
7236
7248
|
text: text.slice(cp, end),
|
|
7237
7249
|
directBold: direct(2101),
|
|
7238
7250
|
directItalic: direct(2102),
|
|
7251
|
+
directUnderline: piece.prm === 0 && row.prls.every((p) => SAFE_OPERANDS.has(p.opcode)) ? kul === 0 ? "none" : kul === 1 ? "single" : kul === 3 ? "double" : void 0 : void 0,
|
|
7239
7252
|
directFontSizePoints: piece.prm === 0 && halfPoints !== void 0 && halfPoints >= 2 && halfPoints <= 3276 && row.prls.every((p) => SAFE_OPERANDS.has(p.opcode)) ? halfPoints / 2 : void 0,
|
|
7240
|
-
sprms
|
|
7253
|
+
sprms,
|
|
7241
7254
|
physical: row,
|
|
7242
7255
|
prm: piece.prm
|
|
7243
7256
|
});
|
|
@@ -7270,10 +7283,23 @@ function readDocParagraphStyleIndices(input) {
|
|
|
7270
7283
|
function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
7271
7284
|
if (typeof value !== "boolean" || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd) || flag !== "bold" && flag !== "italic")
|
|
7272
7285
|
throw new Error("invalid-formatting");
|
|
7286
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, flag === "bold" ? 2101 : 2102, Number(value));
|
|
7287
|
+
}
|
|
7288
|
+
function writeDocCharacterRunFontSize(input, cpStart, cpEnd, points) {
|
|
7289
|
+
if (typeof points !== "number" || !Number.isFinite(points) || !Number.isInteger(points * 2) || points < 1 || points > 1638 || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
|
|
7290
|
+
throw new Error("invalid-formatting");
|
|
7291
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, 19011, points * 2);
|
|
7292
|
+
}
|
|
7293
|
+
function writeDocCharacterRunUnderline(input, cpStart, cpEnd, value) {
|
|
7294
|
+
if (typeof value !== "string" || !["none", "single", "double"].includes(value) || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
|
|
7295
|
+
throw new Error("invalid-formatting");
|
|
7296
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, 10814, value === "none" ? 0 : value === "single" ? 1 : 3);
|
|
7297
|
+
}
|
|
7298
|
+
function writeExclusiveOperand(input, cpStart, cpEnd, opcode, value) {
|
|
7273
7299
|
const parsed = inspect2(input), target = parsed.runs.find((run) => run.cpStart === cpStart && run.cpEnd === cpEnd);
|
|
7274
7300
|
if (!target || target.prm !== 0 || /[\x00-\x1f]/u.test(target.text))
|
|
7275
7301
|
throw new Error("unsupported-formatting");
|
|
7276
|
-
const row = target.physical
|
|
7302
|
+
const row = target.physical;
|
|
7277
7303
|
const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
|
|
7278
7304
|
const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
|
|
7279
7305
|
if (row.blob < fibEnd)
|
|
@@ -7281,7 +7307,11 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
|
7281
7307
|
if (row.prls.some((p) => !SAFE_OPERANDS.has(p.opcode)))
|
|
7282
7308
|
throw new Error("opaque-formatting");
|
|
7283
7309
|
const operands = row.prls.filter((p) => p.opcode === opcode);
|
|
7284
|
-
if (operands.length !== 1
|
|
7310
|
+
if (operands.length !== 1)
|
|
7311
|
+
throw new Error("inherited-formatting");
|
|
7312
|
+
const operand = operands[0], size = opcode === 19011;
|
|
7313
|
+
const previous = operand.operand[0] + (size ? operand.operand[1] * 256 : 0);
|
|
7314
|
+
if (size ? operand.operand.length !== 2 || previous < 2 || previous > 3276 : opcode === 10814 ? ![0, 1, 3].includes(previous) : ![0, 1, 128, 129].includes(previous))
|
|
7285
7315
|
throw new Error("inherited-formatting");
|
|
7286
7316
|
const piece = parsed.pieces.find((p) => p.cpStart <= cpStart && p.cpEnd >= cpEnd);
|
|
7287
7317
|
const unit = piece.compressed ? 1 : 2, start = piece.fc + (cpStart - piece.cpStart) * unit;
|
|
@@ -7289,25 +7319,241 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
|
7289
7319
|
throw new Error("shared-formatting");
|
|
7290
7320
|
if (parsed.physical.some((r) => r !== row && r.blob && r.blob < row.blobEnd && row.blob < r.blobEnd) || parsed.papx.pns.includes(Math.floor(row.blob / 512)) || parsed.pieces.some((p) => p.fc < row.blobEnd && row.blob < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
|
|
7291
7321
|
throw new Error("aliased-formatting");
|
|
7292
|
-
|
|
7322
|
+
const sed = parsed.fib.sed;
|
|
7323
|
+
if (sed.lcb > LIMIT * 16 + 4)
|
|
7324
|
+
throw new Error("resource-limit");
|
|
7325
|
+
if (sed.lcb) {
|
|
7326
|
+
if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
|
|
7327
|
+
throw new Error("invalid-formatting");
|
|
7328
|
+
const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
|
|
7329
|
+
const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
|
|
7330
|
+
for (let i = 0; i < n; i++) {
|
|
7331
|
+
const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
|
|
7332
|
+
if (at === -1)
|
|
7333
|
+
continue;
|
|
7334
|
+
if (at < 0 || at > parsed.word.length - 2)
|
|
7335
|
+
throw new Error("invalid-formatting");
|
|
7336
|
+
const end = at + 2 + wordView.getUint16(at, true);
|
|
7337
|
+
if (end > parsed.word.length)
|
|
7338
|
+
throw new Error("invalid-formatting");
|
|
7339
|
+
if (at < row.blobEnd && row.blob < end)
|
|
7340
|
+
throw new Error("aliased-formatting");
|
|
7341
|
+
}
|
|
7342
|
+
}
|
|
7343
|
+
if (previous === value)
|
|
7344
|
+
return input;
|
|
7345
|
+
const word = parsed.word.slice();
|
|
7346
|
+
word[operand.at] = value & 255;
|
|
7347
|
+
if (size)
|
|
7348
|
+
word[operand.at + 1] = value >>> 8;
|
|
7349
|
+
return parsed.doc.rewrap(word, parsed.doc.tableBytes);
|
|
7350
|
+
}
|
|
7351
|
+
|
|
7352
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-paragraph-format.js
|
|
7353
|
+
var LIMIT2 = 65536;
|
|
7354
|
+
var SPRM_LIMIT = 262144;
|
|
7355
|
+
var PAGE_NUMBER_MASK = 4194303;
|
|
7356
|
+
var ALIGNMENTS = ["start", "center", "end", "justify"];
|
|
7357
|
+
var SAFE = /* @__PURE__ */ new Set([
|
|
7358
|
+
9219,
|
|
7359
|
+
9313,
|
|
7360
|
+
25703,
|
|
7361
|
+
9221,
|
|
7362
|
+
9222,
|
|
7363
|
+
9223,
|
|
7364
|
+
9228,
|
|
7365
|
+
25618,
|
|
7366
|
+
42003,
|
|
7367
|
+
42004,
|
|
7368
|
+
9307,
|
|
7369
|
+
9308,
|
|
7370
|
+
33885,
|
|
7371
|
+
33886,
|
|
7372
|
+
33888,
|
|
7373
|
+
9281,
|
|
7374
|
+
9325
|
|
7375
|
+
]);
|
|
7376
|
+
function alignmentOperands(row) {
|
|
7377
|
+
const values = row.prls.filter((p) => p.opcode === 9313), mirrors = row.prls.filter((p) => p.opcode === 9219);
|
|
7378
|
+
if (values.length !== 1 || values[0].operand[0] > 3 || mirrors.length > 1)
|
|
7379
|
+
return void 0;
|
|
7380
|
+
const value = values[0], mirror = mirrors[0];
|
|
7381
|
+
if (mirror && (mirror.at > value.at || mirror.operand[0] !== value.operand[0]))
|
|
7382
|
+
return void 0;
|
|
7383
|
+
return { value, mirror };
|
|
7384
|
+
}
|
|
7385
|
+
function parsePrls2(word, start, end, budget) {
|
|
7386
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7387
|
+
for (let at = start; at < end; ) {
|
|
7388
|
+
if (at + 2 > end)
|
|
7389
|
+
throw new Error("invalid-formatting");
|
|
7390
|
+
const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
|
|
7391
|
+
let length = [1, 1, 2, 4, 2, 2, 0, 3][spra];
|
|
7392
|
+
if (spra === 6) {
|
|
7393
|
+
if (opcode === 54792 || opcode === 50709 || at + 3 > end)
|
|
7394
|
+
throw new Error("unsupported-formatting");
|
|
7395
|
+
length = 1 + word[at + 2];
|
|
7396
|
+
}
|
|
7397
|
+
if (at + 2 + length > end)
|
|
7398
|
+
throw new Error("invalid-formatting");
|
|
7399
|
+
if (budget.remaining === 0)
|
|
7400
|
+
throw new Error("resource-limit");
|
|
7401
|
+
budget.remaining--;
|
|
7402
|
+
out.push({ opcode, at: at + 2, operand: word.subarray(at + 2, at + 2 + length) });
|
|
7403
|
+
at += 2 + length;
|
|
7404
|
+
}
|
|
7405
|
+
return out;
|
|
7406
|
+
}
|
|
7407
|
+
function inspect3(input) {
|
|
7408
|
+
const doc = unwrapDocBytes(input);
|
|
7409
|
+
if (!doc)
|
|
7410
|
+
throw new Error("unsupported-formatting");
|
|
7411
|
+
const word = doc.wordDocBytes, fib = readDocFib(word), limits = DEFAULT_OLE_DOC_PROCESSING_LIMITS;
|
|
7412
|
+
if (fib.ccpText > limits.maxCharacters)
|
|
7413
|
+
throw new Error("resource-limit");
|
|
7414
|
+
const pieces = parseDocClx(doc.tableBytes, fib.clx, limits.maxPieces).pieces;
|
|
7415
|
+
const total = pieces.at(-1)?.cpEnd ?? 0;
|
|
7416
|
+
if (total < fib.ccpText || total > fib.ccpText + fib.ccpOtherStories + 1)
|
|
7417
|
+
throw new Error("invalid-formatting");
|
|
7418
|
+
const text = decodePiecesText(word, pieces, fib.ccpText);
|
|
7419
|
+
if (fib.plcfbtePapx.lcb > LIMIT2 * 8 + 4 || fib.plcfbteChpx.lcb > LIMIT2 * 8 + 4)
|
|
7420
|
+
throw new Error("resource-limit");
|
|
7421
|
+
const papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx), chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx);
|
|
7422
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), rows = [];
|
|
7423
|
+
const sprmBudget = { remaining: SPRM_LIMIT };
|
|
7424
|
+
for (let pageIndex = 0; pageIndex < papx.pns.length; pageIndex++) {
|
|
7425
|
+
const page = (papx.pns[pageIndex] & PAGE_NUMBER_MASK) * 512;
|
|
7426
|
+
if (page > word.length - 512)
|
|
7427
|
+
throw new Error("invalid-formatting");
|
|
7428
|
+
const count = word[page + 511], header = (count + 1) * 4 + count * 13;
|
|
7429
|
+
if (!count || header > 511 || rows.length + count > LIMIT2)
|
|
7430
|
+
throw new Error("resource-limit");
|
|
7431
|
+
for (let i = 0; i < count; i++) {
|
|
7432
|
+
const start = view2.getInt32(page + i * 4, true), end = view2.getInt32(page + (i + 1) * 4, true);
|
|
7433
|
+
if (start < papx.fcs[pageIndex] || end > papx.fcs[pageIndex + 1] || end <= start)
|
|
7434
|
+
throw new Error("invalid-formatting");
|
|
7435
|
+
const offset = word[page + (count + 1) * 4 + i * 13] * 2;
|
|
7436
|
+
if (!offset) {
|
|
7437
|
+
rows.push({ start, end, blob: 0, blobEnd: 0, prls: [] });
|
|
7438
|
+
continue;
|
|
7439
|
+
}
|
|
7440
|
+
if (offset < header || offset + 2 > 511)
|
|
7441
|
+
throw new Error("invalid-formatting");
|
|
7442
|
+
const blob = page + offset, cb = word[blob], prefix = cb === 0 ? 2 : 1;
|
|
7443
|
+
const length = cb === 0 ? 2 + word[blob + 1] * 2 : cb * 2;
|
|
7444
|
+
if (cb === 0 && !word[blob + 1] || length < prefix + 2 || offset + length > 511)
|
|
7445
|
+
throw new Error("invalid-formatting");
|
|
7446
|
+
const blobEnd = blob + length;
|
|
7447
|
+
rows.push({ start, end, blob, blobEnd, prls: parsePrls2(word, blob + prefix + 2, blobEnd, sprmBudget) });
|
|
7448
|
+
}
|
|
7449
|
+
}
|
|
7450
|
+
rows.sort((a, b) => a.start - b.start);
|
|
7451
|
+
for (let i = 1; i < rows.length; i++)
|
|
7452
|
+
if (rows[i].start < rows[i - 1].end)
|
|
7453
|
+
throw new Error("invalid-formatting");
|
|
7454
|
+
const paragraphs = [];
|
|
7455
|
+
let cpStart = 0, pieceIndex = 0;
|
|
7456
|
+
for (let cp = 0; cp < text.length; cp++) {
|
|
7457
|
+
if (text[cp] !== "\r" && cp !== text.length - 1)
|
|
7458
|
+
continue;
|
|
7459
|
+
if (paragraphs.length >= LIMIT2)
|
|
7460
|
+
throw new Error("resource-limit");
|
|
7461
|
+
while (pieces[pieceIndex].cpEnd <= cp)
|
|
7462
|
+
pieceIndex++;
|
|
7463
|
+
const piece = pieces[pieceIndex], fc = piece.fc + (cp - piece.cpStart) * (piece.compressed ? 1 : 2);
|
|
7464
|
+
let lo = 0, hi = rows.length;
|
|
7465
|
+
while (lo < hi) {
|
|
7466
|
+
const middle = lo + hi >>> 1;
|
|
7467
|
+
if (rows[middle].end <= fc)
|
|
7468
|
+
lo = middle + 1;
|
|
7469
|
+
else
|
|
7470
|
+
hi = middle;
|
|
7471
|
+
}
|
|
7472
|
+
const row = rows[lo];
|
|
7473
|
+
if (!row || fc < row.start || fc >= row.end)
|
|
7474
|
+
throw new Error("invalid-formatting");
|
|
7475
|
+
const operands = alignmentOperands(row);
|
|
7476
|
+
const directAlignment = piece.prm === 0 && row.prls.every((p) => SAFE.has(p.opcode)) && operands ? ALIGNMENTS[operands.value.operand[0]] : void 0;
|
|
7477
|
+
paragraphs.push({ cpStart, cpEnd: cp + 1, mark: text[cp] === "\r", row, prm: piece.prm, directAlignment });
|
|
7478
|
+
cpStart = cp + 1;
|
|
7479
|
+
}
|
|
7480
|
+
return { doc, word, fib, pieces, rows, chpx, paragraphs, text };
|
|
7481
|
+
}
|
|
7482
|
+
function readDocParagraphAlignments(input) {
|
|
7483
|
+
return Object.freeze(inspect3(input).paragraphs.map((p) => p.directAlignment));
|
|
7484
|
+
}
|
|
7485
|
+
function writeDocParagraphAlignment(input, index, alignment) {
|
|
7486
|
+
if (!Number.isSafeInteger(index) || index < 0 || typeof alignment !== "string" || !ALIGNMENTS.includes(alignment))
|
|
7487
|
+
throw new Error("invalid-formatting");
|
|
7488
|
+
const parsed = inspect3(input), target = parsed.paragraphs[index];
|
|
7489
|
+
if (!target?.mark || target.prm !== 0 || /[\x00-\x1f]/u.test(parsed.text.slice(target.cpStart, target.cpEnd - 1)))
|
|
7490
|
+
throw new Error("unsupported-formatting");
|
|
7491
|
+
const row = target.row;
|
|
7492
|
+
if (row.prls.some((p) => !SAFE.has(p.opcode)))
|
|
7493
|
+
throw new Error("opaque-formatting");
|
|
7494
|
+
const operands = alignmentOperands(row);
|
|
7495
|
+
if (!operands)
|
|
7496
|
+
throw new Error("inherited-formatting");
|
|
7497
|
+
if (operands.mirror && alignment !== "center" && alignment !== "justify")
|
|
7498
|
+
throw new Error("direction-dependent-alignment");
|
|
7499
|
+
const piece = parsed.pieces.find((p) => p.cpStart <= target.cpStart && p.cpEnd >= target.cpEnd);
|
|
7500
|
+
if (!piece || piece.prm !== 0)
|
|
7501
|
+
throw new Error("unsupported-formatting");
|
|
7502
|
+
const unit = piece.compressed ? 1 : 2, start = piece.fc + (target.cpStart - piece.cpStart) * unit;
|
|
7503
|
+
if (start !== row.start || start + (target.cpEnd - target.cpStart) * unit !== row.end || parsed.paragraphs.some((p) => p !== target && p.row === row) || parsed.pieces.some((p) => p !== piece && p.fc < row.end && row.start < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
|
|
7504
|
+
throw new Error("shared-formatting");
|
|
7505
|
+
const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
|
|
7506
|
+
const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
|
|
7507
|
+
if (row.blob < fibEnd || parsed.rows.some((r) => r !== row && r.blob && r.blob < row.blobEnd && row.blob < r.blobEnd) || parsed.chpx.pns.some((pn) => (pn & PAGE_NUMBER_MASK) === Math.floor(row.blob / 512)) || parsed.pieces.some((p) => p.fc < row.blobEnd && row.blob < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
|
|
7508
|
+
throw new Error("aliased-formatting");
|
|
7509
|
+
const sed = parsed.fib.sed;
|
|
7510
|
+
if (sed.lcb > LIMIT2 * 16 + 4)
|
|
7511
|
+
throw new Error("resource-limit");
|
|
7512
|
+
if (sed.lcb) {
|
|
7513
|
+
if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
|
|
7514
|
+
throw new Error("invalid-formatting");
|
|
7515
|
+
const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
|
|
7516
|
+
const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
|
|
7517
|
+
for (let i = 0; i < n; i++) {
|
|
7518
|
+
const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
|
|
7519
|
+
if (at === -1)
|
|
7520
|
+
continue;
|
|
7521
|
+
if (at < 0 || at > parsed.word.length - 2)
|
|
7522
|
+
throw new Error("invalid-formatting");
|
|
7523
|
+
const end = at + 2 + wordView.getUint16(at, true);
|
|
7524
|
+
if (end > parsed.word.length)
|
|
7525
|
+
throw new Error("invalid-formatting");
|
|
7526
|
+
if (at < row.blobEnd && row.blob < end)
|
|
7527
|
+
throw new Error("aliased-formatting");
|
|
7528
|
+
}
|
|
7529
|
+
}
|
|
7530
|
+
const value = ALIGNMENTS.indexOf(alignment);
|
|
7531
|
+
if (operands.value.operand[0] === value)
|
|
7293
7532
|
return input;
|
|
7294
7533
|
const word = parsed.word.slice();
|
|
7295
|
-
word[operands
|
|
7534
|
+
word[operands.value.at] = value;
|
|
7535
|
+
if (operands.mirror)
|
|
7536
|
+
word[operands.mirror.at] = value;
|
|
7296
7537
|
return parsed.doc.rewrap(word, parsed.doc.tableBytes);
|
|
7297
7538
|
}
|
|
7298
7539
|
|
|
7299
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7540
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/doc-document.js
|
|
7300
7541
|
var DOC_CAPABILITIES = Object.freeze({
|
|
7301
|
-
read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "compound-streams"]),
|
|
7302
|
-
write: Object.freeze(["paragraph-text", "existing-direct-bold-italic"]),
|
|
7542
|
+
read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "direct-paragraph-alignment", "compound-streams"]),
|
|
7543
|
+
write: Object.freeze(["paragraph-text", "existing-direct-bold-italic", "existing-direct-font-size", "existing-direct-underline", "existing-direct-paragraph-alignment"]),
|
|
7303
7544
|
limitations: Object.freeze([
|
|
7304
7545
|
"Paragraph insertion, removal and embedded paragraph breaks are unsupported.",
|
|
7305
7546
|
"Character formatting reports direct CHPX exceptions, without resolving styles or piece PRMs.",
|
|
7306
7547
|
"Bold/italic setters force an absolute value in an existing exclusive understood CHPX run. Run handles expire after edits.",
|
|
7548
|
+
"Underline setters replace an existing exclusive sprmCKul byte with none, single or double; inherited and other styles refuse.",
|
|
7549
|
+
"Font-size setters replace an existing exclusive sprmCHps slot with 1..1638 points in exact half-point increments.",
|
|
7307
7550
|
"Fields, tables, objects and inherited styles are preserved where supported; their models are not editable.",
|
|
7308
7551
|
"Unsupported edits and processing limits throw without changing the document.",
|
|
7309
7552
|
"Text uses the bounded DOC codec defaults: 16,777,216 main-story characters and 65,536 pieces or field records.",
|
|
7310
|
-
"
|
|
7553
|
+
"Character run inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs.",
|
|
7554
|
+
"Rich formatting is bounded to 65,536 physical/mapped runs and paragraph style records.",
|
|
7555
|
+
"Logical paragraph alignment replaces a sole existing exclusive sprmPJc slot. Matching legacy mirrors support center/justify only, with both slots updated. Styles, legacy-only alignment, tables and opaque formatting refuse.",
|
|
7556
|
+
"Paragraph alignment inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs."
|
|
7311
7557
|
])
|
|
7312
7558
|
});
|
|
7313
7559
|
var DocDocument = class extends Ole2DocumentBase {
|
|
@@ -7321,6 +7567,7 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7321
7567
|
#text;
|
|
7322
7568
|
#runsCache;
|
|
7323
7569
|
#stylesCache;
|
|
7570
|
+
#alignmentsCache;
|
|
7324
7571
|
constructor(input) {
|
|
7325
7572
|
super(input);
|
|
7326
7573
|
const text = readOleDocParagraphs(this.getBytes());
|
|
@@ -7337,6 +7584,16 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7337
7584
|
set text(value) {
|
|
7338
7585
|
owner.#setParagraphText(index, value);
|
|
7339
7586
|
},
|
|
7587
|
+
get directAlignment() {
|
|
7588
|
+
try {
|
|
7589
|
+
return owner.#paragraphAlignments()[index];
|
|
7590
|
+
} catch {
|
|
7591
|
+
throw new UnsupportedOle2EditError("unsupported-formatting");
|
|
7592
|
+
}
|
|
7593
|
+
},
|
|
7594
|
+
set directAlignment(value) {
|
|
7595
|
+
owner.#setParagraphAlignment(index, value);
|
|
7596
|
+
},
|
|
7340
7597
|
get runs() {
|
|
7341
7598
|
return owner.#paragraphRuns(index);
|
|
7342
7599
|
},
|
|
@@ -7353,6 +7610,25 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7353
7610
|
get paragraphs() {
|
|
7354
7611
|
return this.#paragraphs;
|
|
7355
7612
|
}
|
|
7613
|
+
#paragraphAlignments() {
|
|
7614
|
+
if (this.#alignmentsCache?.revision !== this.revision)
|
|
7615
|
+
this.#alignmentsCache = { revision: this.revision, alignments: readDocParagraphAlignments(this.getBytes()) };
|
|
7616
|
+
return this.#alignmentsCache.alignments;
|
|
7617
|
+
}
|
|
7618
|
+
#setParagraphAlignment(index, value) {
|
|
7619
|
+
if (typeof value !== "string")
|
|
7620
|
+
throw new UnsupportedOle2EditError("invalid-formatting");
|
|
7621
|
+
let bytes;
|
|
7622
|
+
try {
|
|
7623
|
+
bytes = writeDocParagraphAlignment(this.getBytes(), index, value);
|
|
7624
|
+
} catch (error) {
|
|
7625
|
+
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
|
|
7626
|
+
}
|
|
7627
|
+
const text = readOleDocParagraphs(bytes), alignments = readDocParagraphAlignments(bytes);
|
|
7628
|
+
if (!text || text.length !== this.#text.length || text.some((t, i) => t !== this.#text[i]) || alignments[index] !== value)
|
|
7629
|
+
throw new UnsupportedOle2EditError("invalid-document");
|
|
7630
|
+
this.commitBytes(bytes);
|
|
7631
|
+
}
|
|
7356
7632
|
#currentRuns() {
|
|
7357
7633
|
if (this.#runsCache?.revision !== this.revision)
|
|
7358
7634
|
this.#runsCache = { revision: this.revision, runs: readDocCharacterRuns(this.getBytes()) };
|
|
@@ -7371,15 +7647,15 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7371
7647
|
try {
|
|
7372
7648
|
return Object.freeze(this.#currentRuns().filter((r) => r.cpStart < end && r.cpEnd > start).map((run) => {
|
|
7373
7649
|
const cpStart = Math.max(start, run.cpStart), cpEnd = Math.min(end, run.cpEnd);
|
|
7374
|
-
let bold = run.directBold, italic = run.directItalic, sprms = run.sprms;
|
|
7650
|
+
let bold = run.directBold, italic = run.directItalic, size = run.directFontSizePoints, underline = run.directUnderline, sprms = run.sprms;
|
|
7375
7651
|
const set = (flag, value) => {
|
|
7376
7652
|
if (owner.revision !== revision)
|
|
7377
7653
|
throw new UnsupportedOle2EditError("stale-run");
|
|
7378
|
-
if (typeof value !== "boolean")
|
|
7654
|
+
if (flag === "underline" ? typeof value !== "string" : flag === "size" ? typeof value !== "number" : typeof value !== "boolean")
|
|
7379
7655
|
throw new UnsupportedOle2EditError("invalid-formatting");
|
|
7380
7656
|
let bytes;
|
|
7381
7657
|
try {
|
|
7382
|
-
bytes = writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
|
|
7658
|
+
bytes = flag === "underline" ? writeDocCharacterRunUnderline(owner.getBytes(), cpStart, cpEnd, value) : flag === "size" ? writeDocCharacterRunFontSize(owner.getBytes(), cpStart, cpEnd, value) : writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
|
|
7383
7659
|
} catch (error) {
|
|
7384
7660
|
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
|
|
7385
7661
|
}
|
|
@@ -7390,15 +7666,26 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7390
7666
|
owner.commitBytes(bytes);
|
|
7391
7667
|
if (flag === "bold")
|
|
7392
7668
|
bold = value;
|
|
7393
|
-
else
|
|
7669
|
+
else if (flag === "italic")
|
|
7394
7670
|
italic = value;
|
|
7395
|
-
|
|
7671
|
+
else if (flag === "underline")
|
|
7672
|
+
underline = value;
|
|
7673
|
+
else
|
|
7674
|
+
size = value;
|
|
7675
|
+
const opcode = flag === "bold" ? 2101 : flag === "italic" ? 2102 : flag === "underline" ? 10814 : 19011;
|
|
7676
|
+
const operand = flag === "size" ? [value * 2 & 255, value * 2 >>> 8] : flag === "underline" ? [value === "none" ? 0 : value === "single" ? 1 : 3] : [Number(value)];
|
|
7677
|
+
sprms = Object.freeze(sprms.map((p) => p.opcode === opcode ? Object.freeze({ opcode: p.opcode, operand: Object.freeze(operand) }) : p));
|
|
7396
7678
|
};
|
|
7397
7679
|
return Object.freeze({
|
|
7398
7680
|
cpStart,
|
|
7399
7681
|
cpEnd,
|
|
7400
7682
|
text: run.text.slice(cpStart - run.cpStart, cpEnd - run.cpStart),
|
|
7401
|
-
directFontSizePoints
|
|
7683
|
+
get directFontSizePoints() {
|
|
7684
|
+
return size;
|
|
7685
|
+
},
|
|
7686
|
+
set directFontSizePoints(value) {
|
|
7687
|
+
set("size", value);
|
|
7688
|
+
},
|
|
7402
7689
|
get sprms() {
|
|
7403
7690
|
return sprms;
|
|
7404
7691
|
},
|
|
@@ -7408,6 +7695,12 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7408
7695
|
set directBold(value) {
|
|
7409
7696
|
set("bold", value);
|
|
7410
7697
|
},
|
|
7698
|
+
get directUnderline() {
|
|
7699
|
+
return underline;
|
|
7700
|
+
},
|
|
7701
|
+
set directUnderline(value) {
|
|
7702
|
+
set("underline", value);
|
|
7703
|
+
},
|
|
7411
7704
|
get directItalic() {
|
|
7412
7705
|
return italic;
|
|
7413
7706
|
},
|
|
@@ -7440,7 +7733,7 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7440
7733
|
}
|
|
7441
7734
|
};
|
|
7442
7735
|
|
|
7443
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7736
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
|
|
7444
7737
|
function compareDirEntryNames(a, b) {
|
|
7445
7738
|
const ua = a.toUpperCase();
|
|
7446
7739
|
const ub = b.toUpperCase();
|
|
@@ -7507,7 +7800,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
|
|
|
7507
7800
|
}
|
|
7508
7801
|
}
|
|
7509
7802
|
|
|
7510
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7803
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
|
|
7511
7804
|
function writeHeader(outView, outBytes, params) {
|
|
7512
7805
|
outBytes.set(OLE_MAGIC, 0);
|
|
7513
7806
|
outView.setUint16(24, 62, true);
|
|
@@ -7600,7 +7893,7 @@ function writeStreamSectors(outBytes, streamData, chain2, sectorSize) {
|
|
|
7600
7893
|
}
|
|
7601
7894
|
}
|
|
7602
7895
|
|
|
7603
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7896
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
|
|
7604
7897
|
function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
|
|
7605
7898
|
const sectorSize = 512;
|
|
7606
7899
|
const miniSectorSize = 64;
|
|
@@ -7781,7 +8074,7 @@ function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
|
|
|
7781
8074
|
return output;
|
|
7782
8075
|
}
|
|
7783
8076
|
|
|
7784
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8077
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cfb.js
|
|
7785
8078
|
var WORKBOOK_STREAM_NAMES = ["workbook", "book"];
|
|
7786
8079
|
function unwrapXlsBytes(bytes) {
|
|
7787
8080
|
if (!isCfb(bytes)) {
|
|
@@ -7848,7 +8141,7 @@ function isCfb(bytes) {
|
|
|
7848
8141
|
return OLE_MAGIC.every((value, index) => bytes[index] === value);
|
|
7849
8142
|
}
|
|
7850
8143
|
|
|
7851
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8144
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-functions.js
|
|
7852
8145
|
var TABLE = `0 COUNT -1|1 IF -1|2 ISNA 1|3 ISERROR 1|4 SUM -1|5 AVERAGE -1|6 MIN -1|7 MAX -1|8 ROW -1|9 COLUMN -1|10 NA 0|11 NPV -1|12 STDEV -1|13 DOLLAR -1|14 FIXED -1|15 SIN 1|16 COS 1|17 TAN 1|18 ATAN 1|19 PI 0|20 SQRT 1|21 EXP 1|22 LN 1|23 LOG10 1|24 ABS 1|25 INT 1|26 SIGN 1|27 ROUND 2|28 LOOKUP -1|29 INDEX -1|30 REPT 2|31 MID 3|32 LEN 1|33 VALUE 1|34 TRUE 0|35 FALSE 0|36 AND -1|37 OR -1|38 NOT 1|39 MOD 2|40 DCOUNT 3|41 DSUM 3|42 DAVERAGE 3|43 DMIN 3|44 DMAX 3|45 DSTDEV 3|46 VAR -1|47 DVAR 3|48 TEXT 2|49 LINEST -1|50 TREND -1|51 LOGEST -1|52 GROWTH -1|56 PV -1|57 FV -1|58 NPER -1|59 PMT -1|60 RATE -1|61 MIRR 3|62 IRR -1|63 RAND 0|64 MATCH -1|65 DATE 3|66 TIME 3|67 DAY 1|68 MONTH 1|69 YEAR 1|70 WEEKDAY -1|71 HOUR 1|72 MINUTE 1|73 SECOND 1|74 NOW 0|75 AREAS 1|76 ROWS 1|77 COLUMNS 1|78 OFFSET -1|82 SEARCH -1|83 TRANSPOSE 1|86 TYPE 1|97 ATAN2 2|98 ASIN 1|99 ACOS 1|100 CHOOSE -1|101 HLOOKUP -1|102 VLOOKUP -1|105 ISREF 1|109 LOG -1|111 CHAR 1|112 LOWER 1|113 UPPER 1|114 PROPER 1|115 LEFT -1|116 RIGHT -1|117 EXACT 2|118 TRIM 1|119 REPLACE 4|120 SUBSTITUTE -1|121 CODE 1|124 FIND -1|125 CELL -1|126 ISERR 1|127 ISTEXT 1|128 ISNUMBER 1|129 ISBLANK 1|130 T 1|131 N 1|140 DATEVALUE 1|141 TIMEVALUE 1|142 SLN 3|143 SYD 4|144 DDB -1|148 INDIRECT -1|150 CALL -1|162 CLEAN 1|163 MDETERM 1|164 MINVERSE 1|165 MMULT 2|167 IPMT -1|168 PPMT -1|169 COUNTA -1|183 PRODUCT -1|184 FACT 1|189 DPRODUCT 3|190 ISNONTEXT 1|193 STDEVP -1|194 VARP -1|195 DSTDEVP 3|196 DVARP 3|197 TRUNC -1|198 ISLOGICAL 1|199 DCOUNTA 3|204 USDOLLAR -1|205 FINDB -1|206 SEARCHB -1|207 REPLACEB 4|208 LEFTB -1|209 RIGHTB -1|210 MIDB 3|211 LENB 1|212 ROUNDUP 2|213 ROUNDDOWN 2|214 ASC 1|215 DBCS 1|216 RANK -1|219 ADDRESS -1|220 DAYS360 -1|221 TODAY 0|222 VDB -1|227 MEDIAN -1|228 SUMPRODUCT -1|229 SINH 1|230 COSH 1|231 TANH 1|232 ASINH 1|233 ACOSH 1|234 ATANH 1|235 DGET 3|244 INFO 1|247 DB -1|252 FREQUENCY 2|261 ERROR.TYPE 1|269 AVEDEV -1|270 BETADIST -1|271 GAMMALN 1|272 BETAINV -1|273 BINOMDIST 4|274 CHIDIST 2|275 CHIINV 2|276 COMBIN 2|277 CONFIDENCE 3|278 CRITBINOM 3|279 EVEN 1|280 EXPONDIST 3|281 FDIST 3|282 FINV 3|283 FISHER 1|284 FISHERINV 1|285 FLOOR 2|286 GAMMADIST 4|287 GAMMAINV 3|288 CEILING 2|289 HYPGEOMDIST 4|290 LOGNORMDIST 3|291 LOGINV 3|292 NEGBINOMDIST 3|293 NORMDIST 4|294 NORMSDIST 1|295 NORMINV 3|296 NORMSINV 1|297 STANDARDIZE 3|298 ODD 1|299 PERMUT 2|300 POISSON 3|301 TDIST 3|302 WEIBULL 4|303 SUMXMY2 2|304 SUMX2MY2 2|305 SUMX2PY2 2|306 CHITEST 2|307 CORREL 2|308 COVAR 2|309 FORECAST 3|310 FTEST 2|311 INTERCEPT 2|312 PEARSON 2|313 RSQ 2|314 STEYX 2|315 SLOPE 2|316 TTEST 4|317 PROB -1|318 DEVSQ -1|319 GEOMEAN -1|320 HARMEAN -1|321 SUMSQ -1|322 KURT -1|323 SKEW -1|324 ZTEST -1|325 LARGE 2|326 SMALL 2|327 QUARTILE 2|328 PERCENTILE 2|329 PERCENTRANK -1|330 MODE -1|331 TRIMMEAN 2|332 TINV 2|336 CONCATENATE -1|337 POWER 2|342 RADIANS 1|343 DEGREES 1|344 SUBTOTAL -1|345 SUMIF -1|346 COUNTIF 2|347 COUNTBLANK 1|350 ISPMT 4|351 DATEDIF 3|352 DATESTRING 1|353 NUMBERSTRING 2|354 ROMAN -1|358 GETPIVOTDATA -1|359 HYPERLINK -1|360 PHONETIC 1|361 AVERAGEA -1|362 MAXA -1|363 MINA -1|364 STDEVPA -1|365 VARPA -1|366 STDEVA -1|367 VARA -1|368 BAHTTEXT 1`;
|
|
7853
8146
|
var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
|
|
7854
8147
|
const [id, name, argc] = entry.split(" ");
|
|
@@ -7856,7 +8149,7 @@ var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
|
|
|
7856
8149
|
}));
|
|
7857
8150
|
var XLS_USER_FUNCTION_ID = 255;
|
|
7858
8151
|
|
|
7859
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8152
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg-text.js
|
|
7860
8153
|
var BIFF_ERRORS = {
|
|
7861
8154
|
0: "#NULL!",
|
|
7862
8155
|
7: "#DIV/0!",
|
|
@@ -7951,7 +8244,7 @@ function readArrayConstant(extra) {
|
|
|
7951
8244
|
return `{${lines.join(";")}}`;
|
|
7952
8245
|
}
|
|
7953
8246
|
|
|
7954
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8247
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-records.js
|
|
7955
8248
|
var RT_CONTINUE = 60;
|
|
7956
8249
|
function readXlsRecords(bytes, start = 0, end = bytes.length) {
|
|
7957
8250
|
const records = [];
|
|
@@ -8043,8 +8336,8 @@ var SegmentReader = class _SegmentReader {
|
|
|
8043
8336
|
constructor(segments) {
|
|
8044
8337
|
this.segments = segments;
|
|
8045
8338
|
}
|
|
8046
|
-
static of(
|
|
8047
|
-
return new _SegmentReader([
|
|
8339
|
+
static of(record5) {
|
|
8340
|
+
return new _SegmentReader([record5.data, ...record5.continues]);
|
|
8048
8341
|
}
|
|
8049
8342
|
get done() {
|
|
8050
8343
|
this.normalize();
|
|
@@ -8103,21 +8396,21 @@ var SegmentReader = class _SegmentReader {
|
|
|
8103
8396
|
return this.continuedChars(count, (flags & 1) !== 0);
|
|
8104
8397
|
}
|
|
8105
8398
|
};
|
|
8106
|
-
function joinedData(
|
|
8107
|
-
if (
|
|
8108
|
-
return
|
|
8109
|
-
const total =
|
|
8399
|
+
function joinedData(record5) {
|
|
8400
|
+
if (record5.continues.length === 0)
|
|
8401
|
+
return record5.data;
|
|
8402
|
+
const total = record5.continues.reduce((sum, part) => sum + part.length, record5.data.length);
|
|
8110
8403
|
const out = new Uint8Array(total);
|
|
8111
|
-
out.set(
|
|
8112
|
-
let at =
|
|
8113
|
-
for (const part of
|
|
8404
|
+
out.set(record5.data, 0);
|
|
8405
|
+
let at = record5.data.length;
|
|
8406
|
+
for (const part of record5.continues) {
|
|
8114
8407
|
out.set(part, at);
|
|
8115
8408
|
at += part.length;
|
|
8116
8409
|
}
|
|
8117
8410
|
return out;
|
|
8118
8411
|
}
|
|
8119
8412
|
|
|
8120
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8413
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg.js
|
|
8121
8414
|
function decodeFormula(rgce, extra, context, options) {
|
|
8122
8415
|
try {
|
|
8123
8416
|
return decode(rgce, new ByteReader(extra), context, options);
|
|
@@ -8348,9 +8641,9 @@ function readAttr(reader, stack, whitespace) {
|
|
|
8348
8641
|
}
|
|
8349
8642
|
}
|
|
8350
8643
|
|
|
8351
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8352
|
-
function parseSharedStrings(
|
|
8353
|
-
const reader = SegmentReader.of(
|
|
8644
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sst.js
|
|
8645
|
+
function parseSharedStrings(record5) {
|
|
8646
|
+
const reader = SegmentReader.of(record5);
|
|
8354
8647
|
reader.u32();
|
|
8355
8648
|
const unique = reader.u32();
|
|
8356
8649
|
const strings = [];
|
|
@@ -8365,7 +8658,7 @@ function parseSharedStrings(record4) {
|
|
|
8365
8658
|
return strings;
|
|
8366
8659
|
}
|
|
8367
8660
|
|
|
8368
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8661
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-styles.js
|
|
8369
8662
|
var DEFAULT_XLS_PALETTE = "000000 FFFFFF FF0000 00FF00 0000FF FFFF00 FF00FF 00FFFF 000000 FFFFFF FF0000 00FF00 0000FF FFFF00 FF00FF 00FFFF 800000 008000 000080 808000 800080 008080 C0C0C0 808080 9999FF 993366 FFFFCC CCFFFF 660066 FF8080 0066CC CCCCFF 000080 FF00FF FFFF00 00FFFF 800080 800000 008080 0000FF 00CCFF CCFFFF CCFFCC FFFF99 99CCFF FF99CC CC99FF FFCC99 3366FF 33CCCC 99CC00 FFCC00 FF9900 FF6600 666699 969696 003366 339966 003300 333300 993300 993366 333399 333333".split(" ");
|
|
8370
8663
|
var XLS_BUILTIN_FORMATS = {
|
|
8371
8664
|
0: "General",
|
|
@@ -8622,7 +8915,7 @@ function applyXfExt(data, xfs, palette) {
|
|
|
8622
8915
|
}
|
|
8623
8916
|
}
|
|
8624
8917
|
|
|
8625
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8918
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-types.js
|
|
8626
8919
|
var XlsReadError = class extends Error {
|
|
8627
8920
|
code;
|
|
8628
8921
|
constructor(code, message) {
|
|
@@ -8632,7 +8925,7 @@ var XlsReadError = class extends Error {
|
|
|
8632
8925
|
}
|
|
8633
8926
|
};
|
|
8634
8927
|
|
|
8635
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8928
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-globals.js
|
|
8636
8929
|
var RT = {
|
|
8637
8930
|
BOF: 2057,
|
|
8638
8931
|
EOF: 10,
|
|
@@ -8731,17 +9024,17 @@ function parseGlobals(records) {
|
|
|
8731
9024
|
const version = first.data[0] | first.data[1] << 8;
|
|
8732
9025
|
if (version !== 1536)
|
|
8733
9026
|
throw new XlsReadError("unsupported-version", "Only Excel 97-2003 (BIFF8) workbooks are supported; this file uses an older Excel format.");
|
|
8734
|
-
const end = records.findIndex((
|
|
9027
|
+
const end = records.findIndex((record5) => record5.opcode === RT.EOF);
|
|
8735
9028
|
const globals = end >= 0 ? records.slice(0, end) : records;
|
|
8736
|
-
if (globals.some((
|
|
9029
|
+
if (globals.some((record5) => record5.opcode === RT.FILEPASS))
|
|
8737
9030
|
throw new XlsReadError("encrypted", "The workbook is password protected (encrypted).");
|
|
8738
|
-
const paletteRecord = globals.find((
|
|
9031
|
+
const paletteRecord = globals.find((record5) => record5.opcode === RT.PALETTE);
|
|
8739
9032
|
const palette = paletteRecord ? parsePalette(paletteRecord.data) : [...DEFAULT_XLS_PALETTE];
|
|
8740
9033
|
const numberFormats = /* @__PURE__ */ new Map();
|
|
8741
|
-
for (const
|
|
8742
|
-
if (
|
|
9034
|
+
for (const record5 of globals) {
|
|
9035
|
+
if (record5.opcode !== RT.FORMAT)
|
|
8743
9036
|
continue;
|
|
8744
|
-
const format = parseFormat(joinedData(
|
|
9037
|
+
const format = parseFormat(joinedData(record5));
|
|
8745
9038
|
numberFormats.set(format.id, format.code);
|
|
8746
9039
|
}
|
|
8747
9040
|
const formatCode = (id) => numberFormats.get(id) ?? XLS_BUILTIN_FORMATS[id] ?? "General";
|
|
@@ -8762,17 +9055,17 @@ function parseGlobals(records) {
|
|
|
8762
9055
|
const supbooks = [];
|
|
8763
9056
|
const xtis = [];
|
|
8764
9057
|
const rawNames = [];
|
|
8765
|
-
for (const
|
|
8766
|
-
const r = new ByteReader(
|
|
8767
|
-
switch (
|
|
9058
|
+
for (const record5 of globals) {
|
|
9059
|
+
const r = new ByteReader(record5.data);
|
|
9060
|
+
switch (record5.opcode) {
|
|
8768
9061
|
case RT.FONT:
|
|
8769
|
-
out.fonts.push(parseFont(
|
|
9062
|
+
out.fonts.push(parseFont(record5.data, palette));
|
|
8770
9063
|
break;
|
|
8771
9064
|
case RT.XF:
|
|
8772
|
-
out.xfs.push(parseXf(
|
|
9065
|
+
out.xfs.push(parseXf(record5.data, palette, formatCode));
|
|
8773
9066
|
break;
|
|
8774
9067
|
case RT.XFEXT:
|
|
8775
|
-
applyXfExt(
|
|
9068
|
+
applyXfExt(record5.data, out.xfs, palette);
|
|
8776
9069
|
break;
|
|
8777
9070
|
case RT.DATEMODE:
|
|
8778
9071
|
out.date1904 = r.u16() === 1;
|
|
@@ -8795,26 +9088,26 @@ function parseGlobals(records) {
|
|
|
8795
9088
|
break;
|
|
8796
9089
|
}
|
|
8797
9090
|
case RT.SST:
|
|
8798
|
-
out.sst = parseSharedStrings(
|
|
9091
|
+
out.sst = parseSharedStrings(record5);
|
|
8799
9092
|
break;
|
|
8800
9093
|
case RT.SUPBOOK:
|
|
8801
|
-
supbooks.push(parseSupBook(joinedData(
|
|
9094
|
+
supbooks.push(parseSupBook(joinedData(record5)));
|
|
8802
9095
|
break;
|
|
8803
9096
|
case RT.EXTERNNAME: {
|
|
8804
9097
|
const book = supbooks[supbooks.length - 1];
|
|
8805
|
-
const nr = new ByteReader(joinedData(
|
|
9098
|
+
const nr = new ByteReader(joinedData(record5), 6);
|
|
8806
9099
|
book?.externNames.push(nr.shortXlString());
|
|
8807
9100
|
break;
|
|
8808
9101
|
}
|
|
8809
9102
|
case RT.EXTERNSHEET: {
|
|
8810
|
-
const xr = new ByteReader(joinedData(
|
|
9103
|
+
const xr = new ByteReader(joinedData(record5));
|
|
8811
9104
|
const count = xr.u16();
|
|
8812
9105
|
for (let i = 0; i < count; i++)
|
|
8813
9106
|
xtis.push({ book: xr.u16(), first: xr.i16(), last: xr.i16() });
|
|
8814
9107
|
break;
|
|
8815
9108
|
}
|
|
8816
9109
|
case RT.NAME:
|
|
8817
|
-
rawNames.push(parseName(joinedData(
|
|
9110
|
+
rawNames.push(parseName(joinedData(record5)));
|
|
8818
9111
|
break;
|
|
8819
9112
|
case RT.OBPROJ:
|
|
8820
9113
|
out.unsupported.push("VBA macros");
|
|
@@ -8870,7 +9163,7 @@ function parseGlobals(records) {
|
|
|
8870
9163
|
return out;
|
|
8871
9164
|
}
|
|
8872
9165
|
|
|
8873
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9166
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8-edit.js
|
|
8874
9167
|
function encodeRkExact(value) {
|
|
8875
9168
|
if (!Number.isFinite(value))
|
|
8876
9169
|
return void 0;
|
|
@@ -8898,19 +9191,19 @@ function worksheetRanges(bytes) {
|
|
|
8898
9191
|
const ranges = [];
|
|
8899
9192
|
let depth = 0;
|
|
8900
9193
|
let start;
|
|
8901
|
-
for (const
|
|
8902
|
-
if (
|
|
8903
|
-
if (
|
|
9194
|
+
for (const record5 of records) {
|
|
9195
|
+
if (record5.opcode === 2057) {
|
|
9196
|
+
if (record5.length < 4 || view2.getUint16(record5.dataOffset, true) !== 1536 || depth >= 64)
|
|
8904
9197
|
return void 0;
|
|
8905
|
-
if (depth === 0 && view2.getUint16(
|
|
8906
|
-
start =
|
|
9198
|
+
if (depth === 0 && view2.getUint16(record5.dataOffset + 2, true) === 16)
|
|
9199
|
+
start = record5.headerOffset;
|
|
8907
9200
|
depth++;
|
|
8908
|
-
} else if (
|
|
8909
|
-
if (depth === 0 ||
|
|
9201
|
+
} else if (record5.opcode === 10) {
|
|
9202
|
+
if (depth === 0 || record5.length !== 0)
|
|
8910
9203
|
return void 0;
|
|
8911
9204
|
depth--;
|
|
8912
9205
|
if (depth === 0 && start !== void 0) {
|
|
8913
|
-
ranges.push({ start, end:
|
|
9206
|
+
ranges.push({ start, end: record5.dataOffset });
|
|
8914
9207
|
start = void 0;
|
|
8915
9208
|
}
|
|
8916
9209
|
}
|
|
@@ -8965,24 +9258,24 @@ function editXlsNumericCell(input, edit) {
|
|
|
8965
9258
|
let packed = false;
|
|
8966
9259
|
let depth = 0;
|
|
8967
9260
|
let matches = 0;
|
|
8968
|
-
for (const
|
|
8969
|
-
if (
|
|
9261
|
+
for (const record5 of readRecords(bytes, range.start, range.end)) {
|
|
9262
|
+
if (record5.opcode === 2057) {
|
|
8970
9263
|
depth++;
|
|
8971
9264
|
continue;
|
|
8972
9265
|
}
|
|
8973
|
-
if (
|
|
9266
|
+
if (record5.opcode === 10) {
|
|
8974
9267
|
depth--;
|
|
8975
9268
|
continue;
|
|
8976
9269
|
}
|
|
8977
9270
|
if (depth !== 1)
|
|
8978
9271
|
continue;
|
|
8979
|
-
const p =
|
|
8980
|
-
if (
|
|
8981
|
-
if (
|
|
9272
|
+
const p = record5.dataOffset;
|
|
9273
|
+
if (record5.opcode === 189) {
|
|
9274
|
+
if (record5.length < 12 || (record5.length - 6) % 6 !== 0)
|
|
8982
9275
|
return unchanged("malformed-records");
|
|
8983
9276
|
const first = view2.getUint16(p + 2, true);
|
|
8984
|
-
const lastCol = view2.getUint16(p +
|
|
8985
|
-
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (
|
|
9277
|
+
const lastCol = view2.getUint16(p + record5.length - 2, true);
|
|
9278
|
+
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 6)
|
|
8986
9279
|
return unchanged("malformed-records");
|
|
8987
9280
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol) {
|
|
8988
9281
|
if (++matches > 1)
|
|
@@ -8990,26 +9283,26 @@ function editXlsNumericCell(input, edit) {
|
|
|
8990
9283
|
payload = p + 6 + (edit.col - first) * 6;
|
|
8991
9284
|
packed = true;
|
|
8992
9285
|
}
|
|
8993
|
-
} else if (
|
|
8994
|
-
if (
|
|
9286
|
+
} else if (record5.opcode === 515 || record5.opcode === 638) {
|
|
9287
|
+
if (record5.length !== (record5.opcode === 515 ? 14 : 10))
|
|
8995
9288
|
return unchanged("malformed-records");
|
|
8996
9289
|
if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col) {
|
|
8997
9290
|
if (++matches > 1)
|
|
8998
9291
|
return unchanged("ambiguous-cell");
|
|
8999
9292
|
payload = p + 6;
|
|
9000
|
-
packed =
|
|
9293
|
+
packed = record5.opcode === 638;
|
|
9001
9294
|
}
|
|
9002
|
-
} else if ([6, 513, 516, 517, 253, 214].includes(
|
|
9003
|
-
if (
|
|
9295
|
+
} else if ([6, 513, 516, 517, 253, 214].includes(record5.opcode)) {
|
|
9296
|
+
if (record5.length < 6)
|
|
9004
9297
|
return unchanged("malformed-records");
|
|
9005
9298
|
if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col && ++matches > 1)
|
|
9006
9299
|
return unchanged("ambiguous-cell");
|
|
9007
|
-
} else if (
|
|
9008
|
-
if (
|
|
9300
|
+
} else if (record5.opcode === 190) {
|
|
9301
|
+
if (record5.length < 8 || (record5.length - 6) % 2 !== 0)
|
|
9009
9302
|
return unchanged("malformed-records");
|
|
9010
9303
|
const first = view2.getUint16(p + 2, true);
|
|
9011
|
-
const lastCol = view2.getUint16(p +
|
|
9012
|
-
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (
|
|
9304
|
+
const lastCol = view2.getUint16(p + record5.length - 2, true);
|
|
9305
|
+
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 2)
|
|
9013
9306
|
return unchanged("malformed-records");
|
|
9014
9307
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol && ++matches > 1)
|
|
9015
9308
|
return unchanged("ambiguous-cell");
|
|
@@ -9035,7 +9328,7 @@ function editXlsNumericCell(input, edit) {
|
|
|
9035
9328
|
}
|
|
9036
9329
|
}
|
|
9037
9330
|
|
|
9038
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9331
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8.js
|
|
9039
9332
|
var OPCODE_BOF = 2057;
|
|
9040
9333
|
var OPCODE_EOF = 10;
|
|
9041
9334
|
var OPCODE_FILEPASS = 47;
|
|
@@ -9063,8 +9356,8 @@ function isSupportedBiff8Workbook(bytes) {
|
|
|
9063
9356
|
const view2 = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
9064
9357
|
if (view2.getUint16(bof.dataOffset, true) !== 1536 || view2.getUint16(bof.dataOffset + 2, true) !== 5)
|
|
9065
9358
|
return false;
|
|
9066
|
-
const globalsEnd = records.find((
|
|
9067
|
-
return !records.some((
|
|
9359
|
+
const globalsEnd = records.find((record5) => record5.opcode === OPCODE_EOF)?.headerOffset ?? bytes.length;
|
|
9360
|
+
return !records.some((record5) => record5.opcode === OPCODE_FILEPASS && record5.headerOffset < globalsEnd);
|
|
9068
9361
|
}
|
|
9069
9362
|
function decodeRk(rk) {
|
|
9070
9363
|
const isInt = (rk & 2) !== 0;
|
|
@@ -9082,7 +9375,7 @@ function decodeRk(rk) {
|
|
|
9082
9375
|
return isDiv100 ? value / 100 : value;
|
|
9083
9376
|
}
|
|
9084
9377
|
|
|
9085
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9378
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-formulas.js
|
|
9086
9379
|
function readRefU(r) {
|
|
9087
9380
|
return { firstRow: r.u16(), lastRow: r.u16(), firstCol: r.u8(), lastCol: r.u8() };
|
|
9088
9381
|
}
|
|
@@ -9140,7 +9433,7 @@ function resolveFormulas(formulas, shared, arrays, globals) {
|
|
|
9140
9433
|
}
|
|
9141
9434
|
}
|
|
9142
9435
|
|
|
9143
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9436
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet-extras.js
|
|
9144
9437
|
function parseMergedCells(data) {
|
|
9145
9438
|
const r = new ByteReader(data);
|
|
9146
9439
|
const count = r.u16();
|
|
@@ -9318,11 +9611,11 @@ function parseObj(data) {
|
|
|
9318
9611
|
r.skip(2);
|
|
9319
9612
|
return { type: r.u16(), id: r.u16() };
|
|
9320
9613
|
}
|
|
9321
|
-
function parseTxoText(
|
|
9322
|
-
const count = new ByteReader(
|
|
9323
|
-
if (count === 0 ||
|
|
9614
|
+
function parseTxoText(record5) {
|
|
9615
|
+
const count = new ByteReader(record5.data, 10).u16();
|
|
9616
|
+
if (count === 0 || record5.continues.length === 0)
|
|
9324
9617
|
return "";
|
|
9325
|
-
const reader = new SegmentReader(
|
|
9618
|
+
const reader = new SegmentReader(record5.continues);
|
|
9326
9619
|
const wide = (reader.u8() & 1) !== 0;
|
|
9327
9620
|
return reader.continuedChars(count, wide).replace(/\r\n?/g, "\n");
|
|
9328
9621
|
}
|
|
@@ -9335,7 +9628,7 @@ function parseNote(data) {
|
|
|
9335
9628
|
return { row, col, visible: (flags & 2) !== 0, id, author: r.xlString() };
|
|
9336
9629
|
}
|
|
9337
9630
|
|
|
9338
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9631
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet.js
|
|
9339
9632
|
var UNSUPPORTED = {
|
|
9340
9633
|
432: "conditional formatting",
|
|
9341
9634
|
2169: "conditional formatting",
|
|
@@ -9385,8 +9678,8 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9385
9678
|
return result;
|
|
9386
9679
|
};
|
|
9387
9680
|
for (let index = start; index < records.length; index++) {
|
|
9388
|
-
const
|
|
9389
|
-
const { opcode, data } =
|
|
9681
|
+
const record5 = records[index];
|
|
9682
|
+
const { opcode, data } = record5;
|
|
9390
9683
|
if (opcode === 2057) {
|
|
9391
9684
|
depth++;
|
|
9392
9685
|
if (depth > 1)
|
|
@@ -9438,7 +9731,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9438
9731
|
case 516:
|
|
9439
9732
|
case 214: {
|
|
9440
9733
|
const target = cell(r, "");
|
|
9441
|
-
const reader = SegmentReader.of({ ...
|
|
9734
|
+
const reader = SegmentReader.of({ ...record5, data: data.subarray(6) });
|
|
9442
9735
|
target.value = reader.xlString();
|
|
9443
9736
|
break;
|
|
9444
9737
|
}
|
|
@@ -9462,7 +9755,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9462
9755
|
}
|
|
9463
9756
|
case 519:
|
|
9464
9757
|
if (stringTarget)
|
|
9465
|
-
stringTarget.value = SegmentReader.of(
|
|
9758
|
+
stringTarget.value = SegmentReader.of(record5).xlString();
|
|
9466
9759
|
stringTarget = void 0;
|
|
9467
9760
|
break;
|
|
9468
9761
|
case 1212: {
|
|
@@ -9542,7 +9835,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9542
9835
|
}
|
|
9543
9836
|
case 438:
|
|
9544
9837
|
if (lastObject?.type === 25)
|
|
9545
|
-
texts.set(lastObject.id, parseTxoText(
|
|
9838
|
+
texts.set(lastObject.id, parseTxoText(record5));
|
|
9546
9839
|
break;
|
|
9547
9840
|
case 28:
|
|
9548
9841
|
notes.push(parseNote(data));
|
|
@@ -9591,7 +9884,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9591
9884
|
return sheet;
|
|
9592
9885
|
}
|
|
9593
9886
|
|
|
9594
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9887
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook.js
|
|
9595
9888
|
function compoundStreamNames(bytes) {
|
|
9596
9889
|
if (!OLE_MAGIC.every((value, index) => bytes[index] === value))
|
|
9597
9890
|
return [];
|
|
@@ -9605,12 +9898,12 @@ function compoundStreamNames(bytes) {
|
|
|
9605
9898
|
function topLevelSubstreams(records) {
|
|
9606
9899
|
const starts = [];
|
|
9607
9900
|
let depth = 0;
|
|
9608
|
-
records.forEach((
|
|
9609
|
-
if (
|
|
9901
|
+
records.forEach((record5, index) => {
|
|
9902
|
+
if (record5.opcode === 2057) {
|
|
9610
9903
|
if (depth === 0 && index > 0)
|
|
9611
9904
|
starts.push(index);
|
|
9612
9905
|
depth++;
|
|
9613
|
-
} else if (
|
|
9906
|
+
} else if (record5.opcode === 10)
|
|
9614
9907
|
depth = Math.max(0, depth - 1);
|
|
9615
9908
|
});
|
|
9616
9909
|
return starts;
|
|
@@ -9633,7 +9926,7 @@ function readXlsWorkbook(bytes) {
|
|
|
9633
9926
|
unsupported2.push("VBA macros");
|
|
9634
9927
|
if (streams.some((name) => name === "_SX_DB_CUR") && !unsupported2.includes("pivot caches"))
|
|
9635
9928
|
unsupported2.push("pivot caches");
|
|
9636
|
-
const byOffset = new Map(records.map((
|
|
9929
|
+
const byOffset = new Map(records.map((record5, index) => [record5.offset, index]));
|
|
9637
9930
|
const substreams = topLevelSubstreams(records);
|
|
9638
9931
|
const sheets = globals.sheets.map((bound2, position) => {
|
|
9639
9932
|
const start = byOffset.get(bound2.offset) ?? substreams[position];
|
|
@@ -9661,7 +9954,7 @@ function readXlsWorkbook(bytes) {
|
|
|
9661
9954
|
};
|
|
9662
9955
|
}
|
|
9663
9956
|
|
|
9664
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9957
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-sst.js
|
|
9665
9958
|
var SstCursor = class {
|
|
9666
9959
|
segments;
|
|
9667
9960
|
segment = 0;
|
|
@@ -9784,7 +10077,7 @@ function appendXlsSstString(value) {
|
|
|
9784
10077
|
return Uint8Array.from(records);
|
|
9785
10078
|
}
|
|
9786
10079
|
|
|
9787
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10080
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cell-record-splices.js
|
|
9788
10081
|
var CELL_OPS = /* @__PURE__ */ new Set([6, 513, 515, 516, 517, 638, 253, 189, 190, 214]);
|
|
9789
10082
|
function record2(opcode, data) {
|
|
9790
10083
|
const out = new Uint8Array(data.length + 4), view2 = new DataView(out.buffer);
|
|
@@ -9876,7 +10169,7 @@ function relocateXlsDbCells(input, out, records, replacement, map) {
|
|
|
9876
10169
|
}
|
|
9877
10170
|
}
|
|
9878
10171
|
|
|
9879
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10172
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-known-records.js
|
|
9880
10173
|
var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
|
|
9881
10174
|
6,
|
|
9882
10175
|
10,
|
|
@@ -10234,7 +10527,7 @@ var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
|
|
|
10234
10527
|
]);
|
|
10235
10528
|
var XLS_FRT_WRAPPER = 2129;
|
|
10236
10529
|
|
|
10237
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10530
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-record-edit-model.js
|
|
10238
10531
|
var EditError = class extends Error {
|
|
10239
10532
|
reason;
|
|
10240
10533
|
constructor(reason) {
|
|
@@ -10335,6 +10628,8 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
|
|
|
10335
10628
|
const first = view2.getUint16(p + 2, true), last = view2.getUint16(p + r.length - 2, true);
|
|
10336
10629
|
if (last > 255 || last < first || last - first + 1 !== (r.length - 6) / stride)
|
|
10337
10630
|
reject("malformed-records");
|
|
10631
|
+
if (r.opcode === 190 && (first > 254 || last <= first))
|
|
10632
|
+
reject("malformed-records");
|
|
10338
10633
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= last)
|
|
10339
10634
|
targets.push(r);
|
|
10340
10635
|
}
|
|
@@ -10344,19 +10639,19 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
|
|
|
10344
10639
|
const target = targets[0];
|
|
10345
10640
|
if (!target || !allowed.includes(target.opcode))
|
|
10346
10641
|
reject("cell-not-supported");
|
|
10347
|
-
if (target.opcode !== 189 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : 10))
|
|
10642
|
+
if (target.opcode !== 189 && target.opcode !== 190 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : target.opcode === 513 ? 6 : 10))
|
|
10348
10643
|
reject("malformed-records");
|
|
10349
|
-
for (const
|
|
10350
|
-
if (
|
|
10644
|
+
for (const record5 of m.records.filter((r) => r.headerOffset >= range.start && r.headerOffset < range.end && r.depth === 1 && [545, 1212, 566].includes(r.opcode))) {
|
|
10645
|
+
if (record5.length < 6)
|
|
10351
10646
|
reject("malformed-records");
|
|
10352
|
-
const p =
|
|
10647
|
+
const p = record5.dataOffset;
|
|
10353
10648
|
if (edit.row >= view2.getUint16(p, true) && edit.row <= view2.getUint16(p + 2, true) && edit.col >= view2.getUint8(p + 4) && edit.col <= view2.getUint8(p + 5))
|
|
10354
10649
|
reject("cell-not-supported");
|
|
10355
10650
|
}
|
|
10356
10651
|
return target;
|
|
10357
10652
|
}
|
|
10358
10653
|
|
|
10359
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10654
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-edit.js
|
|
10360
10655
|
function extSst(entries, map) {
|
|
10361
10656
|
const interval = Math.max(Math.floor(entries.length / 128) + 1, 8);
|
|
10362
10657
|
const count = Math.ceil(entries.length / interval);
|
|
@@ -10468,18 +10763,18 @@ function editXlsStringWorkbookStream(input, edit) {
|
|
|
10468
10763
|
view2.setUint32(map(sst.start) + 8, sst.entries.length + (index === sst.entries.length ? 1 : 0), true);
|
|
10469
10764
|
if (splices.length) {
|
|
10470
10765
|
const byOffset = new Map(m.records.map((r) => [r.headerOffset, r]));
|
|
10471
|
-
for (const
|
|
10472
|
-
if (
|
|
10766
|
+
for (const record5 of m.records) {
|
|
10767
|
+
if (record5.opcode === 133 && (record5.headerOffset >= m.globalsEnd || record5.depth !== 1))
|
|
10473
10768
|
reject("malformed-records");
|
|
10474
|
-
if (
|
|
10475
|
-
view2.setUint32(map(
|
|
10476
|
-
if (
|
|
10477
|
-
if (
|
|
10769
|
+
if (record5.opcode === 133)
|
|
10770
|
+
view2.setUint32(map(record5.dataOffset), map(sourceView.getUint32(record5.dataOffset, true)), true);
|
|
10771
|
+
if (record5.opcode === 523) {
|
|
10772
|
+
if (record5.length < 16 || (record5.length - 16) % 4 !== 0)
|
|
10478
10773
|
reject("malformed-records");
|
|
10479
|
-
for (let p =
|
|
10774
|
+
for (let p = record5.dataOffset + 12; p < record5.dataOffset + record5.length; p += 4) {
|
|
10480
10775
|
const address = sourceView.getUint32(p, true);
|
|
10481
10776
|
const pointed = byOffset.get(address);
|
|
10482
|
-
if (!pointed || pointed.opcode !== (p ===
|
|
10777
|
+
if (!pointed || pointed.opcode !== (p === record5.dataOffset + 12 ? 85 : 215))
|
|
10483
10778
|
reject("malformed-records");
|
|
10484
10779
|
view2.setUint32(map(p), map(address), true);
|
|
10485
10780
|
}
|
|
@@ -10492,7 +10787,7 @@ function editXlsStringWorkbookStream(input, edit) {
|
|
|
10492
10787
|
}
|
|
10493
10788
|
}
|
|
10494
10789
|
|
|
10495
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10790
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-cell.js
|
|
10496
10791
|
function editXlsPreservedStringCell(input, edit) {
|
|
10497
10792
|
if (!OLE_MAGIC.every((value, index) => input[index] === value))
|
|
10498
10793
|
return editXlsStringWorkbookStream(input, edit);
|
|
@@ -10511,7 +10806,7 @@ function editXlsPreservedStringCell(input, edit) {
|
|
|
10511
10806
|
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
10512
10807
|
}
|
|
10513
10808
|
|
|
10514
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10809
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-edit.js
|
|
10515
10810
|
var ERRORS = Object.freeze({
|
|
10516
10811
|
"#NULL!": 0,
|
|
10517
10812
|
"#DIV/0!": 7,
|
|
@@ -10522,6 +10817,9 @@ var ERRORS = Object.freeze({
|
|
|
10522
10817
|
"#N/A": 42,
|
|
10523
10818
|
"#GETTING_DATA": 43
|
|
10524
10819
|
});
|
|
10820
|
+
function isValidXlsBoolErrorRecordValue(flag, value) {
|
|
10821
|
+
return flag === 0 && (value === 0 || value === 1) || flag === 1 && Object.values(ERRORS).includes(value);
|
|
10822
|
+
}
|
|
10525
10823
|
function normalizeXlsErrorValue(value) {
|
|
10526
10824
|
try {
|
|
10527
10825
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
@@ -10549,7 +10847,7 @@ function editXlsBoolErrorWorkbookStream(input, edit) {
|
|
|
10549
10847
|
const source = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
10550
10848
|
if (target.opcode === 517) {
|
|
10551
10849
|
const flag = source.getUint8(target.dataOffset + 7), value2 = source.getUint8(target.dataOffset + 6);
|
|
10552
|
-
if (
|
|
10850
|
+
if (!isValidXlsBoolErrorRecordValue(flag, value2))
|
|
10553
10851
|
reject("malformed-records");
|
|
10554
10852
|
}
|
|
10555
10853
|
const data = new Uint8Array(12), view2 = new DataView(data.buffer);
|
|
@@ -10626,7 +10924,175 @@ function editXlsBoolErrorCell(input, edit) {
|
|
|
10626
10924
|
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
10627
10925
|
}
|
|
10628
10926
|
|
|
10629
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10927
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-record.js
|
|
10928
|
+
function record3(opcode, data) {
|
|
10929
|
+
const out = new Uint8Array(4 + data.length), view2 = new DataView(out.buffer);
|
|
10930
|
+
view2.setUint16(0, opcode, true);
|
|
10931
|
+
view2.setUint16(2, data.length, true);
|
|
10932
|
+
out.set(data, 4);
|
|
10933
|
+
return out;
|
|
10934
|
+
}
|
|
10935
|
+
function replaceXlsBlankRecord(input, target, col, value) {
|
|
10936
|
+
if (!Number.isInteger(col) || col < 0 || col > 255 || !Number.isFinite(value) || !Number.isSafeInteger(target.headerOffset) || target.headerOffset < 0 || target.dataOffset !== target.headerOffset + 4 || !Number.isInteger(target.length) || target.length < 6 || target.dataOffset + target.length > input.length || ![513, 190].includes(target.opcode))
|
|
10937
|
+
throw new Error("Invalid blank record replacement");
|
|
10938
|
+
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength), p = target.dataOffset;
|
|
10939
|
+
if (view2.getUint16(target.headerOffset, true) !== target.opcode || view2.getUint16(target.headerOffset + 2, true) !== target.length)
|
|
10940
|
+
throw new Error("Blank record framing mismatch");
|
|
10941
|
+
const packed = target.opcode === 190;
|
|
10942
|
+
if (packed ? target.length < 10 || (target.length - 6) % 2 !== 0 : target.length !== 6)
|
|
10943
|
+
throw new Error("Invalid blank record length");
|
|
10944
|
+
const row = view2.getUint16(p, true), first = view2.getUint16(p + 2, true), count = packed ? (target.length - 6) / 2 : 1;
|
|
10945
|
+
const selected = col - first;
|
|
10946
|
+
if (first > 255 || first + count - 1 > 255 || selected < 0 || selected >= count || packed && view2.getUint16(p + target.length - 2, true) !== first + count - 1)
|
|
10947
|
+
throw new Error("Invalid blank column range");
|
|
10948
|
+
const data = new Uint8Array(14), cell = new DataView(data.buffer);
|
|
10949
|
+
cell.setUint16(0, row, true);
|
|
10950
|
+
cell.setUint16(2, col, true);
|
|
10951
|
+
cell.setUint16(4, view2.getUint16(p + 4 + (packed ? selected * 2 : 0), true), true);
|
|
10952
|
+
cell.setFloat64(6, value, true);
|
|
10953
|
+
const number2 = record3(515, data);
|
|
10954
|
+
const group = (start, size) => {
|
|
10955
|
+
if (!size)
|
|
10956
|
+
return new Uint8Array();
|
|
10957
|
+
const data2 = new Uint8Array(size === 1 ? 6 : 6 + size * 2), groupView = new DataView(data2.buffer);
|
|
10958
|
+
groupView.setUint16(0, row, true);
|
|
10959
|
+
groupView.setUint16(2, first + start, true);
|
|
10960
|
+
data2.set(input.subarray(p + 4 + start * 2, p + 4 + (start + size) * 2), 4);
|
|
10961
|
+
if (size > 1)
|
|
10962
|
+
groupView.setUint16(data2.length - 2, first + start + size - 1, true);
|
|
10963
|
+
return record3(size === 1 ? 513 : 190, data2);
|
|
10964
|
+
};
|
|
10965
|
+
const prefix = packed ? group(0, selected) : new Uint8Array(), suffix = packed ? group(selected + 1, count - selected - 1) : new Uint8Array();
|
|
10966
|
+
const bytes = new Uint8Array(prefix.length + number2.length + suffix.length);
|
|
10967
|
+
bytes.set(prefix);
|
|
10968
|
+
bytes.set(number2, prefix.length);
|
|
10969
|
+
bytes.set(suffix, prefix.length + number2.length);
|
|
10970
|
+
return { start: target.headerOffset, end: p + target.length, bytes };
|
|
10971
|
+
}
|
|
10972
|
+
|
|
10973
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-stored-cell-edit.js
|
|
10974
|
+
function applyXlsCellRecordReplacement(input, m, replacement) {
|
|
10975
|
+
if (!Number.isSafeInteger(replacement.start) || !Number.isSafeInteger(replacement.end) || replacement.start < 0 || replacement.end <= replacement.start || replacement.end > input.length || !(replacement.bytes instanceof Uint8Array))
|
|
10976
|
+
reject("malformed-records");
|
|
10977
|
+
const target = m.records.find((r) => r.headerOffset === replacement.start);
|
|
10978
|
+
if (!target || target.dataOffset + target.length !== replacement.end || ![513, 190, 517].includes(target.opcode))
|
|
10979
|
+
reject("malformed-records");
|
|
10980
|
+
const delta = replacement.bytes.length - (replacement.end - replacement.start);
|
|
10981
|
+
if (delta !== 0 && m.records.some((r) => !KNOWN_XLS_RECORDS.has(r.opcode) || r.opcode === XLS_FRT_WRAPPER))
|
|
10982
|
+
reject("unsupported-pointer-record");
|
|
10983
|
+
const map = (address) => {
|
|
10984
|
+
if (!Number.isSafeInteger(address) || address < 0 || address > input.length || address > replacement.start && address < replacement.end)
|
|
10985
|
+
reject("malformed-records");
|
|
10986
|
+
return address >= replacement.end ? address + delta : address;
|
|
10987
|
+
};
|
|
10988
|
+
const out = new Uint8Array(input.length + delta);
|
|
10989
|
+
out.set(input.subarray(0, replacement.start));
|
|
10990
|
+
out.set(replacement.bytes, replacement.start);
|
|
10991
|
+
out.set(input.subarray(replacement.end), replacement.start + replacement.bytes.length);
|
|
10992
|
+
if (delta !== 0) {
|
|
10993
|
+
relocateXlsDbCells(input, out, m.records, replacement, map);
|
|
10994
|
+
const source = new DataView(input.buffer, input.byteOffset, input.byteLength), dest = new DataView(out.buffer), byOffset = new Map(m.records.map((r) => [r.headerOffset, r]));
|
|
10995
|
+
for (const r of m.records) {
|
|
10996
|
+
if (r.opcode === 133) {
|
|
10997
|
+
if (r.headerOffset >= m.globalsEnd || r.depth !== 1)
|
|
10998
|
+
reject("malformed-records");
|
|
10999
|
+
dest.setUint32(map(r.dataOffset), map(source.getUint32(r.dataOffset, true)), true);
|
|
11000
|
+
}
|
|
11001
|
+
if (r.opcode === 523) {
|
|
11002
|
+
if (r.length < 16 || (r.length - 16) % 4 !== 0)
|
|
11003
|
+
reject("malformed-records");
|
|
11004
|
+
const owner = m.worksheets.find((sheet) => r.depth === 1 && r.headerOffset >= sheet.start && r.headerOffset < sheet.end);
|
|
11005
|
+
if (!owner)
|
|
11006
|
+
reject("malformed-records");
|
|
11007
|
+
const pointers = /* @__PURE__ */ new Set();
|
|
11008
|
+
for (let p = r.dataOffset + 12; p < r.dataOffset + r.length; p += 4) {
|
|
11009
|
+
const address = source.getUint32(p, true);
|
|
11010
|
+
const pointed = byOffset.get(address);
|
|
11011
|
+
if (pointed?.opcode !== (p === r.dataOffset + 12 ? 85 : 215) || pointed.depth !== 1 || address < owner.start || address >= owner.end)
|
|
11012
|
+
reject("malformed-records");
|
|
11013
|
+
if (pointers.has(address))
|
|
11014
|
+
reject("malformed-records");
|
|
11015
|
+
pointers.add(address);
|
|
11016
|
+
dest.setUint32(map(p), map(address), true);
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
}
|
|
11020
|
+
}
|
|
11021
|
+
return out;
|
|
11022
|
+
}
|
|
11023
|
+
function editXlsStoredCellWorkbookStream(input, edit, sourceKind) {
|
|
11024
|
+
const unchanged = (reason) => ({ status: "unchanged", bytes: input, reason });
|
|
11025
|
+
const row = edit.row, col = edit.col, worksheetIndex = edit.worksheetIndex ?? 0, supplied = edit.value;
|
|
11026
|
+
const value = supplied !== null && typeof supplied === "object" ? normalizeXlsErrorValue(supplied) : supplied;
|
|
11027
|
+
if (!["blank", "bool-error"].includes(sourceKind) || !Number.isInteger(row) || row < 0 || row > 65535 || !Number.isInteger(col) || col < 0 || col > 255 || !Number.isInteger(worksheetIndex) || worksheetIndex < 0 || sourceKind === "bool-error" && typeof value !== "number" && typeof value !== "string" || (typeof value === "number" ? !Number.isFinite(value) : typeof value !== "string" && typeof value !== "boolean" && (value === void 0 || value === null || typeof value !== "object")))
|
|
11028
|
+
return unchanged("invalid-edit");
|
|
11029
|
+
try {
|
|
11030
|
+
const m = model(input), target = findTarget(input, m, { row, col, worksheetIndex }, sourceKind === "blank" ? [513, 190] : [517]);
|
|
11031
|
+
const range = m.worksheets[worksheetIndex], source = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
11032
|
+
for (const record5 of m.records.filter((r) => r.opcode === 229 && r.depth === 1 && r.headerOffset >= range.start && r.headerOffset < range.end)) {
|
|
11033
|
+
if (record5.length < 2)
|
|
11034
|
+
reject("malformed-records");
|
|
11035
|
+
const count = source.getUint16(record5.dataOffset, true);
|
|
11036
|
+
if (record5.length !== 2 + count * 8)
|
|
11037
|
+
reject("malformed-records");
|
|
11038
|
+
for (let p = record5.dataOffset + 2; p < record5.dataOffset + record5.length; p += 8) {
|
|
11039
|
+
const firstRow = source.getUint16(p, true), lastRow = source.getUint16(p + 2, true), firstCol = source.getUint16(p + 4, true), lastCol = source.getUint16(p + 6, true);
|
|
11040
|
+
if (firstRow > lastRow || firstCol > lastCol || lastCol > 255)
|
|
11041
|
+
reject("malformed-records");
|
|
11042
|
+
if (row >= firstRow && row <= lastRow && col >= firstCol && col <= lastCol && (row !== firstRow || col !== firstCol))
|
|
11043
|
+
reject("cell-not-supported");
|
|
11044
|
+
}
|
|
11045
|
+
}
|
|
11046
|
+
let replacement;
|
|
11047
|
+
if (sourceKind === "blank")
|
|
11048
|
+
replacement = replaceXlsBlankRecord(input, target, col, typeof value === "number" ? value : 0);
|
|
11049
|
+
else {
|
|
11050
|
+
if (!isValidXlsBoolErrorRecordValue(source.getUint8(target.dataOffset + 7), source.getUint8(target.dataOffset + 6)))
|
|
11051
|
+
reject("malformed-records");
|
|
11052
|
+
const bytes = new Uint8Array(18), number2 = new DataView(bytes.buffer);
|
|
11053
|
+
number2.setUint16(0, 515, true);
|
|
11054
|
+
number2.setUint16(2, 14, true);
|
|
11055
|
+
bytes.set(input.subarray(target.dataOffset, target.dataOffset + 6), 4);
|
|
11056
|
+
number2.setFloat64(10, typeof value === "number" ? value : 0, true);
|
|
11057
|
+
replacement = { start: target.headerOffset, end: target.dataOffset + target.length, bytes };
|
|
11058
|
+
}
|
|
11059
|
+
const staged = applyXlsCellRecordReplacement(input, m, replacement);
|
|
11060
|
+
if (typeof value === "number")
|
|
11061
|
+
return { status: "edited", bytes: staged, recalculationRequired: true };
|
|
11062
|
+
const result = typeof value === "string" ? editXlsStringWorkbookStream(staged, { row, col, worksheetIndex, value }) : editXlsBoolErrorWorkbookStream(staged, { row, col, worksheetIndex, value });
|
|
11063
|
+
return result.status === "edited" ? result : { ...result, bytes: input };
|
|
11064
|
+
} catch (error) {
|
|
11065
|
+
return unchanged(error instanceof EditError ? error.reason : "malformed-records");
|
|
11066
|
+
}
|
|
11067
|
+
}
|
|
11068
|
+
function editXlsStoredCell(input, edit, sourceKind) {
|
|
11069
|
+
if (!OLE_MAGIC.every((value, index) => input[index] === value))
|
|
11070
|
+
return editXlsStoredCellWorkbookStream(input, edit, sourceKind);
|
|
11071
|
+
const streams = ["Workbook", "Book"].map((name) => ({ name, bytes: readCompoundFileStream(input, [name]) })).filter((s) => s.bytes !== void 0);
|
|
11072
|
+
if (streams.length !== 1)
|
|
11073
|
+
return { status: "unchanged", bytes: input, reason: "unsupported-workbook" };
|
|
11074
|
+
const stream = streams[0], result = editXlsStoredCellWorkbookStream(stream.bytes, edit, sourceKind);
|
|
11075
|
+
if (result.status !== "edited")
|
|
11076
|
+
return { ...result, bytes: input };
|
|
11077
|
+
if (result.bytes.length === stream.bytes.length) {
|
|
11078
|
+
const bytes = replaceCompoundFileStream(input, [stream.name], result.bytes);
|
|
11079
|
+
return bytes === input ? { status: "unchanged", bytes: input, reason: "container-not-writable" } : { ...result, bytes };
|
|
11080
|
+
}
|
|
11081
|
+
const resized = resizeCompoundFileStream(input, [stream.name], result.bytes);
|
|
11082
|
+
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
11083
|
+
}
|
|
11084
|
+
|
|
11085
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-edit.js
|
|
11086
|
+
function editXlsBlankCell(input, edit) {
|
|
11087
|
+
return editXlsStoredCell(input, edit, "blank");
|
|
11088
|
+
}
|
|
11089
|
+
|
|
11090
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-conversion.js
|
|
11091
|
+
function editXlsBoolErrorScalarCell(input, edit) {
|
|
11092
|
+
return editXlsStoredCell(input, edit, "bool-error");
|
|
11093
|
+
}
|
|
11094
|
+
|
|
11095
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/xls-document.js
|
|
10630
11096
|
function cellType(cell) {
|
|
10631
11097
|
if (cell.formula !== void 0 || cell.formulaUndecoded || cell.arrayRange || cell.sharedFormula)
|
|
10632
11098
|
return "formula";
|
|
@@ -10726,8 +11192,8 @@ var XlsSheetNode = class {
|
|
|
10726
11192
|
};
|
|
10727
11193
|
var XLS_CAPABILITIES = Object.freeze({
|
|
10728
11194
|
read: Object.freeze(["BIFF8 worksheets", "cell values and cached formulas", "styles and merges", "opaque compound streams"]),
|
|
10729
|
-
write: Object.freeze(["existing NUMBER/RK/MULRK numeric values", "existing LABELSST/NUMBER/RK/MULRK plain string values", "existing NUMBER/RK/MULRK/BOOLERR boolean and error values"]),
|
|
10730
|
-
limitations: Object.freeze(["No cell creation, formula editing or recalculation", "Numeric
|
|
11195
|
+
write: Object.freeze(["existing NUMBER/RK/MULRK numeric values", "existing LABELSST/NUMBER/RK/MULRK plain string values", "existing NUMBER/RK/MULRK/BOOLERR boolean and error values", "existing BLANK/MULBLANK cells to number, plain string, boolean or error values", "existing BOOLERR cells to finite number or plain string values"]),
|
|
11196
|
+
limitations: Object.freeze(["No implicit cell creation, formula editing or recalculation", "Numeric replacement of existing numeric cells requires exact original encoding", "Resizing writes reject unsupported relocation records and container layouts", "Plain string replacement removes selected rich text runs", "String-to-boolean/error conversions unsupported"])
|
|
10731
11197
|
});
|
|
10732
11198
|
var XlsDocument = class extends Ole2DocumentBase {
|
|
10733
11199
|
get kind() {
|
|
@@ -10742,6 +11208,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10742
11208
|
}
|
|
10743
11209
|
#model;
|
|
10744
11210
|
#needsRecalculation = false;
|
|
11211
|
+
#settingCellValue = false;
|
|
10745
11212
|
constructor(input) {
|
|
10746
11213
|
super(input);
|
|
10747
11214
|
const bytes = this.getBytes();
|
|
@@ -10772,6 +11239,16 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10772
11239
|
}
|
|
10773
11240
|
/** @internal All changes are validated and parsed before committing bytes. */
|
|
10774
11241
|
setCellValue(sheetIndex, row, col, value) {
|
|
11242
|
+
if (this.#settingCellValue)
|
|
11243
|
+
throw new UnsupportedOle2EditError("reentrant-cell-edit");
|
|
11244
|
+
this.#settingCellValue = true;
|
|
11245
|
+
try {
|
|
11246
|
+
this.#applyCellValue(sheetIndex, row, col, value);
|
|
11247
|
+
} finally {
|
|
11248
|
+
this.#settingCellValue = false;
|
|
11249
|
+
}
|
|
11250
|
+
}
|
|
11251
|
+
#applyCellValue(sheetIndex, row, col, value) {
|
|
10775
11252
|
if (value !== null && typeof value === "object") {
|
|
10776
11253
|
const normalized = normalizeXlsErrorValue(value);
|
|
10777
11254
|
if (!normalized)
|
|
@@ -10784,13 +11261,14 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10784
11261
|
const sheet = this.#model.sheets[sheetIndex];
|
|
10785
11262
|
if (sheet?.kind !== "worksheet")
|
|
10786
11263
|
throw new UnsupportedOle2EditError("sheet-not-supported");
|
|
10787
|
-
if (cell.value === null)
|
|
10788
|
-
|
|
11264
|
+
if (cell.value === null && value === null)
|
|
11265
|
+
return;
|
|
10789
11266
|
if (typeof value !== "number" && typeof value !== "string" && typeof value !== "boolean" && !isXlsErrorValue(value))
|
|
10790
11267
|
throw new UnsupportedOle2EditError("value-type-not-supported");
|
|
10791
|
-
|
|
11268
|
+
const boolError = typeof cell.value === "boolean" || isXlsErrorValue(cell.value);
|
|
11269
|
+
if (typeof value === "number" && (cell.value !== null && typeof cell.value !== "number" && !boolError || !Number.isFinite(value)))
|
|
10792
11270
|
throw new UnsupportedOle2EditError("numeric-type-change-not-supported");
|
|
10793
|
-
if (typeof value === "string" && typeof cell.value !== "number" && typeof cell.value !== "string")
|
|
11271
|
+
if (typeof value === "string" && cell.value !== null && typeof cell.value !== "number" && typeof cell.value !== "string" && !boolError)
|
|
10794
11272
|
throw new UnsupportedOle2EditError("string-type-change-not-supported");
|
|
10795
11273
|
if ((typeof value === "boolean" || isXlsErrorValue(value)) && typeof cell.value === "string")
|
|
10796
11274
|
throw new UnsupportedOle2EditError("bool-error-type-change-not-supported");
|
|
@@ -10798,7 +11276,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10798
11276
|
return;
|
|
10799
11277
|
const worksheetIndex = this.#model.sheets.slice(0, sheetIndex).filter((s) => s.kind === "worksheet").length;
|
|
10800
11278
|
const edit = { row, col, value, worksheetIndex };
|
|
10801
|
-
const result = typeof value === "number" ? editXlsNumericCell(this.getBytes(), { ...edit, value }) : typeof value === "string" ? editXlsPreservedStringCell(this.getBytes(), { ...edit, value }) : editXlsBoolErrorCell(this.getBytes(), { ...edit, value });
|
|
11279
|
+
const result = cell.value === null ? editXlsBlankCell(this.getBytes(), { ...edit, value }) : boolError && (typeof value === "number" || typeof value === "string") ? editXlsBoolErrorScalarCell(this.getBytes(), { ...edit, value }) : typeof value === "number" ? editXlsNumericCell(this.getBytes(), { ...edit, value }) : typeof value === "string" ? editXlsPreservedStringCell(this.getBytes(), { ...edit, value }) : editXlsBoolErrorCell(this.getBytes(), { ...edit, value });
|
|
10802
11280
|
if (result.status !== "edited")
|
|
10803
11281
|
throw new UnsupportedOle2EditError(result.reason);
|
|
10804
11282
|
const next = readXlsWorkbook(result.bytes);
|
|
@@ -10811,7 +11289,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10811
11289
|
}
|
|
10812
11290
|
};
|
|
10813
11291
|
|
|
10814
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11292
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-stream.js
|
|
10815
11293
|
var PptParseError = class extends Error {
|
|
10816
11294
|
constructor(message) {
|
|
10817
11295
|
super(message);
|
|
@@ -10845,18 +11323,88 @@ function readRecordOrThrow(view2, offset) {
|
|
|
10845
11323
|
return rec;
|
|
10846
11324
|
}
|
|
10847
11325
|
|
|
10848
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11326
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-types.js
|
|
10849
11327
|
var RT2 = {
|
|
10850
11328
|
Document: 1e3,
|
|
11329
|
+
DocumentAtom: 1001,
|
|
11330
|
+
EndDocumentAtom: 1002,
|
|
10851
11331
|
Slide: 1006,
|
|
11332
|
+
SlideAtom: 1007,
|
|
11333
|
+
Notes: 1008,
|
|
11334
|
+
NotesAtom: 1009,
|
|
11335
|
+
Environment: 1010,
|
|
10852
11336
|
SlidePersistAtom: 1011,
|
|
11337
|
+
MainMaster: 1016,
|
|
11338
|
+
SlideShowSlideInfoAtom: 1017,
|
|
11339
|
+
SlideViewInfo: 1018,
|
|
11340
|
+
ExternalObjectList: 1033,
|
|
11341
|
+
ExternalObjectListAtom: 1034,
|
|
11342
|
+
DrawingGroup: 1035,
|
|
11343
|
+
Drawing: 1036,
|
|
11344
|
+
List: 2e3,
|
|
11345
|
+
FontCollection: 2005,
|
|
11346
|
+
SoundCollection: 2020,
|
|
11347
|
+
SoundCollectionAtom: 2021,
|
|
11348
|
+
Sound: 2022,
|
|
11349
|
+
SoundDataBlob: 2023,
|
|
11350
|
+
ColorSchemeAtom: 2032,
|
|
11351
|
+
ExternalObjectRefAtom: 3009,
|
|
11352
|
+
OEPlaceholderAtom: 3011,
|
|
11353
|
+
RoundTripSlideSyncInfo12: 3012,
|
|
10853
11354
|
OutlineTextRefAtom: 3998,
|
|
11355
|
+
TextHeaderAtom: 3999,
|
|
10854
11356
|
TextCharsAtom: 4e3,
|
|
11357
|
+
StyleTextPropAtom: 4001,
|
|
11358
|
+
MasterTextPropAtom: 4002,
|
|
11359
|
+
TextMasterStyleAtom: 4003,
|
|
10855
11360
|
TextBytesAtom: 4008,
|
|
11361
|
+
TextSpecInfoAtom: 4010,
|
|
11362
|
+
CString: 4026,
|
|
11363
|
+
ExternalOleObjectAtom: 4035,
|
|
11364
|
+
ExternalOleEmbed: 4044,
|
|
11365
|
+
ExternalOleEmbedAtom: 4045,
|
|
11366
|
+
ExternalHyperlinkAtom: 4051,
|
|
11367
|
+
ExternalHyperlink: 4055,
|
|
11368
|
+
ExternalOleObjectStg: 4113,
|
|
11369
|
+
/** [MS-PPT] 2.10.6: information about external audio/video data (exObjId + loop/rewind/narration flags). */
|
|
11370
|
+
ExternalMediaAtom: 4100,
|
|
11371
|
+
/** [MS-PPT] 2.10.5: wraps an ExMediaAtom + optional UncOrLocalPathAtom for a linked video file. */
|
|
11372
|
+
ExternalVideo: 4101,
|
|
11373
|
+
/** [MS-PPT] 2.10.4: wraps an ExVideoContainer for a linked AVI movie. */
|
|
11374
|
+
ExternalAviMovie: 4102,
|
|
11375
|
+
/** [MS-PPT] 2.10.3: wraps an ExVideoContainer for a linked (generic/MCI-played) movie; what real
|
|
11376
|
+
* PowerPoint 16.0 writes for a linked non-AVI video file (COM-verified). */
|
|
11377
|
+
ExternalMciMovie: 4103,
|
|
11378
|
+
/** [MS-PPT] 2.10.8: wraps an ExMediaAtom + ExWAVAudioEmbeddedAtom referencing a SoundCollection entry. */
|
|
11379
|
+
ExternalWavAudioEmbedded: 4111,
|
|
11380
|
+
/** [MS-PPT] 2.10.9: soundIdRef (into SoundCollectionContainer) + soundLength (ms). recVer/recInstance = 0x1/0x001. */
|
|
11381
|
+
ExternalWavAudioEmbeddedAtom: 4115,
|
|
11382
|
+
TextInteractiveInfoAtom: 4063,
|
|
10856
11383
|
SlideListWithText: 4080,
|
|
11384
|
+
InteractiveInfo: 4082,
|
|
11385
|
+
InteractiveInfoAtom: 4083,
|
|
10857
11386
|
UserEditAtom: 4085,
|
|
10858
11387
|
CurrentUserAtom: 4086,
|
|
10859
|
-
|
|
11388
|
+
FontEntityAtom: 4023,
|
|
11389
|
+
CryptSession10Container: 12052,
|
|
11390
|
+
PersistDirectoryAtom: 6002,
|
|
11391
|
+
HeadersFooters: 4057,
|
|
11392
|
+
HeadersFootersAtom: 4058,
|
|
11393
|
+
ProgTags: 5e3,
|
|
11394
|
+
ProgBinaryTag: 5002,
|
|
11395
|
+
BinaryTagDataBlob: 5003,
|
|
11396
|
+
RoundTripCustomTableStyles12Atom: 17036,
|
|
11397
|
+
/** [MS-PPT] 2.11.21: a master's theme as a zipped OOXML package. */
|
|
11398
|
+
RoundTripTheme12Atom: 1038,
|
|
11399
|
+
/** [MS-PPT] 2.11.19: a master's `a:clrMap` as an XML string. */
|
|
11400
|
+
RoundTripColorMapping12Atom: 1039,
|
|
11401
|
+
/** [MS-PPT] 2.11.22: a master's `p:txStyles` as a zipped OOXML package. */
|
|
11402
|
+
RoundTripOArtTextStyles12Atom: 1059,
|
|
11403
|
+
/** [MS-PPT] 2.9.28: a date field (`*`) in a master date placeholder. */
|
|
11404
|
+
GenericDateMCAtom: 4088,
|
|
11405
|
+
/** [MS-PPT] 2.9.25: a slide-number field (`*`) in a placeholder. */
|
|
11406
|
+
SlideNumberMCAtom: 4056
|
|
11407
|
+
};
|
|
10860
11408
|
var OA = {
|
|
10861
11409
|
SpgrContainer: 61443,
|
|
10862
11410
|
SpContainer: 61444,
|
|
@@ -10870,7 +11418,7 @@ var OA = {
|
|
|
10870
11418
|
var HEADER_TOKEN_PLAIN = 3817979999;
|
|
10871
11419
|
var HEADER_TOKEN_ENCRYPTED = 4090610911;
|
|
10872
11420
|
|
|
10873
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11421
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt/persist-directory.js
|
|
10874
11422
|
var DEFAULT_MAX_EDITS = 1e4;
|
|
10875
11423
|
var DEFAULT_MAX_ENTRIES = 1e6;
|
|
10876
11424
|
function checkedLimit(value) {
|
|
@@ -10987,7 +11535,7 @@ function buildPersistDirectory(view2, offsetToCurrentEdit, limits = {}) {
|
|
|
10987
11535
|
return { currentEdit: edits[0], directory };
|
|
10988
11536
|
}
|
|
10989
11537
|
|
|
10990
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11538
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text.js
|
|
10991
11539
|
var PptTextError = class extends PptParseError {
|
|
10992
11540
|
code;
|
|
10993
11541
|
constructor(code, message) {
|
|
@@ -11062,7 +11610,7 @@ function inlineText(view2, parent) {
|
|
|
11062
11610
|
}
|
|
11063
11611
|
return { texts: result.sort((a, b) => a.headerOffset - b.headerOffset), mirrors };
|
|
11064
11612
|
}
|
|
11065
|
-
function
|
|
11613
|
+
function inspect4(input) {
|
|
11066
11614
|
const current = readCompoundFileStream(input, ["Current User"]);
|
|
11067
11615
|
const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
11068
11616
|
if (!current || !stream)
|
|
@@ -11140,19 +11688,69 @@ function inspect3(input) {
|
|
|
11140
11688
|
}
|
|
11141
11689
|
function readPptSlideTexts(input) {
|
|
11142
11690
|
try {
|
|
11143
|
-
return
|
|
11691
|
+
return inspect4(input).model;
|
|
11144
11692
|
} catch (error) {
|
|
11145
11693
|
if (error instanceof PptTextError)
|
|
11146
11694
|
throw error;
|
|
11147
11695
|
throw new PptTextError("corrupt", error instanceof Error ? error.message : "Malformed PPT");
|
|
11148
11696
|
}
|
|
11149
11697
|
}
|
|
11698
|
+
function textOwnershipRefusal(input, stream, persistId, atom) {
|
|
11699
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
11700
|
+
if (!user)
|
|
11701
|
+
throw new PptParseError("Missing Current User stream");
|
|
11702
|
+
const view2 = viewOf(stream), uv = viewOf(user), cu = readRecordOrThrow(uv, 0);
|
|
11703
|
+
const editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
11704
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
|
|
11705
|
+
const slideOffset = directory.get(persistId);
|
|
11706
|
+
if (slideOffset === void 0)
|
|
11707
|
+
return "Missing active slide persist object";
|
|
11708
|
+
const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
|
|
11709
|
+
const textEnd = text.dataOffset + text.recLen;
|
|
11710
|
+
const owners = [persistId];
|
|
11711
|
+
if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
|
|
11712
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
11713
|
+
if (docOffset === void 0)
|
|
11714
|
+
return "Missing outline text owner";
|
|
11715
|
+
const doc = readRecordOrThrow(view2, docOffset);
|
|
11716
|
+
if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
|
|
11717
|
+
return "Text is outside its active owning containers";
|
|
11718
|
+
owners.push(currentEdit.docPersistIdRef);
|
|
11719
|
+
}
|
|
11720
|
+
for (const ownerId of owners) {
|
|
11721
|
+
const owned = readRecordOrThrow(view2, directory.get(ownerId));
|
|
11722
|
+
const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
11723
|
+
if (end > view2.byteLength)
|
|
11724
|
+
return "Unbounded text owning persist object";
|
|
11725
|
+
const overlaps = (offset) => {
|
|
11726
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
11727
|
+
if (otherEnd > view2.byteLength)
|
|
11728
|
+
throw new PptParseError("Unbounded live persist object prevents safe text edit");
|
|
11729
|
+
return start < otherEnd && other.headerOffset < end;
|
|
11730
|
+
};
|
|
11731
|
+
for (const [id, offset] of directory)
|
|
11732
|
+
if (id !== ownerId && overlaps(offset))
|
|
11733
|
+
return "Text owning container overlaps another live persist object";
|
|
11734
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11735
|
+
for (let offset = editOffset; offset; ) {
|
|
11736
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
11737
|
+
return "Invalid text save-history ownership";
|
|
11738
|
+
visited.add(offset);
|
|
11739
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
11740
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
11741
|
+
return "Text owning container overlaps save-history metadata";
|
|
11742
|
+
offset = edit.offsetLastEdit;
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11745
|
+
return void 0;
|
|
11746
|
+
}
|
|
11150
11747
|
function editPptSlideText(input, edit) {
|
|
11151
11748
|
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
11152
11749
|
try {
|
|
11750
|
+
edit = { slideIndex: edit.slideIndex, textIndex: edit.textIndex, expectedText: edit.expectedText, text: edit.text };
|
|
11153
11751
|
if (!Number.isSafeInteger(edit.slideIndex) || !Number.isSafeInteger(edit.textIndex) || edit.slideIndex < 0 || edit.textIndex < 0)
|
|
11154
11752
|
return reject2("Invalid text location");
|
|
11155
|
-
const { stream, model: model2, mirroredAtoms } =
|
|
11753
|
+
const { stream, model: model2, mirroredAtoms } = inspect4(input);
|
|
11156
11754
|
const atom = model2.slides[edit.slideIndex]?.texts[edit.textIndex];
|
|
11157
11755
|
if (!atom || atom.text !== edit.expectedText)
|
|
11158
11756
|
return reject2("Text location or expected text does not match");
|
|
@@ -11175,6 +11773,9 @@ function editPptSlideText(input, edit) {
|
|
|
11175
11773
|
if (value >= 56320 && value <= 57343 && !(edit.text.charCodeAt(i - 1) >= 55296 && edit.text.charCodeAt(i - 1) <= 56319))
|
|
11176
11774
|
return reject2("Unpaired UTF-16 surrogate");
|
|
11177
11775
|
}
|
|
11776
|
+
const ownership = textOwnershipRefusal(input, stream, model2.slides[edit.slideIndex].persistId, atom);
|
|
11777
|
+
if (ownership)
|
|
11778
|
+
return reject2(ownership);
|
|
11178
11779
|
const output = stream.slice(), view2 = viewOf(output), start = atom.headerOffset + 8;
|
|
11179
11780
|
for (let i = 0; i < edit.text.length; i++) {
|
|
11180
11781
|
if (atom.encoding === "utf16")
|
|
@@ -11189,7 +11790,7 @@ function editPptSlideText(input, edit) {
|
|
|
11189
11790
|
}
|
|
11190
11791
|
}
|
|
11191
11792
|
|
|
11192
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11793
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-reader.js
|
|
11193
11794
|
var DEFAULT_LIMITS = { maxRecords: 1e5, maxShapes: 1e4, maxProperties: 1e5, maxNameChars: 1e6, maxTextBytes: 16 * 1024 * 1024 };
|
|
11194
11795
|
var GEOMETRY_PROPERTY_IDS = /* @__PURE__ */ new Set([4, 127, 128, 191, 385, 447, 448, 459, 511, 896, 959]);
|
|
11195
11796
|
function pptShapeChildren(view2, parent) {
|
|
@@ -11229,13 +11830,13 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11229
11830
|
if (documentOffset === void 0)
|
|
11230
11831
|
throw new PptTextError("corrupt", "Missing active document");
|
|
11231
11832
|
const documentRecord = readRecordOrThrow(view2, documentOffset);
|
|
11232
|
-
const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((
|
|
11833
|
+
const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((record5) => record5.recType === RT2.SlideListWithText && record5.recInstance === 0);
|
|
11233
11834
|
for (const list of activeLists)
|
|
11234
|
-
for (const
|
|
11235
|
-
if (
|
|
11236
|
-
if (
|
|
11835
|
+
for (const record5 of pptShapeChildren(view2, list))
|
|
11836
|
+
if (record5.recType === RT2.SlidePersistAtom) {
|
|
11837
|
+
if (record5.recLen !== 20)
|
|
11237
11838
|
throw new PptTextError("corrupt", "Invalid slide persist atom");
|
|
11238
|
-
const offset = chain2.directory.get(view2.getUint32(
|
|
11839
|
+
const offset = chain2.directory.get(view2.getUint32(record5.dataOffset, true));
|
|
11239
11840
|
if (offset === void 0)
|
|
11240
11841
|
throw new PptTextError("corrupt", "Missing active slide");
|
|
11241
11842
|
slideOffsets.push(offset);
|
|
@@ -11280,9 +11881,9 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11280
11881
|
const item = stack.pop();
|
|
11281
11882
|
if (item.depth > 128)
|
|
11282
11883
|
throw new PptTextError("corrupt", "Shape nesting exceeds limit");
|
|
11283
|
-
const
|
|
11884
|
+
const children4 = pptShapeChildren(view2, item.rec);
|
|
11284
11885
|
if (item.rec.recType === OA.SpContainer) {
|
|
11285
|
-
const fsps =
|
|
11886
|
+
const fsps = children4.filter((rec) => rec.recType === OA.FSP);
|
|
11286
11887
|
if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
|
|
11287
11888
|
throw new PptTextError("corrupt", "Missing or ambiguous OfficeArtFSP");
|
|
11288
11889
|
const fsp = fsps[0], shapeId = view2.getUint32(fsp.dataOffset, true), flags = view2.getUint32(fsp.dataOffset + 4, true);
|
|
@@ -11307,7 +11908,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11307
11908
|
};
|
|
11308
11909
|
let propertyAmbiguity = false, unknownProperties = false, protectedGeometry = false, unknownTextFit = false;
|
|
11309
11910
|
const seenProperties = /* @__PURE__ */ new Set();
|
|
11310
|
-
const anchors =
|
|
11911
|
+
const anchors = children4.filter((rec) => rec.recType === OA.ClientAnchor || rec.recType === OA.ChildAnchor);
|
|
11311
11912
|
if (anchors.length === 1) {
|
|
11312
11913
|
const rec = anchors[0];
|
|
11313
11914
|
if (rec.recVer !== 0 || rec.recInstance !== 0 || (rec.recType === OA.ClientAnchor ? rec.recLen !== 8 && rec.recLen !== 16 : rec.recLen !== 16))
|
|
@@ -11321,13 +11922,13 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11321
11922
|
};
|
|
11322
11923
|
shape.coordinateSpace = largeClient ? "unknown" : rec.recType === OA.ChildAnchor ? "group-child-master-units" : item.group !== void 0 || flags & 2 ? "unknown" : "slide-master-units";
|
|
11323
11924
|
}
|
|
11324
|
-
const group =
|
|
11925
|
+
const group = children4.find((rec) => rec.recType === OA.FSPGR);
|
|
11325
11926
|
if (group) {
|
|
11326
11927
|
if (group.recVer !== 1 || group.recLen !== 16)
|
|
11327
11928
|
throw new PptTextError("corrupt", "Invalid group coordinate space");
|
|
11328
11929
|
shape.groupBounds = bounds(view2, group);
|
|
11329
11930
|
}
|
|
11330
|
-
for (const rec of
|
|
11931
|
+
for (const rec of children4.filter((rec2) => rec2.recType === OA.FOPT || rec2.recType === OA.TertiaryFOPT || rec2.recType === 61729)) {
|
|
11331
11932
|
if (rec.recVer !== 3 || rec.recInstance * 6 > rec.recLen)
|
|
11332
11933
|
throw new PptTextError("corrupt", "Invalid shape property table");
|
|
11333
11934
|
let complexOffset = rec.dataOffset + rec.recInstance * 6;
|
|
@@ -11365,7 +11966,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11365
11966
|
shape.textIndexes = slide.texts.flatMap((atom, index) => atom.headerOffset >= item.rec.dataOffset && atom.headerOffset < shape.recordEnd ? [index] : []);
|
|
11366
11967
|
if (shape.textIndexes.length)
|
|
11367
11968
|
shape.textReference = "inline";
|
|
11368
|
-
for (const textbox of
|
|
11969
|
+
for (const textbox of children4.filter((rec) => rec.recType === OA.ClientTextbox))
|
|
11369
11970
|
if (pptShapeChildren(view2, textbox).some((rec) => rec.recType === RT2.OutlineTextRefAtom))
|
|
11370
11971
|
shape.textReference = "unresolved";
|
|
11371
11972
|
if (shape.mirrored)
|
|
@@ -11389,7 +11990,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11389
11990
|
}
|
|
11390
11991
|
let parentGroup = item.group;
|
|
11391
11992
|
if (item.rec.recType === OA.SpgrContainer) {
|
|
11392
|
-
const head =
|
|
11993
|
+
const head = children4[0];
|
|
11393
11994
|
if (!head || head.recType !== OA.SpContainer)
|
|
11394
11995
|
throw new PptTextError("corrupt", "Group has no shape container");
|
|
11395
11996
|
const fsp = pptShapeChildren(view2, head).find((rec) => rec.recType === OA.FSP);
|
|
@@ -11398,8 +11999,8 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11398
11999
|
if (!(view2.getUint32(fsp.dataOffset + 4, true) & 4))
|
|
11399
12000
|
parentGroup = view2.getUint32(fsp.dataOffset, true);
|
|
11400
12001
|
}
|
|
11401
|
-
for (let i =
|
|
11402
|
-
const rec =
|
|
12002
|
+
for (let i = children4.length - 1; i >= 0; i--) {
|
|
12003
|
+
const rec = children4[i];
|
|
11403
12004
|
if (rec.recVer === 15 || rec.recType === OA.ClientTextbox)
|
|
11404
12005
|
stack.push({ rec, depth: item.depth + 1, group: item.rec.recType === OA.SpgrContainer && i === 0 ? item.group : parentGroup });
|
|
11405
12006
|
}
|
|
@@ -11408,10 +12009,44 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11408
12009
|
});
|
|
11409
12010
|
}
|
|
11410
12011
|
|
|
11411
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
12012
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-edit.js
|
|
11412
12013
|
function equalPptShapeBounds(a, b) {
|
|
11413
12014
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
11414
12015
|
}
|
|
12016
|
+
function slideOwnershipRefusal(input, stream, persistId) {
|
|
12017
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
12018
|
+
if (!user)
|
|
12019
|
+
throw new PptParseError("Missing Current User stream");
|
|
12020
|
+
const view2 = new DataView(stream.buffer, stream.byteOffset, stream.byteLength), uv = new DataView(user.buffer, user.byteOffset, user.byteLength);
|
|
12021
|
+
const cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12022
|
+
const { directory } = buildPersistDirectory(view2, editOffset), ownedOffset = directory.get(persistId);
|
|
12023
|
+
if (ownedOffset === void 0)
|
|
12024
|
+
return "Missing active slide persist object";
|
|
12025
|
+
const owned = readRecordOrThrow(view2, ownedOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12026
|
+
if (end > view2.byteLength)
|
|
12027
|
+
return "Unbounded slide persist object";
|
|
12028
|
+
const overlaps = (offset) => {
|
|
12029
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
12030
|
+
if (otherEnd > view2.byteLength)
|
|
12031
|
+
throw new PptParseError("Unbounded live persist object prevents safe geometry edit");
|
|
12032
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12033
|
+
};
|
|
12034
|
+
for (const [id, offset] of directory) {
|
|
12035
|
+
if (id !== persistId && overlaps(offset))
|
|
12036
|
+
return "Slide container overlaps another live persist object";
|
|
12037
|
+
}
|
|
12038
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12039
|
+
for (let offset = editOffset; offset; ) {
|
|
12040
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12041
|
+
return "Invalid geometry save-history ownership";
|
|
12042
|
+
visited.add(offset);
|
|
12043
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12044
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12045
|
+
return "Slide container overlaps save-history metadata";
|
|
12046
|
+
offset = edit.offsetLastEdit;
|
|
12047
|
+
}
|
|
12048
|
+
return void 0;
|
|
12049
|
+
}
|
|
11415
12050
|
function editPptShapeBounds(input, edit) {
|
|
11416
12051
|
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
11417
12052
|
try {
|
|
@@ -11444,7 +12079,11 @@ function editPptShapeBounds(input, edit) {
|
|
|
11444
12079
|
const edges = [next.y, next.x, next.x + next.width, next.y + next.height];
|
|
11445
12080
|
if (!edges.every((value) => Number.isSafeInteger(value) && value >= -32768 && value <= 32767))
|
|
11446
12081
|
return reject2("Geometry exceeds the existing small anchor encoding");
|
|
11447
|
-
const stream = readCompoundFileStream(input, ["PowerPoint Document"])
|
|
12082
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
12083
|
+
const ownership = slideOwnershipRefusal(input, stream, persistId);
|
|
12084
|
+
if (ownership)
|
|
12085
|
+
return reject2(ownership);
|
|
12086
|
+
const out = stream.slice(), view2 = new DataView(out.buffer);
|
|
11448
12087
|
for (let i = 0; i < edges.length; i++)
|
|
11449
12088
|
view2.setInt16(anchor + 8 + i * 2, edges[i], true);
|
|
11450
12089
|
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], out);
|
|
@@ -11459,12 +12098,604 @@ function editPptShapeBounds(input, edit) {
|
|
|
11459
12098
|
}
|
|
11460
12099
|
}
|
|
11461
12100
|
|
|
11462
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
12101
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-notes.js
|
|
12102
|
+
var viewOf2 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
12103
|
+
function fail2(message) {
|
|
12104
|
+
throw new PptTextError("corrupt", message);
|
|
12105
|
+
}
|
|
12106
|
+
function inspect5(input, limits = {}) {
|
|
12107
|
+
const maxRecords = limits.maxRecords ?? 1e5, maxNotes = limits.maxNotes ?? 1e4, maxTextBytes = limits.maxTextBytes ?? 16 * 1024 * 1024;
|
|
12108
|
+
for (const value of [maxRecords, maxNotes, maxTextBytes])
|
|
12109
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
12110
|
+
fail2("Invalid notes resource limit");
|
|
12111
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
|
|
12112
|
+
if (!stream || !user)
|
|
12113
|
+
fail2("Missing PowerPoint streams");
|
|
12114
|
+
const view2 = viewOf2(stream), uv = viewOf2(user);
|
|
12115
|
+
const record5 = (offset, type) => {
|
|
12116
|
+
const r = readRecordOrThrow(view2, offset);
|
|
12117
|
+
if (r.dataOffset + r.recLen > view2.byteLength || type !== void 0 && r.recType !== type)
|
|
12118
|
+
fail2("Invalid notes record bounds/type");
|
|
12119
|
+
return r;
|
|
12120
|
+
};
|
|
12121
|
+
const cu = readRecordOrThrow(uv, 0);
|
|
12122
|
+
if (cu.recType !== RT2.CurrentUserAtom || cu.recVer !== 0 || cu.recInstance !== 0 || cu.recLen < 24 || cu.dataOffset + cu.recLen > uv.byteLength)
|
|
12123
|
+
fail2("Invalid CurrentUserAtom");
|
|
12124
|
+
const token = uv.getUint32(cu.dataOffset + 4, true);
|
|
12125
|
+
if (token === HEADER_TOKEN_ENCRYPTED)
|
|
12126
|
+
throw new PptTextError("encrypted", "Encrypted PPT notes are unsupported");
|
|
12127
|
+
if (token !== HEADER_TOKEN_PLAIN)
|
|
12128
|
+
fail2("Unknown encryption token");
|
|
12129
|
+
const { currentEdit, directory } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true), { maxEntries: maxRecords });
|
|
12130
|
+
if (currentEdit.encryptSessionPersistIdRef !== void 0)
|
|
12131
|
+
throw new PptTextError("encrypted", "Encrypted notes persist objects are unsupported");
|
|
12132
|
+
let recordCount = 0, textBytes = 0;
|
|
12133
|
+
const children4 = (r) => {
|
|
12134
|
+
const result = [], end = r.dataOffset + r.recLen;
|
|
12135
|
+
for (let pos = r.dataOffset; pos < end; ) {
|
|
12136
|
+
if (++recordCount > maxRecords)
|
|
12137
|
+
fail2("Notes record budget exceeded");
|
|
12138
|
+
if (end - pos < 8)
|
|
12139
|
+
fail2("Truncated notes child header");
|
|
12140
|
+
const child2 = record5(pos);
|
|
12141
|
+
if (child2.dataOffset + child2.recLen > end)
|
|
12142
|
+
fail2("Notes child exceeds parent");
|
|
12143
|
+
result.push(child2);
|
|
12144
|
+
pos = child2.dataOffset + child2.recLen;
|
|
12145
|
+
}
|
|
12146
|
+
return result;
|
|
12147
|
+
};
|
|
12148
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
12149
|
+
if (docOffset === void 0)
|
|
12150
|
+
fail2("Missing active document");
|
|
12151
|
+
const doc = record5(docOffset, RT2.Document);
|
|
12152
|
+
if (doc.recVer !== 15)
|
|
12153
|
+
fail2("Invalid document container");
|
|
12154
|
+
const docChildren = children4(doc), refs = /* @__PURE__ */ new Map(), persistIds = /* @__PURE__ */ new Set();
|
|
12155
|
+
const notesLists = docChildren.filter((r) => r.recType === RT2.SlideListWithText && r.recInstance === 2);
|
|
12156
|
+
if (notesLists.length > 1)
|
|
12157
|
+
fail2("Ambiguous notes list");
|
|
12158
|
+
for (const list of notesLists) {
|
|
12159
|
+
if (list.recVer !== 15)
|
|
12160
|
+
fail2("Invalid notes list");
|
|
12161
|
+
for (const r of children4(list)) {
|
|
12162
|
+
if (r.recType !== RT2.SlidePersistAtom || r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 20)
|
|
12163
|
+
fail2("Invalid NotesPersistAtom");
|
|
12164
|
+
const persistId = view2.getUint32(r.dataOffset, true), notesId = view2.getUint32(r.dataOffset + 12, true);
|
|
12165
|
+
if (!notesId || !persistId || refs.has(notesId) || persistIds.has(persistId))
|
|
12166
|
+
fail2("Duplicate or null notes identity");
|
|
12167
|
+
if (refs.size >= maxNotes)
|
|
12168
|
+
fail2("Notes count budget exceeded");
|
|
12169
|
+
refs.set(notesId, persistId);
|
|
12170
|
+
persistIds.add(persistId);
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
const slides = readPptSlideShapes(input, { maxRecords, maxTextBytes, maxShapes: maxRecords });
|
|
12174
|
+
if (slides.length > maxNotes)
|
|
12175
|
+
fail2("Active slide budget exceeded");
|
|
12176
|
+
const links = /* @__PURE__ */ new Map(), linkedNotes = /* @__PURE__ */ new Set();
|
|
12177
|
+
for (const slide of slides) {
|
|
12178
|
+
const offset = directory.get(slide.persistId);
|
|
12179
|
+
if (offset === void 0)
|
|
12180
|
+
fail2("Missing active slide");
|
|
12181
|
+
const sr = record5(offset, RT2.Slide), slideAtoms = children4(sr).filter((r) => r.recType === RT2.SlideAtom);
|
|
12182
|
+
if (slideAtoms.length !== 1 || slideAtoms[0].recVer !== 2 || slideAtoms[0].recInstance !== 0 || slideAtoms[0].recLen !== 24)
|
|
12183
|
+
fail2("Invalid SlideAtom notes linkage");
|
|
12184
|
+
const notesId = view2.getUint32(slideAtoms[0].dataOffset + 16, true);
|
|
12185
|
+
if (notesId && linkedNotes.has(notesId))
|
|
12186
|
+
fail2("Notes linked by multiple active slides");
|
|
12187
|
+
if (notesId)
|
|
12188
|
+
linkedNotes.add(notesId);
|
|
12189
|
+
links.set(slide.slideId, notesId);
|
|
12190
|
+
}
|
|
12191
|
+
const activeNotes = new Set(links.values());
|
|
12192
|
+
const raw = /* @__PURE__ */ new Map();
|
|
12193
|
+
for (const [notesId, persistId] of refs) {
|
|
12194
|
+
if (!activeNotes.has(notesId))
|
|
12195
|
+
continue;
|
|
12196
|
+
const offset = directory.get(persistId);
|
|
12197
|
+
if (offset === void 0)
|
|
12198
|
+
fail2("Missing notes persist object");
|
|
12199
|
+
const header = record5(offset, RT2.Notes);
|
|
12200
|
+
if (header.recVer !== 15 || header.recInstance !== 0)
|
|
12201
|
+
fail2("Invalid NotesContainer");
|
|
12202
|
+
const direct = children4(header), atoms = direct.filter((r) => r.recType === RT2.NotesAtom);
|
|
12203
|
+
if (atoms.length !== 1 || atoms[0].recVer !== 1 || atoms[0].recInstance !== 0 || atoms[0].recLen !== 8)
|
|
12204
|
+
fail2("Invalid NotesAtom");
|
|
12205
|
+
const records = [...direct], stack = direct.filter((r) => r.recVer === 15 || r.recType === OA.ClientTextbox).map((r) => ({ r, depth: 1 }));
|
|
12206
|
+
while (stack.length) {
|
|
12207
|
+
const item = stack.pop();
|
|
12208
|
+
if (item.depth > 128)
|
|
12209
|
+
fail2("Notes nesting budget exceeded");
|
|
12210
|
+
for (const r of children4(item.r)) {
|
|
12211
|
+
records.push(r);
|
|
12212
|
+
if (r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom) {
|
|
12213
|
+
textBytes += r.recLen;
|
|
12214
|
+
if (textBytes > maxTextBytes)
|
|
12215
|
+
fail2("Notes text byte budget exceeded");
|
|
12216
|
+
if (r.recVer !== 0 || r.recInstance !== 0 || r.recType === RT2.TextCharsAtom && r.recLen % 2)
|
|
12217
|
+
fail2("Invalid notes text atom");
|
|
12218
|
+
}
|
|
12219
|
+
if (r.recVer === 15 || r.recType === OA.ClientTextbox)
|
|
12220
|
+
stack.push({ r, depth: item.depth + 1 });
|
|
12221
|
+
}
|
|
12222
|
+
}
|
|
12223
|
+
raw.set(notesId, { header, backref: view2.getUint32(atoms[0].dataOffset, true), records });
|
|
12224
|
+
}
|
|
12225
|
+
const notes = [];
|
|
12226
|
+
for (const slide of slides) {
|
|
12227
|
+
const notesId = links.get(slide.slideId);
|
|
12228
|
+
if (!notesId)
|
|
12229
|
+
continue;
|
|
12230
|
+
const info = raw.get(notesId), persistId = refs.get(notesId);
|
|
12231
|
+
if (!info || persistId === void 0 || info.backref !== slide.slideId)
|
|
12232
|
+
fail2("Notes ID or slide back-reference mismatch");
|
|
12233
|
+
const all = info.records;
|
|
12234
|
+
let notesMirror = false;
|
|
12235
|
+
for (const r of all.filter((r2) => [OA.FOPT, OA.TertiaryFOPT, 61729].includes(r2.recType))) {
|
|
12236
|
+
if (r.recVer !== 3 || r.recInstance * 6 > r.recLen)
|
|
12237
|
+
fail2("Invalid notes property table");
|
|
12238
|
+
for (let i = 0; i < r.recInstance; i++)
|
|
12239
|
+
if ((view2.getUint16(r.dataOffset + i * 6, true) & 16383) === 937)
|
|
12240
|
+
notesMirror = true;
|
|
12241
|
+
}
|
|
12242
|
+
const texts = [], shapeIds = /* @__PURE__ */ new Set();
|
|
12243
|
+
const shapeRecords = [];
|
|
12244
|
+
let activeShape;
|
|
12245
|
+
for (const r of all.sort((a, b) => a.headerOffset - b.headerOffset)) {
|
|
12246
|
+
if (activeShape && r.headerOffset >= activeShape.shape.dataOffset + activeShape.shape.recLen)
|
|
12247
|
+
activeShape = void 0;
|
|
12248
|
+
if (r.recType === OA.SpContainer) {
|
|
12249
|
+
if (activeShape)
|
|
12250
|
+
fail2("Nested notes shape containers");
|
|
12251
|
+
activeShape = { shape: r, within: [] };
|
|
12252
|
+
shapeRecords.push(activeShape);
|
|
12253
|
+
} else if (activeShape)
|
|
12254
|
+
activeShape.within.push(r);
|
|
12255
|
+
}
|
|
12256
|
+
for (const { shape, within } of shapeRecords) {
|
|
12257
|
+
const fsps = within.filter((r) => r.recType === OA.FSP);
|
|
12258
|
+
if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
|
|
12259
|
+
fail2("Invalid notes shape identity");
|
|
12260
|
+
const shapeId = view2.getUint32(fsps[0].dataOffset, true);
|
|
12261
|
+
if (!shapeId || shapeIds.has(shapeId))
|
|
12262
|
+
fail2("Duplicate notes shape identity");
|
|
12263
|
+
shapeIds.add(shapeId);
|
|
12264
|
+
const placeholders = within.filter((r) => r.recType === RT2.OEPlaceholderAtom);
|
|
12265
|
+
if (placeholders.some((r) => r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 8))
|
|
12266
|
+
fail2("Invalid notes PlaceholderAtom");
|
|
12267
|
+
const placeholderId = placeholders.length === 1 ? view2.getUint8(placeholders[0].dataOffset + 4) : void 0;
|
|
12268
|
+
const atoms = within.filter((r) => r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom);
|
|
12269
|
+
const headers = within.filter((r) => r.recType === RT2.TextHeaderAtom);
|
|
12270
|
+
const textboxes = within.filter((r) => r.recType === OA.ClientTextbox);
|
|
12271
|
+
const body = placeholderId === 12 && headers.length === 1 && headers[0].recVer === 0 && headers[0].recInstance === 0 && headers[0].recLen === 4 && view2.getUint32(headers[0].dataOffset, true) === 2;
|
|
12272
|
+
for (const atom of atoms) {
|
|
12273
|
+
const wide = atom.recType === RT2.TextCharsAtom;
|
|
12274
|
+
let text = "";
|
|
12275
|
+
for (let p = atom.dataOffset; p < atom.dataOffset + atom.recLen; p += wide ? 2 : 1) {
|
|
12276
|
+
const value = wide ? view2.getUint16(p, true) : view2.getUint8(p);
|
|
12277
|
+
if (!value)
|
|
12278
|
+
fail2("NUL in notes text atom");
|
|
12279
|
+
text += String.fromCharCode(value);
|
|
12280
|
+
}
|
|
12281
|
+
texts.push({
|
|
12282
|
+
shapeId,
|
|
12283
|
+
shapeHeaderOffset: shape.headerOffset,
|
|
12284
|
+
placeholderId,
|
|
12285
|
+
role: body ? "body" : "other",
|
|
12286
|
+
text,
|
|
12287
|
+
headerOffset: atom.headerOffset,
|
|
12288
|
+
encoding: wide ? "utf16" : "compressed-unicode",
|
|
12289
|
+
editRefusal: notesMirror ? "Notes have an OOXML mirror" : !body ? "Not a validated notes body placeholder" : atoms.length !== 1 || placeholders.length !== 1 || textboxes.length !== 1 || headers[0].headerOffset < textboxes[0].dataOffset || headers[0].headerOffset > atom.headerOffset || atom.dataOffset + atom.recLen > textboxes[0].dataOffset + textboxes[0].recLen ? "Ambiguous notes text slot" : void 0
|
|
12290
|
+
});
|
|
12291
|
+
}
|
|
12292
|
+
}
|
|
12293
|
+
notes.push({ slideId: slide.slideId, slidePersistId: slide.persistId, notesId, persistId, headerOffset: info.header.headerOffset, texts });
|
|
12294
|
+
}
|
|
12295
|
+
return { stream, notes };
|
|
12296
|
+
}
|
|
12297
|
+
function readPptSlideNotes(input, limits = {}) {
|
|
12298
|
+
return inspect5(input, limits).notes;
|
|
12299
|
+
}
|
|
12300
|
+
function ownershipRefusal(input, stream, note) {
|
|
12301
|
+
const view2 = viewOf2(stream), user = readCompoundFileStream(input, ["Current User"]);
|
|
12302
|
+
const uv = viewOf2(user), cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12303
|
+
const { directory } = buildPersistDirectory(view2, editOffset);
|
|
12304
|
+
const owned = readRecordOrThrow(view2, note.headerOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12305
|
+
const overlaps = (offset2) => {
|
|
12306
|
+
const other = readRecordOrThrow(view2, offset2), otherEnd = other.dataOffset + other.recLen;
|
|
12307
|
+
if (otherEnd > view2.byteLength)
|
|
12308
|
+
fail2("Unbounded live persist object prevents safe notes edit");
|
|
12309
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12310
|
+
};
|
|
12311
|
+
for (const [persistId, offset2] of directory) {
|
|
12312
|
+
if (persistId !== note.persistId && overlaps(offset2))
|
|
12313
|
+
return "Notes container overlaps another live persist object";
|
|
12314
|
+
}
|
|
12315
|
+
let offset = editOffset;
|
|
12316
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12317
|
+
while (offset) {
|
|
12318
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12319
|
+
return "Invalid notes save-history ownership";
|
|
12320
|
+
visited.add(offset);
|
|
12321
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12322
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12323
|
+
return "Notes container overlaps save-history metadata";
|
|
12324
|
+
offset = edit.offsetLastEdit;
|
|
12325
|
+
}
|
|
12326
|
+
return void 0;
|
|
12327
|
+
}
|
|
12328
|
+
function editPptNotesText(input, edit) {
|
|
12329
|
+
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
12330
|
+
try {
|
|
12331
|
+
const { slideId, slidePersistId, notesId, persistId, shapeId, expectedHeaderOffset, expectedText, text } = edit;
|
|
12332
|
+
if (typeof text !== "string" || typeof expectedText !== "string")
|
|
12333
|
+
return reject2("Notes replacement must be a string");
|
|
12334
|
+
const { stream, notes } = inspect5(input);
|
|
12335
|
+
const selected = notes.filter((n) => n.slideId === slideId && n.slidePersistId === slidePersistId && n.notesId === notesId && n.persistId === persistId);
|
|
12336
|
+
const matches = selected.length === 1 ? selected[0].texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset) : [];
|
|
12337
|
+
const atom = matches[0];
|
|
12338
|
+
if (matches.length !== 1 || !atom || atom.text !== expectedText)
|
|
12339
|
+
return reject2("Notes identity or expected text no longer matches");
|
|
12340
|
+
if (text === atom.text)
|
|
12341
|
+
return { status: "unchanged", bytes: input };
|
|
12342
|
+
if (atom.editRefusal)
|
|
12343
|
+
return reject2(atom.editRefusal);
|
|
12344
|
+
const ownership = ownershipRefusal(input, stream, selected[0]);
|
|
12345
|
+
if (ownership)
|
|
12346
|
+
return reject2(ownership);
|
|
12347
|
+
if (notes.reduce((n, note) => n + note.texts.filter((t) => t.headerOffset === atom.headerOffset).length, 0) !== 1)
|
|
12348
|
+
return reject2("Notes text atom is shared by active locations");
|
|
12349
|
+
const start = atom.headerOffset, end = start + 8 + atom.text.length * (atom.encoding === "utf16" ? 2 : 1);
|
|
12350
|
+
for (const slide of readPptSlideTexts(input).slides)
|
|
12351
|
+
for (const text2 of slide.texts) {
|
|
12352
|
+
const textEnd = text2.headerOffset + 8 + text2.text.length * (text2.encoding === "utf16" ? 2 : 1);
|
|
12353
|
+
if (start < textEnd && text2.headerOffset < end)
|
|
12354
|
+
return reject2("Notes slot overlaps active slide text");
|
|
12355
|
+
}
|
|
12356
|
+
if (text.length !== atom.text.length)
|
|
12357
|
+
return reject2("Notes replacement must keep the UTF-16 character count");
|
|
12358
|
+
for (let i = 0; i < text.length; i++) {
|
|
12359
|
+
const old = atom.text.charCodeAt(i), value = text.charCodeAt(i);
|
|
12360
|
+
if (!value || (old < 32 || value < 32 || old === 42 || value === 42) && old !== value)
|
|
12361
|
+
return reject2("Notes controls and field markers must remain at the same offsets");
|
|
12362
|
+
if (atom.encoding === "compressed-unicode" && value > 255)
|
|
12363
|
+
return reject2("Notes character does not fit existing encoding");
|
|
12364
|
+
if (value >= 55296 && value <= 56319 && !(text.charCodeAt(i + 1) >= 56320 && text.charCodeAt(i + 1) <= 57343) || value >= 56320 && value <= 57343 && !(text.charCodeAt(i - 1) >= 55296 && text.charCodeAt(i - 1) <= 56319))
|
|
12365
|
+
return reject2("Unpaired notes UTF-16 surrogate");
|
|
12366
|
+
}
|
|
12367
|
+
const next = stream.slice(), view2 = viewOf2(next);
|
|
12368
|
+
for (let i = 0; i < text.length; i++) {
|
|
12369
|
+
if (atom.encoding === "utf16")
|
|
12370
|
+
view2.setUint16(atom.headerOffset + 8 + i * 2, text.charCodeAt(i), true);
|
|
12371
|
+
else
|
|
12372
|
+
next[atom.headerOffset + 8 + i] = text.charCodeAt(i);
|
|
12373
|
+
}
|
|
12374
|
+
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], next);
|
|
12375
|
+
if (bytes === input)
|
|
12376
|
+
return reject2("Notes compound stream cannot be safely replaced");
|
|
12377
|
+
const candidate = inspect5(bytes).notes.find((n) => n.slideId === slideId && n.notesId === notesId && n.persistId === persistId);
|
|
12378
|
+
const confirmed = candidate?.texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset);
|
|
12379
|
+
if (confirmed?.length !== 1 || confirmed[0].text !== text)
|
|
12380
|
+
return reject2("Candidate notes revalidation failed");
|
|
12381
|
+
return { status: "edited", bytes };
|
|
12382
|
+
} catch (error) {
|
|
12383
|
+
return reject2(error instanceof Error ? error.message : "Malformed PPT notes");
|
|
12384
|
+
}
|
|
12385
|
+
}
|
|
12386
|
+
|
|
12387
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text-style.js
|
|
12388
|
+
var viewOf3 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
12389
|
+
var MAX_RECORDS = 1e5;
|
|
12390
|
+
var MAX_RUNS = 2e4;
|
|
12391
|
+
var MAX_STYLE_BYTES = 16 * 1024 * 1024;
|
|
12392
|
+
function children3(view2, parent) {
|
|
12393
|
+
const result = [], end = parent.dataOffset + parent.recLen;
|
|
12394
|
+
if (end > view2.byteLength)
|
|
12395
|
+
throw new Error("Unbounded formatting parent");
|
|
12396
|
+
for (let offset = parent.dataOffset; offset < end; ) {
|
|
12397
|
+
if (result.length >= MAX_RECORDS || end - offset < 8)
|
|
12398
|
+
throw new Error("Formatting record bounds exceeded");
|
|
12399
|
+
const record5 = readRecordOrThrow(view2, offset);
|
|
12400
|
+
if (record5.dataOffset + record5.recLen > end)
|
|
12401
|
+
throw new Error("Formatting child exceeds its parent");
|
|
12402
|
+
result.push(record5);
|
|
12403
|
+
offset = record5.dataOffset + record5.recLen;
|
|
12404
|
+
}
|
|
12405
|
+
return result;
|
|
12406
|
+
}
|
|
12407
|
+
function decodeStyle(view2, style, textLength, budget) {
|
|
12408
|
+
if (style.recVer !== 0 || style.recInstance !== 0)
|
|
12409
|
+
throw new Error("Invalid StyleTextPropAtom header");
|
|
12410
|
+
let pos = style.dataOffset;
|
|
12411
|
+
const end = pos + style.recLen, total = textLength + 1;
|
|
12412
|
+
const take = (bytes) => {
|
|
12413
|
+
if (bytes > end - pos)
|
|
12414
|
+
throw new Error("Truncated formatting exception");
|
|
12415
|
+
const offset = pos;
|
|
12416
|
+
pos += bytes;
|
|
12417
|
+
return offset;
|
|
12418
|
+
};
|
|
12419
|
+
const u16 = () => view2.getUint16(take(2), true), u32 = () => view2.getUint32(take(4), true);
|
|
12420
|
+
const count = (sum) => {
|
|
12421
|
+
if (++budget.runs > budget.maxRuns)
|
|
12422
|
+
throw new Error("Character/paragraph run budget exceeded");
|
|
12423
|
+
const value = u32();
|
|
12424
|
+
if (value === 0 || value > total - sum)
|
|
12425
|
+
throw new Error("Invalid formatting run count");
|
|
12426
|
+
return value;
|
|
12427
|
+
};
|
|
12428
|
+
for (let sum = 0; sum < total; ) {
|
|
12429
|
+
sum += count(sum);
|
|
12430
|
+
if (u16() > 4)
|
|
12431
|
+
throw new Error("Invalid paragraph indentation");
|
|
12432
|
+
const mask = u32();
|
|
12433
|
+
if (mask & -3111680)
|
|
12434
|
+
throw new Error("Unsupported paragraph formatting mask");
|
|
12435
|
+
if (mask & 15)
|
|
12436
|
+
take(2);
|
|
12437
|
+
for (const bit of [128, 16, 64])
|
|
12438
|
+
if (mask & bit)
|
|
12439
|
+
take(2);
|
|
12440
|
+
if (mask & 32)
|
|
12441
|
+
take(4);
|
|
12442
|
+
for (const bit of [2048, 4096, 8192, 16384, 65536])
|
|
12443
|
+
if (mask & bit)
|
|
12444
|
+
take(2);
|
|
12445
|
+
if (mask & 917504)
|
|
12446
|
+
take(2);
|
|
12447
|
+
if (mask & 2097152)
|
|
12448
|
+
take(2);
|
|
12449
|
+
}
|
|
12450
|
+
const result = [];
|
|
12451
|
+
for (let sum = 0; sum < total; ) {
|
|
12452
|
+
const runOffset = pos, rawCount = count(sum), start = sum;
|
|
12453
|
+
sum += rawCount;
|
|
12454
|
+
const mask = u32();
|
|
12455
|
+
if (mask & -15728640)
|
|
12456
|
+
throw new Error("Unsupported character formatting mask");
|
|
12457
|
+
if (mask & 16055)
|
|
12458
|
+
take(2);
|
|
12459
|
+
for (const bit of [65536, 2097152, 4194304, 8388608])
|
|
12460
|
+
if (mask & bit)
|
|
12461
|
+
take(2);
|
|
12462
|
+
let fontSizeOffset, directFontSizePoints;
|
|
12463
|
+
if (mask & 131072) {
|
|
12464
|
+
fontSizeOffset = take(2);
|
|
12465
|
+
directFontSizePoints = view2.getInt16(fontSizeOffset, true);
|
|
12466
|
+
if (directFontSizePoints < 1 || directFontSizePoints > 4e3)
|
|
12467
|
+
throw new Error("Invalid literal font size");
|
|
12468
|
+
}
|
|
12469
|
+
if (mask & 262144)
|
|
12470
|
+
take(4);
|
|
12471
|
+
if (mask & 524288) {
|
|
12472
|
+
const position = view2.getInt16(take(2), true);
|
|
12473
|
+
if (position < -100 || position > 100)
|
|
12474
|
+
throw new Error("Invalid baseline position");
|
|
12475
|
+
}
|
|
12476
|
+
result.push({
|
|
12477
|
+
start: Math.min(start, textLength),
|
|
12478
|
+
end: Math.min(sum, textLength),
|
|
12479
|
+
rawCount,
|
|
12480
|
+
mask,
|
|
12481
|
+
styleHeaderOffset: style.headerOffset,
|
|
12482
|
+
runOffset,
|
|
12483
|
+
fontSizeOffset,
|
|
12484
|
+
directFontSizePoints
|
|
12485
|
+
});
|
|
12486
|
+
}
|
|
12487
|
+
if (pos !== end)
|
|
12488
|
+
throw new Error("Unconsumed StyleTextPropAtom bytes");
|
|
12489
|
+
return result;
|
|
12490
|
+
}
|
|
12491
|
+
function textOwnershipRefusal2(input, stream, persistId, atom) {
|
|
12492
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
12493
|
+
if (!user)
|
|
12494
|
+
throw new PptParseError("Missing Current User stream");
|
|
12495
|
+
const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
|
|
12496
|
+
const editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12497
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
|
|
12498
|
+
const slideOffset = directory.get(persistId);
|
|
12499
|
+
if (slideOffset === void 0)
|
|
12500
|
+
return "Missing active slide persist object";
|
|
12501
|
+
const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
|
|
12502
|
+
const textEnd = text.dataOffset + text.recLen;
|
|
12503
|
+
const owners = [persistId];
|
|
12504
|
+
if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
|
|
12505
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
12506
|
+
if (docOffset === void 0)
|
|
12507
|
+
return "Missing outline text owner";
|
|
12508
|
+
const doc = readRecordOrThrow(view2, docOffset);
|
|
12509
|
+
if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
|
|
12510
|
+
return "Text is outside its active owning containers";
|
|
12511
|
+
owners.push(currentEdit.docPersistIdRef);
|
|
12512
|
+
}
|
|
12513
|
+
for (const ownerId of owners) {
|
|
12514
|
+
const owned = readRecordOrThrow(view2, directory.get(ownerId));
|
|
12515
|
+
const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12516
|
+
if (end > view2.byteLength)
|
|
12517
|
+
return "Unbounded text owning persist object";
|
|
12518
|
+
const overlaps = (offset) => {
|
|
12519
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
12520
|
+
if (otherEnd > view2.byteLength)
|
|
12521
|
+
throw new PptParseError("Unbounded live persist object prevents safe text edit");
|
|
12522
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12523
|
+
};
|
|
12524
|
+
for (const [id, offset] of directory)
|
|
12525
|
+
if (id !== ownerId && overlaps(offset))
|
|
12526
|
+
return "Text owning container overlaps another live persist object";
|
|
12527
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12528
|
+
for (let offset = editOffset; offset; ) {
|
|
12529
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12530
|
+
return "Invalid text save-history ownership";
|
|
12531
|
+
visited.add(offset);
|
|
12532
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12533
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12534
|
+
return "Text owning container overlaps save-history metadata";
|
|
12535
|
+
offset = edit.offsetLastEdit;
|
|
12536
|
+
}
|
|
12537
|
+
}
|
|
12538
|
+
return void 0;
|
|
12539
|
+
}
|
|
12540
|
+
function readPptCharacterRuns(input, limits = {}) {
|
|
12541
|
+
const maxRecords = limits.maxRecords ?? MAX_RECORDS, maxRuns = limits.maxRuns ?? MAX_RUNS, maxStyleBytes = limits.maxStyleBytes ?? MAX_STYLE_BYTES;
|
|
12542
|
+
if (![maxRecords, maxRuns, maxStyleBytes].every((value) => Number.isSafeInteger(value) && value > 0))
|
|
12543
|
+
throw new Error("Invalid character-format resource limit");
|
|
12544
|
+
readPptSlideShapes(input, { maxRecords });
|
|
12545
|
+
const texts = readPptSlideTexts(input), stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
|
|
12546
|
+
const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
|
|
12547
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true));
|
|
12548
|
+
const associations = /* @__PURE__ */ new Map();
|
|
12549
|
+
let records = 0, styleBytes = 0;
|
|
12550
|
+
const scan = (root) => {
|
|
12551
|
+
const stack = [{ record: root, depth: 0 }];
|
|
12552
|
+
while (stack.length) {
|
|
12553
|
+
const { record: record5, depth } = stack.pop();
|
|
12554
|
+
if (depth > 128)
|
|
12555
|
+
throw new Error("Formatting nesting exceeds limit");
|
|
12556
|
+
const list = children3(view2, record5);
|
|
12557
|
+
records += list.length;
|
|
12558
|
+
if (records > maxRecords)
|
|
12559
|
+
throw new Error("Formatting record budget exceeded");
|
|
12560
|
+
let group;
|
|
12561
|
+
const textParent = record5.recType === OA.ClientTextbox || record5.recType === RT2.SlideListWithText && record5.recInstance === 0;
|
|
12562
|
+
const finish = () => {
|
|
12563
|
+
if (group)
|
|
12564
|
+
for (const atom of group.atoms) {
|
|
12565
|
+
if (associations.has(atom))
|
|
12566
|
+
throw new Error("Ambiguous formatting parent");
|
|
12567
|
+
associations.set(atom, { styles: group.styles, textCount: group.atoms.length });
|
|
12568
|
+
}
|
|
12569
|
+
};
|
|
12570
|
+
for (const child2 of list) {
|
|
12571
|
+
if (textParent && (child2.recType === RT2.TextHeaderAtom || child2.recType === RT2.SlidePersistAtom)) {
|
|
12572
|
+
finish();
|
|
12573
|
+
group = child2.recType === RT2.TextHeaderAtom ? { atoms: [], styles: [] } : void 0;
|
|
12574
|
+
if (group && (child2.recVer !== 0 || child2.recInstance > (record5.recType === OA.ClientTextbox ? 0 : 5) || child2.recLen !== 4))
|
|
12575
|
+
throw new Error("Invalid formatting TextHeaderAtom");
|
|
12576
|
+
} else if (group && (child2.recType === RT2.TextCharsAtom || child2.recType === RT2.TextBytesAtom))
|
|
12577
|
+
group.atoms.push(child2.headerOffset);
|
|
12578
|
+
else if (group && child2.recType === RT2.StyleTextPropAtom) {
|
|
12579
|
+
styleBytes += child2.recLen;
|
|
12580
|
+
if (styleBytes > maxStyleBytes)
|
|
12581
|
+
throw new Error("Formatting payload budget exceeded");
|
|
12582
|
+
group.styles.push(child2);
|
|
12583
|
+
}
|
|
12584
|
+
if (child2.recVer === 15 || child2.recType === OA.ClientTextbox)
|
|
12585
|
+
stack.push({ record: child2, depth: depth + 1 });
|
|
12586
|
+
}
|
|
12587
|
+
finish();
|
|
12588
|
+
}
|
|
12589
|
+
};
|
|
12590
|
+
let scanDiagnostic;
|
|
12591
|
+
try {
|
|
12592
|
+
const doc = readRecordOrThrow(view2, directory.get(currentEdit.docPersistIdRef));
|
|
12593
|
+
for (const list of children3(view2, doc))
|
|
12594
|
+
if (list.recType === RT2.SlideListWithText && list.recInstance === 0)
|
|
12595
|
+
scan(list);
|
|
12596
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12597
|
+
for (const slide of texts.slides) {
|
|
12598
|
+
const offset = directory.get(slide.persistId);
|
|
12599
|
+
if (!visited.has(offset)) {
|
|
12600
|
+
visited.add(offset);
|
|
12601
|
+
scan(readRecordOrThrow(view2, offset));
|
|
12602
|
+
}
|
|
12603
|
+
}
|
|
12604
|
+
} catch (error) {
|
|
12605
|
+
scanDiagnostic = error instanceof Error ? error.message : "Unsupported formatting graph";
|
|
12606
|
+
}
|
|
12607
|
+
const budget = { runs: 0, maxRuns };
|
|
12608
|
+
return texts.slides.flatMap((slide) => slide.texts.map((atom) => {
|
|
12609
|
+
const base = { slideId: slide.slideId, persistId: slide.persistId, headerOffset: atom.headerOffset, text: atom.text };
|
|
12610
|
+
if (scanDiagnostic)
|
|
12611
|
+
return { ...base, status: "unsupported", diagnostic: scanDiagnostic, runs: [] };
|
|
12612
|
+
const group = associations.get(atom.headerOffset);
|
|
12613
|
+
if (!group)
|
|
12614
|
+
return { ...base, status: "unsupported", diagnostic: "Text has no unambiguous TextHeader formatting parent", runs: [] };
|
|
12615
|
+
if (!group.styles.length)
|
|
12616
|
+
return { ...base, status: "absent", runs: [] };
|
|
12617
|
+
if (group.textCount !== 1 || group.styles.length !== 1)
|
|
12618
|
+
return { ...base, status: "unsupported", diagnostic: "Text or style atom association is ambiguous", runs: [] };
|
|
12619
|
+
try {
|
|
12620
|
+
return { ...base, status: "decoded", runs: decodeStyle(view2, group.styles[0], atom.text.length, budget) };
|
|
12621
|
+
} catch (error) {
|
|
12622
|
+
return { ...base, status: "unsupported", diagnostic: error instanceof Error ? error.message : "Unsupported formatting", runs: [] };
|
|
12623
|
+
}
|
|
12624
|
+
}));
|
|
12625
|
+
}
|
|
12626
|
+
function editPptCharacterFontSize(input, edit) {
|
|
12627
|
+
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
12628
|
+
try {
|
|
12629
|
+
const { slideId, persistId, headerOffset, runOffset, styleHeaderOffset, start, end, expectedFontSizePoints, fontSizePoints } = edit;
|
|
12630
|
+
const matches = readPptCharacterRuns(input).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
|
|
12631
|
+
const record5 = matches.length === 1 ? matches[0] : void 0;
|
|
12632
|
+
const runs = record5?.status === "decoded" ? record5.runs.filter((run2) => run2.runOffset === runOffset && run2.styleHeaderOffset === styleHeaderOffset && run2.start === start && run2.end === end) : [];
|
|
12633
|
+
const run = runs.length === 1 ? runs[0] : void 0;
|
|
12634
|
+
if (!run || run.directFontSizePoints !== expectedFontSizePoints)
|
|
12635
|
+
return reject2(record5?.diagnostic ?? "Character run identity or expected font size does not match");
|
|
12636
|
+
if (fontSizePoints === run.directFontSizePoints)
|
|
12637
|
+
return { status: "unchanged", bytes: input };
|
|
12638
|
+
if (run.start === run.end)
|
|
12639
|
+
return reject2("Run covers only the implicit paragraph mark");
|
|
12640
|
+
if (run.fontSizeOffset === void 0)
|
|
12641
|
+
return reject2("Font size is inherited; no existing literal slot");
|
|
12642
|
+
if (!Number.isSafeInteger(fontSizePoints) || fontSizePoints < 1 || fontSizePoints > 4e3)
|
|
12643
|
+
return reject2("Literal font size must be an integer from 1 to 4000 points");
|
|
12644
|
+
const textModel = readPptSlideTexts(input), slides = textModel.slides.filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
|
|
12645
|
+
const indexes = slides.length === 1 ? slides[0].texts.flatMap((atom, index) => atom.headerOffset === headerOffset ? [index] : []) : [];
|
|
12646
|
+
if (indexes.length !== 1 || textModel.slides.reduce((count, slide) => count + slide.texts.filter((atom) => atom.headerOffset === headerOffset).length, 0) !== 1)
|
|
12647
|
+
return reject2("Text atom is shared by multiple active slide positions");
|
|
12648
|
+
const shapeSlides = readPptSlideShapes(input).filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
|
|
12649
|
+
const shapes = shapeSlides.length === 1 ? shapeSlides[0].shapes.filter((shape) => shape.textReference === "inline" && shape.textIndexes.includes(indexes[0])) : [];
|
|
12650
|
+
if (shapes.length !== 1 || shapes[0].kind !== "text-box")
|
|
12651
|
+
return reject2("Font-size edits require uniquely linked inline text-box text");
|
|
12652
|
+
if (shapes[0].geometryRefusal)
|
|
12653
|
+
return reject2(`Unsupported text-box formatting context: ${shapes[0].geometryRefusal}`);
|
|
12654
|
+
const originalStream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
12655
|
+
const refusal = textOwnershipRefusal2(input, originalStream, persistId, slides[0].texts[indexes[0]]);
|
|
12656
|
+
if (refusal)
|
|
12657
|
+
return reject2(refusal);
|
|
12658
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]).slice();
|
|
12659
|
+
viewOf3(stream).setInt16(run.fontSizeOffset, fontSizePoints, true);
|
|
12660
|
+
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], stream);
|
|
12661
|
+
if (bytes === input)
|
|
12662
|
+
return reject2("Compound stream cannot be safely replaced");
|
|
12663
|
+
const candidate = readPptCharacterRuns(bytes).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
|
|
12664
|
+
const next = candidate.length === 1 && candidate[0].status === "decoded" ? candidate[0].runs.find((item) => item.runOffset === runOffset && item.styleHeaderOffset === styleHeaderOffset && item.start === start && item.end === end) : void 0;
|
|
12665
|
+
if (!next || next.directFontSizePoints !== fontSizePoints || candidate[0].text !== record5.text)
|
|
12666
|
+
return reject2("Edited character run failed candidate validation");
|
|
12667
|
+
return { status: "edited", bytes };
|
|
12668
|
+
} catch (error) {
|
|
12669
|
+
return reject2(error instanceof Error ? error.message : "Malformed PPT formatting");
|
|
12670
|
+
}
|
|
12671
|
+
}
|
|
12672
|
+
|
|
12673
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt-document.js
|
|
11463
12674
|
var PPT_CAPABILITIES = Object.freeze({
|
|
11464
|
-
read: Object.freeze(["active-slide-ids", "active-outline-and-inline-text", "text-encoding", "active-shape-ids-and-flags", "primitive-shape-kind", "explicit-anchor-geometry", "validated-inline-shape-text", "opaque-streams"]),
|
|
11465
|
-
write: Object.freeze(["existing-text-fixed-utf16-length", "unmirrored-top-level-small-anchor-bounds"]),
|
|
11466
|
-
limitations: Object.freeze(["unresolved-outline-shape-text", "
|
|
12675
|
+
read: Object.freeze(["active-slide-ids", "active-outline-and-inline-text", "text-encoding", "direct-character-run-spans-and-font-size", "active-shape-ids-and-flags", "primitive-shape-kind", "explicit-anchor-geometry", "validated-inline-shape-text", "active-notes-identities-and-inline-text", "opaque-streams"]),
|
|
12676
|
+
write: Object.freeze(["existing-text-fixed-utf16-length", "existing-literal-inline-text-box-font-size", "unmirrored-top-level-small-anchor-bounds", "existing-notes-body-fixed-utf16-length"]),
|
|
12677
|
+
limitations: Object.freeze(["unresolved-outline-shape-text", "inherited-character-formatting", "run-splitting-and-style-insertion", "character-properties-except-existing-font-size", "outline-and-unsupported-shape-font-size-edits", "notes-creation-and-inherited-fields", "variable-length-text", "OOXML-mirrored-text-and-shapes", "group-transforms-and-geometry", "large-anchor-writes", "inherited-rotated-or-flipped-geometry", "animations", "masters", "embedded-objects"])
|
|
11467
12678
|
});
|
|
12679
|
+
var RUN_LOOKUPS = /* @__PURE__ */ new WeakMap();
|
|
12680
|
+
function resolveCharacterRun(record5, original) {
|
|
12681
|
+
let lookup = RUN_LOOKUPS.get(record5);
|
|
12682
|
+
if (!lookup) {
|
|
12683
|
+
lookup = /* @__PURE__ */ new Map();
|
|
12684
|
+
for (const run2 of record5.runs) {
|
|
12685
|
+
const bucket = lookup.get(run2.runOffset);
|
|
12686
|
+
if (bucket)
|
|
12687
|
+
bucket.push(run2);
|
|
12688
|
+
else
|
|
12689
|
+
lookup.set(run2.runOffset, [run2]);
|
|
12690
|
+
}
|
|
12691
|
+
RUN_LOOKUPS.set(record5, lookup);
|
|
12692
|
+
}
|
|
12693
|
+
const matches = record5.status === "decoded" ? lookup.get(original.runOffset) : void 0, run = matches?.[0];
|
|
12694
|
+
if (matches?.length !== 1 || !run || run.styleHeaderOffset !== original.styleHeaderOffset || run.start !== original.start || run.end !== original.end || run.rawCount !== original.rawCount || run.mask !== original.mask || run.fontSizeOffset !== original.fontSizeOffset)
|
|
12695
|
+
throw new UnsupportedOle2EditError("PPT character run identity no longer matches or is ambiguous");
|
|
12696
|
+
return run;
|
|
12697
|
+
}
|
|
12698
|
+
var textRunKey = (node) => `${node.slideId}:${node.persistId}:${node.headerOffset}`;
|
|
11468
12699
|
var PptText = class {
|
|
11469
12700
|
slideId;
|
|
11470
12701
|
persistId;
|
|
@@ -11474,7 +12705,10 @@ var PptText = class {
|
|
|
11474
12705
|
headerOffset;
|
|
11475
12706
|
#text;
|
|
11476
12707
|
#write;
|
|
11477
|
-
|
|
12708
|
+
#readRuns;
|
|
12709
|
+
#writeRun;
|
|
12710
|
+
#runs;
|
|
12711
|
+
constructor(identity, atom, write, readRuns, writeRun) {
|
|
11478
12712
|
this.slideId = identity.slideId;
|
|
11479
12713
|
this.persistId = identity.persistId;
|
|
11480
12714
|
this.textIndex = identity.textIndex;
|
|
@@ -11482,6 +12716,10 @@ var PptText = class {
|
|
|
11482
12716
|
this.headerOffset = atom.headerOffset;
|
|
11483
12717
|
this.#text = atom.text;
|
|
11484
12718
|
this.#write = write;
|
|
12719
|
+
this.#readRuns = readRuns ?? (() => ({ ...identity, headerOffset: atom.headerOffset, text: this.#text, status: "unsupported", diagnostic: "Text has no document formatting owner", runs: [] }));
|
|
12720
|
+
this.#writeRun = writeRun ?? (() => {
|
|
12721
|
+
throw new UnsupportedOle2EditError("Text has no document formatting owner");
|
|
12722
|
+
});
|
|
11485
12723
|
Object.freeze(this);
|
|
11486
12724
|
}
|
|
11487
12725
|
get text() {
|
|
@@ -11493,8 +12731,50 @@ var PptText = class {
|
|
|
11493
12731
|
this.#write(this, value);
|
|
11494
12732
|
this.#text = value;
|
|
11495
12733
|
}
|
|
12734
|
+
get runsStatus() {
|
|
12735
|
+
return this.#readRuns(this).status;
|
|
12736
|
+
}
|
|
12737
|
+
get runsDiagnostic() {
|
|
12738
|
+
return this.#readRuns(this).diagnostic;
|
|
12739
|
+
}
|
|
12740
|
+
/** Direct character exceptions only; inherited/effective formatting is unresolved. */
|
|
11496
12741
|
get runs() {
|
|
11497
|
-
|
|
12742
|
+
if (!this.#runs) {
|
|
12743
|
+
const model2 = this.#readRuns(this);
|
|
12744
|
+
this.#runs = Object.freeze(model2.runs.map((run) => new PptCharacterRun(run, () => {
|
|
12745
|
+
const current = this.#readRuns(this);
|
|
12746
|
+
return { text: current.text, run: resolveCharacterRun(current, run) };
|
|
12747
|
+
}, (value) => this.#writeRun(this, run, value))));
|
|
12748
|
+
}
|
|
12749
|
+
return this.#runs;
|
|
12750
|
+
}
|
|
12751
|
+
};
|
|
12752
|
+
var PptCharacterRun = class {
|
|
12753
|
+
start;
|
|
12754
|
+
end;
|
|
12755
|
+
styleHeaderOffset;
|
|
12756
|
+
runOffset;
|
|
12757
|
+
#read;
|
|
12758
|
+
#write;
|
|
12759
|
+
constructor(record5, read, write) {
|
|
12760
|
+
this.start = record5.start;
|
|
12761
|
+
this.end = record5.end;
|
|
12762
|
+
this.styleHeaderOffset = record5.styleHeaderOffset;
|
|
12763
|
+
this.runOffset = record5.runOffset;
|
|
12764
|
+
this.#read = read;
|
|
12765
|
+
this.#write = write;
|
|
12766
|
+
Object.freeze(this);
|
|
12767
|
+
}
|
|
12768
|
+
get text() {
|
|
12769
|
+
return this.#read().text.slice(this.start, this.end);
|
|
12770
|
+
}
|
|
12771
|
+
get directFontSizePoints() {
|
|
12772
|
+
return this.#read().run.directFontSizePoints;
|
|
12773
|
+
}
|
|
12774
|
+
set directFontSizePoints(value) {
|
|
12775
|
+
if (value !== void 0 && typeof value !== "number")
|
|
12776
|
+
throw new UnsupportedOle2EditError("PPT direct font size must be numeric");
|
|
12777
|
+
this.#write(value);
|
|
11498
12778
|
}
|
|
11499
12779
|
};
|
|
11500
12780
|
var PptSlide = class {
|
|
@@ -11505,15 +12785,71 @@ var PptSlide = class {
|
|
|
11505
12785
|
/** Flat OfficeArt preorder, including group descendants with parentGroupId.
|
|
11506
12786
|
* Canvas patriarchs/background structures remain preserved outside this list. */
|
|
11507
12787
|
shapes;
|
|
11508
|
-
|
|
12788
|
+
/** Existing active notes; undefined when the slide has a null notes reference. */
|
|
12789
|
+
notes;
|
|
12790
|
+
notesStatus;
|
|
12791
|
+
/** A decode refusal is distinct from a null notes reference. Bytes remain opaque. */
|
|
12792
|
+
notesDiagnostic;
|
|
12793
|
+
constructor(slideId, persistId, texts, shapes = [], notes, notesDiagnostic) {
|
|
11509
12794
|
this.slideId = slideId;
|
|
11510
12795
|
this.persistId = persistId;
|
|
11511
12796
|
this.texts = Object.freeze([...texts]);
|
|
11512
12797
|
this.shapes = Object.freeze([...shapes]);
|
|
12798
|
+
this.notes = notes;
|
|
12799
|
+
this.notesDiagnostic = notesDiagnostic;
|
|
12800
|
+
this.notesStatus = notesDiagnostic ? "unsupported" : notes ? "present" : "absent";
|
|
12801
|
+
Object.freeze(this);
|
|
12802
|
+
}
|
|
12803
|
+
};
|
|
12804
|
+
var PptNoteText = class {
|
|
12805
|
+
shapeId;
|
|
12806
|
+
headerOffset;
|
|
12807
|
+
#read;
|
|
12808
|
+
#write;
|
|
12809
|
+
constructor(atom, read, write) {
|
|
12810
|
+
this.shapeId = atom.shapeId;
|
|
12811
|
+
this.headerOffset = atom.headerOffset;
|
|
12812
|
+
this.#read = read;
|
|
12813
|
+
this.#write = write;
|
|
11513
12814
|
Object.freeze(this);
|
|
11514
12815
|
}
|
|
11515
|
-
get
|
|
11516
|
-
|
|
12816
|
+
get text() {
|
|
12817
|
+
return this.#read().text;
|
|
12818
|
+
}
|
|
12819
|
+
set text(value) {
|
|
12820
|
+
if (typeof value !== "string")
|
|
12821
|
+
throw new UnsupportedOle2EditError("Notes replacement must be a string");
|
|
12822
|
+
this.#write(value);
|
|
12823
|
+
}
|
|
12824
|
+
get role() {
|
|
12825
|
+
return this.#read().role;
|
|
12826
|
+
}
|
|
12827
|
+
get placeholderId() {
|
|
12828
|
+
return this.#read().placeholderId;
|
|
12829
|
+
}
|
|
12830
|
+
get encoding() {
|
|
12831
|
+
return this.#read().encoding;
|
|
12832
|
+
}
|
|
12833
|
+
get editRefusal() {
|
|
12834
|
+
return this.#read().editRefusal;
|
|
12835
|
+
}
|
|
12836
|
+
get runs() {
|
|
12837
|
+
throw new UnsupportedOle2EditError("PPT notes rich-text runs are preserved but not decoded");
|
|
12838
|
+
}
|
|
12839
|
+
};
|
|
12840
|
+
var PptNotes = class {
|
|
12841
|
+
slideId;
|
|
12842
|
+
slidePersistId;
|
|
12843
|
+
notesId;
|
|
12844
|
+
persistId;
|
|
12845
|
+
texts;
|
|
12846
|
+
constructor(record5, texts) {
|
|
12847
|
+
this.slideId = record5.slideId;
|
|
12848
|
+
this.slidePersistId = record5.slidePersistId;
|
|
12849
|
+
this.notesId = record5.notesId;
|
|
12850
|
+
this.persistId = record5.persistId;
|
|
12851
|
+
this.texts = Object.freeze([...texts]);
|
|
12852
|
+
Object.freeze(this);
|
|
11517
12853
|
}
|
|
11518
12854
|
};
|
|
11519
12855
|
var PptShape = class {
|
|
@@ -11526,13 +12862,13 @@ var PptShape = class {
|
|
|
11526
12862
|
texts;
|
|
11527
12863
|
#read;
|
|
11528
12864
|
#write;
|
|
11529
|
-
constructor(identity,
|
|
12865
|
+
constructor(identity, record5, texts, read, write) {
|
|
11530
12866
|
this.slideId = identity.slideId;
|
|
11531
12867
|
this.persistId = identity.persistId;
|
|
11532
|
-
this.shapeId =
|
|
11533
|
-
this.headerOffset =
|
|
11534
|
-
this.flags =
|
|
11535
|
-
this.shapeType =
|
|
12868
|
+
this.shapeId = record5.shapeId;
|
|
12869
|
+
this.headerOffset = record5.headerOffset;
|
|
12870
|
+
this.flags = record5.flags;
|
|
12871
|
+
this.shapeType = record5.shapeType;
|
|
11536
12872
|
this.texts = Object.freeze([...texts]);
|
|
11537
12873
|
this.#read = read;
|
|
11538
12874
|
this.#write = write;
|
|
@@ -11622,6 +12958,9 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11622
12958
|
#slides;
|
|
11623
12959
|
#unsupported;
|
|
11624
12960
|
#shapeCache;
|
|
12961
|
+
#notesCache;
|
|
12962
|
+
#runsCache;
|
|
12963
|
+
#validatedTextRuns = /* @__PURE__ */ new WeakMap();
|
|
11625
12964
|
get slides() {
|
|
11626
12965
|
return this.#slides;
|
|
11627
12966
|
}
|
|
@@ -11632,14 +12971,102 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11632
12971
|
super(input);
|
|
11633
12972
|
const shapeModel = readPptSlideShapes(this.getBytes());
|
|
11634
12973
|
const model2 = readPptSlideTexts(this.getBytes());
|
|
12974
|
+
let notesModel = [], notesDiagnostic;
|
|
12975
|
+
try {
|
|
12976
|
+
notesModel = readPptSlideNotes(this.getBytes());
|
|
12977
|
+
} catch (error) {
|
|
12978
|
+
notesDiagnostic = error instanceof Error ? error.message : "Notes decoding unsupported";
|
|
12979
|
+
}
|
|
11635
12980
|
this.#shapeCache = { revision: this.revision, slides: shapeModel };
|
|
11636
|
-
this.#
|
|
12981
|
+
this.#notesCache = { revision: this.revision, notes: notesModel };
|
|
12982
|
+
this.#unsupported = Object.freeze(["formatting", "group-transforms", "pictures-content", "masters", "notes-creation-and-inherited-fields", "animations", "embedded-objects", "unresolved-outline-shape-text", "variable-length-text", ...notesDiagnostic ? ["notes-decoding"] : []]);
|
|
11637
12983
|
this.#slides = Object.freeze(model2.slides.map((slide, index) => {
|
|
11638
|
-
const texts = slide.texts.map((atom, textIndex) => new PptText({ slideId: slide.slideId, persistId: slide.persistId, textIndex }, atom, (node, value) => this.#edit(node, value)));
|
|
11639
|
-
const shapes = shapeModel[index].shapes.map((
|
|
11640
|
-
|
|
12984
|
+
const texts = slide.texts.map((atom, textIndex) => new PptText({ slideId: slide.slideId, persistId: slide.persistId, textIndex }, atom, (node, value) => this.#edit(node, value), (node) => this.#readTextRuns(node), (node, run, value) => this.#editRun(node, run, value)));
|
|
12985
|
+
const shapes = shapeModel[index].shapes.map((record6) => new PptShape(slide, record6, record6.textIndexes.map((textIndex) => texts[textIndex]), () => this.#readShape(slide.slideId, slide.persistId, record6), (value) => this.#editShape(slide.slideId, slide.persistId, record6, value)));
|
|
12986
|
+
const record5 = notesModel.find((note) => note.slideId === slide.slideId && note.slidePersistId === slide.persistId);
|
|
12987
|
+
const notes = record5 && new PptNotes(record5, record5.texts.map((atom) => new PptNoteText(atom, () => this.#readNote(record5, atom), (value) => this.#editNote(record5, atom, value))));
|
|
12988
|
+
return new PptSlide(slide.slideId, slide.persistId, texts, shapes, notes, notesDiagnostic);
|
|
11641
12989
|
}));
|
|
11642
12990
|
}
|
|
12991
|
+
#readTextRuns(node) {
|
|
12992
|
+
if (!this.#runsCache || this.#runsCache.revision !== this.revision) {
|
|
12993
|
+
const revision = this.revision;
|
|
12994
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
12995
|
+
for (const record6 of readPptCharacterRuns(this.getBytes())) {
|
|
12996
|
+
const key2 = textRunKey(record6), bucket = byIdentity.get(key2);
|
|
12997
|
+
if (bucket)
|
|
12998
|
+
bucket.push(record6);
|
|
12999
|
+
else
|
|
13000
|
+
byIdentity.set(key2, [record6]);
|
|
13001
|
+
}
|
|
13002
|
+
if (this.revision !== revision)
|
|
13003
|
+
throw new UnsupportedOle2EditError("Document changed during character formatting read");
|
|
13004
|
+
this.#runsCache = { revision, byIdentity };
|
|
13005
|
+
}
|
|
13006
|
+
const matches = this.#runsCache.byIdentity.get(textRunKey(node)), record5 = matches?.[0];
|
|
13007
|
+
if (matches?.length !== 1 || !record5)
|
|
13008
|
+
throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
|
|
13009
|
+
if (this.#validatedTextRuns.get(node) !== record5) {
|
|
13010
|
+
if (record5.text !== node.text)
|
|
13011
|
+
throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
|
|
13012
|
+
this.#validatedTextRuns.set(node, record5);
|
|
13013
|
+
}
|
|
13014
|
+
return record5;
|
|
13015
|
+
}
|
|
13016
|
+
#editRun(node, original, fontSizePoints) {
|
|
13017
|
+
const revision = this.revision, current = this.#readTextRuns(node);
|
|
13018
|
+
const run = resolveCharacterRun(current, original);
|
|
13019
|
+
const result = editPptCharacterFontSize(this.getBytes(), {
|
|
13020
|
+
slideId: node.slideId,
|
|
13021
|
+
persistId: node.persistId,
|
|
13022
|
+
headerOffset: node.headerOffset,
|
|
13023
|
+
runOffset: run.runOffset,
|
|
13024
|
+
styleHeaderOffset: run.styleHeaderOffset,
|
|
13025
|
+
start: run.start,
|
|
13026
|
+
end: run.end,
|
|
13027
|
+
expectedFontSizePoints: run.directFontSizePoints,
|
|
13028
|
+
fontSizePoints
|
|
13029
|
+
});
|
|
13030
|
+
if (this.revision !== revision)
|
|
13031
|
+
throw new UnsupportedOle2EditError("Document changed during character formatting edit");
|
|
13032
|
+
if (result.status === "unsupported")
|
|
13033
|
+
throw new UnsupportedOle2EditError(result.reason);
|
|
13034
|
+
if (result.status === "edited")
|
|
13035
|
+
this.commitBytes(result.bytes);
|
|
13036
|
+
}
|
|
13037
|
+
#readNote(original, atom) {
|
|
13038
|
+
if (this.#notesCache.revision !== this.revision) {
|
|
13039
|
+
try {
|
|
13040
|
+
this.#notesCache = { revision: this.revision, notes: readPptSlideNotes(this.getBytes()) };
|
|
13041
|
+
} catch (error) {
|
|
13042
|
+
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "Notes decoding unsupported");
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
13045
|
+
const notes = this.#notesCache.notes.filter((note) => note.slideId === original.slideId && note.slidePersistId === original.slidePersistId && note.notesId === original.notesId && note.persistId === original.persistId && note.headerOffset === original.headerOffset);
|
|
13046
|
+
const matches = notes.length === 1 ? notes[0].texts.filter((text) => text.shapeId === atom.shapeId && text.headerOffset === atom.headerOffset && text.shapeHeaderOffset === atom.shapeHeaderOffset && text.encoding === atom.encoding && text.placeholderId === atom.placeholderId) : [];
|
|
13047
|
+
if (matches.length !== 1)
|
|
13048
|
+
throw new UnsupportedOle2EditError("PPT notes identity no longer matches or is ambiguous");
|
|
13049
|
+
return matches[0];
|
|
13050
|
+
}
|
|
13051
|
+
#editNote(note, atom, text) {
|
|
13052
|
+
const revision = this.revision, current = this.#readNote(note, atom);
|
|
13053
|
+
const result = editPptNotesText(this.getBytes(), {
|
|
13054
|
+
slideId: note.slideId,
|
|
13055
|
+
slidePersistId: note.slidePersistId,
|
|
13056
|
+
notesId: note.notesId,
|
|
13057
|
+
persistId: note.persistId,
|
|
13058
|
+
shapeId: atom.shapeId,
|
|
13059
|
+
expectedHeaderOffset: atom.headerOffset,
|
|
13060
|
+
expectedText: current.text,
|
|
13061
|
+
text
|
|
13062
|
+
});
|
|
13063
|
+
if (this.revision !== revision)
|
|
13064
|
+
throw new UnsupportedOle2EditError("Document changed during notes edit");
|
|
13065
|
+
if (result.status === "unsupported")
|
|
13066
|
+
throw new UnsupportedOle2EditError(result.reason);
|
|
13067
|
+
if (result.status === "edited")
|
|
13068
|
+
this.commitBytes(result.bytes);
|
|
13069
|
+
}
|
|
11643
13070
|
#readShape(slideId, persistId, original) {
|
|
11644
13071
|
if (this.#shapeCache.revision !== this.revision)
|
|
11645
13072
|
this.#shapeCache = { revision: this.revision, slides: readPptSlideShapes(this.getBytes()) };
|
|
@@ -11679,7 +13106,7 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11679
13106
|
}
|
|
11680
13107
|
};
|
|
11681
13108
|
|
|
11682
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13109
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression.js
|
|
11683
13110
|
function decodeVsdBlock(input, limit3 = 32 * 1024 * 1024) {
|
|
11684
13111
|
if (!Number.isSafeInteger(limit3) || limit3 < 0 || limit3 > 64 * 1024 * 1024)
|
|
11685
13112
|
throw new Error("Invalid VSD decompression limit");
|
|
@@ -11726,7 +13153,7 @@ function encodeVsdBlock(input) {
|
|
|
11726
13153
|
return output;
|
|
11727
13154
|
}
|
|
11728
13155
|
|
|
11729
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13156
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-reader.js
|
|
11730
13157
|
var VsdError = class extends Error {
|
|
11731
13158
|
reason;
|
|
11732
13159
|
constructor(reason) {
|
|
@@ -11774,6 +13201,8 @@ function readVsdDrawing(input) {
|
|
|
11774
13201
|
if (size < 54 || size > stream.length)
|
|
11775
13202
|
throw new VsdError("document-size");
|
|
11776
13203
|
const data = { stream, streamPath, version: 11, pages: [], blocks: [], writable: true };
|
|
13204
|
+
const shapeOrders = /* @__PURE__ */ new Map(), sheetIds = /* @__PURE__ */ new Map();
|
|
13205
|
+
let orderElements = 0;
|
|
11777
13206
|
const active = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set();
|
|
11778
13207
|
let decodedBudget = MAX_BYTES, records = 0;
|
|
11779
13208
|
function visit(ownerBytes, pointerOffset, parent, page, shape, depth = 0, id = 0) {
|
|
@@ -11847,7 +13276,7 @@ function readVsdDrawing(input) {
|
|
|
11847
13276
|
for (const idx of indexes)
|
|
11848
13277
|
visit(bytes, table + 12 + idx * 18, block, page, shape, depth + 1, idx);
|
|
11849
13278
|
} else if (page && [8, 12, 13].includes(mode)) {
|
|
11850
|
-
const stack = [];
|
|
13279
|
+
const stack = [], orderStack = [];
|
|
11851
13280
|
let cursor = 0;
|
|
11852
13281
|
while (cursor < bytes.length) {
|
|
11853
13282
|
while (cursor < bytes.length && bytes[cursor] === 0)
|
|
@@ -11875,6 +13304,57 @@ function readVsdDrawing(input) {
|
|
|
11875
13304
|
let current = stack[stack.length - 1]?.shape ?? shape;
|
|
11876
13305
|
if (current && [70, 74].includes(chunk))
|
|
11877
13306
|
throw new VsdError("unsupported-sheet-owner");
|
|
13307
|
+
while (orderStack.length && level <= orderStack[orderStack.length - 1].level)
|
|
13308
|
+
orderStack.pop();
|
|
13309
|
+
if (page && chunk === 70) {
|
|
13310
|
+
if (sheetIds.has(page))
|
|
13311
|
+
page.shapeOrderIssue = "ambiguous-page-owner";
|
|
13312
|
+
sheetIds.set(page, length2 >= 54 && level === 1 && [10, 18, 26].every((o) => cv.getUint32(start + o, true) === 4294967295) ? chunkId : void 0);
|
|
13313
|
+
}
|
|
13314
|
+
if (page && chunk === 101) {
|
|
13315
|
+
const orders = shapeOrders.get(page) ?? /* @__PURE__ */ new Map();
|
|
13316
|
+
shapeOrders.set(page, orders);
|
|
13317
|
+
const order = { owner: current, elements: [], ids: /* @__PURE__ */ new Map(), level };
|
|
13318
|
+
if (orders.has(current))
|
|
13319
|
+
order.issue = "duplicate-shape-order";
|
|
13320
|
+
orders.set(current, order);
|
|
13321
|
+
orderStack.push(order);
|
|
13322
|
+
const end = start + length2 + trailer - 4;
|
|
13323
|
+
if (end - start < 8)
|
|
13324
|
+
order.issue = "shape-order-bounds";
|
|
13325
|
+
else {
|
|
13326
|
+
const subHeader = cv.getUint32(start, true), childrenBytes = cv.getUint32(start + 4, true), children4 = start + 8 + subHeader;
|
|
13327
|
+
if (children4 > end || childrenBytes > end - children4 || childrenBytes % 4)
|
|
13328
|
+
order.issue = "shape-order-bounds";
|
|
13329
|
+
else {
|
|
13330
|
+
const count = childrenBytes / 4;
|
|
13331
|
+
orderElements += count;
|
|
13332
|
+
if (orderElements > 1e5)
|
|
13333
|
+
throw new VsdError("shape-order-budget");
|
|
13334
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
13335
|
+
for (let i = 0; i < count; i++) {
|
|
13336
|
+
const id2 = cv.getUint32(children4 + i * 4, true);
|
|
13337
|
+
if (seen2.has(id2))
|
|
13338
|
+
order.issue = "duplicate-order-element";
|
|
13339
|
+
seen2.add(id2);
|
|
13340
|
+
order.elements.push(id2);
|
|
13341
|
+
}
|
|
13342
|
+
}
|
|
13343
|
+
}
|
|
13344
|
+
}
|
|
13345
|
+
if (page && chunk === 131) {
|
|
13346
|
+
const order = orderStack[orderStack.length - 1];
|
|
13347
|
+
if (!order)
|
|
13348
|
+
page.shapeOrderIssue = "orphan-shape-id";
|
|
13349
|
+
else if (level !== order.level + 1)
|
|
13350
|
+
order.issue = "shape-id-owner-level";
|
|
13351
|
+
else if (length2 < 4)
|
|
13352
|
+
order.issue = "shape-id-bounds";
|
|
13353
|
+
else if (order.ids.has(chunkId))
|
|
13354
|
+
order.issue = "duplicate-shape-id-map";
|
|
13355
|
+
else
|
|
13356
|
+
order.ids.set(chunkId, cv.getUint32(start, true));
|
|
13357
|
+
}
|
|
11878
13358
|
if (page && [71, 72, 78].includes(chunk)) {
|
|
11879
13359
|
current = { id: chunkId, kind: chunk === 71 ? "group" : chunk === 78 ? "foreign" : "shape", coordinateSpace: "shape-local", unsupportedGeometry: false, unsafeTransform: false, geometry: [], unsafeText: false };
|
|
11880
13360
|
if (length2 < 54)
|
|
@@ -11949,42 +13429,304 @@ function readVsdDrawing(input) {
|
|
|
11949
13429
|
ids.add(shape.id);
|
|
11950
13430
|
}
|
|
11951
13431
|
}
|
|
13432
|
+
for (const page of data.pages) {
|
|
13433
|
+
const shapes = new Map(page.shapes.map((s) => [s.id, s])), orders = shapeOrders.get(page), sheet = sheetIds.get(page);
|
|
13434
|
+
if (sheet !== void 0 && shapes.has(sheet))
|
|
13435
|
+
page.shapeOrderIssue = "ambiguous-page-owner";
|
|
13436
|
+
const rootParent = (s) => s.parentId === 4294967295 || sheet !== void 0 && s.parentId === sheet;
|
|
13437
|
+
const rootIds = /* @__PURE__ */ new Set(), childrenByParent = /* @__PURE__ */ new Map(), emptyIds = /* @__PURE__ */ new Set();
|
|
13438
|
+
for (const shape of page.shapes) {
|
|
13439
|
+
if (rootParent(shape))
|
|
13440
|
+
rootIds.add(shape.id);
|
|
13441
|
+
if (shape.parentId !== void 0) {
|
|
13442
|
+
const children4 = childrenByParent.get(shape.parentId) ?? /* @__PURE__ */ new Set();
|
|
13443
|
+
children4.add(shape.id);
|
|
13444
|
+
childrenByParent.set(shape.parentId, children4);
|
|
13445
|
+
}
|
|
13446
|
+
}
|
|
13447
|
+
const resolve = (owner) => {
|
|
13448
|
+
const order = orders?.get(owner);
|
|
13449
|
+
let issue2 = order?.issue;
|
|
13450
|
+
if (!order)
|
|
13451
|
+
issue2 = "missing-shape-order";
|
|
13452
|
+
if (owner && owner.kind !== "group" && order?.elements.length)
|
|
13453
|
+
issue2 = "unsupported-child-owner";
|
|
13454
|
+
const result = [], seen2 = /* @__PURE__ */ new Set();
|
|
13455
|
+
if (order && !issue2) {
|
|
13456
|
+
for (const element of order.elements) {
|
|
13457
|
+
const id = order.ids.get(element), shape = id === void 0 ? void 0 : shapes.get(id);
|
|
13458
|
+
if (!shape) {
|
|
13459
|
+
issue2 = "unresolved-shape-id";
|
|
13460
|
+
break;
|
|
13461
|
+
}
|
|
13462
|
+
if (seen2.has(id)) {
|
|
13463
|
+
issue2 = "duplicate-shape-reference";
|
|
13464
|
+
break;
|
|
13465
|
+
}
|
|
13466
|
+
seen2.add(id);
|
|
13467
|
+
if (owner ? shape.parentId !== owner.id : !rootParent(shape)) {
|
|
13468
|
+
issue2 = "contradictory-shape-owner";
|
|
13469
|
+
break;
|
|
13470
|
+
}
|
|
13471
|
+
result.push(id);
|
|
13472
|
+
}
|
|
13473
|
+
if (!issue2) {
|
|
13474
|
+
const expected = owner ? childrenByParent.get(owner.id) ?? emptyIds : rootIds;
|
|
13475
|
+
if (expected.size !== result.length || [...expected].some((id) => !seen2.has(id)))
|
|
13476
|
+
issue2 = "incomplete-shape-order";
|
|
13477
|
+
}
|
|
13478
|
+
}
|
|
13479
|
+
if (issue2) {
|
|
13480
|
+
if (owner)
|
|
13481
|
+
owner.shapeOrderIssue = issue2;
|
|
13482
|
+
else
|
|
13483
|
+
page.shapeOrderIssue ??= issue2;
|
|
13484
|
+
return void 0;
|
|
13485
|
+
}
|
|
13486
|
+
return result;
|
|
13487
|
+
};
|
|
13488
|
+
const root = resolve(void 0);
|
|
13489
|
+
for (const shape of page.shapes)
|
|
13490
|
+
if (shape.kind === "group" || orders?.has(shape))
|
|
13491
|
+
shape.childShapeIds = resolve(shape);
|
|
13492
|
+
let issue = page.shapeOrderIssue;
|
|
13493
|
+
const queue = (root ?? []).map((id) => ({ id, depth: 0 })), visited = /* @__PURE__ */ new Set();
|
|
13494
|
+
if (root && !issue) {
|
|
13495
|
+
for (let i = 0; i < queue.length; i++) {
|
|
13496
|
+
const item = queue[i];
|
|
13497
|
+
if (item.depth > 64) {
|
|
13498
|
+
issue = "shape-order-depth";
|
|
13499
|
+
break;
|
|
13500
|
+
}
|
|
13501
|
+
if (visited.has(item.id)) {
|
|
13502
|
+
issue = "cyclic-shape-order";
|
|
13503
|
+
break;
|
|
13504
|
+
}
|
|
13505
|
+
visited.add(item.id);
|
|
13506
|
+
const shape = shapes.get(item.id);
|
|
13507
|
+
if (shape.shapeOrderIssue) {
|
|
13508
|
+
issue = "unresolved-child-order";
|
|
13509
|
+
break;
|
|
13510
|
+
}
|
|
13511
|
+
for (const id of shape.childShapeIds ?? [])
|
|
13512
|
+
queue.push({ id, depth: item.depth + 1 });
|
|
13513
|
+
}
|
|
13514
|
+
if (!issue && visited.size !== page.shapes.length)
|
|
13515
|
+
issue = "unreachable-shape-order";
|
|
13516
|
+
}
|
|
13517
|
+
if (issue) {
|
|
13518
|
+
page.shapeOrderIssue = issue;
|
|
13519
|
+
for (const shape of page.shapes)
|
|
13520
|
+
if (shape.childShapeIds) {
|
|
13521
|
+
shape.childShapeIds = void 0;
|
|
13522
|
+
shape.shapeOrderIssue ??= "unresolved-page-order";
|
|
13523
|
+
}
|
|
13524
|
+
} else
|
|
13525
|
+
page.topLevelShapeIds = root;
|
|
13526
|
+
}
|
|
11952
13527
|
return data;
|
|
11953
13528
|
}
|
|
11954
13529
|
|
|
11955
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11956
|
-
|
|
13530
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression-fit.js
|
|
13531
|
+
var VSD_COMPRESSION_FIT_MAX_BYTES = 8 * 1024 * 1024;
|
|
13532
|
+
var MAX_INPUT = VSD_COMPRESSION_FIT_MAX_BYTES;
|
|
13533
|
+
var MAX_GAP = 4096;
|
|
13534
|
+
var MAX_PROBES = 16 * 1024 * 1024;
|
|
13535
|
+
var VsdCompressionFitError = class extends Error {
|
|
13536
|
+
reason;
|
|
13537
|
+
constructor(reason) {
|
|
13538
|
+
super(`VSD compression ${reason}`);
|
|
13539
|
+
this.reason = reason;
|
|
13540
|
+
this.name = "VsdCompressionFitError";
|
|
13541
|
+
}
|
|
13542
|
+
};
|
|
13543
|
+
function encodeVsdBlockToSize(input, capacity) {
|
|
13544
|
+
if (!(input instanceof Uint8Array) || input.length > MAX_INPUT || !Number.isSafeInteger(capacity) || capacity < 0 || capacity > MAX_INPUT)
|
|
13545
|
+
throw new VsdCompressionFitError("input-budget");
|
|
13546
|
+
const output = new Uint8Array(capacity), heads = new Int32Array(65536).fill(-1), previous = new Int32Array(input.length).fill(-1);
|
|
13547
|
+
let cursor = 0, flagOffset = -1, bit = 8, tokens = 0, probes = 0;
|
|
13548
|
+
const tailSize = 4096, positions = new Int32Array(tailSize), lengths = new Uint8Array(tailSize), sources = new Int32Array(tailSize), starts = new Int32Array(tailSize);
|
|
13549
|
+
function emit(literal2, a, b) {
|
|
13550
|
+
const size = (bit === 8 ? 1 : 0) + (literal2 ? 1 : 2);
|
|
13551
|
+
if (size > capacity - cursor)
|
|
13552
|
+
return false;
|
|
13553
|
+
if (bit === 8) {
|
|
13554
|
+
flagOffset = cursor++;
|
|
13555
|
+
output[flagOffset] = 0;
|
|
13556
|
+
bit = 0;
|
|
13557
|
+
}
|
|
13558
|
+
if (literal2)
|
|
13559
|
+
output[flagOffset] |= 1 << bit;
|
|
13560
|
+
output[cursor++] = a;
|
|
13561
|
+
if (!literal2)
|
|
13562
|
+
output[cursor++] = b;
|
|
13563
|
+
bit++;
|
|
13564
|
+
tokens++;
|
|
13565
|
+
return true;
|
|
13566
|
+
}
|
|
13567
|
+
const hash2 = (p) => (input[p] * 251 + input[p + 1]) * 251 + input[p + 2] & 65535;
|
|
13568
|
+
function remember(p) {
|
|
13569
|
+
if (p + 2 < input.length) {
|
|
13570
|
+
const h = hash2(p);
|
|
13571
|
+
previous[p] = heads[h];
|
|
13572
|
+
heads[h] = p;
|
|
13573
|
+
}
|
|
13574
|
+
}
|
|
13575
|
+
function match(position) {
|
|
13576
|
+
let length = 0, source = -1;
|
|
13577
|
+
if (position < 4060) {
|
|
13578
|
+
while (length < 18 && position + length < input.length && input[position + length] === 0)
|
|
13579
|
+
length++;
|
|
13580
|
+
if (length >= 3)
|
|
13581
|
+
source = -18;
|
|
13582
|
+
else
|
|
13583
|
+
length = 0;
|
|
13584
|
+
}
|
|
13585
|
+
if (position + 2 < input.length) {
|
|
13586
|
+
let candidate = heads[hash2(position)], attempts = 0;
|
|
13587
|
+
while (candidate >= Math.max(0, position - 4096) && candidate < position && attempts++ < 512) {
|
|
13588
|
+
let n = 0;
|
|
13589
|
+
while (n < 18 && position + n < input.length) {
|
|
13590
|
+
if (++probes > MAX_PROBES)
|
|
13591
|
+
throw new VsdCompressionFitError("work-limit");
|
|
13592
|
+
if (input[candidate + n] !== input[position + n])
|
|
13593
|
+
break;
|
|
13594
|
+
n++;
|
|
13595
|
+
}
|
|
13596
|
+
if (n >= 3 && n > length) {
|
|
13597
|
+
length = n;
|
|
13598
|
+
source = candidate;
|
|
13599
|
+
if (n === 18)
|
|
13600
|
+
break;
|
|
13601
|
+
}
|
|
13602
|
+
candidate = previous[candidate];
|
|
13603
|
+
}
|
|
13604
|
+
}
|
|
13605
|
+
return { length, source };
|
|
13606
|
+
}
|
|
13607
|
+
for (let position = 0; position < input.length; ) {
|
|
13608
|
+
let { length, source } = match(position);
|
|
13609
|
+
if (length >= 3 && length < 18 && position + 1 < input.length && match(position + 1).length > length + 1)
|
|
13610
|
+
length = 0;
|
|
13611
|
+
const slot = tokens % tailSize;
|
|
13612
|
+
positions[slot] = position;
|
|
13613
|
+
lengths[slot] = length >= 3 ? length : 1;
|
|
13614
|
+
sources[slot] = source;
|
|
13615
|
+
starts[slot] = cursor;
|
|
13616
|
+
if (length >= 3) {
|
|
13617
|
+
const address = source - 18 & 4095;
|
|
13618
|
+
if (!emit(false, address & 255, address >> 4 & 240 | length - 3))
|
|
13619
|
+
return void 0;
|
|
13620
|
+
} else {
|
|
13621
|
+
length = 1;
|
|
13622
|
+
if (!emit(true, input[position]))
|
|
13623
|
+
return void 0;
|
|
13624
|
+
}
|
|
13625
|
+
for (let i = 0; i < length; i++)
|
|
13626
|
+
remember(position + i);
|
|
13627
|
+
position += length;
|
|
13628
|
+
}
|
|
13629
|
+
const remaining = capacity - cursor;
|
|
13630
|
+
if (remaining) {
|
|
13631
|
+
if (remaining > MAX_GAP || !tokens)
|
|
13632
|
+
return void 0;
|
|
13633
|
+
const baseTokens = tokens, tailStart = Math.ceil(Math.max(0, tokens - tailSize) / 8) * 8;
|
|
13634
|
+
let states2 = [{ extra: 0, count: 0, cost: 0, index: -1, k: 0 }], answer, planningWork = 0, nodes = 0, references = 0;
|
|
13635
|
+
for (let index = tokens - 1; index >= tailStart && !answer; index--) {
|
|
13636
|
+
const length = lengths[index % tailSize];
|
|
13637
|
+
if (length < 3)
|
|
13638
|
+
continue;
|
|
13639
|
+
if (++references > 512)
|
|
13640
|
+
break;
|
|
13641
|
+
const next = /* @__PURE__ */ new Map();
|
|
13642
|
+
for (const state of states2)
|
|
13643
|
+
next.set(state.cost * 8 + (baseTokens + state.count) % 8, state);
|
|
13644
|
+
for (const state of states2) {
|
|
13645
|
+
for (let k = 1; k <= length; k++) {
|
|
13646
|
+
if (++planningWork > 1024 * 1024 || nodes >= 65536)
|
|
13647
|
+
throw new VsdCompressionFitError("work-limit");
|
|
13648
|
+
if (k > length - 3 && k !== length)
|
|
13649
|
+
continue;
|
|
13650
|
+
const count = state.count + (k === length ? k - 1 : k), extra = state.extra + (k === length ? k - 2 : k), cost = extra + Math.ceil((baseTokens + count) / 8) - Math.ceil(baseTokens / 8);
|
|
13651
|
+
if (cost > remaining)
|
|
13652
|
+
continue;
|
|
13653
|
+
const key2 = cost * 8 + (baseTokens + count) % 8;
|
|
13654
|
+
if (next.has(key2))
|
|
13655
|
+
continue;
|
|
13656
|
+
const node = { extra, count, cost, parent: state, index, k };
|
|
13657
|
+
nodes++;
|
|
13658
|
+
if (cost === remaining) {
|
|
13659
|
+
answer = node;
|
|
13660
|
+
break;
|
|
13661
|
+
}
|
|
13662
|
+
next.set(key2, node);
|
|
13663
|
+
}
|
|
13664
|
+
if (answer)
|
|
13665
|
+
break;
|
|
13666
|
+
}
|
|
13667
|
+
states2 = [...next.values()].sort((a, b) => b.cost - a.cost).slice(0, 63);
|
|
13668
|
+
if (!states2.some((p) => p.cost === 0))
|
|
13669
|
+
states2.push({ extra: 0, count: 0, cost: 0, index: -1, k: 0 });
|
|
13670
|
+
}
|
|
13671
|
+
if (!answer)
|
|
13672
|
+
return void 0;
|
|
13673
|
+
const changes = /* @__PURE__ */ new Map();
|
|
13674
|
+
for (let node = answer; node?.parent; node = node.parent)
|
|
13675
|
+
changes.set(node.index, node.k);
|
|
13676
|
+
cursor = starts[tailStart % tailSize];
|
|
13677
|
+
bit = 8;
|
|
13678
|
+
flagOffset = -1;
|
|
13679
|
+
tokens = tailStart;
|
|
13680
|
+
for (let index = tailStart; index < baseTokens; index++) {
|
|
13681
|
+
const slot = index % tailSize, position = positions[slot], length = lengths[slot], k = changes.get(index) ?? 0;
|
|
13682
|
+
for (let j = 0; j < k; j++)
|
|
13683
|
+
if (!emit(true, input[position + j]))
|
|
13684
|
+
return void 0;
|
|
13685
|
+
if (k < length) {
|
|
13686
|
+
if (length === 1) {
|
|
13687
|
+
if (!emit(true, input[position]))
|
|
13688
|
+
return void 0;
|
|
13689
|
+
} else {
|
|
13690
|
+
const address = sources[slot] + k - 18 & 4095;
|
|
13691
|
+
if (!emit(false, address & 255, address >> 4 & 240 | length - k - 3))
|
|
13692
|
+
return void 0;
|
|
13693
|
+
}
|
|
13694
|
+
}
|
|
13695
|
+
}
|
|
13696
|
+
}
|
|
13697
|
+
if (cursor !== capacity)
|
|
13698
|
+
return void 0;
|
|
13699
|
+
const decoded = decodeVsdBlock(output, input.length);
|
|
13700
|
+
if (decoded.length !== input.length || !input.every((v, i) => decoded[i] === v))
|
|
13701
|
+
throw new VsdCompressionFitError("verification");
|
|
13702
|
+
return { bytes: output, paddingBytes: 0 };
|
|
13703
|
+
}
|
|
13704
|
+
|
|
13705
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-writer.js
|
|
13706
|
+
function replaceRecord(input, drawing, record5, replacement) {
|
|
11957
13707
|
if (!drawing.writable)
|
|
11958
13708
|
throw new VsdError("shared-or-overlapping-allocation");
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
const
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
block = block.parent;
|
|
11978
|
-
decoded = owner;
|
|
11979
|
-
}
|
|
11980
|
-
const stream = new Uint8Array(size);
|
|
11981
|
-
stream.set(header);
|
|
11982
|
-
let offset = header.length;
|
|
11983
|
-
for (const bytes of appended) {
|
|
11984
|
-
stream.set(bytes, offset);
|
|
11985
|
-
offset += bytes.length;
|
|
13709
|
+
if (record5.block.format & 2 && (record5.block.bytes.length > VSD_COMPRESSION_FIT_MAX_BYTES || record5.block.length > VSD_COMPRESSION_FIT_MAX_BYTES))
|
|
13710
|
+
throw new VsdError("compression-input-budget");
|
|
13711
|
+
const block = record5.block, decoded = block.bytes.slice();
|
|
13712
|
+
decoded.set(replacement, record5.offset);
|
|
13713
|
+
let stored = block.format & 2 ? encodeVsdBlock(decoded) : decoded;
|
|
13714
|
+
if (stored.length !== block.length) {
|
|
13715
|
+
if (!(block.format & 2) || ![8, 12, 13].includes(block.format >>> 4))
|
|
13716
|
+
throw new VsdError("unsafe-block-relocation");
|
|
13717
|
+
try {
|
|
13718
|
+
const fit = encodeVsdBlockToSize(decoded, block.length);
|
|
13719
|
+
if (!fit)
|
|
13720
|
+
throw new VsdError("unsafe-block-relocation");
|
|
13721
|
+
stored = fit.bytes;
|
|
13722
|
+
} catch (error) {
|
|
13723
|
+
if (error instanceof VsdCompressionFitError)
|
|
13724
|
+
throw new VsdError(`compression-${error.reason}`);
|
|
13725
|
+
throw error;
|
|
13726
|
+
}
|
|
11986
13727
|
}
|
|
11987
|
-
|
|
13728
|
+
const stream = drawing.stream.slice();
|
|
13729
|
+
stream.set(stored, block.offset);
|
|
11988
13730
|
const result = resizeCompoundFileStream(input, drawing.streamPath, stream);
|
|
11989
13731
|
if (!result.ok)
|
|
11990
13732
|
throw new VsdError(`compound-resize-${result.reason}`);
|
|
@@ -12044,7 +13786,7 @@ function replaceVsdShapeTransform(input, pageId, shapeId, transform2) {
|
|
|
12044
13786
|
return candidate;
|
|
12045
13787
|
}
|
|
12046
13788
|
|
|
12047
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13789
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-document.js
|
|
12048
13790
|
var VsdShape = class {
|
|
12049
13791
|
id;
|
|
12050
13792
|
#read;
|
|
@@ -12091,6 +13833,14 @@ var VsdShape = class {
|
|
|
12091
13833
|
set transform(value) {
|
|
12092
13834
|
this.#editTransform(value);
|
|
12093
13835
|
}
|
|
13836
|
+
/** Validated drawing order of this owner's explicit children; undefined when unresolved. */
|
|
13837
|
+
get childShapeIds() {
|
|
13838
|
+
const ids = this.#read().childShapeIds;
|
|
13839
|
+
return ids && Object.freeze([...ids]);
|
|
13840
|
+
}
|
|
13841
|
+
get shapeOrderIssue() {
|
|
13842
|
+
return this.#read().shapeOrderIssue;
|
|
13843
|
+
}
|
|
12094
13844
|
get geometry() {
|
|
12095
13845
|
return Object.freeze(this.#read().geometry.map((row) => Object.freeze({ ...row })));
|
|
12096
13846
|
}
|
|
@@ -12105,6 +13855,14 @@ var VsdPage = class {
|
|
|
12105
13855
|
this.shapes = Object.freeze(shapes);
|
|
12106
13856
|
Object.freeze(this);
|
|
12107
13857
|
}
|
|
13858
|
+
/** Validated top-level drawing order. The existing shapes array remains flat. */
|
|
13859
|
+
get topLevelShapeIds() {
|
|
13860
|
+
const ids = this.#read().topLevelShapeIds;
|
|
13861
|
+
return ids && Object.freeze([...ids]);
|
|
13862
|
+
}
|
|
13863
|
+
get shapeOrderIssue() {
|
|
13864
|
+
return this.#read().shapeOrderIssue;
|
|
13865
|
+
}
|
|
12108
13866
|
get background() {
|
|
12109
13867
|
return this.#read().background;
|
|
12110
13868
|
}
|
|
@@ -12119,7 +13877,7 @@ var VsdPage = class {
|
|
|
12119
13877
|
return this.#read().scale;
|
|
12120
13878
|
}
|
|
12121
13879
|
};
|
|
12122
|
-
var CAPABILITIES = Object.freeze({ read: Object.freeze(["v11-pages", "explicit-shape-transform", "utf16-shape-text", "move-to-line-to"]), write: Object.freeze(["equal-length-shape-text", "literal-shape-transform"]), limitations: Object.freeze(["Version 11 only; stored values without master/style/formula evaluation.", "No added/deleted shapes, text length changes or text field edits.", "Shared/overlapping VSD blocks cannot be edited;
|
|
13880
|
+
var CAPABILITIES = Object.freeze({ read: Object.freeze(["v11-pages", "validated-page-and-group-order", "explicit-shape-transform", "utf16-shape-text", "move-to-line-to"]), write: Object.freeze(["equal-length-shape-text", "literal-shape-transform"]), limitations: Object.freeze(["Version 11 only; stored values without master/style/formula evaluation.", "Drawing order may be unresolved; flat shape arrays retain physical order and group coordinates stay local.", "Edits require an exact stored-block fit at the original offset; relocation is refused. Bounded compression preserves exact decoded length and supports at most 8 MiB decoded leaf/allocation, with bounded token-fit search and no added decoded bytes.", "No added/deleted shapes, text length changes or text field edits.", "Shared/overlapping VSD blocks cannot be edited; native evidence covers only declared fixture edits, not full Visio fidelity."]) });
|
|
12123
13881
|
var VsdDocument = class extends Ole2DocumentBase {
|
|
12124
13882
|
#drawing;
|
|
12125
13883
|
#pages;
|
|
@@ -12179,7 +13937,7 @@ var VsdDocument = class extends Ole2DocumentBase {
|
|
|
12179
13937
|
}
|
|
12180
13938
|
};
|
|
12181
13939
|
|
|
12182
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13940
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document.js
|
|
12183
13941
|
var CfbDocument = class extends Ole2DocumentBase {
|
|
12184
13942
|
get kind() {
|
|
12185
13943
|
return "cfb";
|
|
@@ -12292,7 +14050,7 @@ function parseVsd(input) {
|
|
|
12292
14050
|
return parseOle22(input, { expect: "vsd" });
|
|
12293
14051
|
}
|
|
12294
14052
|
|
|
12295
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
14053
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/utils/png-encoder.js
|
|
12296
14054
|
(() => {
|
|
12297
14055
|
const table = new Uint32Array(256);
|
|
12298
14056
|
for (let n = 0; n < 256; n++) {
|
|
@@ -14540,7 +16298,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14540
16298
|
return result;
|
|
14541
16299
|
};
|
|
14542
16300
|
let steps = 1e5;
|
|
14543
|
-
const
|
|
16301
|
+
const inspect6 = (binding, name) => {
|
|
14544
16302
|
check();
|
|
14545
16303
|
if (--steps < 0) problem("Master dependency proof exceeded its cell budget.");
|
|
14546
16304
|
name = name.toLowerCase();
|
|
@@ -14565,7 +16323,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14565
16323
|
txtlocpiny: "txtheight"
|
|
14566
16324
|
};
|
|
14567
16325
|
const dimension = defaults[name];
|
|
14568
|
-
if (dimension)
|
|
16326
|
+
if (dimension) inspect6(binding, dimension);
|
|
14569
16327
|
else if (!themeCell.test(name)) problem(`Missing effective master reference ${name}.`);
|
|
14570
16328
|
} else {
|
|
14571
16329
|
const formula = executableCellFormula(attribute2(source.node, "F"));
|
|
@@ -14586,17 +16344,17 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14586
16344
|
for (const ref of analysis.references) {
|
|
14587
16345
|
if (analysis.readsText && ref.shapeId === void 0 && ref.cell.toLowerCase() === "thetext")
|
|
14588
16346
|
continue;
|
|
14589
|
-
if (ref.shapeId === void 0)
|
|
16347
|
+
if (ref.shapeId === void 0) inspect6(binding, ref.cell);
|
|
14590
16348
|
else if (source.kind === "template") {
|
|
14591
16349
|
const target = binding.context.get(ref.shapeId);
|
|
14592
16350
|
if (!target) problem("Missing master-local Sheet reference.");
|
|
14593
|
-
|
|
16351
|
+
inspect6(target, ref.cell);
|
|
14594
16352
|
} else {
|
|
14595
16353
|
if (source.kind === "style")
|
|
14596
16354
|
problem("Explicit sheet references in inherited master styles are ambiguous.");
|
|
14597
16355
|
if (directAffected(binding.pageId, ref.shapeId, ref.cell) || query({ pageId: binding.pageId, shapeId: ref.shapeId, cell: ref.cell }, changed))
|
|
14598
16356
|
problem("Effective master cache depends on an edited page shape.");
|
|
14599
|
-
|
|
16357
|
+
inspect6(pageInput(binding.pageId, ref.shapeId), ref.cell);
|
|
14600
16358
|
}
|
|
14601
16359
|
}
|
|
14602
16360
|
if (analysis.readsText) {
|
|
@@ -14604,7 +16362,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14604
16362
|
if (/^(character\.|paragraph\.|tabs\.|leftmargin$|rightmargin$|topmargin$|bottommargin$)/i.test(
|
|
14605
16363
|
cell
|
|
14606
16364
|
))
|
|
14607
|
-
|
|
16365
|
+
inspect6(binding, cell);
|
|
14608
16366
|
}
|
|
14609
16367
|
}
|
|
14610
16368
|
}
|
|
@@ -14616,7 +16374,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14616
16374
|
const source = binding.cells.get(name);
|
|
14617
16375
|
if (["pinx", "piny"].includes(name) && source?.kind === "instance" && movePins.pins.has(source.node))
|
|
14618
16376
|
continue;
|
|
14619
|
-
|
|
16377
|
+
inspect6(binding, name);
|
|
14620
16378
|
}
|
|
14621
16379
|
return movePins;
|
|
14622
16380
|
}
|