Skip to content

Commit cf880cb

Browse files
authored
Merge pull request #7 from nickmessing/feat/support-argument-and-modifiers
feat: add support for argument and modifiers for directives
2 parents 8f56240 + b1c8036 commit cf880cb

File tree

2 files changed

+51
-26
lines changed

2 files changed

+51
-26
lines changed

packages/babel-plugin-transform-vue-jsx/src/index.js

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ const mustUseDomProps = (tag, type, attributeName) => {
2424
)
2525
}
2626

27+
/**
28+
* Checks if string is describing a directive
29+
* @param src string
30+
*/
31+
const isDirective = src =>
32+
src.startsWith(`v-`) || (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z')
33+
2734
/**
2835
* Get tag (first attribute for h) from JSXOpeningElement
2936
* @param t
@@ -128,16 +135,21 @@ const parseAttributeJSXAttribute = (t, path, attributes, tagName, elementType) =
128135
const namePath = path.get('name')
129136
let prefix
130137
let name
131-
/* istanbul ignore else */
132-
if (t.isJSXIdentifier(namePath)) {
133-
name = path.get('name.name').node
134-
prefix = prefixes.find(el => name.startsWith(el)) || 'attrs'
135-
name = name.replace(new RegExp(`^${prefix}\-?`), '')
136-
name = name[0].toLowerCase() + name.substr(1)
138+
let modifiers
139+
let argument
140+
if (t.isJSXNamespacedName(namePath)) {
141+
name = `${namePath.get('namespace.name').node}:${namePath.get('name.name').node}`
137142
} else {
138-
throw new Error(`getAttributes (attribute name): ${namePath.type} is not supported`)
143+
name = namePath.get('name').node
139144
}
140145

146+
;[name, ...modifiers] = name.split('_')
147+
;[name, argument] = name.split(':')
148+
149+
prefix = prefixes.find(el => name.startsWith(el)) || 'attrs'
150+
name = name.replace(new RegExp(`^${prefix}\-?`), '')
151+
name = name[0].toLowerCase() + name.substr(1)
152+
141153
const valuePath = path.get('value')
142154
let value
143155
if (!valuePath.node) {
@@ -156,13 +168,13 @@ const parseAttributeJSXAttribute = (t, path, attributes, tagName, elementType) =
156168
}
157169
}
158170

171+
value._argument = argument
172+
value._modifiers = modifiers
173+
159174
if (rootAttributes.includes(name)) {
160175
attributes[name] = value
161176
} else {
162-
if (name.startsWith(`v-`)) {
163-
name = name.replace(directiveRE, '')
164-
prefix = 'directives'
165-
} else if (name.startsWith('v') && name.length >= 2 && name[1] >= 'A' && name[1] <= 'Z') {
177+
if (isDirective(name)) {
166178
name = kebabcase(name.substr(1))
167179
prefix = 'directives'
168180
}
@@ -255,6 +267,21 @@ const transformDirectives = (t, directives) =>
255267
t.objectExpression([
256268
t.objectProperty(t.identifier('name'), directive.key),
257269
t.objectProperty(t.identifier('value'), directive.value),
270+
...(directive.value._argument
271+
? [t.objectProperty(t.identifier('arg'), t.stringLiteral(directive.value._argument))]
272+
: []),
273+
...(directive.value._modifiers && directive.value._modifiers.length > 0
274+
? [
275+
t.objectProperty(
276+
t.identifier('modifiers'),
277+
t.objectExpression(
278+
directive.value._modifiers.map(modifier =>
279+
t.objectProperty(t.stringLiteral(modifier), t.booleanLiteral(true)),
280+
),
281+
),
282+
),
283+
]
284+
: []),
258285
]),
259286
),
260287
)

packages/babel-plugin-transform-vue-jsx/test/snapshot.js

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,25 @@ render(h => h("div", _mergeJSXProps([{}, spread, {
215215
},
216216
{
217217
name: 'Directives',
218-
from: `render(h => <div v-test={ 123 } vOtherStuff={ 234 } />)`,
218+
from: `render(h => <div v-test={ 123 } vSomething_modifier={ 1234 } vOtherStuff:argument_modifier1_modifier2={ 234 } />)`,
219219
to: `render(h => h("div", {
220220
"directives": [{
221221
name: "test",
222222
value: 123
223+
}, {
224+
name: "something",
225+
value: 1234,
226+
modifiers: {
227+
"modifier": true
228+
}
223229
}, {
224230
name: "other-stuff",
225-
value: 234
231+
value: 234,
232+
arg: "argument",
233+
modifiers: {
234+
"modifier1": true,
235+
"modifier2": true
236+
}
226237
}]
227238
}));`,
228239
},
@@ -278,19 +289,6 @@ render(h => h("div", _mergeJSXProps([{}, spread, {
278289

279290
tests.forEach(({ name, from, to }) => test(name, async t => t.is(await transpile(from), to)))
280291

281-
test('JSXNamespacedName attribute name throws error', t =>
282-
new Promise(resolve => {
283-
transpile(`render(h => <a a:b="test" />)`)
284-
.then(() => {
285-
t.fail()
286-
resolve()
287-
})
288-
.catch(e => {
289-
t.is(e.message, 'getAttributes (attribute name): JSXNamespacedName is not supported')
290-
resolve()
291-
})
292-
}))
293-
294292
test('JSXElement attribute value throws error', t =>
295293
new Promise(resolve => {
296294
transpile(`render(h => <a key=<b/> />)`)

0 commit comments

Comments
 (0)