Перейти к содержимому
ФреймворкJavaScript

Blocks API: вставка, перенос и удаление блоков

Управление блоками в редакторе: создание, удаление, обновление и переупорядочивание контента.

Обновлено 5 окт. 2026 г.Редактировать на GitHub

Как получить экземпляр редактора

Методы ниже вызываются на редакторе, созданном через new Blok(). Они доступны после того, как разрешится editor.isReady.

TypeScript
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');

Методы

blocks.clear()

Promise<void>

Удалить все блоки из редактора.

Когда использовать

То же самое, что clear() верхнего уровня, но на модуле blocks. Используйте, когда у вас уже есть ссылка на editor.blocks.

TypeScript
await editor.blocks.clear();
// All content removed; editor keeps one empty paragraph

blocks.render(data)

Promise<void>

Отрисовывает переданные JSON-данные как блоки и заменяет текущий документ. Метод устойчив к эху: если входящий документ структурно равен текущему сохранённому содержимому (time и version игнорируются), вызов становится no-op и сохраняет курсор. Поэтому круговому пути data → render → onSave → setState → data не нужна дедупликация на вашей стороне.

Метод принимает нестрогий формат (LooseOutputData). Редактор делает глубокую копию данных, поэтому переданный объект не мутируется и не удерживается. Замороженное состояние хранилища (Redux, Immer) можно передавать напрямую.

Рендер, который заменяет документ, также очищает историю отмен, поэтому отмена не вернёт предыдущий документ.

Когда использовать

Заменяет весь документ. Повторная передача собственного вывода редактора становится no-op и сохраняет курсор, поэтому дедупликация на вашей стороне не нужна. Чтобы добавить блоки без очистки, используйте insert() или insertMany().

TypeScript
const data = {
  blocks: [
    { id: '1', type: 'paragraph', data: { text: 'Hello World' } },
    { id: '2', type: 'header', data: { text: 'Title', level: 1 } }
  ]
};
await editor.blocks.render(data);

blocks.renderFromHTML(data)

Promise<void>

Отрисовать HTML-строку как блоки, преобразовав её в формат блоков.

Когда использовать

Удобно для импорта старого HTML, но результат зависит от обработчиков вставки в инструментах. Если источник под вашим контролем, JSON через render() сохраняет больше точности.

TypeScript
const html = '<h1>Title</h1><p>Hello World</p>';
await editor.blocks.renderFromHTML(html);
// HTML is converted to appropriate blocks

blocks.importMarkdown(md, options?)

Promise<OutputData>

Преобразует Markdown-строку в блоки и отрисовывает их. Это ЗАМЕНЯЕТ текущий документ, потому что внутри вызывается blocks.render().

Конвертер загружается лениво при первом вызове. Промис резолвится тем OutputData, который был отрисован. Параметр options имеет тип MarkdownImportConfig (сопоставление инструментов, переключатель GFM, расширения micromark/mdast).

Чтобы добавить блоки, а не заменить документ, используйте markdownToBlocks() из отдельного подпути @bloklabs/core/markdown вместе с blocks.insertMany().

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
mdstringОбязательный—

Исходная Markdown-строка.

optionsMarkdownImportConfig—undefined

Сопоставление инструментов, переключатель GFM и расширения micromark/mdast.

TypeScript
const data = await editor.blocks.importMarkdown('# Title\n\n- one\n- two');
// The whole document is replaced; data is the rendered OutputData

blocks.exportMarkdown()

Promise<string>

Сериализует текущий документ в Markdown. Это исходящий близнец importMarkdown. Блоки читаются через Saver, поэтому вывод отражает сохранённый (провалидированный) документ, а не сырой DOM.

Промис резолвится в '', когда сохранять нечего. Блоки, принадлежащие ячейке таблицы, сериализуются внутри pipe-таблицы, а не повторяются отдельными строками.

То, что Markdown выразить не может, деградирует.

  • Значения colspan и rowspan таблицы и столбцы заголовков отбрасываются.
  • Таблица без строки заголовков получает пустую строку заголовка, потому что GFM её требует.
TypeScript
const md = await editor.blocks.exportMarkdown();
// → '# Title\n\n- one\n- two'

blocks.delete(index?, setCaret?)

