UNPKG

@tencentcloud/ai-desk-customer-uniapp

Version:

uni-app Vue2/Vue3 UIKit for AI Desk

63 lines (57 loc) 2.48 kB
import { marked } from '../../../../../../utils/lib-marked'; import Log from '../../../../../../utils/logger'; const rendererMD = new marked.Renderer(); rendererMD.image = (href, title, text) => { return ` <img src="${href}" alt="${text}" style="max-width: 100%;"> `; } rendererMD.link = (href, title, text) => { if (href) { // marked 库会把 & 默认转义成 &amp; 这里我们先还原再匹配,避免 url 异常 // 匹配以 http:// 或 https:// 开头,所有 URL 主体字符,遇到第一个非主体字符(如中文括号、空格、表情符号等)时停止 let ret = href.replace(/&amp;/g, '&').replace(/https?:\/\/[\w\-./?=&:#]+(?=[^\w\-./?=&:#]|$)/g, (matchedUrl) => { let isURLInText = false; if (matchedUrl !== href) { // 如果 text 里包含 url,我们就用 matchedUrl 作为 a 标签的值;否则用 text 作为值 isURLInText = true; } return `<a target="_blank" rel="noreferrer noopenner" class="message-marked_link" href="${matchedUrl || ''}" title="${title}">${isURLInText ? matchedUrl : text}</a>`; }); if (ret === href) { Log.w(`Unable to extract url, href:${href}`); } return ret; } return text; } rendererMD.paragraph = (text: string) => { if (text.startsWith('<video')) { const videoSrc = extractVideoSrc(text) || ''; if (videoSrc) { return `<video src="${videoSrc}" preload="auto" controls/>`; } } return `<p>${text}</p>`; } marked.setOptions({ gfm: false, breaks: true, pedantic: false, sanitize: false, smartLists: true, smartypants: false, }); export const extractVideoSrc = (text: string) => { const videoSrcRegex = /<video[^>]*src=["']([^"']*)["'][^>]*>/gi; const result = videoSrcRegex.exec(text); return result ? result[1] : null; } // uni-app 的 jscore 版本比较低,不支持 Unicode 属性 // marked 库v4.0起使用了 /\p{L}\p{N}/gu 等 Unicode 属性正则表达式,这些特性在 ES2018 引入,低版本 jscore 不支持,会报错 // 使用传统的正则代替,以规避问题 // uni-app android 不支持 marked v7.0.5 或更高版本(会白屏,uni-app ios 可以用,为了更好的兼容性,目前都用 marked v4.0) export const parseMarkdown = (text: string) => { // 不要手动替换,如把 \n\n 替换成 p 或者 <br/>,否则可能会导致Markdown结构被破坏,进而导致 bad case return marked.parse(text, { renderer: rendererMD }) };