diff options
Diffstat (limited to 'packages/create-astro')
| -rw-r--r-- | packages/create-astro/package.json | 1 | ||||
| -rw-r--r-- | packages/create-astro/src/gradient.ts | 91 | ||||
| -rw-r--r-- | packages/create-astro/src/index.ts | 47 | 
3 files changed, 116 insertions, 23 deletions
| diff --git a/packages/create-astro/package.json b/packages/create-astro/package.json index 5a1e2af99..de3c1a35b 100644 --- a/packages/create-astro/package.json +++ b/packages/create-astro/package.json @@ -30,6 +30,7 @@    "dependencies": {      "@types/degit": "^2.8.3",      "@types/prompts": "^2.0.14", +    "chalk": "^5.0.1",      "degit": "^2.8.4",      "execa": "^6.1.0",      "kleur": "^4.1.4", diff --git a/packages/create-astro/src/gradient.ts b/packages/create-astro/src/gradient.ts new file mode 100644 index 000000000..2d4c48d81 --- /dev/null +++ b/packages/create-astro/src/gradient.ts @@ -0,0 +1,91 @@ +import chalk from 'chalk'; +import ora from 'ora'; +import type { Ora } from 'ora'; + +const gradientColors = [ +	`#ff5e00`, +	`#ff4c29`, +	`#ff383f`, +	`#ff2453`, +	`#ff0565`, +	`#ff007b`, +	`#f5008b`, +	`#e6149c`, +	`#d629ae`, +	`#c238bd`, +]; + +export const rocketAscii = '■■▶'; + +// get a reference to scroll through while loading +// visual representation of what this generates: +// gradientColors: "..xxXX" +// referenceGradient: "..xxXXXXxx....xxXX" +const referenceGradient = [ +	...gradientColors, +	// draw the reverse of the gradient without +	// accidentally mutating the gradient (ugh, reverse()) +	...[...gradientColors].reverse(), +	...gradientColors, +]; + +// async-friendly setTimeout +const sleep = (time: number) => +	new Promise((resolve) => { +		setTimeout(resolve, time); +	}); + +function getGradientAnimFrames() { +	const frames = []; +	for (let start = 0; start < gradientColors.length * 2; start++) { +		const end = start + gradientColors.length - 1; +		frames.push( +			referenceGradient +				.slice(start, end) +				.map((g) => chalk.bgHex(g)(' ')) +				.join('') +		); +	} +	return frames; +} + +function getIntroAnimFrames() { +	const frames = []; +	for (let end = 1; end <= gradientColors.length; end++) { +		const leadingSpacesArr = Array.from( +			new Array(Math.abs(gradientColors.length - end - 1)), +			() => ' ' +		); +		const gradientArr = gradientColors.slice(0, end).map((g) => chalk.bgHex(g)(' ')); +		frames.push([...leadingSpacesArr, ...gradientArr].join('')); +	} +	return frames; +} + +/** + * Generate loading spinner with rocket flames! + * @param text display text next to rocket + * @returns Ora spinner for running .stop() + */ +export async function loadWithRocketGradient(text: string): Promise<Ora> { +	const frames = getIntroAnimFrames(); +	const intro = ora({ +		spinner: { +			interval: 30, +			frames, +		}, +		text: `${rocketAscii} ${text}`, +	}); +	intro.start(); +	await sleep((frames.length - 1) * intro.interval); +	intro.stop(); +	const spinner = ora({ +		spinner: { +			interval: 80, +			frames: getGradientAnimFrames(), +		}, +		text: `${rocketAscii} ${text}`, +	}).start(); + +	return spinner; +} diff --git a/packages/create-astro/src/index.ts b/packages/create-astro/src/index.ts index dab8e7a3b..0546bd751 100644 --- a/packages/create-astro/src/index.ts +++ b/packages/create-astro/src/index.ts @@ -8,6 +8,7 @@ import ora from 'ora';  import { TEMPLATES } from './templates.js';  import { logger, defaultLogLevel } from './logger.js';  import { execa, execaCommand } from 'execa'; +import { loadWithRocketGradient, rocketAscii } from './gradient.js';  // NOTE: In the v7.x version of npm, the default behavior of `npm init` was changed  // to no longer require `--` to pass args and instead pass `--` directly to us. This @@ -42,10 +43,6 @@ export async function main() {  	logger.debug('Verbose logging turned on');  	console.log(`\n${bold('Welcome to Astro!')} ${gray(`(create-astro v${version})`)}`); -	let spinner = ora({ color: 'green', text: 'Prepare for liftoff.' }); - -	spinner.succeed(); -  	let cwd = args['_'][2] as string;  	if (cwd && isEmpty(cwd)) { @@ -95,6 +92,8 @@ export async function main() {  		process.exit(1);  	} +	const templateSpinner = await loadWithRocketGradient('Copying project files...'); +  	const hash = args.commit ? `#${args.commit}` : '';  	const templateTarget = `withastro/astro/examples/${options.template}#latest`; @@ -111,8 +110,6 @@ export async function main() {  		verbose: defaultLogLevel === 'debug' ? true : false,  	}); -	spinner = ora({ color: 'green', text: 'Copying project files...' }).start(); -  	// Copy  	if (!args.dryrun) {  		try { @@ -152,7 +149,7 @@ export async function main() {  					)  				);  			} -			spinner.fail(); +			templateSpinner.fail();  			process.exit(1);  		} @@ -167,8 +164,8 @@ export async function main() {  		);  	} -	spinner.succeed(); -	console.log(bold(green('✔') + ' Done!')); +	templateSpinner.text = green('Template copied!'); +	templateSpinner.succeed();  	const installResponse = await prompts({  		type: 'confirm', @@ -184,15 +181,18 @@ export async function main() {  	if (installResponse.install && !args.dryrun) {  		const installExec = execa(pkgManager, ['install'], { cwd });  		const installingPackagesMsg = `Installing packages${emojiWithFallback(' 📦', '...')}`; -		spinner = ora({ color: 'green', text: installingPackagesMsg }).start(); +		const installSpinner = await loadWithRocketGradient(installingPackagesMsg);  		await new Promise<void>((resolve, reject) => {  			installExec.stdout?.on('data', function (data) { -				spinner.text = `${installingPackagesMsg}\n${bold(`[${pkgManager}]`)} ${data}`; +				installSpinner.text = `${rocketAscii} ${installingPackagesMsg}\n${bold( +					`[${pkgManager}]` +				)} ${data}`;  			});  			installExec.on('error', (error) => reject(error));  			installExec.on('close', () => resolve());  		}); -		spinner.succeed(); +		installSpinner.text = green('Packages installed!'); +		installSpinner.succeed();  	}  	const astroAddCommand = installResponse.install @@ -240,21 +240,22 @@ export async function main() {  		await execaCommand('git init', { cwd });  	} +	ora({ text: green('Done. Ready for liftoff!') }).succeed();  	console.log(`\n${bgCyan(black(' Next steps '))}\n`); -	const relative = path.relative(process.cwd(), cwd); -	const startCommand = []; -	if (relative !== '') { -		startCommand.push(bold(cyan(`cd ${relative}`))); -	} +	const projectDir = path.relative(process.cwd(), cwd); +	const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`; + +	console.log( +		`You can now ${bold(cyan('cd'))} into the ${bold(cyan(projectDir))} project directory.` +	); +	console.log( +		`Run ${bold(cyan(devCmd))} to start the Astro dev server. ${bold(cyan('CTRL-C'))} to close.` +	);  	if (!installResponse.install) { -		startCommand.push(bold(cyan(`${pkgManager} install`))); +		console.log(yellow(`Remember to install dependencies first!`));  	} -	startCommand.push(bold(cyan(pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`))); -	console.log(startCommand.join(' && ')); - -	console.log(`\nTo close the dev server, hit ${bold(cyan('Ctrl-C'))}`); -	console.log(`Stuck? Visit us at ${cyan('https://astro.build/chat')}\n`); +	console.log(`\nStuck? Come join us at ${bold(cyan('https://astro.build/chat'))}`);  }  function emojiWithFallback(char: string, fallback: string) { | 