Promise<void>

Удалить блок по указанному индексу или текущий блок, если индекс не передан.

Когда использовать

Без индекса удаляет блок в фокусе. Удаление последнего оставшегося блока автоматически вставляет свежий пустой параграф, поэтому редактор никогда не остаётся без цели для курсора.

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
indexnumber—current block index

Индекс блока для удаления.

setCaretboolean—true

Перемещать ли курсор на уцелевший блок после удаления. Передайте false, чтобы не отбирать курсор у пользователя при программном удалении.

TypeScript
// Delete current block
await editor.blocks.delete();

// Delete block at index 0
await editor.blocks.delete(0);

// Delete without moving the user's caret (programmatic deletion)
await editor.blocks.delete(0, false);

blocks.move(toIndex, fromIndex?)

void

Перемещает блок на новую позицию. Если fromIndex не передан, перемещает текущий блок.

Когда использовать

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

TypeScript
// Move current block to top
editor.blocks.move(0);

// Move block from index 2 to index 0
editor.blocks.move(0, 2);

blocks.getBlockByIndex(index)

BlockAPI | undefined

Получить объект BlockAPI для блока по указанному индексу.

Когда использовать

Возвращает undefined для индексов вне диапазона. Вызов метода на результате undefined приведёт к ошибке, поэтому сначала проверьте результат.

TypeScript
const block = editor.blocks.getBlockByIndex(0);
if (block) {
  console.log(block.id, block.name);
}

blocks.getById(id)

BlockAPI | null

Получить объект BlockAPI для блока с указанным ID.

Когда использовать

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

TypeScript
const block = editor.blocks.getById('block-123');
if (block) {
  await editor.blocks.update(block.id, { text: 'New content' });
}

blocks.getCurrentBlockIndex()

number

Получить индекс блока, который сейчас в фокусе.

Когда использовать

Отражает блок с курсором. Возвращает -1, когда ничего не в фокусе. Проверяйте значение, прежде чем использовать его как индекс.

TypeScript
const index = editor.blocks.getCurrentBlockIndex();
console.log('Current block index:', index);

blocks.getBlockIndex(blockId)

number | undefined

Получить индекс блока по его ID.

Когда использовать

Находит текущую позицию известного блока. Сочетайте его с getById(), когда есть id, а нужна позиция.

TypeScript
const index = editor.blocks.getBlockIndex('block-123');
if (index !== undefined) {
  console.log('Block is at index:', index);
}

blocks.getBlockByElement(element)

BlockAPI | undefined

Получить объект BlockAPI для блока, который содержит переданный HTML-элемент.

Когда использовать

Мост от DOM-узла (например, от цели клика) обратно к его блоку. Полезно в собственных обработчиках событий.

TypeScript
document.addEventListener('click', (e) => {
  const block = editor.blocks.getBlockByElement(e.target);
  if (block) {
    console.log('Clicked on block:', block.id);
  }
});

blocks.scrollToBlock(id)

void

Прокручивает страницу к блоку, выделяет его, показывает подсветку прибытия и объявляет переход вспомогательным технологиям. Это публичный аналог прокрутки по хешу URL при загрузке. Если блока с таким id в документе нет, метод ничего не делает.

Новый переход заменяет уже выделенные блоки. Передайте вторым аргументом { select: false }, чтобы перейти без выделения, как это делает навигация по странице, например оглавление: выделенный блок удаляется следующим нажатием Backspace.

Адаптеры фреймворков, которые монтируются в отсоединённый холдер (React/Vue/Angular), отрисовывают засеянный контент до того, как он попадёт на страницу, поэтому загрузочная прокрутка по хешу откладывается. @bloklabs/react выполняет её автоматически, как только холдер подключается.

Для глубоких ссылок вызывайте этот метод сами, после того как редактор готов.

TypeScript
editor.blocks.scrollToBlock(nodeId);

blocks.getChildren(parentId)

BlockAPI[]

Получить все дочерние блоки родительского блока-контейнера.

Когда использовать

Возвращает прямых потомков блока-контейнера (колонки, тоггла или базы данных). Пустой массив, если потомков нет.

TypeScript
const children = editor.blocks.getChildren('parent-block-id');
children.forEach(child => {
  console.log('Child:', child.id);
});

