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

Try: Custom save serializer, Editable as array tree #4049

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions blocks/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ export {
doBlocksMatchTemplate,
synchronizeBlocksWithTemplate,
} from './templates';
export { nodeListToTree } from './matchers';
63 changes: 55 additions & 8 deletions blocks/api/matchers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,61 @@
/**
* WordPress dependencies
*/
import { createElement } from '@wordpress/element';

/**
* External dependencies
*/
import { nodeListToReact, nodeToReact } from 'dom-react';
export { attr, prop, html, text, query } from 'hpq';

export function buildTree( type, attributes, ...children ) {
children = children.map( ( child ) => {
if ( 'boolean' === typeof child ) {
child = null;
}

if ( null === child || undefined === child ) {
child = '';
} else if ( 'number' === typeof child ) {
child = String( child );
}

if ( 'string' === typeof child ) {
return child;
}

return buildTree( child );
} );

return [ type, attributes, children ];
}

export function nodeListToTree( nodeList, createElement ) {
return [ ...nodeList ].map( ( node ) => nodeToTree( node, createElement ) );
}

export function elementAsArray( type, attributes, children ) {
return [ type, attributes, children ];
}

export function nodeToTree( node, createElement = elementAsArray ) {
if ( ! node ) {
return null;
}

if ( node.nodeType === 3 ) {
Copy link
Member

Choose a reason for hiding this comment

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

We should use window.Node here.

return node.nodeValue;
}

if ( node.nodeType !== 1 ) {
return null;
}

const type = node.nodeName.toLowerCase();
const attributes = [ ...node.attributes ].reduce( ( result, { name, value } ) => {
result[ name ] = value;
return result;
}, {} );
const children = nodeListToTree( node.childNodes );

return createElement( type, attributes, children );
}

