@mpxjs/webpack-plugin 2.9.64 → 2.9.66

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 (80) hide show
  1. package/lib/config.js +38 -10
  2. package/lib/index.js +5 -1
  3. package/lib/platform/style/wx/index.js +66 -60
  4. package/lib/platform/template/wx/index.js +12 -8
  5. package/lib/react/processTemplate.js +4 -2
  6. package/lib/react/style-helper.js +2 -5
  7. package/lib/runtime/components/react/context.ts +8 -0
  8. package/lib/runtime/components/react/dist/context.js +1 -0
  9. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -1
  10. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -1
  11. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +3 -2
  12. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -1
  13. package/lib/runtime/components/react/dist/mpx-icon.jsx +3 -2
  14. package/lib/runtime/components/react/dist/mpx-image/index.jsx +2 -1
  15. package/lib/runtime/components/react/dist/mpx-input.jsx +2 -1
  16. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -1
  17. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +3 -2
  18. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +2 -1
  19. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +2 -1
  20. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +2 -1
  21. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +2 -1
  22. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +2 -1
  23. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +2 -1
  24. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +4 -2
  25. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +3 -2
  26. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +2 -1
  27. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -1
  28. package/lib/runtime/components/react/dist/mpx-radio.jsx +3 -2
  29. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -3
  30. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +78 -77
  31. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +2 -1
  32. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +3 -2
  33. package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -2
  34. package/lib/runtime/components/react/dist/mpx-text.jsx +2 -1
  35. package/lib/runtime/components/react/dist/mpx-view.jsx +45 -15
  36. package/lib/runtime/components/react/dist/mpx-web-view.jsx +4 -3
  37. package/lib/runtime/components/react/dist/useAnimationHooks.js +215 -0
  38. package/lib/runtime/components/react/dist/useNodesRef.js +1 -5
  39. package/lib/runtime/components/react/dist/utils.jsx +50 -37
  40. package/lib/runtime/components/react/mpx-button.tsx +3 -1
  41. package/lib/runtime/components/react/mpx-checkbox-group.tsx +3 -1
  42. package/lib/runtime/components/react/mpx-checkbox.tsx +4 -1
  43. package/lib/runtime/components/react/mpx-form.tsx +2 -1
  44. package/lib/runtime/components/react/mpx-icon.tsx +3 -2
  45. package/lib/runtime/components/react/mpx-image/index.tsx +2 -1
  46. package/lib/runtime/components/react/mpx-input.tsx +2 -1
  47. package/lib/runtime/components/react/mpx-label.tsx +2 -1
  48. package/lib/runtime/components/react/mpx-movable-area.tsx +3 -2
  49. package/lib/runtime/components/react/mpx-movable-view.tsx +2 -1
  50. package/lib/runtime/components/react/mpx-picker/date.tsx +2 -1
  51. package/lib/runtime/components/react/mpx-picker/index.tsx +2 -1
  52. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +2 -1
  53. package/lib/runtime/components/react/mpx-picker/region.tsx +2 -1
  54. package/lib/runtime/components/react/mpx-picker/selector.tsx +2 -1
  55. package/lib/runtime/components/react/mpx-picker/time.tsx +4 -2
  56. package/lib/runtime/components/react/mpx-picker-view-column.tsx +3 -2
  57. package/lib/runtime/components/react/mpx-picker-view.tsx +2 -1
  58. package/lib/runtime/components/react/mpx-radio-group.tsx +2 -1
  59. package/lib/runtime/components/react/mpx-radio.tsx +3 -2
  60. package/lib/runtime/components/react/mpx-scroll-view.tsx +14 -2
  61. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +77 -75
  62. package/lib/runtime/components/react/mpx-swiper/index.tsx +4 -1
  63. package/lib/runtime/components/react/mpx-swiper-item.tsx +2 -1
  64. package/lib/runtime/components/react/mpx-switch.tsx +2 -1
  65. package/lib/runtime/components/react/mpx-text.tsx +2 -1
  66. package/lib/runtime/components/react/mpx-view.tsx +55 -23
  67. package/lib/runtime/components/react/mpx-web-view.tsx +4 -3
  68. package/lib/runtime/components/react/types/common.ts +8 -2
  69. package/lib/runtime/components/react/types/global.d.ts +11 -1
  70. package/lib/runtime/components/react/useAnimationHooks.ts +248 -0
  71. package/lib/runtime/components/react/useNodesRef.ts +1 -6
  72. package/lib/runtime/components/react/utils.tsx +71 -50
  73. package/lib/runtime/components/web/mpx-scroll-view.vue +25 -5
  74. package/lib/style-compiler/index.js +5 -4
  75. package/lib/template-compiler/compiler.js +127 -158
  76. package/lib/utils/const.js +2 -1
  77. package/lib/web/processStyles.js +6 -2
  78. package/lib/web/processTemplate.js +2 -3
  79. package/lib/wxml/loader.js +1 -1
  80. package/package.json +6 -4