blocks.setBlockParent(blockId, parentId)

void

Меняет родителя блока. Обновляет parentId блока и contentIds родителя через единственную в ядре точку смены родителя.

  • Передайте null, чтобы вернуть блок на корневой уровень.
  • Неизвестный blockId ничего не делает и пишет предупреждение в лог.
  • parentId, который сделал бы блок потомком самого себя, выбрасывает ошибку.

Место блока в порядке документа следует за новым родителем.

  • Если блок уже стоит внутри поддерева родителя, он не перемещается. Это значит, что он идёт сразу после родителя или сразу после одного из его потомков.
  • Иначе блок переезжает в конец поддерева родителя. Его собственные дочерние блоки переезжают вместе с ним.
  • Таблица и база данных сами расставляют свои дочерние блоки, поэтому блок, который к ним присоединяется, не перемещается.
  • Блок, который уходит на корневой уровень или к одному из своих предков, переезжает вместе с дочерними блоками сразу за поддерево, из которого ушёл, если он ещё не стоит там. Чтобы вынести из контейнера несколько соседних блоков и сохранить их порядок, начните с последнего.
TypeScript
// Move a block into a container block
editor.blocks.setBlockParent('child-block-id', 'parent-block-id');

// Move it back to the root level
editor.blocks.setBlockParent('child-block-id', null);

blocks.insertInsideParent(parentId, insertIndex, childData?, toolName?)

BlockAPI

Вставляет блок как дочерний для parentId атомарно. Создание и назначение родителя объединяются в ОДИН шаг отмены, поэтому одно нажатие Cmd+Z убирает блок полностью. Это лучше, чем insert() с последующей сменой родителя: там шага два.

  • Параметр insertIndex задаёт ПЛОСКИЙ индекс документа, по которому должен появиться дочерний блок. Индекс ограничивается поддеревом родителя.
    • Индекс на месте родителя или раньше него превращается в позицию сразу после родителя.
    • Индекс за концом поддерева превращается в конец поддерева.
  • toolName выбирает блочный инструмент дочернего блока и по умолчанию равен config.defaultBlock.
    • Инструмент, запрещённый внутри ячеек таблицы, понижается до блока по умолчанию, если новый дочерний блок попал бы в такую ячейку.
    • Незарегистрированное имя выбрасывает ошибку до того, как что-либо будет записано.
  • childData по умолчанию равен { text: '' } для блока по умолчанию.
    • Для любого другого toolName значение по умолчанию равно {}, и тогда инструмент применяет собственные значения по умолчанию.
TypeScript
const parentIndex = editor.blocks.getBlockIndex('parent-block-id') ?? 0;
const child = editor.blocks.insertInsideParent(
  'parent-block-id',
  parentIndex + 1,
  { text: 'Nested content' },
);

// A TYPED child in the same single undo entry — no insert-then-reparent
editor.blocks.insertInsideParent(
  'parent-block-id',
  parentIndex + 1,
  { text: 'Nested heading', level: 2 },
  'header',
);

blocks.insertAt(type?, data?, options?)

BlockAPI

Вставляет новый блок в место, заданное родителем и соседями, а не плоским индексом. Это ОДИН шаг отмены.

  • position принимает 'start', 'end' (по умолчанию), { before: id } или { after: id }.
    • { after: id } ставит блок после всего поддерева этого соседа, а не среди его детей.
  • parentId задаёт родителя; null означает корень.
    • Если его не передать, before/after берут родителя соседа, а 'start'/'end' ставят блок в корень.
  • replace: id ставит новый блок на место этого блока. Родитель сохраняется, а дети следуют правилам смены типа блока. Нельзя сочетать с parentId или position.
  • focus по умолчанию false, поэтому программная вставка не меняет текущий блок.
  • Инструмент, который родитель не разрешает, заменяется, как в insertInsideParent.

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

TypeScript
// Last child of a toggle
editor.blocks.insertAt('paragraph', { text: 'Inside' }, { parentId: toggleId });

// Right after a block's whole subtree, at the block's own level
editor.blocks.insertAt('header', { text: 'Next', level: 2 }, { position: { after: blockId } });

// First block of the document
editor.blocks.insertAt('paragraph', { text: 'Top' }, { parentId: null, position: 'start' });

