@docusaurus/utils 3.9.2 → 3.10.1-canary-6591

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 (74) hide show
  1. package/lib/index.d.ts +5 -4
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.js +13 -11
  4. package/lib/index.js.map +1 -1
  5. package/lib/lastUpdateUtils.d.ts +2 -6
  6. package/lib/lastUpdateUtils.d.ts.map +1 -1
  7. package/lib/lastUpdateUtils.js +13 -60
  8. package/lib/lastUpdateUtils.js.map +1 -1
  9. package/lib/markdownHeadingIdUtils.d.ts +49 -0
  10. package/lib/markdownHeadingIdUtils.d.ts.map +1 -0
  11. package/lib/markdownHeadingIdUtils.js +148 -0
  12. package/lib/markdownHeadingIdUtils.js.map +1 -0
  13. package/lib/markdownUtils.d.ts +0 -31
  14. package/lib/markdownUtils.d.ts.map +1 -1
  15. package/lib/markdownUtils.js +0 -89
  16. package/lib/markdownUtils.js.map +1 -1
  17. package/lib/moduleUtils.d.ts.map +1 -1
  18. package/lib/moduleUtils.js +4 -4
  19. package/lib/moduleUtils.js.map +1 -1
  20. package/lib/{gitUtils.d.ts → vcs/gitUtils.d.ts} +18 -0
  21. package/lib/vcs/gitUtils.d.ts.map +1 -0
  22. package/lib/vcs/gitUtils.js +343 -0
  23. package/lib/vcs/gitUtils.js.map +1 -0
  24. package/lib/vcs/vcs.d.ts +19 -0
  25. package/lib/vcs/vcs.d.ts.map +1 -0
  26. package/lib/vcs/vcs.js +46 -0
  27. package/lib/vcs/vcs.js.map +1 -0
  28. package/lib/vcs/vcsDefaultV1.d.ts +13 -0
  29. package/lib/vcs/vcsDefaultV1.d.ts.map +1 -0
  30. package/lib/vcs/vcsDefaultV1.js +33 -0
  31. package/lib/vcs/vcsDefaultV1.js.map +1 -0
  32. package/lib/vcs/vcsDefaultV2.d.ts +13 -0
  33. package/lib/vcs/vcsDefaultV2.d.ts.map +1 -0
  34. package/lib/vcs/vcsDefaultV2.js +33 -0
  35. package/lib/vcs/vcsDefaultV2.js.map +1 -0
  36. package/lib/vcs/vcsDisabled.d.ts +12 -0
  37. package/lib/vcs/vcsDisabled.d.ts.map +1 -0
  38. package/lib/vcs/vcsDisabled.js +24 -0
  39. package/lib/vcs/vcsDisabled.js.map +1 -0
  40. package/lib/vcs/vcsGitAdHoc.d.ts +16 -0
  41. package/lib/vcs/vcsGitAdHoc.d.ts.map +1 -0
  42. package/lib/vcs/vcsGitAdHoc.js +29 -0
  43. package/lib/vcs/vcsGitAdHoc.js.map +1 -0
  44. package/lib/vcs/vcsGitEager.d.ts +10 -0
  45. package/lib/vcs/vcsGitEager.d.ts.map +1 -0
  46. package/lib/vcs/vcsGitEager.js +89 -0
  47. package/lib/vcs/vcsGitEager.js.map +1 -0
  48. package/lib/vcs/vcsHardcoded.d.ts +17 -0
  49. package/lib/vcs/vcsHardcoded.d.ts.map +1 -0
  50. package/lib/vcs/vcsHardcoded.js +41 -0
  51. package/lib/vcs/vcsHardcoded.js.map +1 -0
  52. package/package.json +11 -11
  53. package/src/index.ts +11 -8
  54. package/src/lastUpdateUtils.ts +18 -76
  55. package/src/markdownHeadingIdUtils.ts +209 -0
  56. package/src/markdownUtils.ts +0 -119
  57. package/src/moduleUtils.ts +6 -8
  58. package/src/vcs/gitUtils.ts +541 -0
  59. package/src/vcs/vcs.ts +54 -0
  60. package/src/vcs/vcsDefaultV1.ts +33 -0
  61. package/src/vcs/vcsDefaultV2.ts +33 -0
  62. package/src/vcs/vcsDisabled.ts +25 -0
  63. package/src/vcs/vcsGitAdHoc.ts +30 -0
  64. package/src/vcs/vcsGitEager.ts +135 -0
  65. package/src/vcs/vcsHardcoded.ts +45 -0
  66. package/lib/cliUtils.d.ts +0 -14
  67. package/lib/cliUtils.d.ts.map +0 -1
  68. package/lib/cliUtils.js +0 -49
  69. package/lib/cliUtils.js.map +0 -1
  70. package/lib/gitUtils.d.ts.map +0 -1
  71. package/lib/gitUtils.js +0 -103
  72. package/lib/gitUtils.js.map +0 -1
  73. package/src/cliUtils.ts +0 -65
  74. package/src/gitUtils.ts +0 -200
