提交 3fd9fd21 编写于 作者: fxy060608's avatar fxy060608

wip(app): nvue

上级 0366dac7
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}>`).tag).toBe(`u-${tag}`)
})
})
test('video', () => {
expect(compile(`<video></video>`).children.length).toBe(0)
expect(
(compile(`<video><view></view></video>`).children[0] as ElementNode).tag
).toBe('u-scalable')
})
test('scroll-view', () => {
compile(`<view></view>`)
})
test('render-whole', () => {
expect(
(
(
findProp(
compile(`<view :render-whole="true">hello</view>`),
'appendAsTree',
true,
false
) as DirectiveNode
).arg as SimpleExpressionNode
).content
).toBe('appendAsTree')
})
test('unitary tag', () => {
expect(
findProp(compile(`<text>hello</text>`), 'appendAsTree', true, false)
).toBeTruthy()
})
test('tap=>click', () => {
expect(
(
findDir(compile(`<view @tap="click"></view>`), 'on')!
.arg as SimpleExpressionNode
).content
).toBe('click')
})
})
......@@ -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 }),
......
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',
......
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'))
}
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)
}
import { NodeTransform, NodeTypes } from '@vue/compiler-core'
export const transformScrollView: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.ROOT) {
return
}
console.log(context)
}
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,
}
}
......@@ -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,
......
import type { NodeTransform } from '@vue/compiler-core'
export const transformRenderjs: NodeTransform = () => {}
......@@ -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
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册