compiler.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * @file compile & output regular vue component files
  3. */
  4. const compiler = require('vue-template-compiler')
  5. const path = require('path')
  6. const fs = require('fs')
  7. const pug = require('pug')
  8. const babel = require('babel-core')
  9. const rmdir = require('rmdir')
  10. const rootPath = path.resolve(__dirname, '../src')
  11. const isArray = Array.isArray
  12. function attrsToString (attrs) {
  13. let ret = ''
  14. for (const name in attrs) {
  15. const value = attrs[name]
  16. if (value === true) {
  17. ret += `${name} `
  18. } else if (value) {
  19. ret += `${name}="${value}" `
  20. }
  21. }
  22. return ret
  23. }
  24. function tagToString (tag) {
  25. return tag ? `<${tag.type} ${attrsToString(tag.attrs)}>${tag.content}</${tag.type}>` : ''
  26. }
  27. function reverseToComponent (componentObj) {
  28. let ret = ''
  29. for (const key in componentObj) {
  30. const tag = componentObj[key]
  31. if (isArray(tag)) {
  32. ret += tag.map(tagToString).join('')
  33. } else {
  34. ret += tagToString(tag)
  35. }
  36. }
  37. return ret
  38. }
  39. function transformAlias (content, level) {
  40. return babel.transform(content, {
  41. plugins: [
  42. [
  43. 'module-alias', [
  44. {src: '../'.repeat(level), expose: '@'}
  45. ]
  46. ]
  47. ]
  48. }).code
  49. }
  50. function transformES (content) {
  51. return babel.transform(content, {
  52. presets: [
  53. 'es2015'
  54. ]
  55. }).code
  56. }
  57. function walkComponents (rootPath, level = 0, pathName = '.', result = []) {
  58. const files = fs.readdirSync(rootPath)
  59. files.forEach(file => {
  60. const filePath = path.resolve(rootPath, file)
  61. const extName = path.extname(filePath)
  62. const isDirectory = fs.lstatSync(filePath).isDirectory()
  63. if (isDirectory) {
  64. walkComponents(filePath, level + 1, path.join(pathName, file), result)
  65. } else if (extName === '.vue') {
  66. const componentFile = fs.readFileSync(filePath).toString()
  67. const component = compiler.parseComponent(componentFile)
  68. const baseName = path.basename(filePath)
  69. if (component.template) {
  70. component.template.content = pug.render(component.template.content)
  71. if (component.template.attrs) {
  72. component.template.attrs.lang = false
  73. }
  74. }
  75. if (component.script) {
  76. component.script.content = transformAlias(component.script.content, level)
  77. }
  78. result.push({
  79. content: reverseToComponent(component),
  80. path: pathName,
  81. name: baseName
  82. })
  83. } else if (extName === '.js') {
  84. const content = fs.readFileSync(filePath).toString()
  85. const baseName = path.basename(filePath)
  86. result.push({
  87. content: transformES(transformAlias(content, level)),
  88. path: pathName,
  89. name: baseName
  90. })
  91. }
  92. })
  93. return result
  94. }
  95. function mkdirp (filepath) {
  96. var dirname = path.dirname(filepath)
  97. if (!fs.existsSync(dirname)) {
  98. mkdirp(dirname)
  99. }
  100. if (!fs.existsSync(filepath)) {
  101. fs.mkdirSync(filepath)
  102. }
  103. }
  104. const compiledFiles = walkComponents(rootPath)
  105. const componentDir = path.resolve(__dirname, '../components')
  106. rmdir(componentDir, () => {
  107. mkdirp(componentDir)
  108. compiledFiles.forEach(file => {
  109. const pathName = path.resolve(componentDir, file.path)
  110. mkdirp(pathName)
  111. const fd = fs.openSync(path.resolve(pathName, file.name), 'w')
  112. fs.writeSync(fd, file.content)
  113. fs.closeSync(fd)
  114. })
  115. })