@weapp-vite/web 1.3.37 → 1.4.1

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 (334) hide show
  1. package/README.md +144 -5
  2. package/dist/_virtual/_rolldown/runtime.mjs +19 -1
  3. package/dist/compiler/wxml/attributes.mjs +1 -1
  4. package/dist/compiler/wxml/attributes.mjs.map +1 -1
  5. package/dist/compiler/wxml/compile.mjs +6 -3
  6. package/dist/compiler/wxml/compile.mjs.map +1 -1
  7. package/dist/compiler/wxml/interpolation.mjs +1 -2
  8. package/dist/compiler/wxml/interpolation.mjs.map +1 -1
  9. package/dist/compiler/wxml/navigation.mjs +5 -7
  10. package/dist/compiler/wxml/navigation.mjs.map +1 -1
  11. package/dist/compiler/wxml/parser.mjs +5 -5
  12. package/dist/compiler/wxml/parser.mjs.map +1 -1
  13. package/dist/compiler/wxml/renderer.mjs +16 -12
  14. package/dist/compiler/wxml/renderer.mjs.map +1 -1
  15. package/dist/compiler/wxml/specialNodes.mjs +8 -2
  16. package/dist/compiler/wxml/specialNodes.mjs.map +1 -1
  17. package/dist/compiler/wxml/types.d.mts +12 -0
  18. package/dist/compiler/wxs.mjs +5 -5
  19. package/dist/compiler/wxs.mjs.map +1 -1
  20. package/dist/css/wxss.d.mts +1 -0
  21. package/dist/css/wxss.mjs +110 -9
  22. package/dist/css/wxss.mjs.map +1 -1
  23. package/dist/index.d.mts +24 -6
  24. package/dist/index.mjs +21 -4
  25. package/dist/plugin/assets.d.mts +7 -0
  26. package/dist/plugin/assets.mjs +122 -0
  27. package/dist/plugin/assets.mjs.map +1 -0
  28. package/dist/plugin/constants.mjs +10 -1
  29. package/dist/plugin/constants.mjs.map +1 -1
  30. package/dist/plugin/dependencyScan.mjs +41 -0
  31. package/dist/plugin/dependencyScan.mjs.map +1 -0
  32. package/dist/plugin/entry.mjs +55 -6
  33. package/dist/plugin/entry.mjs.map +1 -1
  34. package/dist/plugin/files.mjs +1 -1
  35. package/dist/plugin/files.mjs.map +1 -1
  36. package/dist/plugin/index.d.mts +37 -3
  37. package/dist/plugin/index.mjs +244 -73
  38. package/dist/plugin/index.mjs.map +1 -1
  39. package/dist/plugin/layout.mjs +24 -0
  40. package/dist/plugin/layout.mjs.map +1 -0
  41. package/dist/plugin/path.mjs +6 -2
  42. package/dist/plugin/path.mjs.map +1 -1
  43. package/dist/plugin/register.mjs +45 -33
  44. package/dist/plugin/register.mjs.map +1 -1
  45. package/dist/plugin/scan.mjs +211 -92
  46. package/dist/plugin/scan.mjs.map +1 -1
  47. package/dist/plugin/scanSfc.mjs +65 -0
  48. package/dist/plugin/scanSfc.mjs.map +1 -0
  49. package/dist/plugin/state.mjs +3 -2
  50. package/dist/plugin/state.mjs.map +1 -1
  51. package/dist/plugin/styleModule.mjs +52 -0
  52. package/dist/plugin/styleModule.mjs.map +1 -0
  53. package/dist/plugin/types.d.mts +37 -1
  54. package/dist/plugin/vueSfc.mjs +150 -0
  55. package/dist/plugin/vueSfc.mjs.map +1 -0
  56. package/dist/runtime/appShell/container.mjs +25 -0
  57. package/dist/runtime/appShell/container.mjs.map +1 -0
  58. package/dist/runtime/appShell/tabBar/index.mjs +192 -0
  59. package/dist/runtime/appShell/tabBar/index.mjs.map +1 -0
  60. package/dist/runtime/appShell/tabBar/style.mjs +127 -0
  61. package/dist/runtime/appShell/tabBar/style.mjs.map +1 -0
  62. package/dist/runtime/button/helpers.mjs +1 -58
  63. package/dist/runtime/button/helpers.mjs.map +1 -1
  64. package/dist/runtime/button/index.d.mts +4 -5
  65. package/dist/runtime/button/index.mjs +6 -28
  66. package/dist/runtime/button/index.mjs.map +1 -1
  67. package/dist/runtime/button/style.mjs +53 -28
  68. package/dist/runtime/button/style.mjs.map +1 -1
  69. package/dist/runtime/component/behavior.mjs +26 -2
  70. package/dist/runtime/component/behavior.mjs.map +1 -1
  71. package/dist/runtime/component/element.mjs +107 -31
  72. package/dist/runtime/component/element.mjs.map +1 -1
  73. package/dist/runtime/component/observers.mjs +36 -0
  74. package/dist/runtime/component/observers.mjs.map +1 -0
  75. package/dist/runtime/component/publicInstance.mjs +48 -0
  76. package/dist/runtime/component/publicInstance.mjs.map +1 -0
  77. package/dist/runtime/component/relations.mjs +36 -0
  78. package/dist/runtime/component/relations.mjs.map +1 -0
  79. package/dist/runtime/component/slots.mjs +24 -0
  80. package/dist/runtime/component/slots.mjs.map +1 -0
  81. package/dist/runtime/component/state.mjs +13 -3
  82. package/dist/runtime/component/state.mjs.map +1 -1
  83. package/dist/runtime/component/types.d.mts +29 -4
  84. package/dist/runtime/component/virtualHost.mjs +83 -0
  85. package/dist/runtime/component/virtualHost.mjs.map +1 -0
  86. package/dist/runtime/host/index.d.mts +13 -0
  87. package/dist/runtime/host/index.mjs +47 -0
  88. package/dist/runtime/host/index.mjs.map +1 -0
  89. package/dist/runtime/host/types.d.mts +28 -0
  90. package/dist/runtime/hostGlobals.d.mts +9 -0
  91. package/dist/runtime/hostGlobals.mjs +39 -0
  92. package/dist/runtime/hostGlobals.mjs.map +1 -0
  93. package/dist/runtime/index.d.mts +21 -3
  94. package/dist/runtime/index.mjs +26 -4
  95. package/dist/runtime/index.mjs.map +1 -0
  96. package/dist/runtime/legacyTemplate/dom.mjs +3 -3
  97. package/dist/runtime/legacyTemplate/dom.mjs.map +1 -1
  98. package/dist/runtime/legacyTemplate/expression.mjs +9 -9
  99. package/dist/runtime/legacyTemplate/expression.mjs.map +1 -1
  100. package/dist/runtime/legacyTemplate/index.mjs +6 -6
  101. package/dist/runtime/legacyTemplate/index.mjs.map +1 -1
  102. package/dist/runtime/nativeComponents/canvas/index.mjs +53 -0
  103. package/dist/runtime/nativeComponents/canvas/index.mjs.map +1 -0
  104. package/dist/runtime/nativeComponents/checkbox.mjs +137 -0
  105. package/dist/runtime/nativeComponents/checkbox.mjs.map +1 -0
  106. package/dist/runtime/nativeComponents/cover/index.mjs +23 -0
  107. package/dist/runtime/nativeComponents/cover/index.mjs.map +1 -0
  108. package/dist/runtime/nativeComponents/form.d.mts +7 -0
  109. package/dist/runtime/nativeComponents/form.mjs +50 -0
  110. package/dist/runtime/nativeComponents/form.mjs.map +1 -0
  111. package/dist/runtime/nativeComponents/formControl.mjs +61 -0
  112. package/dist/runtime/nativeComponents/formControl.mjs.map +1 -0
  113. package/dist/runtime/nativeComponents/helpers.mjs +25 -0
  114. package/dist/runtime/nativeComponents/helpers.mjs.map +1 -0
  115. package/dist/runtime/nativeComponents/icon/helpers.mjs +42 -0
  116. package/dist/runtime/nativeComponents/icon/helpers.mjs.map +1 -0
  117. package/dist/runtime/nativeComponents/icon/index.mjs +45 -0
  118. package/dist/runtime/nativeComponents/icon/index.mjs.map +1 -0
  119. package/dist/runtime/nativeComponents/icon/style.mjs +176 -0
  120. package/dist/runtime/nativeComponents/icon/style.mjs.map +1 -0
  121. package/dist/runtime/nativeComponents/image.d.mts +8 -0
  122. package/dist/runtime/nativeComponents/image.mjs +121 -0
  123. package/dist/runtime/nativeComponents/image.mjs.map +1 -0
  124. package/dist/runtime/nativeComponents/index.d.mts +11 -0
  125. package/dist/runtime/nativeComponents/index.mjs +83 -0
  126. package/dist/runtime/nativeComponents/index.mjs.map +1 -0
  127. package/dist/runtime/nativeComponents/input.d.mts +8 -0
  128. package/dist/runtime/nativeComponents/input.mjs +131 -0
  129. package/dist/runtime/nativeComponents/input.mjs.map +1 -0
  130. package/dist/runtime/nativeComponents/label.mjs +36 -0
  131. package/dist/runtime/nativeComponents/label.mjs.map +1 -0
  132. package/dist/runtime/nativeComponents/mediaRegistry.mjs +47 -0
  133. package/dist/runtime/nativeComponents/mediaRegistry.mjs.map +1 -0
  134. package/dist/runtime/nativeComponents/movable/helpers.mjs +23 -0
  135. package/dist/runtime/nativeComponents/movable/helpers.mjs.map +1 -0
  136. package/dist/runtime/nativeComponents/movable/index.mjs +117 -0
  137. package/dist/runtime/nativeComponents/movable/index.mjs.map +1 -0
  138. package/dist/runtime/nativeComponents/navigator.mjs +200 -0
  139. package/dist/runtime/nativeComponents/navigator.mjs.map +1 -0
  140. package/dist/runtime/nativeComponents/picker/editors.mjs +74 -0
  141. package/dist/runtime/nativeComponents/picker/editors.mjs.map +1 -0
  142. package/dist/runtime/nativeComponents/picker/helpers.mjs +57 -0
  143. package/dist/runtime/nativeComponents/picker/helpers.mjs.map +1 -0
  144. package/dist/runtime/nativeComponents/picker/index.mjs +210 -0
  145. package/dist/runtime/nativeComponents/picker/index.mjs.map +1 -0
  146. package/dist/runtime/nativeComponents/picker/style.mjs +71 -0
  147. package/dist/runtime/nativeComponents/picker/style.mjs.map +1 -0
  148. package/dist/runtime/nativeComponents/pickerView/column.mjs +134 -0
  149. package/dist/runtime/nativeComponents/pickerView/column.mjs.map +1 -0
  150. package/dist/runtime/nativeComponents/pickerView/helpers.mjs +17 -0
  151. package/dist/runtime/nativeComponents/pickerView/helpers.mjs.map +1 -0
  152. package/dist/runtime/nativeComponents/pickerView/index.mjs +128 -0
  153. package/dist/runtime/nativeComponents/pickerView/index.mjs.map +1 -0
  154. package/dist/runtime/nativeComponents/pickerView/style.mjs +58 -0
  155. package/dist/runtime/nativeComponents/pickerView/style.mjs.map +1 -0
  156. package/dist/runtime/nativeComponents/primitives.mjs +16 -0
  157. package/dist/runtime/nativeComponents/primitives.mjs.map +1 -0
  158. package/dist/runtime/nativeComponents/progress/helpers.mjs +29 -0
  159. package/dist/runtime/nativeComponents/progress/helpers.mjs.map +1 -0
  160. package/dist/runtime/nativeComponents/progress/index.mjs +130 -0
  161. package/dist/runtime/nativeComponents/progress/index.mjs.map +1 -0
  162. package/dist/runtime/nativeComponents/progress/style.mjs +40 -0
  163. package/dist/runtime/nativeComponents/progress/style.mjs.map +1 -0
  164. package/dist/runtime/nativeComponents/radio.mjs +147 -0
  165. package/dist/runtime/nativeComponents/radio.mjs.map +1 -0
  166. package/dist/runtime/nativeComponents/richText/helpers.mjs +230 -0
  167. package/dist/runtime/nativeComponents/richText/helpers.mjs.map +1 -0
  168. package/dist/runtime/nativeComponents/richText/index.mjs +74 -0
  169. package/dist/runtime/nativeComponents/richText/index.mjs.map +1 -0
  170. package/dist/runtime/nativeComponents/scrollView.d.mts +15 -0
  171. package/dist/runtime/nativeComponents/scrollView.mjs +79 -0
  172. package/dist/runtime/nativeComponents/scrollView.mjs.map +1 -0
  173. package/dist/runtime/nativeComponents/slider/helpers.mjs +28 -0
  174. package/dist/runtime/nativeComponents/slider/helpers.mjs.map +1 -0
  175. package/dist/runtime/nativeComponents/slider/index.mjs +120 -0
  176. package/dist/runtime/nativeComponents/slider/index.mjs.map +1 -0
  177. package/dist/runtime/nativeComponents/slider/style.mjs +60 -0
  178. package/dist/runtime/nativeComponents/slider/style.mjs.map +1 -0
  179. package/dist/runtime/nativeComponents/style.mjs +41 -0
  180. package/dist/runtime/nativeComponents/style.mjs.map +1 -0
  181. package/dist/runtime/nativeComponents/swiper/helpers.mjs +52 -0
  182. package/dist/runtime/nativeComponents/swiper/helpers.mjs.map +1 -0
  183. package/dist/runtime/nativeComponents/swiper/index.mjs +235 -0
  184. package/dist/runtime/nativeComponents/swiper/index.mjs.map +1 -0
  185. package/dist/runtime/nativeComponents/swiper/item.mjs +14 -0
  186. package/dist/runtime/nativeComponents/swiper/item.mjs.map +1 -0
  187. package/dist/runtime/nativeComponents/swiper/style.mjs +20 -0
  188. package/dist/runtime/nativeComponents/swiper/style.mjs.map +1 -0
  189. package/dist/runtime/nativeComponents/switch.d.mts +7 -0
  190. package/dist/runtime/nativeComponents/switch.mjs +132 -0
  191. package/dist/runtime/nativeComponents/switch.mjs.map +1 -0
  192. package/dist/runtime/nativeComponents/textarea.d.mts +9 -0
  193. package/dist/runtime/nativeComponents/textarea.mjs +144 -0
  194. package/dist/runtime/nativeComponents/textarea.mjs.map +1 -0
  195. package/dist/runtime/nativeComponents/video/helpers.d.mts +12 -0
  196. package/dist/runtime/nativeComponents/video/helpers.mjs +21 -0
  197. package/dist/runtime/nativeComponents/video/helpers.mjs.map +1 -0
  198. package/dist/runtime/nativeComponents/video/index.mjs +124 -0
  199. package/dist/runtime/nativeComponents/video/index.mjs.map +1 -0
  200. package/dist/runtime/nativeComponents/video/style.mjs +14 -0
  201. package/dist/runtime/nativeComponents/video/style.mjs.map +1 -0
  202. package/dist/runtime/navigationBar/index.mjs +1 -3
  203. package/dist/runtime/navigationBar/index.mjs.map +1 -1
  204. package/dist/runtime/pageLayout.d.mts +9 -0
  205. package/dist/runtime/pageLayout.mjs +16 -0
  206. package/dist/runtime/pageLayout.mjs.map +1 -0
  207. package/dist/runtime/polyfill/animation.mjs +120 -0
  208. package/dist/runtime/polyfill/animation.mjs.map +1 -0
  209. package/dist/runtime/polyfill/appState.mjs +1 -1
  210. package/dist/runtime/polyfill/appState.mjs.map +1 -1
  211. package/dist/runtime/polyfill/async.d.mts +7 -0
  212. package/dist/runtime/polyfill/async.mjs.map +1 -1
  213. package/dist/runtime/polyfill/canvasContext.mjs +41 -0
  214. package/dist/runtime/polyfill/canvasContext.mjs.map +1 -1
  215. package/dist/runtime/polyfill/device.mjs +1 -1
  216. package/dist/runtime/polyfill/device.mjs.map +1 -1
  217. package/dist/runtime/polyfill/deviceApi.mjs +6 -3
  218. package/dist/runtime/polyfill/deviceApi.mjs.map +1 -1
  219. package/dist/runtime/polyfill/deviceAuthSystemApi.mjs +8 -2
  220. package/dist/runtime/polyfill/deviceAuthSystemApi.mjs.map +1 -1
  221. package/dist/runtime/polyfill/eventBus.mjs +56 -0
  222. package/dist/runtime/polyfill/eventBus.mjs.map +1 -0
  223. package/dist/runtime/polyfill/fileSystemManager.mjs +5 -2
  224. package/dist/runtime/polyfill/fileSystemManager.mjs.map +1 -1
  225. package/dist/runtime/polyfill/files.mjs +10 -10
  226. package/dist/runtime/polyfill/files.mjs.map +1 -1
  227. package/dist/runtime/polyfill/font.mjs +33 -0
  228. package/dist/runtime/polyfill/font.mjs.map +1 -0
  229. package/dist/runtime/polyfill/index.d.mts +2 -2
  230. package/dist/runtime/polyfill/index.mjs +49 -45
  231. package/dist/runtime/polyfill/index.mjs.map +1 -1
  232. package/dist/runtime/polyfill/interaction.mjs +7 -6
  233. package/dist/runtime/polyfill/interaction.mjs.map +1 -1
  234. package/dist/runtime/polyfill/interactionApi.mjs +9 -5
  235. package/dist/runtime/polyfill/interactionApi.mjs.map +1 -1
  236. package/dist/runtime/polyfill/intersectionObserver.mjs +106 -0
  237. package/dist/runtime/polyfill/intersectionObserver.mjs.map +1 -0
  238. package/dist/runtime/polyfill/locale.mjs +14 -0
  239. package/dist/runtime/polyfill/locale.mjs.map +1 -0
  240. package/dist/runtime/polyfill/locationApi.mjs +11 -6
  241. package/dist/runtime/polyfill/locationApi.mjs.map +1 -1
  242. package/dist/runtime/polyfill/mediaActions.mjs +2 -2
  243. package/dist/runtime/polyfill/mediaActions.mjs.map +1 -1
  244. package/dist/runtime/polyfill/mediaApi/file.mjs +3 -2
  245. package/dist/runtime/polyfill/mediaApi/file.mjs.map +1 -1
  246. package/dist/runtime/polyfill/mediaApi/info.mjs +6 -4
  247. package/dist/runtime/polyfill/mediaApi/info.mjs.map +1 -1
  248. package/dist/runtime/polyfill/mediaApi/picker.mjs +16 -8
  249. package/dist/runtime/polyfill/mediaApi/picker.mjs.map +1 -1
  250. package/dist/runtime/polyfill/mediaApi/preview.mjs +4 -2
  251. package/dist/runtime/polyfill/mediaApi/preview.mjs.map +1 -1
  252. package/dist/runtime/polyfill/mediaApi/process.mjs +4 -2
  253. package/dist/runtime/polyfill/mediaApi/process.mjs.map +1 -1
  254. package/dist/runtime/polyfill/menuApi.mjs +39 -4
  255. package/dist/runtime/polyfill/menuApi.mjs.map +1 -1
  256. package/dist/runtime/polyfill/navigationBarRuntime.mjs +6 -1
  257. package/dist/runtime/polyfill/navigationBarRuntime.mjs.map +1 -1
  258. package/dist/runtime/polyfill/network/request.mjs +2 -2
  259. package/dist/runtime/polyfill/network/request.mjs.map +1 -1
  260. package/dist/runtime/polyfill/platformApi.mjs +3 -2
  261. package/dist/runtime/polyfill/platformApi.mjs.map +1 -1
  262. package/dist/runtime/polyfill/routeRuntime/appLifecycle.mjs +88 -0
  263. package/dist/runtime/polyfill/routeRuntime/appLifecycle.mjs.map +1 -0
  264. package/dist/runtime/polyfill/routeRuntime/dom.mjs +44 -15
  265. package/dist/runtime/polyfill/routeRuntime/dom.mjs.map +1 -1
  266. package/dist/runtime/polyfill/routeRuntime/history.d.mts +30 -0
  267. package/dist/runtime/polyfill/routeRuntime/history.mjs +148 -0
  268. package/dist/runtime/polyfill/routeRuntime/history.mjs.map +1 -0
  269. package/dist/runtime/polyfill/routeRuntime/lifecycle.mjs +39 -8
  270. package/dist/runtime/polyfill/routeRuntime/lifecycle.mjs.map +1 -1
  271. package/dist/runtime/polyfill/routeRuntime/options.d.mts +11 -1
  272. package/dist/runtime/polyfill/routeRuntime/options.mjs +0 -1
  273. package/dist/runtime/polyfill/routeRuntime/options.mjs.map +1 -1
  274. package/dist/runtime/polyfill/routeRuntime/result.mjs +12 -0
  275. package/dist/runtime/polyfill/routeRuntime/result.mjs.map +1 -0
  276. package/dist/runtime/polyfill/routeRuntime/scroll.mjs +39 -0
  277. package/dist/runtime/polyfill/routeRuntime/scroll.mjs.map +1 -0
  278. package/dist/runtime/polyfill/routeRuntime/stack.mjs +122 -0
  279. package/dist/runtime/polyfill/routeRuntime/stack.mjs.map +1 -0
  280. package/dist/runtime/polyfill/routeRuntime.d.mts +26 -17
  281. package/dist/runtime/polyfill/routeRuntime.mjs +121 -96
  282. package/dist/runtime/polyfill/routeRuntime.mjs.map +1 -1
  283. package/dist/runtime/polyfill/runtimeDataApi.mjs +8 -3
  284. package/dist/runtime/polyfill/runtimeDataApi.mjs.map +1 -1
  285. package/dist/runtime/polyfill/runtimeOps.mjs +10 -6
  286. package/dist/runtime/polyfill/runtimeOps.mjs.map +1 -1
  287. package/dist/runtime/polyfill/selectorQuery.mjs +70 -14
  288. package/dist/runtime/polyfill/selectorQuery.mjs.map +1 -1
  289. package/dist/runtime/polyfill/storage.mjs +5 -2
  290. package/dist/runtime/polyfill/storage.mjs.map +1 -1
  291. package/dist/runtime/polyfill/storageAsync.mjs +4 -2
  292. package/dist/runtime/polyfill/storageAsync.mjs.map +1 -1
  293. package/dist/runtime/polyfill/system.mjs +31 -4
  294. package/dist/runtime/polyfill/system.mjs.map +1 -1
  295. package/dist/runtime/polyfill/systemApi.mjs +2 -1
  296. package/dist/runtime/polyfill/systemApi.mjs.map +1 -1
  297. package/dist/runtime/polyfill/types/locationRuntime.d.mts +1 -4
  298. package/dist/runtime/polyfill/types/platformRuntime.d.mts +9 -0
  299. package/dist/runtime/polyfill/types/systemAuth.d.mts +20 -9
  300. package/dist/runtime/polyfill/types/tabBarRuntime.d.mts +25 -0
  301. package/dist/runtime/polyfill/ui.mjs +2 -6
  302. package/dist/runtime/polyfill/ui.mjs.map +1 -1
  303. package/dist/runtime/polyfill/uiMediaApi.d.mts +11 -10
  304. package/dist/runtime/polyfill/uiMediaApi.mjs +26 -2
  305. package/dist/runtime/polyfill/uiMediaApi.mjs.map +1 -1
  306. package/dist/runtime/polyfill/videoContext.mjs +4 -0
  307. package/dist/runtime/polyfill/videoContext.mjs.map +1 -1
  308. package/dist/runtime/polyfill/vkSession.mjs +4 -14
  309. package/dist/runtime/polyfill/vkSession.mjs.map +1 -1
  310. package/dist/runtime/polyfill.d.mts +2 -2
  311. package/dist/runtime/renderContext.mjs +1 -1
  312. package/dist/runtime/renderContext.mjs.map +1 -1
  313. package/dist/runtime/rpx.mjs +17 -8
  314. package/dist/runtime/rpx.mjs.map +1 -1
  315. package/dist/runtime/seo/index.d.mts +31 -0
  316. package/dist/runtime/seo/index.mjs +94 -0
  317. package/dist/runtime/seo/index.mjs.map +1 -0
  318. package/dist/runtime/viewport/index.d.mts +12 -0
  319. package/dist/runtime/viewport/index.mjs +44 -0
  320. package/dist/runtime/viewport/index.mjs.map +1 -0
  321. package/dist/runtime/viewport/style.mjs +62 -0
  322. package/dist/runtime/viewport/style.mjs.map +1 -0
  323. package/dist/runtime/viewport/types.d.mts +14 -0
  324. package/dist/runtime/wevu.d.mts +20 -0
  325. package/dist/runtime/wevu.mjs +73 -0
  326. package/dist/runtime/wevu.mjs.map +1 -0
  327. package/dist/shared/nativeComponents.mjs +401 -0
  328. package/dist/shared/nativeComponents.mjs.map +1 -0
  329. package/dist/shared/tabBar.d.mts +19 -0
  330. package/dist/shared/tabBar.mjs +37 -0
  331. package/dist/shared/tabBar.mjs.map +1 -0
  332. package/dist/shared/wxml.mjs +3 -20
  333. package/dist/shared/wxml.mjs.map +1 -1
  334. package/package.json +14 -6
