@s-hirano-ist/s-scripts 1.26.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +2 -0
  2. package/dist/chunk-5OXUZW2Q.js +590 -0
  3. package/dist/chunk-7PVU2Z32.js +71 -0
  4. package/dist/chunk-AJMTRCPJ.js +15 -0
  5. package/dist/chunk-AZF2R2BF.js +85 -0
  6. package/dist/chunk-F4J6JBR4.js +115 -0
  7. package/dist/chunk-HDYQV2Y2.js +58 -0
  8. package/dist/chunk-HIK7SX34.js +85 -0
  9. package/dist/chunk-IWNZQXDG.js +7660 -0
  10. package/dist/chunk-J4VLH4VA.js +267 -0
  11. package/dist/chunk-JZOR5GA2.js +42 -0
  12. package/dist/chunk-KKZP7ZF3.js +77 -0
  13. package/dist/chunk-N6TZF755.js +102 -0
  14. package/dist/chunk-S5WJ5VXW.js +85 -0
  15. package/dist/chunk-UXGLXHQ6.js +40 -0
  16. package/dist/cleanup-minio-images.js +115 -92
  17. package/dist/enrich-books.js +87 -78
  18. package/dist/fetch-articles.js +101 -90
  19. package/dist/fetch-books.js +147 -128
  20. package/dist/fetch-images.js +88 -72
  21. package/dist/fetch-notes.js +66 -54
  22. package/dist/find-duplicate-json-articles.js +100 -97
  23. package/dist/fix-book-frontmatter.js +111 -99
  24. package/dist/fix-image-formats.js +81 -65
  25. package/dist/ingest-articles.js +30 -249
  26. package/dist/ingest-books.js +61 -318
  27. package/dist/ingest-images.js +33 -184
  28. package/dist/ingest-notes.js +41 -171
  29. package/dist/rag/delete-collection.js +32 -22
  30. package/dist/rag/ingest.js +371 -92
  31. package/dist/rag/search.js +80 -76
  32. package/dist/reset-articles.js +57 -60
  33. package/dist/reset-books.js +57 -59
  34. package/dist/reset-images.js +57 -59
  35. package/dist/reset-notes.js +57 -59
  36. package/dist/revert-articles.js +53 -55
  37. package/dist/revert-books.js +53 -53
  38. package/dist/revert-images.js +53 -53
  39. package/dist/revert-notes.js +53 -53
  40. package/dist/s-content-format.js +103 -13
  41. package/dist/update-json-articles.js +101 -97
  42. package/dist/update-raw-articles.js +130 -130
  43. package/dist/validate-json-articles.js +129 -130
  44. package/package.json +13 -50
  45. package/dist/cleanup-minio-images.d.ts +0 -3
  46. package/dist/cleanup-minio-images.d.ts.map +0 -1
  47. package/dist/cleanup-minio-images.js.map +0 -1
  48. package/dist/enrich-books.d.ts +0 -3
  49. package/dist/enrich-books.d.ts.map +0 -1
  50. package/dist/enrich-books.js.map +0 -1
  51. package/dist/fetch-articles.d.ts +0 -3
  52. package/dist/fetch-articles.d.ts.map +0 -1
  53. package/dist/fetch-articles.js.map +0 -1
  54. package/dist/fetch-books.d.ts +0 -3
  55. package/dist/fetch-books.d.ts.map +0 -1
  56. package/dist/fetch-books.js.map +0 -1
  57. package/dist/fetch-images.d.ts +0 -3
  58. package/dist/fetch-images.d.ts.map +0 -1
  59. package/dist/fetch-images.js.map +0 -1
  60. package/dist/fetch-notes.d.ts +0 -3
  61. package/dist/fetch-notes.d.ts.map +0 -1
  62. package/dist/fetch-notes.js.map +0 -1
  63. package/dist/find-duplicate-json-articles.d.ts +0 -3
  64. package/dist/find-duplicate-json-articles.d.ts.map +0 -1
  65. package/dist/find-duplicate-json-articles.js.map +0 -1
  66. package/dist/fix-book-frontmatter.d.ts +0 -3
  67. package/dist/fix-book-frontmatter.d.ts.map +0 -1
  68. package/dist/fix-book-frontmatter.js.map +0 -1
  69. package/dist/fix-image-formats.d.ts +0 -3
  70. package/dist/fix-image-formats.d.ts.map +0 -1
  71. package/dist/fix-image-formats.js.map +0 -1
  72. package/dist/infrastructures/articles-command-repository.d.ts +0 -57
  73. package/dist/infrastructures/articles-command-repository.d.ts.map +0 -1
  74. package/dist/infrastructures/articles-command-repository.js +0 -68
  75. package/dist/infrastructures/articles-command-repository.js.map +0 -1
  76. package/dist/infrastructures/books-command-repository.d.ts +0 -34
  77. package/dist/infrastructures/books-command-repository.d.ts.map +0 -1
  78. package/dist/infrastructures/books-command-repository.js +0 -53
  79. package/dist/infrastructures/books-command-repository.js.map +0 -1
  80. package/dist/infrastructures/cache-invalidation-client.d.ts +0 -9
  81. package/dist/infrastructures/cache-invalidation-client.d.ts.map +0 -1
  82. package/dist/infrastructures/cache-invalidation-client.js +0 -21
  83. package/dist/infrastructures/cache-invalidation-client.js.map +0 -1
  84. package/dist/infrastructures/cache-invalidation-client.test.d.ts +0 -2
  85. package/dist/infrastructures/cache-invalidation-client.test.d.ts.map +0 -1
  86. package/dist/infrastructures/cache-invalidation-client.test.js +0 -25
  87. package/dist/infrastructures/cache-invalidation-client.test.js.map +0 -1
  88. package/dist/infrastructures/images-command-repository.d.ts +0 -34
  89. package/dist/infrastructures/images-command-repository.d.ts.map +0 -1
  90. package/dist/infrastructures/images-command-repository.js +0 -53
  91. package/dist/infrastructures/images-command-repository.js.map +0 -1
  92. package/dist/infrastructures/notes-command-repository.d.ts +0 -34
  93. package/dist/infrastructures/notes-command-repository.d.ts.map +0 -1
  94. package/dist/infrastructures/notes-command-repository.js +0 -53
  95. package/dist/infrastructures/notes-command-repository.js.map +0 -1
  96. package/dist/ingest-articles.d.ts +0 -3
  97. package/dist/ingest-articles.d.ts.map +0 -1
  98. package/dist/ingest-articles.js.map +0 -1
  99. package/dist/ingest-books.d.ts +0 -3
  100. package/dist/ingest-books.d.ts.map +0 -1
  101. package/dist/ingest-books.js.map +0 -1
  102. package/dist/ingest-images.d.ts +0 -3
  103. package/dist/ingest-images.d.ts.map +0 -1
  104. package/dist/ingest-images.js.map +0 -1
  105. package/dist/ingest-notes.d.ts +0 -3
  106. package/dist/ingest-notes.d.ts.map +0 -1
  107. package/dist/ingest-notes.js.map +0 -1
  108. package/dist/lib/glob-paths.d.ts +0 -6
  109. package/dist/lib/glob-paths.d.ts.map +0 -1
  110. package/dist/lib/glob-paths.js +0 -9
  111. package/dist/lib/glob-paths.js.map +0 -1
  112. package/dist/lib/glob-paths.test.d.ts +0 -2
  113. package/dist/lib/glob-paths.test.d.ts.map +0 -1
  114. package/dist/lib/glob-paths.test.js +0 -30
  115. package/dist/lib/glob-paths.test.js.map +0 -1
  116. package/dist/lib/html-charset.d.ts +0 -4
  117. package/dist/lib/html-charset.d.ts.map +0 -1
  118. package/dist/lib/html-charset.js +0 -33
  119. package/dist/lib/html-charset.js.map +0 -1
  120. package/dist/lib/html-charset.test.d.ts +0 -2
  121. package/dist/lib/html-charset.test.d.ts.map +0 -1
  122. package/dist/lib/html-charset.test.js +0 -27
  123. package/dist/lib/html-charset.test.js.map +0 -1
  124. package/dist/rag/delete-collection.d.ts +0 -3
  125. package/dist/rag/delete-collection.d.ts.map +0 -1
  126. package/dist/rag/delete-collection.js.map +0 -1
  127. package/dist/rag/ingest-config.d.ts +0 -8
  128. package/dist/rag/ingest-config.d.ts.map +0 -1
  129. package/dist/rag/ingest-config.js +0 -8
  130. package/dist/rag/ingest-config.js.map +0 -1
  131. package/dist/rag/ingest.d.ts +0 -3
  132. package/dist/rag/ingest.d.ts.map +0 -1
  133. package/dist/rag/ingest.js.map +0 -1
  134. package/dist/rag/search.d.ts +0 -3
  135. package/dist/rag/search.d.ts.map +0 -1
  136. package/dist/rag/search.js.map +0 -1
  137. package/dist/reset-articles.d.ts +0 -3
  138. package/dist/reset-articles.d.ts.map +0 -1
  139. package/dist/reset-articles.js.map +0 -1
  140. package/dist/reset-books.d.ts +0 -3
  141. package/dist/reset-books.d.ts.map +0 -1
  142. package/dist/reset-books.js.map +0 -1
  143. package/dist/reset-images.d.ts +0 -3
  144. package/dist/reset-images.d.ts.map +0 -1
  145. package/dist/reset-images.js.map +0 -1
  146. package/dist/reset-notes.d.ts +0 -3
  147. package/dist/reset-notes.d.ts.map +0 -1
  148. package/dist/reset-notes.js.map +0 -1
  149. package/dist/revert-articles.d.ts +0 -3
  150. package/dist/revert-articles.d.ts.map +0 -1
  151. package/dist/revert-articles.js.map +0 -1
  152. package/dist/revert-books.d.ts +0 -3
  153. package/dist/revert-books.d.ts.map +0 -1
  154. package/dist/revert-books.js.map +0 -1
  155. package/dist/revert-images.d.ts +0 -3
  156. package/dist/revert-images.d.ts.map +0 -1
  157. package/dist/revert-images.js.map +0 -1
  158. package/dist/revert-notes.d.ts +0 -3
  159. package/dist/revert-notes.d.ts.map +0 -1
  160. package/dist/revert-notes.js.map +0 -1
  161. package/dist/s-content-format-runner.d.ts +0 -10
  162. package/dist/s-content-format-runner.d.ts.map +0 -1
  163. package/dist/s-content-format-runner.js +0 -76
  164. package/dist/s-content-format-runner.js.map +0 -1
  165. package/dist/s-content-format.d.ts +0 -3
  166. package/dist/s-content-format.d.ts.map +0 -1
  167. package/dist/s-content-format.js.map +0 -1
  168. package/dist/s-content-format.test.d.ts +0 -2
  169. package/dist/s-content-format.test.d.ts.map +0 -1
  170. package/dist/s-content-format.test.js +0 -99
  171. package/dist/s-content-format.test.js.map +0 -1
  172. package/dist/update-json-articles.d.ts +0 -3
  173. package/dist/update-json-articles.d.ts.map +0 -1
  174. package/dist/update-json-articles.js.map +0 -1
  175. package/dist/update-raw-articles.d.ts +0 -3
  176. package/dist/update-raw-articles.d.ts.map +0 -1
  177. package/dist/update-raw-articles.js.map +0 -1
  178. package/dist/validate-json-articles.d.ts +0 -3
  179. package/dist/validate-json-articles.d.ts.map +0 -1
  180. package/dist/validate-json-articles.js.map +0 -1
