xlkit 1.2.1 → 1.3.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/LICENSE +21 -21
- package/README.md +57 -841
- package/dist/index.cjs +70 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +77 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -8
package/dist/index.d.cts
CHANGED
|
@@ -139,6 +139,14 @@ declare class SheetBuilder {
|
|
|
139
139
|
* 新しいシートを追加(WorkbookBuilderに委譲)
|
|
140
140
|
*/
|
|
141
141
|
sheet(name?: string): SheetBuilder;
|
|
142
|
+
/**
|
|
143
|
+
* 複数のワークブックをマージする(WorkbookBuilderに委譲)
|
|
144
|
+
*/
|
|
145
|
+
merge(workbooks: (WorkbookBuilder | SheetBuilder)[]): WorkbookBuilder;
|
|
146
|
+
/**
|
|
147
|
+
* ワークブックの状態を取得(WorkbookBuilderに委譲)
|
|
148
|
+
*/
|
|
149
|
+
getState(): WorkbookState;
|
|
142
150
|
/**
|
|
143
151
|
* ブラウザ向け出力オブジェクトを取得(WorkbookBuilderに委譲)
|
|
144
152
|
*/
|
|
@@ -157,6 +165,12 @@ declare class WorkbookBuilder {
|
|
|
157
165
|
* @param name シート名(省略時は "Sheet1", "Sheet2", ...)
|
|
158
166
|
*/
|
|
159
167
|
sheet(name?: string): SheetBuilder;
|
|
168
|
+
/**
|
|
169
|
+
* 複数のワークブックをマージする
|
|
170
|
+
* @param workbooks マージするワークブックの配列
|
|
171
|
+
* @returns this(メソッドチェーン用)
|
|
172
|
+
*/
|
|
173
|
+
merge(workbooks: (WorkbookBuilder | SheetBuilder)[]): this;
|
|
160
174
|
/**
|
|
161
175
|
* ワークブックの状態を取得(内部用)
|
|
162
176
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,14 @@ declare class SheetBuilder {
|
|
|
139
139
|
* 新しいシートを追加(WorkbookBuilderに委譲)
|
|
140
140
|
*/
|
|
141
141
|
sheet(name?: string): SheetBuilder;
|
|
142
|
+
/**
|
|
143
|
+
* 複数のワークブックをマージする(WorkbookBuilderに委譲)
|
|
144
|
+
*/
|
|
145
|
+
merge(workbooks: (WorkbookBuilder | SheetBuilder)[]): WorkbookBuilder;
|
|
146
|
+
/**
|
|
147
|
+
* ワークブックの状態を取得(WorkbookBuilderに委譲)
|
|
148
|
+
*/
|
|
149
|
+
getState(): WorkbookState;
|
|
142
150
|
/**
|
|
143
151
|
* ブラウザ向け出力オブジェクトを取得(WorkbookBuilderに委譲)
|
|
144
152
|
*/
|
|
@@ -157,6 +165,12 @@ declare class WorkbookBuilder {
|
|
|
157
165
|
* @param name シート名(省略時は "Sheet1", "Sheet2", ...)
|
|
158
166
|
*/
|
|
159
167
|
sheet(name?: string): SheetBuilder;
|
|
168
|
+
/**
|
|
169
|
+
* 複数のワークブックをマージする
|
|
170
|
+
* @param workbooks マージするワークブックの配列
|
|
171
|
+
* @returns this(メソッドチェーン用)
|
|
172
|
+
*/
|
|
173
|
+
merge(workbooks: (WorkbookBuilder | SheetBuilder)[]): this;
|
|
160
174
|
/**
|
|
161
175
|
* ワークブックの状態を取得(内部用)
|
|
162
176
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/engine/writer.ts
|
|
2
9
|
import ExcelJS from "exceljs";
|
|
3
10
|
|
|
4
|
-
// src/engine/sheet-writer.ts
|
|
5
|
-
import { readFileSync } from "fs";
|
|
6
|
-
|
|
7
11
|
// src/styles/converter.ts
|
|
8
12
|
function convertToExcelJSStyle(style) {
|
|
9
13
|
if (!style) return {};
|
|
@@ -201,7 +205,7 @@ var TABLE_PRESETS = {
|
|
|
201
205
|
function getPreset(presetName) {
|
|
202
206
|
const preset = TABLE_PRESETS[presetName];
|
|
203
207
|
if (!preset) {
|
|
204
|
-
throw new Error(
|
|
208
|
+
throw new Error(`Unknown preset name: ${presetName}`);
|
|
205
209
|
}
|
|
206
210
|
return preset;
|
|
207
211
|
}
|
|
@@ -225,6 +229,14 @@ function isSpaceBlock(block) {
|
|
|
225
229
|
return block.type === "space";
|
|
226
230
|
}
|
|
227
231
|
|
|
232
|
+
// src/utils/buffer.ts
|
|
233
|
+
function isBuffer(value) {
|
|
234
|
+
return typeof Buffer !== "undefined" && Buffer.isBuffer(value);
|
|
235
|
+
}
|
|
236
|
+
function isUrl(value) {
|
|
237
|
+
return value.startsWith("http://") || value.startsWith("https://");
|
|
238
|
+
}
|
|
239
|
+
|
|
228
240
|
// src/types/column.ts
|
|
229
241
|
function isLeafColumn(column) {
|
|
230
242
|
return "key" in column;
|
|
@@ -355,21 +367,21 @@ var SheetWriter = class {
|
|
|
355
367
|
/**
|
|
356
368
|
* SheetStateを書き込む
|
|
357
369
|
*/
|
|
358
|
-
writeSheet(sheetState) {
|
|
370
|
+
async writeSheet(sheetState) {
|
|
359
371
|
for (const block of sheetState.blocks) {
|
|
360
|
-
this.writeBlock(block);
|
|
372
|
+
await this.writeBlock(block);
|
|
361
373
|
}
|
|
362
374
|
}
|
|
363
375
|
/**
|
|
364
376
|
* ブロックを書き込む
|
|
365
377
|
*/
|
|
366
|
-
writeBlock(block) {
|
|
378
|
+
async writeBlock(block) {
|
|
367
379
|
if (isTableBlock(block)) {
|
|
368
380
|
this.writeTable(block.options);
|
|
369
381
|
} else if (isTextBlock(block)) {
|
|
370
382
|
this.writeText(block.input);
|
|
371
383
|
} else if (isImageBlock(block)) {
|
|
372
|
-
this.writeImage(block.options);
|
|
384
|
+
await this.writeImage(block.options);
|
|
373
385
|
} else if (isSpaceBlock(block)) {
|
|
374
386
|
this.writeSpace(block.lines);
|
|
375
387
|
}
|
|
@@ -602,13 +614,20 @@ var SheetWriter = class {
|
|
|
602
614
|
/**
|
|
603
615
|
* 画像を書き込む
|
|
604
616
|
*/
|
|
605
|
-
writeImage(options) {
|
|
617
|
+
async writeImage(options) {
|
|
606
618
|
const { source, width = 100, height = 100, row, col = 0 } = options;
|
|
607
619
|
let imageBuffer;
|
|
608
|
-
if (
|
|
620
|
+
if (isBuffer(source)) {
|
|
609
621
|
imageBuffer = source;
|
|
622
|
+
} else if (isUrl(source)) {
|
|
623
|
+
const response = await fetch(source);
|
|
624
|
+
imageBuffer = await response.arrayBuffer();
|
|
610
625
|
} else {
|
|
611
|
-
|
|
626
|
+
if (typeof window !== "undefined") {
|
|
627
|
+
throw new Error("File path is not supported in browser. Use URL or Buffer.");
|
|
628
|
+
}
|
|
629
|
+
const fs = __require("fs");
|
|
630
|
+
imageBuffer = fs.readFileSync(source);
|
|
612
631
|
}
|
|
613
632
|
const imageId = this.workbook.addImage({
|
|
614
633
|
buffer: imageBuffer,
|
|
@@ -637,7 +656,7 @@ async function writeWorkbook(state) {
|
|
|
637
656
|
for (const sheetState of state.sheets) {
|
|
638
657
|
const worksheet = workbook.addWorksheet(sheetState.name);
|
|
639
658
|
const writer = new SheetWriter(workbook, worksheet);
|
|
640
|
-
writer.writeSheet(sheetState);
|
|
659
|
+
await writer.writeSheet(sheetState);
|
|
641
660
|
}
|
|
642
661
|
return workbook;
|
|
643
662
|
}
|
|
@@ -693,30 +712,32 @@ var EXCEL_LIMITS = {
|
|
|
693
712
|
};
|
|
694
713
|
function validateSheetName(name) {
|
|
695
714
|
if (name.length > EXCEL_LIMITS.SHEET_NAME_MAX_LENGTH) {
|
|
696
|
-
throw new Error("
|
|
715
|
+
throw new Error("Sheet name must be 31 characters or less");
|
|
697
716
|
}
|
|
698
717
|
for (const char of EXCEL_LIMITS.SHEET_NAME_INVALID_CHARS) {
|
|
699
718
|
if (name.includes(char)) {
|
|
700
|
-
throw new Error(
|
|
719
|
+
throw new Error(`Sheet name contains invalid character: ${char}`);
|
|
701
720
|
}
|
|
702
721
|
}
|
|
703
722
|
if (name.trim().length === 0) {
|
|
704
|
-
throw new Error("
|
|
723
|
+
throw new Error("Sheet name cannot be only whitespace");
|
|
705
724
|
}
|
|
706
725
|
}
|
|
707
726
|
function validateDataSize(rowCount, columnCount) {
|
|
708
727
|
if (rowCount > EXCEL_LIMITS.MAX_ROWS) {
|
|
709
|
-
throw new Error("
|
|
728
|
+
throw new Error("Row count exceeds Excel limit (1,048,576 rows)");
|
|
710
729
|
}
|
|
711
730
|
if (columnCount > EXCEL_LIMITS.MAX_COLUMNS) {
|
|
712
|
-
throw new Error("
|
|
731
|
+
throw new Error("Column count exceeds Excel limit (16,384 columns)");
|
|
713
732
|
}
|
|
714
733
|
}
|
|
715
734
|
|
|
716
735
|
// src/schemas/image.ts
|
|
717
736
|
import { z } from "zod";
|
|
718
737
|
var imageSourceSchema = z.union([
|
|
719
|
-
z.
|
|
738
|
+
z.custom((val) => isBuffer(val), {
|
|
739
|
+
message: "Expected Buffer"
|
|
740
|
+
}),
|
|
720
741
|
z.string().url(),
|
|
721
742
|
// URL形式
|
|
722
743
|
z.string().min(1)
|
|
@@ -856,7 +877,7 @@ var SheetBuilder = class {
|
|
|
856
877
|
*/
|
|
857
878
|
space(lines = 1) {
|
|
858
879
|
if (lines <= 0) {
|
|
859
|
-
throw new Error("space()
|
|
880
|
+
throw new Error("space() argument must be a positive integer");
|
|
860
881
|
}
|
|
861
882
|
const block = { type: "space", lines };
|
|
862
883
|
this.sheetState.blocks.push(block);
|
|
@@ -868,6 +889,18 @@ var SheetBuilder = class {
|
|
|
868
889
|
sheet(name) {
|
|
869
890
|
return this.workbook.sheet(name);
|
|
870
891
|
}
|
|
892
|
+
/**
|
|
893
|
+
* 複数のワークブックをマージする(WorkbookBuilderに委譲)
|
|
894
|
+
*/
|
|
895
|
+
merge(workbooks) {
|
|
896
|
+
return this.workbook.merge(workbooks);
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* ワークブックの状態を取得(WorkbookBuilderに委譲)
|
|
900
|
+
*/
|
|
901
|
+
getState() {
|
|
902
|
+
return this.workbook.getState();
|
|
903
|
+
}
|
|
871
904
|
/**
|
|
872
905
|
* ブラウザ向け出力オブジェクトを取得(WorkbookBuilderに委譲)
|
|
873
906
|
*/
|
|
@@ -897,12 +930,33 @@ var WorkbookBuilder = class {
|
|
|
897
930
|
const sheetName = name ?? `Sheet${this.state.sheets.length + 1}`;
|
|
898
931
|
validateSheetName(sheetName);
|
|
899
932
|
if (this.state.sheets.some((s) => s.name === sheetName)) {
|
|
900
|
-
throw new Error(
|
|
933
|
+
throw new Error(`Sheet name "${sheetName}" already exists`);
|
|
901
934
|
}
|
|
902
935
|
const sheetState = { name: sheetName, blocks: [] };
|
|
903
936
|
this.state.sheets.push(sheetState);
|
|
904
937
|
return new SheetBuilder(this, sheetState);
|
|
905
938
|
}
|
|
939
|
+
/**
|
|
940
|
+
* 複数のワークブックをマージする
|
|
941
|
+
* @param workbooks マージするワークブックの配列
|
|
942
|
+
* @returns this(メソッドチェーン用)
|
|
943
|
+
*/
|
|
944
|
+
merge(workbooks) {
|
|
945
|
+
for (const workbook of workbooks) {
|
|
946
|
+
const sourceState = workbook.getState();
|
|
947
|
+
if (sourceState.sheets.length === 0) {
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
for (const sheet of sourceState.sheets) {
|
|
951
|
+
if (this.state.sheets.some((s) => s.name === sheet.name)) {
|
|
952
|
+
throw new Error(`Sheet name "${sheet.name}" already exists`);
|
|
953
|
+
}
|
|
954
|
+
validateSheetName(sheet.name);
|
|
955
|
+
this.state.sheets.push(sheet);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return this;
|
|
959
|
+
}
|
|
906
960
|
/**
|
|
907
961
|
* ワークブックの状態を取得(内部用)
|
|
908
962
|
*/
|
|
@@ -1108,7 +1162,7 @@ var WorkbookReader = class {
|
|
|
1108
1162
|
sheet(name) {
|
|
1109
1163
|
const worksheet = this.workbook.getWorksheet(name);
|
|
1110
1164
|
if (!worksheet) {
|
|
1111
|
-
throw new Error(
|
|
1165
|
+
throw new Error(`Sheet "${name}" not found`);
|
|
1112
1166
|
}
|
|
1113
1167
|
return new SheetReader(worksheet);
|
|
1114
1168
|
}
|
|
@@ -1118,7 +1172,7 @@ var WorkbookReader = class {
|
|
|
1118
1172
|
sheetAt(index) {
|
|
1119
1173
|
const worksheet = this.workbook.worksheets[index];
|
|
1120
1174
|
if (!worksheet) {
|
|
1121
|
-
throw new Error(
|
|
1175
|
+
throw new Error(`Sheet at index ${index} not found`);
|
|
1122
1176
|
}
|
|
1123
1177
|
return new SheetReader(worksheet);
|
|
1124
1178
|
}
|
|
@@ -1131,7 +1185,7 @@ var WorkbookReader = class {
|
|
|
1131
1185
|
};
|
|
1132
1186
|
async function read(source) {
|
|
1133
1187
|
const workbook = new ExcelJS2.Workbook();
|
|
1134
|
-
if (
|
|
1188
|
+
if (isBuffer(source)) {
|
|
1135
1189
|
await workbook.xlsx.load(source);
|
|
1136
1190
|
} else {
|
|
1137
1191
|
await workbook.xlsx.readFile(source);
|