@mpxjs/webpack-plugin 2.9.62 → 2.9.65

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 (95) hide show
  1. package/lib/config.js +38 -10
  2. package/lib/index.js +1 -3
  3. package/lib/platform/style/wx/index.js +115 -66
  4. package/lib/platform/template/wx/index.js +12 -8
  5. package/lib/react/processStyles.js +1 -0
  6. package/lib/react/processTemplate.js +2 -3
  7. package/lib/react/style-helper.js +9 -7
  8. package/lib/runtime/components/react/context.ts +9 -7
  9. package/lib/runtime/components/react/dist/context.js +1 -0
  10. package/lib/runtime/components/react/dist/getInnerListeners.js +12 -1
  11. package/lib/runtime/components/react/dist/mpx-button.jsx +53 -74
  12. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +20 -18
  13. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +30 -42
  14. package/lib/runtime/components/react/dist/mpx-form.jsx +18 -15
  15. package/lib/runtime/components/react/dist/mpx-icon.jsx +15 -17
  16. package/lib/runtime/components/react/dist/mpx-image/index.jsx +36 -34
  17. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -1
  18. package/lib/runtime/components/react/dist/mpx-input.jsx +36 -31
  19. package/lib/runtime/components/react/dist/mpx-label.jsx +30 -37
  20. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +15 -19
  21. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +10 -9
  22. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +2 -1
  23. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -10
  24. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +9 -5
  25. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +13 -8
  26. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +3 -2
  27. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +22 -20
  28. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +103 -10
  29. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +149 -54
  30. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +20 -18
  31. package/lib/runtime/components/react/dist/mpx-radio.jsx +29 -43
  32. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +8 -4
  33. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +36 -27
  34. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +141 -75
  35. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +16 -7
  36. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +20 -11
  37. package/lib/runtime/components/react/dist/mpx-switch.jsx +18 -14
  38. package/lib/runtime/components/react/dist/mpx-text.jsx +20 -35
  39. package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
  40. package/lib/runtime/components/react/dist/mpx-view.jsx +296 -210
  41. package/lib/runtime/components/react/dist/mpx-web-view.jsx +11 -7
  42. package/lib/runtime/components/react/dist/parser.js +218 -0
  43. package/lib/runtime/components/react/dist/useNodesRef.js +1 -5
  44. package/lib/runtime/components/react/dist/utils.jsx +445 -0
  45. package/lib/runtime/components/react/getInnerListeners.ts +18 -8
  46. package/lib/runtime/components/react/mpx-button.tsx +83 -91
  47. package/lib/runtime/components/react/mpx-checkbox-group.tsx +50 -43
  48. package/lib/runtime/components/react/mpx-checkbox.tsx +56 -64
  49. package/lib/runtime/components/react/mpx-form.tsx +51 -22
  50. package/lib/runtime/components/react/mpx-icon.tsx +31 -27
  51. package/lib/runtime/components/react/mpx-image/index.tsx +54 -47
  52. package/lib/runtime/components/react/mpx-image/svg.tsx +5 -3
  53. package/lib/runtime/components/react/mpx-input.tsx +59 -38
  54. package/lib/runtime/components/react/mpx-label.tsx +55 -59
  55. package/lib/runtime/components/react/mpx-movable-area.tsx +40 -25
  56. package/lib/runtime/components/react/mpx-movable-view.tsx +29 -29
  57. package/lib/runtime/components/react/mpx-navigator.tsx +2 -2
  58. package/lib/runtime/components/react/mpx-picker/date.tsx +4 -4
  59. package/lib/runtime/components/react/mpx-picker/index.tsx +12 -11
  60. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +17 -13
  61. package/lib/runtime/components/react/mpx-picker/region.tsx +23 -19
  62. package/lib/runtime/components/react/mpx-picker/selector.tsx +7 -7
  63. package/lib/runtime/components/react/mpx-picker/time.tsx +29 -31
  64. package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
  65. package/lib/runtime/components/react/mpx-picker-view-column.tsx +149 -20
  66. package/lib/runtime/components/react/mpx-picker-view.tsx +180 -63
  67. package/lib/runtime/components/react/mpx-radio-group.tsx +51 -47
  68. package/lib/runtime/components/react/mpx-radio.tsx +57 -72
  69. package/lib/runtime/components/react/mpx-root-portal.tsx +10 -8
  70. package/lib/runtime/components/react/mpx-scroll-view.tsx +136 -104
  71. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +175 -96
  72. package/lib/runtime/components/react/mpx-swiper/index.tsx +21 -9
  73. package/lib/runtime/components/react/mpx-swiper/type.ts +16 -5
  74. package/lib/runtime/components/react/mpx-swiper-item.tsx +48 -14
  75. package/lib/runtime/components/react/mpx-switch.tsx +46 -24
  76. package/lib/runtime/components/react/mpx-text.tsx +38 -45
  77. package/lib/runtime/components/react/mpx-textarea.tsx +1 -1
  78. package/lib/runtime/components/react/mpx-view.tsx +401 -241
  79. package/lib/runtime/components/react/mpx-web-view.tsx +22 -22
  80. package/lib/runtime/components/react/parser.ts +245 -0
  81. package/lib/runtime/components/react/types/common.ts +4 -4
  82. package/lib/runtime/components/react/types/global.d.ts +24 -2
  83. package/lib/runtime/components/react/useNodesRef.ts +1 -7
  84. package/lib/runtime/components/react/utils.tsx +524 -0
  85. package/lib/runtime/components/web/mpx-scroll-view.vue +25 -5
  86. package/lib/style-compiler/index.js +5 -4
  87. package/lib/template-compiler/compiler.js +133 -161
  88. package/lib/template-compiler/gen-node-react.js +1 -3
  89. package/lib/utils/const.js +2 -1
  90. package/lib/web/processStyles.js +2 -1
  91. package/lib/web/processTemplate.js +2 -3
  92. package/lib/wxml/loader.js +1 -1
  93. package/package.json +7 -4
  94. package/lib/runtime/components/react/dist/utils.js +0 -148
  95. package/lib/runtime/components/react/utils.ts +0 -170
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
@@ -1812,7 +1812,6 @@ try {
1812
1812
  }
