@particle-academy/holy-sheet 2.5.0 → 2.6.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/CHANGELOG.md +550 -0
- package/dist/index.cjs +103 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +103 -61
- package/dist/index.js.map +1 -1
- package/package.json +67 -66
package/dist/index.cjs
CHANGED
|
@@ -495,6 +495,54 @@ var DateConverter = {
|
|
|
495
495
|
}
|
|
496
496
|
};
|
|
497
497
|
|
|
498
|
+
// src/exceptions.ts
|
|
499
|
+
var SchemaException = class _SchemaException extends Error {
|
|
500
|
+
constructor(errors, message) {
|
|
501
|
+
super(message ?? summarize(errors));
|
|
502
|
+
this.name = "SchemaException";
|
|
503
|
+
this.errors = errors;
|
|
504
|
+
Object.setPrototypeOf(this, _SchemaException.prototype);
|
|
505
|
+
}
|
|
506
|
+
static fromErrors(errors) {
|
|
507
|
+
return new _SchemaException(errors);
|
|
508
|
+
}
|
|
509
|
+
getErrors() {
|
|
510
|
+
return this.errors;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
function summarize(errors) {
|
|
514
|
+
if (errors.length === 1) {
|
|
515
|
+
const e = errors[0];
|
|
516
|
+
return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
|
|
517
|
+
}
|
|
518
|
+
const first2 = errors[0];
|
|
519
|
+
const rest = errors.length - 1;
|
|
520
|
+
return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
|
|
521
|
+
}
|
|
522
|
+
var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
|
|
523
|
+
constructor(message, path = null, mimetype = null) {
|
|
524
|
+
super(message);
|
|
525
|
+
this.name = "UnsupportedFormatException";
|
|
526
|
+
this.path = path;
|
|
527
|
+
this.mimetype = mimetype;
|
|
528
|
+
Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
|
|
529
|
+
}
|
|
530
|
+
static notAZip(path = null) {
|
|
531
|
+
return new _UnsupportedFormatException(
|
|
532
|
+
`[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
|
|
533
|
+
path
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
static unknownPackage(path, mimetype) {
|
|
537
|
+
const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
|
|
538
|
+
return new _UnsupportedFormatException(
|
|
539
|
+
`[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
|
|
540
|
+
path,
|
|
541
|
+
mimetype !== "" ? mimetype : null
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
|
|
498
546
|
// src/schema/theme.ts
|
|
499
547
|
var Theme = class {
|
|
500
548
|
constructor(key) {
|
|
@@ -572,7 +620,7 @@ var Normalizer = class {
|
|
|
572
620
|
const columnFormat = columnFormats.get(c) ?? null;
|
|
573
621
|
const rowBand = theme.dataFormat(r);
|
|
574
622
|
const merged = rowBand !== null ? columnFormat ? columnFormat.mergeWith(rowBand) : rowBand : columnFormat;
|
|
575
|
-
cells.set(address, this.buildCell(address, value, merged));
|
|
623
|
+
cells.set(address, this.buildCell(address, value, merged, name));
|
|
576
624
|
});
|
|
577
625
|
});
|
|
578
626
|
if (sheet.totals && isPlainObject(sheet.totals) && Object.keys(sheet.totals).length > 0 && rows.length > 0 && columns.length > 0) {
|
|
@@ -596,7 +644,7 @@ var Normalizer = class {
|
|
|
596
644
|
}
|
|
597
645
|
}
|
|
598
646
|
if (sheet.cells != null) {
|
|
599
|
-
for (const [address, cell] of this.normalizeCellMap(sheet.cells)) {
|
|
647
|
+
for (const [address, cell] of this.normalizeCellMap(sheet.cells, name)) {
|
|
600
648
|
const beneath = cells.get(address);
|
|
601
649
|
cells.set(
|
|
602
650
|
address,
|
|
@@ -620,14 +668,18 @@ var Normalizer = class {
|
|
|
620
668
|
toInt(sheet.frozenCols ?? 0)
|
|
621
669
|
);
|
|
622
670
|
}
|
|
623
|
-
normalizeCellMap(map) {
|
|
671
|
+
normalizeCellMap(map, sheetName2) {
|
|
624
672
|
const cells = /* @__PURE__ */ new Map();
|
|
625
673
|
for (const [address, cellData] of Object.entries(map)) {
|
|
626
|
-
if (!
|
|
674
|
+
if (!isCellSpec(cellData)) {
|
|
627
675
|
const [bare, formula] = promoteFormula(cellData);
|
|
628
676
|
cells.set(
|
|
629
677
|
address,
|
|
630
|
-
new Cell(
|
|
678
|
+
new Cell(
|
|
679
|
+
address,
|
|
680
|
+
formula !== null ? null : this.coerceValue(bare, null, address, sheetName2),
|
|
681
|
+
formula
|
|
682
|
+
)
|
|
631
683
|
);
|
|
632
684
|
continue;
|
|
633
685
|
}
|
|
@@ -642,7 +694,7 @@ var Normalizer = class {
|
|
|
642
694
|
address,
|
|
643
695
|
new Cell(
|
|
644
696
|
address,
|
|
645
|
-
this.coerceValue(rawValue, format),
|
|
697
|
+
this.coerceValue(rawValue, format, address, sheetName2),
|
|
646
698
|
cellData?.formula ?? null,
|
|
647
699
|
format,
|
|
648
700
|
comment,
|
|
@@ -723,8 +775,8 @@ var Normalizer = class {
|
|
|
723
775
|
return null;
|
|
724
776
|
}
|
|
725
777
|
}
|
|
726
|
-
buildCell(address, value, columnFormat) {
|
|
727
|
-
if (
|
|
778
|
+
buildCell(address, value, columnFormat, sheetName2) {
|
|
779
|
+
if (isCellSpec(value)) {
|
|
728
780
|
const cellFormat = isPlainObject(value.format) ? CellFormat.fromInput(value.format) : null;
|
|
729
781
|
const merged = columnFormat ? columnFormat.mergeWith(cellFormat) : cellFormat;
|
|
730
782
|
const comment = isPlainObject(value.comment) ? new CellComment(
|
|
@@ -735,7 +787,7 @@ var Normalizer = class {
|
|
|
735
787
|
const rawValue = value.value ?? null;
|
|
736
788
|
return new Cell(
|
|
737
789
|
address,
|
|
738
|
-
this.coerceValue(rawValue, merged),
|
|
790
|
+
this.coerceValue(rawValue, merged, address, sheetName2),
|
|
739
791
|
value.formula ?? null,
|
|
740
792
|
merged,
|
|
741
793
|
comment,
|
|
@@ -745,12 +797,12 @@ var Normalizer = class {
|
|
|
745
797
|
const [bare, formula] = promoteFormula(value);
|
|
746
798
|
return new Cell(
|
|
747
799
|
address,
|
|
748
|
-
formula !== null ? null : this.coerceValue(bare, columnFormat),
|
|
800
|
+
formula !== null ? null : this.coerceValue(bare, columnFormat, address, sheetName2),
|
|
749
801
|
formula,
|
|
750
802
|
columnFormat
|
|
751
803
|
);
|
|
752
804
|
}
|
|
753
|
-
coerceValue(value, format) {
|
|
805
|
+
coerceValue(value, format, address = "?", sheetName2) {
|
|
754
806
|
if (value === null || value === void 0) return null;
|
|
755
807
|
const df = format?.displayFormat;
|
|
756
808
|
if (df === "date" || df === "datetime") {
|
|
@@ -764,12 +816,36 @@ var Normalizer = class {
|
|
|
764
816
|
if (value instanceof Date) {
|
|
765
817
|
return DateConverter.toSerial(value, true);
|
|
766
818
|
}
|
|
767
|
-
if (typeof value
|
|
819
|
+
if (typeof value === "bigint") {
|
|
820
|
+
return String(value);
|
|
821
|
+
}
|
|
822
|
+
if (typeof value === "object" && !Array.isArray(value) && hasOwnToString(value)) {
|
|
768
823
|
return String(value);
|
|
769
824
|
}
|
|
825
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
826
|
+
const where = sheetName2 === void 0 ? address : `${sheetName2}!${address}`;
|
|
827
|
+
const got = typeOf(value);
|
|
828
|
+
throw SchemaException.fromErrors([
|
|
829
|
+
{
|
|
830
|
+
path: where,
|
|
831
|
+
expected: "a string, number, bool, null, Date, or an object with its own toString",
|
|
832
|
+
got,
|
|
833
|
+
value,
|
|
834
|
+
hint: Array.isArray(value) ? 'This cell holds an array. The usual cause is a `rows` entry nested one level too deep: `rows: [[["x"]]]` makes cell A1 an array, where `rows: [["x"]]` makes it the string "x". For a cell with formatting use the object form: {value: "x", format: {...}}.' : "Give the cell a scalar or a Date, or define toString() on the object so the conversion is yours rather than implicit."
|
|
835
|
+
}
|
|
836
|
+
]);
|
|
837
|
+
}
|
|
770
838
|
return value;
|
|
771
839
|
}
|
|
772
840
|
};
|
|
841
|
+
function isCellSpec(value) {
|
|
842
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
843
|
+
return Object.getPrototypeOf(value) === Object.prototype;
|
|
844
|
+
}
|
|
845
|
+
function hasOwnToString(value) {
|
|
846
|
+
const fn = value.toString;
|
|
847
|
+
return typeof fn === "function" && fn !== Object.prototype.toString;
|
|
848
|
+
}
|
|
773
849
|
function promoteFormula(value) {
|
|
774
850
|
if (typeof value === "string" && value.length > 1 && value[0] === "=") {
|
|
775
851
|
return [null, value.slice(1)];
|
|
@@ -1301,54 +1377,6 @@ function phpRound(x, n) {
|
|
|
1301
1377
|
return Math.sign(x) * Math.round(Math.abs(x) * factor) / factor;
|
|
1302
1378
|
}
|
|
1303
1379
|
|
|
1304
|
-
// src/exceptions.ts
|
|
1305
|
-
var SchemaException = class _SchemaException extends Error {
|
|
1306
|
-
constructor(errors, message) {
|
|
1307
|
-
super(message ?? summarize(errors));
|
|
1308
|
-
this.name = "SchemaException";
|
|
1309
|
-
this.errors = errors;
|
|
1310
|
-
Object.setPrototypeOf(this, _SchemaException.prototype);
|
|
1311
|
-
}
|
|
1312
|
-
static fromErrors(errors) {
|
|
1313
|
-
return new _SchemaException(errors);
|
|
1314
|
-
}
|
|
1315
|
-
getErrors() {
|
|
1316
|
-
return this.errors;
|
|
1317
|
-
}
|
|
1318
|
-
};
|
|
1319
|
-
function summarize(errors) {
|
|
1320
|
-
if (errors.length === 1) {
|
|
1321
|
-
const e = errors[0];
|
|
1322
|
-
return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
|
|
1323
|
-
}
|
|
1324
|
-
const first2 = errors[0];
|
|
1325
|
-
const rest = errors.length - 1;
|
|
1326
|
-
return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
|
|
1327
|
-
}
|
|
1328
|
-
var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
|
|
1329
|
-
constructor(message, path = null, mimetype = null) {
|
|
1330
|
-
super(message);
|
|
1331
|
-
this.name = "UnsupportedFormatException";
|
|
1332
|
-
this.path = path;
|
|
1333
|
-
this.mimetype = mimetype;
|
|
1334
|
-
Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
|
|
1335
|
-
}
|
|
1336
|
-
static notAZip(path = null) {
|
|
1337
|
-
return new _UnsupportedFormatException(
|
|
1338
|
-
`[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
|
|
1339
|
-
path
|
|
1340
|
-
);
|
|
1341
|
-
}
|
|
1342
|
-
static unknownPackage(path, mimetype) {
|
|
1343
|
-
const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
|
|
1344
|
-
return new _UnsupportedFormatException(
|
|
1345
|
-
`[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
|
|
1346
|
-
path,
|
|
1347
|
-
mimetype !== "" ? mimetype : null
|
|
1348
|
-
);
|
|
1349
|
-
}
|
|
1350
|
-
};
|
|
1351
|
-
|
|
1352
1380
|
// src/schema/repairer.ts
|
|
1353
1381
|
var VALID_THEMES = ["default", "minimal", "plain", "business"];
|
|
1354
1382
|
var ISO_DATE2 = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?$/;
|
|
@@ -1595,7 +1623,21 @@ var Validator = class {
|
|
|
1595
1623
|
"Each row is an array of cell values, in column order."
|
|
1596
1624
|
)
|
|
1597
1625
|
);
|
|
1626
|
+
return;
|
|
1598
1627
|
}
|
|
1628
|
+
row.forEach((cell, k) => {
|
|
1629
|
+
if (Array.isArray(cell)) {
|
|
1630
|
+
errors.push(
|
|
1631
|
+
error(
|
|
1632
|
+
`${path}.rows[${j}][${k}]`,
|
|
1633
|
+
"a cell value or a cell object",
|
|
1634
|
+
"array",
|
|
1635
|
+
cell,
|
|
1636
|
+
'This cell is an array, which usually means the row is nested one level too deep: `rows: [[["x"]]]` makes cell A1 an array, where `rows: [["x"]]` makes it "x". For a cell with formatting use the object form: {value: "x", format: {...}}.'
|
|
1637
|
+
)
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1599
1641
|
});
|
|
1600
1642
|
}
|
|
1601
1643
|
}
|
|
@@ -5179,7 +5221,7 @@ var holy_sheet_schema_default = {
|
|
|
5179
5221
|
};
|
|
5180
5222
|
|
|
5181
5223
|
// src/agent.ts
|
|
5182
|
-
var VERSION = "2.
|
|
5224
|
+
var VERSION = "2.6.0";
|
|
5183
5225
|
function toU8(input) {
|
|
5184
5226
|
return input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
5185
5227
|
}
|