mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-28 17:57:48 +02:00
Merge f927499c42
into 67924ca979
This commit is contained in:
commit
1f5e42c89b
8 changed files with 97 additions and 12 deletions
9
packages/docusaurus-types/src/bronkenLinks.d.ts
vendored
Normal file
9
packages/docusaurus-types/src/bronkenLinks.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
export type BrokenLink = {
|
||||
link: string;
|
||||
resolvedLink: string;
|
||||
anchor: boolean;
|
||||
};
|
||||
|
||||
export type BrokenLinksMap = {
|
||||
[pathname: string]: BrokenLink[]
|
||||
};
|
10
packages/docusaurus-types/src/config.d.ts
vendored
10
packages/docusaurus-types/src/config.d.ts
vendored
|
@ -13,6 +13,8 @@ import type {PluginConfig, PresetConfig, HtmlTagObject} from './plugin';
|
|||
|
||||
import type {ProcessorOptions} from '@mdx-js/mdx';
|
||||
|
||||
import type {BrokenLinksMap} from './bronkenLinks';
|
||||
|
||||
export type RemarkRehypeOptions = ProcessorOptions['remarkRehypeOptions'];
|
||||
|
||||
export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw';
|
||||
|
@ -251,6 +253,14 @@ export type DocusaurusConfig = {
|
|||
* @default "warn"
|
||||
*/
|
||||
onBrokenAnchors: ReportingSeverity;
|
||||
/**
|
||||
* The behavior of Docusaurus when it detects any broken link or anchor and generates a report.
|
||||
* This functions runs before generating a report.
|
||||
*
|
||||
* @see https://docusaurus.io/docs/api/docusaurus-config#onReportBrokenLinks
|
||||
* @default "warn"
|
||||
*/
|
||||
onReportBrokenLinks: (brokenLinksMap: BrokenLinksMap) => void;
|
||||
/**
|
||||
* The behavior of Docusaurus when it detects any broken markdown link.
|
||||
*
|
||||
|
|
6
packages/docusaurus-types/src/index.d.ts
vendored
6
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -90,3 +90,9 @@ export {
|
|||
} from './routing';
|
||||
|
||||
export {UseDataOptions} from './utils';
|
||||
|
||||
export {
|
||||
BrokenLinksMap,
|
||||
BrokenLink
|
||||
} from './bronkenLinks';
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ async function executePluginsPostBuild({
|
|||
async function executeBrokenLinksCheck({
|
||||
props: {
|
||||
routes,
|
||||
siteConfig: {onBrokenLinks, onBrokenAnchors},
|
||||
siteConfig: {onBrokenLinks, onBrokenAnchors, onReportBrokenLinks},
|
||||
},
|
||||
collectedData,
|
||||
}: {
|
||||
|
@ -172,9 +172,10 @@ async function executeBrokenLinksCheck({
|
|||
}));
|
||||
await handleBrokenLinks({
|
||||
collectedLinks,
|
||||
routes,
|
||||
onBrokenLinks,
|
||||
onBrokenAnchors,
|
||||
routes,
|
||||
onReportBrokenLinks
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import {jest} from '@jest/globals';
|
||||
import reactRouterConfig from 'react-router-config';
|
||||
import {handleBrokenLinks} from '../brokenLinks';
|
||||
import type {RouteConfig} from '@docusaurus/types';
|
||||
import type {BrokenLinksMap, RouteConfig} from '@docusaurus/types';
|
||||
|
||||
type Params = Parameters<typeof handleBrokenLinks>[0];
|
||||
|
||||
|
@ -26,6 +26,7 @@ async function testBrokenLinks(params: {
|
|||
onBrokenLinks?: Params['onBrokenLinks'];
|
||||
onBrokenAnchors?: Params['onBrokenAnchors'];
|
||||
routes?: SimpleRoute[];
|
||||
onReportBrokenLinks?: Params['onReportBrokenLinks'];
|
||||
}) {
|
||||
await handleBrokenLinks({
|
||||
collectedLinks: {},
|
||||
|
@ -34,6 +35,7 @@ async function testBrokenLinks(params: {
|
|||
...params,
|
||||
// Unsafe but convenient for tests
|
||||
routes: (params.routes ?? []) as RouteConfig[],
|
||||
onReportBrokenLinks: params.onReportBrokenLinks,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -728,6 +730,31 @@ describe('handleBrokenLinks', () => {
|
|||
warnMock.mockRestore();
|
||||
});
|
||||
|
||||
it('can warn for broken links and remove them before building the report', async () => {
|
||||
const warnMock = jest.spyOn(console, 'warn');
|
||||
|
||||
await testBrokenLinks({
|
||||
onBrokenLinks: 'warn',
|
||||
routes: [{path: '/page1'}],
|
||||
collectedLinks: {
|
||||
'/page1': {
|
||||
links: ['/page2'],
|
||||
anchors: [],
|
||||
},
|
||||
},
|
||||
onReportBrokenLinks: (brokenLinksMap: BrokenLinksMap) => {
|
||||
for (const pathname in brokenLinksMap) {
|
||||
if (pathname.startsWith('/page1')) {
|
||||
delete brokenLinksMap[pathname];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
expect(warnMock).toHaveBeenCalledTimes(0);
|
||||
warnMock.mockRestore();
|
||||
});
|
||||
|
||||
it('can warn for broken anchors', async () => {
|
||||
const warnMock = jest.spyOn(console, 'warn');
|
||||
|
||||
|
|
|
@ -15,7 +15,12 @@ import {
|
|||
type URLPath,
|
||||
} from '@docusaurus/utils';
|
||||
import {addTrailingSlash, removeTrailingSlash} from '@docusaurus/utils-common';
|
||||
import type {RouteConfig, ReportingSeverity} from '@docusaurus/types';
|
||||
import type {
|
||||
RouteConfig,
|
||||
ReportingSeverity,
|
||||
BrokenLink,
|
||||
BrokenLinksMap,
|
||||
} from '@docusaurus/types';
|
||||
|
||||
function matchRoutes(routeConfig: RouteConfig[], pathname: string) {
|
||||
// @ts-expect-error: React router types RouteConfig with an actual React
|
||||
|
@ -24,14 +29,6 @@ function matchRoutes(routeConfig: RouteConfig[], pathname: string) {
|
|||
return reactRouterMatchRoutes(routeConfig, pathname);
|
||||
}
|
||||
|
||||
type BrokenLink = {
|
||||
link: string;
|
||||
resolvedLink: string;
|
||||
anchor: boolean;
|
||||
};
|
||||
|
||||
type BrokenLinksMap = {[pathname: string]: BrokenLink[]};
|
||||
|
||||
// The linking data that has been collected on Docusaurus pages during SSG
|
||||
// {rendered page pathname => links and anchors collected on that page}
|
||||
type CollectedLinks = {
|
||||
|
@ -404,11 +401,13 @@ export async function handleBrokenLinks({
|
|||
onBrokenLinks,
|
||||
onBrokenAnchors,
|
||||
routes,
|
||||
onReportBrokenLinks,
|
||||
}: {
|
||||
collectedLinks: CollectedLinks;
|
||||
onBrokenLinks: ReportingSeverity;
|
||||
onBrokenAnchors: ReportingSeverity;
|
||||
routes: RouteConfig[];
|
||||
onReportBrokenLinks?: (brokenLinksMap: BrokenLinksMap) => void;
|
||||
}): Promise<void> {
|
||||
if (onBrokenLinks === 'ignore' && onBrokenAnchors === 'ignore') {
|
||||
return;
|
||||
|
@ -417,5 +416,10 @@ export async function handleBrokenLinks({
|
|||
routes,
|
||||
collectedLinks: normalizeCollectedLinks(collectedLinks),
|
||||
});
|
||||
|
||||
if (onReportBrokenLinks) {
|
||||
onReportBrokenLinks(brokenLinks);
|
||||
}
|
||||
|
||||
reportBrokenLinks({brokenLinks, onBrokenLinks, onBrokenAnchors});
|
||||
}
|
||||
|
|
|
@ -343,6 +343,7 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({
|
|||
onBrokenAnchors: Joi.string()
|
||||
.equal('ignore', 'log', 'warn', 'throw')
|
||||
.default(DEFAULT_CONFIG.onBrokenAnchors),
|
||||
onReportBrokenLinks: Joi.function(),
|
||||
onBrokenMarkdownLinks: Joi.string()
|
||||
.equal('ignore', 'log', 'warn', 'throw')
|
||||
.default(DEFAULT_CONFIG.onBrokenMarkdownLinks),
|
||||
|
|
|
@ -271,6 +271,33 @@ The behavior of Docusaurus when it detects any broken anchor declared with the `
|
|||
|
||||
By default, it prints a warning, to let you know about your broken anchors.
|
||||
|
||||
### `onReportBrokenLinks` {#onReportBrokenLinks}
|
||||
|
||||
- Type: `function`
|
||||
|
||||
When Docusaurus detects a broken link or anchor, it generates a report detailing the issues.
|
||||
|
||||
This function runs before the report is generated, allowing you to modify its contents before final output.
|
||||
|
||||
#### USAGE
|
||||
|
||||
In this example we will delete broken links that start with the path "/api" from the final report.
|
||||
|
||||
```javascript
|
||||
import { Config, BrokenLinksMap } from '@docusaurus/types';
|
||||
|
||||
const config: Config = {
|
||||
onReportBrokenLinks: (brokenLinksMap: BrokenLinksMap) => {
|
||||
for (const pathname in brokenLinksMap) {
|
||||
if (pathname.startsWith('/api')) {
|
||||
delete brokenLinksMap[pathname];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### `onBrokenMarkdownLinks` {#onBrokenMarkdownLinks}
|
||||
|
||||
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
|
||||
|
|
Loading…
Add table
Reference in a new issue