@@ -1,117 +1,120 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
3
+
4
+ // src/find-duplicate-json-articles.ts
2
5
  import fs from "node:fs";
3
6
  import { join } from "node:path";
4
7
  function getAllJsonFiles(directory) {
5
- return fs
6
- .readdirSync(directory)
7
- .filter((file) => file.endsWith(".json") && file !== ".DS_Store");
8
+ return fs.readdirSync(directory).filter((file) => file.endsWith(".json") && file !== ".DS_Store");
8
9
  }
9
10
  function readArticleFile(filePath) {
10
- const fileContents = fs.readFileSync(filePath, "utf8");
11
- return JSON.parse(fileContents);
11
+ const fileContents = fs.readFileSync(filePath, "utf8");
12
+ return JSON.parse(fileContents);
12
13
  }
13
14
  function findDuplicateUrls() {
14
- const articleDirectory = join(process.cwd(), "json", "article");
15
- const jsonFiles = getAllJsonFiles(articleDirectory);
16
- console.log(`検索対象のJSONファイル数: ${jsonFiles.length}`);
17
- console.log(`ファイル一覧: ${jsonFiles.join(", ")}\n`);
18
- // URLの出現回数を追跡するマップ
19
- const urlMap = new Map();
20
- let totalUrls = 0;
21
- // 各JSONファイルを処理
22
- for (const fileName of jsonFiles) {
23
- const filePath = join(articleDirectory, fileName);
24
- try {
25
- const articleFile = readArticleFile(filePath);
26
- const category = articleFile.heading;
27
- console.log(`処理中: ${fileName} (カテゴリ: ${category}, 記事数: ${articleFile.body.length})`);
28
- // 各記事のURLを処理
29
- for (const item of articleFile.body) {
30
- totalUrls++;
31
- const occurrence = {
32
- url: item.url,
33
- title: item.title,
34
- fileName,
35
- category,
36
- };
37
- if (urlMap.has(item.url)) {
38
- urlMap.get(item.url)?.push(occurrence);
39
- }
40
- else {
41
- urlMap.set(item.url, [occurrence]);
42
- }
43
- }
44
- }
45
- catch (error) {
46
- console.error(`エラー: ${fileName} の読み込みに失敗しました:`, error);
15
+ const articleDirectory = join(process.cwd(), "json", "article");
16
+ const jsonFiles = getAllJsonFiles(articleDirectory);
17
+ console.log(`\u691C\u7D22\u5BFE\u8C61\u306EJSON\u30D5\u30A1\u30A4\u30EB\u6570: ${jsonFiles.length}`);
18
+ console.log(`\u30D5\u30A1\u30A4\u30EB\u4E00\u89A7: ${jsonFiles.join(", ")}
19
+ `);
20
+ const urlMap = /* @__PURE__ */ new Map();
21
+ let totalUrls = 0;
22
+ for (const fileName of jsonFiles) {
23
+ const filePath = join(articleDirectory, fileName);
24
+ try {
25
+ const articleFile = readArticleFile(filePath);
26
+ const category = articleFile.heading;
27
+ console.log(
28
+ `\u51E6\u7406\u4E2D: ${fileName} (\u30AB\u30C6\u30B4\u30EA: ${category}, \u8A18\u4E8B\u6570: ${articleFile.body.length})`
29
+ );
30
+ for (const item of articleFile.body) {
31
+ totalUrls++;
32
+ const occurrence = {
33
+ url: item.url,
34
+ title: item.title,
35
+ fileName,
36
+ category
37
+ };
38
+ if (urlMap.has(item.url)) {
39
+ urlMap.get(item.url)?.push(occurrence);
40
+ } else {
41
+ urlMap.set(item.url, [occurrence]);
47
42
  }
43
+ }
44
+ } catch (error) {
45
+ console.error(`\u30A8\u30E9\u30FC: ${fileName} \u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F:`, error);
48
46
  }
49
- console.log(`\n合計URL数: ${totalUrls}`);
50
- console.log(`ユニークURL数: ${urlMap.size}`);
51
- // 重複URLを特定
52
- const duplicates = [];
53
- for (const [url, occurrences] of urlMap.entries()) {
54
- if (occurrences.length > 1) {
55
- duplicates.push({
56
- url,
57
- occurrences,
58
- });
59
- }
47
+ }
48
+ console.log(`
49
+ \u5408\u8A08URL\u6570: ${totalUrls}`);
50
+ console.log(`\u30E6\u30CB\u30FC\u30AFURL\u6570: ${urlMap.size}`);
51
+ const duplicates = [];
52
+ for (const [url, occurrences] of urlMap.entries()) {
53
+ if (occurrences.length > 1) {
54
+ duplicates.push({
55
+ url,
56
+ occurrences
57
+ });
60
58
  }
61
- return duplicates;
59
+ }
60
+ return duplicates;
62
61
  }
63
62
  function displayResults(duplicates) {
64
- console.log("\n=== 重複URL検出結果 ===");
65
- console.log(`重複URL数: ${duplicates.length}\n`);
66
- if (duplicates.length === 0) {
67
- console.log("重複URLは見つかりませんでした!");
68
- return;
69
- }
70
- // 重複数でソート(多い順)
71
- duplicates.sort((a, b) => b.occurrences.length - a.occurrences.length);
72
- duplicates.forEach((duplicate, index) => {
73
- console.log(`${index + 1}. URL: ${duplicate.url}`);
74
- console.log(` 重複数: ${duplicate.occurrences.length}回`);
75
- duplicate.occurrences.forEach((occurrence, occIndex) => {
76
- console.log(` ${occIndex + 1}) [${occurrence.category}] ${occurrence.fileName}`);
77
- console.log(` タイトル: ${occurrence.title}`);
78
- });
79
- console.log(""); // 空行
80
- });
81
- // サマリー統計
82
- const totalDuplicateOccurrences = duplicates.reduce((sum, dup) => sum + dup.occurrences.length, 0);
83
- const wastedEntries = totalDuplicateOccurrences - duplicates.length;
84
- console.log("=== サマリー ===");
85
- console.log(`重複により無駄になっているエントリ数: ${wastedEntries}`);
86
- console.log(`最も多く重複しているURL: ${duplicates[0]?.occurrences.length || 0}回重複`);
87
- // カテゴリ別の重複統計
88
- const categoryStats = new Map();
89
- duplicates.forEach((dup) => {
90
- dup.occurrences.forEach((occ) => {
91
- categoryStats.set(occ.category, (categoryStats.get(occ.category) || 0) + 1);
92
- });
63
+ console.log("\n=== \u91CD\u8907URL\u691C\u51FA\u7D50\u679C ===");
64
+ console.log(`\u91CD\u8907URL\u6570: ${duplicates.length}
65
+ `);
66
+ if (duplicates.length === 0) {
67
+ console.log("\u91CD\u8907URL\u306F\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF01");
68
+ return;
69
+ }
70
+ duplicates.sort((a, b) => b.occurrences.length - a.occurrences.length);
71
+ duplicates.forEach((duplicate, index) => {
72
+ console.log(`${index + 1}. URL: ${duplicate.url}`);
73
+ console.log(` \u91CD\u8907\u6570: ${duplicate.occurrences.length}\u56DE`);
74
+ duplicate.occurrences.forEach((occurrence, occIndex) => {
75
+ console.log(
76
+ ` ${occIndex + 1}) [${occurrence.category}] ${occurrence.fileName}`
77
+ );
78
+ console.log(` \u30BF\u30A4\u30C8\u30EB: ${occurrence.title}`);
93
79
  });
94
- console.log("\nカテゴリ別重複統計:");
95
- Array.from(categoryStats.entries())
96
- .toSorted((a, b) => b[1] - a[1])
97
- .forEach(([category, count]) => {
98
- console.log(` ${category}: ${count}個の重複エントリ`);
80
+ console.log("");
81
+ });
82
+ const totalDuplicateOccurrences = duplicates.reduce(
83
+ (sum, dup) => sum + dup.occurrences.length,
84
+ 0
85
+ );
86
+ const wastedEntries = totalDuplicateOccurrences - duplicates.length;
87
+ console.log("=== \u30B5\u30DE\u30EA\u30FC ===");
88
+ console.log(`\u91CD\u8907\u306B\u3088\u308A\u7121\u99C4\u306B\u306A\u3063\u3066\u3044\u308B\u30A8\u30F3\u30C8\u30EA\u6570: ${wastedEntries}`);
89
+ console.log(
90
+ `\u6700\u3082\u591A\u304F\u91CD\u8907\u3057\u3066\u3044\u308BURL: ${duplicates[0]?.occurrences.length || 0}\u56DE\u91CD\u8907`
91
+ );
92
+ const categoryStats = /* @__PURE__ */ new Map();
93
+ duplicates.forEach((dup) => {
94
+ dup.occurrences.forEach((occ) => {
95
+ categoryStats.set(
96
+ occ.category,
97
+ (categoryStats.get(occ.category) || 0) + 1
98
+ );
99
99
  });
100
+ });
101
+ console.log("\n\u30AB\u30C6\u30B4\u30EA\u5225\u91CD\u8907\u7D71\u8A08:");
102
+ Array.from(categoryStats.entries()).toSorted((a, b) => b[1] - a[1]).forEach(([category, count]) => {
103
+ console.log(` ${category}: ${count}\u500B\u306E\u91CD\u8907\u30A8\u30F3\u30C8\u30EA`);
104
+ });
100
105
  }
101
106
  async function main() {
102
- try {
103
- console.log("json/articleディレクトリ内のURL重複を検索中...\n");
104
- const duplicates = findDuplicateUrls();
105
- displayResults(duplicates);
106
- console.log("\n検索完了");
107
- }
108
- catch (error) {
109
- console.error("❌ エラーが発生しました:", error);
110
- process.exit(1);
111
- }
107
+ try {
108
+ console.log("json/article\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306EURL\u91CD\u8907\u3092\u691C\u7D22\u4E2D...\n");
109
+ const duplicates = findDuplicateUrls();
110
+ displayResults(duplicates);
111
+ console.log("\n\u691C\u7D22\u5B8C\u4E86");
112
+ } catch (error) {
113
+ console.error("\u274C \u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:", error);
114
+ process.exit(1);
115
+ }
112
116
  }
113
117
  main().catch((error) => {
114
- console.error(error);
115
- process.exit(1);
118
+ console.error(error);
119
+ process.exit(1);
116
120
  });
117
- //# sourceMappingURL=find-duplicate-json-articles.js.map
@@ -1,121 +1,133 @@
1
1
  #!/usr/bin/env node
2
- import { parseMarkdownFrontmatter } from "@s-hirano-ist/s-search/frontmatter";
2
+ import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
3
+ import {
4
+ parseMarkdownFrontmatter
5
+ } from "./chunk-HDYQV2Y2.js";
6
+ import {
7
+ globPaths
8
+ } from "./chunk-AJMTRCPJ.js";
9
+ import "./chunk-JZOR5GA2.js";
10
+
11
+ // src/fix-book-frontmatter.ts
3
12
  import { dump } from "js-yaml";
4
13
  import { readFile, writeFile } from "node:fs/promises";
5
14
  import { basename, join } from "node:path";
6
- import { globPaths } from "./lib/glob-paths.js";
7
- const REQUIRED_KEYS = [
8
- "heading",
9
- "title",
10
- "draft",
11
- "rating",
12
- "tags",
13
- "googleSubtitle",
14
- "googleAuthors",
15
- "googleDescription",
16
- "googleImgSrc",
17
- "googleHref",
15
+ var REQUIRED_KEYS = [
16
+ "heading",
17
+ "title",
18
+ "draft",
19
+ "rating",
20
+ "tags",
21
+ "googleSubtitle",
22
+ "googleAuthors",
23
+ "googleDescription",
24
+ "googleImgSrc",
25
+ "googleHref"
18
26
  ];
19
- const LEGACY_KEYS = ["googleTitle"];
27
+ var LEGACY_KEYS = ["googleTitle"];
20
28
  function dumpFrontmatter(data) {
21
- return dump(data, {
22
- lineWidth: -1,
23
- forceQuotes: false,
24
- noRefs: true,
25
- });
29
+ return dump(data, {
30
+ lineWidth: -1,
31
+ forceQuotes: false,
32
+ noRefs: true
33
+ });
26
34
  }
27
35
  function extractTitleFromContent(content) {
28
- const match = /^# (.+)$/mu.exec(content);
29
- return match ? match[1].trim() : null;
36
+ const match = /^# (.+)$/mu.exec(content);
37
+ return match ? match[1].trim() : null;
30
38
  }
31
39
  function buildFrontmatter(existing, isbn, title) {
32
- return {
33
- heading: existing.heading ?? isbn,
34
- title,
35
- draft: existing.draft ?? false,
36
- rating: "rating" in existing ? existing.rating : null,
37
- tags: Array.isArray(existing.tags) ? existing.tags : [],
38
- googleSubtitle: "googleSubtitle" in existing ? existing.googleSubtitle : null,
39
- googleAuthors: Array.isArray(existing.googleAuthors)
40
- ? existing.googleAuthors
41
- : [],
42
- googleDescription: "googleDescription" in existing ? existing.googleDescription : null,
43
- googleImgSrc: "googleImgSrc" in existing ? existing.googleImgSrc : null,
44
- googleHref: "googleHref" in existing ? existing.googleHref : null,
45
- };
40
+ return {
41
+ heading: existing.heading ?? isbn,
42
+ title,
43
+ draft: existing.draft ?? false,
44
+ rating: "rating" in existing ? existing.rating : null,
45
+ tags: Array.isArray(existing.tags) ? existing.tags : [],
46
+ googleSubtitle: "googleSubtitle" in existing ? existing.googleSubtitle : null,
47
+ googleAuthors: Array.isArray(existing.googleAuthors) ? existing.googleAuthors : [],
48
+ googleDescription: "googleDescription" in existing ? existing.googleDescription : null,
49
+ googleImgSrc: "googleImgSrc" in existing ? existing.googleImgSrc : null,
50
+ googleHref: "googleHref" in existing ? existing.googleHref : null
51
+ };
46
52
  }
47
53
  function resolveTitle(existing, content, fileName) {
48
- const title = typeof existing.title === "string" ? existing.title : "";
49
- if (title) {
50
- return title;
51
- }
52
- const h1 = extractTitleFromContent(content);
53
- if (!h1) {
54
- console.error(`⚠️ ${fileName}: title も H1 も見つかりません。スキップします。`);
55
- return null;
56
- }
57
- return h1;
54
+ const title = typeof existing.title === "string" ? existing.title : "";
55
+ if (title) {
56
+ return title;
57
+ }
58
+ const h1 = extractTitleFromContent(content);
59
+ if (!h1) {
60
+ console.error(
61
+ `\u26A0\uFE0F ${fileName}: title \u3082 H1 \u3082\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3059\u3002`
62
+ );
63
+ return null;
64
+ }
65
+ return h1;
58
66
  }
59
67
  async function processFile(filePath, dryRun) {
60
- const fileName = basename(filePath);
61
- const isbn = basename(filePath, ".md");
62
- try {
63
- const raw = await readFile(filePath, "utf8");
64
- const parsed = parseMarkdownFrontmatter(raw);
65
- const existing = parsed.data;
66
- const hasAllKeys = REQUIRED_KEYS.every((k) => Object.hasOwn(existing, k));
67
- const hasLegacyKeys = LEGACY_KEYS.some((k) => Object.hasOwn(existing, k));
68
- if (hasAllKeys && !hasLegacyKeys) {
69
- return "skipped";
70
- }
71
- // title: frontmatter.title を優先、無ければ本文 H1 にフォールバック
72
- const title = resolveTitle(existing, parsed.content, fileName);
73
- if (title === null) {
74
- return "error";
75
- }
76
- const next = buildFrontmatter(existing, isbn, title);
77
- const body = parsed.content.replace(/^\n+/u, "");
78
- const newContent = `---\n${dumpFrontmatter(next)}---\n\n${body}`;
79
- if (dryRun) {
80
- console.log(`🔍 [dry-run] 修正予定: ${fileName}`);
81
- }
82
- else {
83
- await writeFile(filePath, newContent, "utf8");
84
- console.log(`✅ 修正完了: ${fileName} (${title})`);
85
- }
86
- return "fixed";
68
+ const fileName = basename(filePath);
69
+ const isbn = basename(filePath, ".md");
70
+ try {
71
+ const raw = await readFile(filePath, "utf8");
72
+ const parsed = parseMarkdownFrontmatter(raw);
73
+ const existing = parsed.data;
74
+ const hasAllKeys = REQUIRED_KEYS.every((k) => Object.hasOwn(existing, k));
75
+ const hasLegacyKeys = LEGACY_KEYS.some((k) => Object.hasOwn(existing, k));
76
+ if (hasAllKeys && !hasLegacyKeys) {
77
+ return "skipped";
78
+ }
79
+ const title = resolveTitle(existing, parsed.content, fileName);
80
+ if (title === null) {
81
+ return "error";
87
82
  }
88
- catch (error) {
89
- console.error(`❌ ${fileName}: ${String(error)}`);
90
- return "error";
83
+ const next = buildFrontmatter(existing, isbn, title);
84
+ const body = parsed.content.replace(/^\n+/u, "");
85
+ const newContent = `---
86
+ ${dumpFrontmatter(next)}---
87
+
88
+ ${body}`;
89
+ if (dryRun) {
90
+ console.log(`\u{1F50D} [dry-run] \u4FEE\u6B63\u4E88\u5B9A: ${fileName}`);
91
+ } else {
92
+ await writeFile(filePath, newContent, "utf8");
93
+ console.log(`\u2705 \u4FEE\u6B63\u5B8C\u4E86: ${fileName} (${title})`);
91
94
  }
95
+ return "fixed";
96
+ } catch (error) {
97
+ console.error(`\u274C ${fileName}: ${String(error)}`);
98
+ return "error";
99
+ }
92
100
  }
93
101
  async function main() {
94
- const dryRun = process.argv.includes("--dry-run");
95
- const contentsPath = process.env.S_CONTENTS_PATH ?? process.cwd();
96
- const bookDir = join(contentsPath, "markdown", "book");
97
- console.log(`markdown/book ディレクトリのfrontmatterを検証中...${dryRun ? " (dry-run)" : ""}\n`);
98
- const files = await globPaths(`${bookDir}/*.md`);
99
- console.log(`検出ファイル数: ${files.length}\n`);
100
- let fixedCount = 0;
101
- let skippedCount = 0;
102
- let errorCount = 0;
103
- for (const filePath of files) {
104
- const result = await processFile(filePath, dryRun);
105
- if (result === "fixed") {
106
- fixedCount++;
107
- }
108
- else if (result === "skipped") {
109
- skippedCount++;
110
- }
111
- else {
112
- errorCount++;
113
- }
102
+ const dryRun = process.argv.includes("--dry-run");
103
+ const contentsPath = process.env.S_CONTENTS_PATH ?? process.cwd();
104
+ const bookDir = join(contentsPath, "markdown", "book");
105
+ console.log(
106
+ `markdown/book \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Efrontmatter\u3092\u691C\u8A3C\u4E2D...${dryRun ? " (dry-run)" : ""}
107
+ `
108
+ );
109
+ const files = await globPaths(`${bookDir}/*.md`);
110
+ console.log(`\u691C\u51FA\u30D5\u30A1\u30A4\u30EB\u6570: ${files.length}
111
+ `);
112
+ let fixedCount = 0;
113
+ let skippedCount = 0;
114
+ let errorCount = 0;
115
+ for (const filePath of files) {
116
+ const result = await processFile(filePath, dryRun);
117
+ if (result === "fixed") {
118
+ fixedCount++;
119
+ } else if (result === "skipped") {
120
+ skippedCount++;
121
+ } else {
122
+ errorCount++;
114
123
  }
115
- console.log(`\n📊 結果: 修正 ${fixedCount} 件, スキップ ${skippedCount} 件, エラー ${errorCount} 件${dryRun ? " (dry-run)" : ""}`);
124
+ }
125
+ console.log(
126
+ `
127
+ \u{1F4CA} \u7D50\u679C: \u4FEE\u6B63 ${fixedCount} \u4EF6, \u30B9\u30AD\u30C3\u30D7 ${skippedCount} \u4EF6, \u30A8\u30E9\u30FC ${errorCount} \u4EF6${dryRun ? " (dry-run)" : ""}`
128
+ );
116
129
  }
117
130
  main().catch((error) => {
118
- console.error("❌ エラーが発生しました:", error);
119
- process.exit(1);
131
+ console.error("\u274C \u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:", error);
132
+ process.exit(1);
120
133
  });
121
- //# sourceMappingURL=fix-book-frontmatter.js.map
@@ -1,80 +1,96 @@
1
1
  #!/usr/bin/env node
2
- import { convertToWebp as convertImageToWebp } from "@s-hirano-ist/s-image-processing/node";
2
+ import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
3
+ import {
4
+ convertToWebp
5
+ } from "./chunk-KKZP7ZF3.js";
6
+ import {
7
+ globPaths
8
+ } from "./chunk-AJMTRCPJ.js";
9
+ import "./chunk-JZOR5GA2.js";
10
+
11
+ // src/fix-image-formats.ts
3
12
  import { readFile, stat, unlink, writeFile } from "node:fs/promises";
4
13
  import { basename, extname, join } from "node:path";
5
- import { globPaths } from "./lib/glob-paths.js";
6
- const WEBP_QUALITY = 80;
14
+ var WEBP_QUALITY = 80;
7
15
  function isConvertibleImage(filePath) {
8
- const ext = extname(filePath).toLowerCase();
9
- return [".jpg", ".jpeg", ".png"].includes(ext);
16
+ const ext = extname(filePath).toLowerCase();
17
+ return [".jpg", ".jpeg", ".png"].includes(ext);
10
18
  }
11
19
  function getWebpOutputPath(filePath) {
12
- const ext = extname(filePath);
13
- return `${filePath.slice(0, -ext.length)}.webp`;
20
+ const ext = extname(filePath);
21
+ return `${filePath.slice(0, -ext.length)}.webp`;
14
22
  }
15
- async function convertToWebp(inputPath, outputPath) {
16
- const inputBytes = await readFile(inputPath);
17
- const outputBytes = await convertImageToWebp(inputBytes, {
18
- quality: WEBP_QUALITY,
19
- });
20
- await writeFile(outputPath, outputBytes);
23
+ async function convertToWebp2(inputPath, outputPath) {
24
+ const inputBytes = await readFile(inputPath);
25
+ const outputBytes = await convertToWebp(inputBytes, {
26
+ quality: WEBP_QUALITY
27
+ });
28
+ await writeFile(outputPath, outputBytes);
21
29
  }
22
30
  async function processDirectory(directory, label, dryRun) {
23
- const files = await globPaths(`${directory}/*`);
24
- const convertible = files.filter((filePath) => isConvertibleImage(filePath));
25
- console.log(`\n📁 ${label}: ${convertible.length} 件の変換対象を検出(全 ${files.length} ファイル中)`);
26
- let converted = 0;
27
- let skipped = 0;
28
- let errors = 0;
29
- for (const filePath of convertible) {
30
- const fileName = basename(filePath);
31
- const outputPath = getWebpOutputPath(filePath);
32
- try {
33
- // 出力先が既に存在する場合はスキップ
34
- try {
35
- await stat(outputPath);
36
- console.log(`⏭️ スキップ(WebP既存): ${fileName}`);
37
- skipped++;
38
- continue;
39
- }
40
- catch {
41
- // ファイルが存在しない場合は変換続行
42
- }
43
- if (dryRun) {
44
- console.log(`🔍 [dry-run] 変換予定: ${fileName} → ${basename(outputPath)}`);
45
- converted++;
46
- continue;
47
- }
48
- await convertToWebp(filePath, outputPath);
49
- // 出力ファイルの存在とサイズを確認
50
- const outputStat = await stat(outputPath);
51
- if (outputStat.size === 0) {
52
- throw new Error("変換後のファイルサイズが0です");
53
- }
54
- await unlink(filePath);
55
- console.log(`✅ 変換完了: ${fileName} → ${basename(outputPath)}`);
56
- converted++;
57
- }
58
- catch (error) {
59
- console.error(`❌ ${fileName}: ${String(error)}`);
60
- errors++;
61
- }
31
+ const files = await globPaths(`${directory}/*`);
32
+ const convertible = files.filter((filePath) => isConvertibleImage(filePath));
33
+ console.log(
34
+ `
35
+ \u{1F4C1} ${label}: ${convertible.length} \u4EF6\u306E\u5909\u63DB\u5BFE\u8C61\u3092\u691C\u51FA\uFF08\u5168 ${files.length} \u30D5\u30A1\u30A4\u30EB\u4E2D\uFF09`
36
+ );
37
+ let converted = 0;
38
+ let skipped = 0;
39
+ let errors = 0;
40
+ for (const filePath of convertible) {
41
+ const fileName = basename(filePath);
42
+ const outputPath = getWebpOutputPath(filePath);
43
+ try {
44
+ try {
45
+ await stat(outputPath);
46
+ console.log(`\u23ED\uFE0F \u30B9\u30AD\u30C3\u30D7\uFF08WebP\u65E2\u5B58\uFF09: ${fileName}`);
47
+ skipped++;
48
+ continue;
49
+ } catch {
50
+ }
51
+ if (dryRun) {
52
+ console.log(
53
+ `\u{1F50D} [dry-run] \u5909\u63DB\u4E88\u5B9A: ${fileName} \u2192 ${basename(outputPath)}`
54
+ );
55
+ converted++;
56
+ continue;
57
+ }
58
+ await convertToWebp2(filePath, outputPath);
59
+ const outputStat = await stat(outputPath);
60
+ if (outputStat.size === 0) {
61
+ throw new Error("\u5909\u63DB\u5F8C\u306E\u30D5\u30A1\u30A4\u30EB\u30B5\u30A4\u30BA\u304C0\u3067\u3059");
62
+ }
63
+ await unlink(filePath);
64
+ console.log(`\u2705 \u5909\u63DB\u5B8C\u4E86: ${fileName} \u2192 ${basename(outputPath)}`);
65
+ converted++;
66
+ } catch (error) {
67
+ console.error(`\u274C ${fileName}: ${String(error)}`);
68
+ errors++;
62
69
  }
63
- return { converted, skipped, errors };
70
+ }
71
+ return { converted, skipped, errors };
64
72
  }
65
73
  async function main() {
66
- const dryRun = process.argv.includes("--dry-run");
67
- const contentsPath = process.env.S_CONTENTS_PATH ?? process.cwd();
68
- console.log(`書籍画像をWebPフォーマットに変換中...${dryRun ? " (dry-run)" : ""}`);
69
- const bookDir = join(contentsPath, "image", "book");
70
- const { converted, skipped, errors } = await processDirectory(bookDir, "image/book", dryRun);
71
- console.log(`\n📊 合計: 変換 ${converted} 件, スキップ ${skipped} 件, エラー ${errors} 件${dryRun ? " (dry-run)" : ""}`);
72
- if (errors > 0) {
73
- process.exit(1);
74
- }
74
+ const dryRun = process.argv.includes("--dry-run");
75
+ const contentsPath = process.env.S_CONTENTS_PATH ?? process.cwd();
76
+ console.log(
77
+ `\u66F8\u7C4D\u753B\u50CF\u3092WebP\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u306B\u5909\u63DB\u4E2D...${dryRun ? " (dry-run)" : ""}`
78
+ );
79
+ const bookDir = join(contentsPath, "image", "book");
80
+ const { converted, skipped, errors } = await processDirectory(
81
+ bookDir,
82
+ "image/book",
83
+ dryRun
84
+ );
85
+ console.log(
86
+ `
87
+ \u{1F4CA} \u5408\u8A08: \u5909\u63DB ${converted} \u4EF6, \u30B9\u30AD\u30C3\u30D7 ${skipped} \u4EF6, \u30A8\u30E9\u30FC ${errors} \u4EF6${dryRun ? " (dry-run)" : ""}`
88
+ );
89
+ if (errors > 0) {
90
+ process.exit(1);
91
+ }
75
92
  }
76
93
  main().catch((error) => {
77
- console.error("❌ エラーが発生しました:", error);
78
- process.exit(1);
94
+ console.error("\u274C \u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:", error);
95
+ process.exit(1);
79
96
  });
80
- //# sourceMappingURL=fix-image-formats.js.map