@pixerate/editor 0.51.0 → 0.53.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/agent/index.cjs +23 -23
- package/dist/agent/index.js +4 -4
- package/dist/chart/index.cjs +475 -124
- package/dist/chart/index.cjs.map +1 -1
- package/dist/chart/index.d.cts +174 -25
- package/dist/chart/index.d.ts +174 -25
- package/dist/chart/index.js +375 -24
- package/dist/chart/index.js.map +1 -1
- package/dist/{chunk-GJBIVWB2.js → chunk-3S72F46R.js} +387 -9
- package/dist/chunk-3S72F46R.js.map +1 -0
- package/dist/{chunk-5TWIN7ZJ.js → chunk-47WWV3LI.js} +34 -4
- package/dist/chunk-47WWV3LI.js.map +1 -0
- package/dist/{chunk-OV7UAKIY.js → chunk-633QC34G.js} +172 -1
- package/dist/chunk-633QC34G.js.map +1 -0
- package/dist/{chunk-MR2764X2.js → chunk-AGGUNWT6.js} +2 -322
- package/dist/chunk-AGGUNWT6.js.map +1 -0
- package/dist/{chunk-T6XU4B54.js → chunk-BQQZ6MOI.js} +7 -7
- package/dist/{chunk-LNKZPIQD.cjs → chunk-C3JHII3M.cjs} +67 -67
- package/dist/{chunk-LNKZPIQD.cjs.map → chunk-C3JHII3M.cjs.map} +1 -1
- package/dist/{chunk-JOX6MJW4.cjs → chunk-CKRNELPO.cjs} +176 -5
- package/dist/chunk-CKRNELPO.cjs.map +1 -0
- package/dist/{chunk-TGBCBQFV.cjs → chunk-DK6QBGCS.cjs} +45 -15
- package/dist/chunk-DK6QBGCS.cjs.map +1 -0
- package/dist/{chunk-GTZXF4BI.cjs → chunk-NK3WL5TJ.cjs} +298 -133
- package/dist/chunk-NK3WL5TJ.cjs.map +1 -0
- package/dist/{chunk-3JNRQVTS.cjs → chunk-NN3JGUSX.cjs} +402 -24
- package/dist/chunk-NN3JGUSX.cjs.map +1 -0
- package/dist/{chunk-3CC7OPUQ.cjs → chunk-O6FO6VI3.cjs} +3 -323
- package/dist/chunk-O6FO6VI3.cjs.map +1 -0
- package/dist/{chunk-DQPBQXKG.js → chunk-OIKYP7XC.js} +8 -8
- package/dist/{chunk-FEMIVHN3.cjs → chunk-P43HUQRX.cjs} +16 -16
- package/dist/{chunk-FEMIVHN3.cjs.map → chunk-P43HUQRX.cjs.map} +1 -1
- package/dist/{chunk-QFTVLEVN.js → chunk-RIXTW3C4.js} +3 -3
- package/dist/{chunk-WBOAXDKD.js → chunk-VODBAO32.js} +222 -57
- package/dist/chunk-VODBAO32.js.map +1 -0
- package/dist/{chunk-2Q46FKZK.cjs → chunk-YZZMX6V7.cjs} +25 -25
- package/dist/{chunk-2Q46FKZK.cjs.map → chunk-YZZMX6V7.cjs.map} +1 -1
- package/dist/{controller-DS3drIvy.d.cts → controller-CX0QfSv0.d.cts} +53 -2
- package/dist/{controller-BdKzaxs2.d.ts → controller-DscWQbjO.d.ts} +53 -2
- package/dist/export/index.cjs +5 -5
- package/dist/export/index.js +4 -4
- package/dist/extensions/index.cjs +7 -7
- package/dist/extensions/index.d.cts +2 -2
- package/dist/extensions/index.d.ts +2 -2
- package/dist/extensions/index.js +6 -6
- package/dist/{index-Dt9lzydb.d.ts → index-CALDD35B.d.ts} +1 -1
- package/dist/{index-DOy9HzfC.d.cts → index-DIWB6xMf.d.cts} +1 -1
- package/dist/index.cjs +15 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -113
- package/dist/index.d.ts +6 -113
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/zip-4nG0YAH7.d.cts +110 -0
- package/dist/zip-4nG0YAH7.d.ts +110 -0
- package/package.json +1 -1
- package/dist/chunk-3CC7OPUQ.cjs.map +0 -1
- package/dist/chunk-3JNRQVTS.cjs.map +0 -1
- package/dist/chunk-5TWIN7ZJ.js.map +0 -1
- package/dist/chunk-GJBIVWB2.js.map +0 -1
- package/dist/chunk-GTZXF4BI.cjs.map +0 -1
- package/dist/chunk-JOX6MJW4.cjs.map +0 -1
- package/dist/chunk-MR2764X2.js.map +0 -1
- package/dist/chunk-OV7UAKIY.js.map +0 -1
- package/dist/chunk-TGBCBQFV.cjs.map +0 -1
- package/dist/chunk-WBOAXDKD.js.map +0 -1
- /package/dist/{chunk-T6XU4B54.js.map → chunk-BQQZ6MOI.js.map} +0 -0
- /package/dist/{chunk-DQPBQXKG.js.map → chunk-OIKYP7XC.js.map} +0 -0
- /package/dist/{chunk-QFTVLEVN.js.map → chunk-RIXTW3C4.js.map} +0 -0
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
isCartesianChart,
|
|
7
7
|
normalizeChartSpec,
|
|
8
8
|
parseChartColor
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-633QC34G.js";
|
|
10
10
|
|
|
11
11
|
// src/chart/ooxml.ts
|
|
12
12
|
var CHART_OOXML_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart";
|
|
@@ -81,6 +81,27 @@ var MARKERS = { circle: "circle", dot: "circle", square: "square", diamond: "dia
|
|
|
81
81
|
var TREND_IN = { linear: "linear", exp: "exponential", log: "logarithmic", poly: "polynomial", power: "power", movingAvg: "moving-average" };
|
|
82
82
|
var TREND_OUT = { linear: "linear", exponential: "exp", logarithmic: "log", polynomial: "poly", power: "power", "moving-average": "movingAvg" };
|
|
83
83
|
var LEGEND_IN = { b: "bottom", t: "top", l: "left", r: "right", tr: "right" };
|
|
84
|
+
var ERR_IN = { fixedVal: "fixed", percentage: "percent", stdDev: "stddev", stdErr: "stderr", cust: "custom" };
|
|
85
|
+
var ERR_OUT = { fixed: "fixedVal", percent: "percentage", stddev: "stdDev", stderr: "stdErr", custom: "cust" };
|
|
86
|
+
function readErrorBars(e) {
|
|
87
|
+
const type = ERR_IN[val(e, "errValType") ?? "fixedVal"];
|
|
88
|
+
if (!type) return null;
|
|
89
|
+
const bars = { type };
|
|
90
|
+
const value = numberOf(val(e, "val"));
|
|
91
|
+
if (value !== null && type !== "custom" && type !== "stderr") bars.value = Math.abs(value);
|
|
92
|
+
if (type === "custom") {
|
|
93
|
+
const plus = kid(e, "plus");
|
|
94
|
+
const minus = kid(e, "minus");
|
|
95
|
+
const p = plus ? numbers(plus).map((v) => v === null ? null : Math.abs(v)) : [];
|
|
96
|
+
const m = minus ? numbers(minus).map((v) => v === null ? null : Math.abs(v)) : [];
|
|
97
|
+
if (p.some((v) => v !== null)) bars.plus = p;
|
|
98
|
+
if (m.some((v) => v !== null) && JSON.stringify(m) !== JSON.stringify(p)) bars.minus = m;
|
|
99
|
+
}
|
|
100
|
+
const direction = val(e, "errBarType");
|
|
101
|
+
if (direction === "plus" || direction === "minus") bars.direction = direction;
|
|
102
|
+
if (bool(val(e, "noEndCap"))) bars.cap = false;
|
|
103
|
+
return bars;
|
|
104
|
+
}
|
|
84
105
|
function chartFromOoxml(xml, options = {}) {
|
|
85
106
|
const issues = [];
|
|
86
107
|
const unsupported = [];
|
|
@@ -240,7 +261,18 @@ function chartFromOoxml(xml, options = {}) {
|
|
|
240
261
|
trends.push(line);
|
|
241
262
|
}
|
|
242
263
|
if (trends.length) out.trendlines = trends;
|
|
243
|
-
|
|
264
|
+
for (const e of kids(s, "errBars")) {
|
|
265
|
+
const bars = readErrorBars(e);
|
|
266
|
+
if (!bars) {
|
|
267
|
+
unsupported.push(`error bars of type "${val(e, "errValType")}"`);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (val(e, "errDir") === "x") {
|
|
271
|
+
if (type === "scatter" || type === "bubble") out.xErrorBars = bars;
|
|
272
|
+
else unsupported.push("x error bars on a category chart");
|
|
273
|
+
} else if (type === "pie" || type === "donut" || type === "radar") unsupported.push(`error bars on a ${type} chart`);
|
|
274
|
+
else out.errorBars = bars;
|
|
275
|
+
}
|
|
244
276
|
series.push(out);
|
|
245
277
|
}
|
|
246
278
|
}
|
|
@@ -273,8 +305,15 @@ function chartFromOoxml(xml, options = {}) {
|
|
|
273
305
|
const scaling = kid(a, "scaling");
|
|
274
306
|
axis.min = numberOf(val(scaling, "min"));
|
|
275
307
|
axis.max = numberOf(val(scaling, "max"));
|
|
276
|
-
if (val(scaling, "orientation") === "maxMin")
|
|
277
|
-
if (kid(scaling, "logBase"))
|
|
308
|
+
if (val(scaling, "orientation") === "maxMin") axis.reverse = true;
|
|
309
|
+
if (kid(scaling, "logBase")) {
|
|
310
|
+
if (a.localName !== "valAx") unsupported.push("a logarithmic category axis");
|
|
311
|
+
else {
|
|
312
|
+
axis.scale = "log";
|
|
313
|
+
const base = numberOf(val(scaling, "logBase")) ?? 10;
|
|
314
|
+
if (base !== 10) axis.logBase = base;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
278
317
|
axis.step = numberOf(val(a, "majorUnit"));
|
|
279
318
|
const fmt = kid(a, "numFmt");
|
|
280
319
|
const code = fmt?.getAttribute("formatCode");
|
|
@@ -384,6 +423,14 @@ function chartFormatToCode(format) {
|
|
|
384
423
|
return d !== void 0 || format.prefix || format.suffix ? wrap(`#,##0${frac(d, 0)}`) : "General";
|
|
385
424
|
}
|
|
386
425
|
}
|
|
426
|
+
function errBarsXml(bars, dir) {
|
|
427
|
+
let x = `<c:errBars>${dir ? `<c:errDir val="${dir}"/>` : ""}<c:errBarType val="${bars.direction ?? "both"}"/><c:errValType val="${ERR_OUT[bars.type]}"/><c:noEndCap val="${bars.cap === false ? 1 : 0}"/>`;
|
|
428
|
+
if (bars.type === "custom") {
|
|
429
|
+
const plus = bars.plus ?? (bars.minus ?? []).map(() => null);
|
|
430
|
+
x += `<c:plus>${numLit(plus)}</c:plus><c:minus>${numLit(bars.minus ?? plus)}</c:minus>`;
|
|
431
|
+
} else if (bars.type !== "stderr") x += `<c:val val="${bars.value ?? (bars.type === "percent" ? 5 : 1)}"/>`;
|
|
432
|
+
return `${x}</c:errBars>`;
|
|
433
|
+
}
|
|
387
434
|
var MARKER_OUT = { circle: "circle", square: "square", diamond: "diamond", triangle: "triangle", cross: "x", none: "none" };
|
|
388
435
|
function chartToOoxml(spec) {
|
|
389
436
|
const issues = [];
|
|
@@ -442,6 +489,14 @@ function chartToOoxml(spec) {
|
|
|
442
489
|
x += `<c:dispRSqr val="${t.showR2 ? 1 : 0}"/><c:dispEq val="${t.showEquation ? 1 : 0}"/></c:trendline>`;
|
|
443
490
|
parts.push(x);
|
|
444
491
|
}
|
|
492
|
+
if (!pieLike && kind !== "radar") {
|
|
493
|
+
const xyKind = kind === "scatter" || kind === "bubble";
|
|
494
|
+
if (s.errorBars) parts.push(errBarsXml(s.errorBars, xyKind ? "y" : null));
|
|
495
|
+
if (s.xErrorBars) {
|
|
496
|
+
if (xyKind) parts.push(errBarsXml(s.xErrorBars, "x"));
|
|
497
|
+
else issues.push(`"${s.name}" has x error bars, which only scatter and bubble charts can hold; they are left out.`);
|
|
498
|
+
}
|
|
499
|
+
} else if (s.errorBars || s.xErrorBars) issues.push(`Error bars on "${s.name}" are left out: ${kind} charts cannot show them.`);
|
|
445
500
|
const valCode = chartFormatToCode(s.format ?? (s.axis === "secondary" ? spec.yAxis2.format : spec.yAxis.format));
|
|
446
501
|
if (kind === "scatter" || kind === "bubble") {
|
|
447
502
|
const xs = s.x ?? spec.categories.map((_, i) => i + 1);
|
|
@@ -484,7 +539,7 @@ function chartToOoxml(spec) {
|
|
|
484
539
|
return `<c:pieChart><c:varyColors val="1"/>${sers}${dLbls}<c:firstSliceAng val="0"/></c:pieChart>`;
|
|
485
540
|
}
|
|
486
541
|
});
|
|
487
|
-
const scaling = (a) => `<c:scaling
|
|
542
|
+
const scaling = (a) => `<c:scaling>${a.scale === "log" ? `<c:logBase val="${a.logBase ?? 10}"/>` : ""}<c:orientation val="${a.reverse ? "maxMin" : "minMax"}"/>${a.max !== null ? `<c:max val="${a.max}"/>` : ""}${a.min !== null ? `<c:min val="${a.min}"/>` : ""}</c:scaling>`;
|
|
488
543
|
const title = (a) => a.title ? `<c:title>${rich(a.title)}</c:title>` : "";
|
|
489
544
|
const fmt = (a) => {
|
|
490
545
|
const code = chartFormatToCode(a.format);
|
|
@@ -494,11 +549,14 @@ function chartToOoxml(spec) {
|
|
|
494
549
|
const catPos = horizontal ? "l" : "b";
|
|
495
550
|
const valPos = horizontal ? "b" : "l";
|
|
496
551
|
const valAx = (id, cross, a, pos, crosses, catKind = false) => `<c:valAx><c:axId val="${id}"/>${scaling(a)}<c:delete val="${a.show ? 0 : 1}"/><c:axPos val="${pos}"/>${a.gridlines ? "<c:majorGridlines/>" : ""}${title(a)}${fmt(a)}<c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crossAx val="${cross}"/><c:crosses val="${crosses}"/><c:crossBetween val="${catKind ? "midCat" : "between"}"/>${a.step ? `<c:majorUnit val="${a.step}"/>` : ""}</c:valAx>`;
|
|
497
|
-
const catAx = (id, cross, a, pos, hidden = false) => `<c:${a.kind === "date" ? "dateAx" : "catAx"}><c:axId val="${id}"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:delete val="${a.show && !hidden ? 0 : 1}"/><c:axPos val="${pos}"/>${a.gridlines ? "<c:majorGridlines/>" : ""}${title(a)}<c:numFmt formatCode="General" sourceLinked="1"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crossAx val="${cross}"/><c:crosses val="autoZero"/><c:auto val="1"/>${a.kind === "date" ? '<c:lblOffset val="100"/><c:baseTimeUnit val="days"/>' : '<c:lblAlgn val="ctr"/><c:lblOffset val="100"/><c:noMultiLvlLbl val="0"/>'}</c:${a.kind === "date" ? "dateAx" : "catAx"}>`;
|
|
552
|
+
const catAx = (id, cross, a, pos, hidden = false) => `<c:${a.kind === "date" ? "dateAx" : "catAx"}><c:axId val="${id}"/><c:scaling><c:orientation val="${a.reverse ? "maxMin" : "minMax"}"/></c:scaling><c:delete val="${a.show && !hidden ? 0 : 1}"/><c:axPos val="${pos}"/>${a.gridlines ? "<c:majorGridlines/>" : ""}${title(a)}<c:numFmt formatCode="General" sourceLinked="1"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crossAx val="${cross}"/><c:crosses val="autoZero"/><c:auto val="1"/>${a.kind === "date" ? '<c:lblOffset val="100"/><c:baseTimeUnit val="days"/>' : '<c:lblAlgn val="ctr"/><c:lblOffset val="100"/><c:noMultiLvlLbl val="0"/>'}</c:${a.kind === "date" ? "dateAx" : "catAx"}>`;
|
|
498
553
|
let axes = "";
|
|
499
554
|
if (!pieLike) {
|
|
500
555
|
if (xy) axes = valAx(ids.cat, ids.val, spec.xAxis, "b", "autoZero", true) + valAx(ids.val, ids.cat, spec.yAxis, "l", "autoZero", true);
|
|
501
|
-
else
|
|
556
|
+
else {
|
|
557
|
+
if (spec.xAxis.scale === "log") issues.push("The category axis cannot be logarithmic; its log scale is left out.");
|
|
558
|
+
axes = catAx(ids.cat, ids.val, spec.xAxis, catPos) + valAx(ids.val, ids.cat, spec.yAxis, valPos, "autoZero");
|
|
559
|
+
}
|
|
502
560
|
if (groups.some((g) => g.secondary)) axes += catAx(ids.cat2, ids.val2, spec.xAxis, catPos, true) + valAx(ids.val2, ids.cat2, spec.yAxis2, horizontal ? "t" : "r", "max");
|
|
503
561
|
}
|
|
504
562
|
const legendPos = { bottom: "b", top: "t", left: "l", right: "r" }[spec.legend.position];
|
|
@@ -510,12 +568,332 @@ function chartToOoxml(spec) {
|
|
|
510
568
|
return { xml, issues: [...new Set(issues)] };
|
|
511
569
|
}
|
|
512
570
|
|
|
571
|
+
// src/import/zip.ts
|
|
572
|
+
var ZipError = class extends Error {
|
|
573
|
+
code;
|
|
574
|
+
entryName;
|
|
575
|
+
constructor(code, message, details = {}) {
|
|
576
|
+
super(message, details.cause !== void 0 ? { cause: details.cause } : void 0);
|
|
577
|
+
this.name = "ZipError";
|
|
578
|
+
this.code = code;
|
|
579
|
+
this.entryName = details.entryName;
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
var DEFAULT_ZIP_MAX_ENTRIES = 1e4;
|
|
583
|
+
var DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;
|
|
584
|
+
var SIG_EOCD = 101010256;
|
|
585
|
+
var SIG_ZIP64_EOCD = 101075792;
|
|
586
|
+
var SIG_ZIP64_LOCATOR = 117853008;
|
|
587
|
+
var SIG_CENTRAL = 33639248;
|
|
588
|
+
var SIG_LOCAL = 67324752;
|
|
589
|
+
var EOCD_SIZE = 22;
|
|
590
|
+
var MAX_COMMENT = 65535;
|
|
591
|
+
var crcTable = null;
|
|
592
|
+
function zipCrc32(data) {
|
|
593
|
+
if (!crcTable) {
|
|
594
|
+
crcTable = new Uint32Array(256);
|
|
595
|
+
for (let n = 0; n < 256; n++) {
|
|
596
|
+
let c = n;
|
|
597
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
598
|
+
crcTable[n] = c >>> 0;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
let crc = 4294967295;
|
|
602
|
+
for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 255] ^ crc >>> 8;
|
|
603
|
+
return (crc ^ 4294967295) >>> 0;
|
|
604
|
+
}
|
|
605
|
+
function toBytes(data) {
|
|
606
|
+
if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
607
|
+
return new Uint8Array(data);
|
|
608
|
+
}
|
|
609
|
+
function isUnsafeZipPath(name) {
|
|
610
|
+
if (!name || name.includes("\0")) return true;
|
|
611
|
+
const normalized = name.replace(/\\/g, "/");
|
|
612
|
+
if (normalized.startsWith("/") || /^[a-zA-Z]:/.test(normalized)) return true;
|
|
613
|
+
return normalized.split("/").some((segment) => segment === "..");
|
|
614
|
+
}
|
|
615
|
+
var utf8 = new TextDecoder("utf-8");
|
|
616
|
+
var CP437_HIGH = "\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
|
|
617
|
+
function decodeName(bytes, isUtf8) {
|
|
618
|
+
if (isUtf8 || bytes.every((b) => b < 128)) return utf8.decode(bytes);
|
|
619
|
+
let out = "";
|
|
620
|
+
for (const b of bytes) out += b < 128 ? String.fromCharCode(b) : CP437_HIGH[b - 128];
|
|
621
|
+
return out;
|
|
622
|
+
}
|
|
623
|
+
var ZipArchive = class {
|
|
624
|
+
constructor(bytes, entries, maxTotalSize) {
|
|
625
|
+
this.bytes = bytes;
|
|
626
|
+
this.maxTotalSize = maxTotalSize;
|
|
627
|
+
this.entries = entries;
|
|
628
|
+
entries.forEach((entry) => {
|
|
629
|
+
if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
bytes;
|
|
633
|
+
maxTotalSize;
|
|
634
|
+
/** Entries in central-directory order. */
|
|
635
|
+
entries;
|
|
636
|
+
byName = /* @__PURE__ */ new Map();
|
|
637
|
+
extracted = 0;
|
|
638
|
+
/** Looks up an entry by exact name (a leading `/` is ignored). */
|
|
639
|
+
get(name) {
|
|
640
|
+
return this.byName.get(name.replace(/^\/+/, ""));
|
|
641
|
+
}
|
|
642
|
+
has(name) {
|
|
643
|
+
return !!this.get(name);
|
|
644
|
+
}
|
|
645
|
+
/** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */
|
|
646
|
+
get extractedSize() {
|
|
647
|
+
return this.extracted;
|
|
648
|
+
}
|
|
649
|
+
/** Extracts an entry's data, verifying its size and CRC-32. */
|
|
650
|
+
async read(entryOrName) {
|
|
651
|
+
const entry = typeof entryOrName === "string" ? this.get(entryOrName) : entryOrName;
|
|
652
|
+
if (!entry) {
|
|
653
|
+
throw new ZipError("entry_not_found", `ZIP entry "${String(entryOrName)}" not found.`, {
|
|
654
|
+
entryName: String(entryOrName)
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
const name = entry.name;
|
|
658
|
+
if (entry.encrypted) {
|
|
659
|
+
throw new ZipError("encrypted", `ZIP entry "${name}" is encrypted; encrypted archives are not supported.`, {
|
|
660
|
+
entryName: name
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
if (entry.isDirectory) return new Uint8Array(0);
|
|
664
|
+
const remaining = this.maxTotalSize - this.extracted;
|
|
665
|
+
if (entry.size > remaining) {
|
|
666
|
+
throw new ZipError(
|
|
667
|
+
"too_large",
|
|
668
|
+
`Extracting "${name}" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,
|
|
669
|
+
{ entryName: name }
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
const { bytes } = this;
|
|
673
|
+
const offset = entry.localHeaderOffset;
|
|
674
|
+
if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {
|
|
675
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" has no valid local header.`, { entryName: name });
|
|
676
|
+
}
|
|
677
|
+
const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);
|
|
678
|
+
const dataEnd = dataStart + entry.compressedSize;
|
|
679
|
+
if (dataEnd > bytes.length) {
|
|
680
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" is truncated.`, { entryName: name });
|
|
681
|
+
}
|
|
682
|
+
const raw = bytes.subarray(dataStart, dataEnd);
|
|
683
|
+
let data;
|
|
684
|
+
if (entry.method === 0) {
|
|
685
|
+
if (entry.compressedSize !== entry.size) {
|
|
686
|
+
throw new ZipError("corrupt_entry", `Stored ZIP entry "${name}" has inconsistent sizes.`, { entryName: name });
|
|
687
|
+
}
|
|
688
|
+
data = raw.slice();
|
|
689
|
+
} else if (entry.method === 8) {
|
|
690
|
+
data = await inflateRaw(raw, entry.size, name);
|
|
691
|
+
} else {
|
|
692
|
+
throw new ZipError(
|
|
693
|
+
"unsupported_feature",
|
|
694
|
+
`ZIP entry "${name}" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,
|
|
695
|
+
{ entryName: name }
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
if (data.length !== entry.size) {
|
|
699
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" size does not match the directory.`, { entryName: name });
|
|
700
|
+
}
|
|
701
|
+
this.extracted += data.length;
|
|
702
|
+
if (zipCrc32(data) !== entry.crc32) {
|
|
703
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" failed its CRC-32 check.`, { entryName: name });
|
|
704
|
+
}
|
|
705
|
+
return data;
|
|
706
|
+
}
|
|
707
|
+
/** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */
|
|
708
|
+
async readText(entryOrName) {
|
|
709
|
+
const text = utf8.decode(await this.read(entryOrName));
|
|
710
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
function readU16(bytes, offset) {
|
|
714
|
+
return bytes[offset] | bytes[offset + 1] << 8;
|
|
715
|
+
}
|
|
716
|
+
function readU32(bytes, offset) {
|
|
717
|
+
return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;
|
|
718
|
+
}
|
|
719
|
+
function readU64(bytes, offset) {
|
|
720
|
+
const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 4294967296;
|
|
721
|
+
if (!Number.isSafeInteger(value)) {
|
|
722
|
+
throw new ZipError("unsupported_feature", "ZIP64 value exceeds the supported range.");
|
|
723
|
+
}
|
|
724
|
+
return value;
|
|
725
|
+
}
|
|
726
|
+
async function inflateRaw(raw, limit, entryName) {
|
|
727
|
+
const Stream = globalThis.DecompressionStream;
|
|
728
|
+
if (typeof Stream !== "function") {
|
|
729
|
+
throw new ZipError(
|
|
730
|
+
"unsupported_environment",
|
|
731
|
+
"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).",
|
|
732
|
+
{ entryName }
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
const stream = new Stream("deflate-raw");
|
|
736
|
+
const writer = stream.writable.getWriter();
|
|
737
|
+
const reader = stream.readable.getReader();
|
|
738
|
+
const CHUNK = 64 * 1024;
|
|
739
|
+
const feeding = (async () => {
|
|
740
|
+
for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK));
|
|
741
|
+
await writer.close();
|
|
742
|
+
})();
|
|
743
|
+
feeding.catch(() => {
|
|
744
|
+
});
|
|
745
|
+
const chunks = [];
|
|
746
|
+
let total = 0;
|
|
747
|
+
try {
|
|
748
|
+
for (; ; ) {
|
|
749
|
+
const { done, value } = await reader.read();
|
|
750
|
+
if (done) break;
|
|
751
|
+
total += value.length;
|
|
752
|
+
if (total > limit) {
|
|
753
|
+
throw new ZipError(
|
|
754
|
+
"corrupt_entry",
|
|
755
|
+
`ZIP entry "${entryName}" inflates beyond its declared size of ${limit} bytes.`,
|
|
756
|
+
{ entryName }
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
chunks.push(value);
|
|
760
|
+
}
|
|
761
|
+
} catch (error) {
|
|
762
|
+
reader.cancel().catch(() => {
|
|
763
|
+
});
|
|
764
|
+
writer.abort().catch(() => {
|
|
765
|
+
});
|
|
766
|
+
if (error instanceof ZipError) throw error;
|
|
767
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${entryName}" has an invalid deflate stream.`, {
|
|
768
|
+
entryName,
|
|
769
|
+
cause: error
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
await feeding.catch(() => {
|
|
773
|
+
});
|
|
774
|
+
const out = new Uint8Array(total);
|
|
775
|
+
let pos = 0;
|
|
776
|
+
for (const chunk of chunks) {
|
|
777
|
+
out.set(chunk, pos);
|
|
778
|
+
pos += chunk.length;
|
|
779
|
+
}
|
|
780
|
+
return out;
|
|
781
|
+
}
|
|
782
|
+
function findEndOfCentralDirectory(bytes) {
|
|
783
|
+
const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);
|
|
784
|
+
for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {
|
|
785
|
+
if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;
|
|
786
|
+
}
|
|
787
|
+
return -1;
|
|
788
|
+
}
|
|
789
|
+
async function readZip(data, options = {}) {
|
|
790
|
+
const bytes = toBytes(data);
|
|
791
|
+
const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;
|
|
792
|
+
const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;
|
|
793
|
+
const eocd = findEndOfCentralDirectory(bytes);
|
|
794
|
+
if (eocd < 0) throw new ZipError("invalid_archive", "Not a ZIP archive (no end of central directory record).");
|
|
795
|
+
let diskNumber = readU16(bytes, eocd + 4);
|
|
796
|
+
let cdDisk = readU16(bytes, eocd + 6);
|
|
797
|
+
let count = readU16(bytes, eocd + 10);
|
|
798
|
+
let cdSize = readU32(bytes, eocd + 12);
|
|
799
|
+
let cdOffset = readU32(bytes, eocd + 16);
|
|
800
|
+
if (count === 65535 || cdSize === 4294967295 || cdOffset === 4294967295) {
|
|
801
|
+
const locator = eocd - 20;
|
|
802
|
+
if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {
|
|
803
|
+
throw new ZipError("invalid_archive", "ZIP64 archive is missing its end of central directory locator.");
|
|
804
|
+
}
|
|
805
|
+
const record = readU64(bytes, locator + 8);
|
|
806
|
+
if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {
|
|
807
|
+
throw new ZipError("invalid_archive", "ZIP64 end of central directory record not found.");
|
|
808
|
+
}
|
|
809
|
+
diskNumber = readU32(bytes, record + 16);
|
|
810
|
+
cdDisk = readU32(bytes, record + 20);
|
|
811
|
+
count = readU64(bytes, record + 32);
|
|
812
|
+
cdSize = readU64(bytes, record + 40);
|
|
813
|
+
cdOffset = readU64(bytes, record + 48);
|
|
814
|
+
}
|
|
815
|
+
if (diskNumber !== 0 || cdDisk !== 0) {
|
|
816
|
+
throw new ZipError("unsupported_feature", "Multi-disk (spanned) ZIP archives are not supported.");
|
|
817
|
+
}
|
|
818
|
+
if (count > maxEntries) {
|
|
819
|
+
throw new ZipError("too_many_entries", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);
|
|
820
|
+
}
|
|
821
|
+
if (cdOffset + cdSize > bytes.length) {
|
|
822
|
+
throw new ZipError("invalid_archive", "ZIP central directory lies outside the file.");
|
|
823
|
+
}
|
|
824
|
+
const entries = [];
|
|
825
|
+
let p = cdOffset;
|
|
826
|
+
for (let i = 0; i < count; i++) {
|
|
827
|
+
if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {
|
|
828
|
+
throw new ZipError("invalid_archive", "ZIP central directory is corrupt.");
|
|
829
|
+
}
|
|
830
|
+
const flags = readU16(bytes, p + 8);
|
|
831
|
+
const method = readU16(bytes, p + 10);
|
|
832
|
+
const crc32 = readU32(bytes, p + 16);
|
|
833
|
+
let compressedSize = readU32(bytes, p + 20);
|
|
834
|
+
let size = readU32(bytes, p + 24);
|
|
835
|
+
const nameLength = readU16(bytes, p + 28);
|
|
836
|
+
const extraLength = readU16(bytes, p + 30);
|
|
837
|
+
const commentLength = readU16(bytes, p + 32);
|
|
838
|
+
let localHeaderOffset = readU32(bytes, p + 42);
|
|
839
|
+
const nameStart = p + 46;
|
|
840
|
+
const extraStart = nameStart + nameLength;
|
|
841
|
+
const next = extraStart + extraLength + commentLength;
|
|
842
|
+
if (next > bytes.length) throw new ZipError("invalid_archive", "ZIP central directory is truncated.");
|
|
843
|
+
for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {
|
|
844
|
+
const id = readU16(bytes, e);
|
|
845
|
+
const len = readU16(bytes, e + 2);
|
|
846
|
+
if (id === 1) {
|
|
847
|
+
let f = e + 4;
|
|
848
|
+
const end = f + len;
|
|
849
|
+
if (size === 4294967295 && f + 8 <= end) {
|
|
850
|
+
size = readU64(bytes, f);
|
|
851
|
+
f += 8;
|
|
852
|
+
}
|
|
853
|
+
if (compressedSize === 4294967295 && f + 8 <= end) {
|
|
854
|
+
compressedSize = readU64(bytes, f);
|
|
855
|
+
f += 8;
|
|
856
|
+
}
|
|
857
|
+
if (localHeaderOffset === 4294967295 && f + 8 <= end) localHeaderOffset = readU64(bytes, f);
|
|
858
|
+
}
|
|
859
|
+
e += 4 + len;
|
|
860
|
+
}
|
|
861
|
+
const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 2048) !== 0);
|
|
862
|
+
const name = rawName.replace(/\\/g, "/");
|
|
863
|
+
p = next;
|
|
864
|
+
if (isUnsafeZipPath(rawName)) {
|
|
865
|
+
if (options.unsafePaths === "skip") continue;
|
|
866
|
+
throw new ZipError("unsafe_path", `ZIP entry name "${rawName}" is absolute or escapes the archive root.`, {
|
|
867
|
+
entryName: rawName
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
entries.push({
|
|
871
|
+
name,
|
|
872
|
+
isDirectory: name.endsWith("/"),
|
|
873
|
+
encrypted: (flags & 1) !== 0,
|
|
874
|
+
method,
|
|
875
|
+
compressedSize,
|
|
876
|
+
size,
|
|
877
|
+
crc32,
|
|
878
|
+
localHeaderOffset
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
return new ZipArchive(bytes, entries, maxTotalSize);
|
|
882
|
+
}
|
|
883
|
+
|
|
513
884
|
export {
|
|
514
885
|
CHART_OOXML_NS,
|
|
515
886
|
CHART_OOXML_CONTENT_TYPE,
|
|
516
887
|
CHART_OOXML_RELATIONSHIP,
|
|
517
888
|
chartFromOoxml,
|
|
518
889
|
chartFormatToCode,
|
|
519
|
-
chartToOoxml
|
|
890
|
+
chartToOoxml,
|
|
891
|
+
ZipError,
|
|
892
|
+
DEFAULT_ZIP_MAX_ENTRIES,
|
|
893
|
+
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
894
|
+
zipCrc32,
|
|
895
|
+
isUnsafeZipPath,
|
|
896
|
+
ZipArchive,
|
|
897
|
+
readZip
|
|
520
898
|
};
|
|
521
|
-
//# sourceMappingURL=chunk-
|
|
899
|
+
//# sourceMappingURL=chunk-3S72F46R.js.map
|