@mpxjs/webpack-plugin 2.9.18 → 2.9.19-react.0

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 (57) hide show
  1. package/lib/config.js +59 -97
  2. package/lib/dependencies/ResolveDependency.js +2 -2
  3. package/lib/helpers.js +5 -1
  4. package/lib/index.js +21 -18
  5. package/lib/loader.js +44 -97
  6. package/lib/native-loader.js +1 -1
  7. package/lib/platform/index.js +3 -0
  8. package/lib/platform/style/wx/index.js +413 -0
  9. package/lib/platform/template/wx/component-config/button.js +36 -0
  10. package/lib/platform/template/wx/component-config/image.js +15 -0
  11. package/lib/platform/template/wx/component-config/input.js +36 -0
  12. package/lib/platform/template/wx/component-config/scroll-view.js +27 -1
  13. package/lib/platform/template/wx/component-config/swiper-item.js +13 -1
  14. package/lib/platform/template/wx/component-config/swiper.js +25 -1
  15. package/lib/platform/template/wx/component-config/text.js +15 -0
  16. package/lib/platform/template/wx/component-config/textarea.js +39 -0
  17. package/lib/platform/template/wx/component-config/unsupported.js +18 -0
  18. package/lib/platform/template/wx/component-config/view.js +14 -0
  19. package/lib/platform/template/wx/index.js +88 -4
  20. package/lib/react/index.js +92 -0
  21. package/lib/react/processJSON.js +362 -0
  22. package/lib/react/processScript.js +40 -0
  23. package/lib/react/processStyles.js +63 -0
  24. package/lib/react/processTemplate.js +151 -0
  25. package/lib/react/script-helper.js +79 -0
  26. package/lib/react/style-helper.js +91 -0
  27. package/lib/runtime/components/react/event.config.ts +32 -0
  28. package/lib/runtime/components/react/getInnerListeners.ts +289 -0
  29. package/lib/runtime/components/react/getInnerListeners.type.ts +68 -0
  30. package/lib/runtime/components/react/mpx-button.tsx +402 -0
  31. package/lib/runtime/components/react/mpx-image/index.tsx +351 -0
  32. package/lib/runtime/components/react/mpx-image/svg.tsx +21 -0
  33. package/lib/runtime/components/react/mpx-input.tsx +389 -0
  34. package/lib/runtime/components/react/mpx-scroll-view.tsx +412 -0
  35. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +407 -0
  36. package/lib/runtime/components/react/mpx-swiper/index.tsx +68 -0
  37. package/lib/runtime/components/react/mpx-swiper/type.ts +69 -0
  38. package/lib/runtime/components/react/mpx-swiper-item.tsx +42 -0
  39. package/lib/runtime/components/react/mpx-text.tsx +106 -0
  40. package/lib/runtime/components/react/mpx-textarea.tsx +46 -0
  41. package/lib/runtime/components/react/mpx-view.tsx +397 -0
  42. package/lib/runtime/components/react/utils.ts +92 -0
  43. package/lib/runtime/stringify.wxs +3 -7
  44. package/lib/runtime/useNodesRef.ts +39 -0
  45. package/lib/style-compiler/index.js +2 -1
  46. package/lib/template-compiler/compiler.js +539 -287
  47. package/lib/template-compiler/gen-node-react.js +95 -0
  48. package/lib/template-compiler/index.js +19 -31
  49. package/lib/utils/env.js +17 -0
  50. package/lib/utils/make-map.js +1 -1
  51. package/lib/utils/shallow-stringify.js +17 -0
  52. package/lib/web/index.js +122 -0
  53. package/lib/web/processMainScript.js +3 -4
  54. package/lib/web/processScript.js +9 -5
  55. package/lib/web/processTemplate.js +14 -14
  56. package/lib/web/script-helper.js +11 -19
  57. package/package.json +7 -3
@@ -12,6 +12,8 @@ const transDynamicClassExpr = require('./trans-dynamic-class-expr')
12
12
  const dash2hump = require('../utils/hump-dash').dash2hump
13
13
  const makeMap = require('../utils/make-map')
14
14
  const { isNonPhrasingTag } = require('../utils/dom-tag-config')
15
+ const shallowStringify = require('../utils/shallow-stringify')
16
+ const { isReact } = require('../utils/env')
15
17
 
