Текстовый редактор для ТамТам
Минималистичный текстовый редактор и парсер текста, оптимизированный для небольших (5—10 КБ) сообщений.
Основные возможности:
- Парсинг эмоджи
☺️ и текстовых смайлов :) - Парсинг e-mail и ссылок с учётом структуры предложения. Например, в «Ты был на tamtam.chat?» и «Заходи на tamtam.chat?a=b» правильно определяет принадлежность
?
ссылке. - Частичное соответствие RFC1738 для парсинга ссылок, можно использовать как валидатор URL.
- Префиксные токены:
@mention
,#hashtag
,/command
. - Форматирование фрагментов текста (жирный, курсив, и т.д.).
- Ограниченная поддержка Markdown.
- Маленький: весь редактор весит всего 18 КБ (min/brotli).
- Быстрый: написан с учётом особенностей оптимизаций современных JS VM для мгновенной обработки текста.
Так как собранный npm-пакет хранится в GitHub, для установки редактора сначала необходимо сделать файл .npmrc
в основной папке вашего проекта и добавить туда следующую строку:
@tamtam-chat:registry=https://npm.pkg.github.com
Затем выполняем стандартную установку:
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
— изменилось содержимое редактора.