index.mjs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import inquirer from 'inquirer';
  2. import { getComponentCode, getComponentDocCode, getDemoCode } from './templates/index.mjs';
  3. import fs from 'fs';
  4. import _ from 'lodash';
  5. import path from 'path';
  6. const CWD = process.cwd();
  7. inquirer.prompt([{
  8. type: 'input',
  9. message: '请填写组件英文名称(需要使用大驼峰命名,例如MultiMarker)',
  10. name: 'name',
  11. }, {
  12. type: 'input',
  13. message: '请填写组件中文名称(例如点标记)',
  14. name: 'zhName',
  15. }]).then((answers) => {
  16. // console.log(getComponentCode(answers.name));
  17. // 生成组件文件
  18. const indexPath = path.resolve(CWD, 'src/index.ts');
  19. const componentFilePath = `${CWD}/src/${_.kebabCase(answers.name)}.ts`;
  20. generateFile(componentFilePath, getComponentCode(answers.name));
  21. insertComponentToIndex(answers.name, indexPath);
  22. // 生成示例文件
  23. const demoFilePath = `${CWD}/demos/${_.kebabCase(answers.name)}.vue`;
  24. generateFile(demoFilePath, getDemoCode(answers.name));
  25. insertComponentToDemos(answers.name, answers.zhName, `${CWD}/demos/App.vue`);
  26. // 生成文档文件
  27. const docsFilePath = `${CWD}/docs/components/${_.kebabCase(answers.name)}.md`;
  28. generateFile(docsFilePath, getComponentDocCode(answers.name, answers.zhName));
  29. insertComponentToDocsTheme(answers.name);
  30. insertComponentToDocsConfig(answers.name, answers.zhName);
  31. console.log('组件文件、示例文件、文档文件创建成功');
  32. });
  33. const generateFile = (filePath, content) => {
  34. // if (fs.existsSync(filePath)) {
  35. // console.log(`${filePath}已存在,请重新创建`);
  36. // return;
  37. // }
  38. try {
  39. fs.writeFileSync(filePath, content);
  40. } catch (err) {
  41. console.error('创建文件时出错:', err);
  42. }
  43. };
  44. function insertComponentToIndex(name, indexPath) {
  45. const importPattern = /import.*?;(?=\n\n)/;
  46. const importPath = getImportStr(name);
  47. let data = fs.readFileSync(indexPath).toString();
  48. if (data.match(new RegExp(importPath))) {
  49. console.log(`there is already ${name} in /src/index.ts`, 'notice');
  50. return;
  51. }
  52. // 插入import
  53. data = data.replace(importPattern, a => `${a}\n${importPath}`);
  54. // 写入components数组
  55. const componentsRegex = /const\s+components\s*=\s*\[\n([\s\S]*?)\n\];/;
  56. const arrayContent = data.match(componentsRegex)[1];
  57. const modifiedContent = `${arrayContent}\n ${name},`;
  58. data = data.replace(componentsRegex, `const components = [\n${modifiedContent}\n];`);
  59. // 写入export
  60. const exportRegex = /export\s+\{\n([\s\S]*?)\n\};/;
  61. const objectContent = data.match(exportRegex)[1];
  62. const modifiedObjectContent = `${objectContent}\n ${name},`;
  63. data = data.replace(exportRegex, `export {\n${modifiedObjectContent}\n};`);
  64. fs.writeFile(indexPath, data, (err) => {
  65. if (err) {
  66. console.log(err, 'error');
  67. }
  68. });
  69. }
  70. function insertComponentToDemos(name, zhName, demoPath) {
  71. // eslint-disable-next-line no-useless-escape
  72. const importPattern = /((?:import\s+.+\s+from\s+\'.+\'\s*;\r?\n)+)/;
  73. const importPath = getImportStr(`${name}`, 'vue');
  74. let data = fs.readFileSync(demoPath).toString();
  75. if (data.match(new RegExp(importPath))) {
  76. console.log(`there is already ${name} in /demos/App.vue`, 'notice');
  77. return;
  78. }
  79. // 插入import
  80. data = data.replace(importPattern, a => `${a}${importPath}\n`);
  81. // 写入components数组
  82. const componentsRegex = /const\s+components\s*=\s*\{\n([\s\S]*?)\n\};/;
  83. const arrayContent = data.match(componentsRegex)[1];
  84. const modifiedComponentsContent = `${arrayContent}\n ${name},`;
  85. data = data.replace(componentsRegex, `const components = {\n${modifiedComponentsContent}\n};`);
  86. // 插入组件
  87. const newComponent = ` <h2>${zhName}</h2>
  88. <${name} />`;
  89. const regex = /<div>\n(.*?)(\n {2}<\/div>)/s;
  90. const match = data.match(regex);
  91. if (!match) {
  92. console.error('Template not found in the file.');
  93. return;
  94. }
  95. const divContent = match[1];
  96. const modifiedContent = `${divContent}\n ${newComponent}`;
  97. // 替换原始内容
  98. data = data.replace(regex, `<div>\n${modifiedContent}\n </div>`);
  99. fs.writeFile(demoPath, data, (err) => {
  100. if (err) {
  101. console.log(err, 'error');
  102. }
  103. });
  104. }
  105. function insertComponentToDocsTheme(name) {
  106. const indexPath = path.resolve(CWD, 'docs/.vitepress/theme/index.js');
  107. const importPattern = /import.*?;(?=\n\n)/;
  108. const importPath = `import ${name} from '../../../demos/${_.kebabCase(name)}.vue';`;
  109. let data = fs.readFileSync(indexPath).toString();
  110. if (data.match(new RegExp(importPath))) {
  111. console.log(`there is already ${name} in /src/index.ts`, 'notice');
  112. return;
  113. }
  114. // 插入import
  115. data = data.replace(importPattern, a => `${a}\n${importPath}`);
  116. // 写入components数组
  117. const componentsRegex = /const\s+components\s*=\s*\[\n([\s\S]*?)\n\];/;
  118. const arrayContent = data.match(componentsRegex)[1];
  119. const modifiedContent = `${arrayContent}\n ${name},`;
  120. data = data.replace(componentsRegex, `const components = [\n${modifiedContent}\n];`);
  121. fs.writeFile(indexPath, data, (err) => {
  122. if (err) {
  123. console.log(err, 'error');
  124. }
  125. });
  126. }
  127. function insertComponentToDocsConfig(name, zhName) {
  128. const configPath = path.resolve(CWD, 'docs/.vitepress/config.js');
  129. // 写入componentItmes数组
  130. const componentsRegex = /const\s+componentItmes\s*=\s*\[\n([\s\S]*?)];/;
  131. let data = fs.readFileSync(configPath).toString();
  132. const arrayContent = data.match(componentsRegex)[1];
  133. const itemStr = `{ text: '${zhName}', link: '/components/${_.kebabCase(name)}' },`;
  134. const modifiedContent = `${arrayContent} ${itemStr}`;
  135. data = data.replace(componentsRegex, `const componentItmes = [\n${modifiedContent}\n ];`);
  136. fs.writeFile(configPath, data, (err) => {
  137. if (err) {
  138. console.log(err, 'error');
  139. }
  140. });
  141. }
  142. function getImportStr(name, suffix = '') {
  143. return `import ${getFirstLetterUpper(name)} from './${_.kebabCase(name)}${suffix ? `.${suffix}` : ''}';`;
  144. }
  145. function getFirstLetterUpper(a) {
  146. return a[0].toUpperCase() + a.slice(1);
  147. }