blocks.moveTo(id, target)

void

Перемещает блок вместе со всем поддеревом в место, заданное родителем и соседями. Это ОДИН шаг отмены, даже если меняется родитель.

  • position работает так же, как в insertAt. { after: id } ставит блок после всего поддерева соседа.
  • parentId задаёт нового родителя; null означает корень. Если его не передать, before/after берут родителя соседа, а 'start'/'end' ставят блок в корень.

Метод бросает ошибку и ничего не меняет, если:

  • блок не найден или сосед не является дочерним для parentId;
  • цель указывает на сам блок или на место внутри его поддерева;
  • перемещение выводит блок из контейнера, который сам управляет детьми (таблица, ряд колонок), из колонки или ячейки таблицы, либо вводит его туда;
  • новый родитель не разрешает этот инструмент (childTools).
TypeScript
// Into a toggle, as its first child
editor.blocks.moveTo(blockId, { parentId: toggleId, position: 'start' });

// Out of a container, right after it
editor.blocks.moveTo(childId, { position: { after: containerId } });

blocks.getBlocksCount()

number

Получить общее количество блоков в редакторе.

Когда использовать

Считает все блоки, включая вложенные дочерние (колонки, тогглы, ячейки таблиц), а не только блоки верхнего уровня. Используйте его для проверки границ перед insert() или move() по индексу.

TypeScript
const count = editor.blocks.getBlocksCount();
console.log('Total blocks:', count);

blocks.insert(type?, data?, config?, index?, needToFocus?, replace?, id?, tunes?, origin?)

BlockAPI

Вставить новый блок с полным контролем над его свойствами и позицией.

Когда использовать

Все параметры необязательны. Вызовите insert(), чтобы получить пустой параграф, или передайте type/data/index для полного контроля. Передайте replace: true, чтобы заменить блок по индексу index.

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
typestring—config.defaultBlock

Имя инструмента для создания блока.

dataBlockToolData—{}

Начальные данные инструмента для нового блока.

configToolConfig—{}

Игнорируется. Принимается только ради того, чтобы позиционная сигнатура оставалась стабильной. Редактор связывает его с _config и никогда не читает. Опции вставки в block-manager не содержат поля config, поэтому созданный блок использует конфигурацию инструмента уровня редактора из config.tools.

Передавайте undefined.

indexnumber—current block index + 1

Позиция для вставки блока.

Новый блок также получает родителя, которого подразумевает эта позиция. Это верно и тогда, когда index не передан.

  • Сразу после контейнера с дочерними блоками новый блок становится его первым дочерним блоком.
  • В любом другом месте блок получает того же родителя, что и блок, который идёт следом. Поэтому между двумя дочерними блоками тоггла он становится дочерним блоком этого тоггла.
  • В начале и в конце документа блок становится корневым.
  • Сразу после свёрнутого тоггла с дочерними блоками новый блок встаёт после этих скрытых блоков. Родителя там выбирают правила выше, а итоговый индекс может оказаться больше index.
  • Сразу после блока внутри column новый блок попадает в эту колонку.

Строка колонок никогда не принимает блок таким способом. Сразу после таблицы или базы данных, а также после блока внутри них, родитель не подбирается. Блок становится корневым, если только он не идёт сразу после блока в колонке. При replace: true родитель не подбирается.

Действуют правила childTools родителя. Инструмент, который родитель не разрешает, заменяется на разрешённый.

needToFocusboolean—true

Переводить ли фокус на вставленный блок. Передайте false, чтобы вставить блок, не перемещая курсор.

replaceboolean—false

Заменить существующий блок по индексу вместо вставки рядом с ним.

idstring—auto-generated

Собственный id для нового блока.

tunes{ [name: string]: BlockTuneData }—undefined

Необязательные данные тюнов, применяемые при создании, с ключами по имени тюна.

originBlockOrigin—'api'

