提交 7ccd61ee 编写于 作者: fxy060608's avatar fxy060608

feat(cli): support wxs(mp-weixin,mp-qq,app-plus),filter(mp-baidu),sjs(mp-alipay)

上级 d7dc1b03
module.exports = {
const config = {
ignore: [
"./packages",
],
......@@ -8,4 +8,10 @@ module.exports = {
}]
],
plugins: [require('./lib/babel-plugin-uni-api/index.js')]
}
if (process.env.NODE_ENV === 'test') {
delete config.ignore
}
module.exports = config
module.exports = {
globals: {
__DEV__: true
},
coverageDirectory: 'coverage',
coverageReporters: ['html', 'lcov', 'text'],
collectCoverageFrom: ['packages/*/src/**/*.js'],
moduleFileExtensions: ['js', 'json'],
moduleNameMapper: {
'^@dcloudio/(.*?)$': '<rootDir>/packages/$1/src'
},
rootDir: __dirname,
testMatch: ['<rootDir>/packages/**/__tests__/**/*spec.(t|j)s']
}
......@@ -17,6 +17,7 @@
"build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js",
"build:runtime": "npm run lint && npm run build:mp-weixin && npm run build:mp-qq && npm run build:mp-alipay && npm run build:mp-baidu && npm run build:mp-toutiao && npm run build:app-plus",
"build:stat": "npm run lint && rollup -c build/rollup.config.stat.js",
"test:cli": "cross-env NODE_ENV=test jest",
"test:unit": "cross-env NODE_ENV=test UNI_PLATFORM=h5 mocha-webpack --require tests/unit/setup.js --webpack-config build/webpack.config.test.js tests/unit/**/*.spec.js",
"release": "npm run lint:cli && lerna publish --force-publish=*",
"release:alpha": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=alpha"
......@@ -49,6 +50,7 @@
"eslint-plugin-promise": "^4.0.0",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^4.7.1",
"jest": "^24.9.0",
"jsdom": "^13.0.0",
"jsdom-global": "^3.0.2",
"jsonfile": "^5.0.0",
......
......@@ -80,7 +80,6 @@ const PLATFORMS = {
vue: '@dcloudio/vue-cli-plugin-uni/packages/h5-vue',
compiler: false,
megalo: false,
filters: true,
subPackages: false,
cssVars: {
'--status-bar-height': '0px'
......@@ -114,7 +113,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: false,
cssVars: {
'--window-top': '0px',
......@@ -143,7 +142,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -170,7 +169,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -207,7 +206,7 @@ const PLATFORMS = {
vue: megaloRuntime,
compiler: megaloCompiler,
megalo: 'swan',
filters: true,
filterTag: 'filter',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -234,7 +233,7 @@ const PLATFORMS = {
vue: megaloRuntime,
compiler: megaloCompiler,
megalo: 'alipay',
filters: true,
filterTag: 'import-sjs',
subPackages: false,
cssVars: {
'--status-bar-height': '25px',
......@@ -440,9 +439,6 @@ module.exports = {
type: 'html',
context: nvuePreprocessContext
},
isSupportFilters () {
return platform.filters
},
isSupportSubPackages () {
return platform.subPackages
},
......@@ -464,6 +460,9 @@ module.exports = {
getPlatformProject () {
return platform.project
},
getPlatformFilterTag () {
return platform.filterTag
},
getPlatformVue () {
if (process.env.UNI_USING_COMPONENTS) {
return uniRuntime
......
const compiler = require('../lib')
function assertCodegen (template, templateCode, renderCode = `with(this){}`, options = {}, mpOptions = {}) {
const res = compiler.compile(template, Object.assign({
const res = compiler.compile(template, Object.assign({
resourcePath: 'test.wxml',
mp: Object.assign({
minified: true,
......@@ -14,7 +14,18 @@ function assertCodegen (template, templateCode, renderCode = `with(this){}`, opt
expect(res.render).toBe(renderCode)
}
describe('mp:compiler-extra', () => {
describe('mp:compiler-extra', () => {
it('generate mp filter ', () => {
assertCodegen(
/* eslint-disable no-template-curly-in-string */
`<view @touchmove="a.touchmove">{{t.a}}{{t['a']}}{{t.a(b)}}{{t['a'](b)}}{{u.t.a(b)}}{{u.t.a}}</view>`,
`<view bindtouchmove="{{a.touchmove}}">{{t.a+t[\'a\']+t.a(b)+t[\'a\'](b)+$root.g0+u.t.a}}</view>`,
'with(this){var g0=u.t.a(b);$mp.data=Object.assign({},{$root:{g0:g0}})}', {
filterModules: ['t', 'a']
}
)
})
it('generate scopeId', () => {
assertCodegen(
'<view></view>',
......@@ -199,11 +210,11 @@ describe('mp:compiler-extra', () => {
)
})
it('generate v-slot', () => {
assertCodegen(
'<view><template></template></view>',
`<view></view>`
)
it('generate v-slot', () => {
assertCodegen(
'<view><template></template></view>',
`<view></view>`
)
assertCodegen(
'<component1><template slot="f">f</template><template slot="c">c</template>默认</component1>',
......@@ -280,19 +291,19 @@ describe('mp:compiler-extra', () => {
</block>
</block>`,
`<block wx:for="{{canlender.weeks}}" wx:for-item="weeks" wx:for-index="week" wx:key="week"><block><block wx:for="{{weeks}}" wx:for-item="day" wx:for-index="index" wx:key="index"><block>,<view data-event-opts="{{[['tap',[['selectDays',[week,index,canlender.month===day.month,'$0','$1'],[[['canlender.weeks','',week],['','',index,'disable']],'canlender.lunar']]]]]}}" bindtap="__e"></view></block></block></block></block>`
)
assertCodegen(
`<view v-for="item in list">9<input type="text" v-for="meta in item.meta" :key="meta.id" v-model="meta.value"></view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="__i0__"><view>9<block wx:for="{{item.meta}}" wx:for-item="meta" wx:for-index="__i1__" wx:key="id"><input type="text" data-event-opts="{{[['input',[['__set_model',['$0','value','$event',[]],[[['list','',__i0__],['meta','id',meta.id]]]]]]]}}" value="{{meta.value}}" bindinput="__e"/></block></view></block>`
)
assertCodegen(
`<view @click="onSetYear(+1,-1)"></view>`,
`<view data-event-opts="{{[['tap',[['onSetYear',[1,-1]]]]]}}" bindtap="__e"></view>`
)
assertCodegen(
`<view class="input-list" v-for="(item,index) in dataList" :key="item.id"><input v-model.trim="dataList2[index].val" /></view>`,
`<block wx:for="{{dataList}}" wx:for-item="item" wx:for-index="index" wx:key="id"><view class="input-list"><input data-event-opts="{{[['input',[['__set_model',['$0','val','$event',['trim']],['dataList2.'+index+'']]]],['blur',[['$forceUpdate']]]]}}" value="{{dataList2[index].val}}" bindinput="__e" bindblur="__e"/></view></block>`
)
)
assertCodegen(
`<view v-for="item in list">9<input type="text" v-for="meta in item.meta" :key="meta.id" v-model="meta.value"></view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="__i0__"><view>9<block wx:for="{{item.meta}}" wx:for-item="meta" wx:for-index="__i1__" wx:key="id"><input type="text" data-event-opts="{{[['input',[['__set_model',['$0','value','$event',[]],[[['list','',__i0__],['meta','id',meta.id]]]]]]]}}" value="{{meta.value}}" bindinput="__e"/></block></view></block>`
)
assertCodegen(
`<view @click="onSetYear(+1,-1)"></view>`,
`<view data-event-opts="{{[['tap',[['onSetYear',[1,-1]]]]]}}" bindtap="__e"></view>`
)
assertCodegen(
`<view class="input-list" v-for="(item,index) in dataList" :key="item.id"><input v-model.trim="dataList2[index].val" /></view>`,
`<block wx:for="{{dataList}}" wx:for-item="item" wx:for-index="index" wx:key="id"><view class="input-list"><input data-event-opts="{{[['input',[['__set_model',['$0','val','$event',['trim']],['dataList2.'+index+'']]]],['blur',[['$forceUpdate']]]]}}" value="{{dataList2[index].val}}" bindinput="__e" bindblur="__e"/></view></block>`
)
})
it('generate class binding', () => {
......@@ -419,18 +430,18 @@ describe('mp:compiler-extra', () => {
assertCodegen(
'<my-component v-model="test" @click="handle">2</my-component>',
`<my-component bind:click="__e" bind:input="__e" vue-id="1" value="{{test}}" data-event-opts="{{[['^click',[['handle']]],['^input',[['__set_model',['','test','$event',[]]]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">2</my-component>`
)
assertCodegen(
'<my-component v-model="test.a">3</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test.a}}" data-event-opts="{{[['^input',[['__set_model',['$0','a','$event',[]],['test']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">3</my-component>`
)
assertCodegen(
'<my-component v-model="test.a.b">4</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test.a.b}}" data-event-opts="{{[['^input',[['__set_model',['$0','b','$event',[]],['test.a']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">4</my-component>`
)
assertCodegen(
'<my-component v-model="test[a.b][a.b]">4</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test[a.b][a.b]}}" data-event-opts="{{[['^input',[['__set_model',['$0','$1','$event',[]],['test.'+a.b+'','a.b']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">4</my-component>`
)
assertCodegen(
'<my-component v-model="test.a">3</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test.a}}" data-event-opts="{{[['^input',[['__set_model',['$0','a','$event',[]],['test']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">3</my-component>`
)
assertCodegen(
'<my-component v-model="test.a.b">4</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test.a.b}}" data-event-opts="{{[['^input',[['__set_model',['$0','b','$event',[]],['test.a']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">4</my-component>`
)
assertCodegen(
'<my-component v-model="test[a.b][a.b]">4</my-component>',
`<my-component bind:input="__e" vue-id="1" value="{{test[a.b][a.b]}}" data-event-opts="{{[['^input',[['__set_model',['$0','$1','$event',[]],['test.'+a.b+'','a.b']]]]]}}" bind:__l="__l" vue-slots="{{['default']}}">4</my-component>`
)
})
......@@ -500,18 +511,18 @@ describe('mp:compiler-extra', () => {
assertCodegen(
'<input class="uni-input" @input="replaceInput" v-model="changeValue" placeholder="连续的两个1会变成2" />',
`<input class="uni-input" placeholder="连续的两个1会变成2" data-event-opts="{{[['input',[['__set_model',['','changeValue','$event',[]]],['replaceInput',['$event']]]]]}}" value="{{changeValue}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model2.m" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','m','$event',[]],['model2']]]]]}}" value="{{model2.m}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model3.m.m" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','m','$event',[]],['model3.m']]]]]}}" value="{{model3.m.m}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model3[a.b][a.b]" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','$1','$event',[]],['model3.'+a.b+'','a.b']]]]]}}" value="{{model3[a.b][a.b]}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model2.m" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','m','$event',[]],['model2']]]]]}}" value="{{model2.m}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model3.m.m" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','m','$event',[]],['model3.m']]]]]}}" value="{{model3.m.m}}" bindinput="__e"/>`
)
assertCodegen(
'<input v-model="model3[a.b][a.b]" />',
`<input data-event-opts="{{[['input',[['__set_model',['$0','$1','$event',[]],['model3.'+a.b+'','a.b']]]]]}}" value="{{model3[a.b][a.b]}}" bindinput="__e"/>`
)
})
......@@ -530,28 +541,28 @@ describe('mp:compiler-extra', () => {
`<view><view v-for="(item, index) in list"><view v-for="(item1,index1) in list1">{{handle(item1)}}{{item1.title}}</view></view></view>`,
`<view><block wx:for="{{$root.l1}}" wx:for-item="item" wx:for-index="index"><view><block wx:for="{{item.l0}}" wx:for-item="item1" wx:for-index="index1"><view>{{item1.m0+item1.$orig.title}}</view></block></view></block></view>`,
`with(this){var l1=__map(list,function(item,index){var l0=__map(list1,function(item1,index1){var m0=handle(item1);return{$orig:__get_orig(item1),m0:m0}});return{$orig:__get_orig(item),l0:l0}});$mp.data=Object.assign({},{$root:{l1:l1}})}`
)
assertCodegen(
`<view v-for="(section, index) in sections" :key="index">title: {{ section.title|prefix }}<view v-for="(sub_titles, _index) in section.sub_titles" :key="_index">{{ sub_titles|prefix }}</view></view>`,
`<block wx:for="{{$root.l1}}" wx:for-item="section" wx:for-index="index" wx:key="index"><view>{{"title: "+section.f0}}<block wx:for="{{section.l0}}" wx:for-item="sub_titles" wx:for-index="_index" wx:key="_index"><view>{{sub_titles.f1}}</view></block></view></block>`,
`with(this){var l1=__map(sections,function(section,index){var f0=_f("prefix")(section.title);var l0=__map(section.sub_titles,function(sub_titles,_index){var f1=_f("prefix")(sub_titles);return{$orig:__get_orig(sub_titles),f1:f1}});return{$orig:__get_orig(section),f0:f0,l0:l0}});$mp.data=Object.assign({},{$root:{l1:l1}})}`
)
assertCodegen(
`<view v-for="(item, index) in list" :key="item">{{aaa.item.id | test | test1}}</view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="*this"><view>{{$root.f0}}</view></block>`,
`with(this){var f0=_f("test1")(_f("test")(aaa.item.id));$mp.data=Object.assign({},{$root:{f0:f0}})}`
)
assertCodegen(
`<view v-for="(item, index) in list" :key="item">{{item.item.id | test | test1}}</view>`,
`<block wx:for="{{$root.l0}}" wx:for-item="item" wx:for-index="index" wx:key="$orig"><view>{{item.f0}}</view></block>`,
`with(this){var l0=__map(list,function(item,index){var f0=_f("test1")(_f("test")(item.item.id));return{$orig:__get_orig(item),f0:f0}});$mp.data=Object.assign({},{$root:{l0:l0}})}`
)
assertCodegen(
`<text v-for="(item, i) in list" v-bind:key="i" >{{ item.split('').join(' ') }}</text>`,
`<block wx:for="{{$root.l0}}" wx:for-item="item" wx:for-index="i" wx:key="i"><text>{{item.g0}}</text></block>`,
`with(this){var l0=__map(list,function(item,i){var g0=item.split("").join(" ");return{$orig:__get_orig(item),g0:g0}});$mp.data=Object.assign({},{$root:{l0:l0}})}`
)
)
assertCodegen(
`<view v-for="(section, index) in sections" :key="index">title: {{ section.title|prefix }}<view v-for="(sub_titles, _index) in section.sub_titles" :key="_index">{{ sub_titles|prefix }}</view></view>`,
`<block wx:for="{{$root.l1}}" wx:for-item="section" wx:for-index="index" wx:key="index"><view>{{"title: "+section.f0}}<block wx:for="{{section.l0}}" wx:for-item="sub_titles" wx:for-index="_index" wx:key="_index"><view>{{sub_titles.f1}}</view></block></view></block>`,
`with(this){var l1=__map(sections,function(section,index){var f0=_f("prefix")(section.title);var l0=__map(section.sub_titles,function(sub_titles,_index){var f1=_f("prefix")(sub_titles);return{$orig:__get_orig(sub_titles),f1:f1}});return{$orig:__get_orig(section),f0:f0,l0:l0}});$mp.data=Object.assign({},{$root:{l1:l1}})}`
)
assertCodegen(
`<view v-for="(item, index) in list" :key="item">{{aaa.item.id | test | test1}}</view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="*this"><view>{{$root.f0}}</view></block>`,
`with(this){var f0=_f("test1")(_f("test")(aaa.item.id));$mp.data=Object.assign({},{$root:{f0:f0}})}`
)
assertCodegen(
`<view v-for="(item, index) in list" :key="item">{{item.item.id | test | test1}}</view>`,
`<block wx:for="{{$root.l0}}" wx:for-item="item" wx:for-index="index" wx:key="$orig"><view>{{item.f0}}</view></block>`,
`with(this){var l0=__map(list,function(item,index){var f0=_f("test1")(_f("test")(item.item.id));return{$orig:__get_orig(item),f0:f0}});$mp.data=Object.assign({},{$root:{l0:l0}})}`
)
assertCodegen(
`<text v-for="(item, i) in list" v-bind:key="i" >{{ item.split('').join(' ') }}</text>`,
`<block wx:for="{{$root.l0}}" wx:for-item="item" wx:for-index="i" wx:key="i"><text>{{item.g0}}</text></block>`,
`with(this){var l0=__map(list,function(item,i){var g0=item.split("").join(" ");return{$orig:__get_orig(item),g0:g0}});$mp.data=Object.assign({},{$root:{l0:l0}})}`
)
})
it('generate TemplateLiteral ', () => {
......@@ -566,11 +577,11 @@ describe('mp:compiler-extra', () => {
`<view data-test="{{'hello'+aaa}}"></view>`
)
})
it('generate event ', () => {
assertCodegen(
`<text v-for="item in items['metas']" :key="item['id']" class="title" @tap="handle(item['id'],item['title'])">{{item.title}}</text>`,
`<block wx:for="{{items['metas']}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><text data-event-opts="{{[['tap',[['handle',['$0','$1'],[[['items.metas','id',item['id'],'id']],[['items.metas','id',item['id'],'title']]]]]]]}}" class="title" bindtap="__e">{{item.title}}</text></block>`
)
it('generate event ', () => {
assertCodegen(
`<text v-for="item in items['metas']" :key="item['id']" class="title" @tap="handle(item['id'],item['title'])">{{item.title}}</text>`,
`<block wx:for="{{items['metas']}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><text data-event-opts="{{[['tap',[['handle',['$0','$1'],[[['items.metas','id',item['id'],'id']],[['items.metas','id',item['id'],'title']]]]]]]}}" class="title" bindtap="__e">{{item.title}}</text></block>`
)
assertCodegen(
`<view @touchmove>1</view>`,
`<view data-event-opts="{{[['touchmove',[['',['$event']]]]]}}" bindtouchmove="__e">1</view>`
......@@ -586,34 +597,34 @@ describe('mp:compiler-extra', () => {
assertCodegen(
`<view @tap="change(item,item.b,'a',true)"></view>`,
`<view data-event-opts="{{[['tap',[['change',['$0','$1','a',true],['item','item.b']]]]]}}" bindtap="__e"></view>`
)
assertCodegen(
`<view @click="handle({name:'a',b:123},[1,2,3])"></view>`,
`<view data-event-opts="{{[['tap',[['handle',[['o',['name','a'],['b',123]],[1,2,3]]]]]]}}" bindtap="__e"></view>`
)
assertCodegen(
`<text v-for="(item,index) in pickerList[pickerIndex[0][2]['asdf']].children" :key="index">{{item.title}}</text>`,
`<block wx:for="{{pickerList[pickerIndex[0][2]['asdf']].children}}" wx:for-item="item" wx:for-index="index" wx:key="index"><text>{{item.title}}</text></block>`
)
assertCodegen(
`<text v-for="(item,index) in pickerList[0][1].children" :key="index" @tap="handle(item,index)">{{item.title}}</text>`,
`<block wx:for="{{pickerList[0][1].children}}" wx:for-item="item" wx:for-index="index" wx:key="index"><text data-event-opts="{{[['tap',[['handle',['$0',index],[[['pickerList.__$n0.__$n1.children','',index]]]]]]]}}" bindtap="__e">{{item.title}}</text></block>`
)
assertCodegen(
`<view v-for="(v2,i2) in ddd.item[0]" :key="i2" @tap="toInfo(v2)"></view>`,
`<block wx:for="{{ddd.item[0]}}" wx:for-item="v2" wx:for-index="i2" wx:key="i2"><view data-event-opts="{{[['tap',[['toInfo',['$0'],[[['ddd.item.__$n0','',i2]]]]]]]}}" bindtap="__e"></view></block>`
)
assertCodegen(
`<button type="primary" @click="test(arr, arr[index+1])">click me</button>`,
`<button type="primary" data-event-opts="{{[['tap',[['test',['$0','$1'],['arr','arr.'+index+1+'']]]]]}}" bindtap="__e">click me</button>`
)
assertCodegen(
`<button type="primary" @click="test(arr, arr[0])">click me</button>`,
`<button type="primary" data-event-opts="{{[['tap',[['test',['$0','$1'],['arr','arr.__$n0']]]]]}}" bindtap="__e">click me</button>`
)
assertCodegen(
`<view v-for="item in list" @click="test(item)">{{ item }}</view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="__i0__"><view data-event-opts="{{[['tap',[['test',['$0'],[[['list','',__i0__]]]]]]]}}" bindtap="__e">{{item}}</view></block>`
)
)
assertCodegen(
`<view @click="handle({name:'a',b:123},[1,2,3])"></view>`,
`<view data-event-opts="{{[['tap',[['handle',[['o',['name','a'],['b',123]],[1,2,3]]]]]]}}" bindtap="__e"></view>`
)
assertCodegen(
`<text v-for="(item,index) in pickerList[pickerIndex[0][2]['asdf']].children" :key="index">{{item.title}}</text>`,
`<block wx:for="{{pickerList[pickerIndex[0][2]['asdf']].children}}" wx:for-item="item" wx:for-index="index" wx:key="index"><text>{{item.title}}</text></block>`
)
assertCodegen(
`<text v-for="(item,index) in pickerList[0][1].children" :key="index" @tap="handle(item,index)">{{item.title}}</text>`,
`<block wx:for="{{pickerList[0][1].children}}" wx:for-item="item" wx:for-index="index" wx:key="index"><text data-event-opts="{{[['tap',[['handle',['$0',index],[[['pickerList.__$n0.__$n1.children','',index]]]]]]]}}" bindtap="__e">{{item.title}}</text></block>`
)
assertCodegen(
`<view v-for="(v2,i2) in ddd.item[0]" :key="i2" @tap="toInfo(v2)"></view>`,
`<block wx:for="{{ddd.item[0]}}" wx:for-item="v2" wx:for-index="i2" wx:key="i2"><view data-event-opts="{{[['tap',[['toInfo',['$0'],[[['ddd.item.__$n0','',i2]]]]]]]}}" bindtap="__e"></view></block>`
)
assertCodegen(
`<button type="primary" @click="test(arr, arr[index+1])">click me</button>`,
`<button type="primary" data-event-opts="{{[['tap',[['test',['$0','$1'],['arr','arr.'+index+1+'']]]]]}}" bindtap="__e">click me</button>`
)
assertCodegen(
`<button type="primary" @click="test(arr, arr[0])">click me</button>`,
`<button type="primary" data-event-opts="{{[['tap',[['test',['$0','$1'],['arr','arr.__$n0']]]]]}}" bindtap="__e">click me</button>`
)
assertCodegen(
`<view v-for="item in list" @click="test(item)">{{ item }}</view>`,
`<block wx:for="{{list}}" wx:for-item="item" wx:for-index="__i0__"><view data-event-opts="{{[['tap',[['test',['$0'],[[['list','',__i0__]]]]]]]}}" bindtap="__e">{{item}}</view></block>`
)
})
})
const compiler = require('../lib')
const res = compiler.compile(
`
<view @touchmove="a.touchmove">{{t.a}}{{t['a']}}{{t.a(b)}}{{t['a'](b)}}{{u.t.a(b)}}{{u.t.a}}</view>
`, {
resourcePath: '/User/fxy/Documents/test.wxml',
mp: {
minified: true,
isTest: true,
platform: 'mp-weixin'
},
filterModules: ['t', 'a']
})
// ---BEGIN:JSON---{"n":"v"}---END:JSON---
console.log(res)
......@@ -39,6 +39,8 @@ module.exports = {
options.mp.resourcePath = options.resourcePath
options.mp.globalUsingComponents = options.globalUsingComponents || Object.create(null)
options.mp.filterModules = options.filterModules || []
// (可用的原生微信小程序组件,global+scoped)
options.mp.wxComponents = options.wxComponents || Object.create(null)
......
......@@ -138,8 +138,8 @@ function parseMethod (method, state) {
return t.stringLiteral('$' + (extraArrayElements.length - 1))
} else if ( // +1=>1
t.isUnaryExpression(element) &&
element.operator === '+' &&
t.isNumericLiteral(element.argument)
element.operator === '+' &&
t.isNumericLiteral(element.argument)
) {
element = t.numericLiteral(element.argument.value)
} else if (t.isObjectExpression(element)) {
......@@ -199,7 +199,22 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
}
valuePath.forEach(funcPath => {
if (funcPath.isIdentifier()) { // on:{click:handle}
if ( // wxs event
funcPath.isMemberExpression() &&
t.isIdentifier(funcPath.node.object) &&
state.options.filterModules.includes(funcPath.node.object.name)
) {
const {
getEventType,
formatEventType
} = state.options.platform
const wxsEventType = formatEventType(getEventType(type))
if (key.value) {
key.value = wxsEventType
} else {
key.name = wxsEventType
}
} else if (funcPath.isIdentifier()) { // on:{click:handle}
if (!isSpecialEvent) {
const arrayExpression = [t.stringLiteral(getMethodName(funcPath.node.name))]
if (!isCustom) { // native events
......@@ -224,7 +239,7 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
noScope: true,
MemberExpression (path) {
if (path.node.object.name === '$event' && path.node.property.name ===
'stopPropagation') {
'stopPropagation') {
isCatch = true
path.stop()
}
......@@ -234,9 +249,9 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
const right = path.node.right
// v-bind:title.sync="title"
if (t.isIdentifier(left) &&
t.isIdentifier(right) &&
right.name === '$event' &&
type.indexOf('update:') === 0) {
t.isIdentifier(right) &&
right.name === '$event' &&
type.indexOf('update:') === 0) {
methods.push(t.arrayExpression( // ['$set',['title','$event']]
[
t.stringLiteral(INTERNAL_SET_SYNC),
......
......@@ -17,6 +17,7 @@ const {
const {
hyphenate,
traverseFilter,
getComponentName
} = require('../../util')
......@@ -130,9 +131,19 @@ function checkUsingGlobalComponents (name, globalUsingComponents, state) {
module.exports = {
noScope: true,
MemberExpression (path) {
if ( // t.m(123)
t.isIdentifier(path.node.object) &&
this.options.filterModules.includes(path.node.object.name)
) {
path.skip()
}
},
CallExpression (path) {
const callee = path.node.callee
if (t.isIdentifier(callee)) {
if (traverseFilter(callee, this)) {
return path.skip()
} else if (t.isIdentifier(callee)) {
const methodName = callee.name
switch (methodName) {
case METHOD_CREATE_ELEMENT:
......@@ -174,6 +185,7 @@ module.exports = {
path.skip()
break
default:
// TODO 检测是否是 filterModules
if (!METHOD_BUILT_IN.includes(methodName)) {
if (
path.findParent(
......@@ -200,8 +212,8 @@ module.exports = {
}
} else if (
t.isCallExpression(callee) &&
t.isIdentifier(callee.callee) &&
callee.callee.name === METHOD_RESOLVE_FILTER
t.isIdentifier(callee.callee) &&
callee.callee.name === METHOD_RESOLVE_FILTER
) {
// multi filter
path.replaceWith(getMemberExpr(path, IDENTIFIER_FILTER, path.node, this))
......
......@@ -53,6 +53,34 @@ function traverseKey (ast, state) {
return forKey
}
function traverseFilter (ast, state) {
const filterModules = state.options.filterModules
if (!filterModules.length) {
return false
}
let isFilter = false
babelTraverse(ast, {
noScope: true,
Identifier (path) {
if (filterModules.includes(path.node.name)) {
const parentNode = path.parent
if ( // t.msg || t['msg']
t.isMemberExpression(parentNode) &&
parentNode.object === path.node &&
(
t.isIdentifier(parentNode.property) ||
t.isLiteral(parentNode.property)
)
) {
isFilter = true
path.stop()
}
}
}
})
return isFilter
}
function wrapper (code, reverse = false) {
return reverse ? `{{!(${code})}}` : `{{${code}}}`
}
......@@ -142,7 +170,7 @@ function processMemberExpression (element, state) {
})
}
return element
}
}
module.exports = {
genCode,
......@@ -159,6 +187,7 @@ module.exports = {
}),
getForKey,
traverseKey,
traverseFilter,
getComponentName: cached((str) => {
if (str.indexOf('wx-') === 0) {
return str.replace('wx-', 'weixin-')
......@@ -167,4 +196,4 @@ module.exports = {
}),
processMemberExpression,
getForIndexIdentifier
}
}
......@@ -142,6 +142,12 @@ module.exports = {
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-nvue-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
.end()
......
const path = require('path')
const loaderUtils = require('loader-utils')
const {
parse
} = require(require.resolve('@vue/component-compiler-utils', {
paths: [require.resolve('vue-loader')]
})) // 确保使用的与 vue-loader 一致
const {
getPlatformFilterTag
} = require('@dcloudio/uni-cli-shared/lib/platform')
const FILTER_TAG = getPlatformFilterTag()
module.exports = function(source) {
if (!FILTER_TAG) {
return source
}
const loaderContext = this
const {
sourceMap,
rootContext,
resourcePath
} = loaderContext
const options = loaderUtils.getOptions(loaderContext) || {}
const filename = path.basename(resourcePath)
const context = rootContext || process.cwd()
const sourceRoot = path.dirname(path.relative(context, resourcePath))
// 使用 @vue/component-compiler-utils 来处理,共用 cache
const descriptor = parse({
source,
compiler: options.compiler,
filename,
sourceRoot,
needMap: sourceMap
})
if (!descriptor.template) {
return source
}
const modules = new Set()
descriptor.customBlocks.filter(block => {
if (block.type === FILTER_TAG && block.attrs.module) {
modules.add(block.attrs.module)
}
})
if (modules.size) {
descriptor.template.attrs['filter-modules'] = [...modules]
}
// delete customBlocks
descriptor.customBlocks.length = 0
return source
}
const path = require('path')
const loaderUtils = require('loader-utils')
const {
removeExt,
getPlatformExts,
getPlatformExts,
getShadowTemplate
} = require('@dcloudio/uni-cli-shared')
const {
const {
getJsonFile,
getWXComponents,
getWXComponents,
updateSpecialMethods,
getGlobalUsingComponents,
updateGenericComponents, // resolve
......@@ -31,15 +33,21 @@ module.exports = function (content) {
const realResourcePath = path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)
const resourcePath = normalizeNodeModules(removeExt(realResourcePath) + templateExt)
const wxComponents = getWXComponents(resourcePath.replace(path.extname(resourcePath), ''))
const params = loaderUtils.parseQuery(this.resourceQuery)
const filterModules = (params && params['filter-modules'] || '').split(',')
Object.assign(vueLoaderOptions.options.compilerOptions, {
mp: {
platform: process.env.UNI_PLATFORM
},
filterModules,
resourcePath,
emitFile: this.emitFile,
wxComponents,
getJsonFile,
getShadowTemplate,
wxComponents,
getJsonFile,
getShadowTemplate,
updateSpecialMethods,
globalUsingComponents,
updateGenericComponents,
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册