fix(theme): docsVersionDropdown navbar item not showing the appropriate version (#10309)

Co-authored-by: sebastien <lorber.sebastien@gmail.com>
This commit is contained in:
ozaki 2024-07-25 12:34:34 +02:00 committed by GitHub
parent 5e9e1d051b
commit fb4e32fb81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 257 additions and 138 deletions

View file

@ -6,6 +6,7 @@
*/ */
import _ from 'lodash'; import _ from 'lodash';
import {fromPartial} from '@total-typescript/shoehorn';
import { import {
getActivePlugin, getActivePlugin,
getLatestVersion, getLatestVersion,
@ -20,6 +21,14 @@ import type {
GlobalDoc, GlobalDoc,
} from '../index'; } from '../index';
function globalVersion(partial: Partial<GlobalVersion>): GlobalVersion {
return fromPartial<GlobalVersion>(partial);
}
function globalDoc(partial: Partial<GlobalDoc>): GlobalDoc {
return fromPartial<GlobalDoc>(partial);
}
describe('docsClientUtils', () => { describe('docsClientUtils', () => {
it('getActivePlugin', () => { it('getActivePlugin', () => {
const data: {[key: string]: GlobalPluginData} = { const data: {[key: string]: GlobalPluginData} = {
@ -100,149 +109,261 @@ describe('docsClientUtils', () => {
it('getLatestVersion', () => { it('getLatestVersion', () => {
const versions: GlobalVersion[] = [ const versions: GlobalVersion[] = [
{ globalVersion({
name: 'version1',
label: 'version1',
path: '/???',
isLast: false, isLast: false,
docs: [], }),
mainDocId: '???', globalVersion({
draftIds: [],
},
{
name: 'version2',
label: 'version2',
path: '/???',
isLast: true, isLast: true,
docs: [], }),
mainDocId: '???', globalVersion({
draftIds: [],
},
{
name: 'version3',
label: 'version3',
path: '/???',
isLast: false, isLast: false,
docs: [], }),
mainDocId: '???',
draftIds: [],
},
]; ];
expect( expect(
getLatestVersion({ getLatestVersion(
path: '???', fromPartial({
versions, versions,
breadcrumbs: true, }),
}), ),
).toEqual(versions[1]); ).toEqual(versions[1]);
}); });
it('getActiveVersion', () => { describe('getActiveVersion', () => {
const data: GlobalPluginData = { function testActiveVersion(versions: GlobalVersion[], path: string) {
path: 'docs', return getActiveVersion(fromPartial({versions}), path);
versions: [ }
{
it('getActiveVersion for regular docs versions', () => {
const versions: GlobalVersion[] = [
globalVersion({
name: 'next', name: 'next',
label: 'next',
isLast: false,
path: '/docs/next', path: '/docs/next',
docs: [], }),
mainDocId: '???', globalVersion({
draftIds: [],
},
{
name: 'version2', name: 'version2',
label: 'version2',
isLast: true,
path: '/docs', path: '/docs',
docs: [], }),
mainDocId: '???', globalVersion({
draftIds: [],
},
{
name: 'version1', name: 'version1',
label: 'version1',
isLast: false,
path: '/docs/version1', path: '/docs/version1',
docs: [], }),
mainDocId: '???', ];
draftIds: [],
},
],
breadcrumbs: true,
};
expect(getActiveVersion(data, '/someUnknownPath')).toBeUndefined(); expect(testActiveVersion(versions, '/someUnknownPath')).toBeUndefined();
expect(getActiveVersion(data, '/docs/next')?.name).toBe('next'); expect(testActiveVersion(versions, '/docs/next')?.name).toBe('next');
expect(getActiveVersion(data, '/docs/next/')?.name).toBe('next'); expect(testActiveVersion(versions, '/docs/next/')?.name).toBe('next');
expect(getActiveVersion(data, '/docs/next/someDoc')?.name).toBe('next'); expect(testActiveVersion(versions, '/docs/next/someDoc')?.name).toBe(
'next',
);
expect(getActiveVersion(data, '/docs')?.name).toBe('version2'); expect(testActiveVersion(versions, '/docs')?.name).toBe('version2');
expect(getActiveVersion(data, '/docs/')?.name).toBe('version2'); expect(testActiveVersion(versions, '/docs/')?.name).toBe('version2');
expect(getActiveVersion(data, '/docs/someDoc')?.name).toBe('version2'); expect(testActiveVersion(versions, '/docs/someDoc')?.name).toBe(
'version2',
);
expect(getActiveVersion(data, '/docs/version1')?.name).toBe('version1'); expect(testActiveVersion(versions, '/docs/version1')?.name).toBe(
expect(getActiveVersion(data, '/docs/version1')?.name).toBe('version1'); 'version1',
expect(getActiveVersion(data, '/docs/version1/someDoc')?.name).toBe( );
'version1', expect(testActiveVersion(versions, '/docs/version1/')?.name).toBe(
); 'version1',
);
expect(testActiveVersion(versions, '/docs/version1/someDoc')?.name).toBe(
'version1',
);
});
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',
);
});
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');
});
it('getActiveVersion matches first version when same paths', () => {
const v1 = globalVersion({
name: 'version1',
path: '/docs',
});
const v2 = globalVersion({
name: 'version2',
path: '/docs',
});
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 versions = [
globalVersion({
name: 'current',
path: '/docs',
}),
globalVersion({
name: 'version2',
path: '/docs/version2',
}),
globalVersion({
name: 'version1',
path: '/docs/version1',
}),
];
expect(testActiveVersion(versions, '/docs')?.name).toBe('current');
});
it('getActiveVersion with trailing slash', () => {
const versions = [
globalVersion({
name: 'current',
path: '/docs/',
}),
globalVersion({
name: 'version2',
path: '/docs/version2/',
}),
globalVersion({
name: 'version1',
path: '/docs/version1/',
}),
];
expect(testActiveVersion(versions, '/docs')?.name).toBe('current');
});
it('getActiveVersion - docs only without trailing slash', () => {
const versions = [
globalVersion({
name: 'current',
path: '/',
}),
globalVersion({
name: 'version2',
path: '/version2',
}),
globalVersion({
name: 'version1',
path: '/version1',
}),
];
expect(testActiveVersion(versions, '/')?.name).toBe('current');
});
it('getActiveVersion - docs only with trailing slash', () => {
const versions = [
globalVersion({
name: 'current',
path: '/',
}),
globalVersion({
name: 'version2',
path: '/version2/',
}),
globalVersion({
name: 'version1',
path: '/version1/',
}),
];
expect(testActiveVersion(versions, '/')?.name).toBe('current');
});
}); });
it('getActiveDocContext', () => { it('getActiveDocContext', () => {
const versionNext: GlobalVersion = { const versionNext: GlobalVersion = globalVersion({
name: 'next', name: 'next',
label: 'next',
path: '/docs/next', path: '/docs/next',
isLast: false,
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/next/', path: '/docs/next/',
}, }),
{ globalDoc({
id: 'doc2', id: 'doc2',
path: '/docs/next/doc2', path: '/docs/next/doc2',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
const version2: GlobalVersion = { const version2: GlobalVersion = globalVersion({
name: 'version2', name: 'version2',
label: 'version2',
isLast: true,
path: '/docs', path: '/docs',
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/', path: '/docs/',
}, }),
{ globalDoc({
id: 'doc2', id: 'doc2',
path: '/docs/doc2', path: '/docs/doc2',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
const version1: GlobalVersion = { const version1: GlobalVersion = globalVersion({
name: 'version1', name: 'version1',
label: 'version1',
path: '/docs/version1', path: '/docs/version1',
isLast: false,
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/version1/', path: '/docs/version1/',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
// Shuffle, because order shouldn't matter // Shuffle, because order shouldn't matter
const versions: GlobalVersion[] = _.shuffle([ const versions: GlobalVersion[] = _.shuffle([
@ -324,58 +445,47 @@ describe('docsClientUtils', () => {
}); });
it('getDocVersionSuggestions', () => { it('getDocVersionSuggestions', () => {
const versionNext: GlobalVersion = { const versionNext: GlobalVersion = globalVersion({
name: 'next', name: 'next',
label: 'next',
isLast: false,
path: '/docs/next', path: '/docs/next',
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/next/', path: '/docs/next/',
}, }),
{ globalDoc({
id: 'doc2', id: 'doc2',
path: '/docs/next/doc2', path: '/docs/next/doc2',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
const version2: GlobalVersion = { const version2: GlobalVersion = globalVersion({
name: 'version2', name: 'version2',
label: 'version2',
path: '/docs', path: '/docs',
isLast: true, isLast: true,
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/', path: '/docs/',
}, }),
{ globalDoc({
id: 'doc2', id: 'doc2',
path: '/docs/doc2', path: '/docs/doc2',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
const version1: GlobalVersion = { const version1: GlobalVersion = globalVersion({
name: 'version1', name: 'version1',
label: 'version1',
isLast: false,
path: '/docs/version1', path: '/docs/version1',
mainDocId: 'doc1',
docs: [ docs: [
{ globalDoc({
id: 'doc1', id: 'doc1',
path: '/docs/version1/', path: '/docs/version1/',
}, }),
] as GlobalDoc[], ],
draftIds: [], });
};
// Shuffle, because order shouldn't matter // Shuffle, because order shouldn't matter
const versions: GlobalVersion[] = _.shuffle([ const versions: GlobalVersion[] = _.shuffle([

View file

@ -63,14 +63,23 @@ export function getActiveVersion(
data: GlobalPluginData, data: GlobalPluginData,
pathname: string, pathname: string,
): GlobalVersion | undefined { ): GlobalVersion | undefined {
const lastVersion = getLatestVersion(data); // Sort paths so that a match-all version like /docs/* is matched last
// Last version is a route like /docs/*, // Otherwise /docs/* would match /docs/1.0.0/* routes
// we need to match it last or it would match /docs/version-1.0/* as well // This is simplified but similar to the core sortRoutes() logic
const orderedVersionsMetadata = [ const sortedVersions = [...data.versions].sort((a, b) => {
...data.versions.filter((version) => version !== lastVersion), if (a.path === b.path) {
lastVersion, return 0;
]; }
return orderedVersionsMetadata.find( if (a.path.includes(b.path)) {
return -1;
}
if (b.path.includes(a.path)) {
return 1;
}
return 0;
});
return sortedVersions.find(
(version) => (version) =>
!!matchPath(pathname, { !!matchPath(pathname, {
path: version.path, path: version.path,