1813
1813
 
1814
1814
  if (isWeb(mpx.mode)) {
1815
- const mpxStyleOptions = queryObj.mpxStyleOptions
1816
1815
  const firstLoader = loaders[0] ? toPosix(loaders[0].loader) : ''
1817
1816
  const isPitcherRequest = firstLoader.includes('node_modules/vue-loader/lib/loaders/pitcher')
1818
1817
  let cssLoaderIndex = -1
@@ -1837,8 +1836,7 @@ try {
1837
1836
  }
1838
1837
  if (loaderIndex > -1) {
1839
1838
  loaders.splice(loaderIndex + 1, 0, {
1840
- loader: styleCompilerPath,
1841
- options: (mpxStyleOptions && JSON.parse(mpxStyleOptions)) || {}
1839
+ loader: styleCompilerPath
1842
1840
  })
1843
1841
  }
1844
1842
  }
@@ -9,16 +9,21 @@ module.exports = function getSpec ({ warn, error }) {
9
9
  // React Native android 不支持的 CSS property
10
10
  android: /^(text-decoration-style|text-decoration-color|shadow-offset|shadow-opacity|shadow-radius)$/
11
11
  }
12
+ // var(xx)
13
+ const cssVariableExp = /var\(/
14
+ // calc(xx)
15
+ const calcExp = /calc\(/
16
+ const envExp = /env\(/
12
17
  // 不支持的属性提示
13
- const unsupportedPropError = ({ prop, mode }) => {
14
- error(`Property [${prop}] is not supported in React Native ${mode} environment!`)
18
+ const unsupportedPropError = ({ prop, value, selector }, { mode }, isError = true) => {
19
+ const tips = isError ? error : warn
20
+ tips(`Property [${prop}] on ${selector} is not supported in ${mode} environment!`)
15
21
  }
16
22
  // prop 校验
17
- const verifyProps = ({ prop, value }, { mode }, isError = true) => {
23
+ const verifyProps = ({ prop, value, selector }, { mode }, isError = true) => {
18
24
  prop = prop.trim()
19
- const tips = isError ? error : warn
20
25
  if (unsupportedPropExp.test(prop) || unsupportedPropMode[mode].test(prop)) {
21
- tips(`Property [${prop}] is not supported in React Native ${mode} environment!`)
26
+ unsupportedPropError({ prop, value, selector }, { mode }, isError)
22
27
  return false
23
28
  }
24
29
  return true
@@ -81,28 +86,67 @@ module.exports = function getSpec ({ warn, error }) {
81
86
  if (rule[1].test(prop)) return rule[0]
82
87
  }
83
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
+ // }
84
119
  // 属性值校验
85
- const verifyValues = ({ prop, value }, isError = true) => {
120
+ const verifyValues = ({ prop, value, selector }, isError = true) => {
86
121
  prop = prop.trim()
87
122
  value = value.trim()
88
- const type = getValueType(prop)
123
+ const tips = isError ? error : warn
124
+ if (cssVariableExp.test(value) || calcExp.test(value) || envExp.test(value)) return true
89
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']
90
126
  const valueExp = {
91
- number: /^(-?\d+(\.\d+)?)(rpx|px|%)?$/,
127
+ number: /^((-?(\d+(\.\d+)?|\.\d+))(rpx|px|%|vw|vh)?|hairlineWidth)$/,
92
128
  color: new RegExp(('^(' + namedColor.join('|') + ')$') + '|(^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$)|^(rgb|rgba|hsl|hsla|hwb)\\(.+\\)$')
93
129
  }
94
- const tips = isError ? error : warn
130
+ const type = getValueType(prop)
131
+ const tipsType = (type) => {
132
+ const info = {
133
+ [ValueType.number]: '2rpx,10%,30rpx',
134
+ [ValueType.color]: 'rgb,rgba,hsl,hsla,hwb,named color,#000000',
135
+ [ValueType.enum]: `${SUPPORTED_PROP_VAL_ARR[prop]?.join(',')}`
136
+ }
137
+ tips(`Value of ${prop} in ${selector} should be ${type}, eg ${info[type]}, received [${value}], please check again!`)
138
+ }
95
139
  switch (type) {
96
140
  case ValueType.number: {
97
141
  if (!valueExp.number.test(value)) {
98
- tips(`The value type of [${prop}] only supports [Number] in React Native environment, eg 10rpx, 10px, 10%, 10, please check again`)
142
+ tipsType(type)
99
143
  return false
100
144
  }
101
145
  return true
102
146
  }
103
147
  case ValueType.color: {
104
148
  if (!valueExp.color.test(value)) {
105
- tips(`The value type of [${prop}] only supports [Color] in React Native environment, eg #000, rgba(0,0,0,0), please check again`)
149
+ tipsType(type)
106
150
  return false
107
151
  }
108
152
  return true
@@ -111,7 +155,7 @@ module.exports = function getSpec ({ warn, error }) {
111
155
  const isIn = SUPPORTED_PROP_VAL_ARR[prop].includes(value)
112
156
  const isType = Object.keys(valueExp).some(item => valueExp[item].test(value) && SUPPORTED_PROP_VAL_ARR[prop].includes(ValueType[item]))
113
157
  if (!isIn && !isType) {
114
- tips(`Property [${prop}] only support value [${SUPPORTED_PROP_VAL_ARR[prop]?.join(',')}] in React Native environment, the value [${value}] does not support!`)
158
+ tipsType(type)
115
159
  return false
116
160
  }
117
161
  return true
@@ -120,8 +164,8 @@ module.exports = function getSpec ({ warn, error }) {
120
164
  return true
121
165
  }
122
166
  // prop & value 校验:过滤的不合法的属性和属性值
123
- const verification = ({ prop, value }, { mode }) => {
124
- return verifyProps({ prop, value }, { mode }) && verifyValues({ prop, value }) && ({ prop, value })
167
+ const verification = ({ prop, value, selector }, { mode }) => {
168
+ return verifyProps({ prop, value, selector }, { mode }) && verifyValues({ prop, value, selector }) && ({ prop, value })
125
169
  }
126
170
 
127
171
  // 简写转换规则
@@ -148,10 +192,10 @@ module.exports = function getSpec ({ warn, error }) {
148
192
  'flex-flow': ['flexDirection', 'flexWrap'],
149
193
  'border-radius': ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius']
150
194
  }
151
- const formatAbbreviation = ({ prop, value }, { mode }) => {
195
+ const formatAbbreviation = ({ prop, value, selector }, { mode }) => {
152
196
  const original = `${prop}:${value}`
153
197
  const props = AbbreviationMap[prop]
154
- const values = value.trim().split(/\s(?![^()]*\))/)
198
+ const values = parseValues(value)
155
199
  const cssMap = []
156
200
  let idx = 0
157
201
  let propsIdx = 0
@@ -159,12 +203,12 @@ module.exports = function getSpec ({ warn, error }) {
159
203
  while (idx < values.length) {
160
204
  const prop = props[propsIdx]
161
205
  if (!prop) {
162
- error(`the value of [${original}] has not enough props to assign in React Native environment, please check again`)
206
+ warn(`Value of [${original}] in ${selector} has not enough props to assign, please check again!`)
163
207
  break
164
208
  }
165
209
  const value = values[idx]
166
210
  const newProp = hump2dash(prop.replace(/\..+/, ''))
167
- if (!verifyProps({ prop: newProp, value }, { mode }, diff === 0)) {
211
+ if (!verifyProps({ prop: newProp, value, selector }, { mode }, diff === 0)) {
168
212
  // 有 ios or android 不支持的 prop,跳过 prop
169
213
  if (diff === 0) {
170
214
  propsIdx++
@@ -172,7 +216,7 @@ module.exports = function getSpec ({ warn, error }) {
172
216
  } else {
173
217
  propsIdx++
174
218
  }
175
- } else if (!verifyValues({ prop: newProp, value }, diff === 0)) {
219
+ } else if (!verifyValues({ prop: newProp, value, selector }, diff === 0)) {
176
220
  // 值不合法 跳过 value
177
221
  if (diff === 0) {
178
222
  propsIdx++
@@ -212,8 +256,8 @@ module.exports = function getSpec ({ warn, error }) {
212
256
  }
213
257
 
214
258
  // margin padding
215
- const formatMargins = ({ prop, value }) => {
216
- const values = value.trim().split(/\s(?![^()]*\))/)
259
+ const formatMargins = ({ prop, value, selector }) => {
260
+ const values = parseValues(value)
217
261
  // format
218
262
  let suffix = []
219
263
  switch (values.length) {
@@ -231,7 +275,7 @@ module.exports = function getSpec ({ warn, error }) {
231
275
  return values.map((value, index) => {
232
276
  const newProp = `${prop}${suffix[index] || ''}`
233
277
  // validate
234
- verifyValues({ prop: hump2dash(newProp), value }, false)
278
+ verifyValues({ prop: hump2dash(newProp), value, selector }, false)
235
279
  return {
236
280
  prop: newProp,
237
281
  value: value
@@ -240,17 +284,17 @@ module.exports = function getSpec ({ warn, error }) {
240
284
  }
241
285
 
242
286
  // line-height
243
- const formatLineHeight = ({ prop, value }) => {
244
- return verifyValues({ prop, value }) && ({
287
+ const formatLineHeight = ({ prop, value, selector }) => {
288
+ return verifyValues({ prop, value, selector }) && ({
245
289
  prop,
246
- value: /^\s*-?\d+(\.\d+)?\s*$/.test(value) ? `${Math.round(value * 100)}%` : value
290
+ value: /^\s*(-?(\d+(\.\d+)?|\.\d+))\s*$/.test(value) ? `${Math.round(value * 100)}%` : value
247
291
  })
248
292
  }
249
293
 
250
294
  // background 相关属性的转换 Todo
251
295
  // 仅支持以下属性,不支持其他背景相关的属性
252
296
  // /^((?!(-color)).)*background((?!(-color)).)*$/ 包含background且不包含background-color
253
- const checkBackgroundImage = ({ prop, value }, { mode }) => {
297
+ const checkBackgroundImage = ({ prop, value, selector }, { mode }) => {
254
298
  const bgPropMap = {
255
299
  image: 'background-image',
256
300
  color: 'background-color',
@@ -260,17 +304,18 @@ module.exports = function getSpec ({ warn, error }) {
260
304
  all: 'background'
261
305
  }
262
306
  const urlExp = /url\(["']?(.*?)["']?\)/
307
+ const linerExp = /linear-gradient\(.*\)\s*$/
263
308
  switch (prop) {
264
309
  case bgPropMap.image: {
265
310
  // background-image 仅支持背景图
266
311
  const imgUrl = value.match(urlExp)?.[0]
267
- if (/.*linear-gradient*./.test(value)) {
268
- error(`<linear-gradient()> is not supported in React Native ${mode} environment!`)
269
- }
312
+ const linerVal = value.match(linerExp)?.[0]
270
313
  if (imgUrl) {
271
314
  return { prop, value: imgUrl }
315
+ } else if (linerVal) {
316
+ return { prop, value: linerVal }
272
317
  } else {
273
- error(`[${prop}] only support value <url()>`)
318
+ error(`Value of ${prop} in ${selector} selector only support value <url()> or <linear-gradient()>, received ${value}, please check again!`)
274
319
  return false
275
320
  }
276
321
  }
@@ -279,13 +324,13 @@ module.exports = function getSpec ({ warn, error }) {
279
324
  // 不支持逗号分隔的多个值:设置多重背景!!!
280
325
  // 支持一个值:这个值指定图片的宽度,图片的高度隐式的为 auto
281
326
  // 支持两个值:第一个值指定图片的宽度,第二个值指定图片的高度
282
- if (value.includes(',')) { // commas are not allowed in values
283
- error(`background size value[${value}] does not support commas in React Native ${mode} environment!`)
327
+ if (parseValues(value, ',').length > 1) { // commas are not allowed in values
328
+ error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
284
329
  return false
285
330
  }
286
331
  const values = []
287
- value.trim().split(/\s(?![^()]*\))/).forEach(item => {
288
- if (verifyValues({ prop, value: item })) {
332
+ parseValues(value).forEach(item => {
333
+ if (verifyValues({ prop, value: item, selector })) {
289
334
  // 支持 number 值 / container cover auto 枚举
290
335
  values.push(item)
291
336
  }
@@ -295,45 +340,45 @@ module.exports = function getSpec ({ warn, error }) {
295
340
  }
296
341
  case bgPropMap.position: {
297
342
  const values = []
298
- value.trim().split(/\s(?![^()]*\))/).forEach(item => {
299
- if (verifyValues({ prop, value: item })) {
343
+ parseValues(value).forEach(item => {
344
+ if (verifyValues({ prop, value: item, selector })) {
300
345
  // 支持 number 值 / 枚举, center与50%等价
301
346
  values.push(item === 'center' ? '50%' : item)
302
347
  } else {
303
- error(`background position value[${value}] does not support in React Native ${mode} environment!`)
348
+ error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
304
349
  }
305
350
  })
306
-
307
351
  return { prop, value: values }
308
352
  }
309
353
  case bgPropMap.all: {
310
354
  // background: 仅支持 background-image & background-color & background-repeat
311
355
  const bgMap = []
312
- const values = value.trim().split(/\s(?![^()]*\))/)
356
+ const values = parseValues(value)
313
357
  values.forEach(item => {
314
358
  const url = item.match(urlExp)?.[0]
315
- if (/.*linear-gradient*./.test(item)) {
316
- error(`<linear-gradient()> is not supported in React Native ${mode} environment!`)
317
- } else if (url) {
359
+ const linerVal = item.match(linerExp)?.[0]
360
+ if (url) {
318
361
  bgMap.push({ prop: bgPropMap.image, value: url })
362
+ } else if (linerVal) {
363
+ bgMap.push({ prop: bgPropMap.image, value: linerVal })
319
364
  } else if (verifyValues({ prop: bgPropMap.color, value: item }, false)) {
320
365
  bgMap.push({ prop: bgPropMap.color, value: item })
321
- } else if (verifyValues({ prop: bgPropMap.repeat, value: item }, false)) {
366
+ } else if (verifyValues({ prop: bgPropMap.repeat, value: item, selector }, false)) {
322
367
  bgMap.push({ prop: bgPropMap.repeat, value: item })
323
368
  }
324
369
  })
325
370
  return bgMap.length ? bgMap : false
326
371
  }
327
372
  }
328
- unsupportedPropError({ prop, mode })
373
+ unsupportedPropError({ prop, value, selector }, { mode })
329
374
  return false
330
375
  }
331
376
 
332
377
  // border-radius 缩写转换
333
- const getBorderRadius = ({ prop, value }, { mode }) => {
334
- const values = value.trim().split(/\s(?![^()]*\))/)
378
+ const getBorderRadius = ({ prop, value, selector }, { mode }) => {
379
+ const values = parseValues(value)
335
380
  if (values.length === 1) {
336
- verifyValues({ prop, value }, false)
381
+ verifyValues({ prop, value, selector }, false)
337
382
  return { prop, value }
338
383
  } else {
339
384
  if (values.length === 2) {
@@ -346,9 +391,9 @@ module.exports = function getSpec ({ warn, error }) {
346
391
  }
347
392
 
348
393
  // transform 转换
349
- const formatTransform = ({ prop, value }, { mode }) => {
394
+ const formatTransform = ({ prop, value, selector }, { mode }) => {
350
395
  if (Array.isArray(value)) return { prop, value }
351
- const values = value.trim().split(/\s(?![^()]*\))/)
396
+ const values = parseValues(value)
352
397
  const transform = []
353
398
  values.forEach(item => {
354
399
  const match = item.match(/([/\w]+)\(([^)]+)\)/)
@@ -384,10 +429,14 @@ module.exports = function getSpec ({ warn, error }) {
384
429
  // 2 个以上的值处理
385
430
  key = key.replace('3d', '')
386
431
  const vals = val.split(',').splice(0, key === 'rotate' ? 4 : 3)
432
+ // scale(.5) === scaleX(.5) scaleY(.5)
433
+ if (vals.length === 1 && key === 'scale') {
434
+ vals.push(vals[0])
435
+ }
387
436
  const xyz = ['X', 'Y', 'Z']
388
437
  transform.push(...vals.map((v, index) => {
389
438
  if (key !== 'rotate' && index > 1) {
390
- unsupportedPropError({ prop: `${key}Z`, mode })
439
+ unsupportedPropError({ prop: `${key}Z`, value, selector }, { mode })
391
440
  }
392
441
  return { [`${key}${xyz[index] || ''}`]: v.trim() }
393
442
  }))
@@ -397,11 +446,11 @@ module.exports = function getSpec ({ warn, error }) {
397
446
  case 'scaleZ':
398
447
  default:
399
448
  // 不支持的属性处理
400
- unsupportedPropError({ prop: key, mode })
449
+ unsupportedPropError({ prop, value, selector }, { mode })
401
450
  break
402
451
  }
403
452
  } else {
404
- error(`Property [${prop}] is invalid, please check the value!`)
453
+ error(`Property [${prop}] is invalid in ${selector}, received [${value}], please check again!`)
405
454
  }
406
455
  })
407
456
  return {
@@ -414,19 +463,19 @@ module.exports = function getSpec ({ warn, error }) {
414
463
  return !isNaN(+value)
415
464
  }
416
465
 
417
- const getIntegersFlex = ({ prop, value }) => {
418
- if (isNumber(value) && value >= 0) {
466
+ const getIntegersFlex = ({ prop, value, selector }) => {
467
+ if ((isNumber(value) && value >= 0) || cssVariableExp.test(value)) {
419
468
  return { prop, value }
420
469
  } else {
421
- error(`The value of ${prop} accepts any floating point value >= 0.`)
470
+ error(`Value of [${prop}] in ${selector} accepts any floating point value >= 0, received [${value}], please check again!`)
422
471
  return false
423
472
  }
424
473
  }
425
474
 
426
- const formatFlex = ({ prop, value }, { mode }) => {
427
- let values = value.trim().split(/\s(?![^()]*\))/)
475
+ const formatFlex = ({ prop, value, selector }) => {
476
+ let values = parseValues(value)
428
477
  if (values.length > 3) {
429
- error('The value of prop [flex] supports up to three values')
478
+ error(`Value of [flex] in ${selector} supports up to three values, received [${value}], please check again!`)
430
479
  values = values.splice(0, 3)
431
480
  }
432
481
  const cssMap = []
@@ -441,20 +490,20 @@ module.exports = function getSpec ({ warn, error }) {
441
490
  // value=initial 则 flexShrink=1,其他场景都是0
442
491
  cssMap.push(...[{ prop: 'flexGrow', value: 0 }, { prop: 'flexShrink', value: +(values[0] === 'initial') }])
443
492
  } else {
444
- error('When setting the value of flex to none or initial, only one value is supported.')
493
+ error(`Value of [${prop}] in ${selector} is invalid, When setting the value of flex to none or initial, only one value is supported.`)
445
494
  }
446
495
  return cssMap
447
496
  }
448
497
  // 最后一个值是flexBasis 的有效值(auto或者有单位百分比、px等)
449
498
  // flex 0 1 auto flex auto flex 1 auto flex 1 30px flex 1 10% flex 1 1 auto
450
- if (!isNumber(lastOne)) {
499
+ if (!isNumber(lastOne) || !cssVariableExp.test(value)) {
451
500
  // 添加 grow 和 shrink
452
501
  // 在设置 flex basis 有效值的场景下,如果没有设置 grow 和 shrink,则默认为1
453
502
  // 单值 flex: 1 1 <flex-basis>
454
503
  // 双值 flex: <flex-grow> 1 <flex-basis>
455
504
  // 三值 flex: <flex-grow> <flex-shrink> <flex-basis>
456
505
  for (let i = 0; i < 2; i++) {
457
- const item = getIntegersFlex({ prop: AbbreviationMap[prop][i], value: isNumber(values[i]) ? values[i] : 1 })
506
+ const item = getIntegersFlex({ prop: AbbreviationMap[prop][i], value: isNumber(values[i]) || cssVariableExp.test(value) ? values[i] : 1 })
458
507
  item && cssMap.push(item)
459
508
  }
460
509
  if (!isAuto) {
@@ -481,25 +530,25 @@ module.exports = function getSpec ({ warn, error }) {
481
530
  return cssMap
482
531
  }
483
532
 
484
- const formatFontFamily = ({ prop, value }) => {
533
+ const formatFontFamily = ({ prop, value, selector }) => {
485
534
  // 去掉引号 取逗号分隔后的第一个
486
535
  const newVal = value.replace(/"|'/g, '').trim()
487
536
  const values = newVal.split(',').filter(i => i)
488
537
  if (!newVal || !values.length) {
489
- error(`The value of prop [${prop}: ${value}] is invaild, please check again`)
538
+ error(`Value of [${prop}] is invalid in ${selector}, received [${value}], please check again!`)
490
539
  return false
491
540
  } else if (values.length > 1) {
492
- warn(`The value of prop [${prop}] only supports one, and the first one is used by default`)
541
+ warn(`Value of [${prop}] only supports one in ${selector}, received [${value}], and the first one is used by default.`)
493
542
  }
494
543
  return { prop, value: values[0].trim() }
495
544
  }
496
545
 
497
- const formatBoxShadow = ({ prop, value }, { mode }) => {
546
+ const formatBoxShadow = ({ prop, value, selector }, { mode }) => {
498
547
  value = value.trim()
499
548
  if (value === 'none') {
500
549
  return false
501
550
  }
502
- const cssMap = formatAbbreviation({ prop, value }, { mode })
551
+ const cssMap = formatAbbreviation({ prop, value, selector }, { mode })
503
552
  if (mode === 'android') return cssMap
504
553
  // ios 阴影需要额外设置 shadowOpacity=1
505
554
  cssMap.push({
@@ -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
@@ -31,6 +31,7 @@ module.exports = function (styles, {
31
31
  scoped,
32
32
  extract: false
33
33
  }
34
+ // todo 建立新的request在内部导出classMap,便于样式模块复用
34
35
  loaderContext.importModule(JSON.parse(getRequestString('styles', style, extraOptions, i))).then((result) => {
35
36
  if (Array.isArray(result)) {
36
37
  result = result.map((item) => {
@@ -113,13 +113,12 @@ module.exports = function (template, {
113
113
  try {
114
114
  const ignoreMap = Object.assign({
115
115
  createElement: true,
116
- getComponent: true,
117
- rootProps: true
116
+ getComponent: true
118
117
  }, meta.wxsModuleMap)
119
118
  const bindResult = bindThis.transform(rawCode, {
120
119
  ignoreMap
121
120
  })
122
- output += `global.currentInject.render = function (createElement, getComponent, rootProps) {
121
+ output += `global.currentInject.render = function (createElement, getComponent) {
123
122
  return ${bindResult.code}
124
123
  };\n`
125
124
  } catch (e) {