Skip to content

Commit 03928a5

Browse files
pentoellatrix
andcommitted
Block API: Pasting content that results in a new block shouldn't be treated as inline content. (WordPress#19084)
* Only treat the paste as inline if it results in a paragraph block. * Whitelist blocks that can be treated as inline pastes. * Add a supports.pasteTextInline property to blocks, and some tests. * Mark pasteTextInline unstable Co-authored-by: Ella van Durpe <[email protected]>
1 parent 56cd1df commit 03928a5

File tree

6 files changed

+58
-3
lines changed

6 files changed

+58
-3
lines changed

docs/designers-developers/developers/block-api/block-registration.md

-1
Original file line numberDiff line numberDiff line change
@@ -653,4 +653,3 @@ By default all blocks can be converted to a reusable block. If supports reusable
653653
// Don't allow the block to be converted into a reusable block.
654654
reusable: false,
655655
```
656-

packages/block-library/src/heading/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const settings = {
2424
supports: {
2525
className: false,
2626
anchor: true,
27+
__unstablePasteTextInline: true,
2728
},
2829
example: {
2930
attributes: {

packages/block-library/src/list/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const settings = {
2323
keywords: [ __( 'bullet list' ), __( 'ordered list' ), __( 'numbered list' ) ],
2424
supports: {
2525
className: false,
26+
__unstablePasteTextInline: true,
2627
},
2728
example: {
2829
attributes: {

packages/block-library/src/paragraph/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const settings = {
3131
},
3232
supports: {
3333
className: false,
34+
__unstablePasteTextInline: true,
3435
},
3536
transforms,
3637
deprecated,

packages/blocks/src/api/raw-handling/paste-handler.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { flatMap, filter, compact } from 'lodash';
77
* Internal dependencies
88
*/
99
import { createBlock, getBlockTransforms, findTransform } from '../factory';
10+
import { hasBlockSupport } from '../registration';
1011
import { getBlockContent } from '../serializer';
1112
import { getBlockAttributes, parseWithGrammar } from '../parser';
1213
import normaliseBlocks from './normalise-blocks';
@@ -244,10 +245,14 @@ export function pasteHandler( { HTML = '', plainText = '', mode = 'AUTO', tagNam
244245
return htmlToBlocks( { html: piece, rawTransforms } );
245246
} ) );
246247

247-
// If we're allowed to return inline content and there is only one block
248+
// If we're allowed to return inline content, and there is only one inlineable block,
248249
// and the original plain text content does not have any line breaks, then
249250
// treat it as inline paste.
250-
if ( mode === 'AUTO' && blocks.length === 1 ) {
251+
if (
252+
mode === 'AUTO' &&
253+
blocks.length === 1 &&
254+
hasBlockSupport( blocks[ 0 ].name, '__unstablePasteTextInline', false )
255+
) {
251256
const trimmedPlainText = plainText.trim();
252257

253258
if ( trimmedPlainText !== '' && trimmedPlainText.indexOf( '\n' ) === -1 ) {

test/integration/blocks-raw-handling.test.js

+48
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import path from 'path';
88
* WordPress dependencies
99
*/
1010
import {
11+
createBlock,
1112
getBlockContent,
1213
pasteHandler,
1314
rawHandler,
@@ -57,6 +58,30 @@ describe( 'Blocks raw handling', () => {
5758
},
5859
save: () => null,
5960
} );
61+
62+
registerBlockType( 'test/non-inline-block', {
63+
title: 'Test Non Inline Block',
64+
category: 'common',
65+
supports: {
66+
pasteTextInline: false,
67+
},
68+
transforms: {
69+
from: [
70+
{
71+
type: 'raw',
72+
isMatch: ( node ) => {
73+
return 'words to live by' === node.textContent.trim();
74+
},
75+
transform: () => {
76+
return createBlock( 'core-embed/youtube', {
77+
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
78+
} );
79+
},
80+
},
81+
],
82+
},
83+
save: () => null,
84+
} );
6085
} );
6186

6287
it( 'should filter inline content', () => {
@@ -153,6 +178,29 @@ describe( 'Blocks raw handling', () => {
153178
expect( console ).toHaveLogged();
154179
} );
155180

181+
it( 'should not treat single non-inlineable block as inline text', () => {
182+
const filtered = pasteHandler( {
183+
HTML: '<p>words to live by</p>',
184+
plainText: 'words to live by\n',
185+
mode: 'AUTO',
186+
} );
187+
188+
expect( filtered ).toHaveLength( 1 );
189+
expect( filtered[ 0 ].name ).toBe( 'core-embed/youtube' );
190+
expect( console ).toHaveLogged();
191+
} );
192+
193+
it( 'should treat single heading as inline text', () => {
194+
const filtered = pasteHandler( {
195+
HTML: '<h1>FOO</h1>',
196+
plainText: 'FOO\n',
197+
mode: 'AUTO',
198+
} );
199+
200+
expect( filtered ).toBe( 'FOO' );
201+
expect( console ).toHaveLogged();
202+
} );
203+
156204
it( 'should treat single list item as inline text', () => {
157205
const filtered = pasteHandler( {
158206
HTML: '<ul><li>Some <strong>bold</strong> text.</li></ul>',

0 commit comments

Comments
 (0)