@docusaurus/core 2.0.0-beta.21 → 2.0.0-beta.22

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.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/bin/docusaurus.mjs +11 -26
  3. package/lib/client/BaseUrlIssueBanner/index.js +1 -0
  4. package/lib/client/PendingNavigation.js +7 -1
  5. package/lib/client/exports/ErrorBoundary.js +1 -0
  6. package/lib/client/serverEntry.js +3 -0
  7. package/lib/commands/build.d.ts +1 -1
  8. package/lib/commands/build.js +2 -1
  9. package/lib/commands/clear.d.ts +1 -1
  10. package/lib/commands/clear.js +2 -1
  11. package/lib/commands/deploy.d.ts +1 -1
  12. package/lib/commands/deploy.js +12 -1
  13. package/lib/commands/external.d.ts +1 -1
  14. package/lib/commands/external.js +4 -1
  15. package/lib/commands/serve.d.ts +1 -1
  16. package/lib/commands/serve.js +3 -1
  17. package/lib/commands/start.d.ts +1 -1
  18. package/lib/commands/start.js +5 -11
  19. package/lib/commands/swizzle/actions.js +3 -2
  20. package/lib/commands/swizzle/index.d.ts +1 -1
  21. package/lib/commands/swizzle/index.js +3 -1
  22. package/lib/commands/writeHeadingIds.d.ts +1 -1
  23. package/lib/commands/writeHeadingIds.js +2 -1
  24. package/lib/commands/writeTranslations.d.ts +1 -1
  25. package/lib/commands/writeTranslations.js +8 -6
  26. package/lib/server/brokenLinks.js +1 -1
  27. package/lib/server/configValidation.js +6 -3
  28. package/lib/server/i18n.js +2 -0
  29. package/lib/server/index.js +8 -6
  30. package/lib/server/plugins/index.js +1 -2
  31. package/lib/server/plugins/synthetic.js +1 -2
  32. package/lib/server/routes.js +2 -5
  33. package/lib/server/translations/translations.d.ts +3 -5
  34. package/lib/server/translations/translations.js +8 -16
  35. package/lib/webpack/server.js +5 -0
  36. package/package.json +26 -27
  37. package/lib/client/.eslintrc.js +0 -27
package/README.md CHANGED
@@ -0,0 +1 @@
1
+ # Docusaurus core
@@ -8,7 +8,6 @@
8
8
 
9
9
  // @ts-check
10
10
 
11
- import fs from 'fs-extra';
12
11
  import logger from '@docusaurus/logger';
13
12
  import cli from 'commander';
14
13
  import {DOCUSAURUS_VERSION} from '@docusaurus/utils';
@@ -27,8 +26,6 @@ import beforeCli from './beforeCli.mjs';
27
26
 
28
27
  await beforeCli();
29
28
 
30
- const resolveDir = (dir = '.') => fs.realpath(dir);
31
-
32
29
  cli.version(DOCUSAURUS_VERSION).usage('<command> [options]');
33
30
 
34
31
  cli
@@ -54,9 +51,9 @@ cli
54
51
  '--no-minify',
55
52
  'build website without minimizing JS bundles (default: false)',
56
53
  )
57
- .action(async (siteDir, options) => {
58
- build(await resolveDir(siteDir), options);
59
- });
54
+ // @ts-expect-error: Promise<string> is not assignable to Promise<void>... but
55
+ // good enough here.
56
+ .action(build);
60
57
 
61
58
  cli
62
59
  .command('swizzle [themeName] [componentName] [siteDir]')
@@ -80,9 +77,7 @@ cli
80
77
  'copy TypeScript theme files when possible (default: false)',
81
78
  )
82
79
  .option('--danger', 'enable swizzle for unsafe component of themes')
83
- .action(async (themeName, componentName, siteDir, options) =>
84
- swizzle(await resolveDir(siteDir), themeName, componentName, options),
85
- );
80
+ .action(swizzle);
86
81
 
87
82
  cli
88
83
  .command('deploy [siteDir]')
@@ -103,9 +98,7 @@ cli
103
98
  '--skip-build',
104
99
  'skip building website before deploy it (default: false)',
105
100
  )
106
- .action(async (siteDir, options) =>
107
- deploy(await resolveDir(siteDir), options),
108
- );
101
+ .action(deploy);
109
102
 
110
103
  cli
111
104
  .command('start [siteDir]')
@@ -130,9 +123,7 @@ cli
130
123
  '--no-minify',
131
124
  'build website without minimizing JS bundles (default: false)',
132
125
  )
133
- .action(async (siteDir, options) =>
134
- start(await resolveDir(siteDir), options),
135
- );
126
+ .action(start);
136
127
 
137
128
  cli
138
129
  .command('serve [siteDir]')
@@ -152,14 +143,12 @@ cli
152
143
  '--no-open',
153
144
  'do not open page in the browser (default: false, or true in CI)',
154
145
  )
155
- .action(async (siteDir, options) =>
156
- serve(await resolveDir(siteDir), options),
157
- );
146
+ .action(serve);
158
147
 
159
148
  cli
160
149
  .command('clear [siteDir]')
161
150
  .description('Remove build artifacts.')
162
- .action(async (siteDir) => clear(await resolveDir(siteDir)));
151
+ .action(clear);
163
152
 
164
153
  cli
165
154
  .command('write-translations [siteDir]')
@@ -180,9 +169,7 @@ cli
180
169
  '--messagePrefix <messagePrefix>',
181
170
  'Allows to init new written messages with a given prefix. This might help you to highlight untranslated message by making them stand out in the UI (default: "")',
182
171
  )
183
- .action(async (siteDir, options) =>
184
- writeTranslations(await resolveDir(siteDir), options),
185
- );
172
+ .action(writeTranslations);
186
173
 
187
174
  cli
188
175
  .command('write-heading-ids [siteDir] [files...]')
