mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-06 02:08:55 +02:00
Merge 7df0e771a5
into a3324ff65e
This commit is contained in:
commit
b484c5212c
8 changed files with 56 additions and 2 deletions
8
packages/docusaurus-types/src/config.d.ts
vendored
8
packages/docusaurus-types/src/config.d.ts
vendored
|
@ -169,6 +169,14 @@ export type DocusaurusConfig = {
|
||||||
* @default "warn"
|
* @default "warn"
|
||||||
*/
|
*/
|
||||||
onDuplicateRoutes: ReportingSeverity;
|
onDuplicateRoutes: ReportingSeverity;
|
||||||
|
/**
|
||||||
|
* This option controls whether external links (links are not for the same site)
|
||||||
|
* open in a new tab or not.
|
||||||
|
*
|
||||||
|
* @see https://docusaurus.io/docs/api/docusaurus-config#openExternalLinksInNewTab
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
openExternalLinksInNewTab: boolean;
|
||||||
/**
|
/**
|
||||||
* The tagline for your website.
|
* The tagline for your website.
|
||||||
*
|
*
|
||||||
|
|
|
@ -42,7 +42,7 @@ function Link(
|
||||||
forwardedRef: React.ForwardedRef<HTMLAnchorElement>,
|
forwardedRef: React.ForwardedRef<HTMLAnchorElement>,
|
||||||
): ReactNode {
|
): ReactNode {
|
||||||
const {siteConfig} = useDocusaurusContext();
|
const {siteConfig} = useDocusaurusContext();
|
||||||
const {trailingSlash, baseUrl} = siteConfig;
|
const {trailingSlash, baseUrl, openExternalLinksInNewTab} = siteConfig;
|
||||||
const router = siteConfig.future.experimental_router;
|
const router = siteConfig.future.experimental_router;
|
||||||
const {withBaseUrl} = useBaseUrlUtils();
|
const {withBaseUrl} = useBaseUrlUtils();
|
||||||
const brokenLinks = useBrokenLinks();
|
const brokenLinks = useBrokenLinks();
|
||||||
|
@ -188,7 +188,11 @@ function Link(
|
||||||
ref={innerRef}
|
ref={innerRef}
|
||||||
href={targetLink}
|
href={targetLink}
|
||||||
{...(targetLinkUnprefixed &&
|
{...(targetLinkUnprefixed &&
|
||||||
!isInternal && {target: '_blank', rel: 'noopener noreferrer'})}
|
!isInternal &&
|
||||||
|
openExternalLinksInNewTab && {
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener noreferrer',
|
||||||
|
})}
|
||||||
{...props}
|
{...props}
|
||||||
{...testOnlyProps}
|
{...testOnlyProps}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -19,6 +19,7 @@ type Options = {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
router: DocusaurusContext['siteConfig']['future']['experimental_router'];
|
router: DocusaurusContext['siteConfig']['future']['experimental_router'];
|
||||||
currentLocation: string;
|
currentLocation: string;
|
||||||
|
openExternalLinksInNewTab: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultOptions: Options = {
|
const defaultOptions: Options = {
|
||||||
|
@ -27,6 +28,7 @@ const defaultOptions: Options = {
|
||||||
router: 'browser',
|
router: 'browser',
|
||||||
// currentLocation is nested on purpose, shows relative link resolution
|
// currentLocation is nested on purpose, shows relative link resolution
|
||||||
currentLocation: '/sub/category/currentPathname',
|
currentLocation: '/sub/category/currentPathname',
|
||||||
|
openExternalLinksInNewTab: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function createDocusaurusContext(
|
function createDocusaurusContext(
|
||||||
|
@ -40,6 +42,7 @@ function createDocusaurusContext(
|
||||||
future: {
|
future: {
|
||||||
experimental_router: options.router,
|
experimental_router: options.router,
|
||||||
},
|
},
|
||||||
|
openExternalLinksInNewTab: options.openExternalLinksInNewTab,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -238,6 +241,19 @@ describe('<Link>', () => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("can render 'https://example.com/xyz' without opening to a new window", () => {
|
||||||
|
expect(
|
||||||
|
render(<Link to="https://example.com/xyz" />, {
|
||||||
|
openExternalLinksInNewTab: false,
|
||||||
|
}),
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
<a
|
||||||
|
data-test-link-type="regular"
|
||||||
|
href="https://example.com/xyz"
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it("can render 'pathname:///docs/intro'", () => {
|
it("can render 'pathname:///docs/intro'", () => {
|
||||||
expect(render(<Link to="pathname:///docs/intro" />))
|
expect(render(<Link to="pathname:///docs/intro" />))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
|
|
|
@ -61,6 +61,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -140,6 +141,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -219,6 +221,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -298,6 +301,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -377,6 +381,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -456,6 +461,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
@ -535,6 +541,7 @@ exports[`loadSiteConfig website with valid async config 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"organizationName": "endiliey",
|
"organizationName": "endiliey",
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
|
@ -616,6 +623,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"organizationName": "endiliey",
|
"organizationName": "endiliey",
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
|
@ -697,6 +705,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"organizationName": "endiliey",
|
"organizationName": "endiliey",
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
|
@ -781,6 +790,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"organizationName": "endiliey",
|
"organizationName": "endiliey",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -147,6 +147,7 @@ exports[`load loads props for site 1`] = `
|
||||||
"onBrokenAnchors": "warn",
|
"onBrokenAnchors": "warn",
|
||||||
"onBrokenLinks": "throw",
|
"onBrokenLinks": "throw",
|
||||||
"onDuplicateRoutes": "warn",
|
"onDuplicateRoutes": "warn",
|
||||||
|
"openExternalLinksInNewTab": true,
|
||||||
"plugins": [],
|
"plugins": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
|
|
|
@ -114,6 +114,7 @@ export const DEFAULT_CONFIG: Pick<
|
||||||
| 'onBrokenAnchors'
|
| 'onBrokenAnchors'
|
||||||
| 'onBrokenMarkdownLinks'
|
| 'onBrokenMarkdownLinks'
|
||||||
| 'onDuplicateRoutes'
|
| 'onDuplicateRoutes'
|
||||||
|
| 'openExternalLinksInNewTab'
|
||||||
| 'plugins'
|
| 'plugins'
|
||||||
| 'themes'
|
| 'themes'
|
||||||
| 'presets'
|
| 'presets'
|
||||||
|
@ -136,6 +137,7 @@ export const DEFAULT_CONFIG: Pick<
|
||||||
onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw
|
onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw
|
||||||
onBrokenMarkdownLinks: undefined,
|
onBrokenMarkdownLinks: undefined,
|
||||||
onDuplicateRoutes: 'warn',
|
onDuplicateRoutes: 'warn',
|
||||||
|
openExternalLinksInNewTab: true,
|
||||||
plugins: [],
|
plugins: [],
|
||||||
themes: [],
|
themes: [],
|
||||||
presets: [],
|
presets: [],
|
||||||
|
@ -360,6 +362,9 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({
|
||||||
onDuplicateRoutes: Joi.string()
|
onDuplicateRoutes: Joi.string()
|
||||||
.equal('ignore', 'log', 'warn', 'throw')
|
.equal('ignore', 'log', 'warn', 'throw')
|
||||||
.default(DEFAULT_CONFIG.onDuplicateRoutes),
|
.default(DEFAULT_CONFIG.onDuplicateRoutes),
|
||||||
|
openExternalLinksInNewTab: Joi.boolean().default(
|
||||||
|
DEFAULT_CONFIG.openExternalLinksInNewTab,
|
||||||
|
),
|
||||||
organizationName: Joi.string().allow(''),
|
organizationName: Joi.string().allow(''),
|
||||||
staticDirectories: Joi.array()
|
staticDirectories: Joi.array()
|
||||||
.items(Joi.string())
|
.items(Joi.string())
|
||||||
|
|
|
@ -413,6 +413,8 @@ These links are broken (try to single click on them) and should be reported. We
|
||||||
- <TestLink href="/dogfooding/javadoc#badlink2" noCheck />
|
- <TestLink href="/dogfooding/javadoc#badlink2" noCheck />
|
||||||
- <TestLink to="/dogfooding/javadoc#badlink3" target="_self" noCheck />
|
- <TestLink to="/dogfooding/javadoc#badlink3" target="_self" noCheck />
|
||||||
- <TestLink href="/dogfooding/javadoc#badlink4" target="_self" noCheck />
|
- <TestLink href="/dogfooding/javadoc#badlink4" target="_self" noCheck />
|
||||||
|
- <TestLink to="https://example.com/fail" noCheck />
|
||||||
|
- <TestLink href="https://example.com/fail" noCheck />
|
||||||
|
|
||||||
### Linking to JSON
|
### Linking to JSON
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,14 @@ The behavior of Docusaurus when it detects any broken Markdown link.
|
||||||
|
|
||||||
By default, it prints a warning, to let you know about your broken Markdown link.
|
By default, it prints a warning, to let you know about your broken Markdown link.
|
||||||
|
|
||||||
|
### `openExternalLinksInNewTab` {#openExternalLinksInNewTab}
|
||||||
|
|
||||||
|
- Type: `boolean`
|
||||||
|
|
||||||
|
When enabled, Docusaurus will automatically add `target="_blank"` to all external links, so that they open in a new tab.
|
||||||
|
|
||||||
|
By default, external links are opened in a new tab.
|
||||||
|
|
||||||
### `onDuplicateRoutes` {#onDuplicateRoutes}
|
### `onDuplicateRoutes` {#onDuplicateRoutes}
|
||||||
|
|
||||||
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
|
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue