create-docusaurus 3.10.2 → 4.0.0-canary-6809

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,3 +54,32 @@ yarn typecheck
54
54
  yarn build
55
55
  yarn start
56
56
  ```
57
+
58
+ ### End-to-end tests
59
+
60
+ To run end-to-end tests similar to our CI workflows, publishing monorepo packages to a local Verdaccio repository inside Docker.
61
+
62
+ **Important**: this modifies `package.json` files before publish, so make sure to commit your work first!
63
+
64
+ ```bash
65
+ cd `git rev-parse --show-toplevel` # Back to repo root
66
+ pnpm install
67
+
68
+ docker rm -f verdaccio
69
+ pnpm test:build:website -st
70
+
71
+ cd ../test-website # website is generated outside of the monorepo
72
+
73
+ cat > pnpm-workspace.yaml <<'YAML'
74
+ strictDepBuilds: true
75
+ allowBuilds:
76
+ '@swc/core': false
77
+ core-js: false
78
+ YAML
79
+
80
+ pnpm_config_registry=http://localhost:4873 pnpm install
81
+
82
+ pnpm run typecheck
83
+ pnpm start --no-open
84
+ pnpm run build --locale en --locale fr
85
+ ```
package/bin/index.js CHANGED
@@ -15,7 +15,7 @@ import {logger} from '@docusaurus/logger';
15
15
  import semver from 'semver';
16
16
  import {program} from 'commander';
17
17
 
18
- const packageJson = /** @type {import("../package.json")} */ (
18
+ const packageJson = /** @type {typeof import("../package.json")} */ (
19
19
  createRequire(import.meta.url)('../package.json')
20
20
  );
21
21
  const requiredVersion = packageJson.engines.node;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type PackageManager, type Source } from './constants.js';
8
+ export declare function getAvailablePackageManagers(): Promise<PackageManager[]>;
9
+ export declare function runPackageManagerInstallCommand(pkgManager: PackageManager): Promise<boolean>;
10
+ export declare function runGitCloneCommand(source: Source & {
11
+ type: 'git';
12
+ }, dest: string): Promise<boolean>;
@@ -0,0 +1,76 @@
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
+ // We use cross-spawn instead of spawn because of Windows compatibility issues.
8
+ // For example, "yarn" doesn't work on Windows, it requires "yarn.cmd"
9
+ import crossSpawn from 'cross-spawn';
10
+ import supportsColor from 'supports-color';
11
+ import { PackageManagers, } from './constants.js';
12
+ import { askForCustomGitCloneCommand } from './prompts.js';
13
+ /**
14
+ * Run a command, similar to execa(cmd,args) but simpler
15
+ * @param command
16
+ * @param args
17
+ * @param options
18
+ * @returns the command exit code
19
+ */
20
+ async function runCommand(command, args = [], options = {}) {
21
+ // This does something similar to execa.command()
22
+ // we split a string command (with optional args) into command+args
23
+ // this way it's compatible with spawn()
24
+ const [realCommand, ...baseArgs] = command.split(' ');
25
+ const allArgs = [...baseArgs, ...args];
26
+ if (!realCommand) {
27
+ throw new Error(`Invalid command: ${command}`);
28
+ }
29
+ return new Promise((resolve, reject) => {
30
+ const p = crossSpawn(realCommand, allArgs, { stdio: 'ignore', ...options });
31
+ p.on('error', reject);
32
+ p.on('close', (exitCode) => exitCode !== null
33
+ ? resolve(exitCode)
34
+ : reject(new Error(`No exit code for command ${command}`)));
35
+ });
36
+ }
37
+ async function hasPackageManager(packageManager) {
38
+ return (await runCommand(packageManager, ['--version'])) === 0;
39
+ }
40
+ export async function getAvailablePackageManagers() {
41
+ const list = await Promise.all(PackageManagers.map(async (name) => {
42
+ return (await hasPackageManager(name)) ? name : null;
43
+ }));
44
+ return list.filter((item) => item !== null);
45
+ }
46
+ export async function runPackageManagerInstallCommand(pkgManager) {
47
+ const installCommand = pkgManager === 'yarn'
48
+ ? 'yarn'
49
+ : pkgManager === 'bun'
50
+ ? 'bun install'
51
+ : `${pkgManager} install --color always`;
52
+ return ((await runCommand(installCommand, [], {
53
+ env: {
54
+ ...process.env,
55
+ // Force coloring the output
56
+ ...(supportsColor.stdout ? { FORCE_COLOR: '1' } : {}),
57
+ },
58
+ })) === 0);
59
+ }
60
+ async function getGitCloneCommand(gitStrategy) {
61
+ switch (gitStrategy) {
62
+ case 'shallow':
63
+ case 'copy':
64
+ return 'git clone --recursive --depth 1';
65
+ case 'custom': {
66
+ return askForCustomGitCloneCommand();
67
+ }
68
+ case 'deep':
69
+ default:
70
+ return 'git clone';
71
+ }
72
+ }
73
+ export async function runGitCloneCommand(source, dest) {
74
+ const gitCommand = await getGitCloneCommand(source.strategy);
75
+ return (await runCommand(gitCommand, [source.url, dest])) === 0;
76
+ }
@@ -0,0 +1,34 @@
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
+ export declare const DefaultPackageManager = "npm";
8
+ export declare const LockfileNames: {
9
+ npm: string;
10
+ yarn: string;
11
+ pnpm: string;
12
+ bun: string;
13
+ };
14
+ export type PackageManager = keyof typeof LockfileNames;
15
+ export declare const PackageManagers: PackageManager[];
16
+ export declare const GitCloneStrategies: readonly ['deep', 'shallow', 'copy', 'custom'];
17
+ export type GitCloneStrategy = (typeof GitCloneStrategies)[number];
18
+ export type Template = {
19
+ name: string;
20
+ path: string;
21
+ tsVariantPath: string | undefined;
22
+ };
23
+ export type Source = {
24
+ type: 'template';
25
+ template: Template;
26
+ language: 'javascript' | 'typescript';
27
+ } | {
28
+ type: 'git';
29
+ url: string;
30
+ strategy: GitCloneStrategy;
31
+ } | {
32
+ type: 'local';
33
+ path: string;
34
+ };
@@ -0,0 +1,23 @@
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
+ // Only used in the rare, rare case of running globally installed create +
8
+ // using --skip-install. We need a default name to show the tip text
9
+ export const DefaultPackageManager = 'npm';
10
+ // Order matters
11
+ export const LockfileNames = {
12
+ npm: 'package-lock.json',
13
+ yarn: 'yarn.lock',
14
+ pnpm: 'pnpm-lock.yaml',
15
+ bun: 'bun.lockb',
16
+ };
17
+ export const PackageManagers = Object.keys(LockfileNames);
18
+ export const GitCloneStrategies = [
19
+ 'deep',
20
+ 'shallow',
21
+ 'copy',
22
+ 'custom',
23
+ ];
package/lib/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
+ import { type PackageManager, type GitCloneStrategy } from './constants.js';
7
8
  type LanguagesOptions = {
8
9
  javascript?: boolean;
9
10
  typescript?: boolean;
@@ -11,16 +12,7 @@ type LanguagesOptions = {
11
12
  type CLIOptions = LanguagesOptions & {
12
13
  packageManager?: PackageManager;
13
14
  skipInstall?: boolean;
14
- gitStrategy?: GitStrategy;
15
+ gitStrategy?: GitCloneStrategy;
15
16
  };
16
- declare const lockfileNames: {
17
- npm: string;
18
- yarn: string;
19
- pnpm: string;
20
- bun: string;
21
- };
22
- type PackageManager = keyof typeof lockfileNames;
23
- declare const gitStrategies: readonly ["deep", "shallow", "copy", "custom"];
24
- type GitStrategy = (typeof gitStrategies)[number];
25
17
  export default function init(rootDir: string, reqName?: string, reqTemplate?: string, cliOptions?: CLIOptions): Promise<void>;
26
18
  export {};
package/lib/index.js CHANGED
@@ -12,8 +12,9 @@ import path from 'node:path';
12
12
  // TODO try to remove these third-party dependencies if possible
13
13
  import { logger } from '@docusaurus/logger';
14
14
  import prompts from 'prompts';
15
- import supportsColor from 'supports-color';
16
- import { runCommand, siteNameToPackageName } from './utils.js';
15
+ import { LockfileNames, PackageManagers, DefaultPackageManager, GitCloneStrategies, } from './constants.js';
16
+ import { getAvailablePackageManagers, runGitCloneCommand, runPackageManagerInstallCommand, } from './commands.js';
17
+ import { siteNameToPackageName, updatePkg, pathExists, printPackageManagerHelp, } from './utils.js';
17
18
  import { askPreferredLanguage } from './prompts.js';
18
19
  async function getLanguage(options) {
19
20
  if (options.typescript) {
@@ -24,25 +25,9 @@ async function getLanguage(options) {
24
25
  }
25
26
  return askPreferredLanguage();
26
27
  }
27
- // Only used in the rare, rare case of running globally installed create +
28
- // using --skip-install. We need a default name to show the tip text
29
- const defaultPackageManager = 'npm';
30
- const lockfileNames = {
31
- npm: 'package-lock.json',
32
- yarn: 'yarn.lock',
33
- pnpm: 'pnpm-lock.yaml',
34
- bun: 'bun.lockb',
35
- };
36
- const packageManagers = Object.keys(lockfileNames);
37
- function pathExists(filePath) {
38
- return fs
39
- .access(filePath, fs.constants.F_OK)
40
- .then(() => true)
41
- .catch(() => false);
42
- }
43
28
  async function findPackageManagerFromLockFile(rootDir) {
44
- for (const packageManager of packageManagers) {
45
- const lockFilePath = path.join(rootDir, lockfileNames[packageManager]);
29
+ for (const packageManager of PackageManagers) {
30
+ const lockFilePath = path.join(rootDir, LockfileNames[packageManager]);
46
31
  if (await pathExists(lockFilePath)) {
47
32
  return packageManager;
48
33
  }
@@ -50,18 +35,18 @@ async function findPackageManagerFromLockFile(rootDir) {
50
35
  return undefined;
51
36
  }
52
37
  function findPackageManagerFromUserAgent() {
53
- return packageManagers.find((packageManager) => process.env.npm_config_user_agent?.startsWith(packageManager));
38
+ return PackageManagers.find((packageManager) => process.env.npm_config_user_agent?.startsWith(packageManager));
54
39
  }
55
40
  async function askForPackageManagerChoice() {
56
- const hasYarn = (await runCommand('yarn --version')) === 0;
57
- const hasPnpm = (await runCommand('pnpm --version')) === 0;
58
- const hasBun = (await runCommand('bun --version')) === 0;
59
- if (!hasYarn && !hasPnpm && !hasBun) {
60
- return 'npm';
41
+ const packageManagers = await getAvailablePackageManagers();
42
+ if (packageManagers.length === 0) {
43
+ logger.warn `No package maintainer available? Trying with name=${DefaultPackageManager}`;
44
+ return DefaultPackageManager;
45
+ }
46
+ if (packageManagers.length === 1) {
47
+ return packageManagers[0];
61
48
  }
62
- const choices = ['npm', hasYarn && 'yarn', hasPnpm && 'pnpm', hasBun && 'bun']
63
- .filter((p) => Boolean(p))
64
- .map((p) => ({ title: p, value: p }));
49
+ const choices = packageManagers.map((p) => ({ title: p, value: p }));
65
50
  return ((await prompts({
66
51
  type: 'select',
67
52
  name: 'packageManager',
@@ -69,13 +54,13 @@ async function askForPackageManagerChoice() {
69
54
  choices,
70
55
  }, {
71
56
  onCancel() {
72
- logger.info `Falling back to name=${defaultPackageManager}`;
57
+ logger.info `Falling back to name=${DefaultPackageManager}`;
73
58
  },
74
- })).packageManager ?? defaultPackageManager);
59
+ })).packageManager ?? DefaultPackageManager);
75
60
  }
76
61
  async function getPackageManager(dest, { packageManager, skipInstall }) {
77
- if (packageManager && !packageManagers.includes(packageManager)) {
78
- throw new Error(`Invalid package manager choice ${packageManager}. Must be one of ${packageManagers.join(', ')}`);
62
+ if (packageManager && !PackageManagers.includes(packageManager)) {
63
+ throw new Error(`Invalid package manager choice ${packageManager}. Must be one of ${PackageManagers.join(', ')}`);
79
64
  }
80
65
  return (
81
66
  // If dest already contains a lockfile (e.g. if using a local template), we
@@ -85,7 +70,7 @@ async function getPackageManager(dest, { packageManager, skipInstall }) {
85
70
  (await findPackageManagerFromLockFile('.')) ??
86
71
  findPackageManagerFromUserAgent() ??
87
72
  // This only happens if the user has a global installation in PATH
88
- (skipInstall ? defaultPackageManager : askForPackageManagerChoice()));
73
+ (skipInstall ? DefaultPackageManager : await askForPackageManagerChoice()));
89
74
  }
90
75
  const recommendedTemplate = 'classic';
91
76
  const typeScriptTemplateSuffix = '-typescript';
@@ -164,29 +149,6 @@ async function askTemplateChoice({ templates, cliOptions, }) {
164
149
  function isValidGitRepoUrl(gitRepoUrl) {
165
150
  return ['https://', 'git@'].some((item) => gitRepoUrl.startsWith(item));
166
151
  }
167
- const gitStrategies = ['deep', 'shallow', 'copy', 'custom'];
168
- async function getGitCommand(gitStrategy) {
169
- switch (gitStrategy) {
170
- case 'shallow':
171
- case 'copy':
172
- return 'git clone --recursive --depth 1';
173
- case 'custom': {
174
- const { command } = (await prompts({
175
- type: 'text',
176
- name: 'command',
177
- message: 'Write your own git clone command. The repository URL and destination directory will be supplied. E.g. "git clone --depth 10"',
178
- }, {
179
- onCancel() {
180
- logger.info `Falling back to code=${'git clone'}`;
181
- },
182
- }));
183
- return command ?? 'git clone';
184
- }
185
- case 'deep':
186
- default:
187
- return 'git clone';
188
- }
189
- }
190
152
  async function getSiteName(reqName, rootDir) {
191
153
  async function validateSiteName(siteName) {
192
154
  if (!siteName) {
@@ -246,8 +208,8 @@ async function getTemplateSource({ templateName, templates, cliOptions, }) {
246
208
  async function getUserProvidedSource({ reqTemplate, templates, cliOptions, }) {
247
209
  if (isValidGitRepoUrl(reqTemplate)) {
248
210
  if (cliOptions.gitStrategy &&
249
- !gitStrategies.includes(cliOptions.gitStrategy)) {
250
- logger.error `Invalid git strategy: name=${cliOptions.gitStrategy}. Value must be one of ${gitStrategies.join(', ')}.`;
211
+ !GitCloneStrategies.includes(cliOptions.gitStrategy)) {
212
+ logger.error `Invalid git strategy: name=${cliOptions.gitStrategy}. Value must be one of ${GitCloneStrategies.join(', ')}.`;
251
213
  process.exit(1);
252
214
  }
253
215
  return {
@@ -358,12 +320,6 @@ async function getSource(reqTemplate, templates, cliOptions) {
358
320
  cliOptions,
359
321
  });
360
322
  }
361
- async function updatePkg(pkgPath, obj) {
362
- const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
363
- const newPkg = Object.assign(pkg, obj);
364
- await fs.mkdir(path.dirname(pkgPath), { recursive: true });
365
- await fs.writeFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`);
366
- }
367
323
  export default async function init(rootDir, reqName, reqTemplate, cliOptions = {}) {
368
324
  const [templates, siteName] = await Promise.all([
369
325
  readTemplates(),
@@ -373,8 +329,7 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
373
329
  const source = await getSource(reqTemplate, templates, cliOptions);
374
330
  logger.info('Creating new Docusaurus project...');
375
331
  if (source.type === 'git') {
376
- const gitCommand = await getGitCommand(source.strategy);
377
- if ((await runCommand(gitCommand, [source.url, dest])) !== 0) {
332
+ if (!(await runGitCloneCommand(source, dest))) {
378
333
  logger.error `Cloning Git template failed!`;
379
334
  process.exit(1);
380
335
  }
@@ -427,17 +382,7 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
427
382
  process.chdir(dest);
428
383
  logger.info `Installing dependencies with name=${pkgManager}...`;
429
384
  // ...
430
- if ((await runCommand(pkgManager === 'yarn'
431
- ? 'yarn'
432
- : pkgManager === 'bun'
433
- ? 'bun install'
434
- : `${pkgManager} install --color always`, [], {
435
- env: {
436
- ...process.env,
437
- // Force coloring the output
438
- ...(supportsColor.stdout ? { FORCE_COLOR: '1' } : {}),
439
- },
440
- })) !== 0) {
385
+ if (!(await runPackageManagerInstallCommand(pkgManager))) {
441
386
  logger.error('Dependency installation failed.');
442
387
  logger.info `The site directory has already been created, and you can retry by typing:
443
388
 
@@ -446,29 +391,5 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
446
391
  process.exit(0);
447
392
  }
448
393
  }
449
- const useNpm = pkgManager === 'npm';
450
- const useBun = pkgManager === 'bun';
451
- const useRunCommand = useNpm || useBun;
452
- logger.success `Created name=${cdpath}.`;
453
- logger.info `Inside that directory, you can run several commands:
454
-
455
- code=${`${pkgManager} start`}
456
- Starts the development server.
457
-
458
- code=${`${pkgManager} ${useRunCommand ? 'run ' : ''}build`}
459
- Bundles your website into static files for production.
460
-
461
- code=${`${pkgManager} ${useRunCommand ? 'run ' : ''}serve`}
462
- Serves the built website locally.
463
-
464
- code=${`${pkgManager} ${useRunCommand ? 'run ' : ''}deploy`}
465
- Publishes the website to GitHub pages.
466
-
467
- We recommend that you begin by typing:
468
-
469
- code=${`cd ${cdpath}`}
470
- code=${`${pkgManager} start`}
471
-
472
- Happy building awesome websites!
473
- `;
394
+ printPackageManagerHelp({ pkgManager, cdpath });
474
395
  }
package/lib/prompts.d.ts CHANGED
@@ -5,3 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  export declare function askPreferredLanguage(): Promise<'javascript' | 'typescript'>;
8
+ export declare function askForCustomGitCloneCommand(): Promise<string>;
package/lib/prompts.js CHANGED
@@ -21,3 +21,15 @@ export async function askPreferredLanguage() {
21
21
  }
22
22
  return language;
23
23
  }
24
+ export async function askForCustomGitCloneCommand() {
25
+ const { command } = (await prompts({
26
+ type: 'text',
27
+ name: 'command',
28
+ message: 'Write your own git clone command. The repository URL and destination directory will be supplied. E.g. "git clone --depth 10"',
29
+ }, {
30
+ onCancel() {
31
+ logger.info `Falling back to code=${'git clone'}`;
32
+ },
33
+ }));
34
+ return command ?? 'git clone';
35
+ }
package/lib/utils.d.ts CHANGED
@@ -4,15 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import type { SpawnOptions } from 'node:child_process';
8
- /**
9
- * Run a command, similar to execa(cmd,args) but simpler
10
- * @param command
11
- * @param args
12
- * @param options
13
- * @returns the command exit code
14
- */
15
- export declare function runCommand(command: string, args?: string[], options?: SpawnOptions): Promise<number>;
7
+ import { type PackageManager } from './constants.js';
16
8
  /**
17
9
  * We use a simple kebab-case-like conversion
18
10
  * It's not perfect, but good enough
@@ -21,3 +13,11 @@ export declare function runCommand(command: string, args?: string[], options?: S
21
13
  * @param siteName
22
14
  */
23
15
  export declare function siteNameToPackageName(siteName: string): string;
16
+ export declare function updatePkg(pkgPath: string, obj: {
17
+ [key: string]: unknown;
18
+ }): Promise<void>;
19
+ export declare function pathExists(filePath: string): Promise<boolean>;
20
+ export declare function printPackageManagerHelp({ pkgManager, cdpath, }: {
21
+ pkgManager: PackageManager;
22
+ cdpath: string;
23
+ }): void;
package/lib/utils.js CHANGED
@@ -4,36 +4,9 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- // @ts-expect-error: no types, but same as spawn()
8
- import CrossSpawn from 'cross-spawn';
9
- // We use cross-spawn instead of spawn because of Windows compatibility issues.
10
- // For example, "yarn" doesn't work on Windows, it requires "yarn.cmd"
11
- // Tools like execa() use cross-spawn under the hood, and "resolve" the command
12
- const crossSpawn = CrossSpawn;
13
- /**
14
- * Run a command, similar to execa(cmd,args) but simpler
15
- * @param command
16
- * @param args
17
- * @param options
18
- * @returns the command exit code
19
- */
20
- export async function runCommand(command, args = [], options = {}) {
21
- // This does something similar to execa.command()
22
- // we split a string command (with optional args) into command+args
23
- // this way it's compatible with spawn()
24
- const [realCommand, ...baseArgs] = command.split(' ');
25
- const allArgs = [...baseArgs, ...args];
26
- if (!realCommand) {
27
- throw new Error(`Invalid command: ${command}`);
28
- }
29
- return new Promise((resolve, reject) => {
30
- const p = crossSpawn(realCommand, allArgs, { stdio: 'ignore', ...options });
31
- p.on('error', reject);
32
- p.on('close', (exitCode) => exitCode !== null
33
- ? resolve(exitCode)
34
- : reject(new Error(`No exit code for command ${command}`)));
35
- });
36
- }
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+ import { logger } from '@docusaurus/logger';
37
10
  /**
38
11
  * We use a simple kebab-case-like conversion
39
12
  * It's not perfect, but good enough
@@ -48,3 +21,43 @@ export function siteNameToPackageName(siteName) {
48
21
  }
49
22
  return siteName;
50
23
  }
24
+ export async function updatePkg(pkgPath, obj) {
25
+ const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
26
+ const newPkg = Object.assign(pkg, obj);
27
+ await fs.mkdir(path.dirname(pkgPath), { recursive: true });
28
+ await fs.writeFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`);
29
+ }
30
+ // No need for fs-extra dependency
31
+ export async function pathExists(filePath) {
32
+ return fs
33
+ .access(filePath, fs.constants.F_OK)
34
+ .then(() => true)
35
+ .catch(() => false);
36
+ }
37
+ export function printPackageManagerHelp({ pkgManager, cdpath, }) {
38
+ const useNpm = pkgManager === 'npm';
39
+ const useBun = pkgManager === 'bun';
40
+ const run = useNpm || useBun ? 'run ' : '';
41
+ logger.success `Created name=${cdpath}.`;
42
+ logger.info `Inside that directory, you can run several commands:
43
+
44
+ code=${`${pkgManager} start`}
45
+ Starts the development server.
46
+
47
+ code=${`${pkgManager} ${run}build`}
48
+ Bundles your website into static files for production.
49
+
50
+ code=${`${pkgManager} ${run}serve`}
51
+ Serves the built website locally.
52
+
53
+ code=${`${pkgManager} ${run}deploy`}
54
+ Publishes the website to GitHub pages.
55
+
56
+ We recommend that you begin by typing:
57
+
58
+ code=${`cd ${cdpath}`}
59
+ code=${`${pkgManager} start`}
60
+
61
+ Happy building awesome websites!
62
+ `;
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-docusaurus",
3
- "version": "3.10.2",
3
+ "version": "4.0.0-canary-6809",
4
4
  "description": "Create Docusaurus apps easily.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -22,19 +22,20 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@docusaurus/logger": "3.10.2",
25
+ "@docusaurus/logger": "4.0.0-canary-6809",
26
26
  "commander": "^5.1.0",
27
- "cross-spawn": "^7.0.0",
27
+ "cross-spawn": "^7.0.6",
28
28
  "prompts": "^2.4.2",
29
- "semver": "^7.5.4",
30
- "supports-color": "^9.4.0",
31
- "tslib": "^2.6.0"
29
+ "semver": "^7.8.5",
30
+ "supports-color": "^10.2.2",
31
+ "tslib": "^2.8.1"
32
32
  },
33
33
  "devDependencies": {
34
- "@types/supports-color": "^8.1.1"
34
+ "@types/cross-spawn": "^6.0.6",
35
+ "@types/supports-color": "^10.0.0"
35
36
  },
36
37
  "engines": {
37
- "node": ">=20.0"
38
+ "node": ">=24.14"
38
39
  },
39
- "gitHead": "f37f9035584917a97a260b91fc2842cba4f8b94f"
40
+ "gitHead": "db942b07f3529b5359bcae27ab3796cb07dec10e"
40
41
  }
@@ -4,5 +4,5 @@ Official templates provided by Docusaurus. They are designed to be selected when
4
4
 
5
5
  ## Guide to Test Templates for Developer
6
6
 
7
- 1. `yarn install` in the root of the repo (one level above this directory).
8
- 1. Go to any template's directory, example: `cd classic && yarn start`.
7
+ 1. `pnpm install` in the root of the repo (one level above this directory).
8
+ 1. Go to any template's directory, example: `cd classic && pnpm start`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-template",
3
- "version": "3.10.2",
3
+ "version": "4.0.0-canary-6809",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -14,18 +14,18 @@
14
14
  "write-heading-ids": "docusaurus write-heading-ids"
15
15
  },
16
16
  "dependencies": {
17
- "@docusaurus/core": "3.10.2",
18
- "@docusaurus/faster": "3.10.2",
19
- "@docusaurus/preset-classic": "3.10.2",
20
- "@mdx-js/react": "^3.0.0",
21
- "clsx": "^2.0.0",
22
- "prism-react-renderer": "^2.3.0",
23
- "react": "^19.0.0",
24
- "react-dom": "^19.0.0"
17
+ "@docusaurus/core": "4.0.0-canary-6809",
18
+ "@docusaurus/faster": "4.0.0-canary-6809",
19
+ "@docusaurus/preset-classic": "4.0.0-canary-6809",
20
+ "@mdx-js/react": "^3.1.1",
21
+ "clsx": "^2.1.1",
22
+ "prism-react-renderer": "^2.4.1",
23
+ "react": "^19.3.0",
24
+ "react-dom": "^19.3.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@docusaurus/module-type-aliases": "3.10.2",
28
- "@docusaurus/types": "3.10.2"
27
+ "@docusaurus/module-type-aliases": "4.0.0-canary-6809",
28
+ "@docusaurus/types": "4.0.0-canary-6809"
29
29
  },
30
30
  "browserslist": {
31
31
  "production": [
@@ -40,6 +40,6 @@
40
40
  ]
41
41
  },
42
42
  "engines": {
43
- "node": ">=20.0"
43
+ "node": ">=24.14"
44
44
  }
45
45
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-typescript-template",
3
- "version": "3.10.2",
3
+ "version": "4.0.0-canary-6809",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -15,21 +15,21 @@
15
15
  "typecheck": "tsc"
16
16
  },
17
17
  "dependencies": {
18
- "@docusaurus/core": "3.10.2",
19
- "@docusaurus/faster": "3.10.2",
20
- "@docusaurus/preset-classic": "3.10.2",
21
- "@mdx-js/react": "^3.0.0",
22
- "clsx": "^2.0.0",
23
- "prism-react-renderer": "^2.3.0",
24
- "react": "^19.0.0",
25
- "react-dom": "^19.0.0"
18
+ "@docusaurus/core": "4.0.0-canary-6809",
19
+ "@docusaurus/faster": "4.0.0-canary-6809",
20
+ "@docusaurus/preset-classic": "4.0.0-canary-6809",
21
+ "@mdx-js/react": "^3.1.1",
22
+ "clsx": "^2.1.1",
23
+ "prism-react-renderer": "^2.4.1",
24
+ "react": "^19.3.0",
25
+ "react-dom": "^19.3.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@docusaurus/module-type-aliases": "3.10.2",
29
- "@docusaurus/tsconfig": "3.10.2",
30
- "@docusaurus/types": "3.10.2",
31
- "@types/react": "^19.0.0",
32
- "typescript": "~6.0.2"
28
+ "@docusaurus/module-type-aliases": "4.0.0-canary-6809",
29
+ "@docusaurus/tsconfig": "4.0.0-canary-6809",
30
+ "@docusaurus/types": "4.0.0-canary-6809",
31
+ "@types/react": "^19.3.0",
32
+ "typescript": "~7.0.2"
33
33
  },
34
34
  "browserslist": {
35
35
  "production": [
@@ -44,6 +44,6 @@
44
44
  ]
45
45
  },
46
46
  "engines": {
47
- "node": ">=20.0"
47
+ "node": ">=24.14"
48
48
  }
49
49
  }
@@ -1,12 +1,7 @@
1
1
  // This file is not used by "docusaurus start/build" commands.
2
- // It is here to improve your IDE experience (type-checking, autocompletion...),
3
- // and can also run the package.json "typecheck" script manually.
2
+ // It helps improve your IDE experience (type-checking, autocompletion...),
3
+ // You can also run the package.json "typecheck" script manually.
4
+ // Our base config is often good enough, but feel free to customize it!
4
5
  {
5
- "extends": "@docusaurus/tsconfig",
6
- "compilerOptions": {
7
- "baseUrl": ".",
8
- "ignoreDeprecations": "6.0",
9
- "strict": true
10
- },
11
- "exclude": [".docusaurus", "build"]
6
+ "extends": "@docusaurus/tsconfig"
12
7
  }
@@ -14,7 +14,7 @@ Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new
14
14
 
15
15
  ### What you'll need
16
16
 
17
- - [Node.js](https://nodejs.org/en/download/) version 20.0 or above:
17
+ - [Node.js](https://nodejs.org/en/download/) version 24.14 or above:
18
18
  - When installing Node.js, you are recommended to check all checkboxes related to dependencies.
19
19
 
20
20
  ## Generate a new site
package/lib/types.d.ts DELETED
@@ -1,7 +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
- export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
package/lib/types.js DELETED
@@ -1,7 +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
- export {};