Skip to content

Commit 30e80f9

Browse files
committed
fix(audits): require exact export targets to exist and resolve markdown links strictly
1 parent 5c0d278 commit 30e80f9

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

‎scripts/check-guidance-refs.ts‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,15 @@ function importResolves(spec: string, packages: Map<string, WorkspacePackage>):
178178
if (!pkg) return false
179179
if (!pkg.exports) return rest.length === 0 || moduleResolves(pkg.dir, rest.join('/'))
180180
const subpath = rest.length === 0 ? '.' : `./${rest.join('/')}`
181+
// An export key only proves the specifier is declared; the file it maps to must also exist.
181182
return Object.entries(pkg.exports).some(([key, value]) => {
183+
const target = exportTarget(value)
184+
if (target === null) return false
182185
const [head, tail] = key.split('*')
183-
if (tail === undefined) return key === subpath
186+
if (tail === undefined) return key === subpath && moduleResolves(pkg.dir, target)
184187
if (!subpath.startsWith(head) || !subpath.endsWith(tail)) return false
185-
// A wildcard export only proves the pattern; the file it maps to must also exist.
186-
const target = exportTarget(value)
187188
const matched = subpath.slice(head.length, subpath.length - tail.length)
188-
return target !== null && moduleResolves(pkg.dir, target.replace('*', matched))
189+
return moduleResolves(pkg.dir, target.replace('*', matched))
189190
})
190191
}
191192

@@ -309,8 +310,18 @@ function auditDocument(relFile: string, workspaces: Workspaces, files: string[])
309310
for (const match of text.matchAll(MD_LINK)) {
310311
const target = match[1]
311312
if (/^(mailto:|#)/.test(target)) continue
312-
// A leading `/` in a link is the repo root.
313-
checkPath(line, target.replace(/^\//, ''))
313+
if (isPlaceholder(target) || /^[a-z]+:\/\//i.test(target)) continue
314+
if (target.startsWith('@/') || target.startsWith('@sim/')) {
315+
checkPath(line, target)
316+
continue
317+
}
318+
// A link names its destination explicitly, so there is no prose fallback: it resolves from
319+
// the repo root (leading `/`) or from the document's own folder.
320+
const dest = target.replace(/[#?].*$/, '')
321+
const base = dest.startsWith('/') ? ROOT : docDir
322+
if (dest && !resolvesFrom(base, dest.replace(/^\//, '').replace(/\/$/, ''))) {
323+
report(line, 'path', target)
324+
}
314325
}
315326

316327
const outsideSpans = text.replace(/`[^`\n]*`/g, (span) =>

0 commit comments

Comments
 (0)