From 2a786a837a35c3450c1d68a31ab454c6fc2bb70e Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Fri, 16 Dec 2022 23:36:24 +0900 Subject: [PATCH 01/12] Table Block: Support rowspan attribute in table HTML, including when pasting --- packages/block-library/src/table/block.json | 15 ++ packages/block-library/src/table/edit.js | 13 +- packages/block-library/src/table/save.js | 21 +- .../block-library/src/table/transforms.js | 4 +- packages/block-library/src/table/utils.js | 10 + .../api/raw-handling/test/paste-handler.js | 181 ++++++++++++------ 6 files changed, 183 insertions(+), 61 deletions(-) create mode 100644 packages/block-library/src/table/utils.js diff --git a/packages/block-library/src/table/block.json b/packages/block-library/src/table/block.json index 5e21c1f07f8ba..adac1e9c2130e 100644 --- a/packages/block-library/src/table/block.json +++ b/packages/block-library/src/table/block.json @@ -52,6 +52,11 @@ "type": "string", "source": "attribute", "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" } } } @@ -92,6 +97,11 @@ "type": "string", "source": "attribute", "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" } } } @@ -132,6 +142,11 @@ "type": "string", "source": "attribute", "attribute": "colspan" + }, + "rowspan": { + "type": "string", + "source": "attribute", + "attribute": "rowspan" } } } diff --git a/packages/block-library/src/table/edit.js b/packages/block-library/src/table/edit.js index f417645036ffc..4dea9416a00ab 100644 --- a/packages/block-library/src/table/edit.js +++ b/packages/block-library/src/table/edit.js @@ -57,6 +57,7 @@ import { toggleSection, isEmptyTableSection, } from './state'; +import { normalizeRowColSpan } from './utils'; const ALIGNMENT_CONTROLS = [ { @@ -404,7 +405,14 @@ function TableEdit( { { cells.map( ( - { content, tag: CellTag, scope, align, colspan }, + { + content, + tag: CellTag, + scope, + align, + colspan, + rowspan, + }, columnIndex ) => ( { diff --git a/packages/block-library/src/table/save.js b/packages/block-library/src/table/save.js index d3393267b754d..5766887895a97 100644 --- a/packages/block-library/src/table/save.js +++ b/packages/block-library/src/table/save.js @@ -14,6 +14,11 @@ import { __experimentalGetElementClassName, } from '@wordpress/block-editor'; +/** + * Internal dependencies + */ +import { normalizeRowColSpan } from './utils'; + export default function save( { attributes } ) { const { hasFixedLayout, head, body, foot, caption } = attributes; const isEmpty = ! head.length && ! body.length && ! foot.length; @@ -44,7 +49,14 @@ export default function save( { attributes } ) { { cells.map( ( - { content, tag, scope, align, colspan }, + { + content, + tag, + scope, + align, + colspan, + rowspan, + }, cellIndex ) => { const cellClasses = classnames( { @@ -65,7 +77,12 @@ export default function save( { attributes } ) { scope={ tag === 'th' ? scope : undefined } - colSpan={ colspan } + colSpan={ normalizeRowColSpan( + colspan + ) } + rowSpan={ normalizeRowColSpan( + rowspan + ) } /> ); } diff --git a/packages/block-library/src/table/transforms.js b/packages/block-library/src/table/transforms.js index 0651c3bc64c41..906af299e2557 100644 --- a/packages/block-library/src/table/transforms.js +++ b/packages/block-library/src/table/transforms.js @@ -5,12 +5,12 @@ const tableContentPasteSchema = ( { phrasingContentSchema } ) => ( { th: { allowEmpty: true, children: phrasingContentSchema, - attributes: [ 'scope', 'colspan' ], + attributes: [ 'scope', 'colspan', 'rowspan' ], }, td: { allowEmpty: true, children: phrasingContentSchema, - attributes: [ 'colspan' ], + attributes: [ 'colspan', 'rowspan' ], }, }, }, diff --git a/packages/block-library/src/table/utils.js b/packages/block-library/src/table/utils.js new file mode 100644 index 0000000000000..240cf4b361e2d --- /dev/null +++ b/packages/block-library/src/table/utils.js @@ -0,0 +1,10 @@ +/** + * Normalize the row or column span value. + * + * @param {number|undefined} rowColSpan normalized value. + */ +export function normalizeRowColSpan( rowColSpan ) { + return parseInt( rowColSpan, 10 ) && parseInt( rowColSpan, 10 ) !== 1 + ? parseInt( rowColSpan, 10 ) + : undefined; +} diff --git a/packages/blocks/src/api/raw-handling/test/paste-handler.js b/packages/blocks/src/api/raw-handling/test/paste-handler.js index 378189b10e0ea..a601f30813736 100644 --- a/packages/blocks/src/api/raw-handling/test/paste-handler.js +++ b/packages/blocks/src/api/raw-handling/test/paste-handler.js @@ -7,48 +7,42 @@ import { pasteHandler } from '@wordpress/blocks'; */ import { init as initAndRegisterTableBlock } from '../../../../../block-library/src/table'; -const tableWithHeaderFooterAndBodyUsingColspan = ` +const tableWithHeaderFooterAndBodyUsingColspanAndRowspan = ` - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Colspan 2Header Cell
Footer CellFooter Cell
Colspan 2Cell Data
Header CellHeader CellRowspan 2
Colspan 2
Body CellBody CellRowspan 2
Colspan 2
Footer CellFooter CellRowspan 2
Colspan 2
`; -const googleDocsTableWithColspan = ` - -
- - - - - - - - - - -
-

Test colspan -

-
-

+const googleDocsTableWithColspanAndRowspan = ` +
Body CellBody Cell
Rowspan 2
Colspan 2
`; describe( 'pasteHandler', () => { @@ -56,9 +50,9 @@ describe( 'pasteHandler', () => { initAndRegisterTableBlock(); } ); - it( 'can handle a table with thead, tbody and tfoot using colspan', () => { + it( 'can handle a table with thead, tbody and tfoot using colspan and rowspan', () => { const [ result ] = pasteHandler( { - HTML: tableWithHeaderFooterAndBodyUsingColspan, + HTML: tableWithHeaderFooterAndBodyUsingColspanAndRowspan, tagName: 'p', preserveWhiteSpace: false, } ); @@ -71,24 +65,84 @@ describe( 'pasteHandler', () => { head: [ { cells: [ - { content: 'Colspan 2', tag: 'th', colspan: '2' }, - { content: 'Header Cell', tag: 'th' }, + { + content: 'Header Cell', + tag: 'th', + }, + { + content: 'Header Cell', + tag: 'th', + }, + { + content: 'Rowspan 2', + tag: 'th', + rowspan: '2', + }, + ], + }, + { + cells: [ + { + content: 'Colspan 2', + tag: 'th', + colspan: '2', + }, ], }, ], body: [ { cells: [ - { content: 'Colspan 2', tag: 'td', colspan: '2' }, - { content: 'Cell Data', tag: 'td' }, + { + content: 'Body Cell', + tag: 'td', + }, + { + content: 'Body Cell', + tag: 'td', + }, + { + content: 'Rowspan 2', + tag: 'td', + rowspan: '2', + }, + ], + }, + { + cells: [ + { + content: 'Colspan 2', + tag: 'td', + colspan: '2', + }, ], }, ], foot: [ { cells: [ - { content: 'Footer Cell', tag: 'th', colspan: '2' }, - { content: 'Footer Cell', tag: 'th' }, + { + content: 'Footer Cell', + tag: 'td', + }, + { + content: 'Footer Cell', + tag: 'td', + }, + { + content: 'Rowspan 2', + tag: 'td', + rowspan: '2', + }, + ], + }, + { + cells: [ + { + content: 'Colspan 2', + tag: 'td', + colspan: '2', + }, ], }, ], @@ -97,9 +151,9 @@ describe( 'pasteHandler', () => { expect( result.isValid ).toBeTruthy(); } ); - it( 'can handle a google docs table with colspan', () => { + it( 'can handle a google docs table with colspan and rowspan', () => { const [ result ] = pasteHandler( { - HTML: googleDocsTableWithColspan, + HTML: googleDocsTableWithColspanAndRowspan, tagName: 'p', preserveWhiteSpace: false, } ); @@ -107,23 +161,40 @@ describe( 'pasteHandler', () => { expect( console ).toHaveLogged(); expect( result.attributes ).toEqual( { + hasFixedLayout: false, + caption: '', body: [ { cells: [ { - align: undefined, - colspan: '2', - content: 'Test colspan', - scope: undefined, + content: 'Body Cell', + tag: 'td', + }, + { + content: 'Body Cell', + tag: 'td', + }, + { + content: 'Rowspan 2', tag: 'td', + colspan: '1', + rowspan: '2', + }, + ], + }, + { + cells: [ + { + content: 'Colspan 2', + tag: 'td', + colspan: '2', + rowspan: '1', }, ], }, ], - caption: '', - foot: [], - hasFixedLayout: false, head: [], + foot: [], } ); expect( result.name ).toEqual( 'core/table' ); expect( result.isValid ).toBeTruthy(); From 641e77f18eedd1bf19a9c2dd5c9cb452e9e1b67a Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 12:32:23 +0900 Subject: [PATCH 02/12] Updated normalize function and add unit tests --- .../block-library/src/table/test/utils.js | 20 +++++++++++++++++++ packages/block-library/src/table/utils.js | 12 +++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 packages/block-library/src/table/test/utils.js diff --git a/packages/block-library/src/table/test/utils.js b/packages/block-library/src/table/test/utils.js new file mode 100644 index 0000000000000..5669b619c53a7 --- /dev/null +++ b/packages/block-library/src/table/test/utils.js @@ -0,0 +1,20 @@ +/** + * Internal dependencies + */ +import { normalizeRowColSpan } from '../utils'; + +describe( 'normalizeRowColSpan', () => { + it( 'should convert a value to an integer', () => { + expect( normalizeRowColSpan( 2 ) ).toBe( 2 ); + expect( normalizeRowColSpan( '2' ) ).toBe( 2 ); + expect( normalizeRowColSpan( 2.55 ) ).toBe( 2 ); + expect( normalizeRowColSpan( '2.55' ) ).toBe( 2 ); + } ); + + it( 'should return undefined for values not allowed as the rowspan/colspan attributes', () => { + expect( normalizeRowColSpan( -2 ) ).toBe( undefined ); + expect( normalizeRowColSpan( '-2' ) ).toBe( undefined ); + expect( normalizeRowColSpan( 1 ) ).toBe( undefined ); + expect( normalizeRowColSpan( '1' ) ).toBe( undefined ); + } ); +} ); diff --git a/packages/block-library/src/table/utils.js b/packages/block-library/src/table/utils.js index 240cf4b361e2d..f01eef6315c8f 100644 --- a/packages/block-library/src/table/utils.js +++ b/packages/block-library/src/table/utils.js @@ -1,10 +1,14 @@ /** - * Normalize the row or column span value. + * Normalize the rowspan/colspan value. + * Returns undefined if the parameter is not a positive number + * or the default value (1) for rowspan/colspan. * * @param {number|undefined} rowColSpan normalized value. */ export function normalizeRowColSpan( rowColSpan ) { - return parseInt( rowColSpan, 10 ) && parseInt( rowColSpan, 10 ) !== 1 - ? parseInt( rowColSpan, 10 ) - : undefined; + const parsedValue = parseInt( rowColSpan, 10 ); + if ( ! Number.isInteger( parsedValue ) ) { + return undefined; + } + return parsedValue < 0 || parsedValue === 1 ? undefined : parsedValue; } From f909370c4330c3181e1dcee5c17c8eaf1bed6d6f Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:14:41 +0900 Subject: [PATCH 03/12] Move colspan test to integration tests --- .../integration/__snapshots__/blocks-raw-handling.test.js.snap | 2 ++ test/integration/blocks-raw-handling.test.js | 1 + .../fixtures/documents/google-docs-table-colspan-in.html | 1 + .../fixtures/documents/google-docs-table-colspan-out.html | 3 +++ 4 files changed, 7 insertions(+) create mode 100644 test/integration/fixtures/documents/google-docs-table-colspan-in.html create mode 100644 test/integration/fixtures/documents/google-docs-table-colspan-out.html diff --git a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap index 19aa5bd262ea3..5f802bd460fc6 100644 --- a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap +++ b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap @@ -12,6 +12,8 @@ exports[`Blocks raw handling pasteHandler google-docs-list-only 1`] = `"My first exports[`Blocks raw handling pasteHandler google-docs-table 1`] = `"



One
Two
Three
1
2
3
I
II
III"`; +exports[`Blocks raw handling pasteHandler google-docs-table-colspan 1`] = `"

Test colspan

"`; + exports[`Blocks raw handling pasteHandler google-docs-table-with-comments 1`] = `"



One
Two
Three
1
2
3
I
II
III"`; exports[`Blocks raw handling pasteHandler google-docs-with-comments 1`] = `"This is a title

This is a heading

Formatting test: bold, italic, link, strikethrough, superscript, subscript, nested.

A
Bulleted
Indented
List

One
Two
Three




One
Two
Three
1
2
3
I
II
III





An image:



"`; diff --git a/test/integration/blocks-raw-handling.test.js b/test/integration/blocks-raw-handling.test.js index eeab475567d27..c78fd2d19a310 100644 --- a/test/integration/blocks-raw-handling.test.js +++ b/test/integration/blocks-raw-handling.test.js @@ -378,6 +378,7 @@ describe( 'Blocks raw handling', () => { 'google-docs', 'google-docs-list-only', 'google-docs-table', + 'google-docs-table-colspan', 'google-docs-table-with-comments', 'google-docs-with-comments', 'ms-word', diff --git a/test/integration/fixtures/documents/google-docs-table-colspan-in.html b/test/integration/fixtures/documents/google-docs-table-colspan-in.html new file mode 100644 index 0000000000000..99f41829e6c8e --- /dev/null +++ b/test/integration/fixtures/documents/google-docs-table-colspan-in.html @@ -0,0 +1 @@ +

Test colspan



diff --git a/test/integration/fixtures/documents/google-docs-table-colspan-out.html b/test/integration/fixtures/documents/google-docs-table-colspan-out.html new file mode 100644 index 0000000000000..3c397c142e34d --- /dev/null +++ b/test/integration/fixtures/documents/google-docs-table-colspan-out.html @@ -0,0 +1,3 @@ + +
Test colspan
+ From b3d45971b72c0386898bd85c77d3ba62799adeaf Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:19:24 +0900 Subject: [PATCH 04/12] Revert unit test for colspan --- .../api/raw-handling/test/paste-handler.js | 151 ++---------------- 1 file changed, 13 insertions(+), 138 deletions(-) diff --git a/packages/blocks/src/api/raw-handling/test/paste-handler.js b/packages/blocks/src/api/raw-handling/test/paste-handler.js index a601f30813736..bd702b176b74a 100644 --- a/packages/blocks/src/api/raw-handling/test/paste-handler.js +++ b/packages/blocks/src/api/raw-handling/test/paste-handler.js @@ -7,52 +7,36 @@ import { pasteHandler } from '@wordpress/blocks'; */ import { init as initAndRegisterTableBlock } from '../../../../../block-library/src/table'; -const tableWithHeaderFooterAndBodyUsingColspanAndRowspan = ` +const tableWithHeaderFooterAndBodyUsingColspan = ` - - - - - + - - - - - + - - - - - - + +
Header CellHeader CellRowspan 2
Colspan 2Header Cell
Body CellBody CellRowspan 2
Colspan 2Cell Data
Footer CellFooter CellRowspan 2
Colspan 2Footer CellFooter Cell
`; -const googleDocsTableWithColspanAndRowspan = ` -
Body CellBody Cell
Rowspan 2
Colspan 2
-`; - describe( 'pasteHandler', () => { beforeAll( () => { initAndRegisterTableBlock(); } ); - it( 'can handle a table with thead, tbody and tfoot using colspan and rowspan', () => { + it( 'can handle a table with thead, tbody and tfoot using colspan', () => { const [ result ] = pasteHandler( { - HTML: tableWithHeaderFooterAndBodyUsingColspanAndRowspan, + HTML: tableWithHeaderFooterAndBodyUsingColspan, tagName: 'p', preserveWhiteSpace: false, } ); @@ -65,136 +49,27 @@ describe( 'pasteHandler', () => { head: [ { cells: [ - { - content: 'Header Cell', - tag: 'th', - }, - { - content: 'Header Cell', - tag: 'th', - }, - { - content: 'Rowspan 2', - tag: 'th', - rowspan: '2', - }, - ], - }, - { - cells: [ - { - content: 'Colspan 2', - tag: 'th', - colspan: '2', - }, + { content: 'Colspan 2', tag: 'th', colspan: '2' }, + { content: 'Header Cell', tag: 'th' }, ], }, ], body: [ { cells: [ - { - content: 'Body Cell', - tag: 'td', - }, - { - content: 'Body Cell', - tag: 'td', - }, - { - content: 'Rowspan 2', - tag: 'td', - rowspan: '2', - }, - ], - }, - { - cells: [ - { - content: 'Colspan 2', - tag: 'td', - colspan: '2', - }, + { content: 'Colspan 2', tag: 'td', colspan: '2' }, + { content: 'Cell Data', tag: 'td' }, ], }, ], foot: [ { cells: [ - { - content: 'Footer Cell', - tag: 'td', - }, - { - content: 'Footer Cell', - tag: 'td', - }, - { - content: 'Rowspan 2', - tag: 'td', - rowspan: '2', - }, - ], - }, - { - cells: [ - { - content: 'Colspan 2', - tag: 'td', - colspan: '2', - }, - ], - }, - ], - } ); - expect( result.name ).toEqual( 'core/table' ); - expect( result.isValid ).toBeTruthy(); - } ); - - it( 'can handle a google docs table with colspan and rowspan', () => { - const [ result ] = pasteHandler( { - HTML: googleDocsTableWithColspanAndRowspan, - tagName: 'p', - preserveWhiteSpace: false, - } ); - - expect( console ).toHaveLogged(); - - expect( result.attributes ).toEqual( { - hasFixedLayout: false, - caption: '', - body: [ - { - cells: [ - { - content: 'Body Cell', - tag: 'td', - }, - { - content: 'Body Cell', - tag: 'td', - }, - { - content: 'Rowspan 2', - tag: 'td', - colspan: '1', - rowspan: '2', - }, - ], - }, - { - cells: [ - { - content: 'Colspan 2', - tag: 'td', - colspan: '2', - rowspan: '1', - }, + { content: 'Footer Cell', tag: 'th', colspan: '2' }, + { content: 'Footer Cell', tag: 'th' }, ], }, ], - head: [], - foot: [], } ); expect( result.name ).toEqual( 'core/table' ); expect( result.isValid ).toBeTruthy(); From 5ca5e939368ddf964064ef6025b4bc559ab94718 Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:26:50 +0900 Subject: [PATCH 05/12] Add unit test for rowspan --- .../api/raw-handling/test/paste-handler.js | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/packages/blocks/src/api/raw-handling/test/paste-handler.js b/packages/blocks/src/api/raw-handling/test/paste-handler.js index bd702b176b74a..cf9943056bd32 100644 --- a/packages/blocks/src/api/raw-handling/test/paste-handler.js +++ b/packages/blocks/src/api/raw-handling/test/paste-handler.js @@ -29,6 +29,37 @@ const tableWithHeaderFooterAndBodyUsingColspan = ` `; +const tableWithHeaderFooterAndBodyUsingRowspan = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Rowspan 2Header Cell
Header Cell
Rowspan 2Cell Data
Cell Data
Rowspan 2Footer Cell
Footer Cell
`; + describe( 'pasteHandler', () => { beforeAll( () => { initAndRegisterTableBlock(); @@ -74,4 +105,54 @@ describe( 'pasteHandler', () => { expect( result.name ).toEqual( 'core/table' ); expect( result.isValid ).toBeTruthy(); } ); + + it( 'can handle a table with thead, tbody and tfoot using rowspan', () => { + const [ result ] = pasteHandler( { + HTML: tableWithHeaderFooterAndBodyUsingRowspan, + tagName: 'p', + preserveWhiteSpace: false, + } ); + + expect( console ).toHaveLogged(); + + expect( result.attributes ).toEqual( { + hasFixedLayout: false, + caption: '', + head: [ + { + cells: [ + { content: 'Rowspan 2', tag: 'th', rowspan: '2' }, + { content: 'Header Cell', tag: 'th' }, + ], + }, + { + cells: [ { content: 'Header Cell', tag: 'th' } ], + }, + ], + body: [ + { + cells: [ + { content: 'Rowspan 2', tag: 'td', rowspan: '2' }, + { content: 'Cell Data', tag: 'td' }, + ], + }, + { + cells: [ { content: 'Cell Data', tag: 'td' } ], + }, + ], + foot: [ + { + cells: [ + { content: 'Rowspan 2', tag: 'td', rowspan: '2' }, + { content: 'Footer Cell', tag: 'td' }, + ], + }, + { + cells: [ { content: 'Footer Cell', tag: 'td' } ], + }, + ], + } ); + expect( result.name ).toEqual( 'core/table' ); + expect( result.isValid ).toBeTruthy(); + } ); } ); From 6f675ccd29ad2667c2beb21656445f1004c1117f Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:31:16 +0900 Subject: [PATCH 06/12] Add integration test for rowspan --- .../__snapshots__/blocks-raw-handling.test.js.snap | 2 ++ test/integration/blocks-raw-handling.test.js | 1 + .../documents/google-docs-table-rowspan-in.html | 14 ++++++++++++++ .../documents/google-docs-table-rowspan-out.html | 3 +++ 4 files changed, 20 insertions(+) create mode 100644 test/integration/fixtures/documents/google-docs-table-rowspan-in.html create mode 100644 test/integration/fixtures/documents/google-docs-table-rowspan-out.html diff --git a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap index 5f802bd460fc6..2f97a51c8c6ad 100644 --- a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap +++ b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap @@ -14,6 +14,8 @@ exports[`Blocks raw handling pasteHandler google-docs-table 1`] = `"


exports[`Blocks raw handling pasteHandler google-docs-table-colspan 1`] = `"

Test colspan

"`; +exports[`Blocks raw handling pasteHandler google-docs-table-rowspan 1`] = `"

Test rowspan

"`; + exports[`Blocks raw handling pasteHandler google-docs-table-with-comments 1`] = `"



One
Two
Three
1
2
3
I
II
III"`; exports[`Blocks raw handling pasteHandler google-docs-with-comments 1`] = `"This is a title

This is a heading

Formatting test: bold, italic, link, strikethrough, superscript, subscript, nested.

A
Bulleted
Indented
List

One
Two
Three




One
Two
Three
1
2
3
I
II
III





An image:



"`; diff --git a/test/integration/blocks-raw-handling.test.js b/test/integration/blocks-raw-handling.test.js index c78fd2d19a310..387d7331cf87c 100644 --- a/test/integration/blocks-raw-handling.test.js +++ b/test/integration/blocks-raw-handling.test.js @@ -379,6 +379,7 @@ describe( 'Blocks raw handling', () => { 'google-docs-list-only', 'google-docs-table', 'google-docs-table-colspan', + 'google-docs-table-rowspan', 'google-docs-table-with-comments', 'google-docs-with-comments', 'ms-word', diff --git a/test/integration/fixtures/documents/google-docs-table-rowspan-in.html b/test/integration/fixtures/documents/google-docs-table-rowspan-in.html new file mode 100644 index 0000000000000..d24f46879a4ec --- /dev/null +++ b/test/integration/fixtures/documents/google-docs-table-rowspan-in.html @@ -0,0 +1,14 @@ +
+ + + + + + + + +
+

Test rowspan

+
+ +


diff --git a/test/integration/fixtures/documents/google-docs-table-rowspan-out.html b/test/integration/fixtures/documents/google-docs-table-rowspan-out.html new file mode 100644 index 0000000000000..d451d6eb2988b --- /dev/null +++ b/test/integration/fixtures/documents/google-docs-table-rowspan-out.html @@ -0,0 +1,3 @@ + +
Test rowspan
+ From 75c476a88e25b03bc4b015ec421edf85ab00fc89 Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:38:15 +0900 Subject: [PATCH 07/12] Update integration test file name --- .../__snapshots__/blocks-raw-handling.test.js.snap | 4 ++-- test/integration/blocks-raw-handling.test.js | 4 ++-- ...colspan-in.html => google-docs-table-with-colspan-in.html} | 0 ...lspan-out.html => google-docs-table-with-colspan-out.html} | 0 ...rowspan-in.html => google-docs-table-with-rowspan-in.html} | 0 ...wspan-out.html => google-docs-table-with-rowspan-out.html} | 0 6 files changed, 4 insertions(+), 4 deletions(-) rename test/integration/fixtures/documents/{google-docs-table-colspan-in.html => google-docs-table-with-colspan-in.html} (100%) rename test/integration/fixtures/documents/{google-docs-table-colspan-out.html => google-docs-table-with-colspan-out.html} (100%) rename test/integration/fixtures/documents/{google-docs-table-rowspan-in.html => google-docs-table-with-rowspan-in.html} (100%) rename test/integration/fixtures/documents/{google-docs-table-rowspan-out.html => google-docs-table-with-rowspan-out.html} (100%) diff --git a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap index 2f97a51c8c6ad..84717b0254438 100644 --- a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap +++ b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap @@ -12,9 +12,9 @@ exports[`Blocks raw handling pasteHandler google-docs-list-only 1`] = `"My first exports[`Blocks raw handling pasteHandler google-docs-table 1`] = `"



One
Two
Three
1
2
3
I
II
III"`; -exports[`Blocks raw handling pasteHandler google-docs-table-colspan 1`] = `"

Test colspan

"`; +exports[`Blocks raw handling pasteHandler google-docs-table-with-colspan 1`] = `"

Test colspan

"`; -exports[`Blocks raw handling pasteHandler google-docs-table-rowspan 1`] = `"

Test rowspan

"`; +exports[`Blocks raw handling pasteHandler google-docs-table-with-rowspan 1`] = `"

Test rowspan

"`; exports[`Blocks raw handling pasteHandler google-docs-table-with-comments 1`] = `"



One
Two
Three
1
2
3
I
II
III"`; diff --git a/test/integration/blocks-raw-handling.test.js b/test/integration/blocks-raw-handling.test.js index 387d7331cf87c..2a31d0b0ceaa2 100644 --- a/test/integration/blocks-raw-handling.test.js +++ b/test/integration/blocks-raw-handling.test.js @@ -378,8 +378,8 @@ describe( 'Blocks raw handling', () => { 'google-docs', 'google-docs-list-only', 'google-docs-table', - 'google-docs-table-colspan', - 'google-docs-table-rowspan', + 'google-docs-table-with-colspan', + 'google-docs-table-with-rowspan', 'google-docs-table-with-comments', 'google-docs-with-comments', 'ms-word', diff --git a/test/integration/fixtures/documents/google-docs-table-colspan-in.html b/test/integration/fixtures/documents/google-docs-table-with-colspan-in.html similarity index 100% rename from test/integration/fixtures/documents/google-docs-table-colspan-in.html rename to test/integration/fixtures/documents/google-docs-table-with-colspan-in.html diff --git a/test/integration/fixtures/documents/google-docs-table-colspan-out.html b/test/integration/fixtures/documents/google-docs-table-with-colspan-out.html similarity index 100% rename from test/integration/fixtures/documents/google-docs-table-colspan-out.html rename to test/integration/fixtures/documents/google-docs-table-with-colspan-out.html diff --git a/test/integration/fixtures/documents/google-docs-table-rowspan-in.html b/test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html similarity index 100% rename from test/integration/fixtures/documents/google-docs-table-rowspan-in.html rename to test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html diff --git a/test/integration/fixtures/documents/google-docs-table-rowspan-out.html b/test/integration/fixtures/documents/google-docs-table-with-rowspan-out.html similarity index 100% rename from test/integration/fixtures/documents/google-docs-table-rowspan-out.html rename to test/integration/fixtures/documents/google-docs-table-with-rowspan-out.html From e1b1ed4c4c12801629d621ff1bc48b087faf9e56 Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Tue, 20 Dec 2022 22:45:06 +0900 Subject: [PATCH 08/12] remove space --- .../google-docs-table-with-rowspan-in.html | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html b/test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html index d24f46879a4ec..5665f905752c5 100644 --- a/test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html +++ b/test/integration/fixtures/documents/google-docs-table-with-rowspan-in.html @@ -1,14 +1 @@ -
- - - - - - - - -
-

Test rowspan

-
- -


+

Test rowspan



From cd5a9c8397212f846d62e005a7571e4a7782e11c Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Fri, 23 Dec 2022 20:36:01 +0900 Subject: [PATCH 09/12] Update cell text on unit test --- packages/blocks/src/api/raw-handling/test/paste-handler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/blocks/src/api/raw-handling/test/paste-handler.js b/packages/blocks/src/api/raw-handling/test/paste-handler.js index cf9943056bd32..e8e1e34c7d57a 100644 --- a/packages/blocks/src/api/raw-handling/test/paste-handler.js +++ b/packages/blocks/src/api/raw-handling/test/paste-handler.js @@ -23,7 +23,7 @@ const tableWithHeaderFooterAndBodyUsingColspan = ` - Footer Cell + Colspan 2 Footer Cell @@ -96,7 +96,7 @@ describe( 'pasteHandler', () => { foot: [ { cells: [ - { content: 'Footer Cell', tag: 'th', colspan: '2' }, + { content: 'Colspan 2', tag: 'th', colspan: '2' }, { content: 'Footer Cell', tag: 'th' }, ], }, From bc1c6c50dc2f0015f104123959f0c5d380540bc4 Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Fri, 6 Jan 2023 23:23:42 +0900 Subject: [PATCH 10/12] Normalize rowspan/colspan in transforms --- packages/block-library/src/table/edit.js | 5 +- packages/block-library/src/table/save.js | 13 +--- .../block-library/src/table/transforms.js | 63 +++++++++++++++++++ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/packages/block-library/src/table/edit.js b/packages/block-library/src/table/edit.js index 4dea9416a00ab..af3d7d3990071 100644 --- a/packages/block-library/src/table/edit.js +++ b/packages/block-library/src/table/edit.js @@ -57,7 +57,6 @@ import { toggleSection, isEmptyTableSection, } from './state'; -import { normalizeRowColSpan } from './utils'; const ALIGNMENT_CONTROLS = [ { @@ -425,8 +424,8 @@ function TableEdit( { 'wp-block-table__cell-content' ) } scope={ CellTag === 'th' ? scope : undefined } - colSpan={ normalizeRowColSpan( colspan ) } - rowSpan={ normalizeRowColSpan( rowspan ) } + colSpan={ colspan } + rowSpan={ rowspan } value={ content } onChange={ onChange } unstableOnFocus={ () => { diff --git a/packages/block-library/src/table/save.js b/packages/block-library/src/table/save.js index 5766887895a97..dca1295656aa6 100644 --- a/packages/block-library/src/table/save.js +++ b/packages/block-library/src/table/save.js @@ -14,11 +14,6 @@ import { __experimentalGetElementClassName, } from '@wordpress/block-editor'; -/** - * Internal dependencies - */ -import { normalizeRowColSpan } from './utils'; - export default function save( { attributes } ) { const { hasFixedLayout, head, body, foot, caption } = attributes; const isEmpty = ! head.length && ! body.length && ! foot.length; @@ -77,12 +72,8 @@ export default function save( { attributes } ) { scope={ tag === 'th' ? scope : undefined } - colSpan={ normalizeRowColSpan( - colspan - ) } - rowSpan={ normalizeRowColSpan( - rowspan - ) } + colSpan={ colspan } + rowSpan={ rowspan } /> ); } diff --git a/packages/block-library/src/table/transforms.js b/packages/block-library/src/table/transforms.js index 906af299e2557..bce2f56158d15 100644 --- a/packages/block-library/src/table/transforms.js +++ b/packages/block-library/src/table/transforms.js @@ -1,3 +1,13 @@ +/** + * WordPress dependencies + */ +import { createBlock } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import { normalizeRowColSpan } from './utils'; + const tableContentPasteSchema = ( { phrasingContentSchema } ) => ( { tr: { allowEmpty: true, @@ -41,6 +51,59 @@ const transforms = { type: 'raw', selector: 'table', schema: tablePasteSchema, + transform: ( node ) => { + const attributes = Array.from( node.children ).reduce( + ( sectionAcc, section ) => { + if ( ! section.children.length ) { + return sectionAcc; + } + + const sectionName = section.nodeName + .toLowerCase() + .slice( 1 ); + + const sectionAttributes = Array.from( + section.children + ).reduce( ( rowAcc, row ) => { + if ( ! row.children.length ) { + return rowAcc; + } + + const rowAttributes = Array.from( + row.children + ).reduce( ( colAcc, col ) => { + const rowspan = normalizeRowColSpan( + col.getAttribute( 'rowspan' ) + ); + const colspan = normalizeRowColSpan( + col.getAttribute( 'colspan' ) + ); + + colAcc.push( { + tag: col.nodeName.toLowerCase(), + content: col.innerHTML, + rowspan, + colspan, + } ); + + return colAcc; + }, [] ); + + rowAcc.push( { + cells: rowAttributes, + } ); + + return rowAcc; + }, [] ); + + sectionAcc[ sectionName ] = sectionAttributes; + return sectionAcc; + }, + {} + ); + + return createBlock( 'core/table', attributes ); + }, }, ], }; From ba71d017684f307fe1a5b1c5edef97cf9f88c8e5 Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Fri, 6 Jan 2023 23:27:09 +0900 Subject: [PATCH 11/12] Fix unit test and utils --- packages/block-library/src/table/utils.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/table/utils.js b/packages/block-library/src/table/utils.js index f01eef6315c8f..a445c7f5547a7 100644 --- a/packages/block-library/src/table/utils.js +++ b/packages/block-library/src/table/utils.js @@ -3,12 +3,16 @@ * Returns undefined if the parameter is not a positive number * or the default value (1) for rowspan/colspan. * - * @param {number|undefined} rowColSpan normalized value. + * @param {number|undefined} rowColSpan rowspan/colspan value. + * + * @return {string|undefined} normalized rowspan/colspan value. */ export function normalizeRowColSpan( rowColSpan ) { const parsedValue = parseInt( rowColSpan, 10 ); if ( ! Number.isInteger( parsedValue ) ) { return undefined; } - return parsedValue < 0 || parsedValue === 1 ? undefined : parsedValue; + return parsedValue < 0 || parsedValue === 1 + ? undefined + : parsedValue.toString(); } From 5da6ba5d677723a758108f2c3633870853cee21a Mon Sep 17 00:00:00 2001 From: Tetsuaki Hamano Date: Sat, 7 Jan 2023 00:10:47 +0900 Subject: [PATCH 12/12] fix unit test --- packages/block-library/src/table/test/utils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/table/test/utils.js b/packages/block-library/src/table/test/utils.js index 5669b619c53a7..4dc9d8121dd12 100644 --- a/packages/block-library/src/table/test/utils.js +++ b/packages/block-library/src/table/test/utils.js @@ -4,11 +4,11 @@ import { normalizeRowColSpan } from '../utils'; describe( 'normalizeRowColSpan', () => { - it( 'should convert a value to an integer', () => { - expect( normalizeRowColSpan( 2 ) ).toBe( 2 ); - expect( normalizeRowColSpan( '2' ) ).toBe( 2 ); - expect( normalizeRowColSpan( 2.55 ) ).toBe( 2 ); - expect( normalizeRowColSpan( '2.55' ) ).toBe( 2 ); + it( 'should convert a value to a string', () => { + expect( normalizeRowColSpan( 2 ) ).toBe( '2' ); + expect( normalizeRowColSpan( '2' ) ).toBe( '2' ); + expect( normalizeRowColSpan( 2.55 ) ).toBe( '2' ); + expect( normalizeRowColSpan( '2.55' ) ).toBe( '2' ); } ); it( 'should return undefined for values not allowed as the rowspan/colspan attributes', () => {