@@ -0,0 +1,30 @@
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
+ import {getGitLastUpdate, getGitCreation} from './gitUtils';
9
+ import type {VcsConfig} from '@docusaurus/types';
10
+
11
+ /**
12
+ * A VCS strategy to query Git information in an ad-hoc way.
13
+ * This is the default/historical Docusaurus Git VCS implementation.
14
+ * Unfortunately, it is a major bottleneck for large sites/repositories.
15
+ *
16
+ * See also https://github.com/facebook/docusaurus/issues/11208
17
+ */
18
+ export const VcsGitAdHoc: VcsConfig = {
19
+ initialize: () => {
20
+ // Nothing to do here for the default/historical Git implementation
21
+ },
22
+
23
+ getFileCreationInfo: async (filePath: string) => {
24
+ return getGitCreation(filePath);
25
+ },
26
+
27
+ getFileLastUpdateInfo: async (filePath: string) => {
28
+ return getGitLastUpdate(filePath);
29
+ },
30
+ };
@@ -0,0 +1,135 @@
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
+ import {resolve, basename} from 'node:path';
9
+ import logger, {PerfLogger} from '@docusaurus/logger';
10
+ import {
11
+ getGitAllRepoRoots,
12
+ getGitRepositoryFilesInfo,
13
+ isGitInsideWorktree,
14
+ } from './gitUtils';
15
+ import type {GitFileInfo, GitFileInfoMap} from './gitUtils';
16
+ import type {VcsConfig} from '@docusaurus/types';
17
+
18
+ // The Map keys should be absolute file paths, not relative Git paths
19
+ function resolveFileInfoMapPaths(
20
+ repoRoot: string,
21
+ filesInfo: GitFileInfoMap,
22
+ ): GitFileInfoMap {
23
+ function transformMapEntry(
24
+ entry: [string, GitFileInfo],
25
+ ): [string, GitFileInfo] {
26
+ // We just resolve the Git paths that are relative to the repo root
27
+ return [resolve(repoRoot, entry[0]), entry[1]];
28
+ }
29
+
30
+ return new Map(Array.from(filesInfo.entries()).map(transformMapEntry));
31
+ }
32
+
33
+ function mergeFileMaps(fileMaps: GitFileInfoMap[]): GitFileInfoMap {
34
+ return new Map(fileMaps.flatMap((m) => [...m]));
35
+ }
36
+
37
+ async function loadAllGitFilesInfoMap(cwd: string): Promise<GitFileInfoMap> {
38
+ const roots = await PerfLogger.async('Reading Git root dirs', () =>
39
+ getGitAllRepoRoots(cwd),
40
+ );
41
+
42
+ const allMaps: GitFileInfoMap[] = await Promise.all(
43
+ roots.map(async (root) => {
44
+ const map = await PerfLogger.async(
45
+ `Reading Git history for repo ${logger.path(basename(root))}`,
46
+ () => getGitRepositoryFilesInfo(root),
47
+ );
48
+ return resolveFileInfoMapPaths(root, map);
49
+ }),
50
+ );
51
+
52
+ return mergeFileMaps(allMaps);
53
+ }
54
+
55
+ type InitializeResult =
56
+ | {
57
+ type: 'success';
58
+ filesMap: GitFileInfoMap;
59
+ }
60
+ | {
61
+ type: 'error';
62
+ reason: 'not-in-worktree' | 'unknown';
63
+ cause?: Error;
64
+ };
65
+
66
+ async function initialize({
67
+ siteDir,
68
+ }: {
69
+ siteDir: string;
70
+ }): Promise<InitializeResult> {
71
+ try {
72
+ const isInWorktree = await isGitInsideWorktree(siteDir);
73
+ if (!isInWorktree) {
74
+ return {type: 'error', reason: 'not-in-worktree'};
75
+ }
76
+ const filesMap = await loadAllGitFilesInfoMap(siteDir);
77
+ return {type: 'success', filesMap};
78
+ } catch (error) {
79
+ return {type: 'error', reason: 'unknown', cause: error as Error};
80
+ }
81
+ }
82
+
83
+ export function createVcsGitEagerConfig(): VcsConfig {
84
+ let initPromise: Promise<InitializeResult> | null = null;
85
+
86
+ async function getGitFileInfo(filePath: string): Promise<GitFileInfo | null> {
87
+ const init = (await initPromise)!;
88
+ if (init.type === 'success') {
89
+ return init.filesMap.get(filePath) ?? null;
90
+ } else if (init.reason === 'not-in-worktree') {
91
+ throw new Error(
92
+ `This Docusaurus site is outside any Git worktree.
93
+ Unable to read Git info for file ${logger.path(filePath)} `,
94
+ );
95
+ } else {
96
+ throw init.cause;
97
+ }
98
+ }
99
+
100
+ return {
101
+ initialize: ({siteDir}) => {
102
+ if (initPromise) {
103
+ // We only initialize this VCS once!
104
+ // For i18n sites, this permits reading ahead of time for all locales
105
+ // so that it only slows down the first locale
106
+ // I assume this logic is fine, but we'll see if it causes trouble
107
+
108
+ // Note: we could also only call "initialize()" once from the outside,
109
+ // But maybe it could be useful for custom VCS implementations to be
110
+ // able to initialize once per locale?
111
+ PerfLogger.log(
112
+ 'Git Eager VCS strategy already initialized, skipping re-initialization',
113
+ );
114
+ return;
115
+ }
116
+
117
+ initPromise = PerfLogger.async('Git Eager VCS init', () =>
118
+ initialize({siteDir}),
119
+ );
120
+ },
121
+
122
+ getFileCreationInfo: async (filePath: string) => {
123
+ const fileInfo = await getGitFileInfo(filePath);
124
+ return fileInfo?.creation ?? null;
125
+ },
126
+
127
+ getFileLastUpdateInfo: async (filePath: string) => {
128
+ const fileInfo = await getGitFileInfo(filePath);
129
+ return fileInfo?.lastUpdate ?? null;
130
+ },
131
+ };
132
+ }
133
+
134
+ // TODO it probably shouldn't be a singleton, but good enough for now
135
+ export const VscGitEager: VcsConfig = createVcsGitEagerConfig();
@@ -0,0 +1,45 @@
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
+ import type {VcsConfig, VcsChangeInfo} from '@docusaurus/types';
9
+
10
+ export const VCS_HARDCODED_CREATION_INFO: VcsChangeInfo = {
11
+ timestamp: 1490997600000, // 1st Apr 2017
12
+ author: 'Creator',
13
+ };
14
+
15
+ export const VCS_HARDCODED_LAST_UPDATE_INFO: VcsChangeInfo = {
16
+ timestamp: 1539502055000, // 14th Oct 2018
17
+ author: 'Author',
18
+ };
19
+
20
+ export const VCS_HARDCODED_UNTRACKED_FILE_PATH = `file/path/${Math.random()}.mdx`;
21
+
22
+ /**
23
+ * This VCS implementation always returns hardcoded values for testing purposes.
24
+ * It is also useful in dev environments where VCS info is not important.
25
+ * Reading information from the VCS can be slow and is not always necessary.
26
+ */
27
+ export const VcsHardcoded: VcsConfig = {
28
+ initialize: () => {
29
+ // Noop
30
+ },
31
+
32
+ getFileCreationInfo: async (filePath: string) => {
33
+ if (filePath === VCS_HARDCODED_UNTRACKED_FILE_PATH) {
34
+ return null;
35
+ }
36
+ return VCS_HARDCODED_CREATION_INFO;
37
+ },
38
+
39
+ getFileLastUpdateInfo: async (filePath: string) => {
40
+ if (filePath === VCS_HARDCODED_UNTRACKED_FILE_PATH) {
41
+ return null;
42
+ }
43
+ return VCS_HARDCODED_LAST_UPDATE_INFO;
44
+ },
45
+ };
package/lib/cliUtils.d.ts DELETED
@@ -1,14 +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
- type PreferredLanguage = 'javascript' | 'typescript';
8
- type AskPreferredLanguageOptions = {
9
- fallback: PreferredLanguage | undefined;
10
- exit: boolean;
11
- };
12
- export declare function askPreferredLanguage(options?: Partial<AskPreferredLanguageOptions>): Promise<'javascript' | 'typescript'>;
13
- export {};
14
- //# sourceMappingURL=cliUtils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cliUtils.d.ts","sourceRoot":"","sources":["../src/cliUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,KAAK,iBAAiB,GAAG,YAAY,GAAG,YAAY,CAAC;AAErD,KAAK,2BAA2B,GAAG;IACjC,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AASF,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACjD,OAAO,CAAC,YAAY,GAAG,YAAY,CAAC,CAsCtC"}
package/lib/cliUtils.js DELETED
@@ -1,49 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Facebook, Inc. and its affiliates.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.askPreferredLanguage = askPreferredLanguage;
10
- const tslib_1 = require("tslib");
11
- const prompts_1 = tslib_1.__importDefault(require("prompts"));
12
- const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
- const DefaultOptions = {
14
- fallback: undefined,
15
- exit: false,
16
- };
17
- const ExitChoice = { title: logger_1.default.yellow('[Exit]'), value: '[Exit]' };
18
- async function askPreferredLanguage(options = {}) {
19
- const { fallback, exit } = { ...DefaultOptions, ...options };
20
- const choices = [
21
- { title: logger_1.default.bold('JavaScript'), value: 'javascript' },
22
- { title: logger_1.default.bold('TypeScript'), value: 'typescript' },
23
- ];
24
- if (exit) {
25
- choices.push(ExitChoice);
26
- }
27
- const { language } = await (0, prompts_1.default)({
28
- type: 'select',
29
- name: 'language',
30
- message: 'Which language do you want to use?',
31
- choices,
32
- }, {
33
- onCancel() {
34
- exit && process.exit(0);
35
- },
36
- });
37
- if (language === ExitChoice.value) {
38
- process.exit(0);
39
- }
40
- if (!language) {
41
- if (fallback) {
42
- logger_1.default.info `Falling back to language=${fallback}`;
43
- return fallback;
44
- }
45
- process.exit(0);
46
- }
47
- return language;
48
- }
49
- //# sourceMappingURL=cliUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cliUtils.js","sourceRoot":"","sources":["../src/cliUtils.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAmBH,oDAwCC;;AAzDD,8DAA6C;AAC7C,wEAAwC;AASxC,MAAM,cAAc,GAAgC;IAClD,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF,MAAM,UAAU,GAAW,EAAC,KAAK,EAAE,gBAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAC,CAAC;AAEtE,KAAK,UAAU,oBAAoB,CACxC,UAAgD,EAAE;IAElD,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAC,GAAG,EAAC,GAAG,cAAc,EAAE,GAAG,OAAO,EAAC,CAAC;IAEzD,MAAM,OAAO,GAAa;QACxB,EAAC,KAAK,EAAE,gBAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,YAAY,EAAC;QACvD,EAAC,KAAK,EAAE,gBAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,YAAY,EAAC;KACxD,CAAC;IACF,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,EAAC,QAAQ,EAAC,GAAG,MAAM,IAAA,iBAAO,EAC9B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,oCAAoC;QAC7C,OAAO;KACR,EACD;QACE,QAAQ;YACN,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;KACF,CACF,CAAC;IAEF,IAAI,QAAQ,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,QAAQ,EAAE,CAAC;YACb,gBAAM,CAAC,IAAI,CAAA,4BAA4B,QAAQ,EAAE,CAAC;YAClD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"gitUtils.d.ts","sourceRoot":"","sources":["../src/gitUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6CH,2DAA2D;AAC3D,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAE9C,uEAAuE;AACvE,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB;AACrC,iCAAiC;AACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IACJ;;;OAGG;IACH,GAAG,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,uEAAuE;IACvE,aAAa,CAAC,EAAE,KAAK,CAAC;CACvB,GACA,OAAO,CAAC;IACT,4BAA4B;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AACH;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB;AACrC,iCAAiC;AACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IACJ;;;OAGG;IACH,GAAG,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,aAAa,EAAE,IAAI,CAAC;CACrB,GACA,OAAO,CAAC;IACT,4BAA4B;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC"}
package/lib/gitUtils.js DELETED
@@ -1,103 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Facebook, Inc. and its affiliates.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.FileNotTrackedError = exports.GitNotFoundError = void 0;
10
- exports.getFileCommitDate = getFileCommitDate;
11
- const tslib_1 = require("tslib");
12
- const path_1 = tslib_1.__importDefault(require("path"));
13
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
14
- const os_1 = tslib_1.__importDefault(require("os"));
15
- const lodash_1 = tslib_1.__importDefault(require("lodash"));
16
- const execa_1 = tslib_1.__importDefault(require("execa"));
17
- const p_queue_1 = tslib_1.__importDefault(require("p-queue"));
18
- // Quite high/conservative concurrency value (it was previously "Infinity")
19
- // See https://github.com/facebook/docusaurus/pull/10915
20
- const DefaultGitCommandConcurrency =
21
- // TODO Docusaurus v4: bump node, availableParallelism() now always exists
22
- (typeof os_1.default.availableParallelism === 'function'
23
- ? os_1.default.availableParallelism()
24
- : os_1.default.cpus().length) * 4;
25
- const GitCommandConcurrencyEnv = process.env.DOCUSAURUS_GIT_COMMAND_CONCURRENCY
26
- ? parseInt(process.env.DOCUSAURUS_GIT_COMMAND_CONCURRENCY, 10)
27
- : undefined;
28
- const GitCommandConcurrency = GitCommandConcurrencyEnv && GitCommandConcurrencyEnv > 0
29
- ? GitCommandConcurrencyEnv
30
- : DefaultGitCommandConcurrency;
31
- // We use a queue to avoid running too many concurrent Git commands at once
32
- // See https://github.com/facebook/docusaurus/issues/10348
33
- const GitCommandQueue = new p_queue_1.default({
34
- concurrency: GitCommandConcurrency,
35
- });
36
- const realHasGitFn = () => {
37
- try {
38
- return execa_1.default.sync('git', ['--version']).exitCode === 0;
39
- }
40
- catch (error) {
41
- return false;
42
- }
43
- };
44
- // The hasGit call is synchronous IO so we memoize it
45
- // The user won't install Git in the middle of a build anyway...
46
- const hasGit = process.env.NODE_ENV === 'test' ? realHasGitFn : lodash_1.default.memoize(realHasGitFn);
47
- /** Custom error thrown when git is not found in `PATH`. */
48
- class GitNotFoundError extends Error {
49
- }
50
- exports.GitNotFoundError = GitNotFoundError;
51
- /** Custom error thrown when the current file is not tracked by git. */
52
- class FileNotTrackedError extends Error {
53
- }
54
- exports.FileNotTrackedError = FileNotTrackedError;
55
- async function getFileCommitDate(file, { age = 'oldest', includeAuthor = false, }) {
56
- if (!hasGit()) {
57
- throw new GitNotFoundError(`Failed to retrieve git history for "${file}" because git is not installed.`);
58
- }
59
- if (!(await fs_extra_1.default.pathExists(file))) {
60
- throw new Error(`Failed to retrieve git history for "${file}" because the file does not exist.`);
61
- }
62
- // We add a "RESULT:" prefix to make parsing easier
63
- // See why: https://github.com/facebook/docusaurus/pull/10022
64
- const resultFormat = includeAuthor ? 'RESULT:%ct,%an' : 'RESULT:%ct';
65
- const args = [
66
- `--format=${resultFormat}`,
67
- '--max-count=1',
68
- age === 'oldest' ? '--follow --diff-filter=A' : undefined,
69
- ]
70
- .filter(Boolean)
71
- .join(' ');
72
- const command = `git -c log.showSignature=false log ${args} -- "${path_1.default.basename(file)}"`;
73
- const result = (await GitCommandQueue.add(() => {
74
- return (0, execa_1.default)(command, {
75
- cwd: path_1.default.dirname(file),
76
- shell: true,
77
- });
78
- }));
79
- if (result.exitCode !== 0) {
80
- throw new Error(`Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}`);
81
- }
82
- // We only parse the output line starting with our "RESULT:" prefix
83
- // See why https://github.com/facebook/docusaurus/pull/10022
84
- const regex = includeAuthor
85
- ? /(?:^|\n)RESULT:(?<timestamp>\d+),(?<author>.+)(?:$|\n)/
86
- : /(?:^|\n)RESULT:(?<timestamp>\d+)(?:$|\n)/;
87
- const output = result.stdout.trim();
88
- if (!output) {
89
- throw new FileNotTrackedError(`Failed to retrieve the git history for file "${file}" because the file is not tracked by git.`);
90
- }
91
- const match = output.match(regex);
92
- if (!match) {
93
- throw new Error(`Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`);
94
- }
95
- const timestampInSeconds = Number(match.groups.timestamp);
96
- const timestamp = timestampInSeconds * 1000;
97
- const date = new Date(timestamp);
98
- if (includeAuthor) {
99
- return { date, timestamp, author: match.groups.author };
100
- }
101
- return { date, timestamp };
102
- }
103
- //# sourceMappingURL=gitUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gitUtils.js","sourceRoot":"","sources":["../src/gitUtils.ts"],"names":[],"mappings":"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"}
package/src/cliUtils.ts DELETED
@@ -1,65 +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
- import prompts, {type Choice} from 'prompts';
9
- import logger from '@docusaurus/logger';
10
-
11
- type PreferredLanguage = 'javascript' | 'typescript';
12
-
13
- type AskPreferredLanguageOptions = {
14
- fallback: PreferredLanguage | undefined;
15
- exit: boolean;
16
- };
17
-
18
- const DefaultOptions: AskPreferredLanguageOptions = {
19
- fallback: undefined,
20
- exit: false,
21
- };
22
-
23
- const ExitChoice: Choice = {title: logger.yellow('[Exit]'), value: '[Exit]'};
24
-
25
- export async function askPreferredLanguage(
26
- options: Partial<AskPreferredLanguageOptions> = {},
27
- ): Promise<'javascript' | 'typescript'> {
28
- const {fallback, exit} = {...DefaultOptions, ...options};
29
-
30
- const choices: Choice[] = [
31
- {title: logger.bold('JavaScript'), value: 'javascript'},
32
- {title: logger.bold('TypeScript'), value: 'typescript'},
33
- ];
34
- if (exit) {
35
- choices.push(ExitChoice);
36
- }
37
-
38
- const {language} = await prompts(
39
- {
40
- type: 'select',
41
- name: 'language',
42
- message: 'Which language do you want to use?',
43
- choices,
44
- },
45
- {
46
- onCancel() {
47
- exit && process.exit(0);
48
- },
49
- },
50
- );
51
-
52
- if (language === ExitChoice.value) {
53
- process.exit(0);
54
- }
55
-
56
- if (!language) {
57
- if (fallback) {
58
- logger.info`Falling back to language=${fallback}`;
59
- return fallback;
60
- }
61
- process.exit(0);
62
- }
63
-
64
- return language;
65
- }
package/src/gitUtils.ts DELETED
@@ -1,200 +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
- import path from 'path';
9
- import fs from 'fs-extra';
10
- import os from 'os';
11
- import _ from 'lodash';
12
- import execa from 'execa';
13
- import PQueue from 'p-queue';
14
-
15
- // Quite high/conservative concurrency value (it was previously "Infinity")
16
- // See https://github.com/facebook/docusaurus/pull/10915
17
- const DefaultGitCommandConcurrency =
18
- // TODO Docusaurus v4: bump node, availableParallelism() now always exists
19
- (typeof os.availableParallelism === 'function'
20
- ? os.availableParallelism()
21
- : os.cpus().length) * 4;
22
-
23
- const GitCommandConcurrencyEnv = process.env.DOCUSAURUS_GIT_COMMAND_CONCURRENCY
24
- ? parseInt(process.env.DOCUSAURUS_GIT_COMMAND_CONCURRENCY, 10)
25
- : undefined;
26
-
27
- const GitCommandConcurrency =
28
- GitCommandConcurrencyEnv && GitCommandConcurrencyEnv > 0
29
- ? GitCommandConcurrencyEnv
30
- : DefaultGitCommandConcurrency;
31
-
32
- // We use a queue to avoid running too many concurrent Git commands at once
33
- // See https://github.com/facebook/docusaurus/issues/10348
34
- const GitCommandQueue = new PQueue({
35
- concurrency: GitCommandConcurrency,
36
- });
37
-
38
- const realHasGitFn = () => {
39
- try {
40
- return execa.sync('git', ['--version']).exitCode === 0;
41
- } catch (error) {
42
- return false;
43
- }
44
- };
45
-
46
- // The hasGit call is synchronous IO so we memoize it
47
- // The user won't install Git in the middle of a build anyway...
48
- const hasGit =
49
- process.env.NODE_ENV === 'test' ? realHasGitFn : _.memoize(realHasGitFn);
50
-
51
- /** Custom error thrown when git is not found in `PATH`. */
52
- export class GitNotFoundError extends Error {}
53
-
54
- /** Custom error thrown when the current file is not tracked by git. */
55
- export class FileNotTrackedError extends Error {}
56
-
57
- /**
58
- * Fetches the git history of a file and returns a relevant commit date.
59
- * It gets the commit date instead of author date so that amended commits
60
- * can have their dates updated.
61
- *
62
- * @throws {@link GitNotFoundError} If git is not found in `PATH`.
63
- * @throws {@link FileNotTrackedError} If the current file is not tracked by git.
64
- * @throws Also throws when `git log` exited with non-zero, or when it outputs
65
- * unexpected text.
66
- */
67
- export async function getFileCommitDate(
68
- /** Absolute path to the file. */
69
- file: string,
70
- args: {
71
- /**
72
- * `"oldest"` is the commit that added the file, following renames;
73
- * `"newest"` is the last commit that edited the file.
74
- */
75
- age?: 'oldest' | 'newest';
76
- /** Use `includeAuthor: true` to get the author information as well. */
77
- includeAuthor?: false;
78
- },
79
- ): Promise<{
80
- /** Relevant commit date. */
81
- date: Date;
82
- /** Timestamp returned from git, converted to **milliseconds**. */
83
- timestamp: number;
84
- }>;
85
- /**
86
- * Fetches the git history of a file and returns a relevant commit date.
87
- * It gets the commit date instead of author date so that amended commits
88
- * can have their dates updated.
89
- *
90
- * @throws {@link GitNotFoundError} If git is not found in `PATH`.
91
- * @throws {@link FileNotTrackedError} If the current file is not tracked by git.
92
- * @throws Also throws when `git log` exited with non-zero, or when it outputs
93
- * unexpected text.
94
- */
95
- export async function getFileCommitDate(
96
- /** Absolute path to the file. */
97
- file: string,
98
- args: {
99
- /**
100
- * `"oldest"` is the commit that added the file, following renames;
101
- * `"newest"` is the last commit that edited the file.
102
- */
103
- age?: 'oldest' | 'newest';
104
- includeAuthor: true;
105
- },
106
- ): Promise<{
107
- /** Relevant commit date. */
108
- date: Date;
109
- /** Timestamp returned from git, converted to **milliseconds**. */
110
- timestamp: number;
111
- /** The author's name, as returned from git. */
112
- author: string;
113
- }>;
114
-
115
- export async function getFileCommitDate(
116
- file: string,
117
- {
118
- age = 'oldest',
119
- includeAuthor = false,
120
- }: {
121
- age?: 'oldest' | 'newest';
122
- includeAuthor?: boolean;
123
- },
124
- ): Promise<{
125
- date: Date;
126
- timestamp: number;
127
- author?: string;
128
- }> {
129
- if (!hasGit()) {
130
- throw new GitNotFoundError(
131
- `Failed to retrieve git history for "${file}" because git is not installed.`,
132
- );
133
- }
134
-
135
- if (!(await fs.pathExists(file))) {
136
- throw new Error(
137
- `Failed to retrieve git history for "${file}" because the file does not exist.`,
138
- );
139
- }
140
-
141
- // We add a "RESULT:" prefix to make parsing easier
142
- // See why: https://github.com/facebook/docusaurus/pull/10022
143
- const resultFormat = includeAuthor ? 'RESULT:%ct,%an' : 'RESULT:%ct';
144
-
145
- const args = [
146
- `--format=${resultFormat}`,
147
- '--max-count=1',
148
- age === 'oldest' ? '--follow --diff-filter=A' : undefined,
149
- ]
150
- .filter(Boolean)
151
- .join(' ');
152
-
153
- const command = `git -c log.showSignature=false log ${args} -- "${path.basename(
154
- file,
155
- )}"`;
156
-
157
- const result = (await GitCommandQueue.add(() => {
158
- return execa(command, {
159
- cwd: path.dirname(file),
160
- shell: true,
161
- });
162
- }))!;
163
-
164
- if (result.exitCode !== 0) {
165
- throw new Error(
166
- `Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}`,
167
- );
168
- }
169
-
170
- // We only parse the output line starting with our "RESULT:" prefix
171
- // See why https://github.com/facebook/docusaurus/pull/10022
172
- const regex = includeAuthor
173
- ? /(?:^|\n)RESULT:(?<timestamp>\d+),(?<author>.+)(?:$|\n)/
174
- : /(?:^|\n)RESULT:(?<timestamp>\d+)(?:$|\n)/;
175
-
176
- const output = result.stdout.trim();
177
-
178
- if (!output) {
179
- throw new FileNotTrackedError(
180
- `Failed to retrieve the git history for file "${file}" because the file is not tracked by git.`,
181
- );
182
- }
183
-
184
- const match = output.match(regex);
185
-
186
- if (!match) {
187
- throw new Error(
188
- `Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`,
189
- );
190
- }
191
-
192
- const timestampInSeconds = Number(match.groups!.timestamp);
193
- const timestamp = timestampInSeconds * 1_000;
194
- const date = new Date(timestamp);
195
-
196
- if (includeAuthor) {
197
- return {date, timestamp, author: match.groups!.author!};
198
- }
199
- return {date, timestamp};
200
- }