index.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import fs from 'fs'
  2. import path from 'path'
  3. import chokidar from 'chokidar'
  4. const toPascalCase = (str) => {
  5. return str.replace(/(^\w|-\w)/g, clearAndUpper)
  6. }
  7. const clearAndUpper = (text) => {
  8. return text.replace(/-/, '').toUpperCase()
  9. }
  10. // 递归获取目录下所有的 .vue 文件
  11. const getAllVueFiles = (dir, fileList = []) => {
  12. const files = fs.readdirSync(dir)
  13. files.forEach((file) => {
  14. const filePath = path.join(dir, file)
  15. if (fs.statSync(filePath).isDirectory()) {
  16. getAllVueFiles(filePath, fileList)
  17. } else if (filePath.endsWith('.vue')) {
  18. fileList.push(filePath)
  19. }
  20. })
  21. return fileList
  22. }
  23. // 从 .vue 文件内容中提取组件名称
  24. const extractComponentName = (fileContent) => {
  25. const regex = /defineOptions\(\s*{\s*name:\s*["']([^"']+)["']/
  26. const match = fileContent.match(regex)
  27. return match ? match[1] : null
  28. }
  29. // Vite 插件定义
  30. const vueFilePathPlugin = (outputFilePath) => {
  31. let root
  32. const generatePathNameMap = () => {
  33. const vueFiles = [
  34. ...getAllVueFiles(path.join(root, 'src/view')),
  35. ...getAllVueFiles(path.join(root, 'src/plugin'))
  36. ]
  37. const pathNameMap = vueFiles.reduce((acc, filePath) => {
  38. const content = fs.readFileSync(filePath, 'utf-8')
  39. const componentName = extractComponentName(content)
  40. let relativePath = '/' + path.relative(root, filePath).replace(/\\/g, '/')
  41. acc[relativePath] =
  42. componentName || toPascalCase(path.basename(filePath, '.vue'))
  43. return acc
  44. }, {})
  45. const outputContent = JSON.stringify(pathNameMap, null, 2)
  46. fs.writeFileSync(outputFilePath, outputContent)
  47. }
  48. const watchDirectoryChanges = () => {
  49. const watchDirectories = [
  50. path.join(root, 'src/view'),
  51. path.join(root, 'src/plugin')
  52. ]
  53. const watcher = chokidar.watch(watchDirectories, {
  54. persistent: true,
  55. ignoreInitial: true
  56. })
  57. watcher.on('all', () => {
  58. generatePathNameMap()
  59. })
  60. }
  61. return {
  62. name: 'vue-file-path-plugin',
  63. configResolved(resolvedConfig) {
  64. root = resolvedConfig.root
  65. },
  66. buildStart() {
  67. generatePathNameMap()
  68. },
  69. buildEnd() {
  70. if (process.env.NODE_ENV === 'development') {
  71. watchDirectoryChanges()
  72. }
  73. }
  74. }
  75. }
  76. export default vueFilePathPlugin