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

Fix normalisation and First Column issues #2657

Merged
merged 11 commits into from
May 24, 2024
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
hasSelectionInBlockGroup,
getFirstSelectedTable,
normalizeTable,
setTableCellBackgroundColor,
} from 'roosterjs-content-model-dom';
import type { IEditor } from 'roosterjs-content-model-types';
Expand All @@ -19,8 +18,6 @@ export function setTableCellShade(editor: IEditor, color: string | null) {
const [table] = getFirstSelectedTable(model);

if (table) {
normalizeTable(table);

table.rows.forEach(row =>
row.cells.forEach(cell => {
if (hasSelectionInBlockGroup(cell)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function formatCells(
// Format Background Color
if (!metaOverrides.bgColorOverrides[rowIndex][colIndex]) {
let color: string | null | undefined;
if (hasFirstColumn && colIndex == 0) {
if (hasFirstColumn && colIndex == 0 && rowIndex > 0) {
color = null;
} else {
color =
Expand Down Expand Up @@ -239,7 +239,7 @@ function formatCells(
}

/**
* Set the first column format borders for the table
* Set the first column format borders for the table as well as header property
* @param rows The rows of the table
* @param format The table metadata format
*/
Expand All @@ -261,6 +261,7 @@ export function setFirstColumnFormatBorders(

switch (rowIndex) {
case 0:
cell.isHeader = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the cell was header? This will set it to false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the idea is that First Column does not apply to the first cell, at least that is the behaviour we implemented and I am just restoring it.

However I noticed that this can conflict with hasHeaderRow, so I made a change to apply the header status accordingly.

cell.isHeader = !!format.hasHeaderRow;

break;
case 1:
setBorderColor(cell.format, 'borderBottom');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relate to this change, but I realize that it is possible there are only 2 rows, in that case, "1" is the same with "rows.length-1", but then there are different handling. Is that ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, they should be flipped in order. The order should be row 0, then last row, then row 1, and then any other row.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const MIN_HEIGHT = 22;
/**
* Normalize a Content Model table, make sure:
* 1. Fist cells are not spanned
* 2. Inner cells are not header
* 2. Only first column and row can have headers
* 3. All cells have content and width
* 4. Table and table row have correct width/height
* 5. Spanned cell has no child blocks
Expand Down Expand Up @@ -64,7 +64,7 @@ export function normalizeTable(

if (rowIndex == 0) {
cell.spanAbove = false;
} else if (rowIndex > 0 && cell.isHeader) {
} else if (rowIndex > 0 && colIndex > 0 && cell.isHeader) {
cell.isHeader = false;
delete cell.cachedElement;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ describe('normalizeTable', () => {

normalizeTable(table as ReadonlyContentModelTable);

console.log('FAILED', table);
Andres-CT98 marked this conversation as resolved.
Show resolved Hide resolved
expect(table).toEqual({
blockType: 'Table',
rows: [
Expand Down Expand Up @@ -159,7 +160,7 @@ describe('normalizeTable', () => {
blockGroupType: 'TableCell',
spanLeft: false,
spanAbove: false,
isHeader: false,
isHeader: true,
format: { useBorderBox: true },
blocks: [
{
Expand All @@ -183,6 +184,133 @@ describe('normalizeTable', () => {
});
});

it('Normalize a table with only TH', () => {
const table = createTable(2);

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

table.widths = [100, 100];
table.rows[0].height = 200;
table.rows[1].height = 200;

normalizeTable(table);

expect(table).toEqual({
blockType: 'Table',
rows: [
{
height: 200,
format: {},
cells: [
{
blockGroupType: 'TableCell',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'Br',
format: {},
},
],
format: {},
},
],
format: {
useBorderBox: true,
},
spanLeft: false,
spanAbove: false,
isHeader: true,
dataset: {},
},
{
blockGroupType: 'TableCell',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'Br',
format: {},
},
],
format: {},
},
],
format: {
useBorderBox: true,
},
spanLeft: false,
spanAbove: false,
isHeader: true,
dataset: {},
},
],
},
{
height: 200,
format: {},
cells: [
{
blockGroupType: 'TableCell',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'Br',
format: {},
},
],
format: {},
},
],
format: {
useBorderBox: true,
},
spanLeft: false,
spanAbove: false,
isHeader: true,
dataset: {},
},
{
blockGroupType: 'TableCell',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'Br',
format: {},
},
],
format: {},
},
],
format: {
useBorderBox: true,
},
spanLeft: false,
spanAbove: false,
isHeader: false,
dataset: {},
},
],
},
],
format: {
borderCollapse: true,
useBorderBox: true,
},
widths: [100, 100],
dataset: {},
});
});

it('Normalize a table with left-spanned cells', () => {
const table = createTable(1);

Expand Down
Loading