File Coverage

blib/lib/Perl6/Pod/Block/item.pm
Criterion Covered Total %
statement 18 119 15.1
branch 0 60 0.0
condition 0 23 0.0
subroutine 6 14 42.8
pod 1 8 12.5
total 25 224 11.1


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # DESCRIPTION: ordered and unordered lists
4             #
5             # AUTHOR: Aliaksandr P. Zahatski,
6             #===============================================================================
7             package Perl6::Pod::Block::item;
8              
9             =pod
10              
11             =head1 NAME
12              
13             Perl6::Pod::Block::item - lists
14              
15             =head1 SYNOPSIS
16              
17             =item Happy
18             =item Dopey
19             =item Sleepy
20              
21             =item1 Animal
22             =item2 Vertebrate
23             =item2 Invertebrate
24              
25             =head1 DESCRIPTION
26              
27             Lists in Pod are specified as a series of contiguous C<=item> blocks. No
28             special "container" directives or other delimiters are required to
29             enclose the entire list. For example:
30              
31             The seven suspects are:
32              
33             =item Happy
34             =item Dopey
35             =item Sleepy
36             =item Bashful
37             =item Sneezy
38             =item Grumpy
39             =item Keyser Soze
40              
41             List items have one implicit level of nesting:
42              
43             Lists may be multi-level, with items at each level specified using the
44             C<=item1>, C<=item2>, C<=item3>, etc. blocks. Note that C<=item> is just
45             an abbreviation for C<=item1>. For example:
46              
47             =item1 Animal
48             =item2 Vertebrate
49             =item2 Invertebrate
50              
51             =item1 Phase
52             =item2 Solid
53             =item2 Liquid
54             =item2 Gas
55             =item2 Chocolate
56              
57             Note that item blocks within the same list are not physically nested.
58             That is, lower-level items should I be specified inside
59             higher-level items:
60              
61             =comment WRONG...
62             =begin item1 --------------
63             The choices are: |
64             =item2 Liberty ==< Level 2 |==< Level 1
65             =item2 Death ==< Level 2 |
66             =item2 Beer ==< Level 2 |
67             =end item1 --------------
68              
69             =comment CORRECT...
70             =begin item1 ---------------
71             The choices are: |==< Level 1
72             =end item1 ---------------
73             =item2 Liberty ==================< Level 2
74             =item2 Death ==================< Level 2
75             =item2 Beer ==================< Level 2
76              
77             =head2 Ordered lists
78              
79             An item is part of an ordered list if the item has a C<:numbered>
80             configuration option:
81              
82             =for item1 :numbered
83             Visito
84            
85             =for item2 :numbered
86             Veni
87            
88             =for item2 :numbered
89             Vidi
90            
91             =for item2 :numbered
92             Vici
93              
94             Alternatively, if the first word of the item consists of a single C<#>
95             character, the item is treated as having a C<:numbered> option:
96              
97             =item1 # Visito
98             =item2 # Veni
99             =item2 # Vidi
100             =item2 # Vici
101              
102              
103             To specify an I list item that starts with a literal C<#>, either
104             make the octothorpe verbatim:
105              
106              
107             =item V<#> introduces a comment
108              
109             or explicitly mark the item itself as being unnumbered:
110              
111             =for item :!numbered
112             # introduces a comment
113              
114             =head2 Unordered lists
115              
116             List items that are not C<:numbered> are treated as defining unordered
117             lists. Typically, such lists are rendered with bullets. For example:
118              
119             =item1 Reading
120             =item2 Writing
121             =item3 'Rithmetic
122              
123             =head2 Multi-paragraph list items
124              
125             Use the delimited form of the C<=item> block to specify items that
126             contain multiple paragraphs. For example:
127              
128             Let's consider two common proverbs:
129            
130             =begin item :numbered
131             I
132            
133             This is a common myth and an unconscionable slur on the Spanish
134             people, the majority of whom are extremely attractive.
135             =end item
136            
137             =begin item :numbered
138             I
139            
140             In deciding whether to become an early riser, it is worth
141             considering whether you would actually enjoy annelids
142             for breakfast.
143             =end item
144              
145             As you can see, folk wisdom is often of dubious value.
146              
147             =head2 Definition lists
148              
149             =defn MAD
150             Affected with a high degree of intellectual independence.
151              
152             =defn MEEKNESS
153             Uncommon patience in planning a revenge that is worth while.
154              
155             =defn
156             MORAL
157             Conforming to a local and mutable standard of right.
158             Having the quality of general expediency.
159              
160             =head1 METHODS
161              
162             =cut
163              
164 3     3   15 use strict;
  3         5  
  3         76  
165 3     3   14 use warnings;
  3         6  
  3         66  
166 3     3   14 use Data::Dumper;
  3         6  
  3         130  
167 3     3   13 use Perl6::Pod::Block;
  3         5  
  3         74  
