@particle-academy/holy-sheet 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.cjs +141 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +141 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -223,7 +223,7 @@ interface SetMetaOp {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/** This package's own version, pinned to package.json by `version.test.ts`. */
|
|
226
|
-
declare const VERSION = "2.
|
|
226
|
+
declare const VERSION = "2.5.0";
|
|
227
227
|
type Any$6 = any;
|
|
228
228
|
/**
|
|
229
229
|
* Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
|
|
@@ -295,7 +295,7 @@ type Any$5 = any;
|
|
|
295
295
|
* over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
|
|
296
296
|
*/
|
|
297
297
|
declare class HolySheet {
|
|
298
|
-
static readonly VERSION = "2.
|
|
298
|
+
static readonly VERSION = "2.5.0";
|
|
299
299
|
validate(schema: Any$5): ValidationError[];
|
|
300
300
|
toBytes(schema: Any$5): Uint8Array;
|
|
301
301
|
write(schema: Any$5, path: string): Promise<WriteResult>;
|
|
@@ -460,6 +460,22 @@ declare class Normalizer {
|
|
|
460
460
|
private normalizeSheet;
|
|
461
461
|
private normalizeCellMap;
|
|
462
462
|
private normalizeMerges;
|
|
463
|
+
/**
|
|
464
|
+
* The two ways a width can be stated, folded into one map.
|
|
465
|
+
*
|
|
466
|
+
* `columns[].width` widens the column at that POSITION; the sheet-level
|
|
467
|
+
* `columnWidths` map keys the same columns by 0-based index. Both have been
|
|
468
|
+
* described in the shared `skills/holy-sheet.schema.json` ("Same as
|
|
469
|
+
* columnWidths but per-column") for as long as the field has existed, and only
|
|
470
|
+
* the map was ever read — so a width written the way the schema documents it
|
|
471
|
+
* emitted no `<cols>` element at all, with no error and no repair note
|
|
472
|
+
* (holy-sheet#8, fixed in PHP 2.4.0; this is the twin).
|
|
473
|
+
*
|
|
474
|
+
* The MAP IS APPLIED LAST and wins, matching PHP. It is the mechanism that
|
|
475
|
+
* already worked, so anyone who reached for it to work around this bug must not
|
|
476
|
+
* now find a leftover `width` quietly overriding it.
|
|
477
|
+
*/
|
|
478
|
+
private normalizeWidths;
|
|
463
479
|
private normalizeColumnWidths;
|
|
464
480
|
private columnFormat;
|
|
465
481
|
private buildCell;
|
package/dist/index.d.ts
CHANGED
|
@@ -223,7 +223,7 @@ interface SetMetaOp {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/** This package's own version, pinned to package.json by `version.test.ts`. */
|
|
226
|
-
declare const VERSION = "2.
|
|
226
|
+
declare const VERSION = "2.5.0";
|
|
227
227
|
type Any$6 = any;
|
|
228
228
|
/**
|
|
229
229
|
* Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
|
|
@@ -295,7 +295,7 @@ type Any$5 = any;
|
|
|
295
295
|
* over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
|
|
296
296
|
*/
|
|
297
297
|
declare class HolySheet {
|
|
298
|
-
static readonly VERSION = "2.
|
|
298
|
+
static readonly VERSION = "2.5.0";
|
|
299
299
|
validate(schema: Any$5): ValidationError[];
|
|
300
300
|
toBytes(schema: Any$5): Uint8Array;
|
|
301
301
|
write(schema: Any$5, path: string): Promise<WriteResult>;
|
|
@@ -460,6 +460,22 @@ declare class Normalizer {
|
|
|
460
460
|
private normalizeSheet;
|
|
461
461
|
private normalizeCellMap;
|
|
462
462
|
private normalizeMerges;
|
|
463
|
+
/**
|
|
464
|
+
* The two ways a width can be stated, folded into one map.
|
|
465
|
+
*
|
|
466
|
+
* `columns[].width` widens the column at that POSITION; the sheet-level
|
|
467
|
+
* `columnWidths` map keys the same columns by 0-based index. Both have been
|
|
468
|
+
* described in the shared `skills/holy-sheet.schema.json` ("Same as
|
|
469
|
+
* columnWidths but per-column") for as long as the field has existed, and only
|
|
470
|
+
* the map was ever read — so a width written the way the schema documents it
|
|
471
|
+
* emitted no `<cols>` element at all, with no error and no repair note
|
|
472
|
+
* (holy-sheet#8, fixed in PHP 2.4.0; this is the twin).
|
|
473
|
+
*
|
|
474
|
+
* The MAP IS APPLIED LAST and wins, matching PHP. It is the mechanism that
|
|
475
|
+
* already worked, so anyone who reached for it to work around this bug must not
|
|
476
|
+
* now find a leftover `width` quietly overriding it.
|
|
477
|
+
*/
|
|
478
|
+
private normalizeWidths;
|
|
463
479
|
private normalizeColumnWidths;
|
|
464
480
|
private columnFormat;
|
|
465
481
|
private buildCell;
|
package/dist/index.js
CHANGED
|
@@ -285,6 +285,39 @@ var Cell = class {
|
|
|
285
285
|
}
|
|
286
286
|
};
|
|
287
287
|
|
|
288
|
+
// src/schema/column-widths.ts
|
|
289
|
+
var ColumnWidths = {
|
|
290
|
+
MAX_INDEX: 16383,
|
|
291
|
+
index(key) {
|
|
292
|
+
if (typeof key === "number") {
|
|
293
|
+
return Number.isInteger(key) && key >= 0 && key <= ColumnWidths.MAX_INDEX ? key : null;
|
|
294
|
+
}
|
|
295
|
+
if (typeof key === "string" && /^[0-9]{1,5}$/.test(key)) {
|
|
296
|
+
const index = parseInt(key, 10);
|
|
297
|
+
return index <= ColumnWidths.MAX_INDEX ? index : null;
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
},
|
|
301
|
+
width(px) {
|
|
302
|
+
if (typeof px === "number") {
|
|
303
|
+
return Number.isFinite(px) && px >= 0 ? px : null;
|
|
304
|
+
}
|
|
305
|
+
if (typeof px === "string" && /^[0-9]+(\.[0-9]+)?$/.test(px)) {
|
|
306
|
+
return Number(px);
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
},
|
|
310
|
+
/**
|
|
311
|
+
* A column letter key (`"B"`, `"aa"`) as an index, for repair only. One or two
|
|
312
|
+
* letters (A to ZZ): a longer run like `"abc"` is more likely a mistake than
|
|
313
|
+
* column ABC, and a repair must not guess.
|
|
314
|
+
*/
|
|
315
|
+
fromLetters(key) {
|
|
316
|
+
if (typeof key !== "string" || !/^[A-Za-z]{1,2}$/.test(key.trim())) return null;
|
|
317
|
+
return CellAddress.index(key.trim());
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
288
321
|
// src/workbook/cell-comment.ts
|
|
289
322
|
var CellComment = class {
|
|
290
323
|
constructor(text, author = null, color2 = null) {
|
|
@@ -580,7 +613,7 @@ var Normalizer = class {
|
|
|
580
613
|
name,
|
|
581
614
|
cells,
|
|
582
615
|
this.normalizeMerges(sheet.mergedRegions ?? []),
|
|
583
|
-
this.
|
|
616
|
+
this.normalizeWidths(sheet),
|
|
584
617
|
toInt(sheet.frozenRows ?? 0),
|
|
585
618
|
toInt(sheet.frozenCols ?? 0)
|
|
586
619
|
);
|
|
@@ -626,10 +659,43 @@ var Normalizer = class {
|
|
|
626
659
|
}
|
|
627
660
|
return out;
|
|
628
661
|
}
|
|
662
|
+
/**
|
|
663
|
+
* The two ways a width can be stated, folded into one map.
|
|
664
|
+
*
|
|
665
|
+
* `columns[].width` widens the column at that POSITION; the sheet-level
|
|
666
|
+
* `columnWidths` map keys the same columns by 0-based index. Both have been
|
|
667
|
+
* described in the shared `skills/holy-sheet.schema.json` ("Same as
|
|
668
|
+
* columnWidths but per-column") for as long as the field has existed, and only
|
|
669
|
+
* the map was ever read — so a width written the way the schema documents it
|
|
670
|
+
* emitted no `<cols>` element at all, with no error and no repair note
|
|
671
|
+
* (holy-sheet#8, fixed in PHP 2.4.0; this is the twin).
|
|
672
|
+
*
|
|
673
|
+
* The MAP IS APPLIED LAST and wins, matching PHP. It is the mechanism that
|
|
674
|
+
* already worked, so anyone who reached for it to work around this bug must not
|
|
675
|
+
* now find a leftover `width` quietly overriding it.
|
|
676
|
+
*/
|
|
677
|
+
normalizeWidths(sheet) {
|
|
678
|
+
const out = /* @__PURE__ */ new Map();
|
|
679
|
+
for (const [colIdx, columnDef] of (sheet.columns ?? []).entries()) {
|
|
680
|
+
if (columnDef === null || typeof columnDef !== "object") continue;
|
|
681
|
+
if (columnDef.width === void 0) continue;
|
|
682
|
+
const index = ColumnWidths.index(colIdx);
|
|
683
|
+
const width = ColumnWidths.width(columnDef.width);
|
|
684
|
+
if (index === null || width === null) continue;
|
|
685
|
+
out.set(index, width);
|
|
686
|
+
}
|
|
687
|
+
for (const [index, width] of this.normalizeColumnWidths(sheet.columnWidths ?? {})) {
|
|
688
|
+
out.set(index, width);
|
|
689
|
+
}
|
|
690
|
+
return new Map([...out.entries()].sort((a, b) => a[0] - b[0]));
|
|
691
|
+
}
|
|
629
692
|
normalizeColumnWidths(widths) {
|
|
630
693
|
const out = /* @__PURE__ */ new Map();
|
|
631
694
|
for (const [key, px] of Object.entries(widths)) {
|
|
632
|
-
|
|
695
|
+
const index = ColumnWidths.index(key);
|
|
696
|
+
const width = ColumnWidths.width(px);
|
|
697
|
+
if (index === null || width === null) continue;
|
|
698
|
+
out.set(index, width);
|
|
633
699
|
}
|
|
634
700
|
return out;
|
|
635
701
|
}
|
|
@@ -1327,6 +1393,30 @@ var Repairer = class {
|
|
|
1327
1393
|
sheet.theme = "default";
|
|
1328
1394
|
this.repairs.push(`changed '${path}.theme' from '${original}' to 'default' (unknown theme)`);
|
|
1329
1395
|
}
|
|
1396
|
+
if (sheet.columnWidths != null && (isPlainObject(sheet.columnWidths) || Array.isArray(sheet.columnWidths))) {
|
|
1397
|
+
const widths = {};
|
|
1398
|
+
let changed = false;
|
|
1399
|
+
for (const [key, px] of Object.entries(sheet.columnWidths)) {
|
|
1400
|
+
let index = ColumnWidths.index(key);
|
|
1401
|
+
if (index === null) {
|
|
1402
|
+
const letters = ColumnWidths.fromLetters(key);
|
|
1403
|
+
if (letters !== null) {
|
|
1404
|
+
index = letters;
|
|
1405
|
+
this.repairs.push(`converted '${path}.columnWidths.${key}' to column index ${index}`);
|
|
1406
|
+
changed = true;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
if (index === null || ColumnWidths.width(px) === null) {
|
|
1410
|
+
this.repairs.push(`dropped '${path}.columnWidths.${key}' (not a column index and a width)`);
|
|
1411
|
+
changed = true;
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
widths[String(index)] = px;
|
|
1415
|
+
}
|
|
1416
|
+
if (changed) {
|
|
1417
|
+
sheet.columnWidths = widths;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1330
1420
|
if (sheet.cells != null && isPlainObject(sheet.cells)) {
|
|
1331
1421
|
const cleaned = {};
|
|
1332
1422
|
let changed = false;
|
|
@@ -1532,6 +1622,43 @@ var Validator = class {
|
|
|
1532
1622
|
)
|
|
1533
1623
|
);
|
|
1534
1624
|
}
|
|
1625
|
+
if (sheet.columnWidths != null) {
|
|
1626
|
+
if (!isPlainObject(sheet.columnWidths) && !Array.isArray(sheet.columnWidths)) {
|
|
1627
|
+
errors.push(
|
|
1628
|
+
error(
|
|
1629
|
+
`${path}.columnWidths`,
|
|
1630
|
+
"object keyed by 0-based column index",
|
|
1631
|
+
typeOf(sheet.columnWidths),
|
|
1632
|
+
sheet.columnWidths,
|
|
1633
|
+
'Column widths map a 0-based column index to pixels: {"0": 120, "1": 80}.'
|
|
1634
|
+
)
|
|
1635
|
+
);
|
|
1636
|
+
} else {
|
|
1637
|
+
for (const [key, px] of Object.entries(sheet.columnWidths)) {
|
|
1638
|
+
if (ColumnWidths.index(key) === null) {
|
|
1639
|
+
errors.push(
|
|
1640
|
+
error(
|
|
1641
|
+
`${path}.columnWidths.${key}`,
|
|
1642
|
+
`a 0-based column index from 0 to ${ColumnWidths.MAX_INDEX}`,
|
|
1643
|
+
typeOf(key),
|
|
1644
|
+
key,
|
|
1645
|
+
'Keys are 0-based column indexes: "0" is column A, "1" is column B. Use the index, not the letter.'
|
|
1646
|
+
)
|
|
1647
|
+
);
|
|
1648
|
+
} else if (ColumnWidths.width(px) === null) {
|
|
1649
|
+
errors.push(
|
|
1650
|
+
error(
|
|
1651
|
+
`${path}.columnWidths.${key}`,
|
|
1652
|
+
"a non-negative number of pixels",
|
|
1653
|
+
typeOf(px),
|
|
1654
|
+
px,
|
|
1655
|
+
"A width is a number of pixels, like 120."
|
|
1656
|
+
)
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1535
1662
|
return errors;
|
|
1536
1663
|
}
|
|
1537
1664
|
validateColumn(col, path) {
|
|
@@ -1563,6 +1690,17 @@ var Validator = class {
|
|
|
1563
1690
|
)
|
|
1564
1691
|
);
|
|
1565
1692
|
}
|
|
1693
|
+
if (col.width !== void 0 && ColumnWidths.width(col.width) === null) {
|
|
1694
|
+
errors.push(
|
|
1695
|
+
error(
|
|
1696
|
+
`${path}.width`,
|
|
1697
|
+
"a non-negative number of pixels",
|
|
1698
|
+
typeOf(col.width),
|
|
1699
|
+
col.width,
|
|
1700
|
+
"A column width is a number of pixels, like 120. The sheet-level columnWidths map takes precedence over it."
|
|
1701
|
+
)
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1566
1704
|
return errors;
|
|
1567
1705
|
}
|
|
1568
1706
|
};
|
|
@@ -5039,7 +5177,7 @@ var holy_sheet_schema_default = {
|
|
|
5039
5177
|
};
|
|
5040
5178
|
|
|
5041
5179
|
// src/agent.ts
|
|
5042
|
-
var VERSION = "2.
|
|
5180
|
+
var VERSION = "2.5.0";
|
|
5043
5181
|
function toU8(input) {
|
|
5044
5182
|
return input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
5045
5183
|
}
|