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