diff --git a/README.md b/README.md index 1ee2483..3c997e7 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,20 @@ npm add @rstackjs/create-toolkit -D ## Features +### Custom Startup Banner + +Pass the optional `banner` string to customize the startup greeting: + +```ts +create({ + name: 'rsbuild', + banner: 'create-rsbuild v2.2.14', + // ...other options +}); +``` + +Supply the complete text; the toolkit applies the existing greeting style. Omit `banner` to keep `Create Project`. The `version` option for template dependencies is unchanged. + ### Configure Built-in Tools The toolkit provides ESLint, Rslint, Biome, and Prettier as built-in tools. Use diff --git a/src/index.ts b/src/index.ts index 5b7353c..b0c4822 100644 --- a/src/index.ts +++ b/src/index.ts @@ -725,6 +725,7 @@ export async function create({ mapESLintTemplate, mapRslintTemplate, version, + banner, noteInformation, git = true, onGitResolved, @@ -761,6 +762,11 @@ export async function create({ context: { distFolder: string }, ) => RslintTemplateName | null; version?: Record | string; + /** + * The complete text to display in the startup greeting. + * Omit this option to use `Create Project`. + */ + banner?: string; noteInformation?: string[]; /** * Whether to initialize a Git repository by default when the target directory @@ -801,7 +807,7 @@ export async function create({ return; } - logger.greet(`\n◆ Create ${upperFirst(name)} Project`); + logger.greet(`\n◆ ${banner ?? `Create ${upperFirst(name)} Project`}`); const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent); const detectedPackageManager = pkgInfo ? pkgInfo.name : 'npm'; diff --git a/test/banner.test.ts b/test/banner.test.ts new file mode 100644 index 0000000..f4276dd --- /dev/null +++ b/test/banner.test.ts @@ -0,0 +1,42 @@ +import { afterEach, expect, rs, test } from 'rstack/test'; +import { logger } from 'rslog'; +import { create } from '../src'; + +const options = { + name: 'test', + root: '.', + templates: [{ name: 'custom', create: rs.fn() }], + getTemplateName: async () => 'custom', + argv: ['node', 'test', '.', '--template', 'custom', '--override'], +}; + +afterEach(() => { + rs.restoreAllMocks(); +}); + +test.each([ + { banner: undefined, expected: 'Create Test Project' }, + { banner: 'create-rsbuild v2.2.14', expected: 'create-rsbuild v2.2.14' }, +])( + 'should display the startup banner: $expected', + async ({ banner, expected }) => { + const greet = rs.spyOn(logger, 'greet').mockImplementation(() => {}); + + await create({ ...options, banner }); + + expect(greet).toHaveBeenCalledExactlyOnceWith(`\n◆ ${expected}`); + }, +); + +test('should skip the banner when displaying help', async () => { + const greet = rs.spyOn(logger, 'greet').mockImplementation(() => {}); + rs.spyOn(logger, 'log').mockImplementation(() => {}); + + await create({ + ...options, + banner: 'create-rsbuild v2.2.14', + argv: ['node', 'test', '--help'], + }); + + expect(greet).not.toHaveBeenCalled(); +});