@@ -192,9 +179,7 @@ cli
192
179
  "keep the headings' casing, otherwise make all lowercase (default: false)",
193
180
  )
194
181
  .option('--overwrite', 'overwrite existing heading IDs (default: false)')
195
- .action(async (siteDir, files, options) =>
196
- writeHeadingIds(await resolveDir(siteDir), files, options),
197
- );
182
+ .action(writeHeadingIds);
198
183
 
199
184
  cli.arguments('<command>').action((cmd) => {
200
185
  cli.outputHelp();
@@ -221,7 +206,7 @@ function isInternalCommand(command) {
221
206
  }
222
207
 
223
208
  if (!isInternalCommand(process.argv.slice(2)[0])) {
224
- await externalCommand(cli, await resolveDir('.'));
209
+ await externalCommand(cli);
225
210
  }
226
211
 
227
212
  if (!process.argv.slice(2).length) {
@@ -32,6 +32,7 @@ function createInlineHtmlBanner(baseUrl) {
32
32
  }
33
33
  // Needs to work for older browsers!
34
34
  function createInlineScript(baseUrl) {
35
+ /* language=js */
35
36
  return `
36
37
  window['${InsertBannerWindowAttribute}'] = true;
37
38
 
@@ -52,7 +52,13 @@ class PendingNavigation extends React.Component {
52
52
  this.routeUpdateCleanupCb();
53
53
  this.setState({ nextRouteHasLoaded: true });
54
54
  })
55
- .catch((e) => console.warn(e));
55
+ .catch((e) => {
56
+ console.warn(e);
57
+ // If chunk loading failed, it could be because the path to a chunk
58
+ // no longer exists due to a new deployment. Force refresh the page
59
+ // instead of just not navigating.
60
+ window.location.reload();
61
+ });
56
62
  return false;
57
63
  }
58
64
  render() {
@@ -7,6 +7,7 @@
7
7
  import React from 'react';
8
8
  import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
9
9
  import ThemeError from '@theme/Error';
10
+ // eslint-disable-next-line react/function-component-definition
10
11
  const DefaultFallback = (params) => (<ThemeError {...params}/>);
11
12
  export default class ErrorBoundary extends React.Component {
12
13
  constructor(props) {
@@ -108,6 +108,9 @@ async function doRender(locals) {
108
108
  version: DOCUSAURUS_VERSION,
109
109
  });
110
110
  try {
111
+ if (process.env.SKIP_HTML_MINIFICATION === 'true') {
112
+ return renderedHtml;
113
+ }
111
114
  // Minify html with https://github.com/DanielRuf/html-minifier-terser
112
115
  return await minify(renderedHtml, {
113
116
  removeComments: false,
@@ -9,4 +9,4 @@ export declare type BuildCLIOptions = Pick<LoadContextOptions, 'config' | 'local
9
9
  bundleAnalyzer?: boolean;
10
10
  minify?: boolean;
11
11
  };
12
- export declare function build(siteDir: string, cliOptions: Partial<BuildCLIOptions>, forceTerminate?: boolean): Promise<string>;
12
+ export declare function build(siteDirParam?: string, cliOptions?: Partial<BuildCLIOptions>, forceTerminate?: boolean): Promise<string>;
@@ -23,12 +23,13 @@ const server_2 = tslib_1.__importDefault(require("../webpack/server"));
23
23
  const utils_2 = require("../webpack/utils");
24
24
  const CleanWebpackPlugin_1 = tslib_1.__importDefault(require("../webpack/plugins/CleanWebpackPlugin"));
25
25
  const i18n_1 = require("../server/i18n");
26
- async function build(siteDir, cliOptions,
26
+ async function build(siteDirParam = '.', cliOptions = {},
27
27
  // When running build, we force terminate the process to prevent async
28
28
  // operations from never returning. However, if run as part of docusaurus
29
29
  // deploy, we have to let deploy finish.
30
30
  // See https://github.com/facebook/docusaurus/pull/2496
31
31
  forceTerminate = true) {
32
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
32
33
  ['SIGINT', 'SIGTERM'].forEach((sig) => {
33
34
  process.on(sig, () => process.exit());
34
35
  });
@@ -4,4 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export declare function clear(siteDir: string): Promise<void>;
7
+ export declare function clear(siteDirParam?: string): Promise<void>;
@@ -25,7 +25,8 @@ async function removePath(entry) {
25
25
  logger_1.default.error(err);
26
26
  }
27
27
  }
28
- async function clear(siteDir) {
28
+ async function clear(siteDirParam = '.') {
29
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
29
30
  const generatedFolder = {
30
31
  path: path_1.default.join(siteDir, utils_1.GENERATED_FILES_DIR_NAME),
31
32
  description: 'generated folder',
@@ -8,4 +8,4 @@ import { type LoadContextOptions } from '../server';
8
8
  export declare type DeployCLIOptions = Pick<LoadContextOptions, 'config' | 'locale' | 'outDir'> & {
9
9
  skipBuild?: boolean;
10
10
  };
11
- export declare function deploy(siteDir: string, cliOptions: Partial<DeployCLIOptions>): Promise<void>;
11
+ export declare function deploy(siteDirParam?: string, cliOptions?: Partial<DeployCLIOptions>): Promise<void>;
@@ -34,7 +34,8 @@ function shellExecLog(cmd) {
34
34
  throw err;
35
35
  }
36
36
  }
37
- async function deploy(siteDir, cliOptions) {
37
+ async function deploy(siteDirParam = '.', cliOptions = {}) {
38
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
38
39
  const { outDir, siteConfig, siteConfigPath } = await (0, server_1.loadContext)({
39
40
  siteDir,
40
41
  config: cliOptions.config,
@@ -126,6 +127,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
126
127
  // Save the commit hash that triggers publish-gh-pages before checking
127
128
  // out to deployment branch.
128
129
  const currentCommit = shellExecLog('git rev-parse HEAD').stdout.trim();
130
+ const currentGitRootDir = shellExecLog('git rev-parse --show-toplevel').stdout.trim();
129
131
  const runDeploy = async (outputDirectory) => {
130
132
  const fromPath = outputDirectory;
131
133
  const toPath = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), `${projectName}-${deploymentBranch}`));
@@ -149,6 +151,15 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
149
151
  logger_1.default.error `Copying build assets from path=${fromPath} to path=${toPath} failed.`;
150
152
  throw err;
151
153
  }
154
+ const gitConfigFromPath = path_1.default.join(currentGitRootDir, `.git`, `config`);
155
+ const gitConfigToPath = path_1.default.join(toPath, `.git`, `config`);
156
+ try {
157
+ await fs_extra_1.default.copy(gitConfigFromPath, gitConfigToPath);
158
+ }
159
+ catch (err) {
160
+ logger_1.default.error `Copying git config from path=${gitConfigFromPath} to path=${gitConfigToPath} failed.`;
161
+ throw err;
162
+ }
152
163
  shellExecLog('git add --all');
153
164
  const commitMessage = process.env.CUSTOM_COMMIT_MESSAGE ??
154
165
  `Deploy website - based on ${currentCommit}`;
@@ -5,4 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { CommanderStatic } from 'commander';
8
- export declare function externalCommand(cli: CommanderStatic, siteDir: string): Promise<void>;
8
+ export declare function externalCommand(cli: CommanderStatic): Promise<void>;
@@ -7,9 +7,12 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.externalCommand = void 0;
10
+ const tslib_1 = require("tslib");
11
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
10
12
  const server_1 = require("../server");
11
13
  const init_1 = require("../server/plugins/init");
12
- async function externalCommand(cli, siteDir) {
14
+ async function externalCommand(cli) {
15
+ const siteDir = await fs_extra_1.default.realpath('.');
13
16
  const context = await (0, server_1.loadContext)({ siteDir });
14
17
  const plugins = await (0, init_1.initPlugins)(context);
15
18
  // Plugin Lifecycle - extendCli.
@@ -11,4 +11,4 @@ export declare type ServeCLIOptions = HostPortOptions & Pick<LoadContextOptions,
11
11
  build?: boolean;
12
12
  open?: boolean;
13
13
  };
14
- export declare function serve(siteDir: string, cliOptions: Partial<ServeCLIOptions>): Promise<void>;
14
+ export declare function serve(siteDirParam?: string, cliOptions?: Partial<ServeCLIOptions>): Promise<void>;
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.serve = void 0;
10
10
  const tslib_1 = require("tslib");
11
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
11
12
  const http_1 = tslib_1.__importDefault(require("http"));
12
13
  const path_1 = tslib_1.__importDefault(require("path"));
13
14
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
@@ -17,7 +18,8 @@ const openBrowser_1 = tslib_1.__importDefault(require("react-dev-utils/openBrows
17
18
  const config_1 = require("../server/config");
18
19
  const build_1 = require("./build");
19
20
  const getHostPort_1 = require("../server/getHostPort");
20
- async function serve(siteDir, cliOptions) {
21
+ async function serve(siteDirParam = '.', cliOptions = {}) {
22
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
21
23
  const buildDir = cliOptions.dir ?? utils_1.DEFAULT_BUILD_DIR_NAME;
22
24
  let dir = path_1.default.resolve(siteDir, buildDir);
23
25
  if (cliOptions.build) {
@@ -12,4 +12,4 @@ export declare type StartCLIOptions = HostPortOptions & Pick<LoadContextOptions,
12
12
  poll?: boolean | number;
13
13
  minify?: boolean;
14
14
  };
15
- export declare function start(siteDir: string, cliOptions: Partial<StartCLIOptions>): Promise<void>;
15
+ export declare function start(siteDirParam?: string, cliOptions?: Partial<StartCLIOptions>): Promise<void>;
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.start = void 0;
10
10
  const tslib_1 = require("tslib");
11
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
11
12
  const path_1 = tslib_1.__importDefault(require("path"));
12
13
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
13
14
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
@@ -24,8 +25,8 @@ const server_1 = require("../server");
24
25
  const client_1 = tslib_1.__importDefault(require("../webpack/client"));
25
26
  const utils_2 = require("../webpack/utils");
26
27
  const getHostPort_1 = require("../server/getHostPort");
27
- const translations_1 = require("../server/translations/translations");
28
- async function start(siteDir, cliOptions) {
28
+ async function start(siteDirParam = '.', cliOptions = {}) {
29
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
29
30
  process.env.NODE_ENV = 'development';
30
31
  process.env.BABEL_ENV = 'development';
31
32
  logger_1.default.info('Starting the development server...');
@@ -61,7 +62,7 @@ async function start(siteDir, cliOptions) {
61
62
  logger_1.default.error(err.stack);
62
63
  });
63
64
  }, 500);
64
- const { siteConfig, plugins } = props;
65
+ const { siteConfig, plugins, localizationDir } = props;
65
66
  const normalizeToSiteDir = (filepath) => {
66
67
  if (filepath && path_1.default.isAbsolute(filepath)) {
67
68
  return (0, utils_1.posixPath)(path_1.default.relative(siteDir, filepath));
@@ -72,14 +73,7 @@ async function start(siteDir, cliOptions) {
72
73
  .flatMap((plugin) => plugin.getPathsToWatch?.() ?? [])
73
74
  .filter(Boolean)
74
75
  .map(normalizeToSiteDir);
75
- const pathsToWatch = [
76
- ...pluginPaths,
77
- props.siteConfigPath,
78
- (0, translations_1.getTranslationsLocaleDirPath)({
79
- siteDir,
80
- locale: props.i18n.currentLocale,
81
- }),
82
- ];
76
+ const pathsToWatch = [...pluginPaths, props.siteConfigPath, localizationDir];
83
77
  const pollingOptions = {
84
78
  usePolling: !!cliOptions.poll,
85
79
  interval: Number.isInteger(cliOptions.poll)
@@ -69,11 +69,12 @@ async function wrap({ siteDir, themePath, componentName: themeComponentName, typ
69
69
  await fs_extra_1.default.ensureDir(path_1.default.resolve(siteDir, utils_1.THEME_PATH));
70
70
  const toPath = path_1.default.resolve(siteDir, utils_1.THEME_PATH, wrapperFileName);
71
71
  const content = typescript
72
- ? `import React, {ComponentProps} from 'react';
72
+ ? `import React from 'react';
73
73
  import ${componentName} from '@theme-${importType}/${themeComponentName}';
74
74
  import type ${componentName}Type from '@theme/${themeComponentName}';
75
+ import type {WrapperProps} from '@docusaurus/types';
75
76
 
76
- type Props = ComponentProps<typeof ${componentName}Type>;
77
+ type Props = WrapperProps<typeof ${componentName}Type>;
77
78
 
78
79
  export default function ${wrapperComponentName}(props: Props): JSX.Element {
79
80
  return (
@@ -5,4 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { SwizzleCLIOptions } from './common';
8
- export declare function swizzle(siteDir: string, themeNameParam: string | undefined, componentNameParam: string | undefined, optionsParam: Partial<SwizzleCLIOptions>): Promise<void>;
8
+ export declare function swizzle(themeNameParam?: string | undefined, componentNameParam?: string | undefined, siteDirParam?: string, optionsParam?: Partial<SwizzleCLIOptions>): Promise<void>;
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.swizzle = void 0;
10
10
  const tslib_1 = require("tslib");
11
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
11
12
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
12
13
  const themes_1 = require("./themes");
13
14
  const components_1 = require("./components");
@@ -57,7 +58,8 @@ If you want to swizzle it, use the code=${'--danger'} flag, or confirm that you
57
58
  }
58
59
  return undefined;
59
60
  }
60
- async function swizzle(siteDir, themeNameParam, componentNameParam, optionsParam) {
61
+ async function swizzle(themeNameParam = undefined, componentNameParam = undefined, siteDirParam = '.', optionsParam = {}) {
62
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
61
63
  const options = (0, common_1.normalizeOptions)(optionsParam);
62
64
  const { list, danger, typescript } = options;
63
65
  const { plugins } = await (0, context_1.initSwizzleContext)(siteDir);
@@ -5,4 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { type WriteHeadingIDOptions } from '@docusaurus/utils';
8
- export declare function writeHeadingIds(siteDir: string, files: string[] | undefined, options: WriteHeadingIDOptions): Promise<void>;
8
+ export declare function writeHeadingIds(siteDirParam?: string, files?: string[], options?: WriteHeadingIDOptions): Promise<void>;
@@ -34,7 +34,8 @@ async function getPathsToWatch(siteDir) {
34
34
  const plugins = await (0, init_1.initPlugins)(context);
35
35
  return plugins.flatMap((plugin) => plugin.getPathsToWatch?.() ?? []);
36
36
  }
37
- async function writeHeadingIds(siteDir, files, options) {
37
+ async function writeHeadingIds(siteDirParam = '.', files = [], options = {}) {
38
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
38
39
  const markdownFiles = await (0, utils_2.safeGlobby)(files ?? (await getPathsToWatch(siteDir)), {
39
40
  expandDirectories: ['**/*.{md,mdx}'],
40
41
  });
@@ -7,4 +7,4 @@
7
7
  import { type LoadContextOptions } from '../server';
8
8
  import { type WriteTranslationsOptions } from '../server/translations/translations';
9
9
  export declare type WriteTranslationsCLIOptions = Pick<LoadContextOptions, 'config' | 'locale'> & WriteTranslationsOptions;
10
- export declare function writeTranslations(siteDir: string, options: Partial<WriteTranslationsCLIOptions>): Promise<void>;
10
+ export declare function writeTranslations(siteDirParam?: string, options?: Partial<WriteTranslationsCLIOptions>): Promise<void>;
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.writeTranslations = void 0;
10
10
  const tslib_1 = require("tslib");
11
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
11
12
  const path_1 = tslib_1.__importDefault(require("path"));
12
13
  const server_1 = require("../server");
13
14
  const init_1 = require("../server/plugins/init");
@@ -30,7 +31,7 @@ async function getExtraSourceCodeFilePaths() {
30
31
  return []; // User may not use a Docusaurus official theme? Quite unlikely...
31
32
  }
32
33
  }
33
- async function writePluginTranslationFiles({ siteDir, plugin, locale, options, }) {
34
+ async function writePluginTranslationFiles({ localizationDir, plugin, options, }) {
34
35
  if (plugin.getTranslationFiles) {
35
36
  const content = await plugin.loadContent?.();
36
37
  const translationFiles = await plugin.getTranslationFiles({
@@ -38,21 +39,22 @@ async function writePluginTranslationFiles({ siteDir, plugin, locale, options, }
38
39
  });
39
40
  await Promise.all(translationFiles.map(async (translationFile) => {
40
41
  await (0, translations_1.writePluginTranslations)({
41
- siteDir,
42
+ localizationDir,
42
43
  plugin,
43
44
  translationFile,
44
- locale,
45
45
  options,
46
46
  });
47
47
  }));
48
48
  }
49
49
  }
50
- async function writeTranslations(siteDir, options) {
50
+ async function writeTranslations(siteDirParam = '.', options = {}) {
51
+ const siteDir = await fs_extra_1.default.realpath(siteDirParam);
51
52
  const context = await (0, server_1.loadContext)({
52
53
  siteDir,
53
54
  config: options.config,
54
55
  locale: options.locale,
55
56
  });
57
+ const { localizationDir } = context;
56
58
  const plugins = await (0, init_1.initPlugins)(context);
57
59
  const locale = options.locale ?? context.i18n.defaultLocale;
58
60
  if (!context.i18n.locales.includes(locale)) {
@@ -69,9 +71,9 @@ Available locales are: ${context.i18n.locales.join(',')}.`);
69
71
  extractedCodeTranslations,
70
72
  defaultCodeMessages,
71
73
  });
72
- await (0, translations_1.writeCodeTranslations)({ siteDir, locale }, codeTranslations, options);
74
+ await (0, translations_1.writeCodeTranslations)({ localizationDir }, codeTranslations, options);
73
75
  await Promise.all(plugins.map(async (plugin) => {
74
- await writePluginTranslationFiles({ siteDir, plugin, locale, options });
76
+ await writePluginTranslationFiles({ localizationDir, plugin, options });
75
77
  }));
76
78
  }
