Skip to content

Commit

Permalink
TinyMCE per block: Using a simpler grammar parser
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Mar 3, 2017
1 parent 83800da commit 1f02d59
Show file tree
Hide file tree
Showing 10 changed files with 1,026 additions and 1,922 deletions.
26 changes: 13 additions & 13 deletions tinymce-per-block/build/app.js

Large diffs are not rendered by default.

23 changes: 9 additions & 14 deletions tinymce-per-block/src/blocks/heading-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
import { registerBlock } from 'wp-blocks';
import { EditorHeadingIcon } from 'dashicons';

import { parse } from 'parsers/block';
import { serialize } from 'serializers/block';

/**
* Internal dependencies
*/
Expand All @@ -17,32 +14,30 @@ registerBlock( 'heading', {
form: form,
icon: EditorHeadingIcon,
parse: ( rawBlock ) => {
const nodeNames = [ 'h1', 'h2', 'h3' ];
const div = document.createElement( 'div' );
div.innerHTML = rawBlock.rawContent;
const nodeNames = [ 'H1', 'H2', 'H3' ];
if (
rawBlock.children.length !== 1 ||
nodeNames.indexOf( rawBlock.children[ 0 ].name ) === -1
div.childNodes.length !== 1 ||
nodeNames.indexOf( div.firstChild.nodeName ) === -1
) {
return false;
}

return {
blockType: 'heading',
content: serialize( rawBlock.children[ 0 ].children ),
size: rawBlock.children[ 0 ].name
content: div.firstChild.innerHTML,
size: div.firstChild.nodeName.toLowerCase()
};
},
serialize: ( block ) => {
const elementName = block.size ? block.size : 'h2';
const rawHtml = `<${ elementName }>` + block.content + `</${ elementName }>`;
const rawContent = `<${ elementName }>` + block.content + `</${ elementName }>`;

return {
type: 'WP_Block',
blockType: 'heading',
attrs: { size: elementName },
startText: '<!-- wp:heading -->',
endText: '<!-- /wp -->',
rawContent: '<!-- wp:heading -->' + rawHtml + '<!-- /wp -->',
children: parse( rawHtml )
rawContent
};
}
} );
38 changes: 25 additions & 13 deletions tinymce-per-block/src/blocks/image-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import { registerBlock } from 'wp-blocks';
import { FormatImageIcon } from 'dashicons';

import { parse } from 'parsers/block';

/**
* Internal dependencies
*/
Expand All @@ -16,31 +14,45 @@ registerBlock( 'image', {
icon: FormatImageIcon,
form,
parse: ( rawBlock ) => {
const div = document.createElement( 'div' );
div.innerHTML = rawBlock.rawContent;
if (
rawBlock.children.length !== 1 ||
rawBlock.children[ 0 ].name !== 'img'
div.childNodes.length !== 1 ||
! (
div.firstChild.nodeName === 'IMG' ||
(
div.firstChild.nodeName === 'FIGURE' &&
div.firstChild.childNodes.length &&
div.firstChild.firstChild.nodeName === 'IMG'
)
)
) {
return false;
}

const src = div.firstChild.nodeName === 'IMG'
? div.firstChild.getAttribute( 'src' )
: div.firstChild.firstChild.getAttribute( 'src' );

const caption = div.firstChild.childNodes.length > 1
? rawBlock.firstChild.childNodes[ 1 ].innerHTML
: '';

return {
blockType: 'image',
src: rawBlock.children[ 0 ].attrs.src,
caption: rawBlock.children[ 0 ].attrs.caption || '',
align: rawBlock.children[ 0 ].attrs.align || 'no-align'
align: rawBlock.attrs.align || 'no-align',
src,
caption
};
},
serialize: ( block ) => {
const rawHtml = `<img src="${ block.src }">`;
const captionHtml = block.caption ? `<figcaption>${ block.caption }</figcaption>` : '';
const rawContent = `<figure><img src="${ block.src }" />${ captionHtml }</figure>`;

return {
type: 'WP_Block',
blockType: 'image',
attrs: { /* caption: block.caption , align: block.align */ },
startText: '<!-- wp:image -->',
endText: '<!-- /wp -->',
rawContent: '<!-- wp:image -->' + rawHtml + '<!-- /wp -->',
children: parse( rawHtml )
rawContent
};
}
} );
16 changes: 7 additions & 9 deletions tinymce-per-block/src/blocks/inline-text-block/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,26 @@
import { createElement, Component } from 'wp-elements';
import { EditableComponent } from 'wp-blocks';

import { parse } from 'parsers/block';
import { serialize } from 'serializers/block';

