56 lines
2.6 KiB
TypeScript
56 lines
2.6 KiB
TypeScript
|
|
/**
|
||
|
|
* Токен кастомного эмодзи сервера (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}>`;
|
||
|
|
}
|