From d1092aef88eb09a004de4fcce919ee19f0eb7cb6 Mon Sep 17 00:00:00 2001 From: Lakshmi Date: Thu, 8 Oct 2026 14:36:47 +0530 Subject: [PATCH 1/3] fix(docs): support js versioned sidebars --- .../docusaurus-plugin-content-docs/src/cli.ts | 2 +- .../src/versions/__tests__/files.test.ts | 33 +++++++++++++++++++ .../version-1.0.0-sidebars.js | 6 ++++ .../src/versions/files.ts | 15 ++++++--- 4 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/fixtures/versioned_sidebars/version-1.0.0-sidebars.js diff --git a/packages/docusaurus-plugin-content-docs/src/cli.ts b/packages/docusaurus-plugin-content-docs/src/cli.ts index d19d3f5fbda7..e61ed22cb43a 100644 --- a/packages/docusaurus-plugin-content-docs/src/cli.ts +++ b/packages/docusaurus-plugin-content-docs/src/cli.ts @@ -46,7 +46,7 @@ async function createVersionedSidebarFile({ if (shouldCreateVersionedSidebarFile) { await fs.outputFile( - getVersionSidebarsPath(siteDir, pluginId, version), + await getVersionSidebarsPath(siteDir, pluginId, version), `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8', ); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts new file mode 100644 index 000000000000..d5c4060f3f5e --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts @@ -0,0 +1,33 @@ +import {describe, expect, it} from 'vitest'; +import path from 'path'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; +import {getVersionSidebarsPath} from '../files'; + +describe('getVersionSidebarsPath', () => { + it('returns the JSON versioned sidebar path', async () => { + await expect( + getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '1.0.0'), + ).resolves.toBe( + path.join('/site', 'versioned_sidebars', 'version-1.0.0-sidebars.json'), + ); + }); + it('returns the JSON versioned sidebar path when using a version name', async () => { + await expect( + getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '2.0.0'), + ).resolves.toBe( + path.join('/site', 'versioned_sidebars', 'version-2.0.0-sidebars.json'), + ); + }); + it('returns the JavaScript versioned sidebar path when it exists', async () => { + const siteDir = path.join(__dirname, 'fixtures'); + const expectedPath = path.join( + siteDir, + 'versioned_sidebars', + 'version-1.0.0-sidebars.js', + ); + + await expect( + getVersionSidebarsPath(siteDir, DEFAULT_PLUGIN_ID, '1.0.0'), + ).resolves.toBe(expectedPath); + }); +}); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/fixtures/versioned_sidebars/version-1.0.0-sidebars.js b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/fixtures/versioned_sidebars/version-1.0.0-sidebars.js new file mode 100644 index 000000000000..ad43adfde190 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/fixtures/versioned_sidebars/version-1.0.0-sidebars.js @@ -0,0 +1,6 @@ +module.exports = { + docs: { + Test: ['foo/bar', 'foo/baz'], + Guides: ['hello'], + }, +}; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index 824c8092eef3..ca838ec5bddc 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -46,16 +46,21 @@ export function getVersionDocsDirPath( } /** `[siteDir]/community_versioned_sidebars/version-1.0.0-sidebars.json` */ -export function getVersionSidebarsPath( +export async function getVersionSidebarsPath( siteDir: string, pluginId: string, versionName: string, -): string { - return path.join( +): Promise { + const sidebarsDir = path.join( siteDir, addPluginIdPrefix(VERSIONED_SIDEBARS_DIR, pluginId), - `version-${versionName}-sidebars.json`, ); + const versionedSidebarBaseName = `version-${versionName}-sidebars`; + + const jsPath = path.join(sidebarsDir, `${versionedSidebarBaseName}.js`); + const jsonPath = path.join(sidebarsDir, `${versionedSidebarBaseName}.json`); + + return (await fs.pathExists(jsPath)) ? jsPath : jsonPath; } export function getDocsDirPathLocalized({ @@ -205,7 +210,7 @@ export async function getVersionMetadataPaths({ : getVersionDocsDirPath(context.siteDir, options.id, versionName); const sidebarFilePath = isCurrent ? options.sidebarPath - : getVersionSidebarsPath(context.siteDir, options.id, versionName); + : await getVersionSidebarsPath(context.siteDir, options.id, versionName); if (!(await fs.pathExists(contentPath))) { throw new Error( From 4e37e1e64516881f4797a3504f34b4f1e4b065a4 Mon Sep 17 00:00:00 2001 From: Lakshmi Date: Fri, 9 Oct 2026 14:08:26 +0530 Subject: [PATCH 2/3] fix(docs): preserve sync sidebar path helper --- .../docusaurus-plugin-content-docs/src/cli.ts | 2 +- .../src/versions/__tests__/files.test.ts | 24 +++++++++----- .../src/versions/files.ts | 31 +++++++++++++++---- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/cli.ts b/packages/docusaurus-plugin-content-docs/src/cli.ts index e61ed22cb43a..d19d3f5fbda7 100644 --- a/packages/docusaurus-plugin-content-docs/src/cli.ts +++ b/packages/docusaurus-plugin-content-docs/src/cli.ts @@ -46,7 +46,7 @@ async function createVersionedSidebarFile({ if (shouldCreateVersionedSidebarFile) { await fs.outputFile( - await getVersionSidebarsPath(siteDir, pluginId, version), + getVersionSidebarsPath(siteDir, pluginId, version), `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8', ); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts index d5c4060f3f5e..08e352a95f34 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/files.test.ts @@ -1,20 +1,16 @@ import {describe, expect, it} from 'vitest'; import path from 'path'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; -import {getVersionSidebarsPath} from '../files'; +import {getVersionSidebarsPath, resolveVersionSidebarsPath} from '../files'; describe('getVersionSidebarsPath', () => { it('returns the JSON versioned sidebar path', async () => { - await expect( - getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '1.0.0'), - ).resolves.toBe( + expect(getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '1.0.0')).toBe( path.join('/site', 'versioned_sidebars', 'version-1.0.0-sidebars.json'), ); }); it('returns the JSON versioned sidebar path when using a version name', async () => { - await expect( - getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '2.0.0'), - ).resolves.toBe( + expect(getVersionSidebarsPath('/site', DEFAULT_PLUGIN_ID, '2.0.0')).toBe( path.join('/site', 'versioned_sidebars', 'version-2.0.0-sidebars.json'), ); }); @@ -27,7 +23,19 @@ describe('getVersionSidebarsPath', () => { ); await expect( - getVersionSidebarsPath(siteDir, DEFAULT_PLUGIN_ID, '1.0.0'), + resolveVersionSidebarsPath(siteDir, DEFAULT_PLUGIN_ID, '1.0.0'), + ).resolves.toBe(expectedPath); + }); + it('falls back to the JSON versioned sidebar path when no JavaScript file exists', async () => { + const siteDir = '/site'; + const expectedPath = path.join( + siteDir, + 'versioned_sidebars', + 'version-1.0.0-sidebars.json', + ); + + await expect( + resolveVersionSidebarsPath(siteDir, DEFAULT_PLUGIN_ID, '1.0.0'), ).resolves.toBe(expectedPath); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index ca838ec5bddc..17c581c112e8 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -46,7 +46,21 @@ export function getVersionDocsDirPath( } /** `[siteDir]/community_versioned_sidebars/version-1.0.0-sidebars.json` */ -export async function getVersionSidebarsPath( +export function getVersionSidebarsPath( + siteDir: string, + pluginId: string, + versionName: string, +): string { + const sidebarsDir = path.join( + siteDir, + addPluginIdPrefix(VERSIONED_SIDEBARS_DIR, pluginId), + ); + + return path.join(sidebarsDir, `version-${versionName}-sidebars.json`); +} + +/** Resolves a versioned sidebar, supporting both `.js` and `.json` files. */ +export async function resolveVersionSidebarsPath( siteDir: string, pluginId: string, versionName: string, @@ -55,12 +69,13 @@ export async function getVersionSidebarsPath( siteDir, addPluginIdPrefix(VERSIONED_SIDEBARS_DIR, pluginId), ); - const versionedSidebarBaseName = `version-${versionName}-sidebars`; - const jsPath = path.join(sidebarsDir, `${versionedSidebarBaseName}.js`); - const jsonPath = path.join(sidebarsDir, `${versionedSidebarBaseName}.json`); + const baseName = `version-${versionName}-sidebars`; + const jsPath = path.join(sidebarsDir, `${baseName}.js`); - return (await fs.pathExists(jsPath)) ? jsPath : jsonPath; + return (await fs.pathExists(jsPath)) + ? jsPath + : getVersionSidebarsPath(siteDir, pluginId, versionName); } export function getDocsDirPathLocalized({ @@ -210,7 +225,11 @@ export async function getVersionMetadataPaths({ : getVersionDocsDirPath(context.siteDir, options.id, versionName); const sidebarFilePath = isCurrent ? options.sidebarPath - : await getVersionSidebarsPath(context.siteDir, options.id, versionName); + : await resolveVersionSidebarsPath( + context.siteDir, + options.id, + versionName, + ); if (!(await fs.pathExists(contentPath))) { throw new Error( From 4d10f738500ef46e27ecae3b165f5b636fb89b2f Mon Sep 17 00:00:00 2001 From: Lakshmi Date: Thu, 15 Oct 2026 13:44:46 +0530 Subject: [PATCH 3/3] test(docs): cover JavaScript versioned sidebars --- .../site-js-sidebar/docs/hello.md | 1 + .../versioned_docs/version-1.0.0/hello.md | 1 + .../version-1.0.0-sidebars.js | 3 +++ .../site-js-sidebar/versions.json | 1 + .../versions/__tests__/loadVersion.test.ts | 19 +++++++++++++++++++ 5 files changed, 25 insertions(+) create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/docs/hello.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_docs/version-1.0.0/hello.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_sidebars/version-1.0.0-sidebars.js create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versions.json diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/docs/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/docs/hello.md new file mode 100644 index 000000000000..6e39f0eb8588 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/docs/hello.md @@ -0,0 +1 @@ +# Current documentation diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_docs/version-1.0.0/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_docs/version-1.0.0/hello.md new file mode 100644 index 000000000000..362c2726d8c9 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_docs/version-1.0.0/hello.md @@ -0,0 +1 @@ +# Version 1 documentation diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_sidebars/version-1.0.0-sidebars.js b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_sidebars/version-1.0.0-sidebars.js new file mode 100644 index 000000000000..a2c5cc51a3b3 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versioned_sidebars/version-1.0.0-sidebars.js @@ -0,0 +1,3 @@ +module.exports = { + docs: ['hello'], +}; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versions.json b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versions.json new file mode 100644 index 000000000000..64de05e14b9e --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-js-sidebar/versions.json @@ -0,0 +1 @@ +["1.0.0"] 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..4bc1d591891d 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 @@ -59,6 +59,25 @@ async function siteFixture(fixture: string) { } describe('loadVersion', () => { + describe('site with JavaScript versioned sidebar', () => { + it('loads a versioned sidebar from a JavaScript file', async () => { + const {options, context, versions} = await siteFixture('site-js-sidebar'); + + const version = versions.find((v) => v.versionName === '1.0.0'); + expect(version).toBeDefined(); + + const loadedVersion = await loadVersion({ + context, + options, + versionMetadata: version!, + env: 'production', + }); + + expect(loadedVersion.sidebars).toEqual({ + docs: [{type: 'doc', id: 'hello'}], + }); + }); + }); describe('minimal site', () => { it('can load current version', async () => { const {options, context, versions} = await siteFixture('site-minimal');