Skip to content

Commit

Permalink
Merge branch 'master' into u/jisong/2880
Browse files Browse the repository at this point in the history
  • Loading branch information
JiuqingSong authored Nov 22, 2024
2 parents 618c202 + 2a249dd commit 53d18bd
Show file tree
Hide file tree
Showing 56 changed files with 2,931 additions and 154 deletions.
1 change: 1 addition & 0 deletions packages/roosterjs-content-model-api/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ export { setModelIndentation } from './modelApi/block/setModelIndentation';
export { matchLink } from './modelApi/link/matchLink';
export { promoteLink } from './modelApi/link/promoteLink';
export { getListAnnounceData } from './modelApi/list/getListAnnounceData';
export { queryContentModelBlocks } from './modelApi/common/queryContentModelBlocks';
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import type {
ContentModelBlockType,
ReadonlyContentModelBlock,
ReadonlyContentModelBlockBase,
ReadonlyContentModelBlockGroup,
} from 'roosterjs-content-model-types';

/**
* Query content model blocks
* @param group The block group to query
* @param type The type of block to query
* @param filter Optional selector to filter the blocks
* @param findFirstOnly True to return the first block only, false to return all blocks
*/
export function queryContentModelBlocks<T extends ReadonlyContentModelBlock>(
group: ReadonlyContentModelBlockGroup,
type: T extends ReadonlyContentModelBlockBase<infer U> ? U : never,
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;
}
const block = group.blocks[i];

switch (block.blockType) {
case 'Paragraph':
case 'Divider':
case 'Entity':
if (isExpectedBlockType(block, type, filter)) {
elements.push(block);
}
break;
case 'BlockGroup':
if (isExpectedBlockType(block, type, filter)) {
elements.push(block);
}
const results = queryContentModelBlocks<T>(block, type, filter, findFirstOnly);
elements.push(...results);
break;
case 'Table':
if (isExpectedBlockType(block, type, filter)) {
elements.push(block);
}
for (const row of block.rows) {
for (const cell of row.cells) {
const results = queryContentModelBlocks<T>(
cell,
type,
filter,
findFirstOnly
);
elements.push(...results);
}
}
break;
}
}
return elements;
}

function isExpectedBlockType<T extends ReadonlyContentModelBlock>(
block: ReadonlyContentModelBlock,
type: ContentModelBlockType,
filter?: (element: T) => element is T
): block is T {
return isBlockType<T>(block, type) && (!filter || filter(block));
}

function isBlockType<T extends ReadonlyContentModelBlock>(
block: ReadonlyContentModelBlock,
type: ContentModelBlockType
): block is T {
return block.blockType == type;
}
Loading

0 comments on commit 53d18bd

Please sign in to comment.