Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(create-docusaurus): ask user for preferred language when no language CLI option provided #9442

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/create-docusaurus/bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ program
'Do not run package manager immediately after scaffolding',
)
.option('-t, --typescript', 'Use the TypeScript template variant')
.option('-j, --javascript', 'Use the JavaScript template variant')
.option(
'-g, --git-strategy <strategy>',
`Only used if the template is a git repository.
Expand Down
53 changes: 38 additions & 15 deletions packages/create-docusaurus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ import logger from '@docusaurus/logger';
import shell from 'shelljs';
import prompts, {type Choice} from 'prompts';
import supportsColor from 'supports-color';
import {escapeShellArg} from '@docusaurus/utils';
import {
escapeShellArg,
getLanguage,
type LanguagesOptions,
} from '@docusaurus/utils';

type CLIOptions = {
packageManager?: PackageManager;
skipInstall?: boolean;
typescript?: boolean;
gitStrategy?: GitStrategy;
};
} & LanguagesOptions;

// Only used in the rare, rare case of running globally installed create +
// using --skip-install. We need a default name to show the tip text
Expand Down Expand Up @@ -217,6 +220,23 @@ async function getGitCommand(gitStrategy: GitStrategy): Promise<string> {
}
}

function getTemplate(
templates: Template[],
reqTemplate?: string,
typescript?: boolean,
) {
const template = templates.find((t) => t.name === reqTemplate);
if (!template) {
logger.error('Invalid template.');
process.exit(1);
}
if (typescript && !template.tsVariantPath) {
logger.error`Template name=${reqTemplate!} doesn't provide the TypeScript variant.`;
process.exit(1);
}
return template;
}

async function getSiteName(
reqName: string | undefined,
rootDir: string,
Expand Down Expand Up @@ -275,6 +295,7 @@ type Source =
async function getSource(
reqTemplate: string | undefined,
templates: Template[],
language: LanguagesOptions,
cliOptions: CLIOptions,
): Promise<Source> {
if (reqTemplate) {
Expand All @@ -299,19 +320,13 @@ async function getSource(
path: path.resolve(reqTemplate),
};
}
const template = templates.find((t) => t.name === reqTemplate);
if (!template) {
logger.error('Invalid template.');
process.exit(1);
}
if (cliOptions.typescript && !template.tsVariantPath) {
logger.error`Template name=${reqTemplate} doesn't provide the TypeScript variant.`;
process.exit(1);
}

const template = getTemplate(templates, reqTemplate, language.typescript);

return {
type: 'template',
template,
typescript: cliOptions.typescript ?? false,
typescript: language.typescript ?? false,
};
}
const template = cliOptions.gitStrategy
Expand Down Expand Up @@ -417,7 +432,8 @@ async function getSource(
path: templateDir,
};
}
let useTS = cliOptions.typescript;
let useTS = language.typescript;

if (!useTS && template.tsVariantPath) {
({useTS} = (await prompts({
type: 'confirm',
Expand Down Expand Up @@ -452,7 +468,14 @@ export default async function init(
getSiteName(reqName, rootDir),
]);
const dest = path.resolve(rootDir, siteName);
const source = await getSource(reqTemplate, templates, cliOptions);
const {typescript, javascript} = cliOptions;
const languageOptions = {typescript, javascript};
const noTsVersionAvailable = !getTemplate(templates, reqTemplate, typescript)
.tsVariantPath;

const language = await getLanguage(languageOptions, noTsVersionAvailable);

const source = await getSource(reqTemplate, templates, language, cliOptions);

logger.info('Creating new Docusaurus project...');

Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"micromatch": "^4.0.5",
"prompts": "^2.4.2",
"resolve-pathname": "^3.0.0",
"shelljs": "^0.8.5",
"tslib": "^2.6.0",
Expand Down
44 changes: 44 additions & 0 deletions packages/docusaurus-utils/src/cliUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import prompts from 'prompts';
import logger from '@docusaurus/logger';

export type LanguagesOptions = {
javascript?: boolean;
typescript?: boolean;
};

export async function getLanguage(
Copy link
Collaborator

@Josh-Cena Josh-Cena Oct 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only used in create-docusaurus. Please don't put it in utils. (You even had to add an entire prompts dependency.)

Copy link
Contributor Author

@Rafael-Martins Rafael-Martins Oct 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, I carried out this extraction in response to @slorber's comment, which suggested that it might be reused in another part of the code. If that's the case, I'm considering passing the 'prompt' function as a parameter to eliminate the dependency. What are your thoughts on this idea? I'm also open to the possibility of reintegrating it into 'create-docusaurus' if that's a better solution.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, considering we also want this for swizzle it's fine to add it to docusaurus utils

see also related pr: #9681

languages: LanguagesOptions,
noTsVersionAvailable?: boolean,
): Promise<LanguagesOptions> {
if (languages.typescript || languages.javascript) {
return languages;
}
if (noTsVersionAvailable) {
return {javascript: true};
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's a good thing to have this thing here, will try to see where to move it

const {language: selectedLanguage} = (await prompts(
{
type: 'select',
name: 'language',
message: 'Which language do you want to use?',
choices: [
{title: 'JavaScript', value: 'javascript'},
{title: 'TypeScript', value: 'typescript'},
],
},
{
onCancel() {
logger.info`Falling back to language=${'javascript'}`;
},
},
)) as {language: keyof LanguagesOptions};

return {[selectedLanguage]: true};
}
1 change: 1 addition & 0 deletions packages/docusaurus-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,4 @@ export {
} from './dataFileUtils';
export {isDraft, isUnlisted} from './contentVisibilityUtils';
export {escapeRegexp} from './regExpUtils';
export {getLanguage, type LanguagesOptions} from './cliUtils';