77
79
  exports.writeTranslations = writeTranslations;
@@ -150,7 +150,7 @@ async function handleBrokenLinks({ allCollectedLinks, onBrokenLinks, routes, bas
150
150
  });
151
151
  const errorMessage = getBrokenLinksErrorMessage(allBrokenLinks);
152
152
  if (errorMessage) {
153
- (0, utils_1.reportMessage)(errorMessage, onBrokenLinks);
153
+ logger_1.default.report(onBrokenLinks)(errorMessage);
154
154
  }
155
155
  }
156
156
  exports.handleBrokenLinks = handleBrokenLinks;
@@ -12,6 +12,7 @@ const utils_validation_1 = require("@docusaurus/utils-validation");
12
12
  const DEFAULT_I18N_LOCALE = 'en';
13
13
  exports.DEFAULT_I18N_CONFIG = {
14
14
  defaultLocale: DEFAULT_I18N_LOCALE,
15
+ path: utils_1.DEFAULT_I18N_DIR_NAME,
15
16
  locales: [DEFAULT_I18N_LOCALE],
16
17
  localeConfigs: {},
17
18
  };
@@ -88,9 +89,11 @@ const LocaleConfigSchema = utils_validation_1.Joi.object({
88
89
  htmlLang: utils_validation_1.Joi.string(),
89
90
  direction: utils_validation_1.Joi.string().equal('ltr', 'rtl').default('ltr'),
90
91
  calendar: utils_validation_1.Joi.string(),
92
+ path: utils_validation_1.Joi.string(),
91
93
  });