export default class InlineTextBlockForm extends Component {
merge = ( block, index ) => {
const acceptedBlockTypes = [ 'quote', 'paragraph', 'heading' ];
if ( acceptedBlockTypes.indexOf( block.blockType ) === -1 ) {
return;
}

const getLeaves = children => {
if ( children.length === 1 && children[ 0 ].name === 'p' ) {
return getLeaves( children[ 0 ].children );
const getLeaves = html => {
const div = document.createElement( 'div' );
div.innerHTML = html;
if ( div.childNodes.length === 1 && div.firstChild.nodeName === 'P' ) {
return getLeaves( div.firstChild.innerHTML );
}

return children;
return html;
};

const { block: { content }, remove, change } = this.props;
remove( index );
setTimeout( () => change(
{ content: serialize( getLeaves( parse( content ) ).concat( getLeaves( parse( block.content ) ) ) ) }
{ content: getLeaves( content ) + getLeaves( block.content ) }
) );
setTimeout( () => this.editable.updateContent() );
}
Expand Down
25 changes: 12 additions & 13 deletions tinymce-per-block/src/blocks/paragraph-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,40 @@ import { EditorParagraphIcon } from 'dashicons';
* Internal dependencies
*/
import form from './form';
import { parse } from 'parsers/block';
import { serialize } from 'serializers/block';

registerBlock( 'paragraph', {
title: 'Paragraph',
form: form,
icon: EditorParagraphIcon,
parse: ( rawBlock ) => {
const div = document.createElement( 'div' );
div.innerHTML = rawBlock.rawContent;
if (
rawBlock.children.length !== 1 ||
rawBlock.children[ 0 ].name !== 'p'
div.childNodes.length !== 1 ||
div.firstChild.nodeName !== 'P'
) {
return false;
}

return {
blockType: 'paragraph',
align: rawBlock.attrs.align || 'no-align',
content: serialize( rawBlock.children[ 0 ].children ),
content: div.firstChild.innerHTML,
};
},
serialize: ( block ) => {
let children = parse( block.content );
const div = document.createElement( 'div' );
div.innerHTML = block.content;
// Should probably be handled in the form
children = children.length === 1 && children[ 0 ].name === 'p' ? children[ 0 ].children : children;
const rawHtml = `<p style="text-align: ${ block.align };">${ serialize( children ) }</p>`;
const content = div.childNodes.length === 1 && div.firstChild.nodeName === 'P'
? div.firstChild.innerHTML
: block.content;
const rawContent = `<p style="text-align: ${ block.align };">${ content }</p>`;

return {
type: 'WP_Block',
blockType: 'paragraph',
attrs: { /* align: block.align */ },
startText: '<!-- wp:paragraph -->',
endText: '<!-- /wp -->',
rawContent: '<!-- wp:paragraph -->' + rawHtml + '<!-- /wp -->',
children: parse( rawHtml )
rawContent
};
}
} );
13 changes: 7 additions & 6 deletions tinymce-per-block/src/blocks/quote-block/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ export default class QuoteBlockForm extends Component {
return;
}

const getLeaves = children => {
if ( children.length === 1 && children[ 0 ].name === 'p' ) {
return getLeaves( children[ 0 ].children );
const getLeaves = html => {
const div = document.createElement( 'div' );
div.innerHTML = html;
if ( div.childNodes.length === 1 && div.firstChild.nodeName === 'P' ) {
return getLeaves( div.firstChild.innerHTML );
}

return children;
return html;
};

const { block: { content }, remove, change } = this.props;
remove( index );
setTimeout( () => change(
{ content: serialize( getLeaves( parse( content ) ).concat( getLeaves( parse( block.content ) ) ) ) }
{ content: getLeaves( content ) + getLeaves( block.content ) }
) );
setTimeout( () => this.content.updateContent() );
}
Expand Down
19 changes: 6 additions & 13 deletions tinymce-per-block/src/blocks/quote-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,33 @@ import {
/**
* Internal dependencies
*/
import { parse } from 'parsers/block';
import { serialize } from 'serializers/block';
import form from './form';

registerBlock( 'quote', {
title: 'Quote',
form: form,
icon: EditorQuoteIcon,
parse: ( rawBlock ) => {
const div = document.createElement( 'div' );
div.innerHTML = rawBlock.rawContent;
if (
rawBlock.children.length !== 1 ||
rawBlock.children[ 0 ].name !== 'p'
div.childNodes.length !== 1 ||
div.firstChild.nodeName !== 'P'
) {
return false;
}

return {
blockType: 'quote',
cite: rawBlock.attrs.cite || '',
content: serialize( rawBlock.children ),
content: rawBlock.rawContent,
};
},
serialize: ( block ) => {
const children = parse( block.content );
const rawHtml = serialize( children );

return {
type: 'WP_Block',
blockType: 'quote',
attrs: { cite: block.cite },
startText: '<!-- wp:quote -->',
endText: '<!-- /wp -->',
rawContent: '<!-- wp:quote -->' + rawHtml + '<!-- /wp -->',
children
rawContent: block.content
};
}
} );
13 changes: 2 additions & 11 deletions tinymce-per-block/src/blocks/text-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { EditorTableIcon } from 'dashicons';
/**
* Internal dependencies
*/
import { parse } from 'parsers/block';
import { serialize } from 'serializers/block';
import form from './form';

registerBlock( 'text', {
Expand All @@ -19,21 +17,14 @@ registerBlock( 'text', {
return {
blockType: 'text',
align: rawBlock.attrs.align || 'no-align',
content: serialize( rawBlock.children ),
content: rawBlock.rawContent,
};
},
serialize: ( block ) => {
const children = parse( block.content );
const rawHtml = serialize( children );

return {
type: 'WP_Block',
blockType: 'text',
attrs: { /* align: block.align */ },
startText: '<!-- wp:text -->',
endText: '<!-- /wp -->',
rawContent: '<!-- wp:text -->' + rawHtml + '<!-- /wp -->',
children
rawContent: block.content
};
}
} );
Loading

0 comments on commit 1f02d59

Please sign in to comment.