@mpxjs/webpack-plugin 2.8.22 → 2.8.23-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +14 -0
  3. package/lib/dependencies/AddEntryDependency.js +24 -0
  4. package/lib/dependencies/ResolveDependency.js +4 -0
  5. package/lib/index.js +35 -5
  6. package/lib/loader.js +40 -0
  7. package/lib/platform/template/wx/component-config/button.js +14 -2
  8. package/lib/platform/template/wx/component-config/image.js +4 -0
  9. package/lib/platform/template/wx/component-config/input.js +4 -0
  10. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  11. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  12. package/lib/platform/template/wx/component-config/switch.js +4 -0
  13. package/lib/platform/template/wx/component-config/text.js +4 -0
  14. package/lib/platform/template/wx/component-config/textarea.js +5 -0
  15. package/lib/platform/template/wx/component-config/view.js +4 -0
  16. package/lib/platform/template/wx/index.js +121 -1
  17. package/lib/resolve-loader.js +4 -1
  18. package/lib/runtime/components/tenon/getInnerListeners.js +314 -0
  19. package/lib/runtime/components/tenon/tenon-button.vue +305 -0
  20. package/lib/runtime/components/tenon/tenon-image.vue +61 -0
  21. package/lib/runtime/components/tenon/tenon-input.vue +104 -0
  22. package/lib/runtime/components/tenon/tenon-rich-text.vue +21 -0
  23. package/lib/runtime/components/tenon/tenon-scroll-view.vue +124 -0
  24. package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
  25. package/lib/runtime/components/tenon/tenon-text-area.vue +77 -0
  26. package/lib/runtime/components/tenon/tenon-text.vue +64 -0
  27. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  28. package/lib/runtime/optionProcessor.tenon.js +388 -0
  29. package/lib/style-compiler/index.js +1 -1
  30. package/lib/style-compiler/plugins/hm.js +20 -0
  31. package/lib/template-compiler/compiler.js +11 -2
  32. package/lib/tenon/index.js +104 -0
  33. package/lib/tenon/processJSON.js +356 -0
  34. package/lib/tenon/processScript.js +262 -0
  35. package/lib/tenon/processStyles.js +21 -0
  36. package/lib/tenon/processTemplate.js +133 -0
  37. package/lib/utils/get-relative-path.js +25 -0
  38. package/package.json +5 -2
