From 0351fb9181ab6a25878d9c888d53f8bd73416d4b Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:07:49 +0200 Subject: [PATCH 1/8] fix: current version freeze --- .../src/client/docsClientUtils.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index f3229ac46522..e308bd81e063 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -63,13 +63,17 @@ export function getActiveVersion( data: GlobalPluginData, pathname: string, ): GlobalVersion | undefined { - const lastVersion = getLatestVersion(data); - // Last version is a route like /docs/*, - // we need to match it last or it would match /docs/version-1.0/* as well - const orderedVersionsMetadata = [ - ...data.versions.filter((version) => version !== lastVersion), - lastVersion, - ]; + // Sort versions: non-root paths first (by length, descending), then root path + const orderedVersionsMetadata = [...data.versions].sort((a, b) => { + if (a.path === '/') { + return 1; + } + if (b.path === '/') { + return -1; + } + return b.path.length - a.path.length; + }); + return orderedVersionsMetadata.find( (version) => !!matchPath(pathname, { From 7fc6d599afda725b2ef9cd3814c14ce9bfc84cc3 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:32:03 +0200 Subject: [PATCH 2/8] fix --- .../src/client/docsClientUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index e308bd81e063..2af0182c6142 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -65,10 +65,10 @@ export function getActiveVersion( ): GlobalVersion | undefined { // Sort versions: non-root paths first (by length, descending), then root path const orderedVersionsMetadata = [...data.versions].sort((a, b) => { - if (a.path === '/') { + if (a.path === `${data.path}/`) { return 1; } - if (b.path === '/') { + if (b.path === `${data.path}/`) { return -1; } return b.path.length - a.path.length; From 2ac906d6a82e76461716b7095dd9793ef5aab9a5 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:45:12 +0200 Subject: [PATCH 3/8] add tests and refactor logic --- .../client/__tests__/docsClientUtils.test.ts | 62 ++++++++++++++++++- .../src/client/docsClientUtils.ts | 37 ++++++++--- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index 16fc4e7a9c80..044f23639915 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -12,6 +12,7 @@ import { getActiveDocContext, getActiveVersion, getDocVersionSuggestions, + sortVersionsByPathDepth, } from '../docsClientUtils'; import type { GlobalPluginData, @@ -184,12 +185,71 @@ describe('docsClientUtils', () => { expect(getActiveVersion(data, '/docs/someDoc')?.name).toBe('version2'); expect(getActiveVersion(data, '/docs/version1')?.name).toBe('version1'); - expect(getActiveVersion(data, '/docs/version1')?.name).toBe('version1'); + expect(getActiveVersion(data, '/docs/version1/')?.name).toBe('version1'); expect(getActiveVersion(data, '/docs/version1/someDoc')?.name).toBe( 'version1', ); }); + it('sortVersionsByPathDepth', () => { + function createVersion(name: string, path: string, isLast: boolean) { + return { + name, + label: name, + path, + isLast, + docs: [], + mainDocId: '???', + draftIds: [], + }; + } + const test1 = [ + createVersion('current', '/docs', false), + createVersion('version2', '/docs/version2', true), + createVersion('version1', '/docs/version1', false), + ]; + const test2 = [ + createVersion('current', '/docs/', false), + createVersion('version2', '/docs/version2/', true), + createVersion('version1', '/docs/version1/', false), + ]; + + // docs only website + const test3 = [ + createVersion('current', '/', false), + createVersion('version2', '/version2', true), + createVersion('version1', '/version1', false), + ]; + + // docs only with trailing slash + const test4 = [ + createVersion('current', '/', false), + createVersion('version2', '/version2/', true), + createVersion('version1', '/version1/', false), + ]; + + expect(sortVersionsByPathDepth(test1)).toEqual([ + test1[2], // version1 + test1[1], // version2 + test1[0], // current + ]); + expect(sortVersionsByPathDepth(test2)).toEqual([ + test2[2], // version1 + test2[1], // version2 + test2[0], // current + ]); + expect(sortVersionsByPathDepth(test3)).toEqual([ + test3[2], // version1 + test3[1], // version2 + test3[0], // current + ]); + expect(sortVersionsByPathDepth(test4)).toEqual([ + test4[2], // version1 + test4[1], // version2 + test4[0], // current + ]); + }); + it('getActiveDocContext', () => { const versionNext: GlobalVersion = { name: 'next', diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index 2af0182c6142..6c6b7eb2ac5a 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -59,20 +59,37 @@ export function getActivePlugin( export const getLatestVersion = (data: GlobalPluginData): GlobalVersion => data.versions.find((version) => version.isLast)!; +export function sortVersionsByPathDepth( + versions: GlobalVersion[], +): GlobalVersion[] { + return [...versions].sort((a, b) => { + const getDepth = (path: string): number => { + if (path === '/') { + return 0; + } + const trimmedPath = path.replace(/^\/|\/$/g, ''); + return trimmedPath ? trimmedPath.split('/').length : 0; + }; + + const depthA = getDepth(a.path); + const depthB = getDepth(b.path); + + // Sort by depth (descending order) + if (depthA !== depthB) { + return depthB - depthA; + } + + // else sort alphabetically + return a.path.localeCompare(b.path); + }); +} + export function getActiveVersion( data: GlobalPluginData, pathname: string, ): GlobalVersion | undefined { - // Sort versions: non-root paths first (by length, descending), then root path - const orderedVersionsMetadata = [...data.versions].sort((a, b) => { - if (a.path === `${data.path}/`) { - return 1; - } - if (b.path === `${data.path}/`) { - return -1; - } - return b.path.length - a.path.length; - }); + // Sort paths by depth, deepest first + const orderedVersionsMetadata = sortVersionsByPathDepth(data.versions); return orderedVersionsMetadata.find( (version) => From e0159606c87631dd7f373952b52ca7d77d916b1d Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:05:55 +0200 Subject: [PATCH 4/8] refactor --- .../client/__tests__/docsClientUtils.test.ts | 69 +++++++++++-------- .../src/client/docsClientUtils.ts | 24 +++---- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index 044f23639915..f6a4967da8cb 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -21,6 +21,18 @@ import type { GlobalDoc, } from '@docusaurus/plugin-content-docs/client'; +function createVersion(name: string, path: string, isLast: boolean) { + return { + name, + label: name, + path, + isLast, + docs: [], + mainDocId: '???', + draftIds: [], + }; +} + describe('docsClientUtils', () => { it('getActivePlugin', () => { const data: {[key: string]: GlobalPluginData} = { @@ -191,61 +203,58 @@ describe('docsClientUtils', () => { ); }); - it('sortVersionsByPathDepth', () => { - function createVersion(name: string, path: string, isLast: boolean) { - return { - name, - label: name, - path, - isLast, - docs: [], - mainDocId: '???', - draftIds: [], - }; - } + it('sortVersionsByPathDepth without trailing slash', () => { const test1 = [ createVersion('current', '/docs', false), createVersion('version2', '/docs/version2', true), createVersion('version1', '/docs/version1', false), ]; + + expect(sortVersionsByPathDepth(test1)).toEqual([ + test1[1], // version2 + test1[2], // version1 + test1[0], // current + ]); + }); + + it('sortVersionsByPathDepth with trailing slash', () => { const test2 = [ createVersion('current', '/docs/', false), createVersion('version2', '/docs/version2/', true), createVersion('version1', '/docs/version1/', false), ]; - // docs only website + expect(sortVersionsByPathDepth(test2)).toEqual([ + test2[1], // version2 + test2[2], // version1 + test2[0], // current + ]); + }); + + it('sortVersionsByPathDepth docs only without trailing slash', () => { const test3 = [ createVersion('current', '/', false), createVersion('version2', '/version2', true), createVersion('version1', '/version1', false), ]; - // docs only with trailing slash + expect(sortVersionsByPathDepth(test3)).toEqual([ + test3[1], // version2 + test3[2], // version1 + test3[0], // current + ]); + }); + + it('sortVersionsByPathDepth docs only with trailing slash', () => { const test4 = [ createVersion('current', '/', false), createVersion('version2', '/version2/', true), createVersion('version1', '/version1/', false), ]; - expect(sortVersionsByPathDepth(test1)).toEqual([ - test1[2], // version1 - test1[1], // version2 - test1[0], // current - ]); - expect(sortVersionsByPathDepth(test2)).toEqual([ - test2[2], // version1 - test2[1], // version2 - test2[0], // current - ]); - expect(sortVersionsByPathDepth(test3)).toEqual([ - test3[2], // version1 - test3[1], // version2 - test3[0], // current - ]); expect(sortVersionsByPathDepth(test4)).toEqual([ - test4[2], // version1 test4[1], // version2 + test4[2], // version1 test4[0], // current ]); }); diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index 6c6b7eb2ac5a..f9722100e2ca 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -63,24 +63,18 @@ export function sortVersionsByPathDepth( versions: GlobalVersion[], ): GlobalVersion[] { return [...versions].sort((a, b) => { - const getDepth = (path: string): number => { - if (path === '/') { - return 0; + if (a.path === b.path) { + return 0; + } else { + if (a.path.includes(b.path)) { + return -1; + } + if (b.path.includes(a.path)) { + return 1; } - const trimmedPath = path.replace(/^\/|\/$/g, ''); - return trimmedPath ? trimmedPath.split('/').length : 0; - }; - - const depthA = getDepth(a.path); - const depthB = getDepth(b.path); - - // Sort by depth (descending order) - if (depthA !== depthB) { - return depthB - depthA; } - // else sort alphabetically - return a.path.localeCompare(b.path); + return 0; }); } From 9641f4c8a98761e1967771b602b3cf549fc0a672 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:06:51 +0200 Subject: [PATCH 5/8] rename --- .../client/__tests__/docsClientUtils.test.ts | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index f6a4967da8cb..2936d6bb5d83 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -204,58 +204,58 @@ describe('docsClientUtils', () => { }); it('sortVersionsByPathDepth without trailing slash', () => { - const test1 = [ + const test = [ createVersion('current', '/docs', false), createVersion('version2', '/docs/version2', true), createVersion('version1', '/docs/version1', false), ]; - expect(sortVersionsByPathDepth(test1)).toEqual([ - test1[1], // version2 - test1[2], // version1 - test1[0], // current + expect(sortVersionsByPathDepth(test)).toEqual([ + test[1], // version2 + test[2], // version1 + test[0], // current ]); }); it('sortVersionsByPathDepth with trailing slash', () => { - const test2 = [ + const test = [ createVersion('current', '/docs/', false), createVersion('version2', '/docs/version2/', true), createVersion('version1', '/docs/version1/', false), ]; - expect(sortVersionsByPathDepth(test2)).toEqual([ - test2[1], // version2 - test2[2], // version1 - test2[0], // current + expect(sortVersionsByPathDepth(test)).toEqual([ + test[1], // version2 + test[2], // version1 + test[0], // current ]); }); it('sortVersionsByPathDepth docs only without trailing slash', () => { - const test3 = [ + const test = [ createVersion('current', '/', false), createVersion('version2', '/version2', true), createVersion('version1', '/version1', false), ]; - expect(sortVersionsByPathDepth(test3)).toEqual([ - test3[1], // version2 - test3[2], // version1 - test3[0], // current + expect(sortVersionsByPathDepth(test)).toEqual([ + test[1], // version2 + test[2], // version1 + test[0], // current ]); }); it('sortVersionsByPathDepth docs only with trailing slash', () => { - const test4 = [ + const test = [ createVersion('current', '/', false), createVersion('version2', '/version2/', true), createVersion('version1', '/version1/', false), ]; - expect(sortVersionsByPathDepth(test4)).toEqual([ - test4[1], // version2 - test4[2], // version1 - test4[0], // current + expect(sortVersionsByPathDepth(test)).toEqual([ + test[1], // version2 + test[2], // version1 + test[0], // current ]); }); From 9434e8c47273bc804e8ef168a66d99e278b9e13c Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:21:21 +0200 Subject: [PATCH 6/8] refactor --- .../src/client/docsClientUtils.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index f9722100e2ca..85c0e255cd25 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -63,15 +63,11 @@ export function sortVersionsByPathDepth( versions: GlobalVersion[], ): GlobalVersion[] { return [...versions].sort((a, b) => { - if (a.path === b.path) { - return 0; - } else { - if (a.path.includes(b.path)) { - return -1; - } - if (b.path.includes(a.path)) { - return 1; - } + if (a.path.includes(b.path)) { + return -1; + } + if (b.path.includes(a.path)) { + return 1; } return 0; From ffca31dcdda1457623bcb36f7512835f51c371bc Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:14:44 +0200 Subject: [PATCH 7/8] refactor --- .../client/__tests__/docsClientUtils.test.ts | 120 ++++++++++-------- .../src/client/docsClientUtils.ts | 19 +-- 2 files changed, 76 insertions(+), 63 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index 2936d6bb5d83..21142d02545c 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -12,7 +12,6 @@ import { getActiveDocContext, getActiveVersion, getDocVersionSuggestions, - sortVersionsByPathDepth, } from '../docsClientUtils'; import type { GlobalPluginData, @@ -20,13 +19,16 @@ import type { ActivePlugin, GlobalDoc, } from '@docusaurus/plugin-content-docs/client'; +import type {VersionMetadata} from '@docusaurus/plugin-content-docs'; -function createVersion(name: string, path: string, isLast: boolean) { +function createVersion( + partialVersion: Partial, +): GlobalVersion { return { - name, - label: name, - path, - isLast, + name: partialVersion.label ?? '???', + label: partialVersion.label ?? '???', + path: partialVersion.path ?? '???', + isLast: partialVersion.isLast ?? false, docs: [], mainDocId: '???', draftIds: [], @@ -203,60 +205,76 @@ describe('docsClientUtils', () => { ); }); - it('sortVersionsByPathDepth without trailing slash', () => { - const test = [ - createVersion('current', '/docs', false), - createVersion('version2', '/docs/version2', true), - createVersion('version1', '/docs/version1', false), - ]; + it('getActiveVersion without trailing slash', () => { + const test: GlobalPluginData = { + path: 'docs', + versions: [ + createVersion({label: 'current', path: '/docs', isLast: false}), + createVersion({ + label: 'version2', + path: '/docs/version2', + isLast: true, + }), + createVersion({ + label: 'version1', + path: '/docs/version1', + isLast: false, + }), + ], + breadcrumbs: true, + }; - expect(sortVersionsByPathDepth(test)).toEqual([ - test[1], // version2 - test[2], // version1 - test[0], // current - ]); + expect(getActiveVersion(test, '/docs')?.name).toBe('current'); }); - it('sortVersionsByPathDepth with trailing slash', () => { - const test = [ - createVersion('current', '/docs/', false), - createVersion('version2', '/docs/version2/', true), - createVersion('version1', '/docs/version1/', false), - ]; - - expect(sortVersionsByPathDepth(test)).toEqual([ - test[1], // version2 - test[2], // version1 - test[0], // current - ]); + it('getActiveVersion with trailing slash', () => { + const test: GlobalPluginData = { + path: 'docs', + versions: [ + createVersion({label: 'current', path: '/docs/', isLast: false}), + createVersion({ + label: 'version2', + path: '/docs/version2/', + isLast: true, + }), + createVersion({ + label: 'version1', + path: '/docs/version1/', + isLast: false, + }), + ], + breadcrumbs: true, + }; + expect(getActiveVersion(test, '/docs')?.name).toBe('current'); }); - it('sortVersionsByPathDepth docs only without trailing slash', () => { - const test = [ - createVersion('current', '/', false), - createVersion('version2', '/version2', true), - createVersion('version1', '/version1', false), - ]; + it('getActiveVersion docs only without trailing slash', () => { + const test: GlobalPluginData = { + path: 'docs', + versions: [ + createVersion({label: 'current', path: '/', isLast: false}), + createVersion({label: 'version2', path: '/version2', isLast: true}), + createVersion({label: 'version1', path: '/version1', isLast: false}), + ], - expect(sortVersionsByPathDepth(test)).toEqual([ - test[1], // version2 - test[2], // version1 - test[0], // current - ]); + breadcrumbs: true, + }; + + expect(getActiveVersion(test, '/')?.name).toBe('current'); }); - it('sortVersionsByPathDepth docs only with trailing slash', () => { - const test = [ - createVersion('current', '/', false), - createVersion('version2', '/version2/', true), - createVersion('version1', '/version1/', false), - ]; + it('getActiveVersion docs only with trailing slash', () => { + const test: GlobalPluginData = { + path: 'docs', + versions: [ + createVersion({label: 'current', path: '/', isLast: false}), + createVersion({label: 'version2', path: '/version2/', isLast: true}), + createVersion({label: 'version1', path: '/version1/', isLast: false}), + ], + breadcrumbs: true, + }; - expect(sortVersionsByPathDepth(test)).toEqual([ - test[1], // version2 - test[2], // version1 - test[0], // current - ]); + expect(getActiveVersion(test, '/')?.name).toBe('current'); }); it('getActiveDocContext', () => { diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index 85c0e255cd25..05a6f75171b9 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -59,10 +59,13 @@ export function getActivePlugin( export const getLatestVersion = (data: GlobalPluginData): GlobalVersion => data.versions.find((version) => version.isLast)!; -export function sortVersionsByPathDepth( - versions: GlobalVersion[], -): GlobalVersion[] { - return [...versions].sort((a, b) => { +export function getActiveVersion( + data: GlobalPluginData, + pathname: string, +): GlobalVersion | undefined { + console.log('data:', data); + // Sort paths by depth, deepest first + const orderedVersionsMetadata = [...data.versions].sort((a, b) => { if (a.path.includes(b.path)) { return -1; } @@ -72,14 +75,6 @@ export function sortVersionsByPathDepth( return 0; }); -} - -export function getActiveVersion( - data: GlobalPluginData, - pathname: string, -): GlobalVersion | undefined { - // Sort paths by depth, deepest first - const orderedVersionsMetadata = sortVersionsByPathDepth(data.versions); return orderedVersionsMetadata.find( (version) => From 8ae5b4b7e426ba63fe66278c75bbace3fe3d1ab5 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 25 Jul 2024 12:12:50 +0200 Subject: [PATCH 8/8] Improve getActiveVersion tests + siblings --- .../client/__tests__/docsClientUtils.test.ts | 423 +++++++++--------- .../src/client/docsClientUtils.ts | 13 +- 2 files changed, 231 insertions(+), 205 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts index e4d69d7cc892..d1f560001d2a 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsClientUtils.test.ts @@ -6,6 +6,7 @@ */ import _ from 'lodash'; +import {fromPartial} from '@total-typescript/shoehorn'; import { getActivePlugin, getLatestVersion, @@ -19,20 +20,13 @@ import type { ActivePlugin, GlobalDoc, } from '../index'; -import type {VersionMetadata} from '@docusaurus/plugin-content-docs'; - -function createVersion( - partialVersion: Partial, -): GlobalVersion { - return { - name: partialVersion.label ?? '???', - label: partialVersion.label ?? '???', - path: partialVersion.path ?? '???', - isLast: partialVersion.isLast ?? false, - docs: [], - mainDocId: '???', - draftIds: [], - }; + +function globalVersion(partial: Partial): GlobalVersion { + return fromPartial(partial); +} + +function globalDoc(partial: Partial): GlobalDoc { + return fromPartial(partial); } describe('docsClientUtils', () => { @@ -115,221 +109,261 @@ describe('docsClientUtils', () => { it('getLatestVersion', () => { const versions: GlobalVersion[] = [ - { - name: 'version1', - label: 'version1', - path: '/???', + globalVersion({ isLast: false, - docs: [], - mainDocId: '???', - draftIds: [], - }, - { - name: 'version2', - label: 'version2', - path: '/???', + }), + globalVersion({ isLast: true, - docs: [], - mainDocId: '???', - draftIds: [], - }, - { - name: 'version3', - label: 'version3', - path: '/???', + }), + globalVersion({ isLast: false, - docs: [], - mainDocId: '???', - draftIds: [], - }, + }), ]; expect( - getLatestVersion({ - path: '???', - versions, - breadcrumbs: true, - }), + getLatestVersion( + fromPartial({ + versions, + }), + ), ).toEqual(versions[1]); }); - it('getActiveVersion', () => { - const data: GlobalPluginData = { - path: 'docs', - versions: [ - { + describe('getActiveVersion', () => { + function testActiveVersion(versions: GlobalVersion[], path: string) { + return getActiveVersion(fromPartial({versions}), path); + } + + it('getActiveVersion for regular docs versions', () => { + const versions: GlobalVersion[] = [ + globalVersion({ name: 'next', - label: 'next', - isLast: false, path: '/docs/next', - docs: [], - mainDocId: '???', - draftIds: [], - }, - { + }), + globalVersion({ name: 'version2', - label: 'version2', - isLast: true, path: '/docs', - docs: [], - mainDocId: '???', - draftIds: [], - }, - { + }), + globalVersion({ name: 'version1', - label: 'version1', - isLast: false, path: '/docs/version1', - docs: [], - mainDocId: '???', - draftIds: [], - }, - ], - breadcrumbs: true, - }; + }), + ]; + + expect(testActiveVersion(versions, '/someUnknownPath')).toBeUndefined(); + + expect(testActiveVersion(versions, '/docs/next')?.name).toBe('next'); + expect(testActiveVersion(versions, '/docs/next/')?.name).toBe('next'); + expect(testActiveVersion(versions, '/docs/next/someDoc')?.name).toBe( + 'next', + ); + + expect(testActiveVersion(versions, '/docs')?.name).toBe('version2'); + expect(testActiveVersion(versions, '/docs/')?.name).toBe('version2'); + expect(testActiveVersion(versions, '/docs/someDoc')?.name).toBe( + 'version2', + ); + + expect(testActiveVersion(versions, '/docs/version1')?.name).toBe( + 'version1', + ); + expect(testActiveVersion(versions, '/docs/version1/')?.name).toBe( + 'version1', + ); + expect(testActiveVersion(versions, '/docs/version1/someDoc')?.name).toBe( + 'version1', + ); + }); - expect(getActiveVersion(data, '/someUnknownPath')).toBeUndefined(); + it('getActiveVersion is not sensitive to version order', () => { + const v1 = globalVersion({ + name: 'version1', + path: '/docs', + }); + const v2 = globalVersion({ + name: 'version2', + path: '/docs/v2', + }); + + expect(testActiveVersion([v1, v2], '/docs')?.name).toBe('version1'); + expect(testActiveVersion([v2, v1], '/docs')?.name).toBe('version1'); + expect(testActiveVersion([v1, v2], '/docs/myDoc')?.name).toBe('version1'); + expect(testActiveVersion([v2, v1], '/docs/myDoc')?.name).toBe('version1'); + + expect(testActiveVersion([v1, v2], '/docs/v2')?.name).toBe('version2'); + expect(testActiveVersion([v2, v1], '/docs/v2')?.name).toBe('version2'); + expect(testActiveVersion([v1, v2], '/docs/v2/myDoc')?.name).toBe( + 'version2', + ); + expect(testActiveVersion([v2, v1], '/docs/v2/myDoc')?.name).toBe( + 'version2', + ); + }); - expect(getActiveVersion(data, '/docs/next')?.name).toBe('next'); - expect(getActiveVersion(data, '/docs/next/')?.name).toBe('next'); - expect(getActiveVersion(data, '/docs/next/someDoc')?.name).toBe('next'); + it('getActiveVersion is not sensitive to isLast attribute', () => { + const v1 = globalVersion({ + name: 'version1', + path: '/docs', + isLast: false, + }); + const v2 = globalVersion({ + name: 'version2', + path: '/docs/v2', + isLast: false, + }); + + expect(testActiveVersion([v1, v2], '/docs')?.name).toBe('version1'); + expect(testActiveVersion([v1, v2], '/docs/v2')?.name).toBe('version2'); + + expect( + testActiveVersion([{...v1, isLast: true}, v2], '/docs')?.name, + ).toBe('version1'); + expect( + testActiveVersion([{...v1, isLast: true}, v2], '/docs/v2')?.name, + ).toBe('version2'); + + expect( + testActiveVersion([v1, {...v2, isLast: true}], '/docs')?.name, + ).toBe('version1'); + expect( + testActiveVersion([v1, {...v2, isLast: true}], '/docs/v2')?.name, + ).toBe('version2'); + }); - expect(getActiveVersion(data, '/docs')?.name).toBe('version2'); - expect(getActiveVersion(data, '/docs/')?.name).toBe('version2'); - expect(getActiveVersion(data, '/docs/someDoc')?.name).toBe('version2'); + it('getActiveVersion matches first version when same paths', () => { + const v1 = globalVersion({ + name: 'version1', + path: '/docs', + }); + const v2 = globalVersion({ + name: 'version2', + path: '/docs', + }); - expect(getActiveVersion(data, '/docs/version1')?.name).toBe('version1'); - expect(getActiveVersion(data, '/docs/version1/')?.name).toBe('version1'); - expect(getActiveVersion(data, '/docs/version1/someDoc')?.name).toBe( - 'version1', - ); - }); + expect(testActiveVersion([v1, v2], '/docs')?.name).toBe('version1'); + expect(testActiveVersion([v2, v1], '/docs')?.name).toBe('version2'); + expect(testActiveVersion([v1, v2], '/docs/myDoc')?.name).toBe('version1'); + expect(testActiveVersion([v2, v1], '/docs/myDoc')?.name).toBe('version2'); + }); - it('getActiveVersion without trailing slash', () => { - const test: GlobalPluginData = { - path: 'docs', - versions: [ - createVersion({label: 'current', path: '/docs', isLast: false}), - createVersion({ - label: 'version2', + it('getActiveVersion without trailing slash', () => { + const versions = [ + globalVersion({ + name: 'current', + path: '/docs', + }), + globalVersion({ + name: 'version2', path: '/docs/version2', - isLast: true, }), - createVersion({ - label: 'version1', + globalVersion({ + name: 'version1', path: '/docs/version1', - isLast: false, }), - ], - breadcrumbs: true, - }; + ]; - expect(getActiveVersion(test, '/docs')?.name).toBe('current'); - }); + expect(testActiveVersion(versions, '/docs')?.name).toBe('current'); + }); - it('getActiveVersion with trailing slash', () => { - const test: GlobalPluginData = { - path: 'docs', - versions: [ - createVersion({label: 'current', path: '/docs/', isLast: false}), - createVersion({ - label: 'version2', + it('getActiveVersion with trailing slash', () => { + const versions = [ + globalVersion({ + name: 'current', + path: '/docs/', + }), + globalVersion({ + name: 'version2', path: '/docs/version2/', - isLast: true, }), - createVersion({ - label: 'version1', + globalVersion({ + name: 'version1', path: '/docs/version1/', - isLast: false, }), - ], - breadcrumbs: true, - }; - expect(getActiveVersion(test, '/docs')?.name).toBe('current'); - }); + ]; - it('getActiveVersion docs only without trailing slash', () => { - const test: GlobalPluginData = { - path: 'docs', - versions: [ - createVersion({label: 'current', path: '/', isLast: false}), - createVersion({label: 'version2', path: '/version2', isLast: true}), - createVersion({label: 'version1', path: '/version1', isLast: false}), - ], + expect(testActiveVersion(versions, '/docs')?.name).toBe('current'); + }); - breadcrumbs: true, - }; + it('getActiveVersion - docs only without trailing slash', () => { + const versions = [ + globalVersion({ + name: 'current', + path: '/', + }), + globalVersion({ + name: 'version2', + path: '/version2', + }), + globalVersion({ + name: 'version1', + path: '/version1', + }), + ]; - expect(getActiveVersion(test, '/')?.name).toBe('current'); - }); + expect(testActiveVersion(versions, '/')?.name).toBe('current'); + }); - it('getActiveVersion docs only with trailing slash', () => { - const test: GlobalPluginData = { - path: 'docs', - versions: [ - createVersion({label: 'current', path: '/', isLast: false}), - createVersion({label: 'version2', path: '/version2/', isLast: true}), - createVersion({label: 'version1', path: '/version1/', isLast: false}), - ], - breadcrumbs: true, - }; + it('getActiveVersion - docs only with trailing slash', () => { + const versions = [ + globalVersion({ + name: 'current', + path: '/', + }), + globalVersion({ + name: 'version2', + path: '/version2/', + }), + globalVersion({ + name: 'version1', + path: '/version1/', + }), + ]; - expect(getActiveVersion(test, '/')?.name).toBe('current'); + expect(testActiveVersion(versions, '/')?.name).toBe('current'); + }); }); it('getActiveDocContext', () => { - const versionNext: GlobalVersion = { + const versionNext: GlobalVersion = globalVersion({ name: 'next', - label: 'next', path: '/docs/next', - isLast: false, - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/next/', - }, - { + }), + globalDoc({ id: 'doc2', path: '/docs/next/doc2', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); - const version2: GlobalVersion = { + const version2: GlobalVersion = globalVersion({ name: 'version2', - label: 'version2', - isLast: true, path: '/docs', - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/', - }, - { + }), + globalDoc({ id: 'doc2', path: '/docs/doc2', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); - const version1: GlobalVersion = { + const version1: GlobalVersion = globalVersion({ name: 'version1', - label: 'version1', path: '/docs/version1', - isLast: false, - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/version1/', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); // Shuffle, because order shouldn't matter const versions: GlobalVersion[] = _.shuffle([ @@ -411,58 +445,47 @@ describe('docsClientUtils', () => { }); it('getDocVersionSuggestions', () => { - const versionNext: GlobalVersion = { + const versionNext: GlobalVersion = globalVersion({ name: 'next', - label: 'next', - isLast: false, path: '/docs/next', - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/next/', - }, - { + }), + globalDoc({ id: 'doc2', path: '/docs/next/doc2', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); - const version2: GlobalVersion = { + const version2: GlobalVersion = globalVersion({ name: 'version2', - label: 'version2', path: '/docs', isLast: true, - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/', - }, - { + }), + globalDoc({ id: 'doc2', path: '/docs/doc2', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); - const version1: GlobalVersion = { + const version1: GlobalVersion = globalVersion({ name: 'version1', - label: 'version1', - isLast: false, path: '/docs/version1', - mainDocId: 'doc1', docs: [ - { + globalDoc({ id: 'doc1', path: '/docs/version1/', - }, - ] as GlobalDoc[], - draftIds: [], - }; + }), + ], + }); // Shuffle, because order shouldn't matter const versions: GlobalVersion[] = _.shuffle([ diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts index 05a6f75171b9..29bb9c0e0622 100644 --- a/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts +++ b/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts @@ -63,20 +63,23 @@ export function getActiveVersion( data: GlobalPluginData, pathname: string, ): GlobalVersion | undefined { - console.log('data:', data); - // Sort paths by depth, deepest first - const orderedVersionsMetadata = [...data.versions].sort((a, b) => { + // Sort paths so that a match-all version like /docs/* is matched last + // Otherwise /docs/* would match /docs/1.0.0/* routes + // This is simplified but similar to the core sortRoutes() logic + const sortedVersions = [...data.versions].sort((a, b) => { + if (a.path === b.path) { + return 0; + } if (a.path.includes(b.path)) { return -1; } if (b.path.includes(a.path)) { return 1; } - return 0; }); - return orderedVersionsMetadata.find( + return sortedVersions.find( (version) => !!matchPath(pathname, { path: version.path,