Skip to content

Commit 3618fc5

Browse files
committed
Fix newlines disappearing inside PRE,TEXTAREA elements
1 parent 09c0076 commit 3618fc5

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

src/wp-includes/html-api/class-wp-html-processor.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,25 @@ public function serialize_token(): string {
13581358
break;
13591359

13601360
case '#text':
1361-
$html .= htmlspecialchars( $this->get_modifiable_text(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8' );
1361+
$text = $this->get_modifiable_text();
1362+
if (
1363+
WP_HTML_Tag_Processor::TEXT_IS_WHITESPACE === $this->text_node_classification &&
1364+
'PRE' === $this->state->stack_of_open_elements->at( $this->state->stack_of_open_elements->count() - 1 )?->node_name
1365+
) {
1366+
/*
1367+
* DO NOT DO THIS
1368+
* This case is exceptional and we must peek at processor internals.
1369+
*/
1370+
$newline_was_erased = Closure::bind(
1371+
fn () => $this->skip_newline_at === $this->token_starts_at,
1372+
$this,
1373+
WP_HTML_Tag_Processor::class
1374+
)();
1375+
if ( $newline_was_erased ) {
1376+
$text = "\n{$text}";
1377+
}
1378+
}
1379+
$html .= htmlspecialchars( $text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8' );
13621380
break;
13631381

13641382
// Unlike the `<>` which is interpreted as plaintext, this is ignored entirely.
@@ -1427,6 +1445,19 @@ public function serialize_token(): string {
14271445
case 'STYLE':
14281446
break;
14291447

1448+
/*
1449+
* Textarea elements ignore a leading newline. It is not present in `get_modifiable_text()`
1450+
* because the HTML parser doesn't include it in the text node.
1451+
* Serialization can always add a leading newline because it will be ignored by an
1452+
* HTML parser.
1453+
* This is especially important in case the text starts with a sequence of newlines.
1454+
* If normalization removes a single leading newline, it would cause the
1455+
* _significant_ following newline to be ignore by any later processing
1456+
* or a browser.
1457+
*/
1458+
case 'TEXTAREA':
1459+
$text = "\n{$text}";
1460+
// Intentional fallthrough, TEXTAREA should have default handling.
14301461
default:
14311462
$text = htmlspecialchars( $text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8' );
14321463
}

0 commit comments

Comments
 (0)