@particle-academy/holy-sheet 2.6.0 → 2.7.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 +10 -0
- package/dist/index.cjs +248 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -7
- package/dist/index.d.ts +30 -7
- package/dist/index.js +248 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -58,6 +58,18 @@ interface SheetSchema {
|
|
|
58
58
|
columnWidths?: Record<number | string, number>;
|
|
59
59
|
frozenRows?: number;
|
|
60
60
|
frozenCols?: number;
|
|
61
|
+
/** 1-based row number → pixels. */
|
|
62
|
+
rowHeights?: Record<number | string, number>;
|
|
63
|
+
print?: {
|
|
64
|
+
orientation?: "portrait" | "landscape";
|
|
65
|
+
fitToWidth?: boolean;
|
|
66
|
+
/** `{page}` / `{pages}` print the page number and count. */
|
|
67
|
+
footer?: {
|
|
68
|
+
left?: string;
|
|
69
|
+
center?: string;
|
|
70
|
+
right?: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
61
73
|
}
|
|
62
74
|
interface HolySheetSchema {
|
|
63
75
|
sheets: SheetSchema[];
|
|
@@ -223,7 +235,7 @@ interface SetMetaOp {
|
|
|
223
235
|
}
|
|
224
236
|
|
|
225
237
|
/** This package's own version, pinned to package.json by `version.test.ts`. */
|
|
226
|
-
declare const VERSION = "2.
|
|
238
|
+
declare const VERSION = "2.7.0";
|
|
227
239
|
type Any$6 = any;
|
|
228
240
|
/**
|
|
229
241
|
* Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
|
|
@@ -295,7 +307,7 @@ type Any$5 = any;
|
|
|
295
307
|
* over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
|
|
296
308
|
*/
|
|
297
309
|
declare class HolySheet {
|
|
298
|
-
static readonly VERSION = "2.
|
|
310
|
+
static readonly VERSION = "2.7.0";
|
|
299
311
|
validate(schema: Any$5): ValidationError[];
|
|
300
312
|
toBytes(schema: Any$5): Uint8Array;
|
|
301
313
|
write(schema: Any$5, path: string): Promise<WriteResult>;
|
|
@@ -428,6 +440,16 @@ declare class MergedRegion {
|
|
|
428
440
|
ref(): string;
|
|
429
441
|
}
|
|
430
442
|
|
|
443
|
+
/** How a sheet prints. Mirrors the PHP `Sheet::$print` array. */
|
|
444
|
+
interface PrintSetup {
|
|
445
|
+
orientation: "portrait" | "landscape" | null;
|
|
446
|
+
fitToWidth: boolean;
|
|
447
|
+
footer: {
|
|
448
|
+
left: string;
|
|
449
|
+
center: string;
|
|
450
|
+
right: string;
|
|
451
|
+
} | null;
|
|
452
|
+
}
|
|
431
453
|
/** A worksheet. Mirrors PHP `Workbook\Sheet`. Cells are an A1-keyed map. */
|
|
432
454
|
declare class Sheet {
|
|
433
455
|
readonly name: string;
|
|
@@ -436,7 +458,12 @@ declare class Sheet {
|
|
|
436
458
|
readonly columnWidths: Map<number, number>;
|
|
437
459
|
readonly frozenRows: number;
|
|
438
460
|
readonly frozenCols: number;
|
|
439
|
-
|
|
461
|
+
/** 1-based row number → pixels. */
|
|
462
|
+
readonly rowHeights: Map<number, number>;
|
|
463
|
+
readonly print: PrintSetup | null;
|
|
464
|
+
constructor(name: string, cells?: Map<string, Cell>, mergedRegions?: MergedRegion[], columnWidths?: Map<number, number>, frozenRows?: number, frozenCols?: number,
|
|
465
|
+
/** 1-based row number → pixels. */
|
|
466
|
+
rowHeights?: Map<number, number>, print?: PrintSetup | null);
|
|
440
467
|
/** rowNumber → (colLetter → Cell), sorted by ascending row number. */
|
|
441
468
|
rows(): Map<number, Map<string, Cell>>;
|
|
442
469
|
hasComments(): boolean;
|
|
@@ -547,10 +574,6 @@ declare class Theme {
|
|
|
547
574
|
totalsFormat(): CellFormat | null;
|
|
548
575
|
}
|
|
549
576
|
|
|
550
|
-
/**
|
|
551
|
-
* XLSX writer — emits a complete OOXML SpreadsheetML package as bytes.
|
|
552
|
-
* Mirrors PHP `Writer\XlsxWriter` (file I/O moved to the Agent for isomorphism).
|
|
553
|
-
*/
|
|
554
577
|
declare class XlsxWriter {
|
|
555
578
|
toBytes(workbook: Workbook): Uint8Array;
|
|
556
579
|
private contentTypesXml;
|
package/dist/index.d.ts
CHANGED
|
@@ -58,6 +58,18 @@ interface SheetSchema {
|
|
|
58
58
|
columnWidths?: Record<number | string, number>;
|
|
59
59
|
frozenRows?: number;
|
|
60
60
|
frozenCols?: number;
|
|
61
|
+
/** 1-based row number → pixels. */
|
|
62
|
+
rowHeights?: Record<number | string, number>;
|
|
63
|
+
print?: {
|
|
64
|
+
orientation?: "portrait" | "landscape";
|
|
65
|
+
fitToWidth?: boolean;
|
|
66
|
+
/** `{page}` / `{pages}` print the page number and count. */
|
|
67
|
+
footer?: {
|
|
68
|
+
left?: string;
|
|
69
|
+
center?: string;
|
|
70
|
+
right?: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
61
73
|
}
|
|
62
74
|
interface HolySheetSchema {
|
|
63
75
|
sheets: SheetSchema[];
|
|
@@ -223,7 +235,7 @@ interface SetMetaOp {
|
|
|
223
235
|
}
|
|
224
236
|
|
|
225
237
|
/** This package's own version, pinned to package.json by `version.test.ts`. */
|
|
226
|
-
declare const VERSION = "2.
|
|
238
|
+
declare const VERSION = "2.7.0";
|
|
227
239
|
type Any$6 = any;
|
|
228
240
|
/**
|
|
229
241
|
* Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
|
|
@@ -295,7 +307,7 @@ type Any$5 = any;
|
|
|
295
307
|
* over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
|
|
296
308
|
*/
|
|
297
309
|
declare class HolySheet {
|
|
298
|
-
static readonly VERSION = "2.
|
|
310
|
+
static readonly VERSION = "2.7.0";
|
|
299
311
|
validate(schema: Any$5): ValidationError[];
|
|
300
312
|
toBytes(schema: Any$5): Uint8Array;
|
|
301
313
|
write(schema: Any$5, path: string): Promise<WriteResult>;
|
|
@@ -428,6 +440,16 @@ declare class MergedRegion {
|
|
|
428
440
|
ref(): string;
|
|
429
441
|
}
|
|
430
442
|
|
|
443
|
+
/** How a sheet prints. Mirrors the PHP `Sheet::$print` array. */
|
|
444
|
+
interface PrintSetup {
|
|
445
|
+
orientation: "portrait" | "landscape" | null;
|
|
446
|
+
fitToWidth: boolean;
|
|
447
|
+
footer: {
|
|
448
|
+
left: string;
|
|
449
|
+
center: string;
|
|
450
|
+
right: string;
|
|
451
|
+
} | null;
|
|
452
|
+
}
|
|
431
453
|
/** A worksheet. Mirrors PHP `Workbook\Sheet`. Cells are an A1-keyed map. */
|
|
432
454
|
declare class Sheet {
|
|
433
455
|
readonly name: string;
|
|
@@ -436,7 +458,12 @@ declare class Sheet {
|
|
|
436
458
|
readonly columnWidths: Map<number, number>;
|
|
437
459
|
readonly frozenRows: number;
|
|
438
460
|
readonly frozenCols: number;
|
|
439
|
-
|
|
461
|
+
/** 1-based row number → pixels. */
|
|
462
|
+
readonly rowHeights: Map<number, number>;
|
|
463
|
+
readonly print: PrintSetup | null;
|
|
464
|
+
constructor(name: string, cells?: Map<string, Cell>, mergedRegions?: MergedRegion[], columnWidths?: Map<number, number>, frozenRows?: number, frozenCols?: number,
|
|
465
|
+
/** 1-based row number → pixels. */
|
|
466
|
+
rowHeights?: Map<number, number>, print?: PrintSetup | null);
|
|
440
467
|
/** rowNumber → (colLetter → Cell), sorted by ascending row number. */
|
|
441
468
|
rows(): Map<number, Map<string, Cell>>;
|
|
442
469
|
hasComments(): boolean;
|
|
@@ -547,10 +574,6 @@ declare class Theme {
|
|
|
547
574
|
totalsFormat(): CellFormat | null;
|
|
548
575
|
}
|
|
549
576
|
|
|
550
|
-
/**
|
|
551
|
-
* XLSX writer — emits a complete OOXML SpreadsheetML package as bytes.
|
|
552
|
-
* Mirrors PHP `Writer\XlsxWriter` (file I/O moved to the Agent for isomorphism).
|
|
553
|
-
*/
|
|
554
577
|
declare class XlsxWriter {
|
|
555
578
|
toBytes(workbook: Workbook): Uint8Array;
|
|
556
579
|
private contentTypesXml;
|
package/dist/index.js
CHANGED
|
@@ -416,13 +416,15 @@ var MergedRegion = class {
|
|
|
416
416
|
|
|
417
417
|
// src/workbook/sheet.ts
|
|
418
418
|
var Sheet = class {
|
|
419
|
-
constructor(name, cells = /* @__PURE__ */ new Map(), mergedRegions = [], columnWidths = /* @__PURE__ */ new Map(), frozenRows = 0, frozenCols = 0) {
|
|
419
|
+
constructor(name, cells = /* @__PURE__ */ new Map(), mergedRegions = [], columnWidths = /* @__PURE__ */ new Map(), frozenRows = 0, frozenCols = 0, rowHeights = /* @__PURE__ */ new Map(), print = null) {
|
|
420
420
|
this.name = name;
|
|
421
421
|
this.cells = cells;
|
|
422
422
|
this.mergedRegions = mergedRegions;
|
|
423
423
|
this.columnWidths = columnWidths;
|
|
424
424
|
this.frozenRows = frozenRows;
|
|
425
425
|
this.frozenCols = frozenCols;
|
|
426
|
+
this.rowHeights = rowHeights;
|
|
427
|
+
this.print = print;
|
|
426
428
|
}
|
|
427
429
|
/** rowNumber → (colLetter → Cell), sorted by ascending row number. */
|
|
428
430
|
rows() {
|
|
@@ -663,7 +665,9 @@ var Normalizer = class {
|
|
|
663
665
|
this.normalizeMerges(sheet.mergedRegions ?? []),
|
|
664
666
|
this.normalizeWidths(sheet),
|
|
665
667
|
toInt(sheet.frozenRows ?? 0),
|
|
666
|
-
toInt(sheet.frozenCols ?? 0)
|
|
668
|
+
toInt(sheet.frozenCols ?? 0),
|
|
669
|
+
normalizeRowHeights(sheet.rowHeights),
|
|
670
|
+
normalizePrint(sheet.print)
|
|
667
671
|
);
|
|
668
672
|
}
|
|
669
673
|
normalizeCellMap(map, sheetName2) {
|
|
@@ -854,6 +858,34 @@ function toInt(v) {
|
|
|
854
858
|
const n = Math.trunc(Number(v));
|
|
855
859
|
return Number.isFinite(n) ? n : 0;
|
|
856
860
|
}
|
|
861
|
+
function phpNumeric(v) {
|
|
862
|
+
if (typeof v === "number") return Number.isFinite(v) ? v : null;
|
|
863
|
+
return isNumericString(v) ? numericStringToNumber(v) : null;
|
|
864
|
+
}
|
|
865
|
+
function normalizeRowHeights(map) {
|
|
866
|
+
const out = /* @__PURE__ */ new Map();
|
|
867
|
+
if (!isPlainObject(map) && !Array.isArray(map)) return out;
|
|
868
|
+
for (const [row, px] of Object.entries(map)) {
|
|
869
|
+
const n = phpNumeric(px);
|
|
870
|
+
if (/^[1-9]\d{0,6}$/.test(row) && n !== null && n >= 0) out.set(parseInt(row, 10), n);
|
|
871
|
+
}
|
|
872
|
+
return new Map([...out.entries()].sort((a, b) => a[0] - b[0]));
|
|
873
|
+
}
|
|
874
|
+
function normalizePrint(print) {
|
|
875
|
+
if (!isPlainObject(print) && !Array.isArray(print)) return null;
|
|
876
|
+
const p = print;
|
|
877
|
+
const orientation = p.orientation === "portrait" || p.orientation === "landscape" ? p.orientation : null;
|
|
878
|
+
const fitToWidth = p.fitToWidth === true;
|
|
879
|
+
let footer = null;
|
|
880
|
+
if (isPlainObject(p.footer) || Array.isArray(p.footer)) {
|
|
881
|
+
const f = p.footer;
|
|
882
|
+
const slot = (k) => typeof f[k] === "string" ? f[k] : "";
|
|
883
|
+
footer = { left: slot("left"), center: slot("center"), right: slot("right") };
|
|
884
|
+
if (footer.left === "" && footer.center === "" && footer.right === "") footer = null;
|
|
885
|
+
}
|
|
886
|
+
if (orientation === null && !fitToWidth && footer === null) return null;
|
|
887
|
+
return { orientation, fitToWidth, footer };
|
|
888
|
+
}
|
|
857
889
|
|
|
858
890
|
// src/schema/formula-linter.ts
|
|
859
891
|
var ERR_VALUE = "#VALUE!";
|
|
@@ -1701,6 +1733,95 @@ var Validator = class {
|
|
|
1701
1733
|
}
|
|
1702
1734
|
}
|
|
1703
1735
|
}
|
|
1736
|
+
if (sheet.rowHeights != null) {
|
|
1737
|
+
if (!isPlainObject(sheet.rowHeights) && !Array.isArray(sheet.rowHeights)) {
|
|
1738
|
+
errors.push(
|
|
1739
|
+
error(
|
|
1740
|
+
`${path}.rowHeights`,
|
|
1741
|
+
"object keyed by 1-based row number",
|
|
1742
|
+
typeOf(sheet.rowHeights),
|
|
1743
|
+
sheet.rowHeights,
|
|
1744
|
+
'Row heights map a row NUMBER to pixels: {"1": 32, "4": 28}.'
|
|
1745
|
+
)
|
|
1746
|
+
);
|
|
1747
|
+
} else {
|
|
1748
|
+
for (const [row, px] of Object.entries(sheet.rowHeights)) {
|
|
1749
|
+
const n = typeof px === "number" ? px : isNumericString(px) ? numericStringToNumber(px) : null;
|
|
1750
|
+
if (!/^[1-9]\d{0,6}$/.test(row)) {
|
|
1751
|
+
errors.push(error(
|
|
1752
|
+
`${path}.rowHeights.${row}`,
|
|
1753
|
+
"a 1-based row number",
|
|
1754
|
+
typeOf(row),
|
|
1755
|
+
row,
|
|
1756
|
+
'Keys are row numbers as Excel shows them: "1" is the first row.'
|
|
1757
|
+
));
|
|
1758
|
+
} else if (n === null || !Number.isFinite(n) || n < 0) {
|
|
1759
|
+
errors.push(error(
|
|
1760
|
+
`${path}.rowHeights.${row}`,
|
|
1761
|
+
"a non-negative number of pixels",
|
|
1762
|
+
typeOf(px),
|
|
1763
|
+
px,
|
|
1764
|
+
"A height is a number of pixels, like 28 (20 is a default row)."
|
|
1765
|
+
));
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
if (sheet.print != null) {
|
|
1771
|
+
const print = sheet.print;
|
|
1772
|
+
if (!isPlainObject(print) && !Array.isArray(print)) {
|
|
1773
|
+
errors.push(error(
|
|
1774
|
+
`${path}.print`,
|
|
1775
|
+
"object {orientation?, fitToWidth?, footer?}",
|
|
1776
|
+
typeOf(print),
|
|
1777
|
+
print,
|
|
1778
|
+
'Print setup: {"orientation": "landscape", "fitToWidth": true, "footer": {"right": "Page {page} of {pages}"}}.'
|
|
1779
|
+
));
|
|
1780
|
+
} else {
|
|
1781
|
+
if (print.orientation != null && print.orientation !== "portrait" && print.orientation !== "landscape") {
|
|
1782
|
+
errors.push(error(
|
|
1783
|
+
`${path}.print.orientation`,
|
|
1784
|
+
"one of: portrait, landscape",
|
|
1785
|
+
typeOf(print.orientation),
|
|
1786
|
+
print.orientation,
|
|
1787
|
+
"Use landscape for a sheet wider than it is tall."
|
|
1788
|
+
));
|
|
1789
|
+
}
|
|
1790
|
+
if (print.fitToWidth != null && typeof print.fitToWidth !== "boolean") {
|
|
1791
|
+
errors.push(error(
|
|
1792
|
+
`${path}.print.fitToWidth`,
|
|
1793
|
+
"boolean",
|
|
1794
|
+
typeOf(print.fitToWidth),
|
|
1795
|
+
print.fitToWidth,
|
|
1796
|
+
"true scales the sheet to one page wide when printed."
|
|
1797
|
+
));
|
|
1798
|
+
}
|
|
1799
|
+
if (print.footer != null) {
|
|
1800
|
+
if (!isPlainObject(print.footer) && !Array.isArray(print.footer)) {
|
|
1801
|
+
errors.push(error(
|
|
1802
|
+
`${path}.print.footer`,
|
|
1803
|
+
"object {left?, center?, right?}",
|
|
1804
|
+
typeOf(print.footer),
|
|
1805
|
+
print.footer,
|
|
1806
|
+
"A footer has up to three slots of text."
|
|
1807
|
+
));
|
|
1808
|
+
} else {
|
|
1809
|
+
const footer = print.footer;
|
|
1810
|
+
for (const slot of ["left", "center", "right"]) {
|
|
1811
|
+
if (footer[slot] != null && typeof footer[slot] !== "string") {
|
|
1812
|
+
errors.push(error(
|
|
1813
|
+
`${path}.print.footer.${slot}`,
|
|
1814
|
+
"string",
|
|
1815
|
+
typeOf(footer[slot]),
|
|
1816
|
+
footer[slot],
|
|
1817
|
+
"Footer text; {page} and {pages} print the page number and count."
|
|
1818
|
+
));
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1704
1825
|
return errors;
|
|
1705
1826
|
}
|
|
1706
1827
|
validateColumn(col, path) {
|
|
@@ -2790,6 +2911,22 @@ function sheetToSchema(sheet) {
|
|
|
2790
2911
|
}
|
|
2791
2912
|
if (sheet.frozenRows > 0) out["frozenRows"] = sheet.frozenRows;
|
|
2792
2913
|
if (sheet.frozenCols > 0) out["frozenCols"] = sheet.frozenCols;
|
|
2914
|
+
if (sheet.rowHeights.size > 0) {
|
|
2915
|
+
const heights = {};
|
|
2916
|
+
for (const [k, v] of sheet.rowHeights) heights[k] = v;
|
|
2917
|
+
out["rowHeights"] = heights;
|
|
2918
|
+
}
|
|
2919
|
+
if (sheet.print !== null) {
|
|
2920
|
+
const print = {};
|
|
2921
|
+
if (sheet.print.orientation !== null) print["orientation"] = sheet.print.orientation;
|
|
2922
|
+
if (sheet.print.fitToWidth) print["fitToWidth"] = true;
|
|
2923
|
+
if (sheet.print.footer !== null) {
|
|
2924
|
+
const footer = {};
|
|
2925
|
+
for (const k of ["left", "center", "right"]) if (sheet.print.footer[k] !== "") footer[k] = sheet.print.footer[k];
|
|
2926
|
+
print["footer"] = footer;
|
|
2927
|
+
}
|
|
2928
|
+
out["print"] = print;
|
|
2929
|
+
}
|
|
2793
2930
|
return out;
|
|
2794
2931
|
}
|
|
2795
2932
|
function cellToSchema(cell) {
|
|
@@ -3412,9 +3549,62 @@ var WorksheetParser = {
|
|
|
3412
3549
|
const merges = parseMerges(xml);
|
|
3413
3550
|
const columnWidths = parseColumnWidths(xml);
|
|
3414
3551
|
const [frozenRows, frozenCols] = parseFrozen(xml);
|
|
3415
|
-
return new Sheet(name, cells, merges, columnWidths, frozenRows, frozenCols);
|
|
3552
|
+
return new Sheet(name, cells, merges, columnWidths, frozenRows, frozenCols, parseRowHeights(xml), parsePrint(xml));
|
|
3416
3553
|
}
|
|
3417
3554
|
};
|
|
3555
|
+
function parseRowHeights(xml) {
|
|
3556
|
+
const out = /* @__PURE__ */ new Map();
|
|
3557
|
+
const sheetData = el(xml, "sheetData");
|
|
3558
|
+
if (!sheetData) return out;
|
|
3559
|
+
for (const row of els(sheetData, "row")) {
|
|
3560
|
+
const r = parseInt(at(row, "r") ?? "0", 10);
|
|
3561
|
+
const custom = at(row, "customHeight");
|
|
3562
|
+
const ht = at(row, "ht");
|
|
3563
|
+
if (r > 0 && ht !== void 0 && (custom === "1" || custom === "true")) {
|
|
3564
|
+
out.set(r, Math.round(parseFloat(ht) / 0.75 * 100) / 100);
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
return out;
|
|
3568
|
+
}
|
|
3569
|
+
function parsePrint(xml) {
|
|
3570
|
+
const fitToPage = ["1", "true"].includes(at(el(el(xml, "sheetPr"), "pageSetUpPr"), "fitToPage") ?? "");
|
|
3571
|
+
const setup = el(xml, "pageSetup");
|
|
3572
|
+
const o = at(setup, "orientation");
|
|
3573
|
+
const orientation = o === "portrait" || o === "landscape" ? o : null;
|
|
3574
|
+
const fitToWidth = fitToPage && setup !== void 0 && at(setup, "fitToWidth") === "1" && ["0", ""].includes(at(setup, "fitToHeight") ?? "");
|
|
3575
|
+
const oddFooter = el(el(xml, "headerFooter"), "oddFooter");
|
|
3576
|
+
const footer = oddFooter !== void 0 ? parseFooterCodes(oddFooter.text) : null;
|
|
3577
|
+
if (orientation === null && !fitToWidth && footer === null) return null;
|
|
3578
|
+
return { orientation, fitToWidth, footer };
|
|
3579
|
+
}
|
|
3580
|
+
function parseFooterCodes(codes) {
|
|
3581
|
+
const slots = { left: "", center: "", right: "" };
|
|
3582
|
+
let current = "center";
|
|
3583
|
+
const len = codes.length;
|
|
3584
|
+
for (let i = 0; i < len; i++) {
|
|
3585
|
+
const ch = codes[i];
|
|
3586
|
+
if (ch !== "&" || i + 1 >= len) {
|
|
3587
|
+
slots[current] += ch;
|
|
3588
|
+
continue;
|
|
3589
|
+
}
|
|
3590
|
+
const next = codes[++i];
|
|
3591
|
+
if (next === "&") slots[current] += "&";
|
|
3592
|
+
else if (next === "L") current = "left";
|
|
3593
|
+
else if (next === "C") current = "center";
|
|
3594
|
+
else if (next === "R") current = "right";
|
|
3595
|
+
else if (next === "P") slots[current] += "{page}";
|
|
3596
|
+
else if (next === "N") slots[current] += "{pages}";
|
|
3597
|
+
else if (next === '"') {
|
|
3598
|
+
const close = codes.indexOf('"', i + 1);
|
|
3599
|
+
i = close === -1 ? len : close;
|
|
3600
|
+
} else if (/[0-9]/.test(next)) {
|
|
3601
|
+
while (i + 1 < len && /[0-9]/.test(codes[i + 1])) i++;
|
|
3602
|
+
} else if (next === "K") {
|
|
3603
|
+
i = Math.min(len - 1, i + 6);
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
return slots.left === "" && slots.center === "" && slots.right === "" ? null : slots;
|
|
3607
|
+
}
|
|
3418
3608
|
function parseCells(xml, stylesIndex, comments, sharedStrings) {
|
|
3419
3609
|
const cells = /* @__PURE__ */ new Map();
|
|
3420
3610
|
const sheetData = el(xml, "sheetData");
|
|
@@ -3790,6 +3980,19 @@ function hexToArgb(hex2) {
|
|
|
3790
3980
|
|
|
3791
3981
|
// src/writer/xlsx-writer.ts
|
|
3792
3982
|
var encoder2 = new TextEncoder();
|
|
3983
|
+
function footerCodes(footer) {
|
|
3984
|
+
let codes = "";
|
|
3985
|
+
for (const [slot, code] of [["left", "&L"], ["center", "&C"], ["right", "&R"]]) {
|
|
3986
|
+
if (footer[slot] !== "") {
|
|
3987
|
+
codes += code + footer[slot].replace(/&/g, "&&").replace(/\{pages\}/g, "&N").replace(/\{page\}/g, "&P");
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
return codes;
|
|
3991
|
+
}
|
|
3992
|
+
function decimal(value) {
|
|
3993
|
+
const out = value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
|
|
3994
|
+
return out === "" || out === "-0" ? "0" : out;
|
|
3995
|
+
}
|
|
3793
3996
|
var XlsxWriter = class {
|
|
3794
3997
|
toBytes(workbook) {
|
|
3795
3998
|
const styles = new StylesRegistry();
|
|
@@ -3878,14 +4081,20 @@ var XlsxWriter = class {
|
|
|
3878
4081
|
}
|
|
3879
4082
|
colsXml += "</cols>";
|
|
3880
4083
|
}
|
|
4084
|
+
const rows = sheet.rows();
|
|
4085
|
+
for (const rowIndex of sheet.rowHeights.keys()) {
|
|
4086
|
+
if (!rows.has(rowIndex)) rows.set(rowIndex, /* @__PURE__ */ new Map());
|
|
4087
|
+
}
|
|
3881
4088
|
let rowsXml = "";
|
|
3882
|
-
for (const [rowIndex, row] of
|
|
4089
|
+
for (const [rowIndex, row] of [...rows.entries()].sort((a, b) => a[0] - b[0])) {
|
|
3883
4090
|
let cellsXml = "";
|
|
3884
4091
|
const sortedCols = [...row.keys()].sort();
|
|
3885
4092
|
for (const col of sortedCols) {
|
|
3886
4093
|
cellsXml += this.cellXml(row.get(col), styles);
|
|
3887
4094
|
}
|
|
3888
|
-
|
|
4095
|
+
const height = sheet.rowHeights.get(rowIndex);
|
|
4096
|
+
const ht = height !== void 0 ? ` ht="${decimal(height * 0.75)}" customHeight="1"` : "";
|
|
4097
|
+
rowsXml += cellsXml === "" ? `<row r="${rowIndex}"${ht}/>` : `<row r="${rowIndex}"${ht}>${cellsXml}</row>`;
|
|
3889
4098
|
}
|
|
3890
4099
|
let mergesXml = "";
|
|
3891
4100
|
if (sheet.mergedRegions.length > 0) {
|
|
@@ -3894,7 +4103,14 @@ var XlsxWriter = class {
|
|
|
3894
4103
|
mergesXml += "</mergeCells>";
|
|
3895
4104
|
}
|
|
3896
4105
|
const legacyDrawing = sheet.hasComments() ? '<legacyDrawing r:id="rId1"/>' : "";
|
|
3897
|
-
|
|
4106
|
+
const print = sheet.print;
|
|
4107
|
+
const sheetPrXml = print?.fitToWidth ? '<sheetPr><pageSetUpPr fitToPage="1"/></sheetPr>' : "";
|
|
4108
|
+
let pageSetupXml = "";
|
|
4109
|
+
if (print !== null && (print.orientation !== null || print.fitToWidth)) {
|
|
4110
|
+
pageSetupXml = "<pageSetup" + (print.orientation !== null ? ` orientation="${print.orientation}"` : "") + (print.fitToWidth ? ' fitToWidth="1" fitToHeight="0"' : "") + "/>";
|
|
4111
|
+
}
|
|
4112
|
+
const headerFooterXml = print?.footer ? `<headerFooter><oddFooter>${this.escape(footerCodes(print.footer))}</oddFooter></headerFooter>` : "";
|
|
4113
|
+
return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">' + sheetPrXml + sheetViewsXml + colsXml + `<sheetData>${rowsXml}</sheetData>` + mergesXml + pageSetupXml + headerFooterXml + legacyDrawing + "</worksheet>";
|
|
3898
4114
|
}
|
|
3899
4115
|
cellXml(cell, styles) {
|
|
3900
4116
|
const ref = cell.address;
|
|
@@ -5011,6 +5227,31 @@ var holy_sheet_schema_default = {
|
|
|
5011
5227
|
type: "integer",
|
|
5012
5228
|
minimum: 0,
|
|
5013
5229
|
description: "How many columns stay visible while the sheet scrolls sideways. Set to 1 when the first column is the label for the row."
|
|
5230
|
+
},
|
|
5231
|
+
rowHeights: {
|
|
5232
|
+
type: "object",
|
|
5233
|
+
description: 'Row heights in pixels, keyed by 1-based row NUMBER as Excel shows it: {"1": 32, "4": 28}. A default row is 20; give a title row or a header row room (28-36) instead of packing text against its fill.',
|
|
5234
|
+
propertyNames: { pattern: "^[1-9][0-9]*$" },
|
|
5235
|
+
additionalProperties: { type: "number", minimum: 0 }
|
|
5236
|
+
},
|
|
5237
|
+
print: {
|
|
5238
|
+
type: "object",
|
|
5239
|
+
additionalProperties: false,
|
|
5240
|
+
description: "How the sheet prints. A sheet wider than a page splits its columns across pages unless fitToWidth is set.",
|
|
5241
|
+
properties: {
|
|
5242
|
+
orientation: { type: "string", enum: ["portrait", "landscape"] },
|
|
5243
|
+
fitToWidth: { type: "boolean", description: "Scale the sheet to one page wide (as many pages tall as it needs)." },
|
|
5244
|
+
footer: {
|
|
5245
|
+
type: "object",
|
|
5246
|
+
additionalProperties: false,
|
|
5247
|
+
description: 'A printed footer: up to three slots. {page} and {pages} print the page number and count: {"left": "Q3 Revenue Review", "right": "Page {page} of {pages}"}.',
|
|
5248
|
+
properties: {
|
|
5249
|
+
left: { type: "string" },
|
|
5250
|
+
center: { type: "string" },
|
|
5251
|
+
right: { type: "string" }
|
|
5252
|
+
}
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5014
5255
|
}
|
|
5015
5256
|
}
|
|
5016
5257
|
},
|
|
@@ -5219,7 +5460,7 @@ var holy_sheet_schema_default = {
|
|
|
5219
5460
|
};
|
|
5220
5461
|
|
|
5221
5462
|
// src/agent.ts
|
|
5222
|
-
var VERSION = "2.
|
|
5463
|
+
var VERSION = "2.7.0";
|
|
5223
5464
|
function toU8(input) {
|
|
5224
5465
|
return input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
5225
5466
|
}
|