@mpxjs/webpack-plugin 2.10.19 → 2.10.21

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 (137) hide show
  1. package/lib/dependencies/ResolveDependency.js +2 -2
  2. package/lib/index.js +38 -7
  3. package/lib/json-compiler/helper.js +11 -10
  4. package/lib/json-compiler/index.js +7 -4
  5. package/lib/json-compiler/plugin.js +4 -4
  6. package/lib/loader.js +4 -4
  7. package/lib/native-loader.js +4 -4
  8. package/lib/parser.js +1 -1
  9. package/lib/platform/create-diagnostic.js +168 -0
  10. package/lib/platform/index.js +16 -3
  11. package/lib/platform/json/wx/index.js +66 -17
  12. package/lib/platform/run-rules.js +9 -5
  13. package/lib/platform/style/wx/index.js +82 -33
  14. package/lib/platform/template/normalize-component-rules.js +7 -9
  15. package/lib/platform/template/wx/component-config/block.js +2 -1
  16. package/lib/platform/template/wx/component-config/custom-built-in-component.js +34 -0
  17. package/lib/platform/template/wx/component-config/index.js +18 -3
  18. package/lib/platform/template/wx/component-config/input.js +1 -7
  19. package/lib/platform/template/wx/component-config/movable-view.js +1 -7
  20. package/lib/platform/template/wx/component-config/text.js +1 -1
  21. package/lib/platform/template/wx/component-config/textarea.js +1 -25
  22. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  23. package/lib/platform/template/wx/index.js +48 -34
  24. package/lib/react/processJSON.js +7 -4
  25. package/lib/react/processStyles.js +22 -8
  26. package/lib/react/processTemplate.js +98 -41
  27. package/lib/react/style-helper.js +121 -86
  28. package/lib/react/template-loader.js +161 -0
  29. package/lib/runtime/components/react/context.ts +8 -1
  30. package/lib/runtime/components/react/dist/context.d.ts +6 -1
  31. package/lib/runtime/components/react/dist/context.js +1 -0
  32. package/lib/runtime/components/react/dist/getInnerListeners.js +1 -0
  33. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +1 -1
  34. package/lib/runtime/components/react/dist/mpx-button.d.ts +1 -1
  35. package/lib/runtime/components/react/dist/mpx-button.jsx +6 -5
  36. package/lib/runtime/components/react/dist/mpx-camera.jsx +1 -0
  37. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +4 -1
  38. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -1
  39. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +6 -4
  40. package/lib/runtime/components/react/dist/mpx-form.jsx +3 -3
  41. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +5 -1
  42. package/lib/runtime/components/react/dist/mpx-image.d.ts +3 -3
  43. package/lib/runtime/components/react/dist/mpx-image.jsx +45 -12
  44. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +10 -6
  45. package/lib/runtime/components/react/dist/mpx-input.jsx +17 -4
  46. package/lib/runtime/components/react/dist/mpx-label.jsx +6 -4
  47. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +19 -4
  48. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +12 -2
  49. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +1 -1
  50. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +7 -4
  51. package/lib/runtime/components/react/dist/mpx-portal/index.jsx +5 -1
  52. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +4 -1
  53. package/lib/runtime/components/react/dist/mpx-radio.jsx +5 -4
  54. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +3 -1
  55. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -4
  56. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +52 -6
  57. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +36 -6
  58. package/lib/runtime/components/react/dist/mpx-slider.jsx +2 -1
  59. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +8 -4
  60. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +6 -4
  61. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +7 -4
  62. package/lib/runtime/components/react/dist/mpx-swiper.jsx +15 -4
  63. package/lib/runtime/components/react/dist/mpx-switch.jsx +4 -1
  64. package/lib/runtime/components/react/dist/mpx-text.jsx +57 -12
  65. package/lib/runtime/components/react/dist/mpx-video.d.ts +2 -1
  66. package/lib/runtime/components/react/dist/mpx-video.jsx +10 -4
  67. package/lib/runtime/components/react/dist/mpx-view.jsx +42 -7
  68. package/lib/runtime/components/react/dist/utils.d.ts +21 -11
  69. package/lib/runtime/components/react/dist/utils.jsx +105 -35
  70. package/lib/runtime/components/react/getInnerListeners.ts +1 -0
  71. package/lib/runtime/components/react/mpx-async-suspense.tsx +2 -1
  72. package/lib/runtime/components/react/mpx-button.tsx +6 -5
  73. package/lib/runtime/components/react/mpx-camera.tsx +1 -0
  74. package/lib/runtime/components/react/mpx-canvas/index.tsx +4 -1
  75. package/lib/runtime/components/react/mpx-checkbox-group.tsx +2 -1
  76. package/lib/runtime/components/react/mpx-checkbox.tsx +6 -4
  77. package/lib/runtime/components/react/mpx-form.tsx +3 -3
  78. package/lib/runtime/components/react/mpx-icon/index.tsx +5 -1
  79. package/lib/runtime/components/react/mpx-image.tsx +57 -20
  80. package/lib/runtime/components/react/mpx-inline-text.tsx +12 -7
  81. package/lib/runtime/components/react/mpx-input.tsx +17 -4
  82. package/lib/runtime/components/react/mpx-label.tsx +6 -4
  83. package/lib/runtime/components/react/mpx-movable-view.tsx +20 -4
  84. package/lib/runtime/components/react/mpx-picker/index.tsx +12 -2
  85. package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
  86. package/lib/runtime/components/react/mpx-picker-view/index.tsx +8 -4
  87. package/lib/runtime/components/react/mpx-portal/index.tsx +5 -1
  88. package/lib/runtime/components/react/mpx-radio-group.tsx +4 -1
  89. package/lib/runtime/components/react/mpx-radio.tsx +5 -4
  90. package/lib/runtime/components/react/mpx-rich-text/index.tsx +3 -1
  91. package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
  92. package/lib/runtime/components/react/mpx-simple-text.tsx +55 -8
  93. package/lib/runtime/components/react/mpx-simple-view.tsx +30 -6
  94. package/lib/runtime/components/react/mpx-slider.tsx +2 -1
  95. package/lib/runtime/components/react/mpx-sticky-header.tsx +8 -4
  96. package/lib/runtime/components/react/mpx-sticky-section.tsx +6 -4
  97. package/lib/runtime/components/react/mpx-swiper-item.tsx +7 -4
  98. package/lib/runtime/components/react/mpx-swiper.tsx +16 -4
  99. package/lib/runtime/components/react/mpx-switch.tsx +4 -1
  100. package/lib/runtime/components/react/mpx-text.tsx +55 -15
  101. package/lib/runtime/components/react/mpx-video.tsx +11 -5
  102. package/lib/runtime/components/react/mpx-view.tsx +35 -7
  103. package/lib/runtime/components/react/types/global.d.ts +4 -0
  104. package/lib/runtime/components/react/utils.tsx +126 -45
  105. package/lib/runtime/components/wx/default-component.mpx +9 -0
  106. package/lib/runtime/components/wx/default-page.mpx +3 -11
  107. package/lib/runtime/optionProcessor.d.ts +2 -0
  108. package/lib/runtime/optionProcessor.js +77 -1
  109. package/lib/runtime/optionProcessorReact.js +5 -0
  110. package/lib/script-setup-compiler/index.js +1 -1
  111. package/lib/style-compiler/index.js +2 -0
  112. package/lib/style-compiler/plugins/remove-strip-conditional-comments.js +14 -0
  113. package/lib/style-compiler/plugins/trans-special.js +1 -1
  114. package/lib/style-compiler/strip-conditional.js +40 -26
  115. package/lib/template-compiler/compiler.js +306 -125
  116. package/lib/template-compiler/gen-node-react.js +35 -7
  117. package/lib/template-compiler/index.js +9 -7
  118. package/lib/utils/const.js +4 -1
  119. package/lib/utils/gen-component-tag.js +1 -5
  120. package/lib/utils/normalize-perf-options.js +47 -0
  121. package/lib/utils/partial-compile-rules.js +27 -0
  122. package/lib/utils/pre-process-json.js +3 -0
  123. package/lib/utils/source-location.js +96 -0
  124. package/lib/web/compile-wx-template-fragment.js +68 -0
  125. package/lib/web/index.js +3 -0
  126. package/lib/web/processJSON.js +7 -4
  127. package/lib/web/processMainScript.js +3 -7
  128. package/lib/web/processScript.js +43 -8
  129. package/lib/web/processStyles.js +12 -3
  130. package/lib/web/processTemplate.js +61 -19
  131. package/lib/web/template-loader.js +123 -0
  132. package/lib/web/template-shared.js +48 -0
  133. package/lib/wxml/loader.js +4 -3
  134. package/lib/wxss/loader.js +1 -1
  135. package/lib/wxss/utils.js +6 -4
  136. package/package.json +12 -4
  137. package/lib/platform/template/wx/component-config/component.js +0 -41
