diff --git a/README.md b/README.md index f37b47635bd2daf2ed268bbdc4d0fe32737d2813..3ddcb5dfd8d598aa5d3441256905f9b4cd98d83c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ `uni-app` 是一个使用 `Vue.js` 开发小程序、H5、App的统一前端框架。官网地址:[https://uniapp.dcloud.io](https://uniapp.dcloud.io) -开发者使用 `Vue` 语法编写代码,`uni-app` 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/快手/钉钉)、App(iOS/Android)、H5等多个平台,保证其正确运行并达到优秀体验。 +开发者使用 `Vue` 语法编写代码,`uni-app` 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/快手/钉钉/小红书)、App(iOS/Android)、H5等多个平台,保证其正确运行并达到优秀体验。 # uni-app的特点 diff --git a/build/rollup.config.mp.js b/build/rollup.config.mp.js index d5803dcd5db69db6576d445144f2116c22e4a5cc..9ed51ef525bdb4a38c5f192cba4f14b0c7ca9d0a 100644 --- a/build/rollup.config.mp.js +++ b/build/rollup.config.mp.js @@ -1,96 +1,100 @@ -const path = require('path') -const json = require('@rollup/plugin-json') -const alias = require('@rollup/plugin-alias') -const replace = require('@rollup/plugin-replace') - -const PLATFORMS = { - 'mp-weixin': { - prefix: 'wx', - title: '微信小程序' - }, - 'mp-qq': { - prefix: 'wx', - title: 'QQ小程序' - }, - 'mp-alipay': { - prefix: 'my', - title: '支付宝小程序' - }, - 'mp-baidu': { - prefix: 'swan', - title: '百度小程序' - }, - 'mp-toutiao': { - prefix: 'tt', - title: '头条小程序' - }, - 'mp-kuaishou': { - prefix: 'ks', - title: '快手小程序' - }, - 'mp-lark': { - prefix: 'tt', - title: '飞书小程序' - }, - 'mp-jd': { - prefix: 'jd', - title: '京东小程序' - }, - 'quickapp-webview': { - prefix: 'qa', - title: '快应用(Webview)版' - }, - 'app-plus': { - prefix: 'wx', - title: 'app-plus' - } -} - -const platform = PLATFORMS[process.env.UNI_PLATFORM] - -let input = 'src/core/runtime/index.js' -const output = { - file: `packages/uni-${process.env.UNI_PLATFORM}/dist/index.js`, - format: 'es' -} - -if (process.env.UNI_MP) { - input = 'src/core/runtime/mp/index.js' - output.file = `packages/uni-${process.env.UNI_PLATFORM}/dist/mp.js` -} - -module.exports = { - input, - output, - plugins: [ - alias({ - entries: [{ - find: '@dcloudio', - replacement: path.resolve(__dirname, '../packages') - }, { - find: 'uni-shared/query', - replacement: path.resolve(__dirname, '../src/shared/query.js') - }, { - find: 'uni-shared', - replacement: path.resolve(__dirname, '../src/shared/util.js') - }, { - find: 'uni-platform', - replacement: path.resolve(__dirname, '../src/platforms/' + process.env.UNI_PLATFORM) - }, { - find: 'uni-wrapper', - replacement: path.resolve(__dirname, '../src/core/runtime/wrapper') - }, { - find: 'uni-helpers', - replacement: path.resolve(__dirname, '../src/core/helpers') - }] - }), - json(), - replace({ - __GLOBAL__: platform.prefix, - __PLATFORM_TITLE__: platform.title, - __PLATFORM_PREFIX__: JSON.stringify(platform.prefix), - __PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM) - }) - ], - external: ['vue', '@dcloudio/uni-i18n'] -} +const path = require('path') +const json = require('@rollup/plugin-json') +const alias = require('@rollup/plugin-alias') +const replace = require('@rollup/plugin-replace') + +const PLATFORMS = { + 'mp-weixin': { + prefix: 'wx', + title: '微信小程序' + }, + 'mp-qq': { + prefix: 'wx', + title: 'QQ小程序' + }, + 'mp-alipay': { + prefix: 'my', + title: '支付宝小程序' + }, + 'mp-baidu': { + prefix: 'swan', + title: '百度小程序' + }, + 'mp-toutiao': { + prefix: 'tt', + title: '头条小程序' + }, + 'mp-kuaishou': { + prefix: 'ks', + title: '快手小程序' + }, + 'mp-lark': { + prefix: 'tt', + title: '飞书小程序' + }, + 'mp-jd': { + prefix: 'jd', + title: '京东小程序' + }, + 'mp-xhs': { + prefix: 'xhs', + title: '小红书小程序' + }, + 'quickapp-webview': { + prefix: 'qa', + title: '快应用(Webview)版' + }, + 'app-plus': { + prefix: 'wx', + title: 'app-plus' + } +} + +const platform = PLATFORMS[process.env.UNI_PLATFORM] + +let input = 'src/core/runtime/index.js' +const output = { + file: `packages/uni-${process.env.UNI_PLATFORM}/dist/index.js`, + format: 'es' +} + +if (process.env.UNI_MP) { + input = 'src/core/runtime/mp/index.js' + output.file = `packages/uni-${process.env.UNI_PLATFORM}/dist/mp.js` +} + +module.exports = { + input, + output, + plugins: [ + alias({ + entries: [{ + find: '@dcloudio', + replacement: path.resolve(__dirname, '../packages') + }, { + find: 'uni-shared/query', + replacement: path.resolve(__dirname, '../src/shared/query.js') + }, { + find: 'uni-shared', + replacement: path.resolve(__dirname, '../src/shared/util.js') + }, { + find: 'uni-platform', + replacement: path.resolve(__dirname, '../src/platforms/' + process.env.UNI_PLATFORM) + }, { + find: 'uni-wrapper', + replacement: path.resolve(__dirname, '../src/core/runtime/wrapper') + }, { + find: 'uni-helpers', + replacement: path.resolve(__dirname, '../src/core/helpers') + }] + }), + json(), + replace({ + __GLOBAL__: platform.prefix, + __PLATFORM_TITLE__: platform.title, + __PLATFORM_PREFIX__: JSON.stringify(platform.prefix), + __PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM) + }) + ], + external: ['vue', '@dcloudio/uni-i18n'] +} diff --git a/package.json b/package.json index cdd36491ba9a2fa5bdd25b8086a90b09bfc33010..4e75fe6b4b2fb78a121eac21d1c758c469605887 100644 --- a/package.json +++ b/package.json @@ -1,154 +1,156 @@ -{ - "name": "uni-app", - "version": "0.0.1", - "scripts": { - "lint": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore build src", - "lint:cli": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore packages/uni-cli-shared packages/uni-template-compiler \"packages/uni-*/lib/*.js\" \"packages/vue-cli-*/**/*.js\" \"packages/webpack-uni-*/**/*.js\"", - "dev:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.js", - "build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js", - "dev:plugin": "cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.plugin.js", - "build:plugin": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.plugin.js", - "build:app-plus": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.mp.js", - "build:app:v3": "npm run lint && npm run build:app:service && npm run build:app:view", - "build:app:service": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.app.js", - "build:app:view": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js", - "dev:app:view": "cross-env NODE_ENV=development UNI_WATCH=true UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js", - "build:mp-qq": "cross-env UNI_PLATFORM=mp-qq rollup -c build/rollup.config.mp.js", - "build:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin rollup -c build/rollup.config.mp.js", - "build:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.mp.js", - "build:mp-alipay": "cross-env UNI_PLATFORM=mp-alipay rollup -c build/rollup.config.mp.js", - "build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js", - "build:mp-kuaishou": "cross-env UNI_PLATFORM=mp-kuaishou rollup -c build/rollup.config.mp.js", - "build:mp-lark": "cross-env UNI_PLATFORM=mp-lark rollup -c build/rollup.config.mp.js", - "build:mp-jd": "cross-env UNI_PLATFORM=mp-jd rollup -c build/rollup.config.mp.js", - "build:quickapp-webview": "cross-env UNI_PLATFORM=quickapp-webview rollup -c build/rollup.config.mp.js", - "build:mp-weixin:mp": "cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js", - "build:mp-weixin:wxs": "rollup -c build/rollup.config.wxs.js", - "build:quickapp-native": "cross-env NODE_ENV=development node build/build.qa.js && cross-env NODE_ENV=production node build/build.qa.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:mp-jd && npm run build:app-plus && npm run build:quickapp-webview && npm run build:quickapp-native && npm run build:mp-kuaishou && npm run build:mp-lark && npm run build:mp-jd", +{ + "name": "uni-app", + "version": "0.0.1", + "scripts": { + "lint": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore build src", + "lint:cli": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore packages/uni-cli-shared packages/uni-template-compiler \"packages/uni-*/lib/*.js\" \"packages/vue-cli-*/**/*.js\" \"packages/webpack-uni-*/**/*.js\"", + "dev:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.js", + "build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js", + "dev:plugin": "cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.plugin.js", + "build:plugin": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.plugin.js", + "build:app-plus": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.mp.js", + "build:app:v3": "npm run lint && npm run build:app:service && npm run build:app:view", + "build:app:service": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.app.js", + "build:app:view": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js", + "dev:app:view": "cross-env NODE_ENV=development UNI_WATCH=true UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js", + "build:mp-qq": "cross-env UNI_PLATFORM=mp-qq rollup -c build/rollup.config.mp.js", + "build:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin rollup -c build/rollup.config.mp.js", + "build:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.mp.js", + "build:mp-alipay": "cross-env UNI_PLATFORM=mp-alipay rollup -c build/rollup.config.mp.js", + "build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js", + "build:mp-kuaishou": "cross-env UNI_PLATFORM=mp-kuaishou rollup -c build/rollup.config.mp.js", + "build:mp-lark": "cross-env UNI_PLATFORM=mp-lark rollup -c build/rollup.config.mp.js", + "build:mp-jd": "cross-env UNI_PLATFORM=mp-jd rollup -c build/rollup.config.mp.js", + "build:mp-xhs": "cross-env UNI_PLATFORM=mp-xhs rollup -c build/rollup.config.mp.js", + "build:quickapp-webview": "cross-env UNI_PLATFORM=quickapp-webview rollup -c build/rollup.config.mp.js", + "build:mp-weixin:mp": "cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js", + "build:mp-weixin:wxs": "rollup -c build/rollup.config.wxs.js", + "build:quickapp-native": "cross-env NODE_ENV=development node build/build.qa.js && cross-env NODE_ENV=production node build/build.qa.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:mp-jd && npm run build:mp-xhs && npm run build:app-plus && npm run build:quickapp-webview && npm run build:quickapp-native && npm run build:mp-kuaishou && npm run build:mp-lark && npm run build:mp-jd", "build:stat": "npm run lint && rollup -c build/rollup.config.stat.js", - "build:web-view": "rollup -c build/rollup.config.web-view.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", - "release:next": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=next", - "release:v3": "npm run lint:cli && lerna publish --no-git-tag-version --force-publish=* --npm-tag=v3" - }, - "dependencies": { - "base64-arraybuffer": "^0.2.0", - "intersection-observer": "^0.7.0", - "pako": "^1.0.11", - "safe-area-insets": "^1.4.1" - }, - "private": true, - "devDependencies": { - "@rollup/plugin-alias": "^3.1.0", - "@rollup/plugin-commonjs": "^11.1.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^7.1.3", - "@rollup/plugin-replace": "^2.3.1", - "@types/html5plus": "^1.0.0", - "@vue/cli-plugin-babel": "^4.3.1", - "@vue/cli-plugin-eslint": "^4.3.1", - "@vue/cli-plugin-unit-mocha": "^4.3.1", - "@vue/cli-service": "^4.3.1", - "@vue/test-utils": "^1.0.0-beta.33", - "babel-eslint": "^10.1.0", - "babylon": "^6.18.0", - "browserslist": "^4.11.1", - "caniuse-lite": "^1.0.30001040", - "chai": "^4.2.0", - "copy": "^0.3.2", - "cross-env": "^7.0.2", - "del": "^5.1.0", - "eslint": "^6.8.0", - "eslint-config-standard": "^14.1.0", - "eslint-loader": "^3.0.3", - "eslint-plugin-import": "^2.20.1", - "eslint-plugin-node": "^11.0.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.1", - "eslint-plugin-vue": "^6.2.2", - "i18n": "^0.13.3", - "jest": "^25.1.0", - "jsdom": "^16.2.1", - "jsdom-global": "^3.0.2", - "jsonfile": "^6.0.1", - "mustache": "^4.1.0", - "os-locale-s-fix": "^1.0.8-fix-1", - "recast": "^0.20.4", - "rollup": "^2.6.1", - "rollup-plugin-babel": "^4.4.0", - "rollup-plugin-terser": "^5.3.0", - "shell-exec": "^1.0.2", - "stricter-htmlparser2": "^3.9.6", - "strip-json-comments": "^3.1.0", - "vue": "^2.6.11", - "vue-router": "^3.0.1", - "vue-template-compiler": "^2.6.11", - "webpack": "^4.42.0", - "webpack-bundle-analyzer": "^3.6.1" - }, - "eslintConfig": { - "root": true, - "env": { - "node": true - }, - "extends": [ - "plugin:vue/recommended", - "standard" - ], - "globals": { - "App": true, - "Page": true, - "Component": true, - "Behavior": true, - "getApp": true, - "getCurrentPages": true, - "plus": true, - "uni": true, - "Vue": true, - "wx": true, - "my": true, - "swan": true, - "tt": true, - "qh": true, - "qa": true, - "HWH5": true, - "weex": true, - "__id__": true, - "__uniConfig": true, - "__uniRoutes": true, - "__registerPage": true, - "UniViewJSBridge": true, - "UniServiceJSBridge": true, - "__DEV__": true, - "__VIEW__": true, - "__PLATFORM__": true, - "__VERSION__": true, - "__GLOBAL__": true, - "__PLATFORM_TITLE__": true, - "__PLATFORM_PREFIX__": true, - "it": true, - "describe": true, - "expect": true - }, - "rules": { - "no-tabs": 0, - "standard/no-callback-literal": 0 - }, - "parserOptions": { - "parser": "babel-eslint" - } - }, - "browserslist": [ - "last 3 versions", - "Android >= 4.1", - "ios >= 8" - ], - "license": "Apache-2.0", - "main": "index.js", - "description": "", - "author": "" -} + "build:web-view": "rollup -c build/rollup.config.web-view.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", + "release:next": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=next", + "release:v3": "npm run lint:cli && lerna publish --no-git-tag-version --force-publish=* --npm-tag=v3" + }, + "dependencies": { + "base64-arraybuffer": "^0.2.0", + "intersection-observer": "^0.7.0", + "pako": "^1.0.11", + "safe-area-insets": "^1.4.1" + }, + "private": true, + "devDependencies": { + "@rollup/plugin-alias": "^3.1.0", + "@rollup/plugin-commonjs": "^11.1.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^7.1.3", + "@rollup/plugin-replace": "^2.3.1", + "@types/html5plus": "^1.0.0", + "@vue/cli-plugin-babel": "^4.3.1", + "@vue/cli-plugin-eslint": "^4.3.1", + "@vue/cli-plugin-unit-mocha": "^4.3.1", + "@vue/cli-service": "^4.3.1", + "@vue/test-utils": "^1.0.0-beta.33", + "babel-eslint": "^10.1.0", + "babylon": "^6.18.0", + "browserslist": "^4.11.1", + "caniuse-lite": "^1.0.30001040", + "chai": "^4.2.0", + "copy": "^0.3.2", + "cross-env": "^7.0.2", + "del": "^5.1.0", + "eslint": "^6.8.0", + "eslint-config-standard": "^14.1.0", + "eslint-loader": "^3.0.3", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-node": "^11.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "eslint-plugin-vue": "^6.2.2", + "i18n": "^0.13.3", + "jest": "^25.1.0", + "jsdom": "^16.2.1", + "jsdom-global": "^3.0.2", + "jsonfile": "^6.0.1", + "mustache": "^4.1.0", + "os-locale-s-fix": "^1.0.8-fix-1", + "recast": "^0.20.4", + "rollup": "^2.6.1", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-terser": "^5.3.0", + "shell-exec": "^1.0.2", + "stricter-htmlparser2": "^3.9.6", + "strip-json-comments": "^3.1.0", + "vue": "^2.6.11", + "vue-router": "^3.0.1", + "vue-template-compiler": "^2.6.11", + "webpack": "^4.42.0", + "webpack-bundle-analyzer": "^3.6.1" + }, + "eslintConfig": { + "root": true, + "env": { + "node": true + }, + "extends": [ + "plugin:vue/recommended", + "standard" + ], + "globals": { + "App": true, + "Page": true, + "Component": true, + "Behavior": true, + "getApp": true, + "getCurrentPages": true, + "plus": true, + "uni": true, + "Vue": true, + "wx": true, + "my": true, + "swan": true, + "tt": true, + "qh": true, + "qa": true, + "xhs": true, + "HWH5": true, + "weex": true, + "__id__": true, + "__uniConfig": true, + "__uniRoutes": true, + "__registerPage": true, + "UniViewJSBridge": true, + "UniServiceJSBridge": true, + "__DEV__": true, + "__VIEW__": true, + "__PLATFORM__": true, + "__VERSION__": true, + "__GLOBAL__": true, + "__PLATFORM_TITLE__": true, + "__PLATFORM_PREFIX__": true, + "it": true, + "describe": true, + "expect": true + }, + "rules": { + "no-tabs": 0, + "standard/no-callback-literal": 0 + }, + "parserOptions": { + "parser": "babel-eslint" + } + }, + "browserslist": [ + "last 3 versions", + "Android >= 4.1", + "ios >= 8" + ], + "license": "Apache-2.0", + "main": "index.js", + "description": "", + "author": "" +} \ No newline at end of file diff --git a/packages/uni-cli-shared/lib/platform.js b/packages/uni-cli-shared/lib/platform.js index 417f63ad12fcac2314daf75f2660eb9aa49249fc..553085b7ffa7ef12075006fcd3c7a30c4557aaba 100644 --- a/packages/uni-cli-shared/lib/platform.js +++ b/packages/uni-cli-shared/lib/platform.js @@ -148,7 +148,7 @@ module.exports = { getShadowCss, getShadowTemplate (colorType = 'grey') { let tagName = 'cover-image' - if (process.env.UNI_PLATFORM === 'mp-toutiao' || process.env.UNI_PLATFORM === 'mp-lark') { + if (process.env.UNI_PLATFORM === 'mp-toutiao' || process.env.UNI_PLATFORM === 'mp-lark' || process.env.UNI_PLATFORM === 'mp-xhs') { tagName = 'image' } return `<${tagName} src="${getShadowCdn()}/img/shadow-${colorType}.png" style="z-index:998;position:fixed;left:0;top:0;width:100%;height:3px;"/>` diff --git a/packages/uni-cli-shared/lib/plugin.js b/packages/uni-cli-shared/lib/plugin.js index d2be1a13f2330fff6d6c9780dfa607ae3f80d711..73efc591bdbd37a4808486e459fb26d9fd53068c 100644 --- a/packages/uni-cli-shared/lib/plugin.js +++ b/packages/uni-cli-shared/lib/plugin.js @@ -1,122 +1,122 @@ -const path = require('path') -const initPreprocessContext = require('./preprocess') -const uniI18n = require('@dcloudio/uni-cli-i18n') - -const Plugin = { - options: {}, - // 初步校验相关配置是否正确 - validate: [], // (platformOptions, manifestJson) {}, - configureEnv: [], // (){}, - // 以 H5 为基准的平台特殊配置 - configureH5: [], // (h5Options) {}, - configurePages: [], // (pagesJson,manifestJson,loader) {}, - // 链式修改 webpack config - chainWebpack: [], // (config, vueOptions, api) {}, - // 修改 webpack config - configureWebpack: [], // (config, vueOptions, api) {}, - // 配置额外的资源拷贝 - copyWebpackOptions: [] // (platformOptions, vueOptions) {} -} - -const PLUGIN_KEYS = Object.keys(Plugin) - -function initPlugin (plugin) { - let pluginApi - try { - pluginApi = require(path.join(plugin.id, (plugin.config.main || '/lib/uni.config.js'))) - } catch (e) { - console.warn(uniI18n.__('cliShared.missingUniConfig', { 0: plugin.id })) - } - - pluginApi && PLUGIN_KEYS.forEach(name => { - if (pluginApi[name]) { - if (Array.isArray(Plugin[name])) { // hooks - Plugin[name].push(pluginApi[name]) - } else { // options - Object.assign(Plugin[name], pluginApi[name]) - } - } - }) -} - -const pluginRE = /^(uni-|@[\w-]+(\.)?[\w-]+\/uni-)/ - -function resolvePlugins () { - const pkg = require(path.resolve(process.env.UNI_CLI_CONTEXT, 'package.json')) - return Object.keys(pkg.devDependencies || {}) - .concat(Object.keys(pkg.dependencies || {})) - .map(id => { - if (!pluginRE.test(id)) { - return - } - try { - const pluginPkg = require(id + '/package.json') - const config = pluginPkg['uni-app'] - if (!config) { - return - } - if (!config.name) { - return console.warn(uniI18n.__('cliShared.missingNameAttribute', { 0: `${id}/package.json->uni-app` })) - } - return { - id, - name: config.name, - config - } - } catch (e) {} - }).filter(Boolean) -} - -function initExtends (name, plugin, plugins) { - const extendsPlatform = plugin.config.extends - if (extendsPlatform) { - if (extendsPlatform !== 'h5') { - console.error(uniI18n.__('cliShared.extendOnlySupportH5')) - process.exit(0) - } - if (!plugin) { - console.error(uniI18n.__('cliShared.noFoundPlatformPlugin', { 0: extendsPlatform })) - process.exit(0) - } - const extendsPlugin = plugins.find(plugin => plugin.name === extendsPlatform) - process.env.UNI_SUB_PLATFORM = name - process.env.UNI_PLATFORM = extendsPlatform - initPlugin(extendsPlugin) - } -} - -module.exports = { - init () { - // compatible with vue-cli-service lint - process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5' - - // hack - if ( - process.env.UNI_PLATFORM === 'quickapp-webview-huawei' || - process.env.UNI_PLATFORM === 'quickapp-webview-union' - ) { - process.env.UNI_SUB_PLATFORM = process.env.UNI_PLATFORM - process.env.UNI_PLATFORM = 'quickapp-webview' - } - - const plugins = resolvePlugins() - const plugin = plugins.find(plugin => plugin.name === process.env.UNI_PLATFORM) - if (!plugin) { - console.error(uniI18n.__('cliShared.noFoundPlatformPlugin', { 0: process.env.UNI_PLATFORM })) - process.exit(0) - } - const name = plugin.name - - initExtends(name, plugin, plugins) - - initPlugin(plugin) - - Plugin.name = name - Plugin.id = plugin.id - Plugin.config = plugin.config - Plugin.platforms = plugins.map(plugin => plugin.name) - Plugin.preprocess = initPreprocessContext(name, Plugin.platforms, process.UNI_SCRIPT_DEFINE) - - return Plugin - } -} +const path = require('path') +const initPreprocessContext = require('./preprocess') +const uniI18n = require('@dcloudio/uni-cli-i18n') + +const Plugin = { + options: {}, + // 初步校验相关配置是否正确 + validate: [], // (platformOptions, manifestJson) {}, + configureEnv: [], // (){}, + // 以 H5 为基准的平台特殊配置 + configureH5: [], // (h5Options) {}, + configurePages: [], // (pagesJson,manifestJson,loader) {}, + // 链式修改 webpack config + chainWebpack: [], // (config, vueOptions, api) {}, + // 修改 webpack config + configureWebpack: [], // (config, vueOptions, api) {}, + // 配置额外的资源拷贝 + copyWebpackOptions: [] // (platformOptions, vueOptions) {} +} + +const PLUGIN_KEYS = Object.keys(Plugin) + +function initPlugin (plugin) { + let pluginApi + try { + pluginApi = require(path.join(plugin.id, (plugin.config.main || '/lib/uni.config.js'))) + } catch (e) { + console.warn(uniI18n.__('cliShared.missingUniConfig', { 0: plugin.id })) + } + + pluginApi && PLUGIN_KEYS.forEach(name => { + if (pluginApi[name]) { + if (Array.isArray(Plugin[name])) { // hooks + Plugin[name].push(pluginApi[name]) + } else { // options + Object.assign(Plugin[name], pluginApi[name]) + } + } + }) +} + +const pluginRE = /^(uni-|@[\w-]+(\.)?[\w-]+\/uni-)/ + +function resolvePlugins () { + const pkg = require(path.resolve(process.env.UNI_CLI_CONTEXT, 'package.json')) + return Object.keys(pkg.devDependencies || {}) + .concat(Object.keys(pkg.dependencies || {})) + .map(id => { + if (!pluginRE.test(id)) { + return + } + try { + const pluginPkg = require(id + '/package.json') + const config = pluginPkg['uni-app'] + if (!config) { + return + } + if (!config.name) { + return console.warn(uniI18n.__('cliShared.missingNameAttribute', { 0: `${id}/package.json->uni-app` })) + } + return { + id, + name: config.name, + config + } + } catch (e) {} + }).filter(Boolean) +} + +function initExtends (name, plugin, plugins) { + const extendsPlatform = plugin.config.extends + if (extendsPlatform) { + if (extendsPlatform !== 'h5') { + console.error(uniI18n.__('cliShared.extendOnlySupportH5')) + process.exit(0) + } + if (!plugin) { + console.error(uniI18n.__('cliShared.noFoundPlatformPlugin', { 0: extendsPlatform })) + process.exit(0) + } + const extendsPlugin = plugins.find(plugin => plugin.name === extendsPlatform) + process.env.UNI_SUB_PLATFORM = name + process.env.UNI_PLATFORM = extendsPlatform + initPlugin(extendsPlugin) + } +} + +module.exports = { + init () { + // compatible with vue-cli-service lint + process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5' + + // hack + if ( + process.env.UNI_PLATFORM === 'quickapp-webview-huawei' || + process.env.UNI_PLATFORM === 'quickapp-webview-union' + ) { + process.env.UNI_SUB_PLATFORM = process.env.UNI_PLATFORM + process.env.UNI_PLATFORM = 'quickapp-webview' + } + + const plugins = resolvePlugins() + const plugin = plugins.find(plugin => plugin.name === process.env.UNI_PLATFORM) + if (!plugin) { + console.error(uniI18n.__('cliShared.noFoundPlatformPlugin', { 0: process.env.UNI_PLATFORM })) + process.exit(0) + } + const name = plugin.name + + initExtends(name, plugin, plugins) + + initPlugin(plugin) + + Plugin.name = name + Plugin.id = plugin.id + Plugin.config = plugin.config + Plugin.platforms = plugins.map(plugin => plugin.name) + Plugin.preprocess = initPreprocessContext(name, Plugin.platforms, process.UNI_SCRIPT_DEFINE) + + return Plugin + } +} diff --git a/packages/uni-cli-shared/lib/url-loader.js b/packages/uni-cli-shared/lib/url-loader.js index 52c531a131aa4b8009632ceb665f4858a43b7f4a..3536f2682a5bcd548f9c3737b5eedecb75cf9253 100644 --- a/packages/uni-cli-shared/lib/url-loader.js +++ b/packages/uni-cli-shared/lib/url-loader.js @@ -1,51 +1,52 @@ -const fileLoader = require('./file-loader.js') - -const defaultOptions = { - limit: -1, - fallback: fileLoader -} - -const inlineLimit = - process.env.UNI_PLATFORM === 'mp-weixin' || - process.env.UNI_PLATFORM === 'mp-qq' || - process.env.UNI_PLATFORM === 'mp-toutiao' || - process.env.UNI_PLATFORM === 'mp-kuaishou' || - process.env.UNI_PLATFORM === 'mp-lark' || - process.env.UNI_PLATFORM === 'mp-jd' || - process.env.UNI_PLATFORM === 'app-plus' // v2需要base64,v3需要rewriteUrl - -// mp-weixin,mp-qq,app-plus 非v3(即:需要base64的平台) -// 将/static/logo.png转换为~@/static/logo.png -// @import,src,background,background-image - -const rewriteUrl = inlineLimit ? require('postcss-urlrewrite')({ - imports: true, - properties: ['src', 'background', 'background-image'], - rules: [{ - from: /^@\//, - to: '~@/' - }, { - from: /^\/([^/])/, - to: '~@/$1' - }] -}) : () => {} - -module.exports = { - loader: 'url-loader', - options () { - if (process.env.UNI_PLATFORM === 'h5') { - // h5平台,不对 url-loader 作调整,默认limit:4096,也不修改file-loader输出路径 - return {} - } - if (inlineLimit) { - return { - ...defaultOptions, - limit: process.env.UNI_USING_V3 ? -1 : 40960 // (主要用于background-image) - } - } - return { - ...defaultOptions - } - }, - rewriteUrl -} +const fileLoader = require('./file-loader.js') + +const defaultOptions = { + limit: -1, + fallback: fileLoader +} + +const inlineLimit = + process.env.UNI_PLATFORM === 'mp-weixin' || + process.env.UNI_PLATFORM === 'mp-qq' || + process.env.UNI_PLATFORM === 'mp-toutiao' || + process.env.UNI_PLATFORM === 'mp-kuaishou' || + process.env.UNI_PLATFORM === 'mp-lark' || + process.env.UNI_PLATFORM === 'mp-jd' || + process.env.UNI_PLATFORM === 'mp-xhs' || + process.env.UNI_PLATFORM === 'app-plus' // v2需要base64,v3需要rewriteUrl + +// mp-weixin,mp-qq,app-plus 非v3(即:需要base64的平台) +// 将/static/logo.png转换为~@/static/logo.png +// @import,src,background,background-image + +const rewriteUrl = inlineLimit ? require('postcss-urlrewrite')({ + imports: true, + properties: ['src', 'background', 'background-image'], + rules: [{ + from: /^@\//, + to: '~@/' + }, { + from: /^\/([^/])/, + to: '~@/$1' + }] +}) : () => {} + +module.exports = { + loader: 'url-loader', + options () { + if (process.env.UNI_PLATFORM === 'h5') { + // h5平台,不对 url-loader 作调整,默认limit:4096,也不修改file-loader输出路径 + return {} + } + if (inlineLimit) { + return { + ...defaultOptions, + limit: process.env.UNI_USING_V3 ? -1 : 40960 // (主要用于background-image) + } + } + return { + ...defaultOptions + } + }, + rewriteUrl +} diff --git a/packages/uni-mp-xhs/README.md b/packages/uni-mp-xhs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..39810bcbf939336f32019d15c4eaa5c835e02887 --- /dev/null +++ b/packages/uni-mp-xhs/README.md @@ -0,0 +1,11 @@ +# `uni-mp-xhs` + +> 处理模板上的差异,比如文件格式模板上的各种指令。 + +## Usage + +``` +const uniMpXhs = require('uni-mp-xhs'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/uni-mp-xhs/dist/index.js b/packages/uni-mp-xhs/dist/index.js new file mode 100644 index 0000000000000000000000000000000000000000..79506250e5c5558f96a4016dbb336a4ead96a0c6 --- /dev/null +++ b/packages/uni-mp-xhs/dist/index.js @@ -0,0 +1,2179 @@ +import Vue from 'vue'; +import { initVueI18n } from '@dcloudio/uni-i18n'; + +let realAtob; + +const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +const b64re = /^(?:[A-Za-z\d+/]{4})*?(?:[A-Za-z\d+/]{2}(?:==)?|[A-Za-z\d+/]{3}=?)?$/; + +if (typeof atob !== 'function') { + realAtob = function (str) { + str = String(str).replace(/[\t\n\f\r ]+/g, ''); + if (!b64re.test(str)) { throw new Error("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.") } + + // Adding the padding if missing, for semplicity + str += '=='.slice(2 - (str.length & 3)); + var bitmap; var result = ''; var r1; var r2; var i = 0; + for (; i < str.length;) { + bitmap = b64.indexOf(str.charAt(i++)) << 18 | b64.indexOf(str.charAt(i++)) << 12 | + (r1 = b64.indexOf(str.charAt(i++))) << 6 | (r2 = b64.indexOf(str.charAt(i++))); + + result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) + : r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) + : String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); + } + return result + }; +} else { + // 注意atob只能在全局对象上调用,例如:`const Base64 = {atob};Base64.atob('xxxx')`是错误的用法 + realAtob = atob; +} + +function b64DecodeUnicode (str) { + return decodeURIComponent(realAtob(str).split('').map(function (c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + }).join('')) +} + +function getCurrentUserInfo () { + const token = ( xhs).getStorageSync('uni_id_token') || ''; + const tokenArr = token.split('.'); + if (!token || tokenArr.length !== 3) { + return { + uid: null, + role: [], + permission: [], + tokenExpired: 0 + } + } + let userInfo; + try { + userInfo = JSON.parse(b64DecodeUnicode(tokenArr[1])); + } catch (error) { + throw new Error('获取当前用户信息出错,详细错误信息为:' + error.message) + } + userInfo.tokenExpired = userInfo.exp * 1000; + delete userInfo.exp; + delete userInfo.iat; + return userInfo +} + +function uniIdMixin (Vue) { + Vue.prototype.uniIDHasRole = function (roleId) { + const { + role + } = getCurrentUserInfo(); + return role.indexOf(roleId) > -1 + }; + Vue.prototype.uniIDHasPermission = function (permissionId) { + const { + permission + } = getCurrentUserInfo(); + return this.uniIDHasRole('admin') || permission.indexOf(permissionId) > -1 + }; + Vue.prototype.uniIDTokenValid = function () { + const { + tokenExpired + } = getCurrentUserInfo(); + return tokenExpired > Date.now() + }; +} + +const _toString = Object.prototype.toString; +const hasOwnProperty = Object.prototype.hasOwnProperty; + +function isFn (fn) { + return typeof fn === 'function' +} + +function isStr (str) { + return typeof str === 'string' +} + +function isPlainObject (obj) { + return _toString.call(obj) === '[object Object]' +} + +function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) +} + +function noop () {} + +/** + * Create a cached version of a pure function. + */ +function cached (fn) { + const cache = Object.create(null); + return function cachedFn (str) { + const hit = cache[str]; + return hit || (cache[str] = fn(str)) + } +} + +/** + * Camelize a hyphen-delimited string. + */ +const camelizeRE = /-(\w)/g; +const camelize = cached((str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') +}); + +const HOOKS = [ + 'invoke', + 'success', + 'fail', + 'complete', + 'returnValue' +]; + +const globalInterceptors = {}; +const scopedInterceptors = {}; + +function mergeHook (parentVal, childVal) { + const res = childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal : [childVal] + : parentVal; + return res + ? dedupeHooks(res) + : res +} + +function dedupeHooks (hooks) { + const res = []; + for (let i = 0; i < hooks.length; i++) { + if (res.indexOf(hooks[i]) === -1) { + res.push(hooks[i]); + } + } + return res +} + +function removeHook (hooks, hook) { + const index = hooks.indexOf(hook); + if (index !== -1) { + hooks.splice(index, 1); + } +} + +function mergeInterceptorHook (interceptor, option) { + Object.keys(option).forEach(hook => { + if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) { + interceptor[hook] = mergeHook(interceptor[hook], option[hook]); + } + }); +} + +function removeInterceptorHook (interceptor, option) { + if (!interceptor || !option) { + return + } + Object.keys(option).forEach(hook => { + if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) { + removeHook(interceptor[hook], option[hook]); + } + }); +} + +function addInterceptor (method, option) { + if (typeof method === 'string' && isPlainObject(option)) { + mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), option); + } else if (isPlainObject(method)) { + mergeInterceptorHook(globalInterceptors, method); + } +} + +function removeInterceptor (method, option) { + if (typeof method === 'string') { + if (isPlainObject(option)) { + removeInterceptorHook(scopedInterceptors[method], option); + } else { + delete scopedInterceptors[method]; + } + } else if (isPlainObject(method)) { + removeInterceptorHook(globalInterceptors, method); + } +} + +function wrapperHook (hook) { + return function (data) { + return hook(data) || data + } +} + +function isPromise (obj) { + return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' +} + +function queue (hooks, data) { + let promise = false; + for (let i = 0; i < hooks.length; i++) { + const hook = hooks[i]; + if (promise) { + promise = Promise.resolve(wrapperHook(hook)); + } else { + const res = hook(data); + if (isPromise(res)) { + promise = Promise.resolve(res); + } + if (res === false) { + return { + then () { } + } + } + } + } + return promise || { + then (callback) { + return callback(data) + } + } +} + +function wrapperOptions (interceptor, options = {}) { + ['success', 'fail', 'complete'].forEach(name => { + if (Array.isArray(interceptor[name])) { + const oldCallback = options[name]; + options[name] = function callbackInterceptor (res) { + queue(interceptor[name], res).then((res) => { + /* eslint-disable no-mixed-operators */ + return isFn(oldCallback) && oldCallback(res) || res + }); + }; + } + }); + return options +} + +function wrapperReturnValue (method, returnValue) { + const returnValueHooks = []; + if (Array.isArray(globalInterceptors.returnValue)) { + returnValueHooks.push(...globalInterceptors.returnValue); + } + const interceptor = scopedInterceptors[method]; + if (interceptor && Array.isArray(interceptor.returnValue)) { + returnValueHooks.push(...interceptor.returnValue); + } + returnValueHooks.forEach(hook => { + returnValue = hook(returnValue) || returnValue; + }); + return returnValue +} + +function getApiInterceptorHooks (method) { + const interceptor = Object.create(null); + Object.keys(globalInterceptors).forEach(hook => { + if (hook !== 'returnValue') { + interceptor[hook] = globalInterceptors[hook].slice(); + } + }); + const scopedInterceptor = scopedInterceptors[method]; + if (scopedInterceptor) { + Object.keys(scopedInterceptor).forEach(hook => { + if (hook !== 'returnValue') { + interceptor[hook] = (interceptor[hook] || []).concat(scopedInterceptor[hook]); + } + }); + } + return interceptor +} + +function invokeApi (method, api, options, ...params) { + const interceptor = getApiInterceptorHooks(method); + if (interceptor && Object.keys(interceptor).length) { + if (Array.isArray(interceptor.invoke)) { + const res = queue(interceptor.invoke, options); + return res.then((options) => { + return api(wrapperOptions(interceptor, options), ...params) + }) + } else { + return api(wrapperOptions(interceptor, options), ...params) + } + } + return api(options, ...params) +} + +const promiseInterceptor = { + returnValue (res) { + if (!isPromise(res)) { + return res + } + return new Promise((resolve, reject) => { + res.then(res => { + if (res[0]) { + reject(res[0]); + } else { + resolve(res[1]); + } + }); + }) + } +}; + +const SYNC_API_RE = + /^\$|Window$|WindowStyle$|sendHostEvent|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64|getLocale|setLocale/; + +const CONTEXT_API_RE = /^create|Manager$/; + +// Context例外情况 +const CONTEXT_API_RE_EXC = ['createBLEConnection']; + +// 同步例外情况 +const ASYNC_API = ['createBLEConnection']; + +const CALLBACK_API_RE = /^on|^off/; + +function isContextApi (name) { + return CONTEXT_API_RE.test(name) && CONTEXT_API_RE_EXC.indexOf(name) === -1 +} +function isSyncApi (name) { + return SYNC_API_RE.test(name) && ASYNC_API.indexOf(name) === -1 +} + +function isCallbackApi (name) { + return CALLBACK_API_RE.test(name) && name !== 'onPush' +} + +function handlePromise (promise) { + return promise.then(data => { + return [null, data] + }) + .catch(err => [err]) +} + +function shouldPromise (name) { + if ( + isContextApi(name) || + isSyncApi(name) || + isCallbackApi(name) + ) { + return false + } + return true +} + +/* eslint-disable no-extend-native */ +if (!Promise.prototype.finally) { + Promise.prototype.finally = function (callback) { + const promise = this.constructor; + return this.then( + value => promise.resolve(callback()).then(() => value), + reason => promise.resolve(callback()).then(() => { + throw reason + }) + ) + }; +} + +function promisify (name, api) { + if (!shouldPromise(name)) { + return api + } + return function promiseApi (options = {}, ...params) { + if (isFn(options.success) || isFn(options.fail) || isFn(options.complete)) { + return wrapperReturnValue(name, invokeApi(name, api, options, ...params)) + } + return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => { + invokeApi(name, api, Object.assign({}, options, { + success: resolve, + fail: reject + }), ...params); + }))) + } +} + +const EPS = 1e-4; +const BASE_DEVICE_WIDTH = 750; +let isIOS = false; +let deviceWidth = 0; +let deviceDPR = 0; + +function checkDeviceWidth () { + const { + platform, + pixelRatio, + windowWidth + } = xhs.getSystemInfoSync(); // uni=>xhs runtime 编译目标是 uni 对象,内部不允许直接使用 uni + + deviceWidth = windowWidth; + deviceDPR = pixelRatio; + isIOS = platform === 'ios'; +} + +function upx2px (number, newDeviceWidth) { + if (deviceWidth === 0) { + checkDeviceWidth(); + } + + number = Number(number); + if (number === 0) { + return 0 + } + let result = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth); + if (result < 0) { + result = -result; + } + result = Math.floor(result + EPS); + if (result === 0) { + if (deviceDPR === 1 || !isIOS) { + result = 1; + } else { + result = 0.5; + } + } + return number < 0 ? -result : result +} + +function getLocale () { + // 优先使用 $locale + const app = getApp({ + allowDefault: true + }); + if (app && app.$vm) { + return app.$vm.$locale + } + return xhs.getSystemInfoSync().language || 'zh-Hans' +} + +function setLocale (locale) { + const app = getApp(); + if (!app) { + return false + } + const oldLocale = app.$vm.$locale; + if (oldLocale !== locale) { + app.$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ + locale + })); + return true + } + return false +} + +const onLocaleChangeCallbacks = []; +function onLocaleChange (fn) { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +} + +if (typeof global !== 'undefined') { + global.getLocale = getLocale; +} + +const interceptors = { + promiseInterceptor +}; + +var baseApi = /*#__PURE__*/Object.freeze({ + __proto__: null, + upx2px: upx2px, + getLocale: getLocale, + setLocale: setLocale, + onLocaleChange: onLocaleChange, + addInterceptor: addInterceptor, + removeInterceptor: removeInterceptor, + interceptors: interceptors +}); + +// import navigateTo from 'uni-helpers/navigate-to' +// import redirectTo from '../../../mp-weixin/helpers/redirect-to' +// import previewImage from '../../../mp-weixin/helpers/normalize-preview-image' +// import getSystemInfo from '../../../mp-weixin/helpers/system-info' +// import getUserProfile from '../../../mp-weixin/helpers/get-user-profile' + +// 需要做转换的 API 列表 +const protocols = { + // navigateTo, + // redirectTo, + // previewImage, + // getSystemInfo, + // getSystemInfoSync: getSystemInfo, + // getUserProfile +}; + +// 不支持的 API 列表 +// TODO: 补充 +const todos = [ + 'getSelectedTextRange' +]; + +// 存在兼容性的 API 列表 +const canIUses = []; + +const CALLBACKS = ['success', 'fail', 'cancel', 'complete']; + +function processCallback (methodName, method, returnValue) { + return function (res) { + return method(processReturnValue(methodName, res, returnValue)) + } +} + +function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, keepFromArgs = false) { + if (isPlainObject(fromArgs)) { // 一般 api 的参数解析 + const toArgs = keepFromArgs === true ? fromArgs : {}; // returnValue 为 false 时,说明是格式化返回值,直接在返回值对象上修改赋值 + if (isFn(argsOption)) { + argsOption = argsOption(fromArgs, toArgs) || {}; + } + for (const key in fromArgs) { + if (hasOwn(argsOption, key)) { + let keyOption = argsOption[key]; + if (isFn(keyOption)) { + keyOption = keyOption(fromArgs[key], fromArgs, toArgs); + } + if (!keyOption) { // 不支持的参数 + console.warn(`The '${methodName}' method of platform '小红书小程序' does not support option '${key}'`); + } else if (isStr(keyOption)) { // 重写参数 key + toArgs[keyOption] = fromArgs[key]; + } else if (isPlainObject(keyOption)) { // {name:newName,value:value}可重新指定参数 key:value + toArgs[keyOption.name ? keyOption.name : key] = keyOption.value; + } + } else if (CALLBACKS.indexOf(key) !== -1) { + if (isFn(fromArgs[key])) { + toArgs[key] = processCallback(methodName, fromArgs[key], returnValue); + } + } else { + if (!keepFromArgs) { + toArgs[key] = fromArgs[key]; + } + } + } + return toArgs + } else if (isFn(fromArgs)) { + fromArgs = processCallback(methodName, fromArgs, returnValue); + } + return fromArgs +} + +function processReturnValue (methodName, res, returnValue, keepReturnValue = false) { + if (isFn(protocols.returnValue)) { // 处理通用 returnValue + res = protocols.returnValue(methodName, res); + } + return processArgs(methodName, res, returnValue, {}, keepReturnValue) +} + +function wrapper (methodName, method) { + if (hasOwn(protocols, methodName)) { + const protocol = protocols[methodName]; + if (!protocol) { // 暂不支持的 api + return function () { + console.error(`Platform '小红书小程序' does not support '${methodName}'.`); + } + } + return function (arg1, arg2) { // 目前 api 最多两个参数 + let options = protocol; + if (isFn(protocol)) { + options = protocol(arg1); + } + + arg1 = processArgs(methodName, arg1, options.args, options.returnValue); + + const args = [arg1]; + if (typeof arg2 !== 'undefined') { + args.push(arg2); + } + if (isFn(options.name)) { + methodName = options.name(arg1); + } else if (isStr(options.name)) { + methodName = options.name; + } + const returnValue = xhs[methodName].apply(xhs, args); + if (isSyncApi(methodName)) { // 同步 api + return processReturnValue(methodName, returnValue, options.returnValue, isContextApi(methodName)) + } + return returnValue + } + } + return method +} + +const todoApis = Object.create(null); + +const TODOS = [ + 'onTabBarMidButtonTap', + 'subscribePush', + 'unsubscribePush', + 'onPush', + 'offPush', + 'share' +]; + +function createTodoApi (name) { + return function todoApi ({ + fail, + complete + }) { + const res = { + errMsg: `${name}:fail method '${name}' not supported` + }; + isFn(fail) && fail(res); + isFn(complete) && complete(res); + } +} + +TODOS.forEach(function (name) { + todoApis[name] = createTodoApi(name); +}); + +var providers = { + oauth: ['xhs'], + share: ['xhs'], + payment: ['xhs'], + push: ['xhs'] +}; + +function getProvider ({ + service, + success, + fail, + complete +}) { + let res = false; + if (providers[service]) { + res = { + errMsg: 'getProvider:ok', + service, + provider: providers[service] + }; + isFn(success) && success(res); + } else { + res = { + errMsg: 'getProvider:fail service not found' + }; + isFn(fail) && fail(res); + } + isFn(complete) && complete(res); +} + +var extraApi = /*#__PURE__*/Object.freeze({ + __proto__: null, + getProvider: getProvider +}); + +const getEmitter = (function () { + let Emitter; + return function getUniEmitter () { + if (!Emitter) { + Emitter = new Vue(); + } + return Emitter + } +})(); + +function apply (ctx, method, args) { + return ctx[method].apply(ctx, args) +} + +function $on () { + return apply(getEmitter(), '$on', [...arguments]) +} +function $off () { + return apply(getEmitter(), '$off', [...arguments]) +} +function $once () { + return apply(getEmitter(), '$once', [...arguments]) +} +function $emit () { + return apply(getEmitter(), '$emit', [...arguments]) +} + +var eventApi = /*#__PURE__*/Object.freeze({ + __proto__: null, + $on: $on, + $off: $off, + $once: $once, + $emit: $emit +}); + +var api = /*#__PURE__*/Object.freeze({ + __proto__: null +}); + +const MPPage = Page; +const MPComponent = Component; + +const customizeRE = /:/g; + +const customize = cached((str) => { + return camelize(str.replace(customizeRE, '-')) +}); + +function initTriggerEvent (mpInstance) { + const oldTriggerEvent = mpInstance.triggerEvent; + const newTriggerEvent = function (event, ...args) { + return oldTriggerEvent.apply(mpInstance, [customize(event), ...args]) + }; + try { + // 京东小程序 triggerEvent 为只读 + mpInstance.triggerEvent = newTriggerEvent; + } catch (error) { + mpInstance._triggerEvent = newTriggerEvent; + } +} + +function initHook (name, options, isComponent) { + const oldHook = options[name]; + if (!oldHook) { + options[name] = function () { + initTriggerEvent(this); + }; + } else { + options[name] = function (...args) { + initTriggerEvent(this); + return oldHook.apply(this, args) + }; + } +} +if (!MPPage.__$wrappered) { + MPPage.__$wrappered = true; + Page = function (options = {}) { + initHook('onLoad', options); + return MPPage(options) + }; + Page.after = MPPage.after; + + Component = function (options = {}) { + initHook('created', options); + return MPComponent(options) + }; +} + +const PAGE_EVENT_HOOKS = [ + 'onPullDownRefresh', + 'onReachBottom', + 'onAddToFavorites', + 'onShareTimeline', + 'onShareAppMessage', + 'onPageScroll', + 'onResize', + 'onTabItemTap' +]; + +function initMocks (vm, mocks) { + const mpInstance = vm.$mp[vm.mpType]; + mocks.forEach(mock => { + if (hasOwn(mpInstance, mock)) { + vm[mock] = mpInstance[mock]; + } + }); +} + +function hasHook (hook, vueOptions) { + if (!vueOptions) { + return true + } + + if (Vue.options && Array.isArray(Vue.options[hook])) { + return true + } + + vueOptions = vueOptions.default || vueOptions; + + if (isFn(vueOptions)) { + if (isFn(vueOptions.extendOptions[hook])) { + return true + } + if (vueOptions.super && + vueOptions.super.options && + Array.isArray(vueOptions.super.options[hook])) { + return true + } + return false + } + + if (isFn(vueOptions[hook])) { + return true + } + const mixins = vueOptions.mixins; + if (Array.isArray(mixins)) { + return !!mixins.find(mixin => hasHook(hook, mixin)) + } +} + +function initHooks (mpOptions, hooks, vueOptions) { + hooks.forEach(hook => { + if (hasHook(hook, vueOptions)) { + mpOptions[hook] = function (args) { + return this.$vm && this.$vm.__call_hook(hook, args) + }; + } + }); +} + +function initVueComponent (Vue, vueOptions) { + vueOptions = vueOptions.default || vueOptions; + let VueComponent; + if (isFn(vueOptions)) { + VueComponent = vueOptions; + } else { + VueComponent = Vue.extend(vueOptions); + } + vueOptions = VueComponent.options; + return [VueComponent, vueOptions] +} + +function initSlots (vm, vueSlots) { + if (Array.isArray(vueSlots) && vueSlots.length) { + const $slots = Object.create(null); + vueSlots.forEach(slotName => { + $slots[slotName] = true; + }); + vm.$scopedSlots = vm.$slots = $slots; + } +} + +function initVueIds (vueIds, mpInstance) { + vueIds = (vueIds || '').split(','); + const len = vueIds.length; + + if (len === 1) { + mpInstance._$vueId = vueIds[0]; + } else if (len === 2) { + mpInstance._$vueId = vueIds[0]; + mpInstance._$vuePid = vueIds[1]; + } +} + +function initData (vueOptions, context) { + let data = vueOptions.data || {}; + const methods = vueOptions.methods || {}; + + if (typeof data === 'function') { + try { + data = data.call(context); // 支持 Vue.prototype 上挂的数据 + } catch (e) { + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + } + } + } else { + try { + // 对 data 格式化 + data = JSON.parse(JSON.stringify(data)); + } catch (e) {} + } + + if (!isPlainObject(data)) { + data = {}; + } + + Object.keys(methods).forEach(methodName => { + if (context.__lifecycle_hooks__.indexOf(methodName) === -1 && !hasOwn(data, methodName)) { + data[methodName] = methods[methodName]; + } + }); + + return data +} + +const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; + +function createObserver (name) { + return function observer (newVal, oldVal) { + if (this.$vm) { + this.$vm[name] = newVal; // 为了触发其他非 render watcher + } + } +} + +function initBehaviors (vueOptions, initBehavior) { + const vueBehaviors = vueOptions.behaviors; + const vueExtends = vueOptions.extends; + const vueMixins = vueOptions.mixins; + + let vueProps = vueOptions.props; + + if (!vueProps) { + vueOptions.props = vueProps = []; + } + + const behaviors = []; + if (Array.isArray(vueBehaviors)) { + vueBehaviors.forEach(behavior => { + behaviors.push(behavior.replace('uni://', `${"xhs"}://`)); + if (behavior === 'uni://form-field') { + if (Array.isArray(vueProps)) { + vueProps.push('name'); + vueProps.push('value'); + } else { + vueProps.name = { + type: String, + default: '' + }; + vueProps.value = { + type: [String, Number, Boolean, Array, Object, Date], + default: '' + }; + } + } + }); + } + if (isPlainObject(vueExtends) && vueExtends.props) { + behaviors.push( + initBehavior({ + properties: initProperties(vueExtends.props, true) + }) + ); + } + if (Array.isArray(vueMixins)) { + vueMixins.forEach(vueMixin => { + if (isPlainObject(vueMixin) && vueMixin.props) { + behaviors.push( + initBehavior({ + properties: initProperties(vueMixin.props, true) + }) + ); + } + }); + } + return behaviors +} + +function parsePropType (key, type, defaultValue, file) { + // [String]=>String + if (Array.isArray(type) && type.length === 1) { + return type[0] + } + return type +} + +function initProperties (props, isBehavior = false, file = '') { + const properties = {}; + if (!isBehavior) { + properties.vueId = { + type: String, + value: '' + }; + // 用于字节跳动小程序模拟抽象节点 + properties.generic = { + type: Object, + value: null + }; + // scopedSlotsCompiler auto + properties.scopedSlotsCompiler = { + type: String, + value: '' + }; + properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots + type: null, + value: [], + observer: function (newVal, oldVal) { + const $slots = Object.create(null); + newVal.forEach(slotName => { + $slots[slotName] = true; + }); + this.setData({ + $slots + }); + } + }; + } + if (Array.isArray(props)) { // ['title'] + props.forEach(key => { + properties[key] = { + type: null, + observer: createObserver(key) + }; + }); + } else if (isPlainObject(props)) { // {title:{type:String,default:''},content:String} + Object.keys(props).forEach(key => { + const opts = props[key]; + if (isPlainObject(opts)) { // title:{type:String,default:''} + let value = opts.default; + if (isFn(value)) { + value = value(); + } + + opts.type = parsePropType(key, opts.type); + + properties[key] = { + type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null, + value, + observer: createObserver(key) + }; + } else { // content:String + const type = parsePropType(key, opts); + properties[key] = { + type: PROP_TYPES.indexOf(type) !== -1 ? type : null, + observer: createObserver(key) + }; + } + }); + } + return properties +} + +function wrapper$1 (event) { + // TODO 又得兼容 mpvue 的 mp 对象 + try { + event.mp = JSON.parse(JSON.stringify(event)); + } catch (e) {} + + event.stopPropagation = noop; + event.preventDefault = noop; + + event.target = event.target || {}; + + if (!hasOwn(event, 'detail')) { + event.detail = {}; + } + + if (hasOwn(event, 'markerId')) { + event.detail = typeof event.detail === 'object' ? event.detail : {}; + event.detail.markerId = event.markerId; + } + + if (isPlainObject(event.detail)) { + event.target = Object.assign({}, event.target, event.detail); + } + + return event +} + +function getExtraValue (vm, dataPathsArray) { + let context = vm; + dataPathsArray.forEach(dataPathArray => { + const dataPath = dataPathArray[0]; + const value = dataPathArray[2]; + if (dataPath || typeof value !== 'undefined') { // ['','',index,'disable'] + const propPath = dataPathArray[1]; + const valuePath = dataPathArray[3]; + + let vFor; + if (Number.isInteger(dataPath)) { + vFor = dataPath; + } else if (!dataPath) { + vFor = context; + } else if (typeof dataPath === 'string' && dataPath) { + if (dataPath.indexOf('#s#') === 0) { + vFor = dataPath.substr(3); + } else { + vFor = vm.__get_value(dataPath, context); + } + } + + if (Number.isInteger(vFor)) { + context = value; + } else if (!propPath) { + context = vFor[value]; + } else { + if (Array.isArray(vFor)) { + context = vFor.find(vForItem => { + return vm.__get_value(propPath, vForItem) === value + }); + } else if (isPlainObject(vFor)) { + context = Object.keys(vFor).find(vForKey => { + return vm.__get_value(propPath, vFor[vForKey]) === value + }); + } else { + console.error('v-for 暂不支持循环数据:', vFor); + } + } + + if (valuePath) { + context = vm.__get_value(valuePath, context); + } + } + }); + return context +} + +function processEventExtra (vm, extra, event) { + const extraObj = {}; + + if (Array.isArray(extra) && extra.length) { + /** + *[ + * ['data.items', 'data.id', item.data.id], + * ['metas', 'id', meta.id] + *], + *[ + * ['data.items', 'data.id', item.data.id], + * ['metas', 'id', meta.id] + *], + *'test' + */ + extra.forEach((dataPath, index) => { + if (typeof dataPath === 'string') { + if (!dataPath) { // model,prop.sync + extraObj['$' + index] = vm; + } else { + if (dataPath === '$event') { // $event + extraObj['$' + index] = event; + } else if (dataPath === 'arguments') { + if (event.detail && event.detail.__args__) { + extraObj['$' + index] = event.detail.__args__; + } else { + extraObj['$' + index] = [event]; + } + } else if (dataPath.indexOf('$event.') === 0) { // $event.target.value + extraObj['$' + index] = vm.__get_value(dataPath.replace('$event.', ''), event); + } else { + extraObj['$' + index] = vm.__get_value(dataPath); + } + } + } else { + extraObj['$' + index] = getExtraValue(vm, dataPath); + } + }); + } + + return extraObj +} + +function getObjByArray (arr) { + const obj = {}; + for (let i = 1; i < arr.length; i++) { + const element = arr[i]; + obj[element[0]] = element[1]; + } + return obj +} + +function processEventArgs (vm, event, args = [], extra = [], isCustom, methodName) { + let isCustomMPEvent = false; // wxcomponent 组件,传递原始 event 对象 + if (isCustom) { // 自定义事件 + isCustomMPEvent = event.currentTarget && + event.currentTarget.dataset && + event.currentTarget.dataset.comType === 'wx'; + if (!args.length) { // 无参数,直接传入 event 或 detail 数组 + if (isCustomMPEvent) { + return [event] + } + return event.detail.__args__ || event.detail + } + } + + const extraObj = processEventExtra(vm, extra, event); + + const ret = []; + args.forEach(arg => { + if (arg === '$event') { + if (methodName === '__set_model' && !isCustom) { // input v-model value + ret.push(event.target.value); + } else { + if (isCustom && !isCustomMPEvent) { + ret.push(event.detail.__args__[0]); + } else { // wxcomponent 组件或内置组件 + ret.push(event); + } + } + } else { + if (Array.isArray(arg) && arg[0] === 'o') { + ret.push(getObjByArray(arg)); + } else if (typeof arg === 'string' && hasOwn(extraObj, arg)) { + ret.push(extraObj[arg]); + } else { + ret.push(arg); + } + } + }); + + return ret +} + +const ONCE = '~'; +const CUSTOM = '^'; + +function isMatchEventType (eventType, optType) { + return (eventType === optType) || + ( + optType === 'regionchange' && + ( + eventType === 'begin' || + eventType === 'end' + ) + ) +} + +function getContextVm (vm) { + let $parent = vm.$parent; + // 父组件是 scoped slots 或者其他自定义组件时继续查找 + while ($parent && $parent.$parent && ($parent.$options.generic || $parent.$parent.$options.generic || $parent.$scope._$vuePid)) { + $parent = $parent.$parent; + } + return $parent && $parent.$parent +} + +function handleEvent (event) { + event = wrapper$1(event); + + // [['tap',[['handle',[1,2,a]],['handle1',[1,2,a]]]]] + const dataset = (event.currentTarget || event.target).dataset; + if (!dataset) { + return console.warn('事件信息不存在') + } + const eventOpts = dataset.eventOpts || dataset['event-opts']; // 支付宝 web-view 组件 dataset 非驼峰 + if (!eventOpts) { + return console.warn('事件信息不存在') + } + + // [['handle',[1,2,a]],['handle1',[1,2,a]]] + const eventType = event.type; + + const ret = []; + + eventOpts.forEach(eventOpt => { + let type = eventOpt[0]; + const eventsArray = eventOpt[1]; + + const isCustom = type.charAt(0) === CUSTOM; + type = isCustom ? type.slice(1) : type; + const isOnce = type.charAt(0) === ONCE; + type = isOnce ? type.slice(1) : type; + + if (eventsArray && isMatchEventType(eventType, type)) { + eventsArray.forEach(eventArray => { + const methodName = eventArray[0]; + if (methodName) { + let handlerCtx = this.$vm; + if (handlerCtx.$options.generic) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots + handlerCtx = getContextVm(handlerCtx) || handlerCtx; + } + if (methodName === '$emit') { + handlerCtx.$emit.apply(handlerCtx, + processEventArgs( + this.$vm, + event, + eventArray[1], + eventArray[2], + isCustom, + methodName + )); + return + } + const handler = handlerCtx[methodName]; + if (!isFn(handler)) { + throw new Error(` _vm.${methodName} is not a function`) + } + if (isOnce) { + if (handler.once) { + return + } + handler.once = true; + } + let params = processEventArgs( + this.$vm, + event, + eventArray[1], + eventArray[2], + isCustom, + methodName + ); + params = Array.isArray(params) ? params : []; + // 参数尾部增加原始事件对象用于复杂表达式内获取额外数据 + if (/=\s*\S+\.eventParams\s*\|\|\s*\S+\[['"]event-params['"]\]/.test(handler.toString())) { + // eslint-disable-next-line no-sparse-arrays + params = params.concat([, , , , , , , , , , event]); + } + ret.push(handler.apply(handlerCtx, params)); + } + }); + } + }); + + if ( + eventType === 'input' && + ret.length === 1 && + typeof ret[0] !== 'undefined' + ) { + return ret[0] + } +} + +const messages = {}; + +let locale; + +{ + locale = xhs.getSystemInfoSync().language; +} + +function initI18nMessages () { + if (!isEnableLocale()) { + return + } + const localeKeys = Object.keys(__uniConfig.locales); + if (localeKeys.length) { + localeKeys.forEach((locale) => { + const curMessages = messages[locale]; + const userMessages = __uniConfig.locales[locale]; + if (curMessages) { + Object.assign(curMessages, userMessages); + } else { + messages[locale] = userMessages; + } + }); + } +} + +initI18nMessages(); + +const i18n = initVueI18n( + locale, + {} +); +const t = i18n.t; +const i18nMixin = (i18n.mixin = { + beforeCreate () { + const unwatch = i18n.i18n.watchLocale(() => { + this.$forceUpdate(); + }); + this.$once('hook:beforeDestroy', function () { + unwatch(); + }); + }, + methods: { + $$t (key, values) { + return t(key, values) + } + } +}); +const setLocale$1 = i18n.setLocale; +const getLocale$1 = i18n.getLocale; + +function initAppLocale (Vue, appVm, locale) { + const state = Vue.observable({ + locale: locale || i18n.getLocale() + }); + const localeWatchers = []; + appVm.$watchLocale = fn => { + localeWatchers.push(fn); + }; + Object.defineProperty(appVm, '$locale', { + get () { + return state.locale + }, + set (v) { + state.locale = v; + localeWatchers.forEach(watch => watch(v)); + } + }); +} + +function isEnableLocale () { + return typeof __uniConfig !== 'undefined' && __uniConfig.locales && !!Object.keys(__uniConfig.locales).length +} + +// export function initI18n() { +// const localeKeys = Object.keys(__uniConfig.locales || {}) +// if (localeKeys.length) { +// localeKeys.forEach((locale) => +// i18n.add(locale, __uniConfig.locales[locale]) +// ) +// } +// } + +class EventChannel { + constructor (id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach(name => { + this.on(name, events[name]); + }); + } + } + + emit (eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args) + } + fns.forEach(opt => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter(opt => opt.type !== 'once'); + } + + on (eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + + once (eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + + off (eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } else { + delete this.listener[eventName]; + } + } + + _clearCache (eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName].concat(cacheArgs.shift())); + } + } + } + + _addListener (eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type + }); + } +} + +const eventChannels = {}; + +const eventChannelStack = []; + +function getEventChannel (id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel + } + return eventChannelStack.shift() +} + +const hooks = [ + 'onShow', + 'onHide', + 'onError', + 'onPageNotFound', + 'onThemeChange', + 'onUnhandledRejection' +]; + +function initEventChannel () { + Vue.prototype.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__ + }; + const callHook = Vue.prototype.__call_hook; + Vue.prototype.__call_hook = function (hook, args) { + if (hook === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + return callHook.call(this, hook, args) + }; +} + +function initScopedSlotsParams () { + const center = {}; + const parents = {}; + + Vue.prototype.$hasScopedSlotsParams = function (vueId) { + const has = center[vueId]; + if (!has) { + parents[vueId] = this; + this.$on('hook:destroyed', () => { + delete parents[vueId]; + }); + } + return has + }; + + Vue.prototype.$getScopedSlotsParams = function (vueId, name, key) { + const data = center[vueId]; + if (data) { + const object = data[name] || {}; + return key ? object[key] : object + } else { + parents[vueId] = this; + this.$on('hook:destroyed', () => { + delete parents[vueId]; + }); + } + }; + + Vue.prototype.$setScopedSlotsParams = function (name, value) { + const vueIds = this.$options.propsData.vueId; + if (vueIds) { + const vueId = vueIds.split(',')[0]; + const object = center[vueId] = center[vueId] || {}; + object[name] = value; + if (parents[vueId]) { + parents[vueId].$forceUpdate(); + } + } + }; + + Vue.mixin({ + destroyed () { + const propsData = this.$options.propsData; + const vueId = propsData && propsData.vueId; + if (vueId) { + delete center[vueId]; + delete parents[vueId]; + } + } + }); +} + +function parseBaseApp (vm, { + mocks, + initRefs +}) { + initEventChannel(); + { + initScopedSlotsParams(); + } + if (vm.$options.store) { + Vue.prototype.$store = vm.$options.store; + } + uniIdMixin(Vue); + + Vue.prototype.mpHost = "mp-xhs"; + + Vue.mixin({ + beforeCreate () { + if (!this.$options.mpType) { + return + } + + this.mpType = this.$options.mpType; + + this.$mp = { + data: {}, + [this.mpType]: this.$options.mpInstance + }; + + this.$scope = this.$options.mpInstance; + + delete this.$options.mpType; + delete this.$options.mpInstance; + if (this.mpType === 'page' && typeof getApp === 'function') { // hack vue-i18n + const app = getApp(); + if (app.$vm && app.$vm.$i18n) { + this._i18n = app.$vm.$i18n; + } + } + if (this.mpType !== 'app') { + initRefs(this); + initMocks(this, mocks); + } + } + }); + + const appOptions = { + onLaunch (args) { + if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前 + return + } + + this.$vm = vm; + + this.$vm.$mp = { + app: this + }; + + this.$vm.$scope = this; + // vm 上也挂载 globalData + this.$vm.globalData = this.globalData; + + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted', args); + + this.$vm.__call_hook('onLaunch', args); + } + }; + + // 兼容旧版本 globalData + appOptions.globalData = vm.$options.globalData || {}; + // 将 methods 中的方法挂在 getApp() 中 + const methods = vm.$options.methods; + if (methods) { + Object.keys(methods).forEach(name => { + appOptions[name] = methods[name]; + }); + } + + initAppLocale(Vue, vm, xhs.getSystemInfoSync().language || 'zh-Hans'); + + initHooks(appOptions, hooks); + + return appOptions +} + +const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']; + +function findVmByVueId (vm, vuePid) { + const $children = vm.$children; + // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) + for (let i = $children.length - 1; i >= 0; i--) { + const childVm = $children[i]; + if (childVm.$scope._$vueId === vuePid) { + return childVm + } + } + // 反向递归查找 + let parentVm; + for (let i = $children.length - 1; i >= 0; i--) { + parentVm = findVmByVueId($children[i], vuePid); + if (parentVm) { + return parentVm + } + } +} + +function initBehavior (options) { + return Behavior(options) +} + +function isPage () { + return !!this.route +} + +function initRelation (detail) { + this.triggerEvent('__l', detail); +} + +function selectAllComponents (mpInstance, selector, $refs) { + const components = mpInstance.selectAllComponents(selector); + components.forEach(component => { + const ref = component.dataset.ref; + $refs[ref] = component.$vm || component; + }); +} + +function initRefs (vm) { + const mpInstance = vm.$scope; + Object.defineProperty(vm, '$refs', { + get () { + const $refs = {}; + selectAllComponents(mpInstance, '.vue-ref', $refs); + // TODO 暂不考虑 for 中的 scoped + const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for'); + forComponents.forEach(component => { + const ref = component.dataset.ref; + if (!$refs[ref]) { + $refs[ref] = []; + } + $refs[ref].push(component.$vm || component); + }); + return $refs + } + }); +} + +function handleLink (event) { + const { + vuePid, + vueOptions + } = event.detail || event.value; // detail 是微信,value 是百度(dipatch) + + let parentVm; + + if (vuePid) { + parentVm = findVmByVueId(this.$vm, vuePid); + } + + if (!parentVm) { + parentVm = this.$vm; + } + + vueOptions.parent = parentVm; +} + +function parseApp (vm) { + return parseBaseApp(vm, { + mocks, + initRefs + }) +} + +function parseApp$1 (vm) { + return parseApp(vm) +} + +function createApp (vm) { + App(parseApp$1(vm)); + return vm +} + +const encodeReserveRE = /[!'()*]/g; +const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16); +const commaRE = /%2C/g; + +// fixed encodeURIComponent which is more conformant to RFC3986: +// - escapes [!'()*] +// - preserve commas +const encode = str => encodeURIComponent(str) + .replace(encodeReserveRE, encodeReserveReplacer) + .replace(commaRE, ','); + +function stringifyQuery (obj, encodeStr = encode) { + const res = obj ? Object.keys(obj).map(key => { + const val = obj[key]; + + if (val === undefined) { + return '' + } + + if (val === null) { + return encodeStr(key) + } + + if (Array.isArray(val)) { + const result = []; + val.forEach(val2 => { + if (val2 === undefined) { + return + } + if (val2 === null) { + result.push(encodeStr(key)); + } else { + result.push(encodeStr(key) + '=' + encodeStr(val2)); + } + }); + return result.join('&') + } + + return encodeStr(key) + '=' + encodeStr(val) + }).filter(x => x.length > 0).join('&') : null; + return res ? `?${res}` : '' +} + +const isComponent2 = xhs.canIUse('component2'); + +function initSpecialMethods (mpInstance) { + if (!mpInstance.$vm) { + return + } + let path = mpInstance.is || mpInstance.route; + if (!path) { + return + } + if (path.indexOf('/') === 0) { + path = path.substr(1); + } + const specialMethods = xhs.specialMethods && xhs.specialMethods[path]; + if (specialMethods) { + specialMethods.forEach(method => { + if (isFn(mpInstance.$vm[method])) { + mpInstance[method] = function (event) { + if (hasOwn(event, 'markerId')) { + event.detail = typeof event.detail === 'object' ? event.detail : {}; + event.detail.markerId = event.markerId; + } + // TODO normalizeEvent + mpInstance.$vm[method](event); + }; + } + }); + } +} + +const handleWrap = function (mp, destory) { + const vueId = mp.props.vueId; + const list = mp.props['data-event-list'].split(','); + list.forEach(eventName => { + const key = `${eventName}${vueId}`; + if (destory) { + delete this[key]; + } else { + // TODO remove handleRef + this[key] = function () { + mp.props[eventName].apply(this, arguments); + }; + } + }); +}; + +const hooks$1 = [ + 'onShow', + 'onHide', + 'onUnload' +]; + +hooks$1.push(...PAGE_EVENT_HOOKS); + +function parsePage (vuePageOptions) { + const [VueComponent, vueOptions] = initVueComponent(Vue, vuePageOptions); + + const pageOptions = { + mixins: initBehaviors(vueOptions, initBehavior), + data: initData(vueOptions, Vue.prototype), + onLoad (query) { + const properties = this.props; + + const options = { + mpType: 'page', + mpInstance: this, + propsData: properties + }; + + // 初始化 vue 实例 + this.$vm = new VueComponent(options); + + initSpecialMethods(this); + + // 触发首次 setData + this.$vm.$mount(); + + const copyQuery = Object.assign({}, query); + delete copyQuery.__id__; + + this.$page = { + fullPath: '/' + this.route + stringifyQuery(copyQuery) + }; + + this.options = query; + this.$vm.$mp.query = query; // 兼容 mpvue + this.$vm.__call_hook('onLoad', query); + }, + onReady () { + // initChildVues(this) + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); + this.$vm.__call_hook('onReady'); + }, + onUnload () { + this.$vm.__call_hook('onUnload'); + this.$vm.$destroy(); + }, + // __r: handleRef, + __e: handleEvent, + __l: handleLink, + __w: handleWrap, + triggerEvent: function noop () {} + }; + + initHooks(pageOptions, hooks$1, vuePageOptions); + + if (Array.isArray(vueOptions.wxsCallMethods)) { + vueOptions.wxsCallMethods.forEach(callMethod => { + pageOptions[callMethod] = function (args) { + return this.$vm[callMethod](args) + }; + }); + } + + return pageOptions +} + +function createPage (vuePageOptions) { + { + return Page(parsePage(vuePageOptions)) + } +} + +function parseBaseComponent (vueComponentOptions, { + isPage, + initRelation +} = {}) { + const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions); + + const options = { + multipleSlots: true, + addGlobalClass: true, + ...(vueOptions.options || {}) + }; + + const componentOptions = { + options, + data: initData(vueOptions, Vue.prototype), + behaviors: initBehaviors(vueOptions, initBehavior), + properties: initProperties(vueOptions.props, false, vueOptions.__file), + lifetimes: { + attached () { + const properties = this.properties; + + const options = { + mpType: isPage.call(this) ? 'page' : 'component', + mpInstance: this, + propsData: properties + }; + + initVueIds(properties.vueId, this); + + // 处理父子关系 + initRelation.call(this, { + vuePid: this._$vuePid, + vueOptions: options + }); + + // 初始化 vue 实例 + this.$vm = new VueComponent(options); + + // 处理$slots,$scopedSlots(暂不支持动态变化$slots) + initSlots(this.$vm, properties.vueSlots); + + // 触发首次 setData + this.$vm.$mount(); + }, + ready () { + // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发 + // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800 + if (this.$vm) { + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); + this.$vm.__call_hook('onReady'); + } + }, + detached () { + this.$vm && this.$vm.$destroy(); + } + }, + pageLifetimes: { + show (args) { + this.$vm && this.$vm.__call_hook('onPageShow', args); + }, + hide () { + this.$vm && this.$vm.__call_hook('onPageHide'); + }, + resize (size) { + this.$vm && this.$vm.__call_hook('onPageResize', size); + } + }, + methods: { + __l: handleLink, + __e: handleEvent + } + }; + // externalClasses + if (vueOptions.externalClasses) { + componentOptions.externalClasses = vueOptions.externalClasses; + } + + if (Array.isArray(vueOptions.wxsCallMethods)) { + vueOptions.wxsCallMethods.forEach(callMethod => { + componentOptions.methods[callMethod] = function (args) { + return this.$vm[callMethod](args) + }; + }); + } + + if (isPage) { + return componentOptions + } + return [componentOptions, VueComponent] +} + +function parseComponent (vueComponentOptions) { + return parseBaseComponent(vueComponentOptions, { + isPage, + initRelation + }) +} + +/** + * 用于延迟调用 setData + * 在 setData 真实调用的时机需执行 fixSetDataEnd + * @param {*} mpInstance + */ +function fixSetDataStart (mpInstance) { + const setData = mpInstance.setData; + const setDataArgs = []; + mpInstance.setData = function () { + setDataArgs.push(arguments); + }; + mpInstance.__fixInitData = function () { + this.setData = setData; + const fn = () => { + setDataArgs.forEach(args => { + setData.apply(this, args); + }); + }; + if (setDataArgs.length) { + if (this.groupSetData) { + this.groupSetData(fn); + } else { + fn(); + } + } + }; +} +/** + * 恢复真实的 setData 方法 + * @param {*} mpInstance + */ +function fixSetDataEnd (mpInstance) { + if (mpInstance.__fixInitData) { + mpInstance.__fixInitData(); + delete mpInstance.__fixInitData; + } +} + +// import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-parser' + +function parseComponent$1 (vueComponentOptions) { + const componentOptions = parseComponent(vueComponentOptions); + const oldAttached = componentOptions.lifetimes.attached; + componentOptions.lifetimes.attached = function attached () { + // 暂不区分版本 + if (isPage.call(this)) { + fixSetDataStart(this); + setTimeout(() => { + fixSetDataEnd(this); + }, 0); + } + oldAttached.call(this); + }; + return componentOptions +} + +function createComponent (vueOptions) { + { + return Component(parseComponent$1(vueOptions)) + } +} + +function createSubpackageApp (vm) { + const appOptions = parseApp$1(vm); + const app = getApp({ + allowDefault: true + }); + vm.$scope = app; + const globalData = app.globalData; + if (globalData) { + Object.keys(appOptions.globalData).forEach(name => { + if (!hasOwn(globalData, name)) { + globalData[name] = appOptions.globalData[name]; + } + }); + } + Object.keys(appOptions).forEach(name => { + if (!hasOwn(app, name)) { + app[name] = appOptions[name]; + } + }); + if (isFn(appOptions.onShow) && xhs.onAppShow) { + xhs.onAppShow((...args) => { + vm.__call_hook('onShow', args); + }); + } + if (isFn(appOptions.onHide) && xhs.onAppHide) { + xhs.onAppHide((...args) => { + vm.__call_hook('onHide', args); + }); + } + if (isFn(appOptions.onLaunch)) { + const args = xhs.getLaunchOptionsSync && xhs.getLaunchOptionsSync(); + vm.__call_hook('onLaunch', args); + } + return vm +} + +function createPlugin (vm) { + const appOptions = parseApp$1(vm); + if (isFn(appOptions.onShow) && xhs.onAppShow) { + xhs.onAppShow((...args) => { + vm.__call_hook('onShow', args); + }); + } + if (isFn(appOptions.onHide) && xhs.onAppHide) { + xhs.onAppHide((...args) => { + vm.__call_hook('onHide', args); + }); + } + if (isFn(appOptions.onLaunch)) { + const args = xhs.getLaunchOptionsSync && xhs.getLaunchOptionsSync(); + vm.__call_hook('onLaunch', args); + } + return vm +} + +todos.forEach(todoApi => { + protocols[todoApi] = false; +}); + +canIUses.forEach(canIUseApi => { + const apiName = protocols[canIUseApi] && protocols[canIUseApi].name ? protocols[canIUseApi].name + : canIUseApi; + if (!xhs.canIUse(apiName)) { + protocols[canIUseApi] = false; + } +}); + +let uni = {}; + +if (typeof Proxy !== 'undefined' && "mp-xhs" !== 'app-plus') { + uni = new Proxy({}, { + get (target, name) { + if (hasOwn(target, name)) { + return target[name] + } + if (baseApi[name]) { + return baseApi[name] + } + if (api[name]) { + return promisify(name, api[name]) + } + { + if (extraApi[name]) { + return promisify(name, extraApi[name]) + } + if (todoApis[name]) { + return promisify(name, todoApis[name]) + } + } + if (eventApi[name]) { + return eventApi[name] + } + if (!hasOwn(xhs, name) && !hasOwn(protocols, name)) { + return + } + return promisify(name, wrapper(name, xhs[name])) + }, + set (target, name, value) { + target[name] = value; + return true + } + }); +} else { + Object.keys(baseApi).forEach(name => { + uni[name] = baseApi[name]; + }); + + { + Object.keys(todoApis).forEach(name => { + uni[name] = promisify(name, todoApis[name]); + }); + Object.keys(extraApi).forEach(name => { + uni[name] = promisify(name, todoApis[name]); + }); + } + + Object.keys(eventApi).forEach(name => { + uni[name] = eventApi[name]; + }); + + Object.keys(api).forEach(name => { + uni[name] = promisify(name, api[name]); + }); + + Object.keys(xhs).forEach(name => { + if (hasOwn(xhs, name) || hasOwn(protocols, name)) { + uni[name] = promisify(name, wrapper(name, xhs[name])); + } + }); +} + +xhs.createApp = createApp; +xhs.createPage = createPage; +xhs.createComponent = createComponent; +xhs.createSubpackageApp = createSubpackageApp; +xhs.createPlugin = createPlugin; + +var uni$1 = uni; + +export default uni$1; +export { createApp, createComponent, createPage, createPlugin, createSubpackageApp }; diff --git a/packages/uni-mp-xhs/lib/uni.compiler.js b/packages/uni-mp-xhs/lib/uni.compiler.js new file mode 100644 index 0000000000000000000000000000000000000000..f08559e4c02ab41c76419c45c7444b727d1e1080 --- /dev/null +++ b/packages/uni-mp-xhs/lib/uni.compiler.js @@ -0,0 +1,4 @@ +const compiler = require('@dcloudio/uni-mp-weixin/lib/uni.compiler.js') +module.exports = Object.assign({}, compiler, { + directive: 'xhs:' +}) diff --git a/packages/uni-mp-xhs/lib/uni.config.js b/packages/uni-mp-xhs/lib/uni.config.js new file mode 100644 index 0000000000000000000000000000000000000000..eb32fcadfa4521fefd915e2c02d0c7f7cf735411 --- /dev/null +++ b/packages/uni-mp-xhs/lib/uni.config.js @@ -0,0 +1,24 @@ +module.exports = { + options: { + cssVars: { + '--status-bar-height': '25px', + '--window-top': '0px', + '--window-bottom': '0px', + '--window-left': '0px', + '--window-right': '0px' + }, + extnames: { + style: '.css', + template: '.xhsml' + }, + project: 'project.config.json', + subPackages: true + }, + copyWebpackOptions (platformOptions, vueOptions) { + const copyOptions = ['xhscomponents'] + global.uniModules.forEach(module => { + copyOptions.push('uni_modules/' + module + '/xhscomponents') + }) + return copyOptions + } +} diff --git a/packages/uni-mp-xhs/package.json b/packages/uni-mp-xhs/package.json new file mode 100644 index 0000000000000000000000000000000000000000..65346eac3dc0776b21111bc005b9dc288e6e0779 --- /dev/null +++ b/packages/uni-mp-xhs/package.json @@ -0,0 +1,21 @@ +{ + "name": "@dcloudio/uni-mp-xhs", + "version": "2.0.0-32920211029001", + "description": "uni-app mp-xhs", + "main": "dist/index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/dcloudio/uni-app.git", + "directory": "packages/uni-mp-xhs" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "txu", + "license": "Apache-2.0", + "uni-app": { + "name": "mp-xhs", + "title": "小红书小程序" + }, + "gitHead": "9e2d0f8e244724fcd64880316c57d837d1778cf8" +} diff --git a/packages/uni-quickapp-native/dist/vue.dev.js b/packages/uni-quickapp-native/dist/vue.dev.js index 47682f48dee29ff0045a5f762e8e2f73b121b2e1..c7a8bd36a09fe9bc98674d603b7a150635cb572f 100644 --- a/packages/uni-quickapp-native/dist/vue.dev.js +++ b/packages/uni-quickapp-native/dist/vue.dev.js @@ -1,4 +1,4 @@ var dsl=function(){"use strict";const e={initApp:"quickapp.app.initApp",initPage:"quickapp.page.initPage",destroyPage:"quickapp.page.destroyPage",fireEvent:"quickapp.page.fireEvent",onShow:"quickapp.page.onShow",onHide:"quickapp.page.onHide",onBackPress:"quickapp.page.onBackPress",onMenuPress:"quickapp.page.onMenuPress",onOrientationChange:"quickapp.page.onOrientationChange",onConfigurationChanged:"quickapp.page.onConfigurationChanged",onRefresh:"quickapp.page.onRefresh",callbackDone:"quickapp.page.callbackDone"},t=/^@(app)-application\//,n=/^@(app)-component\//,r=/^@(app)-module\//;function o(e){return e.replace(t,"").replace(n,"").replace(r,"")}var i="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var a,s,c=(function(e){e.exports=function(e,t,n){var r=Object.freeze({});function o(e){return null==e}function a(e){return null!=e}function s(e){return!0===e}function c(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function u(e){return null!==e&&"object"==typeof e}var l=Object.prototype.toString;function p(e){return l.call(e).slice(8,-1)}function f(e){return"[object Object]"===l.call(e)}function d(e){return"[object RegExp]"===l.call(e)}function v(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function h(e){return a(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function m(e){return null==e?"":Array.isArray(e)||f(e)&&e.toString===l?JSON.stringify(e,null,2):String(e)}function y(e){var t=parseFloat(e);return isNaN(t)?e:t}function g(e,t){for(var n=Object.create(null),r=e.split(","),o=0;o-1)return e.splice(n,1)}}var w=Object.prototype.hasOwnProperty;function A(e,t){return w.call(e,t)}function k(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var x=/-(\w)/g,O=k(function(e){return e.replace(x,function(e,t){return t?t.toUpperCase():""})}),C=k(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),S=/\B([A-Z])/g,j=k(function(e){return e.replace(S,"-$1").toLowerCase()});var E=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function I(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function P(e,t){for(var n in t)e[n]=t[n];return e}function M(e,t,n){}var T=function(e,t,n){return!1},F=function(e){return e};function D(e,t){if(e===t)return!0;var n=u(e),r=u(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var o=Array.isArray(e),i=Array.isArray(t);if(o&&i)return e.length===t.length&&e.every(function(e,n){return D(e,t[n])});if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(o||i)return!1;var a=Object.keys(e),s=Object.keys(t);return a.length===s.length&&a.every(function(n){return D(e[n],t[n])})}catch(e){return!1}}function N(e,t){for(var n=0;n0,te=X&&X.indexOf("edge/")>0,ne=(X&&X.indexOf("android"),X&&/iphone|ipad|ipod|ios/.test(X)||"ios"===G),re=(X&&/chrome\/\d+/.test(X),X&&/phantomjs/.test(X),X&&X.match(/firefox\/(\d+)/),{}.watch);if(Q)try{var oe={};Object.defineProperty(oe,"passive",{get:function(){}}),window.addEventListener("test-passive",null,oe)}catch(e){}var ie=function(){return void 0===W&&(W=!Q&&!Y&&void 0!==i&&(i.process&&"server"===i.process.env.VUE_ENV)),W},ae=Q&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function se(e){return"function"==typeof e&&/native code/.test(e.toString())}var ce,ue="undefined"!=typeof Symbol&&se(Symbol)&&"undefined"!=typeof Reflect&&se(Reflect.ownKeys);ce="undefined"!=typeof Set&&se(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var le=M,pe=M,fe=M,de=M,ve="undefined"!=typeof console,he=/(?:^|[-_])(\w)/g;le=function(e,t){var n=t?fe(t):"";B.warnHandler?B.warnHandler.call(null,e,t,n):ve&&!B.silent&&console.error("[Vue warn]: "+e+n)},pe=function(e,t){ve&&!B.silent&&console.warn("[Vue tip]: "+e+(t?fe(t):""))},de=function(e,t){if(e.$root===e)return"";var n="function"==typeof e&&null!=e.cid?e.options:e._isVue?e.$options||e.constructor.options:e,r=n.name||n._componentTag,o=n.__file;if(!r&&o){var i=o.match(/([^/\\]+)\.vue$/);r=i&&i[1]}return(r?"<"+r.replace(he,function(e){return e.toUpperCase()}).replace(/[-_]/g,"")+">":"")+(o&&!1!==t?" at "+o:"")};fe=function(e){if(e._isVue&&e.$parent){for(var t=[],n=0;e;){if(t.length>0){var r=t[t.length-1];if(r.constructor===e.constructor){n++,e=e.$parent;continue}n>0&&(t[t.length-1]=[r,n],n=0)}t.push(e),e=e.$parent}return"\n\nfound in\n\n"+t.map(function(e,t){return""+(0===t?"---\x3e ":function(e,t){for(var n="";t;)t%2==1&&(n+=e),t>1&&(e+=e),t>>=1;return n}(" ",5+2*t))+(Array.isArray(e)?de(e[0])+"... ("+e[1]+" recursive calls)":de(e))}).join("\n")}return"\n\n(found in "+de(e)+")"};var me=0,ye=function(){"undefined"!=typeof SharedObject?this.id=SharedObject.uid++:this.id=me++,this.subs=[]};function ge(e){ye.SharedObject.targetStack.push(e),ye.SharedObject.target=e}function _e(){ye.SharedObject.targetStack.pop(),ye.SharedObject.target=ye.SharedObject.targetStack[ye.SharedObject.targetStack.length-1]}ye.prototype.addSub=function(e){this.subs.push(e)},ye.prototype.removeSub=function(e){$(this.subs,e)},ye.prototype.depend=function(){ye.SharedObject.target&&ye.SharedObject.target.addDep(this)},ye.prototype.notify=function(){var e=this.subs.slice();B.async||e.sort(function(e,t){return e.id-t.id});for(var t=0,n=e.length;t-1)if(i&&!A(o,"default"))a=!1;else if(""===a||a===j(e)){var c=Ye(String,o.type);(c<0||s0&&(Pt((u=e(u,(n||"")+"_"+i))[0])&&Pt(p)&&(r[l]=Ae(p.text+u[0].text),u.shift()),r.push.apply(r,u)):c(u)?Pt(p)?r[l]=Ae(p.text+u):""!==u&&r.push(Ae(u)):Pt(u)&&Pt(p)?r[l]=Ae(p.text+u.text):(s(t._isVList)&&a(u.tag)&&o(u.key)&&a(n)&&(u.key="__vlist"+n+"_"+i+"__"),r.push(u)));return r}(e):void 0}function Pt(e){return a(e)&&a(e.text)&&!1===e.isComment}function Mt(e,t){if(e){for(var n=Object.create(null),r=ue?Reflect.ownKeys(e):Object.keys(e),o=0;o0,a=e?!!e.$stable:!i,s=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(a&&n&&n!==r&&s===n.$key&&!i&&!n.$hasNormal)return n;for(var c in o={},e)e[c]&&"$"!==c[0]&&(o[c]=Nt(t,c,e[c]))}else o={};for(var u in t)u in o||(o[u]=Lt(t,u));return e&&Object.isExtensible(e)&&(e._normalized=o),z(o,"$stable",a),z(o,"$key",s),z(o,"$hasNormal",i),o}function Nt(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return(e=e&&"object"==typeof e&&!Array.isArray(e)?[e]:It(e))&&(0===e.length||1===e.length&&e[0].isComment)?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function Lt(e,t){return function(){return e[t]}}function qt(e,t){var n,r,o,i,s;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),r=0,o=e.length;r.",e),l=new be(B.parsePlatformTagName(t),n,r,void 0,void 0,e)):l=n&&n.pre||!a(f=Ue(e.$options,"components",t))?new be(t,n,r,void 0,void 0,e):an(f,n,e,r,t)}else l=an(t,n,e,r);return Array.isArray(l)?l:a(l)?(a(p)&&function e(t,n,r){t.ns=n;"foreignObject"===t.tag&&(n=void 0,r=!0);if(a(t.children))for(var i=0,c=t.children.length;it.createEvent("Event").timeStamp&&(In=function(){return Pn.now()})}function Mn(){var e,t;for(In(),jn=!0,kn.sort(function(e,t){return e.id-t.id}),En=0;EnAn)){le("You may have an infinite update loop "+(e.user?'in watcher with expression "'+e.expression+'"':"in a component render function."),e.vm);break}var n=xn.slice(),r=kn.slice();En=kn.length=xn.length=0,On={},Cn={},Sn=jn=!1,function(e){for(var t=0;tEn&&kn[n].id>e.id;)n--;kn.splice(n+1,0,e)}else kn.push(e);if(!Sn){if(Sn=!0,!B.async)return void Mn();ft(Mn)}}}(this)},Fn.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||u(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Ze(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},Fn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},Fn.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},Fn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||$(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var Dn={enumerable:!0,configurable:!0,get:M,set:M};function Nn(e,t,n){Dn.get=function(){return this[t][n]},Dn.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Dn)}function Ln(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},o=e.$options._propKeys=[],i=!e.$parent;i||je(!1);var a=function(a){o.push(a);var s=ze(a,t,n,e),c=j(a);(b(c)||B.isReservedAttr(c))&&le('"'+c+'" is a reserved attribute and cannot be used as component prop.',e),Pe(r,a,s,function(){i||_n||le("Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: \""+a+'"',e)}),a in e||Nn(e,"_props",a)};for(var s in t)a(s);je(!0)}(e,t.props),t.methods&&function(e,t){var n=e.$options.props;for(var r in t)"function"!=typeof t[r]&&le('Method "'+r+'" has type "'+typeof t[r]+'" in the component definition. Did you reference the function correctly?',e),n&&A(n,r)&&le('Method "'+r+'" has already been defined as a prop.',e),r in e&&U(r)&&le('Method "'+r+'" conflicts with an existing Vue instance method. Avoid defining component methods that start with _ or $.'),e[r]="function"!=typeof t[r]?M:E(t[r],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;f(t=e._data="function"==typeof t?function(e,t){ge();try{return e.call(t,t)}catch(e){return Ze(e,t,"data()"),{}}finally{_e()}}(t,e):t||{})||(t={},le("data functions should return an object:\nhttps://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function",e));var n=Object.keys(t),r=e.$options.props,o=e.$options.methods,i=n.length;for(;i--;){var a=n[i];o&&A(o,a)&&le('Method "'+a+'" has already been defined as a data property.',e),r&&A(r,a)?le('The data property "'+a+'" is already declared as a prop. Use prop default value instead.',e):U(a)||Nn(e,"_data",a)}Ie(t,!0)}(e):Ie(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=ie();for(var o in t){var i=t[o],a="function"==typeof i?i:i.get;null==a&&le('Getter is missing for computed property "'+o+'".',e),r||(n[o]=new Fn(e,a||M,M,qn)),o in e?o in e.$data?le('The computed property "'+o+'" is already defined in data.',e):e.$options.props&&o in e.$options.props&&le('The computed property "'+o+'" is already defined as a prop.',e):Rn(e,o,i)}}(e,t.computed),t.watch&&t.watch!==re&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var o=0;o-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!d(e)&&e.test(t)}function Yn(e,t){var n=e.cache,r=e.keys,o=e._vnode;for(var i in n){var a=n[i];if(a){var s=Kn(a.componentOptions);s&&!t(s)&&Gn(n,i,r,o)}}}function Gn(e,t,n,r){var o=e[t];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),e[t]=null,$(n,t)}!function(e){e.prototype._init=function(e){var t,n,o=this;o._uid=Un++,B.performance&&bt&&(t="vue-perf-start:"+o._uid,n="vue-perf-end:"+o._uid,bt(t)),o._isVue=!0,e&&e._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(o,e):o.$options=He(zn(o.constructor),e||{},o),ot(o),o._self=o,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(o),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&yn(e,t)}(o),function(e){e._vnode=null,e._staticTrees=null;var t=e.$options,n=e.$vnode=t._parentVnode,o=n&&n.context;e.$slots=Tt(t._renderChildren,o),e.$scopedSlots=r,e._c=function(t,n,r,o){return ln(e,t,n,r,o,!1)},e.$createElement=function(t,n,r,o){return ln(e,t,n,r,o,!0)};var i=n&&n.data;Pe(e,"$attrs",i&&i.attrs||r,function(){!_n&&le("$attrs is readonly.",e)},!0),Pe(e,"$listeners",t._parentListeners||r,function(){!_n&&le("$listeners is readonly.",e)},!0)}(o),wn(o,"beforeCreate"),"mp-toutiao"!==o.mpHost&&function(e){var t=Mt(e.$options.inject,e);t&&(je(!1),Object.keys(t).forEach(function(n){Pe(e,n,t[n],function(){le('Avoid mutating an injected value directly since the changes will be overwritten whenever the provided component re-renders. injection being mutated: "'+n+'"',e)})}),je(!0))}(o),Ln(o),"mp-toutiao"!==o.mpHost&&function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(o),"mp-toutiao"!==o.mpHost&&wn(o,"created"),B.performance&&bt&&(o._name=de(o,!1),bt(n),$t("vue "+o._name+" init",t,n)),o.$options.el&&o.$mount(o.$options.el)}}(Jn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};t.set=function(){le("Avoid replacing instance root $data. Use nested data properties instead.",this)},n.set=function(){le("$props is readonly.",this)},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=Me,e.prototype.$delete=Te,e.prototype.$watch=function(e,t,n){if(f(t))return Hn(this,e,t,n);(n=n||{}).user=!0;var r=new Fn(this,e,t,n);if(n.immediate)try{t.call(this,r.value)}catch(e){Ze(e,this,'callback for immediate watcher "'+r.expression+'"')}return function(){r.teardown()}}}(Jn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var o=0,i=e.length;o1?I(r):r;for(var o=I(arguments,1),i='event handler for "'+e+'"',a=0,s=r.length;aparseInt(this.max)&&Gn(s,c[0],c,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return B},set:function(){le("Do not replace the Vue.config object, set individual fields instead.")}};Object.defineProperty(e,"config",t),e.util={warn:le,extend:P,mergeOptions:He,defineReactive:Pe},e.set=Me,e.delete=Te,e.nextTick=ft,e.observable=function(e){return Ie(e),e},e.options=Object.create(null),R.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,P(e.options.components,Zn),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=I(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=He(this.options,e),this}}(e),Wn(e),function(e){R.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&Ve(e),"component"===t&&f(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(Jn),Object.defineProperty(Jn.prototype,"$isServer",{get:ie}),Object.defineProperty(Jn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Jn,"FunctionalRenderContext",{value:en}),Jn.version="2.6.11";function er(e,t,r){n.setElementAttr(e,t,r)}var tr=Object.freeze({namespaceMap:{},createElement:function(e){var r=t.createElement(e);return n.bindElementMethods(r),r},createElementNS:function(e,n){return t.createElement(e+":"+n)},createTextNode:function(e){return t.createTextNode(e)},createComment:function(e){return t.createComment(e)},insertBefore:function(e,t,n){e.insertBefore(t,n)},removeChild:function(e,t){e.removeChild(t)},appendChild:function(e,t){e.appendChild(t)},parentNode:function(e){return e.parentNode},nextSibling:function(e){return e.nextSibling},tagName:function(e){return e.tagName},setTextContent:function(e,t){n.setElementAttr(e.parentNode,"value",t)},setAttribute:er}),nr={create:function(e,t){rr(t)},update:function(e,t){e.data.ref!==t.data.ref&&(rr(e,!0),rr(t))},destroy:function(e){rr(e,!0)}};function rr(e,t){var n=e.data.ref;if(a(n)){var r=e.context,o=e.componentInstance||e.elm,i=r.$refs;t?Array.isArray(i[n])?$(i[n],o):i[n]===o&&(i[n]=void 0):e.data.refInFor?Array.isArray(i[n])?i[n].indexOf(o)<0&&i[n].push(o):i[n]=[o]:i[n]=o}}g("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),g("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0);var or=g("text,number,password,search,email,tel,url"),ir=new be("",{},[]),ar=["create","activate","update","remove","destroy"];function sr(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&a(e.data)===a(t.data)&&function(e,t){if("input"!==e.tag)return!0;var n,r=a(n=e.data)&&a(n=n.attrs)&&n.type,o=a(n=t.data)&&a(n=n.attrs)&&n.type;return r===o||or(r)&&or(o)}(e,t)||s(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&o(t.asyncFactory.error))}function cr(e,t,n){var r,o,i={};for(r=t;r<=n;++r)a(o=e[r].key)&&(i[o]=r);return i}var ur={create:lr,update:lr,destroy:function(e){lr(e,ir)}};function lr(e,t){(e.data.directives||t.data.directives)&&function(e,t){var n,r,o,i=e===ir,a=t===ir,s=fr(e.data.directives,e.context),c=fr(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],o=c[n],r?(o.oldValue=r.value,o.oldArg=r.arg,vr(o,"update",t,e),o.def&&o.def.componentUpdated&&l.push(o)):(vr(o,"bind",t,e),o.def&&o.def.inserted&&u.push(o));if(u.length){var p=function(){for(var n=0;n1,j=t.context.$options.style||{},E=j[$],I=j["@TRANSITION"]&&j["@TRANSITION"][A]||{},T=function(e,t,n,r,o,i){var a={},s=t[n],c=t[r],u=t[o];if(s)for(var l in s)a[l]=e.style[l],null!=a[l]||u&&null!=u[l]||c&&null!=c[l]||le('transition property "'+l+'" is declared in enter starting class (.'+n+"), but not declared anywhere in enter ending class (."+r+"), enter active cass (."+o+") or the element's default styling. Note in Quickapp, CSS properties need explicit values to be transitionable.");if(u)for(var p in u)0!==p.indexOf("transition")&&(a[p]=u[p]);c&&P(a,c);return a}(n,j,$,w,A,t.context),F=Object.keys(T).length>0,D=n._enterCb=L(function(){D.cancelled?C&&C(n):O&&O(n),n._enterCb=null});if(setTimeout(function(){var e=n.parentNode,r=e&&e._pending&&e._pending[t.key];(r&&r.context===t.context&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),x&&x(n,D),F)?t.context.$requireQuickappModule("animation").transition(n.ref,{styles:T,duration:I.duration||0,delay:I.delay||0,timingFunction:I.timingFunction||"linear"},S?M:D):S||D()},16),k&&k(n),E)for(var N in E)n.setStyle(N,E[N]);F||S||D()}}}function qr(e,t){if(!o(e.data.domProps)||!o(t.data.domProps)){var n,r,i=t.elm,s=e.data.domProps||{},c=t.data.domProps||{};for(n in a(c.__ob__)&&(c=t.data.domProps=P({},c)),s)o(c[n])&&er(i,n,"");for(n in c){if(r=c[n],"value"===n)er(i,n,o(r)?"":String(r));else er(i,n,r)}}}var Rr=function(e){var t,n,r={},i=e.modules,u=e.nodeOps;for(t=0;t - did you register the component correctly? For recursive components, make sure to provide the "name" option.',e.context),e.elm=e.ns?u.createElementNS(e.ns,g):u.createElement(g,e),$(e),y(e,v,t),a(d)&&b(e,t),m(n,e.elm,o),d&&d.pre&&f--):s(e.isComment)?(e.elm=u.createComment(e.text),m(n,e.elm,o)):(e.elm=u.createTextNode(e.text),m(n,e.elm,o))}}function h(e,t){a(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,_(e)?(b(e,t),$(e)):(rr(e),t.push(e))}function m(e,t,n){a(e)&&(a(n)?u.parentNode(n)===e&&u.insertBefore(e,t,n):u.appendChild(e,t))}function y(e,t,n){if(Array.isArray(t)){O(t);for(var r=0;rd?w(e,o(n[y+1])?null:n[y+1].elm,n,f,y,r):f>y&&k(t,p,d)}(p,h,m,n,l):a(m)?(O(m),a(e.text)&&u.setTextContent(p,""),w(p,null,m,0,m.length-1,n)):a(h)?k(h,0,h.length-1):a(e.text)&&u.setTextContent(p,""):e.text!==t.text&&u.setTextContent(p,t.text),a(d)&&a(f=d.hook)&&a(f=f.postpatch)&&f(e,t)}}}function j(e,t,n){if(s(n)&&a(e.parent))e.parent.data.pendingInsert=t;else for(var r=0;r, or missing . Bailing hydration and performing full client-side render.")}c=e,e=new be(u.tagName(c).toLowerCase(),{},[],void 0,c)}var d=e.elm,h=u.parentNode(d);if(v(t,p,d._leaveCb?null:h,u.nextSibling(d)),a(t.parent))for(var m=t.parent,y=_(t);m;){for(var g=0;g1,d=e.context.$options.style||{},v=d[o],h=d[i]||d[a],m=d["@TRANSITION"]&&d["@TRANSITION"][a]||{},y=n._leaveCb=L(function(){n.parentNode&&n.parentNode._pending&&(n.parentNode._pending[e.key]=null),y.cancelled?l&&l(n):(t(),u&&u(n)),n._leaveCb=null});p?p(g):g();function g(){var t=e.context.$requireQuickappModule("animation");function r(){t.transition(n.ref,{styles:h,duration:m.duration||0,delay:m.delay||0,timingFunction:m.timingFunction||"linear"},f?M:y)}y.cancelled||(e.data.show||((n.parentNode._pending||(n.parentNode._pending={}))[e.key]=e),s&&s(n),v?t.transition(n.ref,{styles:v},r):r(),c&&c(n,y),h||f||y())}}}].concat(hr),LONG_LIST_THRESHOLD:10}),Vr={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?St(n,"postpatch",function(){Vr.componentUpdated(e,t,n)}):Br(e,t,n.context),e._vOptions=[].map.call(e.options,Ur)):("textarea"===n.tag||kr(e.attr.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||e.addEventListener("change",zr))},componentUpdated:function(e,t,n){if("select"===n.tag){Br(e,t,n.context);var r=e._vOptions,o=e._vOptions=[].map.call(e.options,Ur);if(o.some(function(e,t){return!D(e,r[t])}))(e.multiple?t.value.some(function(e){return Hr(e,o)}):t.value!==t.oldValue&&Hr(t.value,o))&&Jr(e,"change")}}};function Br(e,t,n){!function(e,t,n){var r,o,i=t.value,a=e.multiple;if(a&&!Array.isArray(i))return void le('