hyouji 0.0.8 → 0.0.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.
Files changed (3) hide show
  1. package/README.md +96 -9
  2. package/dist/index.js +166 -50
  3. package/package.json +12 -19
package/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  ### article
4
4
 
5
- https://levelup.gitconnected.com/create-github-labels-from-terminal-158d4868fab
5
+ https://levelup.gitconnected.com/create-github-labels-from-terminal-158d4868fab
6
+ https://github.com/koji/Hyouji/blob/main/blog/article.md
6
7
 
7
8
  [![CI](https://github.com/koji/github-label-manager/actions/workflows/ci.yml/badge.svg)](https://github.com/koji/github-label-manager/actions/workflows/ci.yml)
8
9
  [![Publish](https://github.com/koji/github-label-manager/actions/workflows/publish.yml/badge.svg)](https://github.com/koji/github-label-manager/actions/workflows/publish.yml)
@@ -18,7 +19,6 @@ https://levelup.gitconnected.com/create-github-labels-from-terminal-158d4868fab
18
19
 
19
20
  https://github.com/user-attachments/assets/739f185a-1bd0-411b-8947-dd4600c452c8
20
21
 
21
-
22
22
  ### Labels API
23
23
 
24
24
  https://docs.github.com/en/rest/reference/issues#labels
@@ -60,7 +60,7 @@ This tool provides the following functionality:
60
60
  2. Create multiple labels on a specific repo
61
61
  3. Delete a single label from a specific repo
62
62
  4. Delete all labels from a specific repo
63
- 5. Import labels from JSON file
63
+ 5. Import labels from JSON or YAML file
64
64
  6. **Display your saved settings** - View your stored GitHub configuration
65
65
  7. **Persistent configuration** - Save your GitHub token and username for future use
66
66
 
@@ -77,9 +77,7 @@ hyouji
77
77
  On your first run, you'll be prompted to enter:
78
78
 
79
79
  - **GitHub Personal Token** - Generate one [here](https://github.com/settings/tokens) with `repo` scope
80
- <img width="792" height="564" alt="github_token" src="https://github.com/user-attachments/assets/e460738f-833a-4158-a8ba-61752beaad72" />
81
-
82
-
80
+ <img width="792" height="564" alt="github_token" src="https://github.com/user-attachments/assets/e460738f-833a-4158-a8ba-61752beaad72" />
83
81
  - **GitHub Username** - Your GitHub account name
84
82
 
85
83
  These credentials will be securely saved and reused for future sessions.
@@ -90,9 +88,11 @@ These credentials will be securely saved and reused for future sessions.
90
88
  2. **Create multiple labels on a specific repo**
91
89
  3. **Delete a single label from a specific repo**
92
90
  4. **Delete all labels from a specific repo**
93
- 5. **Import labels from JSON file**
94
- 6. **Display your settings** - View your saved configuration
95
- 7. **Exit**
91
+ 5. **Import labels from JSON or YAML file**
92
+ 6. **Generate sample JSON** - Create a sample JSON file with predefined labels
93
+ 7. **Generate sample YAML** - Create a sample YAML file with predefined labels
94
+ 8. **Display your settings** - View your saved configuration
95
+ 9. **Exit**
96
96
 
97
97
  ### Settings Management
98
98
 
@@ -200,6 +200,93 @@ npm start
200
200
 
201
201
  You can use `pnpm`, `yarn` or `bun`.
202
202
 
203
+ ### File Import Support
204
+
205
+ The "Import labels from JSON or YAML file" option allows you to import multiple labels from external files. Both JSON and YAML formats are supported.
206
+
207
+ #### Supported File Formats
208
+
209
+ - **JSON files** (`.json` extension)
210
+ - **YAML files** (`.yaml` or `.yml` extension)
211
+
212
+ #### Label Structure
213
+
214
+ Both formats support the same label structure:
215
+
216
+ - `name` (required): The label name
217
+ - `color` (optional): Hex color code without the `#` symbol
218
+ - `description` (optional): Label description
219
+
220
+ #### JSON Example
221
+
222
+ ```json
223
+ [
224
+ {
225
+ "name": "bug",
226
+ "color": "d73a4a",
227
+ "description": "Something isn't working"
228
+ },
229
+ {
230
+ "name": "enhancement",
231
+ "color": "a2eeef",
232
+ "description": "New feature or request"
233
+ },
234
+ {
235
+ "name": "documentation",
236
+ "color": "0075ca",
237
+ "description": "Improvements or additions to documentation"
238
+ }
239
+ ]
240
+ ```
241
+
242
+ #### YAML Example
243
+
244
+ ```yaml
245
+ # Sample YAML file for importing GitHub labels
246
+ - name: 'bug'
247
+ color: 'd73a4a'
248
+ description: "Something isn't working"
249
+
250
+ - name: 'enhancement'
251
+ color: 'a2eeef'
252
+ description: 'New feature or request'
253
+
254
+ - name: 'documentation'
255
+ color: '0075ca'
256
+ description: 'Improvements or additions to documentation'
257
+
258
+ # Labels with minimal configuration (name only)
259
+ - name: 'good first issue'
260
+ color: '7057ff'
261
+ description: 'Good for newcomers'
262
+
263
+ # Labels without description (optional field)
264
+ - name: 'wontfix'
265
+ color: 'ffffff'
266
+
267
+ # Labels without color (will use GitHub default)
268
+ - name: 'question'
269
+ description: 'Further information is requested'
270
+ ```
271
+
272
+ #### Sample Files
273
+
274
+ You can find complete example files in the `examples/` directory:
275
+
276
+ - `examples/labels.json` - Basic label examples in JSON format
277
+ - `examples/labels.yaml` - Basic label examples in YAML format
278
+ - `examples/project-labels.json` - Project management labels in JSON format
279
+ - `examples/project-labels.yaml` - Project management labels in YAML format
280
+
281
+ #### Generate Sample Files
282
+
283
+ The tool can generate sample files for you:
284
+
285
+ - **Generate sample JSON** - Creates `hyouji.json` with predefined labels
286
+ - **Generate sample YAML** - Creates `hyouji.yaml` with predefined labels
287
+
288
+ Both generated files contain the same predefined labels and can be used as starting points for your own label configurations.
289
+
203
290
  ### Predefined Labels
204
291
 
205
292
  The "Create multiple labels" option uses predefined labels from `src/constant.ts`. These include common labels for project management:
package/dist/index.js CHANGED
@@ -4,9 +4,12 @@ import { renderFilled } from "oh-my-logo";
4
4
  import * as fs from "fs";
5
5
  import { promises, existsSync } from "fs";
6
6
  import { homedir } from "os";
7
+ import * as path from "path";
7
8
  import { join, dirname } from "path";
8
9
  import { createHash, randomBytes, createCipheriv, createDecipheriv } from "crypto";
9
10
  import prompts from "prompts";
11
+ import * as yaml from "js-yaml";
12
+ import yaml__default from "js-yaml";
10
13
  import { Octokit } from "@octokit/core";
11
14
  import { exec } from "child_process";
12
15
  import { promisify } from "util";
@@ -49,10 +52,10 @@ const deleteLabel$1 = {
49
52
  name: "name",
50
53
  message: "Please type label name you want to delete"
51
54
  };
52
- const jsonFilePath = {
55
+ const labelFilePath = {
53
56
  type: "text",
54
57
  name: "filePath",
55
- message: "Please type the path to your JSON file"
58
+ message: "Please type the path to your JSON or YAML file"
56
59
  };
57
60
  const actionSelector = {
58
61
  type: "multiselect",
@@ -63,10 +66,11 @@ const actionSelector = {
63
66
  { title: "create multiple labels", value: 1 },
64
67
  { title: "delete a label", value: 2 },
65
68
  { title: "delete all labels", value: 3 },
66
- { title: "import JSON", value: 4 },
69
+ { title: "import labels from JSON or YAML", value: 4 },
67
70
  { title: "Generate sample JSON", value: 5 },
68
- { title: "Display your settings", value: 6 },
69
- { title: "exit", value: 7 }
71
+ { title: "Generate sample YAML", value: 6 },
72
+ { title: "Display your settings", value: 7 },
73
+ { title: "exit", value: 8 }
70
74
  ]
71
75
  };
72
76
  const holdToken = {
@@ -265,7 +269,7 @@ Thank you!
265
269
  };
266
270
  const extraGuideText = `If you don't see action selector, please hit space key.`;
267
271
  const linkToPersonalToken = "https://github.com/settings/tokens";
268
- const log$3 = console.log;
272
+ const log$4 = console.log;
269
273
  const createLabel = async (configs2, label) => {
270
274
  const resp = await configs2.octokit.request(
271
275
  "POST /repos/{owner}/{repo}/labels",
@@ -280,16 +284,16 @@ const createLabel = async (configs2, label) => {
280
284
  const status = resp.status;
281
285
  switch (status) {
282
286
  case 201:
283
- log$3(chalk.green(`${resp.status}: Created ${label.name}`));
287
+ log$4(chalk.green(`${resp.status}: Created ${label.name}`));
284
288
  break;
285
289
  case 404:
286
- log$3(chalk.red(`${resp.status}: Resource not found`));
290
+ log$4(chalk.red(`${resp.status}: Resource not found`));
287
291
  break;
288
292
  case 422:
289
- log$3(chalk.red(`${resp.status}: Validation failed`));
293
+ log$4(chalk.red(`${resp.status}: Validation failed`));
290
294
  break;
291
295
  default:
292
- log$3(chalk.yellow(`${resp.status}: Something wrong`));
296
+ log$4(chalk.yellow(`${resp.status}: Something wrong`));
293
297
  break;
294
298
  }
295
299
  };
@@ -297,8 +301,8 @@ const createLabels = async (configs2) => {
297
301
  labels.forEach(async (label) => {
298
302
  createLabel(configs2, label);
299
303
  });
300
- log$3("Created all labels");
301
- log$3(chalk.bgBlueBright(extraGuideText));
304
+ log$4("Created all labels");
305
+ log$4(chalk.bgBlueBright(extraGuideText));
302
306
  };
303
307
  const deleteLabel = async (configs2, labelNames) => {
304
308
  for (const labelName of labelNames) {
@@ -312,15 +316,15 @@ const deleteLabel = async (configs2, labelNames) => {
312
316
  }
313
317
  );
314
318
  if (resp.status === 204) {
315
- log$3(chalk.green(`${resp.status}: Deleted ${labelName}`));
319
+ log$4(chalk.green(`${resp.status}: Deleted ${labelName}`));
316
320
  } else {
317
- log$3(chalk.yellow(`${resp.status}: Something wrong with ${labelName}`));
321
+ log$4(chalk.yellow(`${resp.status}: Something wrong with ${labelName}`));
318
322
  }
319
323
  } catch (error) {
320
324
  if (error && typeof error === "object" && "status" in error && error.status === 404) {
321
- log$3(chalk.red(`404: Label "${labelName}" not found`));
325
+ log$4(chalk.red(`404: Label "${labelName}" not found`));
322
326
  } else {
323
- log$3(
327
+ log$4(
324
328
  chalk.red(
325
329
  `Error deleting label "${labelName}": ${error instanceof Error ? error.message : "Unknown error"}`
326
330
  )
@@ -341,17 +345,17 @@ const getLabels = async (configs2) => {
341
345
  const names = await resp.data.map((label) => label.name);
342
346
  return names;
343
347
  } else {
344
- log$3(chalk.red("something wrong"));
348
+ log$4(chalk.red("something wrong"));
345
349
  return [];
346
350
  }
347
351
  };
348
352
  const deleteLabels = async (configs2) => {
349
353
  const names = await getLabels(configs2);
350
354
  if (names.length === 0) {
351
- log$3(chalk.yellow("No labels found to delete"));
355
+ log$4(chalk.yellow("No labels found to delete"));
352
356
  return;
353
357
  }
354
- log$3(chalk.blue(`Deleting ${names.length} labels...`));
358
+ log$4(chalk.blue(`Deleting ${names.length} labels...`));
355
359
  for (const name of names) {
356
360
  try {
357
361
  const resp = await configs2.octokit.request(
@@ -363,15 +367,15 @@ const deleteLabels = async (configs2) => {
363
367
  }
364
368
  );
365
369
  if (resp.status === 204) {
366
- log$3(chalk.green(`${resp.status}: Deleted ${name}`));
370
+ log$4(chalk.green(`${resp.status}: Deleted ${name}`));
367
371
  } else {
368
- log$3(chalk.yellow(`${resp.status}: Something wrong with ${name}`));
372
+ log$4(chalk.yellow(`${resp.status}: Something wrong with ${name}`));
369
373
  }
370
374
  } catch (error) {
371
375
  if (error && typeof error === "object" && "status" in error && error.status === 404) {
372
- log$3(chalk.red(`404: Label "${name}" not found`));
376
+ log$4(chalk.red(`404: Label "${name}" not found`));
373
377
  } else {
374
- log$3(
378
+ log$4(
375
379
  chalk.red(
376
380
  `Error deleting label "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
377
381
  )
@@ -379,8 +383,8 @@ const deleteLabels = async (configs2) => {
379
383
  }
380
384
  }
381
385
  }
382
- log$3(chalk.blue("Finished deleting labels"));
383
- log$3(chalk.bgBlueBright(extraGuideText));
386
+ log$4(chalk.blue("Finished deleting labels"));
387
+ log$4(chalk.bgBlueBright(extraGuideText));
384
388
  };
385
389
  const _CryptoUtils = class _CryptoUtils {
386
390
  /**
@@ -930,9 +934,9 @@ class ConfigManager {
930
934
  /**
931
935
  * Check if file exists
932
936
  */
933
- async fileExists(path) {
937
+ async fileExists(path2) {
934
938
  try {
935
- await promises.access(path);
939
+ await promises.access(path2);
936
940
  return true;
937
941
  } catch {
938
942
  return false;
@@ -974,14 +978,14 @@ const getConfirmation = async () => {
974
978
  const response = await prompts(holdToken);
975
979
  return response.value;
976
980
  };
977
- const log$2 = console.log;
981
+ const log$3 = console.log;
978
982
  const generateSampleJson = async () => {
979
983
  try {
980
984
  const outputPath = "./hyouji.json";
981
985
  const jsonContent = JSON.stringify(sampleData, null, 2);
982
- log$2(chalk.blue("Generating sample JSON file..."));
986
+ log$3(chalk.blue("Generating sample JSON file..."));
983
987
  fs.writeFileSync(outputPath, jsonContent, "utf8");
984
- log$2(
988
+ log$3(
985
989
  chalk.green(
986
990
  "✅ Sample JSON file generated successfully at ./hyouji.json"
987
991
  )
@@ -990,50 +994,148 @@ const generateSampleJson = async () => {
990
994
  if (error instanceof Error) {
991
995
  const nodeError = error;
992
996
  if (nodeError.code === "EACCES") {
993
- log$2(
997
+ log$3(
994
998
  chalk.red(
995
999
  "❌ Error generating sample JSON file: Permission denied. Please check write permissions for the current directory."
996
1000
  )
997
1001
  );
998
1002
  } else if (nodeError.code === "ENOSPC") {
999
- log$2(
1003
+ log$3(
1000
1004
  chalk.red(
1001
1005
  "❌ Error generating sample JSON file: Insufficient disk space."
1002
1006
  )
1003
1007
  );
1004
1008
  } else if (nodeError.code === "EROFS") {
1005
- log$2(
1009
+ log$3(
1006
1010
  chalk.red(
1007
1011
  "❌ Error generating sample JSON file: Read-only file system."
1008
1012
  )
1009
1013
  );
1010
1014
  } else {
1015
+ log$3(chalk.red(`❌ Error generating sample JSON file: ${error.message}`));
1016
+ }
1017
+ } else {
1018
+ log$3(
1019
+ chalk.red(
1020
+ "❌ An unexpected error occurred while generating the sample JSON file"
1021
+ )
1022
+ );
1023
+ }
1024
+ }
1025
+ };
1026
+ const log$2 = console.log;
1027
+ const generateSampleYaml = async () => {
1028
+ try {
1029
+ const outputPath = "./hyouji.yaml";
1030
+ const yamlContent = yaml__default.dump(sampleData, {
1031
+ indent: 2,
1032
+ lineWidth: -1,
1033
+ // Disable line wrapping
1034
+ noRefs: true,
1035
+ // Disable references
1036
+ quotingType: '"',
1037
+ // Use double quotes for strings
1038
+ forceQuotes: false
1039
+ // Only quote when necessary
1040
+ });
1041
+ log$2(chalk.blue("Generating sample YAML file..."));
1042
+ fs.writeFileSync(outputPath, yamlContent, "utf8");
1043
+ log$2(
1044
+ chalk.green(
1045
+ "✅ Sample YAML file generated successfully at ./hyouji.yaml"
1046
+ )
1047
+ );
1048
+ } catch (error) {
1049
+ if (error instanceof Error) {
1050
+ const nodeError = error;
1051
+ if (nodeError.code === "EACCES") {
1052
+ log$2(
1053
+ chalk.red(
1054
+ "❌ Error generating sample YAML file: Permission denied. Please check write permissions for the current directory."
1055
+ )
1056
+ );
1057
+ } else if (nodeError.code === "ENOSPC") {
1058
+ log$2(
1059
+ chalk.red(
1060
+ "❌ Error generating sample YAML file: Insufficient disk space."
1061
+ )
1062
+ );
1063
+ } else if (nodeError.code === "EROFS") {
1011
1064
  log$2(
1012
- chalk.red(`❌ Error generating sample JSON file: ${error.message}`)
1065
+ chalk.red(
1066
+ "❌ Error generating sample YAML file: Read-only file system."
1067
+ )
1013
1068
  );
1069
+ } else {
1070
+ log$2(chalk.red(`❌ Error generating sample YAML file: ${error.message}`));
1014
1071
  }
1015
1072
  } else {
1016
1073
  log$2(
1017
1074
  chalk.red(
1018
- "❌ An unexpected error occurred while generating the sample JSON file"
1075
+ "❌ An unexpected error occurred while generating the sample YAML file"
1019
1076
  )
1020
1077
  );
1021
1078
  }
1022
1079
  }
1023
1080
  };
1081
+ const detectFileFormat = (filePath) => {
1082
+ const extension = path.extname(filePath).toLowerCase();
1083
+ switch (extension) {
1084
+ case ".json":
1085
+ return "json";
1086
+ case ".yaml":
1087
+ case ".yml":
1088
+ return "yaml";
1089
+ default:
1090
+ return null;
1091
+ }
1092
+ };
1093
+ const parseJsonContent = (content) => {
1094
+ return JSON.parse(content);
1095
+ };
1096
+ const parseYamlContent = (content) => {
1097
+ try {
1098
+ return yaml.load(content);
1099
+ } catch (error) {
1100
+ if (error instanceof yaml.YAMLException) {
1101
+ throw new Error(`YAMLException: ${error.message}`);
1102
+ }
1103
+ throw error;
1104
+ }
1105
+ };
1106
+ const getSupportedExtensions = () => {
1107
+ return [".json", ".yaml", ".yml"];
1108
+ };
1109
+ const formatSupportedExtensions = () => {
1110
+ return getSupportedExtensions().join(", ");
1111
+ };
1024
1112
  const log$1 = console.log;
1025
- const importLabelsFromJson = async (configs2, filePath) => {
1113
+ const importLabelsFromFile = async (configs2, filePath) => {
1026
1114
  try {
1027
1115
  if (!fs.existsSync(filePath)) {
1028
1116
  log$1(chalk.red(`Error: File not found at path: ${filePath}`));
1029
1117
  return;
1030
1118
  }
1119
+ const format = detectFileFormat(filePath);
1120
+ if (!format) {
1121
+ log$1(
1122
+ chalk.red(
1123
+ `Error: Unsupported file format. Supported formats: ${formatSupportedExtensions()}`
1124
+ )
1125
+ );
1126
+ return;
1127
+ }
1031
1128
  const fileContent = fs.readFileSync(filePath, "utf8");
1032
- let jsonData;
1129
+ let parsedData;
1033
1130
  try {
1034
- jsonData = JSON.parse(fileContent);
1131
+ if (format === "json") {
1132
+ parsedData = parseJsonContent(fileContent);
1133
+ } else if (format === "yaml") {
1134
+ parsedData = parseYamlContent(fileContent);
1135
+ }
1035
1136
  } catch (parseError) {
1036
- log$1(chalk.red(`Error: Invalid JSON syntax in file: ${filePath}`));
1137
+ const formatName = format.toUpperCase();
1138
+ log$1(chalk.red(`Error: Invalid ${formatName} syntax in file: ${filePath}`));
1037
1139
  log$1(
1038
1140
  chalk.red(
1039
1141
  `Parse error: ${parseError instanceof Error ? parseError.message : "Unknown error"}`
@@ -1041,13 +1143,13 @@ const importLabelsFromJson = async (configs2, filePath) => {
1041
1143
  );
1042
1144
  return;
1043
1145
  }
1044
- if (!Array.isArray(jsonData)) {
1045
- log$1(chalk.red("Error: JSON file must contain an array of label objects"));
1146
+ if (!Array.isArray(parsedData)) {
1147
+ log$1(chalk.red("Error: File must contain an array of label objects"));
1046
1148
  return;
1047
1149
  }
1048
1150
  const validLabels = [];
1049
- for (let i = 0; i < jsonData.length; i++) {
1050
- const item = jsonData[i];
1151
+ for (let i = 0; i < parsedData.length; i++) {
1152
+ const item = parsedData[i];
1051
1153
  if (typeof item !== "object" || item === null) {
1052
1154
  log$1(chalk.red(`Error: Item at index ${i} is not a valid object`));
1053
1155
  continue;
@@ -1128,7 +1230,7 @@ const importLabelsFromJson = async (configs2, filePath) => {
1128
1230
  validLabels.push(validLabel);
1129
1231
  }
1130
1232
  if (validLabels.length === 0) {
1131
- log$1(chalk.red("Error: No valid labels found in JSON file"));
1233
+ log$1(chalk.red("Error: No valid labels found in file"));
1132
1234
  return;
1133
1235
  }
1134
1236
  log$1(chalk.blue(`Starting import of ${validLabels.length} labels...`));
@@ -1485,8 +1587,8 @@ const getGitHubConfigs = async () => {
1485
1587
  detectionMethod: "manual"
1486
1588
  };
1487
1589
  };
1488
- const getJsonFilePath = async () => {
1489
- const response = await prompts(jsonFilePath);
1590
+ const getLabelFilePath = async () => {
1591
+ const response = await prompts(labelFilePath);
1490
1592
  return response.filePath;
1491
1593
  };
1492
1594
  const getNewLabel = async () => {
@@ -1665,16 +1767,16 @@ const main = async () => {
1665
1767
  }
1666
1768
  case 4: {
1667
1769
  try {
1668
- const filePath = await getJsonFilePath();
1770
+ const filePath = await getLabelFilePath();
1669
1771
  if (filePath) {
1670
- await importLabelsFromJson(configs, filePath);
1772
+ await importLabelsFromFile(configs, filePath);
1671
1773
  } else {
1672
1774
  log(chalk.yellow("No file path provided. Returning to main menu."));
1673
1775
  }
1674
1776
  } catch (error) {
1675
1777
  log(
1676
1778
  chalk.red(
1677
- `Error during JSON import: ${error instanceof Error ? error.message : "Unknown error"}`
1779
+ `Error during label import: ${error instanceof Error ? error.message : "Unknown error"}`
1678
1780
  )
1679
1781
  );
1680
1782
  }
@@ -1695,13 +1797,27 @@ const main = async () => {
1695
1797
  break;
1696
1798
  }
1697
1799
  case 6: {
1698
- await displaySettings();
1800
+ try {
1801
+ await generateSampleYaml();
1802
+ } catch (error) {
1803
+ log(
1804
+ chalk.red(
1805
+ `Error generating sample YAML: ${error instanceof Error ? error.message : "Unknown error"}`
1806
+ )
1807
+ );
1808
+ }
1699
1809
  firstStart = firstStart && false;
1700
1810
  break;
1701
1811
  }
1702
1812
  case 7: {
1813
+ await displaySettings();
1814
+ firstStart = firstStart && false;
1815
+ break;
1816
+ }
1817
+ case 8: {
1703
1818
  console.log("exit");
1704
1819
  process.exit(0);
1820
+ return;
1705
1821
  }
1706
1822
  // eslint-disable-next-line no-fallthrough
1707
1823
  default: {
package/package.json CHANGED
@@ -1,8 +1,10 @@
1
1
  {
2
2
  "name": "hyouji",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Hyouji (表示) — A command-line tool for organizing and displaying GitHub labels with clarity and harmony.",
5
5
  "main": "dist/index.js",
6
+ "author": "koji <baxin1919@gmail.com>",
7
+ "homepage": "https://github.com/koji/Hyouji",
6
8
  "bin": {
7
9
  "hyouji": "dist/index.js"
8
10
  },
@@ -20,21 +22,21 @@
20
22
  "hyouji",
21
23
  "cli",
22
24
  "表示",
23
- "Hyouji(表示)"
25
+ "Hyouji(表示)",
26
+ "JSON",
27
+ "yaml",
28
+ "yml"
24
29
  ],
25
30
  "scripts": {
26
31
  "start": "node dist/index.js",
27
32
  "build": "vite build",
28
33
  "dev": "vite build --watch",
29
- "fix": "run-s fix:*",
30
- "fix:prettier": "prettier \"src/**/*.ts\" --write",
31
- "fix:lint": "eslint src --ext .ts --fix",
34
+ "lint": "biome lint .",
35
+ "lint:fix": "biome lint --write .",
32
36
  "test": "vitest run",
33
37
  "test:watch": "vitest",
34
38
  "test:ui": "vitest --ui",
35
39
  "test:coverage": "vitest run --coverage",
36
- "test:lint": "eslint src --ext .ts",
37
- "test:prettier": "prettier \"src/**/*.ts\" --list-different",
38
40
  "test:error-handling": "node tests/scripts/error-handling/run-all.cjs",
39
41
  "test:config": "node tests/scripts/config/run-all.cjs",
40
42
  "test:integration": "node tests/scripts/run-integration.cjs",
@@ -56,25 +58,19 @@
56
58
  "dependencies": {
57
59
  "@octokit/core": "^7.0.3",
58
60
  "chalk": "^5.4.1",
61
+ "js-yaml": "^4.1.0",
59
62
  "oh-my-logo": "^0.3.0",
60
63
  "prompts": "^2.4.2"
61
64
  },
62
65
  "devDependencies": {
66
+ "@biomejs/biome": "2.2.6",
67
+ "@types/js-yaml": "^4.0.9",
63
68
  "@types/node": "^24.0.13",
64
69
  "@vitest/coverage-v8": "^3.2.4",
65
70
  "@vitest/ui": "^3.2.4",
66
- "eslint": "^9.30.1",
67
- "eslint-config-prettier": "^10.1.5",
68
- "eslint-import-resolver-typescript": "^4.4.4",
69
- "eslint-plugin-eslint-comments": "^3.2.0",
70
- "eslint-plugin-import": "^2.32.0",
71
- "globals": "^16.3.0",
72
- "npm-run-all": "^4.1.5",
73
- "prettier": "^3.6.2",
74
71
  "standard-version": "^9.5.0",
75
72
  "ts-node": "^10.9.2",
76
73
  "typescript": "^5.8.3",
77
- "typescript-eslint": "^8.36.0",
78
74
  "vite": "^7.1.2",
79
75
  "vitest": "^3.2.4"
80
76
  },
@@ -83,8 +79,5 @@
83
79
  "README.md",
84
80
  "LICENSE"
85
81
  ],
86
- "prettier": {
87
- "singleQuote": true
88
- },
89
82
  "type": "module"
90
83
  }