diff --git a/packages/babel-plugin-transform-vue-jsx/src/index.js b/packages/babel-plugin-transform-vue-jsx/src/index.js index e82cfc4..424a0a9 100644 --- a/packages/babel-plugin-transform-vue-jsx/src/index.js +++ b/packages/babel-plugin-transform-vue-jsx/src/index.js @@ -158,6 +158,9 @@ const parseAttributeJSXAttribute = (t, path, attributes, tagName, elementType) = } else { name = namePath.get('name').node } + if (prefixes.includes(name) && t.isJSXExpressionContainer(path.get('value'))) { + return t.JSXSpreadAttribute(t.objectExpression([t.objectProperty(t.stringLiteral(name), path.get('value').node.expression)])) + } ;[name, ...modifiers] = name.split('_') ;[name, argument] = name.split(':') @@ -233,16 +236,24 @@ const parseAttributeJSXSpreadAttribute = (t, path, attributes, attributesArray) * @param t * @param paths Array * @param tag Identifier | StringLiteral | MemberExpression + * @param openingElementPath JSXOpeningElement * @returns Array */ -const getAttributes = (t, paths, tag) => { +const getAttributes = (t, paths, tag, openingElementPath) => { const attributesArray = [] let attributes = {} const { tagName, canContainDomProps, elementType } = parseMagicDomPropsInfo(t, paths, tag) paths.forEach(path => { if (t.isJSXAttribute(path)) { - parseAttributeJSXAttribute(t, path, attributes, tagName, elementType) + const possibleSpreadNode = parseAttributeJSXAttribute(t, path, attributes, tagName, elementType) + if (possibleSpreadNode) { + openingElementPath.node.attributes.push(possibleSpreadNode) + const attributePaths = openingElementPath.get('attributes') + const lastAttributePath = attributePaths[attributePaths.length - 1] + attributes = parseAttributeJSXSpreadAttribute(t, lastAttributePath, attributes, attributesArray) + lastAttributePath.remove() + } return } /* istanbul ignore else */ @@ -328,7 +339,8 @@ const transformAttributes = (t, attributes) => const transformJSXElement = (t, path) => { const tag = getTag(t, path.get('openingElement')) const children = getChildren(t, path.get('children')) - const attributes = getAttributes(t, path.get('openingElement.attributes'), tag) + const openingElementPath = path.get('openingElement') + const attributes = getAttributes(t, openingElementPath.get('attributes'), tag, openingElementPath) const args = [tag] if (attributes) { diff --git a/packages/babel-plugin-transform-vue-jsx/test/snapshot.js b/packages/babel-plugin-transform-vue-jsx/test/snapshot.js index 9a2760d..7b6f90b 100644 --- a/packages/babel-plugin-transform-vue-jsx/test/snapshot.js +++ b/packages/babel-plugin-transform-vue-jsx/test/snapshot.js @@ -301,6 +301,21 @@ render(h => h("div", _mergeJSXProps([{}, spread, { } });`, }, + { + name: 'Root attribute', + from: ``, + to: `import _mergeJSXProps from "@vue/babel-helper-vue-jsx-merge-props"; +h("MyComponent", _mergeJSXProps([{ + "props": { + "prop1": "foo" + } +}, { + "props": { + prop1: 'alpha', + prop2: 'beta' + } +}]));`, + }, ] tests.forEach(({ name, from, to }) => test(name, async t => t.is(await transpile(from), to)))