mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-23 19:48:54 +02:00
refactor(docs): extract loadVersion()
without changing the behavior (#11230)
* refactor, extract loadVersion() without changing behavior * Add minimal test case for loadVersion() * Add minimal test case for loadVersion() * more refactor, rename index.ts to version.ts * fix tests * empty
This commit is contained in:
parent
dacfc17fb4
commit
18b47fdfc1
10 changed files with 281 additions and 121 deletions
|
@ -25,7 +25,7 @@ import {
|
|||
type DocEnv,
|
||||
} from '../docs';
|
||||
import {loadSidebars} from '../sidebars';
|
||||
import {readVersionsMetadata} from '../versions';
|
||||
import {readVersionsMetadata} from '../versions/version';
|
||||
import {DEFAULT_OPTIONS} from '../options';
|
||||
import type {Sidebars} from '../sidebars/types';
|
||||
import type {DocFile} from '../types';
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import _ from 'lodash';
|
||||
import logger from '@docusaurus/logger';
|
||||
import {
|
||||
normalizeUrl,
|
||||
|
@ -17,30 +16,19 @@ import {
|
|||
posixPath,
|
||||
addTrailingPathSeparator,
|
||||
createAbsoluteFilePathMatcher,
|
||||
createSlugger,
|
||||
resolveMarkdownLinkPathname,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
type TagsFile,
|
||||
} from '@docusaurus/utils';
|
||||
import {
|
||||
getTagsFile,
|
||||
getTagsFilePathsToWatch,
|
||||
} from '@docusaurus/utils-validation';
|
||||
import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation';
|
||||
import {createMDXLoaderRule} from '@docusaurus/mdx-loader';
|
||||
import {loadSidebars, resolveSidebarPathOption} from './sidebars';
|
||||
import {resolveSidebarPathOption} from './sidebars';
|
||||
import {CategoryMetadataFilenamePattern} from './sidebars/generator';
|
||||
import {
|
||||
readVersionDocs,
|
||||
processDocMetadata,
|
||||
addDocNavigation,
|
||||
type DocEnv,
|
||||
createDocsByIdIndex,
|
||||
} from './docs';
|
||||
import {type DocEnv} from './docs';
|
||||
import {
|
||||
getVersionFromSourceFilePath,
|
||||
readVersionsMetadata,
|
||||
toFullVersion,
|
||||
} from './versions';
|
||||
} from './versions/version';
|
||||
import cliDocs from './cli';
|
||||
import {VERSIONS_JSON_FILE} from './constants';
|
||||
import {toGlobalDataVersion} from './globalData';
|
||||
|
@ -49,19 +37,17 @@ import {
|
|||
getLoadedContentTranslationFiles,
|
||||
} from './translations';
|
||||
import {createAllRoutes} from './routes';
|
||||
import {createSidebarsUtils} from './sidebars/utils';
|
||||
|
||||
import {createContentHelpers} from './contentHelpers';
|
||||
import {loadVersion} from './versions/loadVersion';
|
||||
import type {
|
||||
PluginOptions,
|
||||
DocMetadataBase,
|
||||
VersionMetadata,
|
||||
DocFrontMatter,
|
||||
LoadedContent,
|
||||
LoadedVersion,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
import type {LoadContext, Plugin} from '@docusaurus/types';
|
||||
import type {DocFile, FullVersion} from './types';
|
||||
import type {FullVersion} from './types';
|
||||
import type {RuleSetRule} from 'webpack';
|
||||
|
||||
// MDX loader is not 100% deterministic, leading to cache invalidation issue
|
||||
|
@ -243,102 +229,17 @@ export default async function pluginContentDocs(
|
|||
},
|
||||
|
||||
async loadContent() {
|
||||
async function loadVersionDocsBase(
|
||||
versionMetadata: VersionMetadata,
|
||||
tagsFile: TagsFile | null,
|
||||
): Promise<DocMetadataBase[]> {
|
||||
const docFiles = await readVersionDocs(versionMetadata, options);
|
||||
if (docFiles.length === 0) {
|
||||
throw new Error(
|
||||
`Docs version "${
|
||||
versionMetadata.versionName
|
||||
}" has no docs! At least one doc should exist at "${path.relative(
|
||||
siteDir,
|
||||
versionMetadata.contentPath,
|
||||
)}".`,
|
||||
);
|
||||
}
|
||||
function processVersionDoc(docFile: DocFile) {
|
||||
return processDocMetadata({
|
||||
docFile,
|
||||
versionMetadata,
|
||||
context,
|
||||
options,
|
||||
env,
|
||||
tagsFile,
|
||||
});
|
||||
}
|
||||
return Promise.all(docFiles.map(processVersionDoc));
|
||||
}
|
||||
|
||||
async function doLoadVersion(
|
||||
versionMetadata: VersionMetadata,
|
||||
): Promise<LoadedVersion> {
|
||||
const tagsFile = await getTagsFile({
|
||||
contentPaths: versionMetadata,
|
||||
tags: options.tags,
|
||||
});
|
||||
|
||||
const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
|
||||
versionMetadata,
|
||||
tagsFile,
|
||||
);
|
||||
|
||||
// TODO we only ever need draftIds in further code, not full draft items
|
||||
// To simplify and prevent mistakes, avoid exposing draft
|
||||
// replace draft=>draftIds in content loaded
|
||||
const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft);
|
||||
|
||||
const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
|
||||
sidebarItemsGenerator: options.sidebarItemsGenerator,
|
||||
numberPrefixParser: options.numberPrefixParser,
|
||||
docs,
|
||||
drafts,
|
||||
version: versionMetadata,
|
||||
sidebarOptions: {
|
||||
sidebarCollapsed: options.sidebarCollapsed,
|
||||
sidebarCollapsible: options.sidebarCollapsible,
|
||||
},
|
||||
categoryLabelSlugger: createSlugger(),
|
||||
});
|
||||
|
||||
const sidebarsUtils = createSidebarsUtils(sidebars);
|
||||
|
||||
const docsById = createDocsByIdIndex(docs);
|
||||
const allDocIds = Object.keys(docsById);
|
||||
|
||||
sidebarsUtils.checkLegacyVersionedSidebarNames({
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
versionMetadata,
|
||||
});
|
||||
sidebarsUtils.checkSidebarsDocIds({
|
||||
allDocIds,
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
versionMetadata,
|
||||
});
|
||||
|
||||
return {
|
||||
...versionMetadata,
|
||||
docs: addDocNavigation({
|
||||
docs,
|
||||
sidebarsUtils,
|
||||
}),
|
||||
drafts,
|
||||
sidebars,
|
||||
};
|
||||
}
|
||||
|
||||
async function loadVersion(versionMetadata: VersionMetadata) {
|
||||
try {
|
||||
return await doLoadVersion(versionMetadata);
|
||||
} catch (err) {
|
||||
logger.error`Loading of version failed for version name=${versionMetadata.versionName}`;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
loadedVersions: await Promise.all(versionsMetadata.map(loadVersion)),
|
||||
loadedVersions: await Promise.all(
|
||||
versionsMetadata.map((versionMetadata) =>
|
||||
loadVersion({
|
||||
context,
|
||||
options,
|
||||
env,
|
||||
versionMetadata,
|
||||
}),
|
||||
),
|
||||
),
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ export {
|
|||
getDefaultVersionBanner,
|
||||
getVersionBadge,
|
||||
getVersionBanner,
|
||||
} from './versions';
|
||||
} from './versions/version';
|
||||
export {readVersionNames} from './versions/files';
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# Hello
|
||||
|
||||
World
|
|
@ -0,0 +1,53 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`minimal site can load current version 1`] = `
|
||||
{
|
||||
"badge": false,
|
||||
"banner": null,
|
||||
"className": "docs-version-current",
|
||||
"contentPath": "<PROJECT_ROOT>/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs",
|
||||
"contentPathLocalized": "<PROJECT_ROOT>/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/i18n/en/docusaurus-plugin-content-docs/current",
|
||||
"docs": [
|
||||
{
|
||||
"description": "World",
|
||||
"draft": false,
|
||||
"editUrl": undefined,
|
||||
"frontMatter": {},
|
||||
"id": "hello",
|
||||
"lastUpdatedAt": undefined,
|
||||
"lastUpdatedBy": undefined,
|
||||
"next": undefined,
|
||||
"permalink": "/docs/hello",
|
||||
"previous": undefined,
|
||||
"sidebar": "defaultSidebar",
|
||||
"sidebarPosition": undefined,
|
||||
"slug": "/hello",
|
||||
"source": "@site/docs/hello.md",
|
||||
"sourceDirName": ".",
|
||||
"tags": [],
|
||||
"title": "Hello",
|
||||
"unlisted": false,
|
||||
"version": "current",
|
||||
},
|
||||
],
|
||||
"drafts": [],
|
||||
"editUrl": undefined,
|
||||
"editUrlLocalized": undefined,
|
||||
"isLast": true,
|
||||
"label": "Next",
|
||||
"noIndex": false,
|
||||
"path": "/docs",
|
||||
"routePriority": -1,
|
||||
"sidebarFilePath": undefined,
|
||||
"sidebars": {
|
||||
"defaultSidebar": [
|
||||
{
|
||||
"id": "hello",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
},
|
||||
"tagsPath": "/docs/tags",
|
||||
"versionName": "current",
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* 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 path from 'path';
|
||||
import {fromPartial} from '@total-typescript/shoehorn';
|
||||
import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils/src';
|
||||
import {readVersionsMetadata} from '../version';
|
||||
import {DEFAULT_OPTIONS} from '../../options';
|
||||
import {loadVersion} from '../loadVersion';
|
||||
import type {I18n, LoadContext} from '@docusaurus/types';
|
||||
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
const DefaultI18N: I18n = {
|
||||
path: 'i18n',
|
||||
currentLocale: 'en',
|
||||
locales: ['en'],
|
||||
defaultLocale: 'en',
|
||||
localeConfigs: {},
|
||||
};
|
||||
|
||||
describe('minimal site', () => {
|
||||
async function loadSite() {
|
||||
const siteDir = path.resolve(
|
||||
path.join(__dirname, './__fixtures__', 'minimal-site'),
|
||||
);
|
||||
const options: PluginOptions = fromPartial<PluginOptions>({
|
||||
...DEFAULT_OPTIONS,
|
||||
});
|
||||
const context = fromPartial<LoadContext>({
|
||||
siteDir,
|
||||
baseUrl: '/',
|
||||
i18n: DefaultI18N,
|
||||
localizationDir: path.join(siteDir, 'i18n/en'),
|
||||
siteConfig: {
|
||||
markdown: {
|
||||
parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER,
|
||||
},
|
||||
},
|
||||
});
|
||||
return {
|
||||
siteDir,
|
||||
options,
|
||||
context,
|
||||
};
|
||||
}
|
||||
|
||||
it('can load current version', async () => {
|
||||
const {options, context} = await loadSite();
|
||||
|
||||
const versionsMetadata = await readVersionsMetadata({
|
||||
options,
|
||||
context,
|
||||
});
|
||||
|
||||
expect(versionsMetadata).toHaveLength(1);
|
||||
expect(versionsMetadata[0]!.versionName).toBe('current');
|
||||
|
||||
const versionMetadata = versionsMetadata[0]!;
|
||||
|
||||
const loadedVersion = loadVersion({
|
||||
context,
|
||||
options,
|
||||
versionMetadata,
|
||||
env: 'production',
|
||||
});
|
||||
|
||||
await expect(loadedVersion).resolves.toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -8,7 +8,7 @@
|
|||
import {jest} from '@jest/globals';
|
||||
import path from 'path';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
||||
import {readVersionsMetadata} from '../index';
|
||||
import {readVersionsMetadata} from '../version';
|
||||
import {DEFAULT_OPTIONS} from '../../options';
|
||||
import type {I18n, LoadContext} from '@docusaurus/types';
|
||||
import type {
|
|
@ -19,7 +19,7 @@ import type {
|
|||
PluginOptions,
|
||||
VersionMetadata,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
import type {VersionContext} from './index';
|
||||
import type {VersionContext} from './version';
|
||||
|
||||
/** Add a prefix like `community_version-1.0.0`. No-op for default instance. */
|
||||
function addPluginIdPrefix(fileOrDir: string, pluginId: string): string {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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 path from 'path';
|
||||
import _ from 'lodash';
|
||||
import {createSlugger} from '@docusaurus/utils';
|
||||
import {getTagsFile} from '@docusaurus/utils-validation';
|
||||
import logger from '@docusaurus/logger';
|
||||
import {
|
||||
addDocNavigation,
|
||||
createDocsByIdIndex,
|
||||
type DocEnv,
|
||||
processDocMetadata,
|
||||
readVersionDocs,
|
||||
} from '../docs';
|
||||
import {loadSidebars} from '../sidebars';
|
||||
import {createSidebarsUtils} from '../sidebars/utils';
|
||||
import type {TagsFile} from '@docusaurus/utils';
|
||||
import type {
|
||||
DocMetadataBase,
|
||||
LoadedVersion,
|
||||
PluginOptions,
|
||||
VersionMetadata,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
import type {DocFile} from '../types';
|
||||
import type {LoadContext} from '@docusaurus/types';
|
||||
|
||||
export async function loadVersion({
|
||||
context,
|
||||
options,
|
||||
versionMetadata,
|
||||
env,
|
||||
}: {
|
||||
context: LoadContext;
|
||||
options: PluginOptions;
|
||||
versionMetadata: VersionMetadata;
|
||||
env: DocEnv;
|
||||
}): Promise<LoadedVersion> {
|
||||
const {siteDir} = context;
|
||||
|
||||
async function loadVersionDocsBase(
|
||||
tagsFile: TagsFile | null,
|
||||
): Promise<DocMetadataBase[]> {
|
||||
const docFiles = await readVersionDocs(versionMetadata, options);
|
||||
if (docFiles.length === 0) {
|
||||
throw new Error(
|
||||
`Docs version "${
|
||||
versionMetadata.versionName
|
||||
}" has no docs! At least one doc should exist at "${path.relative(
|
||||
siteDir,
|
||||
versionMetadata.contentPath,
|
||||
)}".`,
|
||||
);
|
||||
}
|
||||
function processVersionDoc(docFile: DocFile) {
|
||||
return processDocMetadata({
|
||||
docFile,
|
||||
versionMetadata,
|
||||
context,
|
||||
options,
|
||||
env,
|
||||
tagsFile,
|
||||
});
|
||||
}
|
||||
return Promise.all(docFiles.map(processVersionDoc));
|
||||
}
|
||||
|
||||
async function doLoadVersion(): Promise<LoadedVersion> {
|
||||
const tagsFile = await getTagsFile({
|
||||
contentPaths: versionMetadata,
|
||||
tags: options.tags,
|
||||
});
|
||||
|
||||
const docsBase: DocMetadataBase[] = await loadVersionDocsBase(tagsFile);
|
||||
|
||||
// TODO we only ever need draftIds in further code, not full draft items
|
||||
// To simplify and prevent mistakes, avoid exposing draft
|
||||
// replace draft=>draftIds in content loaded
|
||||
const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft);
|
||||
|
||||
const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
|
||||
sidebarItemsGenerator: options.sidebarItemsGenerator,
|
||||
numberPrefixParser: options.numberPrefixParser,
|
||||
docs,
|
||||
drafts,
|
||||
version: versionMetadata,
|
||||
sidebarOptions: {
|
||||
sidebarCollapsed: options.sidebarCollapsed,
|
||||
sidebarCollapsible: options.sidebarCollapsible,
|
||||
},
|
||||
categoryLabelSlugger: createSlugger(),
|
||||
});
|
||||
|
||||
const sidebarsUtils = createSidebarsUtils(sidebars);
|
||||
|
||||
const docsById = createDocsByIdIndex(docs);
|
||||
const allDocIds = Object.keys(docsById);
|
||||
|
||||
sidebarsUtils.checkLegacyVersionedSidebarNames({
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
versionMetadata,
|
||||
});
|
||||
sidebarsUtils.checkSidebarsDocIds({
|
||||
allDocIds,
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
versionMetadata,
|
||||
});
|
||||
|
||||
return {
|
||||
...versionMetadata,
|
||||
docs: addDocNavigation({
|
||||
docs,
|
||||
sidebarsUtils,
|
||||
}),
|
||||
drafts,
|
||||
sidebars,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return await doLoadVersion();
|
||||
} catch (err) {
|
||||
logger.error`Loading of version failed for version name=${versionMetadata.versionName}`;
|
||||
throw err;
|
||||
}
|
||||
}
|
|
@ -243,7 +243,7 @@ export async function readVersionsMetadata({
|
|||
validateVersionsOptions(allVersionNames, options);
|
||||
const versionNames = filterVersions(allVersionNames, options);
|
||||
const lastVersionName = getLastVersionName({versionNames, options});
|
||||
const versionsMetadata = await Promise.all(
|
||||
return Promise.all(
|
||||
versionNames.map((versionName) =>
|
||||
createVersionMetadata({
|
||||
versionName,
|
||||
|
@ -254,7 +254,6 @@ export async function readVersionsMetadata({
|
|||
}),
|
||||
),
|
||||
);
|
||||
return versionsMetadata;
|
||||
}
|
||||
|
||||
export function toFullVersion(version: LoadedVersion): FullVersion {
|
Loading…
Add table
Add a link
Reference in a new issue