diff --git a/core-blocks/index.js b/core-blocks/index.js index a7bc40d32de637..fbc206ab6057d8 100644 --- a/core-blocks/index.js +++ b/core-blocks/index.js @@ -41,6 +41,8 @@ import * as shortcode from './shortcode'; import * as spacer from './spacer'; import * as subhead from './subhead'; import * as table from './table'; +import * as tableRow from './table/row'; +import * as tableCell from './table/cell'; import * as textColumns from './text-columns'; import * as verse from './verse'; import * as video from './video'; @@ -83,6 +85,8 @@ export const registerCoreBlocks = () => { spacer, subhead, table, + tableRow, + tableCell, textColumns, verse, video, diff --git a/core-blocks/paragraph/index.js b/core-blocks/paragraph/index.js index b742fb6cf53f77..3a3e0ee5d5b654 100644 --- a/core-blocks/paragraph/index.js +++ b/core-blocks/paragraph/index.js @@ -18,6 +18,7 @@ import { } from '@wordpress/editor'; import { getPhrasingContentSchema, + richTextStructure, } from '@wordpress/blocks'; /** @@ -200,9 +201,7 @@ export const settings = { migrate( attributes ) { return { ...attributes, - content: [ - { attributes.content }, - ], + content: richTextStructure.create( attributes.content ), }; }, }, diff --git a/core-blocks/table/cell.js b/core-blocks/table/cell.js new file mode 100644 index 00000000000000..8778937252cd91 --- /dev/null +++ b/core-blocks/table/cell.js @@ -0,0 +1,56 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { RichText } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import { name as rowName } from './row'; + +export const name = 'core/table-cell'; + +export const settings = { + title: __( 'Table Cell' ), + + description: __( 'Add some basic text.' ), + + parent: [ rowName ], + + icon: 'editor-table', + + category: 'common', + + keywords: [ __( 'text' ) ], + + supports: { + className: false, + }, + + attributes: { + content: { + type: 'object', + source: 'rich-text', + selector: 'td,th', + }, + }, + + edit( { attributes, setAttributes } ) { + return ( + { + setAttributes( { content } ); + } } + placeholder={ __( 'Add cell content' ) } + /> + ); + }, + + save( { attributes } ) { + return ( + + ); + }, +}; diff --git a/core-blocks/table/editor.scss b/core-blocks/table/editor.scss index 447ebbc9a02c04..d1aa307c029398 100644 --- a/core-blocks/table/editor.scss +++ b/core-blocks/table/editor.scss @@ -15,3 +15,58 @@ background-color: $light-gray-300; } } + +// These margins make sure that nested blocks stack/overlay with the parent block chrome +// This is sort of an experiment at making sure the editor looks as much like the end result as possible +// Potentially the rules here can apply to all nested blocks and enable stacking, in which case it should be moved elsewhere +// When using CSS grid, margins do not collapse on the container. +.wp-block-table .editor-block-list__layout { + margin-top: 0; + margin-bottom: 0; + + &:first-child { + margin-top: -$block-padding; + } + + &:last-child { + margin-bottom: -$block-padding; + } + + // This max-width is used to constrain the main editor column, it should not cascade into columns + .editor-block-list__block { + max-width: none; + } +} + +// This block has flex container children. Flex container margins do not collapse: https://www.w3.org/TR/css-flexbox-1/#flex-containers. +// Therefore, let's at least not add any additional margins here. +// The goal is for the editor to look more like the front-end. +.editor-block-list__layout .editor-block-list__block[data-type="core/table-row"] > .editor-block-list__block-edit, +.editor-block-list__layout .editor-block-list__block[data-type="core/table-row"] > .editor-block-list__block-edit { + margin-top: 0; + margin-bottom: 0; + + // This uncollapses margins on this parent container. + padding-top: 0.1px; + padding-bottom: 0.1px; +} + +.wp-block-table-row { + display: block; + + > .editor-inner-blocks > .editor-block-list__layout { + display: flex; + + > [data-type="core/table-row"] { + display: flex; + flex-direction: column; + flex: 1; + width: 0; + + .editor-block-list__block-edit { + flex-basis: 100%; + } + } + } +} + diff --git a/core-blocks/table/index.js b/core-blocks/table/index.js index cc69c87266aa1f..159170abd1a34f 100644 --- a/core-blocks/table/index.js +++ b/core-blocks/table/index.js @@ -1,23 +1,16 @@ /** * External dependencies */ -import { __ } from '@wordpress/i18n'; import classnames from 'classnames'; /** * WordPress dependencies */ import { Fragment } from '@wordpress/element'; -import { getPhrasingContentSchema } from '@wordpress/blocks'; -import { - RichText, - InspectorControls, -} from '@wordpress/editor'; - -import { - PanelBody, - ToggleControl, -} from '@wordpress/components'; +import { getPhrasingContentSchema, createBlock, getBlockAttributes } from '@wordpress/blocks'; +import { InspectorControls, InnerBlocks } from '@wordpress/editor'; +import { PanelBody, ToggleControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -25,7 +18,8 @@ import { import './editor.scss'; import './style.scss'; import './theme.scss'; -import TableBlock from './table-block'; +import { name as rowName } from './row'; +import { name as cellName, settings as cellSettings } from './cell'; const tableContentSchema = { tr: { @@ -65,26 +59,6 @@ export const settings = { category: 'formatting', attributes: { - rows: { - type: 'array', - default: [], - source: 'query', - selector: 'tr', - query: { - cells: { - type: 'array', - default: [], - source: 'query', - selector: 'th,tr', - query: { - cell: { - type: 'object', - source: 'rich-text', - }, - }, - }, - }, - }, hasFixedLayout: { type: 'boolean', default: false, @@ -101,22 +75,35 @@ export const settings = { type: 'raw', selector: 'table', schema: tableSchema, + transform( node ) { + const rows = Array.from( node.querySelectorAll( 'tr' ) ); + + const block = createBlock( name, {}, rows.map( ( row ) => { + const cells = Array.from( row.querySelectorAll( 'td,th' ) ); + + return createBlock( rowName, {}, cells.map( ( cell ) => { + const blockAttributes = getBlockAttributes( cellSettings, cell.outerHTML ); + + return createBlock( cellName, blockAttributes ); + } ) ); + } ) ); + + return block; + }, }, ], }, - edit( { attributes, setAttributes, isSelected, className } ) { - const { content, hasFixedLayout } = attributes; + edit( { attributes, setAttributes, className } ) { + const { hasFixedLayout } = attributes; + const toggleFixedLayout = () => { setAttributes( { hasFixedLayout: ! hasFixedLayout } ); }; - const classes = classnames( - className, - { - 'has-fixed-layout': hasFixedLayout, - }, - ); + const classes = classnames( className, { + 'has-fixed-layout': hasFixedLayout, + } ); return ( @@ -129,28 +116,28 @@ export const settings = { /> - { - setAttributes( { content: nextContent } ); - } } - content={ content } - className={ classes } - isSelected={ isSelected } - /> +
+ +
); }, save( { attributes } ) { - const { content, hasFixedLayout } = attributes; - const classes = classnames( - { - 'has-fixed-layout': hasFixedLayout, - }, - ); + const classes = classnames( { + 'has-fixed-layout': attributes.hasFixedLayout, + } ); return ( - + + + + +
); }, }; diff --git a/core-blocks/table/row.js b/core-blocks/table/row.js new file mode 100644 index 00000000000000..4a765f0a8029b3 --- /dev/null +++ b/core-blocks/table/row.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { InnerBlocks } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import { name as tableName } from '.'; +import { name as cellName } from './cell'; + +export const name = 'core/table-row'; + +export const settings = { + title: __( 'Table Row' ), + + parent: [ tableName ], + + icon: 'editor-table', + + description: __( 'A single column within a columns block.' ), + + category: 'common', + + supports: { + className: false, + }, + + edit() { + return ( + + ); + }, + + save() { + return ; + }, +}; diff --git a/core-blocks/table/test/__snapshots__/index.js.snap b/core-blocks/table/test/__snapshots__/index.js.snap index e336bc498289ee..e0c77b6f92c624 100644 --- a/core-blocks/table/test/__snapshots__/index.js.snap +++ b/core-blocks/table/test/__snapshots__/index.js.snap @@ -2,40 +2,14 @@ exports[`core/embed block edit matches snapshot 1`] = `
-
-
-
- - - - - - - - - - - - -
-
+
+
`; diff --git a/core-blocks/test/fixtures/core__freeform.json b/core-blocks/test/fixtures/core__freeform.json index 72341f093f2fbc..1fd82536ad6ad0 100644 --- a/core-blocks/test/fixtures/core__freeform.json +++ b/core-blocks/test/fixtures/core__freeform.json @@ -4,7 +4,7 @@ "name": "core/freeform", "isValid": true, "attributes": { - "content": "

Testing freeform block with some\n

\n\tHTML content\n
" + "content": "

Testing freeform block with some\n

\n\tHTML content\n
" }, "innerBlocks": [], "originalContent": "

Testing freeform block with some\n

\n\tHTML content\n
" diff --git a/core-blocks/test/fixtures/core__freeform.serialized.html b/core-blocks/test/fixtures/core__freeform.serialized.html index 4fed04550b031c..311563acb4aa3f 100644 --- a/core-blocks/test/fixtures/core__freeform.serialized.html +++ b/core-blocks/test/fixtures/core__freeform.serialized.html @@ -1,4 +1,4 @@

Testing freeform block with some -

+
HTML content
diff --git a/core-blocks/test/fixtures/core__freeform__undelimited.json b/core-blocks/test/fixtures/core__freeform__undelimited.json index 72341f093f2fbc..1fd82536ad6ad0 100644 --- a/core-blocks/test/fixtures/core__freeform__undelimited.json +++ b/core-blocks/test/fixtures/core__freeform__undelimited.json @@ -4,7 +4,7 @@ "name": "core/freeform", "isValid": true, "attributes": { - "content": "

Testing freeform block with some\n

\n\tHTML content\n
" + "content": "

Testing freeform block with some\n

\n\tHTML content\n
" }, "innerBlocks": [], "originalContent": "

Testing freeform block with some\n

\n\tHTML content\n
" diff --git a/core-blocks/test/fixtures/core__freeform__undelimited.serialized.html b/core-blocks/test/fixtures/core__freeform__undelimited.serialized.html index 4fed04550b031c..311563acb4aa3f 100644 --- a/core-blocks/test/fixtures/core__freeform__undelimited.serialized.html +++ b/core-blocks/test/fixtures/core__freeform__undelimited.serialized.html @@ -1,4 +1,4 @@

Testing freeform block with some -

+
HTML content
diff --git a/core-blocks/test/fixtures/core__paragraph__deprecated.json b/core-blocks/test/fixtures/core__paragraph__deprecated.json index 4279147742265d..daf5da7008a224 100644 --- a/core-blocks/test/fixtures/core__paragraph__deprecated.json +++ b/core-blocks/test/fixtures/core__paragraph__deprecated.json @@ -4,17 +4,56 @@ "name": "core/paragraph", "isValid": true, "attributes": { - "content": [ - { - "key": "html", - "ref": null, - "props": { - "children": "Unwrapped is still valid." - }, - "_owner": null, - "_store": {} - } - ], + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [ + { + "type": "em" + } + ], + [ + { + "type": "em" + } + ], + [ + { + "type": "em" + } + ], + [ + { + "type": "em" + } + ], + [ + { + "type": "em" + } + ], + null, + null, + null, + null, + null, + null, + null + ], + "text": "Unwrapped is still valid." + }, "dropCap": false }, "innerBlocks": [], diff --git a/core-blocks/test/fixtures/core__table-cell.html b/core-blocks/test/fixtures/core__table-cell.html new file mode 100644 index 00000000000000..3c61dc8dae08a0 --- /dev/null +++ b/core-blocks/test/fixtures/core__table-cell.html @@ -0,0 +1,3 @@ + +Version + diff --git a/core-blocks/test/fixtures/core__table-cell.json b/core-blocks/test/fixtures/core__table-cell.json new file mode 100644 index 00000000000000..6aefa8ae829fc9 --- /dev/null +++ b/core-blocks/test/fixtures/core__table-cell.json @@ -0,0 +1,23 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null + ], + "text": "Version" + } + }, + "innerBlocks": [], + "originalContent": "Version" + } +] diff --git a/core-blocks/test/fixtures/core__table-cell.parsed.json b/core-blocks/test/fixtures/core__table-cell.parsed.json new file mode 100644 index 00000000000000..8d00a0bca8050c --- /dev/null +++ b/core-blocks/test/fixtures/core__table-cell.parsed.json @@ -0,0 +1,12 @@ +[ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\nVersion\n" + }, + { + "attrs": {}, + "innerHTML": "\n" + } +] diff --git a/core-blocks/test/fixtures/core__table-cell.serialized.html b/core-blocks/test/fixtures/core__table-cell.serialized.html new file mode 100644 index 00000000000000..3c61dc8dae08a0 --- /dev/null +++ b/core-blocks/test/fixtures/core__table-cell.serialized.html @@ -0,0 +1,3 @@ + +Version + diff --git a/core-blocks/test/fixtures/core__table-row.html b/core-blocks/test/fixtures/core__table-row.html new file mode 100644 index 00000000000000..8492c2f390da2b --- /dev/null +++ b/core-blocks/test/fixtures/core__table-row.html @@ -0,0 +1,15 @@ + + + + Version + + + + Musician + + + + Date + + + diff --git a/core-blocks/test/fixtures/core__table-row.json b/core-blocks/test/fixtures/core__table-row.json new file mode 100644 index 00000000000000..d2e7025a45528a --- /dev/null +++ b/core-blocks/test/fixtures/core__table-row.json @@ -0,0 +1,72 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/table-row", + "isValid": true, + "attributes": {}, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null + ], + "text": "Version" + } + }, + "innerBlocks": [], + "originalContent": "Version" + }, + { + "clientId": "_clientId_1", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "Musician" + } + }, + "innerBlocks": [], + "originalContent": "Musician" + }, + { + "clientId": "_clientId_2", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null + ], + "text": "Date" + } + }, + "innerBlocks": [], + "originalContent": "Date" + } + ], + "originalContent": "\n\t\n\n\t\n\n\t\n" + } +] diff --git a/core-blocks/test/fixtures/core__table-row.parsed.json b/core-blocks/test/fixtures/core__table-row.parsed.json new file mode 100644 index 00000000000000..218d47cf028568 --- /dev/null +++ b/core-blocks/test/fixtures/core__table-row.parsed.json @@ -0,0 +1,31 @@ +[ + { + "blockName": "core/table-row", + "attrs": null, + "innerBlocks": [ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\tVersion\n\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\tMusician\n\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\tDate\n\t" + } + ], + "innerHTML": "\n\n\t\n\n\t\n\n\t\n\n" + }, + { + "attrs": {}, + "innerHTML": "\n" + } +] diff --git a/core-blocks/test/fixtures/core__table-row.serialized.html b/core-blocks/test/fixtures/core__table-row.serialized.html new file mode 100644 index 00000000000000..1f6bfbaa17b9fe --- /dev/null +++ b/core-blocks/test/fixtures/core__table-row.serialized.html @@ -0,0 +1,13 @@ + + +Version + + + +Musician + + + +Date + + diff --git a/core-blocks/test/fixtures/core__table.html b/core-blocks/test/fixtures/core__table.html index b9b41659e835aa..0144aeba894d29 100644 --- a/core-blocks/test/fixtures/core__table.html +++ b/core-blocks/test/fixtures/core__table.html @@ -1,3 +1,69 @@ -
VersionMusicianDate
.70No musician chosen.May 27, 2003
1.0Miles DavisJanuary 3, 2004
Lots of versions skipped, see the full list
4.4Clifford BrownDecember 8, 2015
4.5Coleman HawkinsApril 12, 2016
4.6Pepper AdamsAugust 16, 2016
4.7Sarah VaughanDecember 6, 2016
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VersionMusicianDate
.70No musician chosen.May 27, 2003
1.0Miles DavisJanuary 3, 2004
Lots of versions skipped, see the full list
diff --git a/core-blocks/test/fixtures/core__table.json b/core-blocks/test/fixtures/core__table.json new file mode 100644 index 00000000000000..12e654b9039861 --- /dev/null +++ b/core-blocks/test/fixtures/core__table.json @@ -0,0 +1,477 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/table", + "isValid": true, + "attributes": { + "hasFixedLayout": false + }, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-row", + "isValid": true, + "attributes": {}, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null + ], + "text": "Version" + } + }, + "innerBlocks": [], + "originalContent": "Version" + }, + { + "clientId": "_clientId_1", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "Musician" + } + }, + "innerBlocks": [], + "originalContent": "Musician" + }, + { + "clientId": "_clientId_2", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null + ], + "text": "Date" + } + }, + "innerBlocks": [], + "originalContent": "Date" + } + ], + "originalContent": "\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t" + }, + { + "clientId": "_clientId_1", + "name": "core/table-row", + "isValid": true, + "attributes": {}, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2003/05/wordpress-now-available/" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2003/05/wordpress-now-available/" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2003/05/wordpress-now-available/" + } + } + ] + ], + "text": ".70" + } + }, + "innerBlocks": [], + "originalContent": ".70" + }, + { + "clientId": "_clientId_1", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "No musician chosen." + } + }, + "innerBlocks": [], + "originalContent": "No musician chosen." + }, + { + "clientId": "_clientId_2", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "May 27, 2003" + } + }, + "innerBlocks": [], + "originalContent": "May 27, 2003" + } + ], + "originalContent": "\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t" + }, + { + "clientId": "_clientId_2", + "name": "core/table-row", + "isValid": true, + "attributes": {}, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2004/01/wordpress-10/" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2004/01/wordpress-10/" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://wordpress.org/news/2004/01/wordpress-10/" + } + } + ] + ], + "text": "1.0" + } + }, + "innerBlocks": [], + "originalContent": "1.0" + }, + { + "clientId": "_clientId_1", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "Miles Davis" + } + }, + "innerBlocks": [], + "originalContent": "Miles Davis" + }, + { + "clientId": "_clientId_2", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "text": "January 3, 2004" + } + }, + "innerBlocks": [], + "originalContent": "January 3, 2004" + } + ], + "originalContent": "\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t" + }, + { + "clientId": "_clientId_3", + "name": "core/table-row", + "isValid": true, + "attributes": {}, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ], + [ + { + "type": "a", + "attributes": { + "href": "https://codex.wordpress.org/WordPress_Versions" + } + } + ] + ], + "text": "Lots of versions skipped, see the full list" + } + }, + "innerBlocks": [], + "originalContent": "Lots of versions skipped, see the full list" + }, + { + "clientId": "_clientId_1", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null + ], + "text": "…" + } + }, + "innerBlocks": [], + "originalContent": "…" + }, + { + "clientId": "_clientId_2", + "name": "core/table-cell", + "isValid": true, + "attributes": { + "content": { + "formats": [ + null + ], + "text": "…" + } + }, + "innerBlocks": [], + "originalContent": "…" + } + ], + "originalContent": "\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t" + } + ], + "originalContent": "\n\t\n\t\t\n\n\t\t\n\n\t\t\n\n\t\t\n\t\n
" + } +] diff --git a/core-blocks/test/fixtures/core__table.parsed.json b/core-blocks/test/fixtures/core__table.parsed.json index 737ac5ea49098c..6c6c36f7817d44 100644 --- a/core-blocks/test/fixtures/core__table.parsed.json +++ b/core-blocks/test/fixtures/core__table.parsed.json @@ -2,8 +2,109 @@ { "blockName": "core/table", "attrs": null, - "innerBlocks": [], - "innerHTML": "\n
VersionMusicianDate
.70No musician chosen.May 27, 2003
1.0Miles DavisJanuary 3, 2004
Lots of versions skipped, see the full list
4.4Clifford BrownDecember 8, 2015
4.5Coleman HawkinsApril 12, 2016
4.6Pepper AdamsAugust 16, 2016
4.7Sarah VaughanDecember 6, 2016
\n" + "innerBlocks": [ + { + "blockName": "core/table-row", + "attrs": null, + "innerBlocks": [ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tVersion\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tMusician\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tDate\n\t\t\t" + } + ], + "innerHTML": "\n\t\t\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t\n\t\t" + }, + { + "blockName": "core/table-row", + "attrs": null, + "innerBlocks": [ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\t.70\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tNo musician chosen.\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tMay 27, 2003\n\t\t\t" + } + ], + "innerHTML": "\n\t\t\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t\n\t\t" + }, + { + "blockName": "core/table-row", + "attrs": null, + "innerBlocks": [ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\t1.0\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tMiles Davis\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tJanuary 3, 2004\n\t\t\t" + } + ], + "innerHTML": "\n\t\t\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t\n\t\t" + }, + { + "blockName": "core/table-row", + "attrs": null, + "innerBlocks": [ + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\tLots of versions skipped, see the full list\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\t…\n\t\t\t" + }, + { + "blockName": "core/table-cell", + "attrs": null, + "innerBlocks": [], + "innerHTML": "\n\t\t\t…\n\t\t\t" + } + ], + "innerHTML": "\n\t\t\n\t\t\t\n\n\t\t\t\n\n\t\t\t\n\t\t\n\t\t" + } + ], + "innerHTML": "\n\n\t\n\t\t\n\n\t\t\n\n\t\t\n\n\t\t\n\t\n
\n" }, { "attrs": {}, diff --git a/core-blocks/test/fixtures/core__table.serialized.html b/core-blocks/test/fixtures/core__table.serialized.html new file mode 100644 index 00000000000000..45891d295ff9fb --- /dev/null +++ b/core-blocks/test/fixtures/core__table.serialized.html @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VersionMusicianDate
.70No musician chosen.May 27, 2003
1.0Miles DavisJanuary 3, 2004
Lots of versions skipped, see the full list
+ diff --git a/core-blocks/text-columns/index.js b/core-blocks/text-columns/index.js index 103d7f51121be5..1e967f9f35741f 100644 --- a/core-blocks/text-columns/index.js +++ b/core-blocks/text-columns/index.js @@ -49,7 +49,20 @@ export const settings = { source: 'rich-text', }, }, - default: [ {}, {} ], + default: [ + { + children: { + text: '', + formats: [], + }, + }, + { + children: { + text: '', + formats: [], + }, + }, + ], }, columns: { type: 'number', diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 95bb39f7f5b1d7..0f8ac42ce9098d 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -13,7 +13,7 @@ export { getBlockAttributes, parseWithAttributeSchema, } from './parser'; -export { default as rawHandler, getPhrasingContentSchema } from './raw-handling'; +export { default as rawHandler, getPhrasingContentSchema, htmlToBlocks } from './raw-handling'; export { default as serialize, getBlockContent, diff --git a/packages/blocks/src/api/parser.js b/packages/blocks/src/api/parser.js index dcb01e11c16cd3..7c4d24b33b05bf 100644 --- a/packages/blocks/src/api/parser.js +++ b/packages/blocks/src/api/parser.js @@ -133,7 +133,15 @@ export function matcherFromSource( sourceConfig ) { * @return {*} Attribute value. */ export function parseWithAttributeSchema( innerHTML, attributeSchema ) { - return hpqParse( innerHTML, matcherFromSource( attributeSchema ) ); + if ( attributeSchema.source === 'html' && ! attributeSchema.selector ) { + return innerHTML; + } + + const template = document.createElement( 'template' ); + + template.innerHTML = innerHTML; + + return hpqParse( template.content, matcherFromSource( attributeSchema ) ); } /** diff --git a/packages/blocks/src/api/rich-text-structure.js b/packages/blocks/src/api/rich-text-structure.js index 1031f134d2cece..b4ddfa522ba9aa 100644 --- a/packages/blocks/src/api/rich-text-structure.js +++ b/packages/blocks/src/api/rich-text-structure.js @@ -6,7 +6,19 @@ import { find } from 'lodash'; const { TEXT_NODE, ELEMENT_NODE } = window.Node; +function createElement( html ) { + const doc = document.implementation.createHTMLDocument( '' ); + + doc.body.innerHTML = html; + + return doc.body; +} + export function createWithSelection( element, range, multiline, settings ) { + if ( typeof element === 'string' ) { + element = createElement( element ); + } + if ( ! multiline ) { return createRecord( element, range, settings ); } @@ -67,6 +79,8 @@ function createRecord( element, range, settings = {} ) { filterString = ( string ) => string, } = settings; + const filterStringComplete = ( string ) => filterString( string.replace( '\n', '' ) ); + if ( element.nodeName === 'BR' && ! removeNodeMatch( element ) && @@ -97,15 +111,15 @@ function createRecord( element, range, settings = {} ) { if ( node.nodeType === TEXT_NODE ) { if ( range ) { if ( node === range.startContainer ) { - accumulator.selection.start = accumulator.value.text.length + filterString( node.nodeValue.slice( 0, range.startOffset ) ).length; + accumulator.selection.start = accumulator.value.text.length + filterStringComplete( node.nodeValue.slice( 0, range.startOffset ) ).length; } if ( node === range.endContainer ) { - accumulator.selection.end = accumulator.value.text.length + filterString( node.nodeValue.slice( 0, range.endOffset ) ).length; + accumulator.selection.end = accumulator.value.text.length + filterStringComplete( node.nodeValue.slice( 0, range.endOffset ) ).length; } } - const text = filterString( node.nodeValue, accumulator.selection ); + const text = filterStringComplete( node.nodeValue, accumulator.selection ); accumulator.value.text += text; formats.push( ...Array( text.length ) ); } else if ( node.nodeType === ELEMENT_NODE ) { diff --git a/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap b/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap index b0d595e5d3e90b..4b2478e939a7a1 100644 --- a/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap +++ b/packages/editor/src/components/document-outline/test/__snapshots__/index.js.snap @@ -15,7 +15,12 @@ exports[`DocumentOutline header blocks present should match snapshot 1`] = ` @@ -50,7 +60,12 @@ exports[`DocumentOutline header blocks present should render warnings for multip

{ paragraph = createBlock( 'core/paragraph' ); headingH1 = createBlock( 'core/heading', { - content: 'Heading 1', + content: { + formats: [], + text: 'Heading 1', + }, level: 1, } ); headingParent = createBlock( 'core/heading', { - content: 'Heading parent', + content: { + formats: [], + text: 'Heading parent', + }, level: 2, } ); headingChild = createBlock( 'core/heading', { - content: 'Heading child', + content: { + formats: [], + text: 'Heading child', + }, level: 3, } ); diff --git a/test/integration/fixtures/apple-out.html b/test/integration/fixtures/apple-out.html index 530bf8d34140c2..a7845c75a6a50c 100644 --- a/test/integration/fixtures/apple-out.html +++ b/test/integration/fixtures/apple-out.html @@ -19,25 +19,47 @@ -
-One - -Two - -Three -
-1 - -2 - -3 -
-I - -II - -III -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
One
Two
Three
1
2
3
I
II
III
diff --git a/test/integration/fixtures/evernote-out.html b/test/integration/fixtures/evernote-out.html index 4d8c6c43b9c99e..fe7fa0b93e5d44 100644 --- a/test/integration/fixtures/evernote-out.html +++ b/test/integration/fixtures/evernote-out.html @@ -1,7 +1,5 @@ -

This is a paragraph. -
This is a link. -

+

This is a paragraph.
This is a link.

@@ -17,13 +15,33 @@ -
One -Two -Three -
Four -Five -Six -
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
OneTwoThree
FourFiveSix
diff --git a/test/integration/fixtures/google-docs-out.html b/test/integration/fixtures/google-docs-out.html index a8d31000403d60..3411d19896ac1c 100644 --- a/test/integration/fixtures/google-docs-out.html +++ b/test/integration/fixtures/google-docs-out.html @@ -19,7 +19,47 @@

This is a heading

-
OneTwoThree
123
IIIIII
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OneTwoThree
123
IIIIII
diff --git a/test/integration/fixtures/markdown-out.html b/test/integration/fixtures/markdown-out.html index cf83cf40050c4a..56529c2e02c070 100644 --- a/test/integration/fixtures/markdown-out.html +++ b/test/integration/fixtures/markdown-out.html @@ -7,8 +7,7 @@

This is a heading with italic

-

Preserve
-line breaks please.

+

Preserve
line breaks please.

@@ -28,7 +27,35 @@

Table

-
First HeaderSecond Header
Content from cell 1Content from cell 2
Content in the first columnContent in the second column
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First HeaderSecond Header
Content from cell 1Content from cell 2
Content in the first columnContent in the second column
diff --git a/test/integration/fixtures/ms-word-online-out.html b/test/integration/fixtures/ms-word-online-out.html index 7de40b0e330ef0..88d6a01904956e 100644 --- a/test/integration/fixtures/ms-word-online-out.html +++ b/test/integration/fixtures/ms-word-online-out.html @@ -3,7 +3,7 @@ -

This is a paragraph with a link

+

This is a paragraph with a link

@@ -15,7 +15,47 @@ -
One Two Three 
II III 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
One Two Three 
II III 
diff --git a/test/integration/fixtures/ms-word-out.html b/test/integration/fixtures/ms-word-out.html index c53c5aaeba2e97..1b0b4b02b54d2a 100644 --- a/test/integration/fixtures/ms-word-out.html +++ b/test/integration/fixtures/ms-word-out.html @@ -1,11 +1,9 @@ -

This is a -title

+

This is atitle

-

This is a -subtitle

+

This is asubtitle

@@ -29,25 +27,47 @@

This is a heading level 2

-
- One - - Two - - Three -
- 1 - - 2 - - 3 -
- I - - II - - III -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
One
Two
Three
1
2
3
I
II
III