@docusaurus/core 2.0.0-beta.8e9b829d9 → 2.0.0-beta.9

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 (83) hide show
  1. package/bin/beforeCli.js +29 -7
  2. package/bin/docusaurus.js +36 -40
  3. package/lib/.tsbuildinfo +1 -1
  4. package/lib/babel/preset.js +1 -1
  5. package/lib/choosePort.js +10 -11
  6. package/lib/client/.tsbuildinfo +1 -1
  7. package/lib/client/App.js +8 -22
  8. package/lib/client/PendingNavigation.d.ts +24 -1
  9. package/lib/client/PendingNavigation.js +1 -1
  10. package/lib/client/baseUrlIssueBanner/BaseUrlIssueBanner.js +1 -0
  11. package/lib/client/docusaurus.js +0 -1
  12. package/lib/client/exports/BrowserOnly.js +5 -3
  13. package/lib/client/exports/Link.js +9 -9
  14. package/lib/client/exports/Translate.d.ts +2 -2
  15. package/lib/client/exports/Translate.js +10 -10
  16. package/lib/client/exports/browserContext.d.ts +11 -0
  17. package/lib/client/exports/browserContext.js +21 -0
  18. package/lib/client/exports/constants.js +1 -11
  19. package/lib/client/exports/{context.d.ts → docusaurusContext.d.ts} +5 -3
  20. package/lib/client/exports/docusaurusContext.js +25 -0
  21. package/lib/client/exports/useBaseUrl.js +1 -1
  22. package/lib/client/exports/useDocusaurusContext.js +2 -7
  23. package/lib/client/exports/useGlobalData.js +1 -5
  24. package/lib/client/exports/{context.js → useIsBrowser.d.ts} +1 -2
  25. package/lib/client/exports/useIsBrowser.js +11 -0
  26. package/lib/client/normalizeLocation.d.ts +1 -3
  27. package/lib/client/prefetch.js +0 -1
  28. package/lib/client/serverEntry.js +11 -27
  29. package/lib/commands/build.js +24 -21
  30. package/lib/commands/clear.js +2 -2
  31. package/lib/commands/commandUtils.js +2 -2
  32. package/lib/commands/deploy.js +24 -14
  33. package/lib/commands/external.js +4 -4
  34. package/lib/commands/serve.js +13 -13
  35. package/lib/commands/start.js +69 -70
  36. package/lib/commands/swizzle.js +14 -14
  37. package/lib/commands/writeHeadingIds.d.ts +8 -5
  38. package/lib/commands/writeHeadingIds.js +32 -31
  39. package/lib/commands/writeTranslations.js +25 -11
  40. package/lib/constants.d.ts +1 -0
  41. package/lib/constants.js +4 -1
  42. package/lib/server/brokenLinks.js +13 -13
  43. package/lib/server/config.js +4 -4
  44. package/lib/server/configValidation.js +3 -2
  45. package/lib/server/duplicateRoutes.js +2 -2
  46. package/lib/server/html-tags/htmlTags.js +5 -5
  47. package/lib/server/html-tags/index.js +2 -2
  48. package/lib/server/i18n.js +4 -4
  49. package/lib/server/index.js +98 -49
  50. package/lib/server/loadSetup.js +3 -3
  51. package/lib/server/plugins/applyRouteTrailingSlash.js +1 -1
  52. package/lib/server/plugins/index.d.ts +1 -1
  53. package/lib/server/plugins/index.js +20 -13
  54. package/lib/server/plugins/init.js +7 -10
  55. package/lib/server/plugins/pluginIds.js +2 -2
  56. package/lib/server/presets/index.js +4 -7
  57. package/lib/server/routes.js +9 -11
  58. package/lib/server/themes/alias.d.ts +1 -0
  59. package/lib/server/themes/alias.js +22 -10
  60. package/lib/server/themes/index.js +5 -7
  61. package/lib/server/translations/translations.js +9 -9
  62. package/lib/server/translations/translationsExtractor.d.ts +1 -1
  63. package/lib/server/translations/translationsExtractor.js +58 -47
  64. package/lib/server/utils.d.ts +6 -0
  65. package/lib/server/utils.js +8 -9
  66. package/lib/server/versions/__fixtures__/dummy-plugin.d.ts +0 -0
  67. package/lib/server/versions/__tests/index.test.js +5 -5
  68. package/lib/server/versions/index.js +6 -6
  69. package/lib/webpack/base.js +12 -13
  70. package/lib/webpack/client.js +8 -17
  71. package/lib/webpack/plugins/CleanWebpackPlugin.js +2 -5
  72. package/lib/webpack/plugins/LogPlugin.js +3 -4
  73. package/lib/webpack/plugins/WaitPlugin.js +4 -4
  74. package/lib/webpack/react-dev-utils-webpack5/evalSourceMapMiddleware.d.ts +2 -0
  75. package/lib/webpack/react-dev-utils-webpack5/formatWebpackMessages.d.ts +5 -0
  76. package/lib/webpack/react-dev-utils-webpack5/formatWebpackMessages.js +1 -1
  77. package/lib/webpack/react-dev-utils-webpack5/webpackHotDevClient.d.ts +1 -0
  78. package/lib/webpack/server.js +7 -7
  79. package/lib/webpack/sharedModuleAliases.js +1 -1
  80. package/lib/webpack/utils.js +25 -23
  81. package/package.json +44 -38
  82. package/tsconfig.client.json +0 -1
  83. package/tsconfig.json +4 -3
