Skip to content

Commit

Permalink
Represent Editable value as array tree
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Dec 15, 2017
1 parent ff695ba commit e1fe602
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 35 deletions.
2 changes: 1 addition & 1 deletion blocks/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ export {
hasBlockSupport,
isReusableBlock,
} from './registration';

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 ) {
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 );
};
};
42 changes: 29 additions & 13 deletions blocks/editable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
defer,
noop,
} from 'lodash';
import { nodeListToReact } from 'dom-react';
import 'element-closest';

/**
Expand All @@ -28,7 +27,7 @@ import { 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 ) );
}

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

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

function isLinkBoundary( fragment ) {
Expand Down Expand Up @@ -558,8 +574,8 @@ export default class Editable 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.setContent( beforeElement );
this.props.onSplit( beforeElement, afterElement );
Expand Down Expand Up @@ -613,8 +629,8 @@ export default class Editable extends Component {
const beforeFragment = beforeRange.extractContents();
const afterFragment = afterRange.extractContents();

const beforeElement = nodeListToReact( beforeFragment.childNodes, createTinyMCEElement );
const afterElement = isLinkBoundary( afterFragment ) ? [] : nodeListToReact( afterFragment.childNodes, createTinyMCEElement );
const beforeElement = nodeListToTree( beforeFragment.childNodes, createTinyMCEElement );
const afterElement = isLinkBoundary( afterFragment ) ? [] : nodeListToTree( afterFragment.childNodes, createTinyMCEElement );

this.setContent( beforeElement );
this.props.onSplit( beforeElement, afterElement, ...blocks );
Expand Down Expand Up @@ -667,8 +683,8 @@ export default class Editable extends Component {
this.setContent( this.props.value );

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

Expand Down Expand Up @@ -708,7 +724,7 @@ export default class Editable extends Component {
}

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

updateFocus() {
Expand Down Expand Up @@ -861,7 +877,7 @@ export default class Editable extends Component {
getSettings={ this.getSettings }
onSetup={ this.onSetup }
style={ style }
defaultValue={ value }
defaultValue={ toElement( value ) }
isPlaceholderVisible={ isPlaceholderVisible }
aria-label={ placeholder }
{ ...ariaProps }
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 @@ registerBlockType( 'core/pullquote', {

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 @@ registerBlockType( 'core/pullquote', {

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 && (
<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 @@ -238,9 +238,7 @@ registerBlockType( 'core/quote', {
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 @@ -267,9 +265,7 @@ registerBlockType( 'core/quote', {
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
11 changes: 10 additions & 1 deletion element/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ function renderElement( element ) {
}

if ( Array.isArray( element ) ) {
if ( element[ 1 ] && element[ 1 ].constructor === Object ) {
const [ type, props, children ] = element;
return renderElement( { type, props: { ...props, children } } );
}

return element.map( renderElement ).join( '' );
}

Expand Down Expand Up @@ -271,7 +276,11 @@ function renderChildren( children ) {
if ( typeof child === 'string' ) {
str += child;
} else if ( Array.isArray( child ) ) {
str += renderChildren( child );
if ( child[ 1 ] && child[ 1 ].constructor === Object ) {
str += renderElement( child );
} else {
str += renderChildren( child );
}
} else if ( typeof child === 'object' && child ) {
str += renderElement( child );
} else if ( typeof child === 'number' ) {
Expand Down

0 comments on commit e1fe602

Please sign in to comment.