Files
glchat/web/src/lib/customEmoji.ts
T

56 lines
2.6 KiB
TypeScript
Raw Normal View History

/**
* Токен кастомного эмодзи сервера (AGENT.md 7.12).
*
* В тексте сообщения и в реакции эмодзи едет токеном `<:имя:file_id>`
* (у анимированных — `<a:имя:file_id>`): имя разрешено только из латиницы,
* цифр и подчёркиваний, `file_id` — снежинка. Единое описание формата живёт
* здесь, чтобы разбор в разметке (`lib/markdown.ts`), подсказки композера и
* настройки сервера не расходились.
*/
/** Имя эмодзи: ровно то, что принимает сервер при загрузке и переименовании. */
export const CUSTOM_EMOJI_NAME_SOURCE = '[a-zA-Z0-9_]{2,32}';
/** Токен целиком без якорей — вставляется в общий шаблон разметки. */
export const CUSTOM_EMOJI_TOKEN_SOURCE = `<a?:${CUSTOM_EMOJI_NAME_SOURCE}:\\d+>`;
/** Проверка имени эмодзи на клиенте: до запроса, чтобы не гонять сервер. */
export const CUSTOM_EMOJI_NAME_PATTERN = new RegExp(`^${CUSTOM_EMOJI_NAME_SOURCE}$`, 'u');
const CUSTOM_EMOJI_TOKEN_PATTERN = new RegExp(
`^<(?<animated>a?):(?<name>${CUSTOM_EMOJI_NAME_SOURCE}):(?<fileId>\\d+)>$`,
'u',
);
/** Разобранный токен: имя, файл и признак анимации. */
export interface CustomEmojiToken {
name: string;
fileId: string;
animated: boolean;
}
/**
* Разбор токена. `null` — строка не является токеном эмодзи (битый или
* неизвестный формат): вызывающий код показывает её как обычный текст.
*/
export function parseCustomEmoji(raw: string): CustomEmojiToken | null {
const match = CUSTOM_EMOJI_TOKEN_PATTERN.exec(raw);
const groups = match?.groups;
const name = groups?.['name'];
const fileId = groups?.['fileId'];
if (name === undefined || fileId === undefined) {
return null;
}
return { name, fileId, animated: groups?.['animated'] === 'a' };
}
/** Короткий код эмодзи — то, что видит пользователь: `:имя:`. */
export function customEmojiShortcode(name: string): string {
return `:${name}:`;
}
/** Токен для вставки в текст сообщения или реакцию. */
export function customEmojiToken(name: string, fileId: string, animated = false): string {
return `<${animated ? 'a' : ''}:${name}:${fileId}>`;
}