Skip to content

Commit b9e9788

Browse files
annezazuellatrixtyxlamcsfyouknowriad
authored
Raw Handling: Fix grok markdown pasting issues (#73019)
Co-authored-by: annezazu <[email protected]> Co-authored-by: ellatrix <[email protected]> Co-authored-by: tyxla <[email protected]> Co-authored-by: mcsf <[email protected]> Co-authored-by: youknowriad <[email protected]>
1 parent 07ef968 commit b9e9788

File tree

7 files changed

+89
-2
lines changed

7 files changed

+89
-2
lines changed

packages/blocks/src/api/raw-handling/test/utils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,36 @@ describe( 'isPlain', () => {
3030
expect( isPlain( '<strong>test<br></strong>' ) ).toBe( false );
3131
expect( isPlain( 'test<br-custom>test' ) ).toBe( false );
3232
} );
33+
34+
it( 'should return true for single non-semantic wrapper elements with only text', () => {
35+
expect( isPlain( '<span>test</span>' ) ).toBe( true );
36+
} );
37+
38+
it( 'should return true for single wrapper with styled content but no semantic tags', () => {
39+
expect( isPlain( '<span style="color: red;">test</span>' ) ).toBe(
40+
true
41+
);
42+
} );
43+
44+
it( 'should return true for single wrapper with line breaks', () => {
45+
expect( isPlain( '<span>test<br>test</span>' ) ).toBe( true );
46+
} );
47+
48+
it( 'should return false for wrapper with semantic child elements', () => {
49+
expect( isPlain( '<div><strong>test</strong></div>' ) ).toBe( false );
50+
expect( isPlain( '<span><em>test</em></span>' ) ).toBe( false );
51+
expect( isPlain( '<p>Some <a href="#">link</a></p>' ) ).toBe( false );
52+
} );
53+
54+
it( 'should return false for multiple wrapper elements', () => {
55+
expect( isPlain( '<span>test</span><span>test</span>' ) ).toBe( false );
56+
} );
57+
58+
it( 'should return false for semantic wrapper elements', () => {
59+
expect( isPlain( '<h1>test</h1>' ) ).toBe( false );
60+
expect( isPlain( '<ul><li>test</li></ul>' ) ).toBe( false );
61+
expect( isPlain( '<article>test</article>' ) ).toBe( false );
62+
} );
3363
} );
3464

3565
describe( 'getBlockContentSchema', () => {

packages/blocks/src/api/raw-handling/utils.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,39 @@ export function getBlockContentSchema( context ) {
113113

114114
/**
115115
* Checks whether HTML can be considered plain text. That is, it does not contain
116-
* any elements that are not line breaks.
116+
* any elements that are not line breaks, or it only contains a single non-semantic
117+
* wrapper element (span) with no semantic child elements.
117118
*
118119
* @param {string} HTML The HTML to check.
119120
*
120121
* @return {boolean} Whether the HTML can be considered plain text.
121122
*/
122123
export function isPlain( HTML ) {
123-
return ! /<(?!br[ />])/i.test( HTML );
124+
if ( ! /<(?!br[ />])/i.test( HTML ) ) {
125+
return true;
126+
}
127+
128+
const doc = document.implementation.createHTMLDocument( '' );
129+
doc.body.innerHTML = HTML;
130+
131+
if ( doc.body.children.length !== 1 ) {
132+
return false;
133+
}
134+
135+
const wrapper = doc.body.children.item( 0 );
136+
137+
const descendants = wrapper.getElementsByTagName( '*' );
138+
for ( let i = 0; i < descendants.length; i++ ) {
139+
if ( descendants.item( i ).tagName !== 'BR' ) {
140+
return false;
141+
}
142+
}
143+
144+
if ( wrapper.tagName !== 'SPAN' ) {
145+
return false;
146+
}
147+
148+
return true;
124149
}
125150

126151
/**

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ exports[`Blocks raw handling pasteHandler google-docs-table-with-rowspan 1`] = `
2020

2121
exports[`Blocks raw handling pasteHandler google-docs-with-comments 1`] = `"This is a <strong>title</strong><br><br>This is a <em>heading</em><br><br>Formatting test: <strong>bold</strong>, <em>italic</em>, <a href="https://w.org/">link</a>, <s>strikethrough</s>, <sup>superscript</sup>, <sub>subscript</sub>, <strong><em>nested</em></strong>.<br><br>A<br>Bulleted<br>Indented<br>List<br><br>One<br>Two<br>Three<br><br><br><br><br>One<br>Two<br>Three<br>1<br>2<br>3<br>I<br>II<br>III<br><br><br><br><br><br>An image:<br><br><img src="https://lh4.googleusercontent.com/ID" width="544" height="184"><br><br>"`;
2222

23+
exports[`Blocks raw handling pasteHandler grok-markdown 1`] = `"Heading<br>This is a paragraph with <strong>bold text</strong> and <em>italic text</em>.<br>Subheading<br>Another paragraph with a <a href="https://example.com">link</a>."`;
24+
2325
exports[`Blocks raw handling pasteHandler gutenberg 1`] = `"Test"`;
2426

2527
exports[`Blocks raw handling pasteHandler iframe-embed 1`] = `""`;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ describe( 'Blocks raw handling', () => {
419419
'one-image',
420420
'two-images',
421421
'markdown',
422+
'grok-markdown',
422423
'wordpress',
423424
'gutenberg',
424425
'shortcode-matching',
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<span style="font-family: system-ui, -apple-system, sans-serif; font-size: 14px;"># Heading
2+
3+
This is a paragraph with **bold text** and *italic text*.
4+
5+
## Subheading
6+
7+
Another paragraph with a [link](https://example.com).</span>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Heading
2+
3+
This is a paragraph with **bold text** and *italic text*.
4+
5+
## Subheading
6+
7+
Another paragraph with a [link](https://example.com).
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!-- wp:heading {"level":1} -->
2+
<h1 class="wp-block-heading">Heading</h1>
3+
<!-- /wp:heading -->
4+
5+
<!-- wp:paragraph -->
6+
<p>This is a paragraph with <strong>bold text</strong> and <em>italic text</em>.</p>
7+
<!-- /wp:paragraph -->
8+
9+
<!-- wp:heading -->
10+
<h2 class="wp-block-heading">Subheading</h2>
11+
<!-- /wp:heading -->
12+
13+
<!-- wp:paragraph -->
14+
<p>Another paragraph with a <a href="https://example.com">link</a>.</p>
15+
<!-- /wp:paragraph -->

0 commit comments

Comments
 (0)