# Copyright (C) 2012 Patrick "P. J." McDermott # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . use strict; use warnings; use MarkdownBook::HTMLTree; use HTML::TreeBuilder; package MarkdownBook::Document; sub new { my ($class, $book, $file, $id, $title) = @_; my $self; $class = ref($class) || $class; $self = {}; bless($self,$class); $self->{'book'} = $book; $self->{'file'} = $file; $self->{'id'} = $id; $self->{'title'} = $title; return $self; } sub book { my ($self, $book) = @_; my $old = $self->{'book'}; $self->{'book'} = $book if defined($book); return $old; } sub file { my ($self, $file) = @_; my $old = $self->{'file'}; $self->{'file'} = $file if defined($file); return $old; } sub file_path { my ($self) = @_; return $self->{'book'}->dir() . '/' . $self->{'file'}; } sub title { my ($self, $title) = @_; my $old = $self->{'title'}; $self->{'title'} = $title if defined($title); return $old; } sub prev { my ($self, $other) = @_; my $old = $self->{'prev'}; $self->{'prev'} = $other if defined($other); return $old; } sub next { my ($self, $other) = @_; my $old = $self->{'next'}; $self->{'next'} = $other if defined($other); return $old; } sub parse_html { my ($self) = @_; my $file = $self->{'book'}->dir() . '/' . $self->{'file'} . '.html.in'; $self->{'tree'} = HTML::TreeBuilder->new(); $self->{'tree'}->parse_file($file); } sub number_sections { my ($self) = @_; my @headers; my $header; my @secnums = (0, 0); my $curlev = -1; my $newlev; my $secstr; my @children; my $sectitle; my $secid; @{$self->{'tree_body'}} = MarkdownBook::HTMLTree::find_elements_by_tag_names( $self->{'tree'}, ('body')); @headers = MarkdownBook::HTMLTree::find_elements_by_tag_names( @{$self->{'tree_body'}}[0], ('h1', 'h2')); foreach $header (@headers) { # Calculate section number. $newlev = $header->tag(); $newlev =~ s/^h(\d)$/$1/; if ($newlev != $curlev) { foreach (@secnums[$newlev .. $#secnums]) { $_ = 0; } } $curlev = $newlev; ++$secnums[$newlev - 1]; $secstr = join('.', @secnums); $secstr =~ s/(\.0)*$//; MarkdownBook::HTMLTree::each_text(sub { # Prefix section title with section number. my $sectitle = $_[1]; $sectitle =~ s/^([^\[]+)[ ]*\[[^\]]+\]$/$_[2].$secstr $1/; # Set "id" attribute. if ($_[1] =~ m/^[^\[\]]*\[([^\]]+)\][^\[\]]*$/) { my $secid = $_[1]; $secid =~ s/^[^\[\]]*\[([^\]]+)\][^\[\]]*$/$1/; ${$_[0]}->attr('id', $secid); } # Set section title. $_[1] = $sectitle; }, $header, $self->{'id'}); } } sub output { my ($self) = @_; my $elem; my %opt_end_tags; my $out; # Don't omit any end tags. %opt_end_tags = map([$_ => 0], %HTML::Element::optionalEndTag); foreach $elem (@{$self->{'tree_body'}}[0]->content_list()) { # It's safe to assume (ref($elem) eq 'HTML::Element'). $out .= $elem->as_HTML('<>&', '', \%opt_end_tags) . "\n"; } return $out; } 1;