diff --git a/lib/extract-props.js b/lib/extract-props.js deleted file mode 100644 index a4dea28d..00000000 --- a/lib/extract-props.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = function extractProps (content) { - const DETECT_PROP_DEFINITIONS = /(props\..*?)(}| |\.|\[)/g - const CHARS_TO_REMOVE = /(\.|}| |props|\(|\[)/g - const propDefinitions = content.match(DETECT_PROP_DEFINITIONS) - if (!propDefinitions) return '{}' - let props = propDefinitions.map((match) => { - const propName = match.trim().replace(CHARS_TO_REMOVE, '') - return `'${propName}'` - }) - props = removeDuplicates(props) - return `[ ${props.join(', ')} ]` -} - -function removeDuplicates (props) { - return [...new Set(props)] -} diff --git a/lib/process.js b/lib/process.js index 0d2dac02..c5b2fab4 100644 --- a/lib/process.js +++ b/lib/process.js @@ -5,7 +5,6 @@ const addTemplateMapping = require('./add-template-mapping') const compileBabel = require('./compilers/babel-compiler') const compileTypescript = require('./compilers/typescript-compiler') const compileCoffeeScript = require('./compilers/coffee-compiler') -const extractPropsFromFunctionalTemplate = require('./extract-props') const processStyle = require('./process-style') const getVueJestConfig = require('./get-vue-jest-config') const fs = require('fs') @@ -30,23 +29,11 @@ function processScript (scriptPart, vueJestConfig) { return compileBabel(scriptPart.content, undefined, undefined, vueJestConfig) } -function changePartsIfFunctional (parts) { - const isFunctional = parts.template && parts.template.attrs && parts.template.attrs.functional - if (isFunctional) { - parts.lang = 'javascript' - const functionalProps = extractPropsFromFunctionalTemplate(parts.template.content) - parts.template.content = parts.template.content.replace(/props./g, '') - parts.script = { type: 'script', content: `export default { props: ${functionalProps} }` } - } -} - module.exports = function (src, filePath, jestConfig) { const vueJestConfig = getVueJestConfig(jestConfig) var parts = vueCompiler.parseComponent(src, { pad: true }) - changePartsIfFunctional(parts) - if (parts.script && parts.script.src) { parts.script.content = fs.readFileSync(join(filePath, '..', parts.script.src), 'utf8') } @@ -80,6 +67,10 @@ module.exports = function (src, filePath, jestConfig) { output += '__vue__options__.render = ' + renderFunctions.render + '\n' + '__vue__options__.staticRenderFns = ' + renderFunctions.staticRenderFns + '\n' + if (parts.template.attrs.functional) { + output += '__vue__options__.functional = true\n' + } + if (map) { const beforeLines = output.split(splitRE).length addTemplateMapping(script, parts, output, map, beforeLines) diff --git a/lib/template-compiler.js b/lib/template-compiler.js index 9f0b2a87..f659c345 100644 --- a/lib/template-compiler.js +++ b/lib/template-compiler.js @@ -21,7 +21,6 @@ function getTemplateContent (templatePart, config) { module.exports = function compileTemplate (templatePart, config) { var templateContent = getTemplateContent(templatePart, config) - var compiled = vueCompiler.compile(templateContent) if (compiled.errors.length) { compiled.errors.forEach(function (msg) { @@ -29,13 +28,20 @@ module.exports = function compileTemplate (templatePart, config) { }) throwError('Vue template compilation failed') } else { - return { - render: toFunction(compiled.render), - staticRenderFns: '[' + compiled.staticRenderFns.map(toFunction).join(',') + ']' - } + return compile(compiled, templatePart.attrs.functional) } } -function toFunction (code) { - return transpile('function render () {' + code + '}') +function compile (compiled, isFunctional) { + function toFunction (code) { + var renderArgs = isFunctional ? '_h, _vm' : '' + return transpile('function render (' + renderArgs + ') {' + code + '}', { + transforms: { stripWithFunctional: isFunctional } + }) + } + + return { + render: toFunction(compiled.render), + staticRenderFns: '[' + compiled.staticRenderFns.map(toFunction).join(',') + ']' + } } diff --git a/package.json b/package.json index a21f3634..c7f1d77d 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "object-assign": "^4.1.1", "source-map": "^0.5.6", "tsconfig": "^7.0.0", - "vue-template-es2015-compiler": "^1.5.3" + "vue-template-es2015-compiler": "^1.6.0" }, "jest": { "moduleFileExtensions": [ diff --git a/test/FunctionalSFC.spec.js b/test/FunctionalSFC.spec.js index e1a2a110..7e6bd05c 100644 --- a/test/FunctionalSFC.spec.js +++ b/test/FunctionalSFC.spec.js @@ -5,7 +5,9 @@ let wrapper const clickSpy = jest.fn() beforeEach(() => { wrapper = shallow(FunctionalSFC, { - propsData: { msg: { id: 1, title: 'foo' }, onClick: clickSpy } + context: { + props: { msg: { id: 1, title: 'foo' }, onClick: clickSpy } + } }) }) @@ -18,4 +20,9 @@ describe('Processes .vue file with functional template', () => { wrapper.trigger('click') expect(clickSpy).toHaveBeenCalledWith(1) }) + + it('is functional', () => { + // note: for new version of @vue/vue-utils we can use wrapper.isFunctionalComponent for this + expect(wrapper.vm._vnode.fnOptions.functional).toBe(true) + }) }) diff --git a/test/extract-props.spec.js b/test/extract-props.spec.js deleted file mode 100644 index 01922a40..00000000 --- a/test/extract-props.spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import extractProps from '../lib/extract-props' - -describe('when extracting props with props. prefix from functional template content', () => { - it('extracts interpolated props ', () => { - const content = '