@@ -6,9 +6,11 @@ const { isOriginTag, isBuildInWebTag, isBuildInReactTag } = require('../../../ut
6
6
  const getBuildInTagComponent = require('../../../utils/get-build-tag-component')
7
7
 
8
8
  module.exports = function getSpec ({ warn, error }) {
9
- function print (mode, path, isError) {
9
+ const reactModes = ['ios', 'android', 'harmony']
10
+
11
+ function print (mode, path, value, isError) {
10
12
  const msg = `Json path <${path}> is not supported in ${mode} environment!`
11
- isError ? error(msg) : warn(msg)
13
+ isError ? error(msg, { path, value }) : warn(msg, { path, value })
12
14
  }
13
15
 
14
16
  function deletePath (opts) {
@@ -20,9 +22,10 @@ module.exports = function getSpec ({ warn, error }) {
20
22
  }
21
23
 
22
24
  return function (input, { mode, pathArr = [] }, meta) {
23
- const currPath = meta.paths.join('|')
24
25
  if (shouldLog) {
25
- print(mode, pathArr.concat(currPath).join('.'), isError)
26
+ meta.paths.forEach((path) => {
27
+ print(mode, pathArr.concat(path).join('.'), input[path], isError)
28
+ })
26
29
  }
27
30
  meta.paths.forEach((path) => {
28
31
  delete input[path]
@@ -31,6 +34,14 @@ module.exports = function getSpec ({ warn, error }) {
31
34
  }
32
35
  }
33
36
 
37
+ function createReactRule (test, processor) {
38
+ const rule = { test }
39
+ reactModes.forEach(mode => {
40
+ rule[mode] = processor
41
+ })
42
+ return rule
43
+ }
44
+
34
45
  /**
35
46
  * @desc 在app.mpx里配置usingComponents作为全局组件
36
47
  */
@@ -72,7 +83,10 @@ module.exports = function getSpec ({ warn, error }) {
72
83
  if (componentGenerics && typeof componentGenerics === 'object') {
73
84
  Object.keys(componentGenerics).forEach(key => {
74
85
  if (!componentGenerics[key].default) {
75
- error(`Ali environment componentGenerics need to specify a default custom component! please check the configuration of component ${key}`)
86
+ error(`Ali environment componentGenerics need to specify a default custom component! please check the configuration of component ${key}`, {
87
+ path: ['componentGenerics', key],
88
+ value: componentGenerics[key]
89
+ })
76
90
  }
77
91
  })
78
92
  }
@@ -102,7 +116,10 @@ module.exports = function getSpec ({ warn, error }) {
102
116
  if (keyNeed) {
103
117
  newK = capitalToHyphen(k)
104
118
  if (obj[newK]) {
105
- warn && warn(`Component name "${newK}" already exists, so component "${k}" can't be converted automatically and it isn't supported in ali/swan environment!`)
119
+ warn && warn(`Component name "${newK}" already exists, so component "${k}" can't be converted automatically and it isn't supported in ali/swan environment!`, {
120
+ path: [type, k],
121
+ value: v
122
+ })
106
123
  } else {
107
124
  obj[newK] = v
108
125
  delete obj[k]
@@ -213,6 +230,7 @@ module.exports = function getSpec ({ warn, error }) {
213
230
  },
214
231
  jd: deletePath()
215
232
  },
233
+ createReactRule('enablePullDownRefresh|onReachBottomDistance', deletePath()),
216
234
  {
217
235
  test: 'navigationBarBackgroundColor',
218
236
  ali (input) {
@@ -240,8 +258,13 @@ module.exports = function getSpec ({ warn, error }) {
240
258
  {
241
259
  test: 'backgroundColorTop|backgroundColorBottom',
242
260
  ali: deletePath(),
243
- swan: deletePath()
261
+ swan: deletePath(),
262
+ ios: deletePath(),
263
+ android: deletePath(),
264
+ harmony: deletePath()
244
265
  },
266
+ createReactRule('backgroundColor|backgroundTextStyle', deletePath()),
267
+ createReactRule('pageOrientation', deletePath()),
245
268
  {
246
269
  test: 'navigationBarTextStyle|navigationStyle|backgroundTextStyle',
247
270
  ali: deletePath()
@@ -255,11 +278,12 @@ module.exports = function getSpec ({ warn, error }) {
255
278
  }
256
279
  ]
257
280
 
258
- const getTabBarRule = () => (input, { mode }) => {
281
+ const getTabBarRule = () => (input, { mode, diagnostic }) => {
259
282
  input.tabBar = runRules(spec.tabBar, input.tabBar, {
260
283
  mode,
261
284
  normalizeTest,
262
285
  waterfall: true,
286
+ diagnostic,
263
287
  data: {
264
288
  pathArr: ['tabBar']
265
289
  }
@@ -267,11 +291,12 @@ module.exports = function getSpec ({ warn, error }) {
267
291
  return input
268
292
  }
269
293
 
270
- const getWindowRule = () => (input, { mode }) => {
294
+ const getWindowRule = () => (input, { mode, diagnostic }) => {
271
295
  input.window = runRules(spec.window, input.window, {
272
296
  mode,
273
297
  normalizeTest,
274
298
  waterfall: true,
299
+ diagnostic,
275
300
  data: {
276
301
  pathArr: ['window']
277
302
  }
@@ -329,7 +354,7 @@ module.exports = function getSpec ({ warn, error }) {
329
354
  },
330
355
  {
331
356
  test: 'list',
332
- ali (input) {
357
+ ali (input, { diagnostic }) {
333
358
  const value = input.list
334
359
  delete input.list
335
360
  input.items = value.map((item) => {
@@ -337,6 +362,7 @@ module.exports = function getSpec ({ warn, error }) {
337
362
  mode: 'ali',
338
363
  normalizeTest,
339
364
  waterfall: true,
365
+ diagnostic,
340
366
  data: {
341
367
  pathArr: ['tabBar', 'list']
342
368
  }
@@ -372,7 +398,10 @@ module.exports = function getSpec ({ warn, error }) {
372
398
  qq: deletePath(),
373
399
  swan: deletePath(),
374
400
  tt: deletePath(),
375
- jd: deletePath()
401
+ jd: deletePath(),
402
+ ios: deletePath(),
403
+ android: deletePath(),
404
+ harmony: deletePath()
376
405
  },
377
406
  {
378
407
  test: 'preloadRule',
@@ -384,14 +413,20 @@ module.exports = function getSpec ({ warn, error }) {
384
413
  qq: deletePath(true),
385
414
  swan: deletePath(true),
386
415
  tt: deletePath(),
387
- jd: deletePath(true)
416
+ jd: deletePath(true),
417
+ ios: deletePath(true),
418
+ android: deletePath(true),
419
+ harmony: deletePath(true)
388
420
  },
389
421
  {
390
422
  test: 'plugins',
391
423
  qq: deletePath(true),
392
424
  swan: deletePath(true),
393
425
  tt: deletePath(),
394
- jd: deletePath(true)
426
+ jd: deletePath(true),
427
+ ios: deletePath(true),
428
+ android: deletePath(true),
429
+ harmony: deletePath(true)
395
430
  },
396
431
  {
397
432
  test: 'usingComponents',
@@ -417,19 +452,28 @@ module.exports = function getSpec ({ warn, error }) {
417
452
  {
418
453
  test: 'debug',
419
454
  ali: deletePath(),
420
- swan: deletePath()
455
+ swan: deletePath(),
456
+ ios: deletePath(),
457
+ android: deletePath(),
458
+ harmony: deletePath()
421
459
  },
422
460
  {
423
461
  test: 'requiredBackgroundModes',
424
462
  ali: deletePath(),
425
- tt: deletePath()
463
+ tt: deletePath(),
464
+ ios: deletePath(),
465
+ android: deletePath(),
466
+ harmony: deletePath()
426
467
  },
427
468
  {
428
469
  test: 'workers',
429
470
  jd: deletePath(),
430
471
  ali: deletePath(),
431
472
  swan: deletePath(),
432
- tt: deletePath()
473
+ tt: deletePath(),
474
+ ios: deletePath(),
475
+ android: deletePath(),
476
+ harmony: deletePath()
433
477
  },
434
478
  {
435
479
  test: 'subpackages|subPackages',
@@ -444,6 +488,8 @@ module.exports = function getSpec ({ warn, error }) {
444
488
  ali: deletePath(),
445
489
  jd: deletePath()
446
490
  },
491
+ createReactRule('navigateToMiniProgramAppIdList', deletePath()),
492
+ createReactRule('tabBar', deletePath(true)),
447
493
  {
448
494
  test: 'tabBar',
449
495
  ali: getTabBarRule(),
@@ -460,7 +506,10 @@ module.exports = function getSpec ({ warn, error }) {
460
506
  swan: getWindowRule(),
461
507
  tt: getWindowRule(),
462
508
  ks: getWindowRule(),
463
- jd: getWindowRule()
509
+ jd: getWindowRule(),
510
+ ios: getWindowRule(),
511
+ android: getWindowRule(),
512
+ harmony: getWindowRule()
464
513
  }
465
514
  ]
466
515
  }
@@ -15,19 +15,23 @@ function defaultNormalizeTest (rawTest, context) {
15
15
  }
16
16
 
17
17
  module.exports = function runRules (rules = [], input, options = {}) {
18
- const { mode, testKey, normalizeTest, data = {}, meta = {}, waterfall } = options
18
+ const { mode, testKey, normalizeTest, data = {}, meta = {}, waterfall, diagnostic } = options
19
19
  rules = rules.rules || rules
20
20
  for (let i = 0; i < rules.length; i++) {
21
21
  const rule = rules[i]
22
22
  const tester = (normalizeTest || defaultNormalizeTest)(rule.test, rule)
23
23
  const testInput = testKey ? input[testKey] : input
24
24
  const processor = rule[mode]
25
- // mode传入data中供processor使用
25
+ // mode 和 diagnostic 传入 data 中供 processor 内部使用
26
26
  Object.assign(data, {
27
- mode
27
+ mode,
28
+ diagnostic
28
29
  })
29
- if (tester(testInput, meta) && processor) {
30
- const result = processor.call(rule, input, data, meta)
30
+ if (tester(testInput, meta, data) && processor) {
31
+ const runProcessor = () => processor.call(rule, input, data, meta)
32
+ const result = diagnostic && diagnostic.withContext
33
+ ? diagnostic.withContext({ mode, rule, input, data, meta, testKey, testInput }, runProcessor)
34
+ : runProcessor()
31
35
  meta.processed = true
32
36
  if (result !== undefined) {
33
37
  input = result
@@ -3,7 +3,7 @@ const { parseValues } = require('../../../utils/string')
3
3
 
4
4
  module.exports = function getSpec({ warn, error }) {
5
5
  // React Native 双端都不支持的 CSS property
6
- const unsupportedPropExp = /^(white-space|text-overflow|animation|font-variant-caps|font-variant-numeric|font-variant-east-asian|font-variant-alternates|font-variant-ligatures|background-position|caret-color)$/
6
+ const unsupportedPropExp = /^(white-space|text-overflow|animation|font-variant-caps|font-variant-numeric|font-variant-east-asian|font-variant-alternates|font-variant-ligatures|caret-color|float|clear)$/
7
7
  const unsupportedPropMode = {
8
8
  // React Native ios 不支持的 CSS property
9
9
  ios: /^(vertical-align)$/,
@@ -17,6 +17,7 @@ module.exports = function getSpec({ warn, error }) {
17
17
  // calc(xx)
18
18
  const calcExp = /calc\(/
19
19
  const envExp = /env\(/
20
+ const silentVerify = 'silent'
20
21
  // 不支持的属性提示
21
22
  const unsupportedPropError = ({ prop, value, selector }, { mode }, isError = true) => {
22
23
  const tips = isError ? error : warn
@@ -50,7 +51,7 @@ module.exports = function getSpec({ warn, error }) {
50
51
  'flex-direction': ['row', 'row-reverse', 'column', 'column-reverse'],
51
52
  'flex-wrap': ['wrap', 'nowrap', 'wrap-reverse'],
52
53
  'pointer-events': ['auto', 'box-none', 'box-only', 'none'],
53
- 'vertical-align': ['auto', 'top', 'bottom', 'center'],
54
+ 'vertical-align': ['auto', 'top', 'bottom', 'middle'],
54
55
  position: ['relative', 'absolute', 'fixed'],
55
56
  'font-variant': ['small-caps', 'oldstyle-nums', 'lining-nums', 'tabular-nums', 'proportional-nums'],
56
57
  'text-align': ['left', 'right', 'center', 'justify'],
@@ -118,7 +119,7 @@ module.exports = function getSpec({ warn, error }) {
118
119
  const verifyValues = ({ prop, value, selector }, isError = true) => {
119
120
  prop = prop.trim()
120
121
  const rawValue = value.trim()
121
- const tips = isError ? error : warn
122
+ const tips = isError === silentVerify ? () => {} : isError ? error : warn
122
123
 
123
124
  // CSS 自定义属性(--xxx)是变量定义,不属于 RN 样式属性:
124
125
  // 不能按 `-height/-color` 等后缀推断类型去校验,否则会把变量定义错误过滤,导致运行时 var() 取值失败
@@ -340,6 +341,36 @@ module.exports = function getSpec({ warn, error }) {
340
341
  }
341
342
  const urlExp = /url\(["']?(.*?)["']?\)/
342
343
  const linearExp = /linear-gradient\(.*\)/
344
+ const formatBackgroundSize = (value) => {
345
+ // 不支持逗号分隔的多个值:设置多重背景!!!
346
+ // 支持一个值:这个值指定图片的宽度,图片的高度隐式的为 auto
347
+ // 支持两个值:第一个值指定图片的宽度,第二个值指定图片的高度
348
+ if (parseValues(value, ',').length > 1) { // commas are not allowed in values
349
+ error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
350
+ return false
351
+ }
352
+ const values = []
353
+ parseValues(value).forEach(item => {
354
+ if (verifyValues({ prop: bgPropMap.size, value: item, selector })) {
355
+ // 支持 number 值 / container cover auto 枚举
356
+ values.push(item)
357
+ }
358
+ })
359
+ // value 无有效值时返回false
360
+ return values.length === 0 ? false : { prop: bgPropMap.size, value: values }
361
+ }
362
+ const formatBackgroundPosition = (value) => {
363
+ const values = []
364
+ parseValues(value).forEach(item => {
365
+ if (verifyValues({ prop: bgPropMap.position, value: item, selector })) {
366
+ // 支持 number 值 / 枚举, center与50%等价
367
+ values.push(item === 'center' ? '50%' : item)
368
+ } else {
369
+ error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
370
+ }
371
+ })
372
+ return { prop: bgPropMap.position, value: values }
373
+ }
343
374
  switch (prop) {
344
375
  case bgPropMap.image: {
345
376
  // background-image 支持背景图/渐变/css var
@@ -352,37 +383,13 @@ module.exports = function getSpec({ warn, error }) {
352
383
  }
353
384
  case bgPropMap.size: {
354
385
  // background-size
355
- // 不支持逗号分隔的多个值:设置多重背景!!!
356
- // 支持一个值:这个值指定图片的宽度,图片的高度隐式的为 auto
357
- // 支持两个值:第一个值指定图片的宽度,第二个值指定图片的高度
358
- if (parseValues(value, ',').length > 1) { // commas are not allowed in values
359
- error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
360
- return false
361
- }
362
- const values = []
363
- parseValues(value).forEach(item => {
364
- if (verifyValues({ prop, value: item, selector })) {
365
- // 支持 number 值 / container cover auto 枚举
366
- values.push(item)
367
- }
368
- })
369
- // value 无有效值时返回false
370
- return values.length === 0 ? false : { prop, value: values }
386
+ return formatBackgroundSize(value)
371
387
  }
372
388
  case bgPropMap.position: {
373
- const values = []
374
- parseValues(value).forEach(item => {
375
- if (verifyValues({ prop, value: item, selector })) {
376
- // 支持 number 值 / 枚举, center与50%等价
377
- values.push(item === 'center' ? '50%' : item)
378
- } else {
379
- error(`Value of [${bgPropMap.size}] in ${selector} does not support commas, received [${value}], please check again!`)
380
- }
381
- })
382
- return { prop, value: values }
389
+ return formatBackgroundPosition(value)
383
390
  }
384
391
  case bgPropMap.all: {
385
- // background: 仅支持 background-image & background-color & background-repeat
392
+ // background: 支持 image/color/repeat position/size
386
393
  if (cssVariableExp.test(value)) {
387
394
  error(`Property [${bgPropMap.all}] in ${selector} is abbreviated property and does not support CSS var`)
388
395
  return false
@@ -395,6 +402,37 @@ module.exports = function getSpec({ warn, error }) {
395
402
  ]
396
403
  }
397
404
  const bgMap = []
405
+ const positionValues = []
406
+ const sizeValues = []
407
+ let isSize = false
408
+ const pushPositionOrSize = (item) => {
409
+ if (isSize) {
410
+ if (verifyValues({ prop: bgPropMap.size, value: item, selector }, silentVerify)) {
411
+ sizeValues.push(item)
412
+ }
413
+ } else if (verifyValues({ prop: bgPropMap.position, value: item, selector }, silentVerify)) {
414
+ positionValues.push(item)
415
+ }
416
+ }
417
+ const handlePositionSize = (item) => {
418
+ if (item === '/') {
419
+ isSize = true
420
+ return true
421
+ }
422
+ const parts = parseValues(item, '/')
423
+ if (parts.length > 1) {
424
+ parts.forEach((part, index) => {
425
+ if (index > 0) isSize = true
426
+ part && pushPositionOrSize(part)
427
+ })
428
+ return true
429
+ }
430
+ if (isSize || verifyValues({ prop: bgPropMap.position, value: item, selector }, silentVerify)) {
431
+ pushPositionOrSize(item)
432
+ return true
433
+ }
434
+ return false
435
+ }
398
436
  const values = parseValues(value)
399
437
  values.forEach(item => {
400
438
  const url = item.match(urlExp)?.[0]
@@ -403,12 +441,22 @@ module.exports = function getSpec({ warn, error }) {
403
441
  bgMap.push({ prop: bgPropMap.image, value: url })
404
442
  } else if (linerVal) {
405
443
  bgMap.push({ prop: bgPropMap.image, value: linerVal })
406
- } else if (verifyValues({ prop: bgPropMap.color, value: item }, false)) {
444
+ } else if (verifyValues({ prop: bgPropMap.color, value: item, selector }, silentVerify)) {
407
445
  bgMap.push({ prop: bgPropMap.color, value: item })
408
- } else if (verifyValues({ prop: bgPropMap.repeat, value: item, selector }, false)) {
446
+ } else if (verifyValues({ prop: bgPropMap.repeat, value: item, selector }, silentVerify)) {
409
447
  bgMap.push({ prop: bgPropMap.repeat, value: item })
448
+ } else {
449
+ handlePositionSize(item)
410
450
  }
411
451
  })
452
+ if (positionValues.length) {
453
+ const position = formatBackgroundPosition(positionValues.join(' '))
454
+ position && bgMap.push(position)
455
+ }
456
+ if (sizeValues.length) {
457
+ const size = formatBackgroundSize(sizeValues.join(' '))
458
+ size && bgMap.push(size)
459
+ }
412
460
  return bgMap.length ? bgMap : false
413
461
  }
414
462
  }
@@ -421,8 +469,9 @@ module.exports = function getSpec({ warn, error }) {
421
469
  // css var & 数组直接返回
422
470
  if (Array.isArray(value) || cssVariableExp.test(value)) return { prop, value }
423
471
  const values = parseValues(value)
472
+ // Todo 2 RN下顺序不一致转换结果不一致,故这里不处理,动画前后transform排序不一致的问题,由业务调整写法
424
473
  // Todo transform 排序不一致时,transform动画会闪烁,故这里同样的排序输出 transform
425
- values.sort()
474
+ // values.sort()
426
475
  const transform = []
427
476
  values.forEach(item => {
428
477
  const match = item.match(/([/\w]+)\((.+)\)/)
@@ -20,17 +20,15 @@ module.exports = function normalizeComponentRules (cfgs, spec) {
20
20
  data = Object.assign({}, data, { el, eventRules })
21
21
  const testKey = 'name'
22
22
  let rAttrsList = []
23
- const options = {
24
- mode,
25
- testKey,
26
- data
27
- }
28
23
  el.attrsList.forEach((attr) => {
29
24
  const meta = {}
30
- let rAttr = runRules(spec.directive, attr, {
31
- ...options,
32
- meta
33
- })
25
+ const options = {
26
+ mode,
27
+ testKey,
28
+ diagnostic: data.diagnostic,
29
+ data: Object.assign({}, data, { attr })
30
+ }
31
+ let rAttr = runRules(spec.directive, attr, Object.assign({}, options, { meta }))
34
32
  // 指令未匹配到时说明为props,因为目前所有的指令都需要转换
35
33
  if (!meta.processed) {
36
34
  rAttr = runRules(spec.preProps, rAttr, options)
@@ -3,7 +3,8 @@ const TAG_NAME = 'block'
3
3
  module.exports = function () {
4
4
  return {
5
5
  test: TAG_NAME,
6
- web () {
6
+ web (tag, data) {
7
+ data.el.isBlock = true
7
8
  return 'template'
8
9
  }
9
10
  }
@@ -0,0 +1,34 @@
1
+ const CUSTOM_BUILTIN_MODES = ['web', 'ios', 'android', 'harmony']
2
+
3
+ function testCustomBuiltInTag (tag, meta, data) {
4
+ const map = data && data.customBuiltInComponents
5
+ return !!(map && map[tag])
6
+ }
7
+
8
+ /**
9
+ * 命中后不再走后续常规 component-config(无 waterfall,run-rules 直接 break)。
10
+ * 从 runRules 的 data.customBuiltInComponents 读取配置;先写入 originalTag,再 mpx- 前缀。
11
+ */
12
+ function applyCustomBuiltin (el, data) {
13
+ const map = data && data.customBuiltInComponents
14
+ if (!map || !map[el.tag]) return el
15
+ el.originalTag = el.tag
16
+ el.isBuiltIn = true
17
+ el.tag = 'mpx-' + el.originalTag
18
+ return el
19
+ }
20
+
21
+ /**
22
+ * @returns {object}
23
+ */
24
+ module.exports = function customBuiltInComponent () {
25
+ return {
26
+ skipNormalize: true,
27
+ supportedModes: CUSTOM_BUILTIN_MODES,
28
+ test: testCustomBuiltInTag,
29
+ web: applyCustomBuiltin,
30
+ ios: applyCustomBuiltin,
31
+ android: applyCustomBuiltin,
32
+ harmony: applyCustomBuiltin
33
+ }
34
+ }
@@ -39,12 +39,26 @@ const view = require('./view')
39
39
  const webView = require('./web-view')
40
40
  const label = require('./label')
41
41
  const wxs = require('./wxs')
42
- const component = require('./component')
43
42
  const fixComponentName = require('./fix-component-name')
43
+ const customBuiltInComponent = require('./custom-built-in-component')
44
44
  const rootPortal = require('./root-portal')
45
45
  const stickyHeader = require('./sticky-header')
46
46
  const stickySection = require('./sticky-section')
47
47
 
48
+ /**
49
+ * 未命中上方任一组件 test 的标签,仍须走 normalizeComponentRules 中的通用
50
+ * 指令 / 属性 / 事件链路(如 wx 源码输出 ali 时 bindtap → onTap)。
51
+ * 历史上在 template/wx/index.js 里通过 normalizeComponentRules(cfgs.concat({}), spec)
52
+ * 末尾塞入空对象,由 run-rules 对缺省 test 退化为恒 true;此处改为显式配置且必须排在最后。
53
+ */
54
+ function defaultCatchAllComponentConfig () {
55
+ return {
56
+ test () {
57
+ return true
58
+ }
59
+ }
60
+ }
61
+
48
62
  module.exports = function getComponentConfigs ({ warn, error }) {
49
63
  /**
50
64
  * universal print for detail component warn or error
@@ -85,6 +99,7 @@ module.exports = function getComponentConfigs ({ warn, error }) {
85
99
  // 转换规则只需以微信为基准配置微信和支付宝的差异部分,比如微信和支付宝都支持但是写法不一致,或者微信支持而支付宝不支持的部分(抛出错误或警告)
86
100
  return [
87
101
  fixComponentName({ print }),
102
+ customBuiltInComponent(),
88
103
  ...unsupported({ print }),
89
104
  ad({ print }),
90
105
  view({ print }),
@@ -126,9 +141,9 @@ module.exports = function getComponentConfigs ({ warn, error }) {
126
141
  livePusher({ print }),
127
142
  hyphenTagName({ print }),
128
143
  label({ print }),
129
- component(),
130
144
  rootPortal({ print }),
131
145
  stickyHeader({ print }),
132
- stickySection({ print })
146
+ stickySection({ print }),
147
+ defaultCatchAllComponentConfig()
133
148
  ]
134
149
  }
@@ -92,12 +92,6 @@ module.exports = function ({ print }) {
92
92
  }
93
93
  }
94
94
  },
95
- {
96
- test: /^(password|auto-focus|focus|cursor|selection-start|selection-end|use-built-in)$/,
97
- web (prop, { el }) {
98
- el.isBuiltIn = true
99
- }
100
- },
101
95
  {
102
96
  test: /^(placeholder-style|placeholder-class|cursor-spacing|confirm-type|confirm-hold|adjust-position|hold-keyboard)$/,
103
97
  web: webPropLog
@@ -107,7 +101,7 @@ module.exports = function ({ print }) {
107
101
  qa: qaPropLog
108
102
  },
109
103
  {
110
- test: /^(always-embed|hold-keyboard|safe-password-.+)$/,
104
+ test: /^(always-embed|safe-password-.+)$/,
111
105
  ios: iosPropLog,
112
106
  android: androidPropLog,
113
107
  harmony: harmonyPropLog
@@ -33,10 +33,7 @@ module.exports = function ({ print }) {
33
33
  props: [
34
34
  {
35
35
  test: /^(out-of-bounds)$/,
36
- ali: qaPropLog,
37
- ios: iosPropLog,
38
- android: androidPropLog,
39
- harmony: harmonyPropLog
36
+ ali: qaPropLog
40
37
  },
41
38
  {
42
39
  test: /^(inertia)$/,
@@ -44,9 +41,6 @@ module.exports = function ({ print }) {
44
41
  },
45
42
  {
46
43
  test: /^(damping|friction)$/,
47
- ios: iosPropLog,
48
- android: androidPropLog,
49
- harmony: harmonyPropLog,
50
44
  ks: ksPropLog
51
45
  },
52
46
  {
@@ -49,7 +49,7 @@ module.exports = function ({ print }) {
49
49
  qa: qaPropLog
50
50
  },
51
51
  {
52
- test: /^(space|decode)$/,
52
+ test: /^(space)$/,
53
53
  ios: iosPropLog,
54
54
  android: androidPropLog,
55
55
  harmony: harmonyPropLog
@@ -14,13 +14,10 @@ module.exports = function ({ print }) {
14
14
  const qqEventLog = print({ platform: 'qq', tag: TAG_NAME, isError: false, type: 'event' })
15
15
  const qqPropLog = print({ platform: 'qq', tag: TAG_NAME, isError: false })
16
16
  const baiduPropLog = print({ platform: 'baidu', tag: TAG_NAME, isError: false })
17
- const iosValueLogError = print({ platform: 'ios', tag: TAG_NAME, isError: true, type: 'value' })
18
17
  const iosPropLog = print({ platform: 'ios', tag: TAG_NAME, isError: false })
19
18
  const iosEventLog = print({ platform: 'ios', tag: TAG_NAME, isError: false, type: 'event' })
20
- const androidValueLogError = print({ platform: 'android', tag: TAG_NAME, isError: true, type: 'value' })
21
19
  const androidPropLog = print({ platform: 'android', tag: TAG_NAME, isError: false })
22
20
  const androidEventLog = print({ platform: 'android', tag: TAG_NAME, isError: false, type: 'event' })
23
- const harmonyValueLogError = print({ platform: 'harmony', tag: TAG_NAME, isError: true, type: 'value' })
24
21
  const harmonyPropLog = print({ platform: 'harmony', tag: TAG_NAME, isError: false })
25
22
  const harmonyEventLog = print({ platform: 'harmony', tag: TAG_NAME, isError: false, type: 'event' })
26
23
  const ksPropLog = print({ platform: 'ks', tag: TAG_NAME, isError: false })
@@ -72,28 +69,7 @@ module.exports = function ({ print }) {
72
69
  qa: qaPropLog
73
70
  },
74
71
  {
75
- test: 'confirm-type',
76
- ios ({ name, value }) {
77
- const notSupported = ['return']
78
- if (notSupported.includes(value)) {
79
- iosValueLogError({ name, value })
80
- }
81
- },
82
- android ({ name, value }) {
83
- const notSupported = ['return']
84
- if (notSupported.includes(value)) {
85
- androidValueLogError({ name, value })
86
- }
87
- },
88
- harmony ({ name, value }) {
89
- const notSupported = ['return']
90
- if (notSupported.includes(value)) {
91
- harmonyValueLogError({ name, value })
92
- }
93
- }
94
- },
95
- {
96
- test: /^(always-embed|hold-keyboard|disable-default-padding|adjust-keyboard-to|fixed|show-confirm-bar)$/,
72
+ test: /^(always-embed|confirm-hold|disable-default-padding|adjust-keyboard-to|fixed|show-confirm-bar)$/,
97
73
  ios: iosPropLog,
98
74
  android: androidPropLog,
99
75
  harmony: harmonyPropLog
@@ -13,7 +13,7 @@ const JD_UNSUPPORTED_TAG_NAME_ARR = ['functional-page-navigator', 'live-pusher',
13
13
  // 快应用不支持的标签集合
14
14
  const QA_UNSUPPORTED_TAG_NAME_ARR = ['movable-view', 'movable-area', 'open-data', 'official-account', 'editor', 'functional-page-navigator', 'live-player', 'live-pusher', 'ad', 'cover-image']
15
15
  // RN不支持的标签集合
16
- const RN_UNSUPPORTED_TAG_NAME_ARR = ['open-data', 'official-account', 'editor', 'functional-page-navigator', 'live-player', 'live-pusher', 'ad', 'audio', 'match-media', 'page-container', 'editor', 'keyboard-accessory', 'map']
16
+ const RN_UNSUPPORTED_TAG_NAME_ARR = ['open-data', 'official-account', 'editor', 'functional-page-navigator', 'live-player', 'live-pusher', 'ad', 'audio', 'match-media', 'page-container', 'keyboard-accessory', 'map']
17
17
 
18
18
  /**
19
19
  * @param {function(object): function} print