Skip to content

Commit dbf55d2

Browse files
fix: add app route allowlist + skip unpublished in link validator
Ported from #1777 (app routes) and #1782 (unpublished skip).
1 parent 7ef34a6 commit dbf55d2

1 file changed

Lines changed: 55 additions & 1 deletion

File tree

scripts/validate-links.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ function buildValidPaths(): Set<string> {
4242
paths.add(p)
4343
}
4444

45+
// App routes (behind auth / mobile-ui) — content may link to these
46+
for (const p of [
47+
'/profile',
48+
'/profile/backup',
49+
'/profile/edit',
50+
'/profile/exchange-rate',
51+
'/profile/identity-verification',
52+
'/home',
53+
'/send',
54+
'/request',
55+
'/settings',
56+
'/history',
57+
'/points',
58+
'/recover-funds',
59+
]) {
60+
paths.add(p)
61+
}
62+
4563
const countrySlugs = listDirs(path.join(CONTENT_DIR, 'countries'))
4664
const competitorSlugs = listDirs(path.join(CONTENT_DIR, 'compare'))
4765
const payWithSlugs = listDirs(path.join(CONTENT_DIR, 'pay-with'))
@@ -187,6 +205,30 @@ function isInternalLink(url: string): boolean {
187205
return true
188206
}
189207

208+
// --- Frontmatter parsing ---
209+
210+
function parseFrontmatter(content: string): Record<string, unknown> {
211+
const match = content.match(/^---\n([\s\S]*?)\n---/)
212+
if (!match) return {}
213+
const frontmatter: Record<string, unknown> = {}
214+
for (const line of match[1].split('\n')) {
215+
const colonIdx = line.indexOf(':')
216+
if (colonIdx === -1) continue
217+
const key = line.slice(0, colonIdx).trim()
218+
const value = line.slice(colonIdx + 1).trim()
219+
if (value === 'true') frontmatter[key] = true
220+
else if (value === 'false') frontmatter[key] = false
221+
else frontmatter[key] = value
222+
}
223+
return frontmatter
224+
}
225+
226+
function isPublished(content: string): boolean {
227+
const fm = parseFrontmatter(content)
228+
// If published is explicitly false, skip the file
229+
return fm.published !== false
230+
}
231+
190232
// --- Scan content files ---
191233

192234
function getAllMdFiles(dir: string): string[] {
@@ -225,8 +267,17 @@ function main() {
225267
const broken: BrokenLink[] = []
226268
let totalLinks = 0
227269

270+
let skippedUnpublished = 0
271+
228272
for (const file of files) {
229273
const content = fs.readFileSync(file, 'utf-8')
274+
275+
// Skip unpublished/draft content — links to not-yet-built routes are expected
276+
if (!isPublished(content)) {
277+
skippedUnpublished++
278+
continue
279+
}
280+
230281
const links = extractLinks(content)
231282
totalLinks += links.length
232283

@@ -246,7 +297,10 @@ function main() {
246297
}
247298

248299
// --- Report ---
249-
console.log(`Checked ${totalLinks} internal links across ${files.length} files\n`)
300+
if (skippedUnpublished > 0) {
301+
console.log(` Skipped ${skippedUnpublished} unpublished files\n`)
302+
}
303+
console.log(`Checked ${totalLinks} internal links across ${files.length - skippedUnpublished} published files\n`)
250304

251305
if (broken.length === 0) {
252306
console.log('✓ No broken internal links found!')

0 commit comments

Comments
 (0)