From 3fd9fd21df6ad2bc058b3bc9ce6c02cc3a09386c Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Tue, 18 Jan 2022 13:56:47 +0800 Subject: [PATCH] wip(app): nvue --- .../__tests__/nvue/compiler.spec.ts | 74 +++++++++++++++++++ packages/uni-app-vite/src/nvue/index.ts | 2 + .../uni-app-vite/src/nvue/plugin/index.ts | 24 ++++++ .../transforms/transformAppendAsTree.ts | 31 ++++++++ .../plugin/transforms/transformRenderWhole.ts | 15 ++++ .../plugin/transforms/transformScrollView.ts | 8 ++ .../nvue/plugin/transforms/transformVideo.ts | 52 +++++++++++++ packages/uni-app-vite/src/plugin/uni/index.ts | 5 ++ .../uni/transforms/transformRenderjs.ts | 3 - packages/uni-cli-shared/src/vue/utils.ts | 15 ++++ 10 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 packages/uni-app-vite/__tests__/nvue/compiler.spec.ts create mode 100644 packages/uni-app-vite/src/nvue/plugin/transforms/transformAppendAsTree.ts create mode 100644 packages/uni-app-vite/src/nvue/plugin/transforms/transformRenderWhole.ts create mode 100644 packages/uni-app-vite/src/nvue/plugin/transforms/transformScrollView.ts create mode 100644 packages/uni-app-vite/src/nvue/plugin/transforms/transformVideo.ts delete mode 100644 packages/uni-app-vite/src/plugin/uni/transforms/transformRenderjs.ts diff --git a/packages/uni-app-vite/__tests__/nvue/compiler.spec.ts b/packages/uni-app-vite/__tests__/nvue/compiler.spec.ts new file mode 100644 index 000000000..18ba700a2 --- /dev/null +++ b/packages/uni-app-vite/__tests__/nvue/compiler.spec.ts @@ -0,0 +1,74 @@ +import { + DirectiveNode, + ElementNode, + findDir, + findProp, + SimpleExpressionNode, +} from '@vue/compiler-core' +import { compileTemplate } from '@vue/compiler-sfc' +import { uniOptions } from '../../src/plugin/uni/index' +process.env.UNI_COMPILER = 'nvue' +const { compilerOptions } = uniOptions()! +const filename = 'foo.vue' + +function compile(source: string) { + return compileTemplate({ + source, + filename, + id: filename, + compilerOptions: { + ...compilerOptions, + }, + }).ast!.children[0] as ElementNode +} +describe('app-nvue: compiler', () => { + test('u-tags', () => { + ;[ + 'text', + 'image', + 'input', + 'textarea', + 'video', + 'web-view', + 'slider', + ].forEach((tag) => { + expect(compile(`<${tag}>`).tag).toBe(`u-${tag}`) + }) + }) + test('video', () => { + expect(compile(``).children.length).toBe(0) + expect( + (compile(``).children[0] as ElementNode).tag + ).toBe('u-scalable') + }) + test('scroll-view', () => { + compile(``) + }) + test('render-whole', () => { + expect( + ( + ( + findProp( + compile(`hello`), + 'appendAsTree', + true, + false + ) as DirectiveNode + ).arg as SimpleExpressionNode + ).content + ).toBe('appendAsTree') + }) + test('unitary tag', () => { + expect( + findProp(compile(`hello`), 'appendAsTree', true, false) + ).toBeTruthy() + }) + test('tap=>click', () => { + expect( + ( + findDir(compile(``), 'on')! + .arg as SimpleExpressionNode + ).content + ).toBe('click') + }) +}) diff --git a/packages/uni-app-vite/src/nvue/index.ts b/packages/uni-app-vite/src/nvue/index.ts index 5542141fa..9e550ccc0 100644 --- a/packages/uni-app-vite/src/nvue/index.ts +++ b/packages/uni-app-vite/src/nvue/index.ts @@ -13,6 +13,8 @@ import { uniEsbuildPlugin } from './plugins/esbuild' import { uniMainJsPlugin } from './plugins/mainJs' import { uniPagesJsonPlugin } from './plugins/pagesJson' +export { initNVueNodeTransforms } from './plugin' + export function initNVuePlugins() { return [ uniEasycomPlugin({ exclude: UNI_EASYCOM_EXCLUDE }), diff --git a/packages/uni-app-vite/src/nvue/plugin/index.ts b/packages/uni-app-vite/src/nvue/plugin/index.ts index 94eba435a..1b3b3c293 100644 --- a/packages/uni-app-vite/src/nvue/plugin/index.ts +++ b/packages/uni-app-vite/src/nvue/plugin/index.ts @@ -1,5 +1,6 @@ import path from 'path' import { + createTransformTag, dynamicImportPolyfill, normalizePath, parseVueRequest, @@ -9,6 +10,29 @@ import { import { PreRenderedChunk } from 'rollup' import { Plugin } from 'vite' import { nvueOutDir } from '../../utils' +import { transformRenderWhole } from './transforms/transformRenderWhole' +import { transformAppendAsTree } from './transforms/transformAppendAsTree' +import { transformVideo } from './transforms/transformVideo' +const uTags = { + text: 'u-text', + image: 'u-image', + input: 'u-input', + textarea: 'u-textarea', + video: 'u-video', + 'web-view': 'u-web-view', + slider: 'u-slider', +} + +export function initNVueNodeTransforms() { + // 优先级必须确保 renderWhole > appendAsTree + return [ + createTransformTag(uTags), + transformVideo, + transformRenderWhole, + transformAppendAsTree, + ] +} + export function uniAppNVuePlugin(): Plugin { return { name: 'uni:app-nvue', diff --git a/packages/uni-app-vite/src/nvue/plugin/transforms/transformAppendAsTree.ts b/packages/uni-app-vite/src/nvue/plugin/transforms/transformAppendAsTree.ts new file mode 100644 index 000000000..22a592ee2 --- /dev/null +++ b/packages/uni-app-vite/src/nvue/plugin/transforms/transformAppendAsTree.ts @@ -0,0 +1,31 @@ +import { + createBindDirectiveNode, + isElementNode, + renameProp, +} from '@dcloudio/uni-cli-shared' +import { findProp, NodeTransform } from '@vue/compiler-core' + +const unitaryTags = [ + 'cell', + 'header', + 'cell-slot', + 'recycle-list', + 'text', + 'u-text', +] + +export const transformAppendAsTree: NodeTransform = (node, _) => { + if (!isElementNode(node)) { + return + } + // append => appendAsTree: true + const appendProp = findProp(node, 'append') + if (appendProp) { + renameProp('appendAsTree', appendProp) + return + } + if (!unitaryTags.includes(node.tag)) { + return + } + node.props.push(createBindDirectiveNode('appendAsTree', 'true')) +} diff --git a/packages/uni-app-vite/src/nvue/plugin/transforms/transformRenderWhole.ts b/packages/uni-app-vite/src/nvue/plugin/transforms/transformRenderWhole.ts new file mode 100644 index 000000000..4a5c117ce --- /dev/null +++ b/packages/uni-app-vite/src/nvue/plugin/transforms/transformRenderWhole.ts @@ -0,0 +1,15 @@ +import { renameProp, isElementNode } from '@dcloudio/uni-cli-shared' +import { findProp, NodeTransform } from '@vue/compiler-core' + +export const transformRenderWhole: NodeTransform = (node, _) => { + if (!isElementNode(node)) { + return + } + debugger + const prop = findProp(node, 'render-whole') + if (!prop) { + return + } + // render-whole => append + renameProp('append', prop) +} diff --git a/packages/uni-app-vite/src/nvue/plugin/transforms/transformScrollView.ts b/packages/uni-app-vite/src/nvue/plugin/transforms/transformScrollView.ts new file mode 100644 index 000000000..1d6f77b00 --- /dev/null +++ b/packages/uni-app-vite/src/nvue/plugin/transforms/transformScrollView.ts @@ -0,0 +1,8 @@ +import { NodeTransform, NodeTypes } from '@vue/compiler-core' + +export const transformScrollView: NodeTransform = (node, context) => { + if (node.type !== NodeTypes.ROOT) { + return + } + console.log(context) +} diff --git a/packages/uni-app-vite/src/nvue/plugin/transforms/transformVideo.ts b/packages/uni-app-vite/src/nvue/plugin/transforms/transformVideo.ts new file mode 100644 index 000000000..5e2d64e44 --- /dev/null +++ b/packages/uni-app-vite/src/nvue/plugin/transforms/transformVideo.ts @@ -0,0 +1,52 @@ +import { + createBindDirectiveNode, + isElementNode, +} from '@dcloudio/uni-cli-shared' +import { + createSimpleExpression, + ElementNode, + ElementTypes, + NodeTransform, + NodeTypes, +} from '@vue/compiler-core' + +function isVideo(node: ElementNode) { + return node.tag === 'video' || node.tag === 'u-video' +} + +export const transformVideo: NodeTransform = (node, _) => { + if (!isElementNode(node)) { + return + } + if (!isVideo(node)) { + return + } + if (!node.children.length) { + return + } + const firstChild = node.children[0] + if (isElementNode(firstChild) && firstChild.tag === 'u-scalable') { + return + } + node.children = [createScalable(node)] +} +function createScalable(node: ElementNode): ElementNode { + return { + tag: 'u-scalable', + type: NodeTypes.ELEMENT, + tagType: ElementTypes.ELEMENT, + props: [ + createBindDirectiveNode( + 'style', + createSimpleExpression( + '{position:"absolute",left:"0",right:"0",top:"0",bottom:"0"}' + ) + ), + ], + isSelfClosing: true, + children: node.children, + codegenNode: undefined, + ns: node.ns, + loc: node.loc, + } +} diff --git a/packages/uni-app-vite/src/plugin/uni/index.ts b/packages/uni-app-vite/src/plugin/uni/index.ts index ea2fe5de8..501bf680b 100644 --- a/packages/uni-app-vite/src/plugin/uni/index.ts +++ b/packages/uni-app-vite/src/plugin/uni/index.ts @@ -9,6 +9,8 @@ import { UniViteCopyPluginOptions, } from '@dcloudio/uni-cli-shared' +import { initNVueNodeTransforms } from '../../nvue' + export function uniOptions(): UniVitePlugin['uni'] { return { copyOptions() { @@ -38,6 +40,9 @@ export function uniOptions(): UniVitePlugin['uni'] { compilerOptions: { isNativeTag, nodeTransforms: [ + ...(process.env.UNI_COMPILER === 'nvue' + ? initNVueNodeTransforms() + : []), transformTapToClick, transformMatchMedia, transformPageHead, diff --git a/packages/uni-app-vite/src/plugin/uni/transforms/transformRenderjs.ts b/packages/uni-app-vite/src/plugin/uni/transforms/transformRenderjs.ts deleted file mode 100644 index ab60aa83c..000000000 --- a/packages/uni-app-vite/src/plugin/uni/transforms/transformRenderjs.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { NodeTransform } from '@vue/compiler-core' - -export const transformRenderjs: NodeTransform = () => {} diff --git a/packages/uni-cli-shared/src/vue/utils.ts b/packages/uni-cli-shared/src/vue/utils.ts index 74787ce46..cafe28931 100644 --- a/packages/uni-cli-shared/src/vue/utils.ts +++ b/packages/uni-cli-shared/src/vue/utils.ts @@ -14,9 +14,11 @@ import { ExpressionNode, TemplateChildNode, TransformContext, + isStaticExp, } from '@vue/compiler-core' import { createAssetUrlTransformWithOptions } from './transforms/templateTransformAssetUrl' import { createSrcsetTransformWithOptions } from './transforms/templateTransformSrcset' +import { isDirectiveNode } from '../vite/utils/ast' import { parseVueRequest } from '../vite/utils/url' import { EXTNAME_VUE_RE } from '../constants' @@ -137,3 +139,16 @@ export function getBaseNodeTransforms(base: string) { createSrcsetTransformWithOptions(transformAssetUrls), ] } + +export function renameProp(name: string, prop?: DirectiveNode | AttributeNode) { + if (!prop) { + return + } + if (isDirectiveNode(prop)) { + if (prop.arg && isStaticExp(prop.arg)) { + prop.arg.content = name + } + } else { + prop.name = name + } +} -- GitLab