diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap index 92164b013..11119db64 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap @@ -16,6 +16,90 @@ export function render(_ctx) { }" `; +exports[`compile > directives > custom directive > basic 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > binding value 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, _ctx.msg]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > dynamic parameters 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, _ctx.msg, _ctx.foo]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > modifiers 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, _ctx.msg, void 0, { bar: true }]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > modifiers w/o binding 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, void 0, void 0, { "foo-bar": true }]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > static parameters 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, _ctx.msg, "foo"]]) + return n0 +}" +`; + +exports[`compile > directives > custom directive > static parameters and modifiers 1`] = ` +"import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _withDirectives(n1, [[_ctx.vExample, _ctx.msg, "foo", { bar: true }]]) + return n0 +}" +`; + exports[`compile > directives > v-bind > .camel modifier 1`] = ` "import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor'; diff --git a/packages/compiler-vapor/__tests__/compile.test.ts b/packages/compiler-vapor/__tests__/compile.test.ts index 9459ac00f..95f74715e 100644 --- a/packages/compiler-vapor/__tests__/compile.test.ts +++ b/packages/compiler-vapor/__tests__/compile.test.ts @@ -332,6 +332,76 @@ describe('compile', () => { expect(code).not.contains('v-cloak') }) }) + + describe('custom directive', () => { + test('basic', async () => { + const code = await compile(``, { + bindingMetadata: { + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('binding value', async () => { + const code = await compile(``, { + bindingMetadata: { + msg: BindingTypes.SETUP_REF, + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('static parameters', async () => { + const code = await compile(``, { + bindingMetadata: { + msg: BindingTypes.SETUP_REF, + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('modifiers', async () => { + const code = await compile(``, { + bindingMetadata: { + msg: BindingTypes.SETUP_REF, + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('modifiers w/o binding', async () => { + const code = await compile(``, { + bindingMetadata: { + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('static parameters and modifiers', async () => { + const code = await compile(``, { + bindingMetadata: { + msg: BindingTypes.SETUP_REF, + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + + test('dynamic parameters', async () => { + const code = await compile(``, { + bindingMetadata: { + foo: BindingTypes.SETUP_REF, + vExample: BindingTypes.SETUP_CONST, + }, + }) + expect(code).matchSnapshot() + }) + }) }) describe('expression parsing', () => { diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 8acc18f30..fee38022b 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -10,6 +10,7 @@ import { createSimpleExpression, walkIdentifiers, advancePositionWithClone, + isSimpleIdentifier, } from '@vue/compiler-dom' import { type IRDynamicChildren, @@ -469,21 +470,38 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) { function genWithDirective(oper: WithDirectiveIRNode, context: CodegenContext) { const { push, pushWithNewline, vaporHelper, bindingMetadata } = context + const { dir } = oper // TODO merge directive for the same node pushWithNewline(`${vaporHelper('withDirectives')}(n${oper.element}, [[`) // TODO resolve directive - const directiveReference = camelize(`v-${oper.name}`) + const directiveReference = camelize(`v-${dir.name}`) if (bindingMetadata[directiveReference]) { const directiveExpression = createSimpleExpression(directiveReference) directiveExpression.ast = null genExpression(directiveExpression, context) } - if (oper.binding) { + if (dir.exp) { push(', ') - genExpression(oper.binding, context) + genExpression(dir.exp, context) + } else if (dir.arg || dir.modifiers.length) { + push(', void 0') + } + + if (dir.arg) { + push(', ') + genExpression(dir.arg, context) + } else if (dir.modifiers.length) { + push(', void 0') + } + + if (dir.modifiers.length) { + push(', ') + push('{ ') + push(genDirectiveModifiers(dir.modifiers)) + push(' }') } push(']])') return @@ -576,3 +594,12 @@ function genIdentifier( } push(id, NewlineType.None, loc, name) } + +function genDirectiveModifiers(modifiers: string[]) { + return modifiers + .map( + (value) => + `${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`, + ) + .join(', ') +} diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index bbfd6e7a4..a8c46ce16 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -117,8 +117,7 @@ export interface AppendNodeIRNode extends BaseIRNode { export interface WithDirectiveIRNode extends BaseIRNode { type: IRNodeTypes.WITH_DIRECTIVE element: number - name: string - binding: IRExpression | undefined + dir: VaporDirectiveNode } export type IRNode = diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts index b27509a28..ea468d29b 100644 --- a/packages/compiler-vapor/src/transforms/transformElement.ts +++ b/packages/compiler-vapor/src/transforms/transformElement.ts @@ -59,7 +59,7 @@ function transformProp( node: ElementNode, context: TransformContext