Skip to content

Commit

Permalink
bug #15482 [Yaml] Improve newline handling in folded scalar blocks (t…
Browse files Browse the repository at this point in the history
…eohhanhui)

This PR was merged into the 2.3 branch.

Discussion
----------

[Yaml] Improve newline handling in folded scalar blocks

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #15477
| License       | MIT
| Doc PR        | N/A

Commits
-------

73366d5 [Yaml] Improve newline handling in folded scalar blocks
  • Loading branch information
fabpot committed Sep 30, 2015
2 parents d8dc8f2 + 73366d5 commit c0ff4bf
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 18 deletions.
40 changes: 24 additions & 16 deletions src/Symfony/Component/Yaml/Parser.php
Expand Up @@ -20,7 +20,9 @@
*/
class Parser
{
const FOLDED_SCALAR_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
// BC - wrongly named
const FOLDED_SCALAR_PATTERN = self::BLOCK_SCALAR_HEADER_PATTERN;

private $offset = 0;
private $lines = array();
Expand Down Expand Up @@ -337,8 +339,8 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false)

$isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine);

// Comments must not be removed inside a string block (ie. after a line ending with "|")
$removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~';
// Comments must not be removed inside a block scalar
$removeCommentsPattern = '~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~';
$removeComments = !preg_match($removeCommentsPattern, $this->currentLine);

while ($this->moveToNextLine()) {
Expand Down Expand Up @@ -427,10 +429,10 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport)
return $this->refs[$value];
}

if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) {
if (preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) {
$modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';

return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));
return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));
}

try {
Expand All @@ -444,15 +446,15 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport)
}

/**
* Parses a folded scalar.
* Parses a block scalar.
*
* @param string $separator The separator that was used to begin this folded scalar (| or >)
* @param string $indicator The indicator that was used to begin this folded scalar (+ or -)
* @param int $indentation The indentation that was used to begin this folded scalar
* @param string $style The style indicator that was used to begin this block scalar (| or >)
* @param string $chomping The chomping indicator that was used to begin this block scalar (+ or -)
* @param int $indentation The indentation indicator that was used to begin this block scalar
*
* @return string The text value
*/
private function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
private function parseBlockScalar($style, $chomping = '', $indentation = 0)
{
$notEOF = $this->moveToNextLine();
if (!$notEOF) {
Expand Down Expand Up @@ -507,17 +509,23 @@ private function parseFoldedScalar($separator, $indicator = '', $indentation = 0
$this->moveToPreviousLine();
}

// replace all non-trailing single newlines with spaces in folded blocks
if ('>' === $separator) {
// folded style
if ('>' === $style) {
// folded lines
// replace all non-leading/non-trailing single newlines with spaces
preg_match('/(\n*)$/', $text, $matches);
$text = preg_replace('/(?<!\n)\n(?!\n)/', ' ', rtrim($text, "\n"));
$text = preg_replace('/(?<!\n|^)\n(?!\n)/', ' ', rtrim($text, "\n"));
$text .= $matches[1];

// empty separation lines
// remove one newline from each group of non-leading/non-trailing newlines
$text = preg_replace('/[^\n]\n+\K\n(?=[^\n])/', '', $text);
}

// deal with trailing newlines as indicated
if ('' === $indicator) {
// deal with trailing newlines
if ('' === $chomping) {
$text = preg_replace('/\n+$/', "\n", $text);
} elseif ('-' === $indicator) {
} elseif ('-' === $chomping) {
$text = preg_replace('/\n+$/', '', $text);
}

Expand Down
18 changes: 16 additions & 2 deletions src/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml
Expand Up @@ -51,9 +51,9 @@ php: |
'~',
)
---
test: Empty lines in folded blocks
test: Empty lines in literal blocks
brief: >
Empty lines in folded blocks
Empty lines in literal blocks
yaml: |
foo:
bar: |
Expand All @@ -65,6 +65,20 @@ yaml: |
php: |
array('foo' => array('bar' => "foo\n\n\n \nbar\n"))
---
test: Empty lines in folded blocks
brief: >
Empty lines in folded blocks
yaml: |
foo:
bar: >
foo
bar
php: |
array('foo' => array('bar' => "\nfoo\n\nbar\n"))
---
test: IP addresses
brief: >
IP addresses
Expand Down

0 comments on commit c0ff4bf

Please sign in to comment.