summaryrefslogtreecommitdiffstats
path: root/lib/MarkdownBook/Document/html.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MarkdownBook/Document/html.pm')
-rw-r--r--lib/MarkdownBook/Document/html.pm153
1 files changed, 153 insertions, 0 deletions
diff --git a/lib/MarkdownBook/Document/html.pm b/lib/MarkdownBook/Document/html.pm
new file mode 100644
index 0000000..60f22c7
--- /dev/null
+++ b/lib/MarkdownBook/Document/html.pm
@@ -0,0 +1,153 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+
+use MarkdownBook::Document;
+use MarkdownBook::HTMLTree;
+use Carp;
+use Text::Markdown;
+use HTML::TreeBuilder;
+use HTML::Template;
+
+package MarkdownBook::Document::html;
+
+our @ISA = qw(MarkdownBook::Document);
+
+sub output
+{
+ my ($self) = @_;
+ my $text;
+ my $doc;
+ my $sec;
+
+ # Substitute macros.
+ $text = $self->{'book'}->subst_macros(
+ $self->{'source_text'});
+
+ # Append link definitions.
+ $text .= "\n";
+ foreach $doc (@{$self->{'book'}->documents()}) {
+ $text .= "\n";
+ $text .= '[';
+ $text .= $doc->file();
+ $text .= ']: ';
+ $text .= $doc->file();
+ $text .= '.html';
+ foreach $sec (@{$doc->sections()}) {
+ $text .= "\n";
+ $text .= '[';
+ $text .= $sec->id();
+ $text .= ']: ';
+ $text .= $doc->file();
+ $text .= '.html#';
+ $text .= $sec->id();
+ }
+ }
+
+ # Convert to HTML.
+ $text = Text::Markdown::Markdown($text);
+
+ # Set "id" attributes of headings.
+ $self->_do_set_heading_id_attrs($text);
+
+ # Output the templated HTML.
+ $self->_do_output_template();
+
+ # Clean up.
+ $self->{'tree'}->delete();
+}
+
+sub _do_set_heading_id_attrs
+{
+ my ($self, $text) = @_;
+ my @headings;
+ my $heading;
+ my $i = -1;
+
+ # Parse HTML.
+ $self->{'tree'} = HTML::TreeBuilder->new();
+ $self->{'tree'}->parse($text);
+ $self->{'tree'}->eof($text);
+
+ # Find the "body" element.
+ @{$self->{'tree_body'}} = MarkdownBook::HTMLTree::find_elements_by_tag_names(
+ $self->{'tree'}, ('body'));
+
+ # Don't modify headings of index documents.
+ return if $self->{'type'} eq 'index';
+
+ # Find all headings.
+ @headings = MarkdownBook::HTMLTree::find_elements_by_tag_names(
+ @{$self->{'tree_body'}}[0], ('h1', 'h2'));
+
+ # Set "id" attributes.
+ foreach $heading (@headings) {
+ $heading->attr('id', ${$self->{'sections'}}[++$i]->id());
+ }
+}
+
+sub _do_output_template
+{
+ my ($self) = @_;
+
+ my $doc_tmpl;
+ my %opt_end_tags;
+ my $elem;
+ my $body;
+ my $doc_fh;
+
+ $doc_tmpl = HTML::Template->new(filename => 'include/document.tmpl');
+
+ # Don't omit any end tags.
+ %opt_end_tags = map([$_ => 0], %HTML::Element::optionalEndTag);
+
+ # Get HTML text of all children of the "body" element.
+ foreach $elem (@{$self->{'tree_body'}}[0]->content_list()) {
+ # It's safe to assume (ref($elem) eq 'HTML::Element').
+ $body .= $elem->as_HTML('<>&', '', \%opt_end_tags) . "\n";
+ }
+
+ $doc_tmpl->param(IS_INDEX => ($self->{'type'} eq 'index'));
+
+ $doc_tmpl->param(BOOK_TITLE => $self->{'book'}->title());
+ $doc_tmpl->param(TITLE => $self->{'title'});
+ $doc_tmpl->param(CHAPT_TITLE => $self->full_title());
+
+ if (defined($self->{'prev'})) {
+ $doc_tmpl->param(PREV_LINK => $self->{'prev'}->file() . '.html');
+ $doc_tmpl->param(PREV_TITLE => $self->{'prev'}->title());
+ } else {
+ $doc_tmpl->param(PREV_LINK => undef);
+ $doc_tmpl->param(PREV_TITLE => undef);
+ }
+ if (defined($self->{'next'})) {
+ $doc_tmpl->param(NEXT_LINK => $self->{'next'}->file() . '.html');
+ $doc_tmpl->param(NEXT_TITLE => $self->{'next'}->title());
+ } else {
+ $doc_tmpl->param(NEXT_LINK => undef);
+ $doc_tmpl->param(NEXT_TITLE => undef);
+ }
+
+ $doc_tmpl->param(BODY => $body);
+
+ open($doc_fh, '>', $self->file_path() . '.html')
+ or Carp::croak('Cannot open "' . $self->{'file'} . '" destination document');
+ $doc_tmpl->output(print_to => $doc_fh);
+ close($doc_fh);
+}
+
+1;