From 6a1b71de0fdd0b52b84457425e979f831086dbaf Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:59:08 +0800 Subject: [PATCH] feat: add tieba emoji support --- frontend/src/utils/markdown.js | 24 ++++++++++++++++++++++++ frontend/src/utils/tiebaEmoji.js | 10 ++++++++++ frontend/src/utils/vditor.js | 9 ++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 frontend/src/utils/tiebaEmoji.js diff --git a/frontend/src/utils/markdown.js b/frontend/src/utils/markdown.js index a3ed32ec7..579a6749c 100644 --- a/frontend/src/utils/markdown.js +++ b/frontend/src/utils/markdown.js @@ -2,6 +2,7 @@ import MarkdownIt from 'markdown-it' import hljs from 'highlight.js' import 'highlight.js/styles/github.css' import { toast } from '../main' +import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji' function mentionPlugin(md) { const mentionReg = /^@\[([^\]]+)\]/ @@ -27,6 +28,28 @@ function mentionPlugin(md) { md.inline.ruler.before('emphasis', 'mention', mention) } +function tiebaEmojiPlugin(md) { + md.renderer.rules['tieba-emoji'] = (tokens, idx) => { + const name = tokens[idx].content + const file = tiebaEmoji[name] + return `${name}` + } + 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 + }) +} + const md = new MarkdownIt({ html: false, linkify: true, @@ -43,6 +66,7 @@ const md = new MarkdownIt({ }) md.use(mentionPlugin) +md.use(tiebaEmojiPlugin) export function renderMarkdown(text) { return md.render(text || '') diff --git a/frontend/src/utils/tiebaEmoji.js b/frontend/src/utils/tiebaEmoji.js new file mode 100644 index 000000000..da413d0e9 --- /dev/null +++ b/frontend/src/utils/tiebaEmoji.js @@ -0,0 +1,10 @@ +export const TIEBA_EMOJI_CDN = 'https://cdn.jsdelivr.net/gh/microlong666/tieba_mobile_emotions@master/' + +export const tiebaEmoji = (() => { + const map = { tieba1: 'image_emoticon.png' } + for (let i = 2; i <= 124; i++) { + if (i > 50 && i < 62) continue + map[`tieba${i}`] = `image_emoticon${i}.png` + } + return map +})() diff --git a/frontend/src/utils/vditor.js b/frontend/src/utils/vditor.js index 2e9a2628c..a7fabe346 100644 --- a/frontend/src/utils/vditor.js +++ b/frontend/src/utils/vditor.js @@ -3,6 +3,7 @@ import 'vditor/dist/index.css' import { API_BASE_URL } from '../main' import { getToken, authState } from './auth' import { searchUsers, fetchFollowings, fetchAdmins } from './user' +import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji' export function getEditorTheme() { return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'classic' @@ -42,8 +43,14 @@ export function createVditor(editorId, options = {}) { placeholder, height: 'auto', theme: getEditorTheme(), - preview: Object.assign({ theme: { current: getPreviewTheme() } }, preview), + preview: Object.assign({ + theme: { current: getPreviewTheme() }, + customEmoji: tiebaEmoji, + emojiPath: TIEBA_EMOJI_CDN + }, preview), hint: { + emoji: tiebaEmoji, + emojiPath: TIEBA_EMOJI_CDN, extend: [ { key: '@',