Skip to content
This repository was archived by the owner on Apr 21, 2022. It is now read-only.

Commit 3d4e250

Browse files
committed
test: update
1 parent 5a01220 commit 3d4e250

File tree

4 files changed

+197
-6
lines changed

4 files changed

+197
-6
lines changed

package-lock.json

Lines changed: 16 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"dependencies": {
2525
"@babel/parser": "^7.5.5",
2626
"@babel/traverse": "^7.5.5",
27+
"hast-util-to-html": "^6.0.2",
2728
"lodash": "^4.17.11",
2829
"parse-entities": "^1.2.2",
2930
"rehype-parse": "^6.0.0",

test/fixtures/test.wxml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<template name="staffName">
2+
<view>FirstName: {{firstName}}, LastName: {{lastName}}</view>
3+
<view>FirstName: {{firstName}}, LastName: {{lastName}}</view>
4+
</template>
5+
<template is="staffName" data="{{...staffA}}"></template>
6+
<template is="staffName" data="{{...staffB}}"></template>
7+
<template is="staffName" data="{{...staffC}}"></template>
8+
<view class="container">
9+
<view class="userinfo" bindtap="onTap">
10+
<button wx:if="{{!hasUserInfo && canIUse}}">获取头像昵称</button>
11+
<block wx:else>
12+
<image src="{{userInfo.avatarUrl}}" background-size="cover"></image>
13+
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
14+
</block>
15+
</view>
16+
<view class="usermotto">
17+
<text class="user-motto">{{motto}}</text>
18+
</view>
19+
</view>
20+
<view>
21+
<view>{{ message }}</view>
22+
<view>{{a + b}} + {{c}} + d</view>
23+
<view>{{"hello" + name}}</view>
24+
<view>{{object.key}} {{array[0]}}</view>
25+
</view>
26+
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
27+
{{idx}}: {{itemName.message}}
28+
</view>
29+
<view>
30+
<view>00000000000</view>
31+
<template is="xxxxxxxx"></template>
32+
<template name="xxxxxxxx">
33+
<view>111111111111111111</view>
34+
<template is="xxxxxxxx"></template>
35+
<template name="xxxxxxxx">
36+
<view>222222222222222222</view>
37+
<template is="xxxxxxxx"></template>
38+
<template name="xxxxxxxx">
39+
<view>333333333333333333</view>
40+
<template name="xxxxxxxx">
41+
<view>333333333333333333</view>
42+
</template>
43+
</template>
44+
</template>
45+
</template>
46+
</view>

test/index.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
const { join, dirname } = require('path')
2+
// const { ensureFileSync } = require('fs-extra')
3+
const prettier = require('prettier')
4+
const vfile = require('to-vfile')
5+
const toHTML = require('hast-util-to-html')
6+
const { selectAll } = require('unist-util-select')
7+
const wxml2vue = require('../')
8+
9+
const htmlSettings = {
10+
quoteSmart: true,
11+
closeSelfClosing: true,
12+
omitOptionalTags: true,
13+
entities: { useShortestReferences: true }
14+
}
15+
16+
const testFile = join(__dirname, 'fixtures/test.wxml')
17+
18+
transformFile(testFile).then(console.log)
19+
20+
function transformFile(path) {
21+
const cwd = dirname(path)
22+
const fs = new Map()
23+
const file = vfile.readSync(path, 'utf8')
24+
const plugin = function() {
25+
return tree => transform(tree, { cwd, fs })
26+
}
27+
28+
return wxml2vue(file, plugin).then(file => {
29+
file.extname = '.vue'
30+
fs.set(file.path, file.contents)
31+
return fs
32+
})
33+
}
34+
35+
function transform(tree, { cwd, fs }) {
36+
// step 1
37+
// TODO
38+
// * 标签替换
39+
// * <import /> and <include />
40+
41+
// step 2
42+
// Vue 组件需要 root element
43+
// 所以可能需要包装一层
44+
fixRootElement(tree)
45+
// template 定义也需要包装
46+
const tmplDefs = selectAll('element[tagName=template]', tree)
47+
tmplDefs.forEach(tmpl => fixRootElement(tmpl.content))
48+
49+
// step 3
50+
// template 定义 => template vfile
51+
makeTemplateFiles(tree, null, { cwd, fs })
52+
}
53+
54+
// 这里和小程序有一定区别
55+
// 小程序的同名 template 嵌套比较简单
56+
// SEE https://gist.github.com/AngusFu/2aa3661e8286c413504886f8e8c7d27e
57+
function makeTemplateFiles(node, parent, { fs, cwd }) {
58+
const { children } = node
59+
60+
if (node.type === 'element' && node.tagName === 'template') {
61+
const name = node.properties.name
62+
63+
if (parent) {
64+
parent.children[parent.children.indexOf(node)] = {
65+
type: 'comment',
66+
value: ` Template ${name} is moved to: ./${name}/index.vue `
67+
}
68+
}
69+
70+
cwd = join(cwd, name)
71+
makeTemplateFiles(node.content, null, { cwd, fs })
72+
fs.set(join(cwd, 'index.vue'), makeVueComponent(node))
73+
} else if (children && children.length) {
74+
children.forEach(child => makeTemplateFiles(child, node, { fs, cwd }))
75+
}
76+
}
77+
78+
function fixRootElement(tree) {
79+
const { children } = tree
80+
const elemCount = children.filter(
81+
node => node.type === 'element' && node.tagName !== 'template'
82+
).length
83+
84+
if (elemCount === 1) {
85+
if (
86+
children.filter(node => node.type === 'text' && node.value.trim())
87+
.length === 0
88+
) {
89+
return
90+
}
91+
}
92+
93+
const rootElement = {
94+
type: 'element',
95+
tagName: 'div',
96+
children
97+
}
98+
99+
tree.children = [
100+
{ type: 'text', value: '\n' },
101+
{ type: 'comment', value: ' Tip: Vue SFC need a root element ' },
102+
rootElement,
103+
{ type: 'text', value: '\n' }
104+
]
105+
}
106+
107+
function makeVueComponent(node) {
108+
const props = node.properties
109+
const { scope } = props
110+
111+
let script = ''
112+
113+
if (scope) {
114+
props.scope = null
115+
116+
const propsDelc = scope
117+
.slice(1, -1)
118+
.trim()
119+
.split(/\s*,\s*/)
120+
.map(k => JSON.stringify(k))
121+
.join(', ')
122+
script = `
123+
<script>
124+
export default {
125+
props: [${propsDelc}]
126+
}
127+
</script>
128+
`
129+
}
130+
131+
return prettier.format(`${toHTML(node, htmlSettings)}\n${script}`, {
132+
parser: 'vue'
133+
})
134+
}

0 commit comments

Comments
 (0)