home *** CD-ROM | disk | FTP | other *** search
/ isnet Internet / Isnet Internet CD.iso / prog / hiz / 09 / 09.exe / adynware.exe / perl / lib / site / HTML / Formatter.pm < prev    next >
Encoding:
Perl POD Document  |  1999-12-28  |  8.4 KB  |  525 lines

  1. package HTML::Formatter;
  2.  
  3.  
  4. =head1 NAME
  5.  
  6. HTML::Formatter - Base class for HTML formatters
  7.  
  8. =head1 SYNOPSIS
  9.  
  10.  package HTML::FormatXX;
  11.  require HTML::Formatter;
  12.  @ISA=qw(HTML::Formatter);
  13.  
  14. =head1 DESCRIPTION
  15.  
  16. HTML formatters are able to format a HTML syntax tree into various
  17. printable formats.  Different formatters produce output for different
  18. output media.  Common for all formatters are that they will return the
  19. formatted output when the format() method is called.  Format() takes a
  20. HTML::Element as parameter.
  21.  
  22. =head1 SEE ALSO
  23.  
  24. L<HTML::FormatText>, L<HTML::FormatPS>, L<HTML::Element>
  25.  
  26. =head1 COPYRIGHT
  27.  
  28. Copyright (c) 1995 Gisle Aas. All rights reserved.
  29.  
  30. This library is free software; you can redistribute it and/or
  31. modify it under the same terms as Perl itself.
  32.  
  33. =head1 AUTHOR
  34.  
  35. Gisle Aas <aas@oslonett.no>
  36.  
  37. =cut
  38.  
  39.  
  40. require HTML::Element;
  41.  
  42. use strict;
  43. use Carp;
  44.  
  45. sub new
  46. {
  47.     my $class = shift;
  48.     bless { }, $class;
  49. }
  50.  
  51. sub format
  52. {
  53.     my($self, $html) = @_;
  54.     $self->begin();
  55.     $html->traverse(
  56.     sub {
  57.         my($node, $start, $depth) = @_;
  58.         if (ref $node) {
  59.         my $tag = $node->tag;
  60.         my $func = $tag . '_' . ($start ? "start" : "end");
  61.         my $retval = eval { $self->$func($node); };
  62.         return $@ ? 1 : $retval;
  63.         } else {
  64.         $self->textflow($node);
  65.         }
  66.         1;
  67.     }
  68.      );
  69.     $self->end();
  70.     join('', @{$self->{output}});
  71. }
  72.  
  73. sub begin
  74. {
  75.     my $self = shift;
  76.  
  77.     $self->{anchor}    = 0;
  78.     $self->{underline} = 0;
  79.     $self->{bold}      = 0;
  80.     $self->{italic}    = 0;
  81.     $self->{center}    = 0;
  82.     $self->{nobr}      = 0;
  83.  
  84.     $self->{font_size}     = [3];   # last element is current size
  85.     $self->{basefont_size} = [3];
  86.  
  87.     $self->{makers} = [];           # last element is current marker
  88.     $self->{vspace} = undef;        # vertical space
  89.     $self->{eat_leading_space} = 0;
  90.  
  91.     $self->{output} = [];
  92. }
  93.  
  94. sub end
  95. {
  96. }
  97.  
  98. sub html_start { 1; }  sub html_end {}
  99. sub head_start { 0; }
  100. sub body_start { 1; }  sub body_end {}
  101.  
  102. sub header_start
  103. {
  104.     my($self, $level, $node) = @_;
  105.     my $align = $node->attr('align');
  106.     if (defined($align) && lc($align) eq 'center') {
  107.     $self->{center}++;
  108.     }
  109.     1,
  110. }
  111.  
  112. sub header_end
  113. {
  114.     my($self, $level, $node) = @_;
  115.     my $align = $node->attr('align');
  116.     if (defined($align) && lc($align) eq 'center') {
  117.     $self->{center}--;
  118.     }
  119. }
  120.  
  121. sub h1_start { shift->header_start(1, @_) }
  122. sub h2_start { shift->header_start(2, @_) }
  123. sub h3_start { shift->header_start(3, @_) }
  124. sub h4_start { shift->header_start(4, @_) }
  125. sub h5_start { shift->header_start(5, @_) }
  126. sub h6_start { shift->header_start(6, @_) }
  127.  
  128. sub h1_end   { shift->header_end(1, @_) }
  129. sub h2_end   { shift->header_end(2, @_) }
  130. sub h3_end   { shift->header_end(3, @_) }
  131. sub h4_end   { shift->header_end(4, @_) }
  132. sub h5_end   { shift->header_end(5, @_) }
  133. sub h6_end   { shift->header_end(6, @_) }
  134.  
  135. sub br_start
  136. {
  137.     my $self = shift;
  138.     $self->vspace(0);
  139.     $self->eat_leading_space;
  140.  
  141. }
  142.  
  143. sub hr_start
  144. {
  145.     my $self = shift;
  146.     $self->vspace(1);
  147.     $self->eat_leading_space;
  148. }
  149.  
  150. sub img_start
  151. {
  152.     shift->out(shift->attr('alt') || "[IMAGE]");
  153. }
  154.  
  155. sub a_start
  156. {
  157.     shift->{anchor}++;
  158.     1;
  159. }
  160.  
  161. sub a_end
  162. {
  163.     shift->{anchor}--;
  164. }
  165.  
  166. sub u_start
  167. {
  168.     shift->{underline}++;
  169.     1;
  170. }
  171.  
  172. sub u_end
  173. {
  174.     shift->{underline}--;
  175. }
  176.  
  177. sub b_start
  178. {
  179.     shift->{bold}++;
  180.     1;
  181. }
  182.  
  183. sub b_end
  184. {
  185.     shift->{bold}--;
  186. }
  187.  
  188. sub tt_start
  189. {
  190.     shift->{teletype}++;
  191.     1;
  192. }
  193.  
  194. sub tt_end
  195. {
  196.     shift->{teletype}--;
  197. }
  198.  
  199. sub i_start
  200. {
  201.     shift->{italic}++;
  202.     1;
  203. }
  204.  
  205. sub i_end
  206. {
  207.     shift->{italic}--;
  208. }
  209.  
  210. sub center_start
  211. {
  212.     shift->{center}++;
  213.     1;
  214. }
  215.  
  216. sub center_end
  217. {
  218.     shift->{center}--;
  219. }
  220.  
  221. sub nobr_start
  222. {
  223.     shift->{nobr}++;
  224.     1;
  225. }
  226.  
  227. sub nobr_end
  228. {
  229.     shift->{nobr}--;
  230. }
  231.  
  232. sub wbr_start
  233. {
  234.     1;
  235. }
  236.  
  237. sub font_start
  238. {
  239.     my($self, $elem) = @_;
  240.     my $size = $elem->attr('size');
  241.     return 1 unless defined $size;
  242.     if ($size =~ /^\s*[+\-]/) {
  243.     my $base = $self->{basefont_size}[-1];
  244.     $size = $base + $size;
  245.     }
  246.     push(@{$self->{font_size}}, $size);
  247.     1;
  248. }
  249.  
  250. sub font_end
  251. {
  252.     my($self, $elem) = @_;
  253.     my $size = $elem->attr('size');
  254.     return unless defined $size;
  255.     pop(@{$self->{font_size}});
  256. }
  257.  
  258. sub basefont_start
  259. {
  260.     my($self, $elem) = @_;
  261.     my $size = $elem->attr('size');
  262.     return unless defined $size;
  263.     push(@{$self->{basefont_size}}, $size);
  264.     1;
  265. }
  266.  
  267. sub basefont_end
  268. {
  269.     my($self, $elem) = @_;
  270.     my $size = $elem->attr('size');
  271.     return unless defined $size;
  272.     pop(@{$self->{basefont_size}});
  273. }
  274.  
  275. BEGIN {
  276.     *cite_start   = \&i_start;
  277.     *cite_end     = \&i_end;
  278.     *code_start   = \&tt_start;
  279.     *code_end     = \&tt_end;
  280.     *em_start     = \&i_start;
  281.     *em_end       = \&i_end;
  282.     *kbd_start    = \&tt_start;
  283.     *kbd_end      = \&tt_end;
  284.     *samp_start   = \&tt_start;
  285.     *samp_end     = \&tt_end;
  286.     *strong_start = \&b_start;
  287.     *strong_end   = \&b_end;
  288.     *var_start    = \&tt_start;
  289.     *var_end      = \&tt_end;
  290. }
  291.  
  292. sub p_start
  293. {
  294.     my $self = shift;
  295.     $self->vspace(1);
  296.     $self->eat_leading_space;
  297.     1;
  298. }
  299.  
  300. sub p_end
  301. {
  302.     shift->vspace(1);
  303. }
  304.  
  305. sub pre_start
  306. {
  307.     my $self = shift;
  308.     $self->{pre}++;
  309.     $self->vspace(1);
  310.     1;
  311. }
  312.  
  313. sub pre_end
  314. {
  315.     my $self = shift;
  316.     $self->{pre}--;
  317.     $self->vspace(1);
  318. }
  319.  
  320. BEGIN {
  321.     *listing_start = \&pre_start;
  322.     *listing_end   = \&pre_end;
  323.     *xmp_start     = \&pre_start;
  324.     *xmp_end       = \&pre_end;
  325. }
  326.  
  327. sub blockquote_start
  328. {
  329.     my $self = shift;
  330.     $self->vspace(1);
  331.     $self->eat_leading_space;
  332.     $self->adjust_lm( +2 );
  333.     $self->adjust_rm( -2 );
  334.     1;
  335. }
  336.  
  337. sub blockquote_end
  338. {
  339.     my $self = shift;
  340.     $self->vspace(1);
  341.     $self->adjust_lm( -2 );
  342.     $self->adjust_rm( +2 );
  343. }
  344.  
  345. sub address_start
  346. {
  347.     my $self = shift;
  348.     $self->vspace(1);
  349.     $self->eat_leading_space;
  350.     $self->i_start(@_);
  351.     1;
  352. }
  353.  
  354. sub address_end
  355. {
  356.     my $self = shift;
  357.     $self->i_end(@_);
  358.     $self->vspace(1);
  359. }
  360.  
  361.  
  362. sub ul_start
  363. {
  364.     my $self = shift;
  365.     $self->vspace(1);
  366.     push(@{$self->{markers}}, "*");
  367.     $self->adjust_lm( +2 );
  368.     1;
  369. }
  370.  
  371. sub ul_end
  372. {
  373.     my $self = shift;
  374.     pop(@{$self->{markers}});
  375.     $self->adjust_lm( -2 );
  376.     $self->vspace(1);
  377. }
  378.  
  379. sub li_start
  380. {
  381.     my $self = shift;
  382.     $self->bullet($self->{markers}[-1]);
  383.     $self->adjust_lm(+2);
  384.     $self->eat_leading_space;
  385.     1;
  386. }
  387.  
  388. sub bullet
  389. {
  390.     shift->out(@_);
  391. }
  392.  
  393. sub li_end
  394. {
  395.     my $self = shift;
  396.     $self->vspace(1);
  397.     $self->adjust_lm( -2);
  398.     my $markers = $self->{markers};
  399.     if ($markers->[-1] =~ /^\d+/) {
  400.     $markers->[-1]++;
  401.     }
  402. }
  403.  
  404. BEGIN {
  405.     *menu_start = \&ul_start;
  406.     *menu_end   = \&ul_end;
  407.     *dir_start  = \&ul_start;
  408.     *dir_end    = \&ul_end;
  409. }
  410.  
  411. sub ol_start
  412. {
  413.     my $self = shift;
  414.  
  415.     $self->vspace(1);
  416.     push(@{$self->{markers}}, 1);
  417.     $self->adjust_lm(+2);
  418.     1;
  419. }
  420.  
  421. sub ol_end
  422. {
  423.     my $self = shift;
  424.     $self->adjust_lm(-2);
  425.     pop(@{$self->{markers}});
  426.     $self->vspace(1);
  427. }
  428.  
  429.  
  430. sub dl_start
  431. {
  432.     my $self = shift;
  433.     $self->adjust_lm(+2);
  434.     $self->vspace(1);
  435.     1;
  436. }
  437.  
  438. sub dl_end
  439. {
  440.     my $self = shift;
  441.     $self->adjust_lm(-2);
  442.     $self->vspace(1);
  443. }
  444.  
  445. sub dt_start
  446. {
  447.     my $self = shift;
  448.     $self->vspace(1);
  449.     $self->eat_leading_space;
  450.     1;
  451. }
  452.  
  453. sub dt_end
  454. {
  455. }
  456.  
  457. sub dd_start
  458. {
  459.     my $self = shift;
  460.     $self->adjust_lm(+6);
  461.     $self->vspace(0);
  462.     $self->eat_leading_space;
  463.     1;
  464. }
  465.  
  466. sub dd_end
  467. {
  468.     shift->adjust_lm(-6);
  469. }
  470.  
  471.  
  472. sub table_start { shift->out('[TABLE NOT SHOWN]'); 0; }
  473. sub form_start  { shift->out('[FORM NOT SHOWN]');  0; }
  474.  
  475.  
  476.  
  477. sub textflow
  478. {
  479.     my $self = shift;
  480.     if ($self->{pre}) {
  481.     $self->pre_out($_[0]);
  482.     } else {
  483.     for (split(/(\s+)/, $_[0])) {
  484.         next unless length $_;
  485.         if ($self->{eat_leading_space}) {
  486.         $self->{eat_leading_space} = 0;
  487.         next if /^\s/;
  488.         }
  489.         $self->out($_);
  490.     }
  491.     }
  492. }
  493.  
  494.  
  495.  
  496. sub eat_leading_space
  497. {
  498.     shift->{eat_leading_space} = 1;
  499. }
  500.  
  501.  
  502. sub vspace
  503. {
  504.     my($self, $new) = @_;
  505.     return if defined $self->{vspace} and $self->{vspace} > $new;
  506.     $self->{vspace} = $new;
  507. }
  508.  
  509. sub collect
  510. {
  511.     push(@{shift->{output}}, @_);
  512. }
  513.  
  514. sub out
  515. {
  516.     confess "Must be overridden my subclass";
  517. }
  518.  
  519. sub pre_out
  520. {
  521.     confess "Must be overridden my subclass";
  522. }
  523.  
  524. 1;
  525.