#=============================================================================== # # DESCRIPTION: ordered and unordered lists # # AUTHOR: Aliaksandr P. Zahatski, #=============================================================================== #$Id$ package Perl6::Pod::Block::item; =pod =head1 NAME Perl6::Pod::Block::item - lists =head1 SYNOPSIS =item Happy =item Dopey =item Sleepy =item1 Animal =item2 Vertebrate =item2 Invertebrate =head1 DESCRIPTION Lists in Pod are specified as a series of contiguous C<=item> blocks. No special "container" directives or other delimiters are required to enclose the entire list. For example: The seven suspects are: =item Happy =item Dopey =item Sleepy =item Bashful =item Sneezy =item Grumpy =item Keyser Soze List items have one implicit level of nesting: Lists may be multi-level, with items at each level specified using the C<=item1>, C<=item2>, C<=item3>, etc. blocks. Note that C<=item> is just an abbreviation for C<=item1>. For example: =item1 Animal =item2 Vertebrate =item2 Invertebrate =item1 Phase =item2 Solid =item2 Liquid =item2 Gas =item2 Chocolate Note that item blocks within the same list are not physically nested. That is, lower-level items should I be specified inside higher-level items: =comment WRONG... =begin item1 -------------- The choices are: | =item2 Liberty ==< Level 2 |==< Level 1 =item2 Death ==< Level 2 | =item2 Beer ==< Level 2 | =end item1 -------------- =comment CORRECT... =begin item1 --------------- The choices are: |==< Level 1 =end item1 --------------- =item2 Liberty ==================< Level 2 =item2 Death ==================< Level 2 =item2 Beer ==================< Level 2 =head2 Ordered lists An item is part of an ordered list if the item has a C<:numbered> configuration option: =for item1 :numbered Visito =for item2 :numbered Veni =for item2 :numbered Vidi =for item2 :numbered Vici Alternatively, if the first word of the item consists of a single C<#> character, the item is treated as having a C<:numbered> option: =item1 # Visito =item2 # Veni =item2 # Vidi =item2 # Vici To specify an I list item that starts with a literal C<#>, either make the octothorpe verbatim: =item V<#> introduces a comment or explicitly mark the item itself as being unnumbered: =for item :!numbered # introduces a comment =head2 Unordered lists List items that are not C<:numbered> are treated as defining unordered lists. Typically, such lists are rendered with bullets. For example: =item1 Reading =item2 Writing =item3 'Rithmetic =head2 Multi-paragraph list items Use the delimited form of the C<=item> block to specify items that contain multiple paragraphs. For example: Let's consider two common proverbs: =begin item :numbered I This is a common myth and an unconscionable slur on the Spanish people, the majority of whom are extremely attractive. =end item =begin item :numbered I In deciding whether to become an early riser, it is worth considering whether you would actually enjoy annelids for breakfast. =end item As you can see, folk wisdom is often of dubious value. =head2 Definition lists =defn MAD Affected with a high degree of intellectual independence. =defn MEEKNESS Uncommon patience in planning a revenge that is worth while. =defn MORAL Conforming to a local and mutable standard of right. Having the quality of general expediency. =head1 METHODS =cut use strict; use warnings; use Data::Dumper; use Perl6::Pod::Block; use base 'Perl6::Pod::Block'; use Perl6::Pod::Utl; sub new { my $class = shift; my $self = $class->SUPER::new(@_); #check if item numbered # my $content = $self->{content}->[0]; if ( $self->{content}->[0] =~ s/^(\s*\#\s*)// ) { #set numbered attr #TODO $self->set_attr; push @{ $self->{attr} }, { '' => ':numbered', 'name' => 'numbered', 'type' => 'bool', 'items' => 1 }; } # for definition get TERM #The first non-blank line of content is treated as a term being defined, #and the remaining content is treated as the definition for the term if ( $self->item_type eq 'definition' ) { my $first_para = $self->{'content'}->[0]; if ( $first_para =~ s/^\s*(.*)[\r\n]// ) { $self->{term} = $1; } $self->{'content'}->[0] = $first_para; } return $self; } sub item_type { my $self = shift; #determine item type my $pod_attr = $self->get_attr; #for defn block name return 'definition' if $self->name eq 'defn'; my $type = 'unordered'; if ( $self->is_numbered ) { $type = 'ordered'; } $type; } sub is_numbered { my $self = shift; my $pod_attr = $self->get_attr; return $pod_attr->{numbered} || 0; } sub item_level { my $self = shift; $self->{level} || 1; #default 1 level for items } =head2 to_xhtml =over 1 =item Unordered lists =item Milk =item Toilet Paper =item Cereal =item Bread #
    - unordered list; bullets
    • Milk
    • Toilet Paper
    • Cereal
    • Bread
    =item Ordered =for item :numbered Find a Job =item # Get Money =item # Move Out #
      - ordered list; numbers (
        for :continued)
        1. Find a Job
        2. Get Money
        3. Move Out
        =item definition list; dictionary =defn Fromage French word for cheese. =defn Voiture French word for car. *
        - defines the start of the list *
        - definition term *
        - defining definition
        Fromage
        French word for cheese.
        Voiture
        French word for car.
        L =back =cut sub get_item_sign { my $self = shift; my $el = shift; my $name = $el->name; return $name unless $name eq 'item'; my $sign = join '_'=> $name, $el->item_level, $self->item_type; return $sign } sub to_xhtml { my ( $self, $to, $prev, $next ) = @_; my $w = $to->w; my ( $list_name, $items_name ) = @{ { ordered => [ 'ol', 'li' ], unordered => [ 'ul', 'li' ], definition => [ 'dl', 'dd' ] }->{ $self->item_type } }; if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) { #nesting first (only 2> ) unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->start_nesting( $tonest ) if $tonest; } $w->raw("<$list_name>"); } if ( $self->item_type eq 'definition' ) { $w->raw('
        '); $to->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) ); $w->raw('
        ') } #parse first para $self->{content}->[0] = Perl6::Pod::Utl::parse_para( $self->{content}->[0] ); $w->raw("<$items_name>"); $to->visit_childs($self); $w->raw(""); if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) { $w->raw(""); unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->stop_nesting( $tonest ) if $tonest; } } } sub to_docbook { #setup first number for ordered lists # 'continuation' docbook attribute # http://www.docbook.org/tdg/en/html/orderedlist.html # if ( exists $attr->{number_value} ) { # unless ( exists $rattr->{number_start} ) { # $rattr->{number_start} = $attr->{number_value}; # } # } my ( $self, $to, $prev, $next ) = @_; my $w = $to->w; my ( $list_name, $items_name ) = @{ { ordered => [ 'orderedlist', 'listitem' ], unordered => [ 'itemizedlist', 'listitem' ], definition => [ 'variablelist', 'listitem' ] }->{ $self->item_type } }; if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) { #nesting first (only 2> ) unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->start_nesting( $tonest ) if $tonest; } $w->raw("<$list_name>"); } if ( $self->item_type eq 'definition' ) { $w->raw(''); $to->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) ); $w->raw('') } #parse first para $self->{content}->[0] = Perl6::Pod::Utl::parse_para( $self->{content}->[0] ); if ( ( $self->item_type eq 'unordered' ) && ( $self->item_level > 1 ) ) { #marker #get list from http://www.sagehill.net/docbookxsl/Itemizedlists.html my @markers = qw/bullet opencircle box /; my $marker = $markers[ ($self->item_level - 1) % 3 ]; $w->raw("<$items_name mark='$marker'>"); } else { $w->raw("<$items_name>"); } $to->visit_childs($self); $w->raw(""); if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) { $w->raw(""); unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->stop_nesting( $tonest ) if $tonest; } } } sub to_latex { my ( $self, $to, $prev, $next ) = @_; my $w = $to->w; my ( $list_name, $items_name ) = @{ { ordered => [ 'enumerate', 'item' ], unordered => [ 'itemize', 'item' ], definition => [ 'description', 'item' ] }->{ $self->item_type } }; if (!$prev || $self->get_item_sign($prev) ne $self->get_item_sign($self) ) { #nesting first (only 2> ) unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->start_nesting( $tonest ) if $tonest; } $w->say('\begin{' . $list_name . '}'); } $w->raw('\item'); if ( $self->item_type eq 'definition' ) { $w->raw('['); $self->visit( Perl6::Pod::Utl::parse_para( $self->{term} ) ); $w->raw(']') } $w->raw(' ');#space #parse first para $self->{content}->[0] = Perl6::Pod::Utl::parse_para( $self->{content}->[0] ); $to->visit_childs($self); if ( $self->get_attr->{pause} ) { $w->say('\pause'); } if (!$next || $self->get_item_sign($next) ne $self->get_item_sign($self) ) { $w->say('\end{' . $list_name . '}'); unless (exists $self->get_attr->{nested}) { my $tonest = $self->item_level - 1 ; $w->stop_nesting( $tonest ) if $tonest; } } } 1; __END__ =head1 SEE ALSO L, Perldoc Pod to HTML converter: L, Perl6::Pod::Lib =head1 AUTHOR Zahatski Aliaksandr, =head1 COPYRIGHT AND LICENSE Copyright (C) 2009-2012 by Zahatski Aliaksandr This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =cut