mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
fix(theme): docsVersionDropdown navbar item not showing the appropriate version (#10309)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
This commit is contained in:
parent
5e9e1d051b
commit
fb4e32fb81
2 changed files with 257 additions and 138 deletions
|
@ -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(
|
);
|
||||||
|
expect(testActiveVersion(versions, '/docs/version1/')?.name).toBe(
|
||||||
|
'version1',
|
||||||
|
);
|
||||||
|
expect(testActiveVersion(versions, '/docs/version1/someDoc')?.name).toBe(
|
||||||
'version1',
|
'version1',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getActiveDocContext', () => {
|
it('getActiveVersion is not sensitive to version order', () => {
|
||||||
const versionNext: GlobalVersion = {
|
const v1 = globalVersion({
|
||||||
name: 'next',
|
name: 'version1',
|
||||||
label: 'next',
|
path: '/docs',
|
||||||
path: '/docs/next',
|
});
|
||||||
|
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,
|
isLast: false,
|
||||||
mainDocId: 'doc1',
|
});
|
||||||
|
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', () => {
|
||||||
|
const versionNext: GlobalVersion = globalVersion({
|
||||||
|
name: 'next',
|
||||||
|
path: '/docs/next',
|
||||||
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([
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue