diff --git a/blocks/api/index.js b/blocks/api/index.js
index f9a45baca27549..e1a7a5d8d9ab61 100644
--- a/blocks/api/index.js
+++ b/blocks/api/index.js
@@ -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';
diff --git a/blocks/api/paste/blockquote-normaliser.js b/blocks/api/raw-handling/blockquote-normaliser.js
similarity index 100%
rename from blocks/api/paste/blockquote-normaliser.js
rename to blocks/api/raw-handling/blockquote-normaliser.js
diff --git a/blocks/api/paste/comment-remover.js b/blocks/api/raw-handling/comment-remover.js
similarity index 100%
rename from blocks/api/paste/comment-remover.js
rename to blocks/api/raw-handling/comment-remover.js
diff --git a/blocks/api/paste/create-unwrapper.js b/blocks/api/raw-handling/create-unwrapper.js
similarity index 100%
rename from blocks/api/paste/create-unwrapper.js
rename to blocks/api/raw-handling/create-unwrapper.js
diff --git a/blocks/api/paste/formatting-transformer.js b/blocks/api/raw-handling/formatting-transformer.js
similarity index 100%
rename from blocks/api/paste/formatting-transformer.js
rename to blocks/api/raw-handling/formatting-transformer.js
diff --git a/blocks/api/paste/image-corrector.js b/blocks/api/raw-handling/image-corrector.js
similarity index 100%
rename from blocks/api/paste/image-corrector.js
rename to blocks/api/raw-handling/image-corrector.js
diff --git a/blocks/api/paste/index.js b/blocks/api/raw-handling/index.js
similarity index 83%
rename from blocks/api/paste/index.js
rename to blocks/api/raw-handling/index.js
index ca826bb3bb009f..d4d42e37900953 100644
--- a/blocks/api/paste/index.js
+++ b/blocks/api/raw-handling/index.js
@@ -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( /]+>/, '' );
// Block delimiters detected.
@@ -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 );
diff --git a/blocks/api/paste/inline-content-converter.js b/blocks/api/raw-handling/inline-content-converter.js
similarity index 100%
rename from blocks/api/paste/inline-content-converter.js
rename to blocks/api/raw-handling/inline-content-converter.js
diff --git a/blocks/api/paste/is-inline-content.js b/blocks/api/raw-handling/is-inline-content.js
similarity index 100%
rename from blocks/api/paste/is-inline-content.js
rename to blocks/api/raw-handling/is-inline-content.js
diff --git a/blocks/api/paste/list-merger.js b/blocks/api/raw-handling/list-merger.js
similarity index 100%
rename from blocks/api/paste/list-merger.js
rename to blocks/api/raw-handling/list-merger.js
diff --git a/blocks/api/paste/ms-list-converter.js b/blocks/api/raw-handling/ms-list-converter.js
similarity index 100%
rename from blocks/api/paste/ms-list-converter.js
rename to blocks/api/raw-handling/ms-list-converter.js
diff --git a/blocks/api/paste/normalise-blocks.js b/blocks/api/raw-handling/normalise-blocks.js
similarity index 100%
rename from blocks/api/paste/normalise-blocks.js
rename to blocks/api/raw-handling/normalise-blocks.js
diff --git a/blocks/api/paste/readme.md b/blocks/api/raw-handling/readme.md
similarity index 98%
rename from blocks/api/paste/readme.md
rename to blocks/api/raw-handling/readme.md
index a921aab1a4f82f..aea5dc2e2ee39b 100644
--- a/blocks/api/paste/readme.md
+++ b/blocks/api/raw-handling/readme.md
@@ -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.
diff --git a/blocks/api/paste/strip-attributes.js b/blocks/api/raw-handling/strip-attributes.js
similarity index 100%
rename from blocks/api/paste/strip-attributes.js
rename to blocks/api/raw-handling/strip-attributes.js
diff --git a/blocks/api/paste/table-normaliser.js b/blocks/api/raw-handling/table-normaliser.js
similarity index 100%
rename from blocks/api/paste/table-normaliser.js
rename to blocks/api/raw-handling/table-normaliser.js
diff --git a/blocks/api/paste/test/blockquote-normaliser.js b/blocks/api/raw-handling/test/blockquote-normaliser.js
similarity index 100%
rename from blocks/api/paste/test/blockquote-normaliser.js
rename to blocks/api/raw-handling/test/blockquote-normaliser.js
diff --git a/blocks/api/paste/test/comment-remover.js b/blocks/api/raw-handling/test/comment-remover.js
similarity index 100%
rename from blocks/api/paste/test/comment-remover.js
rename to blocks/api/raw-handling/test/comment-remover.js
diff --git a/blocks/api/paste/test/create-unwrapper.js b/blocks/api/raw-handling/test/create-unwrapper.js
similarity index 100%
rename from blocks/api/paste/test/create-unwrapper.js
rename to blocks/api/raw-handling/test/create-unwrapper.js
diff --git a/blocks/api/paste/test/formatting-transformer.js b/blocks/api/raw-handling/test/formatting-transformer.js
similarity index 100%
rename from blocks/api/paste/test/formatting-transformer.js
rename to blocks/api/raw-handling/test/formatting-transformer.js
diff --git a/blocks/api/paste/test/image-corrector.js b/blocks/api/raw-handling/test/image-corrector.js
similarity index 100%
rename from blocks/api/paste/test/image-corrector.js
rename to blocks/api/raw-handling/test/image-corrector.js
diff --git a/blocks/api/paste/test/index.js b/blocks/api/raw-handling/test/index.js
similarity index 61%
rename from blocks/api/paste/test/index.js
rename to blocks/api/raw-handling/test/index.js
index 2eacda7a389d8e..c0a371906d6643 100644
--- a/blocks/api/paste/test/index.js
+++ b/blocks/api/raw-handling/test/index.js
@@ -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',
@@ -54,29 +54,38 @@ describe( 'paste', () => {
setUnknownTypeHandlerName( undefined );
} );
- it( 'should convert recognised pasted content', () => {
- const pastedBlock = paste( { HTML: '' } )[ 0 ];
- const block = createBlock( 'test/figure', { content: [ 'test' ] } );
+ it( 'should convert recognised raw content', () => {
+ const block = rawHandler( { HTML: '' } )[ 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: 'test' } )[ 0 ];
+ it( 'should handle unknown raw content', () => {
+ const block = rawHandler( { HTML: 'test' } )[ 0 ];
- equal( pastedBlock.name, 'test/unknown' );
- equal( pastedBlock.attributes.content, 'test' );
+ equal( block.name, 'test/unknown' );
+ equal( block.attributes.content, 'test' );
} );
it( 'should filter inline content', () => {
- const filtered = paste( {
+ const filtered = rawHandler( {
HTML: '
test
',
inline: true,
} );
equal( filtered, 'test' );
} );
+
+ it( 'should always return blocks', () => {
+ const blocks = rawHandler( {
+ HTML: 'test',
+ inline: false,
+ } );
+
+ equal( Array.isArray( blocks ), true );
+ } );
} );
import './integration';
diff --git a/blocks/api/paste/test/inline-content-converter.js b/blocks/api/raw-handling/test/inline-content-converter.js
similarity index 100%
rename from blocks/api/paste/test/inline-content-converter.js
rename to blocks/api/raw-handling/test/inline-content-converter.js
diff --git a/blocks/api/paste/test/integration/apple-in.html b/blocks/api/raw-handling/test/integration/apple-in.html
similarity index 100%
rename from blocks/api/paste/test/integration/apple-in.html
rename to blocks/api/raw-handling/test/integration/apple-in.html
diff --git a/blocks/api/paste/test/integration/apple-out.html b/blocks/api/raw-handling/test/integration/apple-out.html
similarity index 100%
rename from blocks/api/paste/test/integration/apple-out.html
rename to blocks/api/raw-handling/test/integration/apple-out.html
diff --git a/blocks/api/paste/test/integration/google-docs-in.html b/blocks/api/raw-handling/test/integration/google-docs-in.html
similarity index 100%
rename from blocks/api/paste/test/integration/google-docs-in.html
rename to blocks/api/raw-handling/test/integration/google-docs-in.html
diff --git a/blocks/api/paste/test/integration/google-docs-out.html b/blocks/api/raw-handling/test/integration/google-docs-out.html
similarity index 100%
rename from blocks/api/paste/test/integration/google-docs-out.html
rename to blocks/api/raw-handling/test/integration/google-docs-out.html
diff --git a/blocks/api/paste/test/integration/index.js b/blocks/api/raw-handling/test/integration/index.js
similarity index 72%
rename from blocks/api/paste/test/integration/index.js
rename to blocks/api/raw-handling/test/integration/index.js
index 039e573da52180..0c316eaa016744 100644
--- a/blocks/api/paste/test/integration/index.js
+++ b/blocks/api/raw-handling/test/integration/index.js
@@ -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 = [
@@ -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 );
} );
diff --git a/blocks/api/paste/test/integration/ms-word-in.html b/blocks/api/raw-handling/test/integration/ms-word-in.html
similarity index 100%
rename from blocks/api/paste/test/integration/ms-word-in.html
rename to blocks/api/raw-handling/test/integration/ms-word-in.html
diff --git a/blocks/api/paste/test/integration/ms-word-online-in.html b/blocks/api/raw-handling/test/integration/ms-word-online-in.html
similarity index 100%
rename from blocks/api/paste/test/integration/ms-word-online-in.html
rename to blocks/api/raw-handling/test/integration/ms-word-online-in.html
diff --git a/blocks/api/paste/test/integration/ms-word-online-out.html b/blocks/api/raw-handling/test/integration/ms-word-online-out.html
similarity index 100%
rename from blocks/api/paste/test/integration/ms-word-online-out.html
rename to blocks/api/raw-handling/test/integration/ms-word-online-out.html
diff --git a/blocks/api/paste/test/integration/ms-word-out.html b/blocks/api/raw-handling/test/integration/ms-word-out.html
similarity index 100%
rename from blocks/api/paste/test/integration/ms-word-out.html
rename to blocks/api/raw-handling/test/integration/ms-word-out.html
diff --git a/blocks/api/paste/test/integration/plain-in.html b/blocks/api/raw-handling/test/integration/plain-in.html
similarity index 100%
rename from blocks/api/paste/test/integration/plain-in.html
rename to blocks/api/raw-handling/test/integration/plain-in.html
diff --git a/blocks/api/paste/test/integration/plain-out.html b/blocks/api/raw-handling/test/integration/plain-out.html
similarity index 100%
rename from blocks/api/paste/test/integration/plain-out.html
rename to blocks/api/raw-handling/test/integration/plain-out.html
diff --git a/blocks/api/paste/test/is-inline-content.js b/blocks/api/raw-handling/test/is-inline-content.js
similarity index 100%
rename from blocks/api/paste/test/is-inline-content.js
rename to blocks/api/raw-handling/test/is-inline-content.js
diff --git a/blocks/api/paste/test/list-merger.js b/blocks/api/raw-handling/test/list-merger.js
similarity index 100%
rename from blocks/api/paste/test/list-merger.js
rename to blocks/api/raw-handling/test/list-merger.js
diff --git a/blocks/api/paste/test/ms-list-converter.js b/blocks/api/raw-handling/test/ms-list-converter.js
similarity index 100%
rename from blocks/api/paste/test/ms-list-converter.js
rename to blocks/api/raw-handling/test/ms-list-converter.js
diff --git a/blocks/api/paste/test/normalise-blocks.js b/blocks/api/raw-handling/test/normalise-blocks.js
similarity index 100%
rename from blocks/api/paste/test/normalise-blocks.js
rename to blocks/api/raw-handling/test/normalise-blocks.js
diff --git a/blocks/api/paste/test/strip-attributes.js b/blocks/api/raw-handling/test/strip-attributes.js
similarity index 100%
rename from blocks/api/paste/test/strip-attributes.js
rename to blocks/api/raw-handling/test/strip-attributes.js
diff --git a/blocks/api/paste/test/table-normaliser.js b/blocks/api/raw-handling/test/table-normaliser.js
similarity index 100%
rename from blocks/api/paste/test/table-normaliser.js
rename to blocks/api/raw-handling/test/table-normaliser.js
diff --git a/blocks/api/paste/test/utils.js b/blocks/api/raw-handling/test/utils.js
similarity index 100%
rename from blocks/api/paste/test/utils.js
rename to blocks/api/raw-handling/test/utils.js
diff --git a/blocks/api/paste/utils.js b/blocks/api/raw-handling/utils.js
similarity index 100%
rename from blocks/api/paste/utils.js
rename to blocks/api/raw-handling/utils.js
diff --git a/blocks/editable/index.js b/blocks/editable/index.js
index 99fce7bec187be..85ff82e07e47ef 100644
--- a/blocks/editable/index.js
+++ b/blocks/editable/index.js
@@ -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';
@@ -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,
diff --git a/editor/block-settings-menu/index.js b/editor/block-settings-menu/index.js
index 7f8ccb1c1152ab..c265b97f152e0c 100644
--- a/editor/block-settings-menu/index.js
+++ b/editor/block-settings-menu/index.js
@@ -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;
@@ -50,6 +51,7 @@ function BlockSettingsMenu( { uids, onSelect } ) {
{ count === 1 && }
+ { count === 1 && }
) }
diff --git a/editor/block-settings-menu/unknown-converter.js b/editor/block-settings-menu/unknown-converter.js
new file mode 100644
index 00000000000000..62f51398cf74ad
--- /dev/null
+++ b/editor/block-settings-menu/unknown-converter.js
@@ -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 (
+ convertToBlocks( block ) }
+ icon="screenoptions"
+ label={ small ? label : undefined }
+ >
+ { ! small && label }
+
+ );
+}
+
+export default connect(
+ ( state, { uid } ) => ( {
+ block: getBlock( state, uid ),
+ } ),
+ ( dispatch, { uid } ) => ( {
+ convertToBlocks( block ) {
+ dispatch( replaceBlocks( uid, rawHandler( {
+ HTML: serialize( block ),
+ inline: false,
+ } ) ) );
+ },
+ } )
+)( UnknownConverter );
diff --git a/editor/block-toolbar/index.js b/editor/block-toolbar/index.js
index 8ddbc7a904ae97..7d9a70c5685ee2 100644
--- a/editor/block-toolbar/index.js
+++ b/editor/block-toolbar/index.js
@@ -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() {
@@ -77,6 +78,7 @@ class BlockToolbar extends Component {
+
}