diff --git a/packages/roosterjs-content-model-api/lib/modelApi/common/queryContentModelBlocks.ts b/packages/roosterjs-content-model-api/lib/modelApi/common/queryContentModelBlocks.ts index afceced01b5..aed7d04f0f7 100644 --- a/packages/roosterjs-content-model-api/lib/modelApi/common/queryContentModelBlocks.ts +++ b/packages/roosterjs-content-model-api/lib/modelApi/common/queryContentModelBlocks.ts @@ -2,7 +2,6 @@ import type { ContentModelBlockType, ReadonlyContentModelBlock, ReadonlyContentModelBlockGroup, - ReadonlyContentModelTable, } from 'roosterjs-content-model-types'; /** @@ -36,73 +35,74 @@ export function queryContentModelBlocks( ): T[] { const { blockType, filter, findFirstOnly } = options; const type = blockType || 'Paragraph'; - - return queryContentModelBlocksInternal(group, type, filter, findFirstOnly); + const elements: T[] = []; + for (let i = 0; i < group.blocks.length; i++) { + if (findFirstOnly && elements.length > 0) { + return elements; + } + const block = group.blocks[i]; + const results = queryContentModelBlocksInternal(block, type, filter, findFirstOnly); + elements.push(...results); + } + return elements; } function queryContentModelBlocksInternal( - group: ReadonlyContentModelBlockGroup, + block: ReadonlyContentModelBlock, type: ContentModelBlockType, filter?: (element: T) => element is T, findFirstOnly?: boolean ): T[] { const elements: T[] = []; - for (let i = 0; i < group.blocks.length; i++) { - if (findFirstOnly && elements.length > 0) { - return elements; + if (isExpectedBlockType(block, type, filter)) { + elements.push(block); + } + + if (block.blockType == 'BlockGroup') { + for (const childBlock of block.blocks) { + if (findFirstOnly && elements.length > 0) { + return elements; + } + const results = queryContentModelBlocksInternal( + childBlock, + type, + filter, + findFirstOnly + ); + elements.push(...results); } - const block = group.blocks[i]; - switch (block.blockType) { - case 'BlockGroup': - if (isBlockType(block, type) && (!filter || filter(block))) { - elements.push(block); - } - const blockGroupsResults = queryContentModelBlocksInternal( - block, - type, - filter, - findFirstOnly - ); - elements.push(...blockGroupsResults); - break; - case 'Table': - if (isBlockType(block, type) && (!filter || filter(block))) { - elements.push(block); - } - const tableResults = searchInTables(block, type, filter, findFirstOnly); - elements.push(...tableResults); - break; - case 'Divider': - case 'Entity': - case 'Paragraph': - if (isBlockType(block, type) && (!filter || filter(block))) { - elements.push(block); + } + + if (block.blockType == 'Table') { + const table = block; + for (const row of table.rows) { + for (const cell of row.cells) { + for (const cellBlock of cell.blocks) { + const results = queryContentModelBlocksInternal( + cellBlock, + type, + filter, + findFirstOnly + ); + elements.push(...results); } - break; + } } } return elements; } +function isExpectedBlockType( + block: ReadonlyContentModelBlock, + type: ContentModelBlockType, + filter?: (element: T) => element is T +): block is T { + return isBlockType(block, type) && (!filter || filter(block)); +} + function isBlockType( block: ReadonlyContentModelBlock, type: string ): block is T { return block.blockType == type; } - -function searchInTables( - table: ReadonlyContentModelTable, - type: ContentModelBlockType, - filter?: (element: T) => element is T, - findFirstOnly?: boolean -): T[] { - const blocks: T[] = []; - for (const row of table.rows) { - for (const cell of row.cells) { - const items = queryContentModelBlocksInternal(cell, type, filter, findFirstOnly); - blocks.push(...items); - } - } - return blocks; -}