@docusaurus/core 2.0.0-beta.12faed89d → 2.0.0-beta.14

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 (111) hide show
  1. package/bin/beforeCli.js +46 -22
  2. package/bin/docusaurus.js +42 -44
  3. package/lib/babel/preset.d.ts +6 -0
  4. package/lib/babel/preset.js +3 -3
  5. package/lib/choosePort.js +19 -20
  6. package/lib/client/.eslintrc.js +0 -1
  7. package/lib/client/App.js +12 -22
  8. package/lib/client/LinksCollector.d.ts +2 -2
  9. package/lib/client/LinksCollector.js +4 -8
  10. package/lib/client/PendingNavigation.d.ts +24 -1
  11. package/lib/client/PendingNavigation.js +1 -1
  12. package/lib/client/baseUrlIssueBanner/BaseUrlIssueBanner.d.ts +5 -0
  13. package/lib/client/client-lifecycles-dispatcher.d.ts +2 -2
  14. package/lib/client/client-lifecycles-dispatcher.js +0 -2
  15. package/lib/client/docusaurus.d.ts +6 -0
  16. package/lib/client/docusaurus.js +11 -19
  17. package/lib/client/exports/BrowserOnly.js +5 -3
  18. package/lib/client/exports/ErrorBoundary.d.ts +18 -0
  19. package/lib/client/exports/ErrorBoundary.js +35 -0
  20. package/lib/client/exports/Interpolate.js +12 -15
  21. package/lib/client/exports/Link.js +9 -9
  22. package/lib/client/exports/Translate.d.ts +2 -2
  23. package/lib/client/exports/Translate.js +13 -9
  24. package/lib/client/exports/browserContext.d.ts +11 -0
  25. package/lib/client/exports/browserContext.js +21 -0
  26. package/lib/client/exports/constants.js +1 -11
  27. package/lib/client/exports/{context.d.ts → docusaurusContext.d.ts} +5 -3
  28. package/lib/client/exports/docusaurusContext.js +25 -0
  29. package/lib/client/exports/useBaseUrl.js +2 -4
  30. package/lib/client/exports/useDocusaurusContext.js +2 -7
  31. package/lib/client/exports/useGlobalData.js +1 -5
  32. package/lib/client/exports/{context.js → useIsBrowser.d.ts} +1 -2
  33. package/lib/{webpack/sharedModuleAliases.d.ts → client/exports/useIsBrowser.js} +5 -4
  34. package/lib/client/flat.d.ts +2 -1
  35. package/lib/client/flat.js +7 -9
  36. package/lib/client/normalizeLocation.d.ts +1 -3
  37. package/lib/client/prefetch.js +0 -1
  38. package/lib/client/serverEntry.js +20 -42
  39. package/lib/client/theme-fallback/Error/index.js +47 -0
  40. package/lib/client/theme-fallback/Layout/index.js +1 -1
  41. package/lib/client/theme-fallback/Loading/index.js +2 -2
  42. package/lib/client/theme-fallback/Root/index.js +1 -3
  43. package/lib/commands/build.js +39 -44
  44. package/lib/commands/clear.d.ts +6 -0
  45. package/lib/commands/clear.js +17 -18
  46. package/lib/commands/commandUtils.d.ts +6 -0
  47. package/lib/commands/commandUtils.js +7 -7
  48. package/lib/commands/deploy.d.ts +3 -0
  49. package/lib/commands/deploy.js +99 -64
  50. package/lib/commands/external.js +4 -4
  51. package/lib/commands/serve.js +12 -18
  52. package/lib/commands/start.js +98 -86
  53. package/lib/commands/swizzle.js +42 -51
  54. package/lib/commands/writeHeadingIds.d.ts +9 -6
  55. package/lib/commands/writeHeadingIds.js +33 -34
  56. package/lib/commands/writeTranslations.js +31 -11
  57. package/lib/server/brokenLinks.js +13 -17
  58. package/lib/server/client-modules/index.js +1 -3
  59. package/lib/server/config.js +4 -4
  60. package/lib/server/configValidation.d.ts +1 -1
  61. package/lib/server/configValidation.js +14 -7
  62. package/lib/server/duplicateRoutes.js +8 -2
  63. package/lib/server/html-tags/htmlTags.js +5 -6
  64. package/lib/server/html-tags/index.js +2 -2
  65. package/lib/server/i18n.js +16 -16
  66. package/lib/server/index.js +132 -59
  67. package/lib/server/loadSetup.js +3 -3
  68. package/lib/server/moduleShorthand.d.ts +9 -0
  69. package/lib/server/moduleShorthand.js +42 -0
  70. package/lib/server/plugins/applyRouteTrailingSlash.js +1 -1
  71. package/lib/server/plugins/index.d.ts +1 -1
  72. package/lib/server/plugins/index.js +25 -21
  73. package/lib/server/plugins/init.js +9 -12
  74. package/lib/server/plugins/pluginIds.js +6 -4
  75. package/lib/server/presets/index.js +12 -12
  76. package/lib/server/routes.js +9 -11
  77. package/lib/server/themes/alias.d.ts +1 -0
  78. package/lib/server/themes/alias.js +21 -12
  79. package/lib/server/themes/index.d.ts +1 -1
  80. package/lib/server/themes/index.js +22 -23
  81. package/lib/server/translations/translations.d.ts +6 -0
  82. package/lib/server/translations/translations.js +19 -26
  83. package/lib/server/translations/translationsExtractor.d.ts +7 -1
  84. package/lib/server/translations/translationsExtractor.js +66 -59
  85. package/lib/server/utils.d.ts +8 -2
  86. package/lib/server/utils.js +8 -10
  87. package/lib/server/versions/__fixtures__/dummy-plugin.d.ts +0 -0
  88. package/lib/server/versions/__tests/index.test.js +5 -5
  89. package/lib/server/versions/index.js +6 -6
  90. package/lib/webpack/base.js +14 -16
  91. package/lib/webpack/client.js +9 -18
  92. package/lib/webpack/plugins/CleanWebpackPlugin.js +4 -11
  93. package/lib/webpack/plugins/LogPlugin.js +5 -6
  94. package/lib/webpack/plugins/WaitPlugin.js +4 -4
  95. package/lib/webpack/server.js +9 -9
  96. package/lib/webpack/utils.d.ts +0 -22
  97. package/lib/webpack/utils.js +37 -134
  98. package/package.json +55 -50
  99. package/lib/.tsbuildinfo +0 -1
  100. package/lib/client/.tsbuildinfo +0 -1
  101. package/lib/commands/buildRemoteBranchUrl.d.ts +0 -7
  102. package/lib/commands/buildRemoteBranchUrl.js +0 -27
  103. package/lib/constants.d.ts +0 -18
  104. package/lib/constants.js +0 -23
  105. package/lib/webpack/react-dev-utils-webpack5/README.md +0 -11
  106. package/lib/webpack/react-dev-utils-webpack5/evalSourceMapMiddleware.js +0 -57
  107. package/lib/webpack/react-dev-utils-webpack5/formatWebpackMessages.js +0 -138
  108. package/lib/webpack/react-dev-utils-webpack5/webpackHotDevClient.js +0 -285
  109. package/lib/webpack/sharedModuleAliases.js +0 -18
  110. package/tsconfig.client.json +0 -13
  111. package/tsconfig.json +0 -13
