fusions-ui 1.2.7 → 1.2.8

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 (547) hide show
  1. package/LICENSE +1 -1
  2. package/changelog.md +2 -0
  3. package/components/avatar/index.ts +1 -0
  4. package/components/avatar/src/avatar.ts +131 -0
  5. package/components/avatar/src/avatar.vue +104 -0
  6. package/components/avatar/src/composables/index.ts +1 -0
  7. package/components/avatar/src/composables/use-avatar.ts +61 -0
  8. package/components/avatar-group/index.ts +1 -0
  9. package/components/avatar-group/src/avatar-group.ts +86 -0
  10. package/components/{fu-avatar-group/fu-avatar-group.vue → avatar-group/src/avatar-group.vue} +27 -34
  11. package/components/avatar-group/src/composables/index.ts +1 -0
  12. package/components/avatar-group/src/composables/use-avatar-group.ts +17 -0
  13. package/components/badge/index.ts +1 -0
  14. package/components/badge/src/badge.ts +126 -0
  15. package/components/{fu-badge/fu-badge.vue → badge/src/badge.vue} +26 -62
  16. package/components/badge/src/composables/badge-custom.ts +51 -0
  17. package/components/badge/src/composables/index.ts +1 -0
  18. package/components/banner-arc/index.ts +1 -0
  19. package/components/banner-arc/src/banner-arc.ts +41 -0
  20. package/components/banner-arc/src/banner-arc.vue +49 -0
  21. package/components/banner-arc/src/composables/banner-arc-custom.ts +19 -0
  22. package/components/banner-arc/src/composables/index.ts +1 -0
  23. package/components/button/index.ts +1 -0
  24. package/components/button/src/button.ts +332 -0
  25. package/components/{fu-button/fu-button.vue → button/src/button.vue} +57 -163
  26. package/components/button/src/composables/button-custom.ts +90 -0
  27. package/components/button/src/composables/index.ts +2 -0
  28. package/components/button/src/composables/use-button.ts +137 -0
  29. package/components/cell/index.ts +1 -0
  30. package/components/cell/src/cell.ts +167 -0
  31. package/components/{fu-cell/fu-cell.vue → cell/src/cell.vue} +29 -38
  32. package/components/cell/src/composables/index.ts +1 -0
  33. package/components/cell/src/composables/use-cell.ts +20 -0
  34. package/components/cell-group/index.ts +1 -0
  35. package/components/cell-group/src/cell-group.ts +23 -0
  36. package/components/{fu-cell-group/fu-cell-group.vue → cell-group/src/cell-group.vue} +8 -13
  37. package/components/checkbox/index.ts +1 -0
  38. package/components/checkbox/src/checkbox.ts +144 -0
  39. package/components/checkbox/src/checkbox.vue +270 -0
  40. package/components/checkbox/src/composables/checkbox-custom.ts +15 -0
  41. package/components/checkbox/src/composables/index.ts +2 -0
  42. package/components/checkbox/src/composables/use-checkbox.ts +200 -0
  43. package/components/code-input/index.ts +1 -0
  44. package/components/code-input/src/code-input.ts +157 -0
  45. package/components/code-input/src/code-input.vue +158 -0
  46. package/components/code-input/src/composables/code-input-custom.ts +74 -0
  47. package/components/code-input/src/composables/index.ts +2 -0
  48. package/components/code-input/src/composables/use-code-input.ts +67 -0
  49. package/components/code-verify/index.ts +1 -0
  50. package/components/code-verify/src/code-verify.ts +160 -0
  51. package/components/code-verify/src/code-verify.vue +87 -0
  52. package/components/code-verify/src/composables/code-verify-custom.ts +23 -0
  53. package/components/code-verify/src/composables/index.ts +2 -0
  54. package/components/code-verify/src/composables/use-code-verify.ts +132 -0
  55. package/components/collapse/index.ts +1 -0
  56. package/components/collapse/src/collapse.ts +41 -0
  57. package/components/collapse/src/collapse.vue +48 -0
  58. package/components/collapse/src/composables/index.ts +1 -0
  59. package/components/collapse/src/composables/use-collapse.ts +150 -0
  60. package/components/collapse-item/index.ts +1 -0
  61. package/components/collapse-item/src/collapse-item.ts +102 -0
  62. package/components/{fu-collapse-item/fu-collapse-item.vue → collapse-item/src/collapse-item.vue} +20 -159
  63. package/components/collapse-item/src/composables/index.ts +1 -0
  64. package/components/collapse-item/src/composables/use-collapse-item.ts +139 -0
  65. package/components/countdown/index.ts +1 -0
  66. package/components/countdown/src/composables/index.ts +1 -0
  67. package/components/countdown/src/composables/use-countdown.ts +133 -0
  68. package/components/countdown/src/countdown.ts +63 -0
  69. package/components/countdown/src/countdown.vue +60 -0
  70. package/components/{fu-countdown/util.js → countdown/src/util.ts} +5 -5
  71. package/components/datetime-picker/index.ts +1 -0
  72. package/components/datetime-picker/src/composables/index.ts +1 -0
  73. package/components/datetime-picker/src/composables/use-datetime-picker.ts +325 -0
  74. package/components/datetime-picker/src/datetime-picker.ts +223 -0
  75. package/components/datetime-picker/src/datetime-picker.vue +96 -0
  76. package/components/form/index.ts +1 -0
  77. package/components/form/src/composables/index.ts +1 -0
  78. package/components/form/src/composables/use-form.ts +256 -0
  79. package/components/form/src/form.ts +108 -0
  80. package/components/form/src/form.vue +64 -0
  81. package/components/{fu-form/utils.js → form/src/utils.ts} +49 -42
  82. package/components/{fu-form/validate.js → form/src/validate.ts} +58 -49
  83. package/components/form-item/index.ts +1 -0
  84. package/components/form-item/src/composables/index.ts +1 -0
  85. package/components/form-item/src/composables/use-form-item.ts +292 -0
  86. package/components/form-item/src/form-item.ts +81 -0
  87. package/components/form-item/src/form-item.vue +229 -0
  88. package/components/fusions-ui/src/fusions-ui.vue +8 -0
  89. package/components/grid/index.ts +1 -0
  90. package/components/grid/src/composables/index.ts +1 -0
  91. package/components/grid/src/composables/use-grid.ts +67 -0
  92. package/components/grid/src/grid.ts +54 -0
  93. package/components/grid/src/grid.vue +69 -0
  94. package/components/grid-item/index.ts +1 -0
  95. package/components/grid-item/src/composables/grid-item-custom.ts +16 -0
  96. package/components/grid-item/src/composables/index.ts +2 -0
  97. package/components/grid-item/src/composables/use-grid-item.ts +55 -0
  98. package/components/grid-item/src/grid-item.ts +15 -0
  99. package/components/grid-item/src/grid-item.vue +102 -0
  100. package/components/icon/index.ts +1 -0
  101. package/components/icon/src/composables/icon-custom.ts +41 -0
  102. package/components/icon/src/composables/index.ts +2 -0
  103. package/components/icon/src/composables/use-icon.ts +14 -0
  104. package/components/{fu-icon → icon/src}/fuicon.css +584 -584
  105. package/components/icon/src/fuicon.ts +1023 -0
  106. package/components/icon/src/icon.ts +84 -0
  107. package/components/icon/src/icon.vue +92 -0
  108. package/components/image/index.ts +1 -0
  109. package/components/image/src/composables/image-custom.ts +36 -0
  110. package/components/image/src/composables/index.ts +2 -0
  111. package/components/image/src/composables/use-image.ts +135 -0
  112. package/components/image/src/image.ts +185 -0
  113. package/components/image/src/image.vue +152 -0
  114. package/components/index-anchor/index.ts +1 -0
  115. package/components/index-anchor/src/composables/index.ts +1 -0
  116. package/components/index-anchor/src/composables/use-index-anchor.ts +44 -0
  117. package/components/index-anchor/src/index-anchor.ts +45 -0
  118. package/components/index-anchor/src/index-anchor.vue +60 -0
  119. package/components/index-item/index.ts +1 -0
  120. package/components/index-item/src/composables/index.ts +1 -0
  121. package/components/index-item/src/composables/use-index-item.ts +75 -0
  122. package/components/index-item/src/index-item.ts +13 -0
  123. package/components/index-item/src/index-item.vue +32 -0
  124. package/components/index-list/index.ts +1 -0
  125. package/components/index-list/src/composables/index.ts +1 -0
  126. package/components/index-list/src/composables/use-index-list.ts +297 -0
  127. package/components/index-list/src/index-list.ts +52 -0
  128. package/components/index-list/src/index-list.vue +178 -0
  129. package/components/index.ts +62 -0
  130. package/components/input/index.ts +1 -0
  131. package/components/input/src/composables/index.ts +2 -0
  132. package/components/input/src/composables/input-custom.ts +69 -0
  133. package/components/input/src/composables/use-input.ts +117 -0
  134. package/components/input/src/input.ts +360 -0
  135. package/components/input/src/input.vue +241 -0
  136. package/components/keyboard/index.ts +1 -0
  137. package/components/keyboard/src/composables/index.ts +3 -0
  138. package/components/keyboard/src/composables/use-keyboard-car.ts +99 -0
  139. package/components/keyboard/src/composables/use-keyboard-number.ts +81 -0
  140. package/components/keyboard/src/composables/use-keyboard.ts +61 -0
  141. package/components/keyboard/src/keyboard-car.ts +53 -0
  142. package/components/{fu-keyboard → keyboard/src}/keyboard-car.vue +37 -199
  143. package/components/keyboard/src/keyboard-number.ts +44 -0
  144. package/components/keyboard/src/keyboard-number.vue +108 -0
  145. package/components/keyboard/src/keyboard.ts +174 -0
  146. package/components/{fu-keyboard/fu-keyboard.vue → keyboard/src/keyboard.vue} +38 -63
  147. package/components/line/index.ts +1 -0
  148. package/components/line/src/composables/index.ts +1 -0
  149. package/components/line/src/composables/line-custom.ts +30 -0
  150. package/components/line/src/line.ts +82 -0
  151. package/components/line/src/line.vue +44 -0
  152. package/components/link/index.ts +1 -0
  153. package/components/link/src/composables/index.ts +2 -0
  154. package/components/link/src/composables/link-custom.ts +19 -0
  155. package/components/link/src/composables/use-link.ts +33 -0
  156. package/components/link/src/link.ts +61 -0
  157. package/components/link/src/link.vue +62 -0
  158. package/components/loading/index.ts +1 -0
  159. package/{libs/function/colorGradient.js → components/loading/src/composables/colorGradient.ts} +4 -4
  160. package/components/loading/src/composables/index.ts +2 -0
  161. package/components/loading/src/composables/loading-custom.ts +21 -0
  162. package/components/loading/src/composables/use-loading.ts +100 -0
  163. package/components/loading/src/loading.ts +77 -0
  164. package/components/{fu-loading/fu-loading.vue → loading/src/loading.vue} +23 -119
  165. package/components/loading-more/index.ts +1 -0
  166. package/components/loading-more/src/loading-more.ts +75 -0
  167. package/components/{fu-loading-more/fu-loading-more.vue → loading-more/src/loading-more.vue} +18 -19
  168. package/components/modal/index.ts +1 -0
  169. package/components/modal/src/composables/index.ts +2 -0
  170. package/components/modal/src/composables/modal-custom.ts +17 -0
  171. package/components/modal/src/composables/use-modal.ts +56 -0
  172. package/components/modal/src/modal.ts +152 -0
  173. package/components/{fu-modal/fu-modal.vue → modal/src/modal.vue} +41 -69
  174. package/components/navbar/index.ts +1 -0
  175. package/components/navbar/src/composables/index.ts +2 -0
  176. package/components/navbar/src/composables/navbar-custom.ts +62 -0
  177. package/components/navbar/src/composables/use-navbar.ts +42 -0
  178. package/components/navbar/src/navbar.ts +151 -0
  179. package/components/navbar/src/navbar.vue +249 -0
  180. package/components/notice-bar/index.ts +3 -0
  181. package/components/notice-bar/src/composables/index.ts +5 -0
  182. package/components/notice-bar/src/composables/notice-column-custom.ts +43 -0
  183. package/components/notice-bar/src/composables/notice-row-custom.ts +26 -0
  184. package/components/notice-bar/src/composables/use-notice-bar.ts +34 -0
  185. package/components/notice-bar/src/composables/use-notice-column.ts +31 -0
  186. package/components/notice-bar/src/composables/use-notice-row.ts +88 -0
  187. package/components/notice-bar/src/notice-bar.ts +197 -0
  188. package/components/{fu-notice-bar/fu-notice-bar.vue → notice-bar/src/notice-bar.vue} +28 -41
  189. package/components/notice-bar/src/notice-column.ts +172 -0
  190. package/components/notice-bar/src/notice-column.vue +129 -0
  191. package/components/notice-bar/src/notice-row.ts +155 -0
  192. package/components/notice-bar/src/notice-row.vue +135 -0
  193. package/components/number-box/index.ts +1 -0
  194. package/components/number-box/src/composables/index.ts +2 -0
  195. package/components/number-box/src/composables/number-box-custom.ts +16 -0
  196. package/components/number-box/src/composables/use-number-box.ts +84 -0
  197. package/components/number-box/src/number-box.ts +98 -0
  198. package/components/number-box/src/number-box.vue +123 -0
  199. package/components/parse/index.ts +1 -0
  200. package/components/parse/src/app-plus/html/js/handler.js +254 -0
  201. package/components/parse/src/app-plus/html/js/uni.webview.min.js +188 -0
  202. package/components/parse/src/app-plus/html/local.html +32 -0
  203. package/components/parse/src/composables/index.ts +1 -0
  204. package/components/parse/src/composables/use-parse.ts +428 -0
  205. package/components/parse/src/node/node.vue +635 -0
  206. package/components/parse/src/parse.ts +156 -0
  207. package/components/parse/src/parse.vue +131 -0
  208. package/components/parse/src/parser.ts +1402 -0
  209. package/components/picker/index.ts +1 -0
  210. package/components/picker/src/composables/index.ts +2 -0
  211. package/components/picker/src/composables/picker-custom.ts +40 -0
  212. package/components/picker/src/composables/use-picker.ts +179 -0
  213. package/components/picker/src/picker.ts +172 -0
  214. package/components/picker/src/picker.vue +197 -0
  215. package/components/popup/index.ts +1 -0
  216. package/components/popup/src/composables/index.ts +1 -0
  217. package/components/popup/src/composables/use-popup.ts +346 -0
  218. package/components/popup/src/keypress.ts +55 -0
  219. package/components/popup/src/popup.ts +101 -0
  220. package/components/popup/src/popup.vue +204 -0
  221. package/components/progress/index.ts +1 -0
  222. package/components/progress/src/composables/index.ts +2 -0
  223. package/components/progress/src/composables/progress-custom.ts +24 -0
  224. package/components/progress/src/composables/use-progress.ts +159 -0
  225. package/components/progress/src/progress.ts +84 -0
  226. package/components/progress/src/progress.vue +150 -0
  227. package/components/rate/index.ts +1 -0
  228. package/components/rate/src/composables/index.ts +1 -0
  229. package/components/rate/src/composables/use-rate.ts +196 -0
  230. package/components/rate/src/rate.ts +114 -0
  231. package/components/rate/src/rate.vue +113 -0
  232. package/components/read-more/index.ts +1 -0
  233. package/components/read-more/src/composables/index.ts +2 -0
  234. package/components/read-more/src/composables/read-more-custom.ts +46 -0
  235. package/components/read-more/src/composables/use-read-more.ts +72 -0
  236. package/components/read-more/src/read-more.ts +102 -0
  237. package/components/read-more/src/read-more.vue +104 -0
  238. package/components/safe-bottom/index.ts +1 -0
  239. package/components/safe-bottom/src/composables/index.ts +2 -0
  240. package/components/safe-bottom/src/composables/safe-bottom-custom.ts +18 -0
  241. package/components/safe-bottom/src/composables/use-safe-bottom.ts +17 -0
  242. package/components/safe-bottom/src/safe-bottom.ts +8 -0
  243. package/components/safe-bottom/src/safe-bottom.vue +43 -0
  244. package/components/scroll-list/index.ts +1 -0
  245. package/components/scroll-list/src/composables/index.ts +2 -0
  246. package/components/scroll-list/src/composables/scroll-list-custom.ts +41 -0
  247. package/components/scroll-list/src/composables/use-scroll-list.ts +126 -0
  248. package/components/scroll-list/src/scroll-list.ts +57 -0
  249. package/components/scroll-list/src/scroll-list.vue +143 -0
  250. package/components/{fu-scroll-list/scrollWxs.wxs → scroll-list/src/scroll-wxs.wxs} +2 -2
  251. package/components/search/index.ts +1 -0
  252. package/components/search/src/composables/index.ts +2 -0
  253. package/components/search/src/composables/search-custom.ts +25 -0
  254. package/components/search/src/composables/use-search.ts +106 -0
  255. package/components/search/src/search.ts +186 -0
  256. package/components/{fu-search/fu-search.vue → search/src/search.vue} +42 -154
  257. package/components/section/index.ts +1 -0
  258. package/components/section/src/composables/index.ts +1 -0
  259. package/components/section/src/composables/use-section.ts +19 -0
  260. package/components/section/src/section.ts +83 -0
  261. package/components/{fu-section/fu-section.vue → section/src/section.vue} +36 -35
  262. package/components/sign-board/index.ts +1 -0
  263. package/components/sign-board/src/composables/index.ts +1 -0
  264. package/components/sign-board/src/composables/use-sign-board.ts +552 -0
  265. package/components/sign-board/src/sign-board.ts +48 -0
  266. package/components/sign-board/src/sign-board.vue +191 -0
  267. package/components/skeleton/index.ts +1 -0
  268. package/components/skeleton/src/composables/index.ts +2 -0
  269. package/components/skeleton/src/composables/skeleton-custom.ts +23 -0
  270. package/components/skeleton/src/composables/use-skeleton.ts +102 -0
  271. package/components/skeleton/src/skeleton.ts +37 -0
  272. package/components/skeleton/src/skeleton.vue +147 -0
  273. package/components/status-bar/src/composables/index.ts +1 -0
  274. package/components/status-bar/src/composables/use-status-bar.ts +29 -0
  275. package/components/status-bar/src/status-bar.vue +21 -0
  276. package/components/steps/index.ts +1 -0
  277. package/components/steps/src/composables/index.ts +1 -0
  278. package/components/steps/src/composables/use-steps.ts +27 -0
  279. package/components/steps/src/steps.ts +65 -0
  280. package/components/steps/src/steps.vue +46 -0
  281. package/components/steps-item/index.ts +1 -0
  282. package/components/steps-item/src/composables/index.ts +2 -0
  283. package/components/steps-item/src/composables/steps-item-custom.ts +81 -0
  284. package/components/steps-item/src/composables/use-steps-item.ts +87 -0
  285. package/components/steps-item/src/steps-item.ts +38 -0
  286. package/components/steps-item/src/steps-item.vue +224 -0
  287. package/components/sticky/index.ts +1 -0
  288. package/components/sticky/src/composables/index.ts +2 -0
  289. package/components/sticky/src/composables/sticky-custom.ts +57 -0
  290. package/components/sticky/src/composables/use-sticky.ts +152 -0
  291. package/components/sticky/src/sticky.ts +62 -0
  292. package/components/sticky/src/sticky.vue +65 -0
  293. package/components/subsection/index.ts +1 -0
  294. package/components/subsection/src/composables/index.ts +2 -0
  295. package/components/subsection/src/composables/subsection-custom.ts +71 -0
  296. package/components/subsection/src/composables/use-subsection.ts +85 -0
  297. package/components/subsection/src/subsection.ts +107 -0
  298. package/components/subsection/src/subsection.vue +165 -0
  299. package/components/swipe-action/src/composables/index.ts +1 -0
  300. package/components/swipe-action/src/composables/use-swipe-action.ts +58 -0
  301. package/components/swipe-action/src/swipe-action.vue +81 -0
  302. package/components/swipe-action-item/index.ts +1 -0
  303. package/components/{fu-swipe-action-item/mpwxs.js → swipe-action-item/src/mpwxs.ts} +22 -27
  304. package/components/swipe-action-item/src/swipe-action-item.ts +68 -0
  305. package/components/{fu-swipe-action-item/fu-swipe-action-item.vue → swipe-action-item/src/swipe-action-item.vue} +24 -17
  306. package/components/{fu-swipe-action-item → swipe-action-item/src}/wx.wxs +2 -2
  307. package/components/swiper/index.ts +1 -0
  308. package/components/swiper/src/composables/index.ts +2 -0
  309. package/components/swiper/src/composables/swiper-custom.ts +40 -0
  310. package/components/swiper/src/composables/use-swiper.ts +75 -0
  311. package/components/swiper/src/swiper.ts +189 -0
  312. package/components/{fu-swiper/fu-swiper.vue → swiper/src/swiper.vue} +49 -118
  313. package/components/switch/index.ts +1 -0
  314. package/components/switch/src/composables/index.ts +2 -0
  315. package/components/switch/src/composables/switch-custom.ts +32 -0
  316. package/components/switch/src/composables/use-switch.ts +38 -0
  317. package/components/switch/src/switch.ts +115 -0
  318. package/components/{fu-switch/fu-switch.vue → switch/src/switch.vue} +25 -73
  319. package/components/tabs/index.ts +1 -0
  320. package/components/tabs/src/composables/index.ts +2 -0
  321. package/components/tabs/src/composables/tabs-custom.ts +43 -0
  322. package/components/tabs/src/composables/use-tabs.ts +210 -0
  323. package/components/tabs/src/tabs.ts +123 -0
  324. package/components/tabs/src/tabs.vue +153 -0
  325. package/components/tag/index.ts +1 -0
  326. package/components/tag/src/composables/index.ts +2 -0
  327. package/components/tag/src/composables/tag-custom.ts +61 -0
  328. package/components/tag/src/composables/use-tag.ts +23 -0
  329. package/components/tag/src/tag.ts +159 -0
  330. package/components/{fu-tag/fu-tag.vue → tag/src/tag.vue} +53 -93
  331. package/components/text/index.ts +1 -0
  332. package/components/text/src/composables/index.ts +2 -0
  333. package/components/text/src/composables/text-custom.ts +120 -0
  334. package/components/text/src/composables/use-text.ts +83 -0
  335. package/components/text/src/text.ts +261 -0
  336. package/components/text/src/text.vue +186 -0
  337. package/components/textarea/index.ts +1 -0
  338. package/components/textarea/src/composables/index.ts +2 -0
  339. package/components/textarea/src/composables/textarea-custom.ts +50 -0
  340. package/components/textarea/src/composables/use-textarea.ts +88 -0
  341. package/components/textarea/src/textarea.ts +250 -0
  342. package/components/textarea/src/textarea.vue +162 -0
  343. package/components/{fu-timeaxis/fu-timeaxis.vue → timeaxis/src/timeaxis.vue} +3 -9
  344. package/components/timeaxis-item/index.ts +1 -0
  345. package/components/timeaxis-item/src/timeaxis-item.ts +20 -0
  346. package/components/timeaxis-item/src/timeaxis-item.vue +50 -0
  347. package/components/transition/index.ts +1 -0
  348. package/components/transition/src/composables/createAnimation.ts +171 -0
  349. package/components/transition/src/composables/index.ts +2 -0
  350. package/components/transition/src/composables/transform-custom.ts +18 -0
  351. package/components/transition/src/composables/use-transition.ts +251 -0
  352. package/components/transition/src/transition.ts +64 -0
  353. package/components/transition/src/transition.vue +70 -0
  354. package/components/upload/index.ts +1 -0
  355. package/components/upload/src/composables/index.ts +5 -0
  356. package/components/upload/src/composables/upload-file-custom.ts +68 -0
  357. package/components/upload/src/composables/upload-image-custom.ts +76 -0
  358. package/components/upload/src/composables/use-upload-file.ts +27 -0
  359. package/components/upload/src/composables/use-upload-image.ts +38 -0
  360. package/components/upload/src/composables/use-upload.ts +388 -0
  361. package/components/upload/src/upload-file.ts +84 -0
  362. package/components/upload/src/upload-file.vue +193 -0
  363. package/components/upload/src/upload-image.ts +90 -0
  364. package/components/upload/src/upload-image.vue +158 -0
  365. package/components/upload/src/upload.ts +196 -0
  366. package/components/upload/src/upload.vue +151 -0
  367. package/components/{fu-upload/utils.js → upload/src/utils.ts} +12 -12
  368. package/components/vtabs/index.ts +1 -0
  369. package/components/vtabs/src/composables/index.ts +2 -0
  370. package/components/vtabs/src/composables/use-vtabs.ts +276 -0
  371. package/components/vtabs/src/composables/vtabs-custom.ts +54 -0
  372. package/components/vtabs/src/vtabs.ts +130 -0
  373. package/components/vtabs/src/vtabs.vue +189 -0
  374. package/components/vtabs-item/index.ts +1 -0
  375. package/components/vtabs-item/src/composables/index.ts +1 -0
  376. package/components/vtabs-item/src/composables/use-vtabs-item.ts +60 -0
  377. package/components/vtabs-item/src/vtabs-item.ts +10 -0
  378. package/components/vtabs-item/src/vtabs-item.vue +20 -0
  379. package/components/waterfall/index.ts +1 -0
  380. package/components/waterfall/src/composables/index.ts +2 -0
  381. package/components/waterfall/src/composables/use-waterfall.ts +139 -0
  382. package/components/waterfall/src/composables/waterfall-custom.ts +18 -0
  383. package/components/waterfall/src/waterfall.ts +114 -0
  384. package/components/waterfall/src/waterfall.vue +104 -0
  385. package/{libs/config/config.js → config/config.ts} +13 -7
  386. package/constants/images.ts +18 -0
  387. package/constants/index.ts +6 -0
  388. package/constants/open-types.ts +33 -0
  389. package/constants/props.ts +18 -0
  390. package/constants/shapes.ts +6 -0
  391. package/constants/types.ts +10 -0
  392. package/constants/z-index.ts +27 -0
  393. package/global.d.ts +103 -0
  394. package/hooks/index.ts +25 -0
  395. package/index.scss +3 -5
  396. package/index.ts +56 -0
  397. package/package.json +1 -1
  398. package/{libs/route/min.route.config.js → route/min.route.config.ts} +62 -23
  399. package/route/route.config.ts +93 -0
  400. package/style/color.scss +26 -0
  401. package/{libs/style → style}/common.scss +1 -14
  402. package/{libs/function/applyEven.js → utils/applyEven.ts} +21 -12
  403. package/utils/check.ts +276 -0
  404. package/{libs/function/chooseUploadFile.js → utils/chooseUploadFile.ts} +22 -26
  405. package/utils/common.ts +609 -0
  406. package/{libs/function/digit.js → utils/digit.ts} +63 -33
  407. package/{components/fu-swipe-action-item/isPC.js → utils/isPC.ts} +1 -1
  408. package/utils/toast.ts +42 -0
  409. package/components/fu-avatar/fu-avatar.vue +0 -157
  410. package/components/fu-avatar/props.js +0 -117
  411. package/components/fu-avatar-group/props.js +0 -74
  412. package/components/fu-badge/props.js +0 -112
  413. package/components/fu-banner-arc/fu-banner-arc.vue +0 -58
  414. package/components/fu-banner-arc/props.js +0 -35
  415. package/components/fu-button/props.js +0 -228
  416. package/components/fu-cell/props.js +0 -108
  417. package/components/fu-cell-group/props.js +0 -19
  418. package/components/fu-checkbox/fu-checkbox.vue +0 -469
  419. package/components/fu-checkbox/props.js +0 -126
  420. package/components/fu-code-input/fu-code-input.vue +0 -269
  421. package/components/fu-code-input/props.js +0 -136
  422. package/components/fu-code-verify/fu-code-verify.vue +0 -221
  423. package/components/fu-code-verify/props.js +0 -136
  424. package/components/fu-collapse/fu-collapse.vue +0 -143
  425. package/components/fu-collapse/props.js +0 -29
  426. package/components/fu-collapse-item/props.js +0 -101
  427. package/components/fu-countdown/fu-countdown.vue +0 -164
  428. package/components/fu-countdown/props.js +0 -35
  429. package/components/fu-datetime-picker/fu-datetime-picker.vue +0 -375
  430. package/components/fu-datetime-picker/props.js +0 -194
  431. package/components/fu-form/fu-form.vue +0 -284
  432. package/components/fu-form/props.js +0 -74
  433. package/components/fu-form-item/fu-form-item.vue +0 -535
  434. package/components/fu-form-item/props.js +0 -66
  435. package/components/fu-grid/fu-grid.vue +0 -113
  436. package/components/fu-grid/props.js +0 -44
  437. package/components/fu-grid-item/fu-grid-item.vue +0 -136
  438. package/components/fu-grid-item/props.js +0 -27
  439. package/components/fu-icon/fu-icon.vue +0 -110
  440. package/components/fu-icon/fuicon.js +0 -1031
  441. package/components/fu-icon/props.js +0 -55
  442. package/components/fu-image/fu-image.vue +0 -268
  443. package/components/fu-image/props.js +0 -145
  444. package/components/fu-index-anchor/fu-index-anchor.vue +0 -91
  445. package/components/fu-index-anchor/props.js +0 -43
  446. package/components/fu-index-item/fu-index-item.vue +0 -79
  447. package/components/fu-index-list/fu-index-list.vue +0 -426
  448. package/components/fu-index-list/props.js +0 -42
  449. package/components/fu-input/fu-input.vue +0 -393
  450. package/components/fu-input/props.js +0 -291
  451. package/components/fu-keyboard/keyboard-number.vue +0 -195
  452. package/components/fu-keyboard/props.js +0 -138
  453. package/components/fu-line/fu-line.vue +0 -64
  454. package/components/fu-line/props.js +0 -58
  455. package/components/fu-link/fu-link.vue +0 -91
  456. package/components/fu-link/props.js +0 -49
  457. package/components/fu-loading/props.js +0 -60
  458. package/components/fu-loading-more/props.js +0 -59
  459. package/components/fu-modal/props.js +0 -128
  460. package/components/fu-navbar/fu-navbar.vue +0 -271
  461. package/components/fu-navbar/props.js +0 -72
  462. package/components/fu-navbar/status-bar.vue +0 -27
  463. package/components/fu-notice-bar/notice-column.vue +0 -313
  464. package/components/fu-notice-bar/notice-row.vue +0 -363
  465. package/components/fu-notice-bar/props.js +0 -173
  466. package/components/fu-number-box/fu-number-box.vue +0 -210
  467. package/components/fu-number-box/props.js +0 -79
  468. package/components/fu-parse/fu-parse.vue +0 -508
  469. package/components/fu-parse/node/node.vue +0 -576
  470. package/components/fu-parse/parser.js +0 -1335
  471. package/components/fu-picker/fu-picker.vue +0 -347
  472. package/components/fu-picker/props.js +0 -150
  473. package/components/fu-popup/fu-popup.vue +0 -475
  474. package/components/fu-popup/keypress.js +0 -45
  475. package/components/fu-popup/props.js +0 -83
  476. package/components/fu-progress/fu-progress.vue +0 -292
  477. package/components/fu-progress/props.js +0 -76
  478. package/components/fu-rate/fu-rate.vue +0 -301
  479. package/components/fu-rate/props.js +0 -103
  480. package/components/fu-read-more/fu-read-more.vue +0 -191
  481. package/components/fu-read-more/props.js +0 -72
  482. package/components/fu-ribbon/fu-ribbon.vue +0 -106
  483. package/components/fu-ribbon/props.js +0 -35
  484. package/components/fu-safe-area/fu-safe-area.vue +0 -61
  485. package/components/fu-scroll-list/fu-scroll-list.vue +0 -196
  486. package/components/fu-scroll-list/nvue.js +0 -28
  487. package/components/fu-scroll-list/props.js +0 -43
  488. package/components/fu-search/props.js +0 -149
  489. package/components/fu-section/props.js +0 -59
  490. package/components/fu-sign-board/fu-sign-board.vue +0 -730
  491. package/components/fu-sign-board/props.js +0 -34
  492. package/components/fu-skeleton/fu-skeleton.vue +0 -238
  493. package/components/fu-skeleton/props.js +0 -35
  494. package/components/fu-steps/fu-steps.vue +0 -81
  495. package/components/fu-steps/props.js +0 -55
  496. package/components/fu-steps-item/fu-steps-item.vue +0 -274
  497. package/components/fu-steps-item/props.js +0 -34
  498. package/components/fu-sticky/fu-sticky.vue +0 -232
  499. package/components/fu-sticky/props.js +0 -54
  500. package/components/fu-subsection/fu-subsection.vue +0 -288
  501. package/components/fu-subsection/props.js +0 -88
  502. package/components/fu-swipe-action/fu-swipe-action.vue +0 -64
  503. package/components/fu-swipe-action-item/props.js +0 -54
  504. package/components/fu-swiper/props.js +0 -163
  505. package/components/fu-switch/props.js +0 -102
  506. package/components/fu-tabs/fu-tabs.vue +0 -361
  507. package/components/fu-tabs/props.js +0 -109
  508. package/components/fu-tag/props.js +0 -135
  509. package/components/fu-text/button.js +0 -13
  510. package/components/fu-text/fu-text.vue +0 -254
  511. package/components/fu-text/openType.js +0 -47
  512. package/components/fu-text/props.js +0 -173
  513. package/components/fu-text/value.js +0 -88
  514. package/components/fu-textarea/fu-textarea.vue +0 -288
  515. package/components/fu-textarea/props.js +0 -206
  516. package/components/fu-timeaxis-item/fu-timeaxis-item.vue +0 -68
  517. package/components/fu-transition/createAnimation.js +0 -131
  518. package/components/fu-transition/fu-transition.vue +0 -292
  519. package/components/fu-transition/props.js +0 -21
  520. package/components/fu-upload/fu-upload.vue +0 -563
  521. package/components/fu-upload/props.js +0 -171
  522. package/components/fu-upload/upload-file.vue +0 -332
  523. package/components/fu-upload/upload-image.vue +0 -304
  524. package/components/fu-vtabs/fu-vtabs.vue +0 -443
  525. package/components/fu-vtabs/props.js +0 -114
  526. package/components/fu-vtabs-item/fu-vtabs-item.vue +0 -71
  527. package/components/fu-waterfall/fu-waterfall.vue +0 -238
  528. package/components/fu-waterfall/props.js +0 -85
  529. package/index.js +0 -71
  530. package/libs/function/check.js +0 -215
  531. package/libs/function/common.js +0 -527
  532. package/libs/function/message.js +0 -47
  533. package/libs/mixin/button.js +0 -85
  534. package/libs/mixin/mixin.js +0 -94
  535. package/libs/mixin/mpMixin.js +0 -8
  536. package/libs/mixin/mpShare.js +0 -15
  537. package/libs/route/route.config.js +0 -66
  538. package/libs/style/color.scss +0 -24
  539. /package/components/{fu-icon → icon/src}/fuicon.ttf +0 -0
  540. /package/components/{fu-swipe-action-item → swipe-action-item/src}/bindingx.js +0 -0
  541. /package/components/{fu-swipe-action-item → swipe-action-item/src}/mpalipay.js +0 -0
  542. /package/components/{fu-swipe-action-item → swipe-action-item/src}/mpother.js +0 -0
  543. /package/components/{fu-swipe-action-item → swipe-action-item/src}/render.js +0 -0
  544. /package/{libs/style → style}/components.scss +0 -0
  545. /package/{libs/style → style}/style.h5.scss +0 -0
  546. /package/{libs/style → style}/style.mp.scss +0 -0
  547. /package/{libs/function → utils}/dayjs.js +0 -0
