feat(core): support docusaurus.config.cjs as default file name (#7371)

This commit is contained in:
Joshua Chen 2022-05-27 17:11:58 +08:00 committed by GitHub
parent 35e63515e6
commit be912c698a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 23 deletions

View file

@ -30,8 +30,11 @@ export const DEFAULT_BUILD_DIR_NAME = 'build';
/** /**
* Can be overridden with cli option `--config`. Code should generally use * Can be overridden with cli option `--config`. Code should generally use
* `context.siteConfigPath` instead (which is always absolute). * `context.siteConfigPath` instead (which is always absolute).
*
* This does not have extensions, so that we can substitute different ones
* when resolving the path.
*/ */
export const DEFAULT_CONFIG_FILE_NAME = 'docusaurus.config.js'; export const DEFAULT_CONFIG_FILE_NAME = 'docusaurus.config';
/** Can be absolute or relative to site directory. */ /** Can be absolute or relative to site directory. */
export const BABEL_CONFIG_FILE_NAME = export const BABEL_CONFIG_FILE_NAME =

View file

@ -0,0 +1,5 @@
module.exports = {
title: 'title',
url: 'https://example.com',
baseUrl: '/'
};

View file

@ -1,5 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
{
"siteConfig": {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": [],
"customFields": {},
"i18n": {
"defaultLocale": "en",
"localeConfigs": {},
"locales": [
"en",
],
},
"noIndex": false,
"onBrokenLinks": "throw",
"onBrokenMarkdownLinks": "warn",
"onDuplicateRoutes": "warn",
"plugins": [],
"presets": [],
"scripts": [],
"staticDirectories": [
"static",
],
"stylesheets": [],
"tagline": "",
"themeConfig": {},
"themes": [],
"title": "title",
"titleDelimiter": "|",
"url": "https://example.com",
},
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/config/docusaurus.config.cjs",
}
`;
exports[`loadSiteConfig website with valid async config 1`] = ` exports[`loadSiteConfig website with valid async config 1`] = `
{ {
"siteConfig": { "siteConfig": {

View file

@ -19,6 +19,12 @@ describe('loadSiteConfig', () => {
expect(config).not.toEqual({}); expect(config).not.toEqual({});
}); });
it('website with .cjs siteConfig', async () => {
const config = await loadSiteConfig({siteDir});
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
it('website with valid config creator function', async () => { it('website with valid config creator function', async () => {
const config = await loadSiteConfig({ const config = await loadSiteConfig({
siteDir, siteDir,
@ -65,7 +71,7 @@ describe('loadSiteConfig', () => {
customConfigFilePath: 'wrong.config.js', customConfigFilePath: 'wrong.config.js',
}), }),
).rejects.toThrowErrorMatchingInlineSnapshot(` ).rejects.toThrowErrorMatchingInlineSnapshot(`
"These field(s) ("useLessField",) are not recognized in docusaurus.config.js. "These field(s) ("useLessField",) are not recognized in wrong.config.js.
If you still want these fields to be in your configuration, put them in the "customFields" field. If you still want these fields to be in your configuration, put them in the "customFields" field.
See https://docusaurus.io/docs/api/docusaurus-config/#customfields" See https://docusaurus.io/docs/api/docusaurus-config/#customfields"
`); `);

View file

@ -19,7 +19,7 @@ const baseConfig = {
} as Config; } as Config;
const normalizeConfig = (config: Partial<Config>) => const normalizeConfig = (config: Partial<Config>) =>
validateConfig({...baseConfig, ...config}); validateConfig({...baseConfig, ...config}, 'docusaurus.config.js');
describe('normalizeConfig', () => { describe('normalizeConfig', () => {
it('normalizes empty config', () => { it('normalizes empty config', () => {
@ -296,13 +296,16 @@ describe('normalizeConfig', () => {
it('throws error for required fields', () => { it('throws error for required fields', () => {
expect(() => expect(() =>
validateConfig({ validateConfig(
{
invalidField: true, invalidField: true,
presets: {}, presets: {},
stylesheets: {}, stylesheets: {},
themes: {}, themes: {},
scripts: {}, scripts: {},
}), },
'docusaurus.config.js',
),
).toThrowErrorMatchingSnapshot(); ).toThrowErrorMatchingSnapshot();
}); });
}); });

View file

@ -8,10 +8,29 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import importFresh from 'import-fresh'; import importFresh from 'import-fresh';
import {DEFAULT_CONFIG_FILE_NAME} from '@docusaurus/utils'; import logger from '@docusaurus/logger';
import {DEFAULT_CONFIG_FILE_NAME, findAsyncSequential} from '@docusaurus/utils';
import {validateConfig} from './configValidation'; import {validateConfig} from './configValidation';
import type {LoadContext} from '@docusaurus/types'; import type {LoadContext} from '@docusaurus/types';
async function findConfig(siteDir: string) {
// We could support .mjs, .ts, etc. in the future
const candidates = ['.js', '.cjs'].map(
(ext) => DEFAULT_CONFIG_FILE_NAME + ext,
);
const configPath = await findAsyncSequential(
candidates.map((file) => path.join(siteDir, file)),
fs.pathExists,
);
if (!configPath) {
logger.error('No config file found.');
logger.info`Expected one of:${candidates}
You can provide a custom config path with the code=${'--config'} option.`;
throw new Error();
}
return configPath;
}
export async function loadSiteConfig({ export async function loadSiteConfig({
siteDir, siteDir,
customConfigFilePath, customConfigFilePath,
@ -19,10 +38,9 @@ export async function loadSiteConfig({
siteDir: string; siteDir: string;
customConfigFilePath?: string; customConfigFilePath?: string;
}): Promise<Pick<LoadContext, 'siteConfig' | 'siteConfigPath'>> { }): Promise<Pick<LoadContext, 'siteConfig' | 'siteConfigPath'>> {
const siteConfigPath = path.resolve( const siteConfigPath = customConfigFilePath
siteDir, ? path.resolve(siteDir, customConfigFilePath)
customConfigFilePath ?? DEFAULT_CONFIG_FILE_NAME, : await findConfig(siteDir);
);
if (!(await fs.pathExists(siteConfigPath))) { if (!(await fs.pathExists(siteConfigPath))) {
throw new Error(`Config file at "${siteConfigPath}" not found.`); throw new Error(`Config file at "${siteConfigPath}" not found.`);
@ -35,6 +53,9 @@ export async function loadSiteConfig({
? await importedConfig() ? await importedConfig()
: await importedConfig; : await importedConfig;
const siteConfig = validateConfig(loadedConfig); const siteConfig = validateConfig(
loadedConfig,
path.relative(siteDir, siteConfigPath),
);
return {siteConfig, siteConfigPath}; return {siteConfig, siteConfigPath};
} }

View file

@ -5,10 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import { import {DEFAULT_STATIC_DIR_NAME} from '@docusaurus/utils';
DEFAULT_CONFIG_FILE_NAME,
DEFAULT_STATIC_DIR_NAME,
} from '@docusaurus/utils';
import {Joi, URISchema, printWarning} from '@docusaurus/utils-validation'; import {Joi, URISchema, printWarning} from '@docusaurus/utils-validation';
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types'; import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
@ -239,7 +236,10 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({
}); });
// TODO move to @docusaurus/utils-validation // TODO move to @docusaurus/utils-validation
export function validateConfig(config: unknown): DocusaurusConfig { export function validateConfig(
config: unknown,
siteConfigPath: string,
): DocusaurusConfig {
const {error, warning, value} = ConfigSchema.validate(config, { const {error, warning, value} = ConfigSchema.validate(config, {
abortEarly: false, abortEarly: false,
}); });
@ -263,7 +263,7 @@ export function validateConfig(config: unknown): DocusaurusConfig {
'', '',
); );
formattedError = unknownFields formattedError = unknownFields
? `${formattedError}These field(s) (${unknownFields}) are not recognized in ${DEFAULT_CONFIG_FILE_NAME}.\nIf you still want these fields to be in your configuration, put them in the "customFields" field.\nSee https://docusaurus.io/docs/api/docusaurus-config/#customfields` ? `${formattedError}These field(s) (${unknownFields}) are not recognized in ${siteConfigPath}.\nIf you still want these fields to be in your configuration, put them in the "customFields" field.\nSee https://docusaurus.io/docs/api/docusaurus-config/#customfields`
: formattedError; : formattedError;
throw new Error(formattedError); throw new Error(formattedError);
} else { } else {

View file

@ -156,7 +156,7 @@ next build. You can clear all build artifacts (including this folder) with the
const genSiteConfig = generate( const genSiteConfig = generate(
generatedFilesDir, generatedFilesDir,
DEFAULT_CONFIG_FILE_NAME, `${DEFAULT_CONFIG_FILE_NAME}.mjs`,
`/* `/*
* AUTOGENERATED - DON'T EDIT * AUTOGENERATED - DON'T EDIT
* Your edits in this file will be overwritten in the next build! * Your edits in this file will be overwritten in the next build!