export const children = ( selector ) => {
return ( domNode ) => {
let match = domNode;
Expand All @@ -18,7 +65,7 @@ export const children = ( selector ) => {
}

if ( match ) {
return nodeListToReact( match.childNodes || [], createElement );
return nodeListToTree( match.childNodes );
}

return [];
Expand All @@ -33,6 +80,6 @@ export const node = ( selector ) => {
match = domNode.querySelector( selector );
}

return nodeToReact( match, createElement );
return nodeToTree( match );
};
};
2 changes: 1 addition & 1 deletion blocks/api/raw-handling/test/integration/evernote-out.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@
<!-- /wp:table -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="" alt="" /></figure>
<figure class="wp-block-image"><img src="" /></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ <h2>This is a <em>heading</em></h2>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh4.googleusercontent.com/ID" alt="" /></figure>
<figure class="wp-block-image"><img src="https://lh4.googleusercontent.com/ID" /></figure>
<!-- /wp:image -->

Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,5 @@
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="" alt="" /></figure>
<figure class="wp-block-image"><img src="" /></figure>
<!-- /wp:image -->
2 changes: 1 addition & 1 deletion blocks/api/raw-handling/test/integration/ms-word-out.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ <h2>This is a heading level 2</h2>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="" alt="" /></figure>
<figure class="wp-block-image"><img src="" /></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image -->
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-08-2017-15-12-24-17-300x137.gif" alt="" /></figure>
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-08-2017-15-12-24-17-300x137.gif" /></figure>
<!-- /wp:image -->
4 changes: 2 additions & 2 deletions blocks/api/raw-handling/test/integration/two-images-out.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- wp:image -->
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-08-2017-15-12-24-17-300x137.gif" alt="" /></figure>
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-08-2017-15-12-24-17-300x137.gif" /></figure>
<!-- /wp:image -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-05-2017-17-52-09-9-300x248.gif" alt="" /></figure>
<figure class="wp-block-image"><img src="http://localhost/wp-content/uploads/2018/01/Dec-05-2017-17-52-09-9-300x248.gif" /></figure>
<!-- /wp:image -->
2 changes: 1 addition & 1 deletion blocks/library/audio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export const settings = {
const { src, caption } = attributes;
return (
<figure>
<audio controls="controls" src={ src } />
<audio controls src={ src } />
{ caption && caption.length > 0 && <figcaption>{ caption }</figcaption> }
</figure>
);
Expand Down
8 changes: 2 additions & 6 deletions blocks/library/pullquote/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ export const settings = {

return (
<blockquote className={ `align${ align }` }>
{ value && value.map( ( paragraph, i ) =>
<p key={ i }>{ paragraph.children && paragraph.children.props.children }</p>
) }
{ value.map( ( paragraph ) => paragraph.children ) }
{ citation && citation.length > 0 && (
<cite>{ citation }</cite>
) }
Expand All @@ -145,9 +143,7 @@ export const settings = {

return (
<blockquote className={ `align${ align }` }>
{ value && value.map( ( paragraph, i ) =>
<p key={ i }>{ paragraph.children && paragraph.children.props.children }</p>
) }
{ value.map( ( paragraph ) => paragraph.children ) }
Copy link
Member

Choose a reason for hiding this comment

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

It's unfortunate that this still means that the block author needs to be aware of the editable value structure.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, in this case this is the structure from the block attribute's query result, necessary because there's no wrapper to separate content from the citation that would allow us to use the children source directly.

{ citation && citation.length > 0 && (
<footer>{ citation }</footer>
) }
Expand Down
8 changes: 2 additions & 6 deletions blocks/library/quote/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,7 @@ export const settings = {
className={ style === 2 ? 'is-large' : '' }
style={ { textAlign: align ? align : null } }
>
{ value.map( ( paragraph, i ) => (
<p key={ i }>{ paragraph.children && paragraph.children.props.children }</p>
) ) }
{ value.map( ( paragraph ) => paragraph.children ) }
{ citation && citation.length > 0 && (
<cite>{ citation }</cite>
) }
Expand All @@ -271,9 +269,7 @@ export const settings = {
className={ `blocks-quote-style-${ style }` }
style={ { textAlign: align ? align : null } }
>
{ value.map( ( paragraph, i ) => (
<p key={ i }>{ paragraph.children && paragraph.children.props.children }</p>
) ) }
{ value.map( ( paragraph ) => paragraph.children ) }
{ citation && citation.length > 0 && (
<footer>{ citation }</footer>
) }
Expand Down
42 changes: 29 additions & 13 deletions blocks/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
noop,
reject,
} from 'lodash';
import { nodeListToReact } from 'dom-react';
import 'element-closest';

/**
Expand All @@ -28,7 +27,7 @@ import { withSafeTimeout, Slot, Fill } from '@wordpress/components';
* Internal dependencies
*/
import './style.scss';
import { rawHandler } from '../api';
import { rawHandler, nodeListToTree } from '../api';
import FormatToolbar from './format-toolbar';
import TinyMCE from './tinymce';
import { pickAriaProps } from './aria';
Expand All @@ -37,6 +36,23 @@ import { EVENTS } from './constants';

const { BACKSPACE, DELETE, ENTER } = keycodes;

function toElement( value ) {
if ( ! value ) {
return null;
}

if ( ! Array.isArray( value ) ) {
return value;
}

const [ type, attributes, children ] = value;
if ( ! attributes || attributes.constructor !== Object ) {
return value.map( toElement );
}

return createElement( type, attributes, children.map( toElement ) );
}

export function createTinyMCEElement( type, props, ...children ) {
if ( props[ 'data-mce-bogus' ] === 'all' ) {
return null;
Expand All @@ -46,11 +62,11 @@ export function createTinyMCEElement( type, props, ...children ) {
return children;
}

return createElement(
return [
type,
omitBy( props, ( value, key ) => key.indexOf( 'data-mce-' ) === 0 ),
...children
);
children,
];
}

/**
Expand Down Expand Up @@ -530,8 +546,8 @@ export class RichText extends Component {
const index = dom.nodeIndex( selectedNode );
const beforeNodes = childNodes.slice( 0, index );
const afterNodes = childNodes.slice( index + 1 );
const beforeElement = nodeListToReact( beforeNodes, createTinyMCEElement );
const afterElement = nodeListToReact( afterNodes, createTinyMCEElement );
const beforeElement = nodeListToTree( beforeNodes, createTinyMCEElement );
const afterElement = nodeListToTree( afterNodes, createTinyMCEElement );

this.restoreContentAndSplit( beforeElement, afterElement );
} else {
Expand Down Expand Up @@ -590,8 +606,8 @@ export class RichText extends Component {
const beforeFragment = beforeRange.extractContents();
const afterFragment = afterRange.extractContents();

const beforeElement = nodeListToReact( beforeFragment.childNodes, createTinyMCEElement );
const afterElement = nodeListToReact( filterEmptyNodes( afterFragment.childNodes ), createTinyMCEElement );
const beforeElement = nodeListToTree( beforeFragment.childNodes, createTinyMCEElement );
const afterElement = nodeListToTree( filterEmptyNodes( afterFragment.childNodes ), createTinyMCEElement );

this.restoreContentAndSplit( beforeElement, afterElement, blocks );
} else {
Expand Down Expand Up @@ -642,8 +658,8 @@ export class RichText extends Component {
this.setContent( this.props.value );

this.restoreContentAndSplit(
nodeListToReact( before, createTinyMCEElement ),
nodeListToReact( after, createTinyMCEElement )
nodeListToTree( before, createTinyMCEElement ),
nodeListToTree( after, createTinyMCEElement )
);
}

Expand Down Expand Up @@ -682,7 +698,7 @@ export class RichText extends Component {
}

getContent() {
return nodeListToReact( this.editor.getBody().childNodes || [], createTinyMCEElement );
return nodeListToTree( this.editor.getBody().childNodes || [], createTinyMCEElement );
}

componentWillUnmount() {
Expand Down Expand Up @@ -823,7 +839,7 @@ export class RichText extends Component {
getSettings={ this.getSettings }
onSetup={ this.onSetup }
style={ style }
defaultValue={ value }
defaultValue={ toElement( value ) }
isPlaceholderVisible={ isPlaceholderVisible }
aria-label={ placeholder }
{ ...ariaProps }
Expand Down
22 changes: 15 additions & 7 deletions blocks/rich-text/test/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`createTinyMCEElement should render a TinyMCE element 1`] = `
<p
a-prop="hi"
>
<p>
Child
</p>
</p>
Array [
"p",
Object {
"a-prop": "hi",
},
Array [
Array [
"p",
Object {},
Array [
"Child",
],
],
],
]
`;
4 changes: 2 additions & 2 deletions blocks/rich-text/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { diffAriaProps, pickAriaProps } from '../aria';

describe( 'createTinyMCEElement', () => {
const type = 'p';
const children = <p>Child</p>;
const children = createTinyMCEElement( 'p', {}, 'Child' );

test( 'should return null', () => {
const props = {
Expand All @@ -42,7 +42,7 @@ describe( 'createTinyMCEElement', () => {
'a-prop': 'hi',
};

const wrapper = shallow( createTinyMCEElement( type, props, children ) );
const wrapper = createTinyMCEElement( type, props, children );
expect( wrapper ).toMatchSnapshot();
} );
} );
Expand Down
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__audio.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- wp:core/audio {"align":"right"} -->
<figure class="wp-block-audio alignright">
<audio controls="" src="https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3"></audio>
<audio controls="true" src="https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3"></audio>
</figure>
<!-- /wp:core/audio -->
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__audio.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"align": "right"
},
"innerBlocks": [],
"originalContent": "<figure class=\"wp-block-audio alignright\">\n <audio controls=\"\" src=\"https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3\"></audio>\n</figure>"
"originalContent": "<figure class=\"wp-block-audio alignright\">\n <audio controls=\"true\" src=\"https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3\"></audio>\n</figure>"
}
]
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__audio.parsed.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"align": "right"
},
"innerBlocks": [],
"innerHTML": "\n<figure class=\"wp-block-audio alignright\">\n <audio controls=\"\" src=\"https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3\"></audio>\n</figure>\n"
"innerHTML": "\n<figure class=\"wp-block-audio alignright\">\n <audio controls=\"true\" src=\"https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3\"></audio>\n</figure>\n"
},
{
"attrs": {},
Expand Down
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__audio.serialized.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:audio {"align":"right"} -->
<figure class="wp-block-audio alignright"><audio controls="" src="https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3"></audio></figure>
<figure class="wp-block-audio alignright"><audio controls="true" src="https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3"></audio></figure>
<!-- /wp:audio -->
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__code.serialized.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- wp:code -->
<pre class="wp-block-code"><code>export default function MyButton() {
return &lt;Button&gt;Click Me!&lt;/Button&gt;;
return &lt;Button>Click Me!&lt;/Button>;
}</code></pre>
<!-- /wp:code -->
11 changes: 7 additions & 4 deletions blocks/test/fixtures/core__heading__h2-em.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
"attributes": {
"content": [
"The ",
{
"type": "em",
"children": "Inserter"
},
[
"em",
{},
[
"Inserter"
]
],
" Tool"
],
"nodeName": "H2"
Expand Down
2 changes: 1 addition & 1 deletion blocks/test/fixtures/core__image.serialized.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cldup.com/uuUqE_dXzy.jpg" alt="" /></figure>
<figure class="wp-block-image"><img src="https://cldup.com/uuUqE_dXzy.jpg" /></figure>
<!-- /wp:image -->
Loading