@@ -12,9 +12,9 @@ const constants_1 = require("../../constants");
12
12
  // It is forbidden to have 2 plugins of the same name sharing the same id
13
13
  // this is required to support multi-instance plugins without conflict
14
14
  function ensureUniquePluginInstanceIds(plugins) {
15
- const pluginsByName = lodash_1.groupBy(plugins, (p) => p.name);
15
+ const pluginsByName = (0, lodash_1.groupBy)(plugins, (p) => p.name);
16
16
  Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => {
17
- const pluginInstancesById = lodash_1.groupBy(pluginInstances, (p) => { var _a; return (_a = p.options.id) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_PLUGIN_ID; });
17
+ const pluginInstancesById = (0, lodash_1.groupBy)(pluginInstances, (p) => { var _a; return (_a = p.options.id) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_PLUGIN_ID; });
18
18
  Object.entries(pluginInstancesById).forEach(([pluginId, pluginInstancesWithId]) => {
19
19
  if (pluginInstancesWithId.length !== 1) {
20
20
  throw new Error(`Plugin "${pluginName}" is used ${pluginInstancesWithId.length} times with id ${pluginId}.\nTo use the same plugin multiple times on a Docusaurus site, you need to assign a unique id to each plugin instance.`);
@@ -7,15 +7,12 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  const tslib_1 = require("tslib");
10
- const module_1 = tslib_1.__importDefault(require("module"));
11
- const import_fresh_1 = tslib_1.__importDefault(require("import-fresh"));
10
+ const module_1 = require("module");
11
+ const import_fresh_1 = (0, tslib_1.__importDefault)(require("import-fresh"));
12
12
  function loadPresets(context) {
13
13
  // We need to resolve plugins from the perspective of the siteDir, since the siteDir's package.json
14
14
  // declares the dependency on these plugins.
15
- // We need to fallback to createRequireFromPath since createRequire is only available in node v12.
16
- // See: https://nodejs.org/api/modules.html#modules_module_createrequire_filename
17
- const createRequire = module_1.default.createRequire || module_1.default.createRequireFromPath;
18
- const pluginRequire = createRequire(context.siteConfigPath);
15
+ const pluginRequire = (0, module_1.createRequire)(context.siteConfigPath);
19
16
  const presets = (context.siteConfig || {}).presets || [];
20
17
  const unflatPlugins = [];
21
18
  const unflatThemes = [];
@@ -31,7 +28,7 @@ function loadPresets(context) {
31
28
  else {
32
29
  throw new Error('Invalid presets format detected in config.');
33
30
  }
34
- const presetModule = import_fresh_1.default(pluginRequire.resolve(presetModuleImport));
31
+ const presetModule = (0, import_fresh_1.default)(pluginRequire.resolve(presetModuleImport));
35
32
  const preset = (presetModule.default || presetModule)(context, presetOptions);
36
33
  if (preset.plugins) {
37
34
  unflatPlugins.push(preset.plugins);
@@ -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,11 +6,26 @@
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 fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
11
- 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"));
12
13
  const utils_1 = require("@docusaurus/utils");
13
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]) => {
24
+ return alias1.includes(`${alias2}/`) ? -1 : 0;
25
+ });
26
+ return Object.fromEntries(entries);
27
+ }
28
+ exports.sortAliases = sortAliases;
14
29
  // TODO make async
15
30
  function themeAlias(themePath, addOriginalAlias) {
16
31
  if (!fs_extra_1.default.pathExistsSync(themePath)) {
@@ -19,21 +34,18 @@ function themeAlias(themePath, addOriginalAlias) {
19
34
  const themeComponentFiles = utils_1.Globby.sync(['**/*.{js,jsx,ts,tsx}'], {
20
35
  cwd: themePath,
21
36
  });
22
- // See https://github.com/facebook/docusaurus/pull/3922
23
- // ensure @theme/NavbarItem alias is created after @theme/NavbarItem/LocaleDropdown
24
- const sortedThemeComponentFiles = lodash_1.sortBy(themeComponentFiles, (file) => file.endsWith('/index.js'));
25
37
  const aliases = {};
26
- sortedThemeComponentFiles.forEach((relativeSource) => {
38
+ themeComponentFiles.forEach((relativeSource) => {
27
39
  const filePath = path_1.default.join(themePath, relativeSource);
28
- const fileName = utils_1.fileToPath(relativeSource);
29
- const aliasName = utils_1.posixPath(utils_1.normalizeUrl(['@theme', fileName]).replace(/\/$/, ''));
40
+ const fileName = (0, utils_1.fileToPath)(relativeSource);
41
+ const aliasName = (0, utils_1.posixPath)((0, utils_1.normalizeUrl)(['@theme', fileName]).replace(/\/$/, ''));
30
42
  aliases[aliasName] = filePath;
31
43
  if (addOriginalAlias) {
32
44
  // For swizzled components to access the original.
33
- const originalAliasName = utils_1.posixPath(utils_1.normalizeUrl(['@theme-original', fileName]).replace(/\/$/, ''));
45
+ const originalAliasName = (0, utils_1.posixPath)((0, utils_1.normalizeUrl)(['@theme-original', fileName]).replace(/\/$/, ''));
34
46
  aliases[originalAliasName] = filePath;
35
47
  }
36
48
  });
37
- return aliases;
49
+ return sortAliases(aliases);
38
50
  }
39
51
  exports.default = themeAlias;
@@ -8,18 +8,16 @@
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"));
11
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
12
12
  const constants_1 = require("../../constants");
13
- const alias_1 = tslib_1.__importDefault(require("./alias"));
13
+ const alias_1 = (0, tslib_1.__importStar)(require("./alias"));
14
14
  const ThemeFallbackDir = path_1.default.resolve(__dirname, '../../client/theme-fallback');
15
15
  function buildThemeAliases(themeAliases, aliases = {}) {
16
16
  Object.keys(themeAliases).forEach((aliasKey) => {
17
17
  if (aliasKey in aliases) {
18
18
  const componentName = aliasKey.substring(aliasKey.indexOf('/') + 1);
19
- // eslint-disable-next-line no-param-reassign
20
19
  aliases[`@theme-init/${componentName}`] = aliases[aliasKey];
21
20
  }
22
- // eslint-disable-next-line no-param-reassign
23
21
  aliases[aliasKey] = themeAliases[aliasKey];
24
22
  });
25
23
  return aliases;
@@ -27,14 +25,14 @@ function buildThemeAliases(themeAliases, aliases = {}) {
27
25
  function loadThemeAliases(themePaths, userThemePaths = []) {
28
26
  let aliases = {}; // TODO refactor, inelegant side-effect
29
27
  themePaths.forEach((themePath) => {
30
- const themeAliases = alias_1.default(themePath, true);
28
+ const themeAliases = (0, alias_1.default)(themePath, true);
31
29
  aliases = { ...aliases, ...buildThemeAliases(themeAliases, aliases) };
32
30
  });
33
31
  userThemePaths.forEach((themePath) => {
34
- const userThemeAliases = alias_1.default(themePath, false);
32
+ const userThemeAliases = (0, alias_1.default)(themePath, false);
35
33
  aliases = { ...aliases, ...buildThemeAliases(userThemeAliases, aliases) };
36
34
  });
37
- return aliases;
35
+ return (0, alias_1.sortAliases)(aliases);
38
36
  }
39
37
  exports.loadThemeAliases = loadThemeAliases;
40
38
  function loadPluginsThemeAliases({ siteDir, plugins, }) {
@@ -8,12 +8,12 @@ const tslib_1 = require("tslib");
8
8
  * This source code is licensed under the MIT license found in the
9
9
  * LICENSE file in the root directory of this source tree.
10
10
  */
11
- const path_1 = tslib_1.__importDefault(require("path"));
12
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
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 chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
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,7 +68,7 @@ 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
73
  console.warn(chalk_1.default.yellow(`Some translation keys looks unknown to us in file ${filePath}
74
74
  Maybe you should remove them?
@@ -83,7 +83,7 @@ Maybe you should remove them?
83
83
  if (Object.keys(mergedContent).length > 0) {
84
84
  console.log(`${Object.keys(mergedContent)
85
85
  .length.toString()
86
- .padStart(3, ' ')} translations will be written at "${utils_1.toMessageRelativeFilePath(filePath)}".`);
86
+ .padStart(3, ' ')} translations will be written at "${(0, utils_1.toMessageRelativeFilePath)(filePath)}".`);
87
87
  await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
88
88
  await fs_extra_1.default.writeFile(filePath, JSON.stringify(mergedContent, null, 2));
89
89
  }
@@ -124,7 +124,7 @@ function addTranslationFileExtension(translationFilePath) {
124
124
  return `${translationFilePath}.json`;
125
125
  }
126
126
  function getPluginTranslationFilePath({ siteDir, plugin, locale, translationFilePath, }) {
127
- const dirPath = utils_1.getPluginI18nPath({
127
+ const dirPath = (0, utils_1.getPluginI18nPath)({
128
128
  siteDir,
129
129
  locale,
130
130
  pluginName: plugin.name,
@@ -178,14 +178,14 @@ async function getPluginsDefaultCodeTranslationMessages(plugins) {
178
178
  }
179
179
  exports.getPluginsDefaultCodeTranslationMessages = getPluginsDefaultCodeTranslationMessages;
180
180
  function applyDefaultCodeTranslations({ extractedCodeTranslations, defaultCodeMessages, }) {
181
- const unusedDefaultCodeMessages = lodash_1.difference(Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations));
181
+ const unusedDefaultCodeMessages = (0, lodash_1.difference)(Object.keys(defaultCodeMessages), Object.keys(extractedCodeTranslations));
182
182
  if (unusedDefaultCodeMessages.length > 0) {
183
183
  console.warn(chalk_1.default.yellow(`Unused default message codes found.
184
184
  Please report this Docusaurus issue.
185
185
  - ${unusedDefaultCodeMessages.join('\n- ')}
186
186
  `));
187
187
  }
188
- return lodash_1.mapValues(extractedCodeTranslations, (messageTranslation, messageId) => {
188
+ return (0, lodash_1.mapValues)(extractedCodeTranslations, (messageTranslation, messageId) => {
189
189
  var _a;
190
190
  return {
191
191
  ...messageTranslation,
@@ -1,7 +1,7 @@
1
1
  import { TransformOptions } from '@babel/core';
2
2
  import { InitializedPlugin, TranslationFileContent, TranslationMessage } from '@docusaurus/types';
3
3
  export declare function globSourceCodeFilePaths(dirPaths: string[]): Promise<string[]>;
4
- export declare function extractSiteSourceCodeTranslations(siteDir: string, plugins: InitializedPlugin[], babelOptions: TransformOptions): Promise<TranslationFileContent>;
4
+ export declare function extractSiteSourceCodeTranslations(siteDir: string, plugins: InitializedPlugin[], babelOptions: TransformOptions, extraSourceCodeFilePaths?: string[]): Promise<TranslationFileContent>;
5
5
  declare type SourceCodeFileTranslations = {
6
6
  sourceCodeFilePath: string;
7
7
  translations: Record<string, TranslationMessage>;
@@ -8,13 +8,12 @@ const tslib_1 = require("tslib");
8
8
  * This source code is licensed under the MIT license found in the
9
9
  * LICENSE file in the root directory of this source tree.
10
10
  */
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"));
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 chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
15
15
  const core_1 = require("@babel/core");
16
- const lodash_1 = require("lodash");
17
- const path_1 = tslib_1.__importDefault(require("path"));
16
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
18
17
  const constants_1 = require("../../constants");
19
18
  const utils_1 = require("../utils");
20
19
  // We only support extracting source code translations from these kind of files
@@ -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_1.safeGlobby)(dirPaths);
52
51
  return filePaths.filter(isTranslatableSourceCodePath);
53
52
  }
54
53
  exports.globSourceCodeFilePaths = globSourceCodeFilePaths;
@@ -57,11 +56,11 @@ 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
66
  return sourceCodeFileTranslations.reduce((acc, item) => {
@@ -69,7 +68,11 @@ async function extractSiteSourceCodeTranslations(siteDir, plugins, babelOptions)
69
68
  }, {});
70
69
  }
71
70
  const sourceCodeFilePaths = await getSourceCodeFilePaths(siteDir, plugins);
72
- const sourceCodeFilesTranslations = await extractAllSourceCodeFileTranslations(sourceCodeFilePaths, babelOptions);
71
+ const allSourceCodeFilePaths = [
72
+ ...sourceCodeFilePaths,
73
+ ...extraSourceCodeFilePaths,
74
+ ];
75
+ const sourceCodeFilesTranslations = await extractAllSourceCodeFileTranslations(allSourceCodeFilePaths, babelOptions);
73
76
  logSourceCodeFileTranslationsWarnings(sourceCodeFilesTranslations);
74
77
  return toTranslationFileContent(sourceCodeFilesTranslations);
75
78
  }
@@ -82,23 +85,26 @@ function logSourceCodeFileTranslationsWarnings(sourceCodeFilesTranslations) {
82
85
  });
83
86
  }
84
87
  async function extractAllSourceCodeFileTranslations(sourceCodeFilePaths, babelOptions) {
85
- return lodash_1.flatten(await Promise.all(sourceCodeFilePaths.map((sourceFilePath) => extractSourceCodeFileTranslations(sourceFilePath, babelOptions))));
88
+ return Promise.all(sourceCodeFilePaths.flatMap((sourceFilePath) => extractSourceCodeFileTranslations(sourceFilePath, babelOptions)));
86
89
  }
87
90
  exports.extractAllSourceCodeFileTranslations = extractAllSourceCodeFileTranslations;
88
91
  async function extractSourceCodeFileTranslations(sourceCodeFilePath, babelOptions) {
89
92
  try {
90
93
  const code = await fs_extra_1.default.readFile(sourceCodeFilePath, 'utf8');
91
- const ast = core_1.parse(code, {
94
+ const ast = (0, core_1.parse)(code, {
92
95
  ...babelOptions,
93
96
  ast: true,
94
97
  // filename is important, because babel does not process the same files according to their js/ts extensions
95
98
  // see see https://twitter.com/NicoloRibaudo/status/1321130735605002243
96
99
  filename: sourceCodeFilePath,
97
100
  });
98
- return await extractSourceCodeAstTranslations(ast, sourceCodeFilePath);
101
+ const translations = await extractSourceCodeAstTranslations(ast, sourceCodeFilePath);
102
+ return translations;
99
103
  }
100
104
  catch (e) {
101
- e.message = `Error while attempting to extract Docusaurus translations from source code file at path=${sourceCodeFilePath}\n${e.message}`;
105
+ if (e instanceof Error) {
106
+ e.message = `Error while attempting to extract Docusaurus translations from source code file at path=${sourceCodeFilePath}\n${e.message}`;
107
+ }
102
108
  throw e;
103
109
  }
104
110
  }
@@ -112,20 +118,14 @@ https://github.com/formatjs/formatjs/blob/main/packages/babel-plugin-formatjs/in
112
118
  https://github.com/pugjs/babel-walk
113
119
  */
114
120
  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) {
121
+ function sourceWarningPart(node) {
119
122
  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;
123
+ 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
124
  }
125
125
  const translations = {};
126
126
  const warnings = [];
127
127
  // TODO we should check the presence of the correct @docusaurus imports here!
128
- traverse_1.default(ast, {
128
+ (0, traverse_1.default)(ast, {
129
129
  JSXElement(path) {
130
130
  if (!path
131
131
  .get('openingElement')
@@ -150,41 +150,52 @@ function extractSourceCodeAstTranslations(ast, sourceCodeFilePath) {
150
150
  return attributeValueEvaluated.value;
151
151
  }
152
152
  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)}`);
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${sourceWarningPart(path.node)}`);
154
154
  }
155
155
  }
156
156
  return undefined;
157
157
  }
158
- // We only handle the optimistic case where we have a single non-empty content
159
- const singleChildren = path
160
- .get('children')
158
+ const id = evaluateJSXProp('id');
159
+ const description = evaluateJSXProp('description');
160
+ let message;
161
+ const childrenPath = path.get('children');
162
+ // Handle empty content
163
+ if (!childrenPath.length) {
164
+ if (!id) {
165
+ warnings.push(`
166
+ <Translate> without children must have id prop.\nExample: <Translate id="my-id" />\n${sourceWarningPart(path.node)}
167
+ `);
168
+ }
169
+ else {
170
+ translations[id] = {
171
+ message: message !== null && message !== void 0 ? message : id,
172
+ ...(description && { description }),
173
+ };
174
+ }
175
+ return;
176
+ }
177
+ // Handle single non-empty content
178
+ const singleChildren = childrenPath
161
179
  // Remove empty/useless text nodes that might be around our translation!
162
180
  // Makes the translation system more reliable to JSX formatting issues
163
- .filter((childrenPath) => !(childrenPath.isJSXText() &&
164
- childrenPath.node.value.replace('\n', '').trim() === ''))
181
+ .filter((children) => !(children.isJSXText() &&
182
+ children.node.value.replace('\n', '').trim() === ''))
165
183
  .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 &&
184
+ const isJSXText = singleChildren && singleChildren.isJSXText();
185
+ const isJSXExpressionContainer = singleChildren &&
176
186
  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');
187
+ singleChildren.get('expression').evaluate().confident;
188
+ if (isJSXText || isJSXExpressionContainer) {
189
+ message = isJSXText
190
+ ? singleChildren.node.value.trim().replace(/\s+/g, ' ')
191
+ : singleChildren.get('expression').evaluate().value;
181
192
  translations[id !== null && id !== void 0 ? id : message] = {
182
193
  message,
183
194
  ...(description && { description }),
184
195
  };
185
196
  }
186
197
  else {
187
- warnings.push(`${staticTranslateJSXWarningPart()}\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
198
+ 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
199
  }
189
200
  },
190
201
  CallExpression(path) {
@@ -202,16 +213,16 @@ function extractSourceCodeAstTranslations(ast, sourceCodeFilePath) {
202
213
  typeof firstArgEvaluated.value === 'object') {
203
214
  const { message, id, description } = firstArgEvaluated.value;
204
215
  translations[id !== null && id !== void 0 ? id : message] = {
205
- message,
216
+ message: message !== null && message !== void 0 ? message : id,
206
217
  ...(description && { description }),
207
218
  };
208
219
  }
209
220
  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)}`);
221
+ 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
222
  }
212
223
  }
213
224
  else {
214
- warnings.push(`translate() function only takes 1 or 2 args\n${sourceFileWarningPart(path.node)}\n${generateCode(path.node)}`);
225
+ warnings.push(`translate() function only takes 1 or 2 args\n${sourceWarningPart(path.node)}`);
215
226
  }
216
227
  },
217
228
  });
@@ -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 { RouteConfig } from '@docusaurus/types';
2
8
  import { Globby } from '@docusaurus/utils';
3
9
  export declare function getAllFinalRoutes(routeConfig: RouteConfig[]): RouteConfig[];
@@ -1,22 +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 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"));
13
12
  const utils_1 = require("@docusaurus/utils");
14
13
  // Recursively get the final routes (routes with no subroutes)
15
14
  function getAllFinalRoutes(routeConfig) {
16
15
  function getFinalRoutes(route) {
17
- return route.routes ? lodash_1.flatMap(route.routes, getFinalRoutes) : [route];
16
+ return route.routes ? route.routes.flatMap(getFinalRoutes) : [route];
18
17
  }
19
- return lodash_1.flatMap(routeConfig, getFinalRoutes);
18
+ return routeConfig.flatMap(getFinalRoutes);
20
19
  }
21
20
  exports.getAllFinalRoutes = getAllFinalRoutes;
22
21
  // Globby that fix Windows path patterns
@@ -24,7 +23,7 @@ exports.getAllFinalRoutes = getAllFinalRoutes;
24
23
  async function safeGlobby(patterns, options) {
25
24
  // Required for Windows support, as paths using \ should not be used by globby
26
25
  // (also using the windows hard drive prefix like c: is not a good idea)
27
- const globPaths = patterns.map((dirPath) => utils_1.posixPath(path_1.default.relative(process.cwd(), dirPath)));
28
- return utils_1.Globby(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);
29
28
  }
30
29
  exports.safeGlobby = safeGlobby;
@@ -10,16 +10,16 @@ const __1 = require("..");
10
10
  const path_1 = require("path");
11
11
  describe('getPluginVersion', () => {
12
12
  it('Can detect external packages plugins versions of correctly.', () => {
13
- expect(__1.getPluginVersion(path_1.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
13
+ expect((0, __1.getPluginVersion)((0, path_1.join)(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
14
14
  // Make the plugin appear external.
15
- path_1.join(__dirname, '..', '..', '..', '..', '..', '..', 'website'))).toEqual({ type: 'package', version: 'random-version' });
15
+ (0, path_1.join)(__dirname, '..', '..', '..', '..', '..', '..', 'website'))).toEqual({ type: 'package', version: 'random-version' });
16
16
  });
17
17
  it('Can detect project plugins versions correctly.', () => {
18
- expect(__1.getPluginVersion(path_1.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
18
+ expect((0, __1.getPluginVersion)((0, path_1.join)(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
19
19
  // Make the plugin appear project local.
20
- path_1.join(__dirname, '..', '__fixtures__'))).toEqual({ type: 'project' });
20
+ (0, path_1.join)(__dirname, '..', '__fixtures__'))).toEqual({ type: 'project' });
21
21
  });
22
22
  it('Can detect local packages versions correctly.', () => {
23
- expect(__1.getPluginVersion('/', '/')).toEqual({ type: 'local' });
23
+ expect((0, __1.getPluginVersion)('/', '/')).toEqual({ type: 'local' });
24
24
  });
25
25
  });
@@ -10,7 +10,7 @@ exports.getPluginVersion = exports.getPackageJsonName = exports.getPackageJsonVe
10
10
  const fs_extra_1 = require("fs-extra");
11
11
  const path_1 = require("path");
12
12
  function getPackageJsonVersion(packageJsonPath) {
13
- if (fs_extra_1.existsSync(packageJsonPath)) {
13
+ if ((0, fs_extra_1.existsSync)(packageJsonPath)) {
14
14
  // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
15
15
  const { version } = require(packageJsonPath);
16
16
  return typeof version === 'string' ? version : undefined;
@@ -19,7 +19,7 @@ function getPackageJsonVersion(packageJsonPath) {
19
19
  }
20
20
  exports.getPackageJsonVersion = getPackageJsonVersion;
21
21
  function getPackageJsonName(packageJsonPath) {
22
- if (fs_extra_1.existsSync(packageJsonPath)) {
22
+ if ((0, fs_extra_1.existsSync)(packageJsonPath)) {
23
23
  // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
24
24
  const { name } = require(packageJsonPath);
25
25
  return typeof name === 'string' ? name : undefined;
@@ -28,10 +28,10 @@ function getPackageJsonName(packageJsonPath) {
28
28
  }
29
29
  exports.getPackageJsonName = getPackageJsonName;
30
30
  function getPluginVersion(pluginPath, siteDir) {
31
- let potentialPluginPackageJsonDirectory = path_1.dirname(pluginPath);
31
+ let potentialPluginPackageJsonDirectory = (0, path_1.dirname)(pluginPath);
32
32
  while (potentialPluginPackageJsonDirectory !== '/') {
33
- const packageJsonPath = path_1.join(potentialPluginPackageJsonDirectory, 'package.json');
34
- if (fs_extra_1.existsSync(packageJsonPath) && fs_extra_1.lstatSync(packageJsonPath).isFile()) {
33
+ const packageJsonPath = (0, path_1.join)(potentialPluginPackageJsonDirectory, 'package.json');
34
+ if ((0, fs_extra_1.existsSync)(packageJsonPath) && (0, fs_extra_1.lstatSync)(packageJsonPath).isFile()) {
35
35
  if (potentialPluginPackageJsonDirectory === siteDir) {
36
36
  // If the plugin belongs to the same docusaurus project, we classify it as local plugin.
37
37
  return { type: 'project' };
@@ -42,7 +42,7 @@ function getPluginVersion(pluginPath, siteDir) {
42
42
  version: getPackageJsonVersion(packageJsonPath),
43
43
  };
44
44
  }
45
- potentialPluginPackageJsonDirectory = path_1.dirname(potentialPluginPackageJsonDirectory);
45
+ potentialPluginPackageJsonDirectory = (0, path_1.dirname)(potentialPluginPackageJsonDirectory);
46
46
  }
47
47
  // In rare cases where a plugin is a path where no parent directory contains package.json, we can only classify it as local.
48
48
  return { type: 'local' };