package/README.md CHANGED
@@ -7,14 +7,25 @@
7
7
  - 将小程序 `Page` / `Component` 映射为自定义元素,Shadow DOM 隔离样式与事件
8
8
  - 事件桥接(如 `bindtap` → `click`),保留 `this.setData`、`this.triggerEvent` 等调用体验
9
9
  - 提供宿主中立的小程序桥,并兼容 `wx.navigateTo` / `my.navigateTo` / `tt.navigateTo` 等路由调用,以及 `getCurrentPages`、`onLoad`、`onShow`、`onHide`、`onUnload` 生命周期
10
- - `App` 级别的 `onLaunch` / `onShow` 回调、`getApp` 全局实例访问
11
- - `wxss` → `css` 的基础转换,默认按 `1rpx = 0.5px`
10
+ - `App` 级别的 `onLaunch` / `onShow` / `onHide` 回调、`getApp` 全局实例访问
11
+ - 为 `view`、`text`、`image`、`button`、`input`、`scroll-view`、`icon`、`progress`、`rich-text`、`navigator`、`swiper` / `swiper-item`、`canvas`、`video`、`cover-view` / `cover-image`、`movable-area` / `movable-view`、picker、slider 及常用表单组件提供保留小程序语义的 Web Components 适配
12
+ - 使用 PostCSS 转换 WXSS 选择器,支持 `page`、原生组件类型选择器、组合选择器和伪类
13
+ - `rpx` 根据实际设备容器宽度动态计算;默认宽屏下使用 375px 居中设备视口
12
14
  - 提供 Vite 插件,自动把 `.wxml` / `.wxss` 转换为 Web 侧模块
