Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content Model: Preserve segment format when insert table #1574

Merged
merged 2 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export interface MergeModelOption {
* @default false
*/
mergeTable?: boolean;

/**
* Use this insert position to merge instead of querying selection from target model
* @default undefined
*/
insertPosition?: InsertPosition;
}

/**
Expand All @@ -35,7 +41,7 @@ export function mergeModel(
source: ContentModelDocument,
options?: MergeModelOption
) {
const insertPosition = deleteSelection(target);
const insertPosition = options?.insertPosition ?? deleteSelection(target);

if (insertPosition) {
for (let i = 0; i < source.blocks.length; i++) {
Expand Down Expand Up @@ -140,7 +146,7 @@ function mergeTable(
}
}

normalizeTable(table);
normalizeTable(table, markerPosition.marker.format);
applyTableFormat(table, undefined /*newFormat*/, true /*keepCellShade*/);
} else {
insertBlock(markerPosition, newTable);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { addSegment } from '../common/addSegment';
import { arrayPush } from 'roosterjs-editor-dom';
import { ContentModelSegment } from '../../publicTypes/segment/ContentModelSegment';
import { ContentModelSegmentFormat } from '../../publicTypes/format/ContentModelSegmentFormat';
import { ContentModelTable } from '../../publicTypes/block/ContentModelTable';
import { ContentModelTableCell } from '../../publicTypes/group/ContentModelTableCell';
import { createBr } from '../creators/createBr';
Expand All @@ -10,7 +11,10 @@ const MIN_HEIGHT = 22;
/**
* @internal
*/
export function normalizeTable(table: ContentModelTable) {
export function normalizeTable(
table: ContentModelTable,
defaultSegmentFormat?: ContentModelSegmentFormat
) {
// Always collapse border and use border box for table in roosterjs to make layout simpler
table.format.borderCollapse = true;
table.format.useBorderBox = true;
Expand All @@ -21,7 +25,7 @@ export function normalizeTable(table: ContentModelTable) {
table.cells.forEach((row, rowIndex) => {
row.forEach((cell, colIndex) => {
if (cell.blocks.length == 0) {
addSegment(cell, createBr());
addSegment(cell, createBr(defaultSegmentFormat));
}

if (rowIndex == 0) {
Expand Down
33 changes: 21 additions & 12 deletions packages/roosterjs-content-model/lib/publicApi/table/insertTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { applyTableFormat } from '../../modelApi/table/applyTableFormat';
import { createContentModelDocument } from '../../modelApi/creators/createContentModelDocument';
import { createSelectionMarker } from '../../modelApi/creators/createSelectionMarker';
import { createTableStructure } from '../../modelApi/table/createTableStructure';
import { deleteSelection } from '../../modelApi/selection/deleteSelections';
import { formatWithContentModel } from '../utils/formatWithContentModel';
import { IContentModelEditor } from '../../publicTypes/IContentModelEditor';
import { mergeModel } from '../../modelApi/common/mergeModel';
Expand All @@ -25,21 +26,29 @@ export default function insertTable(
format?: TableMetadataFormat
) {
formatWithContentModel(editor, 'insertTable', model => {
const doc = createContentModelDocument();
const table = createTableStructure(doc, columns, rows);
const insertPosition = deleteSelection(model);

normalizeTable(table);
applyTableFormat(table, format);
mergeModel(model, doc);
if (insertPosition) {
const doc = createContentModelDocument();
const table = createTableStructure(doc, columns, rows);

const firstBlock = table.cells[0]?.[0]?.blocks[0];
normalizeTable(table, insertPosition.marker.format);
applyTableFormat(table, format);
mergeModel(model, doc, {
insertPosition,
});

if (firstBlock?.blockType == 'Paragraph') {
const marker = createSelectionMarker(firstBlock.segments[0]?.format);
firstBlock.segments.unshift(marker);
setSelection(model, marker);
}
const firstBlock = table.cells[0]?.[0]?.blocks[0];

if (firstBlock?.blockType == 'Paragraph') {
const marker = createSelectionMarker(firstBlock.segments[0]?.format);
firstBlock.segments.unshift(marker);
setSelection(model, marker);
}

return true;
return true;
} else {
return false;
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -1258,4 +1258,74 @@ describe('mergeModel', () => {
],
});
});

it('Use customized insert position', () => {
const majorModel = createContentModelDocument();
const sourceModel = createContentModelDocument();
const para1 = createParagraph();
const text1 = createText('test1');
const text2 = createText('test2');
const marker1 = createSelectionMarker();
const marker2 = createSelectionMarker();
const marker3 = createSelectionMarker();

para1.segments.push(marker1, text1, marker2, text2, marker3);
majorModel.blocks.push(para1);

const newPara = createParagraph();
const newText = createText('new text');

newPara.segments.push(newText);
sourceModel.blocks.push(newPara);

mergeModel(majorModel, sourceModel, {
insertPosition: {
marker: marker2,
paragraph: para1,
path: [majorModel],
},
});

expect(majorModel).toEqual({
blockGroupType: 'Document',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
{
segmentType: 'Text',
text: 'test1',
format: {},
},
{
segmentType: 'Text',
text: 'new text',
format: {},
},
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
{
segmentType: 'Text',
text: 'test2',
format: {},
},
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
],
format: {},
},
],
});
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ContentModelSegmentFormat } from '../../../lib/publicTypes/format/ContentModelSegmentFormat';
import { createParagraph } from '../../../lib/modelApi/creators/createParagraph';
import { createTable } from '../../../lib/modelApi/creators/createTable';
import { createTableCell } from '../../../lib/modelApi/creators/createTableCell';
Expand Down Expand Up @@ -571,4 +572,53 @@ describe('normalizeTable', () => {
dataset: {},
});
});

it('Normalize a table with format', () => {
const table = createTable(1);
const format: ContentModelSegmentFormat = {
fontSize: '10px',
};

table.cells[0].push(createTableCell(1, 1, false));

normalizeTable(table, format);

expect(table).toEqual({
blockType: 'Table',
cells: [
[
{
blockGroupType: 'TableCell',
spanAbove: false,
spanLeft: false,
isHeader: false,
format: { useBorderBox: true },
blocks: [
{
blockType: 'Paragraph',
isImplicit: true,
segments: [
{
segmentType: 'Br',
format: {
fontSize: '10px',
},
},
],
format: {},
},
],
dataset: {},
},
],
],
format: {
borderCollapse: true,
useBorderBox: true,
},
widths: [120],
heights: [22],
dataset: {},
});
});
});