提交 5c86f67a 编写于 作者: fxy060608's avatar fxy060608

feat: support block

上级 721feb16
......@@ -75,6 +75,9 @@ const passiveOptions = passive(true);
export default /*#__PURE__*/ {
name: "ScrollView",
compatConfig: {
MODE: 3
},
mixins: [scroller],
props: {
scrollX: {
......
......@@ -3880,7 +3880,7 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
instance.render = render;
}
// fixed by xxxxxx
const customApplyOptions = ctx.$applyOptions;
const customApplyOptions = instance.appContext.config.globalProperties.$applyOptions;
if (customApplyOptions) {
customApplyOptions(options, instance, publicThis);
}
......
......@@ -4437,7 +4437,7 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
instance.render = render;
}
// fixed by xxxxxx
const customApplyOptions = ctx.$applyOptions;
const customApplyOptions = instance.appContext.config.globalProperties.$applyOptions;
if (customApplyOptions) {
customApplyOptions(options, instance, publicThis);
}
......
......@@ -4431,7 +4431,7 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
instance.render = render;
}
// fixed by xxxxxx
const customApplyOptions = ctx.$applyOptions;
const customApplyOptions = instance.appContext.config.globalProperties.$applyOptions;
if (customApplyOptions) {
customApplyOptions(options, instance, publicThis);
}
......
......@@ -3872,7 +3872,7 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
instance.render = render;
}
// fixed by xxxxxx
const customApplyOptions = ctx.$applyOptions;
const customApplyOptions = instance.appContext.config.globalProperties.$applyOptions;
if (customApplyOptions) {
customApplyOptions(options, instance, publicThis);
}
......
......@@ -6657,6 +6657,9 @@ var scroller = {
const passiveOptions = uniShared.passive(true);
const _sfc_main$4 = {
name: "ScrollView",
compatConfig: {
MODE: 3
},
mixins: [scroller],
props: {
scrollX: {
......@@ -10038,6 +10041,9 @@ const selectorType = {
};
var _sfc_main$1 = {
name: "Picker",
compatConfig: {
MODE: 3
},
components: {PickerView, PickerViewColumn},
props: {
name: {
......
......@@ -11492,6 +11492,9 @@ var scroller = {
const passiveOptions = passive(true);
const _sfc_main$4 = {
name: "ScrollView",
compatConfig: {
MODE: 3
},
mixins: [scroller],
props: {
scrollX: {
......@@ -18394,6 +18397,9 @@ const selectorType = {
};
var _sfc_main$1 = {
name: "Picker",
compatConfig: {
MODE: 3
},
components: {PickerView, PickerViewColumn},
props: {
name: {
......
......@@ -160,6 +160,9 @@ const selectorType = {
};
export default {
name: "Picker",
compatConfig: {
MODE: 3
},
components: { PickerView, PickerViewColumn },
props: {
name: {
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`block normalizeBlockCode 1`] = `
"<template><view><template></template></view></template>
<script>
export default {}
</script>
<style></style>
"
`;
exports[`block normalizeBlockCode 2`] = `
"<template><view><template v-if=\\"a\\">a</template><template v-else>b</template></view></template>
<script>
export default {}
</script>
<style></style>
"
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`wxs normalizeWxsCode 1`] = `
Array [
Array [],
"<template><view></view><view></view></template>
<script>
export default {}
</script>
<renderjs name=\\"echarts\\">
export default{
mounted(){
console.log('mounted')
}
"<template><view></view><view></view></template>
<script>
export default {}
</script>
<renderjs name=\\"echarts\\">
export default{
mounted(){
console.log('mounted')
}
</renderjs>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
",
]
}
</renderjs>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
"
`;
exports[`wxs normalizeWxsCode 2`] = `
Array [
Array [],
"<template><view></view><view></view></template>
<script>
export default {}
</script>
<wxs name=\\"echarts\\">
export default{
mounted(){
console.log('mounted')
}
}
</wxs>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
"<template><view></view><view></view></template>
<script>
export default {}
</script>
<wxs name=\\"echarts\\">
export default{
mounted(){
console.log('mounted')
}
</style>
",
]
}
</wxs>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
"
`;
import { parseVue } from '../src/utils'
import { normalizeBlockCode } from '../src/configResolved/plugins/preVue'
describe('block', () => {
test('normalizeBlockCode', () => {
const blockCode1 = `<template><view><block></block></view></template>
<script>
export default {}
</script>
<style></style>
`
expect(
normalizeBlockCode(parseVue(blockCode1, []), blockCode1)
).toMatchSnapshot()
const blockCode2 = `<template><view><block v-if="a">a</block><block v-else>b</block></view></template>
<script>
export default {}
</script>
<style></style>
`
expect(
normalizeBlockCode(parseVue(blockCode2, []), blockCode2)
).toMatchSnapshot()
})
})
import { parseVue } from '../src/utils'
import { normalizeWxsCode } from '../src/configResolved/plugins/preVue'
describe('wxs', () => {
test('normalizeWxsCode', () => {
expect(
normalizeWxsCode(`<template><view></view><view></view></template>
<script>
export default {}
</script>
<script lang="renderjs" module="echarts">
export default{
mounted(){
console.log('mounted')
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
const renderjsCode = `<template><view></view><view></view></template>
<script>
export default {}
</script>
<script lang="renderjs" module="echarts">
export default{
mounted(){
console.log('mounted')
}
</style>
`)
).toMatchSnapshot()
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
`
expect(
normalizeWxsCode(`<template><view></view><view></view></template>
<script>
export default {}
</script>
<script lang="wxs" module="echarts">
export default{
mounted(){
console.log('mounted')
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
`)
normalizeWxsCode(parseVue(renderjsCode, []), renderjsCode)
).toMatchSnapshot()
const wxsCode = `<template><view></view><view></view></template>
<script>
export default {}
</script>
<script lang="wxs" module="echarts">
export default{
mounted(){
console.log('mounted')
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
`
expect(normalizeWxsCode(parseVue(wxsCode, []), wxsCode)).toMatchSnapshot()
})
})
......@@ -2,17 +2,22 @@ import path from 'path'
import debug from 'debug'
import { Plugin } from 'vite'
import {
TextModes,
RootNode,
NodeTypes,
ParentNode,
ElementNode,
AttributeNode,
TemplateChildNode,
} from '@vue/compiler-core'
import { parse } from '@vue/compiler-dom'
import { MagicString } from '@vue/compiler-sfc'
import { EXTNAME_VUE, parseVueRequest } from '@dcloudio/uni-cli-shared'
import { isElementNode, parseVue } from '../../utils'
const debugPreVue = debug('vite:uni:pre-vue')
const BLOCK_RE = /<\/block>/
const WXS_LANG_RE = /lang=["|'](renderjs|wxs)["|']/
const WXS_ATTRS = ['wxs', 'renderjs']
......@@ -30,36 +35,84 @@ export function uniPreVuePlugin(): Plugin {
if (!EXTNAME_VUE.includes(path.extname(filename))) {
return
}
if (!WXS_LANG_RE.test(code)) {
return
}
const sourceKey = code + filename
const cache = sourceToSFC.get(sourceKey)
if (cache) {
debugPreVue('cache', id)
return cache
}
const hasBlock = BLOCK_RE.test(code)
const hasWxs = WXS_LANG_RE.test(code)
if (!hasBlock && !hasWxs) {
return
}
debugPreVue(id)
const [errors, wxsCode] = normalizeWxsCode(code)
const errors: SyntaxError[] = []
const ast = parseVue(code, errors)
if (hasBlock) {
code = normalizeBlockCode(ast, code)
}
if (hasWxs) {
code = normalizeWxsCode(ast, code)
}
if (errors.length) {
this.error(errors.join('\n'))
}
sourceToSFC.set(sourceKey, wxsCode)
return wxsCode
sourceToSFC.set(sourceKey, code)
return code // 暂不提供sourcemap,意义不大
},
}
}
export function normalizeWxsCode(code: string): [SyntaxError[], string] {
const errors: SyntaxError[] = []
const ast = parse(code, {
isNativeTag: () => true,
isPreTag: () => true,
getTextMode: () => TextModes.DATA,
onError: (e) => {
errors.push(e)
},
function traverseChildren({ children }: ParentNode, blockNodes: ElementNode[]) {
children.forEach((node) => traverseNode(node, blockNodes))
}
function traverseNode(
node: RootNode | TemplateChildNode,
blockNodes: ElementNode[]
) {
if (isElementNode(node) && node.tag === 'block') {
blockNodes.push(node)
}
if (
node.type === NodeTypes.IF_BRANCH ||
node.type === NodeTypes.FOR ||
node.type === NodeTypes.ELEMENT ||
node.type === NodeTypes.ROOT
) {
traverseChildren(node, blockNodes)
}
}
export function normalizeBlockCode(ast: RootNode, code: string) {
const blockNodes: ElementNode[] = []
traverseNode(ast, blockNodes)
if (blockNodes.length) {
return normalizeBlockNode(code, blockNodes)
}
return code
}
const BLOCK_END_LEN = '</block>'.length
const BLOCK_START_LEN = '<block'.length
function normalizeBlockNode(code: string, blocks: ElementNode[]) {
const magicString = new MagicString(code)
blocks.forEach(({ loc }) => {
const startOffset = loc.start.offset
const endOffset = loc.end.offset
magicString.overwrite(
startOffset,
startOffset + BLOCK_START_LEN,
'<template'
)
magicString.overwrite(endOffset - BLOCK_END_LEN, endOffset, '</template>')
})
return magicString.toString()
}
export function normalizeWxsCode(ast: RootNode, code: string) {
const wxsNode = ast.children.find(
(node) =>
node.type === NodeTypes.ELEMENT &&
......@@ -75,7 +128,7 @@ export function normalizeWxsCode(code: string): [SyntaxError[], string] {
if (wxsNode) {
code = normalizeWxsNode(code, wxsNode as ElementNode)
}
return [errors, code]
return code
}
const SCRIPT_END_LEN = '</script>'.length
......
......@@ -9,6 +9,9 @@ import {
ExportSpecifier,
} from 'estree'
import { Node, TextModes, NodeTypes, ElementNode } from '@vue/compiler-core'
import { parse } from '@vue/compiler-dom'
export const isProperty = (node: BaseNode): node is Property =>
node.type === 'Property'
......@@ -52,3 +55,18 @@ export function createLiteral(value: string) {
raw: `'${value}'`,
} as Literal
}
export function parseVue(code: string, errors: SyntaxError[]) {
return parse(code, {
isNativeTag: () => true,
isPreTag: () => true,
getTextMode: () => TextModes.DATA,
onError: (e) => {
errors.push(e)
},
})
}
export function isElementNode(node: Node): node is ElementNode {
return node.type === NodeTypes.ELEMENT
}
......@@ -4,13 +4,12 @@ import { CompilerOptions, SFCTemplateCompileOptions } from '@vue/compiler-sfc'
import { isNativeTag } from '@dcloudio/uni-shared'
import { EXTNAME_VUE_RE, parseCompatConfigOnce } from '@dcloudio/uni-cli-shared'
import { block } from './transforms/block'
import { matchMedia } from './transforms/matchMedia'
import { VitePluginUniResolvedOptions } from '..'
export const uniVueCompilerOptions: CompilerOptions = {
isNativeTag,
nodeTransforms: [block, matchMedia],
nodeTransforms: [matchMedia],
}
export const uniVueTransformAssetUrls: SFCTemplateCompileOptions['transformAssetUrls'] =
......@@ -66,6 +65,5 @@ export function initPluginVueOptions(options: VitePluginUniResolvedOptions) {
)
compilerOptions.nodeTransforms.unshift(matchMedia)
compilerOptions.nodeTransforms.unshift(block)
return vueOptions
}
import { ElementNode, NodeTransform } from '@vue/compiler-core'
export const block: NodeTransform = (node) => {
if ((node as ElementNode).tag !== 'block') {
return
}
const platform = process.env.UNI_PLATFORM
if (platform === 'h5' || platform === 'app') {
;(node as ElementNode).tag = 'template'
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册