Skip to content

Конфигурация

createEditor(config) принимает один объект конфигурации. Обязательны только holder и plugins. Rector сразу проверяет оба значения и выбрасывает TypeError, если контейнер не является HTMLElement или плагины переданы не массивом.

Полная форма конфигурации

ts
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 проходит связи fromto, пока не достигнет текущей версии формата.
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, когда такой плагин зарегистрирован, иначе — первый плагин в массиве. Пустой массив приводит к ошибке, потому что редактору не из чего создать исходный блок.

js
import { Paragraph } from '@shelamkoff/rector/plugins/paragraph'
import { Quote } from '@shelamkoff/rector/plugins/quote'

const plugins = [new Paragraph(), new Quote()]

Исходный документ

data нормализуется до добавления блоков в DOM. Если параметр отсутствует, создаётся пустой документ с одним блоком по умолчанию. Объект копируется на границе владения, поэтому последующие изменения исходного объекта в приложении не изменяют редактор.

Версии, миграции, идентификаторы блоков и данные внутристрочных виджетов описаны в разделе Формат документа.

Внутристрочные инструменты

Если inlineTools не задан, Rector включает полный набор встроенных инструментов. Строковые названия оставляют только выбранные стандартные инструменты, а объекты добавляют или заменяют поведение.

js
createEditor({
  holder,
  plugins,
  inlineTools: ['bold', 'italic', 'link'],
})
js
import { createDefaultInlineTools } from '@shelamkoff/rector'

const defaults = createDefaultInlineTools()

createEditor({
  holder,
  plugins,
  inlineTools: [...defaults, myInlineTool],
})

Сам блочный плагин через свойство inlineTools определяет доступный набор: true включает все настроенные инструменты, массив строк задаёт разрешённые названия, а false отключает панель. Подробности приведены в разделе «Внутристрочные инструменты и плагины».

Все встроенные названия, полный контракт пользовательского инструмента, панели действий, правила истории и освобождение ресурсов описаны в разделе Внутристрочные инструменты и плагины.

Внутристрочные плагины

inlinePlugins регистрирует постоянные виджеты внутри текста, например упоминание пользователя или образец цвета. В отличие от инструмента форматирования, виджет хранит сериализуемые данные в карте inline соответствующего блока.

js
import { createMentionPlugin } from '@shelamkoff/rector/inline-plugins/mention'

createEditor({
  holder,
  plugins,
  inlinePlugins: [createMentionPlugin({ searchFunction: findPeople })],
})

Режим редактирования и размеры

ПараметрЗначение по умолчаниюНазначение
readOnlyfalseВыбирает исходный режим редактирования или чтения. Текущее значение доступно в editor.readOnly, а изменить его можно через editor.setReadOnly(boolean).
placeholderлокализованный текстПодсказка, передаваемая плагину исходного блока, если он реализует setPlaceholder(). Пустая строка отключает её.
autofocusfalseУстанавливает фокус в исходный блок после создания.
minHeightзначение таблицы стилейМинимальная высота области редактирования в пикселях.
themedarkНазвание темы на корневом элементе. Встроенные значения: dark и light.

setReadOnly() сохраняет текущий документ и историю. При переходе DOM плагинов создаётся заново с новым значением context.readOnly, но шаг истории и вызов onChange не происходят; метод также не запрашивает и не восстанавливает фокус браузера. Замена смонтированных элементов плагинов может привести к потере текущего фокуса, поэтому при необходимости после возврата в режим редактирования вызовите editor.focus(). В режиме чтения недоступны пользовательское редактирование, вставка внутристрочных виджетов, отмена и повтор; save(), render(), clear() и структурные команды блоков, вызванные приложением, остаются доступны. Полный контракт приведён в разделе API редактора.

Локализация

locale — единый словарь сообщений ядра и зарегистрированных плагинов. Для встроенного языка импортируйте готовый объединённый словарь.

js
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. Возвращаемое обработчиком значение игнорируется, поэтому асинхронная функция хранения должна самостоятельно обрабатывать свои ошибки. Это уведомление, а не транзакция хранения: пока выполняется предыдущий запрос, пользователь может внести более новое изменение.

js
const editor = createEditor({
  holder,
  plugins,
  onReady() {
    console.log('Редактор готов')
  },
  onChange(document) {
    scheduleAutosave(document)
  },
})