@@ -0,0 +1,388 @@
1
+ // import { inBrowser } from '../utils/env'
2
+
3
+ import { hasOwn } from './utils'
4
+
5
+ export default function processOption (
6
+ option,
7
+ ctorType,
8
+ firstPage,
9
+ componentId,
10
+ pageConfig,
11
+ pagesMap,
12
+ componentsMap,
13
+ tabBarMap,
14
+ componentGenerics,
15
+ genericsInfo,
16
+ mixin,
17
+ Vue,
18
+ VueRouter,
19
+ i18n
20
+ ) {
21
+ if (ctorType === 'app') {
22
+ // 对于app中的组件需要全局注册
23
+ for (const componentName in componentsMap) {
24
+ if (hasOwn(componentsMap, componentName)) {
25
+ const component = componentsMap[componentName]
26
+ Vue.component(componentName, component)
27
+ }
28
+ }
29
+
30
+ // 注册v-ex-classes自定义指令处理externalClasses
31
+ // Vue.directive('ex-classes', (el, binding, vnode) => {
32
+ // const context = vnode.context
33
+ // if (context) {
34
+ // const externalClasses = context.$options.externalClasses || []
35
+ // const classList = el.classList
36
+ // binding.value.forEach((className) => {
37
+ // const actualExternalClassNames = context.$attrs[className]
38
+ // if (externalClasses.indexOf(className) !== -1 && actualExternalClassNames) {
39
+ // classList.remove(className)
40
+ // actualExternalClassNames.split(/\s+/).forEach((actualExternalClassName) => {
41
+ // if (actualExternalClassName) classList.add(actualExternalClassName)
42
+ // })
43
+ // }
44
+ // })
45
+ // }
46
+ // })
47
+ // Vue.directive('animation', (el, binding) => {
48
+ // const newActions = binding?.value?.actions
49
+ // if (el.actions === newActions) {
50
+ // Promise.resolve().then(() => {
51
+ // Object.assign(el.style, el.lastDynamicStyle)
52
+ // })
53
+ // return
54
+ // }
55
+ // el.actions = newActions
56
+ // if (typeof el.setAnimation === 'function') {
57
+ // el.removeEventListener('transitionend', el.setAnimation, false)
58
+ // el.setAnimation = undefined
59
+ // }
60
+ // el.dynamicStyleQueue = []
61
+ // el.lastDynamicStyle = undefined
62
+ // if (Array.isArray(newActions) && newActions.length) {
63
+ // newActions.forEach((item) => {
64
+ // const property = []
65
+ // const { animates, option } = item
66
+ // // 存储动画需要改变的样式属性
67
+ // const dynamicStyle = {
68
+ // transform: ''
69
+ // }
70
+ // animates.forEach((itemAnimation) => {
71
+ // switch (itemAnimation.type) {
72
+ // case 'style':
73
+ // const [key, value] = itemAnimation.args
74
+ // dynamicStyle[key] = value
75
+ // property.push(key)
76
+ // break
77
+ // default:
78
+ // dynamicStyle.transform += `${itemAnimation.type}(${itemAnimation.args}) `
79
+ // if (!property.includes('transform')) {
80
+ // property.push('transform')
81
+ // }
82
+ // }
83
+ // })
84
+ // Object.assign(dynamicStyle, {
85
+ // transition: `${parseInt(option.duration)}ms ${option.timingFunction} ${parseInt(option.delay)}ms`,
86
+ // transitionProperty: `${property}`,
87
+ // transformOrigin: option.transformOrigin
88
+ // })
89
+ // el.dynamicStyleQueue.push(dynamicStyle)
90
+ // })
91
+ // el.setAnimation = function () {
92
+ // if (!el.dynamicStyleQueue.length) {
93
+ // el.removeEventListener('transitionend', el.setAnimation, false)
94
+ // return
95
+ // }
96
+ // const dynamicStyle = el.dynamicStyleQueue.shift()
97
+ // Object.assign(el.style, dynamicStyle)
98
+ // el.lastDynamicStyle = dynamicStyle
99
+ // }
100
+ // // 首次动画属性设置
101
+ // setTimeout(el.setAnimation, 0)
102
+ // // 在transitionend事件内设置动画样式
103
+ // el.addEventListener('transitionend', el.setAnimation, false)
104
+ // }
105
+ // })
106
+
107
+ // const routes = []
108
+
109
+ // for (const pagePath in pagesMap) {
110
+ // if (pagesMap.hasOwnProperty(pagePath)) {
111
+ // const page = pagesMap[pagePath]
112
+ // routes.push({
113
+ // path: '/' + pagePath,
114
+ // component: page
115
+ // })
116
+ // }
117
+ // }
118
+
119
+ // if (routes.length) {
120
+ // if (firstPage) {
121
+ // routes.push({
122
+ // path: '/',
123
+ // redirect: '/' + firstPage
124
+ // })
125
+ // }
126
+ // global.__mpxRouter = option.router = new VueRouter({
127
+ // routes: routes
128
+ // })
129
+ // global.__mpxRouter.stack = []
130
+ // global.__mpxRouter.needCache = null
131
+ // global.__mpxRouter.needRemove = []
132
+ // // 处理reLaunch中传递的url并非首页时的replace逻辑
133
+ // global.__mpxRouter.beforeEach(function (to, from, next) {
134
+ // let action = global.__mpxRouter.__mpxAction
135
+ // const stack = global.__mpxRouter.stack
136
+
137
+ // // 处理人为操作
138
+ // if (!action) {
139
+ // if (stack.length > 1 && stack[stack.length - 2].path === to.path) {
140
+ // action = {
141
+ // type: 'back',
142
+ // delta: 1
143
+ // }
144
+ // } else {
145
+ // action = {
146
+ // type: 'to'
147
+ // }
148
+ // }
149
+ // }
150
+
151
+ // const pageInRoutes = routes.some(item => item.path === to.path)
152
+ // if (!pageInRoutes) {
153
+ // if (stack.length < 1) {
154
+ // if (global.__mpxRouter.app.$options.onPageNotFound) {
155
+ // // onPageNotFound,仅首次进入时生效
156
+ // global.__mpxRouter.app.$options.onPageNotFound({
157
+ // path: to.path,
158
+ // query: to.query,
159
+ // isEntryPage: true
160
+ // })
161
+ // return
162
+ // } else {
163
+ // console.warn(`[Mpx runtime warn]: the ${to.path} path does not exist in the application,will redirect to the home page path ${firstPage}`)
164
+ // return next({
165
+ // path: firstPage,
166
+ // replace: true
167
+ // })
168
+ // }
169
+ // } else {
170
+ // let methods = ''
171
+ // switch (action.type) {
172
+ // case 'to':
173
+ // methods = 'navigateTo'
174
+ // break
175
+ // case 'redirect':
176
+ // methods = 'redirectTo'
177
+ // break
178
+ // case 'back':
179
+ // methods = 'navigateBack'
180
+ // break
181
+ // case 'reLaunch':
182
+ // methods = 'reLaunch'
183
+ // break
184
+ // default:
185
+ // methods = 'navigateTo'
186
+ // }
187
+ // throw new Error(`${methods}:fail page "${to.path}" is not found`)
188
+ // }
189
+ // }
190
+
191
+ // const insertItem = {
192
+ // path: to.path
193
+ // }
194
+ // // 构建历史栈
195
+ // switch (action.type) {
196
+ // case 'to':
197
+ // stack.push(insertItem)
198
+ // global.__mpxRouter.needCache = insertItem
199
+ // break
200
+ // case 'back':
201
+ // global.__mpxRouter.needRemove = stack.splice(stack.length - action.delta, action.delta)
202
+ // break
203
+ // case 'redirect':
204
+ // global.__mpxRouter.needRemove = stack.splice(stack.length - 1, 1, insertItem)
205
+ // global.__mpxRouter.needCache = insertItem
206
+ // break
207
+ // case 'switch':
208
+ // if (!action.replaced) {
209
+ // action.replaced = true
210
+ // return next({
211
+ // path: action.path,
212
+ // replace: true
213
+ // })
214
+ // } else {
215
+ // // 将非tabBar页面remove
216
+ // let tabItem = null
217
+ // global.__mpxRouter.needRemove = stack.filter((item) => {
218
+ // if (tabBarMap[item.path.slice(1)]) {
219
+ // tabItem = item
220
+ // return false
221
+ // }
222
+ // return true
223
+ // })
224
+ // if (tabItem) {
225
+ // global.__mpxRouter.stack = [tabItem]
226
+ // } else {
227
+ // global.__mpxRouter.stack = [insertItem]
228
+ // global.__mpxRouter.needCache = insertItem
229
+ // }
230
+ // }
231
+ // break
232
+ // case 'reLaunch':
233
+ // if (!action.replaced) {
234
+ // action.replaced = true
235
+ // return next({
236
+ // path: action.path,
237
+ // query: {
238
+ // reLaunchCount: action.reLaunchCount
239
+ // },
240
+ // replace: true
241
+ // })
242
+ // } else {
243
+ // global.__mpxRouter.needRemove = stack
244
+ // global.__mpxRouter.stack = [insertItem]
245
+ // global.__mpxRouter.needCache = insertItem
246
+ // }
247
+ // }
248
+ // next()
249
+ // })
250
+ // // 处理visibilitychange时触发当前活跃页面组件的onshow/onhide
251
+ // if (inBrowser) {
252
+ // // const errorHandler = function (e) {
253
+ // // if (global.__mpxAppCbs && global.__mpxAppCbs.error) {
254
+ // // global.__mpxAppCbs.error.forEach((cb) => {
255
+ // // cb(e)
256
+ // // })
257
+ // // }
258
+ // // }
259
+ // // Vue.config.errorHandler = errorHandler
260
+ // // window.addEventListener('error', errorHandler)
261
+ // // window.addEventListener('unhandledrejection', event => {
262
+ // // errorHandler(event.reason)
263
+ // // })
264
+ // // document.addEventListener('visibilitychange', function () {
265
+ // // const vnode = global.__mpxRouter && global.__mpxRouter.__mpxActiveVnode
266
+ // // if (vnode && vnode.componentInstance) {
267
+ // // const currentPage = vnode.tag.endsWith('mpx-tab-bar-container') ? vnode.componentInstance.$refs.tabBarPage : vnode.componentInstance
268
+ // // if (document.hidden) {
269
+ // // if (global.__mpxAppCbs && global.__mpxAppCbs.hide) {
270
+ // // global.__mpxAppCbs.hide.forEach((cb) => {
271
+ // // cb()
272
+ // // })
273
+ // // }
274
+ // // if (currentPage) {
275
+ // // currentPage.mpxPageStatus = 'hide'
276
+ // // currentPage.onHide && currentPage.onHide()
277
+ // // }
278
+ // // } else {
279
+ // // if (global.__mpxAppCbs && global.__mpxAppCbs.show) {
280
+ // // global.__mpxAppCbs.show.forEach((cb) => {
281
+ // // // todo 实现app.onShow参数
282
+ // // /* eslint-disable standard/no-callback-literal */
283
+ // // cb({})
284
+ // // })
285
+ // // }
286
+ // // if (currentPage) {
287
+ // // currentPage.mpxPageStatus = 'show'
288
+ // // currentPage.onShow && currentPage.onShow()
289
+ // // }
290
+ // // }
291
+ // // }
292
+ // // })
293
+ // // 初始化length
294
+ // // global.__mpxRouter.__mpxHistoryLength = global.history.length
295
+ // }
296
+ // }
297
+
298
+ // if (i18n) {
299
+ // option.i18n = i18n
300
+ // }
301
+ } else {
302
+ // 局部注册页面和组件中依赖的组件
303
+ for (const componentName in componentsMap) {
304
+ if (hasOwn(componentsMap, componentName)) {
305
+ const component = componentsMap[componentName]
306
+ if (!option.components) {
307
+ option.components = {}
308
+ }
309
+ option.components[componentName] = component
310
+ }
311
+ }
312
+
313
+ // if (genericsInfo) {
314
+ // const genericHash = genericsInfo.hash
315
+ // global.__mpxGenericsMap[genericHash] = {}
316
+ // Object.keys(genericsInfo.map).forEach((genericValue) => {
317
+ // if (componentsMap[genericValue]) {
318
+ // global.__mpxGenericsMap[genericHash][genericValue] = componentsMap[genericValue]
319
+ // } else {
320
+ // console.log(option)
321
+ // console.warn(`[Mpx runtime warn]: generic value "${genericValue}" must be
322
+ // registered in parent context!`)
323
+ // }
324
+ // })
325
+ // }
326
+
327
+ // if (componentGenerics) {
328
+ // option.props = option.props || {}
329
+ // option.props.generichash = String
330
+ // Object.keys(componentGenerics).forEach((genericName) => {
331
+ // if (componentGenerics[genericName].default) {
332
+ // option.props[`generic${genericName}`] = {
333
+ // type: String,
334
+ // default: `${genericName}default`
335
+ // }
336
+ // } else {
337
+ // option.props[`generic${genericName}`] = String
338
+ // }
339
+ // })
340
+ // }
341
+
342
+ if (ctorType === 'page') {
343
+ (option.mixins ? option.mixins : (option.mixins = [])).push({
344
+ // cache page instance in tenon
345
+ created () {
346
+ global.__currentPageInstance = this
347
+ }
348
+ })
349
+ option.__mpxPageConfig = Object.assign({}, global.__mpxPageConfig, pageConfig)
350
+ }
351
+ }
352
+
353
+ if (mixin) {
354
+ if (option.mixins) {
355
+ option.mixins.push(mixin)
356
+ } else {
357
+ option.mixins = [mixin]
358
+ }
359
+ }
360
+
361
+ if (componentId) {
362
+ option.componentPath = '/' + componentId
363
+ }
364
+
365
+ return option
366
+ }
367
+
368
+ export function getComponent (component, extendOptions) {
369
+ component = component.__esModule ? component.default : component
370
+ // eslint-disable-next-line
371
+ if (extendOptions) Object.assign(component, extendOptions)
372
+ return component
373
+ }
374
+
375
+ export function getWxsMixin (wxsModules) {
376
+ if (!wxsModules) return {}
377
+ return {
378
+ created () {
379
+ Object.keys(wxsModules).forEach((key) => {
380
+ if (key in this) {
381
+ console.error(`[Mpx runtime error]: The wxs module key [${key}] exist in the component/page instance already, please check and rename it!`)
382
+ } else {
383
+ this[key] = wxsModules[key]
384
+ }
385
+ })
386
+ }
387
+ }
388
+ }
@@ -23,7 +23,7 @@ module.exports = function (css, map) {
23
23
  const transRpxRulesRaw = mpx.transRpxRules
24
24
  const transRpxRules = transRpxRulesRaw ? (Array.isArray(transRpxRulesRaw) ? transRpxRulesRaw : [transRpxRulesRaw]) : []
25
25
 
26
- const transRpxFn = mpx.webConfig.transRpxFn
26
+ const transRpxFn = mpx.webConfig && mpx.webConfig.transRpxFn
27
27
  const testResolveRange = (include = () => true, exclude) => {
28
28
  return matchCondition(this.resourcePath, { include, exclude })
29
29
  }
@@ -0,0 +1,20 @@
1
+ const postcss = require('postcss')
2
+ const rpxRegExp = /\b(\d+(\.\d+)?)rpx\b/
3
+ const rpxRegExpG = /\b(\d+(\.\d+)?)rpx\b/g
4
+
5
+ module.exports = postcss.plugin('hm', (options = {}) => root => {
6
+ function transHm (declaration) {
7
+ if (rpxRegExp.test(declaration.value)) {
8
+ declaration.value = declaration.value.replace(rpxRegExpG, function (match, $1) {
9
+ if ($1 === '0') return $1
10
+ return `${$1}hm`
11
+ })
12
+ }
13
+ }
14
+
15
+ root.walkRules(rule => {
16
+ rule.walkDecls(declaration => {
17
+ transHm(declaration)
18
+ })
19
+ })
20
+ })
@@ -2065,6 +2065,15 @@ function processElement (el, root, options, meta) {
2065
2065
  processComponentGenericsForWeb(el, options, meta)
2066
2066
  return
2067
2067
  }
2068
+ if (mode === 'tenon') {
2069
+ // 收集内建组件
2070
+ processBuiltInComponents(el, meta)
2071
+ // 预处理代码维度条件编译
2072
+ processIfForWeb(el)
2073
+ // processWebExternalClassesHack(el, options)
2074
+ // processComponentGenericsForWeb(el, options, meta)
2075
+ return
2076
+ }
2068
2077
 
2069
2078
  const pass = isNative || processTemplate(el) || processingTemplate
2070
2079
 
@@ -2097,7 +2106,7 @@ function processElement (el, root, options, meta) {
2097
2106
 
2098
2107
  function closeElement (el, meta, options) {
2099
2108
  postProcessAtMode(el)
2100
- if (mode === 'web') {
2109
+ if (mode === 'web' || mode === 'tenon') {
2101
2110
  postProcessWxs(el, meta)
2102
2111
  // 处理代码维度条件编译移除死分支
2103
2112
  postProcessIf(el)
@@ -2211,7 +2220,7 @@ function serialize (root) {
2211
2220
  result += node.text
2212
2221
  }
2213
2222
  }
2214
- if (node.tag === 'wxs' && mode === 'web') {
2223
+ if (node.tag === 'wxs' && (mode === 'web' || mode === 'tenon')) {
2215
2224
  return result
2216
2225
  }
2217
2226
  if (node.type === 1) {
@@ -0,0 +1,104 @@
1
+ const processJSON = require('./processJSON')
2
+ const processScript = require('./processScript')
3
+ const processStyles = require('./processStyles')
4
+ const processTemplate = require('./processTemplate')
5
+
6
+ const async = require('async')
7
+
8
+ module.exports = function ({
9
+ mpx,
10
+ loaderContext,
11
+ isProduction,
12
+ parts,
13
+ ctorType,
14
+ filePath,
15
+ queryObj,
16
+ autoScope,
17
+ componentsMap,
18
+ moduleId,
19
+ callback
20
+ }) {
21
+ const hasComment = parts.template && parts.template.attrs && parts.template.attrs.comments
22
+ const isNative = false
23
+ const mode = mpx.mode
24
+ const srcMode = mpx.srcMode
25
+ const env = mpx.env
26
+ const defs = mpx.defs
27
+ const resolveMode = mpx.resolveMode
28
+ const pagesMap = mpx.pagesMap
29
+ const projectRoot = mpx.projectRoot
30
+
31
+ let output = ''
32
+ const usingComponents = [].concat(Object.keys(mpx.usingComponents))
33
+
34
+ return async.waterfall([
35
+ (callback) => {
36
+ async.parallel([
37
+ (callback) => {
38
+ processTemplate(parts.template, {
39
+ hasComment,
40
+ isNative,
41
+ mode,
42
+ srcMode,
43
+ defs,
44
+ loaderContext,
45
+ moduleId,
46
+ ctorType,
47
+ usingComponents,
48
+ decodeHTMLText: mpx.decodeHTMLText,
49
+ externalClasses: mpx.externalClasses,
50
+ checkUsingComponents: mpx.checkUsingComponents
51
+ }, callback)
52
+ },
53
+ (callback) => {
54
+ processStyles(parts.styles, {
55
+ ctorType,
56
+ autoScope
57
+ }, callback)
58
+ },
59
+ (callback) => {
60
+ processJSON(parts.json, {
61
+ mode,
62
+ env,
63
+ defs,
64
+ resolveMode,
65
+ loaderContext,
66
+ pagesMap,
67
+ pathHash: mpx.pathHash,
68
+ componentsMap,
69
+ projectRoot
70
+ }, callback)
71
+ }
72
+ ], (err, res) => {
73
+ callback(err, res)
74
+ })
75
+ },
76
+ ([templateRes, stylesRes, jsonRes], callback) => {
77
+ output += templateRes.output
78
+ output += stylesRes.output
79
+ output += jsonRes.output
80
+ if (ctorType === 'app' && jsonRes.jsonObj.window && jsonRes.jsonObj.window.navigationBarTitleText) {
81
+ mpx.appTitle = jsonRes.jsonObj.window.navigationBarTitleText
82
+ }
83
+
84
+ processScript(parts.script, {
85
+ ctorType,
86
+ srcMode,
87
+ loaderContext,
88
+ isProduction,
89
+ projectRoot,
90
+ jsonConfig: jsonRes.jsonObj,
91
+ componentId: queryObj.componentId || '',
92
+ builtInComponentsMap: templateRes.builtInComponentsMap,
93
+ localComponentsMap: jsonRes.localComponentsMap,
94
+ localPagesMap: jsonRes.localPagesMap,
95
+ forceDisableBuiltInLoader: mpx.forceDisableBuiltInLoader
96
+ }, callback)
97
+ }
98
+ ], (err, scriptRes) => {
99
+ if (err) return callback(err)
100
+ output += scriptRes.output
101
+ mpx.vueContentCache.set(filePath, output)
102
+ callback(null, output)
103
+ })
104
+ }