From b54c4ddf234bbaa3de81fa69461c5830147c7a12 Mon Sep 17 00:00:00 2001 From: Sebastian Bergmann Date: Sat, 23 May 2026 06:27:12 +0200 Subject: [PATCH] Treat lone LF followed by lone CR as two separate line endings --- src/Exporter.php | 1 - tests/ExporterTest.php | 34 +++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Exporter.php b/src/Exporter.php index d7893ba..5fc8275 100644 --- a/src/Exporter.php +++ b/src/Exporter.php @@ -450,7 +450,6 @@ final readonly class Exporter $value, [ "\r\n" => '\r\n' . "\n", - "\n\r" => '\n\r' . "\n", "\r" => '\r' . "\n", "\n" => '\n' . "\n", ], diff --git a/tests/ExporterTest.php b/tests/ExporterTest.php index ecfe8c3..768633c 100644 --- a/tests/ExporterTest.php +++ b/tests/ExporterTest.php @@ -145,7 +145,9 @@ Array &0 [ EOF, 2, ], - // \n\r and \r is converted to \n + // A real newline is inserted after each line ending so the + // escaped text wraps readably; \r\n stays one break while a lone + // \n followed by a lone \r are two separate line endings. 'export multiline text' => ["this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", <<<'EOF' 'this\n @@ -157,8 +159,27 @@ very\n very\n very\n very\r -long\n\r +long\n +\r text' +EOF, + 0, + ], + // A lone \n (Unix) followed by a lone \r (old Mac) are two + // distinct line endings and must each produce their own break. + 'lone newline followed by lone carriage return' => ["a\n\rb", + <<<'EOF' +'a\n +\r +b' +EOF, + 0, + ], + // \r\n (Windows) is a single line ending and stays one break. + 'carriage return followed by newline' => ["a\r\nb", + <<<'EOF' +'a\r\n +b' EOF, 0, ], @@ -180,7 +201,8 @@ very\n very\n very\n very\r -long\n\r +long\n +\r text', 'object' => stdClass Object #%d ( 'foo' => 'bar', @@ -468,7 +490,8 @@ very\n very\n very\n very\r -long\n\r +long\n +\r text', 'object' => stdClass Object #%d ( 'foo' => 'bar', @@ -493,7 +516,8 @@ very\n very\n very\n very\r -long\n\r +long\n +\r text', 'object' => stdClass Object #%d, 'objectagain' => stdClass Object #%d,