mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
feat(core): siteConfig.headTags API to render extra tags in document head (#8151)
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
This commit is contained in:
parent
3558a091c6
commit
1ca4fb50fe
7 changed files with 124 additions and 2 deletions
9
packages/docusaurus-types/src/config.d.ts
vendored
9
packages/docusaurus-types/src/config.d.ts
vendored
|
@ -8,7 +8,7 @@
|
||||||
import type {RuleSetRule} from 'webpack';
|
import type {RuleSetRule} from 'webpack';
|
||||||
import type {Required as RequireKeys, DeepPartial} from 'utility-types';
|
import type {Required as RequireKeys, DeepPartial} from 'utility-types';
|
||||||
import type {I18nConfig} from './i18n';
|
import type {I18nConfig} from './i18n';
|
||||||
import type {PluginConfig, PresetConfig} from './plugin';
|
import type {PluginConfig, PresetConfig, HtmlTagObject} from './plugin';
|
||||||
|
|
||||||
export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw';
|
export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw';
|
||||||
|
|
||||||
|
@ -192,6 +192,13 @@ export type DocusaurusConfig = {
|
||||||
* @default ["static"]
|
* @default ["static"]
|
||||||
*/
|
*/
|
||||||
staticDirectories: string[];
|
staticDirectories: string[];
|
||||||
|
/**
|
||||||
|
* An array of tags that will be inserted in the HTML `<head>`.
|
||||||
|
*
|
||||||
|
* @see https://docusaurus.io/docs/api/docusaurus-config#head
|
||||||
|
* @default []
|
||||||
|
*/
|
||||||
|
headTags: HtmlTagObject[];
|
||||||
/**
|
/**
|
||||||
* An array of scripts to load. The values can be either strings or plain
|
* An array of scripts to load. The values can be either strings or plain
|
||||||
* objects of attribute-value maps. The `<script>` tags will be inserted in
|
* objects of attribute-value maps. The `<script>` tags will be inserted in
|
||||||
|
|
|
@ -7,6 +7,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
|
||||||
"baseUrlIssueBanner": true,
|
"baseUrlIssueBanner": true,
|
||||||
"clientModules": [],
|
"clientModules": [],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {},
|
"localeConfigs": {},
|
||||||
|
@ -44,6 +45,7 @@ exports[`loadSiteConfig website with valid async config 1`] = `
|
||||||
"baseUrlIssueBanner": true,
|
"baseUrlIssueBanner": true,
|
||||||
"clientModules": [],
|
"clientModules": [],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {},
|
"localeConfigs": {},
|
||||||
|
@ -83,6 +85,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
|
||||||
"baseUrlIssueBanner": true,
|
"baseUrlIssueBanner": true,
|
||||||
"clientModules": [],
|
"clientModules": [],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {},
|
"localeConfigs": {},
|
||||||
|
@ -122,6 +125,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
|
||||||
"baseUrlIssueBanner": true,
|
"baseUrlIssueBanner": true,
|
||||||
"clientModules": [],
|
"clientModules": [],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {},
|
"localeConfigs": {},
|
||||||
|
@ -164,6 +168,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
|
||||||
],
|
],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
"favicon": "img/docusaurus.ico",
|
"favicon": "img/docusaurus.ico",
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {},
|
"localeConfigs": {},
|
||||||
|
|
|
@ -71,6 +71,7 @@ exports[`load loads props for site with custom i18n path 1`] = `
|
||||||
"baseUrlIssueBanner": true,
|
"baseUrlIssueBanner": true,
|
||||||
"clientModules": [],
|
"clientModules": [],
|
||||||
"customFields": {},
|
"customFields": {},
|
||||||
|
"headTags": [],
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"localeConfigs": {
|
"localeConfigs": {
|
||||||
|
|
|
@ -351,6 +351,74 @@ describe('normalizeConfig', () => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('accepts headTags with tagName and attributes', () => {
|
||||||
|
expect(() => {
|
||||||
|
normalizeConfig({
|
||||||
|
headTags: [
|
||||||
|
{
|
||||||
|
tagName: 'link',
|
||||||
|
attributes: {
|
||||||
|
rel: 'icon',
|
||||||
|
href: 'img/docusaurus.png',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws error if headTags doesn't have tagName", () => {
|
||||||
|
expect(() => {
|
||||||
|
normalizeConfig({
|
||||||
|
headTags: [
|
||||||
|
{
|
||||||
|
attributes: {
|
||||||
|
rel: 'icon',
|
||||||
|
href: 'img/docusaurus.png',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}).toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
""headTags[0].tagName" is required
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws error if headTags doesn't have attributes", () => {
|
||||||
|
expect(() => {
|
||||||
|
normalizeConfig({
|
||||||
|
headTags: [
|
||||||
|
{
|
||||||
|
tagName: 'link',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}).toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
""headTags[0].attributes" is required
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws error if headTags doesn't have string attributes", () => {
|
||||||
|
expect(() => {
|
||||||
|
normalizeConfig({
|
||||||
|
headTags: [
|
||||||
|
{
|
||||||
|
tagName: 'link',
|
||||||
|
attributes: {
|
||||||
|
rel: false,
|
||||||
|
href: 'img/docusaurus.png',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}).toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
""headTags[0].attributes.rel" must be a string
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it("throws error if css doesn't have href", () => {
|
it("throws error if css doesn't have href", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
normalizeConfig({
|
normalizeConfig({
|
||||||
|
|
|
@ -33,6 +33,7 @@ export const DEFAULT_CONFIG: Pick<
|
||||||
| 'plugins'
|
| 'plugins'
|
||||||
| 'themes'
|
| 'themes'
|
||||||
| 'presets'
|
| 'presets'
|
||||||
|
| 'headTags'
|
||||||
| 'stylesheets'
|
| 'stylesheets'
|
||||||
| 'scripts'
|
| 'scripts'
|
||||||
| 'clientModules'
|
| 'clientModules'
|
||||||
|
@ -51,6 +52,7 @@ export const DEFAULT_CONFIG: Pick<
|
||||||
plugins: [],
|
plugins: [],
|
||||||
themes: [],
|
themes: [],
|
||||||
presets: [],
|
presets: [],
|
||||||
|
headTags: [],
|
||||||
stylesheets: [],
|
stylesheets: [],
|
||||||
scripts: [],
|
scripts: [],
|
||||||
clientModules: [],
|
clientModules: [],
|
||||||
|
@ -222,6 +224,20 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({
|
||||||
})
|
})
|
||||||
.default(DEFAULT_CONFIG.scripts),
|
.default(DEFAULT_CONFIG.scripts),
|
||||||
ssrTemplate: Joi.string(),
|
ssrTemplate: Joi.string(),
|
||||||
|
headTags: Joi.array()
|
||||||
|
.items(
|
||||||
|
Joi.object({
|
||||||
|
tagName: Joi.string().required(),
|
||||||
|
attributes: Joi.object()
|
||||||
|
.pattern(/[\w-]+/, Joi.string())
|
||||||
|
.required(),
|
||||||
|
}).unknown(),
|
||||||
|
)
|
||||||
|
.messages({
|
||||||
|
'array.includes':
|
||||||
|
'{#label} is invalid. A headTag must be an object with at least a "tagName" and an "attributes" property.',
|
||||||
|
})
|
||||||
|
.default(DEFAULT_CONFIG.headTags),
|
||||||
stylesheets: Joi.array()
|
stylesheets: Joi.array()
|
||||||
.items(
|
.items(
|
||||||
Joi.string(),
|
Joi.string(),
|
||||||
|
|
|
@ -21,6 +21,7 @@ export function createBootstrapPlugin({
|
||||||
const {
|
const {
|
||||||
stylesheets,
|
stylesheets,
|
||||||
scripts,
|
scripts,
|
||||||
|
headTags,
|
||||||
clientModules: siteConfigClientModules,
|
clientModules: siteConfigClientModules,
|
||||||
} = siteConfig;
|
} = siteConfig;
|
||||||
return {
|
return {
|
||||||
|
@ -58,7 +59,7 @@ export function createBootstrapPlugin({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
headTags: [...stylesheetsTags, ...scriptsTags],
|
headTags: [...headTags, ...stylesheetsTags, ...scriptsTags],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -429,6 +429,30 @@ module.exports = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `headTags` {#headTags}
|
||||||
|
|
||||||
|
An array of tags that will be inserted in the HTML `<head>`. The values must be objects that contain two properties; `tagName` and `attributes`. `tagName` must be a string that determines the tag being created; eg `"link"`. `attributes` must be an attribute-value map.
|
||||||
|
|
||||||
|
- Type: `{ tagName: string; attributes: Object; }[]`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js title="docusaurus.config.js"
|
||||||
|
module.exports = {
|
||||||
|
headTags: [
|
||||||
|
{
|
||||||
|
tagName: 'link',
|
||||||
|
attributes: {
|
||||||
|
rel: 'icon',
|
||||||
|
href: '/img/docusaurus.png',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This would become `<link rel="icon" href="img/docusaurus.png" />` in the generated HTML.
|
||||||
|
|
||||||
### `scripts` {#scripts}
|
### `scripts` {#scripts}
|
||||||
|
|
||||||
An array of scripts to load. The values can be either strings or plain objects of attribute-value maps. The `<script>` tags will be inserted in the HTML `<head>`. If you use a plain object, the only required attribute is `src`, and any other attributes are permitted (each one should have boolean/string values).
|
An array of scripts to load. The values can be either strings or plain objects of attribute-value maps. The `<script>` tags will be inserted in the HTML `<head>`. If you use a plain object, the only required attribute is `src`, and any other attributes are permitted (each one should have boolean/string values).
|
||||||
|
|
Loading…
Add table
Reference in a new issue