vectify 2.0.0 → 2.0.2

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/cli.js CHANGED
@@ -103,23 +103,23 @@ async function writeFile(filePath, content) {
103
103
  }
104
104
  async function getSvgFiles(dirPath) {
105
105
  const fs2 = await import("fs/promises");
106
- const path6 = await import("path");
106
+ const path7 = await import("path");
107
107
  try {
108
108
  const files = await fs2.readdir(dirPath);
109
- return files.filter((file) => file.endsWith(".svg")).map((file) => path6.join(dirPath, file));
109
+ return files.filter((file) => file.endsWith(".svg")).map((file) => path7.join(dirPath, file));
110
110
  } catch {
111
111
  return [];
112
112
  }
113
113
  }
114
114
  async function findProjectRoot(startDir = process.cwd()) {
115
- const path6 = await import("path");
115
+ const path7 = await import("path");
116
116
  let currentDir = startDir;
117
117
  while (true) {
118
- const packageJsonPath = path6.join(currentDir, "package.json");
118
+ const packageJsonPath = path7.join(currentDir, "package.json");
119
119
  if (await fileExists(packageJsonPath)) {
120
120
  return currentDir;
121
121
  }
122
- const parentDir = path6.dirname(currentDir);
122
+ const parentDir = path7.dirname(currentDir);
123
123
  if (parentDir === currentDir) {
124
124
  return startDir;
125
125
  }
@@ -134,7 +134,7 @@ var init_helpers = __esm({
134
134
 
135
135
  // src/cli.ts
136
136
  var import_node_fs2 = require("fs");
137
- var import_node_path6 = require("path");
137
+ var import_node_path7 = require("path");
138
138
  var import_node_url2 = require("url");
139
139
  var import_chalk4 = __toESM(require("chalk"));
140
140
  var import_commander = require("commander");
@@ -777,7 +777,7 @@ async function findConfig() {
777
777
  }
778
778
 
779
779
  // src/generators/index.ts
780
- var import_node_path3 = __toESM(require("path"));
780
+ var import_node_path4 = __toESM(require("path"));
781
781
 
782
782
  // src/parsers/optimizer.ts
783
783
  var import_svgo = require("svgo");
@@ -811,6 +811,101 @@ async function optimizeSvg(svgContent, config) {
811
811
  }
812
812
  }
813
813
 
814
+ // src/utils/formatter.ts
815
+ var import_node_child_process = require("child_process");
816
+ var import_node_path3 = __toESM(require("path"));
817
+ var import_node_process2 = __toESM(require("process"));
818
+ var import_node_util = require("util");
819
+ init_helpers();
820
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
821
+ var FORMATTER_PATTERNS = {
822
+ biome: ["biome.json", "biome.jsonc"],
823
+ prettier: [
824
+ ".prettierrc",
825
+ ".prettierrc.json",
826
+ ".prettierrc.yml",
827
+ ".prettierrc.yaml",
828
+ ".prettierrc.js",
829
+ ".prettierrc.cjs",
830
+ ".prettierrc.mjs",
831
+ "prettier.config.js",
832
+ "prettier.config.cjs",
833
+ "prettier.config.mjs"
834
+ ],
835
+ eslint: [
836
+ "eslint.config.js",
837
+ "eslint.config.mjs",
838
+ "eslint.config.cjs",
839
+ "eslint.config.ts",
840
+ ".eslintrc",
841
+ ".eslintrc.js",
842
+ ".eslintrc.cjs",
843
+ ".eslintrc.json",
844
+ ".eslintrc.yml",
845
+ ".eslintrc.yaml"
846
+ ]
847
+ };
848
+ var FORMATTER_COMMANDS = {
849
+ biome: (outputDir, args) => `npx @biomejs/biome format --write ${args || ""} "${outputDir}"`.trim(),
850
+ prettier: (outputDir, args) => `npx prettier --write ${args || ""} "${outputDir}"`.trim(),
851
+ eslint: (outputDir, args) => `npx eslint --fix ${args || ""} "${outputDir}"`.trim()
852
+ };
853
+ function normalizeFormatOption(format) {
854
+ if (format === false) {
855
+ return null;
856
+ }
857
+ if (format === true) {
858
+ return { tool: "auto" };
859
+ }
860
+ if (typeof format === "string") {
861
+ return { tool: format };
862
+ }
863
+ return format;
864
+ }
865
+ async function detectFormatter() {
866
+ const cwd = import_node_process2.default.cwd();
867
+ const priority = ["biome", "prettier", "eslint"];
868
+ for (const tool of priority) {
869
+ const patterns = FORMATTER_PATTERNS[tool];
870
+ for (const pattern of patterns) {
871
+ const configPath = import_node_path3.default.join(cwd, pattern);
872
+ if (await fileExists(configPath)) {
873
+ return tool;
874
+ }
875
+ }
876
+ }
877
+ return null;
878
+ }
879
+ async function formatOutput(outputDir, format) {
880
+ const config = normalizeFormatOption(format);
881
+ if (!config) {
882
+ return { success: true };
883
+ }
884
+ let tool = null;
885
+ if (config.tool === "auto") {
886
+ tool = await detectFormatter();
887
+ if (!tool) {
888
+ return {
889
+ success: true,
890
+ error: "No formatter detected. Install prettier, eslint, or biome to enable auto-formatting."
891
+ };
892
+ }
893
+ } else {
894
+ tool = config.tool || "prettier";
895
+ }
896
+ const command = FORMATTER_COMMANDS[tool](outputDir, config.args);
897
+ try {
898
+ await execAsync(command, { cwd: import_node_process2.default.cwd() });
899
+ return { success: true, tool };
900
+ } catch (error) {
901
+ return {
902
+ success: false,
903
+ tool,
904
+ error: `Format failed with ${tool}: ${error.message}`
905
+ };
906
+ }
907
+ }
908
+
814
909
  // src/generators/index.ts
815
910
  init_helpers();
816
911
  async function generateIcons(config, dryRun = false) {
@@ -853,6 +948,14 @@ async function generateIcons(config, dryRun = false) {
853
948
  if (config.generateOptions?.preview && !dryRun) {
854
949
  await generatePreviewHtml(svgFiles, config);
855
950
  }
951
+ if (config.format && !dryRun) {
952
+ const formatResult = await formatOutput(config.output, config.format);
953
+ if (formatResult.success && formatResult.tool) {
954
+ console.log(`Formatted with ${formatResult.tool}`);
955
+ } else if (formatResult.error) {
956
+ console.warn(formatResult.error);
957
+ }
958
+ }
856
959
  if (config.hooks?.onComplete) {
857
960
  await config.hooks.onComplete(stats);
858
961
  }
@@ -863,7 +966,7 @@ async function generateIcons(config, dryRun = false) {
863
966
  }
864
967
  async function generateIconComponent(svgFile, config, dryRun = false) {
865
968
  let svgContent = await readFile(svgFile);
866
- const fileName = import_node_path3.default.basename(svgFile);
969
+ const fileName = import_node_path4.default.basename(svgFile);
867
970
  if (config.hooks?.beforeParse) {
868
971
  svgContent = await config.hooks.beforeParse(svgContent, fileName);
869
972
  }
@@ -887,7 +990,7 @@ async function generateIconComponent(svgFile, config, dryRun = false) {
887
990
  code = await config.hooks.afterGenerate(code, componentName);
888
991
  }
889
992
  const fileExt = strategy.getComponentExtension(typescript);
890
- const outputPath = import_node_path3.default.join(config.output, `${componentName}.${fileExt}`);
993
+ const outputPath = import_node_path4.default.join(config.output, `${componentName}.${fileExt}`);
891
994
  if (dryRun) {
892
995
  console.log(` ${componentName}.${fileExt}`);
893
996
  } else {
@@ -898,7 +1001,7 @@ async function generateBaseComponent(config, dryRun = false) {
898
1001
  const typescript = config.typescript ?? true;
899
1002
  const strategy = getFrameworkStrategy(config.framework);
900
1003
  const { code, fileName } = strategy.generateBaseComponent(typescript);
901
- const outputPath = import_node_path3.default.join(config.output, fileName);
1004
+ const outputPath = import_node_path4.default.join(config.output, fileName);
902
1005
  if (dryRun) {
903
1006
  console.log(` ${fileName}`);
904
1007
  } else {
@@ -909,9 +1012,9 @@ async function generateIndexFile(svgFiles, config, dryRun = false) {
909
1012
  const typescript = config.typescript ?? true;
910
1013
  const strategy = getFrameworkStrategy(config.framework);
911
1014
  const ext = strategy.getIndexExtension(typescript);
912
- const usesDefaultExport = config.framework === "vue" || config.framework === "svelte" || config.framework === "preact";
1015
+ const usesDefaultExport = ["vue", "svelte", "react", "preact"].includes(config.framework);
913
1016
  const exports2 = svgFiles.map((svgFile) => {
914
- const fileName = import_node_path3.default.basename(svgFile);
1017
+ const fileName = import_node_path4.default.basename(svgFile);
915
1018
  const componentName = getComponentName(
916
1019
  fileName,
917
1020
  config.prefix,
@@ -924,7 +1027,7 @@ async function generateIndexFile(svgFiles, config, dryRun = false) {
924
1027
  return `export { ${componentName} } from './${componentName}'`;
925
1028
  }
926
1029
  }).join("\n");
927
- const indexPath = import_node_path3.default.join(config.output, `index.${ext}`);
1030
+ const indexPath = import_node_path4.default.join(config.output, `index.${ext}`);
928
1031
  if (dryRun) {
929
1032
  console.log(` index.${ext}`);
930
1033
  } else {
@@ -934,7 +1037,7 @@ async function generateIndexFile(svgFiles, config, dryRun = false) {
934
1037
  }
935
1038
  async function generatePreviewHtml(svgFiles, config) {
936
1039
  const componentNames = svgFiles.map((svgFile) => {
937
- const fileName = import_node_path3.default.basename(svgFile);
1040
+ const fileName = import_node_path4.default.basename(svgFile);
938
1041
  return getComponentName(
939
1042
  fileName,
940
1043
  config.prefix,
@@ -1106,7 +1209,7 @@ async function generatePreviewHtml(svgFiles, config) {
1106
1209
  </script>
1107
1210
  </body>
1108
1211
  </html>`;
1109
- const previewPath = import_node_path3.default.join(config.output, "preview.html");
1212
+ const previewPath = import_node_path4.default.join(config.output, "preview.html");
1110
1213
  await writeFile(previewPath, html);
1111
1214
  }
1112
1215
  async function cleanOutputDirectory(svgFiles, config) {
@@ -1115,7 +1218,7 @@ async function cleanOutputDirectory(svgFiles, config) {
1115
1218
  const fileExt = strategy.getComponentExtension(config.typescript ?? true);
1116
1219
  const expectedComponents = new Set(
1117
1220
  svgFiles.map((svgFile) => {
1118
- const fileName = import_node_path3.default.basename(svgFile, ".svg");
1221
+ const fileName = import_node_path4.default.basename(svgFile, ".svg");
1119
1222
  const componentName = getComponentName(
1120
1223
  fileName,
1121
1224
  config.prefix,
@@ -1142,7 +1245,7 @@ async function cleanOutputDirectory(svgFiles, config) {
1142
1245
  continue;
1143
1246
  }
1144
1247
  if (!expectedComponents.has(file)) {
1145
- const filePath = import_node_path3.default.join(config.output, file);
1248
+ const filePath = import_node_path4.default.join(config.output, file);
1146
1249
  await unlink(filePath);
1147
1250
  console.log(`Deleted orphaned component: ${file}`);
1148
1251
  }
@@ -1209,8 +1312,8 @@ ${import_chalk.default.bold("Output:")} ${import_chalk.default.cyan(config.outpu
1209
1312
  }
1210
1313
 
1211
1314
  // src/commands/init.ts
1212
- var import_node_path4 = __toESM(require("path"));
1213
- var import_node_process2 = __toESM(require("process"));
1315
+ var import_node_path5 = __toESM(require("path"));
1316
+ var import_node_process3 = __toESM(require("process"));
1214
1317
  var import_chalk2 = __toESM(require("chalk"));
1215
1318
  var import_inquirer = __toESM(require("inquirer"));
1216
1319
  var import_ora2 = __toESM(require("ora"));
@@ -1218,7 +1321,7 @@ init_helpers();
1218
1321
  async function init(options = {}) {
1219
1322
  try {
1220
1323
  const projectRoot = await findProjectRoot();
1221
- const currentDir = import_node_process2.default.cwd();
1324
+ const currentDir = import_node_process3.default.cwd();
1222
1325
  if (currentDir !== projectRoot) {
1223
1326
  console.log(import_chalk2.default.yellow(`
1224
1327
  Note: Project root detected at ${import_chalk2.default.cyan(projectRoot)}`));
@@ -1239,8 +1342,8 @@ Note: Project root detected at ${import_chalk2.default.cyan(projectRoot)}`));
1239
1342
  }
1240
1343
  }
1241
1344
  ]);
1242
- const configPath = import_node_path4.default.resolve(projectRoot, pathAnswers.configPath);
1243
- const configDir = import_node_path4.default.dirname(configPath);
1345
+ const configPath = import_node_path5.default.resolve(projectRoot, pathAnswers.configPath);
1346
+ const configDir = import_node_path5.default.dirname(configPath);
1244
1347
  if (!options.force && await fileExists(configPath)) {
1245
1348
  const { overwrite } = await import_inquirer.default.prompt([
1246
1349
  {
@@ -1304,14 +1407,14 @@ Note: Project root detected at ${import_chalk2.default.cyan(projectRoot)}`));
1304
1407
  default: ""
1305
1408
  }
1306
1409
  ]);
1307
- const inputPath = import_node_path4.default.resolve(projectRoot, answers.input);
1308
- const outputPath = import_node_path4.default.resolve(projectRoot, answers.output);
1410
+ const inputPath = import_node_path5.default.resolve(projectRoot, answers.input);
1411
+ const outputPath = import_node_path5.default.resolve(projectRoot, answers.output);
1309
1412
  const spinner = (0, import_ora2.default)("Setting up directories...").start();
1310
1413
  await ensureDir(inputPath);
1311
1414
  spinner.text = `Created input directory: ${import_chalk2.default.cyan(answers.input)}`;
1312
1415
  await ensureDir(outputPath);
1313
1416
  spinner.succeed(`Created output directory: ${import_chalk2.default.cyan(answers.output)}`);
1314
- const relativeConfigDir = import_node_path4.default.relative(configDir, projectRoot) || ".";
1417
+ const relativeConfigDir = import_node_path5.default.relative(configDir, projectRoot) || ".";
1315
1418
  const configContent = generateConfigContent(answers, relativeConfigDir);
1316
1419
  spinner.start("Creating config file...");
1317
1420
  await writeFile(configPath, configContent);
@@ -1354,7 +1457,7 @@ export default defineConfig({
1354
1457
  }
1355
1458
 
1356
1459
  // src/commands/watch.ts
1357
- var import_node_path5 = __toESM(require("path"));
1460
+ var import_node_path6 = __toESM(require("path"));
1358
1461
  var import_chalk3 = __toESM(require("chalk"));
1359
1462
  var import_chokidar = __toESM(require("chokidar"));
1360
1463
  var import_ora3 = __toESM(require("ora"));
@@ -1376,7 +1479,7 @@ async function watch(options = {}) {
1376
1479
  spinner.start("Generating icon components...");
1377
1480
  const initialStats = await generateIcons(config);
1378
1481
  spinner.succeed(`Generated ${import_chalk3.default.green(initialStats.success)} icon components`);
1379
- const watchPath = import_node_path5.default.join(config.input, "**/*.svg");
1482
+ const watchPath = import_node_path6.default.join(config.input, "**/*.svg");
1380
1483
  const debounce = config.watch?.debounce ?? 300;
1381
1484
  const ignore = config.watch?.ignore ?? ["**/node_modules/**", "**/.git/**"];
1382
1485
  console.log(import_chalk3.default.bold("\nWatching for changes..."));
@@ -1394,7 +1497,7 @@ async function watch(options = {}) {
1394
1497
  }).on("change", (filePath) => {
1395
1498
  handleChange("changed", filePath, config, debounce, debounceTimer);
1396
1499
  }).on("unlink", (filePath) => {
1397
- console.log(import_chalk3.default.yellow(`SVG file removed: ${import_node_path5.default.basename(filePath)}`));
1500
+ console.log(import_chalk3.default.yellow(`SVG file removed: ${import_node_path6.default.basename(filePath)}`));
1398
1501
  handleChange("removed", filePath, config, debounce, debounceTimer);
1399
1502
  }).on("error", (error) => {
1400
1503
  console.error(import_chalk3.default.red(`Watcher error: ${error.message}`));
@@ -1413,7 +1516,7 @@ ${import_chalk3.default.yellow("Stopping watch mode...")}`);
1413
1516
  }
1414
1517
  }
1415
1518
  function handleChange(event, filePath, config, debounce, timer) {
1416
- const fileName = import_node_path5.default.basename(filePath);
1519
+ const fileName = import_node_path6.default.basename(filePath);
1417
1520
  if (timer) {
1418
1521
  clearTimeout(timer);
1419
1522
  }
@@ -1442,11 +1545,11 @@ var import_meta2 = {};
1442
1545
  function getPackageJson() {
1443
1546
  let pkgPath;
1444
1547
  if (typeof __dirname !== "undefined") {
1445
- pkgPath = (0, import_node_path6.join)(__dirname, "../package.json");
1548
+ pkgPath = (0, import_node_path7.join)(__dirname, "../package.json");
1446
1549
  } else {
1447
1550
  const __filename = (0, import_node_url2.fileURLToPath)(import_meta2.url);
1448
- const __dirname2 = (0, import_node_path6.dirname)(__filename);
1449
- pkgPath = (0, import_node_path6.join)(__dirname2, "../package.json");
1551
+ const __dirname2 = (0, import_node_path7.dirname)(__filename);
1552
+ pkgPath = (0, import_node_path7.join)(__dirname2, "../package.json");
1450
1553
  }
1451
1554
  return JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
1452
1555
  }
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  generate,
4
4
  init,
5
5
  watch
6
- } from "./chunk-4BWKFV7W.mjs";
6
+ } from "./chunk-XHYCGABW.mjs";
7
7
  import "./chunk-CIKTK6HI.mjs";
8
8
 
9
9
  // src/cli.ts
package/dist/index.d.mts CHANGED
@@ -54,6 +54,33 @@ interface IconProps {
54
54
  * Framework types supported
55
55
  */
56
56
  type Framework = 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'lit' | 'angular' | 'qwik' | 'astro' | 'vanilla';
57
+ /**
58
+ * Formatter tool types
59
+ */
60
+ type FormatterTool = 'auto' | 'prettier' | 'eslint' | 'biome';
61
+ /**
62
+ * Format configuration
63
+ */
64
+ interface FormatConfig {
65
+ /**
66
+ * Formatter tool to use
67
+ * - 'auto': Auto-detect based on project config files
68
+ * - 'prettier': Use Prettier
69
+ * - 'eslint': Use ESLint --fix
70
+ * - 'biome': Use Biome
71
+ * @default 'auto'
72
+ */
73
+ tool?: FormatterTool;
74
+ /**
75
+ * Additional arguments to pass to the formatter
76
+ * @example '--single-quote'
77
+ */
78
+ args?: string;
79
+ }
80
+ /**
81
+ * Format option type (shorthand or full config)
82
+ */
83
+ type FormatOption = boolean | FormatterTool | FormatConfig;
57
84
  /**
58
85
  * Main configuration interface
59
86
  */
@@ -169,6 +196,15 @@ interface IconForgeConfig {
169
196
  */
170
197
  debounce?: number;
171
198
  };
199
+ /**
200
+ * Format generated files after generation
201
+ * - true: Auto-detect formatter (biome > prettier > eslint)
202
+ * - false: Disable formatting
203
+ * - 'prettier' | 'eslint' | 'biome': Use specific formatter
204
+ * - { tool: 'auto', args: '--single-quote' }: Full config
205
+ * @default false
206
+ */
207
+ format?: FormatOption;
172
208
  /**
173
209
  * Lifecycle hooks
174
210
  */
@@ -278,4 +314,4 @@ declare const frameworkRegistry: FrameworkRegistry;
278
314
  */
279
315
  declare function getFrameworkStrategy(framework: Framework): FrameworkStrategy;
280
316
 
281
- export { type Framework, type FrameworkStrategy, type GenerationStats, type IconForgeConfig, type IconNode, type IconProps, type SVGElementType, defineConfig, findConfig, frameworkRegistry, generate, generateIcons, getFrameworkStrategy, init, loadConfig, watch };
317
+ export { type FormatConfig, type FormatOption, type FormatterTool, type Framework, type FrameworkStrategy, type GenerationStats, type IconForgeConfig, type IconNode, type IconProps, type SVGElementType, defineConfig, findConfig, frameworkRegistry, generate, generateIcons, getFrameworkStrategy, init, loadConfig, watch };
package/dist/index.d.ts CHANGED
@@ -54,6 +54,33 @@ interface IconProps {
54
54
  * Framework types supported
55
55
  */
56
56
  type Framework = 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'lit' | 'angular' | 'qwik' | 'astro' | 'vanilla';
57
+ /**
58
+ * Formatter tool types
59
+ */
60
+ type FormatterTool = 'auto' | 'prettier' | 'eslint' | 'biome';
61
+ /**
62
+ * Format configuration
63
+ */
64
+ interface FormatConfig {
65
+ /**
66
+ * Formatter tool to use
67
+ * - 'auto': Auto-detect based on project config files
68
+ * - 'prettier': Use Prettier
69
+ * - 'eslint': Use ESLint --fix
70
+ * - 'biome': Use Biome
71
+ * @default 'auto'
72
+ */
73
+ tool?: FormatterTool;
74
+ /**
75
+ * Additional arguments to pass to the formatter
76
+ * @example '--single-quote'
77
+ */
78
+ args?: string;
79
+ }
80
+ /**
81
+ * Format option type (shorthand or full config)
82
+ */
83
+ type FormatOption = boolean | FormatterTool | FormatConfig;
57
84
  /**
58
85
  * Main configuration interface
59
86
  */
@@ -169,6 +196,15 @@ interface IconForgeConfig {
169
196
  */
170
197
  debounce?: number;
171
198
  };
199
+ /**
200
+ * Format generated files after generation
201
+ * - true: Auto-detect formatter (biome > prettier > eslint)
202
+ * - false: Disable formatting
203
+ * - 'prettier' | 'eslint' | 'biome': Use specific formatter
204
+ * - { tool: 'auto', args: '--single-quote' }: Full config
205
+ * @default false
206
+ */
207
+ format?: FormatOption;
172
208
  /**
173
209
  * Lifecycle hooks
174
210
  */
@@ -278,4 +314,4 @@ declare const frameworkRegistry: FrameworkRegistry;
278
314
  */
279
315
  declare function getFrameworkStrategy(framework: Framework): FrameworkStrategy;
280
316
 
281
- export { type Framework, type FrameworkStrategy, type GenerationStats, type IconForgeConfig, type IconNode, type IconProps, type SVGElementType, defineConfig, findConfig, frameworkRegistry, generate, generateIcons, getFrameworkStrategy, init, loadConfig, watch };
317
+ export { type FormatConfig, type FormatOption, type FormatterTool, type Framework, type FrameworkStrategy, type GenerationStats, type IconForgeConfig, type IconNode, type IconProps, type SVGElementType, defineConfig, findConfig, frameworkRegistry, generate, generateIcons, getFrameworkStrategy, init, loadConfig, watch };