package/lib/config.js CHANGED
@@ -1,3 +1,5 @@
1
+ const { dash2hump } = require('./utils/hump-dash')
2
+
1
3
  const reactConfig = {
2
4
  event: {
3
5
  parseEvent (attr) {
@@ -70,7 +72,11 @@ module.exports = {
70
72
  }
71
73
  },
72
74
  getEvent (eventName, prefix = 'bind') {
73
- return prefix + eventName
75
+ if (eventName.includes('-')) {
76
+ return `${prefix}:${eventName}`
77
+ } else {
78
+ return prefix + eventName
79
+ }
74
80
  },
75
81
  defaultModelProp: 'value',
76
82
  defaultModelEvent: 'input',
@@ -132,9 +138,7 @@ module.exports = {
132
138
  }
133
139
  },
134
140
  getEvent (eventName, prefix = 'on') {
135
- return prefix + eventName.replace(/^./, (matched) => {
136
- return matched.toUpperCase()
137
- })
141
+ return dash2hump(prefix + '-' + eventName)
138
142
  },
139
143
  defaultModelProp: 'value',
140
144
  defaultModelEvent: 'input',
@@ -192,7 +196,11 @@ module.exports = {
192
196
  }
193
197
  },
194
198
  getEvent (eventName, prefix = 'bind') {
195
- return prefix + eventName
199
+ if (eventName.includes('-')) {
200
+ return `${prefix}:${eventName}`
201
+ } else {
202
+ return prefix + eventName
203
+ }
196
204
  },
197
205
  defaultModelProp: 'value',
198
206
  defaultModelEvent: 'input',
@@ -249,7 +257,11 @@ module.exports = {
249
257
  }
250
258
  },
251
259
  getEvent (eventName, prefix = 'bind') {
252
- return prefix + eventName
260
+ if (eventName.includes('-')) {
261
+ return `${prefix}:${eventName}`
262
+ } else {
263
+ return prefix + eventName
264
+ }
253
265
  },
254
266
  defaultModelProp: 'value',
255
267
  defaultModelEvent: 'input',
@@ -306,7 +318,11 @@ module.exports = {
306
318
  }
307
319
  },
308
320
  getEvent (eventName, prefix = 'bind') {
309
- return prefix + eventName
321
+ if (eventName.includes('-')) {
322
+ return `${prefix}:${eventName}`
323
+ } else {
324
+ return prefix + eventName
325
+ }
310
326
  },
311
327
  defaultModelProp: 'value',
312
328
  defaultModelEvent: 'input',
@@ -377,7 +393,11 @@ module.exports = {
377
393
  }
378
394
  },
379
395
  getEvent (eventName, prefix = 'bind') {
380
- return prefix + eventName
396
+ if (eventName.includes('-')) {
397
+ return `${prefix}:${eventName}`
398
+ } else {
399
+ return prefix + eventName
400
+ }
381
401
  },
382
402
  defaultModelProp: 'value',
383
403
  defaultModelEvent: 'input',
@@ -434,7 +454,11 @@ module.exports = {
434
454
  }
435
455
  },
436
456
  getEvent (eventName, prefix = 'bind') {
437
- return prefix + eventName
457
+ if (eventName.includes('-')) {
458
+ return `${prefix}:${eventName}`
459
+ } else {
460
+ return prefix + eventName
461
+ }
438
462
  },
439
463
  defaultModelProp: 'value',
440
464
  defaultModelEvent: 'input',
@@ -491,7 +515,11 @@ module.exports = {
491
515
  }
492
516
  },
493
517
  getEvent (eventName, prefix = 'bind') {
494
- return prefix + eventName
518
+ if (eventName.includes('-')) {
519
+ return `${prefix}:${eventName}`
520
+ } else {
521
+ return prefix + eventName
522
+ }
495
523
  },
496
524
  defaultModelProp: 'value',
497
525
  defaultModelEvent: 'input',
