@mpxjs/webpack-plugin 2.10.18 → 2.10.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/lib/dependencies/ResolveDependency.js +2 -2
  2. package/lib/index.js +25 -6
  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/platform/create-diagnostic.js +168 -0
  9. package/lib/platform/index.js +16 -3
  10. package/lib/platform/json/wx/index.js +66 -17
  11. package/lib/platform/run-rules.js +9 -5
  12. package/lib/platform/style/wx/index.js +4 -3
  13. package/lib/platform/template/normalize-component-rules.js +7 -9
  14. package/lib/platform/template/wx/component-config/camera.js +12 -0
  15. package/lib/platform/template/wx/component-config/custom-built-in-component.js +34 -0
  16. package/lib/platform/template/wx/component-config/index.js +18 -3
  17. package/lib/platform/template/wx/component-config/input.js +1 -7
  18. package/lib/platform/template/wx/component-config/movable-view.js +1 -7
  19. package/lib/platform/template/wx/component-config/text.js +1 -1
  20. package/lib/platform/template/wx/component-config/textarea.js +1 -25
  21. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  22. package/lib/platform/template/wx/index.js +48 -34
  23. package/lib/react/processJSON.js +7 -4
  24. package/lib/react/processStyles.js +22 -8
  25. package/lib/react/processTemplate.js +85 -41
  26. package/lib/react/style-helper.js +120 -85
  27. package/lib/react/template-loader.js +148 -0
  28. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +1 -1
  29. package/lib/runtime/components/react/dist/mpx-camera.d.ts +31 -0
  30. package/lib/runtime/components/react/dist/mpx-camera.jsx +270 -0
  31. package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
  32. package/lib/runtime/components/react/dist/mpx-image.jsx +1 -2
  33. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +1 -1
  34. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +92 -15
  35. package/lib/runtime/components/react/dist/mpx-web-view.jsx +1 -1
  36. package/lib/runtime/components/react/dist/utils.jsx +3 -2
  37. package/lib/runtime/components/react/mpx-async-suspense.tsx +2 -1
  38. package/lib/runtime/components/react/mpx-camera.tsx +358 -0
  39. package/lib/runtime/components/react/mpx-image.tsx +1 -3
  40. package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
  41. package/lib/runtime/components/react/mpx-scroll-view.tsx +106 -16
  42. package/lib/runtime/components/react/mpx-web-view.tsx +1 -1
  43. package/lib/runtime/components/react/utils.tsx +3 -2
  44. package/lib/runtime/components/wx/default-component.mpx +9 -0
  45. package/lib/runtime/components/wx/default-page.mpx +3 -11
  46. package/lib/runtime/optionProcessor.d.ts +2 -0
  47. package/lib/runtime/optionProcessor.js +77 -1
  48. package/lib/style-compiler/index.js +2 -0
  49. package/lib/style-compiler/plugins/remove-strip-conditional-comments.js +14 -0
  50. package/lib/style-compiler/strip-conditional.js +40 -26
  51. package/lib/template-compiler/compiler.js +274 -116
  52. package/lib/template-compiler/gen-node-react.js +35 -7
  53. package/lib/template-compiler/index.js +9 -7
  54. package/lib/utils/const.js +4 -1
  55. package/lib/utils/dom-tag-config.js +1 -1
  56. package/lib/utils/partial-compile-rules.js +27 -0
  57. package/lib/utils/pre-process-json.js +3 -0
  58. package/lib/utils/source-location.js +96 -0
  59. package/lib/web/compile-wx-template-fragment.js +68 -0
  60. package/lib/web/index.js +2 -0
  61. package/lib/web/processJSON.js +7 -4
  62. package/lib/web/processScript.js +41 -3
  63. package/lib/web/processTemplate.js +61 -19
  64. package/lib/web/template-loader.js +123 -0
  65. package/lib/web/template-shared.js +48 -0
  66. package/lib/wxml/loader.js +3 -2
  67. package/lib/wxss/loader.js +1 -1
  68. package/lib/wxss/utils.js +6 -4
  69. package/package.json +12 -4
  70. package/lib/platform/template/wx/component-config/component.js +0 -41
@@ -1,7 +1,7 @@
1
1
  const JSON5 = require('json5')
2
2
  const he = require('he')
3
3
  const config = require('../config')
4
- const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID, PARENT_MODULE_ID, MPX_TAG_PAGE_SELECTOR } = require('../utils/const')
4
+ const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID, PARENT_MODULE_ID, MPX_TAG_PAGE_SELECTOR, MPX_TEMPLATE_COMPONENT_PREFIX, STYLE_PAD_PLACEHOLDER } = require('../utils/const')
5
5
  const normalize = require('../utils/normalize')
6
6
  const { normalizeCondition } = require('../utils/match-condition')
7
7
  const isValidIdentifierStr = require('../utils/is-valid-identifier-str')
@@ -17,6 +17,8 @@ const { parseExp } = require('./parse-exps')
17
17
  const shallowStringify = require('../utils/shallow-stringify')
