From fe5f16205f2209899b68a711888968f08a5034f2 Mon Sep 17 00:00:00 2001 From: Gusted Date: Sun, 10 Aug 2025 22:44:01 +0200 Subject: [PATCH] feat: make text expander aware of custom emojis The old MDE editor is aware of custom emojis and shows them as suggestions, but the new text expander is not aware of them and seems to re-implement some logic. Simplify it by using what `emoji.js` already provides. Custom emojis require a bit more work to get shown correctly (HTML and adding a `gap` to fake a space). --- web_src/js/features/comp/TextExpander.js | 14 ++++++++++---- web_src/js/features/emoji.js | 1 + web_src/js/utils/match.js | 17 ++++++----------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/web_src/js/features/comp/TextExpander.js b/web_src/js/features/comp/TextExpander.js index 128a2ddff0..8777f3a334 100644 --- a/web_src/js/features/comp/TextExpander.js +++ b/web_src/js/features/comp/TextExpander.js @@ -1,5 +1,6 @@ import {matchEmoji, matchMention} from '../../utils/match.js'; -import {emojiString} from '../emoji.js'; +import {emojiHTML, emojiString} from '../emoji.js'; +const {customEmojis} = window.config; export function initTextExpander(expander) { expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => { @@ -10,11 +11,16 @@ export function initTextExpander(expander) { const ul = document.createElement('ul'); ul.classList.add('suggestions'); for (const name of matches) { - const emoji = emojiString(name); const li = document.createElement('li'); li.setAttribute('role', 'option'); - li.setAttribute('data-value', emoji); - li.textContent = `${emoji} ${name}`; + li.setAttribute('data-value', emojiString(name)); + if (customEmojis.has(name)) { + li.style.gap = '0.25rem'; + li.innerHTML = emojiHTML(name); + li.append(name); + } else { + li.textContent = `${emojiString(name)} ${name}`; + } ul.append(li); } diff --git a/web_src/js/features/emoji.js b/web_src/js/features/emoji.js index 76555bfe05..c7a23ecf0f 100644 --- a/web_src/js/features/emoji.js +++ b/web_src/js/features/emoji.js @@ -10,6 +10,7 @@ for (const {emoji, aliases} of emojis) { } export const emojiKeys = Object.keys(tempMap).sort((a, b) => { + if (b === '+1' && a === '-1') return 1; if (a === '+1' || a === '-1') return -1; if (b === '+1' || b === '-1') return 1; return a.localeCompare(b); diff --git a/web_src/js/utils/match.js b/web_src/js/utils/match.js index 17fdfed113..aa53ad1435 100644 --- a/web_src/js/utils/match.js +++ b/web_src/js/utils/match.js @@ -1,4 +1,4 @@ -import emojis from '../../../assets/emoji.json'; +import {emojiKeys} from '../features/emoji.js'; const maxMatches = 6; @@ -9,19 +9,14 @@ function sortAndReduce(map) { export function matchEmoji(queryText) { const query = queryText.toLowerCase().replaceAll('_', ' '); - if (!query) return emojis.slice(0, maxMatches).map((e) => e.aliases[0]); + if (!query) return emojiKeys.slice(0, maxMatches); // results is a map of weights, lower is better const results = new Map(); - for (const {aliases} of emojis) { - const mainAlias = aliases[0]; - for (const [aliasIndex, alias] of aliases.entries()) { - const index = alias.replaceAll('_', ' ').indexOf(query); - if (index === -1) continue; - const existing = results.get(mainAlias); - const rankedIndex = index + aliasIndex; - results.set(mainAlias, existing ? existing - rankedIndex : rankedIndex); - } + for (const emojiKey of emojiKeys) { + const index = emojiKey.replaceAll('_', ' ').indexOf(query); + if (index === -1) continue; + results.set(emojiKey, index); } return sortAndReduce(results);