uview-ui-wjf 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/changelog.md +388 -0
  4. package/components/u--form/u--form.vue +92 -0
  5. package/components/u--image/u--image.vue +73 -0
  6. package/components/u--input/u--input.vue +115 -0
  7. package/components/u--text/u--text.vue +72 -0
  8. package/components/u--textarea/u--textarea.vue +85 -0
  9. package/components/u-action-sheet/props.js +54 -0
  10. package/components/u-action-sheet/u-action-sheet.vue +278 -0
  11. package/components/u-album/props.js +59 -0
  12. package/components/u-album/u-album.vue +259 -0
  13. package/components/u-alert/props.js +44 -0
  14. package/components/u-alert/u-alert.vue +243 -0
  15. package/components/u-avatar/props.js +78 -0
  16. package/components/u-avatar/u-avatar.vue +173 -0
  17. package/components/u-avatar-group/props.js +52 -0
  18. package/components/u-avatar-group/u-avatar-group.vue +103 -0
  19. package/components/u-back-top/props.js +54 -0
  20. package/components/u-back-top/u-back-top.vue +129 -0
  21. package/components/u-badge/props.js +72 -0
  22. package/components/u-badge/u-badge.vue +171 -0
  23. package/components/u-button/nvue.scss +46 -0
  24. package/components/u-button/props.js +161 -0
  25. package/components/u-button/u-button.vue +495 -0
  26. package/components/u-button/vue.scss +80 -0
  27. package/components/u-calendar/header.vue +99 -0
  28. package/components/u-calendar/month.vue +579 -0
  29. package/components/u-calendar/props.js +144 -0
  30. package/components/u-calendar/u-calendar.vue +384 -0
  31. package/components/u-calendar/util.js +85 -0
  32. package/components/u-car-keyboard/props.js +14 -0
  33. package/components/u-car-keyboard/u-car-keyboard.vue +311 -0
  34. package/components/u-cell/props.js +110 -0
  35. package/components/u-cell/u-cell.vue +229 -0
  36. package/components/u-cell-group/props.js +14 -0
  37. package/components/u-cell-group/u-cell-group.vue +61 -0
  38. package/components/u-checkbox/props.js +69 -0
  39. package/components/u-checkbox/u-checkbox.vue +344 -0
  40. package/components/u-checkbox-group/props.js +82 -0
  41. package/components/u-checkbox-group/u-checkbox-group.vue +103 -0
  42. package/components/u-circle-progress/props.js +8 -0
  43. package/components/u-circle-progress/u-circle-progress.vue +198 -0
  44. package/components/u-code/props.js +34 -0
  45. package/components/u-code/u-code.vue +129 -0
  46. package/components/u-code-input/props.js +79 -0
  47. package/components/u-code-input/u-code-input.vue +252 -0
  48. package/components/u-col/props.js +29 -0
  49. package/components/u-col/u-col.vue +162 -0
  50. package/components/u-collapse/props.js +19 -0
  51. package/components/u-collapse/u-collapse.vue +90 -0
  52. package/components/u-collapse-item/props.js +59 -0
  53. package/components/u-collapse-item/u-collapse-item.vue +225 -0
  54. package/components/u-column-notice/props.js +55 -0
  55. package/components/u-column-notice/u-column-notice.vue +160 -0
  56. package/components/u-count-down/props.js +24 -0
  57. package/components/u-count-down/u-count-down.vue +163 -0
  58. package/components/u-count-down/utils.js +62 -0
  59. package/components/u-count-to/props.js +59 -0
  60. package/components/u-count-to/u-count-to.vue +184 -0
  61. package/components/u-datetime-picker/props.js +120 -0
  62. package/components/u-datetime-picker/u-datetime-picker.vue +361 -0
  63. package/components/u-divider/props.js +44 -0
  64. package/components/u-divider/u-divider.vue +116 -0
  65. package/components/u-dropdown/props.js +65 -0
  66. package/components/u-dropdown/u-dropdown.vue +127 -0
  67. package/components/u-dropdown-item/props.js +36 -0
  68. package/components/u-dropdown-item/u-dropdown-item.vue +127 -0
  69. package/components/u-empty/props.js +59 -0
  70. package/components/u-empty/u-empty.vue +128 -0
  71. package/components/u-form/props.js +45 -0
  72. package/components/u-form/u-form.vue +214 -0
  73. package/components/u-form-item/props.js +48 -0
  74. package/components/u-form-item/u-form-item.vue +235 -0
  75. package/components/u-gap/props.js +24 -0
  76. package/components/u-gap/u-gap.vue +38 -0
  77. package/components/u-grid/props.js +19 -0
  78. package/components/u-grid/u-grid.vue +97 -0
  79. package/components/u-grid-item/props.js +14 -0
  80. package/components/u-grid-item/u-grid-item.vue +209 -0
  81. package/components/u-icon/icons.js +214 -0
  82. package/components/u-icon/props.js +89 -0
  83. package/components/u-icon/u-icon.vue +237 -0
  84. package/components/u-image/props.js +84 -0
  85. package/components/u-image/u-image.vue +232 -0
  86. package/components/u-index-anchor/props.js +29 -0
  87. package/components/u-index-anchor/u-index-anchor.vue +91 -0
  88. package/components/u-index-item/props.js +5 -0
  89. package/components/u-index-item/u-index-item.vue +87 -0
  90. package/components/u-index-list/props.js +29 -0
  91. package/components/u-index-list/u-index-list.vue +440 -0
  92. package/components/u-input/props.js +187 -0
  93. package/components/u-input/u-input.vue +369 -0
  94. package/components/u-keyboard/props.js +84 -0
  95. package/components/u-keyboard/u-keyboard.vue +164 -0
  96. package/components/u-line/props.js +33 -0
  97. package/components/u-line/u-line.vue +62 -0
  98. package/components/u-line-progress/props.js +28 -0
  99. package/components/u-line-progress/u-line-progress.vue +144 -0
  100. package/components/u-link/props.js +39 -0
  101. package/components/u-link/u-link.vue +83 -0
  102. package/components/u-list/props.js +76 -0
  103. package/components/u-list/u-list.vue +157 -0
  104. package/components/u-list-item/props.js +9 -0
  105. package/components/u-list-item/u-list-item.vue +116 -0
  106. package/components/u-loading-icon/props.js +59 -0
  107. package/components/u-loading-icon/u-loading-icon.vue +343 -0
  108. package/components/u-loading-page/props.js +49 -0
  109. package/components/u-loading-page/u-loading-page.vue +115 -0
  110. package/components/u-loadmore/props.js +94 -0
  111. package/components/u-loadmore/u-loadmore.vue +150 -0
  112. package/components/u-modal/props.js +89 -0
  113. package/components/u-modal/u-modal.vue +228 -0
  114. package/components/u-navbar/props.js +84 -0
  115. package/components/u-navbar/u-navbar.vue +186 -0
  116. package/components/u-no-network/props.js +19 -0
  117. package/components/u-no-network/u-no-network.vue +220 -0
  118. package/components/u-notice-bar/props.js +70 -0
  119. package/components/u-notice-bar/u-notice-bar.vue +101 -0
  120. package/components/u-notify/props.js +49 -0
  121. package/components/u-notify/u-notify.vue +211 -0
  122. package/components/u-number-box/props.js +109 -0
  123. package/components/u-number-box/u-number-box.vue +416 -0
  124. package/components/u-number-keyboard/props.js +19 -0
  125. package/components/u-number-keyboard/u-number-keyboard.vue +196 -0
  126. package/components/u-overlay/props.js +24 -0
  127. package/components/u-overlay/u-overlay.vue +68 -0
  128. package/components/u-parse/node/node.vue +499 -0
  129. package/components/u-parse/parser.js +1075 -0
  130. package/components/u-parse/props.js +45 -0
  131. package/components/u-parse/u-parse.vue +366 -0
  132. package/components/u-picker/props.js +79 -0
  133. package/components/u-picker/u-picker.vue +286 -0
  134. package/components/u-picker-column/props.js +5 -0
  135. package/components/u-picker-column/u-picker-column.vue +27 -0
  136. package/components/u-popup/props.js +79 -0
  137. package/components/u-popup/u-popup.vue +304 -0
  138. package/components/u-radio/props.js +64 -0
  139. package/components/u-radio/u-radio.vue +339 -0
  140. package/components/u-radio-group/props.js +85 -0
  141. package/components/u-radio-group/u-radio-group.vue +108 -0
  142. package/components/u-rate/props.js +69 -0
  143. package/components/u-rate/u-rate.vue +306 -0
  144. package/components/u-read-more/props.js +61 -0
  145. package/components/u-read-more/u-read-more.vue +157 -0
  146. package/components/u-row/props.js +19 -0
  147. package/components/u-row/u-row.vue +93 -0
  148. package/components/u-row-notice/props.js +39 -0
  149. package/components/u-row-notice/u-row-notice.vue +330 -0
  150. package/components/u-safe-bottom/props.js +5 -0
  151. package/components/u-safe-bottom/u-safe-bottom.vue +56 -0
  152. package/components/u-scroll-list/nvue.js +28 -0
  153. package/components/u-scroll-list/other.js +0 -0
  154. package/components/u-scroll-list/props.js +34 -0
  155. package/components/u-scroll-list/scrollWxs.wxs +50 -0
  156. package/components/u-scroll-list/u-scroll-list.vue +224 -0
  157. package/components/u-search/props.js +118 -0
  158. package/components/u-search/u-search.vue +303 -0
  159. package/components/u-skeleton/props.js +59 -0
  160. package/components/u-skeleton/u-skeleton.vue +244 -0
  161. package/components/u-slider/mpother.js +113 -0
  162. package/components/u-slider/mpwxs.js +42 -0
  163. package/components/u-slider/mpwxs.wxs +121 -0
  164. package/components/u-slider/nvue - /345/211/257/346/234/254.js" +180 -0
  165. package/components/u-slider/nvue.js +193 -0
  166. package/components/u-slider/props.js +54 -0
  167. package/components/u-slider/u-slider.vue +55 -0
  168. package/components/u-status-bar/props.js +8 -0
  169. package/components/u-status-bar/u-status-bar.vue +46 -0
  170. package/components/u-steps/props.js +39 -0
  171. package/components/u-steps/u-steps.vue +80 -0
  172. package/components/u-steps-item/props.js +24 -0
  173. package/components/u-steps-item/u-steps-item.vue +316 -0
  174. package/components/u-sticky/props.js +40 -0
  175. package/components/u-sticky/u-sticky.vue +212 -0
  176. package/components/u-subsection/props.js +49 -0
  177. package/components/u-subsection/u-subsection.vue +299 -0
  178. package/components/u-swipe-action/props.js +9 -0
  179. package/components/u-swipe-action/u-swipe-action.vue +67 -0
  180. package/components/u-swipe-action-item/index - backup.wxs +256 -0
  181. package/components/u-swipe-action-item/index.wxs +225 -0
  182. package/components/u-swipe-action-item/nvue - backup.js +270 -0
  183. package/components/u-swipe-action-item/nvue.js +174 -0
  184. package/components/u-swipe-action-item/props.js +41 -0
  185. package/components/u-swipe-action-item/u-swipe-action-item.vue +190 -0
  186. package/components/u-swipe-action-item/wxs.js +15 -0
  187. package/components/u-swiper/props.js +125 -0
  188. package/components/u-swiper/u-swiper.vue +255 -0
  189. package/components/u-swiper-indicator/props.js +29 -0
  190. package/components/u-swiper-indicator/u-swiper-indicator.vue +110 -0
  191. package/components/u-switch/props.js +54 -0
  192. package/components/u-switch/u-switch.vue +177 -0
  193. package/components/u-tabbar/props.js +44 -0
  194. package/components/u-tabbar/u-tabbar.vue +141 -0
  195. package/components/u-tabbar-item/props.js +35 -0
  196. package/components/u-tabbar-item/u-tabbar-item.vue +142 -0
  197. package/components/u-table/props.js +5 -0
  198. package/components/u-table/u-table.vue +29 -0
  199. package/components/u-tabs/props.js +64 -0
  200. package/components/u-tabs/u-tabs.vue +363 -0
  201. package/components/u-tabs-item/props.js +5 -0
  202. package/components/u-tabs-item/u-tabs-item.vue +29 -0
  203. package/components/u-tag/props.js +84 -0
  204. package/components/u-tag/u-tag.vue +358 -0
  205. package/components/u-td/props.js +5 -0
  206. package/components/u-td/u-td.vue +31 -0
  207. package/components/u-text/props.js +110 -0
  208. package/components/u-text/u-text.vue +223 -0
  209. package/components/u-text/value.js +85 -0
  210. package/components/u-textarea/props.js +119 -0
  211. package/components/u-textarea/u-textarea.vue +239 -0
  212. package/components/u-toast/u-toast.vue +291 -0
  213. package/components/u-toolbar/props.js +34 -0
  214. package/components/u-toolbar/u-toolbar.vue +102 -0
  215. package/components/u-tooltip/clipboard.min.js +58 -0
  216. package/components/u-tooltip/props.js +59 -0
  217. package/components/u-tooltip/u-tooltip.vue +366 -0
  218. package/components/u-tr/props.js +5 -0
  219. package/components/u-tr/u-tr.vue +31 -0
  220. package/components/u-transition/nvue.ani-map.js +68 -0
  221. package/components/u-transition/props.js +24 -0
  222. package/components/u-transition/transition.js +157 -0
  223. package/components/u-transition/u-transition.vue +92 -0
  224. package/components/u-transition/vue.ani-style.scss +113 -0
  225. package/components/u-upload/mixin.js +21 -0
  226. package/components/u-upload/props.js +124 -0
  227. package/components/u-upload/u-upload.vue +566 -0
  228. package/components/u-upload/utils.js +151 -0
  229. package/components/uview-ui/uview-ui.vue +15 -0
  230. package/index.js +79 -0
  231. package/index.scss +23 -0
  232. package/libs/config/color.js +17 -0
  233. package/libs/config/config.js +34 -0
  234. package/libs/config/props/actionSheet.js +25 -0
  235. package/libs/config/props/album.js +25 -0
  236. package/libs/config/props/alert.js +22 -0
  237. package/libs/config/props/avatar.js +28 -0
  238. package/libs/config/props/avatarGroup.js +23 -0
  239. package/libs/config/props/backtop.js +27 -0
  240. package/libs/config/props/badge.js +27 -0
  241. package/libs/config/props/button.js +42 -0
  242. package/libs/config/props/calendar.js +42 -0
  243. package/libs/config/props/carKeyboard.js +15 -0
  244. package/libs/config/props/cell.js +35 -0
  245. package/libs/config/props/cellGroup.js +17 -0
  246. package/libs/config/props/checkbox.js +27 -0
  247. package/libs/config/props/checkboxGroup.js +29 -0
  248. package/libs/config/props/circleProgress.js +15 -0
  249. package/libs/config/props/code.js +21 -0
  250. package/libs/config/props/codeInput.js +29 -0
  251. package/libs/config/props/col.js +19 -0
  252. package/libs/config/props/collapse.js +17 -0
  253. package/libs/config/props/collapseItem.js +25 -0
  254. package/libs/config/props/columnNotice.js +24 -0
  255. package/libs/config/props/countDown.js +18 -0
  256. package/libs/config/props/countTo.js +25 -0
  257. package/libs/config/props/datetimePicker.js +37 -0
  258. package/libs/config/props/divider.js +23 -0
  259. package/libs/config/props/empty.js +26 -0
  260. package/libs/config/props/form.js +22 -0
  261. package/libs/config/props/formItem.js +23 -0
  262. package/libs/config/props/gap.js +19 -0
  263. package/libs/config/props/grid.js +17 -0
  264. package/libs/config/props/gridItem.js +16 -0
  265. package/libs/config/props/icon.js +36 -0
  266. package/libs/config/props/image.js +30 -0
  267. package/libs/config/props/indexAnchor.js +19 -0
  268. package/libs/config/props/indexList.js +19 -0
  269. package/libs/config/props/input.js +48 -0
  270. package/libs/config/props/keyboard.js +30 -0
  271. package/libs/config/props/line.js +20 -0
  272. package/libs/config/props/lineProgress.js +19 -0
  273. package/libs/config/props/link.js +26 -0
  274. package/libs/config/props/list.js +28 -0
  275. package/libs/config/props/listItem.js +15 -0
  276. package/libs/config/props/loadingIcon.js +30 -0
  277. package/libs/config/props/loadingPage.js +23 -0
  278. package/libs/config/props/loadmore.js +32 -0
  279. package/libs/config/props/modal.js +31 -0
  280. package/libs/config/props/navbar.js +32 -0
  281. package/libs/config/props/noNetwork.js +18 -0
  282. package/libs/config/props/noticeBar.js +27 -0
  283. package/libs/config/props/notify.js +22 -0
  284. package/libs/config/props/numberBox.js +35 -0
  285. package/libs/config/props/numberKeyboard.js +17 -0
  286. package/libs/config/props/overlay.js +18 -0
  287. package/libs/config/props/parse.js +22 -0
  288. package/libs/config/props/picker.js +29 -0
  289. package/libs/config/props/popup.js +29 -0
  290. package/libs/config/props/radio.js +27 -0
  291. package/libs/config/props/radioGroup.js +30 -0
  292. package/libs/config/props/rate.js +26 -0
  293. package/libs/config/props/readMore.js +22 -0
  294. package/libs/config/props/row.js +17 -0
  295. package/libs/config/props/rowNotice.js +21 -0
  296. package/libs/config/props/scrollList.js +20 -0
  297. package/libs/config/props/search.js +37 -0
  298. package/libs/config/props/section.js +24 -0
  299. package/libs/config/props/skeleton.js +25 -0
  300. package/libs/config/props/slider.js +25 -0
  301. package/libs/config/props/statusBar.js +15 -0
  302. package/libs/config/props/steps.js +21 -0
  303. package/libs/config/props/stepsItem.js +18 -0
  304. package/libs/config/props/sticky.js +20 -0
  305. package/libs/config/props/subsection.js +23 -0
  306. package/libs/config/props/swipeAction.js +15 -0
  307. package/libs/config/props/swipeActionItem.js +21 -0
  308. package/libs/config/props/swiper.js +39 -0
  309. package/libs/config/props/swipterIndicator.js +19 -0
  310. package/libs/config/props/switch.js +24 -0
  311. package/libs/config/props/tabbar.js +22 -0
  312. package/libs/config/props/tabbarItem.js +20 -0
  313. package/libs/config/props/tabs.js +32 -0
  314. package/libs/config/props/tag.js +29 -0
  315. package/libs/config/props/text.js +38 -0
  316. package/libs/config/props/textarea.js +36 -0
  317. package/libs/config/props/toast.js +30 -0
  318. package/libs/config/props/toolbar.js +21 -0
  319. package/libs/config/props/tooltip.js +25 -0
  320. package/libs/config/props/transition.js +18 -0
  321. package/libs/config/props/upload.js +36 -0
  322. package/libs/config/props.js +190 -0
  323. package/libs/config/zIndex.js +20 -0
  324. package/libs/css/color.scss +155 -0
  325. package/libs/css/common.scss +97 -0
  326. package/libs/css/components.scss +15 -0
  327. package/libs/css/flex.scss +257 -0
  328. package/libs/css/h5.scss +0 -0
  329. package/libs/css/mixin.scss +8 -0
  330. package/libs/css/mp.scss +0 -0
  331. package/libs/css/nvue.scss +0 -0
  332. package/libs/css/vue.scss +27 -0
  333. package/libs/function/colorGradient.js +134 -0
  334. package/libs/function/debounce.js +29 -0
  335. package/libs/function/digit.js +167 -0
  336. package/libs/function/index.js +731 -0
  337. package/libs/function/platform.js +75 -0
  338. package/libs/function/test.js +288 -0
  339. package/libs/function/throttle.js +30 -0
  340. package/libs/luch-request/adapters/index.js +97 -0
  341. package/libs/luch-request/core/InterceptorManager.js +50 -0
  342. package/libs/luch-request/core/Request.js +198 -0
  343. package/libs/luch-request/core/buildFullPath.js +20 -0
  344. package/libs/luch-request/core/defaults.js +29 -0
  345. package/libs/luch-request/core/dispatchRequest.js +3 -0
  346. package/libs/luch-request/core/mergeConfig.js +103 -0
  347. package/libs/luch-request/core/settle.js +16 -0
  348. package/libs/luch-request/helpers/buildURL.js +69 -0
  349. package/libs/luch-request/helpers/combineURLs.js +14 -0
  350. package/libs/luch-request/helpers/isAbsoluteURL.js +14 -0
  351. package/libs/luch-request/index.d.ts +116 -0
  352. package/libs/luch-request/index.js +3 -0
  353. package/libs/luch-request/utils/clone.js +264 -0
  354. package/libs/luch-request/utils.js +131 -0
  355. package/libs/mixin/button.js +13 -0
  356. package/libs/mixin/mixin.js +160 -0
  357. package/libs/mixin/mpMixin.js +8 -0
  358. package/libs/mixin/mpShare.js +13 -0
  359. package/libs/mixin/openType.js +25 -0
  360. package/libs/mixin/style.js +228 -0
  361. package/libs/mixin/touch.js +59 -0
  362. package/libs/util/async-validator.js +1343 -0
  363. package/libs/util/calendar.js +546 -0
  364. package/libs/util/dayjs.js +308 -0
  365. package/libs/util/emitter.js +51 -0
  366. package/libs/util/route.js +124 -0
  367. package/package.json +83 -0
  368. package/theme.scss +44 -0
