tg-format
Боты для Telegram, использующие Telegram Bot API, могут использовать различные методы для отправки и редактирования сообщений – sendMessage
, sendPhoto
, editMessageText
и пр. Все эти методы поддерживают форматирование текста при помощи HTML разметки (используя параметр parse_mode
), либо вручную сформированным массивом размеченных сущностей entities
(или caption_entities
). Эта библиотека упрощает использование обоих способов разметки.
Установка
npm install tg-format
Форматирование при помощи HTML
Самый простой способ разметки — при помощи HTML-тегов. Однако при подстановке пользовательских данных в тело сообщения в них необходимо экранировать символы '<', '>' и '&'. Для этого доступна функция html
, которую предполагается использовать в tagged template literals:
const { html } = require('tgformat');
sendMessage({
text: html`Имя пользователя: <b>${user.firstName}</b> ${user.lastName}`,
parse_mode: 'HTML',
})
Она экранирует символы '<', '>' и '&' для всех подставляемых значений (заменяя их на '<', '>' и '&' соответственно):
const hackyName = 'foo</b> bar';
console.log(`Name: <b>${hackyName}</b>`);
console.log(html`Name: <b>${hackyName}</b>`);
Экранирование текста для разметки с помощью Markdown не поддерживается, так как следует более сложным (и контекстно-зависимым) правилам.
Форматирование при помощи массива entities
Более продвинутый способ создания форматированного текста — с помощью массива сущностей (который передаётся в параметре entities
или caption_entities
). Для этого используйте функцию fmt
:
const { fmt } = require('tgformat');
const formatted = fmt`Имя пользователя: ${[user.firstName, 'bold']} ${user.lastName}`;
sendMessage({
text: formatted.text,
entities: formatted.entities,
})
Чтобы разметить подставляемое значение, используйте массив из двух (или более) элементов: само значение и тип сущности ('bold' в примере выше для выделения текста жирным). Тип сущности можно передавать строкой либо объектом (например { type: 'text_link', url: 'https://telegram.org' }
). Если передать больше двух элементов, будет создано несколько сущностей: например ${[user.firstName, 'bold', 'italic']}
выведет имя полужирным курсивом.
Функция fmt
возвращает экземпляр класса FormattedString
, содержащий два поля: text
и entities
. Так как метод sendMessage
ожидает именно такие параметры, код выше можно записать лаконичнее при помощи оператора деструктуризации:
sendMessage({
...fmt`Имя пользователя: ${[user.firstName, 'bold']} ${user.lastName}`,
})
В случае с методами, ожидающими другие параметры (например, caption
и caption_entities
для sendPhoto
), можно использовать метод toObject
:
sendPhoto({
...fmt`Имя пользователя: ${[user.firstName, 'bold']} ${user.lastName}`.toObject('caption', 'caption_entities'),
})
Класс FormattedString
реализует многие методы класса String
. В данный момент только методы substring
и slice
возвращают новые экземпляры FormattedString
.
В особенности может быть полезен метод concat
, позволяющий конкатенировать с текущим объектом другие строки или экземпляры FormattedString
. Это немутирующий метод, создающий новый экземпляр FormattedString
. У него есть также мутирующий аналог append
(который изменяет текущий экземпляр). Незначительное отличие от метода concat
строк заключается в том, что массивы (любой вложенности), передаваемые как параметры, будут «распакованы» и их элементы будут конкатенированы без разделителей. Кроме того, непосредственно в конструктор FormattedString
может быть передано любое число параметров, которые будут аналогичным образом конкатенированы вместе.
Также доступен статический метод FormattedString.join(strings, separator)
, аналогичный методу join
у массивов, склеивающий элементы массива, используя указанный разделитель.
Объекты FormattedString
(или их массивы) можно использовать при подстановке в другие вызовы fmt
:
const formatted = fmt`Участники:\n${
users.map(user => fmt`\n${[
fmt`${[user.firstName, 'bold']} ${user.lastName}`,
{ type: 'text_link', url: user.website }
]}`)
}`;