@vdhewei/xlsx-template-lib 1.6.6 → 1.6.10

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/bin.mjs CHANGED
@@ -4,7 +4,8 @@ import {
4
4
  XlsxRender,
5
5
  compileAll,
6
6
  compileRuleSheetName,
7
- loadWorkbook
7
+ loadWorkbook,
8
+ toCellValue
8
9
  } from "./chunk-NSFBG6PV.mjs";
9
10
  import "./chunk-3GDQP6AS.mjs";
10
11
 
@@ -17,7 +18,6 @@ import * as path2 from "path";
17
18
 
18
19
  // src/bin-helpers.ts
19
20
  import * as path from "path";
20
- import * as url from "url";
21
21
  import { existsSync } from "fs";
22
22
  import * as fs from "fs/promises";
23
23
  import chalk from "chalk";
@@ -31,42 +31,84 @@ async function resolveFilePath(filePath) {
31
31
  if (existsSync(resolvedPath)) {
32
32
  return resolvedPath;
33
33
  }
34
- const scriptDir = path.dirname(url.fileURLToPath(import.meta.url));
34
+ const scriptDir = path.dirname(process.cwd());
35
35
  const relativePath = path.resolve(scriptDir, filePath);
36
36
  if (existsSync(relativePath)) {
37
37
  return relativePath;
38
38
  }
39
39
  throw new Error(`File not found: ${filePath}`);
40
40
  }
