bin.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env node
  2. import fs from 'node:fs';
  3. import fsExtra from 'fs-extra';
  4. import * as p from '@clack/prompts';
  5. import { bold, cyan, grey, red, blue } from 'kleur/colors';
  6. import * as langAll from './lang/index.mjs';
  7. const { version } = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf-8'));
  8. console.log(`
  9. ${grey(`create-stdf@${version}
  10. `)}`);
  11. const spinner = p.spinner();
  12. p.intro('Welcome to use STDF!');
  13. // 选择一种语言
  14. // Select a language
  15. const languageType = await p.select({
  16. message: bold('Please select your preferred language(请选择你习惯的语言)'),
  17. options: [
  18. { value: 'en_US', label: 'English' },
  19. { value: 'zh_CN', label: '简体中文' },
  20. ],
  21. });
  22. const lang = langAll[languageType] || langAll['en_US'];
  23. if (p.isCancel(languageType)) {
  24. p.cancel(red('⛔ ') + lang.oc);
  25. process.exit(0);
  26. }
  27. const templateOptions = [
  28. { value: 'vt', label: 'Vite + Tailwind' },
  29. { value: 'vu', label: `Vite + UnoCSS(${lang.hnay})` },
  30. { value: 'skt', label: `SvelteKit + Tailwind(${lang.hnay})` },
  31. { value: 'sku', label: `SvelteKit + UnoCSS(${lang.hnay})` },
  32. { value: 'vtt', label: `Vite + Tailwind + TypeScript(${lang.hnay})` },
  33. { value: 'vut', label: `Vite + UnoCSS+TypeScript(${lang.hnay})` },
  34. { value: 'sktt', label: `SvelteKit + Tailwind + TypeScript(${lang.hnay})` },
  35. { value: 'skut', label: `SvelteKit + UnoCSS + TypeScript(${lang.hnay})` },
  36. ];
  37. // 选择一个模板
  38. // Select a template
  39. let template = await p.select({
  40. message: bold(lang.psat),
  41. options: templateOptions,
  42. });
  43. // 直到选择的 template 是 vt 为止,否则一直重新选择
  44. // Until the selected template is vt or vu, otherwise keep reselecting
  45. while (template !== 'vt') {
  46. if (p.isCancel(template)) {
  47. p.cancel(red('⛔ ') + lang.oc);
  48. process.exit(0);
  49. }
  50. p.intro(red(templateOptions.find(item => item.value === template).label + ' ' + lang.pca));
  51. template = await p.select({
  52. message: bold(lang.psat),
  53. options: templateOptions,
  54. });
  55. }
  56. if (p.isCancel(template)) {
  57. p.cancel(red('⛔ ') + lang.oc);
  58. process.exit(0);
  59. }
  60. // 输入项目名称
  61. // Enter the project name
  62. let projectName = await p.text({
  63. message: bold(lang.pn),
  64. initialValue: 'stdf-project',
  65. validate: value => {
  66. if (!value) {
  67. // 判断是否为空,提示 “项目名称不能为空”
  68. // Determine whether it is empty, prompt "Project name cannot be empty"
  69. return lang.pncbne;
  70. }
  71. if (fs.existsSync(value)) {
  72. // 判断是否已存在,提示 “项目名称已存在”
  73. // Determine whether it already exists, prompt "Project name already exists"
  74. return lang.pane;
  75. }
  76. },
  77. });
  78. if (p.isCancel(projectName)) {
  79. p.cancel(red('⛔ ') + lang.oc);
  80. process.exit(0);
  81. }
  82. // 项目目录
  83. // Project directory
  84. const projectDir = `${process.cwd()}/${projectName}`;
  85. const templatePaths = [
  86. { template: 'vt', path: './templates/vite-tailwind' },
  87. { template: 'vu', path: './templates/vite-uno' },
  88. { template: 'skt', path: './templates/sveltekit-tailwind' },
  89. { template: 'sku', path: './templates/sveltekit-uno' },
  90. { template: 'vtt', path: './templates/vite-tailwind-typescript' },
  91. { template: 'vut', path: './templates/vite-uno-typescript' },
  92. { template: 'sktt', path: './templates/sveltekit-tailwind-typescript' },
  93. { template: 'skut', path: './templates/sveltekit-uno-typescript' },
  94. ];
  95. spinner.start('🚀 ' + lang.cfsing);
  96. // 根据 template 的值,复制对应目录下的所有文件到当前目录
  97. // According to the value of template, copy all files under the corresponding directory to the current directory
  98. templatePaths.forEach(item => {
  99. if (item.template === template) {
  100. fs.mkdirSync(projectDir);
  101. // 获取模板目录的绝对路径
  102. // Get the absolute path of the template directory
  103. const filePath = new URL(item.path, import.meta.url).pathname;
  104. // 将 filePath 目录下的所有文件复制到 projectDir 目录下
  105. // Copy all files under the filePath directory to the projectDir directory
  106. fsExtra.copySync(filePath, projectDir, {
  107. filter: (src, dest) => {
  108. return !src.endsWith('/pnpm-lock.yaml');
  109. },
  110. });
  111. }
  112. });
  113. spinner.stop();
  114. console.log(`🎉 ${lang.pcsucc}
  115. `);
  116. // 读取 package.json 文件,获得 vite svelte tailwind stdf 的版本号
  117. // Read the package.json file to get the version number of vite svelte tailwind stdf
  118. const packageJson = JSON.parse(fs.readFileSync(`${projectDir}/package.json`, 'utf-8'));
  119. const versions = {
  120. vite: packageJson.devDependencies.vite,
  121. svelte: packageJson.devDependencies.svelte,
  122. tailwindcss: packageJson.devDependencies.tailwindcss,
  123. stdf: packageJson.devDependencies.stdf,
  124. };
  125. // 显示版本号
  126. // Display version number
  127. console.log(
  128. `📦 ${bold('Vite:')} ${cyan(versions.vite)} ${bold('Svelte:')} ${cyan(versions.svelte)} ${bold('Tailwind:')} ${cyan(
  129. versions.tailwindcss
  130. )} ${bold('STDF:')} ${cyan(versions.stdf)}
  131. `
  132. );
  133. // 显示提示信息
  134. // Display prompt information
  135. console.log(
  136. `👉 ${bold(lang.tgs)}
  137. ${blue(`cd ${projectName}`)}
  138. ${blue('pnpm i or npm i or yarn')}
  139. ${blue('npm run dev')}
  140. `
  141. );
  142. // 显示配置主题色
  143. // Display configuration theme color
  144. console.log(
  145. `🎨 ${bold(lang.pcyt)}
  146. `
  147. );