@mpxjs/webpack-plugin 2.10.19 → 2.10.20
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.
- package/lib/dependencies/ResolveDependency.js +2 -2
- package/lib/index.js +25 -6
- package/lib/json-compiler/helper.js +11 -10
- package/lib/json-compiler/index.js +7 -4
- package/lib/json-compiler/plugin.js +4 -4
- package/lib/loader.js +4 -4
- package/lib/native-loader.js +4 -4
- package/lib/platform/create-diagnostic.js +168 -0
- package/lib/platform/index.js +16 -3
- package/lib/platform/json/wx/index.js +66 -17
- package/lib/platform/run-rules.js +9 -5
- package/lib/platform/style/wx/index.js +4 -3
- package/lib/platform/template/normalize-component-rules.js +7 -9
- package/lib/platform/template/wx/component-config/custom-built-in-component.js +34 -0
- package/lib/platform/template/wx/component-config/index.js +18 -3
- package/lib/platform/template/wx/component-config/input.js +1 -7
- package/lib/platform/template/wx/component-config/movable-view.js +1 -7
- package/lib/platform/template/wx/component-config/text.js +1 -1
- package/lib/platform/template/wx/component-config/textarea.js +1 -25
- package/lib/platform/template/wx/index.js +48 -34
- package/lib/react/processJSON.js +7 -4
- package/lib/react/processStyles.js +22 -8
- package/lib/react/processTemplate.js +85 -41
- package/lib/react/style-helper.js +120 -85
- package/lib/react/template-loader.js +148 -0
- package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-image.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +1 -1
- package/lib/runtime/components/react/dist/utils.jsx +3 -2
- package/lib/runtime/components/react/mpx-async-suspense.tsx +2 -1
- package/lib/runtime/components/react/mpx-image.tsx +1 -3
- package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
- package/lib/runtime/components/react/utils.tsx +3 -2
- package/lib/runtime/components/wx/default-component.mpx +9 -0
- package/lib/runtime/components/wx/default-page.mpx +3 -11
- package/lib/runtime/optionProcessor.d.ts +2 -0
- package/lib/runtime/optionProcessor.js +77 -1
- package/lib/style-compiler/index.js +2 -0
- package/lib/style-compiler/plugins/remove-strip-conditional-comments.js +14 -0
- package/lib/style-compiler/strip-conditional.js +40 -26
- package/lib/template-compiler/compiler.js +274 -116
- package/lib/template-compiler/gen-node-react.js +35 -7
- package/lib/template-compiler/index.js +9 -7
- package/lib/utils/const.js +4 -1
- package/lib/utils/partial-compile-rules.js +27 -0
- package/lib/utils/pre-process-json.js +3 -0
- package/lib/utils/source-location.js +96 -0
- package/lib/web/compile-wx-template-fragment.js +68 -0
- package/lib/web/index.js +2 -0
- package/lib/web/processJSON.js +7 -4
- package/lib/web/processScript.js +41 -3
- package/lib/web/processTemplate.js +61 -19
- package/lib/web/template-loader.js +123 -0
- package/lib/web/template-shared.js +48 -0
- package/lib/wxml/loader.js +3 -2
- package/lib/wxss/loader.js +1 -1
- package/lib/wxss/utils.js +6 -4
- package/package.json +11 -4
- package/lib/platform/template/wx/component-config/component.js +0 -41
|
@@ -48,7 +48,6 @@ export type Mode =
|
|
|
48
48
|
export interface ImageProps {
|
|
49
49
|
src?: string
|
|
50
50
|
mode?: Mode
|
|
51
|
-
svg?: boolean
|
|
52
51
|
style?: ImageStyle & Record<string, any>
|
|
53
52
|
'enable-offset'?: boolean
|
|
54
53
|
'enable-var'?: boolean
|
|
@@ -456,8 +455,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
|
|
|
456
455
|
),
|
|
457
456
|
[
|
|
458
457
|
'src',
|
|
459
|
-
'mode'
|
|
460
|
-
'svg'
|
|
458
|
+
'mode'
|
|
461
459
|
],
|
|
462
460
|
{
|
|
463
461
|
layoutRef
|
|
@@ -79,7 +79,7 @@ export interface RegionProps extends BasePickerProps {
|
|
|
79
79
|
/** 表示选中的省市区,默认选中每一列的第一个值, 默认值 [] */
|
|
80
80
|
value?: string[]
|
|
81
81
|
/** 默认值 region */
|
|
82
|
-
level?: 'province' | 'city' | 'region'
|
|
82
|
+
level?: 'province' | 'city' | 'region'
|
|
83
83
|
/** 可为每一列的顶部添加一个自定义的项 */
|
|
84
84
|
'custom-item'?: string
|
|
85
85
|
/** value 改变时触发 change 事件, event.detail = {value, code, postcode},
|
|
@@ -334,8 +334,9 @@ export function parseValues (str: string, char = ' ') {
|
|
|
334
334
|
// parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
|
|
335
335
|
function parseTransform (transformStr: string) {
|
|
336
336
|
const values = parseValues(transformStr)
|
|
337
|
-
// Todo
|
|
338
|
-
|
|
337
|
+
// Todo 2 RN下顺序不一致转换结果不一致,故这里不处理,动画前后transform 排序不一致的问题,由业务调整写法
|
|
338
|
+
// Todo 1 transform 排序不一致时,transform动画会闪烁,故这里同样的排序输出 transform
|
|
339
|
+
// values.sort()
|
|
339
340
|
const transform: { [propName: string]: string | number | number[] }[] = []
|
|
340
341
|
values.forEach(item => {
|
|
341
342
|
const match = item.match(/([/\w]+)\((.+)\)/)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view
|
|
3
|
-
<view>当前路由:{{currentRoute}}</view>
|
|
2
|
+
<view>局部构建兜底页面:{{pageRoute}}</view>
|
|
4
3
|
</template>
|
|
5
4
|
|
|
6
5
|
<script>
|
|
@@ -10,18 +9,11 @@ import { createPage } from '@mpxjs/core'
|
|
|
10
9
|
createPage({
|
|
11
10
|
data() {
|
|
12
11
|
return {
|
|
13
|
-
|
|
12
|
+
pageRoute: ''
|
|
14
13
|
}
|
|
15
14
|
},
|
|
16
15
|
onLoad() {
|
|
17
|
-
this.
|
|
18
|
-
},
|
|
19
|
-
methods: {
|
|
20
|
-
getPagePath() {
|
|
21
|
-
const pages = getCurrentPages() || []
|
|
22
|
-
const currPage = pages[pages.length - 1]
|
|
23
|
-
this.currentRoute = currPage && currPage.route || ''
|
|
24
|
-
},
|
|
16
|
+
this.pageRoute = this.route
|
|
25
17
|
}
|
|
26
18
|
})
|
|
27
19
|
</script>
|
|
@@ -2,13 +2,15 @@ import { hasOwn, isEmptyObject, extend } from './utils'
|
|
|
2
2
|
import { isBrowser } from './env'
|
|
3
3
|
import transRpxStyle from './transRpxStyle'
|
|
4
4
|
import animation from './animation'
|
|
5
|
-
import { error } from '@mpxjs/utils'
|
|
5
|
+
import { error, proxy } from '@mpxjs/utils'
|
|
6
6
|
const dash2hump = require('../utils/hump-dash').dash2hump
|
|
7
7
|
|
|
8
8
|
export function processComponentOption (
|
|
9
9
|
{
|
|
10
10
|
option,
|
|
11
11
|
ctorType,
|
|
12
|
+
moduleId,
|
|
13
|
+
hasScoped,
|
|
12
14
|
outputPath,
|
|
13
15
|
pageConfig,
|
|
14
16
|
componentsMap,
|
|
@@ -75,6 +77,19 @@ registered in parent context!`)
|
|
|
75
77
|
if (outputPath) {
|
|
76
78
|
option.componentPath = '/' + outputPath
|
|
77
79
|
}
|
|
80
|
+
|
|
81
|
+
// 宿主组件的 moduleId / scoped / ctorType 信息挂在 option 上,供 mpx-tpl-* 子模版通过 __mpxHost.$options 读取
|
|
82
|
+
option.__mpxModuleId = moduleId || ''
|
|
83
|
+
option.__mpxScoped = !!hasScoped
|
|
84
|
+
option.__mpxCtorType = ctorType
|
|
85
|
+
// 暴露宿主实例引用,供 mpx-tpl-* 子模版组件通过 inject 获取
|
|
86
|
+
const prevProvide = option.provide
|
|
87
|
+
option.provide = function () {
|
|
88
|
+
const base = typeof prevProvide === 'function'
|
|
89
|
+
? prevProvide.call(this)
|
|
90
|
+
: (prevProvide || {})
|
|
91
|
+
return extend({}, base, { __mpxHost: this })
|
|
92
|
+
}
|
|
78
93
|
if (ctorType === 'app') {
|
|
79
94
|
option.data = function () {
|
|
80
95
|
return {
|
|
@@ -134,6 +149,67 @@ export function getWxsMixin (wxsModules) {
|
|
|
134
149
|
}
|
|
135
150
|
}
|
|
136
151
|
|
|
152
|
+
/**
|
|
153
|
+
* 将子模版实例的 `$slots` 代理到 `inject` 的宿主 `__mpxHost.$slots`(仅默认 / 具名,与 solutions/web-template-support.md §2.8 一致)。
|
|
154
|
+
* 不使用 `$watch`;若无法 defineProperty(如属性已不可配置),开发环境告警并跳过。
|
|
155
|
+
*/
|
|
156
|
+
function installMpxWxTemplateHostSlotsProxy (vm) {
|
|
157
|
+
if (!vm.__mpxHost) return
|
|
158
|
+
try {
|
|
159
|
+
Object.defineProperty(vm, '$slots', {
|
|
160
|
+
configurable: true,
|
|
161
|
+
enumerable: true,
|
|
162
|
+
get () {
|
|
163
|
+
const h = this.__mpxHost
|
|
164
|
+
return (h && h.$slots) || {}
|
|
165
|
+
},
|
|
166
|
+
set () { } // 不支持写入
|
|
167
|
+
})
|
|
168
|
+
} catch (e) {
|
|
169
|
+
if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production') {
|
|
170
|
+
console.warn('[Mpx] mpx-tpl: could not proxy $slots to __mpxHost:', e && e.message)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 创建 wxml template 对应的 Vue 子组件选项(仅接受构建期编译产物,见 web/compile-wx-template-fragment)
|
|
176
|
+
// - props.mpxData:承载模版调用传入的数据,通过 proxy 在 this 上建立访问代理
|
|
177
|
+
// - inject.__mpxHost:从最近的 mpx 宿主获取 this,用于继承 methods/components;其 $slots 经 installMpxWxTemplateHostSlotsProxy 供模版内 <slot> 使用
|
|
178
|
+
// - wxsModules:由模版所在 wxml 自身声明的 wxs 模块(不继承宿主 wxs)
|
|
179
|
+
// - render / staticRenderFns:须由 `vue/compiler-sfc` compileTemplate 等在构建期注入,不支持字符串 template
|
|
180
|
+
export function createTemplateComponent ({ name, render, staticRenderFns, components, wxsModules }) {
|
|
181
|
+
if (typeof render !== 'function') {
|
|
182
|
+
throw new Error('[Mpx] createTemplateComponent requires a build-time `render` function (string template is not supported).')
|
|
183
|
+
}
|
|
184
|
+
const wxsMixin = getWxsMixin(wxsModules)
|
|
185
|
+
const base = {
|
|
186
|
+
name,
|
|
187
|
+
render,
|
|
188
|
+
components: components || {},
|
|
189
|
+
mixins: wxsMixin ? [wxsMixin] : [],
|
|
190
|
+
props: { mpxData: { type: Object, default: () => ({}) } },
|
|
191
|
+
inject: { __mpxHost: { default: null } },
|
|
192
|
+
created () {
|
|
193
|
+
const host = this.__mpxHost
|
|
194
|
+
if (host) {
|
|
195
|
+
const hostMethods = host.$options.methods || {}
|
|
196
|
+
Object.keys(hostMethods).forEach((k) => {
|
|
197
|
+
if (!(k in this)) this[k] = hostMethods[k].bind(host)
|
|
198
|
+
})
|
|
199
|
+
const compBase = this.$options.components || {}
|
|
200
|
+
const merged = Object.create(Object.getPrototypeOf(compBase) || null)
|
|
201
|
+
extend(merged, compBase, host.$options.components || {})
|
|
202
|
+
this.$options.components = merged
|
|
203
|
+
installMpxWxTemplateHostSlotsProxy(this)
|
|
204
|
+
}
|
|
205
|
+
// mpxData 常为宿主每次 render 的新字面量:source 传 getter,proxy 每次读都解析当前 this.mpxData;假定 key 集合在生命周期内不变(不在 updated 中补全新 key)
|
|
206
|
+
proxy(this, () => this.mpxData || {})
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (staticRenderFns && staticRenderFns.length) base.staticRenderFns = staticRenderFns
|
|
210
|
+
return base
|
|
211
|
+
}
|
|
212
|
+
|
|
137
213
|
function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, tabBarMap }) {
|
|
138
214
|
const option = {}
|
|
139
215
|
// 对于app中的组件需要全局注册
|
|
@@ -7,6 +7,7 @@ const vw = require('./plugins/vw')
|
|
|
7
7
|
const scopeId = require('./plugins/scope-id')
|
|
8
8
|
const transSpecial = require('./plugins/trans-special')
|
|
9
9
|
const cssArrayList = require('./plugins/css-array-list')
|
|
10
|
+
const removeStripConditionalComments = require('./plugins/remove-strip-conditional-comments')
|
|
10
11
|
const { matchCondition } = require('../utils/match-condition')
|
|
11
12
|
const parseRequest = require('../utils/parse-request')
|
|
12
13
|
const isReact = require('../utils/env').isReact
|
|
@@ -96,6 +97,7 @@ module.exports = function (css, map) {
|
|
|
96
97
|
if (mpx.mode === 'web') {
|
|
97
98
|
postPlugins.push(vw({ transRpxFn }))
|
|
98
99
|
}
|
|
100
|
+
postPlugins.push(removeStripConditionalComments())
|
|
99
101
|
|
|
100
102
|
const finalPlugins = config.prePlugins.concat(plugins, config.plugins, postPlugins)
|
|
101
103
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { STYLE_PAD_PLACEHOLDER } = require('../../utils/const')
|
|
2
|
+
|
|
3
|
+
module.exports = () => {
|
|
4
|
+
return {
|
|
5
|
+
postcssPlugin: 'remove-strip-conditional-comments',
|
|
6
|
+
Comment (comment) {
|
|
7
|
+
if (comment.text.trim() === STYLE_PAD_PLACEHOLDER) {
|
|
8
|
+
comment.remove()
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports.postcss = true
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
|
+
const { STYLE_PAD_PLACEHOLDER } = require('../utils/const')
|
|
2
3
|
|
|
3
4
|
class Node {
|
|
4
|
-
constructor(type, condition = null) {
|
|
5
|
+
constructor(type, condition = null, value = '') {
|
|
5
6
|
this.type = type // 'If', 'ElseIf', 'Else' 或 'Text'
|
|
6
7
|
this.condition = condition // If 或 Elif 的条件
|
|
7
8
|
this.children = []
|
|
8
|
-
this.value =
|
|
9
|
+
this.value = value
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
function keepLines(content) {
|
|
14
|
+
return content.replace(/([^\r\n]*)(\r\n|\r|\n|$)/g, (all, line, lineBreak) => {
|
|
15
|
+
if (!all) return ''
|
|
16
|
+
const indent = (/^[ \t]*/.exec(line) || [''])[0]
|
|
17
|
+
return `${indent}/* ${STYLE_PAD_PLACEHOLDER} */${lineBreak}`
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
// 提取 css string 为 token
|
|
13
22
|
function tokenize(cssString) {
|
|
14
23
|
// Support /* ... */, // ..., and <!-- ... --> styles
|
|
@@ -35,7 +44,8 @@ function tokenize(cssString) {
|
|
|
35
44
|
|
|
36
45
|
tokens.push({
|
|
37
46
|
type: type,
|
|
38
|
-
condition: condition ? condition.trim() : null
|
|
47
|
+
condition: condition ? condition.trim() : null,
|
|
48
|
+
content: match[0]
|
|
39
49
|
})
|
|
40
50
|
lastIndex = regex.lastIndex
|
|
41
51
|
}
|
|
@@ -55,11 +65,10 @@ function parse(cssString) {
|
|
|
55
65
|
let currentChildren = ast
|
|
56
66
|
tokens.forEach(token => {
|
|
57
67
|
if (token.type === 'text') {
|
|
58
|
-
const node = new Node('Text')
|
|
59
|
-
node.value = token.content
|
|
68
|
+
const node = new Node('Text', null, token.content)
|
|
60
69
|
currentChildren.push(node)
|
|
61
70
|
} else if (token.type === 'if') {
|
|
62
|
-
const node = new Node('If', token.condition)
|
|
71
|
+
const node = new Node('If', token.condition, token.content)
|
|
63
72
|
currentChildren.push(node)
|
|
64
73
|
nodeStack.push(currentChildren)
|
|
65
74
|
currentChildren = node.children
|
|
@@ -68,7 +77,7 @@ function parse(cssString) {
|
|
|
68
77
|
throw new Error('[Mpx style error]: elif without a preceding if')
|
|
69
78
|
}
|
|
70
79
|
currentChildren = nodeStack[nodeStack.length - 1]
|
|
71
|
-
const node = new Node('ElseIf', token.condition)
|
|
80
|
+
const node = new Node('ElseIf', token.condition, token.content)
|
|
72
81
|
currentChildren.push(node)
|
|
73
82
|
currentChildren = node.children
|
|
74
83
|
} else if (token.type === 'else') {
|
|
@@ -76,11 +85,12 @@ function parse(cssString) {
|
|
|
76
85
|
throw new Error('[Mpx style error]: else without a preceding if')
|
|
77
86
|
}
|
|
78
87
|
currentChildren = nodeStack[nodeStack.length - 1]
|
|
79
|
-
const node = new Node('Else')
|
|
88
|
+
const node = new Node('Else', null, token.content)
|
|
80
89
|
currentChildren.push(node)
|
|
81
90
|
currentChildren = node.children
|
|
82
91
|
} else if (token.type === 'endif') {
|
|
83
92
|
if (nodeStack.length > 0) {
|
|
93
|
+
currentChildren.push(new Node('EndIf', null, token.content))
|
|
84
94
|
currentChildren = nodeStack.pop()
|
|
85
95
|
}
|
|
86
96
|
}
|
|
@@ -105,31 +115,35 @@ function evaluateCondition(condition, defs) {
|
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
function traverseAndEvaluate(ast, defs) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
118
|
+
function traverse(nodes, active) {
|
|
119
|
+
let output = ''
|
|
120
|
+
let batchedIf = false
|
|
111
121
|
for (const node of nodes) {
|
|
112
122
|
if (node.type === 'Text') {
|
|
113
|
-
output += node.value
|
|
123
|
+
output += active ? node.value : keepLines(node.value)
|
|
114
124
|
} else if (node.type === 'If') {
|
|
115
125
|
// 直接判断 If 节点
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
output += keepLines(node.value)
|
|
127
|
+
const currentMatched = active && evaluateCondition(node.condition, defs)
|
|
128
|
+
output += traverse(node.children, currentMatched)
|
|
129
|
+
batchedIf = currentMatched
|
|
130
|
+
} else if (node.type === 'ElseIf') {
|
|
131
|
+
output += keepLines(node.value)
|
|
132
|
+
const currentMatched = active && !batchedIf && evaluateCondition(node.condition, defs)
|
|
133
|
+
output += traverse(node.children, currentMatched)
|
|
134
|
+
batchedIf = batchedIf || currentMatched
|
|
135
|
+
} else if (node.type === 'Else') {
|
|
136
|
+
output += keepLines(node.value)
|
|
137
|
+
const currentMatched = active && !batchedIf
|
|
138
|
+
output += traverse(node.children, currentMatched)
|
|
139
|
+
batchedIf = true
|
|
140
|
+
} else if (node.type === 'EndIf') {
|
|
141
|
+
output += keepLines(node.value)
|
|
128
142
|
}
|
|
129
143
|
}
|
|
144
|
+
return output
|
|
130
145
|
}
|
|
131
|
-
traverse(ast)
|
|
132
|
-
return output
|
|
146
|
+
return traverse(ast, true)
|
|
133
147
|
}
|
|
134
148
|
|
|
135
149
|
/**
|