import type { BlockElement } from '@blockeditor/lit'; import { asyncFocusRichText, getInlineEditorByModel, matchFlavours, } from '../../../../_common/utils/index.js'; import type { ListType } from '../../../../list-block/index.js'; function addSpace(element: BlockElement, index: number) { element.model.text?.insert(' ', index); const currentText = element.selection.find('text'); element.selection.setGroup('note', [ element.selection.create('text', { from: { path: element.path, index: (currentText?.from.index ?? 0) + 1, length: 0, }, to: null, }), ]); } export function convertToList( element: BlockElement, listType: ListType, prefix: string, otherProperties?: Record ): boolean { const { page, model } = element; if (matchFlavours(model, ['affine:list'])) { return false; } if (matchFlavours(model, ['affine:paragraph'])) { const parent = page.getParent(model); if (!parent) return false; const index = parent.children.indexOf(model); addSpace(element, prefix.length); page.captureSync(); model.text?.delete(0, prefix.length + 1); const blockProps = { type: listType, text: model.text?.clone(), children: model.children, ...otherProperties, }; page.deleteBlock(model, { deleteChildren: false, }); const id = page.addBlock('affine:list', blockProps, parent, index); asyncFocusRichText(element.host, page, id)?.catch(console.error); } return true; } export function convertToParagraph( element: BlockElement, type: 'text' | 'quote' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', prefix: string ): boolean { const { page, model } = element; if (matchFlavours(model, ['affine:paragraph']) && model['type'] === type) { return false; } if (!matchFlavours(model, ['affine:paragraph'])) { const parent = page.getParent(model); if (!parent) return false; const index = parent.children.indexOf(model); addSpace(element, prefix.length); page.captureSync(); model.text?.delete(0, prefix.length + 1); const blockProps = { type: type, text: model.text?.clone(), children: model.children, }; page.deleteBlock(model, { deleteChildren: false, }); const id = page.addBlock('affine:paragraph', blockProps, parent, index); asyncFocusRichText(element.host, page, id)?.catch(console.error); } else if ( matchFlavours(model, ['affine:paragraph']) && model['type'] !== type ) { addSpace(element, prefix.length); page.captureSync(); model.text?.delete(0, prefix.length + 1); const inlineEditor = getInlineEditorByModel(element.host, model); if (inlineEditor) { inlineEditor.setInlineRange({ index: 0, length: 0, }); } page.updateBlock(model, { type: type }); } return true; } export function convertToDivider( element: BlockElement, prefix: string ): boolean { const { page, model } = element; if ( matchFlavours(model, ['affine:divider']) || (matchFlavours(model, ['affine:paragraph']) && model.type === 'quote') ) { return false; } if (!matchFlavours(model, ['affine:divider'])) { const parent = page.getParent(model); if (!parent) return false; const index = parent.children.indexOf(model); addSpace(element, prefix.length); page.captureSync(); model.text?.delete(0, prefix.length + 1); const blockProps = { children: model.children, }; page.addBlock('affine:divider', blockProps, parent, index); const nextBlock = parent.children[index + 1]; if (nextBlock) { asyncFocusRichText(element.host, page, nextBlock.id)?.catch( console.error ); } else { const nextId = page.addBlock('affine:paragraph', {}, parent); asyncFocusRichText(element.host, page, nextId)?.catch(console.error); } } return true; }