]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat: camel modifier for `v-bind` (#39)
authorRizumu Ayaka <rizumu@ayaka.moe>
Sat, 9 Dec 2023 10:41:59 +0000 (18:41 +0800)
committerGitHub <noreply@github.com>
Sat, 9 Dec 2023 10:41:59 +0000 (18:41 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
packages/compiler-vapor/src/generate.ts
packages/compiler-vapor/src/ir.ts
packages/compiler-vapor/src/transforms/vBind.ts

index 3352803132f521f87e079b1dacada0c0fc9f7c17..0c115735cf5d6875d5a3f4c029c2ec4b6006ac84 100644 (file)
@@ -8,7 +8,7 @@ export function render(_ctx) {
   const n0 = t0()
   const { 0: [n1],} = _children(n0)
   _effect(() => {
-    _setAttr(n1, "foo-bar", undefined, _ctx.id)
+    _setAttr(n1, "fooBar", undefined, _ctx.id)
   })
   return n0
 }"
index fbaf2b0891d791e28ffb898a97d3505a290e4d79..416f65c4eba27fcdb93aec1c751b8a7a9cb34c84 100644 (file)
@@ -165,7 +165,7 @@ describe('compiler: transform v-bind', () => {
     })
   })
 
-  test.fails('.camel modifier', () => {
+  test('.camel modifier', () => {
     const node = parseWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
     expect(node.effect[0].operations[0]).toMatchObject({
       key: {
@@ -179,7 +179,7 @@ describe('compiler: transform v-bind', () => {
     })
   })
 
-  test.fails('.camel modifier w/ no expression', () => {
+  test('.camel modifier w/ no expression', () => {
     const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
     expect(node.effect[0].operations[0]).toMatchObject({
       key: {
@@ -193,13 +193,13 @@ describe('compiler: transform v-bind', () => {
     })
   })
 
-  test.fails('.camel modifier w/ dynamic arg', () => {
+  test('.camel modifier w/ dynamic arg', () => {
     const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
     expect(node.effect[0].operations[0]).toMatchObject({
+      runtimeCamelize: true,
       key: {
         content: `foo`,
         isStatic: false,
-        somethingShouldBeTrue: true,
       },
       value: {
         content: `id`,
@@ -289,8 +289,7 @@ describe('compiler: codegen v-bind', () => {
     expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
   })
 
-  // TODO: camel modifier for v-bind
-  test.fails('.camel modifier', () => {
+  test('.camel modifier', () => {
     const code = compile(`<div v-bind:foo-bar.camel="id"/>`)
 
     expect(code).matchSnapshot()
index d92def7fe2f2500df46e6e42a61205a72ab2c675..4bce56044d561aa359ea2d0f411886aa4cbc541a 100644 (file)
@@ -370,9 +370,11 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
 }
 
 function genSetProp(oper: SetPropIRNode, context: CodegenContext) {
-  const { push, pushWithNewline, vaporHelper } = context
+  const { push, pushWithNewline, vaporHelper, helper } = context
   pushWithNewline(`${vaporHelper('setAttr')}(n${oper.element}, `)
+  if (oper.runtimeCamelize) push(`${helper('camelize')}(`)
   genExpression(oper.key, context)
+  if (oper.runtimeCamelize) push(`)`)
   push(`, undefined, `)
   genExpression(oper.value, context)
   push(')')
index 172f32fd7e8f1ae89b7b09f20037568587628dc3..979536af80d3e1575ad5928ebddbf104ade3502d 100644 (file)
@@ -60,6 +60,7 @@ export interface SetPropIRNode extends BaseIRNode {
   element: number
   key: IRExpression
   value: IRExpression
+  runtimeCamelize: boolean
 }
 
 export interface SetTextIRNode extends BaseIRNode {
index 6bd4cc939a2a29b9a656b6f7d9b2751626fd1c09..84fd1ac43825efe099bb62c724957cb42ea75022 100644 (file)
@@ -8,7 +8,7 @@ import { IRNodeTypes } from '../ir'
 import type { DirectiveTransform } from '../transform'
 
 export const transformVBind: DirectiveTransform = (dir, node, context) => {
-  let { arg, exp, loc } = dir
+  let { arg, exp, loc, modifiers } = dir
 
   if (!arg) {
     // TODO support v-bind="{}"
@@ -21,6 +21,15 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
     exp.ast = null
   }
 
+  let camel = false
+  if (modifiers.includes('camel')) {
+    if (arg.isStatic) {
+      arg.content = camelize(arg.content)
+    } else {
+      camel = true
+    }
+  }
+
   if (!exp.content.trim()) {
     context.options.onError(
       createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
@@ -38,6 +47,7 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
         element: context.reference(),
         key: arg,
         value: exp,
+        runtimeCamelize: camel,
       },
     ],
   )