Skip to content

Commit

Permalink
fix(comment): respect single newlines (#3012)
Browse files Browse the repository at this point in the history
  • Loading branch information
wescopeland authored Jan 3, 2025
1 parent 67b9798 commit aaf88b4
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 11 deletions.
24 changes: 13 additions & 11 deletions app/Community/Actions/FormatLegacyCommentPayloadAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ class FormatLegacyCommentPayloadAction

public function execute(string $payload, bool $isTicketComment): string
{
// Replace all <br /> tags with newlines for consistent processing.
$text = str_replace('<br />', "\n", $payload);

if (!$isTicketComment) {
return $this->formatText($text);
return $this->formatText($payload);
}

// Store original link tags with angle brackets in markers.
Expand All @@ -27,7 +24,7 @@ public function execute(string $payload, bool $isTicketComment): string
$links[] = $match[0];

return $marker . (count($links) - 1) . $marker;
}, $text);
}, $payload);

// Process the text and restore links.
$text = $this->formatText($text);
Expand All @@ -40,14 +37,19 @@ public function execute(string $payload, bool $isTicketComment): string

private function formatText(string $text): string
{
// First, normalize all existing <br /> tags to \n for consistent processing.
$text = preg_replace('/<br\s*\/?>\s*/', "\n", $text);

// Convert special characters to HTML entities.
$text = htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5);

// Convert newlines to <br /> tags and normalize multiple line breaks.
return preg_replace(
'/<br\s*\/?>(\s*<br\s*\/?>)+/',
'<br /><br />',
nl2br($text)
);
// Convert newlines to <br /> tags without adding additional \n.
$text = str_replace("\n", '<br />', $text);

// Collapse multiple consecutive line breaks into exactly two.
$text = preg_replace('/(<br\s*\/?>\s*){2,}/', '<br /><br />', $text);

// Add required \n after double breaks while preserving single breaks.
return preg_replace('/<br \/><br \/>/', "<br /><br />\n", $text);
}
}
2 changes: 2 additions & 0 deletions public/request/forum-topic-comment/preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

$mutatedBody = $input['body'];
$mutatedBody = normalize_shortcodes($mutatedBody);
$mutatedBody = str_replace(["\r\n", "\r"], "\n", $mutatedBody); // Convert to Unix newlines.
$mutatedBody = preg_replace('/\n{3,}|(<br\s*\/?>\s*){3,}/i', "\n\n", $mutatedBody); // Handle both \n and <br>.
$mutatedBody = htmlspecialchars($mutatedBody, ENT_QUOTES, 'UTF-8');

return response()->json([
Expand Down
2 changes: 2 additions & 0 deletions resources/views/pages-legacy/viewtopic.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@
$mutatedBody = $forumTopicComment->body;
$mutatedBody = normalize_shortcodes($mutatedBody);
$mutatedBody = str_replace(["\r\n", "\r"], "\n", $mutatedBody); // Convert to Unix newlines.
$mutatedBody = preg_replace('/\n{3,}|(<br\s*\/?>\s*){3,}/i', "\n\n", $mutatedBody); // Handle both \n and <br>.
$mutatedBody = htmlspecialchars($mutatedBody, ENT_QUOTES, 'UTF-8');
$mutatedBody = Shortcode::render($mutatedBody);
?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ public function testItNormalizesMultipleLineBreaks(): void
$this->assertEquals($expected, $this->action->execute($input, isTicketComment: false));
}

public function testItPreservesSingleLineBreaksBetweenListItems(): void
{
$input = "Line 1\n- Item 1\n- Item 2\n- Item 3";
$expected = "Line 1<br />- Item 1<br />- Item 2<br />- Item 3";

$this->assertEquals($expected, $this->action->execute($input, isTicketComment: false));
}

public function testItPreservesSingleLineBreaksBetweenListItems2(): void
{
$input = "Line 1<br />- Item 1<br />- Item 2<br />- Item 3";
$expected = "Line 1<br />- Item 1<br />- Item 2<br />- Item 3";

$this->assertEquals($expected, $this->action->execute($input, isTicketComment: false));
}

public function testItHandlesAttemptedMaliciousInput(): void
{
$cases = [
Expand Down

0 comments on commit aaf88b4

Please sign in to comment.