@docusaurus/core 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client/clientEntry.js +7 -3
- package/lib/client/exports/Link.js +12 -2
- package/lib/client/exports/useBaseUrl.d.ts +8 -0
- package/lib/client/exports/useBaseUrl.js +11 -3
- package/lib/commands/build.js +35 -21
- package/lib/commands/serve.js +15 -4
- package/lib/commands/start/utils.d.ts +3 -2
- package/lib/commands/start/utils.js +7 -2
- package/lib/commands/start/webpack.js +3 -3
- package/lib/server/brokenLinks.js +9 -1
- package/lib/server/codegen/codegen.d.ts +2 -1
- package/lib/server/codegen/codegen.js +4 -0
- package/lib/server/codegen/codegenRoutes.d.ts +1 -0
- package/lib/server/codegen/codegenRoutes.js +20 -6
- package/lib/server/configValidation.d.ts +4 -1
- package/lib/server/configValidation.js +29 -1
- package/lib/server/htmlTags.d.ts +5 -2
- package/lib/server/htmlTags.js +15 -6
- package/lib/server/i18n.js +37 -8
- package/lib/server/site.js +13 -5
- package/lib/server/storage.d.ts +13 -0
- package/lib/server/storage.js +36 -0
- package/lib/ssg.d.ts +4 -0
- package/lib/ssg.js +9 -1
- package/lib/templates/templates.d.ts +3 -0
- package/lib/templates/templates.js +26 -1
- package/lib/webpack/base.js +1 -1
- package/lib/webpack/client.js +10 -18
- package/lib/webpack/configure.d.ts +25 -0
- package/lib/webpack/configure.js +100 -0
- package/lib/webpack/plugins/ForceTerminatePlugin.d.ts +10 -0
- package/lib/webpack/plugins/ForceTerminatePlugin.js +25 -0
- package/lib/webpack/plugins/StaticDirectoriesCopyPlugin.d.ts +11 -0
- package/lib/webpack/plugins/StaticDirectoriesCopyPlugin.js +39 -0
- package/lib/webpack/server.js +0 -28
- package/lib/webpack/utils.d.ts +0 -22
- package/lib/webpack/utils.js +1 -80
- package/package.json +10 -10
package/lib/server/i18n.js
CHANGED
|
@@ -10,8 +10,32 @@ exports.loadI18n = exports.getDefaultLocaleConfig = void 0;
|
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
12
12
|
const rtl_detect_1 = require("rtl-detect");
|
|
13
|
+
function inferLanguageDisplayName(locale) {
|
|
14
|
+
const tryLocale = (l) => {
|
|
15
|
+
try {
|
|
16
|
+
return new Intl.DisplayNames(l, {
|
|
17
|
+
type: 'language',
|
|
18
|
+
fallback: 'code',
|
|
19
|
+
}).of(l);
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
// This is to compensate "of()" that is a bit strict
|
|
23
|
+
// Looks like starting Node 22, this locale throws: "en-US-u-ca-buddhist"
|
|
24
|
+
// RangeError: invalid_argument
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const parts = locale.split('-');
|
|
29
|
+
// This is a best effort, we try various locale forms that could give a result
|
|
30
|
+
return (tryLocale(locale) ??
|
|
31
|
+
tryLocale(`${parts[0]}-${parts[1]}`) ??
|
|
32
|
+
tryLocale(parts[0]));
|
|
33
|
+
}
|
|
13
34
|
function getDefaultLocaleLabel(locale) {
|
|
14
|
-
const languageName =
|
|
35
|
+
const languageName = inferLanguageDisplayName(locale);
|
|
36
|
+
if (!languageName) {
|
|
37
|
+
return locale;
|
|
38
|
+
}
|
|
15
39
|
return (languageName.charAt(0).toLocaleUpperCase(locale) + languageName.substring(1));
|
|
16
40
|
}
|
|
17
41
|
function getDefaultCalendar(localeStr) {
|
|
@@ -34,13 +58,18 @@ function getDefaultCalendar(localeStr) {
|
|
|
34
58
|
return 'gregory';
|
|
35
59
|
}
|
|
36
60
|
function getDefaultLocaleConfig(locale) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
try {
|
|
62
|
+
return {
|
|
63
|
+
label: getDefaultLocaleLabel(locale),
|
|
64
|
+
direction: (0, rtl_detect_1.getLangDir)(locale),
|
|
65
|
+
htmlLang: locale,
|
|
66
|
+
calendar: getDefaultCalendar(locale),
|
|
67
|
+
path: locale,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
throw new Error(`Docusaurus couldn't get default locale config for ${locale}`, { cause: e });
|
|
72
|
+
}
|
|
44
73
|
}
|
|
45
74
|
exports.getDefaultLocaleConfig = getDefaultLocaleConfig;
|
|
46
75
|
async function loadI18n(config, options) {
|
package/lib/server/site.js
CHANGED
|
@@ -21,6 +21,7 @@ const translations_1 = require("./translations/translations");
|
|
|
21
21
|
const utils_2 = require("../utils");
|
|
22
22
|
const codegen_1 = require("./codegen/codegen");
|
|
23
23
|
const routes_1 = require("./routes");
|
|
24
|
+
const storage_1 = require("./storage");
|
|
24
25
|
/**
|
|
25
26
|
* Loading context is the very first step in site building. Its params are
|
|
26
27
|
* directly acquired from CLI options. It mainly loads `siteConfig` and the i18n
|
|
@@ -53,9 +54,11 @@ async function loadContext(params) {
|
|
|
53
54
|
const localizationDir = path_1.default.resolve(siteDir, i18n.path, i18n.localeConfigs[i18n.currentLocale].path);
|
|
54
55
|
const siteConfig = { ...initialSiteConfig, baseUrl };
|
|
55
56
|
const codeTranslations = await (0, translations_1.loadSiteCodeTranslations)({ localizationDir });
|
|
57
|
+
const siteStorage = (0, storage_1.createSiteStorage)(siteConfig);
|
|
56
58
|
return {
|
|
57
59
|
siteDir,
|
|
58
60
|
siteVersion,
|
|
61
|
+
siteStorage,
|
|
59
62
|
generatedFilesDir,
|
|
60
63
|
localizationDir,
|
|
61
64
|
siteConfig,
|
|
@@ -69,8 +72,11 @@ async function loadContext(params) {
|
|
|
69
72
|
exports.loadContext = loadContext;
|
|
70
73
|
function createSiteProps(params) {
|
|
71
74
|
const { plugins, routes, context } = params;
|
|
72
|
-
const { generatedFilesDir, siteDir, siteVersion, siteConfig, siteConfigPath, outDir, baseUrl, i18n, localizationDir, codeTranslations: siteCodeTranslations, } = context;
|
|
73
|
-
const { headTags, preBodyTags, postBodyTags } = (0, htmlTags_1.loadHtmlTags)(
|
|
75
|
+
const { generatedFilesDir, siteDir, siteVersion, siteConfig, siteConfigPath, siteStorage, outDir, baseUrl, i18n, localizationDir, codeTranslations: siteCodeTranslations, } = context;
|
|
76
|
+
const { headTags, preBodyTags, postBodyTags } = (0, htmlTags_1.loadHtmlTags)({
|
|
77
|
+
plugins,
|
|
78
|
+
router: siteConfig.future.experimental_router,
|
|
79
|
+
});
|
|
74
80
|
const siteMetadata = (0, siteMetadata_1.createSiteMetadata)({ plugins, siteVersion });
|
|
75
81
|
const codeTranslations = {
|
|
76
82
|
...(0, translations_1.getPluginsDefaultCodeTranslations)({ plugins }),
|
|
@@ -83,6 +89,7 @@ function createSiteProps(params) {
|
|
|
83
89
|
siteConfigPath,
|
|
84
90
|
siteMetadata,
|
|
85
91
|
siteVersion,
|
|
92
|
+
siteStorage,
|
|
86
93
|
siteDir,
|
|
87
94
|
outDir,
|
|
88
95
|
baseUrl,
|
|
@@ -101,13 +108,14 @@ function createSiteProps(params) {
|
|
|
101
108
|
// TODO global data should be part of site props?
|
|
102
109
|
async function createSiteFiles({ site, globalData, }) {
|
|
103
110
|
return utils_2.PerfLogger.async('Create site files', async () => {
|
|
104
|
-
const { props: { plugins, generatedFilesDir, siteConfig, siteMetadata, i18n, codeTranslations, routes, baseUrl, }, } = site;
|
|
111
|
+
const { props: { plugins, generatedFilesDir, siteConfig, siteMetadata, siteStorage, i18n, codeTranslations, routes, baseUrl, }, } = site;
|
|
105
112
|
const clientModules = (0, clientModules_1.getAllClientModules)(plugins);
|
|
106
113
|
await (0, codegen_1.generateSiteFiles)({
|
|
107
114
|
generatedFilesDir,
|
|
108
115
|
clientModules,
|
|
109
116
|
siteConfig,
|
|
110
117
|
siteMetadata,
|
|
118
|
+
siteStorage,
|
|
111
119
|
i18n,
|
|
112
120
|
codeTranslations,
|
|
113
121
|
globalData,
|
|
@@ -125,7 +133,7 @@ async function createSiteFiles({ site, globalData, }) {
|
|
|
125
133
|
async function loadSite(params) {
|
|
126
134
|
const context = await utils_2.PerfLogger.async('Load context', () => loadContext(params));
|
|
127
135
|
const { plugins, routes, globalData } = await (0, plugins_1.loadPlugins)(context);
|
|
128
|
-
const props =
|
|
136
|
+
const props = createSiteProps({ plugins, routes, globalData, context });
|
|
129
137
|
const site = { props, params };
|
|
130
138
|
await createSiteFiles({
|
|
131
139
|
site,
|
|
@@ -147,7 +155,7 @@ async function reloadSitePlugin(site, pluginIdentifier) {
|
|
|
147
155
|
plugins: site.props.plugins,
|
|
148
156
|
context: site.props,
|
|
149
157
|
});
|
|
150
|
-
const newProps =
|
|
158
|
+
const newProps = createSiteProps({
|
|
151
159
|
plugins,
|
|
152
160
|
routes,
|
|
153
161
|
globalData,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { DocusaurusConfig, SiteStorage } from '@docusaurus/types';
|
|
8
|
+
type PartialFuture = Pick<DocusaurusConfig['future'], 'experimental_storage'>;
|
|
9
|
+
type PartialConfig = Pick<DocusaurusConfig, 'url' | 'baseUrl'> & {
|
|
10
|
+
future: PartialFuture;
|
|
11
|
+
};
|
|
12
|
+
export declare function createSiteStorage(config: PartialConfig): SiteStorage;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createSiteStorage = void 0;
|
|
10
|
+
const utils_1 = require("@docusaurus/utils");
|
|
11
|
+
const utils_common_1 = require("@docusaurus/utils-common");
|
|
12
|
+
function automaticNamespace(config) {
|
|
13
|
+
const normalizedUrl = (0, utils_common_1.addTrailingSlash)((0, utils_1.normalizeUrl)([config.url, config.baseUrl]));
|
|
14
|
+
return (0, utils_1.simpleHash)(normalizedUrl, 3);
|
|
15
|
+
}
|
|
16
|
+
function getNamespaceString(config) {
|
|
17
|
+
if (config.future.experimental_storage.namespace === true) {
|
|
18
|
+
return automaticNamespace(config);
|
|
19
|
+
}
|
|
20
|
+
else if (config.future.experimental_storage.namespace === false) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return config.future.experimental_storage.namespace;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function createSiteStorage(config) {
|
|
28
|
+
const { type } = config.future.experimental_storage;
|
|
29
|
+
const namespaceString = getNamespaceString(config);
|
|
30
|
+
const namespace = namespaceString ? `-${namespaceString}` : '';
|
|
31
|
+
return {
|
|
32
|
+
type,
|
|
33
|
+
namespace,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
exports.createSiteStorage = createSiteStorage;
|
package/lib/ssg.d.ts
CHANGED
|
@@ -30,3 +30,7 @@ export declare function generateStaticFiles({ pathnames, renderer, params, }: {
|
|
|
30
30
|
}): Promise<{
|
|
31
31
|
collectedData: SiteCollectedData;
|
|
32
32
|
}>;
|
|
33
|
+
export declare function generateHashRouterEntrypoint({ content, params, }: {
|
|
34
|
+
content: string;
|
|
35
|
+
params: SSGParams;
|
|
36
|
+
}): Promise<void>;
|
package/lib/ssg.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.generateStaticFiles = exports.loadAppRenderer = void 0;
|
|
9
|
+
exports.generateHashRouterEntrypoint = exports.generateStaticFiles = exports.loadAppRenderer = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
12
|
const module_1 = require("module");
|
|
@@ -133,6 +133,14 @@ It might also require to wrap your client code in ${logger_1.default.code('useEf
|
|
|
133
133
|
}
|
|
134
134
|
return parts.join('\n');
|
|
135
135
|
}
|
|
136
|
+
async function generateHashRouterEntrypoint({ content, params, }) {
|
|
137
|
+
await writeStaticFile({
|
|
138
|
+
pathname: '/',
|
|
139
|
+
content,
|
|
140
|
+
params,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
exports.generateHashRouterEntrypoint = generateHashRouterEntrypoint;
|
|
136
144
|
async function writeStaticFile({ content, pathname, params, }) {
|
|
137
145
|
function removeBaseUrl(p, baseUrl) {
|
|
138
146
|
return baseUrl === '/' ? p : p.replace(new RegExp(`^${baseUrl}`), '/');
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.renderSSRTemplate = exports.compileSSRTemplate = void 0;
|
|
9
|
+
exports.renderHashRouterTemplate = exports.renderSSRTemplate = exports.compileSSRTemplate = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const eta = tslib_1.__importStar(require("eta"));
|
|
12
12
|
const react_loadable_ssr_addon_v5_slorber_1 = require("react-loadable-ssr-addon-v5-slorber");
|
|
@@ -61,3 +61,28 @@ function renderSSRTemplate({ params, result, }) {
|
|
|
61
61
|
return ssrTemplate(data);
|
|
62
62
|
}
|
|
63
63
|
exports.renderSSRTemplate = renderSSRTemplate;
|
|
64
|
+
function renderHashRouterTemplate({ params, }) {
|
|
65
|
+
const {
|
|
66
|
+
// baseUrl,
|
|
67
|
+
headTags, preBodyTags, postBodyTags, manifest, DOCUSAURUS_VERSION, ssrTemplate, } = params;
|
|
68
|
+
const { scripts, stylesheets } = getScriptsAndStylesheets({
|
|
69
|
+
manifest,
|
|
70
|
+
modules: [],
|
|
71
|
+
});
|
|
72
|
+
const data = {
|
|
73
|
+
appHtml: '',
|
|
74
|
+
baseUrl: './',
|
|
75
|
+
htmlAttributes: '',
|
|
76
|
+
bodyAttributes: '',
|
|
77
|
+
headTags,
|
|
78
|
+
preBodyTags,
|
|
79
|
+
postBodyTags,
|
|
80
|
+
metaAttributes: [],
|
|
81
|
+
scripts,
|
|
82
|
+
stylesheets,
|
|
83
|
+
noIndex: false,
|
|
84
|
+
version: DOCUSAURUS_VERSION,
|
|
85
|
+
};
|
|
86
|
+
return ssrTemplate(data);
|
|
87
|
+
}
|
|
88
|
+
exports.renderHashRouterTemplate = renderHashRouterTemplate;
|
package/lib/webpack/base.js
CHANGED
|
@@ -79,7 +79,7 @@ async function createBaseConfig({ props, isServer, minify, }) {
|
|
|
79
79
|
chunkFilename: isProd
|
|
80
80
|
? 'assets/js/[name].[contenthash:8].js'
|
|
81
81
|
: '[name].js',
|
|
82
|
-
publicPath: baseUrl,
|
|
82
|
+
publicPath: siteConfig.future.experimental_router === 'hash' ? 'auto' : baseUrl,
|
|
83
83
|
hashFunction: 'xxhash64',
|
|
84
84
|
},
|
|
85
85
|
// Don't throw warning when asset created is over 250kb
|
package/lib/webpack/client.js
CHANGED
|
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.createBuildClientConfig = exports.createStartClientConfig = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
|
-
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
13
12
|
const webpack_merge_1 = tslib_1.__importDefault(require("webpack-merge"));
|
|
14
13
|
const webpackbar_1 = tslib_1.__importDefault(require("webpackbar"));
|
|
15
14
|
const webpack_1 = tslib_1.__importDefault(require("webpack"));
|
|
@@ -18,21 +17,9 @@ const react_loadable_ssr_addon_v5_slorber_1 = tslib_1.__importDefault(require("r
|
|
|
18
17
|
const html_webpack_plugin_1 = tslib_1.__importDefault(require("html-webpack-plugin"));
|
|
19
18
|
const base_1 = require("./base");
|
|
20
19
|
const ChunkAssetPlugin_1 = tslib_1.__importDefault(require("./plugins/ChunkAssetPlugin"));
|
|
21
|
-
const utils_1 = require("./utils");
|
|
22
20
|
const CleanWebpackPlugin_1 = tslib_1.__importDefault(require("./plugins/CleanWebpackPlugin"));
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ForceTerminatePlugin {
|
|
26
|
-
apply(compiler) {
|
|
27
|
-
compiler.hooks.done.tap('client:done', (stats) => {
|
|
28
|
-
if (stats.hasErrors()) {
|
|
29
|
-
const errorsWarnings = stats.toJson('errors-warnings');
|
|
30
|
-
logger_1.default.error(`Client bundle compiled with errors therefore further build is impossible.\n${(0, utils_1.formatStatsErrorMessage)(errorsWarnings)}`);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
21
|
+
const ForceTerminatePlugin_1 = tslib_1.__importDefault(require("./plugins/ForceTerminatePlugin"));
|
|
22
|
+
const StaticDirectoriesCopyPlugin_1 = require("./plugins/StaticDirectoriesCopyPlugin");
|
|
36
23
|
async function createBaseClientConfig({ props, hydrate, minify, }) {
|
|
37
24
|
const baseConfig = await (0, base_1.createBaseConfig)({ props, isServer: false, minify });
|
|
38
25
|
return (0, webpack_merge_1.default)(baseConfig, {
|
|
@@ -54,6 +41,7 @@ async function createBaseClientConfig({ props, hydrate, minify, }) {
|
|
|
54
41
|
new webpackbar_1.default({
|
|
55
42
|
name: 'Client',
|
|
56
43
|
}),
|
|
44
|
+
await (0, StaticDirectoriesCopyPlugin_1.createStaticDirectoriesCopyPlugin)({ props }),
|
|
57
45
|
],
|
|
58
46
|
});
|
|
59
47
|
}
|
|
@@ -93,11 +81,15 @@ exports.createStartClientConfig = createStartClientConfig;
|
|
|
93
81
|
// client config when running "docusaurus build"
|
|
94
82
|
async function createBuildClientConfig({ props, minify, bundleAnalyzer, }) {
|
|
95
83
|
// Apply user webpack config.
|
|
96
|
-
const { generatedFilesDir } = props;
|
|
84
|
+
const { generatedFilesDir, siteConfig } = props;
|
|
85
|
+
const router = siteConfig.future.experimental_router;
|
|
86
|
+
// With the hash router, we don't hydrate the React app, even in build mode!
|
|
87
|
+
// This is because it will always be a client-rendered React app
|
|
88
|
+
const hydrate = router !== 'hash';
|
|
97
89
|
const clientManifestPath = path_1.default.join(generatedFilesDir, 'client-manifest.json');
|
|
98
|
-
const config = (0, webpack_merge_1.default)(await createBaseClientConfig({ props, minify, hydrate
|
|
90
|
+
const config = (0, webpack_merge_1.default)(await createBaseClientConfig({ props, minify, hydrate }), {
|
|
99
91
|
plugins: [
|
|
100
|
-
new
|
|
92
|
+
new ForceTerminatePlugin_1.default(),
|
|
101
93
|
// Remove/clean build folders before building bundles.
|
|
102
94
|
new CleanWebpackPlugin_1.default({ verbose: false }),
|
|
103
95
|
// Visualize size of webpack output files with an interactive zoomable
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { Configuration, RuleSetRule } from 'webpack';
|
|
8
|
+
import type { Plugin, LoadedPlugin } from '@docusaurus/types';
|
|
9
|
+
/**
|
|
10
|
+
* Helper function to modify webpack config
|
|
11
|
+
* @param configureWebpack a webpack config or a function to modify config
|
|
12
|
+
* @param config initial webpack config
|
|
13
|
+
* @param isServer indicates if this is a server webpack configuration
|
|
14
|
+
* @param jsLoader custom js loader config
|
|
15
|
+
* @param content content loaded by the plugin
|
|
16
|
+
* @returns final/ modified webpack config
|
|
17
|
+
*/
|
|
18
|
+
export declare function applyConfigureWebpack(configureWebpack: NonNullable<Plugin['configureWebpack']>, config: Configuration, isServer: boolean, jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) | undefined, content: unknown): Configuration;
|
|
19
|
+
export declare function applyConfigurePostCss(configurePostCss: NonNullable<Plugin['configurePostCss']>, config: Configuration): Configuration;
|
|
20
|
+
export declare function executePluginsConfigureWebpack({ plugins, config, isServer, jsLoader, }: {
|
|
21
|
+
plugins: LoadedPlugin[];
|
|
22
|
+
config: Configuration;
|
|
23
|
+
isServer: boolean;
|
|
24
|
+
jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) | undefined;
|
|
25
|
+
}): Configuration;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.executePluginsConfigureWebpack = exports.applyConfigurePostCss = exports.applyConfigureWebpack = void 0;
|
|
10
|
+
const webpack_merge_1 = require("webpack-merge");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
/**
|
|
13
|
+
* Helper function to modify webpack config
|
|
14
|
+
* @param configureWebpack a webpack config or a function to modify config
|
|
15
|
+
* @param config initial webpack config
|
|
16
|
+
* @param isServer indicates if this is a server webpack configuration
|
|
17
|
+
* @param jsLoader custom js loader config
|
|
18
|
+
* @param content content loaded by the plugin
|
|
19
|
+
* @returns final/ modified webpack config
|
|
20
|
+
*/
|
|
21
|
+
function applyConfigureWebpack(configureWebpack, config, isServer, jsLoader, content) {
|
|
22
|
+
// Export some utility functions
|
|
23
|
+
const utils = {
|
|
24
|
+
getStyleLoaders: utils_1.getStyleLoaders,
|
|
25
|
+
getJSLoader: (0, utils_1.getCustomizableJSLoader)(jsLoader),
|
|
26
|
+
};
|
|
27
|
+
if (typeof configureWebpack === 'function') {
|
|
28
|
+
const { mergeStrategy, ...res } = configureWebpack(config, isServer, utils, content) ?? {};
|
|
29
|
+
const customizeRules = mergeStrategy ?? {};
|
|
30
|
+
return (0, webpack_merge_1.mergeWithCustomize)({
|
|
31
|
+
customizeArray: (0, webpack_merge_1.customizeArray)(customizeRules),
|
|
32
|
+
customizeObject: (0, webpack_merge_1.customizeObject)(customizeRules),
|
|
33
|
+
})(config, res);
|
|
34
|
+
}
|
|
35
|
+
return config;
|
|
36
|
+
}
|
|
37
|
+
exports.applyConfigureWebpack = applyConfigureWebpack;
|
|
38
|
+
function applyConfigurePostCss(configurePostCss, config) {
|
|
39
|
+
// Not ideal heuristic but good enough for our use-case?
|
|
40
|
+
function isPostCssLoader(loader) {
|
|
41
|
+
return !!loader?.options?.postcssOptions;
|
|
42
|
+
}
|
|
43
|
+
// Does not handle all edge cases, but good enough for now
|
|
44
|
+
function overridePostCssOptions(entry) {
|
|
45
|
+
if (isPostCssLoader(entry)) {
|
|
46
|
+
entry.options.postcssOptions = configurePostCss(entry.options.postcssOptions);
|
|
47
|
+
}
|
|
48
|
+
else if (Array.isArray(entry.oneOf)) {
|
|
49
|
+
entry.oneOf.forEach((r) => {
|
|
50
|
+
if (r) {
|
|
51
|
+
overridePostCssOptions(r);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else if (Array.isArray(entry.use)) {
|
|
56
|
+
entry.use
|
|
57
|
+
.filter((u) => typeof u === 'object')
|
|
58
|
+
.forEach((rule) => overridePostCssOptions(rule));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
config.module?.rules?.forEach((rule) => overridePostCssOptions(rule));
|
|
62
|
+
return config;
|
|
63
|
+
}
|
|
64
|
+
exports.applyConfigurePostCss = applyConfigurePostCss;
|
|
65
|
+
// Plugin Lifecycle - configurePostCss()
|
|
66
|
+
function executePluginsConfigurePostCss({ plugins, config, }) {
|
|
67
|
+
let resultConfig = config;
|
|
68
|
+
plugins.forEach((plugin) => {
|
|
69
|
+
const { configurePostCss } = plugin;
|
|
70
|
+
if (configurePostCss) {
|
|
71
|
+
resultConfig = applyConfigurePostCss(configurePostCss.bind(plugin), resultConfig);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return resultConfig;
|
|
75
|
+
}
|
|
76
|
+
// Plugin Lifecycle - configureWebpack()
|
|
77
|
+
function executePluginsConfigureWebpack({ plugins, config, isServer, jsLoader, }) {
|
|
78
|
+
// Step1 - Configure Webpack
|
|
79
|
+
let resultConfig = config;
|
|
80
|
+
plugins.forEach((plugin) => {
|
|
81
|
+
const { configureWebpack } = plugin;
|
|
82
|
+
if (configureWebpack) {
|
|
83
|
+
resultConfig = applyConfigureWebpack(configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
|
84
|
+
resultConfig, isServer, jsLoader, plugin.content);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// Step2 - For client code, configure PostCSS
|
|
88
|
+
// The order matters! We want to configure PostCSS on loaders
|
|
89
|
+
// that were potentially added by configureWebpack
|
|
90
|
+
// See https://github.com/facebook/docusaurus/issues/10106
|
|
91
|
+
// Note: it's useless to configure postCSS for the server
|
|
92
|
+
if (!isServer) {
|
|
93
|
+
resultConfig = executePluginsConfigurePostCss({
|
|
94
|
+
plugins,
|
|
95
|
+
config: resultConfig,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return resultConfig;
|
|
99
|
+
}
|
|
100
|
+
exports.executePluginsConfigureWebpack = executePluginsConfigureWebpack;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type webpack from 'webpack';
|
|
8
|
+
export default class ForceTerminatePlugin implements webpack.WebpackPluginInstance {
|
|
9
|
+
apply(compiler: webpack.Compiler): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
10
|
+
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
// When building, include the plugin to force terminate building if errors
|
|
13
|
+
// happened in the client bundle.
|
|
14
|
+
class ForceTerminatePlugin {
|
|
15
|
+
apply(compiler) {
|
|
16
|
+
compiler.hooks.done.tap('client:done', (stats) => {
|
|
17
|
+
if (stats.hasErrors()) {
|
|
18
|
+
const errorsWarnings = stats.toJson('errors-warnings');
|
|
19
|
+
logger_1.default.error(`Client bundle compiled with errors therefore further build is impossible.\n${(0, utils_1.formatStatsErrorMessage)(errorsWarnings)}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.default = ForceTerminatePlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
|
8
|
+
import type { Props } from '@docusaurus/types';
|
|
9
|
+
export declare function createStaticDirectoriesCopyPlugin({ props, }: {
|
|
10
|
+
props: Props;
|
|
11
|
+
}): Promise<CopyWebpackPlugin | undefined>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createStaticDirectoriesCopyPlugin = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
13
|
+
const copy_webpack_plugin_1 = tslib_1.__importDefault(require("copy-webpack-plugin"));
|
|
14
|
+
async function createStaticDirectoriesCopyPlugin({ props, }) {
|
|
15
|
+
const { outDir, siteDir, siteConfig: { staticDirectories: staticDirectoriesOption }, } = props;
|
|
16
|
+
// The staticDirectories option can contain empty directories, or non-existent
|
|
17
|
+
// directories (e.g. user deleted `static`). Instead of issuing an error, we
|
|
18
|
+
// just silently filter them out, because user could have never configured it
|
|
19
|
+
// in the first place (the default option should always "work").
|
|
20
|
+
const staticDirectories = (await Promise.all(staticDirectoriesOption.map(async (dir) => {
|
|
21
|
+
const staticDir = path_1.default.resolve(siteDir, dir);
|
|
22
|
+
if ((await fs_extra_1.default.pathExists(staticDir)) &&
|
|
23
|
+
(await fs_extra_1.default.readdir(staticDir)).length > 0) {
|
|
24
|
+
return staticDir;
|
|
25
|
+
}
|
|
26
|
+
return '';
|
|
27
|
+
}))).filter(Boolean);
|
|
28
|
+
if (staticDirectories.length === 0) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return new copy_webpack_plugin_1.default({
|
|
32
|
+
patterns: staticDirectories.map((dir) => ({
|
|
33
|
+
from: dir,
|
|
34
|
+
to: outDir,
|
|
35
|
+
toType: 'dir',
|
|
36
|
+
})),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
exports.createStaticDirectoriesCopyPlugin = createStaticDirectoriesCopyPlugin;
|
package/lib/webpack/server.js
CHANGED
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
const tslib_1 = require("tslib");
|
|
10
10
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
|
-
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
11
|
const webpack_merge_1 = tslib_1.__importDefault(require("webpack-merge"));
|
|
13
12
|
const utils_1 = require("@docusaurus/utils");
|
|
14
13
|
const webpackbar_1 = tslib_1.__importDefault(require("webpackbar"));
|
|
15
|
-
const copy_webpack_plugin_1 = tslib_1.__importDefault(require("copy-webpack-plugin"));
|
|
16
14
|
const base_1 = require("./base");
|
|
17
15
|
async function createServerConfig(params) {
|
|
18
16
|
const { props } = params;
|
|
@@ -41,34 +39,8 @@ async function createServerConfig(params) {
|
|
|
41
39
|
name: 'Server',
|
|
42
40
|
color: 'yellow',
|
|
43
41
|
}),
|
|
44
|
-
await createStaticDirectoriesCopyPlugin(params),
|
|
45
42
|
].filter(Boolean),
|
|
46
43
|
});
|
|
47
44
|
return { config, serverBundlePath };
|
|
48
45
|
}
|
|
49
46
|
exports.default = createServerConfig;
|
|
50
|
-
async function createStaticDirectoriesCopyPlugin({ props }) {
|
|
51
|
-
const { outDir, siteDir, siteConfig: { staticDirectories: staticDirectoriesOption }, } = props;
|
|
52
|
-
// The staticDirectories option can contain empty directories, or non-existent
|
|
53
|
-
// directories (e.g. user deleted `static`). Instead of issuing an error, we
|
|
54
|
-
// just silently filter them out, because user could have never configured it
|
|
55
|
-
// in the first place (the default option should always "work").
|
|
56
|
-
const staticDirectories = (await Promise.all(staticDirectoriesOption.map(async (dir) => {
|
|
57
|
-
const staticDir = path_1.default.resolve(siteDir, dir);
|
|
58
|
-
if ((await fs_extra_1.default.pathExists(staticDir)) &&
|
|
59
|
-
(await fs_extra_1.default.readdir(staticDir)).length > 0) {
|
|
60
|
-
return staticDir;
|
|
61
|
-
}
|
|
62
|
-
return '';
|
|
63
|
-
}))).filter(Boolean);
|
|
64
|
-
if (staticDirectories.length === 0) {
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
return new copy_webpack_plugin_1.default({
|
|
68
|
-
patterns: staticDirectories.map((dir) => ({
|
|
69
|
-
from: dir,
|
|
70
|
-
to: outDir,
|
|
71
|
-
toType: 'dir',
|
|
72
|
-
})),
|
|
73
|
-
});
|
|
74
|
-
}
|
package/lib/webpack/utils.d.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
/// <reference types="node" />
|
|
8
8
|
import webpack, { type Configuration, type RuleSetRule } from 'webpack';
|
|
9
9
|
import type { TransformOptions } from '@babel/core';
|
|
10
|
-
import type { Plugin, LoadedPlugin } from '@docusaurus/types';
|
|
11
10
|
export declare function formatStatsErrorMessage(statsJson: ReturnType<webpack.Stats['toJson']> | undefined): string | undefined;
|
|
12
11
|
export declare function printStatsWarnings(statsJson: ReturnType<webpack.Stats['toJson']> | undefined): void;
|
|
13
12
|
export declare function getStyleLoaders(isServer: boolean, cssOptionsArg?: {
|
|
@@ -22,27 +21,6 @@ export declare const getCustomizableJSLoader: (jsLoader?: 'babel' | ((isServer:
|
|
|
22
21
|
isServer: boolean;
|
|
23
22
|
babelOptions?: TransformOptions | string;
|
|
24
23
|
}) => RuleSetRule;
|
|
25
|
-
/**
|
|
26
|
-
* Helper function to modify webpack config
|
|
27
|
-
* @param configureWebpack a webpack config or a function to modify config
|
|
28
|
-
* @param config initial webpack config
|
|
29
|
-
* @param isServer indicates if this is a server webpack configuration
|
|
30
|
-
* @param jsLoader custom js loader config
|
|
31
|
-
* @param content content loaded by the plugin
|
|
32
|
-
* @returns final/ modified webpack config
|
|
33
|
-
*/
|
|
34
|
-
export declare function applyConfigureWebpack(configureWebpack: NonNullable<Plugin['configureWebpack']>, config: Configuration, isServer: boolean, jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) | undefined, content: unknown): Configuration;
|
|
35
|
-
export declare function applyConfigurePostCss(configurePostCss: NonNullable<Plugin['configurePostCss']>, config: Configuration): Configuration;
|
|
36
|
-
export declare function executePluginsConfigurePostCss({ plugins, config, }: {
|
|
37
|
-
plugins: LoadedPlugin[];
|
|
38
|
-
config: Configuration;
|
|
39
|
-
}): Configuration;
|
|
40
|
-
export declare function executePluginsConfigureWebpack({ plugins, config, isServer, jsLoader, }: {
|
|
41
|
-
plugins: LoadedPlugin[];
|
|
42
|
-
config: Configuration;
|
|
43
|
-
isServer: boolean;
|
|
44
|
-
jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) | undefined;
|
|
45
|
-
}): Configuration;
|
|
46
24
|
declare global {
|
|
47
25
|
interface Error {
|
|
48
26
|
/** @see https://webpack.js.org/api/node/#error-handling */
|