hyouji 0.0.7 → 0.0.9

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 +94 -8
  2. package/dist/index.js +241 -42
  3. package/package.json +6 -2
package/README.md CHANGED
@@ -18,7 +18,6 @@ https://levelup.gitconnected.com/create-github-labels-from-terminal-158d4868fab
18
18
 
19
19
  https://github.com/user-attachments/assets/739f185a-1bd0-411b-8947-dd4600c452c8
20
20
 
21
-
22
21
  ### Labels API
23
22
 
24
23
  https://docs.github.com/en/rest/reference/issues#labels
@@ -60,7 +59,7 @@ This tool provides the following functionality:
60
59
  2. Create multiple labels on a specific repo
61
60
  3. Delete a single label from a specific repo
62
61
  4. Delete all labels from a specific repo
63
- 5. Import labels from JSON file
62
+ 5. Import labels from JSON or YAML file
64
63
  6. **Display your saved settings** - View your stored GitHub configuration
65
64
  7. **Persistent configuration** - Save your GitHub token and username for future use
66
65
 
@@ -77,9 +76,7 @@ hyouji
77
76
  On your first run, you'll be prompted to enter:
78
77
 
79
78
  - **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
-
79
+ <img width="792" height="564" alt="github_token" src="https://github.com/user-attachments/assets/e460738f-833a-4158-a8ba-61752beaad72" />
83
80
  - **GitHub Username** - Your GitHub account name
84
81
 
85
82
  These credentials will be securely saved and reused for future sessions.
@@ -90,9 +87,11 @@ These credentials will be securely saved and reused for future sessions.
90
87
  2. **Create multiple labels on a specific repo**
91
88
  3. **Delete a single label from a specific repo**
92
89
  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**
90
+ 5. **Import labels from JSON or YAML file**
91
+ 6. **Generate sample JSON** - Create a sample JSON file with predefined labels
92
+ 7. **Generate sample YAML** - Create a sample YAML file with predefined labels
93
+ 8. **Display your settings** - View your saved configuration
94
+ 9. **Exit**
96
95
 
97
96
  ### Settings Management
98
97
 
@@ -200,6 +199,93 @@ npm start
200
199
 
201
200
  You can use `pnpm`, `yarn` or `bun`.
202
201
 
202
+ ### File Import Support
203
+
204
+ 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.
205
+
206
+ #### Supported File Formats
207
+
208
+ - **JSON files** (`.json` extension)
209
+ - **YAML files** (`.yaml` or `.yml` extension)
210
+
211
+ #### Label Structure
212
+
213
+ Both formats support the same label structure:
214
+
215
+ - `name` (required): The label name
216
+ - `color` (optional): Hex color code without the `#` symbol
217
+ - `description` (optional): Label description
218
+
219
+ #### JSON Example
220
+
221
+ ```json
222
+ [
223
+ {
224
+ "name": "bug",
225
+ "color": "d73a4a",
226
+ "description": "Something isn't working"
227
+ },
228
+ {
229
+ "name": "enhancement",
230
+ "color": "a2eeef",
231
+ "description": "New feature or request"
232
+ },
233
+ {
234
+ "name": "documentation",
235
+ "color": "0075ca",
236
+ "description": "Improvements or additions to documentation"
237
+ }
238
+ ]
239
+ ```
240
+
241
+ #### YAML Example
242
+
243
+ ```yaml
244
+ # Sample YAML file for importing GitHub labels
245
+ - name: 'bug'
246
+ color: 'd73a4a'
247
+ description: "Something isn't working"
248
+
249
+ - name: 'enhancement'
250
+ color: 'a2eeef'
251
+ description: 'New feature or request'
252
+
253
+ - name: 'documentation'
254
+ color: '0075ca'
255
+ description: 'Improvements or additions to documentation'
256
+
257
+ # Labels with minimal configuration (name only)
258
+ - name: 'good first issue'
259
+ color: '7057ff'
260
+ description: 'Good for newcomers'
261
+
262
+ # Labels without description (optional field)
263
+ - name: 'wontfix'
264
+ color: 'ffffff'
265
+
266
+ # Labels without color (will use GitHub default)
267
+ - name: 'question'
268
+ description: 'Further information is requested'
269
+ ```
270
+
271
+ #### Sample Files
272
+
273
+ You can find complete example files in the `examples/` directory:
274
+
275
+ - `examples/labels.json` - Basic label examples in JSON format
276
+ - `examples/labels.yaml` - Basic label examples in YAML format
277
+ - `examples/project-labels.json` - Project management labels in JSON format
278
+ - `examples/project-labels.yaml` - Project management labels in YAML format
279
+
280
+ #### Generate Sample Files
281
+
282
+ The tool can generate sample files for you:
283
+
284
+ - **Generate sample JSON** - Creates `hyouji.json` with predefined labels
285
+ - **Generate sample YAML** - Creates `hyouji.yaml` with predefined labels
286
+
287
+ Both generated files contain the same predefined labels and can be used as starting points for your own label configurations.
288
+
203
289
  ### Predefined Labels
