# 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::Document::Txt; use MarkdownBook::Document::HTML; package MarkdownBook::Book; sub new { my ($class, $format, $dir) = @_; my $self; my $control_fh; $class = ref($class) || $class; $self = {}; bless($self, $class); if ($format eq 'html') { $self->{'format'} = 'html'; $self->{'format_mod'} = 'HTML'; } elsif ($format eq 'txt') { $self->{'format'} = 'txt'; $self->{'format_mod'} = 'Txt'; } $self->{'dir'} = $dir; $self->{'docs'} = []; $self->{'sections'} = []; $self->{'sections_by_id'} = {}; open($control_fh, '<', $dir . '/control'); while (<$control_fh>) { chomp($_); if (m/^Title: /) { s/^Title: (.*)$/$1/; $self->{'title'} = $_; } } close($control_fh); $self->create_documents(); return $self; } sub dir { my ($self, $dir) = @_; my $old = $self->{'dir'}; $self->{'dir'} = $dir if defined($dir); return $old; } sub title { my ($self, $title) = @_; my $old = $self->{'title'}; $self->{'title'} = $title if defined($title); return $old; } sub documents { my ($self, $documents) = @_; my $old = $self->{'docs'}; $self->{'docs'} = $documents if defined($documents); return $old; } sub get_document_module { my ($self) = @_; return 'MarkdownBook::Document::' . $self->{'format_mod'}; } sub create_documents { my ($self) = @_; my $series_fh; my $file; my $title; my $i; my $doc; my $doc_prev; my @letters; $i = 0; $doc = $self->get_document_module()->new($self, 'index', 'index', undef, $self->{'title'}); $doc_prev = $doc; push(@{$self->{'docs'}}, $doc); open($series_fh, '<', $self->{'dir'} . '/chapters'); while (<$series_fh>) { chomp($_); ($file, $title) = split(/[ \t]+/, $_, 2); $doc = $self->get_document_module()->new($self, 'chapter', $file, ++$i, $title); $doc->prev($doc_prev); $doc_prev->next($doc) if defined $doc_prev; $doc_prev = $doc; push(@{$self->{'docs'}}, $doc); } close($series_fh); $i = -1; @letters = ('A' .. 'Z'); if (-e $self->{'dir'} . '/appendices') { open($series_fh, '<', $self->{'dir'} . '/apendices'); while (<$series_fh>) { chomp($_); ($file, $title) = split(/[ \t]+/, $_, 2); $doc = $self->get_document_module()->new($self, 'appendix', $file, $letters[++$i], $title); $doc->prev($doc_prev); $doc_prev->next($doc) if defined $doc_prev; $doc_prev = $doc; push(@{$self->{'docs'}}, $doc); } close($series_fh); } } sub add_section { my ($self, $section) = @_; push(@{$self->{'sections'}}, $section); $self->{'sections_by_id'}->{$section->id()} = $section; } sub subst_macros { my ($self, $text) = @_; $text =~ s/ \$ # Dollar sign \[ # Left square bracket ([^\]]+) # Macro \] # Right square bracket ( \[ # Left square bracket ([^\]]+) # Macro parameters \] # Right square bracket ) /$self->_do_subst_macro($1, split(m@[ \t]+@, $3))/exg; $text =~ s/ \$ # Dollar sign \[ # Left square bracket ([^\]]+) # Macro \] # Right square bracket /$self->_do_subst_macro($1)/exg; return $text; } sub _do_subst_macro { my ($self, $macro, @params) = @_; if ($macro eq 'toc') { return $self->_do_gen_toc(); } elsif ($macro eq 'sectlink') { } else { die("Unrecognized macro \"$macro\""); } } sub _do_gen_toc { my ($self) = @_; my $section; my $toc = ''; # TODO: Add chapters and appendices as well. foreach $section (@{$self->{'sections'}}) { $toc .= "\n" if $toc ne ''; $toc .= ' ' x $section->level(); $toc .= '* '; $toc .= $section->number(); $toc .= ' '; $toc .= $section->title(); } return $toc; } sub parse { my ($self) = @_; my $doc; foreach $doc (@{$self->{'docs'}}) { $doc->parse(); } } sub output { my ($self) = @_; my $doc; foreach $doc (@{$self->{'docs'}}) { $doc->output(); } } sub list_documents { my ($self) = @_; my $doc; foreach $doc (@{$self->{'docs'}}) { printf("Document:\n File: %s\n Title: %s\n Full Title: %s\n", $doc->file(), $doc->title(), $doc->full_title()); printf(" Prev: %s\n", $doc->prev()->file()) if defined $doc->prev(); printf(" Next: %s\n", $doc->next()->file()) if defined $doc->next(); } } 1;