Зачем создаётся блок. Значение передаётся в конструктор инструмента как origin. Именно так контейнерный инструмент отличает настоящее создание (можно засеять детей по умолчанию) от повторной материализации: загрузки документа, воспроизведения undo/redo или вставки (засевать нельзя).

  • Передавайте 'user', когда вставка идёт из вашего собственного интерфейса вставки: своей панели инструментов, слэш-меню или горячей клавиши.
    • Тогда встроенные контейнеры Blok (column_list, column) и ваши собственные ведут себя так же, как при вставке из штатного меню.
  • Для программных вставок и повторной загрузки данных параметр можно не передавать.
    • Значение по умолчанию 'api' тоже считается созданием, но никогда не выдаётся за жест пользователя.

Ошибки

  • Не указан type, и в конфигурации не задан defaultBlock.

    Could not insert Block. Tool name is not specified.

    Передайте явный type или задайте defaultBlock в конфигурации редактора.

  • Определённое имя инструмента не зарегистрировано в редакторе.

    Could not compose Block. Tool «<type>» not found.

    Зарегистрируйте инструмент в конфигурации tools редактора перед вставкой блока этого типа.

  • Передан replace: true, но по index нет блока.

    Could not replace Block at index <index>. Block not found.

    Проверьте index через blocks.getBlocksCount() перед вызовом с replace: true.

TypeScript
// Insert after the current block with the default type
const block = editor.blocks.insert();
// → BlockAPI { id: 'kP3xQ...', name: 'paragraph', ... }

// Insert paragraph with data at index 0
const block = editor.blocks.insert('paragraph', { text: 'Hello' }, undefined, 0);

// Insert with custom ID
const block = editor.blocks.insert('header', { text: 'Title' }, undefined, undefined, undefined, undefined, 'custom-id');

// From your own slash menu / toolbar: declare the user gesture so a container
// tool seeds its default children (see BlockOrigin on the tool contract)
const block = editor.blocks.insert('column_list', undefined, undefined, index, undefined, undefined, undefined, undefined, 'user');

blocks.insertMany(blocks, index?)

BlockAPI[]

Вставить несколько блоков за раз. Когда индекс не передан, блоки добавляются в конец документа.

Когда использовать

Массовая вставка за одну операцию и один шаг отмены. Это гораздо дешевле, чем цикл из insert(), для больших вставок или импорта.

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
blocksOutputBlockData[] | LooseOutputBlockData[]Обязательный—

Блоки для вставки. Принимаются нестрогие блоки. null в data становится {}, а null или пустой id заменяется сгенерированным.

indexnumber—end of document

Позиция для вставки. Когда не передана, по умолчанию блоки добавляются в конец документа.

Ошибки

  • Переданный index отрицательный.

    Index should be greater than or equal to 0

    Передайте index не меньше 0 либо не передавайте его, чтобы добавить блоки в конец.

TypeScript
const blocksToInsert = [
  { id: '1', type: 'paragraph', data: { text: 'First' } },
  { id: '2', type: 'paragraph', data: { text: 'Second' } }
];
const inserted = editor.blocks.insertMany(blocksToInsert, 0);
console.log('Inserted:', inserted.length, 'blocks');

blocks.composeBlockData(toolName)

Promise<BlockToolData>

Создать пустые данные блока для указанного типа инструмента.

Когда использовать

Создаёт данные инструмента по умолчанию, ничего не вставляя. Полезно, когда нужен корректный пустой payload для insert() или update().

Ошибки

  • toolName не является зарегистрированным инструментом.

    Block Tool with type "<toolName>" not found

    Сначала зарегистрируйте инструмент в конфигурации tools редактора.

TypeScript
const emptyData = await editor.blocks.composeBlockData('paragraph');
// Returns: { text: '' } or appropriate empty state for the tool

blocks.update(id, data?, tunes?)

Promise<BlockAPI>

Обновляет данные и/или тюны блока. Обновление данных применяется НА МЕСТЕ, когда инструмент блока реализует setData(newData) в своём прототипе. Так делает каждый React/Vue/Angular-блок, а также встроенные инструменты заголовка, списка, кода, тоггла и таблицы.

«На месте» означает, что тот же экземпляр блока, тот же DOM-холдер и тот же смонтированный компонент продолжают жить. Поэтому эфемерное состояние инструмента, принятые дочерние блоки и курсор сохраняются. Именно поэтому update() безопасно вызывать на каждое нажатие клавиши, например при переименовании карточки во время набора.

