Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
test('working with v-bind transform', () => {
const { node } = transformWithStyleTransform(`<div style="color: red">`, {
nodeTransforms: [transformStyle, transformElement],
directiveTransforms: {
bind: transformBind
}
})
expect((node.codegenNode as CallExpression).arguments[1]).toMatchObject({
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
key: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `style`,
isStatic: true
},
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`,
isStatic: false
}
}
]
})
// should not cause the STYLE patchFlag to be attached</div>
test('cache handler w/ modifiers', () => {
const {
root,
props: [prop]
} = parseWithVOn(`<div>`, {
prefixIdentifiers: true,
cacheHandlers: true
})
expect(root.cached).toBe(1)
// should not treat cached handler as dynamicProp, so no flags
expect((root as any).children[0].codegenNode.arguments.length).toBe(2)
expect(prop.value).toMatchObject({
type: NodeTypes.JS_CACHE_EXPRESSION,
index: 1,
value: {
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
key: { content: 'handler' },
value: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: V_ON_WITH_KEYS
}
},
{
key: { content: 'options' },
value: { type: NodeTypes.JS_OBJECT_EXPRESSION }
}
]
}
})
})</div>
export const transformSrcset: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) {
if (srcsetTags.includes(node.tag) && node.props.length) {
node.props.forEach((attr, index) => {
if (attr.name === 'srcset' && attr.type === NodeTypes.ATTRIBUTE) {
if (!attr.value) return
// same logic as in transform-require.js
const value = attr.value.content
const imageCandidates: ImageCandidate[] = value.split(',').map(s => {
// The attribute value arrives here with all whitespace, except
// normal spaces, represented by escape sequences
const [url, descriptor] = s
.replace(escapedSpaceCharacters, ' ')
.trim()
.split(' ', 2)
return { url, descriptor }
})
node.props.forEach((attr, index) => {
if (attr.name === 'srcset' && attr.type === NodeTypes.ATTRIBUTE) {
if (!attr.value) return
// same logic as in transform-require.js
const value = attr.value.content
const imageCandidates: ImageCandidate[] = value.split(',').map(s => {
// The attribute value arrives here with all whitespace, except
// normal spaces, represented by escape sequences
const [url, descriptor] = s
.replace(escapedSpaceCharacters, ' ')
.trim()
.split(' ', 2)
return { url, descriptor }
})
const compoundExpression = createCompoundExpression([], attr.loc)
imageCandidates.forEach(({ url, descriptor }, index) => {
export const transformStyle: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) {
node.props.forEach((p, i) => {
if (p.type === NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) {
// replace p with an expression node
const parsed = JSON.stringify(parseInlineCSS(p.value.content))
const exp = context.hoist(createSimpleExpression(parsed, false, p.loc))
node.props[i] = {
type: NodeTypes.DIRECTIVE,
name: `bind`,
arg: createSimpleExpression(`style`, true, p.loc),
exp,
modifiers: [],
loc: p.loc
}
}
})
}
keyModifiers.length &&
// if event name is dynamic, always wrap with keys guard
(key.type === NodeTypes.COMPOUND_EXPRESSION ||
!key.isStatic ||
isKeyboardEvent(key.content))
) {
handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [
handlerExp,
JSON.stringify(keyModifiers)
])
}
if (eventOptionModifiers.length) {
handlerExp = createObjectExpression([
createObjectProperty('handler', handlerExp),
createObjectProperty(
'options',
createObjectExpression(
eventOptionModifiers.map(modifier =>
createObjectProperty(
modifier,
createSimpleExpression('true', false)
)
)
)
)
])
}
return {
props: [createObjectProperty(key, handlerExp)],
needRuntime: false
if (
keyModifiers.length &&
// if event name is dynamic, always wrap with keys guard
(key.type === NodeTypes.COMPOUND_EXPRESSION ||
!key.isStatic ||
isKeyboardEvent(key.content))
) {
handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [
handlerExp,
JSON.stringify(keyModifiers)
])
}
if (eventOptionModifiers.length) {
handlerExp = createObjectExpression([
createObjectProperty('handler', handlerExp),
createObjectProperty(
'options',
createObjectExpression(
eventOptionModifiers.map(modifier =>
createObjectProperty(
modifier,
createSimpleExpression('true', false)
)
)
)
)
])
}
return {
props: [createObjectProperty(key, handlerExp)],
node.props.forEach((p, i) => {
if (p.type === NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) {
// replace p with an expression node
const parsed = JSON.stringify(parseInlineCSS(p.value.content))
const exp = context.hoist(createSimpleExpression(parsed, false, p.loc))
node.props[i] = {
type: NodeTypes.DIRECTIVE,
name: `bind`,
arg: createSimpleExpression(`style`, true, p.loc),
exp,
modifiers: [],
loc: p.loc
}
}
})
}
node.props.forEach((p, i) => {
if (p.type === NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) {
// replace p with an expression node
const parsed = JSON.stringify(parseInlineCSS(p.value.content))
const exp = context.hoist(createSimpleExpression(parsed, false, p.loc))
node.props[i] = {
type: NodeTypes.DIRECTIVE,
name: `bind`,
arg: createSimpleExpression(`style`, true, p.loc),
exp,
modifiers: [],
loc: p.loc
}
}
})
}
if (dir.arg) {
context.onError(
createDOMCompilerError(
DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
dir.arg.loc
)
)
}
if (tag === 'input' || tag === 'textarea' || tag === 'select') {
let directiveToUse = V_MODEL_TEXT
let isInvalidType = false
if (tag === 'input') {
const type = findProp(node, `type`)
if (type) {
if (type.type === NodeTypes.DIRECTIVE) {
// :type="foo"
directiveToUse = V_MODEL_DYNAMIC
} else if (type.value) {
switch (type.value.content) {
case 'radio':
directiveToUse = V_MODEL_RADIO
break
case 'checkbox':
directiveToUse = V_MODEL_CHECKBOX
break
case 'file':
isInvalidType = true
context.onError(
createDOMCompilerError(
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
dir.loc