From 4b7f0e6e1d49273179f07ceed057d0c08167506d Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Mon, 6 Apr 2026 16:34:40 +0530 Subject: [PATCH 1/8] Formatting: Add `strip_html_newlines()` function to preserve newlines in specific HTML elements --- src/wp-includes/formatting.php | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 498d676f5c20f..ee7c61bf02c8c 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -868,6 +868,52 @@ function shortcode_unautop( $text ) { return preg_replace( $pattern, '$1', $text ); } +function strip_html_newlines( $text ) { + if ( ! str_contains( $text, "\n" ) && ! str_contains( $text, "\r" ) ) { + return $text; + } + + $preserve_newlines_elements = array( 'pre', 'code', 'kbd', 'script', 'style' ); + + $textarr = wp_html_split( $text ); + $changed = false; + $skip = false; + + foreach ( $textarr as $i => $chunk ) { + if ( '' === $chunk ) { + continue; + } + + if ( 0 !== $i % 2 ) { + foreach ( $preserve_newlines_elements as $element ) { + if ( stripos( $chunk, '<' . $element ) === 0 ) { + $skip = true; + break; + } + if ( stripos( $chunk, '' ) === 0 ) { + $skip = false; + break; + } + } + continue; + } + + if ( ! $skip ) { + $stripped = preg_replace( '/[\n\r]+/', ' ', $chunk ); + if ( $stripped !== $chunk ) { + $textarr[ $i ] = $stripped; + $changed = true; + } + } + } + + if ( $changed ) { + return implode( '', $textarr ); + } + + return $text; +} + /** * Checks to see if a string is utf8 encoded. * From adeeeb0ada1471759a443760ba56a32b406abd7b Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Mon, 6 Apr 2026 16:35:25 +0530 Subject: [PATCH 2/8] Formatting: Add documentation for `strip_html_newlines()` function --- src/wp-includes/formatting.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index ee7c61bf02c8c..c0646ac5d5d80 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -868,6 +868,14 @@ function shortcode_unautop( $text ) { return preg_replace( $pattern, '$1', $text ); } +/** + * Strips unnecessary newlines from HTML content. + * + * @since 7.1.0 + * + * @param string $text The HTML content to strip newlines from. + * @return string The HTML content with unnecessary newlines removed. + */ function strip_html_newlines( $text ) { if ( ! str_contains( $text, "\n" ) && ! str_contains( $text, "\r" ) ) { return $text; From 10dd18797917ce175636db93a6fec29d5f70b698 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Tue, 7 Apr 2026 20:04:47 +0530 Subject: [PATCH 3/8] Tests: Add initial test class --- tests/phpunit/tests/formatting/stripHtmlNewlines.php | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/phpunit/tests/formatting/stripHtmlNewlines.php diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php new file mode 100644 index 0000000000000..5e6c1a0c3ca97 --- /dev/null +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -0,0 +1,5 @@ + Date: Tue, 7 Apr 2026 20:05:13 +0530 Subject: [PATCH 4/8] Tests: Add documentation --- tests/phpunit/tests/formatting/stripHtmlNewlines.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php index 5e6c1a0c3ca97..d984a3111ea93 100644 --- a/tests/phpunit/tests/formatting/stripHtmlNewlines.php +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -1,5 +1,11 @@ Date: Tue, 7 Apr 2026 20:06:21 +0530 Subject: [PATCH 5/8] Tests: Verify if it strips newlines from the nodes --- tests/phpunit/tests/formatting/stripHtmlNewlines.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php index d984a3111ea93..e999844dda581 100644 --- a/tests/phpunit/tests/formatting/stripHtmlNewlines.php +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -8,4 +8,14 @@ * @covers ::strip_html_newlines */ class Tests_Formatting_StripHtmlNewlines extends WP_UnitTestCase { + public function test_strips_newlines_from_text_nodes() { + $this->assertSame( '', strip_html_newlines( '' ), 'Empty string should be returned as-is.' ); + $this->assertSame( '

No newlines here.

', strip_html_newlines( '

No newlines here.

' ), 'Text without newlines should be returned as-is.' ); + $this->assertSame( '

Line one Line two Line three

', strip_html_newlines( "

Line one\n\nLine two\r\nLine three

" ), 'Multiple newlines and carriage returns should be collapsed to a single space.' ); + $this->assertSame( + '

This is a paragraph in which the wpautop() wrapping will happen in the middle of an anchor, which is an inline element.

', + strip_html_newlines( "

This is a paragraph in which the\nwpautop() wrapping will\nhappen in the middle of an\nanchor, which is an inline element.

" ), + 'Newlines within and around inline elements should be stripped.' + ); + } } From 7b12056abd16a856b2be166cd66751bad245d151 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Tue, 7 Apr 2026 20:06:42 +0530 Subject: [PATCH 6/8] Tests: Add documentation --- tests/phpunit/tests/formatting/stripHtmlNewlines.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php index e999844dda581..63a51b380e577 100644 --- a/tests/phpunit/tests/formatting/stripHtmlNewlines.php +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -8,6 +8,13 @@ * @covers ::strip_html_newlines */ class Tests_Formatting_StripHtmlNewlines extends WP_UnitTestCase { + + /** + * Verifies that newlines and carriage returns in text nodes are replaced + * with spaces, including across inline elements like anchors. + * + * @ticket 5678 + */ public function test_strips_newlines_from_text_nodes() { $this->assertSame( '', strip_html_newlines( '' ), 'Empty string should be returned as-is.' ); $this->assertSame( '

No newlines here.

', strip_html_newlines( '

No newlines here.

' ), 'Text without newlines should be returned as-is.' ); From 98fc44dc692aee1cabbf1d2e4f995c295b9a8760 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Tue, 7 Apr 2026 20:07:08 +0530 Subject: [PATCH 7/8] Tests: Verify preservation of newlines in preformatted elements --- .../tests/formatting/stripHtmlNewlines.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php index 63a51b380e577..efeecb4f41fa3 100644 --- a/tests/phpunit/tests/formatting/stripHtmlNewlines.php +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -25,4 +25,25 @@ public function test_strips_newlines_from_text_nodes() { 'Newlines within and around inline elements should be stripped.' ); } + public function test_preserves_newlines_in_preformatted_elements() { + $input = "

Normal\ntext

\n
\nPreformatted\nlines\n
\n

More\ntext

"; + $result = strip_html_newlines( $input ); + + $this->assertStringContainsString( 'Normal text', $result, 'Newlines in normal text should be stripped.' ); + $this->assertStringContainsString( 'More text', $result, 'Newlines in trailing paragraph should be stripped.' ); + $this->assertStringContainsString( "\nPreformatted\nlines\n", $result, 'Newlines inside
 should be preserved.' );
+
+		$preserved_cases = array(
+			'code'   => "

A\nB

x\ny", + 'kbd' => "

A\nB

x\ny", + 'script' => "

A\nB

", + 'style' => "

A\nB

", + ); + + foreach ( $preserved_cases as $tag => $html ) { + $out = strip_html_newlines( $html ); + $this->assertStringContainsString( 'A B', $out, "Text node newline should be stripped around <{$tag}>." ); + $this->assertStringContainsString( "x\ny", $out, "Newline inside <{$tag}> should be preserved." ); + } + } } From 60920d21fcdada55191e9f8e2a89947e50f011a9 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Tue, 7 Apr 2026 20:07:41 +0530 Subject: [PATCH 8/8] Tests: Add documentation for newline preservation test --- tests/phpunit/tests/formatting/stripHtmlNewlines.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/phpunit/tests/formatting/stripHtmlNewlines.php b/tests/phpunit/tests/formatting/stripHtmlNewlines.php index efeecb4f41fa3..aa2ed7608b6e3 100644 --- a/tests/phpunit/tests/formatting/stripHtmlNewlines.php +++ b/tests/phpunit/tests/formatting/stripHtmlNewlines.php @@ -25,6 +25,11 @@ public function test_strips_newlines_from_text_nodes() { 'Newlines within and around inline elements should be stripped.' ); } + + /** + * + * @ticket 5678 + */ public function test_preserves_newlines_in_preformatted_elements() { $input = "

Normal\ntext

\n
\nPreformatted\nlines\n
\n

More\ntext

"; $result = strip_html_newlines( $input );