13
15
 
14
16
  > ⚠️ 当前阶段为 POC,功能与兼容性都较有限,只适合验证思路。
15
17
 
16
18
  ## 快速开始
17
19
 
20
+ 在 `weapp-vite` 项目中准备根目录 `index.html` 后,可直接使用同一份小程序源码启动或构建 Web:
21
+
22
+ ```bash
23
+ pnpm wv dev -p web --host
24
+ pnpm wv build -p web
25
+ ```
26
+
27
+ 仓库内所有 `e2e-apps/*` 与 `templates/*` 项目统一提供 `pnpm dev:web` 和 `pnpm build:web`。`pnpm e2e:web:build-projects` 会验证全部项目的生产构建,`pnpm e2e:web` 会通过 Playwright 逐项目启动并检查 `wx`、页面容器和当前路由。
28
+
18
29
  ```ts
19
30
  import { defineComponent } from '@weapp-vite/web'
20
31
  import template from './index.wxml'
@@ -43,9 +54,137 @@ defineComponent('wv-hello-world', {
43
54
  document.body.innerHTML = '<wv-hello-world title="文档地址"></wv-hello-world>'
44
55
  ```
45
56
 
57
+ ## 设备视口
58
+
59
+ 默认配置模拟小程序页面视口:移动宽度下铺满,浏览器宽度达到 600px 后使用 375px 居中容器。页面、导航栏、`fixed` 元素和 `rpx` 共用这一区域。
60
+
61
+ ```ts
62
+ weappWebPlugin({
63
+ runtime: {
64
+ viewport: {
65
+ mode: 'mini-program',
66
+ maxWidth: 375,
67
+ desktopBreakpoint: 600,
68
+ },
69
+ },
70
+ })
71
+ ```
72
+
73
+ 已有项目需要保留浏览器全宽布局时,设置 `runtime.viewport.mode: 'responsive'`。
74
+
75
+ ## 浏览器路由
76
+
77
+ 默认使用 `memory` 模式,路由只在运行时页面栈内生效。生产站点可以根据部署方式开启地址栏同步:
78
+
79
+ ```ts
80
+ weappWebPlugin({
81
+ runtime: {
82
+ routing: {
83
+ mode: 'history', // 服务端回退到 index.html
84
+ base: '/mini',
85
+ },
86
+ },
87
+ })
88
+ ```
89
+
90
+ - `history` 使用真实路径,支持从 `/mini/pages/detail/index?sku=42` 深链接进入页面,并同步 `navigateTo`、`redirectTo`、`reLaunch`、`switchTab` 和 `navigateBack`。
91
+ - `hash` 使用 `#/pages/detail/index`,适合没有服务端 history fallback 的静态托管。
92
+ - 两种浏览器模式都会响应前进/后退事件并恢复页面栈;`base` 应与部署目录保持一致。
93
+ - 默认 `memory` 保持现有预览与测试行为,不修改浏览器地址栏。
94
+
95
+ ## 宿主注入
96
+
97
+ Web Runtime 默认读取浏览器原语;测试容器、沙箱或业务宿主可以在注册页面前注入最小 host:
98
+
99
+ ```ts
100
+ import { setWebRuntimeHost } from '@weapp-vite/web'
101
+
102
+ setWebRuntimeHost({
103
+ fetch: hostFetch,
104
+ storage: hostStorage,
105
+ clipboard: hostClipboard,
106
+ dialogs: hostDialogs,
107
+ open: hostOpen,
108
+ })
109
+ ```
110
+
111
+ 注入对象只覆盖提供的能力,其余能力仍使用浏览器回退。测试结束或宿主卸载时调用 `resetWebRuntimeHost()`。
112
+
113
+ ## 组件兼容
114
+
115
+ - `image.mode` 会映射到浏览器的 `object-fit` / `object-position`。
116
+ - `input` 同步 `name`、`value`、`placeholder`、`disabled`、`password`、`maxlength`、`focus`,并发送小程序形状的 `input` / `focus` / `blur` / `confirm` 事件。
117
+ - `scroll-view` 支持横纵滚动、初始滚动位置及带 `scrollLeft`、`scrollTop`、`deltaX`、`deltaY` 的 `scroll` 事件。
118
+ - `form` 统一收集带 `name` 的可用控件值,支持 `button form-type="submit|reset"`、`submit` / `reset` 事件及初始状态恢复。
119
+ - `label` 支持通过 `for` 关联控件,也支持包裹 `input`、`textarea`、`checkbox`、`radio`、`switch` 触发聚焦或选择。
120
+ - `textarea`、`checkbox-group` / `checkbox`、`radio-group` / `radio`、`switch` 支持常用属性、表单值和微信形状的交互事件;脚本同步属性不会误发 `change`。
121
+ - `navigator` 复用页面栈路由,支持 `navigate`、`redirect`、`switchTab`、`reLaunch`、`navigateBack`;`target="miniProgram"` 复用 `navigateToMiniProgram` / `exitMiniProgram` 及其回调。
122
+ - `swiper` / `swiper-item` 支持 current、item-id、横纵布局、循环、指示点、边距、触摸切换和 autoplay,并发送微信形状的 `change`、`transition`、`animationfinish` 事件;组件断开连接时会停止计时器。
123
+ - `picker` 支持 selector、multiSelector、date、time 与 region 模式,selector 可使用 `range-key`,并发送 `change`、`cancel`、`columnchange` 事件;region 在 Web 上仅提供当前层级文本编辑,`code` / `postcode` 不包含行政区数据。
124
+ - `picker-view` / `picker-view-column` 支持受控 value、滚动吸附、mask / indicator 样式及 `change`、`pickstart`、`pickend` 事件。
125
+ - `slider` 支持 min、max、step、value、颜色、block-size、show-value、disabled 与表单值,并发送 `changing` / `change` 事件。
126
+ - `icon` 支持九种微信内建类型及 size / color;未知类型稳定降级为 success。
127
+ - `progress` 支持 percent、show-info、线宽、颜色、圆角、字号及 active 动画,`duration` 与微信一致表示进度每增长 1% 的毫秒数;每次真实动画完成后发送一次 `activeend`,颜色等非动画属性更新不会重复发送完成事件。
128
+ - `rich-text.nodes` 通过 property 保留节点数组,也支持 HTML 字符串;两种输入统一归一化为安全节点树,过滤脚本、事件属性、危险 URL 与危险 CSS 后再使用 DOM API 创建内容,不直接注入任意 `innerHTML`。
129
+ - `canvas` 在 Shadow DOM 内维护真实 2D Canvas,支持通过 `canvas-id` / `id` 创建上下文,并桥接矩形、文字、路径、圆弧、填充、保存恢复和常用变换命令。
130
+ - `video` 同步 src、poster、autoplay、loop、muted、controls、initial-time 与 object-fit;`createVideoContext` 可跨 Shadow DOM 控制对应播放器,并发送微信形状的播放、进度、元信息、错误和全屏事件。
131
+ - `cover-view` / `cover-image` 在媒体或图片上方保留绝对定位与层级;`cover-image` 复用 image 的 mode、src 和 load/error 事件。
132
+ - `movable-area` / `movable-view` 提供裁剪边界、初始 x/y、direction、disabled、out-of-bounds、animation 及 pointer 拖拽,并发送带 x/y/source 的 `change`、`htouchmove`、`vtouchmove` 事件。
133
+ - `setWebRuntimeHost` / `resetWebRuntimeHost` 提供宿主注入边界;网络、存储、剪贴板、对话框和打开链接优先使用注入实现,未注入时回退到浏览器 API。
134
+ - 其他已识别但尚未完整适配的原生组件会继续渲染,并输出去重兼容告警。
135
+
136
+ ## 页面栈与生命周期
137
+
138
+ - 首次挂载页面前依次触发 `App.onLaunch` / `App.onShow`;浏览器 `visibilitychange` 会驱动去重的 `App.onHide` / `App.onShow`。`getLaunchOptionsSync()` 保留初始入口,`getEnterOptionsSync()` 在重新进入前台时更新为当前页面。
139
+ - `navigateTo` 会保留原页面 DOM、实例和数据,并依次触发原页面 `onHide` 与新页面 `onLoad` / `onShow`。
140
+ - `navigateBack` 只卸载出栈页面,恢复目标页面的同一实例、`onShow` 和页面容器滚动位置,不会重新触发 `onLoad`。当前页持续拥有 `#app` 的滚动状态,用户滚动与 `pageScrollTo` 都会写回对应栈项。
141
+ - `redirectTo` 只替换并卸载当前页面;`reLaunch` 会从栈顶开始卸载全部旧页面后挂载目标页面。
142
+ - `getCurrentPages()` 返回当前活动路由栈;其他 tab 页面可保活但不会混入当前 tab 栈。路由 API 支持 `success` / `fail` / `complete` 回调与 Promise 结果。
143
+ - `history` / `hash` 模式使用 `history.scrollRestoration = 'manual'`,避免浏览器窗口滚动与小程序设备容器同时恢复位置;关闭路由同步时会还原原值。
144
+
145
+ ## 页面 Head 与首屏资源
146
+
147
+ 启用 `runtime.seo` 后,页面配置中的 `navigationBarTitleText` 会在路由切换时同步到 `document.title`,并可统一写入 description 与 canonical。`titleTemplate` 使用 `%s` 代表当前页面标题:
148
+
149
+ ```ts
150
+ weappWebPlugin({
151
+ runtime: {
152
+ seo: {
153
+ defaultTitle: '商城',
154
+ titleTemplate: '%s | Web Demo',
155
+ description: '小程序页面的 Web 运行时演示。',
156
+ },
157
+ },
158
+ })
159
+ ```
160
+
161
+ `resourceHints.links` 会去重注入 `preconnect`、`dns-prefetch`、`prefetch` 或 `preload` 链接,适合声明首屏字体、图片和 API 域名:
162
+
163
+ ```ts
164
+ const runtime = {
165
+ resourceHints: {
166
+ links: [{ rel: 'preconnect', href: 'https://cdn.example.com' }],
167
+ },
168
+ }
169
+ ```
170
+
171
+ Head 管理只在浏览器文档存在时生效,不会把客户端路由误认为完整 SSR;服务端预渲染仍需要后续接入独立的 HTML 入口。
172
+
173
+ ## App Shell 与 tabBar
174
+
175
+ - Vite 插件会读取 `app.json.tabBar`,标准 tabBar 在 Web 侧使用受设备视口约束的 App Shell 渲染;颜色、背景、边框、图标、文字和底部安全区由同一份配置驱动。
176
+ - `switchTab` 只接受 tabBar 路由。切换时关闭非 tab 页面,缓存其他 tab 页面实例;再次切回会恢复原数据并触发 `onShow`,不会重复触发 `onLoad`。
177
+ - `showTabBar` / `hideTabBar` 会真实改变布局;`setTabBarItem`、`setTabBarStyle`、badge 与 red-dot API 会同步更新当前 shell。
178
+ - tabBar 页面与普通页面共享 `#app` 设备容器。页面底部 inset、宽屏居中边界和安全区变量会随 tabBar 显隐同步更新。
179
+ - `tabBar.custom: true` 会保留 tab 路由与 `switchTab` 语义,但不会渲染标准 shell;自定义 tabBar 组件仍需业务侧实现。
180
+
181
+ 仓库中的 `pnpm e2e:web:update-baselines` 只用于维护者显式刷新微信 DevTools 视觉基线;普通 `pnpm e2e:web` 只读取已提交基线。
182
+
183
+ 微信 DevTools 的 `App.captureScreenshot` 只截取页面 WebView,不包含宿主原生导航栏和 tabBar。视觉 manifest 会记录每个页面实际截图视口;标准 tabBar 的高度、安全区、选中态与动态 API 由浏览器行为 E2E 单独验证。
184
+
46
185
  ## TODO
47
186
 
48
- - 更全面的模板语法(`slot`、`wx:import` 等)
49
- - 丰富组件属性系统、支持 behaviors / observers
187
+ - 更全面的模板语法和原生组件语义
188
+ - 继续扩展组件属性系统和页面级滚动事件
50
189
  - 全局 API 兼容层与更精细的样式适配
51
- - SSR、SEO 友好的页面容器与首屏优化
190
+ - SSR / 服务端预渲染入口
@@ -1,5 +1,8 @@
1
1
  //#region \0rolldown/runtime.js
2
2
  var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
