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

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-6ADTNHCK.js +85 -0
  3. package/dist/chunk-7PVU2Z32.js +71 -0
  4. package/dist/chunk-AJMTRCPJ.js +15 -0
  5. package/dist/chunk-AUD3PD6K.js +85 -0
  6. package/dist/chunk-F4J6JBR4.js +115 -0
  7. package/dist/chunk-HDYQV2Y2.js +58 -0
  8. package/dist/chunk-J4VLH4VA.js +267 -0
  9. package/dist/chunk-JZOR5GA2.js +42 -0
  10. package/dist/chunk-KKZP7ZF3.js +77 -0
  11. package/dist/chunk-M275YZQP.js +7723 -0
  12. package/dist/chunk-Q6QUV5VR.js +102 -0
  13. package/dist/chunk-TK456CR2.js +85 -0
  14. package/dist/chunk-UXGLXHQ6.js +40 -0
  15. package/dist/chunk-XG6LAGZO.js +590 -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,114 +1,118 @@
1
1
  #!/usr/bin/env node
2
- import { createPushoverService } from "@s-hirano-ist/s-notification";
2
+ import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
3
+ import {
4
+ decodeHtml
5
+ } from "./chunk-UXGLXHQ6.js";
6
+ import {
7
+ createPushoverService
8
+ } from "./chunk-7PVU2Z32.js";
9
+ import "./chunk-JZOR5GA2.js";
10
+
11
+ // src/update-json-articles.ts
3
12
  import * as cheerio from "cheerio";
4
13
  import { readdirSync, readFileSync, writeFileSync } from "node:fs";
5
14
  import { join } from "node:path";
6
15
  import { setTimeout } from "node:timers/promises";