168 3     3   15 use base 'Perl6::Pod::Block';
  3         4  
  3         191  
169 3     3   16 use Perl6::Pod::Utl;
  3         5  
  3         4449  
170             our $VERSION = '0.01';
171              
172             sub new {
173 0     0 0   my $class = shift;
174 0           my $self = $class->SUPER::new(@_);
175              
176             #check if item numbered
177             # my $content = $self->{content}->[0];
178 0 0         if ( $self->{content}->[0] =~ s/^(\s*\#\s*)// ) {
179              
180             #set numbered attr
181             #TODO $self->set_attr;
182 0           push @{ $self->{attr} },
  0            
183             {
184             '' => ':numbered',
185             'name' => 'numbered',
186             'type' => 'bool',
187             'items' => 1
188             };
189             }
190              
191             # for definition get TERM
192             #The first non-blank line of content is treated as a term being defined,
193             #and the remaining content is treated as the definition for the term
194 0 0         if ( $self->item_type eq 'definition' ) {
195 0           my $first_para = $self->{'content'}->[0];
196 0 0         if ( $first_para =~ s/^\s*(.*)[\r\n]// ) {
197 0           $self->{term} = $1;
198             }
199 0           $self->{'content'}->[0] = $first_para;
200             }
201 0           return $self;
202             }
203              
204             sub item_type {
205 0     0 0   my $self = shift;
206              
207             #determine item type
208 0           my $pod_attr = $self->get_attr;
209              
210             #for defn block name
211 0 0         return 'definition'
212             if $self->name eq 'defn';
213              
214 0           my $type = 'unordered';
215 0 0         if ( $self->is_numbered ) {
216 0           $type = 'ordered';
217             }
218 0           $type;
219             }
220              
221             sub is_numbered {
222 0     0 0   my $self = shift;
223 0           my $pod_attr = $self->get_attr;
224 0   0       return $pod_attr->{numbered} || 0;
225             }
226              
227             sub item_level {
228 0     0 0   my $self = shift;
229 0 0         $self->{level} || 1; #default 1 level for items
230             }
231              
232             =head2 to_xhtml
233              
234             =over 1
235              
236             =item Unordered lists
237              
238             =item Milk
239             =item Toilet Paper
240             =item Cereal
241             =item Bread
242              
243             #
    - unordered list; bullets
244            
245            
  • Milk
  • 246            
  • Toilet Paper
  • 247            
  • Cereal
  • 248            
  • Bread
  • 249            
    250              
    251             =item Ordered
    252            
    253             =for item :numbered
    254             Find a Job
    255             =item # Get Money
    256             =item # Move Out
    257              
    258             #
      - ordered list; numbers (
        for :continued)
    259            
    260            
  • Find a Job
  • 261            
  • Get Money
  • 262            
  • Move Out
  • 263            
    264              
    265             =item definition list; dictionary
    266              
    267             =defn Fromage
    268             French word for cheese.
    269             =defn Voiture
    270             French word for car.
    271              
    272             *
    - defines the start of the list
    273             *
    - definition term
    274             *
    - defining definition
    275              
    276            
    277            
    Fromage
    278            
    French word for cheese.
    279            
    Voiture
    280            
    French word for car.
    281            
    282              
    283             L
    284              
    285             =back
    286            
    287             =cut
    288              
    289             sub get_item_sign {
    290 0     0 0   my $self = shift;
    291 0           my $el = shift;
    292 0           my $name = $el->name;
    293 0 0         return $name unless $name eq 'item';
    294 0           my $sign = join '_'=> $name, $el->item_level, $self->item_type;
    295 0           return $sign
    296             }
    297              
    298             sub to_xhtml {
    299 0     0 1   my ( $self, $to, $prev, $next ) = @_;
    300 0           my $w = $to->w;
    301              
    302              
    303             my ( $list_name, $items_name ) = @{
    304 0           {
    305             ordered => [ 'ol', 'li' ],
    306             unordered => [ 'ul', 'li' ],
    307             definition => [ 'dl', 'dd' ]
    308 0           }->{ $self->item_type }
    309             };
    310 0 0 0       if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) {
    311             #nesting first (only 2> )
    312 0 0         unless (exists $self->get_attr->{nested}) {
    313 0           my $tonest = $self->item_level - 1 ;
    314 0 0         $w->start_nesting( $tonest ) if $tonest;
    315             }
    316              
    317 0           $w->raw("<$list_name>");
    318             }
    319 0 0         if ( $self->item_type eq 'definition' ) {
    320 0           $w->raw('
    ');
    321 0           $to->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) );
    322 0           $w->raw('')
    323              
    324             }
    325              
    326             #parse first para
    327             $self->{content}->[0] =
    328 0           Perl6::Pod::Utl::parse_para( $self->{content}->[0] );
    329 0           $w->raw("<$items_name>");
    330 0           $to->visit_childs($self);
    331 0           $w->raw("");
    332 0 0 0       if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) {
    333 0           $w->raw("");
    334 0 0         unless (exists $self->get_attr->{nested}) {
    335 0           my $tonest = $self->item_level - 1 ;
    336 0 0         $w->stop_nesting( $tonest ) if $tonest;
    337             }
    338              
    339             }
    340              
    341              
    342             }
    343              
    344             sub to_docbook {
    345              
    346             #setup first number for ordered lists
    347             # 'continuation' docbook attribute
    348             # http://www.docbook.org/tdg/en/html/orderedlist.html
    349             # if ( exists $attr->{number_value} ) {
    350             # unless ( exists $rattr->{number_start} ) {
    351             # $rattr->{number_start} = $attr->{number_value};
    352             # }
    353             # }
    354 0     0 0   my ( $self, $to, $prev, $next ) = @_;
    355 0           my $w = $to->w;
    356              
    357             my ( $list_name, $items_name ) = @{
    358 0           {
    359             ordered => [ 'orderedlist', 'listitem' ],
    360             unordered => [ 'itemizedlist', 'listitem' ],
    361             definition => [ 'variablelist', 'listitem' ]
    362 0           }->{ $self->item_type }
    363             };
    364 0 0 0       if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) {
    365             #nesting first (only 2> )
    366 0 0         unless (exists $self->get_attr->{nested}) {
    367 0           my $tonest = $self->item_level - 1 ;
    368 0 0         $w->start_nesting( $tonest ) if $tonest;
    369             }
    370              
    371 0           $w->raw("<$list_name>");
    372             }
    373              
    374            
    375              
    376 0 0         if ( $self->item_type eq 'definition' ) {
    377 0           $w->raw('');
    378 0           $to->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) );
    379 0           $w->raw('')
    380              
    381             }
    382              
    383             #parse first para
    384             $self->{content}->[0] =
    385 0           Perl6::Pod::Utl::parse_para( $self->{content}->[0] );
    386 0 0 0       if ( ( $self->item_type eq 'unordered' )
    387             &&
    388             ( $self->item_level > 1 )
    389             ) {
    390             #marker
    391             #get list from http://www.sagehill.net/docbookxsl/Itemizedlists.html
    392 0           my @markers = qw/bullet opencircle box /;
    393 0           my $marker = $markers[ ($self->item_level - 1) % 3 ];
    394 0           $w->raw("<$items_name mark='$marker'>");
    395             } else {
    396 0           $w->raw("<$items_name>");
    397             }
    398 0           $to->visit_childs($self);
    399 0           $w->raw("");
    400              
    401 0 0 0       if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) {
    402 0           $w->raw("");
    403 0 0         unless (exists $self->get_attr->{nested}) {
    404 0           my $tonest = $self->item_level - 1 ;
    405 0 0         $w->stop_nesting( $tonest ) if $tonest;
    406             }
    407              
    408             }
    409              
    410             }
    411              
    412             sub to_latex {
    413 0     0 0   my ( $self, $to, $prev, $next ) = @_;
    414 0           my $w = $to->w;
    415              
    416             my ( $list_name, $items_name ) = @{
    417 0           {
    418             ordered => [ 'enumerate', 'item' ],
    419             unordered => [ 'itemize', 'item' ],
    420             definition => [ 'description', 'item' ]
    421 0           }->{ $self->item_type }
    422             };
    423 0 0 0       if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) {
    424             #nesting first (only 2> )
    425 0 0         unless (exists $self->get_attr->{nested}) {
    426 0           my $tonest = $self->item_level - 1 ;
    427 0 0         $w->start_nesting( $tonest ) if $tonest;
    428             }
    429              
    430 0           $w->say('\begin{' . $list_name . '}');
    431             }
    432              
    433 0           $w->raw('\item');
    434              
    435 0 0         if ( $self->item_type eq 'definition' ) {
    436 0           $w->raw('[');
    437 0           $self->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) );
    438 0           $w->raw(']')
    439              
    440             }
    441 0           $w->raw(' ');#space
    442              
    443             #parse first para
    444             $self->{content}->[0] =
    445 0           Perl6::Pod::Utl::parse_para( $self->{content}->[0] );
    446 0           $to->visit_childs($self);
    447 0 0         if ( $self->get_attr->{pause} ) {
    448 0           $w->say('\pause');
    449             }
    450              
    451 0 0 0       if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) {
    452 0           $w->say('\end{' . $list_name . '}');
    453 0 0         unless (exists $self->get_attr->{nested}) {
    454 0           my $tonest = $self->item_level - 1 ;
    455 0 0         $w->stop_nesting( $tonest ) if $tonest;
    456             }
    457              
    458             }
    459             }
    460              
    461             1;
    462             __END__