diff --git a/lib/process-functional.js b/lib/extract-props.js similarity index 52% rename from lib/process-functional.js rename to lib/extract-props.js index 7751588b..a4dea28d 100644 --- a/lib/process-functional.js +++ b/lib/extract-props.js @@ -1,11 +1,16 @@ module.exports = function extractProps (content) { - const DETECT_PROP_DEFINITIONS = /(props\..*?)(}| |\.)/g - const CHARS_TO_REMOVE = /(\.|}| |props)/g + const DETECT_PROP_DEFINITIONS = /(props\..*?)(}| |\.|\[)/g + const CHARS_TO_REMOVE = /(\.|}| |props|\(|\[)/g const propDefinitions = content.match(DETECT_PROP_DEFINITIONS) if (!propDefinitions) return '{}' - const props = propDefinitions.map((match) => { + 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 4d8530a7..b45aeaa5 100644 --- a/lib/process.js +++ b/lib/process.js @@ -6,7 +6,7 @@ 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('./process-functional') +const extractPropsFromFunctionalTemplate = require('./extract-props') const splitRE = /\r?\n/g @@ -22,19 +22,12 @@ function processScript (scriptPart) { return compileBabel(scriptPart.content) } -function isFunctionalTemplate (parts) { - try { - if (parts.template.attrs.functional === true) return true - } catch (error) { - return false - } -} - function changePartsIfFunctional (parts) { - if (isFunctionalTemplate(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.', '') + parts.template.content = parts.template.content.replace(/props./g, '') parts.script = { type: 'script', content: `export default { props: ${functionalProps} }` } } } diff --git a/test/FunctionalSFC.spec.js b/test/FunctionalSFC.spec.js index 30c5d106..e1a2a110 100644 --- a/test/FunctionalSFC.spec.js +++ b/test/FunctionalSFC.spec.js @@ -1,10 +1,21 @@ import { shallow } from 'vue-test-utils' import FunctionalSFC from './resources/FunctionalSFC.vue' -test('processes .vue file with functional template', () => { - const wrapper = shallow(FunctionalSFC, { - propsData: { msg: 'Hello' } +let wrapper +const clickSpy = jest.fn() +beforeEach(() => { + wrapper = shallow(FunctionalSFC, { + propsData: { msg: { id: 1, title: 'foo' }, onClick: clickSpy } + }) +}) + +describe('Processes .vue file with functional template', () => { + it('with nested props', () => { + expect(wrapper.text().trim()).toBe('foo') + }) + + it('with callback prop', () => { + wrapper.trigger('click') + expect(clickSpy).toHaveBeenCalledWith(1) }) - expect(wrapper.is('div')).toBe(true) - expect(wrapper.text().trim()).toBe('Hello') }) diff --git a/test/FunctionalSFCParent.spec.js b/test/FunctionalSFCParent.spec.js index 16a4979e..16f1e9c1 100644 --- a/test/FunctionalSFCParent.spec.js +++ b/test/FunctionalSFCParent.spec.js @@ -3,5 +3,5 @@ import FunctionalSFCParent from './resources/FunctionalSFCParent.vue' test('processes .vue file with functional template from parent', () => { const wrapper = mount(FunctionalSFCParent) - expect(wrapper.text().trim()).toBe('TEST') + expect(wrapper.text().trim()).toBe('foo') }) diff --git a/test/extract-props.spec.js b/test/extract-props.spec.js new file mode 100644 index 00000000..01922a40 --- /dev/null +++ b/test/extract-props.spec.js @@ -0,0 +1,31 @@ +import extractProps from '../lib/extract-props' + +describe('when extracting props with props. prefix from functional template content', () => { + it('extracts interpolated props ', () => { + const content = '