File Coverage

blib/lib/Perl6/Pod/To.pm
Criterion Covered Total %
statement 94 142 66.2
branch 25 52 48.0
condition 6 28 21.4
subroutine 17 28 60.7
pod 2 15 13.3
total 144 265 54.3


line stmt bran cond sub pod time code
1             package Perl6::Pod::To;
2             our $VERSION = '0.01';
3 3     3   744 use strict;
  3         5  
  3         71  
4 3     3   17 use warnings;
  3         3  
  3         76  
5              
6             =pod
7              
8             =head1 NAME
9              
10             Perl6::Pod::To - base class for output formatters
11              
12             =head1 SYNOPSIS
13              
14              
15             =head1 DESCRIPTION
16              
17             Perl6::Pod::To - base class for output formatters
18              
19             =cut
20              
21 3     3   18 use Carp;
  3         8  
  3         184  
22 3     3   1631 use Perl6::Pod::Utl::AbstractVisiter;
  3         6  
  3         92  
23 3     3   15 use base 'Perl6::Pod::Utl::AbstractVisiter';
  3         5  
  3         284  
24 3     3   1621 use Perl6::Pod::Block::SEMANTIC;
  3         8  
  3         200  
25              
26             sub new {
27 2     2 0 37 my $class = shift;
28 2 50 33     19 my $self = bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
29              
30             # check if exists context
31             # create them instead
32 2 50       15 unless ( $self->context ) {
33 3     3   1743 use Perl6::Pod::Utl::Context;
  3         11  
  3         185  
34 2         21 $self->context( new Perl6::Pod::Utl::Context:: );
35             }
36 2 50       11 unless ( $self->writer ) {
37 3     3   1891 use Perl6::Pod::Writer;
  3         9  
  3         2935  
38             $self->{writer} = new Perl6::Pod::Writer(
39 2   50     30 out => ( $self->{out} || \*STDOUT ),
40             escape => 'xml'
41             );
42             }
43              
44             #init head levels
45 2         7 $self->{HEAD_LEVELS} = 0;
46 2         7 $self;
47             }
48              
49             sub writer {
50 2     2 0 10 return $_[0]->{writer};
51             }
52              
53             sub w {
54 0     0 0 0 return $_[0]->writer;
55             }
56              
57             sub context {
58 14     14 0 23 my $self = shift;
59 14 100       34 if (@_) {
60 2         7 $self->{context} = shift;
61             }
62 14         90 return $self->{context};
63             }
64              
65             #TODO then visit to child -> create new context !
66             sub visit_childs {
67 0     0 0 0 my $self = shift;
68 0         0 foreach my $n (@_) {
69 0 0 0     0 die "Unknow type $n (not isa Perl6::Pod::Block)"
70             unless UNIVERSAL::isa( $n, 'Perl6::Pod::Block' )
71             || UNIVERSAL::isa( $n, 'Perl6::Pod::Lex::Block' );
72 0 0       0 unless ( defined $n->childs ) {
73              
74             #die " undefined childs for". Dumper ($n)
75 0         0 next;
76             }
77 0         0 $self->visit( $n->childs );
78             }
79             }
80              
81             sub _make_dom_node {
82 5     5   7 my $self = shift;
83 5   50     14 my $n = shift || return;
84              
85             # if string -> nothing to do
86 5 50       13 unless ( ref($n) ) {
87 0         0 return $n;
88             }
89              
90             # here convert lexer base block to
91             # instance of DOM class
92 5         17 my $name = $n->name;
93 5         14 my $map = $self->context->use;
94 5         8 my $class;
95             #convert lexer blocks
96 5 50       29 unless ( UNIVERSAL::isa( $n, 'Perl6::Pod::Block' ) ) {
97              
98 5         11 my %additional_attr = ();
99 5 50       24 if ( UNIVERSAL::isa( $n, 'Perl6::Pod::Lex::FormattingCode' ) ) {
100 0   0     0 $class = $map->{ $name . '<>' } || $map->{'*<>'};
101             }
102              
103             # UNIVERSAL::isa( $n, 'Perl6::Pod::Lex::Block' )
104             else {
105              
106 5 100       32 if ( $name =~ /(para|code)/ ) {
107              
108             # add { name=>$name }
109             # for text and code blocks
110              
111 2         5 $additional_attr{name} = $name;
112             }
113              
114             $class = $map->{$name}
115             || (
116             $name eq uc($name)
117             ? 'Perl6::Pod::Block::SEMANTIC'
118 5   33     32 : $map->{'*'}
119             );
120             }
121              
122             #create instance
123 5 50       207 my $el =
124             $class eq '-'
125             ? $n
126             : $class->new( %$n, %additional_attr, context => $self->context );
127              
128             #if no instanse -> skip this element
129 5 100       26 return undef unless ($el);
130 2         6 $n = $el;
131             }
132 2         8 return $n;
133             }
134              
135             sub visit {
136 4     4 0 7 my $self = shift;
137 4         6 my $n = shift;
138              
139             # if string -> paragraph
140 4 50       13 unless ( ref($n) ) {
141 0         0 return $self->w->print($n);
142             }
143              
144 4 100       12 if ( ref($n) eq 'ARRAY' ) {
145              
146             # $self->visit($_) for @$n;
147 5         15 my @nodes = grep { defined $_ } #skip empty nodes
148 5         17 map { $self->_make_dom_node($_) }
149 2 50       5 map { ref($_) eq 'ARRAY' ? @$_ : $_ } @$n;
  5         19  
150 2         6 my ( $prev, $next ) = ();
151 2         11 for ( my $i = 0 ; $i <= $#nodes ; ++$i ) {
152 2 50       6 if ( $i == $#nodes ) {
153 2         4 $next = undef;
154             }
155             else {
156 0         0 $next = $nodes[ $i + 1 ];
157             }
158 2         10 $self->visit( $nodes[$i], $prev, $next );
159 2         7 $prev = $nodes[$i];
160             }
161 2         8 return;
162             }
163              
164 2 50       11 die "Unknown node type $n (not isa Perl6::Pod::Lex::Block)"
165             unless UNIVERSAL::isa( $n, 'Perl6::Pod::Lex::Block' );
166              
167             #unless already converted to DOM element
168 2 50       7 unless ( UNIVERSAL::isa( $n, 'Perl6::Pod::Block' ) ) {
169 0   0     0 $n = $self->_make_dom_node($n) || return;
170             }
171 2         11 my $name = $n->name;
172              
173             #prcess head levels
174             #TODO also semantic BLOCKS
175 2 50       8 if ( $name eq 'head' ) {
176 0         0 $self->switch_head_level( $n->level );
177             }
178              
179             #process nested attr
180 2         10 my $nested = $n->get_attr->{nested};
181 2 50       11 if ($nested) {
182 0         0 $self->w->start_nesting($nested);
183             }
184              
185             #make method name
186 2         14 my $method = $self->__get_method_name($n);
187              
188             #call method
189 2         25 $self->$method( $n, @_ ); # $prev, $to in @_
190              
191 2 50       23 if ($nested) {
192 0         0 $self->w->stop_nesting($nested);
193             }
194             }
195              
196             =head2 switch_head_level
197              
198             Service method for =head
199              
200             =cut
201              
202             sub switch_head_level {
203 0     0 1 0 my $self = shift;
204 0 0       0 if (@_) {
205 0         0 my $prev = $self->{HEAD_LEVELS};
206 0         0 $self->{HEAD_LEVELS} = shift;
207 0         0 return $prev;
208             }
209 0         0 $self->{HEAD_LEVELS};
210             }
211              
212             sub __get_method_name {
213 2     2   5 my $self = shift;
214 2   33     7 my $el = shift || croak "empty object !";
215 2         2 my $method;
216 3     3   22 use Data::Dumper;
  3         7  
  3         852  
217 2 50       9 unless ( UNIVERSAL::isa( $el, 'Perl6::Pod::Block' ) ) {
218 0         0 warn "unknown block" . Dumper($el);
219             }
220 2   50     8 my $name = $el->name || die "Can't get element name for " . Dumper($el);
221 2 50       16 if ( UNIVERSAL::isa( $el, 'Perl6::Pod::FormattingCode' ) ) {
222 0         0 $method = "code_$name";
223             }
224             else {
225 2         6 $method = "block_$name";
226             }
227 2         6 return $method;
228             }
229              
230             sub block_File {
231 0     0 0 0 my $self = shift;
232 0         0 return $self->visit_childs(shift);
233             }
234              
235             sub block_pod {
236 0     0 0 0 my $self = shift;
237 0         0 return $self->visit_childs(shift);
238             }
239              
240             #comments
241       0 0   sub code_Z { }
242       0 0   sub block_comment { }
243              
244             sub write {
245 2     2 0 15 my $self = shift;
246 2         3 my $tree = shift;
247 2         42 $self->visit($tree);
248             }
249              
250             =head2 parse \$TEXT
251              
252             parse text
253              
254             =cut
255              
256             sub parse {
257 0     0 1   my $self = shift;
258 0           my $text = shift;
259 3     3   20 use Perl6::Pod::Utl;
  3         8  
  3         955  
260 0   0       my $tree = Perl6::Pod::Utl::parse_pod( ref($text) ? $$text : $text, @_ )
261             || return "Error";
262 0           $self->start_write;
263 0           $self->write($tree);
264 0           $self->end_write;
265 0           0;
266             }
267              
268             # unless have export method
269             # try element methods for export
270             sub __default_method {
271 0     0     my $self = shift;
272 0           my $n = shift;
273              
274             #detect output format
275             # Perl6::Pod::To::DocBook -> to_docbook
276 0           my $export_format = $self->{format};
277 0 0         unless ($export_format) {
278 0           ( $export_format = ref($self) ) =~ s/^.*To::([^:]+)/lc "$1"/es;
  0            
279             }
280 0           my $export_method = lc "to_$export_format";
281 0 0 0       unless ( $export_method && UNIVERSAL::can( $n, $export_method ) ) {
282 0           my $method = $self->__get_method_name($n);
283 0           warn ref($self)
284             . ": Method '$method' for class "
285             . ref($n)
286             . " not implemented. But also can't found export method "
287             . ref($n)
288             . "::$export_method";
289 0           return;
290             }
291              
292             #call method for export
293 0           $n->$export_method( $self, @_ ) # $prev, $to
294             }
295              
296             sub start_write {
297 0     0 0   my $self = shift;
298             }
299              
300             sub end_write {
301 0     0 0   my $self = shift;
302             }
303              
304             1;
305             __END__