Конфигурация
createEditor(config) принимает один объект конфигурации. Обязательны только holder и plugins. Rector сразу проверяет оба значения и выбрасывает TypeError, если контейнер не является HTMLElement или плагины переданы не массивом.
Полная форма конфигурации
interface EditorConfig {
holder: HTMLElement
plugins: BlockPlugin[]
inlineTools?: Array<string | InlineTool>
inlinePlugins?: InlinePlugin[]
data?: EditorDocument
migrations?: DocumentMigration[]
documentVersionPolicy?: 'preserve' | 'strict'
readOnly?: boolean
injectStyles?: boolean
placeholder?: string
autofocus?: boolean
minHeight?: number
defaultBlock?: string
locale?: Record<string, LocaleValue>
tuning?: DeepPartial<EditorTuning>
onChange?: (data: EditorDocument) => void
onReady?: () => void
validationMode?: 'preserve' | 'strict'
onValidationError?: (issue: BlockValidationIssue) => void
onDiagnostic?: (diagnostic: EditorDiagnostic) => void
diagnosticThresholds?: Partial<DiagnosticThresholds>
theme?: string
}Все параметры конфигурации
Ниже приведён полный публичный контракт EditorConfig. Если значение по умолчанию указано как «не задан», Rector не подключает скрытый обработчик или внешний сервис.
| Параметр | Обязателен | Значение по умолчанию | Назначение |
|---|---|---|---|
holder | да | — | Элемент HTMLElement, в который добавляется корень редактора. Один контейнер может принадлежать только одному работающему экземпляру. |
plugins | да | — | Созданные экземпляры блочных плагинов. Их уникальные значения type определяют, какие блоки редактор может загрузить, создать, преобразовать и сохранить. Требуется хотя бы один плагин. |
inlineTools | нет | все встроенные инструменты | Инструменты форматирования внутристрочной панели. Строки выбирают встроенные инструменты по type, объекты добавляют или заменяют реализации. Пустой массив отключает все глобальные внутристрочные инструменты. |
inlinePlugins | нет | [] | Постоянные виджеты внутри текста, например упоминания или образцы цвета. В отличие от форматирования их данные сохраняются в карте inline блока. |
data | нет | один пустой блок по умолчанию | Исходный версионированный документ. Rector копирует и нормализует его до передачи плагинам; последующее изменение объекта приложением не меняет редактор. |
migrations | нет | [] | Направленные синхронные миграции документа. Rector проходит связи from → to, пока не достигнет текущей версии формата. |
documentVersionPolicy | нет | 'preserve' | Поведение при неизвестной версии или неполной цепочке миграций. preserve применяет все доступные шаги и сохраняет последнюю достигнутую структурно корректную версию; strict требует полной цепочки и иначе выбрасывает исключение. |
readOnly | нет | false | Выбирает исходный режим. Пользовательские и плагинные элементы изменения отключаются, но разрешённые приложению методы документа остаются доступны. Позже режим меняется через editor.setReadOnly(). |
injectStyles | нет | true | Загружает базовые стили, темы и стили зарегистрированных блочных и inline-плагинов через <link> с подсчётом владельцев. Укажите false, если приложение импортирует CSS пакета через сборщик. |
placeholder | нет | значение из локали плагина | Заменяет подсказку блока по умолчанию, если плагин реализует setPlaceholder(). Пустая строка отключает эту подсказку. На подсказки других плагинов параметр не влияет. |
autofocus | нет | false | После успешного создания переводит фокус в первый редактируемый или фокусируемый элемент. В режиме только для чтения не действует. |
minHeight | нет | значение таблицы стилей | Задаёт корню редактора конечную неотрицательную минимальную высоту в пикселях CSS. Не передавайте параметр, если размером должна управлять таблица стилей. |
defaultBlock | нет | paragraph, иначе первый плагин | Зарегистрированный тип для пустого документа, новых блоков при нажатии Enter и замены, создаваемой после удаления последнего блока. |
locale | нет | встроенный английский словарь | Объединённый словарь ядра и плагинов. Для перевода всего встроенного интерфейса используйте готовую общую локаль; ключ __lang выбирает правила множественного числа. |
tuning | нет | DEFAULT_TUNING | Частичные изменения поведения перетаскивания, истории, уведомлений, панели блоков, анимаций и мобильной границы. Каждый вложенный параметр описан ниже. |
onChange | нет | не задан | Отложенное уведомление с отделённым сериализованным документом после зафиксированного изменения. Для исходного документа не вызывается. |
onReady | нет | не задан | Уведомление в микрозадаче после успешной сборки. Сам createEditor() уже синхронно возвращает готовый дескриптор. |
validationMode | нет | 'preserve' | Поведение, когда validate(data) зарегистрированного плагина возвращает false: сохранить блок и сообщить о нём либо выбросить исключение во время save(). |
onValidationError | нет | не задан | Получает { blockId, type, data } для ошибочных данных плагина. Вызывается в обоих режимах проверки до исключения в режиме strict. |
onDiagnostic | нет | не задан | Получает служебные сигналы без содержимого документа. Если обработчик не передан, диагностика не вызывает код приложения. |
diagnosticThresholds | нет | пороги медленных операций не заданы | Включает отдельные сигналы *.slow, когда операция достигает переданной длительности. У пропущенных полей нет скрытого порога. |
theme | нет | 'dark' | Добавляет корню класс oe-theme-{theme}. Rector поставляет темы dark и light; пользовательское имя можно связать со своими переменными и селекторами CSS. |
Контейнер и блочные плагины
holder — элемент DOM, содержимым которого управляет Rector. Не используйте один контейнер одновременно для нескольких экземпляров редактора.
plugins содержит созданные экземпляры блочных плагинов. Тип блока доступен только после регистрации соответствующего плагина. Значения type должны быть уникальны. В defaultBlock указывается один из зарегистрированных типов. Если параметр не задан, Rector использует paragraph, когда такой плагин зарегистрирован, иначе — первый плагин в массиве. Пустой массив приводит к ошибке, потому что редактору не из чего создать исходный блок.
import { Paragraph } from '@shelamkoff/rector/plugins/paragraph'
import { Quote } from '@shelamkoff/rector/plugins/quote'
const plugins = [new Paragraph(), new Quote()]Исходный документ
data нормализуется до добавления блоков в DOM. Если параметр отсутствует, создаётся пустой документ с одним блоком по умолчанию. Объект копируется на границе владения, поэтому последующие изменения исходного объекта в приложении не изменяют редактор.
Версии, миграции, идентификаторы блоков и данные внутристрочных виджетов описаны в разделе Формат документа.
Внутристрочные инструменты
Если inlineTools не задан, Rector включает полный набор встроенных инструментов. Строковые названия оставляют только выбранные стандартные инструменты, а объекты добавляют или заменяют поведение.
createEditor({
holder,
plugins,
inlineTools: ['bold', 'italic', 'link'],
})import { createDefaultInlineTools } from '@shelamkoff/rector'
const defaults = createDefaultInlineTools()
createEditor({
holder,
plugins,
inlineTools: [...defaults, myInlineTool],
})Сам блочный плагин через свойство inlineTools определяет доступный набор: true включает все настроенные инструменты, массив строк задаёт разрешённые названия, а false отключает панель. Подробности приведены в разделе «Внутристрочные инструменты и плагины».
Все встроенные названия, полный контракт пользовательского инструмента, панели действий, правила истории и освобождение ресурсов описаны в разделе Внутристрочные инструменты и плагины.
Внутристрочные плагины
inlinePlugins регистрирует постоянные виджеты внутри текста, например упоминание пользователя или образец цвета. В отличие от инструмента форматирования, виджет хранит сериализуемые данные в карте inline соответствующего блока.
import { createMentionPlugin } from '@shelamkoff/rector/inline-plugins/mention'
createEditor({
holder,
plugins,
inlinePlugins: [createMentionPlugin({ searchFunction: findPeople })],
})Режим редактирования и размеры
| Параметр | Значение по умолчанию | Назначение |
|---|---|---|
readOnly | false | Выбирает исходный режим редактирования или чтения. Текущее значение доступно в editor.readOnly, а изменить его можно через editor.setReadOnly(boolean). |
placeholder | локализованный текст | Подсказка, передаваемая плагину исходного блока, если он реализует setPlaceholder(). Пустая строка отключает её. |
autofocus | false | Устанавливает фокус в исходный блок после создания. |
minHeight | значение таблицы стилей | Минимальная высота области редактирования в пикселях. |
theme | dark | Название темы на корневом элементе. Встроенные значения: dark и light. |
setReadOnly() сохраняет текущий документ и историю. При переходе DOM плагинов создаётся заново с новым значением context.readOnly, но шаг истории и вызов onChange не происходят; метод также не запрашивает и не восстанавливает фокус браузера. Замена смонтированных элементов плагинов может привести к потере текущего фокуса, поэтому при необходимости после возврата в режим редактирования вызовите editor.focus(). В режиме чтения недоступны пользовательское редактирование, вставка внутристрочных виджетов, отмена и повтор; save(), render(), clear() и структурные команды блоков, вызванные приложением, остаются доступны. Полный контракт приведён в разделе API редактора.
Локализация
locale — единый словарь сообщений ядра и зарегистрированных плагинов. Для встроенного языка импортируйте готовый объединённый словарь.
import ru from '@shelamkoff/rector/locale/ru'
createEditor({ holder, plugins, locale: ru })Пользовательские записи заменяют одноимённые ключи. Добавьте __lang, если правила множественного числа должны соответствовать определённому языку.
Обработчики изменений
onReady ставится в очередь микрозадач после успешной сборки. createEditor() уже синхронно возвращает готовый дескриптор; обработчик нужен для уведомления другой части приложения. Если редактор уничтожен до выполнения микрозадачи, обработчик не вызывается.
onChange не вызывается для исходного документа. После изменения Rector ждёт tuning.change.debounceMs — по умолчанию 250 мс, — синхронно выполняет save() и передаёт обработчику полученный отделённый документ. Более новое изменение перезапускает ещё не завершившуюся задержку. Уничтожение редактора отменяет ожидающее уведомление.
Если внутренний save() выбрасывает исключение, Rector записывает предупреждение и не вызывает onChange. Возвращаемое обработчиком значение игнорируется, поэтому асинхронная функция хранения должна самостоятельно обрабатывать свои ошибки. Это уведомление, а не транзакция хранения: пока выполняется предыдущий запрос, пользователь может внести более новое изменение.
const editor = createEditor({
holder,
plugins,
onReady() {
console.log('Редактор готов')
},
onChange(document) {
scheduleAutosave(document)
},
})В подсистеме хранения отменяйте устаревшие запросы или используйте монотонно возрастающий номер редакции, чтобы старый ответ не перезаписал новое содержимое.
Проверка документа и блоков
documentVersionPolicy определяет поведение при неподдерживаемой версии документа:
preserveприменяет все доступные миграции и, если цепочка обрывается, сохраняет последний достигнутый структурно корректный документ (это может быть и исходная заявленная версия);strictотклоняет неизвестную версию или неполную цепочку миграций.
validationMode определяет поведение, когда validate(data) зарегистрированного плагина возвращает false:
preserveсохраняет блок и передаёт описание ошибки вonValidationError;strictзаставляетsave()выбросить исключение до возвращения документа.
createEditor({
holder,
plugins,
documentVersionPolicy: 'strict',
validationMode: 'strict',
onValidationError(issue) {
console.warn(issue.blockId, issue.type)
},
})Настройка поведения
Частично переданный объект объединяется со следующими значениями:
const defaultTuning = {
drag: { threshold: 5 },
undo: { maxStack: 100, debounceMs: 300 },
change: { debounceMs: 250 },
toolbar: { filterThreshold: 7 },
animations: {
blockInsertMs: 350,
blockMoveMs: 200,
blockRemoveMs: 350,
},
mobileBreakpoint: 768,
}У каждого вложенного параметра одно назначение; эти значения не меняют формат документа.
| Путь | Значение | Единица | Действие |
|---|---|---|---|
drag.threshold | 5 | пиксели CSS | Минимальное движение указателя, после которого нажатие на маркер становится перетаскиванием блока. |
undo.maxStack | 100 | записей истории | Максимальное число сохранённых шагов отмены. После превышения предела удаляется самый старый шаг. |
undo.debounceMs | 300 | мс | Период покоя для объединения последовательных изменений обычного ввода в одном блоке. Явные команды, действия панели и структурные изменения остаются отдельными шагами. |
change.debounceMs | 250 | мс | Период покоя перед сериализацией документа и вызовом onChange. Не объединяет и не меняет порядок истории. |
toolbar.filterThreshold | 7 | типов блоков | Минимальное число записей, после которого в выборе блока появляется поле фильтра. |
animations.blockInsertMs | 350 | мс | Длительность анимации добавления блока. |
animations.blockMoveMs | 200 | мс | Длительность анимации перемещения блока. |
animations.blockRemoveMs | 350 | мс | Длительность анимации удаления блока. |
mobileBreakpoint | 768 | пиксели CSS | Ширина окна, ниже которой элементы редактора переходят к мобильной компоновке. Пользовательские медиазапросы должны использовать согласованное значение. |
undo.debounceMs объединяет непрерывный ввод текста. Явные структурные действия и нажатия инструментов он не объединяет. change.debounceMs влияет только на уведомления, но не меняет порядок истории.
Все числовые значения tuning должны быть конечными и неотрицательными. undo.maxStack дополнительно должен быть целым числом не меньше 1, а toolbar.filterThreshold — целым числом. Ошибочное значение отклоняется синхронно до занятия контейнера и создания DOM плагинов.
Диагностика
Служебная диагностика отключена, пока не передан onDiagnostic. Сигналы содержат сведения об операции, но никогда не содержат данные документа или плагина.
createEditor({
holder,
plugins,
onDiagnostic(signal) {
telemetry.record(signal)
},
diagnosticThresholds: {
commandMs: 16,
saveMs: 50,
renderMs: 50,
pasteMs: 100,
},
})Возможные значения code: command.failed, command.slow, paste.failed, paste.slow, migration.applied, migration.failed, migration.unavailable, save.failed, save.slow, render.slow, editor.create.failed и cleanup.failed.
diagnosticThresholds содержит четыре независимых значения в миллисекундах:
| Поле | Создаваемый сигнал |
|---|---|
commandMs | command.slow, если команда достигла или превысила порог |
saveMs | save.slow при сериализации документа |
renderMs | render.slow для измеряемой операции отображения блока или документа |
pasteMs | paste.slow для операции вставки |
Каждый переданный порог должен быть конечным неотрицательным числом. Ошибочный порог отклоняется во время createEditor() до начала создания DOM.
Каждый EditorDiagnostic содержит code и числовой timestamp. В зависимости от операции также возможны durationMs, operation, pluginType, blockType, fromVersion, toVersion и errorName. Сигнал никогда не содержит текст документа, данные блока, конфигурацию плагина или объект выброшенного исключения.
Формы вспомогательных объектов
Массив migrations состоит из объектов следующего вида:
interface DocumentMigration {
from: string
to: string
migrate(document: EditorDocument): EditorDocument
}Значение from должно быть уникальным в массиве, а from и to не могут совпадать. migrate() обязана вернуть структурно корректный документ. Rector передаёт в каждую миграцию копию и проверяет возвращённую оболочку перед следующим шагом. Миграции выполняются синхронно и упорядочиваются связями версий, а не положением в массиве.
Обработчик onValidationError получает:
interface BlockValidationIssue {
blockId: string
type: string
data: Record<string, unknown>
}data — отделённый снимок ошибочных данных блока. Это диагностическое значение: его изменение не исправляет работающий блок.