3
6
  var __exportAll = (all, no_symbols) => {
4
7
  let target = {};
5
8
  for (var name in all) {
@@ -13,6 +16,21 @@ var __exportAll = (all, no_symbols) => {
13
16
  }
14
17
  return target;
15
18
  };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
22
+ key = keys[i];
23
+ if (!__hasOwnProp.call(to, key) && key !== except) {
24
+ __defProp(to, key, {
25
+ get: ((k) => from[k]).bind(null, key),
26
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
27
+ });
28
+ }
29
+ }
30
+ }
31
+ return to;
32
+ };
33
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
16
34
 
17
35
  //#endregion
18
- export { __exportAll };
36
+ export { __exportAll, __reExport };
@@ -80,7 +80,7 @@ function renderAttributes(attribs, scopeVar, wxsVar, options) {
80
80
  buffer += ` @${domEvent}=\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`;
81
81
  continue;
82
82
  }
83
- const useProperty = options?.preferProperty && shouldBindAsProperty(rawName);
83
+ const useProperty = shouldBindAsProperty(rawName) && (options?.preferProperty || options?.propertyAttributes?.includes(rawName));
84
84
  const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName);
85
85
  const expr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
86
86
  buffer += ` ${useProperty ? "." : ""}${name}=\${${expr}}`;
