@10yun/cv-mobile-ui 0.5.27 → 0.5.29

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