roosterjs-content-model-dom 9.34.0 → 9.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.d.ts +2 -1
- package/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.js +4 -2
- package/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.js.map +1 -1
- package/lib/modelApi/editing/mergeModel.js +1 -1
- package/lib/modelApi/editing/mergeModel.js.map +1 -1
- package/lib/modelApi/selection/collectSelections.d.ts +4 -2
- package/lib/modelApi/selection/collectSelections.js +2 -2
- package/lib/modelApi/selection/collectSelections.js.map +1 -1
- package/lib/modelToDom/handlers/handleParagraph.js +8 -2
- package/lib/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/lib-amd/modelApi/editing/getClosestAncestorBlockGroupIndex.d.ts +2 -1
- package/lib-amd/modelApi/editing/getClosestAncestorBlockGroupIndex.js +4 -2
- package/lib-amd/modelApi/editing/getClosestAncestorBlockGroupIndex.js.map +1 -1
- package/lib-amd/modelApi/editing/mergeModel.js +1 -1
- package/lib-amd/modelApi/editing/mergeModel.js.map +1 -1
- package/lib-amd/modelApi/selection/collectSelections.d.ts +4 -2
- package/lib-amd/modelApi/selection/collectSelections.js +2 -2
- package/lib-amd/modelApi/selection/collectSelections.js.map +1 -1
- package/lib-amd/modelToDom/handlers/handleParagraph.js +8 -2
- package/lib-amd/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/lib-mjs/modelApi/editing/getClosestAncestorBlockGroupIndex.d.ts +2 -1
- package/lib-mjs/modelApi/editing/getClosestAncestorBlockGroupIndex.js +4 -2
- package/lib-mjs/modelApi/editing/getClosestAncestorBlockGroupIndex.js.map +1 -1
- package/lib-mjs/modelApi/editing/mergeModel.js +1 -1
- package/lib-mjs/modelApi/editing/mergeModel.js.map +1 -1
- package/lib-mjs/modelApi/selection/collectSelections.d.ts +4 -2
- package/lib-mjs/modelApi/selection/collectSelections.js +2 -2
- package/lib-mjs/modelApi/selection/collectSelections.js.map +1 -1
- package/lib-mjs/modelToDom/handlers/handleParagraph.js +8 -2
- package/lib-mjs/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,5 +4,6 @@ import type { ContentModelBlockGroup, ContentModelBlockGroupType, ReadonlyConten
|
|
|
4
4
|
* @param path The block group path, from the closest one to root
|
|
5
5
|
* @param blockGroupTypes The expected block group types
|
|
6
6
|
* @param stopTypes @optional Block group types that will cause stop searching
|
|
7
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
7
8
|
*/
|
|
8
|
-
export declare function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(path: ReadonlyContentModelBlockGroup[], blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes?: ContentModelBlockGroupType[]): number;
|
|
9
|
+
export declare function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(path: ReadonlyContentModelBlockGroup[], blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes?: ContentModelBlockGroupType[], isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean): number;
|
|
@@ -6,12 +6,14 @@ exports.getClosestAncestorBlockGroupIndex = void 0;
|
|
|
6
6
|
* @param path The block group path, from the closest one to root
|
|
7
7
|
* @param blockGroupTypes The expected block group types
|
|
8
8
|
* @param stopTypes @optional Block group types that will cause stop searching
|
|
9
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
9
10
|
*/
|
|
10
|
-
function getClosestAncestorBlockGroupIndex(path, blockGroupTypes, stopTypes) {
|
|
11
|
+
function getClosestAncestorBlockGroupIndex(path, blockGroupTypes, stopTypes, isValidTarget) {
|
|
11
12
|
if (stopTypes === void 0) { stopTypes = []; }
|
|
12
13
|
for (var i = 0; i < path.length; i++) {
|
|
13
14
|
var group = path[i];
|
|
14
|
-
if (blockGroupTypes.indexOf(group.blockGroupType) >= 0
|
|
15
|
+
if (blockGroupTypes.indexOf(group.blockGroupType) >= 0 &&
|
|
16
|
+
(!isValidTarget || isValidTarget(group))) {
|
|
15
17
|
return i;
|
|
16
18
|
}
|
|
17
19
|
else if (stopTypes.indexOf(group.blockGroupType) >= 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getClosestAncestorBlockGroupIndex.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.ts"],"names":[],"mappings":";;;AAOA
|
|
1
|
+
{"version":3,"file":"getClosestAncestorBlockGroupIndex.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.ts"],"names":[],"mappings":";;;AAOA;;;;;;GAMG;AACH,SAAgB,iCAAiC,CAC7C,IAAsC,EACtC,eAAsC,EACtC,SAA4C,EAC5C,aAAkE;IADlE,0BAAA,EAAA,cAA4C;IAG5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAClC,IAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,IACK,eAA4B,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;YAChE,CAAC,CAAC,aAAa,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,EAC1C;YACE,OAAO,CAAC,CAAC;SACZ;aAAM,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE;YACrD,oDAAoD;YACpD,+DAA+D;YAC/D,iGAAiG;YACjG,0FAA0F;YAC1F,OAAO,CAAC,CAAC,CAAC;SACb;KACJ;IAED,OAAO,CAAC,CAAC,CAAC;AACd,CAAC;AAxBD,8EAwBC","sourcesContent":["import type {\n ContentModelBlockGroup,\n ContentModelBlockGroupType,\n ReadonlyContentModelBlockGroup,\n TypeOfBlockGroup,\n} from 'roosterjs-content-model-types';\n\n/**\n * Get index of closest ancestor block group of the expected block group type. If not found, return -1\n * @param path The block group path, from the closest one to root\n * @param blockGroupTypes The expected block group types\n * @param stopTypes @optional Block group types that will cause stop searching\n * @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target\n */\nexport function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(\n path: ReadonlyContentModelBlockGroup[],\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[] = [],\n isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean\n): number {\n for (let i = 0; i < path.length; i++) {\n const group = path[i];\n\n if (\n (blockGroupTypes as string[]).indexOf(group.blockGroupType) >= 0 &&\n (!isValidTarget || isValidTarget(group))\n ) {\n return i;\n } else if (stopTypes.indexOf(group.blockGroupType) >= 0) {\n // Do not go across boundary specified by stopTypes.\n // For example, in most case we will set table as the boundary,\n // in order to allow modify list item under a table when the table itself is in another list item\n // Although this is not very likely to happen in most case, but we still need to handle it\n return -1;\n }\n }\n\n return -1;\n}\n"]}
|
|
@@ -177,7 +177,7 @@ function mergeTables(markerPosition, newTable, source) {
|
|
|
177
177
|
function mergeList(markerPosition, newList) {
|
|
178
178
|
splitParagraph(markerPosition, newList.format);
|
|
179
179
|
var path = markerPosition.path, paragraph = markerPosition.paragraph;
|
|
180
|
-
var listItemIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem']);
|
|
180
|
+
var listItemIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell']);
|
|
181
181
|
var listItem = path[listItemIndex];
|
|
182
182
|
var listParent = path[listItemIndex + 1]; // It is ok here when index is -1, that means there is no list and we just insert a new paragraph and use path[0] as its parent
|
|
183
183
|
var blockIndex = listParent.blocks.indexOf(listItem || paragraph);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeModel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/mergeModel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addBlock } from '../common/addBlock';\nimport { addSegment } from '../common/addSegment';\nimport { applyTableFormat } from './applyTableFormat';\nimport { createListItem } from '../creators/createListItem';\nimport { createParagraph } from '../creators/createParagraph';\nimport { createSelectionMarker } from '../creators/createSelectionMarker';\nimport { createTableCell } from '../creators/createTableCell';\nimport { deleteSelection } from './deleteSelection';\nimport { EmptySegmentFormat } from '../../constants/EmptySegmentFormat';\nimport { getClosestAncestorBlockGroupIndex } from './getClosestAncestorBlockGroupIndex';\nimport { getObjectKeys } from '../..//domUtils/getObjectKeys';\nimport { mutateBlock } from '../common/mutate';\nimport { normalizeContentModel } from '../common/normalizeContentModel';\nimport { normalizeTable } from './normalizeTable';\nimport type {\n ContentModelBlock,\n ContentModelBlockFormat,\n ContentModelDocument,\n ContentModelHyperLinkFormat,\n ContentModelListItem,\n ContentModelParagraph,\n ContentModelSegmentFormat,\n ContentModelTable,\n FormatContentModelContext,\n InsertPoint,\n MergeModelOption,\n ReadonlyContentModelBlock,\n ReadonlyContentModelBlockGroup,\n ReadonlyContentModelDocument,\n ShallowMutableContentModelParagraph,\n} from 'roosterjs-content-model-types';\n\nconst HeadingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\nconst KeysOfSegmentFormat = getObjectKeys(EmptySegmentFormat);\n\ntype MergeFormatTypes = 'mergeAll' | 'keepSourceEmphasisFormat' | 'preferSource' | 'preferTarget';\n\n/**\n * Merge source model into target mode\n * @param target Target Content Model that will merge content into\n * @param source Source Content Model will be merged to target model\n * @param context Format context. When call this function inside formatContentModel, provide this context so that formatContentModel will do extra handling to the result\n * @param options More options, see MergeModelOption\n * @returns Insert point after merge, or null if there is no insert point\n */\nexport function mergeModel(\n target: ReadonlyContentModelDocument,\n source: ContentModelDocument,\n context?: FormatContentModelContext,\n options?: MergeModelOption\n): InsertPoint | null {\n const insertPosition =\n options?.insertPosition ?? deleteSelection(target, [], context).insertPoint;\n\n const { addParagraphAfterMergedContent, mergeFormat, mergeTable } = options || {};\n\n if (addParagraphAfterMergedContent && !mergeTable) {\n const { paragraph, marker } = insertPosition || {};\n const newPara = createParagraph(false /* isImplicit */, paragraph?.format, marker?.format);\n addBlock(source, newPara);\n }\n\n if (insertPosition) {\n if (mergeFormat && mergeFormat != 'none') {\n const newFormat: ContentModelSegmentFormat = {\n ...(target.format || {}),\n ...insertPosition.marker.format,\n };\n\n applyDefaultFormat(source, newFormat, mergeFormat);\n }\n\n for (let i = 0; i < source.blocks.length; i++) {\n const block = source.blocks[i];\n\n switch (block.blockType) {\n case 'Paragraph':\n mergeParagraph(insertPosition, block, i == 0, context, options);\n break;\n\n case 'Divider':\n insertBlock(insertPosition, block);\n break;\n\n case 'Entity':\n insertBlock(insertPosition, block);\n context?.newEntities.push(block);\n break;\n\n case 'Table':\n if (source.blocks.length == 1 && mergeTable) {\n mergeTables(insertPosition, block, source);\n } else {\n insertBlock(insertPosition, block);\n }\n break;\n\n case 'BlockGroup':\n switch (block.blockGroupType) {\n case 'General':\n case 'FormatContainer':\n insertBlock(insertPosition, block);\n break;\n case 'ListItem':\n mergeList(insertPosition, block);\n break;\n }\n break;\n }\n }\n }\n\n normalizeContentModel(target);\n\n return insertPosition;\n}\n\nfunction mergeParagraph(\n markerPosition: InsertPoint,\n newPara: ContentModelParagraph,\n mergeToCurrentParagraph: boolean,\n context?: FormatContentModelContext,\n option?: MergeModelOption\n) {\n const { paragraph, marker } = markerPosition;\n const newParagraph = mergeToCurrentParagraph\n ? paragraph\n : splitParagraph(markerPosition, newPara.format);\n const segmentIndex = newParagraph.segments.indexOf(marker);\n\n if (option?.mergeFormat == 'none' && mergeToCurrentParagraph) {\n newParagraph.segments.forEach(segment => {\n segment.format = { ...(newParagraph.segmentFormat || {}), ...segment.format };\n });\n delete newParagraph.segmentFormat;\n }\n if (segmentIndex >= 0) {\n for (let i = 0; i < newPara.segments.length; i++) {\n const segment = newPara.segments[i];\n\n newParagraph.segments.splice(segmentIndex + i, 0, segment);\n\n if (context) {\n if (segment.segmentType == 'Entity') {\n context.newEntities.push(segment);\n }\n\n if (segment.segmentType == 'Image') {\n context.newImages.push(segment);\n }\n }\n }\n }\n\n if (newPara.decorator) {\n newParagraph.decorator = { ...newPara.decorator };\n if (HeadingTags.indexOf(newParagraph.decorator.tagName) > -1) {\n const sourceKeys: (keyof ContentModelSegmentFormat)[] = getObjectKeys(\n newParagraph.decorator.format\n );\n const segmentDecoratorKeys: (keyof ContentModelSegmentFormat)[] = getObjectKeys(\n newParagraph.segmentFormat || {}\n );\n\n sourceKeys.forEach(key => {\n if (segmentDecoratorKeys.indexOf(key) > -1) {\n delete newParagraph.segmentFormat?.[key];\n }\n });\n }\n }\n\n if (!mergeToCurrentParagraph) {\n newParagraph.format = newPara.format;\n } else {\n newParagraph.format = {\n ...newParagraph.format,\n ...newPara.format,\n };\n }\n}\n\nfunction mergeTables(\n markerPosition: InsertPoint,\n newTable: ContentModelTable,\n source: ContentModelDocument\n) {\n const { tableContext, marker } = markerPosition;\n\n if (tableContext && source.blocks.length == 1 && source.blocks[0] == newTable) {\n const { table: readonlyTable, colIndex, rowIndex } = tableContext;\n const table = mutateBlock(readonlyTable);\n\n for (let i = 0; i < newTable.rows.length; i++) {\n for (let j = 0; j < newTable.rows[i].cells.length; j++) {\n const newCell = newTable.rows[i].cells[j];\n\n if (i == 0 && colIndex + j >= table.rows[0].cells.length) {\n for (let k = 0; k < table.rows.length; k++) {\n const leftCell = table.rows[k]?.cells[colIndex + j - 1];\n table.rows[k].cells[colIndex + j] = createTableCell(\n false /*spanLeft*/,\n false /*spanAbove*/,\n leftCell?.isHeader,\n leftCell?.format\n );\n }\n }\n\n if (j == 0 && rowIndex + i >= table.rows.length) {\n if (!table.rows[rowIndex + i]) {\n table.rows[rowIndex + i] = {\n cells: [],\n format: {},\n height: 0,\n };\n }\n\n for (let k = 0; k < table.rows[rowIndex].cells.length; k++) {\n const aboveCell = table.rows[rowIndex + i - 1]?.cells[k];\n table.rows[rowIndex + i].cells[k] = createTableCell(\n false /*spanLeft*/,\n false /*spanAbove*/,\n false /*isHeader*/,\n aboveCell?.format\n );\n }\n }\n\n const oldCell = table.rows[rowIndex + i].cells[colIndex + j];\n table.rows[rowIndex + i].cells[colIndex + j] = newCell;\n\n if (i == 0 && j == 0) {\n const newMarker = createSelectionMarker(marker.format);\n const newPara = addSegment(newCell, newMarker);\n\n if (markerPosition.path[0] == oldCell) {\n // Update insert point to match the change result\n markerPosition.path[0] = newCell;\n markerPosition.marker = newMarker;\n markerPosition.paragraph = newPara;\n }\n }\n }\n }\n\n normalizeTable(table, markerPosition.marker.format);\n applyTableFormat(table, undefined /*newFormat*/, true /*keepCellShade*/);\n } else {\n insertBlock(markerPosition, newTable);\n }\n}\n\nfunction mergeList(markerPosition: InsertPoint, newList: ContentModelListItem) {\n splitParagraph(markerPosition, newList.format);\n\n const { path, paragraph } = markerPosition;\n\n const listItemIndex = getClosestAncestorBlockGroupIndex(path, ['ListItem']);\n const listItem = path[listItemIndex] as ContentModelListItem;\n const listParent = path[listItemIndex + 1]; // It is ok here when index is -1, that means there is no list and we just insert a new paragraph and use path[0] as its parent\n const blockIndex = listParent.blocks.indexOf(listItem || paragraph);\n\n if (blockIndex >= 0) {\n mutateBlock(listParent).blocks.splice(blockIndex, 0, newList);\n }\n\n if (listItem) {\n listItem?.levels.forEach((level, i) => {\n newList.levels[i] = { ...level };\n });\n }\n}\n\nfunction splitParagraph(markerPosition: InsertPoint, newParaFormat: ContentModelBlockFormat) {\n const { paragraph, marker, path } = markerPosition;\n const segmentIndex = paragraph.segments.indexOf(marker);\n const paraIndex = path[0].blocks.indexOf(paragraph);\n const newParagraph: ShallowMutableContentModelParagraph = createParagraph(\n false /*isImplicit*/,\n { ...paragraph.format, ...newParaFormat },\n paragraph.segmentFormat\n );\n\n if (segmentIndex >= 0) {\n newParagraph.segments = paragraph.segments.splice(segmentIndex);\n }\n\n if (paraIndex >= 0) {\n mutateBlock(path[0]).blocks.splice(paraIndex + 1, 0, newParagraph);\n }\n\n const listItemIndex = getClosestAncestorBlockGroupIndex(\n path,\n ['ListItem'],\n ['FormatContainer', 'TableCell']\n );\n const listItem = path[listItemIndex] as ContentModelListItem;\n\n if (listItem) {\n const listParent = listItemIndex >= 0 ? path[listItemIndex + 1] : null;\n const blockIndex = listParent ? listParent.blocks.indexOf(listItem) : -1;\n\n if (blockIndex >= 0 && listParent) {\n const newListItem = createListItem(listItem.levels, listItem.formatHolder.format);\n\n if (paraIndex >= 0) {\n newListItem.blocks = listItem.blocks.splice(paraIndex + 1);\n }\n\n if (blockIndex >= 0) {\n mutateBlock(listParent).blocks.splice(blockIndex + 1, 0, newListItem);\n }\n\n path[listItemIndex] = newListItem;\n }\n }\n\n markerPosition.paragraph = newParagraph;\n\n return newParagraph;\n}\n\nfunction insertBlock(markerPosition: InsertPoint, block: ContentModelBlock) {\n const { path } = markerPosition;\n const newParaFormat = block.blockType !== 'Paragraph' ? {} : block.format;\n const newPara = splitParagraph(markerPosition, newParaFormat);\n const blockIndex = path[0].blocks.indexOf(newPara);\n\n if (blockIndex >= 0) {\n mutateBlock(path[0]).blocks.splice(blockIndex, 0, block);\n }\n}\n\nfunction applyDefaultFormat(\n group: ReadonlyContentModelBlockGroup,\n format: ContentModelSegmentFormat,\n applyDefaultFormatOption: MergeFormatTypes\n) {\n group.blocks.forEach(block => {\n mergeBlockFormat(applyDefaultFormatOption, block);\n\n switch (block.blockType) {\n case 'BlockGroup':\n if (block.blockGroupType == 'ListItem') {\n mutateBlock(block).formatHolder.format = mergeSegmentFormat(\n applyDefaultFormatOption,\n format,\n block.formatHolder.format\n );\n }\n applyDefaultFormat(block, format, applyDefaultFormatOption);\n break;\n\n case 'Table':\n block.rows.forEach(row =>\n row.cells.forEach(cell => {\n applyDefaultFormat(cell, format, applyDefaultFormatOption);\n })\n );\n break;\n\n case 'Paragraph':\n const paragraphFormat = block.decorator?.format || {};\n const paragraph = mutateBlock(block);\n\n paragraph.segments.forEach(segment => {\n if (segment.segmentType == 'General') {\n applyDefaultFormat(segment, format, applyDefaultFormatOption);\n }\n\n segment.format = mergeSegmentFormat(applyDefaultFormatOption, format, {\n ...paragraphFormat,\n ...segment.format,\n });\n\n if (segment.link) {\n segment.link.format = mergeLinkFormat(\n applyDefaultFormatOption,\n format,\n segment.link.format\n );\n }\n });\n\n if (applyDefaultFormatOption === 'keepSourceEmphasisFormat') {\n delete paragraph.decorator;\n }\n break;\n }\n });\n}\n\nfunction mergeBlockFormat(applyDefaultFormatOption: string, block: ReadonlyContentModelBlock) {\n if (applyDefaultFormatOption == 'keepSourceEmphasisFormat' && block.format.backgroundColor) {\n delete mutateBlock(block).format.backgroundColor;\n }\n}\n\n/**\n * Hyperlink format type definition only contains backgroundColor and underline.\n * So create a minimum object with the styles supported in Hyperlink to be used in merge.\n */\nfunction getSegmentFormatInLinkFormat(\n targetFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n const result: ContentModelHyperLinkFormat = {};\n if (targetFormat.backgroundColor) {\n result.backgroundColor = targetFormat.backgroundColor;\n }\n if (targetFormat.underline) {\n result.underline = targetFormat.underline;\n }\n\n return result;\n}\n\nfunction mergeLinkFormat(\n applyDefaultFormatOption: MergeFormatTypes,\n targetFormat: ContentModelSegmentFormat,\n sourceFormat: ContentModelHyperLinkFormat\n) {\n switch (applyDefaultFormatOption) {\n case 'mergeAll':\n case 'preferSource':\n return { ...getSegmentFormatInLinkFormat(targetFormat), ...sourceFormat };\n case 'keepSourceEmphasisFormat':\n return {\n // Hyperlink segment format contains other attributes such as LinkFormat\n // so we have to retain them\n ...getFormatWithoutSegmentFormat(sourceFormat),\n // Link format only have Text color, background color, Underline, but only\n // text color + background color should be merged from the target\n ...getSegmentFormatInLinkFormat(targetFormat),\n // Get the semantic format of the source\n ...getSemanticFormat(sourceFormat),\n // The text color of the hyperlink should not be merged and\n // we should always retain the source text color\n ...getHyperlinkTextColor(sourceFormat),\n };\n case 'preferTarget':\n return { ...sourceFormat, ...getSegmentFormatInLinkFormat(targetFormat) };\n }\n}\n\nfunction mergeSegmentFormat(\n applyDefaultFormatOption: MergeFormatTypes,\n targetFormat: ContentModelSegmentFormat,\n sourceFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n switch (applyDefaultFormatOption) {\n case 'mergeAll':\n case 'preferSource':\n return { ...targetFormat, ...sourceFormat };\n case 'preferTarget':\n return { ...sourceFormat, ...targetFormat };\n case 'keepSourceEmphasisFormat':\n return {\n ...getFormatWithoutSegmentFormat(sourceFormat),\n ...targetFormat,\n ...getSemanticFormat(sourceFormat),\n };\n }\n}\n\nfunction getSemanticFormat(segmentFormat: ContentModelSegmentFormat): ContentModelSegmentFormat {\n const result: ContentModelSegmentFormat = {};\n\n const { fontWeight, italic, underline } = segmentFormat;\n\n if (fontWeight && fontWeight != 'normal') {\n result.fontWeight = fontWeight;\n }\n if (italic) {\n result.italic = italic;\n }\n if (underline) {\n result.underline = underline;\n }\n\n return result;\n}\n\n/**\n * Segment format can also contain other type of metadata, for example in Images/Hyperlink,\n * we want to preserve these properties when merging format\n */\nfunction getFormatWithoutSegmentFormat(\n sourceFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n const resultFormat = {\n ...sourceFormat,\n };\n KeysOfSegmentFormat.forEach(key => delete resultFormat[key]);\n return resultFormat;\n}\nfunction getHyperlinkTextColor(sourceFormat: ContentModelHyperLinkFormat) {\n const result: ContentModelHyperLinkFormat = {};\n if (sourceFormat.textColor) {\n result.textColor = sourceFormat.textColor;\n }\n\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mergeModel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/mergeModel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addBlock } from '../common/addBlock';\nimport { addSegment } from '../common/addSegment';\nimport { applyTableFormat } from './applyTableFormat';\nimport { createListItem } from '../creators/createListItem';\nimport { createParagraph } from '../creators/createParagraph';\nimport { createSelectionMarker } from '../creators/createSelectionMarker';\nimport { createTableCell } from '../creators/createTableCell';\nimport { deleteSelection } from './deleteSelection';\nimport { EmptySegmentFormat } from '../../constants/EmptySegmentFormat';\nimport { getClosestAncestorBlockGroupIndex } from './getClosestAncestorBlockGroupIndex';\nimport { getObjectKeys } from '../..//domUtils/getObjectKeys';\nimport { mutateBlock } from '../common/mutate';\nimport { normalizeContentModel } from '../common/normalizeContentModel';\nimport { normalizeTable } from './normalizeTable';\nimport type {\n ContentModelBlock,\n ContentModelBlockFormat,\n ContentModelDocument,\n ContentModelHyperLinkFormat,\n ContentModelListItem,\n ContentModelParagraph,\n ContentModelSegmentFormat,\n ContentModelTable,\n FormatContentModelContext,\n InsertPoint,\n MergeModelOption,\n ReadonlyContentModelBlock,\n ReadonlyContentModelBlockGroup,\n ReadonlyContentModelDocument,\n ShallowMutableContentModelParagraph,\n} from 'roosterjs-content-model-types';\n\nconst HeadingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\nconst KeysOfSegmentFormat = getObjectKeys(EmptySegmentFormat);\n\ntype MergeFormatTypes = 'mergeAll' | 'keepSourceEmphasisFormat' | 'preferSource' | 'preferTarget';\n\n/**\n * Merge source model into target mode\n * @param target Target Content Model that will merge content into\n * @param source Source Content Model will be merged to target model\n * @param context Format context. When call this function inside formatContentModel, provide this context so that formatContentModel will do extra handling to the result\n * @param options More options, see MergeModelOption\n * @returns Insert point after merge, or null if there is no insert point\n */\nexport function mergeModel(\n target: ReadonlyContentModelDocument,\n source: ContentModelDocument,\n context?: FormatContentModelContext,\n options?: MergeModelOption\n): InsertPoint | null {\n const insertPosition =\n options?.insertPosition ?? deleteSelection(target, [], context).insertPoint;\n\n const { addParagraphAfterMergedContent, mergeFormat, mergeTable } = options || {};\n\n if (addParagraphAfterMergedContent && !mergeTable) {\n const { paragraph, marker } = insertPosition || {};\n const newPara = createParagraph(false /* isImplicit */, paragraph?.format, marker?.format);\n addBlock(source, newPara);\n }\n\n if (insertPosition) {\n if (mergeFormat && mergeFormat != 'none') {\n const newFormat: ContentModelSegmentFormat = {\n ...(target.format || {}),\n ...insertPosition.marker.format,\n };\n\n applyDefaultFormat(source, newFormat, mergeFormat);\n }\n\n for (let i = 0; i < source.blocks.length; i++) {\n const block = source.blocks[i];\n\n switch (block.blockType) {\n case 'Paragraph':\n mergeParagraph(insertPosition, block, i == 0, context, options);\n break;\n\n case 'Divider':\n insertBlock(insertPosition, block);\n break;\n\n case 'Entity':\n insertBlock(insertPosition, block);\n context?.newEntities.push(block);\n break;\n\n case 'Table':\n if (source.blocks.length == 1 && mergeTable) {\n mergeTables(insertPosition, block, source);\n } else {\n insertBlock(insertPosition, block);\n }\n break;\n\n case 'BlockGroup':\n switch (block.blockGroupType) {\n case 'General':\n case 'FormatContainer':\n insertBlock(insertPosition, block);\n break;\n case 'ListItem':\n mergeList(insertPosition, block);\n break;\n }\n break;\n }\n }\n }\n\n normalizeContentModel(target);\n\n return insertPosition;\n}\n\nfunction mergeParagraph(\n markerPosition: InsertPoint,\n newPara: ContentModelParagraph,\n mergeToCurrentParagraph: boolean,\n context?: FormatContentModelContext,\n option?: MergeModelOption\n) {\n const { paragraph, marker } = markerPosition;\n const newParagraph = mergeToCurrentParagraph\n ? paragraph\n : splitParagraph(markerPosition, newPara.format);\n const segmentIndex = newParagraph.segments.indexOf(marker);\n\n if (option?.mergeFormat == 'none' && mergeToCurrentParagraph) {\n newParagraph.segments.forEach(segment => {\n segment.format = { ...(newParagraph.segmentFormat || {}), ...segment.format };\n });\n delete newParagraph.segmentFormat;\n }\n if (segmentIndex >= 0) {\n for (let i = 0; i < newPara.segments.length; i++) {\n const segment = newPara.segments[i];\n\n newParagraph.segments.splice(segmentIndex + i, 0, segment);\n\n if (context) {\n if (segment.segmentType == 'Entity') {\n context.newEntities.push(segment);\n }\n\n if (segment.segmentType == 'Image') {\n context.newImages.push(segment);\n }\n }\n }\n }\n\n if (newPara.decorator) {\n newParagraph.decorator = { ...newPara.decorator };\n if (HeadingTags.indexOf(newParagraph.decorator.tagName) > -1) {\n const sourceKeys: (keyof ContentModelSegmentFormat)[] = getObjectKeys(\n newParagraph.decorator.format\n );\n const segmentDecoratorKeys: (keyof ContentModelSegmentFormat)[] = getObjectKeys(\n newParagraph.segmentFormat || {}\n );\n\n sourceKeys.forEach(key => {\n if (segmentDecoratorKeys.indexOf(key) > -1) {\n delete newParagraph.segmentFormat?.[key];\n }\n });\n }\n }\n\n if (!mergeToCurrentParagraph) {\n newParagraph.format = newPara.format;\n } else {\n newParagraph.format = {\n ...newParagraph.format,\n ...newPara.format,\n };\n }\n}\n\nfunction mergeTables(\n markerPosition: InsertPoint,\n newTable: ContentModelTable,\n source: ContentModelDocument\n) {\n const { tableContext, marker } = markerPosition;\n\n if (tableContext && source.blocks.length == 1 && source.blocks[0] == newTable) {\n const { table: readonlyTable, colIndex, rowIndex } = tableContext;\n const table = mutateBlock(readonlyTable);\n\n for (let i = 0; i < newTable.rows.length; i++) {\n for (let j = 0; j < newTable.rows[i].cells.length; j++) {\n const newCell = newTable.rows[i].cells[j];\n\n if (i == 0 && colIndex + j >= table.rows[0].cells.length) {\n for (let k = 0; k < table.rows.length; k++) {\n const leftCell = table.rows[k]?.cells[colIndex + j - 1];\n table.rows[k].cells[colIndex + j] = createTableCell(\n false /*spanLeft*/,\n false /*spanAbove*/,\n leftCell?.isHeader,\n leftCell?.format\n );\n }\n }\n\n if (j == 0 && rowIndex + i >= table.rows.length) {\n if (!table.rows[rowIndex + i]) {\n table.rows[rowIndex + i] = {\n cells: [],\n format: {},\n height: 0,\n };\n }\n\n for (let k = 0; k < table.rows[rowIndex].cells.length; k++) {\n const aboveCell = table.rows[rowIndex + i - 1]?.cells[k];\n table.rows[rowIndex + i].cells[k] = createTableCell(\n false /*spanLeft*/,\n false /*spanAbove*/,\n false /*isHeader*/,\n aboveCell?.format\n );\n }\n }\n\n const oldCell = table.rows[rowIndex + i].cells[colIndex + j];\n table.rows[rowIndex + i].cells[colIndex + j] = newCell;\n\n if (i == 0 && j == 0) {\n const newMarker = createSelectionMarker(marker.format);\n const newPara = addSegment(newCell, newMarker);\n\n if (markerPosition.path[0] == oldCell) {\n // Update insert point to match the change result\n markerPosition.path[0] = newCell;\n markerPosition.marker = newMarker;\n markerPosition.paragraph = newPara;\n }\n }\n }\n }\n\n normalizeTable(table, markerPosition.marker.format);\n applyTableFormat(table, undefined /*newFormat*/, true /*keepCellShade*/);\n } else {\n insertBlock(markerPosition, newTable);\n }\n}\n\nfunction mergeList(markerPosition: InsertPoint, newList: ContentModelListItem) {\n splitParagraph(markerPosition, newList.format);\n\n const { path, paragraph } = markerPosition;\n\n const listItemIndex = getClosestAncestorBlockGroupIndex(path, ['ListItem'], ['TableCell']);\n const listItem = path[listItemIndex] as ContentModelListItem;\n const listParent = path[listItemIndex + 1]; // It is ok here when index is -1, that means there is no list and we just insert a new paragraph and use path[0] as its parent\n const blockIndex = listParent.blocks.indexOf(listItem || paragraph);\n\n if (blockIndex >= 0) {\n mutateBlock(listParent).blocks.splice(blockIndex, 0, newList);\n }\n\n if (listItem) {\n listItem?.levels.forEach((level, i) => {\n newList.levels[i] = { ...level };\n });\n }\n}\n\nfunction splitParagraph(markerPosition: InsertPoint, newParaFormat: ContentModelBlockFormat) {\n const { paragraph, marker, path } = markerPosition;\n const segmentIndex = paragraph.segments.indexOf(marker);\n const paraIndex = path[0].blocks.indexOf(paragraph);\n const newParagraph: ShallowMutableContentModelParagraph = createParagraph(\n false /*isImplicit*/,\n { ...paragraph.format, ...newParaFormat },\n paragraph.segmentFormat\n );\n\n if (segmentIndex >= 0) {\n newParagraph.segments = paragraph.segments.splice(segmentIndex);\n }\n\n if (paraIndex >= 0) {\n mutateBlock(path[0]).blocks.splice(paraIndex + 1, 0, newParagraph);\n }\n\n const listItemIndex = getClosestAncestorBlockGroupIndex(\n path,\n ['ListItem'],\n ['FormatContainer', 'TableCell']\n );\n const listItem = path[listItemIndex] as ContentModelListItem;\n\n if (listItem) {\n const listParent = listItemIndex >= 0 ? path[listItemIndex + 1] : null;\n const blockIndex = listParent ? listParent.blocks.indexOf(listItem) : -1;\n\n if (blockIndex >= 0 && listParent) {\n const newListItem = createListItem(listItem.levels, listItem.formatHolder.format);\n\n if (paraIndex >= 0) {\n newListItem.blocks = listItem.blocks.splice(paraIndex + 1);\n }\n\n if (blockIndex >= 0) {\n mutateBlock(listParent).blocks.splice(blockIndex + 1, 0, newListItem);\n }\n\n path[listItemIndex] = newListItem;\n }\n }\n\n markerPosition.paragraph = newParagraph;\n\n return newParagraph;\n}\n\nfunction insertBlock(markerPosition: InsertPoint, block: ContentModelBlock) {\n const { path } = markerPosition;\n const newParaFormat = block.blockType !== 'Paragraph' ? {} : block.format;\n const newPara = splitParagraph(markerPosition, newParaFormat);\n const blockIndex = path[0].blocks.indexOf(newPara);\n\n if (blockIndex >= 0) {\n mutateBlock(path[0]).blocks.splice(blockIndex, 0, block);\n }\n}\n\nfunction applyDefaultFormat(\n group: ReadonlyContentModelBlockGroup,\n format: ContentModelSegmentFormat,\n applyDefaultFormatOption: MergeFormatTypes\n) {\n group.blocks.forEach(block => {\n mergeBlockFormat(applyDefaultFormatOption, block);\n\n switch (block.blockType) {\n case 'BlockGroup':\n if (block.blockGroupType == 'ListItem') {\n mutateBlock(block).formatHolder.format = mergeSegmentFormat(\n applyDefaultFormatOption,\n format,\n block.formatHolder.format\n );\n }\n applyDefaultFormat(block, format, applyDefaultFormatOption);\n break;\n\n case 'Table':\n block.rows.forEach(row =>\n row.cells.forEach(cell => {\n applyDefaultFormat(cell, format, applyDefaultFormatOption);\n })\n );\n break;\n\n case 'Paragraph':\n const paragraphFormat = block.decorator?.format || {};\n const paragraph = mutateBlock(block);\n\n paragraph.segments.forEach(segment => {\n if (segment.segmentType == 'General') {\n applyDefaultFormat(segment, format, applyDefaultFormatOption);\n }\n\n segment.format = mergeSegmentFormat(applyDefaultFormatOption, format, {\n ...paragraphFormat,\n ...segment.format,\n });\n\n if (segment.link) {\n segment.link.format = mergeLinkFormat(\n applyDefaultFormatOption,\n format,\n segment.link.format\n );\n }\n });\n\n if (applyDefaultFormatOption === 'keepSourceEmphasisFormat') {\n delete paragraph.decorator;\n }\n break;\n }\n });\n}\n\nfunction mergeBlockFormat(applyDefaultFormatOption: string, block: ReadonlyContentModelBlock) {\n if (applyDefaultFormatOption == 'keepSourceEmphasisFormat' && block.format.backgroundColor) {\n delete mutateBlock(block).format.backgroundColor;\n }\n}\n\n/**\n * Hyperlink format type definition only contains backgroundColor and underline.\n * So create a minimum object with the styles supported in Hyperlink to be used in merge.\n */\nfunction getSegmentFormatInLinkFormat(\n targetFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n const result: ContentModelHyperLinkFormat = {};\n if (targetFormat.backgroundColor) {\n result.backgroundColor = targetFormat.backgroundColor;\n }\n if (targetFormat.underline) {\n result.underline = targetFormat.underline;\n }\n\n return result;\n}\n\nfunction mergeLinkFormat(\n applyDefaultFormatOption: MergeFormatTypes,\n targetFormat: ContentModelSegmentFormat,\n sourceFormat: ContentModelHyperLinkFormat\n) {\n switch (applyDefaultFormatOption) {\n case 'mergeAll':\n case 'preferSource':\n return { ...getSegmentFormatInLinkFormat(targetFormat), ...sourceFormat };\n case 'keepSourceEmphasisFormat':\n return {\n // Hyperlink segment format contains other attributes such as LinkFormat\n // so we have to retain them\n ...getFormatWithoutSegmentFormat(sourceFormat),\n // Link format only have Text color, background color, Underline, but only\n // text color + background color should be merged from the target\n ...getSegmentFormatInLinkFormat(targetFormat),\n // Get the semantic format of the source\n ...getSemanticFormat(sourceFormat),\n // The text color of the hyperlink should not be merged and\n // we should always retain the source text color\n ...getHyperlinkTextColor(sourceFormat),\n };\n case 'preferTarget':\n return { ...sourceFormat, ...getSegmentFormatInLinkFormat(targetFormat) };\n }\n}\n\nfunction mergeSegmentFormat(\n applyDefaultFormatOption: MergeFormatTypes,\n targetFormat: ContentModelSegmentFormat,\n sourceFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n switch (applyDefaultFormatOption) {\n case 'mergeAll':\n case 'preferSource':\n return { ...targetFormat, ...sourceFormat };\n case 'preferTarget':\n return { ...sourceFormat, ...targetFormat };\n case 'keepSourceEmphasisFormat':\n return {\n ...getFormatWithoutSegmentFormat(sourceFormat),\n ...targetFormat,\n ...getSemanticFormat(sourceFormat),\n };\n }\n}\n\nfunction getSemanticFormat(segmentFormat: ContentModelSegmentFormat): ContentModelSegmentFormat {\n const result: ContentModelSegmentFormat = {};\n\n const { fontWeight, italic, underline } = segmentFormat;\n\n if (fontWeight && fontWeight != 'normal') {\n result.fontWeight = fontWeight;\n }\n if (italic) {\n result.italic = italic;\n }\n if (underline) {\n result.underline = underline;\n }\n\n return result;\n}\n\n/**\n * Segment format can also contain other type of metadata, for example in Images/Hyperlink,\n * we want to preserve these properties when merging format\n */\nfunction getFormatWithoutSegmentFormat(\n sourceFormat: ContentModelSegmentFormat\n): ContentModelSegmentFormat {\n const resultFormat = {\n ...sourceFormat,\n };\n KeysOfSegmentFormat.forEach(key => delete resultFormat[key]);\n return resultFormat;\n}\nfunction getHyperlinkTextColor(sourceFormat: ContentModelHyperLinkFormat) {\n const result: ContentModelHyperLinkFormat = {};\n if (sourceFormat.textColor) {\n result.textColor = sourceFormat.textColor;\n }\n\n return result;\n}\n"]}
|
|
@@ -70,16 +70,18 @@ export declare function getSelectedParagraphs(model: ReadonlyContentModelDocumen
|
|
|
70
70
|
* @param blockGroupTypes The expected block group types
|
|
71
71
|
* @param stopTypes Block group types that will stop searching when hit
|
|
72
72
|
* @param deepFirst True means search in deep first, otherwise wide first
|
|
73
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
73
74
|
*/
|
|
74
|
-
export declare function getOperationalBlocks<T extends ContentModelBlockGroup>(group: ContentModelBlockGroup, blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes: ContentModelBlockGroupType[], deepFirst?: boolean): OperationalBlocks<T>[];
|
|
75
|
+
export declare function getOperationalBlocks<T extends ContentModelBlockGroup>(group: ContentModelBlockGroup, blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes: ContentModelBlockGroupType[], deepFirst?: boolean, isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean): OperationalBlocks<T>[];
|
|
75
76
|
/**
|
|
76
77
|
* Get an array of block group - block pair that is of the expected block group type from selection (Readonly)
|
|
77
78
|
* @param group The root block group to search
|
|
78
79
|
* @param blockGroupTypes The expected block group types
|
|
79
80
|
* @param stopTypes Block group types that will stop searching when hit
|
|
80
81
|
* @param deepFirst True means search in deep first, otherwise wide first
|
|
82
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
81
83
|
*/
|
|
82
|
-
export declare function getOperationalBlocks<T extends ReadonlyContentModelBlockGroup>(group: ReadonlyContentModelBlockGroup, blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes: ContentModelBlockGroupType[], deepFirst?: boolean): ReadonlyOperationalBlocks<T>[];
|
|
84
|
+
export declare function getOperationalBlocks<T extends ReadonlyContentModelBlockGroup>(group: ReadonlyContentModelBlockGroup, blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes: ContentModelBlockGroupType[], deepFirst?: boolean, isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean): ReadonlyOperationalBlocks<T>[];
|
|
83
85
|
/**
|
|
84
86
|
* Get the first selected table from content model
|
|
85
87
|
* @param model The Content Model to get selection from
|
|
@@ -66,7 +66,7 @@ function getSelectedParagraphs(model, mutate) {
|
|
|
66
66
|
return result;
|
|
67
67
|
}
|
|
68
68
|
exports.getSelectedParagraphs = getSelectedParagraphs;
|
|
69
|
-
function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst) {
|
|
69
|
+
function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst, isValidTarget) {
|
|
70
70
|
var result = [];
|
|
71
71
|
var findSequence = deepFirst ? blockGroupTypes.map(function (type) { return [type]; }) : [blockGroupTypes];
|
|
72
72
|
var selections = collectSelections(group, {
|
|
@@ -77,7 +77,7 @@ function getOperationalBlocks(group, blockGroupTypes, stopTypes, deepFirst) {
|
|
|
77
77
|
selections.forEach(function (_a) {
|
|
78
78
|
var path = _a.path, block = _a.block;
|
|
79
79
|
var _loop_1 = function (i) {
|
|
80
|
-
var groupIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, findSequence[i], stopTypes);
|
|
80
|
+
var groupIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, findSequence[i], stopTypes, isValidTarget);
|
|
81
81
|
if (groupIndex >= 0) {
|
|
82
82
|
if (result.filter(function (x) { return x.block == path[groupIndex]; }).length <= 0) {
|
|
83
83
|
result.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectSelections.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/selection/collectSelections.ts"],"names":[],"mappings":"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","sourcesContent":["import { getClosestAncestorBlockGroupIndex } from '../editing/getClosestAncestorBlockGroupIndex';\nimport { isBlockGroupOfType } from '../typeCheck/isBlockGroupOfType';\nimport { iterateSelections } from './iterateSelections';\nimport { mutateBlock } from '../common/mutate';\nimport type {\n ContentModelBlock,\n ContentModelBlockGroup,\n ContentModelBlockGroupType,\n ContentModelDocument,\n ContentModelListItem,\n ContentModelParagraph,\n ContentModelSegment,\n ContentModelTable,\n IterateSelectionsOption,\n OperationalBlocks,\n ReadonlyContentModelBlock,\n ReadonlyContentModelBlockGroup,\n ReadonlyContentModelDocument,\n ReadonlyContentModelListItem,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n ReadonlyContentModelTable,\n ReadonlyOperationalBlocks,\n ReadonlyTableSelectionContext,\n ShallowMutableContentModelParagraph,\n ShallowMutableContentModelSegment,\n TableSelectionContext,\n TypeOfBlockGroup,\n} from 'roosterjs-content-model-types';\n\n//#region getSelectedSegmentsAndParagraphs\n/**\n * Get an array of selected parent paragraph and child segment pair\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean\n): [ContentModelSegment, ContentModelParagraph | null, ContentModelBlockGroup[]][];\n\n/**\n * Get an array of selected parent paragraph and child segment pair, return mutable paragraph and segments\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity: boolean,\n mutate: true\n): [\n ShallowMutableContentModelSegment,\n ContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][];\n\n/**\n * Get an array of selected parent paragraph and child segment pair (Readonly)\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean\n): [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][];\n\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean,\n mutate?: boolean\n): [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][] {\n const selections = collectSelections(model, {\n includeListFormatHolder: includingFormatHolder ? 'allSegments' : 'never',\n });\n const result: [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n ][] = [];\n\n selections.forEach(({ segments, block, path }) => {\n if (segments) {\n if (\n includingFormatHolder &&\n !block &&\n segments.length == 1 &&\n path[0].blockGroupType == 'ListItem' &&\n segments[0] == path[0].formatHolder\n ) {\n const list = path[0];\n\n if (mutate) {\n mutateBlock(list);\n }\n\n result.push([list.formatHolder, null, path]);\n } else if (block?.blockType == 'Paragraph') {\n if (mutate) {\n mutateBlock(block);\n }\n\n segments.forEach(segment => {\n if (\n includingEntity ||\n segment.segmentType != 'Entity' ||\n !segment.entityFormat.isReadonly\n ) {\n result.push([segment, block, path]);\n }\n });\n }\n } else if (block?.blockType == 'Entity' && includingEntity) {\n // Here we treat the entity as segment since they are compatible, then it has no parent paragraph\n result.push([block, null /*paragraph*/, path]);\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getSelectedSegments\n/**\n * Get an array of selected segments from a content model\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n */\nexport function getSelectedSegments(\n model: ContentModelDocument,\n includingFormatHolder: boolean\n): ContentModelSegment[];\n\n/**\n * Get an array of selected segments from a content model, return mutable segments\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n mutate: true\n): ShallowMutableContentModelSegment[];\n\n/**\n * Get an array of selected segments from a content model (Readonly)\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n */\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean\n): ReadonlyContentModelSegment[];\n\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n mutate?: boolean\n): ReadonlyContentModelSegment[] {\n const segments = mutate\n ? getSelectedSegmentsAndParagraphs(\n model,\n includingFormatHolder,\n false /*includeEntity*/,\n true /*mutate*/\n )\n : getSelectedSegmentsAndParagraphs(model, includingFormatHolder);\n\n return segments.map(x => x[0]);\n}\n//#endregion\n\n//#region getSelectedParagraphs\n/**\n * Get any array of selected paragraphs from a content model\n * @param model The Content Model to get selection from\n */\nexport function getSelectedParagraphs(model: ContentModelDocument): ContentModelParagraph[];\n\n/**\n * Get any array of selected paragraphs from a content model, return mutable paragraphs\n * @param model The Content Model to get selection from\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument,\n mutate: true\n): ShallowMutableContentModelParagraph[];\n\n/**\n * Get any array of selected paragraphs from a content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelParagraph[];\n\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument,\n mutate?: boolean\n): ReadonlyContentModelParagraph[] {\n const selections = collectSelections(model, { includeListFormatHolder: 'never' });\n const result: ReadonlyContentModelParagraph[] = [];\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ block }) => {\n if (block?.blockType == 'Paragraph') {\n result.push(mutate ? mutateBlock(block) : block);\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getOperationalBlocks\n/**\n * Get an array of block group - block pair that is of the expected block group type from selection\n * @param group The root block group to search\n * @param blockGroupTypes The expected block group types\n * @param stopTypes Block group types that will stop searching when hit\n * @param deepFirst True means search in deep first, otherwise wide first\n */\nexport function getOperationalBlocks<T extends ContentModelBlockGroup>(\n group: ContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean\n): OperationalBlocks<T>[];\n\n/**\n * Get an array of block group - block pair that is of the expected block group type from selection (Readonly)\n * @param group The root block group to search\n * @param blockGroupTypes The expected block group types\n * @param stopTypes Block group types that will stop searching when hit\n * @param deepFirst True means search in deep first, otherwise wide first\n */\nexport function getOperationalBlocks<T extends ReadonlyContentModelBlockGroup>(\n group: ReadonlyContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean\n): ReadonlyOperationalBlocks<T>[];\n\nexport function getOperationalBlocks<T extends ContentModelBlockGroup>(\n group: ReadonlyContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean\n): ReadonlyOperationalBlocks<T>[] {\n const result: ReadonlyOperationalBlocks<T>[] = [];\n const findSequence = deepFirst ? blockGroupTypes.map(type => [type]) : [blockGroupTypes];\n const selections = collectSelections(group, {\n includeListFormatHolder: 'never',\n contentUnderSelectedTableCell: 'ignoreForTable', // When whole table is selected, we treat the table as a single block\n });\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ path, block }) => {\n for (let i = 0; i < findSequence.length; i++) {\n const groupIndex = getClosestAncestorBlockGroupIndex(path, findSequence[i], stopTypes);\n\n if (groupIndex >= 0) {\n if (result.filter(x => x.block == path[groupIndex]).length <= 0) {\n result.push({\n parent: path[groupIndex + 1],\n block: path[groupIndex] as T,\n path: path.slice(groupIndex + 1),\n });\n }\n break;\n } else if (i == findSequence.length - 1 && block) {\n result.push({\n parent: path[0],\n block: block,\n path,\n });\n break;\n }\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getFirstSelectedTable\n/**\n * Get the first selected table from content model\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedTable(\n model: ContentModelDocument\n): [ContentModelTable | undefined, ContentModelBlockGroup[]];\n\n/**\n * Get the first selected table from content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedTable(\n model: ReadonlyContentModelDocument\n): [ReadonlyContentModelTable | undefined, ReadonlyContentModelBlockGroup[]];\n\nexport function getFirstSelectedTable(\n model: ReadonlyContentModelDocument\n): [ReadonlyContentModelTable | undefined, ReadonlyContentModelBlockGroup[]] {\n const selections = collectSelections(model, { includeListFormatHolder: 'never' });\n let table: ReadonlyContentModelTable | undefined;\n let resultPath: ReadonlyContentModelBlockGroup[] = [];\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ block, tableContext, path }) => {\n if (!table) {\n if (block?.blockType == 'Table') {\n table = block;\n resultPath = [...path];\n } else if (tableContext?.table) {\n table = tableContext.table;\n\n const parent = path.filter(\n group => group.blocks.indexOf(tableContext.table) >= 0\n )[0];\n const index = path.indexOf(parent);\n resultPath = index >= 0 ? path.slice(index) : [];\n }\n }\n });\n\n return [table, resultPath];\n}\n//#endregion\n\n//#region getFirstSelectedListItem\n/**\n * Get the first selected list item from content model\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedListItem(\n model: ContentModelDocument\n): ContentModelListItem | undefined;\n\n/**\n * Get the first selected list item from content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedListItem(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelListItem | undefined;\n\nexport function getFirstSelectedListItem(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelListItem | undefined {\n let listItem: ContentModelListItem | undefined;\n\n getOperationalBlocks(model, ['ListItem'], ['TableCell']).forEach(r => {\n if (!listItem && isBlockGroupOfType<ContentModelListItem>(r.block, 'ListItem')) {\n listItem = r.block;\n }\n });\n\n return listItem;\n}\n//#endregion\n\n//#region collectSelections\ninterface SelectionInfo {\n path: ContentModelBlockGroup[];\n segments?: ContentModelSegment[];\n block?: ContentModelBlock;\n tableContext?: TableSelectionContext;\n}\n\ninterface ReadonlySelectionInfo {\n path: ReadonlyContentModelBlockGroup[];\n segments?: ReadonlyContentModelSegment[];\n block?: ReadonlyContentModelBlock;\n tableContext?: ReadonlyTableSelectionContext;\n}\n\nfunction collectSelections(\n group: ContentModelBlockGroup,\n option?: IterateSelectionsOption\n): SelectionInfo[];\n\nfunction collectSelections(\n group: ReadonlyContentModelBlockGroup,\n option?: IterateSelectionsOption\n): ReadonlySelectionInfo[];\n\nfunction collectSelections(\n group: ReadonlyContentModelBlockGroup,\n option?: IterateSelectionsOption\n): ReadonlySelectionInfo[] {\n const selections: ReadonlySelectionInfo[] = [];\n\n iterateSelections(\n group,\n (path, tableContext, block, segments) => {\n selections.push({\n path,\n tableContext,\n block,\n segments,\n });\n },\n option\n );\n\n return selections;\n}\n//#endregion\n\n//#region utils\nfunction removeUnmeaningfulSelections(selections: ReadonlySelectionInfo[]) {\n if (\n selections.length > 1 &&\n isOnlySelectionMarkerSelected(selections, false /*checkFirstParagraph*/)\n ) {\n selections.pop();\n }\n\n // Remove head paragraph if first selection marker is the only selection\n if (\n selections.length > 1 &&\n isOnlySelectionMarkerSelected(selections, true /*checkFirstParagraph*/)\n ) {\n selections.shift();\n }\n}\n\nfunction isOnlySelectionMarkerSelected(\n selections: ReadonlySelectionInfo[],\n checkFirstParagraph: boolean\n): boolean {\n const selection = selections[checkFirstParagraph ? 0 : selections.length - 1];\n\n if (\n selection.block?.blockType == 'Paragraph' &&\n selection.segments &&\n selection.segments.length > 0\n ) {\n const allSegments = selection.block.segments;\n const segment = selection.segments[0];\n\n return (\n selection.segments.length == 1 &&\n segment.segmentType == 'SelectionMarker' &&\n segment == allSegments[checkFirstParagraph ? allSegments.length - 1 : 0]\n );\n } else {\n return false;\n }\n}\n//#endregion\n"]}
|
|
1
|
+
{"version":3,"file":"collectSelections.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/selection/collectSelections.ts"],"names":[],"mappings":"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","sourcesContent":["import { getClosestAncestorBlockGroupIndex } from '../editing/getClosestAncestorBlockGroupIndex';\nimport { isBlockGroupOfType } from '../typeCheck/isBlockGroupOfType';\nimport { iterateSelections } from './iterateSelections';\nimport { mutateBlock } from '../common/mutate';\nimport type {\n ContentModelBlock,\n ContentModelBlockGroup,\n ContentModelBlockGroupType,\n ContentModelDocument,\n ContentModelListItem,\n ContentModelParagraph,\n ContentModelSegment,\n ContentModelTable,\n IterateSelectionsOption,\n OperationalBlocks,\n ReadonlyContentModelBlock,\n ReadonlyContentModelBlockGroup,\n ReadonlyContentModelDocument,\n ReadonlyContentModelListItem,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n ReadonlyContentModelTable,\n ReadonlyOperationalBlocks,\n ReadonlyTableSelectionContext,\n ShallowMutableContentModelParagraph,\n ShallowMutableContentModelSegment,\n TableSelectionContext,\n TypeOfBlockGroup,\n} from 'roosterjs-content-model-types';\n\n//#region getSelectedSegmentsAndParagraphs\n/**\n * Get an array of selected parent paragraph and child segment pair\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean\n): [ContentModelSegment, ContentModelParagraph | null, ContentModelBlockGroup[]][];\n\n/**\n * Get an array of selected parent paragraph and child segment pair, return mutable paragraph and segments\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity: boolean,\n mutate: true\n): [\n ShallowMutableContentModelSegment,\n ContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][];\n\n/**\n * Get an array of selected parent paragraph and child segment pair (Readonly)\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item, in that case paragraph will be null\n * @param includingEntity True to include entity in result as well\n */\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean\n): [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][];\n\nexport function getSelectedSegmentsAndParagraphs(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n includingEntity?: boolean,\n mutate?: boolean\n): [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n][] {\n const selections = collectSelections(model, {\n includeListFormatHolder: includingFormatHolder ? 'allSegments' : 'never',\n });\n const result: [\n ReadonlyContentModelSegment,\n ReadonlyContentModelParagraph | null,\n ReadonlyContentModelBlockGroup[]\n ][] = [];\n\n selections.forEach(({ segments, block, path }) => {\n if (segments) {\n if (\n includingFormatHolder &&\n !block &&\n segments.length == 1 &&\n path[0].blockGroupType == 'ListItem' &&\n segments[0] == path[0].formatHolder\n ) {\n const list = path[0];\n\n if (mutate) {\n mutateBlock(list);\n }\n\n result.push([list.formatHolder, null, path]);\n } else if (block?.blockType == 'Paragraph') {\n if (mutate) {\n mutateBlock(block);\n }\n\n segments.forEach(segment => {\n if (\n includingEntity ||\n segment.segmentType != 'Entity' ||\n !segment.entityFormat.isReadonly\n ) {\n result.push([segment, block, path]);\n }\n });\n }\n } else if (block?.blockType == 'Entity' && includingEntity) {\n // Here we treat the entity as segment since they are compatible, then it has no parent paragraph\n result.push([block, null /*paragraph*/, path]);\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getSelectedSegments\n/**\n * Get an array of selected segments from a content model\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n */\nexport function getSelectedSegments(\n model: ContentModelDocument,\n includingFormatHolder: boolean\n): ContentModelSegment[];\n\n/**\n * Get an array of selected segments from a content model, return mutable segments\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n mutate: true\n): ShallowMutableContentModelSegment[];\n\n/**\n * Get an array of selected segments from a content model (Readonly)\n * @param model The Content Model to get selection from\n * @param includingFormatHolder True means also include format holder as segment from list item\n */\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean\n): ReadonlyContentModelSegment[];\n\nexport function getSelectedSegments(\n model: ReadonlyContentModelDocument,\n includingFormatHolder: boolean,\n mutate?: boolean\n): ReadonlyContentModelSegment[] {\n const segments = mutate\n ? getSelectedSegmentsAndParagraphs(\n model,\n includingFormatHolder,\n false /*includeEntity*/,\n true /*mutate*/\n )\n : getSelectedSegmentsAndParagraphs(model, includingFormatHolder);\n\n return segments.map(x => x[0]);\n}\n//#endregion\n\n//#region getSelectedParagraphs\n/**\n * Get any array of selected paragraphs from a content model\n * @param model The Content Model to get selection from\n */\nexport function getSelectedParagraphs(model: ContentModelDocument): ContentModelParagraph[];\n\n/**\n * Get any array of selected paragraphs from a content model, return mutable paragraphs\n * @param model The Content Model to get selection from\n * @param mutate Set to true to indicate we will mutate the selected paragraphs\n */\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument,\n mutate: true\n): ShallowMutableContentModelParagraph[];\n\n/**\n * Get any array of selected paragraphs from a content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelParagraph[];\n\nexport function getSelectedParagraphs(\n model: ReadonlyContentModelDocument,\n mutate?: boolean\n): ReadonlyContentModelParagraph[] {\n const selections = collectSelections(model, { includeListFormatHolder: 'never' });\n const result: ReadonlyContentModelParagraph[] = [];\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ block }) => {\n if (block?.blockType == 'Paragraph') {\n result.push(mutate ? mutateBlock(block) : block);\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getOperationalBlocks\n/**\n * Get an array of block group - block pair that is of the expected block group type from selection\n * @param group The root block group to search\n * @param blockGroupTypes The expected block group types\n * @param stopTypes Block group types that will stop searching when hit\n * @param deepFirst True means search in deep first, otherwise wide first\n * @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target\n */\nexport function getOperationalBlocks<T extends ContentModelBlockGroup>(\n group: ContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean,\n isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean\n): OperationalBlocks<T>[];\n\n/**\n * Get an array of block group - block pair that is of the expected block group type from selection (Readonly)\n * @param group The root block group to search\n * @param blockGroupTypes The expected block group types\n * @param stopTypes Block group types that will stop searching when hit\n * @param deepFirst True means search in deep first, otherwise wide first\n * @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target\n */\nexport function getOperationalBlocks<T extends ReadonlyContentModelBlockGroup>(\n group: ReadonlyContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean,\n isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean\n): ReadonlyOperationalBlocks<T>[];\n\nexport function getOperationalBlocks<T extends ContentModelBlockGroup>(\n group: ReadonlyContentModelBlockGroup,\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[],\n deepFirst?: boolean,\n isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean\n): ReadonlyOperationalBlocks<T>[] {\n const result: ReadonlyOperationalBlocks<T>[] = [];\n const findSequence = deepFirst ? blockGroupTypes.map(type => [type]) : [blockGroupTypes];\n const selections = collectSelections(group, {\n includeListFormatHolder: 'never',\n contentUnderSelectedTableCell: 'ignoreForTable', // When whole table is selected, we treat the table as a single block\n });\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ path, block }) => {\n for (let i = 0; i < findSequence.length; i++) {\n const groupIndex = getClosestAncestorBlockGroupIndex(\n path,\n findSequence[i],\n stopTypes,\n isValidTarget\n );\n\n if (groupIndex >= 0) {\n if (result.filter(x => x.block == path[groupIndex]).length <= 0) {\n result.push({\n parent: path[groupIndex + 1],\n block: path[groupIndex] as T,\n path: path.slice(groupIndex + 1),\n });\n }\n break;\n } else if (i == findSequence.length - 1 && block) {\n result.push({\n parent: path[0],\n block: block,\n path,\n });\n break;\n }\n }\n });\n\n return result;\n}\n//#endregion\n\n//#region getFirstSelectedTable\n/**\n * Get the first selected table from content model\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedTable(\n model: ContentModelDocument\n): [ContentModelTable | undefined, ContentModelBlockGroup[]];\n\n/**\n * Get the first selected table from content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedTable(\n model: ReadonlyContentModelDocument\n): [ReadonlyContentModelTable | undefined, ReadonlyContentModelBlockGroup[]];\n\nexport function getFirstSelectedTable(\n model: ReadonlyContentModelDocument\n): [ReadonlyContentModelTable | undefined, ReadonlyContentModelBlockGroup[]] {\n const selections = collectSelections(model, { includeListFormatHolder: 'never' });\n let table: ReadonlyContentModelTable | undefined;\n let resultPath: ReadonlyContentModelBlockGroup[] = [];\n\n removeUnmeaningfulSelections(selections);\n\n selections.forEach(({ block, tableContext, path }) => {\n if (!table) {\n if (block?.blockType == 'Table') {\n table = block;\n resultPath = [...path];\n } else if (tableContext?.table) {\n table = tableContext.table;\n\n const parent = path.filter(\n group => group.blocks.indexOf(tableContext.table) >= 0\n )[0];\n const index = path.indexOf(parent);\n resultPath = index >= 0 ? path.slice(index) : [];\n }\n }\n });\n\n return [table, resultPath];\n}\n//#endregion\n\n//#region getFirstSelectedListItem\n/**\n * Get the first selected list item from content model\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedListItem(\n model: ContentModelDocument\n): ContentModelListItem | undefined;\n\n/**\n * Get the first selected list item from content model (Readonly)\n * @param model The Content Model to get selection from\n */\nexport function getFirstSelectedListItem(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelListItem | undefined;\n\nexport function getFirstSelectedListItem(\n model: ReadonlyContentModelDocument\n): ReadonlyContentModelListItem | undefined {\n let listItem: ContentModelListItem | undefined;\n\n getOperationalBlocks(model, ['ListItem'], ['TableCell']).forEach(r => {\n if (!listItem && isBlockGroupOfType<ContentModelListItem>(r.block, 'ListItem')) {\n listItem = r.block;\n }\n });\n\n return listItem;\n}\n//#endregion\n\n//#region collectSelections\ninterface SelectionInfo {\n path: ContentModelBlockGroup[];\n segments?: ContentModelSegment[];\n block?: ContentModelBlock;\n tableContext?: TableSelectionContext;\n}\n\ninterface ReadonlySelectionInfo {\n path: ReadonlyContentModelBlockGroup[];\n segments?: ReadonlyContentModelSegment[];\n block?: ReadonlyContentModelBlock;\n tableContext?: ReadonlyTableSelectionContext;\n}\n\nfunction collectSelections(\n group: ContentModelBlockGroup,\n option?: IterateSelectionsOption\n): SelectionInfo[];\n\nfunction collectSelections(\n group: ReadonlyContentModelBlockGroup,\n option?: IterateSelectionsOption\n): ReadonlySelectionInfo[];\n\nfunction collectSelections(\n group: ReadonlyContentModelBlockGroup,\n option?: IterateSelectionsOption\n): ReadonlySelectionInfo[] {\n const selections: ReadonlySelectionInfo[] = [];\n\n iterateSelections(\n group,\n (path, tableContext, block, segments) => {\n selections.push({\n path,\n tableContext,\n block,\n segments,\n });\n },\n option\n );\n\n return selections;\n}\n//#endregion\n\n//#region utils\nfunction removeUnmeaningfulSelections(selections: ReadonlySelectionInfo[]) {\n if (\n selections.length > 1 &&\n isOnlySelectionMarkerSelected(selections, false /*checkFirstParagraph*/)\n ) {\n selections.pop();\n }\n\n // Remove head paragraph if first selection marker is the only selection\n if (\n selections.length > 1 &&\n isOnlySelectionMarkerSelected(selections, true /*checkFirstParagraph*/)\n ) {\n selections.shift();\n }\n}\n\nfunction isOnlySelectionMarkerSelected(\n selections: ReadonlySelectionInfo[],\n checkFirstParagraph: boolean\n): boolean {\n const selection = selections[checkFirstParagraph ? 0 : selections.length - 1];\n\n if (\n selection.block?.blockType == 'Paragraph' &&\n selection.segments &&\n selection.segments.length > 0\n ) {\n const allSegments = selection.block.segments;\n const segment = selection.segments[0];\n\n return (\n selection.segments.length == 1 &&\n segment.segmentType == 'SelectionMarker' &&\n segment == allSegments[checkFirstParagraph ? allSegments.length - 1 : 0]\n );\n } else {\n return false;\n }\n}\n//#endregion\n"]}
|
|
@@ -27,8 +27,8 @@ var handleParagraph = function (doc, parent, paragraph, context, refNode) {
|
|
|
27
27
|
paragraph.segments.some(function (segment) { return segment.segmentType != 'SelectionMarker'; }));
|
|
28
28
|
var formatOnWrapper = needParagraphWrapper
|
|
29
29
|
? (0, tslib_1.__assign)((0, tslib_1.__assign)({}, (((_a = paragraph.decorator) === null || _a === void 0 ? void 0 : _a.format) || {})), paragraph.segmentFormat) : {};
|
|
30
|
+
var prevRefNode = refNode === null || refNode === void 0 ? void 0 : refNode.previousSibling;
|
|
30
31
|
container = doc.createElement(((_b = paragraph.decorator) === null || _b === void 0 ? void 0 : _b.tagName) || DefaultParagraphTag);
|
|
31
|
-
parent.insertBefore(container, refNode);
|
|
32
32
|
context.regularSelection.current = {
|
|
33
33
|
block: needParagraphWrapper ? container : container.parentNode,
|
|
34
34
|
segment: null,
|
|
@@ -70,7 +70,13 @@ var handleParagraph = function (doc, parent, paragraph, context, refNode) {
|
|
|
70
70
|
// since this paragraph it is implicit. In that case container.nextSibling will become original
|
|
71
71
|
// inline entity's next sibling. So reset refNode to its real next sibling (after change) here
|
|
72
72
|
// to make sure the value is correct.
|
|
73
|
-
refNode =
|
|
73
|
+
refNode =
|
|
74
|
+
prevRefNode === undefined // When refNode is not passed in
|
|
75
|
+
? null
|
|
76
|
+
: prevRefNode === null // When refNode is the first child of parent
|
|
77
|
+
? parent.firstChild
|
|
78
|
+
: prevRefNode.nextSibling; // Normal case
|
|
79
|
+
parent.insertBefore(container, refNode);
|
|
74
80
|
if (container) {
|
|
75
81
|
(_d = context.onNodeCreated) === null || _d === void 0 ? void 0 : _d.call(context, paragraph, container);
|
|
76
82
|
(_e = context.domIndexer) === null || _e === void 0 ? void 0 : _e.onParagraph(container);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":";;;;AAAA,oDAAmD;AACnD,8DAA6D;AAC7D,mDAAkD;AAClD,wEAAuE;AACvE,oDAAmD;AACnD,gDAA+C;AAO/C,IAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC;;GAEG;AACI,IAAM,eAAe,GAAoD,UAC5E,GAAa,EACb,MAAY,EACZ,SAAgC,EAChC,OAA0B,EAC1B,OAAoB;;IAEpB,IAAI,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhF,IAAI,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,EAA3C,CAA2C,CAAC,EAAE;QACzF,OAAO,GAAG,IAAA,uCAAkB,EAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;KACtF;SAAM;QACH,IAAA,yBAAW,EAAC,OAAO,EAAE,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,OAAO,KAAI,IAAI,EAAE;;YACvD,IAAM,oBAAoB,GACtB,CAAC,SAAS,CAAC,UAAU;gBACrB,CAAC,CAAC,SAAS,CAAC,SAAS;gBACrB,CAAC,IAAA,6BAAa,EAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;oBACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,WAAW,IAAI,iBAAiB,EAAxC,CAAwC,CAAC,CAAC,CAAC;YACtF,IAAM,eAAe,GAAG,oBAAoB;gBACxC,CAAC,iDACQ,CAAC,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,MAAM,KAAI,EAAE,CAAC,GACnC,SAAS,CAAC,aAAa,EAEhC,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { getObjectKeys } from '../../domUtils/getObjectKeys';\nimport { optimize } from '../optimizers/optimize';\nimport { reuseCachedElement } from '../../domUtils/reuseCachedElement';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelParagraph,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst DefaultParagraphTag = 'div';\n\n/**\n * @internal\n */\nexport const handleParagraph: ContentModelBlockHandler<ContentModelParagraph> = (\n doc: Document,\n parent: Node,\n paragraph: ContentModelParagraph,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n let container = context.allowCacheElement ? paragraph.cachedElement : undefined;\n\n if (container && paragraph.segments.every(x => x.segmentType != 'General' && !x.isSelected)) {\n refNode = reuseCachedElement(parent, container, refNode, context.rewriteFromModel);\n } else {\n stackFormat(context, paragraph.decorator?.tagName || null, () => {\n const needParagraphWrapper =\n !paragraph.isImplicit ||\n !!paragraph.decorator ||\n (getObjectKeys(paragraph.format).length > 0 &&\n paragraph.segments.some(segment => segment.segmentType != 'SelectionMarker'));\n const formatOnWrapper = needParagraphWrapper\n ? {\n ...(paragraph.decorator?.format || {}),\n ...paragraph.segmentFormat,\n }\n : {};\n const prevRefNode = refNode?.previousSibling;\n\n container = doc.createElement(paragraph.decorator?.tagName || DefaultParagraphTag);\n\n context.regularSelection.current = {\n block: needParagraphWrapper ? container : container.parentNode,\n segment: null,\n };\n\n const handleSegments = () => {\n const parent = container;\n\n if (parent) {\n const firstSegment = paragraph.segments[0];\n\n if (firstSegment?.segmentType == 'SelectionMarker') {\n // Make sure there is a segment created before selection marker.\n // If selection marker is the first selected segment in a paragraph, create a dummy text node,\n // so after rewrite, the regularSelection object can have a valid segment object set to the text node.\n context.modelHandlers.text(\n doc,\n parent,\n {\n ...firstSegment,\n segmentType: 'Text',\n text: '',\n },\n context,\n []\n );\n }\n\n paragraph.segments.forEach(segment => {\n const newSegments: Node[] = [];\n context.modelHandlers.segment(doc, parent, segment, context, newSegments);\n\n newSegments.forEach(node => {\n context.domIndexer?.onSegment(node, paragraph, [segment]);\n });\n });\n }\n };\n\n if (needParagraphWrapper) {\n stackFormat(context, formatOnWrapper, handleSegments);\n\n applyFormat(container, context.formatAppliers.block, paragraph.format, context);\n applyFormat(container, context.formatAppliers.container, paragraph.format, context);\n applyFormat(\n container,\n context.formatAppliers.segmentOnBlock,\n formatOnWrapper,\n context\n );\n\n context.paragraphMap?.applyMarkerToDom(container, paragraph);\n } else {\n handleSegments();\n }\n\n optimize(container, context);\n\n // It is possible the next sibling node is changed during processing child segments\n // e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment\n // The segment will be appended to container as child then the container will be removed\n // since this paragraph it is implicit. In that case container.nextSibling will become original\n // inline entity's next sibling. So reset refNode to its real next sibling (after change) here\n // to make sure the value is correct.\n refNode =\n prevRefNode === undefined // When refNode is not passed in\n ? null\n : prevRefNode === null // When refNode is the first child of parent\n ? parent.firstChild\n : prevRefNode.nextSibling; // Normal case\n\n parent.insertBefore(container, refNode);\n\n if (container) {\n context.onNodeCreated?.(paragraph, container);\n context.domIndexer?.onParagraph(container);\n }\n\n if (needParagraphWrapper) {\n if (context.allowCacheElement) {\n paragraph.cachedElement = container;\n }\n\n context.rewriteFromModel.addedBlockElements.push(container);\n } else {\n unwrap(container);\n container = undefined;\n }\n });\n }\n\n return refNode;\n};\n"]}
|
|
@@ -4,5 +4,6 @@ import type { ContentModelBlockGroup, ContentModelBlockGroupType, ReadonlyConten
|
|
|
4
4
|
* @param path The block group path, from the closest one to root
|
|
5
5
|
* @param blockGroupTypes The expected block group types
|
|
6
6
|
* @param stopTypes @optional Block group types that will cause stop searching
|
|
7
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
7
8
|
*/
|
|
8
|
-
export declare function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(path: ReadonlyContentModelBlockGroup[], blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes?: ContentModelBlockGroupType[]): number;
|
|
9
|
+
export declare function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(path: ReadonlyContentModelBlockGroup[], blockGroupTypes: TypeOfBlockGroup<T>[], stopTypes?: ContentModelBlockGroupType[], isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean): number;
|
|
@@ -7,12 +7,14 @@ define(["require", "exports"], function (require, exports) {
|
|
|
7
7
|
* @param path The block group path, from the closest one to root
|
|
8
8
|
* @param blockGroupTypes The expected block group types
|
|
9
9
|
* @param stopTypes @optional Block group types that will cause stop searching
|
|
10
|
+
* @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target
|
|
10
11
|
*/
|
|
11
|
-
function getClosestAncestorBlockGroupIndex(path, blockGroupTypes, stopTypes) {
|
|
12
|
+
function getClosestAncestorBlockGroupIndex(path, blockGroupTypes, stopTypes, isValidTarget) {
|
|
12
13
|
if (stopTypes === void 0) { stopTypes = []; }
|
|
13
14
|
for (var i = 0; i < path.length; i++) {
|
|
14
15
|
var group = path[i];
|
|
15
|
-
if (blockGroupTypes.indexOf(group.blockGroupType) >= 0
|
|
16
|
+
if (blockGroupTypes.indexOf(group.blockGroupType) >= 0 &&
|
|
17
|
+
(!isValidTarget || isValidTarget(group))) {
|
|
16
18
|
return i;
|
|
17
19
|
}
|
|
18
20
|
else if (stopTypes.indexOf(group.blockGroupType) >= 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getClosestAncestorBlockGroupIndex.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.ts"],"names":[],"mappings":";;;;IAOA
|
|
1
|
+
{"version":3,"file":"getClosestAncestorBlockGroupIndex.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.ts"],"names":[],"mappings":";;;;IAOA;;;;;;OAMG;IACH,SAAgB,iCAAiC,CAC7C,IAAsC,EACtC,eAAsC,EACtC,SAA4C,EAC5C,aAAkE;QADlE,0BAAA,EAAA,cAA4C;QAG5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAClC,IAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAEtB,IACK,eAA4B,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;gBAChE,CAAC,CAAC,aAAa,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,EAC1C;gBACE,OAAO,CAAC,CAAC;aACZ;iBAAM,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE;gBACrD,oDAAoD;gBACpD,+DAA+D;gBAC/D,iGAAiG;gBACjG,0FAA0F;gBAC1F,OAAO,CAAC,CAAC,CAAC;aACb;SACJ;QAED,OAAO,CAAC,CAAC,CAAC;IACd,CAAC;IAxBD,8EAwBC","sourcesContent":["import type {\n ContentModelBlockGroup,\n ContentModelBlockGroupType,\n ReadonlyContentModelBlockGroup,\n TypeOfBlockGroup,\n} from 'roosterjs-content-model-types';\n\n/**\n * Get index of closest ancestor block group of the expected block group type. If not found, return -1\n * @param path The block group path, from the closest one to root\n * @param blockGroupTypes The expected block group types\n * @param stopTypes @optional Block group types that will cause stop searching\n * @param isValidTarget @optional An additional callback to validate whether a matching block group is a valid target\n */\nexport function getClosestAncestorBlockGroupIndex<T extends ContentModelBlockGroup>(\n path: ReadonlyContentModelBlockGroup[],\n blockGroupTypes: TypeOfBlockGroup<T>[],\n stopTypes: ContentModelBlockGroupType[] = [],\n isValidTarget?: (block: ReadonlyContentModelBlockGroup) => boolean\n): number {\n for (let i = 0; i < path.length; i++) {\n const group = path[i];\n\n if (\n (blockGroupTypes as string[]).indexOf(group.blockGroupType) >= 0 &&\n (!isValidTarget || isValidTarget(group))\n ) {\n return i;\n } else if (stopTypes.indexOf(group.blockGroupType) >= 0) {\n // Do not go across boundary specified by stopTypes.\n // For example, in most case we will set table as the boundary,\n // in order to allow modify list item under a table when the table itself is in another list item\n // Although this is not very likely to happen in most case, but we still need to handle it\n return -1;\n }\n }\n\n return -1;\n}\n"]}
|
|
@@ -163,7 +163,7 @@ define(["require", "exports", "tslib", "../common/addBlock", "../common/addSegme
|
|
|
163
163
|
function mergeList(markerPosition, newList) {
|
|
164
164
|
splitParagraph(markerPosition, newList.format);
|
|
165
165
|
var path = markerPosition.path, paragraph = markerPosition.paragraph;
|
|
166
|
-
var listItemIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem']);
|
|
166
|
+
var listItemIndex = (0, getClosestAncestorBlockGroupIndex_1.getClosestAncestorBlockGroupIndex)(path, ['ListItem'], ['TableCell']);
|
|
167
167
|
var listItem = path[listItemIndex];
|
|
168
168
|
var listParent = path[listItemIndex + 1]; // It is ok here when index is -1, that means there is no list and we just insert a new paragraph and use path[0] as its parent
|
|
169
169
|
var blockIndex = listParent.blocks.indexOf(listItem || paragraph);
|