@@ -1 +1 @@
1
- {"version":3,"file":"attributes.mjs","names":[],"sources":["../../../src/compiler/wxml/attributes.ts"],"sourcesContent":["import type { RenderElementNode, RenderNode } from './types'\nimport {\n CONTROL_ATTRS,\n EVENT_KIND_ALIAS,\n EVENT_PREFIX_RE,\n hasControlAttribute,\n normalizeAttributeName,\n resolveControlAttributeValue,\n} from '../../shared/wxml'\nimport { buildExpression, parseInterpolations } from './interpolation'\n\nexport function extractFor(attribs: Record<string, string>) {\n const expr = resolveControlAttributeValue(attribs, 'for')\n const itemName = resolveControlAttributeValue(attribs, 'for-item')?.trim() || 'item'\n let indexName = resolveControlAttributeValue(attribs, 'for-index')?.trim() || 'index'\n const key = resolveControlAttributeValue(attribs, 'key')\n const restAttribs: Record<string, string> = {}\n for (const [name, value] of Object.entries(attribs)) {\n if (CONTROL_ATTRS.has(name)) {\n continue\n }\n restAttribs[name] = value\n }\n if (itemName === indexName) {\n indexName = `${indexName}Index`\n }\n return { expr, itemName, indexName, key, restAttribs }\n}\n\nexport function isConditionalElement(node: RenderNode): node is RenderElementNode {\n if (node.type !== 'element') {\n return false\n }\n const attribs = node.attribs ?? {}\n return hasControlAttribute(attribs, 'if')\n || hasControlAttribute(attribs, 'elif')\n || hasControlAttribute(attribs, 'else')\n}\n\nexport function stripControlAttributes(attribs: Record<string, string>) {\n const result: Record<string, string> = {}\n for (const [name, value] of Object.entries(attribs)) {\n if (!CONTROL_ATTRS.has(name)) {\n result[name] = value\n }\n }\n return result\n}\n\nfunction parseEventAttribute(name: string) {\n if (name.includes(':')) {\n const [prefix, rawEvent] = name.split(':', 2)\n return { prefix, rawEvent }\n }\n const match = EVENT_PREFIX_RE.exec(name)\n if (!match) {\n return undefined\n }\n return { prefix: name.slice(0, name.length - match[1].length), rawEvent: match[1] }\n}\n\nexport function resolveComponentTagName(name: string, componentTags?: Record<string, string>) {\n if (!componentTags) {\n return undefined\n }\n return componentTags[name] ?? componentTags[name.toLowerCase()]\n}\n\nconst PROPERTY_BIND_EXCLUSIONS = new Set(['class', 'style', 'id', 'slot'])\n\nfunction shouldBindAsProperty(name: string) {\n if (PROPERTY_BIND_EXCLUSIONS.has(name)) {\n return false\n }\n if (name.startsWith('data-') || name.startsWith('aria-')) {\n return false\n }\n return true\n}\n\nfunction normalizePropertyName(name: string) {\n return name.replace(/-([a-z])/g, (_, char: string) => char.toUpperCase())\n}\n\nexport function renderAttributes(\n attribs: Record<string, string>,\n scopeVar: string,\n wxsVar: string,\n options?: { skipControl?: boolean, preferProperty?: boolean },\n) {\n let buffer = ''\n for (const [rawName, rawValue] of Object.entries(attribs)) {\n if (options?.skipControl && CONTROL_ATTRS.has(rawName)) {\n continue\n }\n const eventInfo = parseEventAttribute(rawName)\n if (eventInfo) {\n const event = eventInfo.rawEvent.toLowerCase()\n const handlerExpr = buildExpression(parseInterpolations(rawValue ?? ''), scopeVar, wxsVar)\n const domEvent = EVENT_KIND_ALIAS[event] ?? event\n const flags = {\n catch: eventInfo.prefix.includes('catch'),\n capture: eventInfo.prefix.includes('capture'),\n }\n buffer += ` @${domEvent}=\\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`\n continue\n }\n const useProperty = options?.preferProperty && shouldBindAsProperty(rawName)\n const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName)\n const expr = buildExpression(parseInterpolations(rawValue ?? ''), scopeVar, wxsVar)\n buffer += ` ${useProperty ? '.' : ''}${name}=\\${${expr}}`\n }\n return buffer\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"attributes.mjs","names":[],"sources":["../../../src/compiler/wxml/attributes.ts"],"sourcesContent":["import type { RenderElementNode, RenderNode } from './types'\nimport {\n CONTROL_ATTRS,\n EVENT_KIND_ALIAS,\n EVENT_PREFIX_RE,\n hasControlAttribute,\n normalizeAttributeName,\n resolveControlAttributeValue,\n} from '../../shared/wxml'\nimport { buildExpression, parseInterpolations } from './interpolation'\n\nexport function extractFor(attribs: Record<string, string>) {\n const expr = resolveControlAttributeValue(attribs, 'for')\n const itemName = resolveControlAttributeValue(attribs, 'for-item')?.trim() || 'item'\n let indexName = resolveControlAttributeValue(attribs, 'for-index')?.trim() || 'index'\n const key = resolveControlAttributeValue(attribs, 'key')\n const restAttribs: Record<string, string> = {}\n for (const [name, value] of Object.entries(attribs)) {\n if (CONTROL_ATTRS.has(name)) {\n continue\n }\n restAttribs[name] = value\n }\n if (itemName === indexName) {\n indexName = `${indexName}Index`\n }\n return { expr, itemName, indexName, key, restAttribs }\n}\n\nexport function isConditionalElement(node: RenderNode): node is RenderElementNode {\n if (node.type !== 'element') {\n return false\n }\n const attribs = node.attribs ?? {}\n return hasControlAttribute(attribs, 'if')\n || hasControlAttribute(attribs, 'elif')\n || hasControlAttribute(attribs, 'else')\n}\n\nexport function stripControlAttributes(attribs: Record<string, string>) {\n const result: Record<string, string> = {}\n for (const [name, value] of Object.entries(attribs)) {\n if (!CONTROL_ATTRS.has(name)) {\n result[name] = value\n }\n }\n return result\n}\n\nfunction parseEventAttribute(name: string) {\n if (name.includes(':')) {\n const [prefix, rawEvent] = name.split(':', 2)\n return { prefix, rawEvent }\n }\n const match = EVENT_PREFIX_RE.exec(name)\n if (!match) {\n return undefined\n }\n return { prefix: name.slice(0, name.length - match[1].length), rawEvent: match[1] }\n}\n\nexport function resolveComponentTagName(name: string, componentTags?: Record<string, string>) {\n if (!componentTags) {\n return undefined\n }\n return componentTags[name] ?? componentTags[name.toLowerCase()]\n}\n\nconst PROPERTY_BIND_EXCLUSIONS = new Set(['class', 'style', 'id', 'slot'])\n\nfunction shouldBindAsProperty(name: string) {\n if (PROPERTY_BIND_EXCLUSIONS.has(name)) {\n return false\n }\n if (name.startsWith('data-') || name.startsWith('aria-')) {\n return false\n }\n return true\n}\n\nfunction normalizePropertyName(name: string) {\n return name.replace(/-([a-z])/g, (_, char: string) => char.toUpperCase())\n}\n\nexport function renderAttributes(\n attribs: Record<string, string>,\n scopeVar: string,\n wxsVar: string,\n options?: {\n skipControl?: boolean\n preferProperty?: boolean\n propertyAttributes?: readonly string[]\n },\n) {\n let buffer = ''\n for (const [rawName, rawValue] of Object.entries(attribs)) {\n if (options?.skipControl && CONTROL_ATTRS.has(rawName)) {\n continue\n }\n const eventInfo = parseEventAttribute(rawName)\n if (eventInfo) {\n const event = eventInfo.rawEvent.toLowerCase()\n const handlerExpr = buildExpression(parseInterpolations(rawValue ?? ''), scopeVar, wxsVar)\n const domEvent = EVENT_KIND_ALIAS[event] ?? event\n const flags = {\n catch: eventInfo.prefix.includes('catch'),\n capture: eventInfo.prefix.includes('capture'),\n }\n buffer += ` @${domEvent}=\\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`\n continue\n }\n const useProperty = shouldBindAsProperty(rawName)\n && (options?.preferProperty || options?.propertyAttributes?.includes(rawName))\n const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName)\n const expr = buildExpression(parseInterpolations(rawValue ?? ''), scopeVar, wxsVar)\n buffer += ` ${useProperty ? '.' : ''}${name}=\\${${expr}}`\n }\n return buffer\n}\n"],"mappings":"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"}
@@ -6,13 +6,16 @@ import { collectSpecialNodes, normalizeTemplatePath, shouldMarkWxsImport, toRela
6
6
  import { readFileSync } from "node:fs";
7
7
 
8
8
  //#region src/compiler/wxml/compile.ts
9
+ const WEB_TEMPLATE_QUERY = "weapp-web-template";
10
+ function appendTemplateQuery(pathname) {
11
+ return `${pathname}${pathname.includes("?") ? "&" : "?"}${WEB_TEMPLATE_QUERY}`;
12
+ }
9
13
  function compileWxml(options) {
10
14
  const dependencyContext = options.dependencyContext ?? createDependencyContext();
11
15
  const expandDependencies = options.expandDependencies ?? !options.dependencyContext;
12
16
  const warnings = dependencyContext.warnings;
13
17
  const expandDependencyTree = (dependencies, importer) => {
14
18
  for (const target of dependencies) {
15
- if (!target) continue;
16
19
  if (dependencyContext.active.has(target)) {
17
20
  warnCircularTemplate(dependencyContext, importer, target);
18
21
  continue;
@@ -80,12 +83,12 @@ function compileWxml(options) {
80
83
  const directDependencies = [];
81
84
  for (const entry of imports) {
82
85
  const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id));
83
- importLines.push(`import { templates as ${entry.importName} } from '${importPath}'`);
86
+ importLines.push(`import { templates as ${entry.importName} } from '${appendTemplateQuery(importPath)}'`);
84
87
  addDependency(entry.id, dependencyContext, directDependencies);
85
88
  }
86
89
  for (const entry of includes) {
87
90
  const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id));
88
- importLines.push(`import { render as ${entry.importName} } from '${importPath}'`);
91
+ importLines.push(`import { render as ${entry.importName} } from '${appendTemplateQuery(importPath)}'`);
89
92
  addDependency(entry.id, dependencyContext, directDependencies);
90
93
  }
91
94
  for (const entry of wxs) if (entry.kind === "src") {
@@ -1 +1 @@
1
- {"version":3,"file":"compile.mjs","names":[],"sources":["../../../src/compiler/wxml/compile.ts"],"sourcesContent":["import type {\n ImportEntry,\n IncludeEntry,\n TemplateDefinition,\n WxmlCompileOptions,\n WxmlCompileResult,\n WxsEntry,\n} from './types'\n\nimport { readFileSync } from 'node:fs'\nimport { addDependency, createDependencyContext, warnCircularTemplate, warnReadTemplate } from './dependency'\nimport { buildNavigationBarAttrs, extractNavigationBarFromPageMeta } from './navigation'\nimport { parseWxml } from './parser'\nimport { renderer } from './renderer'\nimport { collectSpecialNodes, normalizeTemplatePath, shouldMarkWxsImport, toRelativeImport } from './specialNodes'\n\nexport function compileWxml(options: WxmlCompileOptions): WxmlCompileResult {\n const dependencyContext = options.dependencyContext ?? createDependencyContext()\n const expandDependencies = options.expandDependencies ?? !options.dependencyContext\n const warnings = dependencyContext.warnings\n\n const expandDependencyTree = (dependencies: string[], importer: string) => {\n for (const target of dependencies) {\n if (!target) {\n continue\n }\n if (dependencyContext.active.has(target)) {\n warnCircularTemplate(dependencyContext, importer, target)\n continue\n }\n if (dependencyContext.visited.has(target)) {\n continue\n }\n dependencyContext.visited.add(target)\n dependencyContext.active.add(target)\n let source: string\n try {\n source = readFileSync(target, 'utf8')\n }\n catch {\n warnReadTemplate(dependencyContext, target)\n dependencyContext.active.delete(target)\n continue\n }\n try {\n const result = compileWxml({\n id: target,\n source,\n resolveTemplatePath: options.resolveTemplatePath,\n resolveWxsPath: options.resolveWxsPath,\n dependencyContext,\n expandDependencies: false,\n })\n expandDependencyTree(result.dependencies, target)\n }\n catch (error) {\n if (error instanceof Error && error.message) {\n warnings.push(`[web] 无法解析模板依赖: ${target} ${error.message}`)\n }\n }\n dependencyContext.active.delete(target)\n }\n }\n\n let nodes = parseWxml(options.source)\n let navigationBarAttrs: Record<string, string> | undefined\n if (options.navigationBar) {\n const extracted = extractNavigationBarFromPageMeta(nodes)\n nodes = extracted.nodes\n if (extracted.warnings.length > 0) {\n warnings.push(...extracted.warnings)\n }\n navigationBarAttrs = extracted.attrs\n }\n\n const templates: TemplateDefinition[] = []\n const includes: IncludeEntry[] = []\n const imports: ImportEntry[] = []\n const wxs: WxsEntry[] = []\n const wxsModules = new Map<string, string>()\n\n const renderNodesList = collectSpecialNodes(nodes, {\n templates,\n includes,\n imports,\n wxs,\n wxsModules,\n warnings,\n sourceId: options.id,\n resolveTemplate: (raw: string) => options.resolveTemplatePath(raw, options.id),\n resolveWxs: (raw: string) => options.resolveWxsPath(raw, options.id),\n })\n\n if (options.navigationBar && options.navigationBar.config.navigationStyle !== 'custom') {\n const attrs = buildNavigationBarAttrs(options.navigationBar.config, navigationBarAttrs)\n renderNodesList.unshift({\n type: 'element',\n name: 'weapp-navigation-bar',\n attribs: attrs,\n })\n }\n\n const importLines: string[] = [\n `import { html } from 'lit'`,\n `import { repeat } from 'lit/directives/repeat.js'`,\n ]\n const bodyLines: string[] = []\n const directDependencies: string[] = []\n\n for (const entry of imports) {\n const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id))\n importLines.push(`import { templates as ${entry.importName} } from '${importPath}'`)\n addDependency(entry.id, dependencyContext, directDependencies)\n }\n\n for (const entry of includes) {\n const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id))\n importLines.push(`import { render as ${entry.importName} } from '${importPath}'`)\n addDependency(entry.id, dependencyContext, directDependencies)\n }\n\n for (const entry of wxs) {\n if (entry.kind === 'src') {\n const baseImport = normalizeTemplatePath(toRelativeImport(options.id, entry.value))\n const importPath = shouldMarkWxsImport(entry.value)\n ? `${baseImport}?wxs`\n : baseImport\n importLines.push(`import ${entry.importName} from '${importPath}'`)\n addDependency(entry.value, dependencyContext, directDependencies)\n }\n }\n\n if (templates.length > 0 || imports.length > 0) {\n const templatePairs: string[] = []\n for (const entry of imports) {\n templatePairs.push(`...${entry.importName}`)\n }\n for (const template of templates) {\n const rendered = renderer.renderNodes(template.nodes, 'scope', '__wxs_modules', options.componentTags)\n templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`)\n }\n bodyLines.push(`const __templates = { ${templatePairs.join(', ')} }`)\n }\n else {\n bodyLines.push(`const __templates = {}`)\n }\n\n if (wxs.length > 0) {\n bodyLines.push(`const __wxs_inline_cache = Object.create(null)`)\n bodyLines.push(`let __wxs_modules = {}`)\n const wxsMapEntries: string[] = []\n for (const entry of wxs) {\n if (entry.kind === 'inline') {\n const inlineCode = entry.value.trim()\n const cacheKey = JSON.stringify(entry.module)\n if (inlineCode) {\n bodyLines.push(`function ${entry.importName}(ctx) {`)\n bodyLines.push(` if (!__wxs_inline_cache[${cacheKey}]) {`)\n bodyLines.push(` __wxs_inline_cache[${cacheKey}] = ctx.createWxsModule(${JSON.stringify(inlineCode)}, ${JSON.stringify(options.id)})`)\n bodyLines.push(` }`)\n bodyLines.push(` return __wxs_inline_cache[${cacheKey}]`)\n bodyLines.push(`}`)\n }\n else {\n bodyLines.push(`function ${entry.importName}() { return {} }`)\n }\n wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}(ctx)`)\n continue\n }\n wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}`)\n }\n bodyLines.push(`function __resolveWxsModules(ctx) {`)\n bodyLines.push(` return { ${wxsMapEntries.join(', ')} }`)\n bodyLines.push(`}`)\n }\n else {\n bodyLines.push(`const __wxs_modules = {}`)\n }\n\n const includesRender = includes.map(entry => `${entry.importName}(scope, ctx)`)\n const renderContent = renderer.renderNodes(renderNodesList, 'scope', '__wxs_modules', options.componentTags)\n const contentExpr = includesRender.length > 0\n ? `[${[...includesRender, renderContent].join(', ')}]`\n : renderContent\n\n bodyLines.push(`export function render(scope, ctx) {`)\n if (wxs.length > 0) {\n bodyLines.push(` __wxs_modules = __resolveWxsModules(ctx)`)\n }\n bodyLines.push(` return ${contentExpr}`)\n bodyLines.push(`}`)\n bodyLines.push(`export const templates = __templates`)\n bodyLines.push(`export default render`)\n\n if (expandDependencies) {\n dependencyContext.visited.add(options.id)\n dependencyContext.active.add(options.id)\n expandDependencyTree(directDependencies, options.id)\n dependencyContext.active.delete(options.id)\n }\n\n const code = [...importLines, '', ...bodyLines].join('\\n')\n const dependencies = expandDependencies ? dependencyContext.dependencies : directDependencies\n return {\n code,\n dependencies,\n warnings: warnings.length > 0 ? warnings : undefined,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"compile.mjs","names":[],"sources":["../../../src/compiler/wxml/compile.ts"],"sourcesContent":["import type {\n ImportEntry,\n IncludeEntry,\n TemplateDefinition,\n WxmlCompileOptions,\n WxmlCompileResult,\n WxsEntry,\n} from './types'\n\nimport { readFileSync } from 'node:fs'\nimport { addDependency, createDependencyContext, warnCircularTemplate, warnReadTemplate } from './dependency'\nimport { buildNavigationBarAttrs, extractNavigationBarFromPageMeta } from './navigation'\nimport { parseWxml } from './parser'\nimport { renderer } from './renderer'\nimport { collectSpecialNodes, normalizeTemplatePath, shouldMarkWxsImport, toRelativeImport } from './specialNodes'\n\nconst WEB_TEMPLATE_QUERY = 'weapp-web-template'\n\nfunction appendTemplateQuery(pathname: string) {\n return `${pathname}${pathname.includes('?') ? '&' : '?'}${WEB_TEMPLATE_QUERY}`\n}\n\nexport function compileWxml(options: WxmlCompileOptions): WxmlCompileResult {\n const dependencyContext = options.dependencyContext ?? createDependencyContext()\n const expandDependencies = options.expandDependencies ?? !options.dependencyContext\n const warnings = dependencyContext.warnings\n\n const expandDependencyTree = (dependencies: string[], importer: string) => {\n for (const target of dependencies) {\n if (dependencyContext.active.has(target)) {\n warnCircularTemplate(dependencyContext, importer, target)\n continue\n }\n if (dependencyContext.visited.has(target)) {\n continue\n }\n dependencyContext.visited.add(target)\n dependencyContext.active.add(target)\n let source: string\n try {\n source = readFileSync(target, 'utf8')\n }\n catch {\n warnReadTemplate(dependencyContext, target)\n dependencyContext.active.delete(target)\n continue\n }\n try {\n const result = compileWxml({\n id: target,\n source,\n resolveTemplatePath: options.resolveTemplatePath,\n resolveWxsPath: options.resolveWxsPath,\n dependencyContext,\n expandDependencies: false,\n })\n expandDependencyTree(result.dependencies, target)\n }\n catch (error) {\n if (error instanceof Error && error.message) {\n warnings.push(`[web] 无法解析模板依赖: ${target} ${error.message}`)\n }\n }\n dependencyContext.active.delete(target)\n }\n }\n\n let nodes = parseWxml(options.source)\n let navigationBarAttrs: Record<string, string> | undefined\n if (options.navigationBar) {\n const extracted = extractNavigationBarFromPageMeta(nodes)\n nodes = extracted.nodes\n if (extracted.warnings.length > 0) {\n warnings.push(...extracted.warnings)\n }\n navigationBarAttrs = extracted.attrs\n }\n\n const templates: TemplateDefinition[] = []\n const includes: IncludeEntry[] = []\n const imports: ImportEntry[] = []\n const wxs: WxsEntry[] = []\n const wxsModules = new Map<string, string>()\n\n const renderNodesList = collectSpecialNodes(nodes, {\n templates,\n includes,\n imports,\n wxs,\n wxsModules,\n warnings,\n sourceId: options.id,\n resolveTemplate: (raw: string) => options.resolveTemplatePath(raw, options.id),\n resolveWxs: (raw: string) => options.resolveWxsPath(raw, options.id),\n })\n\n if (options.navigationBar && options.navigationBar.config.navigationStyle !== 'custom') {\n const attrs = buildNavigationBarAttrs(options.navigationBar.config, navigationBarAttrs)\n renderNodesList.unshift({\n type: 'element',\n name: 'weapp-navigation-bar',\n attribs: attrs,\n })\n }\n\n const importLines: string[] = [\n `import { html } from 'lit'`,\n `import { repeat } from 'lit/directives/repeat.js'`,\n ]\n const bodyLines: string[] = []\n const directDependencies: string[] = []\n\n for (const entry of imports) {\n const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id))\n importLines.push(`import { templates as ${entry.importName} } from '${appendTemplateQuery(importPath)}'`)\n addDependency(entry.id, dependencyContext, directDependencies)\n }\n\n for (const entry of includes) {\n const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id))\n importLines.push(`import { render as ${entry.importName} } from '${appendTemplateQuery(importPath)}'`)\n addDependency(entry.id, dependencyContext, directDependencies)\n }\n\n for (const entry of wxs) {\n if (entry.kind === 'src') {\n const baseImport = normalizeTemplatePath(toRelativeImport(options.id, entry.value))\n const importPath = shouldMarkWxsImport(entry.value)\n ? `${baseImport}?wxs`\n : baseImport\n importLines.push(`import ${entry.importName} from '${importPath}'`)\n addDependency(entry.value, dependencyContext, directDependencies)\n }\n }\n\n if (templates.length > 0 || imports.length > 0) {\n const templatePairs: string[] = []\n for (const entry of imports) {\n templatePairs.push(`...${entry.importName}`)\n }\n for (const template of templates) {\n const rendered = renderer.renderNodes(template.nodes, 'scope', '__wxs_modules', options.componentTags)\n templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`)\n }\n bodyLines.push(`const __templates = { ${templatePairs.join(', ')} }`)\n }\n else {\n bodyLines.push(`const __templates = {}`)\n }\n\n if (wxs.length > 0) {\n bodyLines.push(`const __wxs_inline_cache = Object.create(null)`)\n bodyLines.push(`let __wxs_modules = {}`)\n const wxsMapEntries: string[] = []\n for (const entry of wxs) {\n if (entry.kind === 'inline') {\n const inlineCode = entry.value.trim()\n const cacheKey = JSON.stringify(entry.module)\n if (inlineCode) {\n bodyLines.push(`function ${entry.importName}(ctx) {`)\n bodyLines.push(` if (!__wxs_inline_cache[${cacheKey}]) {`)\n bodyLines.push(` __wxs_inline_cache[${cacheKey}] = ctx.createWxsModule(${JSON.stringify(inlineCode)}, ${JSON.stringify(options.id)})`)\n bodyLines.push(` }`)\n bodyLines.push(` return __wxs_inline_cache[${cacheKey}]`)\n bodyLines.push(`}`)\n }\n else {\n bodyLines.push(`function ${entry.importName}() { return {} }`)\n }\n wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}(ctx)`)\n continue\n }\n wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}`)\n }\n bodyLines.push(`function __resolveWxsModules(ctx) {`)\n bodyLines.push(` return { ${wxsMapEntries.join(', ')} }`)\n bodyLines.push(`}`)\n }\n else {\n bodyLines.push(`const __wxs_modules = {}`)\n }\n\n const includesRender = includes.map(entry => `${entry.importName}(scope, ctx)`)\n const renderContent = renderer.renderNodes(renderNodesList, 'scope', '__wxs_modules', options.componentTags)\n const contentExpr = includesRender.length > 0\n ? `[${[...includesRender, renderContent].join(', ')}]`\n : renderContent\n\n bodyLines.push(`export function render(scope, ctx) {`)\n if (wxs.length > 0) {\n bodyLines.push(` __wxs_modules = __resolveWxsModules(ctx)`)\n }\n bodyLines.push(` return ${contentExpr}`)\n bodyLines.push(`}`)\n bodyLines.push(`export const templates = __templates`)\n bodyLines.push(`export default render`)\n\n if (expandDependencies) {\n dependencyContext.visited.add(options.id)\n dependencyContext.active.add(options.id)\n expandDependencyTree(directDependencies, options.id)\n dependencyContext.active.delete(options.id)\n }\n\n const code = [...importLines, '', ...bodyLines].join('\\n')\n const dependencies = expandDependencies ? dependencyContext.dependencies : directDependencies\n return {\n code,\n dependencies,\n warnings: warnings.length > 0 ? warnings : undefined,\n }\n}\n"],"mappings":"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"}
@@ -121,7 +121,6 @@ function hasTopLevelColon(expression) {
121
121
  }
122
122
  function shouldWrapShorthandObject(expression) {
123
123
  const trimmed = expression.trim();
124
- if (!trimmed) return false;
125
124
  if (trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith("(")) return false;
126
125
  return hasTopLevelColon(trimmed);
127
126
  }
@@ -129,7 +128,7 @@ function buildTemplateDataExpression(raw, scopeVar, wxsVar) {
129
128
  const parts = parseInterpolations(raw.trim());
130
129
  if (parts.length === 1 && parts[0]?.type === "expr") {
131
130
  const expr = parts[0].value.trim();
132
- if (expr) return buildExpression([{
131
+ return buildExpression([{
133
132
  type: "expr",
134
133
  value: shouldWrapShorthandObject(expr) ? `{ ${expr} }` : expr
135
134
  }], scopeVar, wxsVar);
@@ -1 +1 @@
1
- {"version":3,"file":"interpolation.mjs","names":[],"sources":["../../../src/compiler/wxml/interpolation.ts"],"sourcesContent":["import type { InterpolationPart } from './types'\n\nexport function parseInterpolations(value: string): InterpolationPart[] {\n const parts: InterpolationPart[] = []\n if (!value.includes('{{')) {\n return [{ type: 'text', value }]\n }\n let cursor = 0\n while (cursor < value.length) {\n const start = value.indexOf('{{', cursor)\n if (start === -1) {\n parts.push({ type: 'text', value: value.slice(cursor) })\n break\n }\n if (start > cursor) {\n parts.push({ type: 'text', value: value.slice(cursor, start) })\n }\n const end = value.indexOf('}}', start + 2)\n if (end === -1) {\n parts.push({ type: 'text', value: value.slice(start) })\n break\n }\n const expr = value.slice(start + 2, end).trim()\n if (expr) {\n parts.push({ type: 'expr', value: expr })\n }\n cursor = end + 2\n }\n return parts\n}\n\nexport function buildExpression(parts: InterpolationPart[], scopeVar: string, wxsVar: string) {\n if (parts.length === 0) {\n return '\"\"'\n }\n if (parts.length === 1 && parts[0]?.type === 'text') {\n return JSON.stringify(parts[0].value)\n }\n if (parts.length === 1 && parts[0]?.type === 'expr') {\n return `ctx.eval(${JSON.stringify(parts[0].value)}, ${scopeVar}, ${wxsVar})`\n }\n const segments = parts.map((part) => {\n if (part.type === 'text') {\n return JSON.stringify(part.value)\n }\n return `ctx.eval(${JSON.stringify(part.value)}, ${scopeVar}, ${wxsVar})`\n })\n return `(${segments.join(' + ')})`\n}\n\nfunction hasTopLevelColon(expression: string) {\n let depth = 0\n let inSingleQuote = false\n let inDoubleQuote = false\n let inTemplate = false\n let escaped = false\n let sawTopLevelQuestion = false\n\n for (let index = 0; index < expression.length; index += 1) {\n const char = expression[index]!\n\n if (inSingleQuote) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '\\'') {\n inSingleQuote = false\n }\n continue\n }\n if (inDoubleQuote) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '\"') {\n inDoubleQuote = false\n }\n continue\n }\n if (inTemplate) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '`') {\n inTemplate = false\n }\n continue\n }\n\n if (char === '\\'') {\n inSingleQuote = true\n continue\n }\n if (char === '\"') {\n inDoubleQuote = true\n continue\n }\n if (char === '`') {\n inTemplate = true\n continue\n }\n\n if (char === '(' || char === '[' || char === '{') {\n depth += 1\n continue\n }\n if (char === ')' || char === ']' || char === '}') {\n depth = Math.max(0, depth - 1)\n continue\n }\n\n if (depth !== 0) {\n continue\n }\n\n if (char === '?') {\n sawTopLevelQuestion = true\n continue\n }\n if (char === ':') {\n return !sawTopLevelQuestion\n }\n }\n\n return false\n}\n\nfunction shouldWrapShorthandObject(expression: string) {\n const trimmed = expression.trim()\n if (!trimmed) {\n return false\n }\n if (trimmed.startsWith('{') || trimmed.startsWith('[') || trimmed.startsWith('(')) {\n return false\n }\n return hasTopLevelColon(trimmed)\n}\n\nexport function buildTemplateDataExpression(raw: string, scopeVar: string, wxsVar: string) {\n const trimmed = raw.trim()\n const parts = parseInterpolations(trimmed)\n if (parts.length === 1 && parts[0]?.type === 'expr') {\n const expr = parts[0].value.trim()\n if (expr) {\n const normalizedExpr = shouldWrapShorthandObject(expr) ? `{ ${expr} }` : expr\n return buildExpression([{ type: 'expr', value: normalizedExpr }], scopeVar, wxsVar)\n }\n }\n return buildExpression(parseInterpolations(raw), scopeVar, wxsVar)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"interpolation.mjs","names":[],"sources":["../../../src/compiler/wxml/interpolation.ts"],"sourcesContent":["import type { InterpolationPart } from './types'\n\nexport function parseInterpolations(value: string): InterpolationPart[] {\n const parts: InterpolationPart[] = []\n if (!value.includes('{{')) {\n return [{ type: 'text', value }]\n }\n let cursor = 0\n while (cursor < value.length) {\n const start = value.indexOf('{{', cursor)\n if (start === -1) {\n parts.push({ type: 'text', value: value.slice(cursor) })\n break\n }\n if (start > cursor) {\n parts.push({ type: 'text', value: value.slice(cursor, start) })\n }\n const end = value.indexOf('}}', start + 2)\n if (end === -1) {\n parts.push({ type: 'text', value: value.slice(start) })\n break\n }\n const expr = value.slice(start + 2, end).trim()\n if (expr) {\n parts.push({ type: 'expr', value: expr })\n }\n cursor = end + 2\n }\n return parts\n}\n\nexport function buildExpression(parts: InterpolationPart[], scopeVar: string, wxsVar: string) {\n if (parts.length === 0) {\n return '\"\"'\n }\n if (parts.length === 1 && parts[0]?.type === 'text') {\n return JSON.stringify(parts[0].value)\n }\n if (parts.length === 1 && parts[0]?.type === 'expr') {\n return `ctx.eval(${JSON.stringify(parts[0].value)}, ${scopeVar}, ${wxsVar})`\n }\n const segments = parts.map((part) => {\n if (part.type === 'text') {\n return JSON.stringify(part.value)\n }\n return `ctx.eval(${JSON.stringify(part.value)}, ${scopeVar}, ${wxsVar})`\n })\n return `(${segments.join(' + ')})`\n}\n\nfunction hasTopLevelColon(expression: string) {\n let depth = 0\n let inSingleQuote = false\n let inDoubleQuote = false\n let inTemplate = false\n let escaped = false\n let sawTopLevelQuestion = false\n\n for (let index = 0; index < expression.length; index += 1) {\n const char = expression[index]!\n\n if (inSingleQuote) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '\\'') {\n inSingleQuote = false\n }\n continue\n }\n if (inDoubleQuote) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '\"') {\n inDoubleQuote = false\n }\n continue\n }\n if (inTemplate) {\n if (escaped) {\n escaped = false\n continue\n }\n if (char === '\\\\') {\n escaped = true\n continue\n }\n if (char === '`') {\n inTemplate = false\n }\n continue\n }\n\n if (char === '\\'') {\n inSingleQuote = true\n continue\n }\n if (char === '\"') {\n inDoubleQuote = true\n continue\n }\n if (char === '`') {\n inTemplate = true\n continue\n }\n\n if (char === '(' || char === '[' || char === '{') {\n depth += 1\n continue\n }\n if (char === ')' || char === ']' || char === '}') {\n depth = Math.max(0, depth - 1)\n continue\n }\n\n if (depth !== 0) {\n continue\n }\n\n if (char === '?') {\n sawTopLevelQuestion = true\n continue\n }\n if (char === ':') {\n return !sawTopLevelQuestion\n }\n }\n\n return false\n}\n\nfunction shouldWrapShorthandObject(expression: string) {\n const trimmed = expression.trim()\n if (trimmed.startsWith('{') || trimmed.startsWith('[') || trimmed.startsWith('(')) {\n return false\n }\n return hasTopLevelColon(trimmed)\n}\n\nexport function buildTemplateDataExpression(raw: string, scopeVar: string, wxsVar: string) {\n const trimmed = raw.trim()\n const parts = parseInterpolations(trimmed)\n if (parts.length === 1 && parts[0]?.type === 'expr') {\n const expr = parts[0].value.trim()\n const normalizedExpr = shouldWrapShorthandObject(expr) ? `{ ${expr} }` : expr\n return buildExpression([{ type: 'expr', value: normalizedExpr }], scopeVar, wxsVar)\n }\n return buildExpression(parseInterpolations(raw), scopeVar, wxsVar)\n}\n"],"mappings":"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"}
@@ -12,13 +12,11 @@ function stripPageMetaNodes(nodes) {
12
12
  if (node.type === "element" && node.name === "page-meta") continue;
13
13
  if (node.type === "element" && node.children?.length) {
14
14
  const nextChildren = stripPageMetaNodes(node.children);
15
- if (nextChildren !== node.children) {
16
- stripped.push({
17
- ...node,
18
- children: nextChildren
19
- });
20
- continue;
21
- }
15
+ stripped.push({
16
+ ...node,
17
+ children: nextChildren
18
+ });
19
+ continue;
22
20
  }
23
21
  stripped.push(node);
24
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.mjs","names":[],"sources":["../../../src/compiler/wxml/navigation.ts"],"sourcesContent":["import type { NavigationBarConfig, RenderElementNode, RenderNode } from './types'\n\nconst NAVIGATION_BAR_ATTRS = new Set([\n 'title',\n 'background-color',\n 'text-style',\n 'front-color',\n 'loading',\n])\n\nfunction stripPageMetaNodes(nodes: RenderNode[]): RenderNode[] {\n const stripped: RenderNode[] = []\n for (const node of nodes) {\n if (node.type === 'element' && node.name === 'page-meta') {\n continue\n }\n if (node.type === 'element' && node.children?.length) {\n const nextChildren = stripPageMetaNodes(node.children)\n if (nextChildren !== node.children) {\n stripped.push({ ...node, children: nextChildren })\n continue\n }\n }\n stripped.push(node)\n }\n return stripped\n}\n\nfunction pickNavigationBarAttrs(attribs: Record<string, string> | undefined) {\n if (!attribs) {\n return undefined\n }\n const picked: Record<string, string> = {}\n for (const [key, value] of Object.entries(attribs)) {\n if (NAVIGATION_BAR_ATTRS.has(key)) {\n picked[key] = value\n }\n }\n return Object.keys(picked).length > 0 ? picked : undefined\n}\n\nfunction findNavigationBarInPageMeta(node: RenderElementNode) {\n const children = node.children ?? []\n for (const child of children) {\n if (child.type === 'element' && child.name === 'navigation-bar') {\n return child\n }\n }\n return undefined\n}\n\nexport function extractNavigationBarFromPageMeta(nodes: RenderNode[]): {\n nodes: RenderNode[]\n attrs?: Record<string, string>\n warnings: string[]\n} {\n let pageMetaIndex = -1\n let navigationBar: RenderElementNode | undefined\n for (let i = 0; i < nodes.length; i += 1) {\n const node = nodes[i]\n if (node.type === 'element' && node.name === 'page-meta') {\n if (pageMetaIndex === -1) {\n pageMetaIndex = i\n }\n if (!navigationBar) {\n navigationBar = findNavigationBarInPageMeta(node)\n }\n }\n }\n const warnings: string[] = []\n if (pageMetaIndex > 0) {\n warnings.push('[web] page-meta 需要作为页面第一个节点,已忽略其位置约束。')\n }\n const cleaned = pageMetaIndex === -1 ? nodes : stripPageMetaNodes(nodes)\n const attrs = navigationBar ? pickNavigationBarAttrs(navigationBar.attribs) : undefined\n return { nodes: cleaned, attrs, warnings }\n}\n\nfunction toAttributeValue(value: unknown) {\n if (value == null) {\n return undefined\n }\n if (typeof value === 'string') {\n return value\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value)\n }\n return undefined\n}\n\nexport function buildNavigationBarAttrs(\n config: NavigationBarConfig | undefined,\n overrides?: Record<string, string>,\n) {\n const attrs: Record<string, string> = {}\n if (config?.title !== undefined) {\n const value = toAttributeValue(config.title)\n if (value !== undefined) {\n attrs.title = value\n }\n }\n if (config?.backgroundColor !== undefined) {\n const value = toAttributeValue(config.backgroundColor)\n if (value !== undefined) {\n attrs['background-color'] = value\n }\n }\n if (config?.textStyle !== undefined) {\n const value = toAttributeValue(config.textStyle)\n if (value !== undefined) {\n attrs['text-style'] = value\n }\n }\n if (config?.frontColor !== undefined) {\n const value = toAttributeValue(config.frontColor)\n if (value !== undefined) {\n attrs['front-color'] = value\n }\n }\n if (config?.loading) {\n attrs.loading = 'true'\n }\n if (overrides) {\n for (const [key, value] of Object.entries(overrides)) {\n attrs[key] = value\n }\n }\n return attrs\n}\n"],"mappings":";AAEA,MAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,mBAAmB,OAAmC;CAC7D,MAAM,WAAyB,CAAC;CAChC,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,SAAS,aAAa,KAAK,SAAS,aAC3C;EAEF,IAAI,KAAK,SAAS,aAAa,KAAK,UAAU,QAAQ;GACpD,MAAM,eAAe,mBAAmB,KAAK,QAAQ;GACrD,IAAI,iBAAiB,KAAK,UAAU;IAClC,SAAS,KAAK;KAAE,GAAG;KAAM,UAAU;IAAa,CAAC;IACjD;GACF;EACF;EACA,SAAS,KAAK,IAAI;CACpB;CACA,OAAO;AACT;AAEA,SAAS,uBAAuB,SAA6C;CAC3E,IAAI,CAAC,SACH;CAEF,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC/C,IAAI,qBAAqB,IAAI,GAAG,GAC9B,OAAO,OAAO;CAGlB,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS;AACnD;AAEA,SAAS,4BAA4B,MAAyB;CAC5D,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,KAAK,MAAM,SAAS,UAClB,IAAI,MAAM,SAAS,aAAa,MAAM,SAAS,kBAC7C,OAAO;AAIb;AAEA,SAAgB,iCAAiC,OAI/C;CACA,IAAI,gBAAgB;CACpB,IAAI;CACJ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,OAAO,MAAM;EACnB,IAAI,KAAK,SAAS,aAAa,KAAK,SAAS,aAAa;GACxD,IAAI,kBAAkB,IACpB,gBAAgB;GAElB,IAAI,CAAC,eACH,gBAAgB,4BAA4B,IAAI;EAEpD;CACF;CACA,MAAM,WAAqB,CAAC;CAC5B,IAAI,gBAAgB,GAClB,SAAS,KAAK,uCAAuC;CAIvD,OAAO;EAAE,OAFO,kBAAkB,KAAK,QAAQ,mBAAmB,KAAK;EAE9C,OADX,gBAAgB,uBAAuB,cAAc,OAAO,IAAI;EAC9C;CAAS;AAC3C;AAEA,SAAS,iBAAiB,OAAgB;CACxC,IAAI,SAAS,MACX;CAEF,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAChD,OAAO,OAAO,KAAK;AAGvB;AAEA,SAAgB,wBACd,QACA,WACA;CACA,MAAM,QAAgC,CAAC;CACvC,IAAI,QAAQ,UAAU,QAAW;EAC/B,MAAM,QAAQ,iBAAiB,OAAO,KAAK;EAC3C,IAAI,UAAU,QACZ,MAAM,QAAQ;CAElB;CACA,IAAI,QAAQ,oBAAoB,QAAW;EACzC,MAAM,QAAQ,iBAAiB,OAAO,eAAe;EACrD,IAAI,UAAU,QACZ,MAAM,sBAAsB;CAEhC;CACA,IAAI,QAAQ,cAAc,QAAW;EACnC,MAAM,QAAQ,iBAAiB,OAAO,SAAS;EAC/C,IAAI,UAAU,QACZ,MAAM,gBAAgB;CAE1B;CACA,IAAI,QAAQ,eAAe,QAAW;EACpC,MAAM,QAAQ,iBAAiB,OAAO,UAAU;EAChD,IAAI,UAAU,QACZ,MAAM,iBAAiB;CAE3B;CACA,IAAI,QAAQ,SACV,MAAM,UAAU;CAElB,IAAI,WACF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,GACjD,MAAM,OAAO;CAGjB,OAAO;AACT"}
1
+ {"version":3,"file":"navigation.mjs","names":[],"sources":["../../../src/compiler/wxml/navigation.ts"],"sourcesContent":["import type { NavigationBarConfig, RenderElementNode, RenderNode } from './types'\n\nconst NAVIGATION_BAR_ATTRS = new Set([\n 'title',\n 'background-color',\n 'text-style',\n 'front-color',\n 'loading',\n])\n\nfunction stripPageMetaNodes(nodes: RenderNode[]): RenderNode[] {\n const stripped: RenderNode[] = []\n for (const node of nodes) {\n if (node.type === 'element' && node.name === 'page-meta') {\n continue\n }\n if (node.type === 'element' && node.children?.length) {\n const nextChildren = stripPageMetaNodes(node.children)\n stripped.push({ ...node, children: nextChildren })\n continue\n }\n stripped.push(node)\n }\n return stripped\n}\n\nfunction pickNavigationBarAttrs(attribs: Record<string, string> | undefined) {\n if (!attribs) {\n return undefined\n }\n const picked: Record<string, string> = {}\n for (const [key, value] of Object.entries(attribs)) {\n if (NAVIGATION_BAR_ATTRS.has(key)) {\n picked[key] = value\n }\n }\n return Object.keys(picked).length > 0 ? picked : undefined\n}\n\nfunction findNavigationBarInPageMeta(node: RenderElementNode) {\n const children = node.children ?? []\n for (const child of children) {\n if (child.type === 'element' && child.name === 'navigation-bar') {\n return child\n }\n }\n return undefined\n}\n\nexport function extractNavigationBarFromPageMeta(nodes: RenderNode[]): {\n nodes: RenderNode[]\n attrs?: Record<string, string>\n warnings: string[]\n} {\n let pageMetaIndex = -1\n let navigationBar: RenderElementNode | undefined\n for (let i = 0; i < nodes.length; i += 1) {\n const node = nodes[i]\n if (node.type === 'element' && node.name === 'page-meta') {\n if (pageMetaIndex === -1) {\n pageMetaIndex = i\n }\n if (!navigationBar) {\n navigationBar = findNavigationBarInPageMeta(node)\n }\n }\n }\n const warnings: string[] = []\n if (pageMetaIndex > 0) {\n warnings.push('[web] page-meta 需要作为页面第一个节点,已忽略其位置约束。')\n }\n const cleaned = pageMetaIndex === -1 ? nodes : stripPageMetaNodes(nodes)\n const attrs = navigationBar ? pickNavigationBarAttrs(navigationBar.attribs) : undefined\n return { nodes: cleaned, attrs, warnings }\n}\n\nfunction toAttributeValue(value: unknown) {\n if (value == null) {\n return undefined\n }\n if (typeof value === 'string') {\n return value\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value)\n }\n return undefined\n}\n\nexport function buildNavigationBarAttrs(\n config: NavigationBarConfig | undefined,\n overrides?: Record<string, string>,\n) {\n const attrs: Record<string, string> = {}\n if (config?.title !== undefined) {\n const value = toAttributeValue(config.title)\n if (value !== undefined) {\n attrs.title = value\n }\n }\n if (config?.backgroundColor !== undefined) {\n const value = toAttributeValue(config.backgroundColor)\n if (value !== undefined) {\n attrs['background-color'] = value\n }\n }\n if (config?.textStyle !== undefined) {\n const value = toAttributeValue(config.textStyle)\n if (value !== undefined) {\n attrs['text-style'] = value\n }\n }\n if (config?.frontColor !== undefined) {\n const value = toAttributeValue(config.frontColor)\n if (value !== undefined) {\n attrs['front-color'] = value\n }\n }\n if (config?.loading) {\n attrs.loading = 'true'\n }\n if (overrides) {\n for (const [key, value] of Object.entries(overrides)) {\n attrs[key] = value\n }\n }\n return attrs\n}\n"],"mappings":";AAEA,MAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,mBAAmB,OAAmC;CAC7D,MAAM,WAAyB,CAAC;CAChC,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,SAAS,aAAa,KAAK,SAAS,aAC3C;EAEF,IAAI,KAAK,SAAS,aAAa,KAAK,UAAU,QAAQ;GACpD,MAAM,eAAe,mBAAmB,KAAK,QAAQ;GACrD,SAAS,KAAK;IAAE,GAAG;IAAM,UAAU;GAAa,CAAC;GACjD;EACF;EACA,SAAS,KAAK,IAAI;CACpB;CACA,OAAO;AACT;AAEA,SAAS,uBAAuB,SAA6C;CAC3E,IAAI,CAAC,SACH;CAEF,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC/C,IAAI,qBAAqB,IAAI,GAAG,GAC9B,OAAO,OAAO;CAGlB,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS;AACnD;AAEA,SAAS,4BAA4B,MAAyB;CAC5D,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,KAAK,MAAM,SAAS,UAClB,IAAI,MAAM,SAAS,aAAa,MAAM,SAAS,kBAC7C,OAAO;AAIb;AAEA,SAAgB,iCAAiC,OAI/C;CACA,IAAI,gBAAgB;CACpB,IAAI;CACJ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,OAAO,MAAM;EACnB,IAAI,KAAK,SAAS,aAAa,KAAK,SAAS,aAAa;GACxD,IAAI,kBAAkB,IACpB,gBAAgB;GAElB,IAAI,CAAC,eACH,gBAAgB,4BAA4B,IAAI;EAEpD;CACF;CACA,MAAM,WAAqB,CAAC;CAC5B,IAAI,gBAAgB,GAClB,SAAS,KAAK,uCAAuC;CAIvD,OAAO;EAAE,OAFO,kBAAkB,KAAK,QAAQ,mBAAmB,KAAK;EAE9C,OADX,gBAAgB,uBAAuB,cAAc,OAAO,IAAI;EAC9C;CAAS;AAC3C;AAEA,SAAS,iBAAiB,OAAgB;CACxC,IAAI,SAAS,MACX;CAEF,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAChD,OAAO,OAAO,KAAK;AAGvB;AAEA,SAAgB,wBACd,QACA,WACA;CACA,MAAM,QAAgC,CAAC;CACvC,IAAI,QAAQ,UAAU,QAAW;EAC/B,MAAM,QAAQ,iBAAiB,OAAO,KAAK;EAC3C,IAAI,UAAU,QACZ,MAAM,QAAQ;CAElB;CACA,IAAI,QAAQ,oBAAoB,QAAW;EACzC,MAAM,QAAQ,iBAAiB,OAAO,eAAe;EACrD,IAAI,UAAU,QACZ,MAAM,sBAAsB;CAEhC;CACA,IAAI,QAAQ,cAAc,QAAW;EACnC,MAAM,QAAQ,iBAAiB,OAAO,SAAS;EAC/C,IAAI,UAAU,QACZ,MAAM,gBAAgB;CAE1B;CACA,IAAI,QAAQ,eAAe,QAAW;EACpC,MAAM,QAAQ,iBAAiB,OAAO,UAAU;EAChD,IAAI,UAAU,QACZ,MAAM,iBAAiB;CAE3B;CACA,IAAI,QAAQ,SACV,MAAM,UAAU;CAElB,IAAI,WACF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,GACjD,MAAM,OAAO;CAGjB,OAAO;AACT"}
@@ -3,7 +3,7 @@ import { parseDocument } from "htmlparser2";
3
3
  //#region src/compiler/wxml/parser.ts
