Skip to content

Commit

Permalink
Add convert button to unknown block type
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Oct 31, 2017
1 parent 12e9366 commit 95d6c39
Show file tree
Hide file tree
Showing 45 changed files with 93 additions and 22 deletions.
2 changes: 1 addition & 1 deletion blocks/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as source from './source';
export { source };
export { createBlock, switchToBlockType } from './factory';
export { default as parse, getSourcedAttributes } from './parser';
export { default as pasteHandler } from './paste';
export { default as rawHandler } from './raw-handling';
export { default as serialize, getBlockDefaultClassname, getBlockContent } from './serializer';
export { isValidBlock } from './validation';
export { getCategories } from './categories';
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 10 additions & 2 deletions blocks/api/paste/index.js → blocks/api/raw-handling/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ import inlineContentConverter from './inline-content-converter';
import { deepFilterHTML, isInvalidInline, isNotWhitelisted, isPlain, isInline } from './utils';
import showdown from 'showdown';

export default function( { HTML, plainText, inline } ) {
/**
* Converts an HTML string to known blocks. Strips everything else.
*
* @param {String} options.HTML The HTML to convert.
* @param {String} [options.plainText] Plain text version.
* @param {Boolean} [options.inline] Whether to content should be inline or not. Null to auto-detect, false to force blocks, true to force a string.
* @return {Array|String} A list of blocks or a string, depending on the `inline` option.
*/
export default function rawHandler( { HTML, plainText = '', inline = null } ) {
HTML = HTML.replace( /<meta[^>]+>/, '' );

// Block delimiters detected.
Expand Down Expand Up @@ -60,7 +68,7 @@ export default function( { HTML, plainText, inline } ) {
] );

// Inline paste.
if ( inline || isInlineContent( HTML ) ) {
if ( inline || ( inline === null && isInlineContent( HTML ) ) ) {
// Allows us to ask for this information when we get a report.
window.console.log( 'Processed inline HTML:\n\n', HTML );

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Paste
# Raw Handling (Paste)

This folder contains all paste specific logic (filters, converters, normalisers...). Each module is tested on their own, and in addition we have some integration tests for frequently used editors.

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { equal, deepEqual } from 'assert';
/**
* Internal dependencies
*/
import paste from '../index';
import rawHandler from '../index';
import { registerBlockType, unregisterBlockType, setUnknownTypeHandlerName } from '../../registration';
import { createBlock } from '../../factory';
import { children, prop } from '../../source';

describe( 'paste', () => {
describe( 'rawHandler', () => {
beforeAll( () => {
registerBlockType( 'test/figure', {
category: 'common',
Expand Down Expand Up @@ -54,29 +54,38 @@ describe( 'paste', () => {
setUnknownTypeHandlerName( undefined );
} );

it( 'should convert recognised pasted content', () => {
const pastedBlock = paste( { HTML: '<figure>test</figure>' } )[ 0 ];
const block = createBlock( 'test/figure', { content: [ 'test' ] } );
it( 'should convert recognised raw content', () => {
const block = rawHandler( { HTML: '<figure>test</figure>' } )[ 0 ];
const { name, attributes } = createBlock( 'test/figure', { content: [ 'test' ] } );

equal( pastedBlock.name, block.name );
deepEqual( pastedBlock.attributes, block.attributes );
equal( block.name, name );
deepEqual( block.attributes, attributes );
} );

it( 'should handle unknown pasted content', () => {
const pastedBlock = paste( { HTML: '<figcaption>test</figcaption>' } )[ 0 ];
it( 'should handle unknown raw content', () => {
const block = rawHandler( { HTML: '<figcaption>test</figcaption>' } )[ 0 ];

equal( pastedBlock.name, 'test/unknown' );
equal( pastedBlock.attributes.content, '<figcaption>test</figcaption>' );
equal( block.name, 'test/unknown' );
equal( block.attributes.content, '<figcaption>test</figcaption>' );
} );

it( 'should filter inline content', () => {
const filtered = paste( {
const filtered = rawHandler( {
HTML: '<h2><em>test</em></h2>',
inline: true,
} );

equal( filtered, '<em>test</em>' );
} );

it( 'should always return blocks', () => {
const blocks = rawHandler( {
HTML: 'test',
inline: false,
} );

equal( Array.isArray( blocks ), true );
} );
} );

import './integration';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import path from 'path';
* Internal dependencies
*/
import '../../../../library';
import paste from '../../index';
import rawHandler from '../../index';
import serialize from '../../../serializer';

const types = [
Expand All @@ -20,13 +20,13 @@ const types = [
'ms-word-online',
];

describe( 'paste: integration', () => {
describe( 'raw handling: integration', () => {
types.forEach( ( type ) => {
it( type, () => {
const input = fs.readFileSync( path.join( __dirname, `${ type }-in.html` ), 'utf8' ).trim();
const output = fs.readFileSync( path.join( __dirname, `${ type }-out.html` ), 'utf8' ).trim();
const pasted = paste( { HTML: input } );
const serialized = typeof pasted === 'string' ? pasted : serialize( pasted );
const converted = rawHandler( { HTML: input } );
const serialized = typeof converted === 'string' ? converted : serialize( converted );

equal( output, serialized );
} );
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions blocks/editable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { keycodes } from '@wordpress/utils';
* Internal dependencies
*/
import './style.scss';
import { pasteHandler } from '../api';
import { rawHandler } from '../api';
import FormatToolbar from './format-toolbar';
import TinyMCE from './tinymce';
import { pickAriaProps } from './aria';
Expand Down Expand Up @@ -248,7 +248,7 @@ export default class Editable extends Component {
window.console.log( 'Received HTML:\n\n', event.content );
window.console.log( 'Received plain text:\n\n', this.pastedPlainText );

const content = pasteHandler( {
const content = rawHandler( {
HTML: event.content,
plainText: this.pastedPlainText,
inline: ! this.props.onSplit,
Expand Down
2 changes: 2 additions & 0 deletions editor/block-settings-menu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import BlockInspectorButton from './block-inspector-button';
import BlockModeToggle from './block-mode-toggle';
import BlockDeleteButton from './block-delete-button';
import { selectBlock } from '../actions';
import UnknownConverter from './unknown-converter';

function BlockSettingsMenu( { uids, onSelect } ) {
const count = uids.length;
Expand Down Expand Up @@ -50,6 +51,7 @@ function BlockSettingsMenu( { uids, onSelect } ) {
<div className="editor-block-settings-menu__content">
<BlockInspectorButton onClick={ onClose } />
{ count === 1 && <BlockModeToggle uid={ uids[ 0 ] } onToggle={ onClose } /> }
{ count === 1 && <UnknownConverter uid={ uids[ 0 ] } /> }
<BlockDeleteButton uids={ uids } />
</div>
) }
Expand Down
50 changes: 50 additions & 0 deletions editor/block-settings-menu/unknown-converter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* External dependencies
*/
import { connect } from 'react-redux';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { IconButton } from '@wordpress/components';
import { getUnknownTypeHandlerName, rawHandler, serialize } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { getBlock } from '../selectors';
import { replaceBlocks } from '../actions';

export function UnknownConverter( { block, convertToBlocks, small } ) {
if ( ! block || getUnknownTypeHandlerName() !== block.name ) {
return null;
}

const label = __( 'Convert to blocks' );

return (
<IconButton
className="editor-block-settings-menu__control"
onClick={ () => convertToBlocks( block ) }
icon="screenoptions"
label={ small ? label : undefined }
>
{ ! small && label }
</IconButton>
);
}

export default connect(
( state, { uid } ) => ( {
block: getBlock( state, uid ),
} ),
( dispatch, { uid } ) => ( {
convertToBlocks( block ) {
dispatch( replaceBlocks( uid, rawHandler( {
HTML: serialize( block ),
inline: false,
} ) ) );
},
} )
)( UnknownConverter );
2 changes: 2 additions & 0 deletions editor/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import BlockInspectorButton from '../block-settings-menu/block-inspector-button'
import BlockModeToggle from '../block-settings-menu/block-mode-toggle';
import BlockDeleteButton from '../block-settings-menu/block-delete-button';
import { getBlockMode, getSelectedBlock } from '../selectors';
import UnknownConverter from '../block-settings-menu/unknown-converter';

class BlockToolbar extends Component {
constructor() {
Expand Down Expand Up @@ -77,6 +78,7 @@ class BlockToolbar extends Component {
<BlockMover uids={ [ block.uid ] } />
<BlockInspectorButton small />
<BlockModeToggle uid={ block.uid } small />
<UnknownConverter uid={ block.uid } small />
<BlockDeleteButton uids={ [ block.uid ] } small />
</div>
}
Expand Down

0 comments on commit 95d6c39

Please sign in to comment.