К пересборке блока откатываются три случая:

  • инструменты без setData
  • инструмент, чей setData возвращает false (ему нужна другая форма DOM)
  • любой вызов, передающий tunes

Пересборка означает, что новый экземпляр инструмента заменяет старый, а старый уничтожается.

Когда использовать

Изменяет data/tunes на месте, сохраняя id и тип блока. Чтобы сменить тип, используйте convert().

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
idstringОбязательный—

Id блока для обновления.

dataPartial<BlockToolData>—undefined

Частичные данные, объединяемые с существующими данными блока.

tunesRecord<string, BlockTuneData>—undefined

Данные тюнов, объединяемые с существующими тюнами блока.

Ошибки

  • Блок с указанным id не существует.

    Block with id "<id>" not found

    Проверьте id через blocks.getById() перед вызовом update().

TypeScript
// Update block data
const block = await editor.blocks.update('block-123', { text: 'New text' });

// Update with tunes
const block = await editor.blocks.update('block-123', undefined, { alignment: 'center' });

// Guard against an id that no longer exists (e.g. the block was deleted
// concurrently) instead of letting the rejection surface unhandled
try {
  await editor.blocks.update(staleId, { text: 'New text' });
} catch {
  console.warn('Block was already removed, skipping update');
}

blocks.convert(id, newType, dataOverrides?)

Promise<BlockAPI>

Преобразовать блок в другой тип. Оба инструмента должны поддерживать конфигурацию преобразования.

Когда использовать

И исходный, и целевой инструменты должны объявлять conversionConfig, иначе вызов выбросит ошибку. По возможности сохраняет текст.

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
idstringОбязательный—

Id блока для преобразования. Его инструмент должен объявлять conversionConfig.export.

newTypestringОбязательный—

Имя зарегистрированного инструмента, в который идёт преобразование. Его инструмент должен объявлять conversionConfig.import.

dataOverridesBlockToolData—undefined

Поля данных для перезаписи в результирующем блоке после преобразования.

Ошибки

  • Блок с указанным id не существует.

    Block with id "<id>" not found

    Проверьте id через blocks.getById() перед вызовом convert().

  • newType не является зарегистрированным инструментом.

    Block Tool with type "<newType>" not found

    Зарегистрируйте целевой инструмент в конфигурации tools редактора.

  • У исходного инструмента нет conversionConfig.export, у целевого нет conversionConfig.import, либо нет ни того, ни другого.

    Conversion from "<sourceType>" to "<newType>" is not possible. <ToolName(s)> tool(s) should provide a "conversionConfig"

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

TypeScript
// Convert paragraph to header
const headerBlock = await editor.blocks.convert('block-123', 'header', { level: 2 });

// Convert with data overrides
const headerBlock = await editor.blocks.convert('block-123', 'header', { text: 'New Title', level: 1 });

// Not every pair of tools supports conversion — guard it rather than
// assuming the target type is always convertible
try {
  await editor.blocks.convert('block-123', 'table');
} catch (error) {
  console.warn('Conversion not supported between these tools:', error);
}

blocks.splitBlock(currentBlockId, currentBlockData, newBlockType, newBlockData, insertIndex)

BlockAPI

Атомарно разделить блок, обновив текущий блок и вставив новый. Обе операции объединяются в один шаг отмены.

Когда использовать

Используйте его для разбиения с учётом курсора, например по Enter посреди текста. update и insert образуют один шаг отмены.

TypeScript
// Split a paragraph at cursor position
const newBlock = editor.blocks.splitBlock(
  'current-block-id',
  { text: 'First part' },
  'paragraph',
  { text: 'Second part' },
  1
);

blocks.stopBlockMutationWatching(index)

void

Остановить наблюдение за мутациями блока по указанному индексу. Используйте это, чтобы предотвратить ложные события block-changed при операциях замены блока.

Когда использовать

Нишевый метод. Вызывайте его перед программной заменой DOM блока, чтобы подавить ложные события block-changed. Следующий рендер включает наблюдение снова.

TypeScript
// Replace a block without triggering change events
editor.blocks.stopBlockMutationWatching(0);
// Perform block replacement...
// Mutation observer will not fire for this block

blocks.startBlockMutationWatching(blockId)

void