7
- import { decodeHtml } from "./lib/html-charset.js";
8
16
  async function getOgTags(url) {
9
- try {
10
- console.log(`Fetching OG tags for: ${url}`);
11
- const response = await fetch(url, {
12
- headers: {
13
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
14
- },
15
- });
16
- if (!response.ok) {
17
- throw new Error(`HTTP error! status: ${response.status}`);
18
- }
19
- const buffer = Buffer.from(await response.arrayBuffer());
20
- const html = decodeHtml(response.headers, buffer);
21
- const $ = cheerio.load(html);
22
- const ogTags = {};
23
- $("meta[property]").each((_, el) => {
24
- const property = $(el).attr("property")?.trim();
25
- const content = $(el).attr("content");
26
- if (property && content) {
27
- ogTags[property] = content;
28
- }
29
- });
30
- const ogImageUrl = ogTags["og:image"];
31
- const ogTitle = ogTags["og:title"];
32
- const ogDescription = ogTags["og:description"];
33
- return { ogImageUrl, ogTitle, ogDescription };
34
- }
35
- catch (error) {
36
- console.error(`Error fetching OG tags for ${url}:`, error);
37
- return {};
17
+ try {
18
+ console.log(`Fetching OG tags for: ${url}`);
19
+ const response = await fetch(url, {
20
+ headers: {
21
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
22
+ }
23
+ });
24
+ if (!response.ok) {
25
+ throw new Error(`HTTP error! status: ${response.status}`);
38
26
  }
27
+ const buffer = Buffer.from(await response.arrayBuffer());
28
+ const html = decodeHtml(response.headers, buffer);
29
+ const $ = cheerio.load(html);
30
+ const ogTags = {};
31
+ $("meta[property]").each((_, el) => {
32
+ const property = $(el).attr("property")?.trim();
33
+ const content = $(el).attr("content");
34
+ if (property && content) {
35
+ ogTags[property] = content;
36
+ }
37
+ });
38
+ const ogImageUrl = ogTags["og:image"];
39
+ const ogTitle = ogTags["og:title"];
40
+ const ogDescription = ogTags["og:description"];
41
+ return { ogImageUrl, ogTitle, ogDescription };
42
+ } catch (error) {
43
+ console.error(`Error fetching OG tags for ${url}:`, error);
44
+ return {};
45
+ }
39
46
  }
40
47
  async function processArticleFile(filePath) {
41
- try {
42
- const jsonContent = readFileSync(filePath, "utf-8");
43
- const articleData = JSON.parse(jsonContent);
44
- console.log(`Processing ${filePath}...`);
45
- for (const item of articleData.body) {
46
- // Skip if OG tags already exist
47
- if (item.ogImageUrl || item.ogTitle || item.ogDescription || item.skip) {
48
- continue;
49
- }
50
- const ogTags = await getOgTags(item.url);
51
- // Only add properties if they have values
52
- if (ogTags.ogImageUrl)
53
- item.ogImageUrl = ogTags.ogImageUrl;
54
- else
55
- console.warn(`No OG image found for ${item.url}`);
56
- if (ogTags.ogTitle)
57
- item.ogTitle = ogTags.ogTitle;
58
- else
59
- console.warn(`No OG title found for ${item.url}`);
60
- if (ogTags.ogDescription)
61
- item.ogDescription = ogTags.ogDescription;
62
- else
63
- console.warn(`No OG description found for ${item.url}`);
64
- // Add a small delay to avoid overwhelming servers
65
- await setTimeout(1000);
66
- }
67
- // Write back to file
68
- writeFileSync(filePath, `${JSON.stringify(articleData, null, "\t")}\n`, "utf-8");
69
- console.log(`Completed processing ${filePath}`);
70
- }
71
- catch (error) {
72
- console.error(`Error processing ${filePath}:`, error);
48
+ try {
49
+ const jsonContent = readFileSync(filePath, "utf-8");
50
+ const articleData = JSON.parse(jsonContent);
51
+ console.log(`Processing ${filePath}...`);
52
+ for (const item of articleData.body) {
53
+ if (item.ogImageUrl || item.ogTitle || item.ogDescription || item.skip) {
54
+ continue;
55
+ }
56
+ const ogTags = await getOgTags(item.url);
57
+ if (ogTags.ogImageUrl) item.ogImageUrl = ogTags.ogImageUrl;
58
+ else console.warn(`No OG image found for ${item.url}`);
59
+ if (ogTags.ogTitle) item.ogTitle = ogTags.ogTitle;
60
+ else console.warn(`No OG title found for ${item.url}`);
61
+ if (ogTags.ogDescription) item.ogDescription = ogTags.ogDescription;
62
+ else console.warn(`No OG description found for ${item.url}`);
63
+ await setTimeout(1e3);
73
64
  }
65
+ writeFileSync(
66
+ filePath,
67
+ `${JSON.stringify(articleData, null, " ")}
68
+ `,
69
+ "utf-8"
70
+ );
71
+ console.log(`Completed processing ${filePath}`);
72
+ } catch (error) {
73
+ console.error(`Error processing ${filePath}:`, error);
74
+ }
74
75
  }
75
76
  async function main() {
76
- const env = {
77
- PUSHOVER_URL: process.env.PUSHOVER_URL,
78
- PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
79
- PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
80
- };
81
- if (Object.values(env).some((v) => !v)) {
82
- throw new Error("Required environment variables are not set.");
77
+ const env = {
78
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
79
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
80
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN
81
+ };
82
+ if (Object.values(env).some((v) => !v)) {
83
+ throw new Error("Required environment variables are not set.");
84
+ }
85
+ const notificationService = createPushoverService({
86
+ url: env.PUSHOVER_URL ?? "",
87
+ userKey: env.PUSHOVER_USER_KEY ?? "",
88
+ appToken: env.PUSHOVER_APP_TOKEN ?? ""
89
+ });
90
+ const articleDir = join(process.cwd(), "json", "article");
91
+ try {
92
+ const files = readdirSync(articleDir).filter(
93
+ (file) => file.endsWith(".json")
94
+ );
95
+ console.log(`Found ${files.length} JSON files to process`);
96
+ for (const file of files) {
97
+ const filePath = join(articleDir, file);
98
+ await processArticleFile(filePath);
83
99
  }
84
- const notificationService = createPushoverService({
85
- url: env.PUSHOVER_URL ?? "",
86
- userKey: env.PUSHOVER_USER_KEY ?? "",
87
- appToken: env.PUSHOVER_APP_TOKEN ?? "",
100
+ console.log("All files processed successfully!");
101
+ await notificationService.notifyInfo("update-json-articles completed", {
102
+ caller: "update-json-articles"
88
103
  });
89
- const articleDir = join(process.cwd(), "json", "article");
90
- try {
91
- const files = readdirSync(articleDir).filter((file) => file.endsWith(".json"));
92
- console.log(`Found ${files.length} JSON files to process`);
93
- for (const file of files) {
94
- const filePath = join(articleDir, file);
95
- await processArticleFile(filePath);
96
- }
97
- console.log("All files processed successfully!");
98
- await notificationService.notifyInfo("update-json-articles completed", {
99
- caller: "update-json-articles",
100
- });
101
- }
102
- catch (error) {
103
- console.error("Error in main process:", error);
104
- await notificationService.notifyError(`update-json-articles failed: ${String(error)}`, {
105
- caller: "update-json-articles",
106
- });
107
- process.exit(1);
108
- }
104
+ } catch (error) {
105
+ console.error("Error in main process:", error);
106
+ await notificationService.notifyError(
107
+ `update-json-articles failed: ${String(error)}`,
108
+ {
109
+ caller: "update-json-articles"
110
+ }
111
+ );
112
+ process.exit(1);
113
+ }
109
114
  }
110
115
  main().catch((error) => {
111
- console.error(error);
112
- process.exit(1);
116
+ console.error(error);
117
+ process.exit(1);
113
118
  });
114
- //# sourceMappingURL=update-json-articles.js.map
@@ -1,102 +1,104 @@
1
1
  #!/usr/bin/env node
2
- import { createPushoverService } from "@s-hirano-ist/s-notification";
2
+ import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
3
+ import {
4
+ decodeHtml
5
+ } from "./chunk-UXGLXHQ6.js";
6
+ import {
7
+ createPushoverService
8
+ } from "./chunk-7PVU2Z32.js";
9
+ import "./chunk-JZOR5GA2.js";
10
+
11
+ // src/update-raw-articles.ts
3
12
  import { existsSync } from "node:fs";
4
13
  import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
5
14
  import path from "node:path";
6
15
  import TurndownService from "turndown";
7
- import { decodeHtml } from "./lib/html-charset.js";
8
- const JSON_DIR = "json/article";
9
- const OUTPUT_DIR = "raw/article";
16
+ var JSON_DIR = "json/article";
17
+ var OUTPUT_DIR = "raw/article";
10
18
  async function fetchWebsiteMarkdown(url) {
11
- try {
12
- const response = await fetch(url, {
13
- headers: {
14
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
15
- },
16
- });
17
- if (!response.ok) {
18
- throw new Error(`HTTP error! status: ${response.status}`);
19
- }
20
- const buffer = Buffer.from(await response.arrayBuffer());
21
- const html = decodeHtml(response.headers, buffer);
22
- const turndownService = new TurndownService({
23
- headingStyle: "atx",
24
- codeBlockStyle: "fenced",
25
- bulletListMarker: "-",
26
- strongDelimiter: "**",
27
- emDelimiter: "_",
28
- });
29
- turndownService.remove(["script", "style", "nav", "footer", "aside"]);
30
- turndownService.addRule("preserveLinks", {
31
- filter: ["a"],
32
- replacement: (content, node) => {
33
- const element = node;
34
- const href = element.getAttribute("href");
35
- if (!href)
36
- return content;
37
- if (href.startsWith("http") || href.startsWith("https")) {
38
- return `[${content}](${href})`;
39
- }
40
- try {
41
- const absoluteUrl = new URL(href, url).href;
42
- return `[${content}](${absoluteUrl})`;
43
- }
44
- catch {
45
- return content;
46
- }
47
- },
48
- });
49
- turndownService.addRule("preserveImages", {
50
- filter: ["img"],
51
- replacement: (_content, node) => {
52
- const element = node;
53
- const src = element.getAttribute("src");
54
- const alt = element.getAttribute("alt") || "";
55
- if (!src)
56
- return "";
57
- if (src.startsWith("http") || src.startsWith("https")) {
58
- return `![${alt}](${src})`;
59
- }
60
- try {
61
- const absoluteUrl = new URL(src, url).href;
62
- return `![${alt}](${absoluteUrl})`;
63
- }
64
- catch {
65
- return "";
66
- }
67
- },
68
- });
69
- const markdown = turndownService.turndown(html);
70
- return markdown.trim();
71
- }
72
- catch (error) {
73
- console.error(`Failed to fetch ${url}:`, error);
74
- return "";
19
+ try {
20
+ const response = await fetch(url, {
21
+ headers: {
22
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
23
+ }
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`HTTP error! status: ${response.status}`);
75
27
  }
28
+ const buffer = Buffer.from(await response.arrayBuffer());
29
+ const html = decodeHtml(response.headers, buffer);
30
+ const turndownService = new TurndownService({
31
+ headingStyle: "atx",
32
+ codeBlockStyle: "fenced",
33
+ bulletListMarker: "-",
34
+ strongDelimiter: "**",
35
+ emDelimiter: "_"
36
+ });
37
+ turndownService.remove(["script", "style", "nav", "footer", "aside"]);
38
+ turndownService.addRule("preserveLinks", {
39
+ filter: ["a"],
40
+ replacement: (content, node) => {
41
+ const element = node;
42
+ const href = element.getAttribute("href");
43
+ if (!href) return content;
44
+ if (href.startsWith("http") || href.startsWith("https")) {
45
+ return `[${content}](${href})`;
46
+ }
47
+ try {
48
+ const absoluteUrl = new URL(href, url).href;
49
+ return `[${content}](${absoluteUrl})`;
50
+ } catch {
51
+ return content;
52
+ }
53
+ }
54
+ });
55
+ turndownService.addRule("preserveImages", {
56
+ filter: ["img"],
57
+ replacement: (_content, node) => {
58
+ const element = node;
59
+ const src = element.getAttribute("src");
60
+ const alt = element.getAttribute("alt") || "";
61
+ if (!src) return "";
62
+ if (src.startsWith("http") || src.startsWith("https")) {
63
+ return `![${alt}](${src})`;
64
+ }
65
+ try {
66
+ const absoluteUrl = new URL(src, url).href;
67
+ return `![${alt}](${absoluteUrl})`;
68
+ } catch {
69
+ return "";
70
+ }
71
+ }
72
+ });
73
+ const markdown = turndownService.turndown(html);
74
+ return markdown.trim();
75
+ } catch (error) {
76
+ console.error(`Failed to fetch ${url}:`, error);
77
+ return "";
78
+ }
76
79
  }
77
80
  async function jsonToMarkdown(jsonFile) {
78
- const rawData = await readFile(jsonFile, "utf-8");
79
- const data = JSON.parse(rawData);
80
- // oxlint-disable-next-line typescript/no-unnecessary-condition -- data comes from an external JSON file; the runtime value may not match ArticlesData
81
- const bodyList = data.body || [];
82
- if (!existsSync(OUTPUT_DIR)) {
83
- await mkdir(OUTPUT_DIR, { recursive: true });
84
- }
85
- for (const item of bodyList) {
86
- const { title, quote, url, skip } = item;
87
- try {
88
- const strippedUrl = url.replace(/^https?:\/\//u, "");
89
- const safeUrl = encodeURIComponent(strippedUrl);
90
- const outputFilename = `${safeUrl}.md`;
91
- const outputPath = path.join(OUTPUT_DIR, outputFilename);
92
- if (existsSync(outputPath) || skip) {
93
- continue;
94
- }
95
- const websiteText = await fetchWebsiteMarkdown(url);
96
- if (!websiteText) {
97
- continue;
98
- }
99
- const markdownContent = `# [${title}](${url})
81
+ const rawData = await readFile(jsonFile, "utf-8");
82
+ const data = JSON.parse(rawData);
83
+ const bodyList = data.body || [];
84
+ if (!existsSync(OUTPUT_DIR)) {
85
+ await mkdir(OUTPUT_DIR, { recursive: true });
86
+ }
87
+ for (const item of bodyList) {
88
+ const { title, quote, url, skip } = item;
89
+ try {
90
+ const strippedUrl = url.replace(/^https?:\/\//u, "");
91
+ const safeUrl = encodeURIComponent(strippedUrl);
92
+ const outputFilename = `${safeUrl}.md`;
93
+ const outputPath = path.join(OUTPUT_DIR, outputFilename);
94
+ if (existsSync(outputPath) || skip) {
95
+ continue;
96
+ }
97
+ const websiteText = await fetchWebsiteMarkdown(url);
98
+ if (!websiteText) {
99
+ continue;
100
+ }
101
+ const markdownContent = `# [${title}](${url})
100
102
 
101
103
  ---
102
104
 
@@ -108,51 +110,49 @@ ${quote}
108
110
 
109
111
  ${websiteText}
110
112
  `;
111
- await writeFile(outputPath, markdownContent, "utf-8");
112
- console.log(`Exported: ${outputPath}`);
113
- }
114
- catch {
115
- console.error("Error on file:", url);
116
- }
113
+ await writeFile(outputPath, markdownContent, "utf-8");
114
+ console.log(`Exported: ${outputPath}`);
115
+ } catch {
116
+ console.error("Error on file:", url);
117
117
  }
118
+ }
118
119
  }
119
120
  async function main() {
120
- const env = {
121
- PUSHOVER_URL: process.env.PUSHOVER_URL,
122
- PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
123
- PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
124
- };
125
- if (Object.values(env).some((v) => !v)) {
126
- throw new Error("Required environment variables are not set.");
121
+ const env = {
122
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
123
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
124
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN
125
+ };
126
+ if (Object.values(env).some((v) => !v)) {
127
+ throw new Error("Required environment variables are not set.");
128
+ }
129
+ const notificationService = createPushoverService({
130
+ url: env.PUSHOVER_URL ?? "",
131
+ userKey: env.PUSHOVER_USER_KEY ?? "",
132
+ appToken: env.PUSHOVER_APP_TOKEN ?? ""
133
+ });
134
+ try {
135
+ const jsonFiles = await readdir(JSON_DIR);
136
+ const jsonFilePaths = jsonFiles.filter((file) => file.endsWith(".json")).map((file) => path.join(JSON_DIR, file));
137
+ for (const jsonFile of jsonFilePaths) {
138
+ console.log(`Processing: ${jsonFile}`);
139
+ await jsonToMarkdown(jsonFile);
127
140
  }
128
- const notificationService = createPushoverService({
129
- url: env.PUSHOVER_URL ?? "",
130
- userKey: env.PUSHOVER_USER_KEY ?? "",
131
- appToken: env.PUSHOVER_APP_TOKEN ?? "",
141
+ await notificationService.notifyInfo("update-raw-articles completed", {
142
+ caller: "update-raw-articles"
132
143
  });
133
- try {
134
- const jsonFiles = await readdir(JSON_DIR);
135
- const jsonFilePaths = jsonFiles
136
- .filter((file) => file.endsWith(".json"))
137
- .map((file) => path.join(JSON_DIR, file));
138
- for (const jsonFile of jsonFilePaths) {
139
- console.log(`Processing: ${jsonFile}`);
140
- await jsonToMarkdown(jsonFile);
141
- }
142
- await notificationService.notifyInfo("update-raw-articles completed", {
143
- caller: "update-raw-articles",
144
- });
145
- }
146
- catch (error) {
147
- console.error("Error in main process:", error);
148
- await notificationService.notifyError(`update-raw-articles failed: ${String(error)}`, {
149
- caller: "update-raw-articles",
150
- });
151
- process.exit(1);
152
- }
144
+ } catch (error) {
145
+ console.error("Error in main process:", error);
146
+ await notificationService.notifyError(
147
+ `update-raw-articles failed: ${String(error)}`,
148
+ {
149
+ caller: "update-raw-articles"
150
+ }
151
+ );
152
+ process.exit(1);
153
+ }
153
154
  }
154
155
  main().catch((error) => {
155
- console.error(error);
156
- process.exit(1);
156
+ console.error(error);
157
+ process.exit(1);
157
158
  });
158
- //# sourceMappingURL=update-raw-articles.js.map