204
290
 
205
291
  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,9 +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 },
67
- { title: "Display your settings", value: 5 },
68
- { title: "exit", value: 6 }
69
+ { title: "import labels from JSON or YAML", value: 4 },
70
+ { title: "Generate sample JSON", value: 5 },
71
+ { title: "Generate sample YAML", value: 6 },
72
+ { title: "Display your settings", value: 7 },
73
+ { title: "exit", value: 8 }
69
74
  ]
70
75
  };
71
76
  const holdToken = {
@@ -74,6 +79,23 @@ const holdToken = {
74
79
  message: "Do you have a personal token?",
75
80
  initial: true
76
81
  };
82
+ const sampleData = [
83
+ {
84
+ name: "Type: Bug Fix",
85
+ color: "FF8A65",
86
+ description: "Fix features that are not working"
87
+ },
88
+ {
89
+ name: "Type: Enhancement",
90
+ color: "64B5F7",
91
+ description: "Add new features"
92
+ },
93
+ {
94
+ name: "Type: Improvement",
95
+ color: "4DB6AC",
96
+ description: "Improve existing functionality"
97
+ }
98
+ ];
77
99
  const labels = (
78
100
  // the following labels are based on this post
79
101
  // https://qiita.com/willow-micro/items/51eeb3efe5b4192a4abd
@@ -247,7 +269,7 @@ Thank you!
247
269
  };
248
270
  const extraGuideText = `If you don't see action selector, please hit space key.`;
249
271
  const linkToPersonalToken = "https://github.com/settings/tokens";
250
- const log$2 = console.log;
272
+ const log$4 = console.log;
251
273
  const createLabel = async (configs2, label) => {
252
274
  const resp = await configs2.octokit.request(
253
275
  "POST /repos/{owner}/{repo}/labels",
@@ -262,16 +284,16 @@ const createLabel = async (configs2, label) => {
262
284
  const status = resp.status;
263
285
  switch (status) {
264
286
  case 201:
265
- log$2(chalk.green(`${resp.status}: Created ${label.name}`));
287
+ log$4(chalk.green(`${resp.status}: Created ${label.name}`));
266
288
  break;
267
289
  case 404:
268
- log$2(chalk.red(`${resp.status}: Resource not found`));
290
+ log$4(chalk.red(`${resp.status}: Resource not found`));
269
291
  break;
270
292
  case 422:
271
- log$2(chalk.red(`${resp.status}: Validation failed`));
293
+ log$4(chalk.red(`${resp.status}: Validation failed`));
272
294
  break;
273
295
  default:
274
- log$2(chalk.yellow(`${resp.status}: Something wrong`));
296
+ log$4(chalk.yellow(`${resp.status}: Something wrong`));
275
297
  break;
276
298
  }
277
299
  };
@@ -279,8 +301,8 @@ const createLabels = async (configs2) => {
279
301
  labels.forEach(async (label) => {
280
302
  createLabel(configs2, label);
281
303
  });
282
- log$2("Created all labels");
283
- log$2(chalk.bgBlueBright(extraGuideText));
304
+ log$4("Created all labels");
305
+ log$4(chalk.bgBlueBright(extraGuideText));
284
306
  };
285
307
  const deleteLabel = async (configs2, labelNames) => {
286
308
  for (const labelName of labelNames) {
@@ -294,15 +316,15 @@ const deleteLabel = async (configs2, labelNames) => {
294
316
  }
295
317
  );
296
318
  if (resp.status === 204) {
297
- log$2(chalk.green(`${resp.status}: Deleted ${labelName}`));
319
+ log$4(chalk.green(`${resp.status}: Deleted ${labelName}`));
298
320
  } else {
299
- log$2(chalk.yellow(`${resp.status}: Something wrong with ${labelName}`));
321
+ log$4(chalk.yellow(`${resp.status}: Something wrong with ${labelName}`));
300
322
  }
301
323
  } catch (error) {
302
324
  if (error && typeof error === "object" && "status" in error && error.status === 404) {
303
- log$2(chalk.red(`404: Label "${labelName}" not found`));
325
+ log$4(chalk.red(`404: Label "${labelName}" not found`));
304
326
  } else {
305
- log$2(
327
+ log$4(
306
328
  chalk.red(
307
329
  `Error deleting label "${labelName}": ${error instanceof Error ? error.message : "Unknown error"}`
308
330
  )
@@ -323,17 +345,17 @@ const getLabels = async (configs2) => {
323
345
  const names = await resp.data.map((label) => label.name);
324
346
  return names;
325
347
  } else {
326
- log$2(chalk.red("something wrong"));
348
+ log$4(chalk.red("something wrong"));
327
349
  return [];
328
350
  }
329
351
  };
330
352
  const deleteLabels = async (configs2) => {
331
353
  const names = await getLabels(configs2);
332
354
  if (names.length === 0) {
333
- log$2(chalk.yellow("No labels found to delete"));
355
+ log$4(chalk.yellow("No labels found to delete"));
334
356
  return;
335
357
  }
336
- log$2(chalk.blue(`Deleting ${names.length} labels...`));
358
+ log$4(chalk.blue(`Deleting ${names.length} labels...`));
337
359
  for (const name of names) {
338
360
  try {
339
361
  const resp = await configs2.octokit.request(
@@ -345,15 +367,15 @@ const deleteLabels = async (configs2) => {
345
367
  }
346
368
  );
347
369
  if (resp.status === 204) {
348
- log$2(chalk.green(`${resp.status}: Deleted ${name}`));
370
+ log$4(chalk.green(`${resp.status}: Deleted ${name}`));
349
371
  } else {
350
- log$2(chalk.yellow(`${resp.status}: Something wrong with ${name}`));
372
+ log$4(chalk.yellow(`${resp.status}: Something wrong with ${name}`));
351
373
  }
352
374
  } catch (error) {
353
375
  if (error && typeof error === "object" && "status" in error && error.status === 404) {
354
- log$2(chalk.red(`404: Label "${name}" not found`));
376
+ log$4(chalk.red(`404: Label "${name}" not found`));
355
377
  } else {
356
- log$2(
378
+ log$4(
357
379
  chalk.red(
358
380
  `Error deleting label "${name}": ${error instanceof Error ? error.message : "Unknown error"}`
359
381
  )
@@ -361,8 +383,8 @@ const deleteLabels = async (configs2) => {
361
383
  }
362
384
  }
363
385
  }
364
- log$2(chalk.blue("Finished deleting labels"));
365
- log$2(chalk.bgBlueBright(extraGuideText));
386
+ log$4(chalk.blue("Finished deleting labels"));
387
+ log$4(chalk.bgBlueBright(extraGuideText));
366
388
  };
367
389
  const _CryptoUtils = class _CryptoUtils {
368
390
  /**
@@ -912,9 +934,9 @@ class ConfigManager {
912
934
  /**
913
935
  * Check if file exists
914
936
  */
915
- async fileExists(path) {
937
+ async fileExists(path2) {
916
938
  try {
917
- await promises.access(path);
939
+ await promises.access(path2);
918
940
  return true;
919
941
  } catch {
920
942
  return false;
@@ -956,19 +978,170 @@ const getConfirmation = async () => {
956
978
  const response = await prompts(holdToken);
957
979
  return response.value;
958
980
  };
981
+ const log$3 = console.log;
982
+ const generateSampleJson = async () => {
983
+ try {
984
+ const outputPath = "./hyouji.json";
985
+ const jsonContent = JSON.stringify(sampleData, null, 2);
986
+ log$3(chalk.blue("Generating sample JSON file..."));
987
+ fs.writeFileSync(outputPath, jsonContent, "utf8");
988
+ log$3(
989
+ chalk.green(
990
+ "✅ Sample JSON file generated successfully at ./hyouji.json"
991
+ )
992
+ );
993
+ } catch (error) {
994
+ if (error instanceof Error) {
995
+ const nodeError = error;
996
+ if (nodeError.code === "EACCES") {
997
+ log$3(
998
+ chalk.red(
999
+ "❌ Error generating sample JSON file: Permission denied. Please check write permissions for the current directory."
1000
+ )
1001
+ );
1002
+ } else if (nodeError.code === "ENOSPC") {
1003
+ log$3(
1004
+ chalk.red(
1005
+ "❌ Error generating sample JSON file: Insufficient disk space."
1006
+ )
1007
+ );
1008
+ } else if (nodeError.code === "EROFS") {
1009
+ log$3(
1010
+ chalk.red(
1011
+ "❌ Error generating sample JSON file: Read-only file system."
1012
+ )
1013
+ );
1014
+ } else {
1015
+ log$3(
1016
+ chalk.red(`❌ Error generating sample JSON file: ${error.message}`)
1017
+ );
1018
+ }
1019
+ } else {
1020
+ log$3(
1021
+ chalk.red(
1022
+ "❌ An unexpected error occurred while generating the sample JSON file"
1023
+ )
1024
+ );
1025
+ }
1026
+ }
1027
+ };
1028
+ const log$2 = console.log;
1029
+ const generateSampleYaml = async () => {
1030
+ try {
1031
+ const outputPath = "./hyouji.yaml";
1032
+ const yamlContent = yaml__default.dump(sampleData, {
1033
+ indent: 2,
1034
+ lineWidth: -1,
1035
+ // Disable line wrapping
1036
+ noRefs: true,
1037
+ // Disable references
1038
+ quotingType: '"',
1039
+ // Use double quotes for strings
1040
+ forceQuotes: false
1041
+ // Only quote when necessary
1042
+ });
1043
+ log$2(chalk.blue("Generating sample YAML file..."));
1044
+ fs.writeFileSync(outputPath, yamlContent, "utf8");
1045
+ log$2(
1046
+ chalk.green(
1047
+ "✅ Sample YAML file generated successfully at ./hyouji.yaml"
1048
+ )
1049
+ );
1050
+ } catch (error) {
1051
+ if (error instanceof Error) {
1052
+ const nodeError = error;
1053
+ if (nodeError.code === "EACCES") {
1054
+ log$2(
1055
+ chalk.red(
1056
+ "❌ Error generating sample YAML file: Permission denied. Please check write permissions for the current directory."
1057
+ )
1058
+ );
1059
+ } else if (nodeError.code === "ENOSPC") {
1060
+ log$2(
1061
+ chalk.red(
1062
+ "❌ Error generating sample YAML file: Insufficient disk space."
1063
+ )
1064
+ );
1065
+ } else if (nodeError.code === "EROFS") {
1066
+ log$2(
1067
+ chalk.red(
1068
+ "❌ Error generating sample YAML file: Read-only file system."
1069
+ )
1070
+ );
1071
+ } else {
1072
+ log$2(
1073
+ chalk.red(`❌ Error generating sample YAML file: ${error.message}`)
1074
+ );
1075
+ }
1076
+ } else {
1077
+ log$2(
1078
+ chalk.red(
1079
+ "❌ An unexpected error occurred while generating the sample YAML file"
1080
+ )
1081
+ );
1082
+ }
1083
+ }
1084
+ };
1085
+ const detectFileFormat = (filePath) => {
1086
+ const extension = path.extname(filePath).toLowerCase();
1087
+ switch (extension) {
1088
+ case ".json":
1089
+ return "json";
1090
+ case ".yaml":
1091
+ case ".yml":
1092
+ return "yaml";
1093
+ default:
1094
+ return null;
1095
+ }
1096
+ };
1097
+ const parseJsonContent = (content) => {
1098
+ return JSON.parse(content);
1099
+ };
1100
+ const parseYamlContent = (content) => {
1101
+ try {
1102
+ return yaml.load(content);
1103
+ } catch (error) {
1104
+ if (error instanceof yaml.YAMLException) {
1105
+ throw new Error(`YAMLException: ${error.message}`);
1106
+ }
1107
+ throw error;
1108
+ }
1109
+ };
1110
+ const getSupportedExtensions = () => {
1111
+ return [".json", ".yaml", ".yml"];
1112
+ };
1113
+ const formatSupportedExtensions = () => {
1114
+ return getSupportedExtensions().join(", ");
1115
+ };
959
1116
  const log$1 = console.log;
960
- const importLabelsFromJson = async (configs2, filePath) => {
1117
+ const importLabelsFromFile = async (configs2, filePath) => {
961
1118
  try {
962
1119
  if (!fs.existsSync(filePath)) {
963
1120
  log$1(chalk.red(`Error: File not found at path: ${filePath}`));
964
1121
  return;
965
1122
  }
1123
+ const format = detectFileFormat(filePath);
1124
+ if (!format) {
1125
+ log$1(
1126
+ chalk.red(
1127
+ `Error: Unsupported file format. Supported formats: ${formatSupportedExtensions()}`
1128
+ )
1129
+ );
1130
+ return;
1131
+ }
966
1132
  const fileContent = fs.readFileSync(filePath, "utf8");
967
- let jsonData;
1133
+ let parsedData;
968
1134
  try {
969
- jsonData = JSON.parse(fileContent);
1135
+ if (format === "json") {
1136
+ parsedData = parseJsonContent(fileContent);
1137
+ } else if (format === "yaml") {
1138
+ parsedData = parseYamlContent(fileContent);
1139
+ }
970
1140
  } catch (parseError) {
971
- log$1(chalk.red(`Error: Invalid JSON syntax in file: ${filePath}`));
1141
+ const formatName = format.toUpperCase();
1142
+ log$1(
1143
+ chalk.red(`Error: Invalid ${formatName} syntax in file: ${filePath}`)
1144
+ );
972
1145
  log$1(
973
1146
  chalk.red(
974
1147
  `Parse error: ${parseError instanceof Error ? parseError.message : "Unknown error"}`
@@ -976,13 +1149,13 @@ const importLabelsFromJson = async (configs2, filePath) => {
976
1149
  );
977
1150
  return;
978
1151
  }
979
- if (!Array.isArray(jsonData)) {
980
- log$1(chalk.red("Error: JSON file must contain an array of label objects"));
1152
+ if (!Array.isArray(parsedData)) {
1153
+ log$1(chalk.red("Error: File must contain an array of label objects"));
981
1154
  return;
982
1155
  }
983
1156
  const validLabels = [];
984
- for (let i = 0; i < jsonData.length; i++) {
985
- const item = jsonData[i];
1157
+ for (let i = 0; i < parsedData.length; i++) {
1158
+ const item = parsedData[i];
986
1159
  if (typeof item !== "object" || item === null) {
987
1160
  log$1(chalk.red(`Error: Item at index ${i} is not a valid object`));
988
1161
  continue;
@@ -1063,7 +1236,7 @@ const importLabelsFromJson = async (configs2, filePath) => {
1063
1236
  validLabels.push(validLabel);
1064
1237
  }
1065
1238
  if (validLabels.length === 0) {
1066
- log$1(chalk.red("Error: No valid labels found in JSON file"));
1239
+ log$1(chalk.red("Error: No valid labels found in file"));
1067
1240
  return;
1068
1241
  }
1069
1242
  log$1(chalk.blue(`Starting import of ${validLabels.length} labels...`));
@@ -1420,8 +1593,8 @@ const getGitHubConfigs = async () => {
1420
1593
  detectionMethod: "manual"
1421
1594
  };
1422
1595
  };
1423
- const getJsonFilePath = async () => {
1424
- const response = await prompts(jsonFilePath);
1596
+ const getLabelFilePath = async () => {
1597
+ const response = await prompts(labelFilePath);
1425
1598
  return response.filePath;
1426
1599
  };
1427
1600
  const getNewLabel = async () => {
@@ -1600,16 +1773,16 @@ const main = async () => {
1600
1773
  }
1601
1774
  case 4: {
1602
1775
  try {
1603
- const filePath = await getJsonFilePath();
1776
+ const filePath = await getLabelFilePath();
1604
1777
  if (filePath) {
1605
- await importLabelsFromJson(configs, filePath);
1778
+ await importLabelsFromFile(configs, filePath);
1606
1779
  } else {
1607
1780
  log(chalk.yellow("No file path provided. Returning to main menu."));
1608
1781
  }
1609
1782
  } catch (error) {
1610
1783
  log(
1611
1784
  chalk.red(
1612
- `Error during JSON import: ${error instanceof Error ? error.message : "Unknown error"}`
1785
+ `Error during label import: ${error instanceof Error ? error.message : "Unknown error"}`
1613
1786
  )
1614
1787
  );
1615
1788
  }
@@ -1617,11 +1790,37 @@ const main = async () => {
1617
1790
  break;
1618
1791
  }
1619
1792
  case 5: {
1620
- await displaySettings();
1793
+ try {
1794
+ await generateSampleJson();
1795
+ } catch (error) {
1796
+ log(
1797
+ chalk.red(
1798
+ `Error generating sample JSON: ${error instanceof Error ? error.message : "Unknown error"}`
1799
+ )
1800
+ );
1801
+ }
1621
1802
  firstStart = firstStart && false;
1622
1803
  break;
1623
1804
  }
1624
1805
  case 6: {
1806
+ try {
1807
+ await generateSampleYaml();
1808
+ } catch (error) {
1809
+ log(
1810
+ chalk.red(
1811
+ `Error generating sample YAML: ${error instanceof Error ? error.message : "Unknown error"}`
1812
+ )
1813
+ );
1814
+ }
1815
+ firstStart = firstStart && false;
1816
+ break;
1817
+ }
1818
+ case 7: {
1819
+ await displaySettings();
1820
+ firstStart = firstStart && false;
1821
+ break;
1822
+ }
1823
+ case 8: {
1625
1824
  console.log("exit");
1626
1825
  process.exit(0);
1627
1826
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyouji",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
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
6
  "bin": {
@@ -20,7 +20,10 @@
20
20
  "hyouji",
21
21
  "cli",
22
22
  "表示",
23
- "Hyouji(表示)"
23
+ "Hyouji(表示)",
24
+ "JSON",
25
+ "yaml",
26
+ "yml"
24
27
  ],
25
28
  "scripts": {
26
29
  "start": "node dist/index.js",
@@ -60,6 +63,7 @@
60
63
  "prompts": "^2.4.2"
61
64
  },
62
65
  "devDependencies": {
66
+ "@types/js-yaml": "^4.0.9",
63
67
  "@types/node": "^24.0.13",
64
68
  "@vitest/coverage-v8": "^3.2.4",
65
69
  "@vitest/ui": "^3.2.4",