Skip to content

Commit 7b1ac85

Browse files
jbergerLeont
authored andcommitted
PodParser now respects =encoding directives
When deriving authors or abstract from pod, if encoding is ignored the related META files will then be incorrect. This implementation makes reading the pod two pass, first to find an =encoding directive if it exists and if so set the binmode, then seeks back to the top to continue parsing as usual. To support this I have also moved away from testing with a tied class, which was then mocking out everything that was attempting to be tested. It now simply uses open to a string.
1 parent 0183ddf commit 7b1ac85

File tree

2 files changed

+43
-31
lines changed

2 files changed

+43
-31
lines changed

lib/Module/Build/PodParser.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ sub parse_from_filehandle {
2424
my ($self, $fh) = @_;
2525

2626
local $_;
27+
while (<$fh>) {
28+
next unless /=encoding \s+ (.*)/ix;
29+
binmode $fh, ":encoding($1)";
30+
last;
31+
}
32+
seek $fh, 0, 0;
33+
2734
while (<$fh>) {
2835
next unless /^=(?!cut)/ .. /^=cut/; # in POD
2936
# Accept Name - abstract or C<Name> - abstract

t/pod_parser.t

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,16 @@
22

33
use strict;
44
use lib 't/lib';
5-
use MBTest tests => 14;
5+
use MBTest tests => 16;
6+
7+
use Encode 'encode';
68

79
blib_load('Module::Build::PodParser');
810

911
#########################
1012

1113
{
12-
package IO::StringBased;
13-
14-
sub TIEHANDLE {
15-
my ($class, $string) = @_;
16-
return bless {
17-
data => [ map "$_\n", split /\n/, $string],
18-
}, $class;
19-
}
20-
21-
sub READLINE {
22-
shift @{ shift()->{data} };
23-
}
24-
}
25-
26-
local *FH;
27-
tie *FH, 'IO::StringBased', <<'EOF';
14+
open my $fh, '<', \<<'EOF';
2815
=head1 NAME
2916
3017
Foo::Bar - Perl extension for blah blah blah
@@ -39,25 +26,24 @@ Home page: http://example.com/~eh/
3926
EOF
4027

4128

42-
my $pp = Module::Build::PodParser->new(fh => \*FH);
29+
my $pp = Module::Build::PodParser->new(fh => $fh);
4330
ok $pp, 'object created';
4431

4532
is $pp->get_author->[0], 'C<Foo::Bar> was written by Engelbert Humperdinck I<E<lt>[email protected]<gt>> in 2004.', 'author';
4633
is $pp->get_abstract, 'Perl extension for blah blah blah', 'abstract';
47-
34+
}
4835

4936
{
5037
# Try again without a valid author spec
51-
untie *FH;
52-
tie *FH, 'IO::StringBased', <<'EOF';
38+
open my $fh, '<', \<<'EOF';
5339
=head1 NAME
5440
5541
Foo::Bar - Perl extension for blah blah blah
5642
5743
=cut
5844
EOF
5945

60-
my $pp = Module::Build::PodParser->new(fh => \*FH);
46+
my $pp = Module::Build::PodParser->new(fh => $fh);
6147
ok $pp, 'object created';
6248

6349
is_deeply $pp->get_author, [], 'author';
@@ -67,8 +53,7 @@ EOF
6753

6854
{
6955
# Try again with mixed-case =head1s.
70-
untie *FH;
71-
tie *FH, 'IO::StringBased', <<'EOF';
56+
open my $fh, '<', \<<'EOF';
7257
=head1 Name
7358
7459
Foo::Bar - Perl extension for blah blah blah
@@ -82,7 +67,7 @@ Home page: http://example.com/~eh/
8267
=cut
8368
EOF
8469

85-
my $pp = Module::Build::PodParser->new(fh => \*FH);
70+
my $pp = Module::Build::PodParser->new(fh => $fh);
8671
ok $pp, 'object created';
8772

8873
is $pp->get_author->[0], 'C<Foo::Bar> was written by Engelbert Humperdinck I<E<lt>[email protected]<gt>> in 2004.', 'author';
@@ -92,8 +77,7 @@ EOF
9277

9378
{
9479
# Now with C<Module::Name>
95-
untie *FH;
96-
tie *FH, 'IO::StringBased', <<'EOF';
80+
open my $fh, '<', \<<'EOF';
9781
=head1 Name
9882
9983
C<Foo::Bar> - Perl extension for blah blah blah
@@ -107,16 +91,15 @@ Home page: http://example.com/~eh/
10791
=cut
10892
EOF
10993

110-
my $pp = Module::Build::PodParser->new(fh => \*FH);
94+
my $pp = Module::Build::PodParser->new(fh => $fh);
11195
ok $pp, 'object created';
11296

11397
is $pp->get_author->[0], 'C<Foo::Bar> was written by Engelbert Humperdinck I<E<lt>[email protected]<gt>> in 2004.', 'author';
11498
is $pp->get_abstract, 'Perl extension for blah blah blah', 'abstract';
11599
}
116100

117101
{
118-
local *FH;
119-
tie *FH, 'IO::StringBased', <<'EOF';
102+
open my $fh, '<', \<<'EOF';
120103
=head1 NAME
121104
122105
Foo_Bar - Perl extension for eating pie
@@ -131,7 +114,29 @@ Home page: http://example.com/~eh/
131114
EOF
132115

133116

134-
my $pp = Module::Build::PodParser->new(fh => \*FH);
117+
my $pp = Module::Build::PodParser->new(fh => $fh);
135118
ok $pp, 'object created';
136119
is $pp->get_abstract, 'Perl extension for eating pie', 'abstract';
137120
}
121+
122+
{
123+
open my $fh, '<', \ encode 'UTF-8', <<"EOF";
124+
=encoding utf8
125+
126+
=head1 NAME
127+
128+
Foo_Bar - I \x{2764} Perl
129+
130+
=head1 AUTHOR
131+
132+
C<Foo_Bar> was written by Engelbert Humperdinck I<E<lt>eh\@example.comE<gt>> in 2004.
133+
134+
Home page: http://example.com/~eh/
135+
136+
=cut
137+
EOF
138+
139+
my $pp = Module::Build::PodParser->new(fh => $fh);
140+
ok $pp, 'object created';
141+
is $pp->get_abstract, "I \x{2764} Perl", 'abstract with unicode';
142+
}

0 commit comments

Comments
 (0)