提交 4b40ab1c 编写于 作者: Q qiang

Merge branch 'dev' into alpha

......@@ -1156,7 +1156,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
const fs = require('fs')
const path = require('path')
const {
getJson
} = require('./json')
function parseThemeByJsonStr (jsonStr, keys, theme) {
if (jsonStr.indexOf('@') === -1) {
return jsonStr
}
keys.forEach(key => {
jsonStr = jsonStr.replace(new RegExp('@' + key, 'g'), theme[key])
})
return jsonStr
}
const themeJsonPath = path.join(process.env.UNI_INPUT_DIR, 'theme.json')
function hasTheme () {
return fs.existsSync(themeJsonPath)
}
function darkmode () {
return !!(global.uniPlugin.options || {}).darkmode
}
module.exports = {
darkmode,
hasTheme,
initTheme () {
if (!hasTheme()) {
return
}
if (darkmode()) {
return
}
try {
const theme = getJson('theme.json', true)
global.uniPlugin.defaultTheme = theme.light
} catch (e) {
console.error(e)
}
},
parseTheme (json) {
const theme = global.uniPlugin.defaultTheme
if (!theme) {
return json
}
const keys = Object.keys(theme)
if (!keys.length) {
return json
}
if (typeof json === 'string') {
return parseThemeByJsonStr(json, keys, theme)
}
return JSON.parse(parseThemeByJsonStr(JSON.stringify(json), keys, theme))
}
}
......@@ -1633,7 +1633,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -1298,7 +1298,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -1214,7 +1214,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -1306,7 +1306,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -1171,7 +1171,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -17,10 +17,12 @@ module.exports = {
},
filterTag: 'wxs',
project: 'project.config.json',
subPackages: true
subPackages: true,
darkmode: true
},
copyWebpackOptions (platformOptions, vueOptions) {
const copyOptions = [
const copyOptions = [
'theme.json',
'sitemap.json',
'ext.json',
'custom-tab-bar'
......
......@@ -1156,7 +1156,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
];
function parseBaseApp (vm, {
......
......@@ -251,10 +251,10 @@ describe('mp:compiler-extra', () => {
)
})
it('generate events inside v-for', () => {
assertCodegen(
'<view v-for="item in dataList" :key="item.id" @click="click1(item, 1);click2(item, 2);"/>',
'<block wx:for="{{dataList}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><view data-event-opts="{{[[\'tap\',[[\'click1\',[\'$0\',1],[[[\'dataList\',\'id\',item.id]]]],[\'click2\',[\'$0\',2],[[[\'dataList\',\'id\',item.id]]]]]]]}}" bindtap="__e"></view></block>'
it('generate events inside v-for', () => {
assertCodegen(
'<view v-for="item in dataList" :key="item.id" @click="click1(item, 1);click2(item, 2);"/>',
'<block wx:for="{{dataList}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><view data-event-opts="{{[[\'tap\',[[\'click1\',[\'$0\',1],[[[\'dataList\',\'id\',item.id]]]],[\'click2\',[\'$0\',2],[[[\'dataList\',\'id\',item.id]]]]]]]}}" bindtap="__e"></view></block>'
)
// TODO vue的数字 item 是从1,小程序是从0,后续考虑抹平差异
assertCodegen(
......@@ -310,23 +310,23 @@ describe('mp:compiler-extra', () => {
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>
<view v-for="item in list[idx]" :key="item.id" class="mid-item-title" @click="m1(item)">
<view class="mid-item-icon" @click.stop="m2(item)"></view>
</view>
</view>`,
'<view><block wx:for="{{list[idx]}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><view data-event-opts="{{[[\'tap\',[[\'m1\',[\'$0\'],[[[\'list.\'+idx+\'\',\'id\',item.id]]]]]]]}}" class="mid-item-title" bindtap="__e"><view data-event-opts="{{[[\'tap\',[[\'m2\',[\'$0\'],[[[\'list.\'+idx+\'\',\'id\',item.id]]]]]]]}}" class="mid-item-icon" catchtap="__e"></view></view></block></view>'
)
assertCodegen(
'<view><view class="item" v-for="i in \'abc\'" :key="i" @click="func(i)"></view></view>',
'<view><block wx:for="abc" wx:for-item="i" wx:for-index="__i0__" wx:key="*this"><view data-event-opts="{{[[\'tap\',[[\'func\',[\'$0\'],[[[\'#s#abc\',\'\',__i0__]]]]]]]}}" class="item" bindtap="__e"></view></block></view>'
)
assertCodegen(
'<view><view class="item" v-for="i in 5" :key="i" @click="func(i)"></view></view>',
'<view><block wx:for="{{5}}" wx:for-item="i" wx:for-index="__i0__" wx:key="*this"><view data-event-opts="{{[[\'tap\',[[\'func\',[\'$0\'],[[[5,\'\',__i0__]]]]]]]}}" class="item" bindtap="__e"></view></block></view>'
)
)
assertCodegen(
` <view>
<view v-for="item in list[idx]" :key="item.id" class="mid-item-title" @click="m1(item)">
<view class="mid-item-icon" @click.stop="m2(item)"></view>
</view>
</view>`,
'<view><block wx:for="{{list[idx]}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><view data-event-opts="{{[[\'tap\',[[\'m1\',[\'$0\'],[[[\'list.\'+idx+\'\',\'id\',item.id]]]]]]]}}" class="mid-item-title" bindtap="__e"><view data-event-opts="{{[[\'tap\',[[\'m2\',[\'$0\'],[[[\'list.\'+idx+\'\',\'id\',item.id]]]]]]]}}" class="mid-item-icon" catchtap="__e"></view></view></block></view>'
)
assertCodegen(
'<view><view class="item" v-for="i in \'abc\'" :key="i" @click="func(i)"></view></view>',
'<view><block wx:for="abc" wx:for-item="i" wx:for-index="__i0__" wx:key="*this"><view data-event-opts="{{[[\'tap\',[[\'func\',[\'$0\'],[[[\'#s#abc\',\'\',__i0__]]]]]]]}}" class="item" bindtap="__e"></view></block></view>'
)
assertCodegen(
'<view><view class="item" v-for="i in 5" :key="i" @click="func(i)"></view></view>',
'<view><block wx:for="{{5}}" wx:for-item="i" wx:for-index="__i0__" wx:key="*this"><view data-event-opts="{{[[\'tap\',[[\'func\',[\'$0\'],[[[5,\'\',__i0__]]]]]]]}}" class="item" bindtap="__e"></view></block></view>'
)
})
it('generate class binding', () => {
......@@ -586,6 +586,17 @@ describe('mp:compiler-extra', () => {
'<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 class="content">
<view v-for="(item, index) in tabList" :key="index">
<view v-for="(item2,index2) in list[item.key]" :key="index2" @click="show(item2.id, item2.id)">
{{formatIt(item2.id)}}
</view>
</view>
</view>`,
'<view class="content"><block wx:for="{{$root.l1}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view><block wx:for="{{item.l0}}" wx:for-item="item2" wx:for-index="index2" wx:key="index2"><view data-event-opts="{{[[\'tap\',[[\'show\',[\'$0\',\'$1\'],[[[\'list.\'+item.$orig.key+\'\',\'\',index2,\'id\']],[[\'list.\'+item.$orig.key+\'\',\'\',index2,\'id\']]]]]]]}}" bindtap="__e">{{\'\'+item2.m0+\'\'}}</view></block></view></block></view>',
'with(this){var l1=__map(tabList,function(item,index){var l0=__map(list[item.key],function(item2,index2){var m0=formatIt(item2.id);return{$orig:__get_orig(item2),m0:m0}});return{$orig:__get_orig(item),l0:l0}});$mp.data=Object.assign({},{$root:{l1:l1}})}'
)
})
it('generate TemplateLiteral ', () => {
......@@ -600,11 +611,11 @@ describe('mp:compiler-extra', () => {
'<view data-test="{{\'hello\'+aaa}}"></view>'
)
})
it('generate event ', () => {
assertCodegen(
'<view @/>',
'<view></view>'
)
it('generate event ', () => {
assertCodegen(
'<view @/>',
'<view></view>'
)
assertCodegen(
'<text v-for="item in items[\'metas\']" :key="item[\'id\']" class="title" @tap="handle(item[\'id\'],item[\'title\'])">{{item.title}}</text>',
......@@ -654,15 +665,15 @@ describe('mp:compiler-extra', () => {
'<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>'
)
})
it('generate bool attr', () => {
assertCodegen(
'<video id class style inline-template controls/>',
'<video id controls="{{true}}"></video>'
)
assertCodegen(
'<video controls=""/>',
'<video controls></video>'
)
})
it('generate bool attr', () => {
assertCodegen(
'<video id class style inline-template controls/>',
'<video id controls="{{true}}"></video>'
)
assertCodegen(
'<video controls=""/>',
'<video controls></video>'
)
})
})
......@@ -146,6 +146,7 @@ module.exports = function traverseRenderList (path, state) {
identifierArray: state.identifierArray,
propertyArray: [],
declarationArray: [],
computedProperty: {},
initExpressionStatementArray: state.initExpressionStatementArray
}
......@@ -173,6 +174,16 @@ module.exports = function traverseRenderList (path, state) {
functionExpression.traverse(origVisitor, {
forItem
})
const keys = Object.keys(forState.computedProperty)
if (keys.length) {
keys.forEach(key => {
const property = forState.computedProperty[key]
if (t.isMemberExpression(property) && property.object.name === forItem) {
property.object = t.memberExpression(t.identifier(forItem), t.identifier(VAR_ORIGINAL))
forState.options.replaceCodes[key] = `'+${genCode(property, true)}+'`
}
})
}
} else {
forPath.traverse(require('./visitor'), forState)
}
......
......@@ -133,6 +133,9 @@ function processMemberProperty (node, state) {
}
const identifier = '__$m' + (state.options.__m__++) + '__'
state.options.replaceCodes[identifier] = `'+${genCode(property, true)}+'`
if (state.computedProperty) {
state.computedProperty[identifier] = property
}
node.property = t.identifier(identifier)
}
node.computed = false
......
......@@ -71,20 +71,20 @@ const sassLoader = {
if (sassLoaderVersion < 8) {
scssLoader.options.data = sassData
scssLoader.options.outputStyle = 'nested'
scssLoader.options.outputStyle = 'expanded'
sassLoader.options.data = sassData
sassLoader.options.outputStyle = 'nested'
sassLoader.options.outputStyle = 'expanded'
sassLoader.options.indentedSyntax = true
} else {
scssLoader.options.prependData = sassData
scssLoader.options.sassOptions = {
outputStyle: 'nested'
outputStyle: 'expanded'
}
sassLoader.options.prependData = sassData
sassLoader.options.sassOptions = {
outputStyle: 'nested',
outputStyle: 'expanded',
indentedSyntax: true
}
}
......
......@@ -5600,6 +5600,15 @@ function cloneWithData(vm) {
ret[key] = vm[key];
return ret
}, ret);
// vue-composition-api
var rawBindings = vm.__secret_vfa_state__ && vm.__secret_vfa_state__.rawBindings;
if (rawBindings) {
Object.keys(rawBindings).forEach(function (key) {
ret[key] = vm[key];
});
}
//TODO 需要把无用数据处理掉,比如 list=>l0 则 list 需要移除,否则多传输一份数据
Object.assign(ret, vm.$mp.data || {});
if (
......@@ -5804,7 +5813,7 @@ function getTarget(obj, path) {
return getTarget(obj[key], parts.slice(1).join('.'))
}
function internalMixin(Vue ) {
function internalMixin(Vue) {
Vue.config.errorHandler = function(err, vm, info) {
Vue.util.warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
......@@ -5952,6 +5961,8 @@ var LIFECYCLE_HOOKS$1 = [
'onShow',
'onHide',
'onUniNViewMessage',
'onPageNotFound',
'onThemeChange',
'onError',
//Page
'onLoad',
......
......@@ -19,7 +19,8 @@ function parseComponents (content, traverse) {
components: [],
options: {
name: null,
inheritAttrs: null
inheritAttrs: null,
props: null
}
})
return {
......@@ -30,4 +31,4 @@ function parseComponents (content, traverse) {
module.exports = {
parseComponents
}
}
......@@ -22,6 +22,28 @@ function assertCodegen (content, expectedComponents, isScoped = true) {
expect(JSON.stringify(components)).toBe(JSON.stringify(expectedComponents))
}
function assertCodegenOptions (content, expectedOptions, isScoped = true) {
const {
state: {
options
}
} = (isScoped ? scopedComponentTraverse : globalComponentTraverse)(parser.parse(content, {
sourceType: 'module',
plugins: [
'typescript'
]
}), {
components: [],
options: {
name: null,
inheritAttrs: null,
props: null
}
})
expect(JSON.stringify(options)).toBe(JSON.stringify(expectedOptions))
}
describe('mp:loader', () => {
it('parse scoped component', () => {
assertCodegen(
......@@ -153,6 +175,46 @@ global['__wxVueOptions'] = {
source: '@/components/my-button/my-button.vue'
}
])
assertCodegenOptions(
`export default {
name: 'test'
}`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`export default {
props: ['id', 'test']
}`,
{
name: null,
inheritAttrs: null,
props: '["id","test"]'
}
)
assertCodegenOptions(
`export default {
props: {
id: {
type: String
},
'test': {
type: String
}
}
}`,
{
name: null,
inheritAttrs: null,
props: '["id","test"]'
}
)
})
it('parse global component', () => {
......
......@@ -6,7 +6,7 @@ const {
} = require('./util')
function handleObjectExpression (declaration, path, state) {
if (state.options) { // name,inheritAttrs
if (state.options) { // name,inheritAttrs,props
Object.keys(state.options).forEach(name => {
const optionProperty = declaration.properties.filter(prop => {
return t.isObjectProperty(prop) &&
......@@ -14,7 +14,21 @@ function handleObjectExpression (declaration, path, state) {
prop.key.name === name
})[0]
if (optionProperty) {
if (t.isStringLiteral(optionProperty.value)) {
if (name === 'props') {
if (t.isArrayExpression(optionProperty.value)) {
state.options[name] = JSON.stringify(optionProperty.value.elements.filter(element => t.isStringLiteral(element)).map(({ value }) => value))
} else if (t.isObjectExpression(optionProperty.value)) {
const props = []
optionProperty.value.properties.forEach(({ key }) => {
if (t.isIdentifier(key)) {
props.push(key.name)
} else if (t.isStringLiteral(key)) {
props.push(key.value)
}
})
state.options[name] = JSON.stringify(props)
}
} else if (t.isStringLiteral(optionProperty.value)) {
state.options[name] = JSON.stringify(optionProperty.value.value)
} else {
state.options[name] = optionProperty.value.value
......
......@@ -16,6 +16,11 @@ const {
updateProjectJson
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
initTheme,
parseTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
// pagesJsonJsFileName,
initAutoImportComponents
......@@ -35,6 +40,8 @@ function renameUsingComponents (jsonObj) {
module.exports = function (content, map) {
this.cacheable && this.cacheable()
initTheme()
let isAppView = false
if (this.resourceQuery) {
const params = loaderUtils.parseQuery(this.resourceQuery)
......@@ -48,13 +55,18 @@ module.exports = function (content, map) {
// this.addDependency(pagesJsonJsPath)
this.addDependency(manifestJsonPath)
const pagesJson = parsePagesJson(content, {
let pagesJson = parsePagesJson(content, {
addDependency: (file) => {
(process.UNI_PAGES_DEPS || (process.UNI_PAGES_DEPS = new Set())).add(normalizePath(file))
this.addDependency(file)
}
})
if (global.uniPlugin.defaultTheme) {
pagesJson = parseTheme(pagesJson)
this.addDependency(path.resolve(process.env.UNI_INPUT_DIR, 'theme.json'))
}
// 组件自动导入配置
process.UNI_AUTO_SCAN_COMPONENTS = !(pagesJson.easycom && pagesJson.easycom.autoscan === false)
initAutoImportComponents(pagesJson.easycom)
......
......@@ -12,6 +12,11 @@ const {
updateAppJsonUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
darkmode,
hasTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
hasOwn,
parseStyle
......@@ -208,6 +213,11 @@ module.exports = function (pagesJson, manifestJson, project = {}) {
updateAppJsonUsingComponents(app.usingComponents)
}
if (darkmode() && hasTheme()) {
app.darkmode = true
app.themeLocation = 'theme.json'
}
const projectName = getPlatformProject()
const projectPath = projectName && path.resolve(process.env.VUE_CLI_CONTEXT || process.cwd(), projectName)
......@@ -309,4 +319,4 @@ module.exports = function (pagesJson, manifestJson, project = {}) {
}
}
}
}
}
......@@ -74,7 +74,13 @@ function parseStyle (style = {}, root = '') {
return Object.assign(windowOptions, platformStyle)
}
if (style.navigationBarTextStyle && style.navigationBarTextStyle !== 'black') {
if (
style.navigationBarTextStyle &&
(
style.navigationBarTextStyle !== 'black' &&
style.navigationBarTextStyle.indexOf('@') !== 0
)
) {
style.navigationBarTextStyle = 'white'
}
......
......@@ -6,7 +6,8 @@ const LIFECYCLE_HOOKS = [
'onShow',
'onHide',
'onUniNViewMessage',
'onPageNotFound',
'onPageNotFound',
'onThemeChange',
'onError',
// Page
'onLoad',
......
......@@ -125,6 +125,13 @@ class ComponentDescriptor {
return this.$el && this.$el.classList.contains(cls)
}
getComputedStyle () {
if (this.$el) {
return window.getComputedStyle(this.$el)
}
return {}
}
getDataset () {
return this.$el && this.$el.dataset
}
......
......@@ -62,7 +62,10 @@ function wrapper (webview) {
}
export function getSubNVueById (id) {
const webview = plus.webview.getWebviewById(id)
const webview = plus.webview.getWebviewById(id)
if (webview === null || webview === undefined) {
throw new Error('Unable to find SubNVue, id=' + id)
}
if (webview && !webview.$processed) {
wrapper(webview)
}
......
......@@ -9,7 +9,8 @@ const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
'onPageNotFound',
'onThemeChange'
]
export default function parseBaseApp (vm, {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册