diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/demo.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/demo.md new file mode 100644 index 000000000000..50ab5ccb4a7b --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/demo.md @@ -0,0 +1,4 @@ +--- +id: demo +--- +# Demo diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/index.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/index.md new file mode 100644 index 000000000000..74b06b612fb3 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-slug-conflicts/demo/index.md @@ -0,0 +1,4 @@ +--- +id: index +--- +# Index diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json index bd6349302e01..183f7ea1056a 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json @@ -1,3 +1,4 @@ [ - "with-id-conflicts" + "with-id-conflicts", + "with-slug-conflicts" ] diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts index 0beb0c6b8f3e..3c34d77a2a5b 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts @@ -118,5 +118,20 @@ describe('loadVersion', () => { ] `); }); + + it('rejects version with doc slug conflict', async () => { + await expect(() => loadTestVersion('with-slug-conflicts')).rejects + .toThrowErrorMatchingInlineSnapshot(` + [Error: The docs plugin found docs sharing the same slug: + + - /demo/ found in 2 docs: + - versioned_docs/version-with-slug-conflicts/demo/demo.md + - versioned_docs/version-with-slug-conflicts/demo/index.md + + Docs should have distinct slugs. + In case of conflict, you can use the \`slug\` front matter to assign an explicit distinct slug to each doc. + ] + `); + }); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts index c47dde2ef452..0aa77c96cf91 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts @@ -74,6 +74,38 @@ In case of conflict, you can rename the docs file, or use the ${logger.code( } } +function ensureNoDuplicateSlug(docs: DocMetadataBase[]): void { + const duplicatesBySlug = _.chain(docs) + .groupBy((d) => d.slug) + .pickBy((group) => group.length > 1) + .value(); + + const duplicateSlugEntries = Object.entries(duplicatesBySlug); + + if (duplicateSlugEntries.length) { + const slugMessages = duplicateSlugEntries + .map(([slug, duplicateDocs]) => { + return logger.interpolate`- url=${slug} found in number=${ + duplicateDocs.length + } docs: + - ${duplicateDocs + .map((d) => aliasedSitePathToRelativePath(d.source)) + .join('\n - ')}`; + }) + .join('\n\n'); + + const message = `The docs plugin found docs sharing the same slug: +\n${slugMessages}\n +Docs should have distinct slugs. +In case of conflict, you can use the ${logger.code( + 'slug', + )} front matter to assign an explicit distinct slug to each doc. + `; + + throw new Error(message); + } +} + async function loadVersionDocsBase({ tagsFile, context, @@ -106,6 +138,7 @@ async function loadVersionDocsBase({ } const docs = await Promise.all(docFiles.map(processVersionDoc)); ensureNoDuplicateDocId(docs); + ensureNoDuplicateSlug(docs); return docs; }