Skip to content

Commit bc26912

Browse files
authored
chore(cli): polish checkDeadLinks logs (#2350)
1 parent e20d174 commit bc26912

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

packages/core/src/node/logger/hint.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,14 @@ export function hintNavJsonChangeThenPanic(
9797
process.exit(1);
9898
}
9999
}
100+
101+
let isLogged = false;
102+
export function hintRelativeMarkdownLink() {
103+
if (isLogged) {
104+
return;
105+
}
106+
isLogged = true;
107+
logger.info(
108+
'[Rspress v2] Markdown links without "./" prefix are now relative links, e.g: [](guide/getting-started) is equal to [](./guide/getting-started). You can rewrite it to [](/guide/getting-started) to always use absolute links, or use [](./getting-started.md)',
109+
);
110+
}

packages/core/src/node/mdx/remarkPlugins/normalizeLink.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,49 @@ import type { Plugin } from 'unified';
1515
import { visit } from 'unist-util-visit';
1616

1717
import { logger } from '@rspress/shared/logger';
18+
import picocolors from 'picocolors';
19+
import { hintRelativeMarkdownLink } from '../../logger/hint';
1820
import type { RouteService } from '../../route/RouteService';
1921
import { getASTNodeImport } from '../../utils';
2022

23+
// TODO: checkDeadLinks support external links and anchor hash links
2124
function checkDeadLinks(
2225
internalLinks: Map<string, string>,
2326
filePath: string,
2427
routeService: RouteService,
2528
) {
26-
const errorInfos: string[] = [];
27-
internalLinks.entries().forEach(([nodeUrl, link]) => {
29+
const errorInfos: [string, string][] = [];
30+
31+
let possibleBreakingChange = false;
32+
33+
[...internalLinks.entries()].forEach(([nodeUrl, link]) => {
2834
const cleanLinkPath = linkToRoutePath(link);
2935
if (!cleanLinkPath) {
3036
return;
3137
}
3238

39+
if (!nodeUrl.startsWith('/') && /^\w/.test(nodeUrl)) {
40+
possibleBreakingChange = true;
41+
}
42+
3343
// allow fuzzy matching, e.g: /guide/ and /guide is equal
3444
// This is a simple judgment, the performance will be better than "matchPath" in react-router-dom
3545
if (
3646
!routeService.isExistRoute(removeTrailingSlash(cleanLinkPath)) &&
3747
!routeService.isExistRoute(addTrailingSlash(cleanLinkPath))
3848
) {
39-
errorInfos.push(
40-
`Internal link to "${nodeUrl}" which points to "${cleanLinkPath}" is dead, check it in "${filePath}"`,
41-
);
49+
errorInfos.push([nodeUrl, link]);
4250
}
4351
});
4452
// output error info
4553
if (errorInfos.length > 0) {
46-
errorInfos?.forEach(err => {
47-
logger.error(err);
48-
});
54+
if (possibleBreakingChange) {
55+
hintRelativeMarkdownLink();
56+
}
57+
58+
logger.error(`Dead links found in ${picocolors.cyan(filePath)}:
59+
${errorInfos.map(([nodeUrl, link]) => ` ${picocolors.green(`"[..](${nodeUrl})"`)} ${picocolors.gray(link)}`).join('\n')}`);
60+
4961
if (isProduction()) {
5062
throw new Error('Dead link found');
5163
}

0 commit comments

Comments
 (0)