@@ -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 ( / ^ ( m a i l t o : | # ) / . 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