4
4
  function isRenderableNode(node) {
5
5
  if (node.type === "directive" || node.type === "comment") return false;
6
- if (node.type === "text") return (node.data ?? "").trim().length > 0;
6
+ if (node.type === "text") return node.data.trim().length > 0;
7
7
  return true;
8
8
  }
9
9
  function hasChildren(node) {
@@ -12,14 +12,14 @@ function hasChildren(node) {
12
12
  function toRenderNode(node, children) {
13
13
  if (node.type === "text") return {
14
14
  type: "text",
15
- data: node.data ?? ""
15
+ data: node.data
16
16
  };
17
17
  if (node.type === "tag" || node.type === "script" || node.type === "style") {
18
18
  const element = node;
19
19
  return {
20
20
  type: "element",
21
21
  name: element.name,
22
- attribs: element.attribs ?? {},
22
+ attribs: element.attribs,
23
23
  children
24
24
  };
25
25
  }
@@ -29,11 +29,11 @@ function convertNode(node) {
29
29
  return toRenderNode(node, hasChildren(node) && node.children.length > 0 ? node.children.map((child) => convertNode(child)).filter((child) => Boolean(child)) : void 0);
30
30
  }
31
31
  function parseWxml(source) {
32
- return (parseDocument(source, {
32
+ return parseDocument(source, {
33
33
  xmlMode: true,
34
34
  decodeEntities: true,
35
35
  recognizeSelfClosing: true
36
- }).children ?? []).filter(isRenderableNode).map((node) => convertNode(node)).filter((node) => Boolean(node));
36
+ }).children.filter(isRenderableNode).map((node) => convertNode(node)).filter((node) => Boolean(node));
37
37
  }
38
38
 
39
39
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"parser.mjs","names":[],"sources":["../../../src/compiler/wxml/parser.ts"],"sourcesContent":["import type { ChildNode, DataNode, Element, Node } from 'domhandler'\n\nimport type { RenderNode } from './types'\n\nimport { parseDocument } from 'htmlparser2'\n\nfunction isRenderableNode(node: Node) {\n if (node.type === 'directive' || node.type === 'comment') {\n return false\n }\n if (node.type === 'text') {\n const data = (node as DataNode).data ?? ''\n return data.trim().length > 0\n }\n return true\n}\n\ntype NodeWithChildren = Node & { children: ChildNode[] }\n\nfunction hasChildren(node: Node): node is NodeWithChildren {\n return Array.isArray((node as NodeWithChildren).children)\n}\n\nfunction toRenderNode(node: Node, children?: RenderNode[]): RenderNode | undefined {\n if (node.type === 'text') {\n const data = (node as DataNode).data ?? ''\n return { type: 'text', data }\n }\n if (node.type === 'tag' || node.type === 'script' || node.type === 'style') {\n const element = node as Element\n return {\n type: 'element',\n name: element.name,\n attribs: element.attribs ?? {},\n children,\n }\n }\n return undefined\n}\n\nfunction convertNode(node: Node): RenderNode | undefined {\n if (!isRenderableNode(node)) {\n return undefined\n }\n const children = (hasChildren(node) && node.children.length > 0)\n ? node.children.map(child => convertNode(child)).filter((child): child is RenderNode => Boolean(child))\n : undefined\n return toRenderNode(node, children)\n}\n\nexport function parseWxml(source: string): RenderNode[] {\n const document = parseDocument(source, {\n xmlMode: true,\n decodeEntities: true,\n recognizeSelfClosing: true,\n })\n const nodes = (document.children ?? []).filter(isRenderableNode)\n return nodes\n .map(node => convertNode(node))\n .filter((node): node is RenderNode => Boolean(node))\n}\n"],"mappings":";;;AAMA,SAAS,iBAAiB,MAAY;CACpC,IAAI,KAAK,SAAS,eAAe,KAAK,SAAS,WAC7C,OAAO;CAET,IAAI,KAAK,SAAS,QAEhB,QADc,KAAkB,QAAQ,GAC7B,CAAC,KAAK,CAAC,CAAC,SAAS;CAE9B,OAAO;AACT;AAIA,SAAS,YAAY,MAAsC;CACzD,OAAO,MAAM,QAAS,KAA0B,QAAQ;AAC1D;AAEA,SAAS,aAAa,MAAY,UAAiD;CACjF,IAAI,KAAK,SAAS,QAEhB,OAAO;EAAE,MAAM;EAAQ,MADT,KAAkB,QAAQ;CACZ;CAE9B,IAAI,KAAK,SAAS,SAAS,KAAK,SAAS,YAAY,KAAK,SAAS,SAAS;EAC1E,MAAM,UAAU;EAChB,OAAO;GACL,MAAM;GACN,MAAM,QAAQ;GACd,SAAS,QAAQ,WAAW,CAAC;GAC7B;EACF;CACF;AAEF;AAEA,SAAS,YAAY,MAAoC;CACvD,IAAI,CAAC,iBAAiB,IAAI,GACxB;CAKF,OAAO,aAAa,MAHF,YAAY,IAAI,KAAK,KAAK,SAAS,SAAS,IAC1D,KAAK,SAAS,KAAI,UAAS,YAAY,KAAK,CAAC,CAAC,CAAC,QAAQ,UAA+B,QAAQ,KAAK,CAAC,IACpG,MAC8B;AACpC;AAEA,SAAgB,UAAU,QAA8B;CAOtD,QANiB,cAAc,QAAQ;EACrC,SAAS;EACT,gBAAgB;EAChB,sBAAsB;CACxB,CACsB,CAAC,CAAC,YAAY,CAAC,EAAC,CAAE,OAAO,gBACpC,CAAC,CACT,KAAI,SAAQ,YAAY,IAAI,CAAC,CAAC,CAC9B,QAAQ,SAA6B,QAAQ,IAAI,CAAC;AACvD"}
1
+ {"version":3,"file":"parser.mjs","names":[],"sources":["../../../src/compiler/wxml/parser.ts"],"sourcesContent":["import type { ChildNode, DataNode, Element, Node } from 'domhandler'\n\nimport type { RenderNode } from './types'\n\nimport { parseDocument } from 'htmlparser2'\n\nfunction isRenderableNode(node: Node) {\n if (node.type === 'directive' || node.type === 'comment') {\n return false\n }\n if (node.type === 'text') {\n const data = (node as DataNode).data\n return data.trim().length > 0\n }\n return true\n}\n\ntype NodeWithChildren = Node & { children: ChildNode[] }\n\nfunction hasChildren(node: Node): node is NodeWithChildren {\n return Array.isArray((node as NodeWithChildren).children)\n}\n\nfunction toRenderNode(node: Node, children?: RenderNode[]): RenderNode | undefined {\n if (node.type === 'text') {\n const data = (node as DataNode).data\n return { type: 'text', data }\n }\n if (node.type === 'tag' || node.type === 'script' || node.type === 'style') {\n const element = node as Element\n return {\n type: 'element',\n name: element.name,\n attribs: element.attribs,\n children,\n }\n }\n return undefined\n}\n\nfunction convertNode(node: Node): RenderNode | undefined {\n if (!isRenderableNode(node)) {\n return undefined\n }\n const children = (hasChildren(node) && node.children.length > 0)\n ? node.children.map(child => convertNode(child)).filter((child): child is RenderNode => Boolean(child))\n : undefined\n return toRenderNode(node, children)\n}\n\nexport function parseWxml(source: string): RenderNode[] {\n const document = parseDocument(source, {\n xmlMode: true,\n decodeEntities: true,\n recognizeSelfClosing: true,\n })\n const nodes = document.children.filter(isRenderableNode)\n return nodes\n .map(node => convertNode(node))\n .filter((node): node is RenderNode => Boolean(node))\n}\n"],"mappings":";;;AAMA,SAAS,iBAAiB,MAAY;CACpC,IAAI,KAAK,SAAS,eAAe,KAAK,SAAS,WAC7C,OAAO;CAET,IAAI,KAAK,SAAS,QAEhB,OADc,KAAkB,KACpB,KAAK,CAAC,CAAC,SAAS;CAE9B,OAAO;AACT;AAIA,SAAS,YAAY,MAAsC;CACzD,OAAO,MAAM,QAAS,KAA0B,QAAQ;AAC1D;AAEA,SAAS,aAAa,MAAY,UAAiD;CACjF,IAAI,KAAK,SAAS,QAEhB,OAAO;EAAE,MAAM;EAAQ,MADT,KAAkB;CACJ;CAE9B,IAAI,KAAK,SAAS,SAAS,KAAK,SAAS,YAAY,KAAK,SAAS,SAAS;EAC1E,MAAM,UAAU;EAChB,OAAO;GACL,MAAM;GACN,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB;EACF;CACF;AAEF;AAEA,SAAS,YAAY,MAAoC;CACvD,IAAI,CAAC,iBAAiB,IAAI,GACxB;CAKF,OAAO,aAAa,MAHF,YAAY,IAAI,KAAK,KAAK,SAAS,SAAS,IAC1D,KAAK,SAAS,KAAI,UAAS,YAAY,KAAK,CAAC,CAAC,CAAC,QAAQ,UAA+B,QAAQ,KAAK,CAAC,IACpG,MAC8B;AACpC;AAEA,SAAgB,UAAU,QAA8B;CAOtD,OANiB,cAAc,QAAQ;EACrC,SAAS;EACT,gBAAgB;EAChB,sBAAsB;CACxB,CACqB,CAAC,CAAC,SAAS,OAAO,gBAC5B,CAAC,CACT,KAAI,SAAQ,YAAY,IAAI,CAAC,CAAC,CAC9B,QAAQ,SAA6B,QAAQ,IAAI,CAAC;AACvD"}
@@ -1,3 +1,4 @@
1
+ import { resolveNativeComponentPropertyAttributes } from "../../shared/nativeComponents.mjs";
1
2
  import { SELF_CLOSING_TAGS, hasControlAttribute, normalizeTagName, resolveControlAttributeValue } from "../../shared/wxml.mjs";
2
3
  import { buildExpression, buildTemplateDataExpression, parseInterpolations } from "./interpolation.mjs";
3
4
  import { extractFor, isConditionalElement, renderAttributes, resolveComponentTagName, stripControlAttributes } from "./attributes.mjs";
@@ -26,7 +27,7 @@ var Renderer = class {
26
27
  while (cursor < nodes.length) {
27
28
  const candidate = nodes[cursor];
28
29
  if (!isConditionalElement(candidate)) break;
29
- const attribs = candidate.attribs ?? {};
30
+ const attribs = candidate.attribs;
30
31
  if (branches.length === 0 && !hasControlAttribute(attribs, "if")) break;
31
32
  if (branches.length > 0 && !hasControlAttribute(attribs, "elif") && !hasControlAttribute(attribs, "else")) break;
32
33
  branches.push({
@@ -55,7 +56,7 @@ var Renderer = class {
55
56
  expr = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
56
57
  continue;
57
58
  }
58
- const conditionExpr = resolveControlAttributeValue(attribs, "if") ?? resolveControlAttributeValue(attribs, "elif") ?? "";
59
+ const conditionExpr = resolveControlAttributeValue(attribs, "if") ?? resolveControlAttributeValue(attribs, "elif");
59
60
  const rendered = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
60
61
  expr = `(${buildExpression(parseInterpolations(conditionExpr), scopeVar, wxsVar)} ? ${rendered} : ${expr})`;
61
62
  }
@@ -65,15 +66,15 @@ var Renderer = class {
65
66
  };
66
67
  }
67
68
  renderNode(node, scopeVar, wxsVar, componentTags) {
68
- if (node.type === "text") return buildExpression(parseInterpolations(node.data ?? ""), scopeVar, wxsVar);
69
- if (node.type === "element") {
70
- if (node.name === "template" && node.attribs?.is) return this.renderTemplateInvoke(node, scopeVar, wxsVar);
71
- return this.renderElement(node, scopeVar, wxsVar, componentTags);
69
+ if (node.type === "text") {
70
+ const parts = parseInterpolations(node.data ?? "");
71
+ return buildExpression(parts, scopeVar, wxsVar);
72
72
  }
73
+ if (node.type === "element") return this.renderElement(node, scopeVar, wxsVar, componentTags);
73
74
  return "\"\"";
74
75
  }
75
- renderTemplateInvoke(node, scopeVar, wxsVar) {
76
- const attribs = node.attribs ?? {};
76
+ renderTemplateInvoke(node, scopeVar, wxsVar, overrideAttribs) {
77
+ const attribs = overrideAttribs ?? node.attribs ?? {};
77
78
  const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
78
79
  const dataExpr = attribs.data ? buildTemplateDataExpression(attribs.data, scopeVar, wxsVar) : void 0;
79
80
  return `ctx.renderTemplate(__templates, ${isExpr}, ${dataExpr ? `ctx.mergeScope(${scopeVar}, ${dataExpr})` : scopeVar}, ctx)`;
@@ -86,23 +87,26 @@ var Renderer = class {
86
87
  const listExpr = `ctx.normalizeList(${buildExpression(parseInterpolations(forInfo.expr), scopeVar, wxsVar)})`;
87
88
  const itemVar = forInfo.itemName;
88
89
  const indexVar = forInfo.indexName;
90
+ const nestedScopeVar = scopeVar === "scope" ? "__scope" : `${scopeVar}_nested`;
89
91
  const scopeExpr = `ctx.createScope(${scopeVar}, { ${itemVar}: ${itemVar}, ${indexVar}: ${indexVar} })`;
90
- const itemRender = this.renderElement(node, "__scope", wxsVar, componentTags, {
92
+ const itemRender = this.renderElement(node, nestedScopeVar, wxsVar, componentTags, {
91
93
  skipFor: true,
92
94
  overrideAttribs: forInfo.restAttribs
93
95
  });
94
- return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${`ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`}, (${itemVar}, ${indexVar}) => { const __scope = ${scopeExpr}; return ${itemRender}; })`;
96
+ return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${`ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`}, (${itemVar}, ${indexVar}) => { const ${nestedScopeVar} = ${scopeExpr}; return ${itemRender}; })`;
95
97
  }
96
98
  }
99
+ if (node.name === "template" && attribs.is) return this.renderTemplateInvoke(node, scopeVar, wxsVar, attribs);
97
100
  const customTag = resolveComponentTagName(node.name ?? "", componentTags);
98
101
  const tagName = customTag ?? normalizeTagName(node.name ?? "");
99
102
  if (tagName === "#fragment") return this.renderNodes(node.children ?? [], scopeVar, wxsVar, componentTags);
100
103
  const attrs = renderAttributes(attribs, scopeVar, wxsVar, {
101
104
  skipControl: true,
102
- preferProperty: Boolean(customTag)
105
+ preferProperty: Boolean(customTag),
106
+ propertyAttributes: customTag ? void 0 : resolveNativeComponentPropertyAttributes(node.name ?? "")
103
107
  });
104
108
  const childNodes = node.children ?? [];
105
- const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar, componentTags)}}`).join("");
109
+ const children = childNodes.length > 0 ? `\${${this.renderNodes(childNodes, scopeVar, wxsVar, componentTags)}}` : "";
106
110
  if (SELF_CLOSING_TAGS.has(tagName) && childNodes.length === 0) return `html\`<${tagName}${attrs} />\``;
107
111
  return `html\`<${tagName}${attrs}>${children}</${tagName}>\``;
108
112
  }