(wip): add reactions
(qol): update todo
This commit is contained in:
parent
d57940d1b3
commit
7ba08090fe
20 changed files with 4533 additions and 5894 deletions
96
packages/markdown/src/emojiData.ts
Normal file
96
packages/markdown/src/emojiData.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import shortcodeData from "emojibase-data/en/shortcodes/joypixels.json";
|
||||
|
||||
type ShortcodeValue = string | string[];
|
||||
|
||||
export type EmojiDefinition = {
|
||||
aliases: readonly string[];
|
||||
hexcode: string;
|
||||
name: string;
|
||||
shortcode: string;
|
||||
};
|
||||
|
||||
function normalizeName(value: string) {
|
||||
return value
|
||||
.trim()
|
||||
.replace(/^:+|:+$/g, "")
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
export const emojis: readonly EmojiDefinition[] = Object.entries(
|
||||
shortcodeData as Record<string, ShortcodeValue>,
|
||||
).map(([hexcode, value]) => {
|
||||
const aliases = Array.isArray(value) ? value : [value];
|
||||
const name = aliases[0];
|
||||
|
||||
return {
|
||||
aliases,
|
||||
hexcode: hexcode.toLowerCase().replaceAll("_", "-"),
|
||||
name,
|
||||
shortcode: `:${name}:`,
|
||||
};
|
||||
});
|
||||
|
||||
const emojiByName = new Map<string, EmojiDefinition>();
|
||||
for (const emoji of emojis) {
|
||||
for (const alias of emoji.aliases) {
|
||||
emojiByName.set(normalizeName(alias), emoji);
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveEmoji(value: string): EmojiDefinition | undefined {
|
||||
return emojiByName.get(normalizeName(value));
|
||||
}
|
||||
|
||||
export function normalizeShortcode(value: string): string | undefined {
|
||||
return resolveEmoji(value)?.shortcode;
|
||||
}
|
||||
|
||||
export function findEmojiShortcodes(value: string) {
|
||||
const matches: Array<{
|
||||
emoji: EmojiDefinition;
|
||||
from: number;
|
||||
to: number;
|
||||
}> = [];
|
||||
let searchFrom = 0;
|
||||
|
||||
while (searchFrom < value.length) {
|
||||
const from = value.indexOf(":", searchFrom);
|
||||
if (from === -1) break;
|
||||
|
||||
const candidate = value.slice(from).match(/^:([a-z0-9_+-]+):/i);
|
||||
if (!candidate) {
|
||||
searchFrom = from + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const emoji = resolveEmoji(candidate[1]);
|
||||
if (!emoji) {
|
||||
// The closing colon may also open the next valid shortcode.
|
||||
searchFrom = from + candidate[0].length - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const to = from + candidate[0].length;
|
||||
matches.push({ emoji, from, to });
|
||||
searchFrom = to;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
export function searchEmojis(query: string): EmojiDefinition[] {
|
||||
const normalizedQuery = normalizeName(query);
|
||||
if (!normalizedQuery) return [...emojis];
|
||||
|
||||
return emojis
|
||||
.map((emoji) => {
|
||||
const names = emoji.aliases.map(normalizeName);
|
||||
const exact = names.includes(normalizedQuery);
|
||||
const prefix = names.some((name) => name.startsWith(normalizedQuery));
|
||||
const contains = names.some((name) => name.includes(normalizedQuery));
|
||||
return { emoji, rank: exact ? 0 : prefix ? 1 : contains ? 2 : 3 };
|
||||
})
|
||||
.filter(({ rank }) => rank < 3)
|
||||
.sort((a, b) => a.rank - b.rank || a.emoji.name.localeCompare(b.emoji.name))
|
||||
.map(({ emoji }) => emoji);
|
||||
}
|
||||
Loading…
Reference in a new issue