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).
This commit is contained in:
Gusted 2025-08-10 22:44:01 +02:00
commit fe5f16205f
No known key found for this signature in database
GPG key ID: FD821B732837125F
3 changed files with 17 additions and 15 deletions

View file

@ -1,5 +1,6 @@
import {matchEmoji, matchMention} from '../../utils/match.js'; 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) { export function initTextExpander(expander) {
expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => { expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => {
@ -10,11 +11,16 @@ export function initTextExpander(expander) {
const ul = document.createElement('ul'); const ul = document.createElement('ul');
ul.classList.add('suggestions'); ul.classList.add('suggestions');
for (const name of matches) { for (const name of matches) {
const emoji = emojiString(name);
const li = document.createElement('li'); const li = document.createElement('li');
li.setAttribute('role', 'option'); li.setAttribute('role', 'option');
li.setAttribute('data-value', emoji); li.setAttribute('data-value', emojiString(name));
li.textContent = `${emoji} ${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); ul.append(li);
} }

View file

@ -10,6 +10,7 @@ for (const {emoji, aliases} of emojis) {
} }
export const emojiKeys = Object.keys(tempMap).sort((a, b) => { export const emojiKeys = Object.keys(tempMap).sort((a, b) => {
if (b === '+1' && a === '-1') return 1;
if (a === '+1' || a === '-1') return -1; if (a === '+1' || a === '-1') return -1;
if (b === '+1' || b === '-1') return 1; if (b === '+1' || b === '-1') return 1;
return a.localeCompare(b); return a.localeCompare(b);

View file

@ -1,4 +1,4 @@
import emojis from '../../../assets/emoji.json'; import {emojiKeys} from '../features/emoji.js';
const maxMatches = 6; const maxMatches = 6;
@ -9,19 +9,14 @@ function sortAndReduce(map) {
export function matchEmoji(queryText) { export function matchEmoji(queryText) {
const query = queryText.toLowerCase().replaceAll('_', ' '); 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 // results is a map of weights, lower is better
const results = new Map(); const results = new Map();
for (const {aliases} of emojis) { for (const emojiKey of emojiKeys) {
const mainAlias = aliases[0]; const index = emojiKey.replaceAll('_', ' ').indexOf(query);
for (const [aliasIndex, alias] of aliases.entries()) {
const index = alias.replaceAll('_', ' ').indexOf(query);
if (index === -1) continue; if (index === -1) continue;
const existing = results.get(mainAlias); results.set(emojiKey, index);
const rankedIndex = index + aliasIndex;
results.set(mainAlias, existing ? existing - rankedIndex : rankedIndex);
}
} }
return sortAndReduce(results); return sortAndReduce(results);