@@ -23,7 +23,7 @@ const createRouteCodeString = ({ routePath, routeHash, exact, subroutesCodeStrin
23
23
  }
24
24
  if (subroutesCodeStrings) {
25
25
  parts.push(`routes: [
26
- ${indent(utils_1.removeSuffix(subroutesCodeStrings.join(',\n'), ',\n'))}
26
+ ${indent((0, utils_1.removeSuffix)(subroutesCodeStrings.join(',\n'), ',\n'))}
27
27
  ]`);
28
28
  }
29
29
  Object.entries(props).forEach(([propName, propValue]) => {
@@ -46,10 +46,10 @@ const RoutesImportsCode = [
46
46
  `import ComponentCreator from '@docusaurus/ComponentCreator';`,
47
47
  ].join('\n');
48
48
  function isModule(value) {
49
- if (lodash_1.isString(value)) {
49
+ if ((0, lodash_1.isString)(value)) {
50
50
  return true;
51
51
  }
52
- if (lodash_1.isPlainObject(value) && lodash_1.has(value, '__import') && lodash_1.has(value, 'path')) {
52
+ if ((0, lodash_1.isPlainObject)(value) && (0, lodash_1.has)(value, '__import') && (0, lodash_1.has)(value, 'path')) {
53
53
  return true;
54
54
  }
55
55
  return false;
@@ -58,19 +58,17 @@ function getModulePath(target) {
58
58
  if (typeof target === 'string') {
59
59
  return target;
60
60
  }
61
- const queryStr = target.query ? `?${querystring_1.stringify(target.query)}` : '';
61
+ const queryStr = target.query ? `?${(0, querystring_1.stringify)(target.query)}` : '';
62
62
  return `${target.path}${queryStr}`;
63
63
  }
64
64
  async function loadRoutes(pluginsRouteConfigs, baseUrl) {
65
65
  const registry = {};
66
- const routesPaths = [utils_1.normalizeUrl([baseUrl, '404.html'])];
66
+ const routesPaths = [(0, utils_1.normalizeUrl)([baseUrl, '404.html'])];
67
67
  const routesChunkNames = {};
68
68
  // This is the higher level overview of route code generation.
69
69
  function generateRouteCode(routeConfig) {
70
- const { path: routePath, component, modules = {}, routes: subroutes, exact,
71
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
72
- priority, ...props } = routeConfig;
73
- if (!lodash_1.isString(routePath) || !component) {
70
+ const { path: routePath, component, modules = {}, routes: subroutes, exact, priority, ...props } = routeConfig;
71
+ if (!(0, lodash_1.isString)(routePath) || !component) {
74
72
  throw new Error(`Invalid route config: path must be a string and component is required.\n${JSON.stringify(routeConfig)}`);
75
73
  }
76
74
  // Collect all page paths for injecting it later in the plugin lifecycle
@@ -82,7 +80,7 @@ async function loadRoutes(pluginsRouteConfigs, baseUrl) {
82
80
  // We hash the route to generate the key, because 2 routes can conflict with
83
81
  // each others if they have the same path, ex: parent=/docs, child=/docs
84
82
  // see https://github.com/facebook/docusaurus/issues/2917
85
- const routeHash = utils_1.simpleHash(JSON.stringify(routeConfig), 3);
83
+ const routeHash = (0, utils_1.simpleHash)(JSON.stringify(routeConfig), 3);
86
84
  const chunkNamesKey = `${routePath}-${routeHash}`;
87
85
  routesChunkNames[chunkNamesKey] = {
88
86
  ...genRouteChunkNames(registry, { component }, 'component', component),
@@ -123,7 +121,7 @@ registry, value, prefix, name) {
123
121
  }
124
122
  if (isModule(value)) {
125
123
  const modulePath = getModulePath(value);
126
- const chunkName = utils_1.genChunkName(modulePath, prefix, name);
124
+ const chunkName = (0, utils_1.genChunkName)(modulePath, prefix, name);
127
125
  // We need to JSON.stringify so that if its on windows, backslashes are escaped.
128
126
  const loader = `() => import(/* webpackChunkName: '${chunkName}' */ ${JSON.stringify(modulePath)})`;
129
127
  registry[chunkName] = {
@@ -5,4 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { ThemeAliases } from '@docusaurus/types';
8
+ export declare function sortAliases(aliases: ThemeAliases): ThemeAliases;
8
9
  export default function themeAlias(themePath: string, addOriginalAlias: boolean): ThemeAliases;
@@ -6,35 +6,44 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.sortAliases = void 0;
9
10
  const tslib_1 = require("tslib");
10
- const globby_1 = tslib_1.__importDefault(require("globby"));
11
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
12
- const path_1 = tslib_1.__importDefault(require("path"));
11
+ const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
13
13
  const utils_1 = require("@docusaurus/utils");
14
14
  const lodash_1 = require("lodash");
15
+ // Order of Webpack aliases is important because one alias can shadow another
16
+ // This ensure @theme/NavbarItem alias is after @theme/NavbarItem/LocaleDropdown
17
+ // See https://github.com/facebook/docusaurus/pull/3922
18
+ // See https://github.com/facebook/docusaurus/issues/5382
19
+ function sortAliases(aliases) {
20
+ // Alphabetical order by default
21
+ const entries = (0, lodash_1.sortBy)(Object.entries(aliases), ([alias]) => alias);
22
+ // @theme/NavbarItem should be after @theme/NavbarItem/LocaleDropdown
23
+ entries.sort(([alias1], [alias2]) => alias1.includes(`${alias2}/`) ? -1 : 0);
24
+ return Object.fromEntries(entries);
25
+ }
26
+ exports.sortAliases = sortAliases;
15
27
  // TODO make async
16
28
  function themeAlias(themePath, addOriginalAlias) {
17
29
  if (!fs_extra_1.default.pathExistsSync(themePath)) {
18
30
  return {};
19
31
  }
20
- const themeComponentFiles = globby_1.default.sync(['**/*.{js,jsx,ts,tsx}'], {
32
+ const themeComponentFiles = utils_1.Globby.sync(['**/*.{js,jsx,ts,tsx}'], {
21
33
  cwd: themePath,
22
34
  });
23
- // See https://github.com/facebook/docusaurus/pull/3922
24
- // ensure @theme/NavbarItem alias is created after @theme/NavbarItem/LocaleDropdown
25
- const sortedThemeComponentFiles = lodash_1.sortBy(themeComponentFiles, (file) => file.endsWith('/index.js'));
26
35
  const aliases = {};
27
- sortedThemeComponentFiles.forEach((relativeSource) => {
36
+ themeComponentFiles.forEach((relativeSource) => {
28
37
  const filePath = path_1.default.join(themePath, relativeSource);
29
- const fileName = utils_1.fileToPath(relativeSource);
30
- const aliasName = utils_1.posixPath(utils_1.normalizeUrl(['@theme', fileName]).replace(/\/$/, ''));
38
+ const fileName = (0, utils_1.fileToPath)(relativeSource);
39
+ const aliasName = (0, utils_1.posixPath)((0, utils_1.normalizeUrl)(['@theme', fileName]).replace(/\/$/, ''));
31
40
  aliases[aliasName] = filePath;
32
41
  if (addOriginalAlias) {
33
42
  // For swizzled components to access the original.
34
- const originalAliasName = utils_1.posixPath(utils_1.normalizeUrl(['@theme-original', fileName]).replace(/\/$/, ''));
43
+ const originalAliasName = (0, utils_1.posixPath)((0, utils_1.normalizeUrl)(['@theme-original', fileName]).replace(/\/$/, ''));
35
44
  aliases[originalAliasName] = filePath;
36
45
  }
37
46
  });
38
- return aliases;
47
+ return sortAliases(aliases);
39
48
  }
40
49
  exports.default = themeAlias;
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { ThemeAliases, LoadedPlugin } from '@docusaurus/types';
8
- export declare function loadThemeAliases(themePaths: string[], userThemePaths?: string[]): ThemeAliases;
8
+ export declare function loadThemeAliases(themePaths: string[], userThemePaths: string[]): ThemeAliases;
9
9
  export declare function loadPluginsThemeAliases({ siteDir, plugins, }: {
10
10
  siteDir: string;
11
11
  plugins: LoadedPlugin[];
@@ -8,40 +8,39 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.loadPluginsThemeAliases = exports.loadThemeAliases = void 0;
10
10
  const tslib_1 = require("tslib");
11
- const path_1 = tslib_1.__importDefault(require("path"));
12
- const constants_1 = require("../../constants");
13
- const alias_1 = tslib_1.__importDefault(require("./alias"));
11
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
12
+ const utils_1 = require("@docusaurus/utils");
13
+ const alias_1 = (0, tslib_1.__importStar)(require("./alias"));
14
14
  const ThemeFallbackDir = path_1.default.resolve(__dirname, '../../client/theme-fallback');
15
- function buildThemeAliases(themeAliases, aliases = {}) {
16
- Object.keys(themeAliases).forEach((aliasKey) => {
17
- if (aliasKey in aliases) {
18
- const componentName = aliasKey.substring(aliasKey.indexOf('/') + 1);
19
- // eslint-disable-next-line no-param-reassign
20
- aliases[`@theme-init/${componentName}`] = aliases[aliasKey];
21
- }
22
- // eslint-disable-next-line no-param-reassign
23
- aliases[aliasKey] = themeAliases[aliasKey];
24
- });
25
- return aliases;
26
- }
27
- function loadThemeAliases(themePaths, userThemePaths = []) {
28
- let aliases = {}; // TODO refactor, inelegant side-effect
15
+ function loadThemeAliases(themePaths, userThemePaths) {
16
+ const aliases = {};
29
17
  themePaths.forEach((themePath) => {
30
- const themeAliases = alias_1.default(themePath, true);
31
- aliases = { ...aliases, ...buildThemeAliases(themeAliases, aliases) };
18
+ const themeAliases = (0, alias_1.default)(themePath, true);
19
+ Object.keys(themeAliases).forEach((aliasKey) => {
20
+ // If this alias shadows a previous one, use @theme-init to preserve the initial one.
21
+ // @theme-init is only applied once: to the initial theme that provided this component
22
+ if (aliasKey in aliases) {
23
+ const componentName = aliasKey.substring(aliasKey.indexOf('/') + 1);
24
+ const initAlias = `@theme-init/${componentName}`;
25
+ if (!(initAlias in aliases)) {
26
+ aliases[initAlias] = aliases[aliasKey];
27
+ }
28
+ }
29
+ aliases[aliasKey] = themeAliases[aliasKey];
30
+ });
32
31
  });
33
32
  userThemePaths.forEach((themePath) => {
34
- const userThemeAliases = alias_1.default(themePath, false);
35
- aliases = { ...aliases, ...buildThemeAliases(userThemeAliases, aliases) };
33
+ const userThemeAliases = (0, alias_1.default)(themePath, false);
34
+ Object.assign(aliases, userThemeAliases);
36
35
  });
37
- return aliases;
36
+ return (0, alias_1.sortAliases)(aliases);
38
37
  }
39
38
  exports.loadThemeAliases = loadThemeAliases;
40
39
  function loadPluginsThemeAliases({ siteDir, plugins, }) {
41
40
  const pluginThemes = plugins
42
41
  .map((plugin) => (plugin.getThemePath ? plugin.getThemePath() : undefined))
43
42
  .filter((x) => Boolean(x));
44
- const userTheme = path_1.default.resolve(siteDir, constants_1.THEME_PATH);
43
+ const userTheme = path_1.default.resolve(siteDir, utils_1.THEME_PATH);
45
44
  return loadThemeAliases([ThemeFallbackDir, ...pluginThemes], [userTheme]);
46
45
  }
47
46
  exports.loadPluginsThemeAliases = loadPluginsThemeAliases;
@@ -1,3 +1,9 @@
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
+ */
1
7
  import { TranslationFileContent, TranslationFile, TranslationMessage, InitializedPlugin } from '@docusaurus/types';
2
8
  export declare type WriteTranslationsOptions = {
3
9
  override?: boolean;
@@ -1,19 +1,19 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.applyDefaultCodeTranslations = exports.getPluginsDefaultCodeTranslationMessages = exports.localizePluginTranslationFile = exports.writePluginTranslations = exports.writeCodeTranslations = exports.readCodeTranslationFileContent = exports.getCodeTranslationsFilePath = exports.getTranslationsLocaleDirPath = exports.getTranslationsDirPath = exports.writeTranslationFileContent = exports.readTranslationFileContent = exports.ensureTranslationFileContent = void 0;
4
- const tslib_1 = require("tslib");
5
2
  /**
6
3
  * Copyright (c) Facebook, Inc. and its affiliates.
7
4
  *
8
5
  * This source code is licensed under the MIT license found in the
9
6
  * LICENSE file in the root directory of this source tree.
10
7
  */
11
- const path_1 = tslib_1.__importDefault(require("path"));
12
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.applyDefaultCodeTranslations = exports.getPluginsDefaultCodeTranslationMessages = exports.localizePluginTranslationFile = exports.writePluginTranslations = exports.writeCodeTranslations = exports.readCodeTranslationFileContent = exports.getCodeTranslationsFilePath = exports.getTranslationsLocaleDirPath = exports.getTranslationsDirPath = exports.writeTranslationFileContent = exports.readTranslationFileContent = exports.ensureTranslationFileContent = void 0;
10
+ const tslib_1 = require("tslib");
11
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
12
+ const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
13
13
  const lodash_1 = require("lodash");
14
14
  const utils_1 = require("@docusaurus/utils");
15
15
  const utils_validation_1 = require("@docusaurus/utils-validation");
16
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
16
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
17
17
  const TranslationFileContentSchema = utils_validation_1.Joi.object()
18
18
  .pattern(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
19
19
  message: utils_validation_1.Joi.string().allow('').required(),
@@ -44,7 +44,7 @@ async function readTranslationFileContent(filePath) {
44
44
  exports.readTranslationFileContent = readTranslationFileContent;
45
45
  function mergeTranslationFileContent({ existingContent = {}, newContent, options, }) {
46
46
  // Apply messagePrefix to all messages
47
- const newContentTransformed = lodash_1.mapValues(newContent, (value) => {
47
+ const newContentTransformed = (0, lodash_1.mapValues)(newContent, (value) => {
48
48
  var _a;
49
49
  return ({
50
50
  ...value,
@@ -68,11 +68,10 @@ function mergeTranslationFileContent({ existingContent = {}, newContent, options
68
68
  async function writeTranslationFileContent({ filePath, content: newContent, options = {}, }) {
69
69
  const existingContent = await readTranslationFileContent(filePath);
70
70
  // Warn about potential legacy keys
71
- const unknownKeys = lodash_1.difference(Object.keys(existingContent !== null && existingContent !== void 0 ? existingContent : {}), Object.keys(newContent));
71
+ const unknownKeys = (0, lodash_1.difference)(Object.keys(existingContent !== null && existingContent !== void 0 ? existingContent : {}), Object.keys(newContent));
72
72
  if (unknownKeys.length > 0) {
73
- console.warn(chalk_1.default.yellow(`Some translation keys looks unknown to us in file ${filePath}
74
- Maybe you should remove them?
75
- - ${unknownKeys.join('\n- ')}`));
73
+ logger_1.default.warn `Some translation keys looks unknown to us in file path=${filePath}.
74
+ Maybe you should remove them? ${unknownKeys}`;
76
75
  }
77
76
  const mergedContent = mergeTranslationFileContent({
78
77
  existingContent,
@@ -81,9 +80,7 @@ Maybe you should remove them?
81
80
  });
82
81
  // Avoid creating empty translation files
83
82
  if (Object.keys(mergedContent).length > 0) {
84
- console.log(`${Object.keys(mergedContent)
85
- .length.toString()
86
- .padStart(3, ' ')} translations will be written at "${utils_1.toMessageRelativeFilePath(filePath)}".`);
83
+ logger_1.default.info `number=${Object.keys(mergedContent).length} translations will be written at path=${(0, utils_1.toMessageRelativeFilePath)(filePath)}.`;
87
84
  await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
88
85
  await fs_extra_1.default.writeFile(filePath, JSON.stringify(mergedContent, null, 2));
89
86
  }
@@ -124,7 +121,7 @@ function addTranslationFileExtension(translationFilePath) {
124
121
  return `${translationFilePath}.json`;
125
122
  }
126
123
  function getPluginTranslationFilePath({ siteDir, plugin, locale, translationFilePath, }) {
127
- const dirPath = utils_1.getPluginI18nPath({
124
+ const dirPath = (0, utils_1.getPluginI18nPath)({
128
125
  siteDir,
129
126
  locale,
130
127
  pluginName: plugin.name,
@@ -172,25 +169,21 @@ async function localizePluginTranslationFile({ siteDir, plugin, locale, translat
172
169
  exports.localizePluginTranslationFile = localizePluginTranslationFile;
173
170
  async function getPluginsDefaultCodeTranslationMessages(plugins) {
174
171
  const pluginsMessages = await Promise.all(plugins.map((plugin) => { var _a, _b; return (_b = (_a = plugin.getDefaultCodeTranslationMessages) === null || _a === void 0 ? void 0 : _a.call(plugin)) !== null && _b !== void 0 ? _b : {}; }));
175
- return pluginsMessages.reduce((allMessages, pluginMessages) => {
176
- return { ...allMessages, ...pluginMessages };
177
- }, {});
172
+ return pluginsMessages.reduce((allMessages, pluginMessages) => ({ ...allMessages, ...pluginMessages }), {});
178
173
  }
179
174
  exports.getPluginsDefaultCodeTranslationMessages = getPluginsDefaultCodeTranslationMessages;
180
175
  function applyDefaultCodeTranslations({ extractedCodeTranslations, defaultCodeMessages, }) {
181
- const unusedDefaultCodeMessages = lodash_1.difference(Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations));
176
+ const unusedDefaultCodeMessages = (0, lodash_1.difference)(Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations));
182
177
  if (unusedDefaultCodeMessages.length > 0) {
183
- console.warn(chalk_1.default.yellow(`Unused default message codes found.
184
- Please report this Docusaurus issue.
185
- - ${unusedDefaultCodeMessages.join('\n- ')}
186
- `));
178
+ logger_1.default.warn `Unused default message codes found.
179
+ Please report this Docusaurus issue. name=${unusedDefaultCodeMessages}`;
187
180
  }
188
- return lodash_1.mapValues(extractedCodeTranslations, (messageTranslation, messageId) => {
181
+ return (0, lodash_1.mapValues)(extractedCodeTranslations, (messageTranslation, messageId) => {
189
182
  var _a;
190
- return {
183
+ return ({
191
184
  ...messageTranslation,
192
185
  message: (_a = defaultCodeMessages[messageId]) !== null && _a !== void 0 ? _a : messageTranslation.message,
193
- };
186
+ });
194
187
  });
195
188
  }
196
189
  exports.applyDefaultCodeTranslations = applyDefaultCodeTranslations;
@@ -1,7 +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
+ */
1
7
  import { TransformOptions } from '@babel/core';
2
8
  import { InitializedPlugin, TranslationFileContent, TranslationMessage } from '@docusaurus/types';
3
9
  export declare function globSourceCodeFilePaths(dirPaths: string[]): Promise<string[]>;
4
- export declare function extractSiteSourceCodeTranslations(siteDir: string, plugins: InitializedPlugin[], babelOptions: TransformOptions): Promise<TranslationFileContent>;
10
+ export declare function extractSiteSourceCodeTranslations(siteDir: string, plugins: InitializedPlugin[], babelOptions: TransformOptions, extraSourceCodeFilePaths?: string[]): Promise<TranslationFileContent>;
5
11
  declare type SourceCodeFileTranslations = {
6
12
  sourceCodeFilePath: string;
7
13
  translations: Record<string, TranslationMessage>;
@@ -1,22 +1,21 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractSourceCodeFileTranslations = exports.extractAllSourceCodeFileTranslations = exports.extractSiteSourceCodeTranslations = exports.globSourceCodeFilePaths = void 0;
4
- const tslib_1 = require("tslib");
5
2
  /**
6
3
  * Copyright (c) Facebook, Inc. and its affiliates.
7
4
  *
8
5
  * This source code is licensed under the MIT license found in the
9
6
  * LICENSE file in the root directory of this source tree.
10
7
  */
11
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
12
- const traverse_1 = tslib_1.__importDefault(require("@babel/traverse"));
13
- const generator_1 = tslib_1.__importDefault(require("@babel/generator"));
14
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.extractSourceCodeFileTranslations = exports.extractAllSourceCodeFileTranslations = exports.extractSiteSourceCodeTranslations = exports.globSourceCodeFilePaths = void 0;
10
+ const tslib_1 = require("tslib");
11
+ const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
+ const traverse_1 = (0, tslib_1.__importDefault)(require("@babel/traverse"));
13
+ const generator_1 = (0, tslib_1.__importDefault)(require("@babel/generator"));
14
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
15
15
  const core_1 = require("@babel/core");
16
- const lodash_1 = require("lodash");
17
- const path_1 = tslib_1.__importDefault(require("path"));
18
- const constants_1 = require("../../constants");
19
- const utils_1 = require("../utils");
16
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
17
+ const utils_1 = require("@docusaurus/utils");
18
+ const utils_2 = require("../utils");
20
19
  // We only support extracting source code translations from these kind of files
21
20
  const TranslatableSourceCodeExtension = new Set([
22
21
  '.js',
@@ -32,7 +31,7 @@ function isTranslatableSourceCodePath(filePath) {
32
31
  return TranslatableSourceCodeExtension.has(path_1.default.extname(filePath));
33
32
  }
34
33
  function getSiteSourceCodeFilePaths(siteDir) {
35
- return [path_1.default.join(siteDir, constants_1.SRC_DIR_NAME)];
34
+ return [path_1.default.join(siteDir, utils_1.SRC_DIR_NAME)];
36
35
  }
37
36
  function getPluginSourceCodeFilePaths(plugin) {
38
37
  var _a, _b, _c;
@@ -48,7 +47,7 @@ function getPluginSourceCodeFilePaths(plugin) {
48
47
  return codePaths;
49
48
  }
50
49
  async function globSourceCodeFilePaths(dirPaths) {
51
- const filePaths = await utils_1.safeGlobby(dirPaths);
50
+ const filePaths = await (0, utils_2.safeGlobby)(dirPaths);
52
51
  return filePaths.filter(isTranslatableSourceCodePath);
53
52
  }
54
53
  exports.globSourceCodeFilePaths = globSourceCodeFilePaths;
@@ -57,19 +56,21 @@ async function getSourceCodeFilePaths(siteDir, plugins) {
57
56
  // The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths
58
57
  // We can use this method as well to know which folders we should try to extract translations from
59
58
  // Hacky/implicit, but do we want to introduce a new lifecycle method for that???
60
- const pluginsPaths = lodash_1.flatten(plugins.map(getPluginSourceCodeFilePaths));
59
+ const pluginsPaths = plugins.flatMap(getPluginSourceCodeFilePaths);
61
60
  const allPaths = [...sitePaths, ...pluginsPaths];
62
61
  return globSourceCodeFilePaths(allPaths);
63
62
  }
64
- async function extractSiteSourceCodeTranslations(siteDir, plugins, babelOptions) {
63
+ async function extractSiteSourceCodeTranslations(siteDir, plugins, babelOptions, extraSourceCodeFilePaths = []) {
65
64
  // Should we warn here if the same translation "key" is found in multiple source code files?
66
65
  function toTranslationFileContent(sourceCodeFileTranslations) {
67
- return sourceCodeFileTranslations.reduce((acc, item) => {
68
- return { ...acc, ...item.translations };
69
- }, {});
66
+ return sourceCodeFileTranslations.reduce((acc, item) => ({ ...acc, ...item.translations }), {});
70
67
  }
71
68
  const sourceCodeFilePaths = await getSourceCodeFilePaths(siteDir, plugins);
72
- const sourceCodeFilesTranslations = await extractAllSourceCodeFileTranslations(sourceCodeFilePaths, babelOptions);
69
+ const allSourceCodeFilePaths = [
70
+ ...sourceCodeFilePaths,
71
+ ...extraSourceCodeFilePaths,
72
+ ];
73
+ const sourceCodeFilesTranslations = await extractAllSourceCodeFileTranslations(allSourceCodeFilePaths, babelOptions);
73
74
  logSourceCodeFileTranslationsWarnings(sourceCodeFilesTranslations);
74
75
  return toTranslationFileContent(sourceCodeFilesTranslations);
75
76
  }
@@ -77,28 +78,31 @@ exports.extractSiteSourceCodeTranslations = extractSiteSourceCodeTranslations;
77
78
  function logSourceCodeFileTranslationsWarnings(sourceCodeFilesTranslations) {
78
79
  sourceCodeFilesTranslations.forEach(({ sourceCodeFilePath, warnings }) => {
79
80
  if (warnings.length > 0) {
80
- console.warn(`Translation extraction warnings for file path=${sourceCodeFilePath}:\n- ${chalk_1.default.yellow(warnings.join('\n\n- '))}`);
81
+ logger_1.default.warn `Translation extraction warnings for file path=${sourceCodeFilePath}: ${warnings}`;
81
82
  }
82
83
  });
83
84
  }
84
85
  async function extractAllSourceCodeFileTranslations(sourceCodeFilePaths, babelOptions) {
85
- return lodash_1.flatten(await Promise.all(sourceCodeFilePaths.map((sourceFilePath) => extractSourceCodeFileTranslations(sourceFilePath, babelOptions))));
86
+ return Promise.all(sourceCodeFilePaths.flatMap((sourceFilePath) => extractSourceCodeFileTranslations(sourceFilePath, babelOptions)));
86
87
  }
87
88
  exports.extractAllSourceCodeFileTranslations = extractAllSourceCodeFileTranslations;
88
89
  async function extractSourceCodeFileTranslations(sourceCodeFilePath, babelOptions) {
89
90
  try {
90
91
  const code = await fs_extra_1.default.readFile(sourceCodeFilePath, 'utf8');
91
- const ast = core_1.parse(code, {
92
+ const ast = (0, core_1.parse)(code, {
92
93
  ...babelOptions,
93
94
  ast: true,
94
95
  // filename is important, because babel does not process the same files according to their js/ts extensions
95
96
  // see see https://twitter.com/NicoloRibaudo/status/1321130735605002243
96
97
  filename: sourceCodeFilePath,
97
98
  });
98
- return await extractSourceCodeAstTranslations(ast, sourceCodeFilePath);
99
+ const translations = await extractSourceCodeAstTranslations(ast, sourceCodeFilePath);
100
+ return translations;
99
101
  }
100
102
  catch (e) {
101
- e.message = `Error while attempting to extract Docusaurus translations from source code file at path=${sourceCodeFilePath}\n${e.message}`;
103
+ if (e instanceof Error) {
104
+ e.message = `Error while attempting to extract Docusaurus translations from source code file at path=${sourceCodeFilePath}\n${e.message}`;
105
+ }
102
106
  throw e;
103
107
  }
104
108
  }
@@ -112,20 +116,14 @@ https://github.com/formatjs/formatjs/blob/main/packages/babel-plugin-formatjs/in
112
116
  https://github.com/pugjs/babel-walk
113
117
  */
114
118
  function extractSourceCodeAstTranslations(ast, sourceCodeFilePath) {
115
- function staticTranslateJSXWarningPart() {
116
- return 'Translate content could not be extracted.\nIt has to be a static string and use optional but static props, like <Translate id="my-id" description="my-description">text</Translate>.';
117
- }
118
- function sourceFileWarningPart(node) {
119
+ function sourceWarningPart(node) {
119
120
  var _a;
120
- return `File=${sourceCodeFilePath} at line=${(_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line}`;
121
- }
122
- function generateCode(node) {
123
- return generator_1.default(node).code;
121
+ return `File: ${sourceCodeFilePath} at ${(_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line} line\nFull code: ${(0, generator_1.default)(node).code}`;
124
122
  }
125
123
  const translations = {};
126
124
  const warnings = [];
127
125
  // TODO we should check the presence of the correct @docusaurus imports here!
128
- traverse_1.default(ast, {
126
+ (0, traverse_1.default)(ast, {
129
127
  JSXElement(path) {
130
128
  if (!path
131
129
  .get('openingElement')
@@ -150,68 +148,77 @@ function extractSourceCodeAstTranslations(ast, sourceCodeFilePath) {
150
148
  return attributeValueEvaluated.value;
151
149
  }
152
150
  else {
153
- warnings.push(`<Translate> prop=${propName} should be a statically evaluable object.\nExample: <Translate id="optional.id" description="optional description">Message</Translate>\nDynamically constructed values are not allowed, because they prevent translations to be extracted.\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
151
+ warnings.push(`<Translate> prop=${propName} should be a statically evaluable object.\nExample: <Translate id="optional.id" description="optional description">Message</Translate>\nDynamically constructed values are not allowed, because they prevent translations to be extracted.\n${sourceWarningPart(path.node)}`);
154
152
  }
155
153
  }
156
154
  return undefined;
157
155
  }
158
- // We only handle the optimistic case where we have a single non-empty content
159
- const singleChildren = path
160
- .get('children')
156
+ const id = evaluateJSXProp('id');
157
+ const description = evaluateJSXProp('description');
158
+ let message;
159
+ const childrenPath = path.get('children');
160
+ // Handle empty content
161
+ if (!childrenPath.length) {
162
+ if (!id) {
163
+ warnings.push(`
164
+ <Translate> without children must have id prop.\nExample: <Translate id="my-id" />\n${sourceWarningPart(path.node)}
165
+ `);
166
+ }
167
+ else {
168
+ translations[id] = {
169
+ message: message !== null && message !== void 0 ? message : id,
170
+ ...(description && { description }),
171
+ };
172
+ }
173
+ return;
174
+ }
175
+ // Handle single non-empty content
176
+ const singleChildren = childrenPath
161
177
  // Remove empty/useless text nodes that might be around our translation!
162
178
  // Makes the translation system more reliable to JSX formatting issues
163
- .filter((childrenPath) => !(childrenPath.isJSXText() &&
164
- childrenPath.node.value.replace('\n', '').trim() === ''))
179
+ .filter((children) => !(children.isJSXText() &&
180
+ children.node.value.replace('\n', '').trim() === ''))
165
181
  .pop();
166
- if (singleChildren && singleChildren.isJSXText()) {
167
- const message = singleChildren.node.value.trim().replace(/\s+/g, ' ');
168
- const id = evaluateJSXProp('id');
169
- const description = evaluateJSXProp('description');
170
- translations[id !== null && id !== void 0 ? id : message] = {
171
- message,
172
- ...(description && { description }),
173
- };
174
- }
175
- else if (singleChildren &&
182
+ const isJSXText = singleChildren && singleChildren.isJSXText();
183
+ const isJSXExpressionContainer = singleChildren &&
176
184
  singleChildren.isJSXExpressionContainer() &&
177
- singleChildren.get('expression').evaluate().confident) {
178
- const message = singleChildren.get('expression').evaluate().value;
179
- const id = evaluateJSXProp('id');
180
- const description = evaluateJSXProp('description');
185
+ singleChildren.get('expression').evaluate().confident;
186
+ if (isJSXText || isJSXExpressionContainer) {
187
+ message = isJSXText
188
+ ? singleChildren.node.value.trim().replace(/\s+/g, ' ')
189
+ : singleChildren.get('expression').evaluate().value;
181
190
  translations[id !== null && id !== void 0 ? id : message] = {
182
191
  message,
183
192
  ...(description && { description }),
184
193
  };
185
194
  }
186
195
  else {
187
- warnings.push(`${staticTranslateJSXWarningPart()}\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
196
+ warnings.push(`Translate content could not be extracted. It has to be a static string and use optional but static props, like <Translate id="my-id" description="my-description">text</Translate>.\n${sourceWarningPart(path.node)}`);
188
197
  }
189
198
  },
190
199
  CallExpression(path) {
191
200
  if (!path.get('callee').isIdentifier({ name: 'translate' })) {
192
201
  return;
193
202
  }
194
- // console.log('CallExpression', path.node);
195
203
  const args = path.get('arguments');
196
204
  if (args.length === 1 || args.length === 2) {
197
205
  const firstArgPath = args[0];
198
206
  // evaluation allows translate("x" + "y"); to be considered as translate("xy");
199
207
  const firstArgEvaluated = firstArgPath.evaluate();
200
- // console.log('firstArgEvaluated', firstArgEvaluated);
201
208
  if (firstArgEvaluated.confident &&
202
209
  typeof firstArgEvaluated.value === 'object') {
203
210
  const { message, id, description } = firstArgEvaluated.value;
204
211
  translations[id !== null && id !== void 0 ? id : message] = {
205
- message,
212
+ message: message !== null && message !== void 0 ? message : id,
206
213
  ...(description && { description }),
207
214
  };
208
215
  }
209
216
  else {
210
- warnings.push(`translate() first arg should be a statically evaluable object.\nExample: translate({message: "text",id: "optional.id",description: "optional description"}\nDynamically constructed values are not allowed, because they prevent translations to be extracted.\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
217
+ warnings.push(`translate() first arg should be a statically evaluable object.\nExample: translate({message: "text",id: "optional.id",description: "optional description"}\nDynamically constructed values are not allowed, because they prevent translations to be extracted.\n${sourceWarningPart(path.node)}`);
211
218
  }
212
219
  }
213
220
  else {
214
- warnings.push(`translate() function only takes 1 or 2 args\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
221
+ warnings.push(`translate() function only takes 1 or 2 args\n${sourceWarningPart(path.node)}`);
215
222
  }
216
223
  },
217
224
  });
@@ -1,4 +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
+ */
1
7
  import { RouteConfig } from '@docusaurus/types';
2
- import globby from 'globby';
8
+ import { Globby } from '@docusaurus/utils';
3
9
  export declare function getAllFinalRoutes(routeConfig: RouteConfig[]): RouteConfig[];
4
- export declare function safeGlobby(patterns: string[], options?: globby.GlobbyOptions): Promise<string[]>;
10
+ export declare function safeGlobby(patterns: string[], options?: Globby.GlobbyOptions): Promise<string[]>;
@@ -1,23 +1,21 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.safeGlobby = exports.getAllFinalRoutes = void 0;
4
- const tslib_1 = require("tslib");
5
2
  /**
6
3
  * Copyright (c) Facebook, Inc. and its affiliates.
7
4
  *
8
5
  * This source code is licensed under the MIT license found in the
9
6
  * LICENSE file in the root directory of this source tree.
10
7
  */
11
- const lodash_1 = require("lodash");
12
- const globby_1 = tslib_1.__importDefault(require("globby"));
13
- const path_1 = tslib_1.__importDefault(require("path"));
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.safeGlobby = exports.getAllFinalRoutes = void 0;
10
+ const tslib_1 = require("tslib");
11
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
14
12
  const utils_1 = require("@docusaurus/utils");
15
13
  // Recursively get the final routes (routes with no subroutes)
16
14
  function getAllFinalRoutes(routeConfig) {
17
15
  function getFinalRoutes(route) {
18
- return route.routes ? lodash_1.flatMap(route.routes, getFinalRoutes) : [route];
16
+ return route.routes ? route.routes.flatMap(getFinalRoutes) : [route];
19
17
  }
20
- return lodash_1.flatMap(routeConfig, getFinalRoutes);
18
+ return routeConfig.flatMap(getFinalRoutes);
21
19
  }
22
20
  exports.getAllFinalRoutes = getAllFinalRoutes;
23
21
  // Globby that fix Windows path patterns
@@ -25,7 +23,7 @@ exports.getAllFinalRoutes = getAllFinalRoutes;
25
23
  async function safeGlobby(patterns, options) {
26
24
  // Required for Windows support, as paths using \ should not be used by globby
27
25
  // (also using the windows hard drive prefix like c: is not a good idea)
28
- const globPaths = patterns.map((dirPath) => utils_1.posixPath(path_1.default.relative(process.cwd(), dirPath)));
29
- return globby_1.default(globPaths, options);
26
+ const globPaths = patterns.map((dirPath) => (0, utils_1.posixPath)(path_1.default.relative(process.cwd(), dirPath)));
27
+ return (0, utils_1.Globby)(globPaths, options);
30
28
  }
31
29
  exports.safeGlobby = safeGlobby;