process.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. const vueCompiler = require('vue-template-compiler')
  2. const compileTemplate = require('./template-compiler')
  3. const generateSourceMap = require('./generate-source-map')
  4. const addTemplateMapping = require('./add-template-mapping')
  5. const compileBabel = require('./compilers/babel-compiler')
  6. const compileTypescript = require('./compilers/typescript-compiler')
  7. const compileCoffeeScript = require('./compilers/coffee-compiler')
  8. const processStyle = require('./process-style')
  9. const getVueJestConfig = require('./get-vue-jest-config')
  10. const fs = require('fs')
  11. const path = require('path')
  12. const join = path.join
  13. const logger = require('./logger')
  14. const convertSourceMap = require('convert-source-map')
  15. const splitRE = /\r?\n/g
  16. function processScript (scriptPart, vueJestConfig, filePath) {
  17. if (!scriptPart) {
  18. return { code: '' }
  19. }
  20. if (/^typescript|tsx?$/.test(scriptPart.lang)) {
  21. return compileTypescript(scriptPart.content, vueJestConfig, filePath)
  22. }
  23. if (scriptPart.lang === 'coffee' || scriptPart.lang === 'coffeescript') {
  24. return compileCoffeeScript(scriptPart.content, vueJestConfig, filePath)
  25. }
  26. return compileBabel(scriptPart.content, undefined, undefined, vueJestConfig, filePath)
  27. }
  28. module.exports = function (src, filePath, jestConfig) {
  29. const vueJestConfig = getVueJestConfig(jestConfig)
  30. var parts = vueCompiler.parseComponent(src, { pad: true })
  31. if (parts.script && parts.script.src) {
  32. parts.script.content = fs.readFileSync(join(filePath, '..', parts.script.src), 'utf8')
  33. }
  34. const result = processScript(parts.script, vueJestConfig, filePath)
  35. const script = result.code
  36. const inputMap = result.sourceMap
  37. let scriptSrc = src
  38. if (parts.script && parts.script.src) {
  39. scriptSrc = parts.script.content
  40. }
  41. const map = generateSourceMap(script, '', filePath, scriptSrc, inputMap)
  42. let output = ';(function(){\n' + script + '\n})()\n' +
  43. 'var defaultExport = (module.exports.__esModule) ? module.exports.default : module.exports;' +
  44. 'var __vue__options__ = (typeof defaultExport === "function"' +
  45. '? defaultExport.options' +
  46. ': defaultExport)\n'
  47. if (parts.template) {
  48. parts.template.filename = filePath
  49. if (parts.template.src) {
  50. parts.template.filename = join(filePath, '..', parts.template.src)
  51. parts.template.content = fs.readFileSync(parts.template.filename, 'utf8')
  52. }
  53. const renderFunctions = compileTemplate(parts.template, vueJestConfig)
  54. output += '__vue__options__.render = ' + renderFunctions.render + '\n' +
  55. '__vue__options__.staticRenderFns = ' + renderFunctions.staticRenderFns + '\n'
  56. if (parts.template.attrs.functional) {
  57. output += '__vue__options__.functional = true\n'
  58. output += '__vue__options__._compiled = true\n'
  59. }
  60. if (map) {
  61. const beforeLines = output.split(splitRE).length
  62. addTemplateMapping(script, parts, output, map, beforeLines)
  63. }
  64. }
  65. if (Array.isArray(parts.styles) && parts.styles.length > 0) {
  66. if ((parts.styles.some(ast => /^less/.test(ast.lang))) && logger.shouldLogStyleWarn) {
  67. !vueJestConfig.hideStyleWarn && logger.warn('Less are not currently compiled by vue-jest')
  68. logger.shouldLogStyleWarn = false
  69. }
  70. const styleStr = parts.styles
  71. .filter(ast => ast.module)
  72. .map(ast => {
  73. const styleObj = (/^less/.test(ast.lang))
  74. ? {}
  75. : processStyle(ast, filePath, jestConfig)
  76. const moduleName = ast.module === true ? '$style' : ast.module
  77. return `
  78. if(!this['${moduleName}']) {
  79. this['${moduleName}'] = {};
  80. }
  81. this['${moduleName}'] = Object.assign(this['${moduleName}'], ${JSON.stringify(styleObj)});
  82. `
  83. })
  84. .filter(_ => _)
  85. .join('')
  86. if (styleStr.length !== 0) {
  87. if (parts.template && parts.template.attrs.functional) {
  88. output += `
  89. ;(function() {
  90. var originalRender = __vue__options__.render
  91. var styleFn = function () { ${styleStr} }
  92. __vue__options__.render = function renderWithStyleInjection (h, context) {
  93. styleFn.call(context)
  94. return originalRender(h, context)
  95. }
  96. })()
  97. `
  98. } else {
  99. output += `
  100. ;(function() {
  101. var beforeCreate = __vue__options__.beforeCreate
  102. var styleFn = function () { ${styleStr} }
  103. __vue__options__.beforeCreate = beforeCreate ? [].concat(beforeCreate, styleFn) : [styleFn]
  104. })()
  105. `
  106. }
  107. }
  108. }
  109. if (map) {
  110. output += '\n' + convertSourceMap.fromJSON(map.toString()).toComment()
  111. }
  112. return { code: output }
  113. }