18
18
  const { isReact, isWeb, isNoMode } = require('../utils/env')
19
19
  const { capitalToHyphen } = require('../utils/string')
20
+ const { isNativeMiniTag } = require('../utils/dom-tag-config')
21
+ const { offsetToLoc } = require('../utils/source-location')
20
22
 
21
23
  const no = function () {
22
24
  return false
@@ -105,6 +107,7 @@ let hasVirtualHost
105
107
  let isCustomText
106
108
  let runtimeCompile
107
109
  let rulesRunner
110
+ let customBuiltInComponentsOpt
108
111
  let currentEl
109
112
  let injectNodes = []
110
113
  let forScopes = []
@@ -180,9 +183,9 @@ const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
180
183
  // 添加~前缀避免wxs绝对路径在存在projectRoot时被拼接为错误路径
181
184
  const i18nWxsRequest = '~' + i18nWxsLoaderPath + '!' + i18nWxsPath
182
185
  const i18nModuleName = '_i_'
183
- const stringifyWxsPath = '~' + normalize.lib('runtime/stringify.wxs')
186
+ const stringifyWxsRequest = '~' + normalize.lib('runtime/stringify.wxs')
184
187
  const stringifyModuleName = '_s_'
185
- const optionalChainWxsPath = '~' + normalize.lib('runtime/oc.wxs')
188
+ const optionalChainWxsRequest = '~' + normalize.lib('runtime/oc.wxs')
186
189
  const optionalChainWxsName = '_oc_' // 改成_oc解决web下_o重名问题
187
190
 
188
191
  const tagRES = /(\{\{(?:.|\n|\r)+?\}\})(?!})/
@@ -339,7 +342,10 @@ function parseHTML (html, options) {
339
342
  advance(start[0].length)
340
343
  let end, attr
341
344
  while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
345
+ const attrStart = index
342
346
  advance(attr[0].length)
347
+ attr.start = attrStart
348
+ attr.end = index
343
349
  match.attrs.push(attr)
344
350
  }
345
351
  if (end) {
@@ -391,7 +397,9 @@ function parseHTML (html, options) {
391
397
  }
392
398
  attrs[i] = {
393
399
  name: args[1],
394
- value: decode(value)
400
+ value: decode(value),
401
+ start: args.start,
402
+ end: args.end
395
403
  }
396
404
  }
397
405
 