@@ -0,0 +1,1402 @@
1
+ /**
2
+ * @fileoverview html 解析器 - TypeScript 版本
3
+ */
4
+ declare const uni : any;
5
+ // 配置
6
+ const config : any = {
7
+ // 信任的标签(保持标签名不变)
8
+ trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
9
+
10
+ // 块级标签(转为 div,其他的非信任标签转为 span)
11
+ blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
12
+
13
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
14
+ // 行内标签
15
+ inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong,sub,sup'),
16
+ // #endif
17
+
18
+ // 要移除的标签
19
+ ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
20
+
21
+ // 自闭合的标签
22
+ voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
23
+
24
+ // html 实体
25
+ entities: {
26
+ lt: '<',
27
+ gt: '>',
28
+ quot: '"',
29
+ apos: "'",
30
+ ensp: '\u2002',
31
+ emsp: '\u2003',
32
+ nbsp: '\xA0',
33
+ semi: ';',
34
+ ndash: '–',
35
+ mdash: '—',
36
+ middot: '·',
37
+ lsquo: '\u2018',
38
+ rsquo: '\u2019',
39
+ ldquo: '\u201c',
40
+ rdquo: '\u201d',
41
+ bull: '•',
42
+ hellip: '…',
43
+ larr: '←',
44
+ uarr: '↑',
45
+ rarr: '→',
46
+ darr: '↓'
47
+ },
48
+
49
+ // 默认的标签样式
50
+ tagStyle: {
51
+ // #ifndef APP-PLUS-NVUE
52
+ address: 'font-style:italic',
53
+ big: 'display:inline;font-size:1.2em',
54
+ caption: 'display:table-caption;text-align:center',
55
+ center: 'text-align:center',
56
+ cite: 'font-style:italic',
57
+ dd: 'margin-left:40px',
58
+ mark: 'background-color:yellow',
59
+ pre: 'font-family:monospace;white-space:pre',
60
+ s: 'text-decoration:line-through',
61
+ small: 'display:inline;font-size:0.8em',
62
+ strike: 'text-decoration:line-through',
63
+ u: 'text-decoration:underline'
64
+ // #endif
65
+ },
66
+
67
+ // svg 大小写对照表
68
+ svgDict: {
69
+ animatetransform: 'animateTransform',
70
+ lineargradient: 'linearGradient',
71
+ viewbox: 'viewBox',
72
+ attributename: 'attributeName',
73
+ repeatcount: 'repeatCount',
74
+ repeatdur: 'repeatDur',
75
+ foreignobject: 'foreignObject'
76
+ }
77
+ }
78
+ const tagSelector : any = {}
79
+ let windowWidth : number, system : any
80
+ // #ifdef MP-WEIXIN
81
+ if (uni.canIUse('getWindowInfo')) {
82
+ windowWidth = uni.getWindowInfo().windowWidth
83
+ system = uni.getDeviceInfo().system
84
+ } else {
85
+ // #endif
86
+ const systemInfo = uni.getSystemInfoSync()
87
+ windowWidth = systemInfo.windowWidth
88
+ // #ifdef MP-WEIXIN
89
+ system = systemInfo.system
90
+ }
91
+ // #endif
92
+ const blankChar : any = makeMap(' ,\r,\n,\t,\f')
93
+ let idIndex = 0
94
+
95
+ // #ifdef H5 || APP-PLUS
96
+ config.ignoreTags.iframe = undefined
97
+ config.trustTags.iframe = true
98
+ config.ignoreTags.embed = undefined
99
+ config.trustTags.embed = true
100
+ // #endif
101
+ // #ifdef APP-PLUS-NVUE
102
+ config.ignoreTags.source = undefined
103
+ config.ignoreTags.style = undefined
104
+ // #endif
105
+
106
+ /**
107
+ * @description 创建 map
108
+ * @param {String} str 逗号分隔
109
+ */
110
+ function makeMap(str : string) : any {
111
+ const map = Object.create(null)
112
+ const list = str.split(',')
113
+ for (let i = list.length; i--;) {
114
+ map[list[i]] = true
115
+ }
116
+ return map
117
+ }
118
+
119
+ /**
120
+ * @description 解码 html 实体
121
+ * @param {String} str 要解码的字符串
122
+ * @param {Boolean} amp 要不要解码 &amp;
123
+ * @returns {String} 解码后的字符串
124
+ */
125
+ function decodeEntity(str : string, amp ?: boolean) : string {
126
+ let i = str.indexOf('&')
127
+ while (i !== -1) {
128
+ const j = str.indexOf(';', i + 3)
129
+ let code : any
130
+ if (j === -1) break
131
+ if (str[i + 1] === '#') {
132
+ // &#123; 形式的实体
133
+ code = parseInt((str[i + 2] === 'x' ? '0' : '') + str.substring(i + 2, j))
134
+ if (!isNaN(code)) {
135
+ str = str.substring(0, i) + String.fromCharCode(code) + str.substring(j + 1)
136
+ }
137
+ } else {
138
+ // &nbsp; 形式的实体
139
+ code = str.substring(i + 1, j)
140
+ if (config.entities[code] || (code === 'amp' && amp)) {
141
+ str = str.substring(0, i) + (config.entities[code] || '&') + str.substring(j + 1)
142
+ }
143
+ }
144
+ i = str.indexOf('&', i + 1)
145
+ }
146
+ return str
147
+ }
148
+
149
+ /**
150
+ * @description 合并多个块级标签,加快长内容渲染
151
+ * @param {Array} nodes 要合并的标签数组
152
+ */
153
+ function mergeNodes(nodes : any[]) : void {
154
+ let i = nodes.length - 1
155
+ for (let j = i; j >= -1; j--) {
156
+ if (j === -1 || nodes[j].c || !nodes[j].name || (nodes[j].name !== 'div' && nodes[j].name !== 'p' && nodes[j].name[0] !== 'h') || (nodes[j].attrs.style || '').includes('inline')) {
157
+ if (i - j >= 5) {
158
+ nodes.splice(j + 1, i - j, {
159
+ name: 'div',
160
+ attrs: {},
161
+ children: nodes.slice(j + 1, i + 1)
162
+ })
163
+ }
164
+ i = j - 1
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * @description html 解析器
171
+ * @param {Object} vm 组件实例
172
+ */
173
+ function Parser(vm : any) {
174
+ this.options = vm || {}
175
+ this.tagStyle = Object.assign({}, config.tagStyle, this.options.tagStyle)
176
+ this.imgList = vm.imgList || []
177
+ this.imgList._unloadimgs = 0
178
+ this.plugins = vm.plugins || []
179
+ this.attrs = Object.create(null)
180
+ this.stack = []
181
+ this.nodes = []
182
+ this.pre = (this.options.containerStyle || '').includes('white-space') && this.options.containerStyle.includes('pre') ? 2 : 0
183
+ }
184
+
185
+ /**
186
+ * @description 执行解析
187
+ * @param {String} content 要解析的文本
188
+ */
189
+ Parser.prototype.parse = function (content : string) : any[] {
190
+ // 插件处理
191
+ for (let i = this.plugins.length; i--;) {
192
+ if (this.plugins[i].onUpdate) {
193
+ content = this.plugins[i].onUpdate(content, config) || content
194
+ }
195
+ }
196
+
197
+ new Lexer(this).parse(content)
198
+ // 出栈未闭合的标签
199
+ while (this.stack.length) {
200
+ this.popNode()
201
+ }
202
+ if (this.nodes.length > 50) {
203
+ mergeNodes(this.nodes)
204
+ }
205
+ return this.nodes
206
+ }
207
+
208
+ /**
209
+ * @description 将标签暴露出来(不被 rich-text 包含)
210
+ */
211
+ Parser.prototype.expose = function () : void {
212
+ // #ifndef APP-PLUS-NVUE
213
+ for (let i = this.stack.length; i--;) {
214
+ const item = this.stack[i]
215
+ if (item.c || item.name === 'a' || item.name === 'video' || item.name === 'audio') return
216
+ item.c = 1
217
+ }
218
+ // #endif
219
+ }
220
+
221
+ /**
222
+ * @description 处理插件
223
+ * @param {Object} node 要处理的标签
224
+ * @returns {Boolean} 是否要移除此标签
225
+ */
226
+ Parser.prototype.hook = function (node : any) : boolean {
227
+ for (let i = this.plugins.length; i--;) {
228
+ if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) === false) {
229
+ return false
230
+ }
231
+ }
232
+ return true
233
+ }
234
+
235
+ /**
236
+ * @description 将链接拼接上主域名
237
+ * @param {String} url 需要拼接的链接
238
+ * @returns {String} 拼接后的链接
239
+ */
240
+ Parser.prototype.getUrl = function (url : string) : string {
241
+ const domain = this.options.domain
242
+ if (url[0] === '/') {
243
+ if (url[1] === '/') {
244
+ // // 开头的补充协议名
245
+ url = (domain ? domain.split('://')[0] : 'http') + ':' + url
246
+ } else if (domain) {
247
+ // 否则补充整个域名
248
+ url = domain + url
249
+ } /* #ifdef APP-PLUS */ else {
250
+ // @ts-ignore
251
+ url = plus.io.convertLocalFileSystemURL(url)
252
+ } /* #endif */
253
+ } else if (!url.includes('data:') && !url.includes('://')) {
254
+ if (domain) {
255
+ url = domain + '/' + url
256
+ } /* #ifdef APP-PLUS */ else {
257
+ // @ts-ignore
258
+ url = plus.io.convertLocalFileSystemURL(url)
259
+ } /* #endif */
260
+ }
261
+ return url
262
+ }
263
+
264
+ /**
265
+ * @description 解析样式表
266
+ * @param {Object} node 标签
267
+ * @returns {Object}
268
+ */
269
+ Parser.prototype.parseStyle = function (node : any) : any {
270
+ const attrs = node.attrs
271
+ const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
272
+ const styleObj : any = {}
273
+ let tmp = ''
274
+
275
+ if (attrs.id && !this.xml) {
276
+ // 暴露锚点
277
+ if (this.options.useAnchor) {
278
+ this.expose()
279
+ } else if (node.name !== 'img' && node.name !== 'a' && node.name !== 'video' && node.name !== 'audio') {
280
+ attrs.id = undefined
281
+ }
282
+ }
283
+
284
+ // 转换 width 和 height 属性
285
+ if (attrs.width) {
286
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
287
+ attrs.width = undefined
288
+ }
289
+ if (attrs.height) {
290
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
291
+ attrs.height = undefined
292
+ }
293
+
294
+ for (let i = 0, len = list.length; i < len; i++) {
295
+ const info = list[i].split(':')
296
+ if (info.length < 2) continue
297
+ const key = info.shift().trim().toLowerCase()
298
+ let value = info.join(':').trim()
299
+ if ((value[0] === '-' && value.lastIndexOf('-') > 0) || value.includes('safe')) {
300
+ // 兼容性的 css 不压缩
301
+ tmp += `;${key}:${value}`
302
+ } else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
303
+ // 重复的样式进行覆盖
304
+ if (value.includes('url')) {
305
+ // 填充链接
306
+ let j = value.indexOf('(') + 1
307
+ if (j) {
308
+ while (value[j] === '"' || value[j] === "'" || blankChar[value[j]]) {
309
+ j++
310
+ }
311
+ value = value.substring(0, j) + this.getUrl(value.substring(j))
312
+ }
313
+ } else if (value.includes('rpx')) {
314
+ // 转换 rpx(rich-text 内部不支持 rpx)
315
+ value = value.replace(/[0-9.]+\s*rpx/g, ($: any) => parseFloat($) * windowWidth / 750 + 'px')
316
+ }
317
+ styleObj[key] = value
318
+ }
319
+ }
320
+
321
+ node.attrs.style = tmp
322
+ return styleObj
323
+ }
324
+
325
+ /**
326
+ * @description 解析到标签名
327
+ * @param {String} name 标签名
328
+ * @private
329
+ */
330
+ Parser.prototype.onTagName = function (name : string) : void {
331
+ this.tagName = this.xml ? name : name.toLowerCase()
332
+ if (this.tagName === 'svg') {
333
+ this.xml = (this.xml || 0) + 1 // svg 标签内大小写敏感
334
+ config.ignoreTags.style = undefined // svg 标签内 style 可用
335
+ }
336
+ }
337
+
338
+ /**
339
+ * @description 解析到属性名
340
+ * @param {String} name 属性名
341
+ * @private
342
+ */
343
+ Parser.prototype.onAttrName = function (name : string) : void {
344
+ name = this.xml ? name : name.toLowerCase()
345
+ // #ifdef (VUE3 && (H5 || APP-PLUS)) || APP-PLUS-NVUE
346
+ if (name.includes('?') || name.includes(';')) {
347
+ this.attrName = undefined
348
+ return
349
+ }
350
+ // #endif
351
+ if (name.substring(0, 5) === 'data-') {
352
+ if (name === 'data-src' && !this.attrs.src) {
353
+ // data-src 自动转为 src
354
+ this.attrName = 'src'
355
+ } else if (this.tagName === 'img' || this.tagName === 'a') {
356
+ // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
357
+ this.attrName = name
358
+ } else {
359
+ // 剩余的移除以减小大小
360
+ this.attrName = undefined
361
+ }
362
+ } else {
363
+ this.attrName = name
364
+ this.attrs[name] = 'T' // boolean 型属性缺省设置
365
+ }
366
+ }
367
+
368
+ /**
369
+ * @description 解析到属性值
370
+ * @param {String} val 属性值
371
+ * @private
372
+ */
373
+ Parser.prototype.onAttrVal = function (val : string) : void {
374
+ const name = this.attrName || ''
375
+ if (name === 'style' || name === 'href') {
376
+ // 部分属性进行实体解码
377
+ this.attrs[name] = decodeEntity(val, true)
378
+ } else if (name.includes('src')) {
379
+ // 拼接主域名
380
+ this.attrs[name] = this.getUrl(decodeEntity(val, true))
381
+ } else if (name) {
382
+ this.attrs[name] = val
383
+ }
384
+ }
385
+
386
+ /**
387
+ * @description 解析到标签开始
388
+ * @param {Boolean} selfClose 是否有自闭合标识 />
389
+ * @private
390
+ */
391
+ Parser.prototype.onOpenTag = function (selfClose : boolean) : void {
392
+ // 拼装 node
393
+ const node : any = Object.create(null)
394
+ node.name = this.tagName
395
+ node.attrs = this.attrs
396
+ // 避免因为自动 diff 使得 type 被设置为 null 导致部分内容不显示
397
+ if (this.options.nodes.length) {
398
+ node.type = 'node'
399
+ }
400
+ this.attrs = Object.create(null)
401
+
402
+ const attrs = node.attrs
403
+ const parent = this.stack[this.stack.length - 1]
404
+ const siblings = parent ? parent.children : this.nodes
405
+ const close = this.xml ? selfClose : config.voidTags[node.name]
406
+
407
+ // 替换标签名选择器
408
+ if (tagSelector[node.name]) {
409
+ attrs.class = tagSelector[node.name] + (attrs.class ? ' ' + attrs.class : '')
410
+ }
411
+
412
+ // 转换 embed 标签
413
+ if (node.name === 'embed') {
414
+ // #ifndef H5 || APP-PLUS
415
+ const src = attrs.src || ''
416
+ // 按照后缀名和 type 将 embed 转为 video 或 audio
417
+ if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) {
418
+ node.name = 'video'
419
+ } else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) {
420
+ node.name = 'audio'
421
+ }
422
+ if (attrs.autostart) {
423
+ attrs.autoplay = 'T'
424
+ }
425
+ attrs.controls = 'T'
426
+ // #endif
427
+ // #ifdef H5 || APP-PLUS
428
+ this.expose()
429
+ // #endif
430
+ }
431
+
432
+ // #ifndef APP-PLUS-NVUE
433
+ // 处理音视频
434
+ if (node.name === 'video' || node.name === 'audio') {
435
+ // 设置 id 以便获取 context
436
+ if (node.name === 'video' && !attrs.id) {
437
+ attrs.id = 'v' + idIndex++
438
+ }
439
+ // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
440
+ if (!attrs.controls && !attrs.autoplay) {
441
+ attrs.controls = 'T'
442
+ }
443
+ // 用数组存储所有可用的 source
444
+ node.src = []
445
+ if (attrs.src) {
446
+ node.src.push(attrs.src)
447
+ attrs.src = undefined
448
+ }
449
+ this.expose()
450
+ }
451
+ // #endif
452
+
453
+ // 处理自闭合标签
454
+ if (close) {
455
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
456
+ // 通过 base 标签设置主域名
457
+ if (node.name === 'base' && !this.options.domain) {
458
+ this.options.domain = attrs.href
459
+ } /* #ifndef APP-PLUS-NVUE */ else if (node.name === 'source' && parent && (parent.name === 'video' || parent.name === 'audio') && attrs.src) {
460
+ // 设置 source 标签(仅父节点为 video 或 audio 时有效)
461
+ parent.src.push(attrs.src)
462
+ } /* #endif */
463
+ return
464
+ }
465
+
466
+ // 解析 style
467
+ const styleObj = this.parseStyle(node)
468
+
469
+ // 处理图片
470
+ if (node.name === 'img') {
471
+ if (attrs.src) {
472
+ // 标记 webp
473
+ if (attrs.src.includes('webp')) {
474
+ node.webp = 'T'
475
+ }
476
+ // data url 图片如果没有设置 original-src 默认为不可预览的小图片
477
+ if (attrs.src.includes('data:') && this.options.previewImg !== 'all' && !attrs['original-src']) {
478
+ attrs.ignore = 'T'
479
+ }
480
+ if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
481
+ for (let i = this.stack.length; i--;) {
482
+ const item = this.stack[i]
483
+ if (item.name === 'a') {
484
+ node.a = item.attrs
485
+ }
486
+ if (item.name === 'table' && !node.webp && !attrs.src.includes('cloud://')) {
487
+ if (!styleObj.display || styleObj.display.includes('inline')) {
488
+ node.t = 'inline-block'
489
+ } else {
490
+ node.t = styleObj.display
491
+ }
492
+ styleObj.display = undefined
493
+ }
494
+ // #ifndef H5 || APP-PLUS
495
+ const style = item.attrs.style || ''
496
+ if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || parseInt(styleObj.width) > 100)) {
497
+ styleObj.width = '100% !important'
498
+ styleObj.height = ''
499
+ for (let j = i + 1; j < this.stack.length; j++) {
500
+ this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
501
+ }
502
+ } else if (style.includes('flex') && styleObj.width === '100%') {
503
+ for (let j = i + 1; j < this.stack.length; j++) {
504
+ const style = this.stack[j].attrs.style || ''
505
+ if (!style.includes(';width') && !style.includes(' width') && style.indexOf('width') !== 0) {
506
+ styleObj.width = ''
507
+ break
508
+ }
509
+ }
510
+ } else if (style.includes('inline-block')) {
511
+ if (styleObj.width && styleObj.width[styleObj.width.length - 1] === '%') {
512
+ item.attrs.style += ';max-width:' + styleObj.width
513
+ styleObj.width = ''
514
+ } else {
515
+ item.attrs.style += ';max-width:100%'
516
+ }
517
+ }
518
+ // #endif
519
+ item.c = 1
520
+ }
521
+ attrs.i = this.imgList.length.toString()
522
+ let src = attrs['original-src'] || attrs.src
523
+ // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
524
+ if (this.imgList.includes(src)) {
525
+ // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
526
+ let i = src.indexOf('://')
527
+ if (i !== -1) {
528
+ i += 3
529
+ let newSrc = src.substring(0, i)
530
+ for (; i < src.length; i++) {
531
+ if (src[i] === '/') break
532
+ newSrc += Math.random() > 0.5 ? src[i].toUpperCase() : src[i]
533
+ }
534
+ newSrc += src.substring(i)
535
+ src = newSrc
536
+ }
537
+ }
538
+ // #endif
539
+ this.imgList.push(src)
540
+ if (!node.t) {
541
+ this.imgList._unloadimgs += 1
542
+ }
543
+ // #ifdef H5 || APP-PLUS
544
+ if (this.options.lazyLoad) {
545
+ attrs['data-src'] = attrs.src
546
+ attrs.src = undefined
547
+ }
548
+ // #endif
549
+ }
550
+ }
551
+ if (styleObj.display === 'inline') {
552
+ styleObj.display = ''
553
+ }
554
+ // #ifndef APP-PLUS-NVUE
555
+ if (attrs.ignore) {
556
+ styleObj['max-width'] = styleObj['max-width'] || '100%'
557
+ attrs.style += ';-webkit-touch-callout:none'
558
+ }
559
+ // #endif
560
+ // 设置的宽度超出屏幕,为避免变形,高度转为自动
561
+ if (parseInt(styleObj.width) > windowWidth) {
562
+ styleObj.height = undefined
563
+ }
564
+ // 记录是否设置了宽高
565
+ if (!isNaN(parseInt(styleObj.width))) {
566
+ node.w = 'T'
567
+ }
568
+ if (!isNaN(parseInt(styleObj.height)) && (!styleObj.height.includes('%') || (parent && (parent.attrs.style || '').includes('height')))) {
569
+ node.h = 'T'
570
+ }
571
+ if (node.w && node.h && styleObj['object-fit']) {
572
+ if (styleObj['object-fit'] === 'contain') {
573
+ node.m = 'aspectFit'
574
+ } else if (styleObj['object-fit'] === 'cover') {
575
+ node.m = 'aspectFill'
576
+ }
577
+ }
578
+ } else if (node.name === 'svg') {
579
+ siblings.push(node)
580
+ this.stack.push(node)
581
+ this.popNode()
582
+ return
583
+ }
584
+ for (const key in styleObj) {
585
+ if (styleObj[key]) {
586
+ attrs.style += `;${key}:${styleObj[key].replace(' !important', '')}`
587
+ }
588
+ }
589
+ attrs.style = attrs.style.substring(1) || undefined
590
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
591
+ if (!attrs.style) {
592
+ delete attrs.style
593
+ }
594
+ // #endif
595
+ } else {
596
+ if ((node.name === 'pre' || ((attrs.style || '').includes('white-space') && attrs.style.includes('pre'))) && this.pre !== 2) {
597
+ this.pre = node.pre = 1
598
+ }
599
+ node.children = []
600
+ this.stack.push(node)
601
+ }
602
+
603
+ // 加入节点树
604
+ siblings.push(node)
605
+ }
606
+
607
+ /**
608
+ * @description 解析到标签结束
609
+ * @param {String} name 标签名
610
+ * @private
611
+ */
612
+ Parser.prototype.onCloseTag = function (name : string) : void {
613
+ // 依次出栈到匹配为止
614
+ name = this.xml ? name : name.toLowerCase()
615
+ let i : number
616
+ for (i = this.stack.length; i--;) {
617
+ if (this.stack[i].name === name) break
618
+ }
619
+ if (i !== -1) {
620
+ while (this.stack.length > i) {
621
+ this.popNode()
622
+ }
623
+ } else if (name === 'p' || name === 'br') {
624
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
625
+ siblings.push({
626
+ name,
627
+ attrs: {
628
+ class: tagSelector[name] || '',
629
+ style: this.tagStyle[name] || ''
630
+ }
631
+ })
632
+ }
633
+ }
634
+
635
+ /**
636
+ * @description 处理标签出栈
637
+ * @private
638
+ */
639
+ Parser.prototype.popNode = function () : void {
640
+ const node = this.stack.pop()
641
+ let attrs = node.attrs
642
+ const children = node.children
643
+ const parent = this.stack[this.stack.length - 1]
644
+ const siblings = parent ? parent.children : this.nodes
645
+
646
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
647
+ // 获取标题
648
+ if (node.name === 'title' && children.length && children[0].type === 'text' && this.options.setTitle) {
649
+ uni.setNavigationBarTitle({
650
+ title: children[0].text
651
+ })
652
+ }
653
+ siblings.pop()
654
+ return
655
+ }
656
+
657
+ if (node.pre && this.pre !== 2) {
658
+ // 是否合并空白符标识
659
+ this.pre = node.pre = undefined
660
+ for (let i = this.stack.length; i--;) {
661
+ if (this.stack[i].pre) {
662
+ this.pre = 1
663
+ }
664
+ }
665
+ }
666
+
667
+ const styleObj : any = {}
668
+
669
+ // 转换 svg
670
+ if (node.name === 'svg') {
671
+ if (this.xml > 1) {
672
+ // 多层 svg 嵌套
673
+ this.xml--
674
+ return
675
+ }
676
+ // #ifdef APP-PLUS-NVUE
677
+ (function traversal(node : any) : void {
678
+ if (node.name) {
679
+ // 调整 svg 的大小写
680
+ node.name = config.svgDict[node.name] || node.name
681
+ for (const item in node.attrs) {
682
+ if (config.svgDict[item]) {
683
+ node.attrs[config.svgDict[item]] = node.attrs[item]
684
+ node.attrs[item] = undefined
685
+ }
686
+ }
687
+ for (let i = 0; i < (node.children || []).length; i++) {
688
+ traversal(node.children[i])
689
+ }
690
+ }
691
+ })(node)
692
+ // #endif
693
+ // #ifndef APP-PLUS-NVUE
694
+ let src = ''
695
+ const style = attrs.style
696
+ attrs.style = ''
697
+ attrs.xmlns = 'http://www.w3.org/2000/svg';
698
+ (function traversal(node : any) : void {
699
+ if (node.type === 'text') {
700
+ src += node.text
701
+ return
702
+ }
703
+ const name = config.svgDict[node.name] || node.name
704
+ if (name === 'foreignObject') {
705
+ for (const child of (node.children || [])) {
706
+ if (child.attrs && !child.attrs.xmlns) {
707
+ child.attrs.xmlns = 'http://www.w3.org/1999/xhtml'
708
+ break
709
+ }
710
+ }
711
+ }
712
+ src += '<' + name
713
+ for (const item in node.attrs) {
714
+ const val = node.attrs[item]
715
+ if (val) {
716
+ src += ` ${config.svgDict[item] || item}="${val.replace(/"/g, '')}"`
717
+ }
718
+ }
719
+ if (!node.children) {
720
+ src += '/>'
721
+ } else {
722
+ src += '>'
723
+ for (let i = 0; i < node.children.length; i++) {
724
+ traversal(node.children[i])
725
+ }
726
+ src += '</' + name + '>'
727
+ }
728
+ })(node)
729
+ node.name = 'img'
730
+ node.attrs = {
731
+ src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
732
+ style,
733
+ ignore: 'T'
734
+ }
735
+ node.children = undefined
736
+ // #endif
737
+ this.xml = false
738
+ config.ignoreTags.style = true
739
+ return
740
+ }
741
+
742
+ // #ifndef APP-PLUS-NVUE
743
+ // 转换 align 属性
744
+ if (attrs.align) {
745
+ if (node.name === 'table') {
746
+ if (attrs.align === 'center') {
747
+ styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'
748
+ } else {
749
+ styleObj.float = attrs.align
750
+ }
751
+ } else {
752
+ styleObj['text-align'] = attrs.align
753
+ }
754
+ attrs.align = undefined
755
+ }
756
+
757
+ // 转换 dir 属性
758
+ if (attrs.dir) {
759
+ styleObj.direction = attrs.dir
760
+ attrs.dir = undefined
761
+ }
762
+
763
+ // 转换 font 标签的属性
764
+ if (node.name === 'font') {
765
+ if (attrs.color) {
766
+ styleObj.color = attrs.color
767
+ attrs.color = undefined
768
+ }
769
+ if (attrs.face) {
770
+ styleObj['font-family'] = attrs.face
771
+ attrs.face = undefined
772
+ }
773
+ if (attrs.size) {
774
+ let size = parseInt(attrs.size)
775
+ if (!isNaN(size)) {
776
+ if (size < 1) {
777
+ size = 1
778
+ } else if (size > 7) {
779
+ size = 7
780
+ }
781
+ styleObj['font-size'] = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-large'][size - 1]
782
+ }
783
+ attrs.size = undefined
784
+ }
785
+ }
786
+ // #endif
787
+
788
+ // 一些编辑器的自带 class
789
+ if ((attrs.class || '').includes('align-center')) {
790
+ styleObj['text-align'] = 'center'
791
+ }
792
+
793
+ Object.assign(styleObj, this.parseStyle(node))
794
+
795
+ if (node.name !== 'table' && parseInt(styleObj.width) > windowWidth) {
796
+ styleObj['max-width'] = '100%'
797
+ styleObj['box-sizing'] = 'border-box'
798
+ }
799
+
800
+ // #ifndef APP-PLUS-NVUE
801
+ if (config.blockTags[node.name]) {
802
+ node.name = 'div'
803
+ } else if (!config.trustTags[node.name] && !this.xml) {
804
+ // 未知标签转为 span,避免无法显示
805
+ node.name = 'span'
806
+ }
807
+
808
+ if (node.name === 'a' || node.name === 'ad'
809
+ // #ifdef H5 || APP-PLUS
810
+ || node.name === 'iframe' // eslint-disable-line
811
+ // #endif
812
+ ) {
813
+ this.expose()
814
+ } else if (node.name === 'video') {
815
+ if ((styleObj.height || '').includes('auto')) {
816
+ styleObj.height = undefined
817
+ }
818
+ /* #ifdef APP-PLUS */
819
+ let str = '<video style="width:100%;height:100%"'
820
+ for (const item in attrs) {
821
+ if (attrs[item]) {
822
+ str += ' ' + item + '="' + attrs[item] + '"'
823
+ }
824
+ }
825
+ if (this.options.pauseVideo) {
826
+ str += ' onplay="this.dispatchEvent(new CustomEvent(\'vplay\',{bubbles:!0}));for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"'
827
+ }
828
+ str += '>'
829
+ for (let i = 0; i < node.src.length; i++) {
830
+ str += '<source src="' + node.src[i] + '">'
831
+ }
832
+ str += '</video>'
833
+ node.html = str
834
+ /* #endif */
835
+ } else if ((node.name === 'ul' || node.name === 'ol') && node.c) {
836
+ // 列表处理
837
+ const types : any = {
838
+ a: 'lower-alpha',
839
+ A: 'upper-alpha',
840
+ i: 'lower-roman',
841
+ I: 'upper-roman'
842
+ }
843
+ if (types[attrs.type]) {
844
+ attrs.style += ';list-style-type:' + types[attrs.type]
845
+ attrs.type = undefined
846
+ }
847
+ for (let i = children.length; i--;) {
848
+ if (children[i].name === 'li') {
849
+ children[i].c = 1
850
+ }
851
+ }
852
+ } else if (node.name === 'table') {
853
+ // 表格处理
854
+ // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
855
+ let padding = parseFloat(attrs.cellpadding)
856
+ let spacing = parseFloat(attrs.cellspacing)
857
+ const border = parseFloat(attrs.border)
858
+ const bordercolor = styleObj['border-color']
859
+ const borderstyle = styleObj['border-style']
860
+ if (node.c) {
861
+ // padding 和 spacing 默认 2
862
+ if (isNaN(padding)) {
863
+ padding = 2
864
+ }
865
+ if (isNaN(spacing)) {
866
+ spacing = 2
867
+ }
868
+ }
869
+ if (border) {
870
+ attrs.style += `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}`
871
+ }
872
+ if (node.flag && node.c) {
873
+ // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
874
+ styleObj.display = 'grid'
875
+ if (styleObj['border-collapse'] === 'collapse') {
876
+ styleObj['border-collapse'] = undefined
877
+ spacing = 0
878
+ }
879
+ if (spacing) {
880
+ styleObj['grid-gap'] = spacing + 'px'
881
+ styleObj.padding = spacing + 'px'
882
+ } else if (border) {
883
+ // 无间隔的情况下避免边框重叠
884
+ attrs.style += ';border-left:0;border-top:0'
885
+ }
886
+
887
+ const width : any[] = [] // 表格的列宽
888
+ const trList : any[] = [] // tr 列表
889
+ const cells : any[] = [] // 保存新的单元格
890
+ const map : any = {}; // 被合并单元格占用的格子
891
+
892
+ (function traversal(nodes : any[]) : void {
893
+ for (let i = 0; i < nodes.length; i++) {
894
+ if (nodes[i].name === 'tr') {
895
+ trList.push(nodes[i])
896
+ } else if (nodes[i].name === 'colgroup') {
897
+ let colI = 1
898
+ for (const col of (nodes[i].children || [])) {
899
+ if (col.name === 'col') {
900
+ const style = col.attrs.style || ''
901
+ const start = style.indexOf('width') ? style.indexOf(';width') : 0
902
+ // 提取出宽度
903
+ if (start !== -1) {
904
+ let end = style.indexOf(';', start + 6)
905
+ if (end === -1) {
906
+ end = style.length
907
+ }
908
+ width[colI] = style.substring(start ? start + 7 : 6, end)
909
+ }
910
+ colI += 1
911
+ }
912
+ }
913
+ } else {
914
+ traversal(nodes[i].children || [])
915
+ }
916
+ }
917
+ })(children)
918
+
919
+ for (let row = 1; row <= trList.length; row++) {
920
+ let col = 1
921
+ for (let j = 0; j < trList[row - 1].children.length; j++) {
922
+ const td = trList[row - 1].children[j]
923
+ if (td.name === 'td' || td.name === 'th') {
924
+ // 这个格子被上面的单元格占用,则列号++
925
+ while (map[row + '.' + col]) {
926
+ col++
927
+ }
928
+ let style = td.attrs.style || ''
929
+ let start = style.indexOf('width') ? style.indexOf(';width') : 0
930
+ // 提取出 td 的宽度
931
+ if (start !== -1) {
932
+ let end = style.indexOf(';', start + 6)
933
+ if (end === -1) {
934
+ end = style.length
935
+ }
936
+ if (!td.attrs.colspan) {
937
+ width[col] = style.substring(start ? start + 7 : 6, end)
938
+ }
939
+ style = style.substring(0, start) + style.substring(end)
940
+ }
941
+ // 设置竖直对齐
942
+ style += ';display:flex'
943
+ start = style.indexOf('vertical-align')
944
+ if (start !== -1) {
945
+ const val = style.substring(start + 15, 10)
946
+ if (val.includes('middle')) {
947
+ style += ';align-items:center'
948
+ } else if (val.includes('bottom')) {
949
+ style += ';align-items:flex-end'
950
+ }
951
+ } else {
952
+ style += ';align-items:center'
953
+ }
954
+ // 设置水平对齐
955
+ start = style.indexOf('text-align')
956
+ if (start !== -1) {
957
+ const val = style.substring(start + 11, 10)
958
+ if (val.includes('center')) {
959
+ style += ';justify-content: center'
960
+ } else if (val.includes('right')) {
961
+ style += ';justify-content: right'
962
+ }
963
+ }
964
+ style = (border ? `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '') + ';' + style
965
+ // 处理列合并
966
+ if (td.attrs.colspan) {
967
+ style += `;grid-column-start:${col};grid-column-end:${col + parseInt(td.attrs.colspan)}`
968
+ if (!td.attrs.rowspan) {
969
+ style += `;grid-row-start:${row};grid-row-end:${row + 1}`
970
+ }
971
+ col += parseInt(td.attrs.colspan) - 1
972
+ }
973
+ // 处理行合并
974
+ if (td.attrs.rowspan) {
975
+ style += `;grid-row-start:${row};grid-row-end:${row + parseInt(td.attrs.rowspan)}`
976
+ if (!td.attrs.colspan) {
977
+ style += `;grid-column-start:${col};grid-column-end:${col + 1}`
978
+ }
979
+ // 记录下方单元格被占用
980
+ for (let rowspan = 1; rowspan < td.attrs.rowspan; rowspan++) {
981
+ for (let colspan = 0; colspan < (td.attrs.colspan || 1); colspan++) {
982
+ map[(row + rowspan) + '.' + (col - colspan)] = 1
983
+ }
984
+ }
985
+ }
986
+ if (style) {
987
+ td.attrs.style = style
988
+ }
989
+ cells.push(td)
990
+ col++
991
+ }
992
+ }
993
+ if (row === 1) {
994
+ let temp = ''
995
+ for (let i = 1; i < col; i++) {
996
+ temp += (width[i] ? width[i] : 'auto') + ' '
997
+ }
998
+ styleObj['grid-template-columns'] = temp
999
+ }
1000
+ }
1001
+ node.children = cells
1002
+ } else {
1003
+ // 没有使用合并单元格的表格通过 table 布局实现
1004
+ if (node.c) {
1005
+ styleObj.display = 'table'
1006
+ }
1007
+ if (!isNaN(spacing)) {
1008
+ styleObj['border-spacing'] = spacing + 'px'
1009
+ }
1010
+ if (border || padding) {
1011
+ // 遍历
1012
+ (function traversal(nodes : any[]) : void {
1013
+ for (let i = 0; i < nodes.length; i++) {
1014
+ const td = nodes[i]
1015
+ if (td.name === 'th' || td.name === 'td') {
1016
+ if (border) {
1017
+ td.attrs.style = `border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'};${td.attrs.style || ''}`
1018
+ }
1019
+ if (padding) {
1020
+ td.attrs.style = `padding:${padding}px;${td.attrs.style || ''}`
1021
+ }
1022
+ } else if (td.children) {
1023
+ traversal(td.children)
1024
+ }
1025
+ }
1026
+ })(children)
1027
+ }
1028
+ }
1029
+ // 给表格添加一个单独的横向滚动层
1030
+ if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
1031
+ const table = Object.assign({}, node)
1032
+ node.name = 'div'
1033
+ node.attrs = {
1034
+ style: 'overflow:auto'
1035
+ }
1036
+ node.children = [table]
1037
+ attrs = table.attrs
1038
+ }
1039
+ } else if ((node.name === 'tbody' || node.name === 'tr') && node.flag && node.c) {
1040
+ node.flag = undefined;
1041
+ (function traversal(nodes : any[]) : void {
1042
+ for (let i = 0; i < nodes.length; i++) {
1043
+ if (nodes[i].name === 'td') {
1044
+ // 颜色样式设置给单元格避免丢失
1045
+ for (const style of ['color', 'background', 'background-color']) {
1046
+ if (styleObj[style]) {
1047
+ nodes[i].attrs.style = style + ':' + styleObj[style] + ';' + (nodes[i].attrs.style || '')
1048
+ }
1049
+ }
1050
+ } else {
1051
+ traversal(nodes[i].children || [])
1052
+ }
1053
+ }
1054
+ })(children)
1055
+ } else if ((node.name === 'td' || node.name === 'th') && (attrs.colspan || attrs.rowspan)) {
1056
+ for (let i = this.stack.length; i--;) {
1057
+ if (this.stack[i].name === 'table' || this.stack[i].name === 'tbody' || this.stack[i].name === 'tr') {
1058
+ this.stack[i].flag = 1 // 指示含有合并单元格
1059
+ }
1060
+ }
1061
+ } else if (node.name === 'ruby') {
1062
+ // 转换 ruby
1063
+ node.name = 'span'
1064
+ for (let i = 0; i < children.length - 1; i++) {
1065
+ if (children[i].type === 'text' && children[i + 1].name === 'rt') {
1066
+ children[i] = {
1067
+ name: 'div',
1068
+ attrs: {
1069
+ style: 'display:inline-block;text-align:center'
1070
+ },
1071
+ children: [{
1072
+ name: 'div', attrs: {
1073
+ style: 'font-size:50%;' + (children[i + 1].attrs.style || '')
1074
+ },
1075
+ children: children[i + 1].children
1076
+ }, children[i]]
1077
+ }
1078
+ children.splice(i + 1, 1)
1079
+ }
1080
+ }
1081
+ } else if (node.c) {
1082
+ (function traversal(node : any) : void {
1083
+ node.c = 2
1084
+ for (let i = node.children.length; i--;) {
1085
+ const child = node.children[i]
1086
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
1087
+ if (child.name && (config.inlineTags[child.name] || ((child.attrs.style || '').includes('inline') && child.children)) && !child.c) {
1088
+ traversal(child)
1089
+ }
1090
+ // #endif
1091
+ if (!child.c || child.name === 'table') {
1092
+ node.c = 1
1093
+ }
1094
+ }
1095
+ })(node)
1096
+ }
1097
+
1098
+ if ((styleObj.display || '').includes('flex') && !node.c) {
1099
+ for (let i = children.length; i--;) {
1100
+ const item = children[i]
1101
+ if (item.f) {
1102
+ item.attrs.style = (item.attrs.style || '') + item.f
1103
+ item.f = undefined
1104
+ }
1105
+ }
1106
+ }
1107
+ // flex 布局时部分样式需要提取到 rich-text 外层
1108
+ const flex = parent && ((parent.attrs.style || '').includes('flex') || (parent.attrs.style || '').includes('grid'))
1109
+ // #ifdef MP-WEIXIN
1110
+ // 检查基础库版本 virtualHost 是否可用
1111
+ // @ts-ignore
1112
+ && !(node.c && wx.getNFCAdapter)
1113
+ // #endif
1114
+ // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
1115
+ && !node.c
1116
+ // #endif
1117
+ if (flex) {
1118
+ node.f = ';max-width:100%'
1119
+ }
1120
+
1121
+ if (children.length >= 50 && node.c && !(styleObj.display || '').includes('flex')) {
1122
+ mergeNodes(children)
1123
+ }
1124
+ // #endif
1125
+
1126
+ for (const key in styleObj) {
1127
+ if (styleObj[key]) {
1128
+ const val = `;${key}:${styleObj[key].replace(' !important', '')}`
1129
+ /* #ifndef APP-PLUS-NVUE */
1130
+ if (flex && ((key.includes('flex') && key !== 'flex-direction') || key === 'align-self' || key.includes('grid') || styleObj[key][0] === '-' || (key.includes('width') && val.includes('%')))) {
1131
+ node.f += val
1132
+ if (key === 'width') {
1133
+ attrs.style += ';width:100%'
1134
+ }
1135
+ } else /* #endif */ {
1136
+ attrs.style += val
1137
+ }
1138
+ }
1139
+ }
1140
+ attrs.style = attrs.style.substring(1) || undefined
1141
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
1142
+ for (const key in attrs) {
1143
+ if (!attrs[key]) {
1144
+ delete attrs[key]
1145
+ }
1146
+ }
1147
+ // #endif
1148
+ }
1149
+
1150
+ /**
1151
+ * @description 解析到文本
1152
+ * @param {String} text 文本内容
1153
+ */
1154
+ Parser.prototype.onText = function (text : string) : void {
1155
+ if (!this.pre) {
1156
+ // 合并空白符
1157
+ let trim = ''
1158
+ let flag: boolean
1159
+ for (let i = 0, len = text.length; i < len; i++) {
1160
+ if (!blankChar[text[i]]) {
1161
+ trim += text[i]
1162
+ } else {
1163
+ if (trim[trim.length - 1] !== ' ') {
1164
+ trim += ' '
1165
+ }
1166
+ if (text[i] === '\n' && !flag) {
1167
+ flag = true
1168
+ }
1169
+ }
1170
+ }
1171
+ // 去除含有换行符的空串
1172
+ if (trim === ' ') {
1173
+ if (flag) return
1174
+ // #ifdef VUE3
1175
+ else {
1176
+ const parent = this.stack[this.stack.length - 1]
1177
+ if (parent && parent.name[0] === 't') return
1178
+ }
1179
+ // #endif
1180
+ }
1181
+ text = trim
1182
+ }
1183
+ const node : any = Object.create(null)
1184
+ node.type = 'text'
1185
+ // #ifdef (MP-BAIDU || MP-ALIPAY || MP-TOUTIAO) && VUE3
1186
+ node.attrs = {}
1187
+ // #endif
1188
+ node.text = decodeEntity(text)
1189
+ if (this.hook(node)) {
1190
+ // #ifdef MP-WEIXIN
1191
+ if (this.options.selectable === 'force' && system.includes('iOS') && !uni.canIUse('rich-text.user-select')) {
1192
+ this.expose()
1193
+ }
1194
+ // #endif
1195
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
1196
+ siblings.push(node)
1197
+ }
1198
+ }
1199
+
1200
+ /**
1201
+ * @description html 词法分析器
1202
+ * @param {Object} handler 高层处理器
1203
+ */
1204
+ function Lexer(handler : any) {
1205
+ this.handler = handler
1206
+ }
1207
+
1208
+ /**
1209
+ * @description 执行解析
1210
+ * @param {String} content 要解析的文本
1211
+ */
1212
+ Lexer.prototype.parse = function (content : string) : void {
1213
+ this.content = content || ''
1214
+ this.i = 0 // 标记解析位置
1215
+ this.start = 0 // 标记一个单词的开始位置
1216
+ this.state = this.text // 当前状态
1217
+ for (let len = this.content.length; this.i !== -1 && this.i < len;) {
1218
+ this.state()
1219
+ }
1220
+ }
1221
+
1222
+ /**
1223
+ * @description 检查标签是否闭合
1224
+ * @param {String} method 如果闭合要进行的操作
1225
+ * @returns {Boolean} 是否闭合
1226
+ * @private
1227
+ */
1228
+ Lexer.prototype.checkClose = function (method ?: string) : boolean {
1229
+ const selfClose = this.content[this.i] === '/'
1230
+ if (this.content[this.i] === '>' || (selfClose && this.content[this.i + 1] === '>')) {
1231
+ if (method) {
1232
+ this.handler[method](this.content.substring(this.start, this.i))
1233
+ }
1234
+ this.i += selfClose ? 2 : 1
1235
+ this.start = this.i
1236
+ this.handler.onOpenTag(selfClose)
1237
+ if (this.handler.tagName === 'script') {
1238
+ this.i = this.content.indexOf('</', this.i)
1239
+ if (this.i !== -1) {
1240
+ this.i += 2
1241
+ this.start = this.i
1242
+ }
1243
+ this.state = this.endTag
1244
+ } else {
1245
+ this.state = this.text
1246
+ }
1247
+ return true
1248
+ }
1249
+ return false
1250
+ }
1251
+
1252
+ /**
1253
+ * @description 文本状态
1254
+ * @private
1255
+ */
1256
+ Lexer.prototype.text = function () : void {
1257
+ this.i = this.content.indexOf('<', this.i) // 查找最近的标签
1258
+ if (this.i === -1) {
1259
+ // 没有标签了
1260
+ if (this.start < this.content.length) {
1261
+ this.handler.onText(this.content.substring(this.start, this.content.length))
1262
+ }
1263
+ return
1264
+ }
1265
+ const c = this.content[this.i + 1]
1266
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1267
+ // 标签开头
1268
+ if (this.start !== this.i) {
1269
+ this.handler.onText(this.content.substring(this.start, this.i))
1270
+ }
1271
+ this.start = ++this.i
1272
+ this.state = this.tagName
1273
+ } else if (c === '/' || c === '!' || c === '?') {
1274
+ if (this.start !== this.i) {
1275
+ this.handler.onText(this.content.substring(this.start, this.i))
1276
+ }
1277
+ const next = this.content[this.i + 2]
1278
+ if (c === '/' && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
1279
+ // 标签结尾
1280
+ this.i += 2
1281
+ this.start = this.i
1282
+ this.state = this.endTag
1283
+ return
1284
+ }
1285
+ // 处理注释
1286
+ let end = '-->'
1287
+ if (c !== '!' || this.content[this.i + 2] !== '-' || this.content[this.i + 3] !== '-') {
1288
+ end = '>'
1289
+ }
1290
+ this.i = this.content.indexOf(end, this.i)
1291
+ if (this.i !== -1) {
1292
+ this.i += end.length
1293
+ this.start = this.i
1294
+ }
1295
+ } else {
1296
+ this.i++
1297
+ }
1298
+ }
1299
+
1300
+ /**
1301
+ * @description 标签名状态
1302
+ * @private
1303
+ */
1304
+ Lexer.prototype.tagName = function () : void {
1305
+ if (blankChar[this.content[this.i]]) {
1306
+ // 解析到标签名
1307
+ this.handler.onTagName(this.content.substring(this.start, this.i))
1308
+ while (blankChar[this.content[++this.i]]);
1309
+ if (this.i < this.content.length && !this.checkClose()) {
1310
+ this.start = this.i
1311
+ this.state = this.attrName
1312
+ }
1313
+ } else if (!this.checkClose('onTagName')) {
1314
+ this.i++
1315
+ }
1316
+ }
1317
+
1318
+ /**
1319
+ * @description 属性名状态
1320
+ * @private
1321
+ */
1322
+ Lexer.prototype.attrName = function () : void {
1323
+ let c = this.content[this.i]
1324
+ if (blankChar[c] || c === '=') {
1325
+ // 解析到属性名
1326
+ this.handler.onAttrName(this.content.substring(this.start, this.i))
1327
+ let needVal = c === '='
1328
+ const len = this.content.length
1329
+ while (++this.i < len) {
1330
+ c = this.content[this.i]
1331
+ if (!blankChar[c]) {
1332
+ if (this.checkClose()) return
1333
+ if (needVal) {
1334
+ // 等号后遇到第一个非空字符
1335
+ this.start = this.i
1336
+ this.state = this.attrVal
1337
+ return
1338
+ }
1339
+ if (this.content[this.i] === '=') {
1340
+ needVal = true
1341
+ } else {
1342
+ this.start = this.i
1343
+ this.state = this.attrName
1344
+ return
1345
+ }
1346
+ }
1347
+ }
1348
+ } else if (!this.checkClose('onAttrName')) {
1349
+ this.i++
1350
+ }
1351
+ }
1352
+
1353
+ /**
1354
+ * @description 属性值状态
1355
+ * @private
1356
+ */
1357
+ Lexer.prototype.attrVal = function () : void {
1358
+ const c = this.content[this.i]
1359
+ const len = this.content.length
1360
+ if (c === '"' || c === "'") {
1361
+ // 有冒号的属性
1362
+ this.start = ++this.i
1363
+ this.i = this.content.indexOf(c, this.i)
1364
+ if (this.i === -1) return
1365
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
1366
+ } else {
1367
+ // 没有冒号的属性
1368
+ for (; this.i < len; this.i++) {
1369
+ if (blankChar[this.content[this.i]]) {
1370
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
1371
+ break
1372
+ } else if (this.checkClose('onAttrVal')) return
1373
+ }
1374
+ }
1375
+ while (blankChar[this.content[++this.i]]);
1376
+ if (this.i < len && !this.checkClose()) {
1377
+ this.start = this.i
1378
+ this.state = this.attrName
1379
+ }
1380
+ }
1381
+
1382
+ /**
1383
+ * @description 结束标签状态
1384
+ * @returns {String} 结束的标签名
1385
+ * @private
1386
+ */
1387
+ Lexer.prototype.endTag = function () : void {
1388
+ const c = this.content[this.i]
1389
+ if (blankChar[c] || c === '>' || c === '/') {
1390
+ this.handler.onCloseTag(this.content.substring(this.start, this.i))
1391
+ if (c !== '>') {
1392
+ this.i = this.content.indexOf('>', this.i)
1393
+ if (this.i === -1) return
1394
+ }
1395
+ this.start = ++this.i
1396
+ this.state = this.text
1397
+ } else {
1398
+ this.i++
1399
+ }
1400
+ }
1401
+
1402
+ export default Parser