diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 2e033b2f1c..6b1815ee25 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -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'; diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 6c0b93f7b3..a740b7f5e2 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -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 { - 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 { - 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, + }), + ), + ), }; }, diff --git a/packages/docusaurus-plugin-content-docs/src/server-export.ts b/packages/docusaurus-plugin-content-docs/src/server-export.ts index 0212758b78..bd2f4e4f76 100644 --- a/packages/docusaurus-plugin-content-docs/src/server-export.ts +++ b/packages/docusaurus-plugin-content-docs/src/server-export.ts @@ -22,5 +22,5 @@ export { getDefaultVersionBanner, getVersionBadge, getVersionBanner, -} from './versions'; +} from './versions/version'; export {readVersionNames} from './versions/files'; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md new file mode 100644 index 0000000000..aef67b7c25 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md @@ -0,0 +1,4 @@ + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap new file mode 100644 index 0000000000..3dde6cbe1a --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap @@ -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": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs", + "contentPathLocalized": "/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", +} +`; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts new file mode 100644 index 0000000000..3e9b6d585f --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts @@ -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({ + ...DEFAULT_OPTIONS, + }); + const context = fromPartial({ + 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(); + }); +}); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts similarity index 99% rename from packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts rename to packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts index 26173cb91e..e4e53b58be 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts @@ -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 { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index 00b3f08270..33839b9027 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -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 { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts new file mode 100644 index 0000000000..837bb0250c --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts @@ -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 { + const {siteDir} = context; + + async function loadVersionDocsBase( + tagsFile: TagsFile | null, + ): Promise { + 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 { + 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; + } +} diff --git a/packages/docusaurus-plugin-content-docs/src/versions/index.ts b/packages/docusaurus-plugin-content-docs/src/versions/version.ts similarity index 99% rename from packages/docusaurus-plugin-content-docs/src/versions/index.ts rename to packages/docusaurus-plugin-content-docs/src/versions/version.ts index bb77f8cbbd..5b4ef5c043 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/version.ts @@ -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 {