feat(core): support custom html elements in head tags (#11571)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run

Co-authored-by: sebastien <lorber.sebastien@gmail.com>
This commit is contained in:
Balthasar Hofer 2025-11-27 11:19:53 +01:00 committed by GitHub
parent d379344e6a
commit c6a86ff717
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 35 additions and 10 deletions

View File

@ -104,6 +104,8 @@ export type HtmlTagObject = {
tagName: string;
/** The inner HTML */
innerHTML?: string;
/** Allow custom html elements, e.g. `<custom-element>` */
customElement?: boolean;
};
export type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];

View File

@ -315,6 +315,19 @@ describe('headTags', () => {
`);
});
it('accepts headTags with a custom element without attributes', () => {
expect(() =>
normalizeConfig({
headTags: [
{
tagName: 'my-custom-element',
customElement: true,
},
],
}),
).not.toThrow();
});
it("throws error if headTags doesn't have string attributes", () => {
expect(() => {
normalizeConfig({

View File

@ -189,7 +189,7 @@ describe('loadHtmlTags', () => {
},
]),
).toThrowErrorMatchingInlineSnapshot(
`"Error loading {"tagName":"endiliey","attributes":{"this":"is invalid"}}, "endiliey" is not a valid HTML tag."`,
`"Error loading {"tagName":"endiliey","attributes":{"this":"is invalid"}}, "endiliey" is not a valid HTML tag. Either use a valid "tagName" or set "customElement: true"."`,
);
});

View File

@ -437,9 +437,14 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({
.items(
Joi.object({
tagName: Joi.string().required(),
attributes: Joi.object()
.pattern(/[\w-]+/, Joi.string())
.required(),
attributes: Joi.object().when('customElement', {
is: Joi.valid(true),
then: Joi.optional(),
otherwise: Joi.object()
.pattern(/[\w-]+/, Joi.string())
.required(),
}),
customElement: Joi.bool().default(false),
}).unknown(),
)
.messages({

View File

@ -17,22 +17,27 @@ import type {
RouterType,
} from '@docusaurus/types';
// TODO this should be done at config validation time, not here
function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject {
if (typeof val !== 'object' || !val) {
throw new Error(`"${val}" is not a valid HTML tag object.`);
}
if (typeof (val as HtmlTagObject).tagName !== 'string') {
const htmlTag = val as HtmlTagObject;
if (typeof htmlTag.tagName !== 'string') {
throw new Error(
`${JSON.stringify(
val,
)} is not a valid HTML tag object. "tagName" must be defined as a string.`,
);
}
if (!(htmlTags as string[]).includes((val as HtmlTagObject).tagName)) {
if (
!htmlTag.customElement &&
!(htmlTags as string[]).includes(htmlTag.tagName)
) {
throw new Error(
`Error loading ${JSON.stringify(val)}, "${
(val as HtmlTagObject).tagName
}" is not a valid HTML tag.`,
htmlTag.tagName
}" is not a valid HTML tag. Either use a valid "tagName" or set "customElement: true".`,
);
}
}

View File

@ -767,9 +767,9 @@ export default {
### `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.
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. When custom html elements are needed, set `customElement: true`.
- Type: `{ tagName: string; attributes: Object; }[]`
- Type: `{ tagName: string; attributes: Object; customElement?: boolean; }[]`
Example: