create-docusaurus 3.1.1 → 3.2.1

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
@@ -25,7 +25,7 @@ For Docusaurus maintainers, templates can be tested with:
25
25
  ```bash
26
26
  cd `git rev-parse --show-toplevel` # Back to repo root
27
27
  rm -rf test-website
28
- yarn create-docusaurus test-website classic
28
+ yarn create-docusaurus test-website classic --javascript
29
29
  cd test-website
30
30
  yarn start
31
31
  ```
@@ -37,7 +37,7 @@ Use the following to test the templates against local packages:
37
37
  ```bash
38
38
  cd `git rev-parse --show-toplevel` # Back to repo root
39
39
  rm -rf test-website-in-workspace
40
- yarn create-docusaurus test-website-in-workspace classic
40
+ yarn create-docusaurus test-website-in-workspace classic --javascript
41
41
  cd test-website-in-workspace
42
42
  yarn build
43
43
  yarn start
package/bin/index.js CHANGED
@@ -38,6 +38,7 @@ program
38
38
  'Do not run package manager immediately after scaffolding',
39
39
  )
40
40
  .option('-t, --typescript', 'Use the TypeScript template variant')
41
+ .option('-j, --javascript', 'Use the JavaScript template variant')
41
42
  .option(
42
43
  '-g, --git-strategy <strategy>',
43
44
  `Only used if the template is a git repository.