16
18
  const no = function () {
17
19
  return false
@@ -34,7 +36,7 @@ const endTag = new RegExp(('^<\\/' + qnameCapture + '[^>]*>'))
34
36
  const doctype = /^<!DOCTYPE [^>]+>/i
35
37
  const comment = /^<!--/
36
38
  const conditionalComment = /^<!\[/
37
-
39
+ const hoverClassReg = /^mpx-((cover-)?view|button|navigator)$/
38
40
  let IS_REGEX_CAPTURING_BROKEN = false
39
41
  'x'.replace(/x(.)?/g, function (m, g) {
40
42
  IS_REGEX_CAPTURING_BROKEN = g === ''
@@ -62,7 +64,7 @@ function makeAttrsMap (attrs) {
62
64
  return map
63
65
  }
64
66
 
65
- function createASTElement (tag, attrs, parent) {
67
+ function createASTElement (tag, attrs = [], parent = null) {
66
68
  return {
67
69
  type: 1,
68
70
  tag: tag,
@@ -88,25 +90,31 @@ function isForbiddenTag (el) {
88
90
  let warn$1
89
91
  let error$1
90
92
  let mode
93
+ let env
91
94
  let defs
92
95
  let i18n
93
96
  let srcMode
94
- let processingTemplate
97
+ let ctorType
98
+ let moduleId
95
99
  let isNative
100
+ let hasScoped
101
+ let hasVirtualHost
96
102
  let rulesRunner
97
103
  let currentEl
98
104
  let injectNodes = []
99
105
  let forScopes = []
100
106
  let forScopesMap = {}
101
- let hasI18n = false
102
- let i18nInjectableComputed = []
103
- let env
104
107
  let platformGetTagNamespace
105
108
  let filePath
106
109
  let refId
107
- let haveOptionChain = false
110
+ let hasI18n = false
111
+ let i18nInjectableComputed = []
112
+ let hasOptionalChaining = false
113
+ let processingTemplate = false
114
+ const rulesResultMap = new Map()
108
115
 
109
116
  function updateForScopesMap () {
117
+ forScopesMap = {}
110
118
  forScopes.forEach((scope) => {
111
119
  forScopesMap[scope.index] = 'index'
112
120
  forScopesMap[scope.item] = 'item'
@@ -126,7 +134,6 @@ function popForScopes () {
126
134
  return scope
127
135
  }
128
136
 
129
- const rulesResultMap = new Map()
130
137
  const deleteErrorInResultMap = (node) => {
131
138
  rulesResultMap.delete(node)
132
139
  Array.isArray(node.children) && node.children.forEach(item => deleteErrorInResultMap(item))
@@ -595,10 +602,30 @@ function parseComponent (content, options) {
595
602
  }
596
603
 
597
604
  function parse (template, options) {
598
- rulesResultMap.clear()
605
+ // global var init
599
606
  warn$1 = options.warn || baseWarn
600
607
  error$1 = options.error || baseError
608
+ mode = options.mode || 'wx'
609
+ env = options.env
610
+ defs = options.defs || {}
611
+ srcMode = options.srcMode || mode
612
+ ctorType = options.ctorType
613
+ moduleId = options.moduleId
614
+ isNative = options.isNative
615
+ hasScoped = options.hasScoped
616
+ hasVirtualHost = options.hasVirtualHost
617
+ filePath = options.filePath
618
+ i18n = options.i18n
619
+ platformGetTagNamespace = options.getTagNamespace || no
620
+ refId = 0
621
+ injectNodes = []
622
+ forScopes = []
623
+ forScopesMap = {}
624
+ hasI18n = false
601
625
  i18nInjectableComputed = []
626
+ hasOptionalChaining = false
627
+ processingTemplate = false
628
+ rulesResultMap.clear()
602
629
 
603
630
  const _warn = content => {
604
631
  const currentElementRuleResult = rulesResultMap.get(currentEl) || rulesResultMap.set(currentEl, {
@@ -615,15 +642,6 @@ function parse (template, options) {
615
642
  currentElementRuleResult.errorArray.push(content)
616
643
  }
617
644
 
618
- mode = options.mode || 'wx'
619
- env = options.env
620
- defs = options.defs || {}
621
- srcMode = options.srcMode || mode
622
- isNative = options.isNative
623
- filePath = options.filePath
624
- i18n = options.i18n
625
- refId = 0
626
-
627
645
  rulesRunner = getRulesRunner({
628
646
  mode,
629
647
  srcMode,
@@ -636,14 +654,6 @@ function parse (template, options) {
636
654
  error: _error
637
655
  })
638
656
 
639
- injectNodes = []
640
- forScopes = []
641
- forScopesMap = {}
642
- hasI18n = false
643
- haveOptionChain = false
644
-
645
- platformGetTagNamespace = options.getTagNamespace || no
646
-
647
657
  const stack = []
648
658
  let root
649
659
  const meta = {}
@@ -736,7 +746,7 @@ function parse (template, options) {
736
746
  parent: currentParent
737
747
  }
738
748
  children.push(el)
739
- processText(el)
749
+ processText(el, meta, options)
740
750
  }
741
751
  }
742
752
  },
@@ -765,7 +775,7 @@ function parse (template, options) {
765
775
  }
766
776
  }
767
777
 
768
- if (haveOptionChain) {
778
+ if (hasOptionalChaining) {
769
779
  injectWxs(meta, optionsChainWxsName, optionsChainWxsPath)
770
780
  }
771
781
 
@@ -785,7 +795,7 @@ function parse (template, options) {
785
795
  arr.push(item)
786
796
  }
787
797
  })
788
- arr.length && warn$1(`\n ${options.filePath} \n 组件 ${arr.join(' | ')} 注册了,但是未被对应的模板引用,建议删除!`)
798
+ arr.length && warn$1(`\n ${filePath} \n 组件 ${arr.join(' | ')} 注册了,但是未被对应的模板引用,建议删除!`)
789
799
  }
790
800
 
791
801
  return {
@@ -795,7 +805,7 @@ function parse (template, options) {
795
805
  }
796
806
 
797
807
  function getTempNode () {
798
- return createASTElement('temp-node', [])
808
+ return createASTElement('temp-node')
799
809
  }
800
810
 
801
811
  function addChild (parent, newChild, before) {
@@ -848,16 +858,23 @@ function modifyAttr (el, name, val) {
848
858
  }
849
859
  }
850
860
 
851
- function moveBaseDirective (target, from, isDelete = true) {
852
- target.for = from.for
853
- target.if = from.if
854
- target.elseif = from.elseif
855
- target.else = from.else
861
+ function postMoveBaseDirective (target, source, isDelete = true) {
862
+ target.for = source.for
863
+ target.if = source.if
864
+ target.elseif = source.elseif
865
+ target.else = source.else
866
+ if (isReact(mode)) {
867
+ postProcessForReact(target)
868
+ postProcessIfReact(target)
869
+ } else {
870
+ postProcessFor(target)
871
+ postProcessIf(target)
872
+ }
856
873
  if (isDelete) {
857
- delete from.for
858
- delete from.if
859
- delete from.elseif
860
- delete from.else
874
+ delete source.for
875
+ delete source.if
876
+ delete source.elseif
877
+ delete source.else
861
878
  }
862
879
  }
863
880
 
@@ -895,7 +912,7 @@ function stringify (str) {
895
912
 
896
913
  const genericRE = /^generic:(.+)$/
897
914
 
898
- function processComponentGenericsForWeb (el, options, meta) {
915
+ function processComponentGenericsWeb (el, options, meta) {
899
916
  if (options.componentGenerics && options.componentGenerics[el.tag]) {
900
917
  const generic = dash2hump(el.tag)
901
918
  el.tag = 'component'
@@ -907,7 +924,7 @@ function processComponentGenericsForWeb (el, options, meta) {
907
924
 
908
925
  let hasGeneric = false
909
926
 
910
- const genericHash = options.moduleId
927
+ const genericHash = moduleId
911
928
 
912
929
  el.attrsList.forEach((attr) => {
913
930
  if (genericRE.test(attr.name)) {
@@ -944,10 +961,10 @@ function processComponentIs (el, options) {
944
961
  return
945
962
  }
946
963
 
947
- options = options || {}
948
- el.components = options.usingComponents
949
- if (!el.components) {
950
- warn$1('Component in which <component> tag is used must have a nonblank usingComponents field')
964
+ const isInRange = makeMap(getAndRemoveAttr(el, 'range').val || '')
965
+ el.components = (options.usingComponents || []).filter(i => isInRange(i))
966
+ if (!el.components.length) {
967
+ warn$1('Component in which <component> tag is used must have a non blank usingComponents field')
951
968
  }
952
969
 
953
970
  const is = getAndRemoveAttr(el, 'is').val
@@ -960,7 +977,7 @@ function processComponentIs (el, options) {
960
977
 
961
978
  const eventIdentifier = '__mpx_event__'
962
979
 
963
- function parseFuncStr2 (str) {
980
+ function parseFuncStr (str) {
964
981
  const funcRE = /^([^()]+)(\((.*)\))?/
965
982
  const match = funcRE.exec(str)
966
983
  if (match) {
@@ -1023,23 +1040,144 @@ function stringifyWithResolveComputed (modelValue) {
1023
1040
  return result.join('+')
1024
1041
  }
1025
1042
 
1026
- function processBindEvent (el, options) {
1043
+ function processStyleReact (el) {
1044
+ // process class/wx:class/style/wx:style/wx:show for react native
1045
+ const dynamicClass = getAndRemoveAttr(el, config[mode].directive.dynamicClass).val
1046
+ let staticClass = getAndRemoveAttr(el, 'class').val || ''
1047
+ staticClass = staticClass.replace(/\s+/g, ' ')
1048
+
1049
+ let staticHoverClass = ''
1050
+ if (hoverClassReg.test(el.tag)) {
1051
+ staticHoverClass = el.attrsMap['hover-class'] || ''
1052
+ staticHoverClass = staticHoverClass.replace(/\s+/g, ' ')
1053
+ }
1054
+
1055
+ const dynamicStyle = getAndRemoveAttr(el, config[mode].directive.dynamicStyle).val
1056
+ let staticStyle = getAndRemoveAttr(el, 'style').val || ''
1057
+ staticStyle = staticStyle.replace(/\s+/g, ' ')
1058
+
1059
+ const show = getAndRemoveAttr(el, config[mode].directive.show).val
1060
+
1061
+ if (dynamicClass || staticClass || dynamicStyle || staticStyle || show) {
1062
+ const staticClassExp = parseMustacheWithContext(staticClass).result
1063
+ const dynamicClassExp = parseMustacheWithContext(dynamicClass).result
1064
+ const staticStyleExp = parseMustacheWithContext(staticStyle).result
1065
+ const dynamicStyleExp = parseMustacheWithContext(dynamicStyle).result
1066
+ const showExp = parseMustacheWithContext(show).result
1067
+
1068
+ addAttrs(el, [{
1069
+ name: 'style',
1070
+ // runtime helper
1071
+ value: `{{this.__getStyle(${staticClassExp}, ${dynamicClassExp}, ${staticStyleExp}, ${dynamicStyleExp}, ${showExp})}}`
1072
+ }])
1073
+ }
1074
+
1075
+ if (staticHoverClass && staticHoverClass !== 'none') {
1076
+ const staticClassExp = parseMustacheWithContext(staticHoverClass).result
1077
+ addAttrs(el, [{
1078
+ name: 'hoverStyle',
1079
+ // runtime helper
1080
+ value: `{{this.__getStyle(${staticClassExp})}}`
1081
+ }])
1082
+ }
1083
+ }
1084
+
1085
+ function processEventReact (el, options, meta) {
1027
1086
  const eventConfigMap = {}
1028
- el.attrsList.forEach(function (attr) {
1029
- const parsedEvent = config[mode].event.parseEvent(attr.name)
1087
+ el.attrsList.forEach(function ({ name, value }) {
1088
+ const parsedEvent = config[mode].event.parseEvent(name)
1089
+ if (parsedEvent) {
1090
+ const type = parsedEvent.eventName
1091
+ const parsedFunc = parseFuncStr(value)
1092
+ if (parsedFunc) {
1093
+ if (!eventConfigMap[type]) {
1094
+ eventConfigMap[type] = {
1095
+ configs: []
1096
+ }
1097
+ }
1098
+ eventConfigMap[type].configs.push(Object.assign({ name }, parsedFunc))
1099
+ }
1100
+ }
1101
+ })
1102
+
1103
+ let wrapper
1104
+
1105
+ for (const type in eventConfigMap) {
1106
+ let { configs } = eventConfigMap[type]
1107
+
1108
+ let resultName
1109
+ configs.forEach(({ name }) => {
1110
+ if (name) {
1111
+ // 清空原始事件绑定
1112
+ let has
1113
+ do {
1114
+ has = getAndRemoveAttr(el, name).has
1115
+ } while (has)
1116
+
1117
+ if (!resultName) {
1118
+ // 清除修饰符
1119
+ resultName = name.replace(/\..*/, '')
1120
+ }
1121
+ }
1122
+ })
1123
+ configs = configs.map((item) => {
1124
+ return item.expStr
1125
+ })
1126
+ const name = resultName || config[mode].event.getEvent(type)
1127
+ const value = `{{(e)=>this.__invoke(e, [${configs}])}}`
1128
+ addAttrs(el, [
1129
+ {
1130
+ name,
1131
+ value
1132
+ }
1133
+ ])
1134
+ // 非button的情况下,press/longPress时间需要包裹TouchableWithoutFeedback进行响应,后续可支持配置
1135
+ // if ((type === 'press' || type === 'longPress') && el.tag !== 'mpx-button') {
1136
+ // if (!wrapper) {
1137
+ // wrapper = createASTElement('TouchableWithoutFeedback')
1138
+ // wrapper.isBuiltIn = true
1139
+ // processBuiltInComponents(wrapper, meta)
1140
+ // }
1141
+ // addAttrs(el, [
1142
+ // {
1143
+ // name,
1144
+ // value
1145
+ // }
1146
+ // ])
1147
+ // } else {
1148
+ // addAttrs(el, [
1149
+ // {
1150
+ // name,
1151
+ // value
1152
+ // }
1153
+ // ])
1154
+ // }
1155
+ }
1156
+
1157
+ if (wrapper) {
1158
+ replaceNode(el, wrapper, true)
1159
+ addChild(wrapper, el)
1160
+ processAttrs(wrapper, options)
1161
+ postMoveBaseDirective(wrapper, el)
1162
+ }
1163
+ }
1164
+
1165
+ function processEvent (el, options) {
1166
+ const eventConfigMap = {}
1167
+ el.attrsList.forEach(function ({ name, value }) {
1168
+ const parsedEvent = config[mode].event.parseEvent(name)
1030
1169
 
1031
1170
  if (parsedEvent) {
1032
1171
  const type = parsedEvent.eventName
1033
1172
  const modifiers = (parsedEvent.modifier || '').split('.')
1034
- const parsedFunc = parseFuncStr2(attr.value)
1173
+ const parsedFunc = parseFuncStr(value)
1035
1174
  if (parsedFunc) {
1036
1175
  if (!eventConfigMap[type]) {
1037
1176
  eventConfigMap[type] = {
1038
- rawName: attr.name,
1039
1177
  configs: []
1040
1178
  }
1041
1179
  }
1042
- eventConfigMap[type].configs.push(parsedFunc)
1180
+ eventConfigMap[type].configs.push(Object.assign({ name }, parsedFunc))
1043
1181
  if (modifiers.indexOf('proxy') > -1 || options.forceProxyEvent) {
1044
1182
  eventConfigMap[type].proxy = true
1045
1183
  }
@@ -1098,7 +1236,7 @@ function processBindEvent (el, options) {
1098
1236
 
1099
1237
  for (const type in eventConfigMap) {
1100
1238
  let needBind = false
1101
- let { configs, rawName, proxy } = eventConfigMap[type]
1239
+ const { configs, proxy } = eventConfigMap[type]
1102
1240
  delete eventConfigMap[type]
1103
1241
  if (proxy) {
1104
1242
  needBind = true
@@ -1116,19 +1254,25 @@ function processBindEvent (el, options) {
1116
1254
  }
1117
1255
 
1118
1256
  if (needBind) {
1119
- if (rawName) {
1120
- // 清空原始事件绑定
1121
- let has
1122
- do {
1123
- has = getAndRemoveAttr(el, rawName).has
1124
- } while (has)
1125
- // 清除修饰符
1126
- rawName = rawName.replace(/\..*/, '')
1127
- }
1257
+ let resultName
1258
+ configs.forEach(({ name }) => {
1259
+ if (name) {
1260
+ // 清空原始事件绑定
1261
+ let has
1262
+ do {
1263
+ has = getAndRemoveAttr(el, name).has
1264
+ } while (has)
1265
+
1266
+ if (!resultName) {
1267
+ // 清除修饰符
1268
+ resultName = name.replace(/\..*/, '')
1269
+ }
1270
+ }
1271
+ })
1128
1272
 
1129
1273
  addAttrs(el, [
1130
1274
  {
1131
- name: rawName || config[mode].event.getEvent(type),
1275
+ name: resultName || config[mode].event.getEvent(type),
1132
1276
  value: '__invoke'
1133
1277
  }
1134
1278
  ])
@@ -1141,15 +1285,181 @@ function processBindEvent (el, options) {
1141
1285
  if (!isEmptyObject(eventConfigMap)) {
1142
1286
  addAttrs(el, [{
1143
1287
  name: 'data-eventconfigs',
1144
- value: `{{${config[mode].event.shallowStringify(eventConfigMap)}}}`
1288
+ value: `{{${shallowStringify(eventConfigMap, true)}}}`
1145
1289
  }])
1146
1290
  }
1147
1291
  }
1148
1292
 
1293
+ function processSlotReact (el) {
1294
+ if (el.tag === 'slot') {
1295
+ el.slot = {
1296
+ name: getAndRemoveAttr(el, 'name').val
1297
+ }
1298
+ }
1299
+ }
1300
+
1149
1301
  function wrapMustache (val) {
1150
1302
  return val && !tagRE.test(val) ? `{{${val}}}` : val
1151
1303
  }
1152
1304
 
1305
+ function parseOptionalChaining (str) {
1306
+ const wxsName = `${optionsChainWxsName}.g`
1307
+ let optionsRes
1308
+ while (optionsRes = /\?\./.exec(str)) {
1309
+ const strLength = str.length
1310
+ const grammarMap = {
1311
+ init () {
1312
+ const initKey = [
1313
+ {
1314
+ mapKey: '[]',
1315
+ mapValue: [
1316
+ {
1317
+ key: '[',
1318
+ value: 1
1319
+ },
1320
+ {
1321
+ key: ']',
1322
+ value: -1
1323
+ }
1324
+ ]
1325
+ },
1326
+ {
1327
+ mapKey: '()',
1328
+ mapValue: [
1329
+ {
1330
+ key: '(',
1331
+ value: 1
1332
+ },
1333
+ {
1334
+ key: ')',
1335
+ value: -1
1336
+ }
1337
+ ]
1338
+ }
1339
+ ]
1340
+ this.count = {}
1341
+ initKey.forEach(({ mapKey, mapValue }) => {
1342
+ mapValue.forEach(({ key, value }) => {
1343
+ this[key] = this.changeState(mapKey, value)
1344
+ })
1345
+ })
1346
+ },
1347
+ changeState (key, value) {
1348
+ if (!this.count[key]) {
1349
+ this.count[key] = 0
1350
+ }
1351
+ return () => {
1352
+ this.count[key] = this.count[key] + value
1353
+ return this.count[key]
1354
+ }
1355
+ },
1356
+ checkState () {
1357
+ return Object.values(this.count).find(i => i)
1358
+ }
1359
+ }
1360
+ let leftIndex = optionsRes.index
1361
+ let rightIndex = leftIndex + 2
1362
+ let haveNotGetValue = true
1363
+ let chainValue = ''
1364
+ let chainKey = ''
1365
+ let notCheck = false
1366
+ grammarMap.init()
1367
+ // 查 ?. 左边值
1368
+ while (haveNotGetValue && leftIndex > 0) {
1369
+ const left = str[leftIndex - 1]
1370
+ const grammar = grammarMap[left]
1371
+ if (notCheck) {
1372
+ // 处于表达式内
1373
+ chainValue = left + chainValue
1374
+ if (grammar) {
1375
+ grammar()
1376
+ if (!grammarMap.checkState()) {
1377
+ // 表达式结束
1378
+ notCheck = false
1379
+ }
1380
+ }
1381
+ } else if (~[']', ')'].indexOf(left)) {
1382
+ // 命中表达式,开始记录表达式
1383
+ chainValue = left + chainValue
1384
+ notCheck = true
1385
+ grammar()
1386
+ } else if (left !== ' ') {
1387
+ if (!/[A-Za-z0-9_$.]/.test(left)) {
1388
+ // 结束
1389
+ haveNotGetValue = false
1390
+ leftIndex++
1391
+ } else {
1392
+ // 正常语法
1393
+ chainValue = left + chainValue
1394
+ }
1395
+ }
1396
+ leftIndex--
1397
+ }
1398
+ if (grammarMap.checkState() && haveNotGetValue) {
1399
+ // 值查找结束但是语法未闭合或者处理到边界还未结束,抛异常
1400
+ throw new Error('[optionChain] option value illegal!!!')
1401
+ }
1402
+ haveNotGetValue = true
1403
+ let keyValue = ''
1404
+ // 查 ?. 右边key
1405
+ while (haveNotGetValue && rightIndex < strLength) {
1406
+ const right = str[rightIndex]
1407
+ const grammar = grammarMap[right]
1408
+ if (notCheck) {
1409
+ // 处于表达式内
1410
+ if (grammar) {
1411
+ grammar()
1412
+ if (grammarMap.checkState()) {
1413
+ keyValue += right
1414
+ } else {
1415
+ // 表达式结束
1416
+ notCheck = false
1417
+ chainKey += `,${keyValue}`
1418
+ keyValue = ''
1419
+ }
1420
+ } else {
1421
+ keyValue += right
1422
+ }
1423
+ } else if (~['[', '('].indexOf(right)) {
1424
+ // 命中表达式,开始记录表达式
1425
+ grammar()
1426
+ if (keyValue) {
1427
+ chainKey += `,'${keyValue}'`
1428
+ keyValue = ''
1429
+ }
1430
+ notCheck = true
1431
+ } else if (!/[A-Za-z0-9_$.?]/.test(right)) {
1432
+ // 结束
1433
+ haveNotGetValue = false
1434
+ rightIndex--
1435
+ } else if (right !== '?') {
1436
+ // 正常语法
1437
+ if (right === '.') {
1438
+ if (keyValue) {
1439
+ chainKey += `,'${keyValue}'`
1440
+ }
1441
+ keyValue = ''
1442
+ } else {
1443
+ keyValue += right
1444
+ }
1445
+ }
1446
+ rightIndex++
1447
+ }
1448
+ if (grammarMap.checkState() && haveNotGetValue) {
1449
+ // key值查找结束但是语法未闭合或者处理到边界还未结束,抛异常
1450
+ throw new Error('[optionChain] option key illegal!!!')
1451
+ }
1452
+ if (keyValue) {
1453
+ chainKey += `,'${keyValue}'`
1454
+ }
1455
+ str = str.slice(0, leftIndex) + `${wxsName}(${chainValue},[${chainKey.slice(1)}])` + str.slice(rightIndex)
1456
+ if (!hasOptionalChaining) {
1457
+ hasOptionalChaining = true
1458
+ }
1459
+ }
1460
+ return str
1461
+ }
1462
+
1153
1463
  function parseMustacheWithContext (raw = '') {
1154
1464
  return parseMustache(raw, (exp) => {
1155
1465
  if (defs) {
@@ -1163,8 +1473,9 @@ function parseMustacheWithContext (raw = '') {
1163
1473
  }
1164
1474
  })
1165
1475
  }
1476
+ // 处理可选链表达式
1477
+ exp = parseOptionalChaining(exp)
1166
1478
 
1167
- exp = parseOptionChain(exp)
1168
1479
  if (i18n) {
1169
1480
  for (const i18nFuncName of i18nFuncNames) {
1170
1481
  const funcNameRE = new RegExp(`(?<![A-Za-z0-9_$.])${i18nFuncName}\\(`)
@@ -1244,12 +1555,12 @@ function parseMustache (raw = '', expHandler = exp => exp, strHandler = str => s
1244
1555
  }
1245
1556
  }
1246
1557
 
1247
- function addExp (el, exp, isProps) {
1558
+ function addExp (el, exp, isProps, attrName) {
1248
1559
  if (exp) {
1249
1560
  if (!el.exps) {
1250
1561
  el.exps = []
1251
1562
  }
1252
- el.exps.push({ exp, isProps })
1563
+ el.exps.push({ exp, isProps, attrName })
1253
1564
  }
1254
1565
  }
1255
1566
 
@@ -1274,7 +1585,7 @@ function processIf (el) {
1274
1585
  }
1275
1586
  }
1276
1587
 
1277
- function processIfForWeb (el) {
1588
+ function processIfWeb (el) {
1278
1589
  let val = getAndRemoveAttr(el, config[mode].directive.if).val
1279
1590
  if (val) {
1280
1591
  el.if = {
@@ -1328,6 +1639,27 @@ function processFor (el) {
1328
1639
  }
1329
1640
  }
1330
1641
 
1642
+ function processRefReact (el, options, meta) {
1643
+ const val = getAndRemoveAttr(el, config[mode].directive.ref).val
1644
+ const type = isComponentNode(el, options) ? 'component' : 'node'
1645
+ if (val) {
1646
+ if (!meta.refs) {
1647
+ meta.refs = []
1648
+ }
1649
+ const all = !!forScopes.length
1650
+ meta.refs.push({
1651
+ key: val,
1652
+ all,
1653
+ type
1654
+ })
1655
+
1656
+ addAttrs(el, [{
1657
+ name: 'ref',
1658
+ value: `{{ this.__getRefVal('${val}') }}`
1659
+ }])
1660
+ }
1661
+ }
1662
+
1331
1663
  function processRef (el, options, meta) {
1332
1664
  const val = getAndRemoveAttr(el, config[mode].directive.ref).val
1333
1665
  const type = isComponentNode(el, options) ? 'component' : 'node'
@@ -1422,7 +1754,7 @@ function processAttrs (el, options) {
1422
1754
  if (parsed.hasBinding) {
1423
1755
  // 该属性判断用于提供给运行时对于计算属性作为props传递时提出警告
1424
1756
  const isProps = isComponentNode(el, options) && !(attr.name === 'class' || attr.name === 'style')
1425
- addExp(el, parsed.result, isProps)
1757
+ addExp(el, parsed.result, isProps, attr.name)
1426
1758
  if (parsed.replaced) {
1427
1759
  modifyAttr(el, attr.name, needWrap ? parsed.val.slice(1, -1) : parsed.val)
1428
1760
  }
@@ -1437,7 +1769,7 @@ function postProcessFor (el) {
1437
1769
  这个操作主要是因为百度小程序不支持这两个directive在同级使用
1438
1770
  */
1439
1771
  if (el.if && mode === 'swan') {
1440
- const block = createASTElement('block', [])
1772
+ const block = createASTElement('block')
1441
1773
  replaceNode(el, block, true)
1442
1774
  block.for = el.for
1443
1775
  delete el.for
@@ -1477,6 +1809,19 @@ function postProcessFor (el) {
1477
1809
  }
1478
1810
  }
1479
1811
 
1812
+ function postProcessForReact (el) {
1813
+ if (el.for) {
1814
+ if (el.for.key) {
1815
+ addExp(el, `this.__getWxKey(${el.for.item || 'item'}, ${stringify(el.for.key)})`, false, 'key')
1816
+ addAttrs(el, [{
1817
+ name: 'key',
1818
+ value: el.for.key
1819
+ }])
1820
+ }
1821
+ popForScopes()
1822
+ }
1823
+ }
1824
+
1480
1825
  function evalExp (exp) {
1481
1826
  let result = { success: false }
1482
1827
  try {
@@ -1553,7 +1898,35 @@ function postProcessIf (el) {
1553
1898
  }
1554
1899
  }
1555
1900
 
1556
- function processText (el) {
1901
+ function addIfCondition (el, condition) {
1902
+ if (!el.ifConditions) {
1903
+ el.ifConditions = []
1904
+ }
1905
+ el.ifConditions.push(condition)
1906
+ }
1907
+
1908
+ function postProcessIfReact (el) {
1909
+ let prevNode
1910
+ if (el.if) {
1911
+ addIfCondition(el, {
1912
+ exp: el.if.exp,
1913
+ block: el
1914
+ })
1915
+ } else if (el.elseif || el.else) {
1916
+ prevNode = findPrevNode(el)
1917
+ if (prevNode && prevNode.if) {
1918
+ addIfCondition(prevNode, {
1919
+ exp: el.elseif && el.elseif.exp,
1920
+ block: el
1921
+ })
1922
+ removeNode(el, true)
1923
+ } else {
1924
+ warn$1(`wx:${el.elseif ? `elif="${el.elseif.raw}"` : 'else'} used on element [${el.tag}] without corresponding wx:if.`)
1925
+ }
1926
+ }
1927
+ }
1928
+
1929
+ function processText (el, meta) {
1557
1930
  if (el.type !== 3 || el.isComment) {
1558
1931
  return
1559
1932
  }
@@ -1562,6 +1935,19 @@ function processText (el) {
1562
1935
  addExp(el, parsed.result)
1563
1936
  }
1564
1937
  el.text = parsed.val
1938
+ if (isReact(mode)) {
1939
+ processWrapTextReact(el, meta)
1940
+ }
1941
+ }
1942
+
1943
+ // RN中文字需被Text包裹
1944
+ function processWrapTextReact (el, meta) {
1945
+ const parentTag = el.parent.tag
1946
+ if (parentTag !== 'mpx-text' && parentTag !== 'Text') {
1947
+ const wrapper = createASTElement('Text')
1948
+ replaceNode(el, wrapper, true)
1949
+ addChild(wrapper, el)
1950
+ }
1565
1951
  }
1566
1952
 
1567
1953
  // function injectComputed (el, meta, type, body) {
@@ -1684,13 +2070,13 @@ function processAliExternalClassesHack (el, options) {
1684
2070
  }
1685
2071
  })
1686
2072
 
1687
- if (options.hasScoped && isComponent) {
2073
+ if (hasScoped && isComponent) {
1688
2074
  options.externalClasses.forEach((className) => {
1689
2075
  const externalClass = getAndRemoveAttr(el, className).val
1690
2076
  if (externalClass) {
1691
2077
  addAttrs(el, [{
1692
2078
  name: className,
1693
- value: `${externalClass} ${options.moduleId}`
2079
+ value: `${externalClass} ${moduleId}`
1694
2080
  }])
1695
2081
  }
1696
2082
  })
@@ -1758,10 +2144,9 @@ function processWebExternalClassesHack (el, options) {
1758
2144
  }
1759
2145
  }
1760
2146
 
1761
- function processScoped (el, options) {
1762
- if (options.hasScoped && isRealNode(el)) {
1763
- const moduleId = options.moduleId
1764
- const rootModuleId = options.isComponent ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
2147
+ function processScoped (el) {
2148
+ if (hasScoped && isRealNode(el)) {
2149
+ const rootModuleId = ctorType === 'component' ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
1765
2150
  const staticClass = getAndRemoveAttr(el, 'class').val
1766
2151
  addAttrs(el, [{
1767
2152
  name: 'class',
@@ -1779,12 +2164,16 @@ function processBuiltInComponents (el, meta) {
1779
2164
  }
1780
2165
  const tag = el.tag
1781
2166
  if (!meta.builtInComponentsMap[tag]) {
1782
- meta.builtInComponentsMap[tag] = `${builtInComponentsPrefix}/${mode}/${tag}.vue`
2167
+ if (isReact(mode)) {
2168
+ meta.builtInComponentsMap[tag] = `${builtInComponentsPrefix}/react/${tag}`
2169
+ } else {
2170
+ meta.builtInComponentsMap[tag] = `${builtInComponentsPrefix}/${mode}/${tag}`
2171
+ }
1783
2172
  }
1784
2173
  }
1785
2174
  }
1786
2175
 
1787
- function processAliAddComponentRootView (el, options) {
2176
+ function postProcessAliComponentRootView (el, options) {
1788
2177
  const processAttrsConditions = [
1789
2178
  { condition: /^(on|catch)Tap$/, action: 'clone' },
1790
2179
  { condition: /^(on|catch)TouchStart$/, action: 'clone' },
@@ -1798,25 +2187,25 @@ function processAliAddComponentRootView (el, options) {
1798
2187
  { condition: /^slot$/, action: 'move' }
1799
2188
  ]
1800
2189
  const processAppendAttrsRules = [
1801
- { name: 'class', value: `${MPX_ROOT_VIEW} host-${options.moduleId}` }
2190
+ { name: 'class', value: `${MPX_ROOT_VIEW} host-${moduleId}` }
1802
2191
  ]
1803
- const newElAttrs = []
2192
+ const newAttrs = []
1804
2193
  const allAttrs = cloneAttrsList(el.attrsList)
1805
2194
 
1806
2195
  function processClone (attr) {
1807
- newElAttrs.push(attr)
2196
+ newAttrs.push(attr)
1808
2197
  }
1809
2198
 
1810
2199
  function processMove (attr) {
1811
2200
  getAndRemoveAttr(el, attr.name)
1812
- newElAttrs.push(attr)
2201
+ newAttrs.push(attr)
1813
2202
  }
1814
2203
 
1815
2204
  function processAppendRules (el) {
1816
2205
  processAppendAttrsRules.forEach((rule) => {
1817
2206
  const getNeedAppendAttrValue = el.attrsMap[rule.name]
1818
2207
  const value = getNeedAppendAttrValue ? getNeedAppendAttrValue + ' ' + rule.value : rule.value
1819
- newElAttrs.push({
2208
+ newAttrs.push({
1820
2209
  name: rule.name,
1821
2210
  value
1822
2211
  })
@@ -1837,32 +2226,27 @@ function processAliAddComponentRootView (el, options) {
1837
2226
  })
1838
2227
 
1839
2228
  processAppendRules(el)
1840
- const componentWrapView = createASTElement('view', newElAttrs)
1841
- moveBaseDirective(componentWrapView, el)
1842
- if (el.is && el.components) {
1843
- el = postProcessComponentIs(el)
1844
- }
1845
-
2229
+ const componentWrapView = createASTElement('view', newAttrs)
1846
2230
  replaceNode(el, componentWrapView, true)
1847
2231
  addChild(componentWrapView, el)
1848
- return componentWrapView
2232
+ postMoveBaseDirective(componentWrapView, el)
1849
2233
  }
1850
2234
 
1851
2235
  // 有virtualHost情况wx组件注入virtualHost。无virtualHost阿里组件注入root-view。其他跳过。
1852
2236
  function getVirtualHostRoot (options, meta) {
1853
2237
  if (srcMode === 'wx') {
1854
- if (options.isComponent) {
1855
- if ((mode === 'wx') && options.hasVirtualHost) {
2238
+ if (ctorType === 'component') {
2239
+ if (mode === 'wx' && hasVirtualHost) {
1856
2240
  // wx组件注入virtualHost配置
1857
2241
  !meta.options && (meta.options = {})
1858
2242
  meta.options.virtualHost = true
1859
2243
  }
1860
- if ((mode === 'web') && !options.hasVirtualHost) {
2244
+ if (mode === 'web' && !hasVirtualHost) {
1861
2245
  // ali组件根节点实体化
1862
2246
  const rootView = createASTElement('view', [
1863
2247
  {
1864
2248
  name: 'class',
1865
- value: `${MPX_ROOT_VIEW} host-${options.moduleId}`
2249
+ value: `${MPX_ROOT_VIEW} host-${moduleId}`
1866
2250
  },
1867
2251
  {
1868
2252
  name: 'v-on',
@@ -1872,12 +2256,21 @@ function getVirtualHostRoot (options, meta) {
1872
2256
  processElement(rootView, rootView, options, meta)
1873
2257
  return rootView
1874
2258
  }
1875
- }
1876
- if (options.isPage) {
1877
- if (mode === 'web') {
1878
- return createASTElement('page', [])
2259
+ if (isReact(mode) && !hasVirtualHost) {
2260
+ const rootView = createASTElement('view', [
2261
+ {
2262
+ name: 'class',
2263
+ value: `${MPX_ROOT_VIEW} host-${moduleId}`
2264
+ }
2265
+ ])
2266
+ rootView.isRoot = true
2267
+ processElement(rootView, rootView, options, meta)
2268
+ return rootView
1879
2269
  }
1880
2270
  }
2271
+ if (mode === 'web' && ctorType === 'page') {
2272
+ return createASTElement('page')
2273
+ }
1881
2274
  }
1882
2275
  return getTempNode()
1883
2276
  }
@@ -1888,8 +2281,8 @@ function processShow (el, options, root) {
1888
2281
  let show = getAndRemoveAttr(el, config[mode].directive.show).val
1889
2282
  if (mode === 'swan') show = wrapMustache(show)
1890
2283
 
1891
- if (options.hasVirtualHost) {
1892
- if (options.isComponent && el.parent === root && isRealNode(el)) {
2284
+ if (hasVirtualHost) {
2285
+ if (ctorType === 'component' && el.parent === root && isRealNode(el)) {
1893
2286
  if (show !== undefined) {
1894
2287
  show = `{{${parseMustacheWithContext(show).result}&&mpxShow}}`
1895
2288
  } else {
@@ -1939,7 +2332,7 @@ function postProcessTemplate (el) {
1939
2332
  }
1940
2333
  }
1941
2334
 
1942
- const isValidMode = makeMap('wx,ali,swan,tt,qq,web,qa,jd,dd,tenon,noMode')
2335
+ const isValidMode = makeMap('wx,ali,swan,tt,qq,web,qa,jd,dd,tenon,ios,android,noMode')
1943
2336
 
1944
2337
  function isValidModeP (i) {
1945
2338
  return isValidMode(i[0] === '_' ? i.slice(1) : i)
@@ -2067,6 +2460,12 @@ function processMpxTagName (el) {
2067
2460
  }
2068
2461
  }
2069
2462
 
2463
+ function postProcessComponent (el, options) {
2464
+ if (isComponentNode(el, options)) {
2465
+ el.isComponent = true
2466
+ }
2467
+ }
2468
+
2070
2469
  function processElement (el, root, options, meta) {
2071
2470
  processAtMode(el)
2072
2471
  // 如果已经标记了这个元素要被清除,直接return跳过后续处理步骤
@@ -2093,9 +2492,24 @@ function processElement (el, root, options, meta) {
2093
2492
  // 收集内建组件
2094
2493
  processBuiltInComponents(el, meta)
2095
2494
  // 预处理代码维度条件编译
2096
- processIfForWeb(el)
2495
+ processIfWeb(el)
2097
2496
  processWebExternalClassesHack(el, options)
2098
- processComponentGenericsForWeb(el, options, meta)
2497
+ processComponentGenericsWeb(el, options, meta)
2498
+ return
2499
+ }
2500
+
2501
+ if (isReact(mode)) {
2502
+ // 收集内建组件
2503
+ processBuiltInComponents(el, meta)
2504
+ // 预处理代码维度条件编译
2505
+ processIf(el)
2506
+ processFor(el)
2507
+ processRefReact(el, options, meta)
2508
+ processStyleReact(el)
2509
+ processEventReact(el, options, meta)
2510
+ processComponentIs(el, options)
2511
+ processSlotReact(el)
2512
+ processAttrs(el, options)
2099
2513
  return
2100
2514
  }
2101
2515
 
@@ -2103,7 +2517,7 @@ function processElement (el, root, options, meta) {
2103
2517
 
2104
2518
  // 仅ali平台需要scoped模拟样式隔离
2105
2519
  if (mode === 'ali') {
2106
- processScoped(el, options)
2520
+ processScoped(el)
2107
2521
  }
2108
2522
 
2109
2523
  if (transAli) {
@@ -2121,7 +2535,7 @@ function processElement (el, root, options, meta) {
2121
2535
  }
2122
2536
 
2123
2537
  if (!pass) {
2124
- processBindEvent(el, options)
2538
+ processEvent(el, options)
2125
2539
  processComponentIs(el, options)
2126
2540
  }
2127
2541
 
@@ -2136,15 +2550,20 @@ function closeElement (el, meta, options) {
2136
2550
  postProcessIf(el)
2137
2551
  return
2138
2552
  }
2553
+ if (isReact(mode)) {
2554
+ postProcessForReact(el)
2555
+ postProcessIfReact(el)
2556
+ // flag component for react
2557
+ postProcessComponent(el, options)
2558
+ return
2559
+ }
2139
2560
  const pass = isNative || postProcessTemplate(el) || processingTemplate
2140
2561
  postProcessWxs(el, meta)
2141
-
2142
2562
  if (!pass) {
2143
- if (isComponentNode(el, options) && !options.hasVirtualHost && mode === 'ali') {
2144
- el = processAliAddComponentRootView(el, options)
2145
- } else {
2146
- el = postProcessComponentIs(el)
2563
+ if (isComponentNode(el, options) && !hasVirtualHost && mode === 'ali') {
2564
+ postProcessAliComponentRootView(el, options)
2147
2565
  }
2566
+ postProcessComponentIs(el)
2148
2567
  }
2149
2568
  postProcessFor(el)
2150
2569
  postProcessIf(el)
@@ -2182,17 +2601,14 @@ function postProcessComponentIs (el) {
2182
2601
  if (el.is && el.components) {
2183
2602
  let tempNode
2184
2603
  if (el.for || el.if || el.elseif || el.else) {
2185
- tempNode = createASTElement('block', [])
2186
- moveBaseDirective(tempNode, el)
2604
+ tempNode = createASTElement('block')
2187
2605
  } else {
2188
2606
  tempNode = getTempNode()
2189
2607
  }
2190
- let range = []
2191
- if (el.attrsMap.range) {
2192
- range = getAndRemoveAttr(el, 'range').val.split(',')
2193
- }
2608
+ replaceNode(el, tempNode, true)
2609
+ postMoveBaseDirective(tempNode, el)
2610
+
2194
2611
  el.components.forEach(function (component) {
2195
- if (range.length > 0 && !range.includes(component)) return
2196
2612
  const newChild = createASTElement(component, cloneAttrsList(el.attrsList), tempNode)
2197
2613
  newChild.if = {
2198
2614
  raw: `{{${el.is} === ${stringify(component)}}}`,
@@ -2209,10 +2625,9 @@ function postProcessComponentIs (el) {
2209
2625
  if (!el.parent) {
2210
2626
  error$1('Dynamic component can not be the template root, considering wrapping it with <view> or <text> tag!')
2211
2627
  } else {
2212
- el = replaceNode(el, tempNode, true) || el
2628
+ replaceNode(el, tempNode, true)
2213
2629
  }
2214
2630
  }
2215
- return el
2216
2631
  }
2217
2632
 
2218
2633
  function stringifyAttr (val) {
@@ -2292,8 +2707,8 @@ function findPrevNode (node) {
2292
2707
  }
2293
2708
  }
2294
2709
 
2295
- function replaceNode (node, newNode, reserveNode) {
2296
- if (!reserveNode) deleteErrorInResultMap(node)
2710
+ function replaceNode (node, newNode, reserveError) {
2711
+ if (!reserveError) deleteErrorInResultMap(node)
2297
2712
  const parent = node.parent
2298
2713
  if (parent) {
2299
2714
  const index = parent.children.indexOf(node)
@@ -2305,8 +2720,8 @@ function replaceNode (node, newNode, reserveNode) {
2305
2720
  }
2306
2721
  }
2307
2722
 
2308
- function removeNode (node, reserveNode) {
2309
- if (!reserveNode) deleteErrorInResultMap(node)
2723
+ function removeNode (node, reserveError) {
2724
+ if (!reserveError) deleteErrorInResultMap(node)
2310
2725
  const parent = node.parent
2311
2726
  if (parent) {
2312
2727
  const index = parent.children.indexOf(node)
@@ -2401,169 +2816,6 @@ function genNode (node) {
2401
2816
  return exp
2402
2817
  }
2403
2818
 
2404
- /**
2405
- * 处理可选链用法
2406
- * @param str
2407
- * @returns
2408
- */
2409
- function parseOptionChain (str) {
2410
- const wxsName = `${optionsChainWxsName}.g`
2411
- let optionsRes
2412
- while (optionsRes = /\?\./.exec(str)) {
2413
- const strLength = str.length
2414
- const grammarMap = {
2415
- init () {
2416
- const initKey = [
2417
- {
2418
- mapKey: '[]',
2419
- mapValue: [
2420
- {
2421
- key: '[',
2422
- value: 1
2423
- },
2424
- {
2425
- key: ']',
2426
- value: -1
2427
- }
2428
- ]
2429
- },
2430
- {
2431
- mapKey: '()',
2432
- mapValue: [
2433
- {
2434
- key: '(',
2435
- value: 1
2436
- },
2437
- {
2438
- key: ')',
2439
- value: -1
2440
- }
2441
- ]
2442
- }
2443
- ]
2444
- this.count = {}
2445
- initKey.forEach(({ mapKey, mapValue }) => {
2446
- mapValue.forEach(({ key, value }) => {
2447
- this[key] = this.changeState(mapKey, value)
2448
- })
2449
- })
2450
- },
2451
- changeState (key, value) {
2452
- if (!this.count[key]) {
2453
- this.count[key] = 0
2454
- }
2455
- return () => {
2456
- this.count[key] = this.count[key] + value
2457
- return this.count[key]
2458
- }
2459
- },
2460
- checkState () {
2461
- return Object.values(this.count).find(i => i)
2462
- }
2463
- }
2464
- let leftIndex = optionsRes.index
2465
- let rightIndex = leftIndex + 2
2466
- let haveNotGetValue = true
2467
- let chainValue = ''
2468
- let chainKey = ''
2469
- let notCheck = false
2470
- grammarMap.init()
2471
- // 查 ?. 左边值
2472
- while (haveNotGetValue && leftIndex > 0) {
2473
- const left = str[leftIndex - 1]
2474
- const grammar = grammarMap[left]
2475
- if (notCheck) {
2476
- // 处于表达式内
2477
- chainValue = left + chainValue
2478
- if (grammar) {
2479
- grammar()
2480
- if (!grammarMap.checkState()) {
2481
- // 表达式结束
2482
- notCheck = false
2483
- }
2484
- }
2485
- } else if (~[']', ')'].indexOf(left)) {
2486
- // 命中表达式,开始记录表达式
2487
- chainValue = left + chainValue
2488
- notCheck = true
2489
- grammar()
2490
- } else if (left !== ' ') {
2491
- if (!/[A-Za-z0-9_$.]/.test(left)) {
2492
- // 结束
2493
- haveNotGetValue = false
2494
- leftIndex++
2495
- } else {
2496
- // 正常语法
2497
- chainValue = left + chainValue
2498
- }
2499
- }
2500
- leftIndex--
2501
- }
2502
- if (grammarMap.checkState() && haveNotGetValue) {
2503
- // 值查找结束但是语法未闭合或者处理到边界还未结束,抛异常
2504
- throw new Error('[optionChain] option value illegal!!!')
2505
- }
2506
- haveNotGetValue = true
2507
- let keyValue = ''
2508
- // 查 ?. 右边key
2509
- while (haveNotGetValue && rightIndex < strLength) {
2510
- const right = str[rightIndex]
2511
- const grammar = grammarMap[right]
2512
- if (notCheck) {
2513
- // 处于表达式内
2514
- if (grammar) {
2515
- grammar()
2516
- if (grammarMap.checkState()) {
2517
- keyValue += right
2518
- } else {
2519
- // 表达式结束
2520
- notCheck = false
2521
- chainKey += `,${keyValue}`
2522
- keyValue = ''
2523
- }
2524
- } else {
2525
- keyValue += right
2526
- }
2527
- } else if (~['[', '('].indexOf(right)) {
2528
- // 命中表达式,开始记录表达式
2529
- grammar()
2530
- if (keyValue) {
2531
- chainKey += `,'${keyValue}'`
2532
- keyValue = ''
2533
- }
2534
- notCheck = true
2535
- } else if (!/[A-Za-z0-9_$.?]/.test(right)) {
2536
- // 结束
2537
- haveNotGetValue = false
2538
- rightIndex--
2539
- } else if (right !== '?') {
2540
- // 正常语法
2541
- if (right === '.') {
2542
- if (keyValue) {
2543
- chainKey += `,'${keyValue}'`
2544
- }
2545
- keyValue = ''
2546
- } else {
2547
- keyValue += right
2548
- }
2549
- }
2550
- rightIndex++
2551
- }
2552
- if (grammarMap.checkState() && haveNotGetValue) {
2553
- // key值查找结束但是语法未闭合或者处理到边界还未结束,抛异常
2554
- throw new Error('[optionChain] option key illegal!!!')
2555
- }
2556
- if (keyValue) {
2557
- chainKey += `,'${keyValue}'`
2558
- }
2559
- str = str.slice(0, leftIndex) + `${wxsName}(${chainValue},[${chainKey.slice(1)}])` + str.slice(rightIndex)
2560
- if (!haveOptionChain) {
2561
- haveOptionChain = true
2562
- }
2563
- }
2564
- return str
2565
- }
2566
-
2567
2819
  module.exports = {
2568
2820
  parseComponent,
2569
2821
  parse,