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   1123 use strict;
  3         7  
  3         87  
4 3     3   18 use warnings;
  3         5  
  3         92  
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         10  
  3         317  
22 3     3   2028 use Perl6::Pod::Utl::AbstractVisiter;
  3         8  
  3         111  
23 3     3   20 use base 'Perl6::Pod::Utl::AbstractVisiter';
  3         5  
  3         366  
24 3     3   1983 use Perl6::Pod::Block::SEMANTIC;
  3         7  
  3         186  
25              
26             sub new {
27 2     2 0 31 my $class = shift;
28 2 50 33     18 my $self = bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
29              
30             # check if exists context
31             # create them instead
32 2 50       11 unless ( $self->context ) {
33 3     3   1781 use Perl6::Pod::Utl::Context;
  3         10  
  3         169  
34 2         22 $self->context( new Perl6::Pod::Utl::Context:: );
35             }
36 2 50       13 unless ( $self->writer ) {
37 3     3   1536 use Perl6::Pod::Writer;
  3         9  
  3         2743  
38             $self->{writer} = new Perl6::Pod::Writer(
39 2   50     24 out => ( $self->{out} || \*STDOUT ),
40             escape => 'xml'
41             );
42             }
43              
44             #init head levels
45 2         5 $self->{HEAD_LEVELS} = 0;
46 2         6 $self;
47             }
48              
49             sub writer {
50 2     2 0 8 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 18 my $self = shift;
59 14 100       31 if (@_) {
60 2         6 $self->{context} = shift;
61             }
62 14         80 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   9 my $self = shift;
83 5   50     13 my $n = shift || return;
84              
85             # if string -> nothing to do
86 5 50       12 unless ( ref($n) ) {
87 0         0 return $n;
88             }
89              
90             # here convert lexer base block to
91             # instance of DOM class
92 5         15 my $name = $n->name;
93 5         13 my $map = $self->context->use;
94 5         8 my $class;
95             #convert lexer blocks
96 5 50       27 unless ( UNIVERSAL::isa( $n, 'Perl6::Pod::Block' ) ) {
97              
98 5         10 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       29 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     26 : $map->{'*'}
119             );
120             }
121              
122             #create instance
123 5 50       161 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       24 return undef unless ($el);
130 2         6 $n = $el;
131             }
132 2         6 return $n;
133             }
134              
135             sub visit {
136 4     4 0 5 my $self = shift;
137 4         5 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       11 if ( ref($n) eq 'ARRAY' ) {
145              
146             # $self->visit($_) for @$n;
147 5         12 my @nodes = grep { defined $_ } #skip empty nodes
148 5         17 map { $self->_make_dom_node($_) }
149 2 50       6 map { ref($_) eq 'ARRAY' ? @$_ : $_ } @$n;
  5         15  
150 2         5 my ( $prev, $next ) = ();
151 2         8 for ( my $i = 0 ; $i <= $#nodes ; ++$i ) {
152 2 50       7 if ( $i == $#nodes ) {
153 2         4 $next = undef;
154             }
155             else {
156 0         0 $next = $nodes[ $i + 1 ];
157             }
158 2         9 $self->visit( $nodes[$i], $prev, $next );
159 2         7 $prev = $nodes[$i];
160             }
161 2         6 return;
162             }
163              
164 2 50       10 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       8 unless ( UNIVERSAL::isa( $n, 'Perl6::Pod::Block' ) ) {
169 0   0     0 $n = $self->_make_dom_node($n) || return;
170             }
171 2         9 my $name = $n->name;
172              
173             #prcess head levels
174             #TODO also semantic BLOCKS
175 2 50       7 if ( $name eq 'head' ) {
176 0         0 $self->switch_head_level( $n->level );
177             }
178              
179             #process nested attr
180 2         9 my $nested = $n->get_attr->{nested};
181 2 50       10 if ($nested) {
182 0         0 $self->w->start_nesting($nested);
183             }
184              
185             #make method name
186 2         10 my $method = $self->__get_method_name($n);
187              
188             #call method
189 2         24 $self->$method( $n, @_ ); # $prev, $to in @_
190              
191 2 50       18 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   4 my $self = shift;
214 2   33     6 my $el = shift || croak "empty object !";
215 2         2 my $method;
216 3     3   19 use Data::Dumper;
  3         8  
  3         766  
217 2 50       10 unless ( UNIVERSAL::isa( $el, 'Perl6::Pod::Block' ) ) {
218 0         0 warn "unknown block" . Dumper($el);
219             }
220 2   50     7 my $name = $el->name || die "Can't get element name for " . Dumper($el);
221 2 50       13 if ( UNIVERSAL::isa( $el, 'Perl6::Pod::FormattingCode' ) ) {
222 0         0 $method = "code_$name";
223             }
224             else {
225 2         5 $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 14 my $self = shift;
246 2         4 my $tree = shift;
247 2         12 $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   18 use Perl6::Pod::Utl;
  3         6  
  3         875  
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__