Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion packages/blocks/src/api/raw-handling/markdown-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ function bulletsToAsterisks( text: string ): string {
return text.replace( /(^|\n)•( +)/g, '$1*$2' );
}

/**
* Escapes an ordered-list marker at the start of single-line input so prose
* like "18. May 2021" isn't parsed as `<ol start="18"><li>May 2021</li></ol>`.
*
* @param text The potential Markdown text to correct.
*/
function escapeSingleLineOrderedListMarker( text: string ): string {
if ( text.includes( '\n' ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is text with newlines ignored?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean: what happens if you have text with a date like that and the text spans multiple lines?

@Mamaduka Mamaduka May 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a rare case, but it will be pasted as a list. Same behavior as on trunk.

There's so much we can guess via Regex, and we probably shouldn't try and parse every date like string 😅

return text;
}
return text.replace( /^(\d+)\.(\s)/, '$1\\.$2' );
}

const correctors = [
escapeSingleLineOrderedListMarker,
bulletsToAsterisks,
slackMarkdownVariantCorrector,
];

/**
* Converts a piece of text into HTML based on any Markdown present.
* Also decodes any encoded HTML.
Expand All @@ -45,6 +64,9 @@ function bulletsToAsterisks( text: string ): string {
*/
export default function markdownConverter( text: string ): string {
return converter.makeHtml(
slackMarkdownVariantCorrector( bulletsToAsterisks( text ) )
correctors.reduce(
( current, corrector ) => corrector( current ),
text
)
);
}
17 changes: 17 additions & 0 deletions packages/blocks/src/api/raw-handling/test/markdown-converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,21 @@ describe( 'markdownConverter', () => {
const output = '<pre><code class="js language-js">test</code></pre>';
expect( markdownConverter( input ) ).toEqual( output );
} );

it( 'should not convert single-line date string into an ordered list', () => {
const input = '18. May 2021';
const output = '<p>18. May 2021</p>';
expect( markdownConverter( input ) ).toEqual( output );
} );

it( 'should not convert single-line "1. foo" into an ordered list', () => {
const input = '1. foo';
const output = '<p>1. foo</p>';
expect( markdownConverter( input ) ).toEqual( output );
} );

it( 'should still convert multi-line ordered list', () => {
const input = '1. apple\n2. banana';
expect( markdownConverter( input ) ).toContain( '<ol>' );
} );
} );
16 changes: 16 additions & 0 deletions test/e2e/specs/editor/various/copy-cut-paste.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,22 @@ test.describe( 'Copy/cut/paste', () => {
] );
} );

// See https://github.com/WordPress/gutenberg/issues/28149
test( 'should not convert pasted date string into an ordered list', async ( {
editor,
pageUtils,
} ) => {
await editor.insertBlock( { name: 'core/paragraph' } );
pageUtils.setClipboardData( { plainText: '4. May 2026' } );
await pageUtils.pressKeys( 'primary+v' );
expect( await editor.getBlocks() ).toMatchObject( [
{
name: 'core/paragraph',
attributes: { content: '4. May 2026' },
},
] );
} );

test( 'should replace the default block on paste when the content is unmodified', async ( {
editor,
pageUtils,
Expand Down
Loading