feat(docs, blog): add support for tags.yml, predefined list of tags (#10137)

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
Co-authored-by: OzakIOne <OzakIOne@users.noreply.github.com>
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
Co-authored-by: slorber <slorber@users.noreply.github.com>
This commit is contained in:
ozaki 2024-05-31 17:32:08 +02:00 committed by GitHub
parent 1049294ba6
commit 0eb7b64aac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
63 changed files with 2597 additions and 722 deletions

View file

@ -5,6 +5,7 @@ slug: bazSlug.html
pagination_label: baz pagination_label
tags:
- tag 1
- globalTag1
- tag-1
- label: tag 2
permalink: tag2-custom-permalink

View file

@ -0,0 +1,5 @@
globalTag1:
label: 'Global Tag 1 label'
description: 'Global Tag 1 description'
permalink: 'global-tag-1-permalink'

View file

@ -1,4 +1,6 @@
---
slug: /
tags: [inlineTag-v1.0.0, globalTag-v1.0.0]
---
Hello `1.0.0` ! (translated en)

View file

@ -0,0 +1,5 @@
globalTag-v1.0.0:
label: 'globalTag-v1.0.0 label (en)'
description: 'globalTag-v1.0.0 description (en)'
permalink: 'globalTag-v1.0.0 permalink (en)'

View file

@ -1,4 +1,6 @@
---
slug: /
tags: [inlineTag-v1.0.0, globalTag-v1.0.0]
---
Hello `1.0.0` ! (translated fr)

View file

@ -0,0 +1,5 @@
globalTag-v1.0.0:
label: 'globalTag-v1.0.0 label (fr)'
description: 'globalTag-v1.0.0 description (fr)'
permalink: 'globalTag-v1.0.0 permalink (fr)'

View file

@ -1,4 +1,6 @@
---
slug: /
tags: [inlineTag-v1.0.0, globalTag-v1.0.0]
---
Hello `1.0.0` !

View file

@ -0,0 +1,5 @@
globalTag-v1.0.0:
label: 'globalTag-v1.0.0 label'
description: 'globalTag-v1.0.0 description'
permalink: 'globalTag-v1.0.0 permalink'

View file

@ -1,4 +1,6 @@
---
slug: /
tags: [inlineTag-v1.0.1, globalTag-v1.0.1]
---
Hello `1.0.1` !

View file

@ -0,0 +1,5 @@
globalTag-v1.0.1:
label: 'globalTag-v1.0.1 label'
description: 'globalTag-v1.0.1 description'
permalink: 'globalTag-v1.0.1 permalink'

View file

@ -58,6 +58,7 @@ exports[`simple website content 1`] = `
"slug": "bazSlug.html",
"tags": [
"tag 1",
"globalTag1",
"tag-1",
{
"label": "tag 2",
@ -85,10 +86,26 @@ exports[`simple website content 1`] = `
"sourceDirName": "foo",
"tags": [
{
"description": undefined,
"inline": true,
"label": "tag 1",
"permalink": "/docs/tags/tag-1",
},
{
"description": "Global Tag 1 description",
"inline": false,
"label": "Global Tag 1 label",
"permalink": "/docs/tags/global-tag-1-permalink",
},
{
"description": undefined,
"inline": true,
"label": "tag-1",
"permalink": "/docs/tags/tag-1",
},
{
"description": undefined,
"inline": true,
"label": "tag 2",
"permalink": "/docs/tags/tag2-custom-permalink",
},
@ -130,10 +147,14 @@ exports[`simple website content 2`] = `
"sourceDirName": ".",
"tags": [
{
"description": undefined,
"inline": true,
"label": "tag-1",
"permalink": "/docs/tags/tag-1",
},
{
"description": undefined,
"inline": true,
"label": "tag 3",
"permalink": "/docs/tags/tag-3",
},
@ -567,6 +588,7 @@ exports[`simple website content: data 1`] = `
"slug": "bazSlug.html",
"tags": [
"tag 1",
"globalTag1",
"tag-1",
{
"label": "tag 2",
@ -594,10 +616,26 @@ exports[`simple website content: data 1`] = `
"sourceDirName": "foo",
"tags": [
{
"description": undefined,
"inline": true,
"label": "tag 1",
"permalink": "/docs/tags/tag-1",
},
{
"description": "Global Tag 1 description",
"inline": false,
"label": "Global Tag 1 label",
"permalink": "/docs/tags/global-tag-1-permalink",
},
{
"description": undefined,
"inline": true,
"label": "tag-1",
"permalink": "/docs/tags/tag-1",
},
{
"description": undefined,
"inline": true,
"label": "tag 2",
"permalink": "/docs/tags/tag2-custom-permalink",
},
@ -663,10 +701,14 @@ exports[`simple website content: data 1`] = `
"sourceDirName": ".",
"tags": [
{
"description": undefined,
"inline": true,
"label": "tag-1",
"permalink": "/docs/tags/tag-1",
},
{
"description": undefined,
"inline": true,
"label": "tag 3",
"permalink": "/docs/tags/tag-3",
},
@ -1520,22 +1562,54 @@ exports[`simple website content: route config 1`] = `
"tags": [
{
"count": 2,
"description": undefined,
"label": "tag 1",
"permalink": "/docs/tags/tag-1",
},
{
"count": 1,
"description": "Global Tag 1 description",
"label": "Global Tag 1 label",
"permalink": "/docs/tags/global-tag-1-permalink",
},
{
"count": 1,
"description": undefined,
"label": "tag 2",
"permalink": "/docs/tags/tag2-custom-permalink",
},
{
"count": 1,
"description": undefined,
"label": "tag 3",
"permalink": "/docs/tags/tag-3",
},
],
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
"path": "/docs/tags/global-tag-1-permalink",
"props": {
"tag": {
"allTagsPath": "/docs/tags",
"count": 1,
"description": "Global Tag 1 description",
"items": [
{
"description": "Images",
"id": "foo/baz",
"permalink": "/docs/foo/bazSlug.html",
"title": "baz",
},
],
"label": "Global Tag 1 label",
"permalink": "/docs/tags/global-tag-1-permalink",
"unlisted": false,
},
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
@ -1544,6 +1618,7 @@ exports[`simple website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/tags",
"count": 2,
"description": undefined,
"items": [
{
"description": "Images",
@ -1572,6 +1647,7 @@ exports[`simple website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "Hi, Endilie here :)",
@ -1594,6 +1670,7 @@ exports[`simple website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "Images",
@ -1929,6 +2006,8 @@ exports[`simple website getPathToWatch 1`] = `
"sidebars.json",
"i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}",
"docs/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs/current/tags.yml",
"docs/tags.yml",
"docs/**/_category_.{json,yml,yaml}",
]
`;
@ -3249,10 +3328,14 @@ exports[`versioned website (community) getPathToWatch 1`] = `
"community_sidebars.json",
"i18n/en/docusaurus-plugin-content-docs-community/current/**/*.{md,mdx}",
"community/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs-community/current/tags.yml",
"community/tags.yml",
"community/**/_category_.{json,yml,yaml}",
"community_versioned_sidebars/version-1.0.0-sidebars.json",
"i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/**/*.{md,mdx}",
"community_versioned_docs/version-1.0.0/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/tags.yml",
"community_versioned_docs/version-1.0.0/tags.yml",
"community_versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}",
]
`;
@ -3289,14 +3372,20 @@ exports[`versioned website content 1`] = `
"sourceDirName": "foo",
"tags": [
{
"description": undefined,
"inline": true,
"label": "barTag 1",
"permalink": "/docs/next/tags/bar-tag-1",
},
{
"description": undefined,
"inline": true,
"label": "barTag-2",
"permalink": "/docs/next/tags/bar-tag-2",
},
{
"description": undefined,
"inline": true,
"label": "barTag 3",
"permalink": "/docs/next/tags/barTag-3-permalink",
},
@ -3370,6 +3459,10 @@ exports[`versioned website content 4`] = `
"editUrl": undefined,
"frontMatter": {
"slug": "/",
"tags": [
"inlineTag-v1.0.1",
"globalTag-v1.0.1",
],
},
"id": "hello",
"lastUpdatedAt": undefined,
@ -3385,7 +3478,20 @@ exports[`versioned website content 4`] = `
"slug": "/",
"source": "@site/versioned_docs/version-1.0.1/hello.md",
"sourceDirName": ".",
"tags": [],
"tags": [
{
"description": undefined,
"inline": true,
"label": "inlineTag-v1.0.1",
"permalink": "/docs/tags/inline-tag-v-1-0-1",
},
{
"description": "globalTag-v1.0.1 description",
"inline": false,
"label": "globalTag-v1.0.1 label",
"permalink": "/docs/tags/globalTag-v1.0.1 permalink",
},
],
"title": "hello",
"unlisted": false,
"version": "1.0.1",
@ -3558,14 +3664,20 @@ exports[`versioned website content: data 1`] = `
"sourceDirName": "foo",
"tags": [
{
"description": undefined,
"inline": true,
"label": "barTag 1",
"permalink": "/docs/next/tags/bar-tag-1",
},
{
"description": undefined,
"inline": true,
"label": "barTag-2",
"permalink": "/docs/next/tags/bar-tag-2",
},
{
"description": undefined,
"inline": true,
"label": "barTag 3",
"permalink": "/docs/next/tags/barTag-3-permalink",
},
@ -3698,6 +3810,10 @@ exports[`versioned website content: data 1`] = `
"editUrl": undefined,
"frontMatter": {
"slug": "/",
"tags": [
"inlineTag-v1.0.0",
"globalTag-v1.0.0",
],
},
"id": "hello",
"lastUpdatedAt": undefined,
@ -3713,7 +3829,20 @@ exports[`versioned website content: data 1`] = `
"slug": "/",
"source": "@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md",
"sourceDirName": ".",
"tags": [],
"tags": [
{
"description": undefined,
"inline": true,
"label": "inlineTag-v1.0.0",
"permalink": "/docs/1.0.0/tags/inline-tag-v-1-0-0",
},
{
"description": "globalTag-v1.0.0 description (en)",
"inline": false,
"label": "globalTag-v1.0.0 label (en)",
"permalink": "/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)",
},
],
"title": "hello",
"unlisted": false,
"version": "1.0.0",
@ -3801,6 +3930,10 @@ exports[`versioned website content: data 1`] = `
"editUrl": undefined,
"frontMatter": {
"slug": "/",
"tags": [
"inlineTag-v1.0.1",
"globalTag-v1.0.1",
],
},
"id": "hello",
"lastUpdatedAt": undefined,
@ -3816,7 +3949,20 @@ exports[`versioned website content: data 1`] = `
"slug": "/",
"source": "@site/versioned_docs/version-1.0.1/hello.md",
"sourceDirName": ".",
"tags": [],
"tags": [
{
"description": undefined,
"inline": true,
"label": "inlineTag-v1.0.1",
"permalink": "/docs/tags/inline-tag-v-1-0-1",
},
{
"description": "globalTag-v1.0.1 description",
"inline": false,
"label": "globalTag-v1.0.1 label",
"permalink": "/docs/tags/globalTag-v1.0.1 permalink",
},
],
"title": "hello",
"unlisted": false,
"version": "1.0.1",
@ -4280,6 +4426,73 @@ exports[`versioned website content: route config 1`] = `
},
},
"routes": [
{
"component": "@theme/DocTagsListPage",
"exact": true,
"path": "/docs/1.0.0/tags",
"props": {
"tags": [
{
"count": 1,
"description": undefined,
"label": "inlineTag-v1.0.0",
"permalink": "/docs/1.0.0/tags/inline-tag-v-1-0-0",
},
{
"count": 1,
"description": "globalTag-v1.0.0 description (en)",
"label": "globalTag-v1.0.0 label (en)",
"permalink": "/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)",
},
],
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
"path": "/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)",
"props": {
"tag": {
"allTagsPath": "/docs/1.0.0/tags",
"count": 1,
"description": "globalTag-v1.0.0 description (en)",
"items": [
{
"description": "Hello 1.0.0 ! (translated en)",
"id": "hello",
"permalink": "/docs/1.0.0/",
"title": "hello",
},
],
"label": "globalTag-v1.0.0 label (en)",
"permalink": "/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)",
"unlisted": false,
},
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
"path": "/docs/1.0.0/tags/inline-tag-v-1-0-0",
"props": {
"tag": {
"allTagsPath": "/docs/1.0.0/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "Hello 1.0.0 ! (translated en)",
"id": "hello",
"permalink": "/docs/1.0.0/",
"title": "hello",
},
],
"label": "inlineTag-v1.0.0",
"permalink": "/docs/1.0.0/tags/inline-tag-v-1-0-0",
"unlisted": false,
},
},
},
{
"component": "@theme/DocRoot",
"exact": false,
@ -4430,16 +4643,19 @@ exports[`versioned website content: route config 1`] = `
"tags": [
{
"count": 1,
"description": undefined,
"label": "barTag 1",
"permalink": "/docs/next/tags/bar-tag-1",
},
{
"count": 1,
"description": undefined,
"label": "barTag-2",
"permalink": "/docs/next/tags/bar-tag-2",
},
{
"count": 1,
"description": undefined,
"label": "barTag 3",
"permalink": "/docs/next/tags/barTag-3-permalink",
},
@ -4454,6 +4670,7 @@ exports[`versioned website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/next/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "This is next version of bar.",
@ -4476,6 +4693,7 @@ exports[`versioned website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/next/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "This is next version of bar.",
@ -4498,6 +4716,7 @@ exports[`versioned website content: route config 1`] = `
"tag": {
"allTagsPath": "/docs/next/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "This is next version of bar.",
@ -4860,6 +5079,73 @@ exports[`versioned website content: route config 1`] = `
},
},
"routes": [
{
"component": "@theme/DocTagsListPage",
"exact": true,
"path": "/docs/tags",
"props": {
"tags": [
{
"count": 1,
"description": undefined,
"label": "inlineTag-v1.0.1",
"permalink": "/docs/tags/inline-tag-v-1-0-1",
},
{
"count": 1,
"description": "globalTag-v1.0.1 description",
"label": "globalTag-v1.0.1 label",
"permalink": "/docs/tags/globalTag-v1.0.1 permalink",
},
],
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
"path": "/docs/tags/globalTag-v1.0.1 permalink",
"props": {
"tag": {
"allTagsPath": "/docs/tags",
"count": 1,
"description": "globalTag-v1.0.1 description",
"items": [
{
"description": "Hello 1.0.1 !",
"id": "hello",
"permalink": "/docs/",
"title": "hello",
},
],
"label": "globalTag-v1.0.1 label",
"permalink": "/docs/tags/globalTag-v1.0.1 permalink",
"unlisted": false,
},
},
},
{
"component": "@theme/DocTagDocListPage",
"exact": true,
"path": "/docs/tags/inline-tag-v-1-0-1",
"props": {
"tag": {
"allTagsPath": "/docs/tags",
"count": 1,
"description": undefined,
"items": [
{
"description": "Hello 1.0.1 !",
"id": "hello",
"permalink": "/docs/",
"title": "hello",
},
],
"label": "inlineTag-v1.0.1",
"permalink": "/docs/tags/inline-tag-v-1-0-1",
"unlisted": false,
},
},
},
{
"component": "@theme/DocRoot",
"exact": false,
@ -4925,18 +5211,26 @@ exports[`versioned website getPathToWatch 1`] = `
"sidebars.json",
"i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}",
"docs/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs/current/tags.yml",
"docs/tags.yml",
"docs/**/_category_.{json,yml,yaml}",
"versioned_sidebars/version-1.0.1-sidebars.json",
"i18n/en/docusaurus-plugin-content-docs/version-1.0.1/**/*.{md,mdx}",
"versioned_docs/version-1.0.1/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs/version-1.0.1/tags.yml",
"versioned_docs/version-1.0.1/tags.yml",
"versioned_docs/version-1.0.1/**/_category_.{json,yml,yaml}",
"versioned_sidebars/version-1.0.0-sidebars.json",
"i18n/en/docusaurus-plugin-content-docs/version-1.0.0/**/*.{md,mdx}",
"versioned_docs/version-1.0.0/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs/version-1.0.0/tags.yml",
"versioned_docs/version-1.0.0/tags.yml",
"versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}",
"versioned_sidebars/version-withSlugs-sidebars.json",
"i18n/en/docusaurus-plugin-content-docs/version-withSlugs/**/*.{md,mdx}",
"versioned_docs/version-withSlugs/**/*.{md,mdx}",
"i18n/en/docusaurus-plugin-content-docs/version-withSlugs/tags.yml",
"versioned_docs/version-withSlugs/tags.yml",
"versioned_docs/version-withSlugs/**/_category_.{json,yml,yaml}",
]
`;

View file

@ -6,7 +6,7 @@
*/
import {jest} from '@jest/globals';
import path from 'path';
import * as path from 'path';
import {loadContext} from '@docusaurus/core/src/server/site';
import {
createSlugger,
@ -14,6 +14,7 @@ import {
DEFAULT_PLUGIN_ID,
LAST_UPDATE_FALLBACK,
} from '@docusaurus/utils';
import {getTagsFile} from '@docusaurus/utils-validation';
import {createSidebarsUtils} from '../sidebars/utils';
import {
processDocMetadata,
@ -73,13 +74,18 @@ type TestUtilsArg = {
env?: DocEnv;
};
function createTestUtils({
async function createTestUtils({
siteDir,
context,
versionMetadata,
options,
env = 'production',
}: TestUtilsArg) {
const tagsFile = await getTagsFile({
contentPaths: versionMetadata,
tags: options.tags,
});
async function readDoc(docFileSource: string) {
return readDocFile(versionMetadata, docFileSource);
}
@ -93,6 +99,7 @@ function createTestUtils({
options,
context,
env,
tagsFile,
});
}
@ -139,6 +146,7 @@ function createTestUtils({
context,
options,
env,
tagsFile: null,
});
expect(metadata.permalink).toEqual(expectedPermalink);
}
@ -159,6 +167,7 @@ function createTestUtils({
context,
options,
env,
tagsFile: null,
}),
),
);
@ -181,7 +190,6 @@ function createTestUtils({
pagination: addDocNavigation({
docs: rawDocs,
sidebarsUtils,
sidebarFilePath: versionMetadata.sidebarFilePath as string,
}).map((doc) => ({prev: doc.previous, next: doc.next, id: doc.id})),
sidebars,
};
@ -214,7 +222,7 @@ describe('simple site', () => {
expect(versionsMetadata).toHaveLength(1);
const currentVersion = versionsMetadata[0]!;
function createTestUtilsPartial(args: Partial<TestUtilsArg>) {
async function createTestUtilsPartial(args: Partial<TestUtilsArg>) {
return createTestUtils({
siteDir,
context,
@ -224,7 +232,7 @@ describe('simple site', () => {
});
}
const defaultTestUtils = createTestUtilsPartial({});
const defaultTestUtils = await createTestUtilsPartial({});
return {
siteDir,
@ -296,6 +304,7 @@ describe('simple site', () => {
slug: '/',
title: 'Hello, World !',
description: `Hi, Endilie here :)`,
sidebarPosition: undefined,
frontMatter: {
id: 'hello',
title: 'Hello, World !',
@ -306,11 +315,15 @@ describe('simple site', () => {
tags: [
{
label: 'tag-1',
inline: true,
permalink: '/docs/tags/tag-1',
description: undefined,
},
{
label: 'tag 3',
inline: true,
permalink: '/docs/tags/tag-3',
description: undefined,
},
],
unlisted: false,
@ -325,7 +338,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -339,6 +352,7 @@ describe('simple site', () => {
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'baz',
sidebarPosition: undefined,
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs/foo/baz.md',
description: 'Images',
@ -349,17 +363,34 @@ describe('simple site', () => {
pagination_label: 'baz pagination_label',
tags: [
'tag 1',
'globalTag1',
'tag-1',
{label: 'tag 2', permalink: 'tag2-custom-permalink'},
],
},
tags: [
{
description: undefined,
inline: true,
label: 'tag 1',
permalink: '/docs/tags/tag-1',
},
{
description: 'Global Tag 1 description',
inline: false,
label: 'Global Tag 1 label',
permalink: '/docs/tags/global-tag-1-permalink',
},
{
description: undefined,
inline: true,
label: 'tag-1',
permalink: '/docs/tags/tag-1',
},
{
label: 'tag 2',
description: undefined,
inline: true,
permalink: '/docs/tags/tag2-custom-permalink',
},
],
@ -400,7 +431,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -416,6 +447,7 @@ describe('simple site', () => {
title: 'baz',
editUrl: hardcodedEditUrl,
description: 'Images',
sidebarPosition: undefined,
frontMatter: {
id: 'baz',
slug: 'bazSlug.html',
@ -423,16 +455,33 @@ describe('simple site', () => {
pagination_label: 'baz pagination_label',
tags: [
'tag 1',
'globalTag1',
'tag-1',
{label: 'tag 2', permalink: 'tag2-custom-permalink'},
],
},
tags: [
{
description: undefined,
inline: true,
label: 'tag 1',
permalink: '/docs/tags/tag-1',
},
{
description: 'Global Tag 1 description',
inline: false,
label: 'Global Tag 1 label',
permalink: '/docs/tags/global-tag-1-permalink',
},
{
description: undefined,
inline: true,
label: 'tag-1',
permalink: '/docs/tags/tag-1',
},
{
description: undefined,
inline: true,
label: 'tag 2',
permalink: '/docs/tags/tag2-custom-permalink',
},
@ -459,7 +508,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -489,7 +538,7 @@ describe('simple site', () => {
it('docs with draft frontmatter', async () => {
const {createTestUtilsPartial} = await loadSite();
const testUtilsProd = createTestUtilsPartial({
const testUtilsProd = await createTestUtilsPartial({
env: 'production',
});
await expect(
@ -498,7 +547,7 @@ describe('simple site', () => {
draft: true,
});
const testUtilsDev = createTestUtilsPartial({
const testUtilsDev = await createTestUtilsPartial({
env: 'development',
});
await expect(
@ -526,7 +575,7 @@ describe('simple site', () => {
tags: [],
};
const testUtilsProd = createTestUtilsPartial({
const testUtilsProd = await createTestUtilsPartial({
env: 'production',
});
@ -535,7 +584,7 @@ describe('simple site', () => {
unlisted: true,
});
const testUtilsDev = createTestUtilsPartial({
const testUtilsDev = await createTestUtilsPartial({
env: 'development',
});
@ -554,7 +603,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -593,7 +642,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -631,7 +680,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -669,7 +718,7 @@ describe('simple site', () => {
},
});
const testUtilsLocal = createTestUtilsPartial({
const testUtilsLocal = await createTestUtilsPartial({
siteDir,
context,
options,
@ -761,7 +810,7 @@ describe('simple site', () => {
it('custom pagination - production', async () => {
const {createTestUtilsPartial, options, versionsMetadata} =
await loadSite();
const testUtils = createTestUtilsPartial({env: 'production'});
const testUtils = await createTestUtilsPartial({env: 'production'});
const docs = await readVersionDocs(versionsMetadata[0]!, options);
await expect(testUtils.generateNavigation(docs)).resolves.toMatchSnapshot();
});
@ -769,7 +818,7 @@ describe('simple site', () => {
it('custom pagination - development', async () => {
const {createTestUtilsPartial, options, versionsMetadata} =
await loadSite();
const testUtils = createTestUtilsPartial({env: 'development'});
const testUtils = await createTestUtilsPartial({env: 'development'});
const docs = await readVersionDocs(versionsMetadata[0]!, options);
await expect(testUtils.generateNavigation(docs)).resolves.toMatchSnapshot();
});
@ -818,27 +867,27 @@ describe('versioned site', () => {
const version100 = versionsMetadata[2]!;
const versionWithSlugs = versionsMetadata[3]!;
const currentVersionTestUtils = createTestUtils({
const currentVersionTestUtils = await createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
const version101TestUtils = createTestUtils({
const version101TestUtils = await createTestUtils({
siteDir,
context,
options,
versionMetadata: version101,
});
const version100TestUtils = createTestUtils({
const version100TestUtils = await createTestUtils({
siteDir,
context,
options,
versionMetadata: version100,
});
const versionWithSlugsTestUtils = createTestUtils({
const versionWithSlugsTestUtils = await createTestUtils({
siteDir,
context,
options,
@ -869,6 +918,7 @@ describe('versioned site', () => {
slug: '/foo/barSlug',
title: 'bar',
description: 'This is next version of bar.',
sidebarPosition: undefined,
frontMatter: {
slug: 'barSlug',
tags: [
@ -883,15 +933,21 @@ describe('versioned site', () => {
tags: [
{
label: 'barTag 1',
inline: true,
permalink: '/docs/next/tags/bar-tag-1',
description: undefined,
},
{
label: 'barTag-2',
inline: true,
permalink: '/docs/next/tags/bar-tag-2',
description: undefined,
},
{
label: 'barTag 3',
inline: true,
permalink: '/docs/next/tags/barTag-3-permalink',
description: undefined,
},
],
unlisted: false,
@ -936,11 +992,25 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated en)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (en)',
inline: false,
label: 'globalTag-v1.0.0 label (en)',
permalink: '/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)',
},
],
unlisted: false,
});
await version101TestUtils.testMeta(path.join('foo', 'bar.md'), {
@ -965,8 +1035,22 @@ describe('versioned site', () => {
version: '1.0.1',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.1', 'globalTag-v1.0.1'],
},
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.1',
permalink: '/docs/tags/inline-tag-v-1-0-1',
},
{
description: 'globalTag-v1.0.1 description',
inline: false,
label: 'globalTag-v1.0.1 label',
permalink: '/docs/tags/globalTag-v1.0.1 permalink',
},
],
unlisted: false,
});
});
@ -1041,7 +1125,7 @@ describe('versioned site', () => {
},
});
const testUtilsLocal = createTestUtils({
const testUtilsLocal = await createTestUtils({
siteDir,
context,
options,
@ -1057,12 +1141,26 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated en)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl: hardcodedEditUrl,
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (en)',
inline: false,
label: 'globalTag-v1.0.0 label (en)',
permalink: '/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)',
},
],
unlisted: false,
});
@ -1083,7 +1181,7 @@ describe('versioned site', () => {
},
});
const testUtilsLocal = createTestUtils({
const testUtilsLocal = await createTestUtils({
siteDir,
context,
options,
@ -1099,13 +1197,27 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated en)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0/hello.md',
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (en)',
inline: false,
label: 'globalTag-v1.0.0 label (en)',
permalink: '/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)',
},
],
unlisted: false,
});
});
@ -1118,7 +1230,7 @@ describe('versioned site', () => {
},
});
const testUtilsLocal = createTestUtils({
const testUtilsLocal = await createTestUtils({
siteDir,
context,
options,
@ -1134,13 +1246,27 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated en)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs/hello.md',
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (en)',
inline: false,
label: 'globalTag-v1.0.0 label (en)',
permalink: '/docs/1.0.0/tags/globalTag-v1.0.0 permalink (en)',
},
],
unlisted: false,
});
});
@ -1154,7 +1280,7 @@ describe('versioned site', () => {
locale: 'fr',
});
const testUtilsLocal = createTestUtils({
const testUtilsLocal = await createTestUtils({
siteDir,
context,
options,
@ -1170,13 +1296,27 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated fr)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/fr/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (fr)',
inline: false,
label: 'globalTag-v1.0.0 label (fr)',
permalink: '/fr/docs/1.0.0/tags/globalTag-v1.0.0 permalink (fr)',
},
],
unlisted: false,
});
});
@ -1191,7 +1331,7 @@ describe('versioned site', () => {
locale: 'fr',
});
const testUtilsLocal = createTestUtils({
const testUtilsLocal = await createTestUtils({
siteDir,
context,
options,
@ -1207,13 +1347,27 @@ describe('versioned site', () => {
description: 'Hello 1.0.0 ! (translated fr)',
frontMatter: {
slug: '/',
tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'],
},
version: '1.0.0',
source:
'@site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/current/hello.md',
tags: [],
tags: [
{
description: undefined,
inline: true,
label: 'inlineTag-v1.0.0',
permalink: '/fr/docs/1.0.0/tags/inline-tag-v-1-0-0',
},
{
description: 'globalTag-v1.0.0 description (fr)',
inline: false,
label: 'globalTag-v1.0.0 label (fr)',
permalink: '/fr/docs/1.0.0/tags/globalTag-v1.0.0 permalink (fr)',
},
],
unlisted: false,
});
});

View file

@ -70,6 +70,8 @@ describe('normalizeDocsPluginOptions', () => {
disableVersioning: true,
editCurrentVersion: true,
editLocalizedFiles: true,
tags: 'docsTags.yml',
onInlineTags: 'throw',
versions: {
current: {
path: 'next',
@ -266,4 +268,68 @@ describe('normalizeDocsPluginOptions', () => {
}).sidebarCollapsed,
).toBe(false);
});
describe('tags', () => {
it('accepts tags - undefined', () => {
expect(testValidate({tags: undefined}).tags).toBeUndefined();
});
it('accepts tags - null', () => {
expect(testValidate({tags: null}).tags).toBeNull();
});
it('accepts tags - false', () => {
expect(testValidate({tags: false}).tags).toBeFalsy();
});
it('accepts tags - customTags.yml', () => {
expect(testValidate({tags: 'customTags.yml'}).tags).toBe(
'customTags.yml',
);
});
it('rejects tags - 42', () => {
// @ts-expect-error: test
expect(() => testValidate({tags: 42})).toThrowErrorMatchingInlineSnapshot(
`""tags" must be a string"`,
);
});
});
describe('onInlineTags', () => {
it('accepts onInlineTags - undefined', () => {
expect(testValidate({onInlineTags: undefined}).onInlineTags).toBe('warn');
});
it('accepts onInlineTags - "throw"', () => {
expect(testValidate({onInlineTags: 'throw'}).onInlineTags).toBe('throw');
});
it('rejects onInlineTags - "trace"', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onInlineTags: 'trace'}),
).toThrowErrorMatchingInlineSnapshot(
`""onInlineTags" must be one of [ignore, log, warn, throw]"`,
);
});
it('rejects onInlineTags - null', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onInlineTags: 42}),
).toThrowErrorMatchingInlineSnapshot(
`""onInlineTags" must be one of [ignore, log, warn, throw]"`,
);
});
it('rejects onInlineTags - 42', () => {
expect(() =>
// @ts-expect-error: test
testValidate({onInlineTags: 42}),
).toThrowErrorMatchingInlineSnapshot(
`""onInlineTags" must be one of [ignore, log, warn, throw]"`,
);
});
});
});

View file

@ -17,15 +17,16 @@ import {
parseMarkdownFile,
posixPath,
Globby,
normalizeFrontMatterTags,
isUnlisted,
isDraft,
readLastUpdateData,
normalizeTags,
} from '@docusaurus/utils';
import {validateDocFrontMatter} from './frontMatter';
import getSlug from './slug';
import {stripPathNumberPrefixes} from './numberPrefix';
import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
import type {TagsFile} from '@docusaurus/utils';
import type {
MetadataOptions,
PluginOptions,
@ -82,12 +83,14 @@ async function doProcessDocMetadata({
context,
options,
env,
tagsFile,
}: {
docFile: DocFile;
versionMetadata: VersionMetadata;
context: LoadContext;
options: MetadataOptions;
env: DocEnv;
tagsFile: TagsFile | null;
}): Promise<DocMetadataBase> {
const {source, content, contentPath, filePath} = docFile;
const {
@ -206,6 +209,14 @@ async function doProcessDocMetadata({
const draft = isDraft({env, frontMatter});
const unlisted = isUnlisted({env, frontMatter});
const tags = normalizeTags({
options,
source,
frontMatterTags: frontMatter.tags,
tagsBaseRoutePath: versionMetadata.tagsPath,
tagsFile,
});
// Assign all of object properties during instantiation (if possible) for
// NodeJS optimization.
// Adding properties to object after instantiation will cause hidden
@ -221,7 +232,7 @@ async function doProcessDocMetadata({
draft,
unlisted,
editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
tags,
version: versionMetadata.versionName,
lastUpdatedBy: lastUpdate.lastUpdatedBy,
lastUpdatedAt: lastUpdate.lastUpdatedAt,
@ -236,6 +247,7 @@ export async function processDocMetadata(args: {
context: LoadContext;
options: MetadataOptions;
env: DocEnv;
tagsFile: TagsFile | null;
}): Promise<DocMetadataBase> {
try {
return await doProcessDocMetadata(args);

View file

@ -20,6 +20,10 @@ import {
resolveMarkdownLinkPathname,
DEFAULT_PLUGIN_ID,
} from '@docusaurus/utils';
import {
getTagsFile,
getTagsFilePathsToWatch,
} from '@docusaurus/utils-validation';
import {loadSidebars, resolveSidebarPathOption} from './sidebars';
import {CategoryMetadataFilenamePattern} from './sidebars/generator';
import {
@ -43,6 +47,7 @@ import {
} from './translations';
import {createAllRoutes} from './routes';
import {createSidebarsUtils} from './sidebars/utils';
import type {TagsFile} from '@docusaurus/utils';
import type {Options as MDXLoaderOptions} from '@docusaurus/mdx-loader';
import type {
@ -119,6 +124,10 @@ export default async function pluginContentDocs(
(docsDirPath) => `${docsDirPath}/${pattern}`,
),
),
...getTagsFilePathsToWatch({
contentPaths: version,
tags: options.tags,
}),
`${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
];
if (typeof version.sidebarFilePath === 'string') {
@ -133,6 +142,7 @@ export default async function pluginContentDocs(
async loadContent() {
async function loadVersionDocsBase(
versionMetadata: VersionMetadata,
tagsFile: TagsFile | null,
): Promise<DocMetadataBase[]> {
const docFiles = await readVersionDocs(versionMetadata, options);
if (docFiles.length === 0) {
@ -152,6 +162,7 @@ export default async function pluginContentDocs(
context,
options,
env,
tagsFile,
});
}
return Promise.all(docFiles.map(processVersionDoc));
@ -160,8 +171,14 @@ export default async function pluginContentDocs(
async function doLoadVersion(
versionMetadata: VersionMetadata,
): Promise<LoadedVersion> {
const tagsFile = await getTagsFile({
contentPaths: versionMetadata,
tags: options.tags,
});
const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
versionMetadata,
tagsFile,
);
// TODO we only ever need draftIds in further code, not full draft items

View file

@ -54,6 +54,8 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
sidebarCollapsible: true,
sidebarCollapsed: true,
breadcrumbs: true,
onInlineTags: 'warn',
tags: undefined,
};
const VersionOptionsSchema = Joi.object({
@ -140,6 +142,13 @@ const OptionsSchema = Joi.object<PluginOptions>({
lastVersion: Joi.string().optional(),
versions: VersionsOptionsSchema,
breadcrumbs: Joi.bool().default(DEFAULT_OPTIONS.breadcrumbs),
onInlineTags: Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(DEFAULT_OPTIONS.onInlineTags),
tags: Joi.string()
.disallow('')
.allow(null, false)
.default(() => DEFAULT_OPTIONS.tags),
});
export function validateOptions({

View file

@ -15,9 +15,10 @@ declare module '@docusaurus/plugin-content-docs' {
FrontMatterTag,
TagsListItem,
TagModule,
Tag,
FrontMatterLastUpdate,
LastUpdateData,
TagMetadata,
TagsPluginOptions,
} from '@docusaurus/utils';
import type {Plugin, LoadContext} from '@docusaurus/types';
import type {Overwrite, Required} from 'utility-types';
@ -64,7 +65,7 @@ declare module '@docusaurus/plugin-content-docs' {
locale: string;
}) => string | undefined;
export type MetadataOptions = {
export type MetadataOptions = TagsPluginOptions & {
/**
* URL route for the docs section of your site. **DO NOT** include a
* trailing slash. Use `/` for shipping docs without base path.
@ -446,7 +447,7 @@ declare module '@docusaurus/plugin-content-docs' {
*/
editUrl?: string | null;
/** Tags, normalized. */
tags: Tag[];
tags: TagMetadata[];
/** Front matter, as-is. */
frontMatter: DocFrontMatter & {[key: string]: unknown};
};

View file

@ -206,6 +206,7 @@ export function toTagDocListProp({
return {
label: tag.label,
permalink: tag.permalink,
description: tag.description,
allTagsPath,
count: tag.docIds.length,
items: toDocListProp(),
@ -221,6 +222,7 @@ export function toTagsListTagsProp(
.map((tagValue) => ({
label: tagValue.label,
permalink: tagValue.permalink,
description: tagValue.description,
count: tagValue.docIds.length,
}));
}

View file

@ -11,19 +11,20 @@ import {
docuHash,
normalizeUrl,
aliasedSitePathToRelativePath,
groupTaggedItems,
getTagVisibility,
} from '@docusaurus/utils';
import {
toTagDocListProp,
toTagsListTagsProp,
toVersionMetadataProp,
} from './props';
import {getVersionTags} from './tags';
import type {
PluginContentLoadedActions,
RouteConfig,
RouteMetadata,
} from '@docusaurus/types';
import type {FullVersion, VersionTag} from './types';
import type {FullVersion, VersionTag, VersionTags} from './types';
import type {
CategoryGeneratedIndexMetadata,
DocMetadata,
@ -112,6 +113,23 @@ async function buildVersionSidebarRoute(param: BuildVersionRoutesParam) {
routes: subRoutes,
};
}
function getVersionTags(docs: DocMetadata[]): VersionTags {
const groups = groupTaggedItems(docs, (doc) => doc.tags);
return _.mapValues(groups, ({tag, items: tagDocs}) => {
const tagVisibility = getTagVisibility({
items: tagDocs,
isUnlisted: (item) => item.unlisted,
});
return {
inline: tag.inline,
label: tag.label,
permalink: tag.permalink,
description: tag.description,
docIds: tagVisibility.listedItems.map((item) => item.id),
unlisted: tagVisibility.unlisted,
};
});
}
async function buildVersionTagsRoutes(
param: BuildVersionRoutesParam,
@ -120,8 +138,9 @@ async function buildVersionTagsRoutes(
const versionTags = getVersionTags(version.docs);
async function buildTagsListRoute(): Promise<RouteConfig | null> {
const tags = toTagsListTagsProp(versionTags);
// Don't create a tags list page if there's no tag
if (Object.keys(versionTags).length === 0) {
if (tags.length === 0) {
return null;
}
return {
@ -129,7 +148,7 @@ async function buildVersionTagsRoutes(
exact: true,
component: options.docTagsListComponent,
props: {
tags: toTagsListTagsProp(versionTags),
tags,
},
};
}

View file

@ -1,27 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import _ from 'lodash';
import {getTagVisibility, groupTaggedItems} from '@docusaurus/utils';
import type {VersionTags} from './types';
import type {DocMetadata} from '@docusaurus/plugin-content-docs';
export function getVersionTags(docs: DocMetadata[]): VersionTags {
const groups = groupTaggedItems(docs, (doc) => doc.tags);
return _.mapValues(groups, ({tag, items: tagDocs}) => {
const tagVisibility = getTagVisibility({
items: tagDocs,
isUnlisted: (item) => item.unlisted,
});
return {
label: tag.label,
docIds: tagVisibility.listedItems.map((item) => item.id),
permalink: tag.permalink,
unlisted: tagVisibility.unlisted,
};
});
}

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import type {Tag} from '@docusaurus/utils';
import type {TagMetadata} from '@docusaurus/utils';
import type {
LoadedVersion,
CategoryGeneratedIndexMetadata,
@ -23,7 +23,7 @@ export type SourceToPermalink = {
[source: string]: string;
};
export type VersionTag = Tag & {
export type VersionTag = TagMetadata & {
/** All doc ids having this tag. */
docIds: string[];
unlisted: boolean;