Снова включает наблюдение за мутациями блока, ранее заглушённого через stopBlockMutationWatching. Метод принимает id, а не индекс, потому что вставки и замены между двумя вызовами сдвигают индексы. Несуществующий id молча пропускается: блок, заменённый на месте, был создан с собственным наблюдателем.

TypeScript
const blockId = editor.blocks.getBlockByIndex(0)?.id;
editor.blocks.stopBlockMutationWatching(0);
// Perform block replacement...
if (blockId) {
  editor.blocks.startBlockMutationWatching(blockId);
}

blocks.transact(fn)

void

Объединяет все операции с блоками внутри fn в один шаг отмены. fn должна быть СИНХРОННОЙ. Операции, которые выполняются после await, в группу уже не входят. Используйте это, чтобы структурные правки нельзя было отменить частично.

TypeScript
editor.blocks.transact(() => {
  editor.blocks.insert('paragraph', { text: 'One' });
  editor.blocks.insert('paragraph', { text: 'Two' });
});
// A single Cmd+Z removes both blocks

blocks.beginTransaction()

void

Открывает группу отмены, которая остаётся открытой через асинхронные границы. Каждая операция с блоками до endTransaction() попадает в один шаг отмены.

Используйте это для жестов указателем, которые непрерывно меняют документ, например для перетаскивания угла таблицы, чтобы добавить строки. transact() здесь не помогает, потому что оборачивает только синхронную функцию. Каждый вызов сопрягайте с endTransaction().

TypeScript
editor.blocks.beginTransaction();
// ... continuous mutations across async boundaries ...
editor.blocks.endTransaction();

blocks.endTransaction()

void

Закрыть группу отмены, открытую через beginTransaction().

TypeScript
editor.blocks.beginTransaction();
// ... continuous mutations across async boundaries ...
editor.blocks.endTransaction();

blocks.transactWithoutCapture(fn)

void

Выполняет операции с блоками, ничего не записывая в историю отмен. Используйте это для автопочинки и нормализации (например, чтобы в пустой ячейке всегда был блок), через которые Cmd+Z никогда не должен проходить.

Передайте { derivedFrom: blockId, from: ['url'] }, если операции записывают данные, вычисленные из этих ключей блока. Так делает, например, загрузка, которая закончилась и заменяет блок. Они по-прежнему не добавляют шаг отмены и не сбрасывают повтор, но входят в шаг, который записал эти значения: отмена этого шага убирает их, повтор возвращает. update(), начатый внутри fn, тоже считается, хотя заканчивается позже. Пока сохранение этого блока ещё не завершено, fn выполнится после него, уже после возврата из вызова.

TypeScript
editor.blocks.transactWithoutCapture(() => {
  editor.blocks.insert('paragraph', {}, undefined, 0);
});
// Nothing was added to the undo history

blocks.setPointerDragActive(active)

void

Сообщает ядру, что перетаскивание указателем началось или закончилось. Пока оно активно, синхронизации Yjs, вызванные мутациями DOM, подавляются. Так изменения DOM в браузере во время перетаскивания не могут испортить состояние Yjs.

TypeScript
editor.blocks.setPointerDragActive(true);
// ... run the drag gesture ...
editor.blocks.setPointerDragActive(false);

Свойства

СвойствоТипОписание
isSyncingFromYjsboolean

Геттер только для чтения. Он равен true, пока идёт операция синхронизации Yjs (отмена или повтор). Инструменты читают его, чтобы пропустить очистку, которая конфликтовала бы с состоянием отмены. Обратите внимание: это СВОЙСТВО на editor.blocks, в отличие от метода isSyncingFromYjs() в React-хуке.

isPointerDragActiveboolean

Геттер только для чтения. Он равен true, пока активно перетаскивание указателем. Адаптеры фреймворков читают его, чтобы отложить программный dispatchChange посреди перетаскивания: ядро молча отбрасывает такое изменение. Повторно они отправляют его, когда перетаскивание закончится.

isApplyingRemoteChangeboolean

Геттер только для чтения. Он равен true, пока редактор применяет изменение, сделанное другим клиентом. Новый блок участника может прийти раньше записи, которая задаёт ему родителя. Инструмент-контейнер читает этот флаг, чтобы отличить такой блок от блока, который этот клиент добавляет в собственном окне синхронизации.