Текстовый редактор для ТамТам
Минималистичный текстовый редактор и парсер текста, оптимизированный для небольших (5—10 КБ) сообщений.
Основные возможности:
- Парсинг эмоджи
☺️ и текстовых смайлов :) - Парсинг e-mail и ссылок с учётом структуры предложения. Например, в «Ты был на tamtam.chat?» и «Заходи на tamtam.chat?a=b» правильно определяет принадлежность
?ссылке. - Частичное соответствие RFC1738 для парсинга ссылок, можно использовать как валидатор URL.
- Префиксные токены:
@mention,#hashtag,/command. - Форматирование фрагментов текста (жирный, курсив, и т.д.).
- Ограниченная поддержка Markdown.
- Маленький: весь редактор весит всего 18 КБ (min/brotli).
- Быстрый: написан с учётом особенностей оптимизаций современных JS VM для мгновенной обработки текста.
Выполняем стандартную установку через npm:
npm install @tamtam-chat/message-editorМодуль можно использовать в качестве полноценного текстового редактора небольших сообщений, а также в качестве парсера статического текста.
Для подключения редактора надо сделать следующее:
import { Editor } from '@tamtam-chat/message-editor';
// Указатель на контейнер, который нужно сделать редактируемым
const elem = document.getElementById('editor');
const editor = new Editor(elem, {
value: 'Hello world! 😇'
});
// Можно слушать события на изменение выделения и текста редактора
editor.on('editor-selectionchange', () => {
console.log('selection changed:', editor.getSelection())
});
editor.on('editor-update', () => {
console.log('content updated:', editor.model)
});Класс Editor создаёт JS-обёртку над переданным DOM-элементом и добавляет ему функциональность редактора. С помощью полученного объекта можно управлять содержимым редактора, прослушивать события жизненного цикла и т.д.
Вторым аргументом в конструктор Editor можно передать объект с опциями редактора:
value— значение редактора по умолчанию.parse— параметры для парсера (см. ниже).shortcuts— объект, где ключом является сочетание клавиш, а значением – функция, которая выполняет действие на вызов указанного сочетания.resetFormatOnNewline— еслиtrue, при вставке перевода строки будет автоматически сбрасываться форматирование.emoji— функция отрисовки эмоджи.
Пример:
const editor = new Editor(document.getElementById('editor'), {
value: 'Hello world!',
shortcuts: {
'Cmd-Shift-B': (ed, evt) => {
ed.setValue('test');
}
}
})В редактор встроен механизм для обработки клавиатурных сочетаний. Как правило, это какой-то печатный символ и модификаторы: Shift, Alt, Ctrl, Meta, Cmd.
Если используется модификатор Cmd, на macOS он будет означать клавишу Command ⌘, а на Windows/Linux — Ctrl.
Пример допустимых сочетаний: Cmd-Alt-V, Ctrl+B, Enter.
Модуль также можно использовать и в качестве парсера статического текста: например, если в тексте вам нужно разметить эмоджи и/или ссылки. Так как кодовая база оптимизирована для tree-shaking, при использовании модуля как парсера, код редактора не будет добавлен в финальный бандл.
import { parse } from '@tamtam-chat/message-editor';
const tokens = parse('test 🥳 tamtam.chat');Функция возвращает плоский массив токенов (см. ниже описание модели парсера). В качестве второго аргумента можно передать объект со следующими параметрами парсера:
markdown— использовать markdown-символы для разметки. На данный момент поддерживаются следующие конструкции:*жирный*,_курсив_,~перечёркнутый~, `код`,[текст ссылки](http://example.com).textEmoji— находить текстовые смайлы в указанной строке и добавить им эмоджи-представления.hashtag— размечать#hashtags.mention— размечать@mention.command— размечать/command.link— находить и размечать ссылки в тексте.
Модель, в котором хранится внутреннее представление текста, представляет из себя плоский массив токенов. Токен – это единица данных текста. Объект, который содержит как минимум следующие поля:
type(string): тип токена.value(string): значение токена, фрагмент оригинальной строки.format(number): битовая маска с текущим форматированием токена.emoji(array): опциональное свойство, если не пустое — это означает, что вvalueесть эмоджи или текстовые смайлы. Массив объектов вида{ from: 1, to: 3 }где поляfromиtoуказывают на диапазон символа эмоджи внутриvalue. Если в этом объекте содержится полеemoji— значит, диапазон указывает на текстовый смайл, а полеemojiсодержит его эмоджи-представление.
Если склеить все значения поля value массива токенов, мы получим оригинальную строку:
import { parse } from '@tamtam-chat/message-editor';
const text = 'a :) 😇 b'
const tokens = parse(text, { textEmoji: true });
console.log(text === tokens.map(t => t.value).join('')); // trueТаким образом, поле value всегда содержит оригинальный текст, а замена эмоджи и текстовых смайлов выполняется только при отрисовке.
В зависимости от типа type, в объекте токена могут содержаться дополнительные свойства:
text— обычный текстовый токен.link— ссылка, абсолютный URL содержится в полеlink. Также есть полеauto, которое указывает, что ссылка была автоматически разпознана в тексте (true) или пользователь указал ссылку самостоятельно (false).mention– упоминание вида@username.hashtag– хэштэг вида#hashtag.command– команда вида/command.
Все события работают как обычные DOM-события на указанном элементе-контейнере. На них можно подписаться как через стандартный elem.addEventListener(eventName, handler), так и через вспомогательную функцию editor.on(eventName, handler) редактора.
editor-selectionchange— изменилась позиция курсора или выделение в редакторе.editor-formatchange— изменилось форматирование на фрагменте текста.editor-update— изменилось содержимое редактора.