From 1511d6cd609a64edb3100f9ed4e9a100d224b2e7 Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 7 Mar 2025 22:17:19 +0800 Subject: [PATCH] wip: add TransformTransition --- packages/compiler-dom/src/index.ts | 1 + .../compiler-dom/src/transforms/Transition.ts | 68 ++++++++++--------- .../transforms/TransformTransition.spec.ts | 35 +++++++++- .../TransformTransition.spec.ts.snap | 24 ++++++- packages/compiler-vapor/src/compile.ts | 2 + .../src/transforms/transformTransition.ts | 15 ++++ 6 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 packages/compiler-vapor/src/transforms/transformTransition.ts diff --git a/packages/compiler-dom/src/index.ts b/packages/compiler-dom/src/index.ts index 950901e7b..446a917ad 100644 --- a/packages/compiler-dom/src/index.ts +++ b/packages/compiler-dom/src/index.ts @@ -76,4 +76,5 @@ export { } from './errors' export { resolveModifiers } from './transforms/vOn' export { isValidHTMLNesting } from './htmlNesting' +export { postTransformTransition } from './transforms/Transition' export * from '@vue/compiler-core' diff --git a/packages/compiler-dom/src/transforms/Transition.ts b/packages/compiler-dom/src/transforms/Transition.ts index f6cf968e3..85f83adc7 100644 --- a/packages/compiler-dom/src/transforms/Transition.ts +++ b/packages/compiler-dom/src/transforms/Transition.ts @@ -1,4 +1,5 @@ import { + type CompilerError, type ComponentNode, ElementTypes, type IfBranchNode, @@ -15,40 +16,43 @@ export const transformTransition: NodeTransform = (node, context) => { ) { const component = context.isBuiltInComponent(node.tag) if (component === TRANSITION) { - return () => { - if (!node.children.length) { - return - } + return postTransformTransition(node, context.onError) + } + } +} - // warn multiple transition children - if (hasMultipleChildren(node)) { - context.onError( - createDOMCompilerError( - DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, - { - start: node.children[0].loc.start, - end: node.children[node.children.length - 1].loc.end, - source: '', - }, - ), - ) - } +export function postTransformTransition( + node: ComponentNode, + onError: (error: CompilerError) => void, +): () => void { + return () => { + if (!node.children.length) { + return + } - // check if it's s single child w/ v-show - // if yes, inject "persisted: true" to the transition props - const child = node.children[0] - if (child.type === NodeTypes.ELEMENT) { - for (const p of child.props) { - if (p.type === NodeTypes.DIRECTIVE && p.name === 'show') { - node.props.push({ - type: NodeTypes.ATTRIBUTE, - name: 'persisted', - nameLoc: node.loc, - value: undefined, - loc: node.loc, - }) - } - } + if (hasMultipleChildren(node)) { + onError( + createDOMCompilerError(DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '', + }), + ) + } + + // check if it's s single child w/ v-show + // if yes, inject "persisted: true" to the transition props + const child = node.children[0] + if (child.type === NodeTypes.ELEMENT) { + for (const p of child.props) { + if (p.type === NodeTypes.DIRECTIVE && p.name === 'show') { + node.props.push({ + type: NodeTypes.ATTRIBUTE, + name: 'persisted', + nameLoc: node.loc, + value: undefined, + loc: node.loc, + }) } } } diff --git a/packages/compiler-vapor/__tests__/transforms/TransformTransition.spec.ts b/packages/compiler-vapor/__tests__/transforms/TransformTransition.spec.ts index 3fbabe733..846179f87 100644 --- a/packages/compiler-vapor/__tests__/transforms/TransformTransition.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/TransformTransition.spec.ts @@ -5,9 +5,11 @@ import { transformText, transformVBind, transformVIf, + transformVShow, transformVSlot, } from '@vue/compiler-vapor' -import { expect } from 'vitest' +import { transformTransition } from '../../src/transforms/transformTransition' +import { DOMErrorCodes } from '@vue/compiler-dom' const compileWithElementTransform = makeCompile({ nodeTransforms: [ @@ -16,9 +18,11 @@ const compileWithElementTransform = makeCompile({ transformElement, transformVSlot, transformChildren, + transformTransition, ], directiveTransforms: { bind: transformVBind, + show: transformVShow, }, }) @@ -52,4 +56,33 @@ describe('compiler: transition', () => { // should preserve key expect(code).contains('n0.$key = _ctx.key') }) + + test('warns if multiple children', () => { + const onError = vi.fn() + compileWithElementTransform( + ` +

foo

+

bar

+
`, + { + onError, + }, + ) + expect(onError).toHaveBeenCalled() + expect(onError.mock.calls).toMatchObject([ + [{ code: DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN }], + ]) + }) + + test('inject persisted when child has v-show', () => { + expect( + compileWithElementTransform(` + +
+ + `).code, + ).toMatchSnapshot() + }) + + // TODO more tests }) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap index dd33a4ddf..4264677c7 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/TransformTransition.spec.ts.snap @@ -1,13 +1,33 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`compiler: transition > basic 1`] = ` -"import { VaporTransition as _VaporTransition, createComponent as _createComponent, template as _template } from 'vue'; +"import { VaporTransition as _VaporTransition, applyVShow as _applyVShow, createComponent as _createComponent, template as _template } from 'vue'; const t0 = _template("

foo

") export function render(_ctx) { - const n1 = _createComponent(_VaporTransition, { appear: () => ("") }, { + const n1 = _createComponent(_VaporTransition, { + appear: () => (""), + persisted: () => ("") + }, { "default": () => { const n0 = t0() + _applyVShow(n0, () => (_ctx.show)) + return n0 + } + }, true) + return n1 +}" +`; + +exports[`compiler: transition > inject persisted when child has v-show 1`] = ` +"import { VaporTransition as _VaporTransition, applyVShow as _applyVShow, createComponent as _createComponent, template as _template } from 'vue'; +const t0 = _template("
") + +export function render(_ctx) { + const n1 = _createComponent(_VaporTransition, { persisted: () => ("") }, { + "default": () => { + const n0 = t0() + _applyVShow(n0, () => (_ctx.ok)) return n0 } }, true) diff --git a/packages/compiler-vapor/src/compile.ts b/packages/compiler-vapor/src/compile.ts index f84eafcbe..04dd6543d 100644 --- a/packages/compiler-vapor/src/compile.ts +++ b/packages/compiler-vapor/src/compile.ts @@ -26,6 +26,7 @@ import { transformVFor } from './transforms/vFor' import { transformComment } from './transforms/transformComment' import { transformSlotOutlet } from './transforms/transformSlotOutlet' import { transformVSlot } from './transforms/vSlot' +import { transformTransition } from './transforms/transformTransition' import type { HackOptions } from './ir' export { wrapTemplate } from './transforms/utils' @@ -54,6 +55,7 @@ export function compile( extend({}, resolvedOptions, { nodeTransforms: [ ...nodeTransforms, + ...(__DEV__ ? [transformTransition] : []), ...(options.nodeTransforms || []), // user transforms ], directiveTransforms: extend( diff --git a/packages/compiler-vapor/src/transforms/transformTransition.ts b/packages/compiler-vapor/src/transforms/transformTransition.ts new file mode 100644 index 000000000..918666dec --- /dev/null +++ b/packages/compiler-vapor/src/transforms/transformTransition.ts @@ -0,0 +1,15 @@ +import type { NodeTransform } from '@vue/compiler-vapor' +import { ElementTypes, NodeTypes } from '@vue/compiler-core' +import { isTransitionTag } from '../utils' +import { postTransformTransition } from '@vue/compiler-dom' + +export const transformTransition: NodeTransform = (node, context) => { + if ( + node.type === NodeTypes.ELEMENT && + node.tagType === ElementTypes.COMPONENT + ) { + if (isTransitionTag(node.tag)) { + return postTransformTransition(node, context.options.onError) + } + } +}