В подсистеме хранения отменяйте устаревшие запросы или используйте монотонно возрастающий номер редакции, чтобы старый ответ не перезаписал новое содержимое.

Проверка документа и блоков

documentVersionPolicy определяет поведение при неподдерживаемой версии документа:

  • preserve применяет все доступные миграции и, если цепочка обрывается, сохраняет последний достигнутый структурно корректный документ (это может быть и исходная заявленная версия);
  • strict отклоняет неизвестную версию или неполную цепочку миграций.

validationMode определяет поведение, когда validate(data) зарегистрированного плагина возвращает false:

  • preserve сохраняет блок и передаёт описание ошибки в onValidationError;
  • strict заставляет save() выбросить исключение до возвращения документа.
js
createEditor({
  holder,
  plugins,
  documentVersionPolicy: 'strict',
  validationMode: 'strict',
  onValidationError(issue) {
    console.warn(issue.blockId, issue.type)
  },
})

Настройка поведения

Частично переданный объект объединяется со следующими значениями:

js
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.threshold5пиксели CSSМинимальное движение указателя, после которого нажатие на маркер становится перетаскиванием блока.
undo.maxStack100записей историиМаксимальное число сохранённых шагов отмены. После превышения предела удаляется самый старый шаг.
undo.debounceMs300мсПериод покоя для объединения последовательных изменений обычного ввода в одном блоке. Явные команды, действия панели и структурные изменения остаются отдельными шагами.
change.debounceMs250мсПериод покоя перед сериализацией документа и вызовом onChange. Не объединяет и не меняет порядок истории.
toolbar.filterThreshold7типов блоковМинимальное число записей, после которого в выборе блока появляется поле фильтра.
animations.blockInsertMs350мсДлительность анимации добавления блока.
animations.blockMoveMs200мсДлительность анимации перемещения блока.
animations.blockRemoveMs350мсДлительность анимации удаления блока.
mobileBreakpoint768пиксели CSSШирина окна, ниже которой элементы редактора переходят к мобильной компоновке. Пользовательские медиазапросы должны использовать согласованное значение.

undo.debounceMs объединяет непрерывный ввод текста. Явные структурные действия и нажатия инструментов он не объединяет. change.debounceMs влияет только на уведомления, но не меняет порядок истории.

Все числовые значения tuning должны быть конечными и неотрицательными. undo.maxStack дополнительно должен быть целым числом не меньше 1, а toolbar.filterThreshold — целым числом. Ошибочное значение отклоняется синхронно до занятия контейнера и создания DOM плагинов.

Диагностика

Служебная диагностика отключена, пока не передан onDiagnostic. Сигналы содержат сведения об операции, но никогда не содержат данные документа или плагина.

js
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 содержит четыре независимых значения в миллисекундах:

ПолеСоздаваемый сигнал
commandMscommand.slow, если команда достигла или превысила порог
saveMssave.slow при сериализации документа
renderMsrender.slow для измеряемой операции отображения блока или документа
pasteMspaste.slow для операции вставки

Каждый переданный порог должен быть конечным неотрицательным числом. Ошибочный порог отклоняется во время createEditor() до начала создания DOM.

Каждый EditorDiagnostic содержит code и числовой timestamp. В зависимости от операции также возможны durationMs, operation, pluginType, blockType, fromVersion, toVersion и errorName. Сигнал никогда не содержит текст документа, данные блока, конфигурацию плагина или объект выброшенного исключения.

Формы вспомогательных объектов

Массив migrations состоит из объектов следующего вида:

ts
interface DocumentMigration {
  from: string
  to: string
  migrate(document: EditorDocument): EditorDocument
}

Значение from должно быть уникальным в массиве, а from и to не могут совпадать. migrate() обязана вернуть структурно корректный документ. Rector передаёт в каждую миграцию копию и проверяет возвращённую оболочку перед следующим шагом. Миграции выполняются синхронно и упорядочиваются связями версий, а не положением в массиве.

Обработчик onValidationError получает:

ts
interface BlockValidationIssue {
  blockId: string
  type: string
  data: Record<string, unknown>
}

data — отделённый снимок ошибочных данных блока. Это диагностическое значение: его изменение не исправляет работающий блок.

Rector is released under the MIT License.