package/lib/index.d.ts CHANGED
@@ -4,10 +4,13 @@
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
- type CLIOptions = {
7
+ type LanguagesOptions = {
8
+ javascript?: boolean;
9
+ typescript?: boolean;
10
+ };
11
+ type CLIOptions = LanguagesOptions & {
8
12
  packageManager?: PackageManager;
9
13
  skipInstall?: boolean;
10
- typescript?: boolean;
11
14
  gitStrategy?: GitStrategy;
12
15
  };
13
16
  declare const lockfileNames: {
package/lib/index.js CHANGED
@@ -12,7 +12,16 @@ import logger from '@docusaurus/logger';
12
12
  import shell from 'shelljs';
13
13
  import prompts from 'prompts';
14
14
  import supportsColor from 'supports-color';
15
- import { escapeShellArg } from '@docusaurus/utils';
15
+ import { escapeShellArg, askPreferredLanguage } from '@docusaurus/utils';
16
+ async function getLanguage(options) {
17
+ if (options.typescript) {
18
+ return 'typescript';
19
+ }
20
+ if (options.javascript) {
21
+ return 'javascript';
22
+ }
23
+ return askPreferredLanguage();
24
+ }
16
25
  // Only used in the rare, rare case of running globally installed create +
17
26
  // using --skip-install. We need a default name to show the tip text
18
27
  const defaultPackageManager = 'npm';
@@ -93,9 +102,10 @@ async function readTemplates() {
93
102
  // Classic should be first in list!
94
103
  return _.sortBy(templates, (t) => t.name !== recommendedTemplate);
95
104
  }
96
- async function copyTemplate(template, dest, typescript) {
105
+ async function copyTemplate(template, dest, language) {
97
106
  await fs.copy(path.join(templatesDir, 'shared'), dest);
98
- await fs.copy(typescript ? template.tsVariantPath : template.path, dest, {
107
+ const sourcePath = language === 'typescript' ? template.tsVariantPath : template.path;
108
+ await fs.copy(sourcePath, dest, {
99
109
  // Symlinks don't exist in published npm packages anymore, so this is only
100
110
  // to prevent errors during local testing
101
111
  filter: async (filePath) => !(await fs.lstat(filePath)).isSymbolicLink(),
@@ -117,6 +127,21 @@ function createTemplateChoices(templates) {
117
127
  makeNameAndValueChoice('Local template'),
118
128
  ];
119
129
  }
130
+ async function askTemplateChoice({ templates, cliOptions, }) {
131
+ return cliOptions.gitStrategy
132
+ ? 'Git repository'
133
+ : (await prompts({
134
+ type: 'select',
135
+ name: 'template',
136
+ message: 'Select a template below...',
137
+ choices: createTemplateChoices(templates),
138
+ }, {
139
+ onCancel() {
140
+ logger.error('A choice is required.');
141
+ process.exit(1);
142
+ },
143
+ })).template;
144
+ }
120
145
  function isValidGitRepoUrl(gitRepoUrl) {
121
146
  return ['https://', 'git@'].some((item) => gitRepoUrl.startsWith(item));
122
147
  }
@@ -175,143 +200,142 @@ async function getSiteName(reqName, rootDir) {
175
200
  }));
176
201
  return siteName;
177
202
  }
178
- async function getSource(reqTemplate, templates, cliOptions) {
179
- if (reqTemplate) {
180
- if (isValidGitRepoUrl(reqTemplate)) {
181
- if (cliOptions.gitStrategy &&
182
- !gitStrategies.includes(cliOptions.gitStrategy)) {
183
- logger.error `Invalid git strategy: name=${cliOptions.gitStrategy}. Value must be one of ${gitStrategies.join(', ')}.`;
184
- process.exit(1);
185
- }
186
- return {
187
- type: 'git',
188
- url: reqTemplate,
189
- strategy: cliOptions.gitStrategy ?? 'deep',
190
- };
191
- }
192
- else if (await fs.pathExists(path.resolve(reqTemplate))) {
193
- return {
194
- type: 'local',
195
- path: path.resolve(reqTemplate),
196
- };
197
- }
198
- const template = templates.find((t) => t.name === reqTemplate);
199
- if (!template) {
200
- logger.error('Invalid template.');
201
- process.exit(1);
202
- }
203
- if (cliOptions.typescript && !template.tsVariantPath) {
204
- logger.error `Template name=${reqTemplate} doesn't provide the TypeScript variant.`;
203
+ async function createTemplateSource({ template, cliOptions, }) {
204
+ const language = await getLanguage(cliOptions);
205
+ if (language === 'typescript' && !template.tsVariantPath) {
206
+ logger.error `Template name=${template.name} doesn't provide a TypeScript variant.`;
207
+ process.exit(1);
208
+ }
209
+ return {
210
+ type: 'template',
211
+ template,
212
+ language,
213
+ };
214
+ }
215
+ async function getTemplateSource({ templateName, templates, cliOptions, }) {
216
+ const template = templates.find((t) => t.name === templateName);
217
+ if (!template) {
218
+ logger.error('Invalid template.');
219
+ process.exit(1);
220
+ }
221
+ return createTemplateSource({ template, cliOptions });
222
+ }
223
+ // Get the template source explicitly requested by the user provided cli option
224
+ async function getUserProvidedSource({ reqTemplate, templates, cliOptions, }) {
225
+ if (isValidGitRepoUrl(reqTemplate)) {
226
+ if (cliOptions.gitStrategy &&
227
+ !gitStrategies.includes(cliOptions.gitStrategy)) {
228
+ logger.error `Invalid git strategy: name=${cliOptions.gitStrategy}. Value must be one of ${gitStrategies.join(', ')}.`;
205
229
  process.exit(1);
206
230
  }
207
231
  return {
208
- type: 'template',
209
- template,
210
- typescript: cliOptions.typescript ?? false,
232
+ type: 'git',
233
+ url: reqTemplate,
234
+ strategy: cliOptions.gitStrategy ?? 'deep',
211
235
  };
212
236
  }
213
- const template = cliOptions.gitStrategy
214
- ? 'Git repository'
215
- : (await prompts({
216
- type: 'select',
217
- name: 'template',
218
- message: 'Select a template below...',
219
- choices: createTemplateChoices(templates),
220
- }, {
221
- onCancel() {
222
- logger.error('A choice is required.');
223
- process.exit(1);
224
- },
225
- })).template;
226
- if (template === 'Git repository') {
227
- const { gitRepoUrl } = (await prompts({
228
- type: 'text',
229
- name: 'gitRepoUrl',
230
- validate: (url) => {
231
- if (url && isValidGitRepoUrl(url)) {
232
- return true;
233
- }
234
- return logger.red('Invalid repository URL');
235
- },
236
- message: logger.interpolate `Enter a repository URL from GitHub, Bitbucket, GitLab, or any other public repo.
237
- (e.g: url=${'https://github.com/ownerName/repoName.git'})`,
238
- }, {
239
- onCancel() {
240
- logger.error('A git repo URL is required.');
241
- process.exit(1);
242
- },
243
- }));
244
- let strategy = cliOptions.gitStrategy;
245
- if (!strategy) {
246
- ({ strategy } = (await prompts({
247
- type: 'select',
248
- name: 'strategy',
249
- message: 'How should we clone this repo?',
250
- choices: [
251
- { title: 'Deep clone: preserve full history', value: 'deep' },
252
- { title: 'Shallow clone: clone with --depth=1', value: 'shallow' },
253
- {
254
- title: 'Copy: do a shallow clone, but do not create a git repo',
255
- value: 'copy',
256
- },
257
- {
258
- title: 'Custom: enter your custom git clone command',
259
- value: 'custom',
260
- },
261
- ],
262
- }, {
263
- onCancel() {
264
- logger.info `Falling back to name=${'deep'}`;
265
- },
266
- })));
267
- }
237
+ if (await fs.pathExists(path.resolve(reqTemplate))) {
268
238
  return {
269
- type: 'git',
270
- url: gitRepoUrl,
271
- strategy: strategy ?? 'deep',
239
+ type: 'local',
240
+ path: path.resolve(reqTemplate),
272
241
  };
273
242
  }
274
- else if (template === 'Local template') {
275
- const { templateDir } = (await prompts({
276
- type: 'text',
277
- name: 'templateDir',
278
- validate: async (dir) => {
279
- if (dir) {
280
- const fullDir = path.resolve(dir);
281
- if (await fs.pathExists(fullDir)) {
282
- return true;
283
- }
284
- return logger.red(logger.interpolate `path=${fullDir} does not exist.`);
285
- }
286
- return logger.red('Please enter a valid path.');
287
- },
288
- message: 'Enter a local folder path, relative to the current working directory.',
243
+ return getTemplateSource({
244
+ templateName: reqTemplate,
245
+ templates,
246
+ cliOptions,
247
+ });
248
+ }
249
+ async function askGitRepositorySource({ cliOptions, }) {
250
+ const { gitRepoUrl } = (await prompts({
251
+ type: 'text',
252
+ name: 'gitRepoUrl',
253
+ validate: (url) => {
254
+ if (url && isValidGitRepoUrl(url)) {
255
+ return true;
256
+ }
257
+ return logger.red('Invalid repository URL');
258
+ },
259
+ message: logger.interpolate `Enter a repository URL from GitHub, Bitbucket, GitLab, or any other public repo.
260
+ (e.g: url=${'https://github.com/ownerName/repoName.git'})`,
261
+ }, {
262
+ onCancel() {
263
+ logger.error('A git repo URL is required.');
264
+ process.exit(1);
265
+ },
266
+ }));
267
+ let strategy = cliOptions.gitStrategy;
268
+ if (!strategy) {
269
+ ({ strategy } = (await prompts({
270
+ type: 'select',
271
+ name: 'strategy',
272
+ message: 'How should we clone this repo?',
273
+ choices: [
274
+ { title: 'Deep clone: preserve full history', value: 'deep' },
275
+ { title: 'Shallow clone: clone with --depth=1', value: 'shallow' },
276
+ {
277
+ title: 'Copy: do a shallow clone, but do not create a git repo',
278
+ value: 'copy',
279
+ },
280
+ {
281
+ title: 'Custom: enter your custom git clone command',
282
+ value: 'custom',
283
+ },
284
+ ],
289
285
  }, {
290
286
  onCancel() {
291
- logger.error('A file path is required.');
292
- process.exit(1);
287
+ logger.info `Falling back to name=${'deep'}`;
293
288
  },
294
- }));
295
- return {
296
- type: 'local',
297
- path: templateDir,
298
- };
299
- }
300
- let useTS = cliOptions.typescript;
301
- if (!useTS && template.tsVariantPath) {
302
- ({ useTS } = (await prompts({
303
- type: 'confirm',
304
- name: 'useTS',
305
- message: 'This template is available in TypeScript. Do you want to use the TS variant?',
306
- initial: false,
307
289
  })));
308
290
  }
309
291
  return {
310
- type: 'template',
311
- template,
312
- typescript: useTS ?? false,
292
+ type: 'git',
293
+ url: gitRepoUrl,
294
+ strategy: strategy ?? 'deep',
295
+ };
296
+ }
297
+ async function askLocalSource() {
298
+ const { templateDir } = (await prompts({
299
+ type: 'text',
300
+ name: 'templateDir',
301
+ validate: async (dir) => {
302
+ if (dir) {
303
+ const fullDir = path.resolve(dir);
304
+ if (await fs.pathExists(fullDir)) {
305
+ return true;
306
+ }
307
+ return logger.red(logger.interpolate `path=${fullDir} does not exist.`);
308
+ }
309
+ return logger.red('Please enter a valid path.');
310
+ },
311
+ message: 'Enter a local folder path, relative to the current working directory.',
312
+ }, {
313
+ onCancel() {
314
+ logger.error('A file path is required.');
315
+ process.exit(1);
316
+ },
317
+ }));
318
+ return {
319
+ type: 'local',
320
+ path: templateDir,
313
321
  };
314
322
  }
323
+ async function getSource(reqTemplate, templates, cliOptions) {
324
+ if (reqTemplate) {
325
+ return getUserProvidedSource({ reqTemplate, templates, cliOptions });
326
+ }
327
+ const template = await askTemplateChoice({ templates, cliOptions });
328
+ if (template === 'Git repository') {
329
+ return askGitRepositorySource({ cliOptions });
330
+ }
331
+ if (template === 'Local template') {
332
+ return askLocalSource();
333
+ }
334
+ return createTemplateSource({
335
+ template,
336
+ cliOptions,
337
+ });
338
+ }
315
339
  async function updatePkg(pkgPath, obj) {
316
340
  const pkg = (await fs.readJSON(pkgPath));
317
341
  const newPkg = Object.assign(pkg, obj);
@@ -338,7 +362,7 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
338
362
  }
339
363
  else if (source.type === 'template') {
340
364
  try {
341
- await copyTemplate(source.template, dest, source.typescript);
365
+ await copyTemplate(source.template, dest, source.language);
342
366
  }
343
367
  catch (err) {
344
368
  logger.error `Copying Docusaurus template name=${source.template.name} failed!`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-docusaurus",
3
- "version": "3.1.1",
3
+ "version": "3.2.1",
4
4
  "description": "Create Docusaurus apps easily.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@docusaurus/logger": "3.1.1",
26
- "@docusaurus/utils": "3.1.1",
25
+ "@docusaurus/logger": "3.2.1",
26
+ "@docusaurus/utils": "3.2.1",
27
27
  "commander": "^5.1.0",
28
28
  "fs-extra": "^11.1.1",
29
29
  "lodash": "^4.17.21",
@@ -39,5 +39,5 @@
39
39
  "engines": {
40
40
  "node": ">=18.0"
41
41
  },
42
- "gitHead": "8017f6a6776ba1bd7065e630a52fe2c2654e2f1b"
42
+ "gitHead": "f268e15264e208e6faf26117258162e988b53773"
43
43
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-template",
3
- "version": "3.1.1",
3
+ "version": "3.2.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -14,8 +14,8 @@
14
14
  "write-heading-ids": "docusaurus write-heading-ids"
15
15
  },
16
16
  "dependencies": {
17
- "@docusaurus/core": "3.1.1",
18
- "@docusaurus/preset-classic": "3.1.1",
17
+ "@docusaurus/core": "3.2.1",
18
+ "@docusaurus/preset-classic": "3.2.1",
19
19
  "@mdx-js/react": "^3.0.0",
20
20
  "clsx": "^2.0.0",
21
21
  "prism-react-renderer": "^2.3.0",
@@ -23,8 +23,8 @@
23
23
  "react-dom": "^18.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@docusaurus/module-type-aliases": "3.1.1",
27
- "@docusaurus/types": "3.1.1"
26
+ "@docusaurus/module-type-aliases": "3.2.1",
27
+ "@docusaurus/types": "3.2.1"
28
28
  },
29
29
  "browserslist": {
30
30
  "production": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-typescript-template",
3
- "version": "3.1.1",
3
+ "version": "3.2.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -15,8 +15,8 @@
15
15
  "typecheck": "tsc"
16
16
  },
17
17
  "dependencies": {
18
- "@docusaurus/core": "3.1.1",
19
- "@docusaurus/preset-classic": "3.1.1",
18
+ "@docusaurus/core": "3.2.1",
19
+ "@docusaurus/preset-classic": "3.2.1",
20
20
  "@mdx-js/react": "^3.0.0",
21
21
  "clsx": "^2.0.0",
22
22
  "prism-react-renderer": "^2.3.0",
@@ -24,9 +24,9 @@
24
24
  "react-dom": "^18.0.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@docusaurus/module-type-aliases": "3.1.1",
28
- "@docusaurus/tsconfig": "3.1.1",
29
- "@docusaurus/types": "3.1.1",
27
+ "@docusaurus/module-type-aliases": "3.2.1",
28
+ "@docusaurus/tsconfig": "3.2.1",
29
+ "@docusaurus/types": "3.2.1",
30
30
  "typescript": "~5.2.2"
31
31
  },
32
32
  "browserslist": {