read_string splits lines and discards any blank lines. The problem
is that _read_hash and _read_array depend on that behavior, so they
have to be fixed. Then _read_scalar has to know what to do with the
blank lines.
This patch keeps embedded blank lines inside block scalars. Once I
fixed that, I realized that the fix would be out of spec (per YAML 1.1,
4.9.3 and the "Support for the chomping indicators on multi-line scalar
styles is required" statement in YAML::Tiny(3)) for everything *but*
`|+`, so I implemented the other indicators and added tests.
I'm making it sound like I know a lot more about this than I actually
do, so I could have gotten something wrong. I'm actually not 100% sure
I'm reading the spec right w.r.t. trailing newlines vs. lack of trailing
newlines, but everything passes the existing tests, and the other
modules pass my added tests.
Patch follows:
--------
diff -ur YAML-Tiny-1.51/lib/YAML/Tiny.pm YAML-Tiny-1.51-ahall/lib/YAML/Tiny.pm
--- YAML-Tiny-1.51/lib/YAML/Tiny.pm 2012-03-10 18:30:04.000000000 -0600
+++ YAML-Tiny-1.51-ahall/lib/YAML/Tiny.pm 2013-05-20 14:06:12.000000000 -0500
@@ -126,8 +126,8 @@
}
# Split the file into lines
- my @lines = grep { ! /^\s*(?:\#.*)?\z/ }
- split /(?:\015{1,2}\012|\015|\012)/, $string;
+ my @lines = grep { ! /^\s*\#.*\z/ }
+ split /(?:\015{1,2}\012|\015|\012)/, $string;
# Strip the initial YAML header
@lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines;
@@ -244,13 +244,24 @@
my @multiline = ();
while ( @$lines ) {
$lines->[0] =~ /^(\s*)/;
- last unless length($1) >= $indent->[-1];
+
+ # Quit if we've hit a non-blank line with a shorter indent
+ last if (($lines->[0] ne '') && (length($1) < $indent->[-1]));
+
push @multiline, substr(shift(@$lines), length($1));
}
- my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
- my $t = (substr($string, 1, 1) eq '-') ? '' : "\n";
- return join( $j, @multiline ) . $t;
+ # fold vs. literal
+ my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
+ my $str = join( $j, @multiline );
+
+ # chomp indicator
+ my $ind = substr($string, 1, 1);
+ if ($ind eq '-') { $str =~ s/\n*\z//; } # strip
+ elsif ($ind eq '+') { $str .= "\n" } # keep
+ else { $str =~ s/\n*\z/\n/; } # clip
+
+ return $str;
}
# Parse an array
@@ -258,6 +269,12 @@
my ($self, $array, $indent, $lines) = @_;
while ( @$lines ) {
+ # Gobble blank lines
+ if ( $lines->[0] =~ /^\s*\z/ ) {
+ shift @$lines;
+ next;
+ }
+
# Check for a new document
if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
while ( @$lines and $lines->[0] !~ /^---/ ) {
@@ -334,6 +351,12 @@
my ($self, $hash, $indent, $lines) = @_;
while ( @$lines ) {
+ # Gobble blank lines
+ if ( $lines->[0] =~ /^\s*\z/ ) {
+ shift @$lines;
+ next;
+ }
+
# Check for a new document
if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
while ( @$lines and $lines->[0] !~ /^---/ ) {
@@ -383,6 +406,11 @@
$self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines );
}
}
+ else {
+ # Blank line, treat it like the end of an indented block;
+ # the top of the loop will gobble the line
+ $hash->{$key} = undef;
+ }
}
}
diff -ur YAML-Tiny-1.51/t/03_regression.t YAML-Tiny-1.51-ahall/t/03_regression.t
--- YAML-Tiny-1.51/t/03_regression.t 2012-03-10 18:30:04.000000000 -0600
+++ YAML-Tiny-1.51-ahall/t/03_regression.t 2013-05-20 13:36:14.000000000 -0500
@@ -10,7 +10,7 @@
use File::Spec::Functions ':ALL';
use t::lib::Test;
-use Test::More tests(37, 0, 13);
+use Test::More tests(41, 0, 13);
use YAML::Tiny qw{
Load Dump
LoadFile DumpFile
@@ -96,7 +96,63 @@
);
+# ... with embedded blank line
+yaml_ok( <<'END_YAML',
+---
+- |
+ foo
+
+ bar
+- 1
+END_YAML
+ [ [ "foo\n\nbar\n", 1 ] ],
+ 'block scalar with embedded empty line',
+);
+
+# ... with embedded and trailing blank lines (keep)
+yaml_ok( <<'END_YAML',
+---
+- |+
+ foo
+
+ bar
+
+- 1
+END_YAML
+ [ [ "foo\n\nbar\n\n\n", 1 ] ],
+ 'block scalar keeps trailing blank line',
+);
+
+# ... with embedded and trailing blank lines (clip)
+yaml_ok( <<'END_YAML',
+---
+- |
+ foo
+
+ bar
+
+
+- 1
+END_YAML
+ [ [ "foo\n\nbar\n", 1 ] ],
+ 'block scalar clips trailing blank lines',
+);
+
+# ... with embedded and trailing blank lines (strip)
+yaml_ok( <<'END_YAML',
+---
+- |-
+ foo
+
+ bar
+
+
+- 1
+END_YAML
+ [ [ "foo\n\nbar", 1 ] ],
+ 'block scalar strips trailing newlines',
+);
#####################################################################