@@ -584,8 +592,7 @@ function parseComponent (content, options) {
584
592
  let text = content.slice(currentBlock.start, currentBlock.end)
585
593
  // pad content so that linters and pre-processors can output correct
586
594
  // line numbers in errors and warnings
587
- // stylus编译遇到大量空行时会出现栈溢出,故针对stylus不走pad
588
- if (options.pad && !(currentBlock.tag === 'style' && currentBlock.lang === 'stylus')) {
595
+ if (options.pad) {
589
596
  text = padContent(currentBlock, options.pad) + text
590
597
  }
591
598
  currentBlock.content = text
@@ -595,6 +602,10 @@ function parseComponent (content, options) {
595
602
  }
596
603
 
597
604
  function padContent (block, pad) {
605
+ if (block.tag === 'style' && pad === 'line') {
606
+ const offset = content.slice(0, block.start).split(splitRE).length
607
+ return Array(offset).join(`/* ${STYLE_PAD_PLACEHOLDER} */\n`)
608
+ }
598
609
  if (pad === 'space') {
599
610
  return content.slice(0, block.start).replace(replaceRE, ' ')
600
611
  } else {
@@ -617,9 +628,9 @@ function parse (template, options) {
617
628
  warn$1 = options.warn || baseWarn
618
629
  error$1 = options.error || baseError
619
630
  mode = options.mode || 'wx'
631
+ srcMode = options.srcMode || mode
620
632
  env = options.env
621
633
  defs = options.defs || {}
622
- srcMode = options.srcMode || mode
623
634
  ctorType = options.ctorType
624
635
  moduleId = options.moduleId
625
636
  isNative = options.isNative
@@ -640,25 +651,26 @@ function parse (template, options) {
640
651
  processingTemplate = false
641
652
  rulesResultMap.clear()
642
653
  componentGenerics = options.componentGenerics || {}
654
+ usingComponentsInfo = options.usingComponentsInfo || {}
655
+ usingComponents = Object.keys(usingComponentsInfo)
656
+ customBuiltInComponentsOpt = options.customBuiltInComponents || null
657
+
643
658
  // 初始化跨平台语法检测配置(每次解析时只初始化一次)
644
659
  crossPlatformConfig = initCrossPlatformConfig()
645
660
 
646
- usingComponents = Object.keys(options.usingComponentsInfo)
647
- usingComponentsInfo = options.usingComponentsInfo
648
-
649
- const _warn = content => {
661
+ const _warn = (content, loc) => {
650
662
  const currentElementRuleResult = rulesResultMap.get(currentEl) || rulesResultMap.set(currentEl, {
651
663
  warnArray: [],
652
664
  errorArray: []
653
665
  }).get(currentEl)
654
- currentElementRuleResult.warnArray.push(content)
666
+ currentElementRuleResult.warnArray.push({ content, loc })
655
667
  }
656
- const _error = content => {
668
+ const _error = (content, loc) => {
657
669
  const currentElementRuleResult = rulesResultMap.get(currentEl) || rulesResultMap.set(currentEl, {
658
670
  warnArray: [],
659
671
  errorArray: []
660
672
  }).get(currentEl)
661
- currentElementRuleResult.errorArray.push(content)
673
+ currentElementRuleResult.errorArray.push({ content, loc })
662
674
  }
663
675
 
664
676
  rulesRunner = getRulesRunner({
@@ -667,10 +679,15 @@ function parse (template, options) {
667
679
  type: 'template',
668
680
  testKey: 'tag',
669
681
  data: {
670
- usingComponents
682
+ usingComponents,
683
+ customBuiltInComponents: customBuiltInComponentsOpt
671
684
  },
672
685
  warn: _warn,
673
- error: _error
686
+ error: _error,
687
+ diagnostic: {
688
+ file: filePath,
689
+ source: template
690
+ }
674
691
  })
675
692
 
676
693
  const stack = []
@@ -700,12 +717,20 @@ function parse (template, options) {
700
717
  isUnaryTag: options.isUnaryTag,
701
718
  canBeLeftOpenTag: options.canBeLeftOpenTag,
702
719
  shouldKeepComment: true,
703
- start: function start (tag, attrs, unary) {
720
+ start: function start (tag, attrs, unary, start, end) {
704
721
  // check namespace.
705
722
  // inherit parent ns if there is one
706
723
  const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag)
707
724
 
708
725
  const element = createASTElement(tag, attrs, currentParent)
726
+ element.start = start
727
+ element.end = end
728
+ element.loc = offsetToLoc(template, start, end)
729
+ element.attrsList.forEach((attr) => {
730
+ if (attr.start != null) {
731
+ attr.loc = offsetToLoc(template, attr.start, attr.end)
732
+ }
733
+ })
709
734
 
710
735
  if (ns) {
711
736
  element.ns = ns
@@ -811,7 +836,7 @@ function parse (template, options) {
811
836
  }
812
837
 
813
838
  if (hasOptionalChaining) {
814
- injectWxs(meta, optionalChainWxsName, optionalChainWxsPath)
839
+ injectWxs(meta, optionalChainWxsName, optionalChainWxsRequest)
815
840
  }
816
841
 
817
842
  injectNodes.forEach((node) => {
@@ -819,8 +844,8 @@ function parse (template, options) {
819
844
  })
820
845
 
821
846
  rulesResultMap.forEach((val) => {
822
- Array.isArray(val.warnArray) && val.warnArray.forEach(item => warn$1(item))
823
- Array.isArray(val.errorArray) && val.errorArray.forEach(item => error$1(item))
847
+ Array.isArray(val.warnArray) && val.warnArray.forEach(item => warn$1(item.content, item.loc))
848
+ Array.isArray(val.errorArray) && val.errorArray.forEach(item => error$1(item.content, item.loc))
824
849
  })
825
850
 
826
851
  if (!tagNames.has('component') && !tagNames.has('template') && options.checkUsingComponents) {
@@ -1703,6 +1728,10 @@ function parseMustacheWithContext (raw = '') {
1703
1728
  const funcNameRE = new RegExp(`(?<![A-Za-z0-9_$.])${i18nFuncName}\\(`)
1704
1729
  const funcNameREG = new RegExp(`(?<![A-Za-z0-9_$.])${i18nFuncName}\\(`, 'g')
1705
1730
  if (funcNameRE.test(exp)) {
1731
+ if (processingTemplate) {
1732
+ warn$1('i18n function is not supported in template!')
1733
+ break
1734
+ }
1706
1735
  if (i18n.useComputed || !i18nFuncName.startsWith('\\$')) {
1707
1736
  const i18nInjectComputedKey = `_i${i18nInjectableComputed.length + 1}`
1708
1737
  i18nInjectableComputed.push(`${i18nInjectComputedKey} () {\nreturn ${exp.trim()}}`)
@@ -2381,7 +2410,7 @@ function processClass (el, meta) {
2381
2410
  // swan中externalClass是通过编译时静态实现,因此需要保留原有的staticClass形式避免externalClass失效
2382
2411
  value: mode === 'swan' && staticClass ? `${staticClass} {{${stringifyModuleName}.c('', ${dynamicClassExp})}}` : `{{${stringifyModuleName}.c(${staticClassExp}, ${dynamicClassExp})}}`
2383
2412
  }])
2384
- injectWxs(meta, stringifyModuleName, stringifyWxsPath)
2413
+ injectWxs(meta, stringifyModuleName, stringifyWxsRequest)
2385
2414
  } else if (staticClass) {
2386
2415
  addAttrs(el, [{
2387
2416
  name: targetType,
@@ -2414,7 +2443,7 @@ function processStyle (el, meta) {
2414
2443
  name: targetType,
2415
2444
  value: `{{${stringifyModuleName}.s(${staticStyleExp}, ${dynamicStyleExp})}}`
2416
2445
  }])
2417
- injectWxs(meta, stringifyModuleName, stringifyWxsPath)
2446
+ injectWxs(meta, stringifyModuleName, stringifyWxsRequest)
2418
2447
  } else if (staticStyle) {
2419
2448
  addAttrs(el, [{
2420
2449
  name: targetType,
@@ -2432,6 +2461,10 @@ function isRealNode (el) {
2432
2461
  }
2433
2462
 
2434
2463
  function isComponentNode (el) {
2464
+ if (processingTemplate) {
2465
+ // 处理模版时无法获取真实的usingComponents信息,除了小程序基础组件和框架内建组件外都识别为用户组件
2466
+ return isRealNode(el) && !isNativeMiniTag(el.tag) && !el.isBuiltIn
2467
+ }
2435
2468
  return usingComponents.indexOf(el.tag) !== -1 || el.tag === 'component' || componentGenerics[el.tag]
2436
2469
  }
2437
2470
 
@@ -2443,81 +2476,102 @@ function isReactComponent (el) {
2443
2476
  return !isComponentNode(el) && isRealNode(el) && !el.isBuiltIn
2444
2477
  }
2445
2478
 
2479
+ function processWebClass (classLikeAttrName, classLikeAttrValue, el, options, processingWebTemplate) {
2480
+ let classNames = classLikeAttrValue.split(/\s+/)
2481
+ let hasExternalClass = false
2482
+ const attrsSource = processingWebTemplate ? '(__mpxHost && __mpxHost.$attrs || {})' : '$attrs'
2483
+ classNames = classNames.map((className) => {
2484
+ if (options.externalClasses.includes(className)) {
2485
+ hasExternalClass = true
2486
+ return `(${attrsSource}[${stringify(className)}] || '')`
2487
+ }
2488
+ return stringify(className)
2489
+ })
2490
+ if (hasExternalClass) {
2491
+ classNames.push(`(${attrsSource}[${stringify(PARENT_MODULE_ID)}] || '')`)
2492
+ }
2493
+ if (classLikeAttrName === 'class') {
2494
+ const dynamicClass = getAndRemoveAttr(el, ':class').val
2495
+ if (dynamicClass) classNames.push(dynamicClass)
2496
+ addAttrs(el, [{
2497
+ name: ':class',
2498
+ value: `[${classNames}]`
2499
+ }])
2500
+ } else {
2501
+ addAttrs(el, [{
2502
+ name: ':' + classLikeAttrName,
2503
+ value: `[${classNames}].join(' ')`
2504
+ }])
2505
+ }
2506
+ }
2507
+
2508
+ function processAliClass (classLikeAttrName, classLikeAttrValue, el, options) {
2509
+ let hasExternalClass = false
2510
+ options.externalClasses.forEach((className) => {
2511
+ const reg = new RegExp('\\b' + className + '\\b', 'g')
2512
+ const replacementClassName = dash2hump(className)
2513
+ if (classLikeAttrValue.includes(className)) hasExternalClass = true
2514
+ classLikeAttrValue = classLikeAttrValue.replace(reg, `{{${replacementClassName} || ''}}`)
2515
+ })
2516
+ if (hasExternalClass) {
2517
+ classLikeAttrValue += ` {{${PARENT_MODULE_ID} || ''}}`
2518
+ }
2519
+ addAttrs(el, [{
2520
+ name: classLikeAttrName,
2521
+ value: classLikeAttrValue
2522
+ }])
2523
+ }
2524
+
2446
2525
  function processExternalClasses (el, options) {
2447
2526
  const isComponent = isComponentNode(el)
2448
2527
  const classLikeAttrNames = isComponent ? ['class'].concat(options.externalClasses) : ['class']
2528
+ const processingWebTemplate = isWeb(mode) && processingTemplate
2449
2529
 
2450
2530
  classLikeAttrNames.forEach((classLikeAttrName) => {
2451
2531
  const classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
2452
2532
  if (classLikeAttrValue) {
2453
2533
  if (mode === 'web') {
2454
- processWebClass(classLikeAttrName, classLikeAttrValue, el, options)
2534
+ processWebClass(classLikeAttrName, classLikeAttrValue, el, options, processingWebTemplate)
2455
2535
  } else {
2456
2536
  processAliClass(classLikeAttrName, classLikeAttrValue, el, options)
2457
2537
  }
2458
2538
  }
2459
2539
  })
2460
2540
 
2461
- if (hasScoped && isComponent) {
2541
+ if ((hasScoped || processingWebTemplate) && isComponent) {
2462
2542
  const needAddModuleId = options.externalClasses.some((className) => {
2463
2543
  return el.attrsMap[className] || (mode === 'web' && el.attrsMap[':' + className])
2464
2544
  })
2465
2545
 
2466
2546
  if (needAddModuleId) {
2467
- addAttrs(el, [{
2468
- name: PARENT_MODULE_ID,
2469
- value: `${moduleId}`
2470
- }])
2471
- }
2472
- }
2473
- function processWebClass (classLikeAttrName, classLikeAttrValue, el, options) {
2474
- let classNames = classLikeAttrValue.split(/\s+/)
2475
- let hasExternalClass = false
2476
- classNames = classNames.map((className) => {
2477
- if (options.externalClasses.includes(className)) {
2478
- hasExternalClass = true
2479
- return `($attrs[${stringify(className)}] || '')`
2547
+ if (processingWebTemplate) {
2548
+ addAttrs(el, [{
2549
+ name: ':' + PARENT_MODULE_ID,
2550
+ value: '(__mpxHost && __mpxHost.$options.__mpxScoped ? (__mpxHost.$options.__mpxModuleId || "") : "")'
2551
+ }])
2552
+ } else {
2553
+ addAttrs(el, [{
2554
+ name: PARENT_MODULE_ID,
2555
+ value: `${moduleId}`
2556
+ }])
2480
2557
  }
2481
- return stringify(className)
2482
- })
2483
- if (hasExternalClass) {
2484
- classNames.push(`($attrs[${stringify(PARENT_MODULE_ID)}] || '')`)
2485
2558
  }
2486
- if (classLikeAttrName === 'class') {
2487
- const dynamicClass = getAndRemoveAttr(el, ':class').val
2488
- if (dynamicClass) classNames.push(dynamicClass)
2489
- addAttrs(el, [{
2490
- name: ':class',
2491
- value: `[${classNames}]`
2492
- }])
2493
- } else {
2494
- addAttrs(el, [{
2495
- name: ':' + classLikeAttrName,
2496
- value: `[${classNames}].join(' ')`
2497
- }])
2498
- }
2499
- }
2500
-
2501
- function processAliClass (classLikeAttrName, classLikeAttrValue, el, options) {
2502
- let hasExternalClass = false
2503
- options.externalClasses.forEach((className) => {
2504
- const reg = new RegExp('\\b' + className + '\\b', 'g')
2505
- const replacementClassName = dash2hump(className)
2506
- if (classLikeAttrValue.includes(className)) hasExternalClass = true
2507
- classLikeAttrValue = classLikeAttrValue.replace(reg, `{{${replacementClassName} || ''}}`)
2508
- })
2509
- if (hasExternalClass) {
2510
- classLikeAttrValue += ` {{${PARENT_MODULE_ID} || ''}}`
2511
- }
2512
- addAttrs(el, [{
2513
- name: classLikeAttrName,
2514
- value: classLikeAttrValue
2515
- }])
2516
2559
  }
2517
2560
  }
2518
2561
 
2519
2562
  function processScoped (el) {
2520
- if (hasScoped && isRealNode(el)) {
2563
+ if (!isRealNode(el)) return
2564
+ // web 模版组件(<template name>)内的节点:scoped 类拼接由运行时 __mpxHost 决定,自成闭环
2565
+ if (isWeb(mode) && processingTemplate) {
2566
+ const parts = []
2567
+ const existingDynamic = getAndRemoveAttr(el, ':class').val
2568
+ if (existingDynamic) parts.push(existingDynamic)
2569
+ const scopedCls = `(__mpxHost && __mpxHost.$options.__mpxScoped ? [__mpxHost.$options.__mpxModuleId || "", __mpxHost.$options.__mpxCtorType !== "component" ? ${stringify(MPX_APP_MODULE_ID)} : ""].filter(Boolean).join(" ") : "")`
2570
+ parts.push(scopedCls)
2571
+ addAttrs(el, [{ name: ':class', value: `[${parts.join(',')}]` }])
2572
+ return
2573
+ }
2574
+ if (hasScoped) {
2521
2575
  const rootModuleId = ctorType === 'component' ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
2522
2576
  const staticClass = getAndRemoveAttr(el, 'class').val
2523
2577
  addAttrs(el, [{
@@ -2529,20 +2583,116 @@ function processScoped (el) {
2529
2583
 
2530
2584
  const builtInComponentsPrefix = '@mpxjs/webpack-plugin/lib/runtime/components'
2531
2585
 
2586
+ function resolveCustomBuiltinResource (el) {
2587
+ if (!customBuiltInComponentsOpt || !el.isBuiltIn) return null
2588
+ if (el.originalTag != null && customBuiltInComponentsOpt[el.originalTag]) {
2589
+ return customBuiltInComponentsOpt[el.originalTag]
2590
+ }
2591
+ return null
2592
+ }
2593
+
2532
2594
  function processBuiltInComponents (el, meta) {
2533
2595
  if (el.isBuiltIn) {
2534
2596
  if (!meta.builtInComponentsMap) {
2535
2597
  meta.builtInComponentsMap = {}
2536
2598
  }
2537
2599
  const tag = el.tag
2538
- if (!meta.builtInComponentsMap[tag]) {
2539
- if (isReact(mode)) {
2540
- meta.builtInComponentsMap[tag] = `${builtInComponentsPrefix}/react/dist/${tag}`
2541
- } else {
2542
- meta.builtInComponentsMap[tag] = `${builtInComponentsPrefix}/${mode}/${tag}`
2543
- }
2600
+ const customResource = resolveCustomBuiltinResource(el)
2601
+ const defaultResource = isReact(mode)
2602
+ ? `${builtInComponentsPrefix}/react/dist/${tag}`
2603
+ : `${builtInComponentsPrefix}/${mode}/${tag}`
2604
+ meta.builtInComponentsMap[tag] = customResource != null ? customResource : defaultResource
2605
+ }
2606
+ }
2607
+
2608
+ /** Web / RN 共用:<import src> 收集并移除 */
2609
+ function processTemplateImport (el, meta) {
2610
+ if (el.tag !== 'import') return false
2611
+ if (el.attrsMap.src) {
2612
+ if (!meta.imports) {
2613
+ meta.imports = []
2614
+ }
2615
+ meta.imports.push(el.attrsMap.src)
2616
+ // RN:存在外部 import 模版时保守关闭 render memo(子文件内 <slot> 不进本轮 AST;见 getDefaultOptions.ios.js __getSlot + useMemo)
2617
+ if (isReact(mode)) {
2618
+ meta.options = Object.assign({}, meta.options, { disableMemo: true })
2619
+ }
2620
+ }
2621
+ el.shouldRemove = true
2622
+ return true
2623
+ }
2624
+
2625
+ /**
2626
+ * Web / RN 共用:`<template is>` / `<template name>`(Web 下 `is`/`data` 在 platform postProps 中原样保留,与 RN 同一条 parse 路径)
2627
+ * @returns {true|undefined} true 表示进入 template 定义子树
2628
+ */
2629
+ function processTemplateTranspile (el, meta) {
2630
+ if (processTemplateImport(el, meta)) return
2631
+
2632
+ if (el.tag !== 'template') return
2633
+
2634
+ const is = getAndRemoveAttr(el, 'is').val
2635
+ if (is) {
2636
+ // template usage, keep processing
2637
+ const data = getAndRemoveAttr(el, 'data').val
2638
+ el.templateInfo = {
2639
+ is: parseMustacheWithContext(is).result,
2640
+ data: data ? parseMustacheWithContext(`{${data}}`).result : ''
2544
2641
  }
2642
+ return
2643
+ }
2644
+
2645
+ if (el.attrsMap.name) {
2646
+ el.isTemplate = true
2647
+ processingTemplate = true
2648
+ return true
2545
2649
  }
2650
+ error$1('Invalid template tag, should have valid is or name attr')
2651
+ el.shouldRemove = true
2652
+ }
2653
+
2654
+ // `<template name="...">` 定义:收集 meta.templates 后移除(Web / RN 共用逻辑)
2655
+ function collectTranspileTemplateDefinition (el, meta) {
2656
+ if (!el.isTemplate) return false
2657
+ if (!meta.templates) {
2658
+ meta.templates = {}
2659
+ }
2660
+ if (meta.templates[el.attrsMap.name]) {
2661
+ error$1(`Duplicated template name "${el.attrsMap.name}" in the same file.`)
2662
+ }
2663
+ meta.templates[el.attrsMap.name] = el
2664
+ removeNode(el, true)
2665
+ processingTemplate = false
2666
+ return true
2667
+ }
2668
+
2669
+ function postProcessTemplateReact (el, meta) {
2670
+ collectTranspileTemplateDefinition(el, meta)
2671
+ }
2672
+
2673
+ // Web:template 定义收集 + `<template is="...">` 使用节点替换为 mpx-tpl-* / component
2674
+ function postProcessTemplateWeb (el, meta) {
2675
+ if (collectTranspileTemplateDefinition(el, meta)) return
2676
+ if (el.tag !== 'template' || !el.templateInfo) return
2677
+ const { is, data } = el.templateInfo
2678
+ if (!is) return
2679
+ const literalMatch = /^"([A-Za-z_][\w-]*)"$/.exec(is)
2680
+ const baseAttrs = cloneAttrsList(el.attrsList)
2681
+ let newNode
2682
+ if (literalMatch) {
2683
+ const name = literalMatch[1]
2684
+ const built = data ? [{ name: ':mpx-data', value: data }] : []
2685
+ newNode = createASTElement(`${MPX_TEMPLATE_COMPONENT_PREFIX}${name}`, baseAttrs.concat(built))
2686
+ newNode.unary = true
2687
+ } else {
2688
+ const built = [
2689
+ { name: ':is', value: `'${MPX_TEMPLATE_COMPONENT_PREFIX}' + (${is})` },
2690
+ ...(data ? [{ name: ':mpx-data', value: data }] : [])
2691
+ ]
2692
+ newNode = createASTElement('component', baseAttrs.concat(built))
2693
+ newNode.unary = true
2694
+ }
2695
+ replaceNode(el, newNode, true)
2546
2696
  }
2547
2697
 
2548
2698
  function postProcessAliComponentRootView (el, options, meta) {
@@ -2615,8 +2765,8 @@ function postProcessAliComponentRootView (el, options, meta) {
2615
2765
  // 有virtualHost情况wx组件注入virtualHost。无virtualHost阿里组件注入root-view。其他跳过。
2616
2766
  function getVirtualHostRoot (options, meta) {
2617
2767
  if (srcMode === 'wx') {
2618
- if (ctorType === 'component') {
2619
- if (isWeb(mode) && !hasVirtualHost) {
2768
+ if (ctorType === 'component' && !hasVirtualHost) {
2769
+ if (isWeb(mode)) {
2620
2770
  // ali组件根节点实体化
2621
2771
  const rootView = createASTElement('view', [
2622
2772
  {
@@ -2631,7 +2781,7 @@ function getVirtualHostRoot (options, meta) {
2631
2781
  processElement(rootView, rootView, options, meta)
2632
2782
  return rootView
2633
2783
  }
2634
- if (isReact(mode) && !hasVirtualHost) {
2784
+ if (isReact(mode)) {
2635
2785
  const tagName = isCustomText ? 'text' : 'view'
2636
2786
  const rootView = createASTElement(tagName, [
2637
2787
  {
@@ -2647,18 +2797,20 @@ function getVirtualHostRoot (options, meta) {
2647
2797
  return rootView
2648
2798
  }
2649
2799
  }
2650
- if (isWeb(mode) && ctorType === 'page') {
2651
- return createASTElement('page')
2652
- }
2653
- if (isReact(mode) && ctorType === 'page') {
2654
- const rootView = createASTElement('view', [
2655
- {
2656
- name: 'class',
2657
- value: MPX_TAG_PAGE_SELECTOR
2658
- }
2659
- ])
2660
- processElement(rootView, rootView, options, meta)
2661
- return rootView
2800
+ if (ctorType === 'page') {
2801
+ if (isWeb(mode)) {
2802
+ return createASTElement('page')
2803
+ }
2804
+ if (isReact(mode)) {
2805
+ const rootView = createASTElement('view', [
2806
+ {
2807
+ name: 'class',
2808
+ value: MPX_TAG_PAGE_SELECTOR
2809
+ }
2810
+ ])
2811
+ processElement(rootView, rootView, options, meta)
2812
+ return rootView
2813
+ }
2662
2814
  }
2663
2815
  }
2664
2816
  return getTempNode()
@@ -2713,7 +2865,6 @@ function processTemplate (el) {
2713
2865
  function postProcessTemplate (el) {
2714
2866
  if (el.isTemplate) {
2715
2867
  processingTemplate = false
2716
- return true
2717
2868
  }
2718
2869
  }
2719
2870
 
@@ -2836,11 +2987,11 @@ function processDuplicateAttrsList (el) {
2836
2987
  }
2837
2988
 
2838
2989
  // 处理wxs注入逻辑
2839
- function processInjectWxs (el, meta) {
2840
- if (el.injectWxsProps && el.injectWxsProps.length) {
2841
- el.injectWxsProps.forEach((injectWxsProp) => {
2842
- const { injectWxsPath, injectWxsModuleName } = injectWxsProp
2843
- injectWxs(meta, injectWxsModuleName, injectWxsPath)
2990
+ function processInjectWxsInfos (el, meta) {
2991
+ if (el.injectWxsInfos && el.injectWxsInfos.length) {
2992
+ el.injectWxsInfos.forEach((injectWxsInfo) => {
2993
+ const { injectWxsRequest, injectWxsModuleName } = injectWxsInfo
2994
+ injectWxs(meta, injectWxsModuleName, injectWxsRequest)
2844
2995
  })
2845
2996
  }
2846
2997
  }
@@ -2934,8 +3085,9 @@ function processMpxTagName (el) {
2934
3085
 
2935
3086
  function processElement (el, root, options, meta) {
2936
3087
  processAtMode(el)
2937
- // 如果已经标记了这个元素要被清除,直接return跳过后续处理步骤
2938
3088
  if (el._matchStatus === statusEnum.MISMATCH) {
3089
+ // 如果已经标记了这个元素要被清除,直接return跳过后续处理步骤
3090
+ el.shouldRemove = true
2939
3091
  return
2940
3092
  }
2941
3093
 
@@ -2957,36 +3109,39 @@ function processElement (el, root, options, meta) {
2957
3109
  // 检测跨平台语法使用情况并给出警告
2958
3110
  processCrossPlatformSyntaxWarning(el)
2959
3111
 
2960
- processInjectWxs(el, meta, options)
3112
+ processInjectWxsInfos(el, meta, options)
2961
3113
 
2962
3114
  const transAli = mode === 'ali' && srcMode === 'wx'
2963
3115
 
2964
3116
  if (isWeb(mode)) {
3117
+ const isTemplate = processTemplateTranspile(el, meta) || processingTemplate
3118
+ if (el.shouldRemove) return
2965
3119
  // 收集内建组件
2966
3120
  processBuiltInComponents(el, meta)
2967
3121
  // 预处理代码维度条件编译
2968
3122
  processIfWeb(el)
2969
3123
  processScoped(el)
2970
3124
  processEventWeb(el)
2971
- // processWebExternalClassesHack(el, options)
2972
3125
  processExternalClasses(el, options)
2973
- processComponentGenerics(el, meta)
3126
+ if (!isTemplate) processComponentGenerics(el, meta)
2974
3127
  return
2975
3128
  }
2976
3129
 
2977
3130
  if (isReact(mode)) {
2978
- const pass = isReactComponent(el, options)
3131
+ const isTemplate = processTemplateTranspile(el, meta) || processingTemplate
3132
+ if (el.shouldRemove) return
3133
+ const isReactComponent$1 = isReactComponent(el, options)
2979
3134
  // 收集内建组件
2980
3135
  processBuiltInComponents(el, meta)
2981
3136
  // 预处理代码维度条件编译
2982
3137
  processIf(el)
2983
3138
  processFor(el)
2984
- processRefReact(el, meta)
3139
+ if (!isTemplate) processRefReact(el, meta)
2985
3140
  processStyleReact(el, options)
2986
- if (!pass) {
3141
+ if (!isReactComponent$1) {
2987
3142
  processEventReact(el, options)
2988
- processComponentGenerics(el, meta)
2989
- processComponentIs(el, options)
3143
+ if (!isTemplate) processComponentGenerics(el, meta)
3144
+ if (!isTemplate) processComponentIs(el, options)
2990
3145
  processSlotReact(el, meta)
2991
3146
  }
2992
3147
  processAttrs(el, options)
@@ -3001,7 +3156,6 @@ function processElement (el, root, options, meta) {
3001
3156
  }
3002
3157
 
3003
3158
  if (transAli) {
3004
- // processAliExternalClassesHack(el, options)
3005
3159
  processExternalClasses(el, options)
3006
3160
  }
3007
3161
 
@@ -3026,22 +3180,24 @@ function processElement (el, root, options, meta) {
3026
3180
  }
3027
3181
 
3028
3182
  function closeElement (el, options, meta) {
3029
- postProcessAtMode(el)
3030
3183
  postProcessWxs(el, meta)
3031
3184
 
3032
3185
  if (isWeb(mode)) {
3033
3186
  // 处理代码维度条件编译移除死分支
3034
3187
  postProcessIf(el)
3188
+ postProcessTemplateWeb(el, meta)
3189
+ postProcessRemove(el)
3035
3190
  return
3036
3191
  }
3037
3192
  if (isReact(mode)) {
3038
3193
  postProcessForReact(el)
3039
3194
  postProcessIfReact(el)
3195
+ postProcessTemplateReact(el, meta)
3196
+ postProcessRemove(el)
3040
3197
  return
3041
3198
  }
3042
3199
 
3043
- const isTemplate = postProcessTemplate(el) || processingTemplate
3044
- if (!isTemplate) {
3200
+ if (!processingTemplate) {
3045
3201
  if (!isNative) {
3046
3202
  postProcessComponentIs(el, (child) => {
3047
3203
  if (!getComponentInfo(el).hasVirtualHost && mode === 'ali') {
@@ -3065,6 +3221,8 @@ function closeElement (el, options, meta) {
3065
3221
  postProcessFor(el)
3066
3222
  postProcessIf(el)
3067
3223
  }
3224
+ postProcessTemplate(el)
3225
+ postProcessRemove(el)
3068
3226
  }
3069
3227
 
3070
3228
  // 运行时组件的模版节点收集,最终注入到 mpx-custom-element-*.wxml 中
@@ -3072,8 +3230,8 @@ function collectDynamicInfo (el, options, meta) {
3072
3230
  setBaseWxml(el, { mode, isComponentNode, options }, meta)
3073
3231
  }
3074
3232
 
3075
- function postProcessAtMode (el) {
3076
- if (el._matchStatus === statusEnum.MISMATCH) {
3233
+ function postProcessRemove (el) {
3234
+ if (el.shouldRemove) {
3077
3235
  removeNode(el)
3078
3236
  }
3079
3237
  }
@@ -3307,7 +3465,7 @@ function addIfConditionDynamic (el, condition) {
3307
3465
  el.ifConditions.push(condition)
3308
3466
  }
3309
3467
 
3310
- function processIfConditionsDynamic (el) {
3468
+ function postProcessIfConditionsDynamic (el) {
3311
3469
  const prevNode = findPrevNode(el)
3312
3470
  if (prevNode && prevNode.if) {
3313
3471
  addIfConditionDynamic(prevNode, {
@@ -3389,7 +3547,7 @@ function postProcessIfDynamic (vnode, config) {
3389
3547
  ? config.directive.elseif
3390
3548
  : config.directive.else
3391
3549
  getAndRemoveAttr(vnode, directive)
3392
- processIfConditionsDynamic(vnode)
3550
+ postProcessIfConditionsDynamic(vnode)
3393
3551
  delete vnode.elseif
3394
3552
  delete vnode.else
3395
3553
  }