// markdown.js import hljs from 'highlight.js/lib/common' import MarkdownIt from 'markdown-it' import sanitizeHtml from 'sanitize-html' import { toast } from '../main' import { tiebaEmoji } from './tiebaEmoji' // 动态切换 hljs 主题(保持你原有逻辑) if (typeof window !== 'undefined') { const theme = document.documentElement.dataset.theme || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') if (theme === 'dark') { import('highlight.js/styles/atom-one-dark.css') } else { import('highlight.js/styles/atom-one-light.css') } } /** @section 自定义插件:@mention */ function mentionPlugin(md) { const mentionReg = /^@\[([^\]]+)\]/ function mention(state, silent) { const pos = state.pos if (state.src.charCodeAt(pos) !== 0x40) return false const match = mentionReg.exec(state.src.slice(pos)) if (!match) return false if (!silent) { const tokenOpen = state.push('link_open', 'a', 1) tokenOpen.attrs = [ ['href', `/users/${match[1]}`], ['target', '_blank'], ['class', 'mention-link'], ['rel', 'noopener noreferrer'], ] const text = state.push('text', '', 0) text.content = `@${match[1]}` state.push('link_close', 'a', -1) } state.pos += match[0].length return true } md.inline.ruler.before('emphasis', 'mention', mention) } /** @section 自定义插件:贴吧表情 :tieba123: */ function tiebaEmojiPlugin(md) { md.renderer.rules['tieba-emoji'] = (tokens, idx) => { const name = tokens[idx].content const file = tiebaEmoji[name] return `` } md.inline.ruler.before('emphasis', 'tieba-emoji', (state, silent) => { const pos = state.pos if (state.src.charCodeAt(pos) !== 0x3a) return false const match = state.src.slice(pos).match(/^:tieba(\d+):/) if (!match) return false const key = `tieba${match[1]}` if (!tiebaEmoji[key]) return false if (!silent) { const token = state.push('tieba-emoji', '', 0) token.content = key } state.pos += match[0].length return true }) } /** @section 链接外开 */ function linkPlugin(md) { const defaultRender = md.renderer.rules.link_open || function (tokens, idx, options, env, self) { return self.renderToken(tokens, idx, options) } md.renderer.rules.link_open = function (tokens, idx, options, env, self) { const token = tokens[idx] const hrefIndex = token.attrIndex('href') if (hrefIndex >= 0) { const href = token.attrs[hrefIndex][1] if (href.startsWith('http://') || href.startsWith('https://')) { token.attrPush(['target', '_blank']) token.attrPush(['rel', 'noopener noreferrer']) } } return defaultRender(tokens, idx, options, env, self) } } /** @section MarkdownIt 实例:开启 HTML,但配合强净化 */ const md = new MarkdownIt({ html: true, // ⭐ 允许行内 HTML(为