package/lib/index.js CHANGED
@@ -139,6 +139,7 @@ class MpxWebpackPlugin {
139
139
  options.writeMode = options.writeMode || 'changed'
140
140
  options.autoScopeRules = options.autoScopeRules || {}
141
141
  options.autoVirtualHostRules = options.autoVirtualHostRules || {}
142
+ options.customTextRules = options.customTextRules || {}
142
143
  options.forceDisableProxyCtor = options.forceDisableProxyCtor || false
143
144
  options.transMpxRules = options.transMpxRules || {
144
145
  include: () => true
@@ -173,6 +174,7 @@ class MpxWebpackPlugin {
173
174
  options.subpackageModulesRules = options.subpackageModulesRules || {}
174
175
  options.forceMainPackageRules = options.forceMainPackageRules || {}
175
176
  options.forceProxyEventRules = options.forceProxyEventRules || {}
177
+ options.disableRequireAsync = options.disableRequireAsync || false
176
178
  options.miniNpmPackages = options.miniNpmPackages || []
177
179
  options.fileConditionRules = options.fileConditionRules || {
178
180
  include: () => true
@@ -687,6 +689,7 @@ class MpxWebpackPlugin {
687
689
  projectName: this.options.projectName,
688
690
  autoScopeRules: this.options.autoScopeRules,
689
691
  autoVirtualHostRules: this.options.autoVirtualHostRules,
692
+ customTextRules: this.options.customTextRules,
690
693
  transRpxRules: this.options.transRpxRules,
691
694
  postcssInlineConfig: this.options.postcssInlineConfig,
692
695
  decodeHTMLText: this.options.decodeHTMLText,
@@ -708,7 +711,8 @@ class MpxWebpackPlugin {
708
711
  useRelativePath: this.options.useRelativePath,
709
712
  removedChunks: [],
710
713
  forceProxyEventRules: this.options.forceProxyEventRules,
711
- supportRequireAsync: this.options.mode === 'wx' || this.options.mode === 'ali' || this.options.mode === 'tt' || isWeb(this.options.mode),
714
+ // 若配置disableRequireAsync=true, 则全平台构建不支持异步分包
715
+ supportRequireAsync: !this.options.disableRequireAsync && (this.options.mode === 'wx' || this.options.mode === 'ali' || this.options.mode === 'tt' || isWeb(this.options.mode)),
712
716
  partialCompileRules: this.options.partialCompileRules,
713
717
  collectDynamicEntryInfo: ({ resource, packageName, filename, entryType, hasAsync }) => {
714
718
  const curInfo = mpx.dynamicEntryInfo[packageName] = mpx.dynamicEntryInfo[packageName] || {
@@ -13,6 +13,7 @@ module.exports = function getSpec ({ warn, error }) {
13
13
  const cssVariableExp = /var\(/
14
14
  // calc(xx)
15
15
  const calcExp = /calc\(/
16
+ const envExp = /env\(/
16
17
  // 不支持的属性提示
17
18
  const unsupportedPropError = ({ prop, value, selector }, { mode }, isError = true) => {
18
19
  const tips = isError ? error : warn
@@ -85,15 +86,45 @@ module.exports = function getSpec ({ warn, error }) {
85
86
  if (rule[1].test(prop)) return rule[0]
86
87
  }
87
88
  }
89
+ // 多value解析
90
+ const parseValues = (str, char = ' ') => {
91
+ let stack = 0
92
+ let temp = ''
93
+ const result = []
94
+ for (let i = 0; i < str.length; i++) {
95
+ if (str[i] === '(') {
96
+ stack++
97
+ } else if (str[i] === ')') {
98
+ stack--
99
+ }
100
+ // 非括号内 或者 非分隔字符且非空
101
+ if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
102
+ temp += str[i]
103
+ }
104
+ if ((stack === 0 && str[i] === char) || i === str.length - 1) {
105
+ result.push(temp)
106
+ temp = ''
107
+ }
108
+ }
109
+ return result
110
+ }
111
+ // const getDefaultValueFromVar = (str) => {
112
+ // const totalVarExp = /^var\((.+)\)$/
113
+ // if (!totalVarExp.test(str)) return str
114
+ // const newVal = parseValues((str.match(totalVarExp)?.[1] || ''), ',')
115
+ // if (newVal.length <= 1) return ''
116
+ // if (!totalVarExp.test(newVal[1])) return newVal[1]
117
+ // return getDefaultValueFromVar(newVal[1])
118
+ // }
88
119
  // 属性值校验
89
120
  const verifyValues = ({ prop, value, selector }, isError = true) => {
90
121
  prop = prop.trim()
91
122
  value = value.trim()
92
123
  const tips = isError ? error : warn
93
- if (cssVariableExp.test(value) || calcExp.test(value)) return true
124
+ if (cssVariableExp.test(value) || calcExp.test(value) || envExp.test(value)) return true
94
125
  const namedColor = ['transparent', 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'rebeccapurple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen']
95
126
  const valueExp = {
96
- number: /^((-?\d+(\.\d+)?)(rpx|px|%|vw|vh)?|hairlineWidth)$/,
127
+ number: /^((-?(\d+(\.\d+)?|\.\d+))(rpx|px|%|vw|vh)?|hairlineWidth)$/,
97
128
  color: new RegExp(('^(' + namedColor.join('|') + ')$') + '|(^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$)|^(rgb|rgba|hsl|hsla|hwb)\\(.+\\)$')
98
129
  }
99
130
  const type = getValueType(prop)
@@ -159,12 +190,16 @@ module.exports = function getSpec ({ warn, error }) {
159
190
  flex: ['flexGrow', 'flexShrink', 'flexBasis'],
160
191
  // flex-flow: <'flex-direction'> or flex-flow: <'flex-direction'> and <'flex-wrap'>
161
192
  'flex-flow': ['flexDirection', 'flexWrap'],
162
- 'border-radius': ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius']
193
+ 'border-radius': ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius'],
194
+ 'border-width': ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'],
195
+ 'border-color': ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'],
196
+ margin: ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'],
197
+ padding: ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']
163
198
  }
164
199
  const formatAbbreviation = ({ prop, value, selector }, { mode }) => {
165
200
  const original = `${prop}:${value}`
166
201
  const props = AbbreviationMap[prop]
167
- const values = value.trim().split(/\s(?![^()]*\))/)
202
+ const values = Array.isArray(value) ? value : parseValues(value)
168
203
  const cssMap = []
169
204
  let idx = 0
170
205
  let propsIdx = 0
@@ -172,7 +207,7 @@ module.exports = function getSpec ({ warn, error }) {
172
207
  while (idx < values.length) {
173
208
  const prop = props[propsIdx]
174
209
  if (!prop) {
175
- error(`Value of [${original}] in ${selector} has not enough props to assign, please check again!`)
210
+ warn(`Value of [${original}] in ${selector} has not enough props to assign, please check again!`)
176
211
  break
177
212
  }
178
213
  const value = values[idx]
@@ -224,39 +259,27 @@ module.exports = function getSpec ({ warn, error }) {
224
259
  return cssMap
225
260
  }
226
261
 
227
- // margin padding
228
- const formatMargins = ({ prop, value, selector }) => {
229
- const values = value.trim().split(/\s(?![^()]*\))/)
230
- // format
231
- let suffix = []
262
+ const formatCompositeVal = ({ prop, value, selector }, { mode }) => {
263
+ const values = parseValues(value).splice(0, 4)
232
264
  switch (values.length) {
233
- // case 1:
265
+ case 1:
266
+ verifyValues({ prop, value, selector }, false)
267
+ return { prop, value }
234
268
  case 2:
235
- suffix = ['Vertical', 'Horizontal']
269
+ values.push(...values)
236
270
  break
237
271
  case 3:
238
- suffix = ['Top', 'Horizontal', 'Bottom']
239
- break
240
- case 4:
241
- suffix = ['Top', 'Right', 'Bottom', 'Left']
272
+ values.push(values[1])
242
273
  break
243
274
  }
244
- return values.map((value, index) => {
245
- const newProp = `${prop}${suffix[index] || ''}`
246
- // validate
247
- verifyValues({ prop: hump2dash(newProp), value, selector }, false)
248
- return {
249
- prop: newProp,
250
- value: value
251
- }
252
- })
275
+ return formatAbbreviation({ prop, value: values, selector }, { mode })
253
276
  }
254
277
 
255
278
  // line-height
256
279
  const formatLineHeight = ({ prop, value, selector }) => {
257
280
  return verifyValues({ prop, value, selector }) && ({
258
281
  prop,
259
- value: /^\s*-?\d+(\.\d+)?\s*$/.test(value) ? `${Math.round(value * 100)}%` : value
282
+ value: /^\s*(-?(\d+(\.\d+)?|\.\d+))\s*$/.test(value) ? `${Math.round(value * 100)}%` : value
260
283
  })
261
284
  }
262
285
 
@@ -273,7 +296,7 @@ module.exports = function getSpec ({ warn, error }) {
273
296
  all: 'background'
274
297
  }
275
298
  const urlExp = /url\(["']?(.*?)["']?\)/
276
- const linerExp = /linear-gradient\(["']?(.*?)["']?\)/
299
+ const linerExp = /linear-gradient\(.*\)\s*$/
277
300
  switch (prop) {
278
301
  case bgPropMap.image: {
279
302
  // background-image 仅支持背景图
@@ -293,12 +316,12 @@ module.exports = function getSpec ({ warn, error }) {
293
316
  // 不支持逗号分隔的多个值:设置多重背景!!!
294
317
  // 支持一个值:这个值指定图片的宽度,图片的高度隐式的为 auto
295
318
  // 支持两个值:第一个值指定图片的宽度,第二个值指定图片的高度
296
- if (value.includes(',')) { // commas are not allowed in values
319
+ if (parseValues(value, ',').length > 1) { // commas are not allowed in values
297
320
  error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
298
321
  return false
299
322
  }
300
323
  const values = []
301
- value.trim().split(/\s(?![^()]*\))/).forEach(item => {
324
+ parseValues(value).forEach(item => {
302
325
  if (verifyValues({ prop, value: item, selector })) {
303
326
  // 支持 number 值 / container cover auto 枚举
304
327
  values.push(item)
@@ -309,7 +332,7 @@ module.exports = function getSpec ({ warn, error }) {
309
332
  }
310
333
  case bgPropMap.position: {
311
334
  const values = []
312
- value.trim().split(/\s(?![^()]*\))/).forEach(item => {
335
+ parseValues(value).forEach(item => {
313
336
  if (verifyValues({ prop, value: item, selector })) {
314
337
  // 支持 number 值 / 枚举, center与50%等价
315
338
  values.push(item === 'center' ? '50%' : item)
@@ -322,7 +345,7 @@ module.exports = function getSpec ({ warn, error }) {
322
345
  case bgPropMap.all: {
323
346
  // background: 仅支持 background-image & background-color & background-repeat
324
347
  const bgMap = []
325
- const values = value.trim().split(/\s(?![^()]*\))/)
348
+ const values = parseValues(value)
326
349
  values.forEach(item => {
327
350
  const url = item.match(urlExp)?.[0]
328
351
  const linerVal = item.match(linerExp)?.[0]
@@ -343,26 +366,10 @@ module.exports = function getSpec ({ warn, error }) {
343
366
  return false
344
367
  }
345
368
 
346
- // border-radius 缩写转换
347
- const getBorderRadius = ({ prop, value, selector }, { mode }) => {
348
- const values = value.trim().split(/\s(?![^()]*\))/)
349
- if (values.length === 1) {
350
- verifyValues({ prop, value, selector }, false)
351
- return { prop, value }
352
- } else {
353
- if (values.length === 2) {
354
- values.push(...values)
355
- } else if (values.length === 3) {
356
- values.push(values[1])
357
- }
358
- return formatAbbreviation({ prop, value: values.join(' ') }, { mode })
359
- }
360
- }
361
-
362
369
  // transform 转换
363
370
  const formatTransform = ({ prop, value, selector }, { mode }) => {
364
371
  if (Array.isArray(value)) return { prop, value }
365
- const values = value.trim().split(/\s(?![^()]*\))/)
372
+ const values = parseValues(value)
366
373
  const transform = []
367
374
  values.forEach(item => {
368
375
  const match = item.match(/([/\w]+)\(([^)]+)\)/)
@@ -398,6 +405,10 @@ module.exports = function getSpec ({ warn, error }) {
398
405
  // 2 个以上的值处理
399
406
  key = key.replace('3d', '')
400
407
  const vals = val.split(',').splice(0, key === 'rotate' ? 4 : 3)
408
+ // scale(.5) === scaleX(.5) scaleY(.5)
409
+ if (vals.length === 1 && key === 'scale') {
410
+ vals.push(vals[0])
411
+ }
401
412
  const xyz = ['X', 'Y', 'Z']
402
413
  transform.push(...vals.map((v, index) => {
403
414
  if (key !== 'rotate' && index > 1) {
@@ -429,7 +440,7 @@ module.exports = function getSpec ({ warn, error }) {
429
440
  }
430
441
 
431
442
  const getIntegersFlex = ({ prop, value, selector }) => {
432
- if (isNumber(value) && value >= 0) {
443
+ if ((isNumber(value) && value >= 0) || cssVariableExp.test(value)) {
433
444
  return { prop, value }
434
445
  } else {
435
446
  error(`Value of [${prop}] in ${selector} accepts any floating point value >= 0, received [${value}], please check again!`)
@@ -438,7 +449,7 @@ module.exports = function getSpec ({ warn, error }) {
438
449
  }
439
450
 
440
451
  const formatFlex = ({ prop, value, selector }) => {
441
- let values = value.trim().split(/\s(?![^()]*\))/)
452
+ let values = parseValues(value)
442
453
  if (values.length > 3) {
443
454
  error(`Value of [flex] in ${selector} supports up to three values, received [${value}], please check again!`)
444
455
  values = values.splice(0, 3)
@@ -461,14 +472,14 @@ module.exports = function getSpec ({ warn, error }) {
461
472
  }
462
473
  // 最后一个值是flexBasis 的有效值(auto或者有单位百分比、px等)
463
474
  // flex 0 1 auto flex auto flex 1 auto flex 1 30px flex 1 10% flex 1 1 auto
464
- if (!isNumber(lastOne)) {
475
+ if (!isNumber(lastOne) || !cssVariableExp.test(value)) {
465
476
  // 添加 grow 和 shrink
466
477
  // 在设置 flex basis 有效值的场景下,如果没有设置 grow 和 shrink,则默认为1
467
478
  // 单值 flex: 1 1 <flex-basis>
468
479
  // 双值 flex: <flex-grow> 1 <flex-basis>
469
480
  // 三值 flex: <flex-grow> <flex-shrink> <flex-basis>
470
481
  for (let i = 0; i < 2; i++) {
471
- const item = getIntegersFlex({ prop: AbbreviationMap[prop][i], value: isNumber(values[i]) ? values[i] : 1 })
482
+ const item = getIntegersFlex({ prop: AbbreviationMap[prop][i], value: isNumber(values[i]) || cssVariableExp.test(value) ? values[i] : 1 })
472
483
  item && cssMap.push(item)
473
484
  }
474
485
  if (!isAuto) {
@@ -531,15 +542,10 @@ module.exports = function getSpec ({ warn, error }) {
531
542
  ios: checkBackgroundImage,
532
543
  android: checkBackgroundImage
533
544
  },
534
- {
535
- test: 'border-radius',
536
- ios: getBorderRadius,
537
- android: getBorderRadius
538
- },
539
545
  { // margin padding 内外边距的处理
540
- test: /^(margin|padding)$/,
541
- ios: formatMargins,
542
- android: formatMargins
546
+ test: /^(margin|padding|border-radius|border-width|border-color)$/,
547
+ ios: formatCompositeVal,
548
+ android: formatCompositeVal
543
549
  },
544
550
  { // line-height 换算
545
551
  test: 'line-height',
@@ -5,6 +5,7 @@ const normalizeComponentRules = require('../normalize-component-rules')
5
5
  const isValidIdentifierStr = require('../../../utils/is-valid-identifier-str')
6
6
  const { parseMustacheWithContext, stringifyWithResolveComputed } = require('../../../template-compiler/compiler')
7
7
  const normalize = require('../../../utils/normalize')
8
+ const { dash2hump } = require('../../../utils/hump-dash')
8
9
 
9
10
  module.exports = function getSpec ({ warn, error }) {
10
11
  const spec = {
@@ -301,9 +302,7 @@ module.exports = function getSpec ({ warn, error }) {
301
302
  const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'ali' })
302
303
  const rEventName = runRules(eventRules, eventName, { mode: 'ali' })
303
304
  return {
304
- name: rPrefix + rEventName.replace(/^./, (matched) => {
305
- return matched.toUpperCase()
306
- }) + modifierStr,
305
+ name: dash2hump(rPrefix + '-' + rEventName) + modifierStr,
307
306
  value
308
307
  }
309
308
  },
@@ -312,8 +311,9 @@ module.exports = function getSpec ({ warn, error }) {
312
311
  const prefix = match[1]
313
312
  const eventName = match[2]
314
313
  const modifierStr = match[3] || ''
315
- const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'swan' })
314
+ let rPrefix = runRules(spec.event.prefix, prefix, { mode: 'swan' })
316
315
  const rEventName = runRules(eventRules, eventName, { mode: 'swan' })
316
+ if (rEventName.includes('-')) rPrefix += ':'
317
317
  return {
318
318
  name: rPrefix + rEventName + modifierStr,
319
319
  value
@@ -324,8 +324,9 @@ module.exports = function getSpec ({ warn, error }) {
324
324
  const prefix = match[1]
325
325
  const eventName = match[2]
326
326
  const modifierStr = match[3] || ''
327
- const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'qq' })
327
+ let rPrefix = runRules(spec.event.prefix, prefix, { mode: 'qq' })
328
328
  const rEventName = runRules(eventRules, eventName, { mode: 'qq' })
329
+ if (rEventName.includes('-')) rPrefix += ':'
329
330
  return {
330
331
  name: rPrefix + rEventName + modifierStr,
331
332
  value
@@ -336,8 +337,9 @@ module.exports = function getSpec ({ warn, error }) {
336
337
  const prefix = match[1]
337
338
  const eventName = match[2]
338
339
  const modifierStr = match[3] || ''
339
- const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'jd' })
340
+ let rPrefix = runRules(spec.event.prefix, prefix, { mode: 'jd' })
340
341
  const rEventName = runRules(eventRules, eventName, { mode: 'jd' })
342
+ if (rEventName.includes('-')) rPrefix += ':'
341
343
  return {
342
344
  name: rPrefix + rEventName + modifierStr,
343
345
  value
@@ -360,8 +362,9 @@ module.exports = function getSpec ({ warn, error }) {
360
362
  const prefix = match[1]
361
363
  const eventName = match[2]
362
364
  const modifierStr = match[3] || ''
363
- const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'tt' })
365
+ let rPrefix = runRules(spec.event.prefix, prefix, { mode: 'tt' })
364
366
  const rEventName = runRules(eventRules, eventName, { mode: 'tt' })
367
+ if (rEventName.includes('-')) rPrefix += ':'
365
368
  return {
366
369
  name: rPrefix + rEventName + modifierStr,
367
370
  value
@@ -372,8 +375,9 @@ module.exports = function getSpec ({ warn, error }) {
372
375
  const prefix = match[1]
373
376
  const eventName = match[2]
374
377
  const modifierStr = match[3] || ''
375
- const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'dd' })
378
+ let rPrefix = runRules(spec.event.prefix, prefix, { mode: 'dd' })
376
379
  const rEventName = runRules(eventRules, eventName, { mode: 'dd' })
380
+ if (rEventName.includes('-')) rPrefix += ':'
377
381
  return {
378
382
  name: rPrefix + rEventName + modifierStr,
379
383
  value
@@ -27,7 +27,8 @@ module.exports = function (template, {
27
27
  decodeHTMLText,
28
28
  externalClasses,
29
29
  checkUsingComponents,
30
- autoVirtualHostRules
30
+ autoVirtualHostRules,
31
+ customTextRules
31
32
  } = mpx
32
33
  const { resourcePath } = parseRequest(loaderContext.resource)
33
34
  const builtInComponentsMap = {}
@@ -84,7 +85,8 @@ module.exports = function (template, {
84
85
  globalComponents: [],
85
86
  // web模式下实现抽象组件
86
87
  componentGenerics,
87
- hasVirtualHost: matchCondition(resourcePath, autoVirtualHostRules)
88
+ hasVirtualHost: matchCondition(resourcePath, autoVirtualHostRules),
89
+ isCustomText: matchCondition(resourcePath, customTextRules)
88
90
  })
89
91
 
90
92
  if (meta.wxsContentMap) {
@@ -20,11 +20,8 @@ function getClassMap ({ content, filename, mode, srcMode, warn, error }) {
20
20
  if ((matched = numberRegExp.exec(value))) {
21
21
  value = matched[1]
22
22
  needStringify = false
23
- } else if ((matched = unitRegExp.exec(value))) {
24
- value = `global.__unit.${matched[2]}(${matched[1]})`
25
- needStringify = false
26
- } else if (hairlineRegExp.test(value)) {
27
- value = 'global.__hairlineWidth'
23
+ } else if (unitRegExp.test(value) || hairlineRegExp.test(value)) {
24
+ value = `global.__formatValue(${JSON.stringify(value)})`
28
25
  needStringify = false
29
26
  }
30
27
  return needStringify ? JSON.stringify(value) : value
@@ -25,6 +25,12 @@ export interface FormContextValue {
25
25
  reset: () => void
26
26
  }
27
27
 
28
+ export interface IntersectionObserver {
29
+ [key: number]: {
30
+ throttleMeasure: () => void
31
+ }
32
+ }
33
+
28
34
  export const MovableAreaContext = createContext({ width: 0, height: 0 })
29
35
 
30
36
  export const FormContext = createContext<FormContextValue | null>(null)
@@ -38,3 +44,5 @@ export const LabelContext = createContext<LabelContextValue | null>(null)
38
44
  export const PickerContext = createContext(null)
39
45
 
40
46
  export const VarContext = createContext({})
47
+
48
+ export const IntersectionObserverContext = createContext<IntersectionObserver | null>(null)
@@ -6,3 +6,4 @@ export const RadioGroupContext = createContext(null);
6
6
  export const LabelContext = createContext(null);
7
7
  export const PickerContext = createContext(null);
8
8
  export const VarContext = createContext({});
9
+ export const IntersectionObserverContext = createContext(null);
@@ -179,7 +179,8 @@ const Button = forwardRef((buttonProps, ref) => {
179
179
  ...(applyHoverEffect && hoverStyle)
180
180
  };
181
181
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
182
- const { nodeRef } = useNodesRef(props, ref, { defaultStyle });
182
+ const nodeRef = useRef(null);
183
+ useNodesRef(props, ref, nodeRef, { defaultStyle });
183
184
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
184
185
  const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle);
185
186
  if (backgroundStyle) {
@@ -25,7 +25,8 @@ const CheckboxGroup = forwardRef((props, ref) => {
25
25
  ...style
26
26
  };
27
27
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
28
- const { nodeRef } = useNodesRef(props, ref, { defaultStyle });
28
+ const nodeRef = useRef(null);
29
+ useNodesRef(props, ref, nodeRef, { defaultStyle });
29
30
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
30
31
  const getSelectionValue = () => {
31
32
  const arr = [];
@@ -4,7 +4,7 @@
4
4
  * ✔ checked
5
5
  * ✔ color
6
6
  */
7
- import { useState, forwardRef, useEffect, useContext } from 'react';
7
+ import { useState, useRef, forwardRef, useEffect, useContext } from 'react';
8
8
  import { View, StyleSheet } from 'react-native';
9
9
  import { warn } from '@mpxjs/utils';
10
10
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
@@ -76,7 +76,8 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
76
76
  onChange(evt);
77
77
  };
78
78
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
79
- const { nodeRef } = useNodesRef(props, ref, {
79
+ const nodeRef = useRef(null);
80
+ useNodesRef(props, ref, nodeRef, {
80
81
  defaultStyle,
81
82
  change: onChange
82
83
  });
@@ -16,7 +16,8 @@ const _Form = forwardRef((fromProps, ref) => {
16
16
  const { style, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
17
17
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
18
18
  const { textStyle, innerStyle } = splitStyle(normalStyle);
19
- const { nodeRef: formRef } = useNodesRef(props, ref);
19
+ const formRef = useRef(null);
20
+ useNodesRef(props, ref, formRef);
20
21
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: formRef });
21
22
  const submit = () => {
22
23
  const { bindsubmit } = props;
@@ -3,7 +3,7 @@
3
3
  * ✔ size
4
4
  * ✔ color
5
5
  */
6
- import { forwardRef } from 'react';
6
+ import { forwardRef, useRef } from 'react';
7
7
  import { Image } from 'react-native';
8
8
  import useInnerProps from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
@@ -28,7 +28,8 @@ const Icon = forwardRef((props, ref) => {
28
28
  ...style
29
29
  };
30
30
  const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
31
- const { nodeRef } = useNodesRef(props, ref, { defaultStyle });
31
+ const nodeRef = useRef(null);
32
+ useNodesRef(props, ref, nodeRef, { defaultStyle });
32
33
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
33
34
  const innerProps = useInnerProps(props, {
34
35
  ref: nodeRef,
@@ -67,7 +67,8 @@ const Image = forwardRef((props, ref) => {
67
67
  ...style,
68
68
  overflow: 'hidden'
69
69
  };
70
- const { nodeRef } = useNodesRef(props, ref, {
70
+ const nodeRef = useRef(null);
71
+ useNodesRef(props, ref, nodeRef, {
71
72
  defaultStyle
72
73
  });
73
74
  const onLayout = ({ nativeEvent: { layout: { width, height } } }) => {
@@ -79,7 +79,8 @@ const Input = forwardRef((props, ref) => {
79
79
  }
80
80
  };
81
81
  const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
82
- const { nodeRef } = useNodesRef(props, ref);
82
+ const nodeRef = useRef(null);
83
+ useNodesRef(props, ref, nodeRef);
83
84
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
84
85
  useEffect(() => {
85
86
  if (inputValue !== value) {
@@ -19,7 +19,8 @@ const Label = forwardRef((labelProps, ref) => {
19
19
  ...style
20
20
  };
21
21
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
22
- const { nodeRef } = useNodesRef(props, ref, { defaultStyle });
22
+ const nodeRef = useRef(null);
23
+ useNodesRef(props, ref, nodeRef, { defaultStyle });
23
24
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
24
25
  const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle);
25
26
  if (backgroundStyle) {