diff --git a/docs/guide/index.md b/docs/guide/index.md index f76d0237918472..c11e5a24f99eaf 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -69,7 +69,7 @@ $ bun create vite Then follow the prompts! -You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: +You can also directly specify the project name as the first parameter, and then template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: ```bash # npm 7+, extra double-dash is needed: @@ -85,6 +85,20 @@ pnpm create vite my-vue-app --template vue bun create vite my-vue-app --template vue ``` +The project name parameter also doubles as the target folder for your new Vite project. So the command: + +```bash +npm create vite@latest my-vue-app -- --template vue +``` + +Will create your new project in the folder ./my-vue-app as a sub-folder of the folder from which you invoked the command, as well as setting its project name to "my-vue-app". If your project name/folder parameter contains a path then the project name will be taken from the deepest level folder of that path. So the the command: + +```bash +npm create vite@latest ./my-sub-folder/my-vue-app -- --template vue +``` + +will create the project in that target folder, but set its project name to just "my-vue-app" again. + See [create-vite](https://github.com/vitejs/vite/tree/main/packages/create-vite) for more details on each supported template: `vanilla`, `vanilla-ts`, `vue`, `vue-ts`, `react`, `react-ts`, `react-swc`, `react-swc-ts`, `preact`, `preact-ts`, `lit`, `lit-ts`, `svelte`, `svelte-ts`, `solid`, `solid-ts`, `qwik`, `qwik-ts`. You can use `.` for the project name to scaffold in the current directory. diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index 4f297032834fcf..7469ac09392696 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -8,6 +8,7 @@ const CLI_PATH = join(__dirname, '..') const projectName = 'test-app' const genPath = join(__dirname, projectName) +const genPathWithSubfolder = join(__dirname, 'subfolder', projectName) const run = ( args: string[], @@ -17,12 +18,13 @@ const run = ( } // Helper to create a non-empty directory -const createNonEmptyDir = () => { +const createNonEmptyDir = (overrideFolder?: string) => { // Create the temporary directory - fs.mkdirpSync(genPath) + const newNonEmptyFolder = overrideFolder || genPath + fs.mkdirpSync(newNonEmptyFolder) // Create a package.json file - const pkgJson = join(genPath, 'package.json') + const pkgJson = join(newNonEmptyFolder, 'package.json') fs.writeFileSync(pkgJson, '{ "foo": "bar" }') } @@ -33,8 +35,24 @@ const templateFiles = fs .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath)) .sort() -beforeAll(() => fs.remove(genPath)) -afterEach(() => fs.remove(genPath)) +// React starter template +const templateFilesReact = fs + .readdirSync(join(CLI_PATH, 'template-react')) + // _gitignore is renamed to .gitignore + .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath)) + .sort() + +const clearAnyPreviousFolders = () => { + if (fs.existsSync(genPath)) { + fs.removeSync(genPath) + } + if (fs.existsSync(genPathWithSubfolder)) { + fs.removeSync(genPathWithSubfolder) + } +} + +beforeAll(() => clearAnyPreviousFolders()) +afterEach(() => clearAnyPreviousFolders()) test('prompts for the project name if none supplied', () => { const { stdout } = run([]) @@ -70,6 +88,14 @@ test('asks to overwrite non-empty target directory', () => { expect(stdout).toContain(`Target directory "${projectName}" is not empty.`) }) +test('asks to overwrite non-empty target directory with subfolder', () => { + createNonEmptyDir(genPathWithSubfolder) + const { stdout } = run([`subfolder/${projectName}`], { cwd: __dirname }) + expect(stdout).toContain( + `Target directory "subfolder/${projectName}" is not empty.`, + ) +}) + test('asks to overwrite non-empty current directory', () => { createNonEmptyDir() const { stdout } = run(['.'], { cwd: genPath }) @@ -87,6 +113,17 @@ test('successfully scaffolds a project based on vue starter template', () => { expect(templateFiles).toEqual(generatedFiles) }) +test('successfully scaffolds a project with subfolder based on react starter template', () => { + const { stdout } = run([`subfolder/${projectName}`, '--template', 'react'], { + cwd: __dirname, + }) + const generatedFiles = fs.readdirSync(genPathWithSubfolder).sort() + + // Assertions + expect(stdout).toContain(`Scaffolding project in ${genPathWithSubfolder}`) + expect(templateFilesReact).toEqual(generatedFiles) +}) + test('works with the -t alias', () => { const { stdout } = run([projectName, '-t', 'vue'], { cwd: __dirname, diff --git a/packages/create-vite/src/index.ts b/packages/create-vite/src/index.ts index ea22e52c2384a7..ca66dcf5a688ef 100755 --- a/packages/create-vite/src/index.ts +++ b/packages/create-vite/src/index.ts @@ -252,8 +252,7 @@ async function init() { const argTemplate = argv.template || argv.t let targetDir = argTargetDir || defaultTargetDir - const getProjectName = () => - targetDir === '.' ? path.basename(path.resolve()) : targetDir + const getProjectName = () => path.basename(path.resolve(targetDir)) let result: prompts.Answers< 'projectName' | 'overwrite' | 'packageName' | 'framework' | 'variant'