@@ -0,0 +1,1075 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * @fileoverview html 解析器
5
+ */
6
+ // 配置
7
+ const config = {
8
+ // 信任的标签(保持标签名不变)
9
+ 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'),
10
+ // 块级标签(转为 div,其他的非信任标签转为 span)
11
+ blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
12
+ // 要移除的标签
13
+ ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
14
+ // 自闭合的标签
15
+ voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
16
+ // html 实体
17
+ entities: {
18
+ lt: '<',
19
+ gt: '>',
20
+ quot: '"',
21
+ apos: "'",
22
+ ensp: '\u2002',
23
+ emsp: '\u2003',
24
+ nbsp: '\xA0',
25
+ semi: ';',
26
+ ndash: '–',
27
+ mdash: '—',
28
+ middot: '·',
29
+ lsquo: '‘',
30
+ rsquo: '’',
31
+ ldquo: '“',
32
+ rdquo: '”',
33
+ bull: '•',
34
+ hellip: '…'
35
+ },
36
+ // 默认的标签样式
37
+ tagStyle: {
38
+ // #ifndef APP-PLUS-NVUE
39
+ address: 'font-style:italic',
40
+ big: 'display:inline;font-size:1.2em',
41
+ caption: 'display:table-caption;text-align:center',
42
+ center: 'text-align:center',
43
+ cite: 'font-style:italic',
44
+ dd: 'margin-left:40px',
45
+ mark: 'background-color:yellow',
46
+ pre: 'font-family:monospace;white-space:pre',
47
+ s: 'text-decoration:line-through',
48
+ small: 'display:inline;font-size:0.8em',
49
+ u: 'text-decoration:underline' // #endif
50
+
51
+ }
52
+ }
53
+ const { windowWidth } = uni.getSystemInfoSync()
54
+ const blankChar = makeMap(' ,\r,\n,\t,\f')
55
+ let idIndex = 0 // #ifdef H5 || APP-PLUS
56
+
57
+ config.ignoreTags.iframe = void 0
58
+ config.trustTags.iframe = true
59
+ config.ignoreTags.embed = void 0
60
+ config.trustTags.embed = true // #endif
61
+ // #ifdef APP-PLUS-NVUE
62
+
63
+ config.ignoreTags.source = void 0
64
+ config.ignoreTags.style = void 0 // #endif
65
+
66
+ /**
67
+ * @description 创建 map
68
+ * @param {String} str 逗号分隔
69
+ */
70
+
71
+ function makeMap(str) {
72
+ const map = Object.create(null)
73
+ const list = str.split(',')
74
+
75
+ for (let i = list.length; i--;) {
76
+ map[list[i]] = true
77
+ }
78
+
79
+ return map
80
+ }
81
+ /**
82
+ * @description 解码 html 实体
83
+ * @param {String} str 要解码的字符串
84
+ * @param {Boolean} amp 要不要解码 &amp;
85
+ * @returns {String} 解码后的字符串
86
+ */
87
+
88
+ function decodeEntity(str, amp) {
89
+ let i = str.indexOf('&')
90
+
91
+ while (i != -1) {
92
+ const j = str.indexOf(';', i + 3)
93
+ let code = void 0
94
+ if (j == -1) break
95
+
96
+ if (str[i + 1] == '#') {
97
+ // &#123; 形式的实体
98
+ code = parseInt((str[i + 2] == 'x' ? '0' : '') + str.substring(i + 2, j))
99
+ if (!isNaN(code)) str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1)
100
+ } else {
101
+ // &nbsp; 形式的实体
102
+ code = str.substring(i + 1, j)
103
+ if (config.entities[code] || code == 'amp' && amp) str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1)
104
+ }
105
+
106
+ i = str.indexOf('&', i + 1)
107
+ }
108
+
109
+ return str
110
+ }
111
+ /**
112
+ * @description html 解析器
113
+ * @param {Object} vm 组件实例
114
+ */
115
+
116
+ function parser(vm) {
117
+ this.options = vm || {}
118
+ this.tagStyle = Object.assign(config.tagStyle, this.options.tagStyle)
119
+ this.imgList = vm.imgList || []
120
+ this.plugins = vm.plugins || []
121
+ this.attrs = Object.create(null)
122
+ this.stack = []
123
+ this.nodes = []
124
+ }
125
+ /**
126
+ * @description 执行解析
127
+ * @param {String} content 要解析的文本
128
+ */
129
+
130
+ parser.prototype.parse = function (content) {
131
+ // 插件处理
132
+ for (let i = this.plugins.length; i--;) {
133
+ if (this.plugins[i].onUpdate) content = this.plugins[i].onUpdate(content, config) || content
134
+ }
135
+
136
+ new lexer(this).parse(content) // 出栈未闭合的标签
137
+
138
+ while (this.stack.length) {
139
+ this.popNode()
140
+ }
141
+
142
+ return this.nodes
143
+ }
144
+ /**
145
+ * @description 将标签暴露出来(不被 rich-text 包含)
146
+ */
147
+
148
+ parser.prototype.expose = function () {
149
+ // #ifndef APP-PLUS-NVUE
150
+ for (let i = this.stack.length; i--;) {
151
+ const item = this.stack[i]
152
+ if (item.name == 'a' || item.c) return
153
+ item.c = 1
154
+ } // #endif
155
+ }
156
+ /**
157
+ * @description 处理插件
158
+ * @param {Object} node 要处理的标签
159
+ * @returns {Boolean} 是否要移除此标签
160
+ */
161
+
162
+ parser.prototype.hook = function (node) {
163
+ for (let i = this.plugins.length; i--;) {
164
+ if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) == false) return false
165
+ }
166
+
167
+ return true
168
+ }
169
+ /**
170
+ * @description 将链接拼接上主域名
171
+ * @param {String} url 需要拼接的链接
172
+ * @returns {String} 拼接后的链接
173
+ */
174
+
175
+ parser.prototype.getUrl = function (url) {
176
+ const { domain } = this.options
177
+
178
+ if (url[0] == '/') {
179
+ // // 开头的补充协议名
180
+ if (url[1] == '/') url = `${domain ? domain.split('://')[0] : 'http'}:${url}` // 否则补充整个域名
181
+ else if (domain) url = domain + url
182
+ } else if (domain && !url.includes('data:') && !url.includes('://')) url = `${domain}/${url}`
183
+
184
+ return url
185
+ }
186
+ /**
187
+ * @description 解析样式表
188
+ * @param {Object} node 标签
189
+ * @returns {Object}
190
+ */
191
+
192
+ parser.prototype.parseStyle = function (node) {
193
+ const { attrs } = node
194
+ const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
195
+ const styleObj = {}
196
+ let tmp = ''
197
+
198
+ if (attrs.id) {
199
+ // 暴露锚点
200
+ if (this.options.useAnchor) this.expose(); else if (node.name != 'img' && node.name != 'a' && node.name != 'video' && node.name != 'audio') attrs.id = void 0
201
+ } // 转换 width 和 height 属性
202
+
203
+ if (attrs.width) {
204
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
205
+ attrs.width = void 0
206
+ }
207
+
208
+ if (attrs.height) {
209
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
210
+ attrs.height = void 0
211
+ }
212
+
213
+ for (let i = 0, len = list.length; i < len; i++) {
214
+ const info = list[i].split(':')
215
+ if (info.length < 2) continue
216
+ const key = info.shift().trim().toLowerCase()
217
+ let value = info.join(':').trim() // 兼容性的 css 不压缩
218
+
219
+ if (value[0] == '-' && value.lastIndexOf('-') > 0 || value.includes('safe')) tmp += ';'.concat(key, ':').concat(value) // 重复的样式进行覆盖
220
+ else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
221
+ // 填充链接
222
+ if (value.includes('url')) {
223
+ let j = value.indexOf('(') + 1
224
+
225
+ if (j) {
226
+ while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) {
227
+ j++
228
+ }
229
+
230
+ value = value.substr(0, j) + this.getUrl(value.substr(j))
231
+ }
232
+ } // 转换 rpx(rich-text 内部不支持 rpx)
233
+ else if (value.includes('rpx')) {
234
+ value = value.replace(/[0-9.]+\s*rpx/g, ($) => `${parseFloat($) * windowWidth / 750}px`)
235
+ }
236
+
237
+ styleObj[key] = value
238
+ }
239
+ }
240
+
241
+ node.attrs.style = tmp
242
+ return styleObj
243
+ }
244
+ /**
245
+ * @description 解析到标签名
246
+ * @param {String} name 标签名
247
+ * @private
248
+ */
249
+
250
+ parser.prototype.onTagName = function (name) {
251
+ this.tagName = this.xml ? name : name.toLowerCase()
252
+ if (this.tagName == 'svg') this.xml = true // svg 标签内大小写敏感
253
+ }
254
+ /**
255
+ * @description 解析到属性名
256
+ * @param {String} name 属性名
257
+ * @private
258
+ */
259
+
260
+ parser.prototype.onAttrName = function (name) {
261
+ name = this.xml ? name : name.toLowerCase()
262
+
263
+ if (name.substr(0, 5) == 'data-') {
264
+ // data-src 自动转为 src
265
+ if (name == 'data-src' && !this.attrs.src) this.attrName = 'src' // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
266
+ else if (this.tagName == 'img' || this.tagName == 'a') this.attrName = name // 剩余的移除以减小大小
267
+ else this.attrName = void 0
268
+ } else {
269
+ this.attrName = name
270
+ this.attrs[name] = 'T' // boolean 型属性缺省设置
271
+ }
272
+ }
273
+ /**
274
+ * @description 解析到属性值
275
+ * @param {String} val 属性值
276
+ * @private
277
+ */
278
+
279
+ parser.prototype.onAttrVal = function (val) {
280
+ const name = this.attrName || '' // 部分属性进行实体解码
281
+
282
+ if (name == 'style' || name == 'href') this.attrs[name] = decodeEntity(val, true) // 拼接主域名
283
+ else if (name.includes('src')) this.attrs[name] = this.getUrl(decodeEntity(val, true)); else if (name) this.attrs[name] = val
284
+ }
285
+ /**
286
+ * @description 解析到标签开始
287
+ * @param {Boolean} selfClose 是否有自闭合标识 />
288
+ * @private
289
+ */
290
+
291
+ parser.prototype.onOpenTag = function (selfClose) {
292
+ // 拼装 node
293
+ const node = Object.create(null)
294
+ node.name = this.tagName
295
+ node.attrs = this.attrs
296
+ this.attrs = Object.create(null)
297
+ const { attrs } = node
298
+ const parent = this.stack[this.stack.length - 1]
299
+ const siblings = parent ? parent.children : this.nodes
300
+ const close = this.xml ? selfClose : config.voidTags[node.name] // 转换 embed 标签
301
+
302
+ if (node.name == 'embed') {
303
+ // #ifndef H5 || APP-PLUS
304
+ const src = attrs.src || '' // 按照后缀名和 type 将 embed 转为 video 或 audio
305
+
306
+ if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) node.name = 'video'; else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) node.name = 'audio'
307
+ if (attrs.autostart) attrs.autoplay = 'T'
308
+ attrs.controls = 'T' // #endif
309
+ // #ifdef H5 || APP-PLUS
310
+
311
+ this.expose() // #endif
312
+ } // #ifndef APP-PLUS-NVUE
313
+ // 处理音视频
314
+
315
+ if (node.name == 'video' || node.name == 'audio') {
316
+ // 设置 id 以便获取 context
317
+ if (node.name == 'video' && !attrs.id) attrs.id = `v${idIndex++}` // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
318
+
319
+ if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T' // 用数组存储所有可用的 source
320
+
321
+ node.src = []
322
+
323
+ if (attrs.src) {
324
+ node.src.push(attrs.src)
325
+ attrs.src = void 0
326
+ }
327
+
328
+ this.expose()
329
+ } // #endif
330
+ // 处理自闭合标签
331
+
332
+ if (close) {
333
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
334
+ // 通过 base 标签设置主域名
335
+ if (node.name == 'base' && !this.options.domain) this.options.domain = attrs.href // #ifndef APP-PLUS-NVUE
336
+ // 设置 source 标签(仅父节点为 video 或 audio 时有效)
337
+ else if (node.name == 'source' && parent && (parent.name == 'video' || parent.name == 'audio') && attrs.src) parent.src.push(attrs.src) // #endif
338
+
339
+ return
340
+ } // 解析 style
341
+
342
+ const styleObj = this.parseStyle(node) // 处理图片
343
+
344
+ if (node.name == 'img') {
345
+ if (attrs.src) {
346
+ // 标记 webp
347
+ if (attrs.src.includes('webp')) node.webp = 'T' // data url 图片如果没有设置 original-src 默认为不可预览的小图片
348
+
349
+ if (attrs.src.includes('data:') && !attrs['original-src']) attrs.ignore = 'T'
350
+
351
+ if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
352
+ for (let i = this.stack.length; i--;) {
353
+ const item = this.stack[i]
354
+
355
+ if (item.name == 'a') {
356
+ node.a = item.attrs
357
+ break
358
+ } // #ifndef H5 || APP-PLUS
359
+
360
+ const style = item.attrs.style || ''
361
+
362
+ if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || !styleObj.width.includes('%'))) {
363
+ styleObj.width = '100% !important'
364
+ styleObj.height = ''
365
+
366
+ for (let j = i + 1; j < this.stack.length; j++) {
367
+ this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
368
+ }
369
+ } else if (style.includes('flex') && styleObj.width == '100%') {
370
+ for (let _j = i + 1; _j < this.stack.length; _j++) {
371
+ const _style = this.stack[_j].attrs.style || ''
372
+
373
+ if (!_style.includes(';width') && !_style.includes(' width') && _style.indexOf('width') != 0) {
374
+ styleObj.width = ''
375
+ break
376
+ }
377
+ }
378
+ } else if (style.includes('inline-block')) {
379
+ if (styleObj.width && styleObj.width[styleObj.width.length - 1] == '%') {
380
+ item.attrs.style += `;max-width:${styleObj.width}`
381
+ styleObj.width = ''
382
+ } else item.attrs.style += ';max-width:100%'
383
+ } // #endif
384
+
385
+ item.c = 1
386
+ }
387
+
388
+ attrs.i = this.imgList.length.toString()
389
+
390
+ let _src = attrs['original-src'] || attrs.src // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
391
+
392
+ if (this.imgList.includes(_src)) {
393
+ // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
394
+ let _i = _src.indexOf('://')
395
+
396
+ if (_i != -1) {
397
+ _i += 3
398
+
399
+ let newSrc = _src.substr(0, _i)
400
+
401
+ for (; _i < _src.length; _i++) {
402
+ if (_src[_i] == '/') break
403
+ newSrc += Math.random() > 0.5 ? _src[_i].toUpperCase() : _src[_i]
404
+ }
405
+
406
+ newSrc += _src.substr(_i)
407
+ _src = newSrc
408
+ }
409
+ } // #endif
410
+
411
+ this.imgList.push(_src) // #ifdef H5 || APP-PLUS
412
+
413
+ if (this.options.lazyLoad) {
414
+ attrs['data-src'] = attrs.src
415
+ attrs.src = void 0
416
+ } // #endif
417
+ }
418
+ }
419
+
420
+ if (styleObj.display == 'inline') styleObj.display = '' // #ifndef APP-PLUS-NVUE
421
+
422
+ if (attrs.ignore) {
423
+ styleObj['max-width'] = styleObj['max-width'] || '100%'
424
+ attrs.style += ';-webkit-touch-callout:none'
425
+ } // #endif
426
+ // 设置的宽度超出屏幕,为避免变形,高度转为自动
427
+
428
+ if (parseInt(styleObj.width) > windowWidth) styleObj.height = void 0 // 记录是否设置了宽高
429
+
430
+ if (styleObj.width) {
431
+ if (styleObj.width.includes('auto')) styleObj.width = ''; else {
432
+ node.w = 'T'
433
+ if (styleObj.height && !styleObj.height.includes('auto')) node.h = 'T'
434
+ }
435
+ }
436
+ } else if (node.name == 'svg') {
437
+ siblings.push(node)
438
+ this.stack.push(node)
439
+ this.popNode()
440
+ return
441
+ }
442
+
443
+ for (const key in styleObj) {
444
+ if (styleObj[key]) attrs.style += ';'.concat(key, ':').concat(styleObj[key].replace(' !important', ''))
445
+ }
446
+
447
+ attrs.style = attrs.style.substr(1) || void 0
448
+ } else {
449
+ if (node.name == 'pre' || (attrs.style || '').includes('white-space') && attrs.style.includes('pre')) this.pre = node.pre = true
450
+ node.children = []
451
+ this.stack.push(node)
452
+ } // 加入节点树
453
+
454
+ siblings.push(node)
455
+ }
456
+ /**
457
+ * @description 解析到标签结束
458
+ * @param {String} name 标签名
459
+ * @private
460
+ */
461
+
462
+ parser.prototype.onCloseTag = function (name) {
463
+ // 依次出栈到匹配为止
464
+ name = this.xml ? name : name.toLowerCase()
465
+ let i
466
+
467
+ for (i = this.stack.length; i--;) {
468
+ if (this.stack[i].name == name) break
469
+ }
470
+
471
+ if (i != -1) {
472
+ while (this.stack.length > i) {
473
+ this.popNode()
474
+ }
475
+ } else if (name == 'p' || name == 'br') {
476
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
477
+ siblings.push({
478
+ name,
479
+ attrs: {}
480
+ })
481
+ }
482
+ }
483
+ /**
484
+ * @description 处理标签出栈
485
+ * @private
486
+ */
487
+
488
+ parser.prototype.popNode = function () {
489
+ const node = this.stack.pop()
490
+ let { attrs } = node
491
+ const { children } = node
492
+ const parent = this.stack[this.stack.length - 1]
493
+ const siblings = parent ? parent.children : this.nodes
494
+
495
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
496
+ // 获取标题
497
+ if (node.name == 'title' && children.length && children[0].type == 'text' && this.options.setTitle) {
498
+ uni.setNavigationBarTitle({
499
+ title: children[0].text
500
+ })
501
+ }
502
+ siblings.pop()
503
+ return
504
+ }
505
+
506
+ if (node.pre) {
507
+ // 是否合并空白符标识
508
+ node.pre = this.pre = void 0
509
+
510
+ for (let i = this.stack.length; i--;) {
511
+ if (this.stack[i].pre) this.pre = true
512
+ }
513
+ }
514
+
515
+ const styleObj = {} // 转换 svg
516
+
517
+ if (node.name == 'svg') {
518
+ // #ifndef APP-PLUS-NVUE
519
+ let src = ''
520
+ const { style } = attrs
521
+ attrs.style = ''
522
+ attrs.xmlns = 'http://www.w3.org/2000/svg';
523
+
524
+ (function traversal(node) {
525
+ src += `<${node.name}`
526
+
527
+ for (let item in node.attrs) {
528
+ const val = node.attrs[item]
529
+
530
+ if (val) {
531
+ if (item == 'viewbox') item = 'viewBox'
532
+ src += ' '.concat(item, '="').concat(val, '"')
533
+ }
534
+ }
535
+
536
+ if (!node.children) src += '/>'; else {
537
+ src += '>'
538
+
539
+ for (let _i2 = 0; _i2 < node.children.length; _i2++) {
540
+ traversal(node.children[_i2])
541
+ }
542
+
543
+ src += `</${node.name}>`
544
+ }
545
+ }(node))
546
+
547
+ node.name = 'img'
548
+ node.attrs = {
549
+ src: `data:image/svg+xml;utf8,${src.replace(/#/g, '%23')}`,
550
+ style,
551
+ ignore: 'T'
552
+ }
553
+ node.children = void 0 // #endif
554
+
555
+ this.xml = false
556
+ return
557
+ } // #ifndef APP-PLUS-NVUE
558
+ // 转换 align 属性
559
+
560
+ if (attrs.align) {
561
+ if (node.name == 'table') {
562
+ if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'; else styleObj.float = attrs.align
563
+ } else styleObj['text-align'] = attrs.align
564
+
565
+ attrs.align = void 0
566
+ } // 转换 font 标签的属性
567
+
568
+ if (node.name == 'font') {
569
+ if (attrs.color) {
570
+ styleObj.color = attrs.color
571
+ attrs.color = void 0
572
+ }
573
+
574
+ if (attrs.face) {
575
+ styleObj['font-family'] = attrs.face
576
+ attrs.face = void 0
577
+ }
578
+
579
+ if (attrs.size) {
580
+ let size = parseInt(attrs.size)
581
+
582
+ if (!isNaN(size)) {
583
+ if (size < 1) size = 1; else if (size > 7) size = 7
584
+ styleObj['font-size'] = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'][size - 1]
585
+ }
586
+
587
+ attrs.size = void 0
588
+ }
589
+ } // #endif
590
+ // 一些编辑器的自带 class
591
+
592
+ if ((attrs.class || '').includes('align-center')) styleObj['text-align'] = 'center'
593
+ Object.assign(styleObj, this.parseStyle(node))
594
+
595
+ if (parseInt(styleObj.width) > windowWidth) {
596
+ styleObj['max-width'] = '100%'
597
+ styleObj['box-sizing'] = 'border-box'
598
+ } // #ifndef APP-PLUS-NVUE
599
+
600
+ if (config.blockTags[node.name]) node.name = 'div' // 未知标签转为 span,避免无法显示
601
+ else if (!config.trustTags[node.name] && !this.xml) node.name = 'span'
602
+ if (node.name == 'a' || node.name == 'ad' // #ifdef H5 || APP-PLUS
603
+ || node.name == 'iframe' // #endif
604
+ ) this.expose() // #ifdef APP-PLUS
605
+ else if (node.name == 'video') {
606
+ let str = '<video style="width:100%;height:100%"' // 空白图占位
607
+
608
+ if (!attrs.poster && !attrs.autoplay) attrs.poster = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'/>"
609
+
610
+ for (const item in attrs) {
611
+ if (attrs[item]) str += ` ${item}="${attrs[item]}"`
612
+ }
613
+
614
+ if (this.options.pauseVideo) str += ' onplay="for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"'
615
+ str += '>'
616
+
617
+ for (let _i3 = 0; _i3 < node.src.length; _i3++) {
618
+ str += `<source src="${node.src[_i3]}">`
619
+ }
620
+
621
+ str += '</video>'
622
+ node.html = str
623
+ } // #endif
624
+ // 列表处理
625
+ else if ((node.name == 'ul' || node.name == 'ol') && node.c) {
626
+ const types = {
627
+ a: 'lower-alpha',
628
+ A: 'upper-alpha',
629
+ i: 'lower-roman',
630
+ I: 'upper-roman'
631
+ }
632
+
633
+ if (types[attrs.type]) {
634
+ attrs.style += `;list-style-type:${types[attrs.type]}`
635
+ attrs.type = void 0
636
+ }
637
+
638
+ for (let _i4 = children.length; _i4--;) {
639
+ if (children[_i4].name == 'li') children[_i4].c = 1
640
+ }
641
+ } // 表格处理
642
+ else if (node.name == 'table') {
643
+ // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
644
+ let padding = parseFloat(attrs.cellpadding)
645
+ let spacing = parseFloat(attrs.cellspacing)
646
+ const border = parseFloat(attrs.border)
647
+
648
+ if (node.c) {
649
+ // padding 和 spacing 默认 2
650
+ if (isNaN(padding)) padding = 2
651
+ if (isNaN(spacing)) spacing = 2
652
+ }
653
+
654
+ if (border) attrs.style += `;border:${border}px solid gray`
655
+
656
+ if (node.flag && node.c) {
657
+ // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
658
+ styleObj.display = 'grid'
659
+
660
+ if (spacing) {
661
+ styleObj['grid-gap'] = `${spacing}px`
662
+ styleObj.padding = `${spacing}px`
663
+ } // 无间隔的情况下避免边框重叠
664
+ else if (border) attrs.style += ';border-left:0;border-top:0'
665
+
666
+ const width = []
667
+ // 表格的列宽
668
+ const trList = []
669
+ // tr 列表
670
+ const cells = []
671
+ // 保存新的单元格
672
+ const map = {}; // 被合并单元格占用的格子
673
+
674
+ (function traversal(nodes) {
675
+ for (let _i5 = 0; _i5 < nodes.length; _i5++) {
676
+ if (nodes[_i5].name == 'tr') trList.push(nodes[_i5]); else traversal(nodes[_i5].children || [])
677
+ }
678
+ }(children))
679
+
680
+ for (let row = 1; row <= trList.length; row++) {
681
+ let col = 1
682
+
683
+ for (let j = 0; j < trList[row - 1].children.length; j++, col++) {
684
+ const td = trList[row - 1].children[j]
685
+
686
+ if (td.name == 'td' || td.name == 'th') {
687
+ // 这个格子被上面的单元格占用,则列号++
688
+ while (map[`${row}.${col}`]) {
689
+ col++
690
+ }
691
+
692
+ let _style2 = td.attrs.style || ''
693
+ const start = _style2.indexOf('width') ? _style2.indexOf(';width') : 0 // 提取出 td 的宽度
694
+
695
+ if (start != -1) {
696
+ let end = _style2.indexOf(';', start + 6)
697
+
698
+ if (end == -1) end = _style2.length
699
+ if (!td.attrs.colspan) width[col] = _style2.substring(start ? start + 7 : 6, end)
700
+ _style2 = _style2.substr(0, start) + _style2.substr(end)
701
+ }
702
+
703
+ _style2 += (border ? ';border:'.concat(border, 'px solid gray') + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? ';padding:'.concat(padding, 'px') : '') // 处理列合并
704
+
705
+ if (td.attrs.colspan) {
706
+ _style2 += ';grid-column-start:'.concat(col, ';grid-column-end:').concat(col + parseInt(td.attrs.colspan))
707
+ if (!td.attrs.rowspan) _style2 += ';grid-row-start:'.concat(row, ';grid-row-end:').concat(row + 1)
708
+ col += parseInt(td.attrs.colspan) - 1
709
+ } // 处理行合并
710
+
711
+ if (td.attrs.rowspan) {
712
+ _style2 += ';grid-row-start:'.concat(row, ';grid-row-end:').concat(row + parseInt(td.attrs.rowspan))
713
+ if (!td.attrs.colspan) _style2 += ';grid-column-start:'.concat(col, ';grid-column-end:').concat(col + 1) // 记录下方单元格被占用
714
+
715
+ for (let k = 1; k < td.attrs.rowspan; k++) {
716
+ map[`${row + k}.${col}`] = 1
717
+ }
718
+ }
719
+
720
+ if (_style2) td.attrs.style = _style2
721
+ cells.push(td)
722
+ }
723
+ }
724
+
725
+ if (row == 1) {
726
+ let temp = ''
727
+
728
+ for (let _i6 = 1; _i6 < col; _i6++) {
729
+ temp += `${width[_i6] ? width[_i6] : 'auto'} `
730
+ }
731
+
732
+ styleObj['grid-template-columns'] = temp
733
+ }
734
+ }
735
+
736
+ node.children = cells
737
+ } else {
738
+ // 没有使用合并单元格的表格通过 table 布局实现
739
+ if (node.c) styleObj.display = 'table'
740
+ if (!isNaN(spacing)) styleObj['border-spacing'] = `${spacing}px`
741
+
742
+ if (border || padding) {
743
+ // 遍历
744
+ (function traversal(nodes) {
745
+ for (let _i7 = 0; _i7 < nodes.length; _i7++) {
746
+ const _td = nodes[_i7]
747
+
748
+ if (_td.name == 'th' || _td.name == 'td') {
749
+ if (border) _td.attrs.style = 'border:'.concat(border, 'px solid gray;').concat(_td.attrs.style || '')
750
+ if (padding) _td.attrs.style = 'padding:'.concat(padding, 'px;').concat(_td.attrs.style || '')
751
+ } else if (_td.children) traversal(_td.children)
752
+ }
753
+ }(children))
754
+ }
755
+ } // 给表格添加一个单独的横向滚动层
756
+
757
+ if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
758
+ const table = { ...node }
759
+ node.name = 'div'
760
+ node.attrs = {
761
+ style: 'overflow:auto'
762
+ }
763
+ node.children = [table]
764
+ attrs = table.attrs
765
+ }
766
+ } else if ((node.name == 'td' || node.name == 'th') && (attrs.colspan || attrs.rowspan)) {
767
+ for (let _i8 = this.stack.length; _i8--;) {
768
+ if (this.stack[_i8].name == 'table') {
769
+ this.stack[_i8].flag = 1 // 指示含有合并单元格
770
+
771
+ break
772
+ }
773
+ }
774
+ } // 转换 ruby
775
+ else if (node.name == 'ruby') {
776
+ node.name = 'span'
777
+
778
+ for (let _i9 = 0; _i9 < children.length - 1; _i9++) {
779
+ if (children[_i9].type == 'text' && children[_i9 + 1].name == 'rt') {
780
+ children[_i9] = {
781
+ name: 'div',
782
+ attrs: {
783
+ style: 'display:inline-block'
784
+ },
785
+ children: [{
786
+ name: 'div',
787
+ attrs: {
788
+ style: 'font-size:50%;text-align:start'
789
+ },
790
+ children: children[_i9 + 1].children
791
+ }, children[_i9]]
792
+ }
793
+ children.splice(_i9 + 1, 1)
794
+ }
795
+ }
796
+ } else if (node.c) {
797
+ node.c = 2
798
+
799
+ for (let _i10 = node.children.length; _i10--;) {
800
+ if (!node.children[_i10].c || node.children[_i10].name == 'table') node.c = 1
801
+ }
802
+ }
803
+ if ((styleObj.display || '').includes('flex') && !node.c) {
804
+ for (let _i11 = children.length; _i11--;) {
805
+ const _item = children[_i11]
806
+
807
+ if (_item.f) {
808
+ _item.attrs.style = (_item.attrs.style || '') + _item.f
809
+ _item.f = void 0
810
+ }
811
+ }
812
+ } // flex 布局时部分样式需要提取到 rich-text 外层
813
+
814
+ const flex = parent && (parent.attrs.style || '').includes('flex') // #ifdef MP-WEIXIN
815
+ // 检查基础库版本 virtualHost 是否可用
816
+ && !(node.c && wx.getNFCAdapter) // #endif
817
+ // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
818
+ && !node.c // #endif
819
+
820
+ if (flex) node.f = ';max-width:100%' // #endif
821
+
822
+ for (const key in styleObj) {
823
+ if (styleObj[key]) {
824
+ const val = ';'.concat(key, ':').concat(styleObj[key].replace(' !important', '')) // #ifndef APP-PLUS-NVUE
825
+
826
+ if (flex && (key.includes('flex') && key != 'flex-direction' || key == 'align-self' || styleObj[key][0] == '-' || key == 'width' && val.includes('%'))) {
827
+ node.f += val
828
+ if (key == 'width') attrs.style += ';width:100%'
829
+ } else // #endif
830
+ { attrs.style += val }
831
+ }
832
+ }
833
+
834
+ attrs.style = attrs.style.substr(1) || void 0
835
+ }
836
+ /**
837
+ * @description 解析到文本
838
+ * @param {String} text 文本内容
839
+ */
840
+
841
+ parser.prototype.onText = function (text) {
842
+ if (!this.pre) {
843
+ // 合并空白符
844
+ let trim = ''
845
+ let flag
846
+
847
+ for (let i = 0, len = text.length; i < len; i++) {
848
+ if (!blankChar[text[i]]) trim += text[i]; else {
849
+ if (trim[trim.length - 1] != ' ') trim += ' '
850
+ if (text[i] == '\n' && !flag) flag = true
851
+ }
852
+ } // 去除含有换行符的空串
853
+
854
+ if (trim == ' ' && flag) return
855
+ text = trim
856
+ }
857
+
858
+ const node = Object.create(null)
859
+ node.type = 'text'
860
+ node.text = decodeEntity(text)
861
+
862
+ if (this.hook(node)) {
863
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
864
+ siblings.push(node)
865
+ }
866
+ }
867
+ /**
868
+ * @description html 词法分析器
869
+ * @param {Object} handler 高层处理器
870
+ */
871
+
872
+ function lexer(handler) {
873
+ this.handler = handler
874
+ }
875
+ /**
876
+ * @description 执行解析
877
+ * @param {String} content 要解析的文本
878
+ */
879
+
880
+ lexer.prototype.parse = function (content) {
881
+ this.content = content || ''
882
+ this.i = 0 // 标记解析位置
883
+
884
+ this.start = 0 // 标记一个单词的开始位置
885
+
886
+ this.state = this.text // 当前状态
887
+
888
+ for (let len = this.content.length; this.i != -1 && this.i < len;) {
889
+ this.state()
890
+ }
891
+ }
892
+ /**
893
+ * @description 检查标签是否闭合
894
+ * @param {String} method 如果闭合要进行的操作
895
+ * @returns {Boolean} 是否闭合
896
+ * @private
897
+ */
898
+
899
+ lexer.prototype.checkClose = function (method) {
900
+ const selfClose = this.content[this.i] == '/'
901
+
902
+ if (this.content[this.i] == '>' || selfClose && this.content[this.i + 1] == '>') {
903
+ if (method) this.handler[method](this.content.substring(this.start, this.i))
904
+ this.i += selfClose ? 2 : 1
905
+ this.start = this.i
906
+ this.handler.onOpenTag(selfClose)
907
+
908
+ if (this.handler.tagName == 'script') {
909
+ this.i = this.content.indexOf('</', this.i)
910
+
911
+ if (this.i != -1) {
912
+ this.i += 2
913
+ this.start = this.i
914
+ }
915
+
916
+ this.state = this.endTag
917
+ } else this.state = this.text
918
+
919
+ return true
920
+ }
921
+
922
+ return false
923
+ }
924
+ /**
925
+ * @description 文本状态
926
+ * @private
927
+ */
928
+
929
+ lexer.prototype.text = function () {
930
+ this.i = this.content.indexOf('<', this.i) // 查找最近的标签
931
+
932
+ if (this.i == -1) {
933
+ // 没有标签了
934
+ if (this.start < this.content.length) this.handler.onText(this.content.substring(this.start, this.content.length))
935
+ return
936
+ }
937
+
938
+ const c = this.content[this.i + 1]
939
+
940
+ if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
941
+ // 标签开头
942
+ if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i))
943
+ this.start = ++this.i
944
+ this.state = this.tagName
945
+ } else if (c == '/' || c == '!' || c == '?') {
946
+ if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i))
947
+ const next = this.content[this.i + 2]
948
+
949
+ if (c == '/' && (next >= 'a' && next <= 'z' || next >= 'A' && next <= 'Z')) {
950
+ // 标签结尾
951
+ this.i += 2
952
+ this.start = this.i
953
+ return this.state = this.endTag
954
+ } // 处理注释
955
+
956
+ let end = '-->'
957
+ if (c != '!' || this.content[this.i + 2] != '-' || this.content[this.i + 3] != '-') end = '>'
958
+ this.i = this.content.indexOf(end, this.i)
959
+
960
+ if (this.i != -1) {
961
+ this.i += end.length
962
+ this.start = this.i
963
+ }
964
+ } else this.i++
965
+ }
966
+ /**
967
+ * @description 标签名状态
968
+ * @private
969
+ */
970
+
971
+ lexer.prototype.tagName = function () {
972
+ if (blankChar[this.content[this.i]]) {
973
+ // 解析到标签名
974
+ this.handler.onTagName(this.content.substring(this.start, this.i))
975
+
976
+ while (blankChar[this.content[++this.i]]) {
977
+
978
+ }
979
+
980
+ if (this.i < this.content.length && !this.checkClose()) {
981
+ this.start = this.i
982
+ this.state = this.attrName
983
+ }
984
+ } else if (!this.checkClose('onTagName')) this.i++
985
+ }
986
+ /**
987
+ * @description 属性名状态
988
+ * @private
989
+ */
990
+
991
+ lexer.prototype.attrName = function () {
992
+ let c = this.content[this.i]
993
+
994
+ if (blankChar[c] || c == '=') {
995
+ // 解析到属性名
996
+ this.handler.onAttrName(this.content.substring(this.start, this.i))
997
+ let needVal = c == '='
998
+ const len = this.content.length
999
+
1000
+ while (++this.i < len) {
1001
+ c = this.content[this.i]
1002
+
1003
+ if (!blankChar[c]) {
1004
+ if (this.checkClose()) return
1005
+
1006
+ if (needVal) {
1007
+ // 等号后遇到第一个非空字符
1008
+ this.start = this.i
1009
+ return this.state = this.attrVal
1010
+ }
1011
+
1012
+ if (this.content[this.i] == '=') needVal = true; else {
1013
+ this.start = this.i
1014
+ return this.state = this.attrName
1015
+ }
1016
+ }
1017
+ }
1018
+ } else if (!this.checkClose('onAttrName')) this.i++
1019
+ }
1020
+ /**
1021
+ * @description 属性值状态
1022
+ * @private
1023
+ */
1024
+
1025
+ lexer.prototype.attrVal = function () {
1026
+ const c = this.content[this.i]
1027
+ const len = this.content.length // 有冒号的属性
1028
+
1029
+ if (c == '"' || c == "'") {
1030
+ this.start = ++this.i
1031
+ this.i = this.content.indexOf(c, this.i)
1032
+ if (this.i == -1) return
1033
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
1034
+ } // 没有冒号的属性
1035
+ else {
1036
+ for (; this.i < len; this.i++) {
1037
+ if (blankChar[this.content[this.i]]) {
1038
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
1039
+ break
1040
+ } else if (this.checkClose('onAttrVal')) return
1041
+ }
1042
+ }
1043
+
1044
+ while (blankChar[this.content[++this.i]]) {
1045
+
1046
+ }
1047
+
1048
+ if (this.i < len && !this.checkClose()) {
1049
+ this.start = this.i
1050
+ this.state = this.attrName
1051
+ }
1052
+ }
1053
+ /**
1054
+ * @description 结束标签状态
1055
+ * @returns {String} 结束的标签名
1056
+ * @private
1057
+ */
1058
+
1059
+ lexer.prototype.endTag = function () {
1060
+ const c = this.content[this.i]
1061
+
1062
+ if (blankChar[c] || c == '>' || c == '/') {
1063
+ this.handler.onCloseTag(this.content.substring(this.start, this.i))
1064
+
1065
+ if (c != '>') {
1066
+ this.i = this.content.indexOf('>', this.i)
1067
+ if (this.i == -1) return
1068
+ }
1069
+
1070
+ this.start = ++this.i
1071
+ this.state = this.text
1072
+ } else this.i++
1073
+ }
1074
+
1075
+ module.exports = parser