41
- async function parseRenderData(dataOption) {
41
+ function isValidJSON(str) {
42
+ const trimmed = str.trim();
43
+ if (!trimmed) return false;
44
+ const firstChar = trimmed[0];
45
+ const lastChar = trimmed.charAt(trimmed.length - 1);
46
+ const validStartEndPairs = [
47
+ ["{", "}"],
48
+ ["[", "]"],
49
+ ['"', '"']
50
+ ];
51
+ const hasValidFormat = validStartEndPairs.some(
52
+ ([start, end]) => firstChar === start && lastChar === end
53
+ );
54
+ if (!hasValidFormat && !["true", "false", "null"].includes(trimmed) && !/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(trimmed)) {
55
+ return false;
56
+ }
57
+ try {
58
+ JSON.parse(str);
59
+ return true;
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+ async function parseRenderData(dataOption, httpHeaders, body) {
42
65
  if (!dataOption) {
43
66
  return {};
44
67
  }
45
68
  try {
46
- return JSON.parse(dataOption);
47
- } catch (e) {
48
- try {
49
- const filePath = await resolveFilePath(dataOption);
50
- const fileContent = await fs.readFile(filePath, "utf-8");
51
- return JSON.parse(fileContent);
52
- } catch (e2) {
53
- if (dataOption.startsWith("http://") || dataOption.startsWith("https://")) {
54
- let fetch;
69
+ if (isValidJSON(dataOption)) {
70
+ return JSON.parse(dataOption);
71
+ }
72
+ if (dataOption.startsWith("http://") || dataOption.startsWith("https://")) {
73
+ let fetch;
74
+ try {
75
+ fetch = globalThis.fetch;
76
+ } catch (e3) {
55
77
  try {
56
- fetch = globalThis.fetch;
57
- } catch (e3) {
58
- try {
59
- const nodeFetch = await import("node-fetch");
60
- fetch = nodeFetch.default;
61
- } catch (e4) {
62
- throw new Error("Remote URLs require Node.js 18+ or node-fetch package");
63
- }
78
+ const nodeFetch = await import("node-fetch");
79
+ fetch = nodeFetch.default;
80
+ } catch (e4) {
81
+ console.error(chalk.red("Remote URLs require Node.js 18+ or node-fetch package"));
82
+ return void 0;
64
83
  }
65
- const response = await fetch(dataOption);
66
- return response.json();
67
84
  }
68
- throw new Error(`Failed to parse render data from: ${dataOption}`);
85
+ const headers = new Headers();
86
+ httpHeaders?.forEach((header) => {
87
+ const [key, value] = header.split(":");
88
+ headers.append(key, value);
89
+ });
90
+ const reqOpts = {
91
+ headers,
92
+ method: headers.get(`method`) ? headers.get(`method`).toUpperCase() : "GET"
93
+ };
94
+ if (body !== void 0 && body !== "") {
95
+ reqOpts.body = body;
96
+ }
97
+ console.log(chalk.gray(`Fetching data from: ${dataOption}`));
98
+ console.log(chalk.gray(`request.init: ${JSON.stringify(reqOpts)}`));
99
+ const response = await fetch(dataOption, reqOpts);
100
+ if (response.status !== 200) {
101
+ console.error(chalk.red(`Failed to fetch data from: ${dataOption}, status: ${response.status},${response.text()}`));
102
+ return void 0;
103
+ }
104
+ return response.json();
69
105
  }
106
+ const filePath = await resolveFilePath(dataOption);
107
+ const fileContent = await fs.readFile(filePath, "utf-8");
108
+ return JSON.parse(fileContent);
109
+ } catch (e) {
110
+ console.error(chalk.red(`Failed to parse render data from: ${dataOption}`));
111
+ return void 0;
70
112
  }
71
113
  }
72
114
  function checkSheetAndPlaceholders(xlsx, sheetName) {
@@ -76,43 +118,70 @@ function checkSheetAndPlaceholders(xlsx, sheetName) {
76
118
  throw new Error(`Sheet "${sheetName}" not found in Excel file`);
77
119
  }
78
120
  }
79
- async function addRuleToSheet(xlsxBuffer, ruleType, ruleExpr, sheetName = "export_metadata.config") {
80
- const workbook = await loadWorkbook(xlsxBuffer);
121
+ async function addRuleToSheet(workbook, ruleType, ruleExpr, sheetName = "export_metadata.config") {
81
122
  let worksheet = workbook.getWorksheet(sheetName);
82
123
  if (!worksheet) {
83
124
  worksheet = workbook.addWorksheet(sheetName);
84
125
  console.log(chalk.gray(`Created new sheet: ${sheetName}`));
85
126
  }
86
127
  let startRow = 1;
87
- let currentRow = 1;
88
- let columnCount = 0;
89
- worksheet.eachRow((row, rowNumber) => {
90
- const cell = row.getCell(1);
91
- const cellValue = cell.value?.toString().trim();
92
- if (!cellValue) {
93
- return;
94
- }
95
- if (cellValue.toLowerCase() === ruleType.toLowerCase()) {
96
- let col = 2;
97
- while (col <= 4) {
98
- const ruleCell = row.getCell(col);
99
- if (ruleCell.value) {
100
- columnCount++;
101
- }
102
- col++;
128
+ let currentRow = NaN;
129
+ if (worksheet.rowCount > 0) {
130
+ let stop = false;
131
+ worksheet.eachRow((row, rowNumber) => {
132
+ let columnCount = 0;
133
+ const cell = row.getCell(1);
134
+ const cellValue = cell.value;
135
+ if (!cellValue || stop) {
136
+ return;
103
137
  }
104
- if (columnCount < 4) {
105
- currentRow = rowNumber;
106
- startRow = rowNumber;
107
- } else {
108
- currentRow = rowNumber + 1;
138
+ const value = toCellValue(cellValue).trim();
139
+ if (value.toLowerCase() === ruleType.toLowerCase()) {
140
+ for (let col = 2; col < 5; col++) {
141
+ const ruleCell2 = row.getCell(col);
142
+ if (ruleCell2.value) {
143
+ columnCount++;
144
+ } else {
145
+ break;
146
+ }
147
+ }
148
+ if (columnCount < 3) {
149
+ currentRow = rowNumber;
150
+ startRow = rowNumber;
151
+ } else {
152
+ currentRow = rowNumber + 1;
153
+ }
154
+ const cell2 = worksheet.getRow(currentRow).getCell(1);
155
+ if (cell2 === void 0 || cell2.value === null || cell2.value === void 0) {
156
+ stop = true;
157
+ return;
158
+ }
159
+ if (toCellValue(cell2.value).toLowerCase() !== ruleType.toLowerCase()) {
160
+ worksheet.insertRow(currentRow, []);
161
+ currentRow = currentRow + 1;
162
+ stop = true;
163
+ return;
164
+ }
165
+ if (toCellValue(cell2.value).toLowerCase() === ruleType.toLowerCase() && columnCount < 3) {
166
+ stop = true;
167
+ return;
168
+ }
109
169
  }
110
- }
111
- });
170
+ });
171
+ }
172
+ if (isNaN(currentRow)) {
173
+ currentRow = worksheet.rowCount + 1;
174
+ worksheet.insertRow(currentRow, []);
175
+ }
112
176
  if (startRow === 1 && currentRow === 1 && worksheet.rowCount === 0) {
113
177
  currentRow = 1;
114
178
  }
115
179
  let targetRow = worksheet.getRow(currentRow);
180
+ let lastCell = targetRow.getCell(4);
181
+ if (lastCell !== void 0 && lastCell.value !== void 0 && lastCell.value !== null && lastCell.value !== "") {
182
+ currentRow = worksheet.rowCount + 1;
183
+ targetRow = worksheet.insertRow(currentRow, []);
184
+ }
116
185
  if (!targetRow.getCell(1).value) {
117
186
  const typeCell = targetRow.getCell(1);
118
187
  typeCell.value = ruleType;
@@ -122,23 +191,21 @@ async function addRuleToSheet(xlsxBuffer, ruleType, ruleExpr, sheetName = "expor
122
191
  let ruleCol = 2;
123
192
  while (ruleCol <= 4) {
124
193
  const existingCell = targetRow.getCell(ruleCol);
125
- if (!existingCell.value) {
194
+ if (existingCell === void 0 || (existingCell.value === void 0 || existingCell.value === null || existingCell.value === "")) {
126
195
  break;
127
196
  }
128
197
  ruleCol++;
129
198
  }
130
- if (ruleCol <= 4) {
131
- const ruleCell = targetRow.getCell(ruleCol);
132
- ruleCell.value = ruleExpr;
133
- ruleCell.alignment = { vertical: "middle" };
134
- const column = worksheet.getColumn(ruleCol);
135
- column.width = Math.max(column.width || 10, ruleExpr.length + 2);
136
- console.log(chalk.gray(`Added rule ${ruleType} at row ${currentRow}, column ${ruleCol}`));
137
- } else {
138
- throw new Error(`Cannot add more than 4 rules for type: ${ruleType}`);
199
+ const ruleCell = targetRow.getCell(ruleCol);
200
+ ruleCell.value = ruleExpr;
201
+ ruleCell.alignment = { vertical: "middle", horizontal: "center" };
202
+ const column = worksheet.getColumn(ruleCol);
203
+ column.width = Math.max(column.width || 10, ruleExpr.length + 2);
204
+ if (currentRow === 1 && ruleCol === 2) {
205
+ const column2 = worksheet.getColumn(1);
206
+ column2.width = Math.max(column2.width || 10, ruleExpr.length + 2);
139
207
  }
140
- const buffer = await workbook.xlsx.writeBuffer();
141
- return Buffer.from(buffer);
208
+ return workbook;
142
209
  }
143
210
  async function parseRulesFromFile(filePath) {
144
211
  const resolvedPath = await resolveFilePath(filePath);
@@ -157,8 +224,17 @@ async function parseRulesFromFile(filePath) {
157
224
  console.log(chalk.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
158
225
  continue;
159
226
  }
227
+ let items = [];
160
228
  const type = line.substring(0, spaceIndex).trim();
161
- const items = line.substring(spaceIndex + 1).trim().split(" ");
229
+ const values = line.substring(spaceIndex + 1).trim();
230
+ if (values.indexOf(" ") >= 0) {
231
+ items = values.split(" ");
232
+ } else if (values.indexOf(" ") >= 0) {
233
+ items = values.split(" ");
234
+ } else {
235
+ items = [values];
236
+ }
237
+ items = items.filter((item) => item.trim() !== "" && item.indexOf("=") > 0);
162
238
  if (!type) {
163
239
  console.log(chalk.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
164
240
  continue;
@@ -172,6 +248,9 @@ async function parseRulesFromFile(filePath) {
172
248
  }
173
249
  for (const rule of items) {
174
250
  let str = rule.trim();
251
+ if (str === void 0 || str === null || str === "" || str === " ") {
252
+ continue;
253
+ }
175
254
  let key = `${type}:${str}`;
176
255
  if (validRulesSet.has(key)) {
177
256
  console.log(chalk.yellow(`\u26A0 Line ${i + 1}: Duplicate rule "${str}"`));
@@ -187,30 +266,38 @@ async function parseRulesFromFile(filePath) {
187
266
  return rules;
188
267
  }
189
268
  async function addMultipleRulesToSheet(xlsxBuffer, rules) {
190
- let buffer = xlsxBuffer;
269
+ let workbook = await loadWorkbook(xlsxBuffer);
191
270
  for (const { type, rule } of rules) {
192
- console.log(chalk.gray(`Adding ${type} rule: ${rule}`));
193
- buffer = await addRuleToSheet(buffer, type, rule);
271
+ workbook = await addRuleToSheet(workbook, type, rule);
194
272
  }
195
- return buffer;
273
+ const buffer = await workbook.xlsx.writeBuffer();
274
+ return Buffer.from(buffer);
196
275
  }
197
276
 
198
277
  // src/bin.ts
199
278
  async function main() {
200
- let version = "1.0.0";
279
+ let version;
201
280
  try {
202
- const possiblePaths = [
203
- path2.join(process.cwd(), "package.json"),
204
- path2.join(process.cwd(), "..", "package.json")
205
- ];
206
- for (const packagePath of possiblePaths) {
207
- if (existsSync2(packagePath)) {
208
- const packageJson = JSON.parse(await fs2.readFile(packagePath, "utf-8"));
209
- version = packageJson.version;
210
- break;
211
- }
281
+ version = __VERSION__;
282
+ if (version.startsWith('"') && version.endsWith('"')) {
283
+ version = version.slice(1, -1);
212
284
  }
213
285
  } catch (e) {
286
+ version = "1.0.0";
287
+ try {
288
+ const possiblePaths = [
289
+ path2.join(process.cwd(), "package.json"),
290
+ path2.join(process.cwd(), "..", "package.json")
291
+ ];
292
+ for (const packagePath of possiblePaths) {
293
+ if (existsSync2(packagePath)) {
294
+ const packageJson = JSON.parse(await fs2.readFile(packagePath, "utf-8"));
295
+ version = packageJson.version;
296
+ break;
297
+ }
298
+ }
299
+ } catch (e2) {
300
+ }
214
301
  }
215
302
  const envPath = path2.join(process.cwd(), ".env");
216
303
  if (existsSync2(envPath)) {
@@ -250,7 +337,7 @@ async function main() {
250
337
  process.exit(1);
251
338
  }
252
339
  });
253
- program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-n,--sheet-name <string>", "render xlsx sheet name when xlsx has multiple sheets").option("-s,--save <string>", "save render xlsx file to user dir").option("-d,--data <string>", "render xlsx file data from").action(async (xlsxFile, options) => {
340
+ program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-n,--sheet-name <string>", "render xlsx sheet name when xlsx has multiple sheets").option("-s,--save <string>", "save render xlsx file to user dir").option("-d,--data <string>", "render xlsx file data from").option("--header <string>", "call remote http json data with header", []).option("--body <string>", "call remote http json request with body").action(async (xlsxFile, options) => {
254
341
  try {
255
342
  console.log(chalk2.green("\u{1F4C4} Rendering Excel template..."));
256
343
  const filePath = await resolveFilePath(xlsxFile);
@@ -262,7 +349,10 @@ async function main() {
262
349
  console.log(chalk2.gray(`Target sheet: ${sheetName}`));
263
350
  checkSheetAndPlaceholders(xlsx, sheetName);
264
351
  console.log(chalk2.gray("Sheet validation passed"));
265
- const renderData = await parseRenderData(options.data);
352
+ const renderData = await parseRenderData(options.data, options.header, options.body);
353
+ if (renderData === void 0) {
354
+ process.exit(1);
355
+ }
266
356
  if (Object.keys(renderData).length > 0) {
267
357
  console.log(chalk2.gray(`Render data loaded with ${Object.keys(renderData).length} keys`));
268
358
  }
package/dist/bin.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/bin-helpers.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport chalk from 'chalk';\r\nimport {Command} from 'commander';\r\nimport * as fs from 'node:fs/promises';\r\nimport {existsSync} from 'node:fs';\r\nimport * as path from 'node:path';\r\nimport {\r\n XlsxRender,\r\n BufferType,\r\n compileAll,\r\n compileRuleSheetName,\r\n AutoOptions, RuleMapOptions,\r\n} from './index';\r\nimport {\r\n generateOutputFilename,\r\n resolveFilePath,\r\n parseRenderData,\r\n checkSheetAndPlaceholders,\r\n addRuleToSheet,\r\n parseRulesFromFile,\r\n addMultipleRulesToSheet,\r\n} from './bin-helpers';\r\n\r\nasync function main() {\r\n // Load package.json version\r\n let version = '1.0.0';\r\n try {\r\n // Try multiple possible paths for package.json\r\n const possiblePaths = [\r\n path.join(process.cwd(), 'package.json'),\r\n path.join(process.cwd(), '..', 'package.json'),\r\n ];\r\n\r\n for (const packagePath of possiblePaths) {\r\n if (existsSync(packagePath)) {\r\n const packageJson = JSON.parse(await fs.readFile(packagePath, 'utf-8'));\r\n version = packageJson.version;\r\n break;\r\n }\r\n }\r\n } catch (e) {\r\n // Fallback to default version\r\n }\r\n\r\n // Load .env if exists\r\n const envPath = path.join(process.cwd(), '.env');\r\n if (existsSync(envPath)) {\r\n try {\r\n const dotenv = (await import('dotenv')).default;\r\n dotenv.config({quiet: true, debug: false, path: envPath});\r\n } catch (e) {\r\n // dotenv is optional\r\n }\r\n }\r\n\r\n const program = new Command();\r\n program\r\n .name('xlsx-cli')\r\n .version(version);\r\n\r\n// 编译存在规则的xlsx 输出 编译后带占位符 的 xlsx\r\n// 为指定 --sheet-name , 默认取 第一个 sheet 名称\r\n// 则自动寻找 export_metadata.config 配置文件,并进行编译替换到指定的sheet 文件中, 不存在则不进行编译\r\n// --remove 启用时,编译后的 xlsx 文件,移除 export_metadata.config 配置文件(可以调用ExprResolver.removeUnExportSheets)\r\n// 以上都成功 则 输出 渲染后的 xlsx 文件 , 有指定 --save 参数 则输出到指定目录,否则输出到当前目录\r\n program.command('compile')\r\n .argument('<string>', \"xlsx file path\")\r\n .option('-s,--save <string>', \"save compiled xlsx file to user dir\")\r\n .option('-n,--sheet-name <string>', \"compile xlsx sheet name when xlsx has multiple sheets\")\r\n .option('-r,--remove', 'remove configure rules sheet', false)\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📄 Compiling Excel file...'));\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n const buffer = await fs.readFile(filePath);\r\n\r\n // Determine sheet name\r\n const xlsx = await XlsxRender.create(buffer);\r\n const sheets = xlsx.getSheets();\r\n const sheetName = options.sheetName || sheets[0].name;\r\n console.log(chalk.gray(`Target sheet: ${sheetName}`));\r\n\r\n // Check if rule sheet exists\r\n const ruleSheetName = options.sheetName || compileRuleSheetName;\r\n\r\n // Compile file\r\n console.log(chalk.gray('Compiling rules...'));\r\n const opts = new RuleMapOptions();\r\n opts.sheetName = ruleSheetName;\r\n opts.remove = options.remove || false;\r\n const compiledBuffer = await compileAll(buffer, opts as AutoOptions);\r\n console.log(chalk.green('✓ Compilation completed'));\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, compiledBuffer);\r\n\r\n console.log(chalk.green('✓ Excel file compiled successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Compilation failed:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// 渲染占位符 xlsx template 文件\r\n// 为指定 --sheet-name , 默认取 第一个 sheet 名称\r\n// 检查 xlsx 对应 sheet 是否存在,检查 对应sheet 是否存在 变量占位符\r\n// 以上检查满足后 渲染 xlsx 文件,不满足 提示 无效的 xlsx 文件或者 sheet不存在\r\n// 渲染的 --data 参数支持 本地文件 json 文件/ json 字符串 / 远程 json 文件\r\n// --compile 参数开启, 则自动寻找 export_metadata.config 配置文件,并进行编译替换到指定的sheet 文件中, 不存在则不进行编译\r\n// 无编译 逻辑,则直接 解析 data 进行 xlsx sheet 渲染\r\n// 以上有任意异常,都输出异常提示 并终止 业务逻辑\r\n// 以上都成功 则 输出 渲染后的 xlsx 文件 , 有指定 --save 参数 则输出到指定目录,否则输出到当前目录\r\n program.command(\"render\")\r\n .argument('<string>', \"xlsx file path\")\r\n .option('-c,--compile', \"auto compile flag\", false)\r\n .option('-n,--sheet-name <string>', \"render xlsx sheet name when xlsx has multiple sheets\")\r\n .option('-s,--save <string>', \"save render xlsx file to user dir\")\r\n .option('-d,--data <string>', \"render xlsx file data from\")\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📄 Rendering Excel template...'));\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n let buffer = await fs.readFile(filePath);\r\n\r\n // Determine sheet name\r\n let xlsx = await XlsxRender.create(buffer);\r\n const sheets = xlsx.getSheets();\r\n const sheetName = options.sheetName || sheets[0].name;\r\n console.log(chalk.gray(`Target sheet: ${sheetName}`));\r\n\r\n // Check sheet exists and has placeholders\r\n checkSheetAndPlaceholders(xlsx, sheetName);\r\n console.log(chalk.gray('Sheet validation passed'));\r\n\r\n // Parse render data\r\n const renderData = await parseRenderData(options.data);\r\n if (Object.keys(renderData).length > 0) {\r\n console.log(chalk.gray(`Render data loaded with ${Object.keys(renderData).length} keys`));\r\n }\r\n\r\n // Compile if needed\r\n if (options.compile) {\r\n console.log(chalk.gray('Auto-compiling rules...'));\r\n const ruleSheetName = options.sheetName || compileRuleSheetName;\r\n const opts = new RuleMapOptions();\r\n opts.sheetName = ruleSheetName;\r\n opts.remove = false;\r\n const compiledResult = await compileAll(buffer, opts as AutoOptions);\r\n buffer = Buffer.from(compiledResult);\r\n xlsx = await XlsxRender.create(buffer);\r\n console.log(chalk.green('✓ Auto-compilation completed'));\r\n }\r\n\r\n // Render sheet\r\n console.log(chalk.gray('Rendering template...'));\r\n await xlsx.render(renderData, sheetName);\r\n\r\n // Generate output\r\n const outputBuffer = await xlsx.generate({\r\n type: BufferType.NodeBuffer,\r\n compression: \"DEFLATE\",\r\n compressionOptions: {\r\n level: 9\r\n }\r\n });\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, outputBuffer);\r\n\r\n console.log(chalk.green('✓ Excel template rendered successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Rendering failed:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// 添加规则配置\r\n// xlsx 不存存在 export_metadata.config sheet 则添加\r\n// 检查 对应 配置 是否存在 , 如果不存在则添加\r\n// 对应 类型 type 规则添加 超过 4列就添加一行,到新行配置记录\r\n// 配置行 都是以 类型 type 值 开头的行 <cell,alias,rowCell,mergeCell>\r\n// 样式要求: type 值为 加粗 居中,配置等式 上下 居中,cell 宽 自适应\r\n program.command(\"rules\")\r\n .argument('<string>', \"xlsx compile rules setting\")\r\n .option('-t,--type <string>', \"xlsx compile rule type <cell,alias,rowCell,mergeCell> (optional when using -f)\")\r\n .option('-r,--rule <string>', \"xlsx compile rule expr (can be specified multiple times)\")\r\n .option('-f,--file <string>', \"read rules from file (format: <type> ruleExpr per line)\")\r\n .option('-s,--save <string>', \"save compiled xlsx file to user dir\")\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📝 Adding rule configuration...'));\r\n\r\n const validTypes = ['cell', 'alias', 'rowCell', 'mergeCell'];\r\n let rules: { type: string; rule: string }[] = [];\r\n\r\n // Mode 1: Read from file\r\n if (options.file) {\r\n console.log(chalk.gray(`Reading rules from file: ${options.file}`));\r\n rules = await parseRulesFromFile(options.file);\r\n console.log(chalk.green(`✓ Loaded ${rules.length} rules from file`));\r\n } else if (options.rule) {\r\n // Mode 2: Read from command line\r\n // Normalize to array if single rule\r\n const ruleArray = Array.isArray(options.rule) ? options.rule : [options.rule];\r\n\r\n // Validate type if specified\r\n if (options.type) {\r\n if (!validTypes.includes(options.type)) {\r\n console.error(chalk.red(`Invalid rule type: ${options.type}. Must be one of: ${validTypes.join(', ')}`));\r\n process.exit(1);\r\n }\r\n // Add all rules with same type\r\n for (const rule of ruleArray) {\r\n rules.push({type: options.type, rule});\r\n }\r\n } else {\r\n console.error(chalk.red('Error: -t,--type is required when using -r,--rule'));\r\n process.exit(1);\r\n }\r\n console.log(chalk.green(`✓ Loaded ${rules.length} rules from command line`));\r\n } else {\r\n console.error(chalk.red('Error: Either -f,--file or -r,--rule must be specified'));\r\n process.exit(1);\r\n }\r\n\r\n if (rules.length === 0) {\r\n console.error(chalk.red('Error: No rules to add'));\r\n process.exit(1);\r\n }\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n const buffer = await fs.readFile(filePath);\r\n\r\n // Add all rules to export_metadata.config sheet\r\n const updatedBuffer = await addMultipleRulesToSheet(buffer, rules);\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, updatedBuffer);\r\n\r\n console.log(chalk.green('✓ All rules added successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Failed to add rule configuration:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n program.parse(process.argv);\r\n}\r\n\r\nmain().catch(error => {\r\n console.error(chalk.red('✗ Fatal error:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n});\r\n","import * as path from 'node:path';\r\nimport * as url from 'node:url';\r\nimport {existsSync} from 'node:fs';\r\nimport * as fs from 'node:fs/promises';\r\nimport {XlsxRender} from './biz';\r\nimport {loadWorkbook, parseWorkSheetRules, RuleToken} from './helper';\r\nimport exceljs from 'exceljs';\r\nimport chalk from 'chalk';\r\n\r\n/**\r\n * Helper function to generate output filename\r\n * Format: <basename>_<timestamp>.xlsx\r\n */\r\nexport function generateOutputFilename(inputFile: string): string {\r\n const basename = path.basename(inputFile, path.extname(inputFile));\r\n const timestamp = Date.now();\r\n return `${basename}_${timestamp}.xlsx`;\r\n}\r\n\r\n/**\r\n * Helper function to resolve file path\r\n * Tries absolute/relative to cwd, then script directory\r\n */\r\nexport async function resolveFilePath(filePath: string): Promise<string> {\r\n // Try as absolute or relative to cwd\r\n const resolvedPath = path.resolve(filePath);\r\n if (existsSync(resolvedPath)) {\r\n return resolvedPath;\r\n }\r\n // Try relative to script directory\r\n const scriptDir = path.dirname(url.fileURLToPath(import.meta.url));\r\n const relativePath = path.resolve(scriptDir, filePath);\r\n if (existsSync(relativePath)) {\r\n return relativePath;\r\n }\r\n throw new Error(`File not found: ${filePath}`);\r\n}\r\n\r\n/**\r\n * Helper function to parse render data\r\n * Supports: JSON string, file path, or URL\r\n */\r\nexport async function parseRenderData(dataOption: string | undefined): Promise<Record<string, any>> {\r\n if (!dataOption) {\r\n return {};\r\n }\r\n\r\n try {\r\n // Try as JSON string first\r\n return JSON.parse(dataOption);\r\n } catch (e) {\r\n // Try as file path\r\n try {\r\n const filePath = await resolveFilePath(dataOption);\r\n const fileContent = await fs.readFile(filePath, 'utf-8');\r\n return JSON.parse(fileContent);\r\n } catch (e2) {\r\n // Try as remote URL\r\n if (dataOption.startsWith('http://') || dataOption.startsWith('https://')) {\r\n let fetch;\r\n // Try to import fetch from native fetch (Node.js 18+) or node-fetch\r\n try {\r\n fetch = globalThis.fetch;\r\n } catch (e3) {\r\n try {\r\n // @ts-expect-error - node-fetch is optional dependency\r\n const nodeFetch = await import('node-fetch');\r\n fetch = nodeFetch.default;\r\n } catch (e4) {\r\n throw new Error('Remote URLs require Node.js 18+ or node-fetch package');\r\n }\r\n }\r\n const response = await fetch(dataOption);\r\n return response.json();\r\n }\r\n throw new Error(`Failed to parse render data from: ${dataOption}`);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to check sheet exists\r\n * Throws error if sheet not found\r\n */\r\nexport function checkSheetAndPlaceholders(xlsx: XlsxRender, sheetName: string): void {\r\n const sheets = xlsx.getSheets();\r\n const sheet = sheets.find(s => s.name === sheetName);\r\n\r\n if (!sheet) {\r\n throw new Error(`Sheet \"${sheetName}\" not found in Excel file`);\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to add rule to export_metadata.config sheet\r\n * Creates sheet if not exists, adds rule with proper styling\r\n */\r\nexport async function addRuleToSheet(\r\n xlsxBuffer: Buffer,\r\n ruleType: string,\r\n ruleExpr: string,\r\n sheetName: string = 'export_metadata.config'\r\n): Promise<Buffer> {\r\n const workbook = await loadWorkbook(xlsxBuffer);\r\n let worksheet = workbook.getWorksheet(sheetName);\r\n\r\n // Create sheet if not exists\r\n if (!worksheet) {\r\n worksheet = workbook.addWorksheet(sheetName);\r\n console.log(chalk.gray(`Created new sheet: ${sheetName}`));\r\n }\r\n\r\n // Find the next available row for the given rule type\r\n let startRow = 1;\r\n let currentRow = 1;\r\n let columnCount = 0;\r\n\r\n // Scan existing rules to find where to add new rule\r\n worksheet.eachRow((row, rowNumber) => {\r\n const cell = row.getCell(1);\r\n const cellValue = cell.value?.toString().trim();\r\n\r\n // Skip empty rows\r\n if (!cellValue) {\r\n return;\r\n }\r\n\r\n // Check if this is our rule type row\r\n if (cellValue.toLowerCase() === ruleType.toLowerCase()) {\r\n // Check how many rules are in this row\r\n let col = 2;\r\n while (col <= 4) {\r\n const ruleCell = row.getCell(col);\r\n if (ruleCell.value) {\r\n columnCount++;\r\n }\r\n col++;\r\n }\r\n\r\n // If we have less than 4 rules, add to this row\r\n if (columnCount < 4) {\r\n currentRow = rowNumber;\r\n startRow = rowNumber;\r\n } else {\r\n // Need to create a new row\r\n currentRow = rowNumber + 1;\r\n }\r\n }\r\n });\r\n\r\n // If no existing rule type found, start from row 1\r\n if (startRow === 1 && currentRow === 1 && worksheet.rowCount === 0) {\r\n currentRow = 1;\r\n }\r\n\r\n // Ensure we have the target row\r\n let targetRow = worksheet.getRow(currentRow);\r\n if (!targetRow.getCell(1).value) {\r\n // New row - set the type header\r\n const typeCell = targetRow.getCell(1);\r\n typeCell.value = ruleType;\r\n typeCell.font = { bold: true };\r\n typeCell.alignment = { horizontal: 'center', vertical: 'middle' };\r\n }\r\n\r\n // Determine column to add rule (skip column 1 which contains type)\r\n let ruleCol = 2;\r\n while (ruleCol <= 4) {\r\n const existingCell = targetRow.getCell(ruleCol);\r\n if (!existingCell.value) {\r\n break;\r\n }\r\n ruleCol++;\r\n }\r\n\r\n // Add rule expression\r\n if (ruleCol <= 4) {\r\n const ruleCell = targetRow.getCell(ruleCol);\r\n ruleCell.value = ruleExpr;\r\n ruleCell.alignment = { vertical: 'middle' };\r\n\r\n // Auto-fit column width\r\n const column = worksheet.getColumn(ruleCol);\r\n column.width = Math.max(column.width || 10, ruleExpr.length + 2);\r\n\r\n console.log(chalk.gray(`Added rule ${ruleType} at row ${currentRow}, column ${ruleCol}`));\r\n } else {\r\n throw new Error(`Cannot add more than 4 rules for type: ${ruleType}`);\r\n }\r\n\r\n // Write buffer\r\n const buffer = await workbook.xlsx.writeBuffer();\r\n return Buffer.from(buffer);\r\n}\r\n\r\n/**\r\n * Helper function to parse rules from file\r\n * File format: <type> ruleExpr\r\n * Lines starting with # are treated as comments\r\n * @param filePath - Path to rules file\r\n * @returns Array of {type, rule} objects\r\n */\r\nexport async function parseRulesFromFile(filePath: string): Promise<{ type: string; rule: string }[]> {\r\n const resolvedPath = await resolveFilePath(filePath);\r\n const fileContent = await fs.readFile(resolvedPath, 'utf-8');\r\n const lines = fileContent.split('\\n');\r\n const rules: { type: string; rule: string }[] = [];\r\n const validTypes = ['cell', 'alias', 'rowCell', 'mergeCell'];\r\n const validRulesSet = new Set<string>();\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n\r\n // Skip empty lines and comments\r\n if (!line || line.startsWith('#')) {\r\n continue;\r\n }\r\n\r\n // Parse line: <type> ruleExpr\r\n const spaceIndex = line.indexOf(' ');\r\n if (spaceIndex === -1) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid format. Expected \"<type> ruleExpr\"`));\r\n continue;\r\n }\r\n\r\n const type = line.substring(0, spaceIndex).trim();\r\n const items = line.substring(spaceIndex + 1).trim().split(' ');\r\n\r\n if (!type) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid format. Expected \"<type> ruleExpr\"`));\r\n continue;\r\n }\r\n if(!items || items.length === 0){\r\n continue\r\n }\r\n\r\n // Validate rule type\r\n if (!validTypes.includes(type)) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid rule type \"${type}\". Must be one of: ${validTypes.join(', ')}`));\r\n continue;\r\n }\r\n for(const rule of items) {\r\n let str = rule.trim();\r\n let key = `${type}:${str}`;\r\n if(validRulesSet.has(key)){\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Duplicate rule \"${str}\"`));\r\n continue;\r\n }\r\n validRulesSet.add(key);\r\n rules.push({ type:type, rule:str});\r\n }\r\n }\r\n\r\n if (rules.length === 0) {\r\n throw new Error('No valid rules found in file');\r\n }\r\n\r\n return rules;\r\n}\r\n\r\n/**\r\n * Helper function to add multiple rules to sheet\r\n * @param xlsxBuffer - Excel file buffer\r\n * @param rules - Array of {type, rule} objects\r\n * @returns Updated Excel buffer\r\n */\r\nexport async function addMultipleRulesToSheet(\r\n xlsxBuffer: Buffer,\r\n rules: { type: string; rule: string }[]\r\n): Promise<Buffer> {\r\n let buffer = xlsxBuffer;\r\n\r\n for (const { type, rule } of rules) {\r\n console.log(chalk.gray(`Adding ${type} rule: ${rule}`));\r\n buffer = await addRuleToSheet(buffer, type, rule);\r\n }\r\n\r\n return buffer;\r\n}\r\n"],"mappings":"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","names":["chalk","fs","existsSync","path","basename","existsSync","chalk"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/bin-helpers.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport chalk from 'chalk';\r\nimport {Command} from 'commander';\r\nimport * as fs from 'node:fs/promises';\r\nimport {existsSync} from 'node:fs';\r\nimport * as path from 'node:path';\r\nimport {\r\n XlsxRender,\r\n BufferType,\r\n compileAll,\r\n compileRuleSheetName,\r\n AutoOptions, RuleMapOptions,\r\n} from './index';\r\nimport {\r\n generateOutputFilename,\r\n resolveFilePath,\r\n parseRenderData,\r\n checkSheetAndPlaceholders,\r\n parseRulesFromFile,\r\n addMultipleRulesToSheet,\r\n} from './bin-helpers';\r\n\r\ndeclare const __VERSION__: string;\r\n\r\nasync function main() {\r\n // Load version: prioritize compile-time injected __VERSION__, otherwise read from package.json\r\n let version: string;\r\n try {\r\n // Try to use compile-time injected version\r\n version = __VERSION__;\r\n // Remove surrounding quotes if present\r\n if (version.startsWith('\"') && version.endsWith('\"')) {\r\n version = version.slice(1, -1);\r\n }\r\n } catch (e) {\r\n // Fallback: read from package.json\r\n version = '1.0.0';\r\n try {\r\n const possiblePaths = [\r\n path.join(process.cwd(), 'package.json'),\r\n path.join(process.cwd(), '..', 'package.json'),\r\n ];\r\n\r\n for (const packagePath of possiblePaths) {\r\n if (existsSync(packagePath)) {\r\n const packageJson = JSON.parse(await fs.readFile(packagePath, 'utf-8'));\r\n version = packageJson.version;\r\n break;\r\n }\r\n }\r\n } catch (e) {\r\n // Fallback to default version\r\n }\r\n }\r\n\r\n // Load .env if exists\r\n const envPath = path.join(process.cwd(), '.env');\r\n if (existsSync(envPath)) {\r\n try {\r\n const dotenv = (await import('dotenv')).default;\r\n dotenv.config({quiet: true, debug: false, path: envPath});\r\n } catch (e) {\r\n // dotenv is optional\r\n }\r\n }\r\n\r\n const program = new Command();\r\n program\r\n .name('xlsx-cli')\r\n .version(version);\r\n\r\n// 编译存在规则的xlsx 输出 编译后带占位符 的 xlsx\r\n// 为指定 --sheet-name , 默认取 第一个 sheet 名称\r\n// 则自动寻找 export_metadata.config 配置文件,并进行编译替换到指定的sheet 文件中, 不存在则不进行编译\r\n// --remove 启用时,编译后的 xlsx 文件,移除 export_metadata.config 配置文件(可以调用ExprResolver.removeUnExportSheets)\r\n// 以上都成功 则 输出 渲染后的 xlsx 文件 , 有指定 --save 参数 则输出到指定目录,否则输出到当前目录\r\n program.command('compile')\r\n .argument('<string>', \"xlsx file path\")\r\n .option('-s,--save <string>', \"save compiled xlsx file to user dir\")\r\n .option('-n,--sheet-name <string>', \"compile xlsx sheet name when xlsx has multiple sheets\")\r\n .option('-r,--remove', 'remove configure rules sheet', false)\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📄 Compiling Excel file...'));\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n const buffer = await fs.readFile(filePath);\r\n\r\n // Determine sheet name\r\n const xlsx = await XlsxRender.create(buffer);\r\n const sheets = xlsx.getSheets();\r\n const sheetName = options.sheetName || sheets[0].name;\r\n console.log(chalk.gray(`Target sheet: ${sheetName}`));\r\n\r\n // Check if rule sheet exists\r\n const ruleSheetName = options.sheetName || compileRuleSheetName;\r\n\r\n // Compile file\r\n console.log(chalk.gray('Compiling rules...'));\r\n const opts = new RuleMapOptions();\r\n opts.sheetName = ruleSheetName;\r\n opts.remove = options.remove || false;\r\n const compiledBuffer = await compileAll(buffer, opts as AutoOptions);\r\n console.log(chalk.green('✓ Compilation completed'));\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, compiledBuffer);\r\n\r\n console.log(chalk.green('✓ Excel file compiled successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Compilation failed:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// 渲染占位符 xlsx template 文件\r\n// 为指定 --sheet-name , 默认取 第一个 sheet 名称\r\n// 检查 xlsx 对应 sheet 是否存在,检查 对应sheet 是否存在 变量占位符\r\n// 以上检查满足后 渲染 xlsx 文件,不满足 提示 无效的 xlsx 文件或者 sheet不存在\r\n// 渲染的 --data 参数支持 本地文件 json 文件/ json 字符串 / 远程 json 文件\r\n// --compile 参数开启, 则自动寻找 export_metadata.config 配置文件,并进行编译替换到指定的sheet 文件中, 不存在则不进行编译\r\n// 无编译 逻辑,则直接 解析 data 进行 xlsx sheet 渲染\r\n// 以上有任意异常,都输出异常提示 并终止 业务逻辑\r\n// 以上都成功 则 输出 渲染后的 xlsx 文件 , 有指定 --save 参数 则输出到指定目录,否则输出到当前目录\r\n program.command(\"render\")\r\n .argument('<string>', \"xlsx file path\")\r\n .option('-c,--compile', \"auto compile flag\", false)\r\n .option('-n,--sheet-name <string>', \"render xlsx sheet name when xlsx has multiple sheets\")\r\n .option('-s,--save <string>', \"save render xlsx file to user dir\")\r\n .option('-d,--data <string>', \"render xlsx file data from\")\r\n .option('--header <string>', \"call remote http json data with header\", [])\r\n .option('--body <string>', \"call remote http json request with body\")\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📄 Rendering Excel template...'));\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n let buffer = await fs.readFile(filePath);\r\n\r\n // Determine sheet name\r\n let xlsx = await XlsxRender.create(buffer);\r\n const sheets = xlsx.getSheets();\r\n const sheetName = options.sheetName || sheets[0].name;\r\n console.log(chalk.gray(`Target sheet: ${sheetName}`));\r\n\r\n // Check sheet exists and has placeholders\r\n checkSheetAndPlaceholders(xlsx, sheetName);\r\n console.log(chalk.gray('Sheet validation passed'));\r\n\r\n // Parse render data\r\n const renderData = await parseRenderData(options.data, options.header as string[], options.body as string);\r\n if (renderData === undefined) {\r\n process.exit(1);\r\n }\r\n if (Object.keys(renderData).length > 0) {\r\n console.log(chalk.gray(`Render data loaded with ${Object.keys(renderData).length} keys`));\r\n }\r\n\r\n // Compile if needed\r\n if (options.compile) {\r\n console.log(chalk.gray('Auto-compiling rules...'));\r\n const ruleSheetName = options.sheetName || compileRuleSheetName;\r\n const opts = new RuleMapOptions();\r\n opts.sheetName = ruleSheetName;\r\n opts.remove = false;\r\n const compiledResult = await compileAll(buffer, opts as AutoOptions);\r\n buffer = Buffer.from(compiledResult);\r\n xlsx = await XlsxRender.create(buffer);\r\n console.log(chalk.green('✓ Auto-compilation completed'));\r\n }\r\n\r\n // Render sheet\r\n console.log(chalk.gray('Rendering template...'));\r\n await xlsx.render(renderData, sheetName);\r\n\r\n // Generate output\r\n const outputBuffer = await xlsx.generate({\r\n type: BufferType.NodeBuffer,\r\n compression: \"DEFLATE\",\r\n compressionOptions: {\r\n level: 9\r\n }\r\n });\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, outputBuffer);\r\n\r\n console.log(chalk.green('✓ Excel template rendered successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Rendering failed:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// 添加规则配置\r\n// xlsx 不存存在 export_metadata.config sheet 则添加\r\n// 检查 对应 配置 是否存在 , 如果不存在则添加\r\n// 对应 类型 type 规则添加 超过 4列就添加一行,到新行配置记录\r\n// 配置行 都是以 类型 type 值 开头的行 <cell,alias,rowCell,mergeCell>\r\n// 样式要求: type 值为 加粗 居中,配置等式 上下 居中,cell 宽 自适应\r\n program.command(\"rules\")\r\n .argument('<string>', \"xlsx compile rules setting\")\r\n .option('-t,--type <string>', \"xlsx compile rule type <cell,alias,rowCell,mergeCell> (optional when using -f)\")\r\n .option('-r,--rule <string>', \"xlsx compile rule expr (can be specified multiple times)\")\r\n .option('-f,--file <string>', \"read rules from file (format: <type> ruleExpr per line)\")\r\n .option('-s,--save <string>', \"save compiled xlsx file to user dir\")\r\n .action(async (xlsxFile: string, options: { [key: string]: any }) => {\r\n try {\r\n console.log(chalk.green('📝 Adding rule configuration...'));\r\n\r\n const validTypes = ['cell', 'alias', 'rowCell', 'mergeCell'];\r\n let rules: { type: string; rule: string }[] = [];\r\n\r\n // Mode 1: Read from file\r\n if (options.file) {\r\n console.log(chalk.gray(`Reading rules from file: ${options.file}`));\r\n rules = await parseRulesFromFile(options.file);\r\n console.log(chalk.green(`✓ Loaded ${rules.length} rules from file`));\r\n } else if (options.rule) {\r\n // Mode 2: Read from command line\r\n // Normalize to array if single rule\r\n const ruleArray = Array.isArray(options.rule) ? options.rule : [options.rule];\r\n\r\n // Validate type if specified\r\n if (options.type) {\r\n if (!validTypes.includes(options.type)) {\r\n console.error(chalk.red(`Invalid rule type: ${options.type}. Must be one of: ${validTypes.join(', ')}`));\r\n process.exit(1);\r\n }\r\n // Add all rules with same type\r\n for (const rule of ruleArray) {\r\n rules.push({type: options.type, rule});\r\n }\r\n } else {\r\n console.error(chalk.red('Error: -t,--type is required when using -r,--rule'));\r\n process.exit(1);\r\n }\r\n console.log(chalk.green(`✓ Loaded ${rules.length} rules from command line`));\r\n } else {\r\n console.error(chalk.red('Error: Either -f,--file or -r,--rule must be specified'));\r\n process.exit(1);\r\n }\r\n\r\n if (rules.length === 0) {\r\n console.error(chalk.red('Error: No rules to add'));\r\n process.exit(1);\r\n }\r\n\r\n // Resolve file path\r\n const filePath = await resolveFilePath(xlsxFile);\r\n console.log(chalk.gray(`Loading file: ${filePath}`));\r\n\r\n // Read file buffer\r\n const buffer = await fs.readFile(filePath);\r\n\r\n // Add all rules to export_metadata.config sheet\r\n const updatedBuffer = await addMultipleRulesToSheet(buffer, rules);\r\n\r\n // Determine output path\r\n const outputFile = path.join(options.save || process.cwd(), generateOutputFilename(xlsxFile));\r\n console.log(chalk.gray(`Saving to: ${outputFile}`));\r\n\r\n // Write output file\r\n await fs.writeFile(outputFile, updatedBuffer);\r\n\r\n console.log(chalk.green('✓ All rules added successfully!'));\r\n console.log(chalk.green(`📁 Output: ${outputFile}`));\r\n } catch (error) {\r\n console.error(chalk.red('✗ Failed to add rule configuration:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n program.parse(process.argv);\r\n}\r\n\r\nmain().catch(error => {\r\n console.error(chalk.red('✗ Fatal error:'));\r\n console.error(chalk.red(error instanceof Error ? error.message : String(error)));\r\n process.exit(1);\r\n});\r\n","import * as path from 'node:path';\r\nimport {existsSync} from 'node:fs';\r\nimport * as fs from 'node:fs/promises';\r\nimport {XlsxRender} from './biz';\r\nimport {columnNumberToLetter, loadWorkbook, toCellValue} from './helper';\r\nimport exceljs from 'exceljs';\r\nimport chalk from 'chalk';\r\n\r\n/**\r\n * Helper function to generate output filename\r\n * Format: <basename>_<timestamp>.xlsx\r\n */\r\nexport function generateOutputFilename(inputFile: string): string {\r\n const basename = path.basename(inputFile, path.extname(inputFile));\r\n const timestamp = Date.now();\r\n return `${basename}_${timestamp}.xlsx`;\r\n}\r\n\r\n/**\r\n * Helper function to resolve file path\r\n * Tries absolute/relative to cwd, then script directory\r\n */\r\nexport async function resolveFilePath(filePath: string): Promise<string> {\r\n // Try as absolute or relative to cwd\r\n const resolvedPath = path.resolve(filePath);\r\n if (existsSync(resolvedPath)) {\r\n return resolvedPath;\r\n }\r\n // Try relative to script directory\r\n const scriptDir = path.dirname(process.cwd());\r\n const relativePath = path.resolve(scriptDir, filePath);\r\n if (existsSync(relativePath)) {\r\n return relativePath;\r\n }\r\n throw new Error(`File not found: ${filePath}`);\r\n}\r\n\r\n/**\r\n * 验证字符串是否为合法 JSON\r\n * 先进行快速格式预检查,再进行精确解析\r\n */\r\nexport function isValidJSON(str: string): boolean {\r\n // 快速预检查:排除明显无效的格式\r\n const trimmed = str.trim();\r\n if (!trimmed) return false;\r\n\r\n const firstChar = trimmed[0];\r\n const lastChar = trimmed.charAt(trimmed.length - 1);\r\n\r\n const validStartEndPairs = [\r\n ['{', '}'],\r\n ['[', ']'],\r\n ['\"', '\"']\r\n ];\r\n\r\n const hasValidFormat = validStartEndPairs.some(\r\n ([start, end]) => firstChar === start && lastChar === end\r\n );\r\n\r\n // 支持基本类型(true/false/null/数字)\r\n if (!hasValidFormat &&\r\n !['true', 'false', 'null'].includes(trimmed) &&\r\n !/^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(trimmed)) {\r\n return false;\r\n }\r\n\r\n // 精确验证\r\n try {\r\n JSON.parse(str);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Helper function to parse render data\r\n * Supports: JSON string, file path, or URL\r\n */\r\nexport async function parseRenderData(dataOption: string | undefined, httpHeaders?: string[], body?: string | undefined): Promise<Record<string, any> | undefined> {\r\n if (!dataOption) {\r\n return {};\r\n }\r\n try {\r\n // Try as JSON string first\r\n if (isValidJSON(dataOption)) {\r\n return JSON.parse(dataOption);\r\n }\r\n // Try Http Remote Call\r\n if (dataOption.startsWith('http://') || dataOption.startsWith('https://')) {\r\n let fetch: any;\r\n // Try to import fetch from native fetch (Node.js 18+) or node-fetch\r\n try {\r\n fetch = globalThis.fetch;\r\n } catch (e3) {\r\n try {\r\n // @ts-expect-error - node-fetch is optional dependency\r\n const nodeFetch = await import('node-fetch');\r\n fetch = nodeFetch.default;\r\n } catch (e4) {\r\n console.error(chalk.red('Remote URLs require Node.js 18+ or node-fetch package'));\r\n return undefined;\r\n }\r\n }\r\n const headers = new Headers();\r\n httpHeaders?.forEach(header => {\r\n const [key, value] = header.split(':');\r\n headers.append(key, value);\r\n });\r\n const reqOpts: RequestInit = {\r\n headers: headers,\r\n method: headers.get(`method`) ? headers.get(`method`).toUpperCase() : 'GET',\r\n };\r\n if (body !== undefined && body !== \"\") {\r\n reqOpts.body = body;\r\n }\r\n console.log(chalk.gray(`Fetching data from: ${dataOption}`))\r\n console.log(chalk.gray(`request.init: ${JSON.stringify(reqOpts)}`))\r\n const response = await fetch(dataOption, reqOpts);\r\n if (response.status !== 200) {\r\n console.error(chalk.red(`Failed to fetch data from: ${dataOption}, status: ${response.status},${response.text()}`));\r\n return undefined;\r\n }\r\n return response.json();\r\n }\r\n // Try Local file\r\n const filePath = await resolveFilePath(dataOption);\r\n const fileContent = await fs.readFile(filePath, 'utf-8');\r\n return JSON.parse(fileContent);\r\n } catch (e) {\r\n // Try as file path\r\n console.error(chalk.red(`Failed to parse render data from: ${dataOption}`));\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to check sheet exists\r\n * Throws error if sheet not found\r\n */\r\nexport function checkSheetAndPlaceholders(xlsx: XlsxRender, sheetName: string): void {\r\n const sheets = xlsx.getSheets();\r\n const sheet = sheets.find(s => s.name === sheetName);\r\n\r\n if (!sheet) {\r\n throw new Error(`Sheet \"${sheetName}\" not found in Excel file`);\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to add rule to export_metadata.config sheet\r\n * Creates sheet if not exists, adds rule with proper styling\r\n */\r\nexport async function addRuleToSheet(\r\n workbook: exceljs.Workbook,\r\n ruleType: string,\r\n ruleExpr: string,\r\n sheetName: string = 'export_metadata.config'\r\n): Promise<exceljs.Workbook> {\r\n let worksheet = workbook.getWorksheet(sheetName);\r\n\r\n // Create sheet if not exists\r\n if (!worksheet) {\r\n worksheet = workbook.addWorksheet(sheetName);\r\n console.log(chalk.gray(`Created new sheet: ${sheetName}`));\r\n }\r\n\r\n // Find the next available row for the given rule type\r\n let startRow = 1;\r\n let currentRow: number = NaN;\r\n\r\n\r\n // Scan existing rules to find where to add new rule\r\n if (worksheet.rowCount > 0) {\r\n let stop = false;\r\n worksheet.eachRow((row, rowNumber) => {\r\n let columnCount = 0;\r\n const cell = row.getCell(1);\r\n const cellValue = cell.value;\r\n // Skip empty rows\r\n if (!cellValue || stop) {\r\n return;\r\n }\r\n\r\n // Check if this is our rule type row\r\n const value: string = toCellValue(cellValue).trim();\r\n if (value.toLowerCase() === ruleType.toLowerCase()) {\r\n // console.log(`worksheet: ${cellValue}`)\r\n // Check how many rules are in this row\r\n for (let col = 2; col < 5; col++) {\r\n const ruleCell = row.getCell(col);\r\n if (ruleCell.value) {\r\n columnCount++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n // If we have less than 4 rules, add to this row\r\n if (columnCount < 3) {\r\n currentRow = rowNumber;\r\n startRow = rowNumber;\r\n } else {\r\n // Need to create a new row\r\n currentRow = rowNumber + 1;\r\n }\r\n const cell = worksheet.getRow(currentRow).getCell(1);\r\n // need stop\r\n if (cell === undefined ||\r\n cell.value === null ||\r\n cell.value === undefined) {\r\n stop = true;\r\n return;\r\n }\r\n if (toCellValue(cell.value).toLowerCase() !== ruleType.toLowerCase()) {\r\n worksheet.insertRow(currentRow, []);\r\n currentRow = currentRow + 1;\r\n stop = true;\r\n return;\r\n }\r\n if (toCellValue(cell.value).toLowerCase() === ruleType.toLowerCase() && columnCount < 3) {\r\n stop = true;\r\n return;\r\n }\r\n }\r\n });\r\n }\r\n // empty sheets\r\n if (isNaN(currentRow)) {\r\n currentRow = worksheet.rowCount + 1;\r\n worksheet.insertRow(currentRow, [])\r\n }\r\n\r\n // If no existing rule type found, start from row 1\r\n if (startRow === 1 && currentRow === 1 && worksheet.rowCount === 0) {\r\n currentRow = 1;\r\n }\r\n\r\n // Ensure we have the target row\r\n let targetRow = worksheet.getRow(currentRow);\r\n let lastCell = targetRow.getCell(4);\r\n if (lastCell !== undefined && lastCell.value !== undefined && lastCell.value !== null && lastCell.value !== \"\") {\r\n currentRow = worksheet.rowCount + 1;\r\n targetRow = worksheet.insertRow(currentRow, [])\r\n }\r\n if (!targetRow.getCell(1).value) {\r\n // New row - set the type header\r\n const typeCell = targetRow.getCell(1);\r\n typeCell.value = ruleType;\r\n typeCell.font = {bold: true};\r\n typeCell.alignment = {horizontal: 'center', vertical: 'middle'};\r\n }\r\n\r\n // Determine column to add rule (skip column 1 which contains type)\r\n let ruleCol = 2;\r\n while (ruleCol <= 4) {\r\n const existingCell = targetRow.getCell(ruleCol);\r\n if (existingCell === undefined ||\r\n (existingCell.value === undefined || existingCell.value === null || existingCell.value === \"\")) {\r\n break;\r\n }\r\n ruleCol++;\r\n }\r\n const ruleCell = targetRow.getCell(ruleCol);\r\n ruleCell.value = ruleExpr;\r\n ruleCell.alignment = {vertical: 'middle', horizontal: 'center'};\r\n\r\n // Auto-fit column width\r\n const column = worksheet.getColumn(ruleCol);\r\n column.width = Math.max(column.width || 10, ruleExpr.length + 2);\r\n if (currentRow === 1 && ruleCol === 2) {\r\n const column = worksheet.getColumn(1);\r\n column.width = Math.max(column.width || 10, ruleExpr.length + 2);\r\n }\r\n // console.log(chalk.gray(`Added rule ${ruleType} at row ${currentRow}, column ${ruleCol}`));\r\n return workbook;\r\n}\r\n\r\n/**\r\n * Helper function to parse rules from file\r\n * File format: <type> ruleExpr\r\n * Lines starting with # are treated as comments\r\n * @param filePath - Path to rules file\r\n * @returns Array of {type, rule} objects\r\n */\r\nexport async function parseRulesFromFile(filePath: string): Promise<{ type: string; rule: string }[]> {\r\n const resolvedPath = await resolveFilePath(filePath);\r\n const fileContent = await fs.readFile(resolvedPath, 'utf-8');\r\n const lines = fileContent.split('\\n');\r\n const rules: { type: string; rule: string }[] = [];\r\n const validTypes = ['cell', 'alias', 'rowCell', 'mergeCell'];\r\n const validRulesSet = new Set<string>();\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n\r\n // Skip empty lines and comments\r\n if (!line || line.startsWith('#')) {\r\n continue;\r\n }\r\n\r\n // Parse line: <type> ruleExpr\r\n const spaceIndex = line.indexOf(' ');\r\n if (spaceIndex === -1) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid format. Expected \"<type> ruleExpr\"`));\r\n continue;\r\n }\r\n\r\n let items: string[] = [];\r\n const type: string = line.substring(0, spaceIndex).trim();\r\n const values: string = line.substring(spaceIndex + 1).trim();\r\n if (values.indexOf(' ') >= 0) {\r\n items = values.split(' ');\r\n } else if (values.indexOf('\\t') >= 0) {\r\n items = values.split('\\t');\r\n } else {\r\n items = [values];\r\n }\r\n items = items.filter(item => item.trim() !== \"\" && item.indexOf(\"=\") > 0)\r\n if (!type) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid format. Expected \"<type> ruleExpr\"`));\r\n continue;\r\n }\r\n if (!items || items.length === 0) {\r\n continue\r\n }\r\n\r\n // Validate rule type\r\n if (!validTypes.includes(type)) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Invalid rule type \"${type}\". Must be one of: ${validTypes.join(', ')}`));\r\n continue;\r\n }\r\n for (const rule of items) {\r\n let str = rule.trim();\r\n if (str === undefined || str === null\r\n || str === \"\" || str === '\\t') {\r\n continue;\r\n }\r\n let key = `${type}:${str}`;\r\n if (validRulesSet.has(key)) {\r\n console.log(chalk.yellow(`⚠ Line ${i + 1}: Duplicate rule \"${str}\"`));\r\n continue;\r\n }\r\n validRulesSet.add(key);\r\n rules.push({type: type, rule: str});\r\n }\r\n }\r\n\r\n if (rules.length === 0) {\r\n throw new Error('No valid rules found in file');\r\n }\r\n\r\n return rules;\r\n}\r\n\r\n/**\r\n * Helper function to add multiple rules to sheet\r\n * @param xlsxBuffer - Excel file buffer\r\n * @param rules - Array of {type, rule} objects\r\n * @returns Updated Excel buffer\r\n */\r\nexport async function addMultipleRulesToSheet(\r\n xlsxBuffer: Buffer,\r\n rules: { type: string; rule: string }[]\r\n): Promise<Buffer> {\r\n let workbook = await loadWorkbook(xlsxBuffer);\r\n\r\n for (const {type, rule} of rules) {\r\n workbook = await addRuleToSheet(workbook, type, rule);\r\n }\r\n const buffer = await workbook.xlsx.writeBuffer();\r\n return Buffer.from(buffer);\r\n}\r\n"],"mappings":"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","names":["chalk","fs","existsSync","path","basename","ruleCell","cell","column","existsSync","e","chalk"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vdhewei/xlsx-template-lib",
3
- "version": "1.6.6",
3
+ "version": "1.6.10",
4
4
  "description": "xlsx template",
5
5
  "files": [
6
6
  "dist",
@@ -60,8 +60,10 @@
60
60
  "scripts": {
61
61
  "build": "tsup",
62
62
  "build-cli": "tsup src/bin.ts -d bin",
63
+ "cli": "node dist/bin.js",
63
64
  "release": "pnpm publish --access public",
64
- "compile-cli": "bun build src/bin.ts --compile --minify --outfile bin/xlsx-cli",
65
+ "compile-cli": "node scripts/build-cli.js",
66
+ "clean": "bun run scripts/clean.js",
65
67
  "test": "vitest",
66
68
  "test:run": "vitest run"
67
69
  }