92
94
  const I18N_CONFIG_SCHEMA = utils_validation_1.Joi.object({
93
95
  defaultLocale: utils_validation_1.Joi.string().required(),
96
+ path: utils_validation_1.Joi.string().default(exports.DEFAULT_I18N_CONFIG.path),
94
97
  locales: utils_validation_1.Joi.array().items().min(1).items(utils_validation_1.Joi.string().required()).required(),
95
98
  localeConfigs: utils_validation_1.Joi.object()
96
99
  .pattern(/.*/, LocaleConfigSchema)
@@ -123,13 +126,13 @@ exports.ConfigSchema = utils_validation_1.Joi.object({
123
126
  trailingSlash: utils_validation_1.Joi.boolean(),
124
127
  i18n: I18N_CONFIG_SCHEMA,
125
128
  onBrokenLinks: utils_validation_1.Joi.string()
126
- .equal('ignore', 'log', 'warn', 'error', 'throw')
129
+ .equal('ignore', 'log', 'warn', 'throw')
127
130
  .default(exports.DEFAULT_CONFIG.onBrokenLinks),
128
131
  onBrokenMarkdownLinks: utils_validation_1.Joi.string()
129
- .equal('ignore', 'log', 'warn', 'error', 'throw')
132
+ .equal('ignore', 'log', 'warn', 'throw')
130
133
  .default(exports.DEFAULT_CONFIG.onBrokenMarkdownLinks),
131
134
  onDuplicateRoutes: utils_validation_1.Joi.string()
132
- .equal('ignore', 'log', 'warn', 'error', 'throw')
135
+ .equal('ignore', 'log', 'warn', 'throw')
133
136
  .default(exports.DEFAULT_CONFIG.onDuplicateRoutes),
134
137
  organizationName: utils_validation_1.Joi.string().allow(''),
135
138
  staticDirectories: utils_validation_1.Joi.array()
@@ -21,6 +21,7 @@ function getDefaultLocaleConfig(locale) {
21
21
  htmlLang: locale,
22
22
  // If the locale name includes -u-ca-xxx the calendar will be defined
23
23
  calendar: new Intl.Locale(locale).calendar ?? 'gregory',
24
+ path: locale,
24
25
  };
25
26
  }
26
27
  exports.getDefaultLocaleConfig = getDefaultLocaleConfig;
@@ -44,6 +45,7 @@ Note: Docusaurus only support running one locale at a time.`;
44
45
  return {
45
46
  defaultLocale: i18nConfig.defaultLocale,
46
47
  locales,
48
+ path: i18nConfig.path,
47
49
  currentLocale,
48
50
  localeConfigs,
49
51
  };
@@ -46,15 +46,14 @@ async function loadContext(options) {
46
46
  pathType: 'fs',
47
47
  });
48
48
  const siteConfig = { ...initialSiteConfig, baseUrl };
49
- const codeTranslationFileContent = (await (0, translations_1.readCodeTranslationFileContent)({
50
- siteDir,
51
- locale: i18n.currentLocale,
52
- })) ?? {};
49
+ const localizationDir = path_1.default.resolve(siteDir, i18n.path, i18n.localeConfigs[i18n.currentLocale].path);
50
+ const codeTranslationFileContent = (await (0, translations_1.readCodeTranslationFileContent)({ localizationDir })) ?? {};
53
51
  // We only need key->message for code translations
54
52
  const codeTranslations = lodash_1.default.mapValues(codeTranslationFileContent, (value) => value.message);
55
53
  return {
56
54
  siteDir,
57
55
  generatedFilesDir,
56
+ localizationDir,
58
57
  siteConfig,
59
58
  siteConfigPath,
60
59
  outDir,
@@ -73,7 +72,7 @@ exports.loadContext = loadContext;
73
72
  async function load(options) {
74
73
  const { siteDir } = options;
75
74
  const context = await loadContext(options);
76
- const { generatedFilesDir, siteConfig, siteConfigPath, outDir, baseUrl, i18n, codeTranslations: siteCodeTranslations, } = context;
75
+ const { generatedFilesDir, siteConfig, siteConfigPath, outDir, baseUrl, i18n, localizationDir, codeTranslations: siteCodeTranslations, } = context;
77
76
  const { plugins, pluginsRouteConfigs, globalData } = await (0, plugins_1.loadPlugins)(context);
78
77
  const clientModules = (0, clientModules_1.loadClientModules)(plugins);
79
78
  const { headTags, preBodyTags, postBodyTags } = (0, htmlTags_1.loadHtmlTags)(plugins);
@@ -84,7 +83,9 @@ async function load(options) {
84
83
  };
85
84
  const siteMetadata = await (0, siteMetadata_1.loadSiteMetadata)({ plugins, siteDir });
86
85
  // === Side-effects part ===
87
- const genWarning = (0, utils_1.generate)(generatedFilesDir, 'DONT-EDIT-THIS-FOLDER', `This folder stores temp files that Docusaurus' client bundler accesses.
86
+ const genWarning = (0, utils_1.generate)(generatedFilesDir,
87
+ // cSpell:ignore DONT
88
+ 'DONT-EDIT-THIS-FOLDER', `This folder stores temp files that Docusaurus' client bundler accesses.
88
89
 
89
90
  DO NOT hand-modify files in this folder because they will be overwritten in the
90
91
  next build. You can clear all build artifacts (including this folder) with the
@@ -137,6 +138,7 @@ ${Object.entries(registry)
137
138
  outDir,
138
139
  baseUrl,
139
140
  i18n,
141
+ localizationDir,
140
142
  generatedFilesDir,
141
143
  routes: pluginsRouteConfigs,
142
144
  routesPaths,
@@ -35,8 +35,7 @@ async function loadPlugins(context) {
35
35
  const content = await plugin.loadContent?.();
36
36
  const rawTranslationFiles = (await plugin.getTranslationFiles?.({ content })) ?? [];
37
37
  const translationFiles = await Promise.all(rawTranslationFiles.map((translationFile) => (0, translations_1.localizePluginTranslationFile)({
38
- locale: context.i18n.currentLocale,
39
- siteDir: context.siteDir,
38
+ localizationDir: context.localizationDir,
40
39
  translationFile,
41
40
  plugin,
42
41
  })));
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.createMDXFallbackPlugin = exports.createBootstrapPlugin = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const path_1 = tslib_1.__importDefault(require("path"));
12
- const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
13
12
  /**
14
13
  * Make a synthetic plugin to:
15
14
  * - Inject site client modules
@@ -81,13 +80,13 @@ function createMDXFallbackPlugin({ siteDir, siteConfig, }) {
81
80
  });
82
81
  }
83
82
  const mdxLoaderOptions = {
83
+ admonitions: true,
84
84
  staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
85
85
  siteDir,
86
86
  // External MDX files are always meant to be imported as partials
87
87
  isMDXPartial: () => true,
88
88
  // External MDX files might have front matter, just disable the warning
89
89
  isMDXPartialFrontMatterWarningDisabled: true,
90
- remarkPlugins: [remark_admonitions_1.default],
91
90
  };
92
91
  return {
93
92
  module: {
@@ -10,6 +10,7 @@ exports.loadRoutes = exports.handleDuplicateRoutes = exports.genChunkName = void
10
10
  const tslib_1 = require("tslib");
11
11
  const querystring_1 = tslib_1.__importDefault(require("querystring"));
12
12
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
13
+ const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
14
  const utils_1 = require("@docusaurus/utils");
14
15
  const utils_2 = require("./utils");
15
16
  /** Indents every line of `str` by one level. */
@@ -133,12 +134,8 @@ function handleDuplicateRoutes(pluginsRouteConfigs, onDuplicateRoutes) {
133
134
  return false;
134
135
  });
135
136
  if (duplicatePaths.length > 0) {
136
- const finalMessage = `Duplicate routes found!
137
- ${duplicatePaths
138
- .map((duplicateRoute) => `- Attempting to create page at ${duplicateRoute}, but a page already exists at this route.`)
139
- .join('\n')}
137
+ logger_1.default.report(onDuplicateRoutes) `Duplicate routes found!${duplicatePaths.map((duplicateRoute) => logger_1.default.interpolate `Attempting to create page at url=${duplicateRoute}, but a page already exists at this route.`)}
140
138
  This could lead to non-deterministic routing behavior.`;
141
- (0, utils_1.reportMessage)(finalMessage, onDuplicateRoutes);
142
139
  }
143
140
  }
144
141
  exports.handleDuplicateRoutes = handleDuplicateRoutes;
@@ -10,18 +10,16 @@ export declare type WriteTranslationsOptions = {
10
10
  messagePrefix?: string;
11
11
  };
12
12
  declare type TranslationContext = {
13
- siteDir: string;
14
- locale: string;
13
+ localizationDir: string;
15
14
  };
16
- export declare function getTranslationsLocaleDirPath(context: TranslationContext): string;
17
15
  export declare function readCodeTranslationFileContent(context: TranslationContext): Promise<TranslationFileContent | undefined>;
18
16
  export declare function writeCodeTranslations(context: TranslationContext, content: TranslationFileContent, options: WriteTranslationsOptions): Promise<void>;
19
- export declare function writePluginTranslations({ siteDir, plugin, locale, translationFile, options, }: TranslationContext & {
17
+ export declare function writePluginTranslations({ localizationDir, plugin, translationFile, options, }: TranslationContext & {
20
18
  plugin: InitializedPlugin;
21
19
  translationFile: TranslationFile;
22
20
  options?: WriteTranslationsOptions;
23
21
  }): Promise<void>;
24
- export declare function localizePluginTranslationFile({ siteDir, plugin, locale, translationFile, }: TranslationContext & {
22
+ export declare function localizePluginTranslationFile({ localizationDir, plugin, translationFile, }: TranslationContext & {
25
23
  plugin: InitializedPlugin;
26
24
  translationFile: TranslationFile;
27
25
  }): Promise<TranslationFile>;
@@ -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.applyDefaultCodeTranslations = exports.getPluginsDefaultCodeTranslationMessages = exports.localizePluginTranslationFile = exports.writePluginTranslations = exports.writeCodeTranslations = exports.readCodeTranslationFileContent = exports.getTranslationsLocaleDirPath = void 0;
9
+ exports.applyDefaultCodeTranslations = exports.getPluginsDefaultCodeTranslationMessages = exports.localizePluginTranslationFile = exports.writePluginTranslations = exports.writeCodeTranslations = exports.readCodeTranslationFileContent = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const path_1 = tslib_1.__importDefault(require("path"));
12
12
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
@@ -79,13 +79,8 @@ Maybe you should remove them? ${unknownKeys}`;
79
79
  await fs_extra_1.default.outputFile(filePath, `${JSON.stringify(mergedContent, null, 2)}\n`);
80
80
  }
81
81
  }
82
- // Should we make this configurable?
83
- function getTranslationsLocaleDirPath(context) {
84
- return path_1.default.join(context.siteDir, utils_1.I18N_DIR_NAME, context.locale);
85
- }
86
- exports.getTranslationsLocaleDirPath = getTranslationsLocaleDirPath;
87
82
  function getCodeTranslationsFilePath(context) {
88
- return path_1.default.join(getTranslationsLocaleDirPath(context), utils_1.CODE_TRANSLATIONS_FILE_NAME);
83
+ return path_1.default.join(context.localizationDir, utils_1.CODE_TRANSLATIONS_FILE_NAME);
89
84
  }
90
85
  async function readCodeTranslationFileContent(context) {
91
86
  return readTranslationFileContent(getCodeTranslationsFilePath(context));
@@ -108,21 +103,19 @@ function addTranslationFileExtension(translationFilePath) {
108
103
  }
109
104
  return `${translationFilePath}.json`;
110
105
  }
111
- function getPluginTranslationFilePath({ siteDir, plugin, locale, translationFilePath, }) {
106
+ function getPluginTranslationFilePath({ localizationDir, plugin, translationFilePath, }) {
112
107
  const dirPath = (0, utils_1.getPluginI18nPath)({
113
- siteDir,
114
- locale,
108
+ localizationDir,
115
109
  pluginName: plugin.name,
116
110
  pluginId: plugin.options.id,
117
111
  });
118
112
  const filePath = addTranslationFileExtension(translationFilePath);
119
113
  return path_1.default.join(dirPath, filePath);
120
114
  }
121
- async function writePluginTranslations({ siteDir, plugin, locale, translationFile, options, }) {
115
+ async function writePluginTranslations({ localizationDir, plugin, translationFile, options, }) {
122
116
  const filePath = getPluginTranslationFilePath({
123
117
  plugin,
124
- siteDir,
125
- locale,
118
+ localizationDir,
126
119
  translationFilePath: translationFile.path,
127
120
  });
128
121
  await writeTranslationFileContent({
@@ -132,11 +125,10 @@ async function writePluginTranslations({ siteDir, plugin, locale, translationFil
132
125
  });
133
126
  }
134
127
  exports.writePluginTranslations = writePluginTranslations;
135
- async function localizePluginTranslationFile({ siteDir, plugin, locale, translationFile, }) {
128
+ async function localizePluginTranslationFile({ localizationDir, plugin, translationFile, }) {
136
129
  const filePath = getPluginTranslationFilePath({
137
130
  plugin,
138
- siteDir,
139
- locale,
131
+ localizationDir,
140
132
  translationFilePath: translationFile.path,
141
133
  });
142
134
  const localizedContent = await readTranslationFileContent(filePath);
@@ -65,6 +65,11 @@ async function createServerConfig({ props, onLinksCollected, onHeadTagsCollected
65
65
  // has any importance for this plugin, just using an empty string to
66
66
  // avoid the error. See https://github.com/facebook/docusaurus/issues/4922
67
67
  globals: { __filename: '' },
68
+ // Secret way to set SSR plugin concurrency option
69
+ // Waiting for feedback before documenting this officially?
70
+ concurrency: process.env.DOCUSAURUS_SSR_CONCURRENCY
71
+ ? parseInt(process.env.DOCUSAURUS_SSR_CONCURRENCY, 10)
72
+ : undefined,
68
73
  }),
69
74
  // Show compilation progress bar.
70
75
  new LogPlugin_1.default({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@docusaurus/core",
3
3
  "description": "Easy to Maintain Open Source Documentation Websites",
4
- "version": "2.0.0-beta.21",
4
+ "version": "2.0.0-beta.22",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -33,24 +33,24 @@
33
33
  "url": "https://github.com/facebook/docusaurus/issues"
34
34
  },
35
35
  "dependencies": {
36
- "@babel/core": "^7.18.2",
37
- "@babel/generator": "^7.18.2",
36
+ "@babel/core": "^7.18.6",
37
+ "@babel/generator": "^7.18.7",
38
38
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
39
- "@babel/plugin-transform-runtime": "^7.18.2",
40
- "@babel/preset-env": "^7.18.2",
41
- "@babel/preset-react": "^7.17.12",
42
- "@babel/preset-typescript": "^7.17.12",
43
- "@babel/runtime": "^7.18.3",
44
- "@babel/runtime-corejs3": "^7.18.3",
45
- "@babel/traverse": "^7.18.2",
46
- "@docusaurus/cssnano-preset": "2.0.0-beta.21",
47
- "@docusaurus/logger": "2.0.0-beta.21",
48
- "@docusaurus/mdx-loader": "2.0.0-beta.21",
39
+ "@babel/plugin-transform-runtime": "^7.18.6",
40
+ "@babel/preset-env": "^7.18.6",
41
+ "@babel/preset-react": "^7.18.6",
42
+ "@babel/preset-typescript": "^7.18.6",
43
+ "@babel/runtime": "^7.18.6",
44
+ "@babel/runtime-corejs3": "^7.18.6",
45
+ "@babel/traverse": "^7.18.6",
46
+ "@docusaurus/cssnano-preset": "2.0.0-beta.22",
47
+ "@docusaurus/logger": "2.0.0-beta.22",
48
+ "@docusaurus/mdx-loader": "2.0.0-beta.22",
49
49
  "@docusaurus/react-loadable": "5.5.2",
50
- "@docusaurus/utils": "2.0.0-beta.21",
51
- "@docusaurus/utils-common": "2.0.0-beta.21",
52
- "@docusaurus/utils-validation": "2.0.0-beta.21",
53
- "@slorber/static-site-generator-webpack-plugin": "^4.0.4",
50
+ "@docusaurus/utils": "2.0.0-beta.22",
51
+ "@docusaurus/utils-common": "2.0.0-beta.22",
52
+ "@docusaurus/utils-validation": "2.0.0-beta.22",
53
+ "@slorber/static-site-generator-webpack-plugin": "^4.0.7",
54
54
  "@svgr/webpack": "^6.2.1",
55
55
  "autoprefixer": "^10.4.7",
56
56
  "babel-loader": "^8.2.5",
@@ -63,10 +63,10 @@
63
63
  "combine-promises": "^1.1.0",
64
64
  "commander": "^5.1.0",
65
65
  "copy-webpack-plugin": "^11.0.0",
66
- "core-js": "^3.22.7",
66
+ "core-js": "^3.23.3",
67
67
  "css-loader": "^6.7.1",
68
68
  "css-minimizer-webpack-plugin": "^4.0.0",
69
- "cssnano": "^5.1.9",
69
+ "cssnano": "^5.1.12",
70
70
  "del": "^6.1.1",
71
71
  "detect-port": "^1.3.0",
72
72
  "escape-html": "^1.0.3",
@@ -79,7 +79,7 @@
79
79
  "import-fresh": "^3.3.0",
80
80
  "leven": "^3.1.0",
81
81
  "lodash": "^4.17.21",
82
- "mini-css-extract-plugin": "^2.6.0",
82
+ "mini-css-extract-plugin": "^2.6.1",
83
83
  "postcss": "^8.4.14",
84
84
  "postcss-loader": "^7.0.0",
85
85
  "prompts": "^2.4.2",
@@ -90,25 +90,24 @@
90
90
  "react-router": "^5.3.3",
91
91
  "react-router-config": "^5.1.1",
92
92
  "react-router-dom": "^5.3.3",
93
- "remark-admonitions": "^1.2.1",
94
93
  "rtl-detect": "^1.0.4",
95
94
  "semver": "^7.3.7",
96
95
  "serve-handler": "^6.1.3",
97
96
  "shelljs": "^0.8.5",
98
- "terser-webpack-plugin": "^5.3.1",
97
+ "terser-webpack-plugin": "^5.3.3",
99
98
  "tslib": "^2.4.0",
100
99
  "update-notifier": "^5.1.0",
101
100
  "url-loader": "^4.1.1",
102
101
  "wait-on": "^6.0.1",
103
- "webpack": "^5.72.1",
102
+ "webpack": "^5.73.0",
104
103
  "webpack-bundle-analyzer": "^4.5.0",
105
- "webpack-dev-server": "^4.9.0",
104
+ "webpack-dev-server": "^4.9.3",
106
105
  "webpack-merge": "^5.8.0",
107
106
  "webpackbar": "^5.0.2"
108
107
  },
109
108
  "devDependencies": {
110
- "@docusaurus/module-type-aliases": "2.0.0-beta.21",
111
- "@docusaurus/types": "2.0.0-beta.21",
109
+ "@docusaurus/module-type-aliases": "2.0.0-beta.22",
110
+ "@docusaurus/types": "2.0.0-beta.22",
112
111
  "@types/detect-port": "^1.3.2",
113
112
  "@types/react-dom": "^18.0.5",
114
113
  "@types/react-router-config": "^5.0.6",
@@ -128,5 +127,5 @@
128
127
  "engines": {
129
128
  "node": ">=16.14"
130
129
  },
131
- "gitHead": "69ac49fc6909517f13615ee40290c4bd00c39df4"
130
+ "gitHead": "daf9e462c4eebb7ac26a940932311f987e768f87"
132
131
  }
@@ -1,27 +0,0 @@
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
-
8
- module.exports = {
9
- rules: {
10
- 'no-restricted-imports': [
11
- 'error',
12
- {
13
- patterns: [
14
- // Prevent importing lodash in client bundle for bundle size
15
- 'lodash',
16
- 'lodash.**',
17
- 'lodash/**',
18
- // Prevent importing server code in client bundle
19
- '**/../babel/**',
20
- '**/../server/**',
21
- '**/../commands/**',
22
- '**/../webpack/**',
23
- ],
24
- },
25
- ],
26
- },
27
- };