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

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

上级 d7dc1b03
module.exports = {
const config = {
ignore: [
"./packages",
],
......@@ -9,3 +9,9 @@ module.exports = {
],
plugins: [require('./lib/babel-plugin-uni-api/index.js')]
}
if (process.env.NODE_ENV === 'test') {
delete config.ignore
}
module.exports = config
module.exports = {
globals: {
__DEV__: true
},
coverageDirectory: 'coverage',
coverageReporters: ['html', 'lcov', 'text'],
collectCoverageFrom: ['packages/*/src/**/*.js'],
moduleFileExtensions: ['js', 'json'],
moduleNameMapper: {
'^@dcloudio/(.*?)$': '<rootDir>/packages/$1/src'
},
rootDir: __dirname,
testMatch: ['<rootDir>/packages/**/__tests__/**/*spec.(t|j)s']
}
......@@ -17,6 +17,7 @@
"build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js",
"build:runtime": "npm run lint && npm run build:mp-weixin && npm run build:mp-qq && npm run build:mp-alipay && npm run build:mp-baidu && npm run build:mp-toutiao && npm run build:app-plus",
"build:stat": "npm run lint && rollup -c build/rollup.config.stat.js",
"test:cli": "cross-env NODE_ENV=test jest",
"test:unit": "cross-env NODE_ENV=test UNI_PLATFORM=h5 mocha-webpack --require tests/unit/setup.js --webpack-config build/webpack.config.test.js tests/unit/**/*.spec.js",
"release": "npm run lint:cli && lerna publish --force-publish=*",
"release:alpha": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=alpha"
......@@ -49,6 +50,7 @@
"eslint-plugin-promise": "^4.0.0",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^4.7.1",
"jest": "^24.9.0",
"jsdom": "^13.0.0",
"jsdom-global": "^3.0.2",
"jsonfile": "^5.0.0",
......
......@@ -80,7 +80,6 @@ const PLATFORMS = {
vue: '@dcloudio/vue-cli-plugin-uni/packages/h5-vue',
compiler: false,
megalo: false,
filters: true,
subPackages: false,
cssVars: {
'--status-bar-height': '0px'
......@@ -114,7 +113,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: false,
cssVars: {
'--window-top': '0px',
......@@ -143,7 +142,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -170,7 +169,7 @@ const PLATFORMS = {
vue: mpvueRuntime,
compiler: mpvueCompiler,
megalo: false,
filters: true,
filterTag: 'wxs',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -207,7 +206,7 @@ const PLATFORMS = {
vue: megaloRuntime,
compiler: megaloCompiler,
megalo: 'swan',
filters: true,
filterTag: 'filter',
subPackages: true,
cssVars: {
'--status-bar-height': '25px',
......@@ -234,7 +233,7 @@ const PLATFORMS = {
vue: megaloRuntime,
compiler: megaloCompiler,
megalo: 'alipay',
filters: true,
filterTag: 'import-sjs',
subPackages: false,
cssVars: {
'--status-bar-height': '25px',
......@@ -440,9 +439,6 @@ module.exports = {
type: 'html',
context: nvuePreprocessContext
},
isSupportFilters () {
return platform.filters
},
isSupportSubPackages () {
return platform.subPackages
},
......@@ -464,6 +460,9 @@ module.exports = {
getPlatformProject () {
return platform.project
},
getPlatformFilterTag () {
return platform.filterTag
},
getPlatformVue () {
if (process.env.UNI_USING_COMPONENTS) {
return uniRuntime
......
......@@ -15,6 +15,17 @@ function assertCodegen (template, templateCode, renderCode = `with(this){}`, opt
}
describe('mp:compiler-extra', () => {
it('generate mp filter ', () => {
assertCodegen(
/* eslint-disable no-template-curly-in-string */
`<view @touchmove="a.touchmove">{{t.a}}{{t['a']}}{{t.a(b)}}{{t['a'](b)}}{{u.t.a(b)}}{{u.t.a}}</view>`,
`<view bindtouchmove="{{a.touchmove}}">{{t.a+t[\'a\']+t.a(b)+t[\'a\'](b)+$root.g0+u.t.a}}</view>`,
'with(this){var g0=u.t.a(b);$mp.data=Object.assign({},{$root:{g0:g0}})}', {
filterModules: ['t', 'a']
}
)
})
it('generate scopeId', () => {
assertCodegen(
'<view></view>',
......
const compiler = require('../lib')
const res = compiler.compile(
`
<view @touchmove="a.touchmove">{{t.a}}{{t['a']}}{{t.a(b)}}{{t['a'](b)}}{{u.t.a(b)}}{{u.t.a}}</view>
`, {
resourcePath: '/User/fxy/Documents/test.wxml',
mp: {
minified: true,
isTest: true,
platform: 'mp-weixin'
},
filterModules: ['t', 'a']
})
// ---BEGIN:JSON---{"n":"v"}---END:JSON---
console.log(res)
......@@ -40,6 +40,8 @@ module.exports = {
options.mp.globalUsingComponents = options.globalUsingComponents || Object.create(null)
options.mp.filterModules = options.filterModules || []
// (可用的原生微信小程序组件,global+scoped)
options.mp.wxComponents = options.wxComponents || Object.create(null)
......
......@@ -199,7 +199,22 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
}
valuePath.forEach(funcPath => {
if (funcPath.isIdentifier()) { // on:{click:handle}
if ( // wxs event
funcPath.isMemberExpression() &&
t.isIdentifier(funcPath.node.object) &&
state.options.filterModules.includes(funcPath.node.object.name)
) {
const {
getEventType,
formatEventType
} = state.options.platform
const wxsEventType = formatEventType(getEventType(type))
if (key.value) {
key.value = wxsEventType
} else {
key.name = wxsEventType
}
} else if (funcPath.isIdentifier()) { // on:{click:handle}
if (!isSpecialEvent) {
const arrayExpression = [t.stringLiteral(getMethodName(funcPath.node.name))]
if (!isCustom) { // native events
......
......@@ -17,6 +17,7 @@ const {
const {
hyphenate,
traverseFilter,
getComponentName
} = require('../../util')
......@@ -130,9 +131,19 @@ function checkUsingGlobalComponents (name, globalUsingComponents, state) {
module.exports = {
noScope: true,
MemberExpression (path) {
if ( // t.m(123)
t.isIdentifier(path.node.object) &&
this.options.filterModules.includes(path.node.object.name)
) {
path.skip()
}
},
CallExpression (path) {
const callee = path.node.callee
if (t.isIdentifier(callee)) {
if (traverseFilter(callee, this)) {
return path.skip()
} else if (t.isIdentifier(callee)) {
const methodName = callee.name
switch (methodName) {
case METHOD_CREATE_ELEMENT:
......@@ -174,6 +185,7 @@ module.exports = {
path.skip()
break
default:
// TODO 检测是否是 filterModules
if (!METHOD_BUILT_IN.includes(methodName)) {
if (
path.findParent(
......
......@@ -53,6 +53,34 @@ function traverseKey (ast, state) {
return forKey
}
function traverseFilter (ast, state) {
const filterModules = state.options.filterModules
if (!filterModules.length) {
return false
}
let isFilter = false
babelTraverse(ast, {
noScope: true,
Identifier (path) {
if (filterModules.includes(path.node.name)) {
const parentNode = path.parent
if ( // t.msg || t['msg']
t.isMemberExpression(parentNode) &&
parentNode.object === path.node &&
(
t.isIdentifier(parentNode.property) ||
t.isLiteral(parentNode.property)
)
) {
isFilter = true
path.stop()
}
}
}
})
return isFilter
}
function wrapper (code, reverse = false) {
return reverse ? `{{!(${code})}}` : `{{${code}}}`
}
......@@ -159,6 +187,7 @@ module.exports = {
}),
getForKey,
traverseKey,
traverseFilter,
getComponentName: cached((str) => {
if (str.indexOf('wx-') === 0) {
return str.replace('wx-', 'weixin-')
......
......@@ -142,6 +142,12 @@ module.exports = {
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-nvue-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
.end()
......
const path = require('path')
const loaderUtils = require('loader-utils')
const {
parse
} = require(require.resolve('@vue/component-compiler-utils', {
paths: [require.resolve('vue-loader')]
})) // 确保使用的与 vue-loader 一致
const {
getPlatformFilterTag
} = require('@dcloudio/uni-cli-shared/lib/platform')
const FILTER_TAG = getPlatformFilterTag()
module.exports = function(source) {
if (!FILTER_TAG) {
return source
}
const loaderContext = this
const {
sourceMap,
rootContext,
resourcePath
} = loaderContext
const options = loaderUtils.getOptions(loaderContext) || {}
const filename = path.basename(resourcePath)
const context = rootContext || process.cwd()
const sourceRoot = path.dirname(path.relative(context, resourcePath))
// 使用 @vue/component-compiler-utils 来处理,共用 cache
const descriptor = parse({
source,
compiler: options.compiler,
filename,
sourceRoot,
needMap: sourceMap
})
if (!descriptor.template) {
return source
}
const modules = new Set()
descriptor.customBlocks.filter(block => {
if (block.type === FILTER_TAG && block.attrs.module) {
modules.add(block.attrs.module)
}
})
if (modules.size) {
descriptor.template.attrs['filter-modules'] = [...modules]
}
// delete customBlocks
descriptor.customBlocks.length = 0
return source
}
const path = require('path')
const loaderUtils = require('loader-utils')
const {
removeExt,
getPlatformExts,
......@@ -31,10 +33,16 @@ module.exports = function (content) {
const realResourcePath = path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)
const resourcePath = normalizeNodeModules(removeExt(realResourcePath) + templateExt)
const wxComponents = getWXComponents(resourcePath.replace(path.extname(resourcePath), ''))
const params = loaderUtils.parseQuery(this.resourceQuery)
const filterModules = (params && params['filter-modules'] || '').split(',')
Object.assign(vueLoaderOptions.options.compilerOptions, {
mp: {
platform: process.env.UNI_PLATFORM
},
filterModules,
resourcePath,
emitFile: this.emitFile,
wxComponents,
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册