docusaurus/packages/docusaurus-plugin-content-docs/src/client/docsClientUtils.ts
Joshua Chen 87592bca03
refactor: ensure all types are using index signature instead of Record (#6995)
* refactor: ensure all types are using index signature instead of Record

* kick CI
2022-03-25 18:06:30 +08:00

133 lines
3.8 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {matchPath} from '@docusaurus/router';
import type {
GlobalPluginData,
GlobalVersion,
GlobalDoc,
GetActivePluginOptions,
ActivePlugin,
ActiveDocContext,
DocVersionSuggestions,
} from '@docusaurus/plugin-content-docs/client';
// This code is not part of the api surface, not in ./theme on purpose
// get the data of the plugin that is currently "active"
// ie the docs of that plugin are currently browsed
// it is useful to support multiple docs plugin instances
export function getActivePlugin(
allPluginData: {[pluginId: string]: GlobalPluginData},
pathname: string,
options: GetActivePluginOptions = {},
): ActivePlugin | undefined {
const activeEntry = Object.entries(allPluginData)
// Route sorting: '/android/foo' should match '/android' instead of '/'
.sort((a, b) => b[1].path.localeCompare(a[1].path))
.find(
([, pluginData]) =>
!!matchPath(pathname, {
path: pluginData.path,
exact: false,
strict: false,
}),
);
const activePlugin: ActivePlugin | undefined = activeEntry
? {pluginId: activeEntry[0], pluginData: activeEntry[1]}
: undefined;
if (!activePlugin && options.failfast) {
throw new Error(
`Can't find active docs plugin for "${pathname}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(
allPluginData,
)
.map((plugin) => plugin.path)
.join(', ')}`,
);
}
return activePlugin;
}
export const getLatestVersion = (data: GlobalPluginData): GlobalVersion =>
data.versions.find((version) => version.isLast)!;
// Note: return undefined on doc-unrelated pages,
// because there's no version currently considered as active
export const 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,
];
return orderedVersionsMetadata.find(
(version) =>
!!matchPath(pathname, {
path: version.path,
exact: false,
strict: false,
}),
);
};
export const getActiveDocContext = (
data: GlobalPluginData,
pathname: string,
): ActiveDocContext => {
const activeVersion = getActiveVersion(data, pathname);
const activeDoc = activeVersion?.docs.find(
(doc) =>
!!matchPath(pathname, {
path: doc.path,
exact: true,
strict: false,
}),
);
function getAlternateVersionDocs(
docId: string,
): ActiveDocContext['alternateDocVersions'] {
const result: ActiveDocContext['alternateDocVersions'] = {};
data.versions.forEach((version) => {
version.docs.forEach((doc) => {
if (doc.id === docId) {
result[version.name] = doc;
}
});
});
return result;
}
const alternateVersionDocs = activeDoc
? getAlternateVersionDocs(activeDoc.id)
: {};
return {
activeVersion,
activeDoc,
alternateDocVersions: alternateVersionDocs,
};
};
export const getDocVersionSuggestions = (
data: GlobalPluginData,
pathname: string,
): DocVersionSuggestions => {
const latestVersion = getLatestVersion(data);
const activeDocContext = getActiveDocContext(data, pathname);
const latestDocSuggestion: GlobalDoc | undefined =
activeDocContext?.alternateDocVersions[latestVersion.name];
return {latestDocSuggestion, latestVersionSuggestion: latestVersion};
};