ooxml-core 0.14.1 → 0.16.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/index.cjs +3058 -1968
- package/dist/automation/index.mjs +3058 -1968
- package/dist/automation/node.d.ts.map +1 -1
- package/dist/collab/emitter.d.ts.map +1 -1
- 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/block-parser.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/embedded.cjs +11 -0
- package/dist/docx/embedded.mjs +11 -0
- 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/index.cjs +59 -4
- package/dist/docx/index.mjs +59 -4
- package/dist/docx/layout/index.cjs +1 -0
- package/dist/docx/layout/index.mjs +1 -0
- 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 +29 -18
- package/dist/docx/load/index.mjs +29 -18
- package/dist/docx/load/legacy-doc.d.ts.map +1 -1
- package/dist/docx/model-paragraph.d.ts +6 -1
- package/dist/docx/model-paragraph.d.ts.map +1 -1
- package/dist/docx/paragraph-styles.d.ts +3 -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/toc-switches.d.ts +16 -0
- package/dist/docx/toc-switches.d.ts.map +1 -0
- 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/complex.d.ts +14 -0
- package/dist/xlsx/formula/functions/complex.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/convert.d.ts +4 -0
- package/dist/xlsx/formula/functions/convert.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/criteria.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/database.d.ts +4 -0
- package/dist/xlsx/formula/functions/database.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/dist-core.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/distributions-f.d.ts +6 -0
- package/dist/xlsx/formula/functions/distributions-f.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/distributions.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/engineering.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/helpers.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/hypothesis-tests.d.ts +4 -0
- package/dist/xlsx/formula/functions/hypothesis-tests.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/math-combin.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/matrix.d.ts +5 -0
- package/dist/xlsx/formula/functions/matrix.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/registry.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/regression-core.d.ts +34 -0
- package/dist/xlsx/formula/functions/regression-core.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/regression.d.ts +4 -0
- package/dist/xlsx/formula/functions/regression.d.ts.map +1 -0
- package/dist/xlsx/formula/functions/statistical.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/index.cjs +2835 -1756
- package/dist/xlsx/index.mjs +2835 -1756
- 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 +2320 -1241
- package/dist/xlsx/load/index.mjs +2320 -1241
- 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.cjs
CHANGED
|
@@ -2252,7 +2252,7 @@ function sanitize(root, limits) {
|
|
|
2252
2252
|
}
|
|
2253
2253
|
return { tag: data2.tag, attrs, children: data2.children };
|
|
2254
2254
|
}
|
|
2255
|
-
function
|
|
2255
|
+
function children4(value, optional = false) {
|
|
2256
2256
|
if (value === void 0 && optional) return [];
|
|
2257
2257
|
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
|
|
2258
2258
|
unsafe("Expected plain child array.");
|
|
@@ -2283,7 +2283,7 @@ function sanitize(root, limits) {
|
|
|
2283
2283
|
return target;
|
|
2284
2284
|
}
|
|
2285
2285
|
function leaf(data2) {
|
|
2286
|
-
if (
|
|
2286
|
+
if (children4(data2.children, true).length !== 0) unsafe("Path cannot contain child elements.");
|
|
2287
2287
|
return pathCommands(data2.attrs.d, limits, pathBudget);
|
|
2288
2288
|
}
|
|
2289
2289
|
function item(value, depth) {
|
|
@@ -2296,7 +2296,7 @@ function sanitize(root, limits) {
|
|
|
2296
2296
|
paint: paint(data2.attrs)
|
|
2297
2297
|
}) : Object.assign(target, {
|
|
2298
2298
|
kind: "group",
|
|
2299
|
-
items: Object.freeze(
|
|
2299
|
+
items: Object.freeze(children4(data2.children).map((child2) => item(child2, depth + 1)))
|
|
2300
2300
|
});
|
|
2301
2301
|
freezeLater.push(result);
|
|
2302
2302
|
return result;
|
|
@@ -2313,7 +2313,7 @@ function sanitize(root, limits) {
|
|
|
2313
2313
|
ids.set(id, clips.length);
|
|
2314
2314
|
const target = base(data2.attrs);
|
|
2315
2315
|
const paths = [];
|
|
2316
|
-
for (const child2 of
|
|
2316
|
+
for (const child2 of children4(data2.children)) {
|
|
2317
2317
|
const part = node(child2, depth + 1, true);
|
|
2318
2318
|
if (part.tag !== "path") unsafe("Clip content must be a path.");
|
|
2319
2319
|
const path = Object.assign(base(part.attrs), {
|
|
@@ -2338,11 +2338,11 @@ function sanitize(root, limits) {
|
|
|
2338
2338
|
if (viewBox[0] !== 0 || viewBox[1] !== 0 || viewBox[2] !== width || viewBox[3] !== height)
|
|
2339
2339
|
unsafe("Viewport differs from dimensions.");
|
|
2340
2340
|
const items = [];
|
|
2341
|
-
for (const child2 of
|
|
2341
|
+
for (const child2 of children4(data.children)) {
|
|
2342
2342
|
const peek = record(child2, ["tag", "attrs", "children"]);
|
|
2343
2343
|
if (peek.tag === "defs") {
|
|
2344
2344
|
const defs = node(child2, 1);
|
|
2345
|
-
for (const value of
|
|
2345
|
+
for (const value of children4(defs.children)) definition(value, 2);
|
|
2346
2346
|
} else items.push(item(child2, 1));
|
|
2347
2347
|
}
|
|
2348
2348
|
for (const { target, id } of pending) {
|
|
@@ -5134,7 +5134,7 @@ function getVisioPageLayers(document, pageId) {
|
|
|
5134
5134
|
return result.reverse();
|
|
5135
5135
|
}
|
|
5136
5136
|
|
|
5137
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5137
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
|
|
5138
5138
|
var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
|
|
5139
5139
|
var ENDOFCHAIN = 4294967294;
|
|
5140
5140
|
var FREESECT = 4294967295;
|
|
@@ -5152,7 +5152,7 @@ var Ole2ParseError = class extends Error {
|
|
|
5152
5152
|
}
|
|
5153
5153
|
};
|
|
5154
5154
|
|
|
5155
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5155
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
|
|
5156
5156
|
function parseOle2(buffer) {
|
|
5157
5157
|
const data = new Uint8Array(buffer);
|
|
5158
5158
|
const view2 = new DataView(buffer);
|
|
@@ -5382,7 +5382,7 @@ function parseOle2(buffer) {
|
|
|
5382
5382
|
return { entries, getStream };
|
|
5383
5383
|
}
|
|
5384
5384
|
|
|
5385
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5385
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document-base.js
|
|
5386
5386
|
var Ole2DocumentError = class extends Error {
|
|
5387
5387
|
code;
|
|
5388
5388
|
constructor(code, message) {
|
|
@@ -5447,7 +5447,7 @@ var Ole2DocumentBase = class {
|
|
|
5447
5447
|
}
|
|
5448
5448
|
};
|
|
5449
5449
|
|
|
5450
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5450
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-edit.js
|
|
5451
5451
|
var END = 4294967294;
|
|
5452
5452
|
var MAX = 4294967290;
|
|
5453
5453
|
var NIL = 4294967295;
|
|
@@ -5607,11 +5607,11 @@ function processCompoundFileStream(input, path, replacement) {
|
|
|
5607
5607
|
if (!workbook)
|
|
5608
5608
|
continue;
|
|
5609
5609
|
for (let p = 0; p + 4 <= workbook.length; ) {
|
|
5610
|
-
const
|
|
5610
|
+
const record5 = workbook[p] | workbook[p + 1] << 8;
|
|
5611
5611
|
const length = workbook[p + 2] | workbook[p + 3] << 8;
|
|
5612
|
-
if (
|
|
5612
|
+
if (record5 === 47)
|
|
5613
5613
|
return reject2();
|
|
5614
|
-
if (p + 4 + length > workbook.length ||
|
|
5614
|
+
if (p + 4 + length > workbook.length || record5 === 10)
|
|
5615
5615
|
break;
|
|
5616
5616
|
p += 4 + length;
|
|
5617
5617
|
}
|
|
@@ -5720,7 +5720,7 @@ function replaceCompoundFileStream(input, path, replacement) {
|
|
|
5720
5720
|
return processCompoundFileStream(input, path, replacement) ?? input;
|
|
5721
5721
|
}
|
|
5722
5722
|
|
|
5723
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5723
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-v4.js
|
|
5724
5724
|
var END2 = 4294967294;
|
|
5725
5725
|
var FREE = 4294967295;
|
|
5726
5726
|
var FAT = 4294967293;
|
|
@@ -5792,49 +5792,49 @@ function validateHierarchy(slots) {
|
|
|
5792
5792
|
throw new Error("Unreachable directory entries");
|
|
5793
5793
|
}
|
|
5794
5794
|
function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
5795
|
-
const
|
|
5795
|
+
const fail3 = (reason) => ({ ok: false, bytes: input, reason });
|
|
5796
5796
|
try {
|
|
5797
5797
|
if (input.length < 512 || !path.length || path.some((part) => !part))
|
|
5798
|
-
return
|
|
5798
|
+
return fail3("invalid-or-missing-stream");
|
|
5799
5799
|
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
5800
5800
|
const read = (offset) => view2.getUint32(offset, true);
|
|
5801
5801
|
const version = view2.getUint16(26, true);
|
|
5802
5802
|
if (version !== 4)
|
|
5803
|
-
return
|
|
5803
|
+
return fail3("unsupported-version");
|
|
5804
5804
|
const SECTOR3 = 4096, FAT_ENTRIES2 = SECTOR3 / 4, DIRECTORY_ENTRIES = SECTOR3 / 128;
|
|
5805
5805
|
if (read(72) !== 0 || read(44) > 109)
|
|
5806
|
-
return
|
|
5806
|
+
return fail3("unsupported-difat");
|
|
5807
5807
|
const cutoff = read(56);
|
|
5808
5808
|
if (cutoff !== 0 && cutoff !== 4096)
|
|
5809
|
-
return
|
|
5809
|
+
return fail3("unsupported-layout");
|
|
5810
5810
|
const original = readCompoundFileStream(input, path);
|
|
5811
5811
|
if (!original)
|
|
5812
|
-
return
|
|
5812
|
+
return fail3("invalid-or-missing-stream");
|
|
5813
5813
|
const name = path[path.length - 1].toLocaleLowerCase();
|
|
5814
5814
|
if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
|
|
5815
|
-
return
|
|
5815
|
+
return fail3("unsafe-edit");
|
|
5816
5816
|
if (name === "book" || name === "workbook") {
|
|
5817
5817
|
for (let offset = 0; offset + 4 <= original.length; ) {
|
|
5818
|
-
const
|
|
5818
|
+
const record5 = original[offset] | original[offset + 1] << 8;
|
|
5819
5819
|
const length = original[offset + 2] | original[offset + 3] << 8;
|
|
5820
|
-
if (
|
|
5821
|
-
return
|
|
5822
|
-
if (
|
|
5820
|
+
if (record5 === 47)
|
|
5821
|
+
return fail3("unsafe-edit");
|
|
5822
|
+
if (record5 === 10 || offset + 4 + length > original.length)
|
|
5823
5823
|
break;
|
|
5824
5824
|
offset += 4 + length;
|
|
5825
5825
|
}
|
|
5826
5826
|
}
|
|
5827
5827
|
const validated = replaceCompoundFileStream(input, path, original);
|
|
5828
5828
|
if (validated === input)
|
|
5829
|
-
return
|
|
5829
|
+
return fail3("unsafe-edit");
|
|
5830
5830
|
const sameLength = replacement.length === original.length;
|
|
5831
5831
|
if (!sameLength && original.length < cutoff)
|
|
5832
|
-
return
|
|
5832
|
+
return fail3("unsupported-mini-stream");
|
|
5833
5833
|
if (!sameLength && replacement.length < cutoff)
|
|
5834
|
-
return
|
|
5834
|
+
return fail3("unsupported-mini-transition");
|
|
5835
5835
|
const sectorCount = input.length / SECTOR3 - 1, fatCount = read(44);
|
|
5836
5836
|
if (sectorCount > fatCount * FAT_ENTRIES2)
|
|
5837
|
-
return
|
|
5837
|
+
return fail3("unsafe-edit");
|
|
5838
5838
|
const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
|
|
5839
5839
|
const fat = [];
|
|
5840
5840
|
for (const id of fatIds) {
|
|
@@ -5842,11 +5842,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5842
5842
|
fat.push(read((id + 1) * SECTOR3 + i * 4));
|
|
5843
5843
|
}
|
|
5844
5844
|
if (fatIds.some((id) => fat[id] !== FAT))
|
|
5845
|
-
return
|
|
5845
|
+
return fail3("unsafe-edit");
|
|
5846
5846
|
const slots = /* @__PURE__ */ new Map();
|
|
5847
5847
|
const directoryChain = follow(fat, read(48));
|
|
5848
5848
|
if (read(40) !== directoryChain.length)
|
|
5849
|
-
return
|
|
5849
|
+
return fail3("unsafe-edit");
|
|
5850
5850
|
for (const [block, sector] of directoryChain.entries()) {
|
|
5851
5851
|
for (let entry = 0; entry < DIRECTORY_ENTRIES; entry++) {
|
|
5852
5852
|
const offset = (sector + 1) * SECTOR3 + entry * 128, type = view2.getUint8(offset + 66);
|
|
@@ -5854,33 +5854,33 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5854
5854
|
continue;
|
|
5855
5855
|
const nameLength = view2.getUint16(offset + 64, true);
|
|
5856
5856
|
if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
|
|
5857
|
-
return
|
|
5857
|
+
return fail3("unsafe-edit");
|
|
5858
5858
|
let name2 = "";
|
|
5859
5859
|
for (let i = 0; i < nameLength - 2; i += 2)
|
|
5860
5860
|
name2 += String.fromCharCode(view2.getUint16(offset + i, true));
|
|
5861
5861
|
if (read(offset + 124) !== 0)
|
|
5862
|
-
return
|
|
5862
|
+
return fail3("unsafe-edit");
|
|
5863
5863
|
const id = block * DIRECTORY_ENTRIES + entry;
|
|
5864
5864
|
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 });
|
|
5865
5865
|
}
|
|
5866
5866
|
}
|
|
5867
5867
|
if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
|
|
5868
|
-
return
|
|
5868
|
+
return fail3("unsafe-edit");
|
|
5869
5869
|
const target = findSlot(slots, path);
|
|
5870
5870
|
validateHierarchy(slots);
|
|
5871
5871
|
if (sameLength) {
|
|
5872
5872
|
const bytes = replaceCompoundFileStream(input, path, replacement);
|
|
5873
|
-
return bytes === input ?
|
|
5873
|
+
return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
|
|
5874
5874
|
}
|
|
5875
5875
|
const oldChain = follow(fat, target.start);
|
|
5876
5876
|
if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR3))
|
|
5877
|
-
return
|
|
5877
|
+
return fail3("unsafe-edit");
|
|
5878
5878
|
const payloadSectors = Math.ceil(replacement.length / SECTOR3);
|
|
5879
5879
|
let newFatCount = fatCount;
|
|
5880
5880
|
while (sectorCount + payloadSectors + newFatCount - fatCount > newFatCount * FAT_ENTRIES2)
|
|
5881
5881
|
newFatCount++;
|
|
5882
5882
|
if (newFatCount > 109)
|
|
5883
|
-
return
|
|
5883
|
+
return fail3("allocation-limit");
|
|
5884
5884
|
const totalSectors = sectorCount + payloadSectors + newFatCount - fatCount;
|
|
5885
5885
|
const output = new Uint8Array((totalSectors + 1) * SECTOR3);
|
|
5886
5886
|
output.set(input);
|
|
@@ -5904,11 +5904,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
|
|
|
5904
5904
|
outView.setUint32(target.offset + 120, replacement.length, true);
|
|
5905
5905
|
return { ok: true, bytes: output };
|
|
5906
5906
|
} catch {
|
|
5907
|
-
return
|
|
5907
|
+
return fail3("unsafe-edit");
|
|
5908
5908
|
}
|
|
5909
5909
|
}
|
|
5910
5910
|
|
|
5911
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5911
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-allocation.js
|
|
5912
5912
|
function appendCompoundAllocations(input, existingFatIds, payloads, sectorSize = 512) {
|
|
5913
5913
|
const sectorCount = input.length / sectorSize - 1;
|
|
5914
5914
|
const entriesPerFat = sectorSize / 4;
|
|
@@ -5955,7 +5955,7 @@ function followCompoundAllocation(table, start) {
|
|
|
5955
5955
|
return ids;
|
|
5956
5956
|
}
|
|
5957
5957
|
|
|
5958
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
5958
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-mini.js
|
|
5959
5959
|
var END3 = 4294967294;
|
|
5960
5960
|
var FREE2 = 4294967295;
|
|
5961
5961
|
var SECTOR = 512;
|
|
@@ -6027,7 +6027,7 @@ function resizeMiniCompoundStream(input, fat, fatIds, root, target, replacement,
|
|
|
6027
6027
|
return output.bytes;
|
|
6028
6028
|
}
|
|
6029
6029
|
|
|
6030
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6030
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize.js
|
|
6031
6031
|
var END4 = 4294967294;
|
|
6032
6032
|
var FREE3 = 4294967295;
|
|
6033
6033
|
var FAT2 = 4294967293;
|
|
@@ -6103,43 +6103,43 @@ function validateHierarchy2(slots) {
|
|
|
6103
6103
|
function resizeCompoundFileStream(input, path, replacement) {
|
|
6104
6104
|
if (input.length >= 512 && new DataView(input.buffer, input.byteOffset, input.byteLength).getUint16(26, true) === 4)
|
|
6105
6105
|
return resizeCompoundFileStreamV4(input, path, replacement);
|
|
6106
|
-
const
|
|
6106
|
+
const fail3 = (reason) => ({ ok: false, bytes: input, reason });
|
|
6107
6107
|
try {
|
|
6108
6108
|
if (input.length < SECTOR2 || !path.length || path.some((part) => !part))
|
|
6109
|
-
return
|
|
6109
|
+
return fail3("invalid-or-missing-stream");
|
|
6110
6110
|
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
6111
6111
|
const read = (offset) => view2.getUint32(offset, true);
|
|
6112
6112
|
if (view2.getUint16(26, true) !== 3)
|
|
6113
|
-
return
|
|
6113
|
+
return fail3("unsupported-version");
|
|
6114
6114
|
if (read(72) !== 0 || read(44) > 109)
|
|
6115
|
-
return
|
|
6115
|
+
return fail3("unsupported-difat");
|
|
6116
6116
|
const cutoff = read(56);
|
|
6117
6117
|
if (cutoff !== 0 && cutoff !== 4096)
|
|
6118
|
-
return
|
|
6118
|
+
return fail3("unsupported-layout");
|
|
6119
6119
|
const original = readCompoundFileStream(input, path);
|
|
6120
6120
|
if (!original)
|
|
6121
|
-
return
|
|
6121
|
+
return fail3("invalid-or-missing-stream");
|
|
6122
6122
|
const name = path[path.length - 1].toLocaleLowerCase();
|
|
6123
6123
|
if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
|
|
6124
|
-
return
|
|
6124
|
+
return fail3("unsafe-edit");
|
|
6125
6125
|
if (name === "book" || name === "workbook") {
|
|
6126
6126
|
for (let offset = 0; offset + 4 <= original.length; ) {
|
|
6127
|
-
const
|
|
6127
|
+
const record5 = original[offset] | original[offset + 1] << 8;
|
|
6128
6128
|
const length = original[offset + 2] | original[offset + 3] << 8;
|
|
6129
|
-
if (
|
|
6130
|
-
return
|
|
6131
|
-
if (
|
|
6129
|
+
if (record5 === 47)
|
|
6130
|
+
return fail3("unsafe-edit");
|
|
6131
|
+
if (record5 === 10 || offset + 4 + length > original.length)
|
|
6132
6132
|
break;
|
|
6133
6133
|
offset += 4 + length;
|
|
6134
6134
|
}
|
|
6135
6135
|
}
|
|
6136
6136
|
const validated = replaceCompoundFileStream(input, path, original);
|
|
6137
6137
|
if (validated === input)
|
|
6138
|
-
return
|
|
6138
|
+
return fail3("unsafe-edit");
|
|
6139
6139
|
const sameLength = replacement.length === original.length;
|
|
6140
6140
|
const sectorCount = input.length / SECTOR2 - 1, fatCount = read(44);
|
|
6141
6141
|
if (sectorCount > fatCount * FAT_ENTRIES)
|
|
6142
|
-
return
|
|
6142
|
+
return fail3("unsafe-edit");
|
|
6143
6143
|
const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
|
|
6144
6144
|
const fat = [];
|
|
6145
6145
|
for (const id of fatIds) {
|
|
@@ -6147,7 +6147,7 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6147
6147
|
fat.push(read((id + 1) * SECTOR2 + i * 4));
|
|
6148
6148
|
}
|
|
6149
6149
|
if (fatIds.some((id) => fat[id] !== FAT2))
|
|
6150
|
-
return
|
|
6150
|
+
return fail3("unsafe-edit");
|
|
6151
6151
|
const slots = /* @__PURE__ */ new Map();
|
|
6152
6152
|
for (const [block, sector] of follow2(fat, read(48)).entries()) {
|
|
6153
6153
|
for (let entry = 0; entry < 4; entry++) {
|
|
@@ -6156,7 +6156,7 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6156
6156
|
continue;
|
|
6157
6157
|
const nameLength = view2.getUint16(offset + 64, true);
|
|
6158
6158
|
if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
|
|
6159
|
-
return
|
|
6159
|
+
return fail3("unsafe-edit");
|
|
6160
6160
|
let name2 = "";
|
|
6161
6161
|
for (let i = 0; i < nameLength - 2; i += 2)
|
|
6162
6162
|
name2 += String.fromCharCode(view2.getUint16(offset + i, true));
|
|
@@ -6165,34 +6165,34 @@ function resizeCompoundFileStream(input, path, replacement) {
|
|
|
6165
6165
|
}
|
|
6166
6166
|
}
|
|
6167
6167
|
if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
|
|
6168
|
-
return
|
|
6168
|
+
return fail3("unsafe-edit");
|
|
6169
6169
|
const target = findSlot2(slots, path);
|
|
6170
6170
|
validateHierarchy2(slots);
|
|
6171
6171
|
if (sameLength) {
|
|
6172
6172
|
const bytes = replaceCompoundFileStream(input, path, replacement);
|
|
6173
|
-
return bytes === input ?
|
|
6173
|
+
return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
|
|
6174
6174
|
}
|
|
6175
6175
|
if (original.length < cutoff || replacement.length < cutoff) {
|
|
6176
6176
|
const bytes = resizeMiniCompoundStream(input, fat, fatIds, slots.get(0), target, replacement, cutoff);
|
|
6177
|
-
return bytes ? { ok: true, bytes } :
|
|
6177
|
+
return bytes ? { ok: true, bytes } : fail3("allocation-limit");
|
|
6178
6178
|
}
|
|
6179
6179
|
const oldChain = follow2(fat, target.start);
|
|
6180
6180
|
if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR2))
|
|
6181
|
-
return
|
|
6181
|
+
return fail3("unsafe-edit");
|
|
6182
6182
|
const output = appendCompoundAllocations(input, fatIds, [replacement]);
|
|
6183
6183
|
if (!output)
|
|
6184
|
-
return
|
|
6184
|
+
return fail3("allocation-limit");
|
|
6185
6185
|
for (const id of oldChain)
|
|
6186
6186
|
output.writeFat(id, FREE3);
|
|
6187
6187
|
output.view.setUint32(target.offset + 116, output.chains[0][0] ?? END4, true);
|
|
6188
6188
|
output.view.setUint32(target.offset + 120, replacement.length, true);
|
|
6189
6189
|
return { ok: true, bytes: output.bytes };
|
|
6190
6190
|
} catch {
|
|
6191
|
-
return
|
|
6191
|
+
return fail3("unsafe-edit");
|
|
6192
6192
|
}
|
|
6193
6193
|
}
|
|
6194
6194
|
|
|
6195
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6195
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fib.js
|
|
6196
6196
|
var FC_LCB_INDEX = {
|
|
6197
6197
|
plcfbteChpx: 12,
|
|
6198
6198
|
plcfbtePapx: 13,
|
|
@@ -6288,7 +6288,7 @@ function patchDocFib(wordDoc, fib, patch) {
|
|
|
6288
6288
|
view2.setUint32(papxOff + 4, patch.plcfbtePapx.lcb, true);
|
|
6289
6289
|
}
|
|
6290
6290
|
|
|
6291
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6291
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cfb.js
|
|
6292
6292
|
var DocCfbRewriteError = class extends Error {
|
|
6293
6293
|
constructor(message) {
|
|
6294
6294
|
super(message);
|
|
@@ -6343,7 +6343,7 @@ function unwrapDocBytes(bytes) {
|
|
|
6343
6343
|
}
|
|
6344
6344
|
}
|
|
6345
6345
|
|
|
6346
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6346
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fkp.js
|
|
6347
6347
|
var PAGE_SIZE = 512;
|
|
6348
6348
|
function parseBteTable(tableStream, at) {
|
|
6349
6349
|
const view2 = new DataView(tableStream.buffer, tableStream.byteOffset, tableStream.byteLength);
|
|
@@ -6484,7 +6484,7 @@ function buildSingleRunChpxPage(fcStart, fcEnd, blob) {
|
|
|
6484
6484
|
return page;
|
|
6485
6485
|
}
|
|
6486
6486
|
|
|
6487
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6487
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cp1252.js
|
|
6488
6488
|
var CP1252_HIGH_BLOCK = [
|
|
6489
6489
|
8364,
|
|
6490
6490
|
129,
|
|
@@ -6552,7 +6552,7 @@ function encodeCp1252(text) {
|
|
|
6552
6552
|
return Uint8Array.from(bytes);
|
|
6553
6553
|
}
|
|
6554
6554
|
|
|
6555
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6555
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-pieces.js
|
|
6556
6556
|
var CLXT_PRC = 1;
|
|
6557
6557
|
var CLXT_PCDT = 2;
|
|
6558
6558
|
var DocResourceLimitError = class extends Error {
|
|
@@ -6764,7 +6764,7 @@ function buildClxBytes(pieces, prcBytes = new Uint8Array()) {
|
|
|
6764
6764
|
return result;
|
|
6765
6765
|
}
|
|
6766
6766
|
|
|
6767
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6767
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fields.js
|
|
6768
6768
|
var UnsupportedDocFieldEditError = class extends Error {
|
|
6769
6769
|
constructor(message) {
|
|
6770
6770
|
super(message);
|
|
@@ -6848,7 +6848,7 @@ function shiftDocMainFieldCps(table, at, body, editStart, editEnd, delta, maxFie
|
|
|
6848
6848
|
return result;
|
|
6849
6849
|
}
|
|
6850
6850
|
|
|
6851
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
6851
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-editor.js
|
|
6852
6852
|
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];
|
|
6853
6853
|
var RISKY_STTB_INDICES = [21, 22, 23];
|
|
6854
6854
|
var SAFE_EXTENDED_FC_LCB_INDICES = /* @__PURE__ */ new Set([93, 94, 113, 181, 182]);
|
|
@@ -7117,7 +7117,7 @@ function tryWriteOleDocParagraphEdit(docBytes, paragraphIndex, text, limits) {
|
|
|
7117
7117
|
}
|
|
7118
7118
|
}
|
|
7119
7119
|
|
|
7120
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7120
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-runs.js
|
|
7121
7121
|
var LIMIT = 65536;
|
|
7122
7122
|
var SAFE_OPERANDS = /* @__PURE__ */ new Set([
|
|
7123
7123
|
2101,
|
|
@@ -7145,9 +7145,12 @@ var SAFE_OPERANDS = /* @__PURE__ */ new Set([
|
|
|
7145
7145
|
26646,
|
|
7146
7146
|
26647
|
|
7147
7147
|
]);
|
|
7148
|
-
function parsePrls(word, start, end) {
|
|
7148
|
+
function parsePrls(word, start, end, budget) {
|
|
7149
7149
|
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7150
7150
|
for (let at = start; at < end; ) {
|
|
7151
|
+
if (budget.remaining <= 0)
|
|
7152
|
+
throw new Error("Formatting SPRM limit");
|
|
7153
|
+
budget.remaining--;
|
|
7151
7154
|
if (at + 2 > end)
|
|
7152
7155
|
throw new Error("Truncated SPRM");
|
|
7153
7156
|
const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
|
|
@@ -7167,9 +7170,9 @@ function parsePrls(word, start, end) {
|
|
|
7167
7170
|
function parsePhysicalRuns(word, table) {
|
|
7168
7171
|
if (table.pns.length > LIMIT)
|
|
7169
7172
|
throw new Error("Formatting page limit");
|
|
7170
|
-
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7173
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [], budget = { remaining: 262144 };
|
|
7171
7174
|
for (let bte = 0; bte < table.pns.length; bte++) {
|
|
7172
|
-
const page = table.pns[bte] * 512;
|
|
7175
|
+
const page = (table.pns[bte] & 4194303) * 512;
|
|
7173
7176
|
if (page > word.length - 512)
|
|
7174
7177
|
throw new Error("Truncated CHPX page");
|
|
7175
7178
|
const count = word[page + 511], header = (count + 1) * 4 + count;
|
|
@@ -7183,7 +7186,7 @@ function parsePhysicalRuns(word, table) {
|
|
|
7183
7186
|
if (offset && (offset < header || offset + 1 + word[page + offset] > 511))
|
|
7184
7187
|
throw new Error("Invalid CHPX blob");
|
|
7185
7188
|
const blob = offset ? page + offset : 0, blobEnd = blob ? blob + 1 + word[blob] : 0;
|
|
7186
|
-
out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd) : [] });
|
|
7189
|
+
out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd, budget) : [] });
|
|
7187
7190
|
}
|
|
7188
7191
|
}
|
|
7189
7192
|
out.sort((a, b) => a.start - b.start);
|
|
@@ -7207,7 +7210,9 @@ function inspect2(input) {
|
|
|
7207
7210
|
if (fib.plcfbteChpx.lcb > LIMIT * 8 + 4 || fib.plcfbtePapx.lcb > LIMIT * 8 + 4)
|
|
7208
7211
|
throw new Error("Formatting table limit");
|
|
7209
7212
|
const chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx), papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx);
|
|
7213
|
+
papx.pns = papx.pns.map((pn) => pn & 4194303);
|
|
7210
7214
|
const physical = parsePhysicalRuns(word, chpx), runs = [];
|
|
7215
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
7211
7216
|
for (const piece of pieces) {
|
|
7212
7217
|
if (piece.cpStart >= fib.ccpText)
|
|
7213
7218
|
break;
|
|
@@ -7234,16 +7239,24 @@ function inspect2(input) {
|
|
|
7234
7239
|
const values = row.prls.filter((p) => p.opcode === opcode);
|
|
7235
7240
|
return values.length === 1 && values[0].operand[0] <= 1 ? values[0].operand[0] === 1 : void 0;
|
|
7236
7241
|
};
|
|
7242
|
+
const underline = row.prls.filter((p) => p.opcode === 10814);
|
|
7243
|
+
const kul = underline.length === 1 ? underline[0].operand[0] : void 0;
|
|
7237
7244
|
const size = row.prls.filter((p) => p.opcode === 19011);
|
|
7238
7245
|
const halfPoints = size.length === 1 ? size[0].operand[0] + size[0].operand[1] * 256 : void 0;
|
|
7246
|
+
let sprms = snapshots.get(row);
|
|
7247
|
+
if (!sprms) {
|
|
7248
|
+
sprms = Object.freeze(row.prls.map((p) => Object.freeze({ opcode: p.opcode, operand: Object.freeze(p.operand.slice()) })));
|
|
7249
|
+
snapshots.set(row, sprms);
|
|
7250
|
+
}
|
|
7239
7251
|
runs.push({
|
|
7240
7252
|
cpStart: cp,
|
|
7241
7253
|
cpEnd: end,
|
|
7242
7254
|
text: text.slice(cp, end),
|
|
7243
7255
|
directBold: direct(2101),
|
|
7244
7256
|
directItalic: direct(2102),
|
|
7257
|
+
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,
|
|
7245
7258
|
directFontSizePoints: piece.prm === 0 && halfPoints !== void 0 && halfPoints >= 2 && halfPoints <= 3276 && row.prls.every((p) => SAFE_OPERANDS.has(p.opcode)) ? halfPoints / 2 : void 0,
|
|
7246
|
-
sprms
|
|
7259
|
+
sprms,
|
|
7247
7260
|
physical: row,
|
|
7248
7261
|
prm: piece.prm
|
|
7249
7262
|
});
|
|
@@ -7276,10 +7289,23 @@ function readDocParagraphStyleIndices(input) {
|
|
|
7276
7289
|
function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
7277
7290
|
if (typeof value !== "boolean" || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd) || flag !== "bold" && flag !== "italic")
|
|
7278
7291
|
throw new Error("invalid-formatting");
|
|
7292
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, flag === "bold" ? 2101 : 2102, Number(value));
|
|
7293
|
+
}
|
|
7294
|
+
function writeDocCharacterRunFontSize(input, cpStart, cpEnd, points) {
|
|
7295
|
+
if (typeof points !== "number" || !Number.isFinite(points) || !Number.isInteger(points * 2) || points < 1 || points > 1638 || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
|
|
7296
|
+
throw new Error("invalid-formatting");
|
|
7297
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, 19011, points * 2);
|
|
7298
|
+
}
|
|
7299
|
+
function writeDocCharacterRunUnderline(input, cpStart, cpEnd, value) {
|
|
7300
|
+
if (typeof value !== "string" || !["none", "single", "double"].includes(value) || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
|
|
7301
|
+
throw new Error("invalid-formatting");
|
|
7302
|
+
return writeExclusiveOperand(input, cpStart, cpEnd, 10814, value === "none" ? 0 : value === "single" ? 1 : 3);
|
|
7303
|
+
}
|
|
7304
|
+
function writeExclusiveOperand(input, cpStart, cpEnd, opcode, value) {
|
|
7279
7305
|
const parsed = inspect2(input), target = parsed.runs.find((run) => run.cpStart === cpStart && run.cpEnd === cpEnd);
|
|
7280
7306
|
if (!target || target.prm !== 0 || /[\x00-\x1f]/u.test(target.text))
|
|
7281
7307
|
throw new Error("unsupported-formatting");
|
|
7282
|
-
const row = target.physical
|
|
7308
|
+
const row = target.physical;
|
|
7283
7309
|
const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
|
|
7284
7310
|
const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
|
|
7285
7311
|
if (row.blob < fibEnd)
|
|
@@ -7287,7 +7313,11 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
|
7287
7313
|
if (row.prls.some((p) => !SAFE_OPERANDS.has(p.opcode)))
|
|
7288
7314
|
throw new Error("opaque-formatting");
|
|
7289
7315
|
const operands = row.prls.filter((p) => p.opcode === opcode);
|
|
7290
|
-
if (operands.length !== 1
|
|
7316
|
+
if (operands.length !== 1)
|
|
7317
|
+
throw new Error("inherited-formatting");
|
|
7318
|
+
const operand = operands[0], size = opcode === 19011;
|
|
7319
|
+
const previous = operand.operand[0] + (size ? operand.operand[1] * 256 : 0);
|
|
7320
|
+
if (size ? operand.operand.length !== 2 || previous < 2 || previous > 3276 : opcode === 10814 ? ![0, 1, 3].includes(previous) : ![0, 1, 128, 129].includes(previous))
|
|
7291
7321
|
throw new Error("inherited-formatting");
|
|
7292
7322
|
const piece = parsed.pieces.find((p) => p.cpStart <= cpStart && p.cpEnd >= cpEnd);
|
|
7293
7323
|
const unit = piece.compressed ? 1 : 2, start = piece.fc + (cpStart - piece.cpStart) * unit;
|
|
@@ -7295,25 +7325,241 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
|
|
|
7295
7325
|
throw new Error("shared-formatting");
|
|
7296
7326
|
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)))
|
|
7297
7327
|
throw new Error("aliased-formatting");
|
|
7298
|
-
|
|
7328
|
+
const sed = parsed.fib.sed;
|
|
7329
|
+
if (sed.lcb > LIMIT * 16 + 4)
|
|
7330
|
+
throw new Error("resource-limit");
|
|
7331
|
+
if (sed.lcb) {
|
|
7332
|
+
if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
|
|
7333
|
+
throw new Error("invalid-formatting");
|
|
7334
|
+
const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
|
|
7335
|
+
const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
|
|
7336
|
+
for (let i = 0; i < n; i++) {
|
|
7337
|
+
const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
|
|
7338
|
+
if (at === -1)
|
|
7339
|
+
continue;
|
|
7340
|
+
if (at < 0 || at > parsed.word.length - 2)
|
|
7341
|
+
throw new Error("invalid-formatting");
|
|
7342
|
+
const end = at + 2 + wordView.getUint16(at, true);
|
|
7343
|
+
if (end > parsed.word.length)
|
|
7344
|
+
throw new Error("invalid-formatting");
|
|
7345
|
+
if (at < row.blobEnd && row.blob < end)
|
|
7346
|
+
throw new Error("aliased-formatting");
|
|
7347
|
+
}
|
|
7348
|
+
}
|
|
7349
|
+
if (previous === value)
|
|
7350
|
+
return input;
|
|
7351
|
+
const word = parsed.word.slice();
|
|
7352
|
+
word[operand.at] = value & 255;
|
|
7353
|
+
if (size)
|
|
7354
|
+
word[operand.at + 1] = value >>> 8;
|
|
7355
|
+
return parsed.doc.rewrap(word, parsed.doc.tableBytes);
|
|
7356
|
+
}
|
|
7357
|
+
|
|
7358
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-paragraph-format.js
|
|
7359
|
+
var LIMIT2 = 65536;
|
|
7360
|
+
var SPRM_LIMIT = 262144;
|
|
7361
|
+
var PAGE_NUMBER_MASK = 4194303;
|
|
7362
|
+
var ALIGNMENTS = ["start", "center", "end", "justify"];
|
|
7363
|
+
var SAFE = /* @__PURE__ */ new Set([
|
|
7364
|
+
9219,
|
|
7365
|
+
9313,
|
|
7366
|
+
25703,
|
|
7367
|
+
9221,
|
|
7368
|
+
9222,
|
|
7369
|
+
9223,
|
|
7370
|
+
9228,
|
|
7371
|
+
25618,
|
|
7372
|
+
42003,
|
|
7373
|
+
42004,
|
|
7374
|
+
9307,
|
|
7375
|
+
9308,
|
|
7376
|
+
33885,
|
|
7377
|
+
33886,
|
|
7378
|
+
33888,
|
|
7379
|
+
9281,
|
|
7380
|
+
9325
|
|
7381
|
+
]);
|
|
7382
|
+
function alignmentOperands(row) {
|
|
7383
|
+
const values = row.prls.filter((p) => p.opcode === 9313), mirrors = row.prls.filter((p) => p.opcode === 9219);
|
|
7384
|
+
if (values.length !== 1 || values[0].operand[0] > 3 || mirrors.length > 1)
|
|
7385
|
+
return void 0;
|
|
7386
|
+
const value = values[0], mirror = mirrors[0];
|
|
7387
|
+
if (mirror && (mirror.at > value.at || mirror.operand[0] !== value.operand[0]))
|
|
7388
|
+
return void 0;
|
|
7389
|
+
return { value, mirror };
|
|
7390
|
+
}
|
|
7391
|
+
function parsePrls2(word, start, end, budget) {
|
|
7392
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
|
|
7393
|
+
for (let at = start; at < end; ) {
|
|
7394
|
+
if (at + 2 > end)
|
|
7395
|
+
throw new Error("invalid-formatting");
|
|
7396
|
+
const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
|
|
7397
|
+
let length = [1, 1, 2, 4, 2, 2, 0, 3][spra];
|
|
7398
|
+
if (spra === 6) {
|
|
7399
|
+
if (opcode === 54792 || opcode === 50709 || at + 3 > end)
|
|
7400
|
+
throw new Error("unsupported-formatting");
|
|
7401
|
+
length = 1 + word[at + 2];
|
|
7402
|
+
}
|
|
7403
|
+
if (at + 2 + length > end)
|
|
7404
|
+
throw new Error("invalid-formatting");
|
|
7405
|
+
if (budget.remaining === 0)
|
|
7406
|
+
throw new Error("resource-limit");
|
|
7407
|
+
budget.remaining--;
|
|
7408
|
+
out.push({ opcode, at: at + 2, operand: word.subarray(at + 2, at + 2 + length) });
|
|
7409
|
+
at += 2 + length;
|
|
7410
|
+
}
|
|
7411
|
+
return out;
|
|
7412
|
+
}
|
|
7413
|
+
function inspect3(input) {
|
|
7414
|
+
const doc = unwrapDocBytes(input);
|
|
7415
|
+
if (!doc)
|
|
7416
|
+
throw new Error("unsupported-formatting");
|
|
7417
|
+
const word = doc.wordDocBytes, fib = readDocFib(word), limits = DEFAULT_OLE_DOC_PROCESSING_LIMITS;
|
|
7418
|
+
if (fib.ccpText > limits.maxCharacters)
|
|
7419
|
+
throw new Error("resource-limit");
|
|
7420
|
+
const pieces = parseDocClx(doc.tableBytes, fib.clx, limits.maxPieces).pieces;
|
|
7421
|
+
const total = pieces.at(-1)?.cpEnd ?? 0;
|
|
7422
|
+
if (total < fib.ccpText || total > fib.ccpText + fib.ccpOtherStories + 1)
|
|
7423
|
+
throw new Error("invalid-formatting");
|
|
7424
|
+
const text = decodePiecesText(word, pieces, fib.ccpText);
|
|
7425
|
+
if (fib.plcfbtePapx.lcb > LIMIT2 * 8 + 4 || fib.plcfbteChpx.lcb > LIMIT2 * 8 + 4)
|
|
7426
|
+
throw new Error("resource-limit");
|
|
7427
|
+
const papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx), chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx);
|
|
7428
|
+
const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), rows = [];
|
|
7429
|
+
const sprmBudget = { remaining: SPRM_LIMIT };
|
|
7430
|
+
for (let pageIndex = 0; pageIndex < papx.pns.length; pageIndex++) {
|
|
7431
|
+
const page = (papx.pns[pageIndex] & PAGE_NUMBER_MASK) * 512;
|
|
7432
|
+
if (page > word.length - 512)
|
|
7433
|
+
throw new Error("invalid-formatting");
|
|
7434
|
+
const count = word[page + 511], header = (count + 1) * 4 + count * 13;
|
|
7435
|
+
if (!count || header > 511 || rows.length + count > LIMIT2)
|
|
7436
|
+
throw new Error("resource-limit");
|
|
7437
|
+
for (let i = 0; i < count; i++) {
|
|
7438
|
+
const start = view2.getInt32(page + i * 4, true), end = view2.getInt32(page + (i + 1) * 4, true);
|
|
7439
|
+
if (start < papx.fcs[pageIndex] || end > papx.fcs[pageIndex + 1] || end <= start)
|
|
7440
|
+
throw new Error("invalid-formatting");
|
|
7441
|
+
const offset = word[page + (count + 1) * 4 + i * 13] * 2;
|
|
7442
|
+
if (!offset) {
|
|
7443
|
+
rows.push({ start, end, blob: 0, blobEnd: 0, prls: [] });
|
|
7444
|
+
continue;
|
|
7445
|
+
}
|
|
7446
|
+
if (offset < header || offset + 2 > 511)
|
|
7447
|
+
throw new Error("invalid-formatting");
|
|
7448
|
+
const blob = page + offset, cb = word[blob], prefix = cb === 0 ? 2 : 1;
|
|
7449
|
+
const length = cb === 0 ? 2 + word[blob + 1] * 2 : cb * 2;
|
|
7450
|
+
if (cb === 0 && !word[blob + 1] || length < prefix + 2 || offset + length > 511)
|
|
7451
|
+
throw new Error("invalid-formatting");
|
|
7452
|
+
const blobEnd = blob + length;
|
|
7453
|
+
rows.push({ start, end, blob, blobEnd, prls: parsePrls2(word, blob + prefix + 2, blobEnd, sprmBudget) });
|
|
7454
|
+
}
|
|
7455
|
+
}
|
|
7456
|
+
rows.sort((a, b) => a.start - b.start);
|
|
7457
|
+
for (let i = 1; i < rows.length; i++)
|
|
7458
|
+
if (rows[i].start < rows[i - 1].end)
|
|
7459
|
+
throw new Error("invalid-formatting");
|
|
7460
|
+
const paragraphs = [];
|
|
7461
|
+
let cpStart = 0, pieceIndex = 0;
|
|
7462
|
+
for (let cp = 0; cp < text.length; cp++) {
|
|
7463
|
+
if (text[cp] !== "\r" && cp !== text.length - 1)
|
|
7464
|
+
continue;
|
|
7465
|
+
if (paragraphs.length >= LIMIT2)
|
|
7466
|
+
throw new Error("resource-limit");
|
|
7467
|
+
while (pieces[pieceIndex].cpEnd <= cp)
|
|
7468
|
+
pieceIndex++;
|
|
7469
|
+
const piece = pieces[pieceIndex], fc = piece.fc + (cp - piece.cpStart) * (piece.compressed ? 1 : 2);
|
|
7470
|
+
let lo = 0, hi = rows.length;
|
|
7471
|
+
while (lo < hi) {
|
|
7472
|
+
const middle = lo + hi >>> 1;
|
|
7473
|
+
if (rows[middle].end <= fc)
|
|
7474
|
+
lo = middle + 1;
|
|
7475
|
+
else
|
|
7476
|
+
hi = middle;
|
|
7477
|
+
}
|
|
7478
|
+
const row = rows[lo];
|
|
7479
|
+
if (!row || fc < row.start || fc >= row.end)
|
|
7480
|
+
throw new Error("invalid-formatting");
|
|
7481
|
+
const operands = alignmentOperands(row);
|
|
7482
|
+
const directAlignment = piece.prm === 0 && row.prls.every((p) => SAFE.has(p.opcode)) && operands ? ALIGNMENTS[operands.value.operand[0]] : void 0;
|
|
7483
|
+
paragraphs.push({ cpStart, cpEnd: cp + 1, mark: text[cp] === "\r", row, prm: piece.prm, directAlignment });
|
|
7484
|
+
cpStart = cp + 1;
|
|
7485
|
+
}
|
|
7486
|
+
return { doc, word, fib, pieces, rows, chpx, paragraphs, text };
|
|
7487
|
+
}
|
|
7488
|
+
function readDocParagraphAlignments(input) {
|
|
7489
|
+
return Object.freeze(inspect3(input).paragraphs.map((p) => p.directAlignment));
|
|
7490
|
+
}
|
|
7491
|
+
function writeDocParagraphAlignment(input, index, alignment) {
|
|
7492
|
+
if (!Number.isSafeInteger(index) || index < 0 || typeof alignment !== "string" || !ALIGNMENTS.includes(alignment))
|
|
7493
|
+
throw new Error("invalid-formatting");
|
|
7494
|
+
const parsed = inspect3(input), target = parsed.paragraphs[index];
|
|
7495
|
+
if (!target?.mark || target.prm !== 0 || /[\x00-\x1f]/u.test(parsed.text.slice(target.cpStart, target.cpEnd - 1)))
|
|
7496
|
+
throw new Error("unsupported-formatting");
|
|
7497
|
+
const row = target.row;
|
|
7498
|
+
if (row.prls.some((p) => !SAFE.has(p.opcode)))
|
|
7499
|
+
throw new Error("opaque-formatting");
|
|
7500
|
+
const operands = alignmentOperands(row);
|
|
7501
|
+
if (!operands)
|
|
7502
|
+
throw new Error("inherited-formatting");
|
|
7503
|
+
if (operands.mirror && alignment !== "center" && alignment !== "justify")
|
|
7504
|
+
throw new Error("direction-dependent-alignment");
|
|
7505
|
+
const piece = parsed.pieces.find((p) => p.cpStart <= target.cpStart && p.cpEnd >= target.cpEnd);
|
|
7506
|
+
if (!piece || piece.prm !== 0)
|
|
7507
|
+
throw new Error("unsupported-formatting");
|
|
7508
|
+
const unit = piece.compressed ? 1 : 2, start = piece.fc + (target.cpStart - piece.cpStart) * unit;
|
|
7509
|
+
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)))
|
|
7510
|
+
throw new Error("shared-formatting");
|
|
7511
|
+
const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
|
|
7512
|
+
const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
|
|
7513
|
+
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)))
|
|
7514
|
+
throw new Error("aliased-formatting");
|
|
7515
|
+
const sed = parsed.fib.sed;
|
|
7516
|
+
if (sed.lcb > LIMIT2 * 16 + 4)
|
|
7517
|
+
throw new Error("resource-limit");
|
|
7518
|
+
if (sed.lcb) {
|
|
7519
|
+
if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
|
|
7520
|
+
throw new Error("invalid-formatting");
|
|
7521
|
+
const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
|
|
7522
|
+
const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
|
|
7523
|
+
for (let i = 0; i < n; i++) {
|
|
7524
|
+
const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
|
|
7525
|
+
if (at === -1)
|
|
7526
|
+
continue;
|
|
7527
|
+
if (at < 0 || at > parsed.word.length - 2)
|
|
7528
|
+
throw new Error("invalid-formatting");
|
|
7529
|
+
const end = at + 2 + wordView.getUint16(at, true);
|
|
7530
|
+
if (end > parsed.word.length)
|
|
7531
|
+
throw new Error("invalid-formatting");
|
|
7532
|
+
if (at < row.blobEnd && row.blob < end)
|
|
7533
|
+
throw new Error("aliased-formatting");
|
|
7534
|
+
}
|
|
7535
|
+
}
|
|
7536
|
+
const value = ALIGNMENTS.indexOf(alignment);
|
|
7537
|
+
if (operands.value.operand[0] === value)
|
|
7299
7538
|
return input;
|
|
7300
7539
|
const word = parsed.word.slice();
|
|
7301
|
-
word[operands
|
|
7540
|
+
word[operands.value.at] = value;
|
|
7541
|
+
if (operands.mirror)
|
|
7542
|
+
word[operands.mirror.at] = value;
|
|
7302
7543
|
return parsed.doc.rewrap(word, parsed.doc.tableBytes);
|
|
7303
7544
|
}
|
|
7304
7545
|
|
|
7305
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7546
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/doc-document.js
|
|
7306
7547
|
var DOC_CAPABILITIES = Object.freeze({
|
|
7307
|
-
read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "compound-streams"]),
|
|
7308
|
-
write: Object.freeze(["paragraph-text", "existing-direct-bold-italic"]),
|
|
7548
|
+
read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "direct-paragraph-alignment", "compound-streams"]),
|
|
7549
|
+
write: Object.freeze(["paragraph-text", "existing-direct-bold-italic", "existing-direct-font-size", "existing-direct-underline", "existing-direct-paragraph-alignment"]),
|
|
7309
7550
|
limitations: Object.freeze([
|
|
7310
7551
|
"Paragraph insertion, removal and embedded paragraph breaks are unsupported.",
|
|
7311
7552
|
"Character formatting reports direct CHPX exceptions, without resolving styles or piece PRMs.",
|
|
7312
7553
|
"Bold/italic setters force an absolute value in an existing exclusive understood CHPX run. Run handles expire after edits.",
|
|
7554
|
+
"Underline setters replace an existing exclusive sprmCKul byte with none, single or double; inherited and other styles refuse.",
|
|
7555
|
+
"Font-size setters replace an existing exclusive sprmCHps slot with 1..1638 points in exact half-point increments.",
|
|
7313
7556
|
"Fields, tables, objects and inherited styles are preserved where supported; their models are not editable.",
|
|
7314
7557
|
"Unsupported edits and processing limits throw without changing the document.",
|
|
7315
7558
|
"Text uses the bounded DOC codec defaults: 16,777,216 main-story characters and 65,536 pieces or field records.",
|
|
7316
|
-
"
|
|
7559
|
+
"Character run inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs.",
|
|
7560
|
+
"Rich formatting is bounded to 65,536 physical/mapped runs and paragraph style records.",
|
|
7561
|
+
"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.",
|
|
7562
|
+
"Paragraph alignment inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs."
|
|
7317
7563
|
])
|
|
7318
7564
|
});
|
|
7319
7565
|
var DocDocument = class extends Ole2DocumentBase {
|
|
@@ -7327,6 +7573,7 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7327
7573
|
#text;
|
|
7328
7574
|
#runsCache;
|
|
7329
7575
|
#stylesCache;
|
|
7576
|
+
#alignmentsCache;
|
|
7330
7577
|
constructor(input) {
|
|
7331
7578
|
super(input);
|
|
7332
7579
|
const text = readOleDocParagraphs(this.getBytes());
|
|
@@ -7343,6 +7590,16 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7343
7590
|
set text(value) {
|
|
7344
7591
|
owner.#setParagraphText(index, value);
|
|
7345
7592
|
},
|
|
7593
|
+
get directAlignment() {
|
|
7594
|
+
try {
|
|
7595
|
+
return owner.#paragraphAlignments()[index];
|
|
7596
|
+
} catch {
|
|
7597
|
+
throw new UnsupportedOle2EditError("unsupported-formatting");
|
|
7598
|
+
}
|
|
7599
|
+
},
|
|
7600
|
+
set directAlignment(value) {
|
|
7601
|
+
owner.#setParagraphAlignment(index, value);
|
|
7602
|
+
},
|
|
7346
7603
|
get runs() {
|
|
7347
7604
|
return owner.#paragraphRuns(index);
|
|
7348
7605
|
},
|
|
@@ -7359,6 +7616,25 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7359
7616
|
get paragraphs() {
|
|
7360
7617
|
return this.#paragraphs;
|
|
7361
7618
|
}
|
|
7619
|
+
#paragraphAlignments() {
|
|
7620
|
+
if (this.#alignmentsCache?.revision !== this.revision)
|
|
7621
|
+
this.#alignmentsCache = { revision: this.revision, alignments: readDocParagraphAlignments(this.getBytes()) };
|
|
7622
|
+
return this.#alignmentsCache.alignments;
|
|
7623
|
+
}
|
|
7624
|
+
#setParagraphAlignment(index, value) {
|
|
7625
|
+
if (typeof value !== "string")
|
|
7626
|
+
throw new UnsupportedOle2EditError("invalid-formatting");
|
|
7627
|
+
let bytes;
|
|
7628
|
+
try {
|
|
7629
|
+
bytes = writeDocParagraphAlignment(this.getBytes(), index, value);
|
|
7630
|
+
} catch (error) {
|
|
7631
|
+
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
|
|
7632
|
+
}
|
|
7633
|
+
const text = readOleDocParagraphs(bytes), alignments = readDocParagraphAlignments(bytes);
|
|
7634
|
+
if (!text || text.length !== this.#text.length || text.some((t, i) => t !== this.#text[i]) || alignments[index] !== value)
|
|
7635
|
+
throw new UnsupportedOle2EditError("invalid-document");
|
|
7636
|
+
this.commitBytes(bytes);
|
|
7637
|
+
}
|
|
7362
7638
|
#currentRuns() {
|
|
7363
7639
|
if (this.#runsCache?.revision !== this.revision)
|
|
7364
7640
|
this.#runsCache = { revision: this.revision, runs: readDocCharacterRuns(this.getBytes()) };
|
|
@@ -7377,15 +7653,15 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7377
7653
|
try {
|
|
7378
7654
|
return Object.freeze(this.#currentRuns().filter((r) => r.cpStart < end && r.cpEnd > start).map((run) => {
|
|
7379
7655
|
const cpStart = Math.max(start, run.cpStart), cpEnd = Math.min(end, run.cpEnd);
|
|
7380
|
-
let bold = run.directBold, italic = run.directItalic, sprms = run.sprms;
|
|
7656
|
+
let bold = run.directBold, italic = run.directItalic, size = run.directFontSizePoints, underline = run.directUnderline, sprms = run.sprms;
|
|
7381
7657
|
const set = (flag, value) => {
|
|
7382
7658
|
if (owner.revision !== revision)
|
|
7383
7659
|
throw new UnsupportedOle2EditError("stale-run");
|
|
7384
|
-
if (typeof value !== "boolean")
|
|
7660
|
+
if (flag === "underline" ? typeof value !== "string" : flag === "size" ? typeof value !== "number" : typeof value !== "boolean")
|
|
7385
7661
|
throw new UnsupportedOle2EditError("invalid-formatting");
|
|
7386
7662
|
let bytes;
|
|
7387
7663
|
try {
|
|
7388
|
-
bytes = writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
|
|
7664
|
+
bytes = flag === "underline" ? writeDocCharacterRunUnderline(owner.getBytes(), cpStart, cpEnd, value) : flag === "size" ? writeDocCharacterRunFontSize(owner.getBytes(), cpStart, cpEnd, value) : writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
|
|
7389
7665
|
} catch (error) {
|
|
7390
7666
|
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
|
|
7391
7667
|
}
|
|
@@ -7396,15 +7672,26 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7396
7672
|
owner.commitBytes(bytes);
|
|
7397
7673
|
if (flag === "bold")
|
|
7398
7674
|
bold = value;
|
|
7399
|
-
else
|
|
7675
|
+
else if (flag === "italic")
|
|
7400
7676
|
italic = value;
|
|
7401
|
-
|
|
7677
|
+
else if (flag === "underline")
|
|
7678
|
+
underline = value;
|
|
7679
|
+
else
|
|
7680
|
+
size = value;
|
|
7681
|
+
const opcode = flag === "bold" ? 2101 : flag === "italic" ? 2102 : flag === "underline" ? 10814 : 19011;
|
|
7682
|
+
const operand = flag === "size" ? [value * 2 & 255, value * 2 >>> 8] : flag === "underline" ? [value === "none" ? 0 : value === "single" ? 1 : 3] : [Number(value)];
|
|
7683
|
+
sprms = Object.freeze(sprms.map((p) => p.opcode === opcode ? Object.freeze({ opcode: p.opcode, operand: Object.freeze(operand) }) : p));
|
|
7402
7684
|
};
|
|
7403
7685
|
return Object.freeze({
|
|
7404
7686
|
cpStart,
|
|
7405
7687
|
cpEnd,
|
|
7406
7688
|
text: run.text.slice(cpStart - run.cpStart, cpEnd - run.cpStart),
|
|
7407
|
-
directFontSizePoints
|
|
7689
|
+
get directFontSizePoints() {
|
|
7690
|
+
return size;
|
|
7691
|
+
},
|
|
7692
|
+
set directFontSizePoints(value) {
|
|
7693
|
+
set("size", value);
|
|
7694
|
+
},
|
|
7408
7695
|
get sprms() {
|
|
7409
7696
|
return sprms;
|
|
7410
7697
|
},
|
|
@@ -7414,6 +7701,12 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7414
7701
|
set directBold(value) {
|
|
7415
7702
|
set("bold", value);
|
|
7416
7703
|
},
|
|
7704
|
+
get directUnderline() {
|
|
7705
|
+
return underline;
|
|
7706
|
+
},
|
|
7707
|
+
set directUnderline(value) {
|
|
7708
|
+
set("underline", value);
|
|
7709
|
+
},
|
|
7417
7710
|
get directItalic() {
|
|
7418
7711
|
return italic;
|
|
7419
7712
|
},
|
|
@@ -7446,7 +7739,7 @@ var DocDocument = class extends Ole2DocumentBase {
|
|
|
7446
7739
|
}
|
|
7447
7740
|
};
|
|
7448
7741
|
|
|
7449
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7742
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
|
|
7450
7743
|
function compareDirEntryNames(a, b) {
|
|
7451
7744
|
const ua = a.toUpperCase();
|
|
7452
7745
|
const ub = b.toUpperCase();
|
|
@@ -7513,7 +7806,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
|
|
|
7513
7806
|
}
|
|
7514
7807
|
}
|
|
7515
7808
|
|
|
7516
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7809
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
|
|
7517
7810
|
function writeHeader(outView, outBytes, params) {
|
|
7518
7811
|
outBytes.set(OLE_MAGIC, 0);
|
|
7519
7812
|
outView.setUint16(24, 62, true);
|
|
@@ -7606,7 +7899,7 @@ function writeStreamSectors(outBytes, streamData, chain2, sectorSize) {
|
|
|
7606
7899
|
}
|
|
7607
7900
|
}
|
|
7608
7901
|
|
|
7609
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
7902
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
|
|
7610
7903
|
function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
|
|
7611
7904
|
const sectorSize = 512;
|
|
7612
7905
|
const miniSectorSize = 64;
|
|
@@ -7787,7 +8080,7 @@ function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
|
|
|
7787
8080
|
return output;
|
|
7788
8081
|
}
|
|
7789
8082
|
|
|
7790
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8083
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cfb.js
|
|
7791
8084
|
var WORKBOOK_STREAM_NAMES = ["workbook", "book"];
|
|
7792
8085
|
function unwrapXlsBytes(bytes) {
|
|
7793
8086
|
if (!isCfb(bytes)) {
|
|
@@ -7854,7 +8147,7 @@ function isCfb(bytes) {
|
|
|
7854
8147
|
return OLE_MAGIC.every((value, index) => bytes[index] === value);
|
|
7855
8148
|
}
|
|
7856
8149
|
|
|
7857
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8150
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-functions.js
|
|
7858
8151
|
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`;
|
|
7859
8152
|
var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
|
|
7860
8153
|
const [id, name, argc] = entry.split(" ");
|
|
@@ -7862,7 +8155,7 @@ var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
|
|
|
7862
8155
|
}));
|
|
7863
8156
|
var XLS_USER_FUNCTION_ID = 255;
|
|
7864
8157
|
|
|
7865
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8158
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg-text.js
|
|
7866
8159
|
var BIFF_ERRORS = {
|
|
7867
8160
|
0: "#NULL!",
|
|
7868
8161
|
7: "#DIV/0!",
|
|
@@ -7957,7 +8250,7 @@ function readArrayConstant(extra) {
|
|
|
7957
8250
|
return `{${lines.join(";")}}`;
|
|
7958
8251
|
}
|
|
7959
8252
|
|
|
7960
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8253
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-records.js
|
|
7961
8254
|
var RT_CONTINUE = 60;
|
|
7962
8255
|
function readXlsRecords(bytes, start = 0, end = bytes.length) {
|
|
7963
8256
|
const records = [];
|
|
@@ -8049,8 +8342,8 @@ var SegmentReader = class _SegmentReader {
|
|
|
8049
8342
|
constructor(segments) {
|
|
8050
8343
|
this.segments = segments;
|
|
8051
8344
|
}
|
|
8052
|
-
static of(
|
|
8053
|
-
return new _SegmentReader([
|
|
8345
|
+
static of(record5) {
|
|
8346
|
+
return new _SegmentReader([record5.data, ...record5.continues]);
|
|
8054
8347
|
}
|
|
8055
8348
|
get done() {
|
|
8056
8349
|
this.normalize();
|
|
@@ -8109,21 +8402,21 @@ var SegmentReader = class _SegmentReader {
|
|
|
8109
8402
|
return this.continuedChars(count, (flags & 1) !== 0);
|
|
8110
8403
|
}
|
|
8111
8404
|
};
|
|
8112
|
-
function joinedData(
|
|
8113
|
-
if (
|
|
8114
|
-
return
|
|
8115
|
-
const total =
|
|
8405
|
+
function joinedData(record5) {
|
|
8406
|
+
if (record5.continues.length === 0)
|
|
8407
|
+
return record5.data;
|
|
8408
|
+
const total = record5.continues.reduce((sum, part) => sum + part.length, record5.data.length);
|
|
8116
8409
|
const out = new Uint8Array(total);
|
|
8117
|
-
out.set(
|
|
8118
|
-
let at =
|
|
8119
|
-
for (const part of
|
|
8410
|
+
out.set(record5.data, 0);
|
|
8411
|
+
let at = record5.data.length;
|
|
8412
|
+
for (const part of record5.continues) {
|
|
8120
8413
|
out.set(part, at);
|
|
8121
8414
|
at += part.length;
|
|
8122
8415
|
}
|
|
8123
8416
|
return out;
|
|
8124
8417
|
}
|
|
8125
8418
|
|
|
8126
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8419
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg.js
|
|
8127
8420
|
function decodeFormula(rgce, extra, context, options) {
|
|
8128
8421
|
try {
|
|
8129
8422
|
return decode(rgce, new ByteReader(extra), context, options);
|
|
@@ -8354,9 +8647,9 @@ function readAttr(reader, stack, whitespace) {
|
|
|
8354
8647
|
}
|
|
8355
8648
|
}
|
|
8356
8649
|
|
|
8357
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8358
|
-
function parseSharedStrings(
|
|
8359
|
-
const reader = SegmentReader.of(
|
|
8650
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sst.js
|
|
8651
|
+
function parseSharedStrings(record5) {
|
|
8652
|
+
const reader = SegmentReader.of(record5);
|
|
8360
8653
|
reader.u32();
|
|
8361
8654
|
const unique = reader.u32();
|
|
8362
8655
|
const strings = [];
|
|
@@ -8371,7 +8664,7 @@ function parseSharedStrings(record4) {
|
|
|
8371
8664
|
return strings;
|
|
8372
8665
|
}
|
|
8373
8666
|
|
|
8374
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8667
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-styles.js
|
|
8375
8668
|
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(" ");
|
|
8376
8669
|
var XLS_BUILTIN_FORMATS = {
|
|
8377
8670
|
0: "General",
|
|
@@ -8628,7 +8921,7 @@ function applyXfExt(data, xfs, palette) {
|
|
|
8628
8921
|
}
|
|
8629
8922
|
}
|
|
8630
8923
|
|
|
8631
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8924
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-types.js
|
|
8632
8925
|
var XlsReadError = class extends Error {
|
|
8633
8926
|
code;
|
|
8634
8927
|
constructor(code, message) {
|
|
@@ -8638,7 +8931,7 @@ var XlsReadError = class extends Error {
|
|
|
8638
8931
|
}
|
|
8639
8932
|
};
|
|
8640
8933
|
|
|
8641
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
8934
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-globals.js
|
|
8642
8935
|
var RT = {
|
|
8643
8936
|
BOF: 2057,
|
|
8644
8937
|
EOF: 10,
|
|
@@ -8737,17 +9030,17 @@ function parseGlobals(records) {
|
|
|
8737
9030
|
const version = first.data[0] | first.data[1] << 8;
|
|
8738
9031
|
if (version !== 1536)
|
|
8739
9032
|
throw new XlsReadError("unsupported-version", "Only Excel 97-2003 (BIFF8) workbooks are supported; this file uses an older Excel format.");
|
|
8740
|
-
const end = records.findIndex((
|
|
9033
|
+
const end = records.findIndex((record5) => record5.opcode === RT.EOF);
|
|
8741
9034
|
const globals = end >= 0 ? records.slice(0, end) : records;
|
|
8742
|
-
if (globals.some((
|
|
9035
|
+
if (globals.some((record5) => record5.opcode === RT.FILEPASS))
|
|
8743
9036
|
throw new XlsReadError("encrypted", "The workbook is password protected (encrypted).");
|
|
8744
|
-
const paletteRecord = globals.find((
|
|
9037
|
+
const paletteRecord = globals.find((record5) => record5.opcode === RT.PALETTE);
|
|
8745
9038
|
const palette = paletteRecord ? parsePalette(paletteRecord.data) : [...DEFAULT_XLS_PALETTE];
|
|
8746
9039
|
const numberFormats = /* @__PURE__ */ new Map();
|
|
8747
|
-
for (const
|
|
8748
|
-
if (
|
|
9040
|
+
for (const record5 of globals) {
|
|
9041
|
+
if (record5.opcode !== RT.FORMAT)
|
|
8749
9042
|
continue;
|
|
8750
|
-
const format = parseFormat(joinedData(
|
|
9043
|
+
const format = parseFormat(joinedData(record5));
|
|
8751
9044
|
numberFormats.set(format.id, format.code);
|
|
8752
9045
|
}
|
|
8753
9046
|
const formatCode = (id) => numberFormats.get(id) ?? XLS_BUILTIN_FORMATS[id] ?? "General";
|
|
@@ -8768,17 +9061,17 @@ function parseGlobals(records) {
|
|
|
8768
9061
|
const supbooks = [];
|
|
8769
9062
|
const xtis = [];
|
|
8770
9063
|
const rawNames = [];
|
|
8771
|
-
for (const
|
|
8772
|
-
const r = new ByteReader(
|
|
8773
|
-
switch (
|
|
9064
|
+
for (const record5 of globals) {
|
|
9065
|
+
const r = new ByteReader(record5.data);
|
|
9066
|
+
switch (record5.opcode) {
|
|
8774
9067
|
case RT.FONT:
|
|
8775
|
-
out.fonts.push(parseFont(
|
|
9068
|
+
out.fonts.push(parseFont(record5.data, palette));
|
|
8776
9069
|
break;
|
|
8777
9070
|
case RT.XF:
|
|
8778
|
-
out.xfs.push(parseXf(
|
|
9071
|
+
out.xfs.push(parseXf(record5.data, palette, formatCode));
|
|
8779
9072
|
break;
|
|
8780
9073
|
case RT.XFEXT:
|
|
8781
|
-
applyXfExt(
|
|
9074
|
+
applyXfExt(record5.data, out.xfs, palette);
|
|
8782
9075
|
break;
|
|
8783
9076
|
case RT.DATEMODE:
|
|
8784
9077
|
out.date1904 = r.u16() === 1;
|
|
@@ -8801,26 +9094,26 @@ function parseGlobals(records) {
|
|
|
8801
9094
|
break;
|
|
8802
9095
|
}
|
|
8803
9096
|
case RT.SST:
|
|
8804
|
-
out.sst = parseSharedStrings(
|
|
9097
|
+
out.sst = parseSharedStrings(record5);
|
|
8805
9098
|
break;
|
|
8806
9099
|
case RT.SUPBOOK:
|
|
8807
|
-
supbooks.push(parseSupBook(joinedData(
|
|
9100
|
+
supbooks.push(parseSupBook(joinedData(record5)));
|
|
8808
9101
|
break;
|
|
8809
9102
|
case RT.EXTERNNAME: {
|
|
8810
9103
|
const book = supbooks[supbooks.length - 1];
|
|
8811
|
-
const nr = new ByteReader(joinedData(
|
|
9104
|
+
const nr = new ByteReader(joinedData(record5), 6);
|
|
8812
9105
|
book?.externNames.push(nr.shortXlString());
|
|
8813
9106
|
break;
|
|
8814
9107
|
}
|
|
8815
9108
|
case RT.EXTERNSHEET: {
|
|
8816
|
-
const xr = new ByteReader(joinedData(
|
|
9109
|
+
const xr = new ByteReader(joinedData(record5));
|
|
8817
9110
|
const count = xr.u16();
|
|
8818
9111
|
for (let i = 0; i < count; i++)
|
|
8819
9112
|
xtis.push({ book: xr.u16(), first: xr.i16(), last: xr.i16() });
|
|
8820
9113
|
break;
|
|
8821
9114
|
}
|
|
8822
9115
|
case RT.NAME:
|
|
8823
|
-
rawNames.push(parseName(joinedData(
|
|
9116
|
+
rawNames.push(parseName(joinedData(record5)));
|
|
8824
9117
|
break;
|
|
8825
9118
|
case RT.OBPROJ:
|
|
8826
9119
|
out.unsupported.push("VBA macros");
|
|
@@ -8876,7 +9169,7 @@ function parseGlobals(records) {
|
|
|
8876
9169
|
return out;
|
|
8877
9170
|
}
|
|
8878
9171
|
|
|
8879
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9172
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8-edit.js
|
|
8880
9173
|
function encodeRkExact(value) {
|
|
8881
9174
|
if (!Number.isFinite(value))
|
|
8882
9175
|
return void 0;
|
|
@@ -8904,19 +9197,19 @@ function worksheetRanges(bytes) {
|
|
|
8904
9197
|
const ranges = [];
|
|
8905
9198
|
let depth = 0;
|
|
8906
9199
|
let start;
|
|
8907
|
-
for (const
|
|
8908
|
-
if (
|
|
8909
|
-
if (
|
|
9200
|
+
for (const record5 of records) {
|
|
9201
|
+
if (record5.opcode === 2057) {
|
|
9202
|
+
if (record5.length < 4 || view2.getUint16(record5.dataOffset, true) !== 1536 || depth >= 64)
|
|
8910
9203
|
return void 0;
|
|
8911
|
-
if (depth === 0 && view2.getUint16(
|
|
8912
|
-
start =
|
|
9204
|
+
if (depth === 0 && view2.getUint16(record5.dataOffset + 2, true) === 16)
|
|
9205
|
+
start = record5.headerOffset;
|
|
8913
9206
|
depth++;
|
|
8914
|
-
} else if (
|
|
8915
|
-
if (depth === 0 ||
|
|
9207
|
+
} else if (record5.opcode === 10) {
|
|
9208
|
+
if (depth === 0 || record5.length !== 0)
|
|
8916
9209
|
return void 0;
|
|
8917
9210
|
depth--;
|
|
8918
9211
|
if (depth === 0 && start !== void 0) {
|
|
8919
|
-
ranges.push({ start, end:
|
|
9212
|
+
ranges.push({ start, end: record5.dataOffset });
|
|
8920
9213
|
start = void 0;
|
|
8921
9214
|
}
|
|
8922
9215
|
}
|
|
@@ -8971,24 +9264,24 @@ function editXlsNumericCell(input, edit) {
|
|
|
8971
9264
|
let packed = false;
|
|
8972
9265
|
let depth = 0;
|
|
8973
9266
|
let matches = 0;
|
|
8974
|
-
for (const
|
|
8975
|
-
if (
|
|
9267
|
+
for (const record5 of readRecords(bytes, range.start, range.end)) {
|
|
9268
|
+
if (record5.opcode === 2057) {
|
|
8976
9269
|
depth++;
|
|
8977
9270
|
continue;
|
|
8978
9271
|
}
|
|
8979
|
-
if (
|
|
9272
|
+
if (record5.opcode === 10) {
|
|
8980
9273
|
depth--;
|
|
8981
9274
|
continue;
|
|
8982
9275
|
}
|
|
8983
9276
|
if (depth !== 1)
|
|
8984
9277
|
continue;
|
|
8985
|
-
const p =
|
|
8986
|
-
if (
|
|
8987
|
-
if (
|
|
9278
|
+
const p = record5.dataOffset;
|
|
9279
|
+
if (record5.opcode === 189) {
|
|
9280
|
+
if (record5.length < 12 || (record5.length - 6) % 6 !== 0)
|
|
8988
9281
|
return unchanged("malformed-records");
|
|
8989
9282
|
const first = view2.getUint16(p + 2, true);
|
|
8990
|
-
const lastCol = view2.getUint16(p +
|
|
8991
|
-
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (
|
|
9283
|
+
const lastCol = view2.getUint16(p + record5.length - 2, true);
|
|
9284
|
+
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 6)
|
|
8992
9285
|
return unchanged("malformed-records");
|
|
8993
9286
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol) {
|
|
8994
9287
|
if (++matches > 1)
|
|
@@ -8996,26 +9289,26 @@ function editXlsNumericCell(input, edit) {
|
|
|
8996
9289
|
payload = p + 6 + (edit.col - first) * 6;
|
|
8997
9290
|
packed = true;
|
|
8998
9291
|
}
|
|
8999
|
-
} else if (
|
|
9000
|
-
if (
|
|
9292
|
+
} else if (record5.opcode === 515 || record5.opcode === 638) {
|
|
9293
|
+
if (record5.length !== (record5.opcode === 515 ? 14 : 10))
|
|
9001
9294
|
return unchanged("malformed-records");
|
|
9002
9295
|
if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col) {
|
|
9003
9296
|
if (++matches > 1)
|
|
9004
9297
|
return unchanged("ambiguous-cell");
|
|
9005
9298
|
payload = p + 6;
|
|
9006
|
-
packed =
|
|
9299
|
+
packed = record5.opcode === 638;
|
|
9007
9300
|
}
|
|
9008
|
-
} else if ([6, 513, 516, 517, 253, 214].includes(
|
|
9009
|
-
if (
|
|
9301
|
+
} else if ([6, 513, 516, 517, 253, 214].includes(record5.opcode)) {
|
|
9302
|
+
if (record5.length < 6)
|
|
9010
9303
|
return unchanged("malformed-records");
|
|
9011
9304
|
if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col && ++matches > 1)
|
|
9012
9305
|
return unchanged("ambiguous-cell");
|
|
9013
|
-
} else if (
|
|
9014
|
-
if (
|
|
9306
|
+
} else if (record5.opcode === 190) {
|
|
9307
|
+
if (record5.length < 8 || (record5.length - 6) % 2 !== 0)
|
|
9015
9308
|
return unchanged("malformed-records");
|
|
9016
9309
|
const first = view2.getUint16(p + 2, true);
|
|
9017
|
-
const lastCol = view2.getUint16(p +
|
|
9018
|
-
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (
|
|
9310
|
+
const lastCol = view2.getUint16(p + record5.length - 2, true);
|
|
9311
|
+
if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 2)
|
|
9019
9312
|
return unchanged("malformed-records");
|
|
9020
9313
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol && ++matches > 1)
|
|
9021
9314
|
return unchanged("ambiguous-cell");
|
|
@@ -9041,7 +9334,7 @@ function editXlsNumericCell(input, edit) {
|
|
|
9041
9334
|
}
|
|
9042
9335
|
}
|
|
9043
9336
|
|
|
9044
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9337
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8.js
|
|
9045
9338
|
var OPCODE_BOF = 2057;
|
|
9046
9339
|
var OPCODE_EOF = 10;
|
|
9047
9340
|
var OPCODE_FILEPASS = 47;
|
|
@@ -9069,8 +9362,8 @@ function isSupportedBiff8Workbook(bytes) {
|
|
|
9069
9362
|
const view2 = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
9070
9363
|
if (view2.getUint16(bof.dataOffset, true) !== 1536 || view2.getUint16(bof.dataOffset + 2, true) !== 5)
|
|
9071
9364
|
return false;
|
|
9072
|
-
const globalsEnd = records.find((
|
|
9073
|
-
return !records.some((
|
|
9365
|
+
const globalsEnd = records.find((record5) => record5.opcode === OPCODE_EOF)?.headerOffset ?? bytes.length;
|
|
9366
|
+
return !records.some((record5) => record5.opcode === OPCODE_FILEPASS && record5.headerOffset < globalsEnd);
|
|
9074
9367
|
}
|
|
9075
9368
|
function decodeRk(rk) {
|
|
9076
9369
|
const isInt = (rk & 2) !== 0;
|
|
@@ -9088,7 +9381,7 @@ function decodeRk(rk) {
|
|
|
9088
9381
|
return isDiv100 ? value / 100 : value;
|
|
9089
9382
|
}
|
|
9090
9383
|
|
|
9091
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9384
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-formulas.js
|
|
9092
9385
|
function readRefU(r) {
|
|
9093
9386
|
return { firstRow: r.u16(), lastRow: r.u16(), firstCol: r.u8(), lastCol: r.u8() };
|
|
9094
9387
|
}
|
|
@@ -9146,7 +9439,7 @@ function resolveFormulas(formulas, shared, arrays, globals) {
|
|
|
9146
9439
|
}
|
|
9147
9440
|
}
|
|
9148
9441
|
|
|
9149
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9442
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet-extras.js
|
|
9150
9443
|
function parseMergedCells(data) {
|
|
9151
9444
|
const r = new ByteReader(data);
|
|
9152
9445
|
const count = r.u16();
|
|
@@ -9324,11 +9617,11 @@ function parseObj(data) {
|
|
|
9324
9617
|
r.skip(2);
|
|
9325
9618
|
return { type: r.u16(), id: r.u16() };
|
|
9326
9619
|
}
|
|
9327
|
-
function parseTxoText(
|
|
9328
|
-
const count = new ByteReader(
|
|
9329
|
-
if (count === 0 ||
|
|
9620
|
+
function parseTxoText(record5) {
|
|
9621
|
+
const count = new ByteReader(record5.data, 10).u16();
|
|
9622
|
+
if (count === 0 || record5.continues.length === 0)
|
|
9330
9623
|
return "";
|
|
9331
|
-
const reader = new SegmentReader(
|
|
9624
|
+
const reader = new SegmentReader(record5.continues);
|
|
9332
9625
|
const wide = (reader.u8() & 1) !== 0;
|
|
9333
9626
|
return reader.continuedChars(count, wide).replace(/\r\n?/g, "\n");
|
|
9334
9627
|
}
|
|
@@ -9341,7 +9634,7 @@ function parseNote(data) {
|
|
|
9341
9634
|
return { row, col, visible: (flags & 2) !== 0, id, author: r.xlString() };
|
|
9342
9635
|
}
|
|
9343
9636
|
|
|
9344
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9637
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet.js
|
|
9345
9638
|
var UNSUPPORTED = {
|
|
9346
9639
|
432: "conditional formatting",
|
|
9347
9640
|
2169: "conditional formatting",
|
|
@@ -9391,8 +9684,8 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9391
9684
|
return result;
|
|
9392
9685
|
};
|
|
9393
9686
|
for (let index = start; index < records.length; index++) {
|
|
9394
|
-
const
|
|
9395
|
-
const { opcode, data } =
|
|
9687
|
+
const record5 = records[index];
|
|
9688
|
+
const { opcode, data } = record5;
|
|
9396
9689
|
if (opcode === 2057) {
|
|
9397
9690
|
depth++;
|
|
9398
9691
|
if (depth > 1)
|
|
@@ -9444,7 +9737,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9444
9737
|
case 516:
|
|
9445
9738
|
case 214: {
|
|
9446
9739
|
const target = cell(r, "");
|
|
9447
|
-
const reader = SegmentReader.of({ ...
|
|
9740
|
+
const reader = SegmentReader.of({ ...record5, data: data.subarray(6) });
|
|
9448
9741
|
target.value = reader.xlString();
|
|
9449
9742
|
break;
|
|
9450
9743
|
}
|
|
@@ -9468,7 +9761,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9468
9761
|
}
|
|
9469
9762
|
case 519:
|
|
9470
9763
|
if (stringTarget)
|
|
9471
|
-
stringTarget.value = SegmentReader.of(
|
|
9764
|
+
stringTarget.value = SegmentReader.of(record5).xlString();
|
|
9472
9765
|
stringTarget = void 0;
|
|
9473
9766
|
break;
|
|
9474
9767
|
case 1212: {
|
|
@@ -9548,7 +9841,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9548
9841
|
}
|
|
9549
9842
|
case 438:
|
|
9550
9843
|
if (lastObject?.type === 25)
|
|
9551
|
-
texts.set(lastObject.id, parseTxoText(
|
|
9844
|
+
texts.set(lastObject.id, parseTxoText(record5));
|
|
9552
9845
|
break;
|
|
9553
9846
|
case 28:
|
|
9554
9847
|
notes.push(parseNote(data));
|
|
@@ -9597,7 +9890,7 @@ function parseSheet(bound2, records, start, globals) {
|
|
|
9597
9890
|
return sheet;
|
|
9598
9891
|
}
|
|
9599
9892
|
|
|
9600
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9893
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook.js
|
|
9601
9894
|
function compoundStreamNames(bytes) {
|
|
9602
9895
|
if (!OLE_MAGIC.every((value, index) => bytes[index] === value))
|
|
9603
9896
|
return [];
|
|
@@ -9611,12 +9904,12 @@ function compoundStreamNames(bytes) {
|
|
|
9611
9904
|
function topLevelSubstreams(records) {
|
|
9612
9905
|
const starts = [];
|
|
9613
9906
|
let depth = 0;
|
|
9614
|
-
records.forEach((
|
|
9615
|
-
if (
|
|
9907
|
+
records.forEach((record5, index) => {
|
|
9908
|
+
if (record5.opcode === 2057) {
|
|
9616
9909
|
if (depth === 0 && index > 0)
|
|
9617
9910
|
starts.push(index);
|
|
9618
9911
|
depth++;
|
|
9619
|
-
} else if (
|
|
9912
|
+
} else if (record5.opcode === 10)
|
|
9620
9913
|
depth = Math.max(0, depth - 1);
|
|
9621
9914
|
});
|
|
9622
9915
|
return starts;
|
|
@@ -9639,7 +9932,7 @@ function readXlsWorkbook(bytes) {
|
|
|
9639
9932
|
unsupported2.push("VBA macros");
|
|
9640
9933
|
if (streams.some((name) => name === "_SX_DB_CUR") && !unsupported2.includes("pivot caches"))
|
|
9641
9934
|
unsupported2.push("pivot caches");
|
|
9642
|
-
const byOffset = new Map(records.map((
|
|
9935
|
+
const byOffset = new Map(records.map((record5, index) => [record5.offset, index]));
|
|
9643
9936
|
const substreams = topLevelSubstreams(records);
|
|
9644
9937
|
const sheets = globals.sheets.map((bound2, position) => {
|
|
9645
9938
|
const start = byOffset.get(bound2.offset) ?? substreams[position];
|
|
@@ -9667,7 +9960,7 @@ function readXlsWorkbook(bytes) {
|
|
|
9667
9960
|
};
|
|
9668
9961
|
}
|
|
9669
9962
|
|
|
9670
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
9963
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-sst.js
|
|
9671
9964
|
var SstCursor = class {
|
|
9672
9965
|
segments;
|
|
9673
9966
|
segment = 0;
|
|
@@ -9790,7 +10083,7 @@ function appendXlsSstString(value) {
|
|
|
9790
10083
|
return Uint8Array.from(records);
|
|
9791
10084
|
}
|
|
9792
10085
|
|
|
9793
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10086
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cell-record-splices.js
|
|
9794
10087
|
var CELL_OPS = /* @__PURE__ */ new Set([6, 513, 515, 516, 517, 638, 253, 189, 190, 214]);
|
|
9795
10088
|
function record2(opcode, data) {
|
|
9796
10089
|
const out = new Uint8Array(data.length + 4), view2 = new DataView(out.buffer);
|
|
@@ -9882,7 +10175,7 @@ function relocateXlsDbCells(input, out, records, replacement, map) {
|
|
|
9882
10175
|
}
|
|
9883
10176
|
}
|
|
9884
10177
|
|
|
9885
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10178
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-known-records.js
|
|
9886
10179
|
var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
|
|
9887
10180
|
6,
|
|
9888
10181
|
10,
|
|
@@ -10240,7 +10533,7 @@ var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
|
|
|
10240
10533
|
]);
|
|
10241
10534
|
var XLS_FRT_WRAPPER = 2129;
|
|
10242
10535
|
|
|
10243
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10536
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-record-edit-model.js
|
|
10244
10537
|
var EditError = class extends Error {
|
|
10245
10538
|
reason;
|
|
10246
10539
|
constructor(reason) {
|
|
@@ -10341,6 +10634,8 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
|
|
|
10341
10634
|
const first = view2.getUint16(p + 2, true), last = view2.getUint16(p + r.length - 2, true);
|
|
10342
10635
|
if (last > 255 || last < first || last - first + 1 !== (r.length - 6) / stride)
|
|
10343
10636
|
reject("malformed-records");
|
|
10637
|
+
if (r.opcode === 190 && (first > 254 || last <= first))
|
|
10638
|
+
reject("malformed-records");
|
|
10344
10639
|
if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= last)
|
|
10345
10640
|
targets.push(r);
|
|
10346
10641
|
}
|
|
@@ -10350,19 +10645,19 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
|
|
|
10350
10645
|
const target = targets[0];
|
|
10351
10646
|
if (!target || !allowed.includes(target.opcode))
|
|
10352
10647
|
reject("cell-not-supported");
|
|
10353
|
-
if (target.opcode !== 189 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : 10))
|
|
10648
|
+
if (target.opcode !== 189 && target.opcode !== 190 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : target.opcode === 513 ? 6 : 10))
|
|
10354
10649
|
reject("malformed-records");
|
|
10355
|
-
for (const
|
|
10356
|
-
if (
|
|
10650
|
+
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))) {
|
|
10651
|
+
if (record5.length < 6)
|
|
10357
10652
|
reject("malformed-records");
|
|
10358
|
-
const p =
|
|
10653
|
+
const p = record5.dataOffset;
|
|
10359
10654
|
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))
|
|
10360
10655
|
reject("cell-not-supported");
|
|
10361
10656
|
}
|
|
10362
10657
|
return target;
|
|
10363
10658
|
}
|
|
10364
10659
|
|
|
10365
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10660
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-edit.js
|
|
10366
10661
|
function extSst(entries, map) {
|
|
10367
10662
|
const interval = Math.max(Math.floor(entries.length / 128) + 1, 8);
|
|
10368
10663
|
const count = Math.ceil(entries.length / interval);
|
|
@@ -10474,18 +10769,18 @@ function editXlsStringWorkbookStream(input, edit) {
|
|
|
10474
10769
|
view2.setUint32(map(sst.start) + 8, sst.entries.length + (index === sst.entries.length ? 1 : 0), true);
|
|
10475
10770
|
if (splices.length) {
|
|
10476
10771
|
const byOffset = new Map(m.records.map((r) => [r.headerOffset, r]));
|
|
10477
|
-
for (const
|
|
10478
|
-
if (
|
|
10772
|
+
for (const record5 of m.records) {
|
|
10773
|
+
if (record5.opcode === 133 && (record5.headerOffset >= m.globalsEnd || record5.depth !== 1))
|
|
10479
10774
|
reject("malformed-records");
|
|
10480
|
-
if (
|
|
10481
|
-
view2.setUint32(map(
|
|
10482
|
-
if (
|
|
10483
|
-
if (
|
|
10775
|
+
if (record5.opcode === 133)
|
|
10776
|
+
view2.setUint32(map(record5.dataOffset), map(sourceView.getUint32(record5.dataOffset, true)), true);
|
|
10777
|
+
if (record5.opcode === 523) {
|
|
10778
|
+
if (record5.length < 16 || (record5.length - 16) % 4 !== 0)
|
|
10484
10779
|
reject("malformed-records");
|
|
10485
|
-
for (let p =
|
|
10780
|
+
for (let p = record5.dataOffset + 12; p < record5.dataOffset + record5.length; p += 4) {
|
|
10486
10781
|
const address = sourceView.getUint32(p, true);
|
|
10487
10782
|
const pointed = byOffset.get(address);
|
|
10488
|
-
if (!pointed || pointed.opcode !== (p ===
|
|
10783
|
+
if (!pointed || pointed.opcode !== (p === record5.dataOffset + 12 ? 85 : 215))
|
|
10489
10784
|
reject("malformed-records");
|
|
10490
10785
|
view2.setUint32(map(p), map(address), true);
|
|
10491
10786
|
}
|
|
@@ -10498,7 +10793,7 @@ function editXlsStringWorkbookStream(input, edit) {
|
|
|
10498
10793
|
}
|
|
10499
10794
|
}
|
|
10500
10795
|
|
|
10501
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10796
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-cell.js
|
|
10502
10797
|
function editXlsPreservedStringCell(input, edit) {
|
|
10503
10798
|
if (!OLE_MAGIC.every((value, index) => input[index] === value))
|
|
10504
10799
|
return editXlsStringWorkbookStream(input, edit);
|
|
@@ -10517,7 +10812,7 @@ function editXlsPreservedStringCell(input, edit) {
|
|
|
10517
10812
|
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
10518
10813
|
}
|
|
10519
10814
|
|
|
10520
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10815
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-edit.js
|
|
10521
10816
|
var ERRORS = Object.freeze({
|
|
10522
10817
|
"#NULL!": 0,
|
|
10523
10818
|
"#DIV/0!": 7,
|
|
@@ -10528,6 +10823,9 @@ var ERRORS = Object.freeze({
|
|
|
10528
10823
|
"#N/A": 42,
|
|
10529
10824
|
"#GETTING_DATA": 43
|
|
10530
10825
|
});
|
|
10826
|
+
function isValidXlsBoolErrorRecordValue(flag, value) {
|
|
10827
|
+
return flag === 0 && (value === 0 || value === 1) || flag === 1 && Object.values(ERRORS).includes(value);
|
|
10828
|
+
}
|
|
10531
10829
|
function normalizeXlsErrorValue(value) {
|
|
10532
10830
|
try {
|
|
10533
10831
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
@@ -10555,7 +10853,7 @@ function editXlsBoolErrorWorkbookStream(input, edit) {
|
|
|
10555
10853
|
const source = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
10556
10854
|
if (target.opcode === 517) {
|
|
10557
10855
|
const flag = source.getUint8(target.dataOffset + 7), value2 = source.getUint8(target.dataOffset + 6);
|
|
10558
|
-
if (
|
|
10856
|
+
if (!isValidXlsBoolErrorRecordValue(flag, value2))
|
|
10559
10857
|
reject("malformed-records");
|
|
10560
10858
|
}
|
|
10561
10859
|
const data = new Uint8Array(12), view2 = new DataView(data.buffer);
|
|
@@ -10632,7 +10930,175 @@ function editXlsBoolErrorCell(input, edit) {
|
|
|
10632
10930
|
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
10633
10931
|
}
|
|
10634
10932
|
|
|
10635
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
10933
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-record.js
|
|
10934
|
+
function record3(opcode, data) {
|
|
10935
|
+
const out = new Uint8Array(4 + data.length), view2 = new DataView(out.buffer);
|
|
10936
|
+
view2.setUint16(0, opcode, true);
|
|
10937
|
+
view2.setUint16(2, data.length, true);
|
|
10938
|
+
out.set(data, 4);
|
|
10939
|
+
return out;
|
|
10940
|
+
}
|
|
10941
|
+
function replaceXlsBlankRecord(input, target, col, value) {
|
|
10942
|
+
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))
|
|
10943
|
+
throw new Error("Invalid blank record replacement");
|
|
10944
|
+
const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength), p = target.dataOffset;
|
|
10945
|
+
if (view2.getUint16(target.headerOffset, true) !== target.opcode || view2.getUint16(target.headerOffset + 2, true) !== target.length)
|
|
10946
|
+
throw new Error("Blank record framing mismatch");
|
|
10947
|
+
const packed = target.opcode === 190;
|
|
10948
|
+
if (packed ? target.length < 10 || (target.length - 6) % 2 !== 0 : target.length !== 6)
|
|
10949
|
+
throw new Error("Invalid blank record length");
|
|
10950
|
+
const row = view2.getUint16(p, true), first = view2.getUint16(p + 2, true), count = packed ? (target.length - 6) / 2 : 1;
|
|
10951
|
+
const selected = col - first;
|
|
10952
|
+
if (first > 255 || first + count - 1 > 255 || selected < 0 || selected >= count || packed && view2.getUint16(p + target.length - 2, true) !== first + count - 1)
|
|
10953
|
+
throw new Error("Invalid blank column range");
|
|
10954
|
+
const data = new Uint8Array(14), cell = new DataView(data.buffer);
|
|
10955
|
+
cell.setUint16(0, row, true);
|
|
10956
|
+
cell.setUint16(2, col, true);
|
|
10957
|
+
cell.setUint16(4, view2.getUint16(p + 4 + (packed ? selected * 2 : 0), true), true);
|
|
10958
|
+
cell.setFloat64(6, value, true);
|
|
10959
|
+
const number2 = record3(515, data);
|
|
10960
|
+
const group = (start, size) => {
|
|
10961
|
+
if (!size)
|
|
10962
|
+
return new Uint8Array();
|
|
10963
|
+
const data2 = new Uint8Array(size === 1 ? 6 : 6 + size * 2), groupView = new DataView(data2.buffer);
|
|
10964
|
+
groupView.setUint16(0, row, true);
|
|
10965
|
+
groupView.setUint16(2, first + start, true);
|
|
10966
|
+
data2.set(input.subarray(p + 4 + start * 2, p + 4 + (start + size) * 2), 4);
|
|
10967
|
+
if (size > 1)
|
|
10968
|
+
groupView.setUint16(data2.length - 2, first + start + size - 1, true);
|
|
10969
|
+
return record3(size === 1 ? 513 : 190, data2);
|
|
10970
|
+
};
|
|
10971
|
+
const prefix = packed ? group(0, selected) : new Uint8Array(), suffix = packed ? group(selected + 1, count - selected - 1) : new Uint8Array();
|
|
10972
|
+
const bytes = new Uint8Array(prefix.length + number2.length + suffix.length);
|
|
10973
|
+
bytes.set(prefix);
|
|
10974
|
+
bytes.set(number2, prefix.length);
|
|
10975
|
+
bytes.set(suffix, prefix.length + number2.length);
|
|
10976
|
+
return { start: target.headerOffset, end: p + target.length, bytes };
|
|
10977
|
+
}
|
|
10978
|
+
|
|
10979
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-stored-cell-edit.js
|
|
10980
|
+
function applyXlsCellRecordReplacement(input, m, replacement) {
|
|
10981
|
+
if (!Number.isSafeInteger(replacement.start) || !Number.isSafeInteger(replacement.end) || replacement.start < 0 || replacement.end <= replacement.start || replacement.end > input.length || !(replacement.bytes instanceof Uint8Array))
|
|
10982
|
+
reject("malformed-records");
|
|
10983
|
+
const target = m.records.find((r) => r.headerOffset === replacement.start);
|
|
10984
|
+
if (!target || target.dataOffset + target.length !== replacement.end || ![513, 190, 517].includes(target.opcode))
|
|
10985
|
+
reject("malformed-records");
|
|
10986
|
+
const delta = replacement.bytes.length - (replacement.end - replacement.start);
|
|
10987
|
+
if (delta !== 0 && m.records.some((r) => !KNOWN_XLS_RECORDS.has(r.opcode) || r.opcode === XLS_FRT_WRAPPER))
|
|
10988
|
+
reject("unsupported-pointer-record");
|
|
10989
|
+
const map = (address) => {
|
|
10990
|
+
if (!Number.isSafeInteger(address) || address < 0 || address > input.length || address > replacement.start && address < replacement.end)
|
|
10991
|
+
reject("malformed-records");
|
|
10992
|
+
return address >= replacement.end ? address + delta : address;
|
|
10993
|
+
};
|
|
10994
|
+
const out = new Uint8Array(input.length + delta);
|
|
10995
|
+
out.set(input.subarray(0, replacement.start));
|
|
10996
|
+
out.set(replacement.bytes, replacement.start);
|
|
10997
|
+
out.set(input.subarray(replacement.end), replacement.start + replacement.bytes.length);
|
|
10998
|
+
if (delta !== 0) {
|
|
10999
|
+
relocateXlsDbCells(input, out, m.records, replacement, map);
|
|
11000
|
+
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]));
|
|
11001
|
+
for (const r of m.records) {
|
|
11002
|
+
if (r.opcode === 133) {
|
|
11003
|
+
if (r.headerOffset >= m.globalsEnd || r.depth !== 1)
|
|
11004
|
+
reject("malformed-records");
|
|
11005
|
+
dest.setUint32(map(r.dataOffset), map(source.getUint32(r.dataOffset, true)), true);
|
|
11006
|
+
}
|
|
11007
|
+
if (r.opcode === 523) {
|
|
11008
|
+
if (r.length < 16 || (r.length - 16) % 4 !== 0)
|
|
11009
|
+
reject("malformed-records");
|
|
11010
|
+
const owner = m.worksheets.find((sheet) => r.depth === 1 && r.headerOffset >= sheet.start && r.headerOffset < sheet.end);
|
|
11011
|
+
if (!owner)
|
|
11012
|
+
reject("malformed-records");
|
|
11013
|
+
const pointers = /* @__PURE__ */ new Set();
|
|
11014
|
+
for (let p = r.dataOffset + 12; p < r.dataOffset + r.length; p += 4) {
|
|
11015
|
+
const address = source.getUint32(p, true);
|
|
11016
|
+
const pointed = byOffset.get(address);
|
|
11017
|
+
if (pointed?.opcode !== (p === r.dataOffset + 12 ? 85 : 215) || pointed.depth !== 1 || address < owner.start || address >= owner.end)
|
|
11018
|
+
reject("malformed-records");
|
|
11019
|
+
if (pointers.has(address))
|
|
11020
|
+
reject("malformed-records");
|
|
11021
|
+
pointers.add(address);
|
|
11022
|
+
dest.setUint32(map(p), map(address), true);
|
|
11023
|
+
}
|
|
11024
|
+
}
|
|
11025
|
+
}
|
|
11026
|
+
}
|
|
11027
|
+
return out;
|
|
11028
|
+
}
|
|
11029
|
+
function editXlsStoredCellWorkbookStream(input, edit, sourceKind) {
|
|
11030
|
+
const unchanged = (reason) => ({ status: "unchanged", bytes: input, reason });
|
|
11031
|
+
const row = edit.row, col = edit.col, worksheetIndex = edit.worksheetIndex ?? 0, supplied = edit.value;
|
|
11032
|
+
const value = supplied !== null && typeof supplied === "object" ? normalizeXlsErrorValue(supplied) : supplied;
|
|
11033
|
+
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")))
|
|
11034
|
+
return unchanged("invalid-edit");
|
|
11035
|
+
try {
|
|
11036
|
+
const m = model(input), target = findTarget(input, m, { row, col, worksheetIndex }, sourceKind === "blank" ? [513, 190] : [517]);
|
|
11037
|
+
const range = m.worksheets[worksheetIndex], source = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
11038
|
+
for (const record5 of m.records.filter((r) => r.opcode === 229 && r.depth === 1 && r.headerOffset >= range.start && r.headerOffset < range.end)) {
|
|
11039
|
+
if (record5.length < 2)
|
|
11040
|
+
reject("malformed-records");
|
|
11041
|
+
const count = source.getUint16(record5.dataOffset, true);
|
|
11042
|
+
if (record5.length !== 2 + count * 8)
|
|
11043
|
+
reject("malformed-records");
|
|
11044
|
+
for (let p = record5.dataOffset + 2; p < record5.dataOffset + record5.length; p += 8) {
|
|
11045
|
+
const firstRow = source.getUint16(p, true), lastRow = source.getUint16(p + 2, true), firstCol = source.getUint16(p + 4, true), lastCol = source.getUint16(p + 6, true);
|
|
11046
|
+
if (firstRow > lastRow || firstCol > lastCol || lastCol > 255)
|
|
11047
|
+
reject("malformed-records");
|
|
11048
|
+
if (row >= firstRow && row <= lastRow && col >= firstCol && col <= lastCol && (row !== firstRow || col !== firstCol))
|
|
11049
|
+
reject("cell-not-supported");
|
|
11050
|
+
}
|
|
11051
|
+
}
|
|
11052
|
+
let replacement;
|
|
11053
|
+
if (sourceKind === "blank")
|
|
11054
|
+
replacement = replaceXlsBlankRecord(input, target, col, typeof value === "number" ? value : 0);
|
|
11055
|
+
else {
|
|
11056
|
+
if (!isValidXlsBoolErrorRecordValue(source.getUint8(target.dataOffset + 7), source.getUint8(target.dataOffset + 6)))
|
|
11057
|
+
reject("malformed-records");
|
|
11058
|
+
const bytes = new Uint8Array(18), number2 = new DataView(bytes.buffer);
|
|
11059
|
+
number2.setUint16(0, 515, true);
|
|
11060
|
+
number2.setUint16(2, 14, true);
|
|
11061
|
+
bytes.set(input.subarray(target.dataOffset, target.dataOffset + 6), 4);
|
|
11062
|
+
number2.setFloat64(10, typeof value === "number" ? value : 0, true);
|
|
11063
|
+
replacement = { start: target.headerOffset, end: target.dataOffset + target.length, bytes };
|
|
11064
|
+
}
|
|
11065
|
+
const staged = applyXlsCellRecordReplacement(input, m, replacement);
|
|
11066
|
+
if (typeof value === "number")
|
|
11067
|
+
return { status: "edited", bytes: staged, recalculationRequired: true };
|
|
11068
|
+
const result = typeof value === "string" ? editXlsStringWorkbookStream(staged, { row, col, worksheetIndex, value }) : editXlsBoolErrorWorkbookStream(staged, { row, col, worksheetIndex, value });
|
|
11069
|
+
return result.status === "edited" ? result : { ...result, bytes: input };
|
|
11070
|
+
} catch (error) {
|
|
11071
|
+
return unchanged(error instanceof EditError ? error.reason : "malformed-records");
|
|
11072
|
+
}
|
|
11073
|
+
}
|
|
11074
|
+
function editXlsStoredCell(input, edit, sourceKind) {
|
|
11075
|
+
if (!OLE_MAGIC.every((value, index) => input[index] === value))
|
|
11076
|
+
return editXlsStoredCellWorkbookStream(input, edit, sourceKind);
|
|
11077
|
+
const streams = ["Workbook", "Book"].map((name) => ({ name, bytes: readCompoundFileStream(input, [name]) })).filter((s) => s.bytes !== void 0);
|
|
11078
|
+
if (streams.length !== 1)
|
|
11079
|
+
return { status: "unchanged", bytes: input, reason: "unsupported-workbook" };
|
|
11080
|
+
const stream = streams[0], result = editXlsStoredCellWorkbookStream(stream.bytes, edit, sourceKind);
|
|
11081
|
+
if (result.status !== "edited")
|
|
11082
|
+
return { ...result, bytes: input };
|
|
11083
|
+
if (result.bytes.length === stream.bytes.length) {
|
|
11084
|
+
const bytes = replaceCompoundFileStream(input, [stream.name], result.bytes);
|
|
11085
|
+
return bytes === input ? { status: "unchanged", bytes: input, reason: "container-not-writable" } : { ...result, bytes };
|
|
11086
|
+
}
|
|
11087
|
+
const resized = resizeCompoundFileStream(input, [stream.name], result.bytes);
|
|
11088
|
+
return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
|
|
11089
|
+
}
|
|
11090
|
+
|
|
11091
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-edit.js
|
|
11092
|
+
function editXlsBlankCell(input, edit) {
|
|
11093
|
+
return editXlsStoredCell(input, edit, "blank");
|
|
11094
|
+
}
|
|
11095
|
+
|
|
11096
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-conversion.js
|
|
11097
|
+
function editXlsBoolErrorScalarCell(input, edit) {
|
|
11098
|
+
return editXlsStoredCell(input, edit, "bool-error");
|
|
11099
|
+
}
|
|
11100
|
+
|
|
11101
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/xls-document.js
|
|
10636
11102
|
function cellType(cell) {
|
|
10637
11103
|
if (cell.formula !== void 0 || cell.formulaUndecoded || cell.arrayRange || cell.sharedFormula)
|
|
10638
11104
|
return "formula";
|
|
@@ -10732,8 +11198,8 @@ var XlsSheetNode = class {
|
|
|
10732
11198
|
};
|
|
10733
11199
|
var XLS_CAPABILITIES = Object.freeze({
|
|
10734
11200
|
read: Object.freeze(["BIFF8 worksheets", "cell values and cached formulas", "styles and merges", "opaque compound streams"]),
|
|
10735
|
-
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"]),
|
|
10736
|
-
limitations: Object.freeze(["No cell creation, formula editing or recalculation", "Numeric
|
|
11201
|
+
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"]),
|
|
11202
|
+
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"])
|
|
10737
11203
|
});
|
|
10738
11204
|
var XlsDocument = class extends Ole2DocumentBase {
|
|
10739
11205
|
get kind() {
|
|
@@ -10748,6 +11214,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10748
11214
|
}
|
|
10749
11215
|
#model;
|
|
10750
11216
|
#needsRecalculation = false;
|
|
11217
|
+
#settingCellValue = false;
|
|
10751
11218
|
constructor(input) {
|
|
10752
11219
|
super(input);
|
|
10753
11220
|
const bytes = this.getBytes();
|
|
@@ -10778,6 +11245,16 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10778
11245
|
}
|
|
10779
11246
|
/** @internal All changes are validated and parsed before committing bytes. */
|
|
10780
11247
|
setCellValue(sheetIndex, row, col, value) {
|
|
11248
|
+
if (this.#settingCellValue)
|
|
11249
|
+
throw new UnsupportedOle2EditError("reentrant-cell-edit");
|
|
11250
|
+
this.#settingCellValue = true;
|
|
11251
|
+
try {
|
|
11252
|
+
this.#applyCellValue(sheetIndex, row, col, value);
|
|
11253
|
+
} finally {
|
|
11254
|
+
this.#settingCellValue = false;
|
|
11255
|
+
}
|
|
11256
|
+
}
|
|
11257
|
+
#applyCellValue(sheetIndex, row, col, value) {
|
|
10781
11258
|
if (value !== null && typeof value === "object") {
|
|
10782
11259
|
const normalized = normalizeXlsErrorValue(value);
|
|
10783
11260
|
if (!normalized)
|
|
@@ -10790,13 +11267,14 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10790
11267
|
const sheet = this.#model.sheets[sheetIndex];
|
|
10791
11268
|
if (sheet?.kind !== "worksheet")
|
|
10792
11269
|
throw new UnsupportedOle2EditError("sheet-not-supported");
|
|
10793
|
-
if (cell.value === null)
|
|
10794
|
-
|
|
11270
|
+
if (cell.value === null && value === null)
|
|
11271
|
+
return;
|
|
10795
11272
|
if (typeof value !== "number" && typeof value !== "string" && typeof value !== "boolean" && !isXlsErrorValue(value))
|
|
10796
11273
|
throw new UnsupportedOle2EditError("value-type-not-supported");
|
|
10797
|
-
|
|
11274
|
+
const boolError = typeof cell.value === "boolean" || isXlsErrorValue(cell.value);
|
|
11275
|
+
if (typeof value === "number" && (cell.value !== null && typeof cell.value !== "number" && !boolError || !Number.isFinite(value)))
|
|
10798
11276
|
throw new UnsupportedOle2EditError("numeric-type-change-not-supported");
|
|
10799
|
-
if (typeof value === "string" && typeof cell.value !== "number" && typeof cell.value !== "string")
|
|
11277
|
+
if (typeof value === "string" && cell.value !== null && typeof cell.value !== "number" && typeof cell.value !== "string" && !boolError)
|
|
10800
11278
|
throw new UnsupportedOle2EditError("string-type-change-not-supported");
|
|
10801
11279
|
if ((typeof value === "boolean" || isXlsErrorValue(value)) && typeof cell.value === "string")
|
|
10802
11280
|
throw new UnsupportedOle2EditError("bool-error-type-change-not-supported");
|
|
@@ -10804,7 +11282,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10804
11282
|
return;
|
|
10805
11283
|
const worksheetIndex = this.#model.sheets.slice(0, sheetIndex).filter((s) => s.kind === "worksheet").length;
|
|
10806
11284
|
const edit = { row, col, value, worksheetIndex };
|
|
10807
|
-
const result = typeof value === "number" ? editXlsNumericCell(this.getBytes(), { ...edit, value }) : typeof value === "string" ? editXlsPreservedStringCell(this.getBytes(), { ...edit, value }) : editXlsBoolErrorCell(this.getBytes(), { ...edit, value });
|
|
11285
|
+
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 });
|
|
10808
11286
|
if (result.status !== "edited")
|
|
10809
11287
|
throw new UnsupportedOle2EditError(result.reason);
|
|
10810
11288
|
const next = readXlsWorkbook(result.bytes);
|
|
@@ -10817,7 +11295,7 @@ var XlsDocument = class extends Ole2DocumentBase {
|
|
|
10817
11295
|
}
|
|
10818
11296
|
};
|
|
10819
11297
|
|
|
10820
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11298
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-stream.js
|
|
10821
11299
|
var PptParseError = class extends Error {
|
|
10822
11300
|
constructor(message) {
|
|
10823
11301
|
super(message);
|
|
@@ -10851,18 +11329,88 @@ function readRecordOrThrow(view2, offset) {
|
|
|
10851
11329
|
return rec;
|
|
10852
11330
|
}
|
|
10853
11331
|
|
|
10854
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11332
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-types.js
|
|
10855
11333
|
var RT2 = {
|
|
10856
11334
|
Document: 1e3,
|
|
11335
|
+
DocumentAtom: 1001,
|
|
11336
|
+
EndDocumentAtom: 1002,
|
|
10857
11337
|
Slide: 1006,
|
|
11338
|
+
SlideAtom: 1007,
|
|
11339
|
+
Notes: 1008,
|
|
11340
|
+
NotesAtom: 1009,
|
|
11341
|
+
Environment: 1010,
|
|
10858
11342
|
SlidePersistAtom: 1011,
|
|
11343
|
+
MainMaster: 1016,
|
|
11344
|
+
SlideShowSlideInfoAtom: 1017,
|
|
11345
|
+
SlideViewInfo: 1018,
|
|
11346
|
+
ExternalObjectList: 1033,
|
|
11347
|
+
ExternalObjectListAtom: 1034,
|
|
11348
|
+
DrawingGroup: 1035,
|
|
11349
|
+
Drawing: 1036,
|
|
11350
|
+
List: 2e3,
|
|
11351
|
+
FontCollection: 2005,
|
|
11352
|
+
SoundCollection: 2020,
|
|
11353
|
+
SoundCollectionAtom: 2021,
|
|
11354
|
+
Sound: 2022,
|
|
11355
|
+
SoundDataBlob: 2023,
|
|
11356
|
+
ColorSchemeAtom: 2032,
|
|
11357
|
+
ExternalObjectRefAtom: 3009,
|
|
11358
|
+
OEPlaceholderAtom: 3011,
|
|
11359
|
+
RoundTripSlideSyncInfo12: 3012,
|
|
10859
11360
|
OutlineTextRefAtom: 3998,
|
|
11361
|
+
TextHeaderAtom: 3999,
|
|
10860
11362
|
TextCharsAtom: 4e3,
|
|
11363
|
+
StyleTextPropAtom: 4001,
|
|
11364
|
+
MasterTextPropAtom: 4002,
|
|
11365
|
+
TextMasterStyleAtom: 4003,
|
|
10861
11366
|
TextBytesAtom: 4008,
|
|
11367
|
+
TextSpecInfoAtom: 4010,
|
|
11368
|
+
CString: 4026,
|
|
11369
|
+
ExternalOleObjectAtom: 4035,
|
|
11370
|
+
ExternalOleEmbed: 4044,
|
|
11371
|
+
ExternalOleEmbedAtom: 4045,
|
|
11372
|
+
ExternalHyperlinkAtom: 4051,
|
|
11373
|
+
ExternalHyperlink: 4055,
|
|
11374
|
+
ExternalOleObjectStg: 4113,
|
|
11375
|
+
/** [MS-PPT] 2.10.6: information about external audio/video data (exObjId + loop/rewind/narration flags). */
|
|
11376
|
+
ExternalMediaAtom: 4100,
|
|
11377
|
+
/** [MS-PPT] 2.10.5: wraps an ExMediaAtom + optional UncOrLocalPathAtom for a linked video file. */
|
|
11378
|
+
ExternalVideo: 4101,
|
|
11379
|
+
/** [MS-PPT] 2.10.4: wraps an ExVideoContainer for a linked AVI movie. */
|
|
11380
|
+
ExternalAviMovie: 4102,
|
|
11381
|
+
/** [MS-PPT] 2.10.3: wraps an ExVideoContainer for a linked (generic/MCI-played) movie; what real
|
|
11382
|
+
* PowerPoint 16.0 writes for a linked non-AVI video file (COM-verified). */
|
|
11383
|
+
ExternalMciMovie: 4103,
|
|
11384
|
+
/** [MS-PPT] 2.10.8: wraps an ExMediaAtom + ExWAVAudioEmbeddedAtom referencing a SoundCollection entry. */
|
|
11385
|
+
ExternalWavAudioEmbedded: 4111,
|
|
11386
|
+
/** [MS-PPT] 2.10.9: soundIdRef (into SoundCollectionContainer) + soundLength (ms). recVer/recInstance = 0x1/0x001. */
|
|
11387
|
+
ExternalWavAudioEmbeddedAtom: 4115,
|
|
11388
|
+
TextInteractiveInfoAtom: 4063,
|
|
10862
11389
|
SlideListWithText: 4080,
|
|
11390
|
+
InteractiveInfo: 4082,
|
|
11391
|
+
InteractiveInfoAtom: 4083,
|
|
10863
11392
|
UserEditAtom: 4085,
|
|
10864
11393
|
CurrentUserAtom: 4086,
|
|
10865
|
-
|
|
11394
|
+
FontEntityAtom: 4023,
|
|
11395
|
+
CryptSession10Container: 12052,
|
|
11396
|
+
PersistDirectoryAtom: 6002,
|
|
11397
|
+
HeadersFooters: 4057,
|
|
11398
|
+
HeadersFootersAtom: 4058,
|
|
11399
|
+
ProgTags: 5e3,
|
|
11400
|
+
ProgBinaryTag: 5002,
|
|
11401
|
+
BinaryTagDataBlob: 5003,
|
|
11402
|
+
RoundTripCustomTableStyles12Atom: 17036,
|
|
11403
|
+
/** [MS-PPT] 2.11.21: a master's theme as a zipped OOXML package. */
|
|
11404
|
+
RoundTripTheme12Atom: 1038,
|
|
11405
|
+
/** [MS-PPT] 2.11.19: a master's `a:clrMap` as an XML string. */
|
|
11406
|
+
RoundTripColorMapping12Atom: 1039,
|
|
11407
|
+
/** [MS-PPT] 2.11.22: a master's `p:txStyles` as a zipped OOXML package. */
|
|
11408
|
+
RoundTripOArtTextStyles12Atom: 1059,
|
|
11409
|
+
/** [MS-PPT] 2.9.28: a date field (`*`) in a master date placeholder. */
|
|
11410
|
+
GenericDateMCAtom: 4088,
|
|
11411
|
+
/** [MS-PPT] 2.9.25: a slide-number field (`*`) in a placeholder. */
|
|
11412
|
+
SlideNumberMCAtom: 4056
|
|
11413
|
+
};
|
|
10866
11414
|
var OA = {
|
|
10867
11415
|
SpgrContainer: 61443,
|
|
10868
11416
|
SpContainer: 61444,
|
|
@@ -10876,7 +11424,7 @@ var OA = {
|
|
|
10876
11424
|
var HEADER_TOKEN_PLAIN = 3817979999;
|
|
10877
11425
|
var HEADER_TOKEN_ENCRYPTED = 4090610911;
|
|
10878
11426
|
|
|
10879
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11427
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt/persist-directory.js
|
|
10880
11428
|
var DEFAULT_MAX_EDITS = 1e4;
|
|
10881
11429
|
var DEFAULT_MAX_ENTRIES = 1e6;
|
|
10882
11430
|
function checkedLimit(value) {
|
|
@@ -10993,7 +11541,7 @@ function buildPersistDirectory(view2, offsetToCurrentEdit, limits = {}) {
|
|
|
10993
11541
|
return { currentEdit: edits[0], directory };
|
|
10994
11542
|
}
|
|
10995
11543
|
|
|
10996
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11544
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text.js
|
|
10997
11545
|
var PptTextError = class extends PptParseError {
|
|
10998
11546
|
code;
|
|
10999
11547
|
constructor(code, message) {
|
|
@@ -11068,7 +11616,7 @@ function inlineText(view2, parent) {
|
|
|
11068
11616
|
}
|
|
11069
11617
|
return { texts: result.sort((a, b) => a.headerOffset - b.headerOffset), mirrors };
|
|
11070
11618
|
}
|
|
11071
|
-
function
|
|
11619
|
+
function inspect4(input) {
|
|
11072
11620
|
const current = readCompoundFileStream(input, ["Current User"]);
|
|
11073
11621
|
const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
11074
11622
|
if (!current || !stream)
|
|
@@ -11146,19 +11694,69 @@ function inspect3(input) {
|
|
|
11146
11694
|
}
|
|
11147
11695
|
function readPptSlideTexts(input) {
|
|
11148
11696
|
try {
|
|
11149
|
-
return
|
|
11697
|
+
return inspect4(input).model;
|
|
11150
11698
|
} catch (error) {
|
|
11151
11699
|
if (error instanceof PptTextError)
|
|
11152
11700
|
throw error;
|
|
11153
11701
|
throw new PptTextError("corrupt", error instanceof Error ? error.message : "Malformed PPT");
|
|
11154
11702
|
}
|
|
11155
11703
|
}
|
|
11704
|
+
function textOwnershipRefusal(input, stream, persistId, atom) {
|
|
11705
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
11706
|
+
if (!user)
|
|
11707
|
+
throw new PptParseError("Missing Current User stream");
|
|
11708
|
+
const view2 = viewOf(stream), uv = viewOf(user), cu = readRecordOrThrow(uv, 0);
|
|
11709
|
+
const editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
11710
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
|
|
11711
|
+
const slideOffset = directory.get(persistId);
|
|
11712
|
+
if (slideOffset === void 0)
|
|
11713
|
+
return "Missing active slide persist object";
|
|
11714
|
+
const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
|
|
11715
|
+
const textEnd = text.dataOffset + text.recLen;
|
|
11716
|
+
const owners = [persistId];
|
|
11717
|
+
if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
|
|
11718
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
11719
|
+
if (docOffset === void 0)
|
|
11720
|
+
return "Missing outline text owner";
|
|
11721
|
+
const doc = readRecordOrThrow(view2, docOffset);
|
|
11722
|
+
if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
|
|
11723
|
+
return "Text is outside its active owning containers";
|
|
11724
|
+
owners.push(currentEdit.docPersistIdRef);
|
|
11725
|
+
}
|
|
11726
|
+
for (const ownerId of owners) {
|
|
11727
|
+
const owned = readRecordOrThrow(view2, directory.get(ownerId));
|
|
11728
|
+
const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
11729
|
+
if (end > view2.byteLength)
|
|
11730
|
+
return "Unbounded text owning persist object";
|
|
11731
|
+
const overlaps = (offset) => {
|
|
11732
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
11733
|
+
if (otherEnd > view2.byteLength)
|
|
11734
|
+
throw new PptParseError("Unbounded live persist object prevents safe text edit");
|
|
11735
|
+
return start < otherEnd && other.headerOffset < end;
|
|
11736
|
+
};
|
|
11737
|
+
for (const [id, offset] of directory)
|
|
11738
|
+
if (id !== ownerId && overlaps(offset))
|
|
11739
|
+
return "Text owning container overlaps another live persist object";
|
|
11740
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11741
|
+
for (let offset = editOffset; offset; ) {
|
|
11742
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
11743
|
+
return "Invalid text save-history ownership";
|
|
11744
|
+
visited.add(offset);
|
|
11745
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
11746
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
11747
|
+
return "Text owning container overlaps save-history metadata";
|
|
11748
|
+
offset = edit.offsetLastEdit;
|
|
11749
|
+
}
|
|
11750
|
+
}
|
|
11751
|
+
return void 0;
|
|
11752
|
+
}
|
|
11156
11753
|
function editPptSlideText(input, edit) {
|
|
11157
11754
|
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
11158
11755
|
try {
|
|
11756
|
+
edit = { slideIndex: edit.slideIndex, textIndex: edit.textIndex, expectedText: edit.expectedText, text: edit.text };
|
|
11159
11757
|
if (!Number.isSafeInteger(edit.slideIndex) || !Number.isSafeInteger(edit.textIndex) || edit.slideIndex < 0 || edit.textIndex < 0)
|
|
11160
11758
|
return reject2("Invalid text location");
|
|
11161
|
-
const { stream, model: model2, mirroredAtoms } =
|
|
11759
|
+
const { stream, model: model2, mirroredAtoms } = inspect4(input);
|
|
11162
11760
|
const atom = model2.slides[edit.slideIndex]?.texts[edit.textIndex];
|
|
11163
11761
|
if (!atom || atom.text !== edit.expectedText)
|
|
11164
11762
|
return reject2("Text location or expected text does not match");
|
|
@@ -11181,6 +11779,9 @@ function editPptSlideText(input, edit) {
|
|
|
11181
11779
|
if (value >= 56320 && value <= 57343 && !(edit.text.charCodeAt(i - 1) >= 55296 && edit.text.charCodeAt(i - 1) <= 56319))
|
|
11182
11780
|
return reject2("Unpaired UTF-16 surrogate");
|
|
11183
11781
|
}
|
|
11782
|
+
const ownership = textOwnershipRefusal(input, stream, model2.slides[edit.slideIndex].persistId, atom);
|
|
11783
|
+
if (ownership)
|
|
11784
|
+
return reject2(ownership);
|
|
11184
11785
|
const output = stream.slice(), view2 = viewOf(output), start = atom.headerOffset + 8;
|
|
11185
11786
|
for (let i = 0; i < edit.text.length; i++) {
|
|
11186
11787
|
if (atom.encoding === "utf16")
|
|
@@ -11195,7 +11796,7 @@ function editPptSlideText(input, edit) {
|
|
|
11195
11796
|
}
|
|
11196
11797
|
}
|
|
11197
11798
|
|
|
11198
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11799
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-reader.js
|
|
11199
11800
|
var DEFAULT_LIMITS = { maxRecords: 1e5, maxShapes: 1e4, maxProperties: 1e5, maxNameChars: 1e6, maxTextBytes: 16 * 1024 * 1024 };
|
|
11200
11801
|
var GEOMETRY_PROPERTY_IDS = /* @__PURE__ */ new Set([4, 127, 128, 191, 385, 447, 448, 459, 511, 896, 959]);
|
|
11201
11802
|
function pptShapeChildren(view2, parent) {
|
|
@@ -11235,13 +11836,13 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11235
11836
|
if (documentOffset === void 0)
|
|
11236
11837
|
throw new PptTextError("corrupt", "Missing active document");
|
|
11237
11838
|
const documentRecord = readRecordOrThrow(view2, documentOffset);
|
|
11238
|
-
const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((
|
|
11839
|
+
const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((record5) => record5.recType === RT2.SlideListWithText && record5.recInstance === 0);
|
|
11239
11840
|
for (const list of activeLists)
|
|
11240
|
-
for (const
|
|
11241
|
-
if (
|
|
11242
|
-
if (
|
|
11841
|
+
for (const record5 of pptShapeChildren(view2, list))
|
|
11842
|
+
if (record5.recType === RT2.SlidePersistAtom) {
|
|
11843
|
+
if (record5.recLen !== 20)
|
|
11243
11844
|
throw new PptTextError("corrupt", "Invalid slide persist atom");
|
|
11244
|
-
const offset = chain2.directory.get(view2.getUint32(
|
|
11845
|
+
const offset = chain2.directory.get(view2.getUint32(record5.dataOffset, true));
|
|
11245
11846
|
if (offset === void 0)
|
|
11246
11847
|
throw new PptTextError("corrupt", "Missing active slide");
|
|
11247
11848
|
slideOffsets.push(offset);
|
|
@@ -11286,9 +11887,9 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11286
11887
|
const item = stack.pop();
|
|
11287
11888
|
if (item.depth > 128)
|
|
11288
11889
|
throw new PptTextError("corrupt", "Shape nesting exceeds limit");
|
|
11289
|
-
const
|
|
11890
|
+
const children4 = pptShapeChildren(view2, item.rec);
|
|
11290
11891
|
if (item.rec.recType === OA.SpContainer) {
|
|
11291
|
-
const fsps =
|
|
11892
|
+
const fsps = children4.filter((rec) => rec.recType === OA.FSP);
|
|
11292
11893
|
if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
|
|
11293
11894
|
throw new PptTextError("corrupt", "Missing or ambiguous OfficeArtFSP");
|
|
11294
11895
|
const fsp = fsps[0], shapeId = view2.getUint32(fsp.dataOffset, true), flags = view2.getUint32(fsp.dataOffset + 4, true);
|
|
@@ -11313,7 +11914,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11313
11914
|
};
|
|
11314
11915
|
let propertyAmbiguity = false, unknownProperties = false, protectedGeometry = false, unknownTextFit = false;
|
|
11315
11916
|
const seenProperties = /* @__PURE__ */ new Set();
|
|
11316
|
-
const anchors =
|
|
11917
|
+
const anchors = children4.filter((rec) => rec.recType === OA.ClientAnchor || rec.recType === OA.ChildAnchor);
|
|
11317
11918
|
if (anchors.length === 1) {
|
|
11318
11919
|
const rec = anchors[0];
|
|
11319
11920
|
if (rec.recVer !== 0 || rec.recInstance !== 0 || (rec.recType === OA.ClientAnchor ? rec.recLen !== 8 && rec.recLen !== 16 : rec.recLen !== 16))
|
|
@@ -11327,13 +11928,13 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11327
11928
|
};
|
|
11328
11929
|
shape.coordinateSpace = largeClient ? "unknown" : rec.recType === OA.ChildAnchor ? "group-child-master-units" : item.group !== void 0 || flags & 2 ? "unknown" : "slide-master-units";
|
|
11329
11930
|
}
|
|
11330
|
-
const group =
|
|
11931
|
+
const group = children4.find((rec) => rec.recType === OA.FSPGR);
|
|
11331
11932
|
if (group) {
|
|
11332
11933
|
if (group.recVer !== 1 || group.recLen !== 16)
|
|
11333
11934
|
throw new PptTextError("corrupt", "Invalid group coordinate space");
|
|
11334
11935
|
shape.groupBounds = bounds(view2, group);
|
|
11335
11936
|
}
|
|
11336
|
-
for (const rec of
|
|
11937
|
+
for (const rec of children4.filter((rec2) => rec2.recType === OA.FOPT || rec2.recType === OA.TertiaryFOPT || rec2.recType === 61729)) {
|
|
11337
11938
|
if (rec.recVer !== 3 || rec.recInstance * 6 > rec.recLen)
|
|
11338
11939
|
throw new PptTextError("corrupt", "Invalid shape property table");
|
|
11339
11940
|
let complexOffset = rec.dataOffset + rec.recInstance * 6;
|
|
@@ -11371,7 +11972,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11371
11972
|
shape.textIndexes = slide.texts.flatMap((atom, index) => atom.headerOffset >= item.rec.dataOffset && atom.headerOffset < shape.recordEnd ? [index] : []);
|
|
11372
11973
|
if (shape.textIndexes.length)
|
|
11373
11974
|
shape.textReference = "inline";
|
|
11374
|
-
for (const textbox of
|
|
11975
|
+
for (const textbox of children4.filter((rec) => rec.recType === OA.ClientTextbox))
|
|
11375
11976
|
if (pptShapeChildren(view2, textbox).some((rec) => rec.recType === RT2.OutlineTextRefAtom))
|
|
11376
11977
|
shape.textReference = "unresolved";
|
|
11377
11978
|
if (shape.mirrored)
|
|
@@ -11395,7 +11996,7 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11395
11996
|
}
|
|
11396
11997
|
let parentGroup = item.group;
|
|
11397
11998
|
if (item.rec.recType === OA.SpgrContainer) {
|
|
11398
|
-
const head =
|
|
11999
|
+
const head = children4[0];
|
|
11399
12000
|
if (!head || head.recType !== OA.SpContainer)
|
|
11400
12001
|
throw new PptTextError("corrupt", "Group has no shape container");
|
|
11401
12002
|
const fsp = pptShapeChildren(view2, head).find((rec) => rec.recType === OA.FSP);
|
|
@@ -11404,8 +12005,8 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11404
12005
|
if (!(view2.getUint32(fsp.dataOffset + 4, true) & 4))
|
|
11405
12006
|
parentGroup = view2.getUint32(fsp.dataOffset, true);
|
|
11406
12007
|
}
|
|
11407
|
-
for (let i =
|
|
11408
|
-
const rec =
|
|
12008
|
+
for (let i = children4.length - 1; i >= 0; i--) {
|
|
12009
|
+
const rec = children4[i];
|
|
11409
12010
|
if (rec.recVer === 15 || rec.recType === OA.ClientTextbox)
|
|
11410
12011
|
stack.push({ rec, depth: item.depth + 1, group: item.rec.recType === OA.SpgrContainer && i === 0 ? item.group : parentGroup });
|
|
11411
12012
|
}
|
|
@@ -11414,10 +12015,44 @@ function readPptSlideShapes(input, limits = {}) {
|
|
|
11414
12015
|
});
|
|
11415
12016
|
}
|
|
11416
12017
|
|
|
11417
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
12018
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-edit.js
|
|
11418
12019
|
function equalPptShapeBounds(a, b) {
|
|
11419
12020
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
11420
12021
|
}
|
|
12022
|
+
function slideOwnershipRefusal(input, stream, persistId) {
|
|
12023
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
12024
|
+
if (!user)
|
|
12025
|
+
throw new PptParseError("Missing Current User stream");
|
|
12026
|
+
const view2 = new DataView(stream.buffer, stream.byteOffset, stream.byteLength), uv = new DataView(user.buffer, user.byteOffset, user.byteLength);
|
|
12027
|
+
const cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12028
|
+
const { directory } = buildPersistDirectory(view2, editOffset), ownedOffset = directory.get(persistId);
|
|
12029
|
+
if (ownedOffset === void 0)
|
|
12030
|
+
return "Missing active slide persist object";
|
|
12031
|
+
const owned = readRecordOrThrow(view2, ownedOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12032
|
+
if (end > view2.byteLength)
|
|
12033
|
+
return "Unbounded slide persist object";
|
|
12034
|
+
const overlaps = (offset) => {
|
|
12035
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
12036
|
+
if (otherEnd > view2.byteLength)
|
|
12037
|
+
throw new PptParseError("Unbounded live persist object prevents safe geometry edit");
|
|
12038
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12039
|
+
};
|
|
12040
|
+
for (const [id, offset] of directory) {
|
|
12041
|
+
if (id !== persistId && overlaps(offset))
|
|
12042
|
+
return "Slide container overlaps another live persist object";
|
|
12043
|
+
}
|
|
12044
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12045
|
+
for (let offset = editOffset; offset; ) {
|
|
12046
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12047
|
+
return "Invalid geometry save-history ownership";
|
|
12048
|
+
visited.add(offset);
|
|
12049
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12050
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12051
|
+
return "Slide container overlaps save-history metadata";
|
|
12052
|
+
offset = edit.offsetLastEdit;
|
|
12053
|
+
}
|
|
12054
|
+
return void 0;
|
|
12055
|
+
}
|
|
11421
12056
|
function editPptShapeBounds(input, edit) {
|
|
11422
12057
|
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
11423
12058
|
try {
|
|
@@ -11450,7 +12085,11 @@ function editPptShapeBounds(input, edit) {
|
|
|
11450
12085
|
const edges = [next.y, next.x, next.x + next.width, next.y + next.height];
|
|
11451
12086
|
if (!edges.every((value) => Number.isSafeInteger(value) && value >= -32768 && value <= 32767))
|
|
11452
12087
|
return reject2("Geometry exceeds the existing small anchor encoding");
|
|
11453
|
-
const stream = readCompoundFileStream(input, ["PowerPoint Document"])
|
|
12088
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
12089
|
+
const ownership = slideOwnershipRefusal(input, stream, persistId);
|
|
12090
|
+
if (ownership)
|
|
12091
|
+
return reject2(ownership);
|
|
12092
|
+
const out = stream.slice(), view2 = new DataView(out.buffer);
|
|
11454
12093
|
for (let i = 0; i < edges.length; i++)
|
|
11455
12094
|
view2.setInt16(anchor + 8 + i * 2, edges[i], true);
|
|
11456
12095
|
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], out);
|
|
@@ -11465,12 +12104,604 @@ function editPptShapeBounds(input, edit) {
|
|
|
11465
12104
|
}
|
|
11466
12105
|
}
|
|
11467
12106
|
|
|
11468
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
12107
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-notes.js
|
|
12108
|
+
var viewOf2 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
12109
|
+
function fail2(message) {
|
|
12110
|
+
throw new PptTextError("corrupt", message);
|
|
12111
|
+
}
|
|
12112
|
+
function inspect5(input, limits = {}) {
|
|
12113
|
+
const maxRecords = limits.maxRecords ?? 1e5, maxNotes = limits.maxNotes ?? 1e4, maxTextBytes = limits.maxTextBytes ?? 16 * 1024 * 1024;
|
|
12114
|
+
for (const value of [maxRecords, maxNotes, maxTextBytes])
|
|
12115
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
12116
|
+
fail2("Invalid notes resource limit");
|
|
12117
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
|
|
12118
|
+
if (!stream || !user)
|
|
12119
|
+
fail2("Missing PowerPoint streams");
|
|
12120
|
+
const view2 = viewOf2(stream), uv = viewOf2(user);
|
|
12121
|
+
const record5 = (offset, type) => {
|
|
12122
|
+
const r = readRecordOrThrow(view2, offset);
|
|
12123
|
+
if (r.dataOffset + r.recLen > view2.byteLength || type !== void 0 && r.recType !== type)
|
|
12124
|
+
fail2("Invalid notes record bounds/type");
|
|
12125
|
+
return r;
|
|
12126
|
+
};
|
|
12127
|
+
const cu = readRecordOrThrow(uv, 0);
|
|
12128
|
+
if (cu.recType !== RT2.CurrentUserAtom || cu.recVer !== 0 || cu.recInstance !== 0 || cu.recLen < 24 || cu.dataOffset + cu.recLen > uv.byteLength)
|
|
12129
|
+
fail2("Invalid CurrentUserAtom");
|
|
12130
|
+
const token = uv.getUint32(cu.dataOffset + 4, true);
|
|
12131
|
+
if (token === HEADER_TOKEN_ENCRYPTED)
|
|
12132
|
+
throw new PptTextError("encrypted", "Encrypted PPT notes are unsupported");
|
|
12133
|
+
if (token !== HEADER_TOKEN_PLAIN)
|
|
12134
|
+
fail2("Unknown encryption token");
|
|
12135
|
+
const { currentEdit, directory } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true), { maxEntries: maxRecords });
|
|
12136
|
+
if (currentEdit.encryptSessionPersistIdRef !== void 0)
|
|
12137
|
+
throw new PptTextError("encrypted", "Encrypted notes persist objects are unsupported");
|
|
12138
|
+
let recordCount = 0, textBytes = 0;
|
|
12139
|
+
const children4 = (r) => {
|
|
12140
|
+
const result = [], end = r.dataOffset + r.recLen;
|
|
12141
|
+
for (let pos = r.dataOffset; pos < end; ) {
|
|
12142
|
+
if (++recordCount > maxRecords)
|
|
12143
|
+
fail2("Notes record budget exceeded");
|
|
12144
|
+
if (end - pos < 8)
|
|
12145
|
+
fail2("Truncated notes child header");
|
|
12146
|
+
const child2 = record5(pos);
|
|
12147
|
+
if (child2.dataOffset + child2.recLen > end)
|
|
12148
|
+
fail2("Notes child exceeds parent");
|
|
12149
|
+
result.push(child2);
|
|
12150
|
+
pos = child2.dataOffset + child2.recLen;
|
|
12151
|
+
}
|
|
12152
|
+
return result;
|
|
12153
|
+
};
|
|
12154
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
12155
|
+
if (docOffset === void 0)
|
|
12156
|
+
fail2("Missing active document");
|
|
12157
|
+
const doc = record5(docOffset, RT2.Document);
|
|
12158
|
+
if (doc.recVer !== 15)
|
|
12159
|
+
fail2("Invalid document container");
|
|
12160
|
+
const docChildren = children4(doc), refs = /* @__PURE__ */ new Map(), persistIds = /* @__PURE__ */ new Set();
|
|
12161
|
+
const notesLists = docChildren.filter((r) => r.recType === RT2.SlideListWithText && r.recInstance === 2);
|
|
12162
|
+
if (notesLists.length > 1)
|
|
12163
|
+
fail2("Ambiguous notes list");
|
|
12164
|
+
for (const list of notesLists) {
|
|
12165
|
+
if (list.recVer !== 15)
|
|
12166
|
+
fail2("Invalid notes list");
|
|
12167
|
+
for (const r of children4(list)) {
|
|
12168
|
+
if (r.recType !== RT2.SlidePersistAtom || r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 20)
|
|
12169
|
+
fail2("Invalid NotesPersistAtom");
|
|
12170
|
+
const persistId = view2.getUint32(r.dataOffset, true), notesId = view2.getUint32(r.dataOffset + 12, true);
|
|
12171
|
+
if (!notesId || !persistId || refs.has(notesId) || persistIds.has(persistId))
|
|
12172
|
+
fail2("Duplicate or null notes identity");
|
|
12173
|
+
if (refs.size >= maxNotes)
|
|
12174
|
+
fail2("Notes count budget exceeded");
|
|
12175
|
+
refs.set(notesId, persistId);
|
|
12176
|
+
persistIds.add(persistId);
|
|
12177
|
+
}
|
|
12178
|
+
}
|
|
12179
|
+
const slides = readPptSlideShapes(input, { maxRecords, maxTextBytes, maxShapes: maxRecords });
|
|
12180
|
+
if (slides.length > maxNotes)
|
|
12181
|
+
fail2("Active slide budget exceeded");
|
|
12182
|
+
const links = /* @__PURE__ */ new Map(), linkedNotes = /* @__PURE__ */ new Set();
|
|
12183
|
+
for (const slide of slides) {
|
|
12184
|
+
const offset = directory.get(slide.persistId);
|
|
12185
|
+
if (offset === void 0)
|
|
12186
|
+
fail2("Missing active slide");
|
|
12187
|
+
const sr = record5(offset, RT2.Slide), slideAtoms = children4(sr).filter((r) => r.recType === RT2.SlideAtom);
|
|
12188
|
+
if (slideAtoms.length !== 1 || slideAtoms[0].recVer !== 2 || slideAtoms[0].recInstance !== 0 || slideAtoms[0].recLen !== 24)
|
|
12189
|
+
fail2("Invalid SlideAtom notes linkage");
|
|
12190
|
+
const notesId = view2.getUint32(slideAtoms[0].dataOffset + 16, true);
|
|
12191
|
+
if (notesId && linkedNotes.has(notesId))
|
|
12192
|
+
fail2("Notes linked by multiple active slides");
|
|
12193
|
+
if (notesId)
|
|
12194
|
+
linkedNotes.add(notesId);
|
|
12195
|
+
links.set(slide.slideId, notesId);
|
|
12196
|
+
}
|
|
12197
|
+
const activeNotes = new Set(links.values());
|
|
12198
|
+
const raw = /* @__PURE__ */ new Map();
|
|
12199
|
+
for (const [notesId, persistId] of refs) {
|
|
12200
|
+
if (!activeNotes.has(notesId))
|
|
12201
|
+
continue;
|
|
12202
|
+
const offset = directory.get(persistId);
|
|
12203
|
+
if (offset === void 0)
|
|
12204
|
+
fail2("Missing notes persist object");
|
|
12205
|
+
const header = record5(offset, RT2.Notes);
|
|
12206
|
+
if (header.recVer !== 15 || header.recInstance !== 0)
|
|
12207
|
+
fail2("Invalid NotesContainer");
|
|
12208
|
+
const direct = children4(header), atoms = direct.filter((r) => r.recType === RT2.NotesAtom);
|
|
12209
|
+
if (atoms.length !== 1 || atoms[0].recVer !== 1 || atoms[0].recInstance !== 0 || atoms[0].recLen !== 8)
|
|
12210
|
+
fail2("Invalid NotesAtom");
|
|
12211
|
+
const records = [...direct], stack = direct.filter((r) => r.recVer === 15 || r.recType === OA.ClientTextbox).map((r) => ({ r, depth: 1 }));
|
|
12212
|
+
while (stack.length) {
|
|
12213
|
+
const item = stack.pop();
|
|
12214
|
+
if (item.depth > 128)
|
|
12215
|
+
fail2("Notes nesting budget exceeded");
|
|
12216
|
+
for (const r of children4(item.r)) {
|
|
12217
|
+
records.push(r);
|
|
12218
|
+
if (r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom) {
|
|
12219
|
+
textBytes += r.recLen;
|
|
12220
|
+
if (textBytes > maxTextBytes)
|
|
12221
|
+
fail2("Notes text byte budget exceeded");
|
|
12222
|
+
if (r.recVer !== 0 || r.recInstance !== 0 || r.recType === RT2.TextCharsAtom && r.recLen % 2)
|
|
12223
|
+
fail2("Invalid notes text atom");
|
|
12224
|
+
}
|
|
12225
|
+
if (r.recVer === 15 || r.recType === OA.ClientTextbox)
|
|
12226
|
+
stack.push({ r, depth: item.depth + 1 });
|
|
12227
|
+
}
|
|
12228
|
+
}
|
|
12229
|
+
raw.set(notesId, { header, backref: view2.getUint32(atoms[0].dataOffset, true), records });
|
|
12230
|
+
}
|
|
12231
|
+
const notes = [];
|
|
12232
|
+
for (const slide of slides) {
|
|
12233
|
+
const notesId = links.get(slide.slideId);
|
|
12234
|
+
if (!notesId)
|
|
12235
|
+
continue;
|
|
12236
|
+
const info = raw.get(notesId), persistId = refs.get(notesId);
|
|
12237
|
+
if (!info || persistId === void 0 || info.backref !== slide.slideId)
|
|
12238
|
+
fail2("Notes ID or slide back-reference mismatch");
|
|
12239
|
+
const all = info.records;
|
|
12240
|
+
let notesMirror = false;
|
|
12241
|
+
for (const r of all.filter((r2) => [OA.FOPT, OA.TertiaryFOPT, 61729].includes(r2.recType))) {
|
|
12242
|
+
if (r.recVer !== 3 || r.recInstance * 6 > r.recLen)
|
|
12243
|
+
fail2("Invalid notes property table");
|
|
12244
|
+
for (let i = 0; i < r.recInstance; i++)
|
|
12245
|
+
if ((view2.getUint16(r.dataOffset + i * 6, true) & 16383) === 937)
|
|
12246
|
+
notesMirror = true;
|
|
12247
|
+
}
|
|
12248
|
+
const texts = [], shapeIds = /* @__PURE__ */ new Set();
|
|
12249
|
+
const shapeRecords = [];
|
|
12250
|
+
let activeShape;
|
|
12251
|
+
for (const r of all.sort((a, b) => a.headerOffset - b.headerOffset)) {
|
|
12252
|
+
if (activeShape && r.headerOffset >= activeShape.shape.dataOffset + activeShape.shape.recLen)
|
|
12253
|
+
activeShape = void 0;
|
|
12254
|
+
if (r.recType === OA.SpContainer) {
|
|
12255
|
+
if (activeShape)
|
|
12256
|
+
fail2("Nested notes shape containers");
|
|
12257
|
+
activeShape = { shape: r, within: [] };
|
|
12258
|
+
shapeRecords.push(activeShape);
|
|
12259
|
+
} else if (activeShape)
|
|
12260
|
+
activeShape.within.push(r);
|
|
12261
|
+
}
|
|
12262
|
+
for (const { shape, within } of shapeRecords) {
|
|
12263
|
+
const fsps = within.filter((r) => r.recType === OA.FSP);
|
|
12264
|
+
if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
|
|
12265
|
+
fail2("Invalid notes shape identity");
|
|
12266
|
+
const shapeId = view2.getUint32(fsps[0].dataOffset, true);
|
|
12267
|
+
if (!shapeId || shapeIds.has(shapeId))
|
|
12268
|
+
fail2("Duplicate notes shape identity");
|
|
12269
|
+
shapeIds.add(shapeId);
|
|
12270
|
+
const placeholders = within.filter((r) => r.recType === RT2.OEPlaceholderAtom);
|
|
12271
|
+
if (placeholders.some((r) => r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 8))
|
|
12272
|
+
fail2("Invalid notes PlaceholderAtom");
|
|
12273
|
+
const placeholderId = placeholders.length === 1 ? view2.getUint8(placeholders[0].dataOffset + 4) : void 0;
|
|
12274
|
+
const atoms = within.filter((r) => r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom);
|
|
12275
|
+
const headers = within.filter((r) => r.recType === RT2.TextHeaderAtom);
|
|
12276
|
+
const textboxes = within.filter((r) => r.recType === OA.ClientTextbox);
|
|
12277
|
+
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;
|
|
12278
|
+
for (const atom of atoms) {
|
|
12279
|
+
const wide = atom.recType === RT2.TextCharsAtom;
|
|
12280
|
+
let text = "";
|
|
12281
|
+
for (let p = atom.dataOffset; p < atom.dataOffset + atom.recLen; p += wide ? 2 : 1) {
|
|
12282
|
+
const value = wide ? view2.getUint16(p, true) : view2.getUint8(p);
|
|
12283
|
+
if (!value)
|
|
12284
|
+
fail2("NUL in notes text atom");
|
|
12285
|
+
text += String.fromCharCode(value);
|
|
12286
|
+
}
|
|
12287
|
+
texts.push({
|
|
12288
|
+
shapeId,
|
|
12289
|
+
shapeHeaderOffset: shape.headerOffset,
|
|
12290
|
+
placeholderId,
|
|
12291
|
+
role: body ? "body" : "other",
|
|
12292
|
+
text,
|
|
12293
|
+
headerOffset: atom.headerOffset,
|
|
12294
|
+
encoding: wide ? "utf16" : "compressed-unicode",
|
|
12295
|
+
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
|
|
12296
|
+
});
|
|
12297
|
+
}
|
|
12298
|
+
}
|
|
12299
|
+
notes.push({ slideId: slide.slideId, slidePersistId: slide.persistId, notesId, persistId, headerOffset: info.header.headerOffset, texts });
|
|
12300
|
+
}
|
|
12301
|
+
return { stream, notes };
|
|
12302
|
+
}
|
|
12303
|
+
function readPptSlideNotes(input, limits = {}) {
|
|
12304
|
+
return inspect5(input, limits).notes;
|
|
12305
|
+
}
|
|
12306
|
+
function ownershipRefusal(input, stream, note) {
|
|
12307
|
+
const view2 = viewOf2(stream), user = readCompoundFileStream(input, ["Current User"]);
|
|
12308
|
+
const uv = viewOf2(user), cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12309
|
+
const { directory } = buildPersistDirectory(view2, editOffset);
|
|
12310
|
+
const owned = readRecordOrThrow(view2, note.headerOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12311
|
+
const overlaps = (offset2) => {
|
|
12312
|
+
const other = readRecordOrThrow(view2, offset2), otherEnd = other.dataOffset + other.recLen;
|
|
12313
|
+
if (otherEnd > view2.byteLength)
|
|
12314
|
+
fail2("Unbounded live persist object prevents safe notes edit");
|
|
12315
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12316
|
+
};
|
|
12317
|
+
for (const [persistId, offset2] of directory) {
|
|
12318
|
+
if (persistId !== note.persistId && overlaps(offset2))
|
|
12319
|
+
return "Notes container overlaps another live persist object";
|
|
12320
|
+
}
|
|
12321
|
+
let offset = editOffset;
|
|
12322
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12323
|
+
while (offset) {
|
|
12324
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12325
|
+
return "Invalid notes save-history ownership";
|
|
12326
|
+
visited.add(offset);
|
|
12327
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12328
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12329
|
+
return "Notes container overlaps save-history metadata";
|
|
12330
|
+
offset = edit.offsetLastEdit;
|
|
12331
|
+
}
|
|
12332
|
+
return void 0;
|
|
12333
|
+
}
|
|
12334
|
+
function editPptNotesText(input, edit) {
|
|
12335
|
+
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
12336
|
+
try {
|
|
12337
|
+
const { slideId, slidePersistId, notesId, persistId, shapeId, expectedHeaderOffset, expectedText, text } = edit;
|
|
12338
|
+
if (typeof text !== "string" || typeof expectedText !== "string")
|
|
12339
|
+
return reject2("Notes replacement must be a string");
|
|
12340
|
+
const { stream, notes } = inspect5(input);
|
|
12341
|
+
const selected = notes.filter((n) => n.slideId === slideId && n.slidePersistId === slidePersistId && n.notesId === notesId && n.persistId === persistId);
|
|
12342
|
+
const matches = selected.length === 1 ? selected[0].texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset) : [];
|
|
12343
|
+
const atom = matches[0];
|
|
12344
|
+
if (matches.length !== 1 || !atom || atom.text !== expectedText)
|
|
12345
|
+
return reject2("Notes identity or expected text no longer matches");
|
|
12346
|
+
if (text === atom.text)
|
|
12347
|
+
return { status: "unchanged", bytes: input };
|
|
12348
|
+
if (atom.editRefusal)
|
|
12349
|
+
return reject2(atom.editRefusal);
|
|
12350
|
+
const ownership = ownershipRefusal(input, stream, selected[0]);
|
|
12351
|
+
if (ownership)
|
|
12352
|
+
return reject2(ownership);
|
|
12353
|
+
if (notes.reduce((n, note) => n + note.texts.filter((t) => t.headerOffset === atom.headerOffset).length, 0) !== 1)
|
|
12354
|
+
return reject2("Notes text atom is shared by active locations");
|
|
12355
|
+
const start = atom.headerOffset, end = start + 8 + atom.text.length * (atom.encoding === "utf16" ? 2 : 1);
|
|
12356
|
+
for (const slide of readPptSlideTexts(input).slides)
|
|
12357
|
+
for (const text2 of slide.texts) {
|
|
12358
|
+
const textEnd = text2.headerOffset + 8 + text2.text.length * (text2.encoding === "utf16" ? 2 : 1);
|
|
12359
|
+
if (start < textEnd && text2.headerOffset < end)
|
|
12360
|
+
return reject2("Notes slot overlaps active slide text");
|
|
12361
|
+
}
|
|
12362
|
+
if (text.length !== atom.text.length)
|
|
12363
|
+
return reject2("Notes replacement must keep the UTF-16 character count");
|
|
12364
|
+
for (let i = 0; i < text.length; i++) {
|
|
12365
|
+
const old = atom.text.charCodeAt(i), value = text.charCodeAt(i);
|
|
12366
|
+
if (!value || (old < 32 || value < 32 || old === 42 || value === 42) && old !== value)
|
|
12367
|
+
return reject2("Notes controls and field markers must remain at the same offsets");
|
|
12368
|
+
if (atom.encoding === "compressed-unicode" && value > 255)
|
|
12369
|
+
return reject2("Notes character does not fit existing encoding");
|
|
12370
|
+
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))
|
|
12371
|
+
return reject2("Unpaired notes UTF-16 surrogate");
|
|
12372
|
+
}
|
|
12373
|
+
const next = stream.slice(), view2 = viewOf2(next);
|
|
12374
|
+
for (let i = 0; i < text.length; i++) {
|
|
12375
|
+
if (atom.encoding === "utf16")
|
|
12376
|
+
view2.setUint16(atom.headerOffset + 8 + i * 2, text.charCodeAt(i), true);
|
|
12377
|
+
else
|
|
12378
|
+
next[atom.headerOffset + 8 + i] = text.charCodeAt(i);
|
|
12379
|
+
}
|
|
12380
|
+
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], next);
|
|
12381
|
+
if (bytes === input)
|
|
12382
|
+
return reject2("Notes compound stream cannot be safely replaced");
|
|
12383
|
+
const candidate = inspect5(bytes).notes.find((n) => n.slideId === slideId && n.notesId === notesId && n.persistId === persistId);
|
|
12384
|
+
const confirmed = candidate?.texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset);
|
|
12385
|
+
if (confirmed?.length !== 1 || confirmed[0].text !== text)
|
|
12386
|
+
return reject2("Candidate notes revalidation failed");
|
|
12387
|
+
return { status: "edited", bytes };
|
|
12388
|
+
} catch (error) {
|
|
12389
|
+
return reject2(error instanceof Error ? error.message : "Malformed PPT notes");
|
|
12390
|
+
}
|
|
12391
|
+
}
|
|
12392
|
+
|
|
12393
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text-style.js
|
|
12394
|
+
var viewOf3 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
12395
|
+
var MAX_RECORDS = 1e5;
|
|
12396
|
+
var MAX_RUNS = 2e4;
|
|
12397
|
+
var MAX_STYLE_BYTES = 16 * 1024 * 1024;
|
|
12398
|
+
function children3(view2, parent) {
|
|
12399
|
+
const result = [], end = parent.dataOffset + parent.recLen;
|
|
12400
|
+
if (end > view2.byteLength)
|
|
12401
|
+
throw new Error("Unbounded formatting parent");
|
|
12402
|
+
for (let offset = parent.dataOffset; offset < end; ) {
|
|
12403
|
+
if (result.length >= MAX_RECORDS || end - offset < 8)
|
|
12404
|
+
throw new Error("Formatting record bounds exceeded");
|
|
12405
|
+
const record5 = readRecordOrThrow(view2, offset);
|
|
12406
|
+
if (record5.dataOffset + record5.recLen > end)
|
|
12407
|
+
throw new Error("Formatting child exceeds its parent");
|
|
12408
|
+
result.push(record5);
|
|
12409
|
+
offset = record5.dataOffset + record5.recLen;
|
|
12410
|
+
}
|
|
12411
|
+
return result;
|
|
12412
|
+
}
|
|
12413
|
+
function decodeStyle(view2, style, textLength, budget) {
|
|
12414
|
+
if (style.recVer !== 0 || style.recInstance !== 0)
|
|
12415
|
+
throw new Error("Invalid StyleTextPropAtom header");
|
|
12416
|
+
let pos = style.dataOffset;
|
|
12417
|
+
const end = pos + style.recLen, total = textLength + 1;
|
|
12418
|
+
const take = (bytes) => {
|
|
12419
|
+
if (bytes > end - pos)
|
|
12420
|
+
throw new Error("Truncated formatting exception");
|
|
12421
|
+
const offset = pos;
|
|
12422
|
+
pos += bytes;
|
|
12423
|
+
return offset;
|
|
12424
|
+
};
|
|
12425
|
+
const u16 = () => view2.getUint16(take(2), true), u32 = () => view2.getUint32(take(4), true);
|
|
12426
|
+
const count = (sum) => {
|
|
12427
|
+
if (++budget.runs > budget.maxRuns)
|
|
12428
|
+
throw new Error("Character/paragraph run budget exceeded");
|
|
12429
|
+
const value = u32();
|
|
12430
|
+
if (value === 0 || value > total - sum)
|
|
12431
|
+
throw new Error("Invalid formatting run count");
|
|
12432
|
+
return value;
|
|
12433
|
+
};
|
|
12434
|
+
for (let sum = 0; sum < total; ) {
|
|
12435
|
+
sum += count(sum);
|
|
12436
|
+
if (u16() > 4)
|
|
12437
|
+
throw new Error("Invalid paragraph indentation");
|
|
12438
|
+
const mask = u32();
|
|
12439
|
+
if (mask & -3111680)
|
|
12440
|
+
throw new Error("Unsupported paragraph formatting mask");
|
|
12441
|
+
if (mask & 15)
|
|
12442
|
+
take(2);
|
|
12443
|
+
for (const bit of [128, 16, 64])
|
|
12444
|
+
if (mask & bit)
|
|
12445
|
+
take(2);
|
|
12446
|
+
if (mask & 32)
|
|
12447
|
+
take(4);
|
|
12448
|
+
for (const bit of [2048, 4096, 8192, 16384, 65536])
|
|
12449
|
+
if (mask & bit)
|
|
12450
|
+
take(2);
|
|
12451
|
+
if (mask & 917504)
|
|
12452
|
+
take(2);
|
|
12453
|
+
if (mask & 2097152)
|
|
12454
|
+
take(2);
|
|
12455
|
+
}
|
|
12456
|
+
const result = [];
|
|
12457
|
+
for (let sum = 0; sum < total; ) {
|
|
12458
|
+
const runOffset = pos, rawCount = count(sum), start = sum;
|
|
12459
|
+
sum += rawCount;
|
|
12460
|
+
const mask = u32();
|
|
12461
|
+
if (mask & -15728640)
|
|
12462
|
+
throw new Error("Unsupported character formatting mask");
|
|
12463
|
+
if (mask & 16055)
|
|
12464
|
+
take(2);
|
|
12465
|
+
for (const bit of [65536, 2097152, 4194304, 8388608])
|
|
12466
|
+
if (mask & bit)
|
|
12467
|
+
take(2);
|
|
12468
|
+
let fontSizeOffset, directFontSizePoints;
|
|
12469
|
+
if (mask & 131072) {
|
|
12470
|
+
fontSizeOffset = take(2);
|
|
12471
|
+
directFontSizePoints = view2.getInt16(fontSizeOffset, true);
|
|
12472
|
+
if (directFontSizePoints < 1 || directFontSizePoints > 4e3)
|
|
12473
|
+
throw new Error("Invalid literal font size");
|
|
12474
|
+
}
|
|
12475
|
+
if (mask & 262144)
|
|
12476
|
+
take(4);
|
|
12477
|
+
if (mask & 524288) {
|
|
12478
|
+
const position = view2.getInt16(take(2), true);
|
|
12479
|
+
if (position < -100 || position > 100)
|
|
12480
|
+
throw new Error("Invalid baseline position");
|
|
12481
|
+
}
|
|
12482
|
+
result.push({
|
|
12483
|
+
start: Math.min(start, textLength),
|
|
12484
|
+
end: Math.min(sum, textLength),
|
|
12485
|
+
rawCount,
|
|
12486
|
+
mask,
|
|
12487
|
+
styleHeaderOffset: style.headerOffset,
|
|
12488
|
+
runOffset,
|
|
12489
|
+
fontSizeOffset,
|
|
12490
|
+
directFontSizePoints
|
|
12491
|
+
});
|
|
12492
|
+
}
|
|
12493
|
+
if (pos !== end)
|
|
12494
|
+
throw new Error("Unconsumed StyleTextPropAtom bytes");
|
|
12495
|
+
return result;
|
|
12496
|
+
}
|
|
12497
|
+
function textOwnershipRefusal2(input, stream, persistId, atom) {
|
|
12498
|
+
const user = readCompoundFileStream(input, ["Current User"]);
|
|
12499
|
+
if (!user)
|
|
12500
|
+
throw new PptParseError("Missing Current User stream");
|
|
12501
|
+
const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
|
|
12502
|
+
const editOffset = uv.getUint32(cu.dataOffset + 8, true);
|
|
12503
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
|
|
12504
|
+
const slideOffset = directory.get(persistId);
|
|
12505
|
+
if (slideOffset === void 0)
|
|
12506
|
+
return "Missing active slide persist object";
|
|
12507
|
+
const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
|
|
12508
|
+
const textEnd = text.dataOffset + text.recLen;
|
|
12509
|
+
const owners = [persistId];
|
|
12510
|
+
if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
|
|
12511
|
+
const docOffset = directory.get(currentEdit.docPersistIdRef);
|
|
12512
|
+
if (docOffset === void 0)
|
|
12513
|
+
return "Missing outline text owner";
|
|
12514
|
+
const doc = readRecordOrThrow(view2, docOffset);
|
|
12515
|
+
if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
|
|
12516
|
+
return "Text is outside its active owning containers";
|
|
12517
|
+
owners.push(currentEdit.docPersistIdRef);
|
|
12518
|
+
}
|
|
12519
|
+
for (const ownerId of owners) {
|
|
12520
|
+
const owned = readRecordOrThrow(view2, directory.get(ownerId));
|
|
12521
|
+
const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
|
|
12522
|
+
if (end > view2.byteLength)
|
|
12523
|
+
return "Unbounded text owning persist object";
|
|
12524
|
+
const overlaps = (offset) => {
|
|
12525
|
+
const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
|
|
12526
|
+
if (otherEnd > view2.byteLength)
|
|
12527
|
+
throw new PptParseError("Unbounded live persist object prevents safe text edit");
|
|
12528
|
+
return start < otherEnd && other.headerOffset < end;
|
|
12529
|
+
};
|
|
12530
|
+
for (const [id, offset] of directory)
|
|
12531
|
+
if (id !== ownerId && overlaps(offset))
|
|
12532
|
+
return "Text owning container overlaps another live persist object";
|
|
12533
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12534
|
+
for (let offset = editOffset; offset; ) {
|
|
12535
|
+
if (visited.has(offset) || visited.size >= 1e4)
|
|
12536
|
+
return "Invalid text save-history ownership";
|
|
12537
|
+
visited.add(offset);
|
|
12538
|
+
const edit = parseUserEditAtom(view2, offset);
|
|
12539
|
+
if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
|
|
12540
|
+
return "Text owning container overlaps save-history metadata";
|
|
12541
|
+
offset = edit.offsetLastEdit;
|
|
12542
|
+
}
|
|
12543
|
+
}
|
|
12544
|
+
return void 0;
|
|
12545
|
+
}
|
|
12546
|
+
function readPptCharacterRuns(input, limits = {}) {
|
|
12547
|
+
const maxRecords = limits.maxRecords ?? MAX_RECORDS, maxRuns = limits.maxRuns ?? MAX_RUNS, maxStyleBytes = limits.maxStyleBytes ?? MAX_STYLE_BYTES;
|
|
12548
|
+
if (![maxRecords, maxRuns, maxStyleBytes].every((value) => Number.isSafeInteger(value) && value > 0))
|
|
12549
|
+
throw new Error("Invalid character-format resource limit");
|
|
12550
|
+
readPptSlideShapes(input, { maxRecords });
|
|
12551
|
+
const texts = readPptSlideTexts(input), stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
|
|
12552
|
+
const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
|
|
12553
|
+
const { directory, currentEdit } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true));
|
|
12554
|
+
const associations = /* @__PURE__ */ new Map();
|
|
12555
|
+
let records = 0, styleBytes = 0;
|
|
12556
|
+
const scan = (root) => {
|
|
12557
|
+
const stack = [{ record: root, depth: 0 }];
|
|
12558
|
+
while (stack.length) {
|
|
12559
|
+
const { record: record5, depth } = stack.pop();
|
|
12560
|
+
if (depth > 128)
|
|
12561
|
+
throw new Error("Formatting nesting exceeds limit");
|
|
12562
|
+
const list = children3(view2, record5);
|
|
12563
|
+
records += list.length;
|
|
12564
|
+
if (records > maxRecords)
|
|
12565
|
+
throw new Error("Formatting record budget exceeded");
|
|
12566
|
+
let group;
|
|
12567
|
+
const textParent = record5.recType === OA.ClientTextbox || record5.recType === RT2.SlideListWithText && record5.recInstance === 0;
|
|
12568
|
+
const finish = () => {
|
|
12569
|
+
if (group)
|
|
12570
|
+
for (const atom of group.atoms) {
|
|
12571
|
+
if (associations.has(atom))
|
|
12572
|
+
throw new Error("Ambiguous formatting parent");
|
|
12573
|
+
associations.set(atom, { styles: group.styles, textCount: group.atoms.length });
|
|
12574
|
+
}
|
|
12575
|
+
};
|
|
12576
|
+
for (const child2 of list) {
|
|
12577
|
+
if (textParent && (child2.recType === RT2.TextHeaderAtom || child2.recType === RT2.SlidePersistAtom)) {
|
|
12578
|
+
finish();
|
|
12579
|
+
group = child2.recType === RT2.TextHeaderAtom ? { atoms: [], styles: [] } : void 0;
|
|
12580
|
+
if (group && (child2.recVer !== 0 || child2.recInstance > (record5.recType === OA.ClientTextbox ? 0 : 5) || child2.recLen !== 4))
|
|
12581
|
+
throw new Error("Invalid formatting TextHeaderAtom");
|
|
12582
|
+
} else if (group && (child2.recType === RT2.TextCharsAtom || child2.recType === RT2.TextBytesAtom))
|
|
12583
|
+
group.atoms.push(child2.headerOffset);
|
|
12584
|
+
else if (group && child2.recType === RT2.StyleTextPropAtom) {
|
|
12585
|
+
styleBytes += child2.recLen;
|
|
12586
|
+
if (styleBytes > maxStyleBytes)
|
|
12587
|
+
throw new Error("Formatting payload budget exceeded");
|
|
12588
|
+
group.styles.push(child2);
|
|
12589
|
+
}
|
|
12590
|
+
if (child2.recVer === 15 || child2.recType === OA.ClientTextbox)
|
|
12591
|
+
stack.push({ record: child2, depth: depth + 1 });
|
|
12592
|
+
}
|
|
12593
|
+
finish();
|
|
12594
|
+
}
|
|
12595
|
+
};
|
|
12596
|
+
let scanDiagnostic;
|
|
12597
|
+
try {
|
|
12598
|
+
const doc = readRecordOrThrow(view2, directory.get(currentEdit.docPersistIdRef));
|
|
12599
|
+
for (const list of children3(view2, doc))
|
|
12600
|
+
if (list.recType === RT2.SlideListWithText && list.recInstance === 0)
|
|
12601
|
+
scan(list);
|
|
12602
|
+
const visited = /* @__PURE__ */ new Set();
|
|
12603
|
+
for (const slide of texts.slides) {
|
|
12604
|
+
const offset = directory.get(slide.persistId);
|
|
12605
|
+
if (!visited.has(offset)) {
|
|
12606
|
+
visited.add(offset);
|
|
12607
|
+
scan(readRecordOrThrow(view2, offset));
|
|
12608
|
+
}
|
|
12609
|
+
}
|
|
12610
|
+
} catch (error) {
|
|
12611
|
+
scanDiagnostic = error instanceof Error ? error.message : "Unsupported formatting graph";
|
|
12612
|
+
}
|
|
12613
|
+
const budget = { runs: 0, maxRuns };
|
|
12614
|
+
return texts.slides.flatMap((slide) => slide.texts.map((atom) => {
|
|
12615
|
+
const base = { slideId: slide.slideId, persistId: slide.persistId, headerOffset: atom.headerOffset, text: atom.text };
|
|
12616
|
+
if (scanDiagnostic)
|
|
12617
|
+
return { ...base, status: "unsupported", diagnostic: scanDiagnostic, runs: [] };
|
|
12618
|
+
const group = associations.get(atom.headerOffset);
|
|
12619
|
+
if (!group)
|
|
12620
|
+
return { ...base, status: "unsupported", diagnostic: "Text has no unambiguous TextHeader formatting parent", runs: [] };
|
|
12621
|
+
if (!group.styles.length)
|
|
12622
|
+
return { ...base, status: "absent", runs: [] };
|
|
12623
|
+
if (group.textCount !== 1 || group.styles.length !== 1)
|
|
12624
|
+
return { ...base, status: "unsupported", diagnostic: "Text or style atom association is ambiguous", runs: [] };
|
|
12625
|
+
try {
|
|
12626
|
+
return { ...base, status: "decoded", runs: decodeStyle(view2, group.styles[0], atom.text.length, budget) };
|
|
12627
|
+
} catch (error) {
|
|
12628
|
+
return { ...base, status: "unsupported", diagnostic: error instanceof Error ? error.message : "Unsupported formatting", runs: [] };
|
|
12629
|
+
}
|
|
12630
|
+
}));
|
|
12631
|
+
}
|
|
12632
|
+
function editPptCharacterFontSize(input, edit) {
|
|
12633
|
+
const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
|
|
12634
|
+
try {
|
|
12635
|
+
const { slideId, persistId, headerOffset, runOffset, styleHeaderOffset, start, end, expectedFontSizePoints, fontSizePoints } = edit;
|
|
12636
|
+
const matches = readPptCharacterRuns(input).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
|
|
12637
|
+
const record5 = matches.length === 1 ? matches[0] : void 0;
|
|
12638
|
+
const runs = record5?.status === "decoded" ? record5.runs.filter((run2) => run2.runOffset === runOffset && run2.styleHeaderOffset === styleHeaderOffset && run2.start === start && run2.end === end) : [];
|
|
12639
|
+
const run = runs.length === 1 ? runs[0] : void 0;
|
|
12640
|
+
if (!run || run.directFontSizePoints !== expectedFontSizePoints)
|
|
12641
|
+
return reject2(record5?.diagnostic ?? "Character run identity or expected font size does not match");
|
|
12642
|
+
if (fontSizePoints === run.directFontSizePoints)
|
|
12643
|
+
return { status: "unchanged", bytes: input };
|
|
12644
|
+
if (run.start === run.end)
|
|
12645
|
+
return reject2("Run covers only the implicit paragraph mark");
|
|
12646
|
+
if (run.fontSizeOffset === void 0)
|
|
12647
|
+
return reject2("Font size is inherited; no existing literal slot");
|
|
12648
|
+
if (!Number.isSafeInteger(fontSizePoints) || fontSizePoints < 1 || fontSizePoints > 4e3)
|
|
12649
|
+
return reject2("Literal font size must be an integer from 1 to 4000 points");
|
|
12650
|
+
const textModel = readPptSlideTexts(input), slides = textModel.slides.filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
|
|
12651
|
+
const indexes = slides.length === 1 ? slides[0].texts.flatMap((atom, index) => atom.headerOffset === headerOffset ? [index] : []) : [];
|
|
12652
|
+
if (indexes.length !== 1 || textModel.slides.reduce((count, slide) => count + slide.texts.filter((atom) => atom.headerOffset === headerOffset).length, 0) !== 1)
|
|
12653
|
+
return reject2("Text atom is shared by multiple active slide positions");
|
|
12654
|
+
const shapeSlides = readPptSlideShapes(input).filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
|
|
12655
|
+
const shapes = shapeSlides.length === 1 ? shapeSlides[0].shapes.filter((shape) => shape.textReference === "inline" && shape.textIndexes.includes(indexes[0])) : [];
|
|
12656
|
+
if (shapes.length !== 1 || shapes[0].kind !== "text-box")
|
|
12657
|
+
return reject2("Font-size edits require uniquely linked inline text-box text");
|
|
12658
|
+
if (shapes[0].geometryRefusal)
|
|
12659
|
+
return reject2(`Unsupported text-box formatting context: ${shapes[0].geometryRefusal}`);
|
|
12660
|
+
const originalStream = readCompoundFileStream(input, ["PowerPoint Document"]);
|
|
12661
|
+
const refusal = textOwnershipRefusal2(input, originalStream, persistId, slides[0].texts[indexes[0]]);
|
|
12662
|
+
if (refusal)
|
|
12663
|
+
return reject2(refusal);
|
|
12664
|
+
const stream = readCompoundFileStream(input, ["PowerPoint Document"]).slice();
|
|
12665
|
+
viewOf3(stream).setInt16(run.fontSizeOffset, fontSizePoints, true);
|
|
12666
|
+
const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], stream);
|
|
12667
|
+
if (bytes === input)
|
|
12668
|
+
return reject2("Compound stream cannot be safely replaced");
|
|
12669
|
+
const candidate = readPptCharacterRuns(bytes).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
|
|
12670
|
+
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;
|
|
12671
|
+
if (!next || next.directFontSizePoints !== fontSizePoints || candidate[0].text !== record5.text)
|
|
12672
|
+
return reject2("Edited character run failed candidate validation");
|
|
12673
|
+
return { status: "edited", bytes };
|
|
12674
|
+
} catch (error) {
|
|
12675
|
+
return reject2(error instanceof Error ? error.message : "Malformed PPT formatting");
|
|
12676
|
+
}
|
|
12677
|
+
}
|
|
12678
|
+
|
|
12679
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt-document.js
|
|
11469
12680
|
var PPT_CAPABILITIES = Object.freeze({
|
|
11470
|
-
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"]),
|
|
11471
|
-
write: Object.freeze(["existing-text-fixed-utf16-length", "unmirrored-top-level-small-anchor-bounds"]),
|
|
11472
|
-
limitations: Object.freeze(["unresolved-outline-shape-text", "
|
|
12681
|
+
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"]),
|
|
12682
|
+
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"]),
|
|
12683
|
+
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"])
|
|
11473
12684
|
});
|
|
12685
|
+
var RUN_LOOKUPS = /* @__PURE__ */ new WeakMap();
|
|
12686
|
+
function resolveCharacterRun(record5, original) {
|
|
12687
|
+
let lookup = RUN_LOOKUPS.get(record5);
|
|
12688
|
+
if (!lookup) {
|
|
12689
|
+
lookup = /* @__PURE__ */ new Map();
|
|
12690
|
+
for (const run2 of record5.runs) {
|
|
12691
|
+
const bucket = lookup.get(run2.runOffset);
|
|
12692
|
+
if (bucket)
|
|
12693
|
+
bucket.push(run2);
|
|
12694
|
+
else
|
|
12695
|
+
lookup.set(run2.runOffset, [run2]);
|
|
12696
|
+
}
|
|
12697
|
+
RUN_LOOKUPS.set(record5, lookup);
|
|
12698
|
+
}
|
|
12699
|
+
const matches = record5.status === "decoded" ? lookup.get(original.runOffset) : void 0, run = matches?.[0];
|
|
12700
|
+
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)
|
|
12701
|
+
throw new UnsupportedOle2EditError("PPT character run identity no longer matches or is ambiguous");
|
|
12702
|
+
return run;
|
|
12703
|
+
}
|
|
12704
|
+
var textRunKey = (node) => `${node.slideId}:${node.persistId}:${node.headerOffset}`;
|
|
11474
12705
|
var PptText = class {
|
|
11475
12706
|
slideId;
|
|
11476
12707
|
persistId;
|
|
@@ -11480,7 +12711,10 @@ var PptText = class {
|
|
|
11480
12711
|
headerOffset;
|
|
11481
12712
|
#text;
|
|
11482
12713
|
#write;
|
|
11483
|
-
|
|
12714
|
+
#readRuns;
|
|
12715
|
+
#writeRun;
|
|
12716
|
+
#runs;
|
|
12717
|
+
constructor(identity, atom, write, readRuns, writeRun) {
|
|
11484
12718
|
this.slideId = identity.slideId;
|
|
11485
12719
|
this.persistId = identity.persistId;
|
|
11486
12720
|
this.textIndex = identity.textIndex;
|
|
@@ -11488,6 +12722,10 @@ var PptText = class {
|
|
|
11488
12722
|
this.headerOffset = atom.headerOffset;
|
|
11489
12723
|
this.#text = atom.text;
|
|
11490
12724
|
this.#write = write;
|
|
12725
|
+
this.#readRuns = readRuns ?? (() => ({ ...identity, headerOffset: atom.headerOffset, text: this.#text, status: "unsupported", diagnostic: "Text has no document formatting owner", runs: [] }));
|
|
12726
|
+
this.#writeRun = writeRun ?? (() => {
|
|
12727
|
+
throw new UnsupportedOle2EditError("Text has no document formatting owner");
|
|
12728
|
+
});
|
|
11491
12729
|
Object.freeze(this);
|
|
11492
12730
|
}
|
|
11493
12731
|
get text() {
|
|
@@ -11499,8 +12737,50 @@ var PptText = class {
|
|
|
11499
12737
|
this.#write(this, value);
|
|
11500
12738
|
this.#text = value;
|
|
11501
12739
|
}
|
|
12740
|
+
get runsStatus() {
|
|
12741
|
+
return this.#readRuns(this).status;
|
|
12742
|
+
}
|
|
12743
|
+
get runsDiagnostic() {
|
|
12744
|
+
return this.#readRuns(this).diagnostic;
|
|
12745
|
+
}
|
|
12746
|
+
/** Direct character exceptions only; inherited/effective formatting is unresolved. */
|
|
11502
12747
|
get runs() {
|
|
11503
|
-
|
|
12748
|
+
if (!this.#runs) {
|
|
12749
|
+
const model2 = this.#readRuns(this);
|
|
12750
|
+
this.#runs = Object.freeze(model2.runs.map((run) => new PptCharacterRun(run, () => {
|
|
12751
|
+
const current = this.#readRuns(this);
|
|
12752
|
+
return { text: current.text, run: resolveCharacterRun(current, run) };
|
|
12753
|
+
}, (value) => this.#writeRun(this, run, value))));
|
|
12754
|
+
}
|
|
12755
|
+
return this.#runs;
|
|
12756
|
+
}
|
|
12757
|
+
};
|
|
12758
|
+
var PptCharacterRun = class {
|
|
12759
|
+
start;
|
|
12760
|
+
end;
|
|
12761
|
+
styleHeaderOffset;
|
|
12762
|
+
runOffset;
|
|
12763
|
+
#read;
|
|
12764
|
+
#write;
|
|
12765
|
+
constructor(record5, read, write) {
|
|
12766
|
+
this.start = record5.start;
|
|
12767
|
+
this.end = record5.end;
|
|
12768
|
+
this.styleHeaderOffset = record5.styleHeaderOffset;
|
|
12769
|
+
this.runOffset = record5.runOffset;
|
|
12770
|
+
this.#read = read;
|
|
12771
|
+
this.#write = write;
|
|
12772
|
+
Object.freeze(this);
|
|
12773
|
+
}
|
|
12774
|
+
get text() {
|
|
12775
|
+
return this.#read().text.slice(this.start, this.end);
|
|
12776
|
+
}
|
|
12777
|
+
get directFontSizePoints() {
|
|
12778
|
+
return this.#read().run.directFontSizePoints;
|
|
12779
|
+
}
|
|
12780
|
+
set directFontSizePoints(value) {
|
|
12781
|
+
if (value !== void 0 && typeof value !== "number")
|
|
12782
|
+
throw new UnsupportedOle2EditError("PPT direct font size must be numeric");
|
|
12783
|
+
this.#write(value);
|
|
11504
12784
|
}
|
|
11505
12785
|
};
|
|
11506
12786
|
var PptSlide = class {
|
|
@@ -11511,15 +12791,71 @@ var PptSlide = class {
|
|
|
11511
12791
|
/** Flat OfficeArt preorder, including group descendants with parentGroupId.
|
|
11512
12792
|
* Canvas patriarchs/background structures remain preserved outside this list. */
|
|
11513
12793
|
shapes;
|
|
11514
|
-
|
|
12794
|
+
/** Existing active notes; undefined when the slide has a null notes reference. */
|
|
12795
|
+
notes;
|
|
12796
|
+
notesStatus;
|
|
12797
|
+
/** A decode refusal is distinct from a null notes reference. Bytes remain opaque. */
|
|
12798
|
+
notesDiagnostic;
|
|
12799
|
+
constructor(slideId, persistId, texts, shapes = [], notes, notesDiagnostic) {
|
|
11515
12800
|
this.slideId = slideId;
|
|
11516
12801
|
this.persistId = persistId;
|
|
11517
12802
|
this.texts = Object.freeze([...texts]);
|
|
11518
12803
|
this.shapes = Object.freeze([...shapes]);
|
|
12804
|
+
this.notes = notes;
|
|
12805
|
+
this.notesDiagnostic = notesDiagnostic;
|
|
12806
|
+
this.notesStatus = notesDiagnostic ? "unsupported" : notes ? "present" : "absent";
|
|
12807
|
+
Object.freeze(this);
|
|
12808
|
+
}
|
|
12809
|
+
};
|
|
12810
|
+
var PptNoteText = class {
|
|
12811
|
+
shapeId;
|
|
12812
|
+
headerOffset;
|
|
12813
|
+
#read;
|
|
12814
|
+
#write;
|
|
12815
|
+
constructor(atom, read, write) {
|
|
12816
|
+
this.shapeId = atom.shapeId;
|
|
12817
|
+
this.headerOffset = atom.headerOffset;
|
|
12818
|
+
this.#read = read;
|
|
12819
|
+
this.#write = write;
|
|
11519
12820
|
Object.freeze(this);
|
|
11520
12821
|
}
|
|
11521
|
-
get
|
|
11522
|
-
|
|
12822
|
+
get text() {
|
|
12823
|
+
return this.#read().text;
|
|
12824
|
+
}
|
|
12825
|
+
set text(value) {
|
|
12826
|
+
if (typeof value !== "string")
|
|
12827
|
+
throw new UnsupportedOle2EditError("Notes replacement must be a string");
|
|
12828
|
+
this.#write(value);
|
|
12829
|
+
}
|
|
12830
|
+
get role() {
|
|
12831
|
+
return this.#read().role;
|
|
12832
|
+
}
|
|
12833
|
+
get placeholderId() {
|
|
12834
|
+
return this.#read().placeholderId;
|
|
12835
|
+
}
|
|
12836
|
+
get encoding() {
|
|
12837
|
+
return this.#read().encoding;
|
|
12838
|
+
}
|
|
12839
|
+
get editRefusal() {
|
|
12840
|
+
return this.#read().editRefusal;
|
|
12841
|
+
}
|
|
12842
|
+
get runs() {
|
|
12843
|
+
throw new UnsupportedOle2EditError("PPT notes rich-text runs are preserved but not decoded");
|
|
12844
|
+
}
|
|
12845
|
+
};
|
|
12846
|
+
var PptNotes = class {
|
|
12847
|
+
slideId;
|
|
12848
|
+
slidePersistId;
|
|
12849
|
+
notesId;
|
|
12850
|
+
persistId;
|
|
12851
|
+
texts;
|
|
12852
|
+
constructor(record5, texts) {
|
|
12853
|
+
this.slideId = record5.slideId;
|
|
12854
|
+
this.slidePersistId = record5.slidePersistId;
|
|
12855
|
+
this.notesId = record5.notesId;
|
|
12856
|
+
this.persistId = record5.persistId;
|
|
12857
|
+
this.texts = Object.freeze([...texts]);
|
|
12858
|
+
Object.freeze(this);
|
|
11523
12859
|
}
|
|
11524
12860
|
};
|
|
11525
12861
|
var PptShape = class {
|
|
@@ -11532,13 +12868,13 @@ var PptShape = class {
|
|
|
11532
12868
|
texts;
|
|
11533
12869
|
#read;
|
|
11534
12870
|
#write;
|
|
11535
|
-
constructor(identity,
|
|
12871
|
+
constructor(identity, record5, texts, read, write) {
|
|
11536
12872
|
this.slideId = identity.slideId;
|
|
11537
12873
|
this.persistId = identity.persistId;
|
|
11538
|
-
this.shapeId =
|
|
11539
|
-
this.headerOffset =
|
|
11540
|
-
this.flags =
|
|
11541
|
-
this.shapeType =
|
|
12874
|
+
this.shapeId = record5.shapeId;
|
|
12875
|
+
this.headerOffset = record5.headerOffset;
|
|
12876
|
+
this.flags = record5.flags;
|
|
12877
|
+
this.shapeType = record5.shapeType;
|
|
11542
12878
|
this.texts = Object.freeze([...texts]);
|
|
11543
12879
|
this.#read = read;
|
|
11544
12880
|
this.#write = write;
|
|
@@ -11628,6 +12964,9 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11628
12964
|
#slides;
|
|
11629
12965
|
#unsupported;
|
|
11630
12966
|
#shapeCache;
|
|
12967
|
+
#notesCache;
|
|
12968
|
+
#runsCache;
|
|
12969
|
+
#validatedTextRuns = /* @__PURE__ */ new WeakMap();
|
|
11631
12970
|
get slides() {
|
|
11632
12971
|
return this.#slides;
|
|
11633
12972
|
}
|
|
@@ -11638,14 +12977,102 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11638
12977
|
super(input);
|
|
11639
12978
|
const shapeModel = readPptSlideShapes(this.getBytes());
|
|
11640
12979
|
const model2 = readPptSlideTexts(this.getBytes());
|
|
12980
|
+
let notesModel = [], notesDiagnostic;
|
|
12981
|
+
try {
|
|
12982
|
+
notesModel = readPptSlideNotes(this.getBytes());
|
|
12983
|
+
} catch (error) {
|
|
12984
|
+
notesDiagnostic = error instanceof Error ? error.message : "Notes decoding unsupported";
|
|
12985
|
+
}
|
|
11641
12986
|
this.#shapeCache = { revision: this.revision, slides: shapeModel };
|
|
11642
|
-
this.#
|
|
12987
|
+
this.#notesCache = { revision: this.revision, notes: notesModel };
|
|
12988
|
+
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"] : []]);
|
|
11643
12989
|
this.#slides = Object.freeze(model2.slides.map((slide, index) => {
|
|
11644
|
-
const texts = slide.texts.map((atom, textIndex) => new PptText({ slideId: slide.slideId, persistId: slide.persistId, textIndex }, atom, (node, value) => this.#edit(node, value)));
|
|
11645
|
-
const shapes = shapeModel[index].shapes.map((
|
|
11646
|
-
|
|
12990
|
+
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)));
|
|
12991
|
+
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)));
|
|
12992
|
+
const record5 = notesModel.find((note) => note.slideId === slide.slideId && note.slidePersistId === slide.persistId);
|
|
12993
|
+
const notes = record5 && new PptNotes(record5, record5.texts.map((atom) => new PptNoteText(atom, () => this.#readNote(record5, atom), (value) => this.#editNote(record5, atom, value))));
|
|
12994
|
+
return new PptSlide(slide.slideId, slide.persistId, texts, shapes, notes, notesDiagnostic);
|
|
11647
12995
|
}));
|
|
11648
12996
|
}
|
|
12997
|
+
#readTextRuns(node) {
|
|
12998
|
+
if (!this.#runsCache || this.#runsCache.revision !== this.revision) {
|
|
12999
|
+
const revision = this.revision;
|
|
13000
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
13001
|
+
for (const record6 of readPptCharacterRuns(this.getBytes())) {
|
|
13002
|
+
const key2 = textRunKey(record6), bucket = byIdentity.get(key2);
|
|
13003
|
+
if (bucket)
|
|
13004
|
+
bucket.push(record6);
|
|
13005
|
+
else
|
|
13006
|
+
byIdentity.set(key2, [record6]);
|
|
13007
|
+
}
|
|
13008
|
+
if (this.revision !== revision)
|
|
13009
|
+
throw new UnsupportedOle2EditError("Document changed during character formatting read");
|
|
13010
|
+
this.#runsCache = { revision, byIdentity };
|
|
13011
|
+
}
|
|
13012
|
+
const matches = this.#runsCache.byIdentity.get(textRunKey(node)), record5 = matches?.[0];
|
|
13013
|
+
if (matches?.length !== 1 || !record5)
|
|
13014
|
+
throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
|
|
13015
|
+
if (this.#validatedTextRuns.get(node) !== record5) {
|
|
13016
|
+
if (record5.text !== node.text)
|
|
13017
|
+
throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
|
|
13018
|
+
this.#validatedTextRuns.set(node, record5);
|
|
13019
|
+
}
|
|
13020
|
+
return record5;
|
|
13021
|
+
}
|
|
13022
|
+
#editRun(node, original, fontSizePoints) {
|
|
13023
|
+
const revision = this.revision, current = this.#readTextRuns(node);
|
|
13024
|
+
const run = resolveCharacterRun(current, original);
|
|
13025
|
+
const result = editPptCharacterFontSize(this.getBytes(), {
|
|
13026
|
+
slideId: node.slideId,
|
|
13027
|
+
persistId: node.persistId,
|
|
13028
|
+
headerOffset: node.headerOffset,
|
|
13029
|
+
runOffset: run.runOffset,
|
|
13030
|
+
styleHeaderOffset: run.styleHeaderOffset,
|
|
13031
|
+
start: run.start,
|
|
13032
|
+
end: run.end,
|
|
13033
|
+
expectedFontSizePoints: run.directFontSizePoints,
|
|
13034
|
+
fontSizePoints
|
|
13035
|
+
});
|
|
13036
|
+
if (this.revision !== revision)
|
|
13037
|
+
throw new UnsupportedOle2EditError("Document changed during character formatting edit");
|
|
13038
|
+
if (result.status === "unsupported")
|
|
13039
|
+
throw new UnsupportedOle2EditError(result.reason);
|
|
13040
|
+
if (result.status === "edited")
|
|
13041
|
+
this.commitBytes(result.bytes);
|
|
13042
|
+
}
|
|
13043
|
+
#readNote(original, atom) {
|
|
13044
|
+
if (this.#notesCache.revision !== this.revision) {
|
|
13045
|
+
try {
|
|
13046
|
+
this.#notesCache = { revision: this.revision, notes: readPptSlideNotes(this.getBytes()) };
|
|
13047
|
+
} catch (error) {
|
|
13048
|
+
throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "Notes decoding unsupported");
|
|
13049
|
+
}
|
|
13050
|
+
}
|
|
13051
|
+
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);
|
|
13052
|
+
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) : [];
|
|
13053
|
+
if (matches.length !== 1)
|
|
13054
|
+
throw new UnsupportedOle2EditError("PPT notes identity no longer matches or is ambiguous");
|
|
13055
|
+
return matches[0];
|
|
13056
|
+
}
|
|
13057
|
+
#editNote(note, atom, text) {
|
|
13058
|
+
const revision = this.revision, current = this.#readNote(note, atom);
|
|
13059
|
+
const result = editPptNotesText(this.getBytes(), {
|
|
13060
|
+
slideId: note.slideId,
|
|
13061
|
+
slidePersistId: note.slidePersistId,
|
|
13062
|
+
notesId: note.notesId,
|
|
13063
|
+
persistId: note.persistId,
|
|
13064
|
+
shapeId: atom.shapeId,
|
|
13065
|
+
expectedHeaderOffset: atom.headerOffset,
|
|
13066
|
+
expectedText: current.text,
|
|
13067
|
+
text
|
|
13068
|
+
});
|
|
13069
|
+
if (this.revision !== revision)
|
|
13070
|
+
throw new UnsupportedOle2EditError("Document changed during notes edit");
|
|
13071
|
+
if (result.status === "unsupported")
|
|
13072
|
+
throw new UnsupportedOle2EditError(result.reason);
|
|
13073
|
+
if (result.status === "edited")
|
|
13074
|
+
this.commitBytes(result.bytes);
|
|
13075
|
+
}
|
|
11649
13076
|
#readShape(slideId, persistId, original) {
|
|
11650
13077
|
if (this.#shapeCache.revision !== this.revision)
|
|
11651
13078
|
this.#shapeCache = { revision: this.revision, slides: readPptSlideShapes(this.getBytes()) };
|
|
@@ -11685,7 +13112,7 @@ var PptDocument = class extends Ole2DocumentBase {
|
|
|
11685
13112
|
}
|
|
11686
13113
|
};
|
|
11687
13114
|
|
|
11688
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13115
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression.js
|
|
11689
13116
|
function decodeVsdBlock(input, limit3 = 32 * 1024 * 1024) {
|
|
11690
13117
|
if (!Number.isSafeInteger(limit3) || limit3 < 0 || limit3 > 64 * 1024 * 1024)
|
|
11691
13118
|
throw new Error("Invalid VSD decompression limit");
|
|
@@ -11732,7 +13159,7 @@ function encodeVsdBlock(input) {
|
|
|
11732
13159
|
return output;
|
|
11733
13160
|
}
|
|
11734
13161
|
|
|
11735
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13162
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-reader.js
|
|
11736
13163
|
var VsdError = class extends Error {
|
|
11737
13164
|
reason;
|
|
11738
13165
|
constructor(reason) {
|
|
@@ -11780,6 +13207,8 @@ function readVsdDrawing(input) {
|
|
|
11780
13207
|
if (size < 54 || size > stream.length)
|
|
11781
13208
|
throw new VsdError("document-size");
|
|
11782
13209
|
const data = { stream, streamPath, version: 11, pages: [], blocks: [], writable: true };
|
|
13210
|
+
const shapeOrders = /* @__PURE__ */ new Map(), sheetIds = /* @__PURE__ */ new Map();
|
|
13211
|
+
let orderElements = 0;
|
|
11783
13212
|
const active = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set();
|
|
11784
13213
|
let decodedBudget = MAX_BYTES, records = 0;
|
|
11785
13214
|
function visit(ownerBytes, pointerOffset, parent, page, shape, depth = 0, id = 0) {
|
|
@@ -11853,7 +13282,7 @@ function readVsdDrawing(input) {
|
|
|
11853
13282
|
for (const idx of indexes)
|
|
11854
13283
|
visit(bytes, table + 12 + idx * 18, block, page, shape, depth + 1, idx);
|
|
11855
13284
|
} else if (page && [8, 12, 13].includes(mode)) {
|
|
11856
|
-
const stack = [];
|
|
13285
|
+
const stack = [], orderStack = [];
|
|
11857
13286
|
let cursor = 0;
|
|
11858
13287
|
while (cursor < bytes.length) {
|
|
11859
13288
|
while (cursor < bytes.length && bytes[cursor] === 0)
|
|
@@ -11881,6 +13310,57 @@ function readVsdDrawing(input) {
|
|
|
11881
13310
|
let current = stack[stack.length - 1]?.shape ?? shape;
|
|
11882
13311
|
if (current && [70, 74].includes(chunk))
|
|
11883
13312
|
throw new VsdError("unsupported-sheet-owner");
|
|
13313
|
+
while (orderStack.length && level <= orderStack[orderStack.length - 1].level)
|
|
13314
|
+
orderStack.pop();
|
|
13315
|
+
if (page && chunk === 70) {
|
|
13316
|
+
if (sheetIds.has(page))
|
|
13317
|
+
page.shapeOrderIssue = "ambiguous-page-owner";
|
|
13318
|
+
sheetIds.set(page, length2 >= 54 && level === 1 && [10, 18, 26].every((o) => cv.getUint32(start + o, true) === 4294967295) ? chunkId : void 0);
|
|
13319
|
+
}
|
|
13320
|
+
if (page && chunk === 101) {
|
|
13321
|
+
const orders = shapeOrders.get(page) ?? /* @__PURE__ */ new Map();
|
|
13322
|
+
shapeOrders.set(page, orders);
|
|
13323
|
+
const order = { owner: current, elements: [], ids: /* @__PURE__ */ new Map(), level };
|
|
13324
|
+
if (orders.has(current))
|
|
13325
|
+
order.issue = "duplicate-shape-order";
|
|
13326
|
+
orders.set(current, order);
|
|
13327
|
+
orderStack.push(order);
|
|
13328
|
+
const end = start + length2 + trailer - 4;
|
|
13329
|
+
if (end - start < 8)
|
|
13330
|
+
order.issue = "shape-order-bounds";
|
|
13331
|
+
else {
|
|
13332
|
+
const subHeader = cv.getUint32(start, true), childrenBytes = cv.getUint32(start + 4, true), children4 = start + 8 + subHeader;
|
|
13333
|
+
if (children4 > end || childrenBytes > end - children4 || childrenBytes % 4)
|
|
13334
|
+
order.issue = "shape-order-bounds";
|
|
13335
|
+
else {
|
|
13336
|
+
const count = childrenBytes / 4;
|
|
13337
|
+
orderElements += count;
|
|
13338
|
+
if (orderElements > 1e5)
|
|
13339
|
+
throw new VsdError("shape-order-budget");
|
|
13340
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
13341
|
+
for (let i = 0; i < count; i++) {
|
|
13342
|
+
const id2 = cv.getUint32(children4 + i * 4, true);
|
|
13343
|
+
if (seen2.has(id2))
|
|
13344
|
+
order.issue = "duplicate-order-element";
|
|
13345
|
+
seen2.add(id2);
|
|
13346
|
+
order.elements.push(id2);
|
|
13347
|
+
}
|
|
13348
|
+
}
|
|
13349
|
+
}
|
|
13350
|
+
}
|
|
13351
|
+
if (page && chunk === 131) {
|
|
13352
|
+
const order = orderStack[orderStack.length - 1];
|
|
13353
|
+
if (!order)
|
|
13354
|
+
page.shapeOrderIssue = "orphan-shape-id";
|
|
13355
|
+
else if (level !== order.level + 1)
|
|
13356
|
+
order.issue = "shape-id-owner-level";
|
|
13357
|
+
else if (length2 < 4)
|
|
13358
|
+
order.issue = "shape-id-bounds";
|
|
13359
|
+
else if (order.ids.has(chunkId))
|
|
13360
|
+
order.issue = "duplicate-shape-id-map";
|
|
13361
|
+
else
|
|
13362
|
+
order.ids.set(chunkId, cv.getUint32(start, true));
|
|
13363
|
+
}
|
|
11884
13364
|
if (page && [71, 72, 78].includes(chunk)) {
|
|
11885
13365
|
current = { id: chunkId, kind: chunk === 71 ? "group" : chunk === 78 ? "foreign" : "shape", coordinateSpace: "shape-local", unsupportedGeometry: false, unsafeTransform: false, geometry: [], unsafeText: false };
|
|
11886
13366
|
if (length2 < 54)
|
|
@@ -11955,42 +13435,304 @@ function readVsdDrawing(input) {
|
|
|
11955
13435
|
ids.add(shape.id);
|
|
11956
13436
|
}
|
|
11957
13437
|
}
|
|
13438
|
+
for (const page of data.pages) {
|
|
13439
|
+
const shapes = new Map(page.shapes.map((s) => [s.id, s])), orders = shapeOrders.get(page), sheet = sheetIds.get(page);
|
|
13440
|
+
if (sheet !== void 0 && shapes.has(sheet))
|
|
13441
|
+
page.shapeOrderIssue = "ambiguous-page-owner";
|
|
13442
|
+
const rootParent = (s) => s.parentId === 4294967295 || sheet !== void 0 && s.parentId === sheet;
|
|
13443
|
+
const rootIds = /* @__PURE__ */ new Set(), childrenByParent = /* @__PURE__ */ new Map(), emptyIds = /* @__PURE__ */ new Set();
|
|
13444
|
+
for (const shape of page.shapes) {
|
|
13445
|
+
if (rootParent(shape))
|
|
13446
|
+
rootIds.add(shape.id);
|
|
13447
|
+
if (shape.parentId !== void 0) {
|
|
13448
|
+
const children4 = childrenByParent.get(shape.parentId) ?? /* @__PURE__ */ new Set();
|
|
13449
|
+
children4.add(shape.id);
|
|
13450
|
+
childrenByParent.set(shape.parentId, children4);
|
|
13451
|
+
}
|
|
13452
|
+
}
|
|
13453
|
+
const resolve = (owner) => {
|
|
13454
|
+
const order = orders?.get(owner);
|
|
13455
|
+
let issue2 = order?.issue;
|
|
13456
|
+
if (!order)
|
|
13457
|
+
issue2 = "missing-shape-order";
|
|
13458
|
+
if (owner && owner.kind !== "group" && order?.elements.length)
|
|
13459
|
+
issue2 = "unsupported-child-owner";
|
|
13460
|
+
const result = [], seen2 = /* @__PURE__ */ new Set();
|
|
13461
|
+
if (order && !issue2) {
|
|
13462
|
+
for (const element of order.elements) {
|
|
13463
|
+
const id = order.ids.get(element), shape = id === void 0 ? void 0 : shapes.get(id);
|
|
13464
|
+
if (!shape) {
|
|
13465
|
+
issue2 = "unresolved-shape-id";
|
|
13466
|
+
break;
|
|
13467
|
+
}
|
|
13468
|
+
if (seen2.has(id)) {
|
|
13469
|
+
issue2 = "duplicate-shape-reference";
|
|
13470
|
+
break;
|
|
13471
|
+
}
|
|
13472
|
+
seen2.add(id);
|
|
13473
|
+
if (owner ? shape.parentId !== owner.id : !rootParent(shape)) {
|
|
13474
|
+
issue2 = "contradictory-shape-owner";
|
|
13475
|
+
break;
|
|
13476
|
+
}
|
|
13477
|
+
result.push(id);
|
|
13478
|
+
}
|
|
13479
|
+
if (!issue2) {
|
|
13480
|
+
const expected = owner ? childrenByParent.get(owner.id) ?? emptyIds : rootIds;
|
|
13481
|
+
if (expected.size !== result.length || [...expected].some((id) => !seen2.has(id)))
|
|
13482
|
+
issue2 = "incomplete-shape-order";
|
|
13483
|
+
}
|
|
13484
|
+
}
|
|
13485
|
+
if (issue2) {
|
|
13486
|
+
if (owner)
|
|
13487
|
+
owner.shapeOrderIssue = issue2;
|
|
13488
|
+
else
|
|
13489
|
+
page.shapeOrderIssue ??= issue2;
|
|
13490
|
+
return void 0;
|
|
13491
|
+
}
|
|
13492
|
+
return result;
|
|
13493
|
+
};
|
|
13494
|
+
const root = resolve(void 0);
|
|
13495
|
+
for (const shape of page.shapes)
|
|
13496
|
+
if (shape.kind === "group" || orders?.has(shape))
|
|
13497
|
+
shape.childShapeIds = resolve(shape);
|
|
13498
|
+
let issue = page.shapeOrderIssue;
|
|
13499
|
+
const queue = (root ?? []).map((id) => ({ id, depth: 0 })), visited = /* @__PURE__ */ new Set();
|
|
13500
|
+
if (root && !issue) {
|
|
13501
|
+
for (let i = 0; i < queue.length; i++) {
|
|
13502
|
+
const item = queue[i];
|
|
13503
|
+
if (item.depth > 64) {
|
|
13504
|
+
issue = "shape-order-depth";
|
|
13505
|
+
break;
|
|
13506
|
+
}
|
|
13507
|
+
if (visited.has(item.id)) {
|
|
13508
|
+
issue = "cyclic-shape-order";
|
|
13509
|
+
break;
|
|
13510
|
+
}
|
|
13511
|
+
visited.add(item.id);
|
|
13512
|
+
const shape = shapes.get(item.id);
|
|
13513
|
+
if (shape.shapeOrderIssue) {
|
|
13514
|
+
issue = "unresolved-child-order";
|
|
13515
|
+
break;
|
|
13516
|
+
}
|
|
13517
|
+
for (const id of shape.childShapeIds ?? [])
|
|
13518
|
+
queue.push({ id, depth: item.depth + 1 });
|
|
13519
|
+
}
|
|
13520
|
+
if (!issue && visited.size !== page.shapes.length)
|
|
13521
|
+
issue = "unreachable-shape-order";
|
|
13522
|
+
}
|
|
13523
|
+
if (issue) {
|
|
13524
|
+
page.shapeOrderIssue = issue;
|
|
13525
|
+
for (const shape of page.shapes)
|
|
13526
|
+
if (shape.childShapeIds) {
|
|
13527
|
+
shape.childShapeIds = void 0;
|
|
13528
|
+
shape.shapeOrderIssue ??= "unresolved-page-order";
|
|
13529
|
+
}
|
|
13530
|
+
} else
|
|
13531
|
+
page.topLevelShapeIds = root;
|
|
13532
|
+
}
|
|
11958
13533
|
return data;
|
|
11959
13534
|
}
|
|
11960
13535
|
|
|
11961
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
11962
|
-
|
|
13536
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression-fit.js
|
|
13537
|
+
var VSD_COMPRESSION_FIT_MAX_BYTES = 8 * 1024 * 1024;
|
|
13538
|
+
var MAX_INPUT = VSD_COMPRESSION_FIT_MAX_BYTES;
|
|
13539
|
+
var MAX_GAP = 4096;
|
|
13540
|
+
var MAX_PROBES = 16 * 1024 * 1024;
|
|
13541
|
+
var VsdCompressionFitError = class extends Error {
|
|
13542
|
+
reason;
|
|
13543
|
+
constructor(reason) {
|
|
13544
|
+
super(`VSD compression ${reason}`);
|
|
13545
|
+
this.reason = reason;
|
|
13546
|
+
this.name = "VsdCompressionFitError";
|
|
13547
|
+
}
|
|
13548
|
+
};
|
|
13549
|
+
function encodeVsdBlockToSize(input, capacity) {
|
|
13550
|
+
if (!(input instanceof Uint8Array) || input.length > MAX_INPUT || !Number.isSafeInteger(capacity) || capacity < 0 || capacity > MAX_INPUT)
|
|
13551
|
+
throw new VsdCompressionFitError("input-budget");
|
|
13552
|
+
const output = new Uint8Array(capacity), heads = new Int32Array(65536).fill(-1), previous = new Int32Array(input.length).fill(-1);
|
|
13553
|
+
let cursor = 0, flagOffset = -1, bit = 8, tokens = 0, probes = 0;
|
|
13554
|
+
const tailSize = 4096, positions = new Int32Array(tailSize), lengths = new Uint8Array(tailSize), sources = new Int32Array(tailSize), starts = new Int32Array(tailSize);
|
|
13555
|
+
function emit(literal2, a, b) {
|
|
13556
|
+
const size = (bit === 8 ? 1 : 0) + (literal2 ? 1 : 2);
|
|
13557
|
+
if (size > capacity - cursor)
|
|
13558
|
+
return false;
|
|
13559
|
+
if (bit === 8) {
|
|
13560
|
+
flagOffset = cursor++;
|
|
13561
|
+
output[flagOffset] = 0;
|
|
13562
|
+
bit = 0;
|
|
13563
|
+
}
|
|
13564
|
+
if (literal2)
|
|
13565
|
+
output[flagOffset] |= 1 << bit;
|
|
13566
|
+
output[cursor++] = a;
|
|
13567
|
+
if (!literal2)
|
|
13568
|
+
output[cursor++] = b;
|
|
13569
|
+
bit++;
|
|
13570
|
+
tokens++;
|
|
13571
|
+
return true;
|
|
13572
|
+
}
|
|
13573
|
+
const hash2 = (p) => (input[p] * 251 + input[p + 1]) * 251 + input[p + 2] & 65535;
|
|
13574
|
+
function remember(p) {
|
|
13575
|
+
if (p + 2 < input.length) {
|
|
13576
|
+
const h = hash2(p);
|
|
13577
|
+
previous[p] = heads[h];
|
|
13578
|
+
heads[h] = p;
|
|
13579
|
+
}
|
|
13580
|
+
}
|
|
13581
|
+
function match(position) {
|
|
13582
|
+
let length = 0, source = -1;
|
|
13583
|
+
if (position < 4060) {
|
|
13584
|
+
while (length < 18 && position + length < input.length && input[position + length] === 0)
|
|
13585
|
+
length++;
|
|
13586
|
+
if (length >= 3)
|
|
13587
|
+
source = -18;
|
|
13588
|
+
else
|
|
13589
|
+
length = 0;
|
|
13590
|
+
}
|
|
13591
|
+
if (position + 2 < input.length) {
|
|
13592
|
+
let candidate = heads[hash2(position)], attempts = 0;
|
|
13593
|
+
while (candidate >= Math.max(0, position - 4096) && candidate < position && attempts++ < 512) {
|
|
13594
|
+
let n = 0;
|
|
13595
|
+
while (n < 18 && position + n < input.length) {
|
|
13596
|
+
if (++probes > MAX_PROBES)
|
|
13597
|
+
throw new VsdCompressionFitError("work-limit");
|
|
13598
|
+
if (input[candidate + n] !== input[position + n])
|
|
13599
|
+
break;
|
|
13600
|
+
n++;
|
|
13601
|
+
}
|
|
13602
|
+
if (n >= 3 && n > length) {
|
|
13603
|
+
length = n;
|
|
13604
|
+
source = candidate;
|
|
13605
|
+
if (n === 18)
|
|
13606
|
+
break;
|
|
13607
|
+
}
|
|
13608
|
+
candidate = previous[candidate];
|
|
13609
|
+
}
|
|
13610
|
+
}
|
|
13611
|
+
return { length, source };
|
|
13612
|
+
}
|
|
13613
|
+
for (let position = 0; position < input.length; ) {
|
|
13614
|
+
let { length, source } = match(position);
|
|
13615
|
+
if (length >= 3 && length < 18 && position + 1 < input.length && match(position + 1).length > length + 1)
|
|
13616
|
+
length = 0;
|
|
13617
|
+
const slot = tokens % tailSize;
|
|
13618
|
+
positions[slot] = position;
|
|
13619
|
+
lengths[slot] = length >= 3 ? length : 1;
|
|
13620
|
+
sources[slot] = source;
|
|
13621
|
+
starts[slot] = cursor;
|
|
13622
|
+
if (length >= 3) {
|
|
13623
|
+
const address = source - 18 & 4095;
|
|
13624
|
+
if (!emit(false, address & 255, address >> 4 & 240 | length - 3))
|
|
13625
|
+
return void 0;
|
|
13626
|
+
} else {
|
|
13627
|
+
length = 1;
|
|
13628
|
+
if (!emit(true, input[position]))
|
|
13629
|
+
return void 0;
|
|
13630
|
+
}
|
|
13631
|
+
for (let i = 0; i < length; i++)
|
|
13632
|
+
remember(position + i);
|
|
13633
|
+
position += length;
|
|
13634
|
+
}
|
|
13635
|
+
const remaining = capacity - cursor;
|
|
13636
|
+
if (remaining) {
|
|
13637
|
+
if (remaining > MAX_GAP || !tokens)
|
|
13638
|
+
return void 0;
|
|
13639
|
+
const baseTokens = tokens, tailStart = Math.ceil(Math.max(0, tokens - tailSize) / 8) * 8;
|
|
13640
|
+
let states2 = [{ extra: 0, count: 0, cost: 0, index: -1, k: 0 }], answer, planningWork = 0, nodes = 0, references = 0;
|
|
13641
|
+
for (let index = tokens - 1; index >= tailStart && !answer; index--) {
|
|
13642
|
+
const length = lengths[index % tailSize];
|
|
13643
|
+
if (length < 3)
|
|
13644
|
+
continue;
|
|
13645
|
+
if (++references > 512)
|
|
13646
|
+
break;
|
|
13647
|
+
const next = /* @__PURE__ */ new Map();
|
|
13648
|
+
for (const state of states2)
|
|
13649
|
+
next.set(state.cost * 8 + (baseTokens + state.count) % 8, state);
|
|
13650
|
+
for (const state of states2) {
|
|
13651
|
+
for (let k = 1; k <= length; k++) {
|
|
13652
|
+
if (++planningWork > 1024 * 1024 || nodes >= 65536)
|
|
13653
|
+
throw new VsdCompressionFitError("work-limit");
|
|
13654
|
+
if (k > length - 3 && k !== length)
|
|
13655
|
+
continue;
|
|
13656
|
+
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);
|
|
13657
|
+
if (cost > remaining)
|
|
13658
|
+
continue;
|
|
13659
|
+
const key2 = cost * 8 + (baseTokens + count) % 8;
|
|
13660
|
+
if (next.has(key2))
|
|
13661
|
+
continue;
|
|
13662
|
+
const node = { extra, count, cost, parent: state, index, k };
|
|
13663
|
+
nodes++;
|
|
13664
|
+
if (cost === remaining) {
|
|
13665
|
+
answer = node;
|
|
13666
|
+
break;
|
|
13667
|
+
}
|
|
13668
|
+
next.set(key2, node);
|
|
13669
|
+
}
|
|
13670
|
+
if (answer)
|
|
13671
|
+
break;
|
|
13672
|
+
}
|
|
13673
|
+
states2 = [...next.values()].sort((a, b) => b.cost - a.cost).slice(0, 63);
|
|
13674
|
+
if (!states2.some((p) => p.cost === 0))
|
|
13675
|
+
states2.push({ extra: 0, count: 0, cost: 0, index: -1, k: 0 });
|
|
13676
|
+
}
|
|
13677
|
+
if (!answer)
|
|
13678
|
+
return void 0;
|
|
13679
|
+
const changes = /* @__PURE__ */ new Map();
|
|
13680
|
+
for (let node = answer; node?.parent; node = node.parent)
|
|
13681
|
+
changes.set(node.index, node.k);
|
|
13682
|
+
cursor = starts[tailStart % tailSize];
|
|
13683
|
+
bit = 8;
|
|
13684
|
+
flagOffset = -1;
|
|
13685
|
+
tokens = tailStart;
|
|
13686
|
+
for (let index = tailStart; index < baseTokens; index++) {
|
|
13687
|
+
const slot = index % tailSize, position = positions[slot], length = lengths[slot], k = changes.get(index) ?? 0;
|
|
13688
|
+
for (let j = 0; j < k; j++)
|
|
13689
|
+
if (!emit(true, input[position + j]))
|
|
13690
|
+
return void 0;
|
|
13691
|
+
if (k < length) {
|
|
13692
|
+
if (length === 1) {
|
|
13693
|
+
if (!emit(true, input[position]))
|
|
13694
|
+
return void 0;
|
|
13695
|
+
} else {
|
|
13696
|
+
const address = sources[slot] + k - 18 & 4095;
|
|
13697
|
+
if (!emit(false, address & 255, address >> 4 & 240 | length - k - 3))
|
|
13698
|
+
return void 0;
|
|
13699
|
+
}
|
|
13700
|
+
}
|
|
13701
|
+
}
|
|
13702
|
+
}
|
|
13703
|
+
if (cursor !== capacity)
|
|
13704
|
+
return void 0;
|
|
13705
|
+
const decoded = decodeVsdBlock(output, input.length);
|
|
13706
|
+
if (decoded.length !== input.length || !input.every((v, i) => decoded[i] === v))
|
|
13707
|
+
throw new VsdCompressionFitError("verification");
|
|
13708
|
+
return { bytes: output, paddingBytes: 0 };
|
|
13709
|
+
}
|
|
13710
|
+
|
|
13711
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-writer.js
|
|
13712
|
+
function replaceRecord(input, drawing, record5, replacement) {
|
|
11963
13713
|
if (!drawing.writable)
|
|
11964
13714
|
throw new VsdError("shared-or-overlapping-allocation");
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
const
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
block = block.parent;
|
|
11984
|
-
decoded = owner;
|
|
11985
|
-
}
|
|
11986
|
-
const stream = new Uint8Array(size);
|
|
11987
|
-
stream.set(header);
|
|
11988
|
-
let offset = header.length;
|
|
11989
|
-
for (const bytes of appended) {
|
|
11990
|
-
stream.set(bytes, offset);
|
|
11991
|
-
offset += bytes.length;
|
|
13715
|
+
if (record5.block.format & 2 && (record5.block.bytes.length > VSD_COMPRESSION_FIT_MAX_BYTES || record5.block.length > VSD_COMPRESSION_FIT_MAX_BYTES))
|
|
13716
|
+
throw new VsdError("compression-input-budget");
|
|
13717
|
+
const block = record5.block, decoded = block.bytes.slice();
|
|
13718
|
+
decoded.set(replacement, record5.offset);
|
|
13719
|
+
let stored = block.format & 2 ? encodeVsdBlock(decoded) : decoded;
|
|
13720
|
+
if (stored.length !== block.length) {
|
|
13721
|
+
if (!(block.format & 2) || ![8, 12, 13].includes(block.format >>> 4))
|
|
13722
|
+
throw new VsdError("unsafe-block-relocation");
|
|
13723
|
+
try {
|
|
13724
|
+
const fit = encodeVsdBlockToSize(decoded, block.length);
|
|
13725
|
+
if (!fit)
|
|
13726
|
+
throw new VsdError("unsafe-block-relocation");
|
|
13727
|
+
stored = fit.bytes;
|
|
13728
|
+
} catch (error) {
|
|
13729
|
+
if (error instanceof VsdCompressionFitError)
|
|
13730
|
+
throw new VsdError(`compression-${error.reason}`);
|
|
13731
|
+
throw error;
|
|
13732
|
+
}
|
|
11992
13733
|
}
|
|
11993
|
-
|
|
13734
|
+
const stream = drawing.stream.slice();
|
|
13735
|
+
stream.set(stored, block.offset);
|
|
11994
13736
|
const result = resizeCompoundFileStream(input, drawing.streamPath, stream);
|
|
11995
13737
|
if (!result.ok)
|
|
11996
13738
|
throw new VsdError(`compound-resize-${result.reason}`);
|
|
@@ -12050,7 +13792,7 @@ function replaceVsdShapeTransform(input, pageId, shapeId, transform2) {
|
|
|
12050
13792
|
return candidate;
|
|
12051
13793
|
}
|
|
12052
13794
|
|
|
12053
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13795
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-document.js
|
|
12054
13796
|
var VsdShape = class {
|
|
12055
13797
|
id;
|
|
12056
13798
|
#read;
|
|
@@ -12097,6 +13839,14 @@ var VsdShape = class {
|
|
|
12097
13839
|
set transform(value) {
|
|
12098
13840
|
this.#editTransform(value);
|
|
12099
13841
|
}
|
|
13842
|
+
/** Validated drawing order of this owner's explicit children; undefined when unresolved. */
|
|
13843
|
+
get childShapeIds() {
|
|
13844
|
+
const ids = this.#read().childShapeIds;
|
|
13845
|
+
return ids && Object.freeze([...ids]);
|
|
13846
|
+
}
|
|
13847
|
+
get shapeOrderIssue() {
|
|
13848
|
+
return this.#read().shapeOrderIssue;
|
|
13849
|
+
}
|
|
12100
13850
|
get geometry() {
|
|
12101
13851
|
return Object.freeze(this.#read().geometry.map((row) => Object.freeze({ ...row })));
|
|
12102
13852
|
}
|
|
@@ -12111,6 +13861,14 @@ var VsdPage = class {
|
|
|
12111
13861
|
this.shapes = Object.freeze(shapes);
|
|
12112
13862
|
Object.freeze(this);
|
|
12113
13863
|
}
|
|
13864
|
+
/** Validated top-level drawing order. The existing shapes array remains flat. */
|
|
13865
|
+
get topLevelShapeIds() {
|
|
13866
|
+
const ids = this.#read().topLevelShapeIds;
|
|
13867
|
+
return ids && Object.freeze([...ids]);
|
|
13868
|
+
}
|
|
13869
|
+
get shapeOrderIssue() {
|
|
13870
|
+
return this.#read().shapeOrderIssue;
|
|
13871
|
+
}
|
|
12114
13872
|
get background() {
|
|
12115
13873
|
return this.#read().background;
|
|
12116
13874
|
}
|
|
@@ -12125,7 +13883,7 @@ var VsdPage = class {
|
|
|
12125
13883
|
return this.#read().scale;
|
|
12126
13884
|
}
|
|
12127
13885
|
};
|
|
12128
|
-
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;
|
|
13886
|
+
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."]) });
|
|
12129
13887
|
var VsdDocument = class extends Ole2DocumentBase {
|
|
12130
13888
|
#drawing;
|
|
12131
13889
|
#pages;
|
|
@@ -12185,7 +13943,7 @@ var VsdDocument = class extends Ole2DocumentBase {
|
|
|
12185
13943
|
}
|
|
12186
13944
|
};
|
|
12187
13945
|
|
|
12188
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
13946
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document.js
|
|
12189
13947
|
var CfbDocument = class extends Ole2DocumentBase {
|
|
12190
13948
|
get kind() {
|
|
12191
13949
|
return "cfb";
|
|
@@ -12298,7 +14056,7 @@ function parseVsd(input) {
|
|
|
12298
14056
|
return parseOle22(input, { expect: "vsd" });
|
|
12299
14057
|
}
|
|
12300
14058
|
|
|
12301
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
14059
|
+
// node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/utils/png-encoder.js
|
|
12302
14060
|
(() => {
|
|
12303
14061
|
const table = new Uint32Array(256);
|
|
12304
14062
|
for (let n = 0; n < 256; n++) {
|
|
@@ -14546,7 +16304,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14546
16304
|
return result;
|
|
14547
16305
|
};
|
|
14548
16306
|
let steps = 1e5;
|
|
14549
|
-
const
|
|
16307
|
+
const inspect6 = (binding, name) => {
|
|
14550
16308
|
check();
|
|
14551
16309
|
if (--steps < 0) problem("Master dependency proof exceeded its cell budget.");
|
|
14552
16310
|
name = name.toLowerCase();
|
|
@@ -14571,7 +16329,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14571
16329
|
txtlocpiny: "txtheight"
|
|
14572
16330
|
};
|
|
14573
16331
|
const dimension = defaults[name];
|
|
14574
|
-
if (dimension)
|
|
16332
|
+
if (dimension) inspect6(binding, dimension);
|
|
14575
16333
|
else if (!themeCell.test(name)) problem(`Missing effective master reference ${name}.`);
|
|
14576
16334
|
} else {
|
|
14577
16335
|
const formula = executableCellFormula(attribute2(source.node, "F"));
|
|
@@ -14592,17 +16350,17 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14592
16350
|
for (const ref of analysis.references) {
|
|
14593
16351
|
if (analysis.readsText && ref.shapeId === void 0 && ref.cell.toLowerCase() === "thetext")
|
|
14594
16352
|
continue;
|
|
14595
|
-
if (ref.shapeId === void 0)
|
|
16353
|
+
if (ref.shapeId === void 0) inspect6(binding, ref.cell);
|
|
14596
16354
|
else if (source.kind === "template") {
|
|
14597
16355
|
const target = binding.context.get(ref.shapeId);
|
|
14598
16356
|
if (!target) problem("Missing master-local Sheet reference.");
|
|
14599
|
-
|
|
16357
|
+
inspect6(target, ref.cell);
|
|
14600
16358
|
} else {
|
|
14601
16359
|
if (source.kind === "style")
|
|
14602
16360
|
problem("Explicit sheet references in inherited master styles are ambiguous.");
|
|
14603
16361
|
if (directAffected(binding.pageId, ref.shapeId, ref.cell) || query({ pageId: binding.pageId, shapeId: ref.shapeId, cell: ref.cell }, changed))
|
|
14604
16362
|
problem("Effective master cache depends on an edited page shape.");
|
|
14605
|
-
|
|
16363
|
+
inspect6(pageInput(binding.pageId, ref.shapeId), ref.cell);
|
|
14606
16364
|
}
|
|
14607
16365
|
}
|
|
14608
16366
|
if (analysis.readsText) {
|
|
@@ -14610,7 +16368,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14610
16368
|
if (/^(character\.|paragraph\.|tabs\.|leftmargin$|rightmargin$|topmargin$|bottommargin$)/i.test(
|
|
14611
16369
|
cell
|
|
14612
16370
|
))
|
|
14613
|
-
|
|
16371
|
+
inspect6(binding, cell);
|
|
14614
16372
|
}
|
|
14615
16373
|
}
|
|
14616
16374
|
}
|
|
@@ -14622,7 +16380,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
|
|
|
14622
16380
|
const source = binding.cells.get(name);
|
|
14623
16381
|
if (["pinx", "piny"].includes(name) && source?.kind === "instance" && movePins.pins.has(source.node))
|
|
14624
16382
|
continue;
|
|
14625
|
-
|
|
16383
|
+
inspect6(binding, name);
|
|
14626
16384
|
}
|
|
14627
16385
|
return movePins;
|
|
14628
16386
|
}
|