|
1 | 1 | import { execFileSync } from "node:child_process"; |
2 | | -import { readdirSync, rmSync, writeFileSync } from "node:fs"; |
| 2 | +import { readdirSync, rmSync, statSync, writeFileSync } from "node:fs"; |
3 | 3 | import { basename, join, relative } from "node:path"; |
4 | 4 | import { parseArgs } from "node:util"; |
5 | 5 | import { defaultLocale, locales, rtlLocales } from "../src/i18n/config"; |
@@ -31,7 +31,17 @@ if (baseBranch && baseRefArg) { |
31 | 31 | process.exit(1); |
32 | 32 | } |
33 | 33 |
|
34 | | -const BLOG_DIR = "src/content/blog"; |
| 34 | +const CONTENT_ROOT = "src/content"; |
| 35 | +const CONTENT_DIRS = readdirSync(CONTENT_ROOT) |
| 36 | + .filter((entry) => !entry.startsWith("_") && !entry.startsWith(".")) |
| 37 | + .map((entry) => join(CONTENT_ROOT, entry)) |
| 38 | + .filter((path) => { |
| 39 | + try { |
| 40 | + return statSync(path).isDirectory(); |
| 41 | + } catch { |
| 42 | + return false; |
| 43 | + } |
| 44 | + }); |
35 | 45 | const OG_ROUTE = "src/pages/open-graph/[...route].ts"; |
36 | 46 | const I18N_CONFIG = "src/i18n/config.ts"; |
37 | 47 | const I18N_DIR = "src/i18n/translations"; |
@@ -117,50 +127,66 @@ let changed: string[] = []; |
117 | 127 | if (baseRef) { |
118 | 128 | const mode = useMergeBase ? "merge-base" : "direct"; |
119 | 129 | console.log(`Diff: ${mode} against ${baseRef}`); |
120 | | - changed = getChangedFiles(baseRef, useMergeBase, BLOG_DIR, I18N_DIR); |
| 130 | + changed = getChangedFiles(baseRef, useMergeBase, ...CONTENT_DIRS, I18N_DIR); |
121 | 131 | console.log( |
122 | 132 | `Diff: ${changed.length} file${changed.length !== 1 ? "s" : ""} changed`, |
123 | 133 | ); |
124 | 134 | } else { |
125 | 135 | console.log("Diff: skipped"); |
126 | 136 | } |
127 | 137 |
|
128 | | -// Limit blog posts, keeping edited ones |
| 138 | +// Limit content entries |
129 | 139 | if (limitPosts) { |
130 | 140 | const limit = Number(limitPosts); |
131 | 141 | if (!Number.isFinite(limit) || limit < 1) { |
132 | 142 | console.error(`Invalid --limit-posts value: ${limitPosts}`); |
133 | 143 | process.exit(1); |
134 | 144 | } |
135 | 145 |
|
136 | | - const isPost = (f: string) => /^\d/.test(f) && f.endsWith(".md"); |
137 | | - |
138 | | - const allPosts = readdirSync(BLOG_DIR).filter(isPost).sort().reverse(); |
139 | | - const keep = new Set(allPosts.slice(0, limit)); |
140 | | - |
141 | | - for (const file of changedFilesUnder(BLOG_DIR)) { |
142 | | - if (isPost(basename(file))) keep.add(basename(file)); |
143 | | - } |
144 | | - |
145 | | - let removed = 0; |
146 | | - for (const file of allPosts) { |
147 | | - if (keep.has(file)) continue; |
148 | | - rmSync(join(BLOG_DIR, file)); |
149 | | - removed++; |
| 146 | + const isContent = (f: string) => !f.startsWith("_") && f.endsWith(".md"); |
| 147 | + const localeSet = new Set(Object.keys(locales)); |
| 148 | + const stats: { name: string; kept: number; total: number }[] = []; |
| 149 | + |
| 150 | + for (const dir of CONTENT_DIRS) { |
| 151 | + const changedKeep = new Set(changedFilesUnder(dir)); |
| 152 | + let kept = 0; |
| 153 | + let total = 0; |
| 154 | + for (const locale of readdirSync(dir)) { |
| 155 | + if (!localeSet.has(locale)) continue; |
| 156 | + const localeDir = join(dir, locale); |
| 157 | + const files = readdirSync(localeDir).filter(isContent).sort().reverse(); |
| 158 | + const baseline = |
| 159 | + locale === defaultLocale |
| 160 | + ? new Set(files.slice(0, limit)) |
| 161 | + : new Set<string>(); |
| 162 | + for (const file of files) { |
| 163 | + total++; |
| 164 | + const rel = join(localeDir, file); |
| 165 | + if (baseline.has(file) || changedKeep.has(rel)) { |
| 166 | + kept++; |
| 167 | + continue; |
| 168 | + } |
| 169 | + rmSync(rel); |
| 170 | + } |
| 171 | + } |
| 172 | + if (total > 0) stats.push({ name: basename(dir), kept, total }); |
150 | 173 | } |
151 | 174 |
|
152 | | - console.log( |
153 | | - `Blog: kept ${allPosts.length - removed} of ${allPosts.length} posts`, |
154 | | - ); |
| 175 | + const summary = stats |
| 176 | + .map(({ name, kept, total }) => `${name} ${kept}/${total}`) |
| 177 | + .join(", "); |
| 178 | + console.log(`Content: kept ${summary || "no entries"}`); |
155 | 179 | } |
156 | 180 |
|
157 | 181 | // Limit locales |
158 | 182 | if (limitLocales) { |
159 | 183 | const keepLocales = new Set([defaultLocale]); |
160 | 184 |
|
161 | | - for (const file of changedFilesUnder(I18N_DIR)) { |
162 | | - const locale = relative(I18N_DIR, file).split("/")[0]; |
163 | | - if (locale && locale !== defaultLocale) keepLocales.add(locale); |
| 185 | + for (const dir of [I18N_DIR, ...CONTENT_DIRS]) { |
| 186 | + for (const file of changedFilesUnder(dir)) { |
| 187 | + const locale = relative(dir, file).split("/")[0]; |
| 188 | + if (locale && locale !== defaultLocale) keepLocales.add(locale); |
| 189 | + } |
164 | 190 | } |
165 | 191 |
|
166 | 192 | writeFileSync(I18N_CONFIG, serializeI18nConfig(keepLocales)); |
|
0 commit comments