formatting and comments
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Verify repository-local Markdown links without making network requests.
|
||||
*
|
||||
* External URLs are intentionally skipped: CI should not fail because an
|
||||
* upstream website is temporarily unavailable. Local documentation links are
|
||||
* deterministic and catch renamed component guides or incorrect relative paths.
|
||||
*/
|
||||
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
||||
import { dirname, extname, resolve } from 'node:path'
|
||||
|
||||
const root = resolve(process.argv[2] ?? new URL('../../..', import.meta.url).pathname)
|
||||
const ignoredDirectories = new Set([
|
||||
'.agents',
|
||||
'.codex',
|
||||
'.git',
|
||||
'dist',
|
||||
'node_modules',
|
||||
'target',
|
||||
'vendor',
|
||||
])
|
||||
const markdownFiles = []
|
||||
|
||||
function collect(directory) {
|
||||
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
||||
if (entry.isDirectory() && ignoredDirectories.has(entry.name)) continue
|
||||
const path = resolve(directory, entry.name)
|
||||
if (entry.isDirectory()) collect(path)
|
||||
else if (extname(entry.name).toLowerCase() === '.md') markdownFiles.push(path)
|
||||
}
|
||||
}
|
||||
|
||||
collect(root)
|
||||
|
||||
const failures = []
|
||||
const markdownLink = /\[[^\]]*\]\(([^)]+)\)/g
|
||||
for (const file of markdownFiles) {
|
||||
const source = readFileSync(file, 'utf8')
|
||||
for (const match of source.matchAll(markdownLink)) {
|
||||
const rawTarget = match[1].trim().replace(/^<|>$/g, '')
|
||||
if (!rawTarget || rawTarget.startsWith('#') || /^[a-z][a-z+.-]*:/i.test(rawTarget)) continue
|
||||
|
||||
// The project does not currently use titled local links. Splitting here
|
||||
// still handles the conventional `(path "title")` form if one is added.
|
||||
const target = decodeURI(rawTarget.split(/\s+["']/)[0].split('#')[0])
|
||||
if (!target) continue
|
||||
const destination = resolve(dirname(file), target)
|
||||
if (!existsSync(destination)) failures.push(`${file}: ${rawTarget}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.length > 0) {
|
||||
console.error(`Broken local documentation links:\n${failures.join('\n')}`)
|
||||
process.exitCode = 1
|
||||
} else {
|
||||
console.log(`Checked ${markdownFiles.length} Markdown files; local links are valid.`)
|
||||
}
|
||||
Reference in New Issue
Block a user