import { assertExists } from '@blockeditor/global/utils'; import type { Page } from '@blockeditor/store'; import { type BlockModel, Text } from '@blockeditor/store'; import type { Flavour } from '../../../models.js'; /** * This file should only contain functions that are used to * operate on block models in store, which means that this operations * just operate on data and will not involve in something about ui like selection reset. */ export function mergeToCodeModel(models: BlockModel[]) { if (models.length === 0) { throw new Error('No models to merge'); } const page = models[0].page; const parent = page.getParent(models[0]); assertExists(parent); const index = parent.children.indexOf(models[0]); const text = models .map(model => { if (model.text instanceof Text) { return model.text.toString(); } return null; }) .filter(Boolean) .join('\n'); models.map(model => page.deleteBlock(model)); const id = page.addBlock( 'affine:code', { text: new Text(text) }, parent, index ); return id; } export function transformModel( model: BlockModel, flavour: Flavour, props?: Parameters[1] ) { const page = model.page; const parent = page.getParent(model); assertExists(parent); const blockProps: { type?: string; text?: Text; children?: BlockModel[]; } = { text: model?.text?.clone(), // should clone before `deleteBlock` children: model.children, ...props, }; const index = parent.children.indexOf(model); // Sometimes the new block can not be added due to some reason, e.g. invalid schema check. // So we need to try to add the new block first, and if it fails, we will not delete the old block. const id = page.addBlock(flavour, blockProps, parent, index); page.deleteBlock(model); return id; }