diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts index 6af73d22ad0d..1828e9560124 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/index.ts @@ -43,6 +43,7 @@ export function resolveSidebarPathOption( async function readCategoriesMetadata(contentPath: string) { const categoryFiles = await Globby('**/_category_.{json,yml,yaml}', { cwd: contentPath, + ignore: ['**/node_modules/**'], }); const categoryToFile = _.groupBy(categoryFiles, path.dirname); return combinePromises( diff --git a/packages/docusaurus-utils/src/__tests__/globUtils.test.ts b/packages/docusaurus-utils/src/__tests__/globUtils.test.ts index 709671e916b1..644e3d54b7af 100644 --- a/packages/docusaurus-utils/src/__tests__/globUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/globUtils.test.ts @@ -27,6 +27,18 @@ describe('isTranslatableSourceFile', () => { }); describe('createMatcher', () => { + it('match default exclude node_modules correctly', () => { + const matcher = createMatcher(GlobExcludeDefault); + expect(matcher('node_modules/pkg/doc.md')).toBe(true); + expect(matcher('node_modules/pkg/index.js')).toBe(true); + expect(matcher('category/node_modules/pkg/doc.md')).toBe(true); + expect(matcher('category/node_modules/@scope/pkg/doc.md')).toBe(true); + // When contentPath is inside node_modules, relative paths of content + // files do NOT contain node_modules, so they should NOT be excluded. + expect(matcher('intro.md')).toBe(false); + expect(matcher('guide/setup.mdx')).toBe(false); + }); + it('match default exclude MD/MDX partials correctly', () => { const matcher = createMatcher(GlobExcludeDefault); expect(matcher('doc.md')).toBe(false); @@ -115,6 +127,36 @@ describe('createAbsoluteFilePathMatcher', () => { expect(matcher('/root/_docs/_category/myDoc.mdx')).toBe(true); }); + it('match default exclude node_modules correctly', () => { + expect(matcher('/_root/docs/node_modules/pkg/doc.md')).toBe(true); + expect(matcher('/_root/docs/node_modules/@scope/pkg/doc.md')).toBe(true); + expect( + matcher('/_root/docs/category/node_modules/pkg/index.js'), + ).toBe(true); + }); + + // Ensures that when contentPath is inside node_modules (e.g., + // node_modules/@myCompany/docs), content files at that root are NOT + // excluded, because their relative paths don't contain node_modules. + it('does not exclude content when root folder is inside node_modules', () => { + const nmMatcher = createAbsoluteFilePathMatcher(GlobExcludeDefault, [ + '/project/node_modules/@myCompany/docs', + ]); + // Content at the root should NOT be excluded + expect( + nmMatcher('/project/node_modules/@myCompany/docs/intro.md'), + ).toBe(false); + expect( + nmMatcher('/project/node_modules/@myCompany/docs/guide/setup.mdx'), + ).toBe(false); + // But nested node_modules inside that root SHOULD be excluded + expect( + nmMatcher( + '/project/node_modules/@myCompany/docs/node_modules/dep/file.md', + ), + ).toBe(true); + }); + it('match default exclude tests correctly', () => { expect(matcher('/__test__/website/src/xyz.js')).toBe(false); expect(matcher('/__test__/website/src/__test__/xyz.js')).toBe(true); diff --git a/packages/docusaurus-utils/src/globUtils.ts b/packages/docusaurus-utils/src/globUtils.ts index c26e84ab65d7..99f109b4d2ed 100644 --- a/packages/docusaurus-utils/src/globUtils.ts +++ b/packages/docusaurus-utils/src/globUtils.ts @@ -26,6 +26,7 @@ export const Globby = Tinyglobby.glob; * - Ignore tests */ export const GlobExcludeDefault = [ + '**/node_modules/**', '**/_*.{js,jsx,ts,tsx,md,mdx}', '**/_*/**', '**/*.test.{js,jsx,ts,tsx}',