← Index
NYTProf Performance Profile   « line view »
For /usr/local/libexec/sympa/task_manager-debug.pl
  Run on Tue Jun 1 22:32:51 2021
Reported on Tue Jun 1 22:35:13 2021

Filename/usr/local/lib/perl5/site_perl/HTML/Formatter.pm
StatementsExecuted 0 statements in 0s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
0000s0sHTML::Formatter::::BEGIN@10HTML::Formatter::BEGIN@10
0000s0sHTML::Formatter::::BEGIN@11HTML::Formatter::BEGIN@11
0000s0sHTML::Formatter::::BEGIN@6HTML::Formatter::BEGIN@6
0000s0sHTML::Formatter::::BEGIN@7HTML::Formatter::BEGIN@7
0000s0sHTML::Formatter::::BEGIN@8HTML::Formatter::BEGIN@8
0000s0sHTML::Formatter::::__ANON__[:167]HTML::Formatter::__ANON__[:167]
0000s0sHTML::Formatter::::_default_treeHTML::Formatter::_default_tree
0000s0sHTML::Formatter::::a_endHTML::Formatter::a_end
0000s0sHTML::Formatter::::a_startHTML::Formatter::a_start
0000s0sHTML::Formatter::::abbr_endHTML::Formatter::abbr_end
0000s0sHTML::Formatter::::abbr_startHTML::Formatter::abbr_start
0000s0sHTML::Formatter::::acronym_endHTML::Formatter::acronym_end
0000s0sHTML::Formatter::::acronym_startHTML::Formatter::acronym_start
0000s0sHTML::Formatter::::address_endHTML::Formatter::address_end
0000s0sHTML::Formatter::::address_startHTML::Formatter::address_start
0000s0sHTML::Formatter::::adjust_lmHTML::Formatter::adjust_lm
0000s0sHTML::Formatter::::adjust_rmHTML::Formatter::adjust_rm
0000s0sHTML::Formatter::::b_endHTML::Formatter::b_end
0000s0sHTML::Formatter::::b_startHTML::Formatter::b_start
0000s0sHTML::Formatter::::basefont_endHTML::Formatter::basefont_end
0000s0sHTML::Formatter::::basefont_startHTML::Formatter::basefont_start
0000s0sHTML::Formatter::::beginHTML::Formatter::begin
0000s0sHTML::Formatter::::big_endHTML::Formatter::big_end
0000s0sHTML::Formatter::::big_startHTML::Formatter::big_start
0000s0sHTML::Formatter::::blockquote_endHTML::Formatter::blockquote_end
0000s0sHTML::Formatter::::blockquote_startHTML::Formatter::blockquote_start
0000s0sHTML::Formatter::::body_endHTML::Formatter::body_end
0000s0sHTML::Formatter::::body_startHTML::Formatter::body_start
0000s0sHTML::Formatter::::br_startHTML::Formatter::br_start
0000s0sHTML::Formatter::::bulletHTML::Formatter::bullet
0000s0sHTML::Formatter::::center_endHTML::Formatter::center_end
0000s0sHTML::Formatter::::center_startHTML::Formatter::center_start
0000s0sHTML::Formatter::::cite_endHTML::Formatter::cite_end
0000s0sHTML::Formatter::::cite_startHTML::Formatter::cite_start
0000s0sHTML::Formatter::::code_endHTML::Formatter::code_end
0000s0sHTML::Formatter::::code_startHTML::Formatter::code_start
0000s0sHTML::Formatter::::collectHTML::Formatter::collect
0000s0sHTML::Formatter::::configureHTML::Formatter::configure
0000s0sHTML::Formatter::::dd_endHTML::Formatter::dd_end
0000s0sHTML::Formatter::::dd_startHTML::Formatter::dd_start
0000s0sHTML::Formatter::::default_valuesHTML::Formatter::default_values
0000s0sHTML::Formatter::::del_endHTML::Formatter::del_end
0000s0sHTML::Formatter::::del_startHTML::Formatter::del_start
0000s0sHTML::Formatter::::dfn_endHTML::Formatter::dfn_end
0000s0sHTML::Formatter::::dfn_startHTML::Formatter::dfn_start
0000s0sHTML::Formatter::::dir_endHTML::Formatter::dir_end
0000s0sHTML::Formatter::::dir_startHTML::Formatter::dir_start
0000s0sHTML::Formatter::::div_endHTML::Formatter::div_end
0000s0sHTML::Formatter::::div_startHTML::Formatter::div_start
0000s0sHTML::Formatter::::dl_endHTML::Formatter::dl_end
0000s0sHTML::Formatter::::dl_startHTML::Formatter::dl_start
0000s0sHTML::Formatter::::dt_endHTML::Formatter::dt_end
0000s0sHTML::Formatter::::dt_startHTML::Formatter::dt_start
0000s0sHTML::Formatter::::em_endHTML::Formatter::em_end
0000s0sHTML::Formatter::::em_startHTML::Formatter::em_start
0000s0sHTML::Formatter::::endHTML::Formatter::end
0000s0sHTML::Formatter::::font_endHTML::Formatter::font_end
0000s0sHTML::Formatter::::font_startHTML::Formatter::font_start
0000s0sHTML::Formatter::::formatHTML::Formatter::format
0000s0sHTML::Formatter::::format_fileHTML::Formatter::format_file
0000s0sHTML::Formatter::::format_from_fileHTML::Formatter::format_from_file
0000s0sHTML::Formatter::::format_from_stringHTML::Formatter::format_from_string
0000s0sHTML::Formatter::::format_stringHTML::Formatter::format_string
0000s0sHTML::Formatter::::frameset_startHTML::Formatter::frameset_start
0000s0sHTML::Formatter::::h1_endHTML::Formatter::h1_end
0000s0sHTML::Formatter::::h1_startHTML::Formatter::h1_start
0000s0sHTML::Formatter::::h2_endHTML::Formatter::h2_end
0000s0sHTML::Formatter::::h2_startHTML::Formatter::h2_start
0000s0sHTML::Formatter::::h3_endHTML::Formatter::h3_end
0000s0sHTML::Formatter::::h3_startHTML::Formatter::h3_start
0000s0sHTML::Formatter::::h4_endHTML::Formatter::h4_end
0000s0sHTML::Formatter::::h4_startHTML::Formatter::h4_start
0000s0sHTML::Formatter::::h5_endHTML::Formatter::h5_end
0000s0sHTML::Formatter::::h5_startHTML::Formatter::h5_start
0000s0sHTML::Formatter::::h6_endHTML::Formatter::h6_end
0000s0sHTML::Formatter::::h6_startHTML::Formatter::h6_start
0000s0sHTML::Formatter::::head_startHTML::Formatter::head_start
0000s0sHTML::Formatter::::header_endHTML::Formatter::header_end
0000s0sHTML::Formatter::::header_startHTML::Formatter::header_start
0000s0sHTML::Formatter::::hr_startHTML::Formatter::hr_start
0000s0sHTML::Formatter::::html_endHTML::Formatter::html_end
0000s0sHTML::Formatter::::html_startHTML::Formatter::html_start
0000s0sHTML::Formatter::::i_endHTML::Formatter::i_end
0000s0sHTML::Formatter::::i_startHTML::Formatter::i_start
0000s0sHTML::Formatter::::img_startHTML::Formatter::img_start
0000s0sHTML::Formatter::::input_startHTML::Formatter::input_start
0000s0sHTML::Formatter::::ins_endHTML::Formatter::ins_end
0000s0sHTML::Formatter::::ins_startHTML::Formatter::ins_start
0000s0sHTML::Formatter::::kbd_endHTML::Formatter::kbd_end
0000s0sHTML::Formatter::::kbd_startHTML::Formatter::kbd_start
0000s0sHTML::Formatter::::li_endHTML::Formatter::li_end
0000s0sHTML::Formatter::::li_startHTML::Formatter::li_start
0000s0sHTML::Formatter::::listing_endHTML::Formatter::listing_end
0000s0sHTML::Formatter::::listing_startHTML::Formatter::listing_start
0000s0sHTML::Formatter::::massage_treeHTML::Formatter::massage_tree
0000s0sHTML::Formatter::::menu_endHTML::Formatter::menu_end
0000s0sHTML::Formatter::::menu_startHTML::Formatter::menu_start
0000s0sHTML::Formatter::::newHTML::Formatter::new
0000s0sHTML::Formatter::::new_font_sizeHTML::Formatter::new_font_size
0000s0sHTML::Formatter::::nobr_endHTML::Formatter::nobr_end
0000s0sHTML::Formatter::::nobr_startHTML::Formatter::nobr_start
0000s0sHTML::Formatter::::ol_endHTML::Formatter::ol_end
0000s0sHTML::Formatter::::ol_startHTML::Formatter::ol_start
0000s0sHTML::Formatter::::option_startHTML::Formatter::option_start
0000s0sHTML::Formatter::::outHTML::Formatter::out
0000s0sHTML::Formatter::::p_endHTML::Formatter::p_end
0000s0sHTML::Formatter::::p_startHTML::Formatter::p_start
0000s0sHTML::Formatter::::pre_endHTML::Formatter::pre_end
0000s0sHTML::Formatter::::pre_outHTML::Formatter::pre_out
0000s0sHTML::Formatter::::pre_startHTML::Formatter::pre_start
0000s0sHTML::Formatter::::q_endHTML::Formatter::q_end
0000s0sHTML::Formatter::::q_startHTML::Formatter::q_start
0000s0sHTML::Formatter::::restore_font_sizeHTML::Formatter::restore_font_size
0000s0sHTML::Formatter::::s_endHTML::Formatter::s_end
0000s0sHTML::Formatter::::s_startHTML::Formatter::s_start
0000s0sHTML::Formatter::::samp_endHTML::Formatter::samp_end
0000s0sHTML::Formatter::::samp_startHTML::Formatter::samp_start
0000s0sHTML::Formatter::::scale_font_forHTML::Formatter::scale_font_for
0000s0sHTML::Formatter::::script_startHTML::Formatter::script_start
0000s0sHTML::Formatter::::select_startHTML::Formatter::select_start
0000s0sHTML::Formatter::::set_version_tagHTML::Formatter::set_version_tag
0000s0sHTML::Formatter::::small_endHTML::Formatter::small_end
0000s0sHTML::Formatter::::small_startHTML::Formatter::small_start
0000s0sHTML::Formatter::::span_endHTML::Formatter::span_end
0000s0sHTML::Formatter::::span_startHTML::Formatter::span_start
0000s0sHTML::Formatter::::strike_endHTML::Formatter::strike_end
0000s0sHTML::Formatter::::strike_startHTML::Formatter::strike_start
0000s0sHTML::Formatter::::strong_endHTML::Formatter::strong_end
0000s0sHTML::Formatter::::strong_startHTML::Formatter::strong_start
0000s0sHTML::Formatter::::style_startHTML::Formatter::style_start
0000s0sHTML::Formatter::::sub_endHTML::Formatter::sub_end
0000s0sHTML::Formatter::::sub_startHTML::Formatter::sub_start
0000s0sHTML::Formatter::::sup_endHTML::Formatter::sup_end
0000s0sHTML::Formatter::::sup_startHTML::Formatter::sup_start
0000s0sHTML::Formatter::::td_endHTML::Formatter::td_end
0000s0sHTML::Formatter::::td_startHTML::Formatter::td_start
0000s0sHTML::Formatter::::textarea_startHTML::Formatter::textarea_start
0000s0sHTML::Formatter::::textflowHTML::Formatter::textflow
0000s0sHTML::Formatter::::th_endHTML::Formatter::th_end
0000s0sHTML::Formatter::::th_startHTML::Formatter::th_start
0000s0sHTML::Formatter::::tt_endHTML::Formatter::tt_end
0000s0sHTML::Formatter::::tt_startHTML::Formatter::tt_start
0000s0sHTML::Formatter::::u_endHTML::Formatter::u_end
0000s0sHTML::Formatter::::u_startHTML::Formatter::u_start
0000s0sHTML::Formatter::::ul_endHTML::Formatter::ul_end
0000s0sHTML::Formatter::::ul_startHTML::Formatter::ul_start
0000s0sHTML::Formatter::::var_endHTML::Formatter::var_end
0000s0sHTML::Formatter::::var_startHTML::Formatter::var_start
0000s0sHTML::Formatter::::version_tagHTML::Formatter::version_tag
0000s0sHTML::Formatter::::vspaceHTML::Formatter::vspace
0000s0sHTML::Formatter::::wbr_startHTML::Formatter::wbr_start
0000s0sHTML::Formatter::::xmp_endHTML::Formatter::xmp_end
0000s0sHTML::Formatter::::xmp_startHTML::Formatter::xmp_start
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package HTML::Formatter;
2
3# ABSTRACT: Base class for HTML formatters
4
5
6use 5.006_001;
7use strict;
8use warnings;
9
10use Carp;
11use HTML::Element 3.15 ();
12
13# We now use Smart::Comments in place of the old DEBUG framework.
14# this should be commented out in release versions....
15##use Smart::Comments;
16
17our $VERSION = '2.12'; # VERSION
18our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY
19
20#
21# A typical formatter will not use all of the features of this
22# class. But it will use some, as best fits the mapping
23# of HTML to the particular output format.
24#
25
26# ------------------------------------------------------------------------
27
28
29sub new {
30 my ( $class, %arg ) = @_;
31
32 my $self = bless { $class->default_values }, $class;
33 $self->configure( \%arg ) if keys %arg;
34
35 return $self;
36}
37
38# ------------------------------------------------------------------------
39sub default_values {
40 ();
41}
42
43# ------------------------------------------------------------------------
44sub configure {
45 my ( $self, $arg ) = @_;
46
47 for ( keys %$arg ) {
48 warn "Unknown configure argument '$_'" if $^W;
49 }
50
51 return $self;
52}
53
54# ------------------------------------------------------------------------
55sub massage_tree {
56 my ( $self, $html ) = @_;
57
58 return if $html->tag eq 'p'; # sanity
59
60 ### Before massaging: $html->dump()
61
62 $html->simplify_pres();
63
64 # Does anything else need doing?
65 ### After massaging: $html->dump()
66
67 return;
68}
69
70# ------------------------------------------------------------------------
71
72
73sub format_from_file { return shift->format_file(@_); }
74
75sub format_file {
76 my ( $self, $filename, @params ) = @_;
77
78 $self = $self->new(@params) unless ref $self;
79
80 croak "What filename to format from?"
81 unless ( defined($filename) and length($filename) );
82
83 my $tree = $self->_default_tree();
84 $tree->parse_file($filename);
85
86 my $out = $self->format($tree);
87 $tree->delete;
88
89 return $out;
90}
91
92# ------------------------------------------------------------------------
93
94
95# ------------------------------------------------------------------------
96sub format_from_string { shift->format_string(@_) }
97
98sub format_string {
99 my ( $self, $content, @params ) = @_;
100
101 $self = $self->new(@params) unless ref $self;
102
103 croak "What string to format?" unless defined $content;
104
105 my $tree = $self->_default_tree();
106 $tree->parse($content);
107 $tree->eof();
108 undef $content;
109
110 my $out = $self->format($tree);
111 $tree->delete;
112
113 return $out;
114}
115
116# ------------------------------------------------------------------------
117sub _default_tree {
118 require HTML::TreeBuilder;
119 my $t = HTML::TreeBuilder->new;
120
121 # If nothing else works, try using these parser options:s
122 #$t->implicit_body_p_tag(1);
123 #$t->p_strict(1);
124
125 return $t;
126}
127
128# ------------------------------------------------------------------------
129
130
131sub format {
132 my ( $self, $html ) = @_;
133
134 croak "Usage: \$formatter->format(\$tree)" unless ( defined($html) and ref($html) and $html->can('tag') );
135
136 #### Tree to format: $html->dump
137
138 $self->set_version_tag($html);
139 $self->massage_tree($html);
140 $self->begin($html);
141 $html->number_lists();
142
143 # Per-iteration scratch:
144 my ( $node, $start, $depth, $tag, $func );
145 $html->traverse(
146 sub {
147 ( $node, $start, $depth ) = @_;
148 if ( ref $node ) {
149 $tag = $node->tag;
150 $func = $tag . '_' . ( $start ? "start" : "end" );
151
152 # Use ->can so that we can recover if
153 # a handler is not defined for the tag.
154 if ( $self->can($func) ) {
155 ### Calling : (' ' x $depth) . $func
156 return $self->$func($node);
157 }
158 else {
159 ### Skipping: (' ' x $depth) . $func
160 return 1;
161 }
162 }
163 else {
164 $self->textflow($node);
165 }
166 1;
167 }
168 );
169
170 $self->end($html);
171
172 return join( '', @{ $self->{output} } );
173}
174
175# ------------------------------------------------------------------------
176sub begin {
177 my $self = shift;
178
179 # Flags
180 $self->{anchor} = 0;
181 $self->{underline} = 0;
182 $self->{bold} = 0;
183 $self->{italic} = 0;
184 $self->{center} = 0;
185
186 $self->{superscript} = 0;
187 $self->{subscript} = 0;
188 $self->{strikethrough} = 0;
189
190 $self->{center_stack} = []; # push and pop 'center' states to it
191 $self->{nobr} = 0;
192
193 $self->{'font_size'} = [3]; # last element is current size
194 $self->{basefont_size} = [3];
195
196 $self->{vspace} = undef; # vertical space (dimension)
197
198 $self->{output} = [];
199}
200
201# ------------------------------------------------------------------------
202sub end { }
203
204# ------------------------------------------------------------------------
205sub set_version_tag {
206 my ( $self, $html ) = @_;
207
208 if ($html) {
209 $self->{'version_tag'} = sprintf(
210 "%s (v%s, using %s v%s%s)",
211 ref($self), $self->VERSION || '?',
212 ref($html),
213 $html->VERSION || '?',
214 $HTML::Parser::VERSION ? ", and HTML::Parser v$HTML::Parser::VERSION" : ''
215 );
216 }
217 elsif ($HTML::Parser::VERSION) {
218 $self->{'version_tag'} =
219 sprintf( "%s (v%s, using %s)", ref($self), $self->VERSION || "?", "HTML::Parser v$HTML::Parser::VERSION", );
220 }
221 else {
222 $self->{'version_tag'} = sprintf( "%s (v%s)", ref($self), $self->VERSION || '?', );
223 }
224}
225
226# ------------------------------------------------------------------------
227sub version_tag { shift->{'version_tag'} }
228
229# ------------------------------------------------------------------------
230sub html_start { 1; }
231sub html_end { }
232sub body_start { 1; }
233sub body_end { }
234sub head_start { 0; }
235sub script_start { 0; }
236sub style_start { 0; }
237sub frameset_start { 0; }
238
239# ------------------------------------------------------------------------
240sub header_start {
241 my ( $self, undef, $node ) = @_;
242
243 my $align = $node->attr('align');
244 if ( defined($align) && lc($align) eq 'center' ) {
245 $self->{center}++;
246 }
247 1;
248}
249
250# ------------------------------------------------------------------------
251sub header_end {
252 my ( $self, undef, $node ) = @_;
253
254 my $align = $node->attr('align');
255 if ( defined($align) && lc($align) eq 'center' ) {
256 $self->{center}--;
257 }
258}
259
260# ------------------------------------------------------------------------
261sub h1_start { shift->header_start( 1, @_ ) }
262sub h2_start { shift->header_start( 2, @_ ) }
263sub h3_start { shift->header_start( 3, @_ ) }
264sub h4_start { shift->header_start( 4, @_ ) }
265sub h5_start { shift->header_start( 5, @_ ) }
266sub h6_start { shift->header_start( 6, @_ ) }
267
268# ------------------------------------------------------------------------
269sub h1_end { shift->header_end( 1, @_ ) }
270sub h2_end { shift->header_end( 2, @_ ) }
271sub h3_end { shift->header_end( 3, @_ ) }
272sub h4_end { shift->header_end( 4, @_ ) }
273sub h5_end { shift->header_end( 5, @_ ) }
274sub h6_end { shift->header_end( 6, @_ ) }
275
276sub br_start { my $self = shift; $self->vspace( 0, 1 ); }
277sub hr_start { my $self = shift; $self->vspace(1); 1; }
278
279# ------------------------------------------------------------------------
280sub img_start {
281 my ( $self, $node ) = @_;
282
283 my $alt = $node->attr('alt');
284 $self->out( defined($alt) ? $alt : "[IMAGE]" );
285}
286
287# ------------------------------------------------------------------------
288sub a_start { shift->{anchor}++; 1; }
289sub a_end { shift->{anchor}--; }
290sub u_start { shift->{underline}++; 1; }
291sub u_end { shift->{underline}--; }
292sub b_start { shift->{bold}++; 1; }
293sub b_end { shift->{bold}--; }
294sub tt_start { shift->{teletype}++; 1; }
295sub tt_end { shift->{teletype}--; }
296sub i_start { shift->{italic}++; 1; }
297sub i_end { shift->{italic}--; }
298sub center_start { shift->{center}++; 1; }
299sub center_end { shift->{center}--; }
300
301# ------------------------------------------------------------------------
302sub div_start { # interesting only for its 'align' attribute
303 my ( $self, $node ) = @_;
304
305 my $align = $node->attr('align');
306 if ( defined($align) && lc($align) eq 'center' ) {
307 return $self->center_start;
308 }
309 1;
310}
311
312# ------------------------------------------------------------------------
313sub div_end {
314 my ( $self, $node ) = @_;
315
316 my $align = $node->attr('align');
317 if ( defined($align) && lc($align) eq 'center' ) {
318 return $self->center_end;
319 }
320}
321
322# ------------------------------------------------------------------------
323sub nobr_start { shift->{nobr}++; 1; }
324sub nobr_end { shift->{nobr}--; }
325sub wbr_start { 1; }
326
327# ------------------------------------------------------------------------
328sub font_start {
329 my ( $self, $elem ) = @_;
330
331 my $size = $elem->attr('size');
332 return 1 unless ( defined($size) );
333 if ( $size =~ /^\s*[+\-]/ ) {
334 my $base = $self->{basefont_size}[-1];
335
336 # yes, base it on the most recent one
337 $size = $base + $size;
338 }
339 push @{ $self->{'font_size'} }, $size;
340 $self->new_font_size($size);
341 1;
342}
343
344# ------------------------------------------------------------------------
345sub font_end {
346 my ( $self, $elem ) = @_;
347 my $size = $elem->attr('size');
348 return unless defined $size;
349 pop @{ $self->{'font_size'} };
350 $self->restore_font_size( $self->{'font_size'}[-1] );
351}
352
353# ------------------------------------------------------------------------
354sub big_start {
355 my $self = $_[0];
356 push @{ $self->{'font_size'} }, $self->{basefont_size}[-1] + 1; # same as font size="+1"
357 $self->new_font_size( $self->{'font_size'}[-1] );
358 1;
359}
360
361# ------------------------------------------------------------------------
362sub small_start {
363 my $self = $_[0];
364 push @{ $self->{'font_size'} }, $self->{basefont_size}[-1] - 1, # same as font size="-1"
365 ;
366 $self->new_font_size( $self->{'font_size'}[-1] );
367 1;
368}
369
370# ------------------------------------------------------------------------
371sub big_end {
372 my $self = $_[0];
373 pop @{ $self->{'font_size'} };
374 $self->restore_font_size( $self->{'font_size'}[-1] );
375 1;
376}
377
378# ------------------------------------------------------------------------
379sub small_end {
380 my $self = $_[0];
381 pop @{ $self->{'font_size'} };
382 $self->restore_font_size( $self->{'font_size'}[-1] );
383 1;
384}
385
386# ------------------------------------------------------------------------
387sub basefont_start {
388 my ( $self, $elem ) = @_;
389 my $size = $elem->attr('size');
390 return unless defined $size;
391 push( @{ $self->{basefont_size} }, $size );
392 1;
393}
394
395# ------------------------------------------------------------------------
396sub basefont_end {
397 my ( $self, $elem ) = @_;
398 my $size = $elem->attr('size');
399 return unless defined $size;
400 pop( @{ $self->{basefont_size} } );
401}
402
403# ------------------------------------------------------------------------
404#
405# Override in subclasses, if you like.
406#
407sub new_font_size { } #my( $self, $font_size_number ) = @_;
408sub restore_font_size { } #my( $self, $font_size_number ) = @_;
409
410# ------------------------------------------------------------------------
411sub q_start { shift->out(q<">); 1; }
412sub q_end { shift->out(q<">); 1; }
413sub sup_start { shift->{superscript}++; 1; }
414sub sup_end { shift->{superscript}--; 1; }
415sub sub_start { shift->{subscript}++; 1; }
416sub sub_end { shift->{subscript}--; 1; }
417sub strike_start { shift->{strikethrough}++; 1; }
418sub strike_end { shift->{strikethrough}--; 1; }
419sub s_start { shift->strike_start(@_); }
420sub s_end { shift->strike_end(@_); }
421sub dfn_start { 1; }
422sub dfn_end { 1; }
423sub abbr_start { 1; }
424sub abbr_end { 1; }
425sub acronym_start { 1; }
426sub acronym_end { 1; }
427sub span_start { 1; }
428sub span_end { 1; }
429sub ins_start { 1; }
430sub ins_end { 1; }
431sub del_start { 0; } # Don't render the del'd bits
432sub del_end { 0; }
433
434# ------------------------------------------------------------------------
435my @Size_magic_numbers = (
436 0.60, 0.75, 0.89, 1, 1.20, 1.50, 2.00, 3.00
437
438 # #0 #1 #2 #3 #4 #5 #6 #7
439 #________________ - | + _________________________
440 # -3 -2 -1 0 +1 +2 +3 +4
441);
442
443# ------------------------------------------------------------------------
444sub scale_font_for {
445 my ( $self, $reference_size ) = @_;
446
447 # Mozilla's source, at
448 # http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsStyleUtil.cpp#299
449 # says:
450 # static PRInt32 sFontSizeFactors[8] = { 60,75,89,100,120,150,200,300 };
451 #
452 # For comparison, Gisle's earlier HTML::FormatPS has:
453 # | # size 0 1 2 3 4 5 6 7
454 # | @FontSizes = ( 5, 6, 8, 10, 12, 14, 18, 24, 32);
455 # ...and gets different sizing via just a scaling factor.
456
457 my $size_number = int( defined( $_[2] ) ? $_[2] : $self->{'font_size'}[-1] );
458
459 # force the size_number into range:
460 $size_number =
461 ( $size_number < 0 ) ? 0
462 : ( $size_number > $#Size_magic_numbers ) ? $#Size_magic_numbers
463 : int($size_number);
464
465 my $result = int( .5 + $reference_size * $Size_magic_numbers[$size_number] );
466
467 ### Scale Font: sprintf("reference %s, size %s => %s", $reference_size, $size_number, $result);
468
469 return $result;
470}
471
472# ------------------------------------------------------------------------
473# Aliases for logical markup:
474sub strong_start { shift->b_start(@_) }
475sub strong_end { shift->b_end(@_) }
476sub cite_start { shift->i_start(@_) }
477sub cite_end { shift->i_end(@_) }
478sub em_start { shift->i_start(@_) }
479sub em_end { shift->i_end(@_) }
480sub code_start { shift->tt_start(@_) }
481sub code_end { shift->tt_end(@_) }
482sub kbd_start { shift->tt_start(@_) }
483sub kbd_end { shift->tt_end(@_) }
484sub samp_start { shift->tt_start(@_) }
485sub samp_end { shift->tt_end(@_) }
486sub var_start { shift->tt_start(@_) }
487sub var_end { shift->tt_end(@_) }
488
489# ------------------------------------------------------------------------
490sub p_start {
491 my $self = shift;
492
493 #$self->adjust_lm(0); # assert new paragraph
494 $self->vspace(1);
495
496 # assert one line's worth of vertical space at para-start
497 $self->out('');
498 1;
499}
500
501# ------------------------------------------------------------------------
502sub p_end {
503 shift->vspace(1); # assert one line's worth of vertical space at para-end
504}
505
506# ------------------------------------------------------------------------
507sub pre_start {
508 my $self = shift;
509
510 $self->{pre}++;
511 $self->vspace(1); # assert one line's worth of vertical space at pre-start
512 1;
513}
514
515# ------------------------------------------------------------------------
516sub pre_end {
517 my $self = shift;
518
519 $self->{pre}--; # assert one line's worth of vertical space at pre-end
520 $self->vspace(1);
521}
522
523# ------------------------------------------------------------------------
524sub listing_start { shift->pre_start(@_) }
525sub listing_end { shift->pre_end(@_) }
526sub xmp_start { shift->pre_start(@_) }
527sub xmp_end { shift->pre_end(@_) }
528
529# ------------------------------------------------------------------------
530sub blockquote_start {
531 my $self = shift;
532
533 $self->vspace(1); # assert one line's worth of vertical space at blockquote-start
534 $self->adjust_lm(+2);
535 $self->adjust_rm(-2);
536 1;
537}
538
539# ------------------------------------------------------------------------
540sub blockquote_end {
541 my $self = shift;
542
543 $self->vspace(1); # assert one line's worth of vertical space at blockquote-end
544 $self->adjust_lm(-2);
545 $self->adjust_rm(+2);
546}
547
548# ------------------------------------------------------------------------
549sub address_start {
550 my $self = shift;
551
552 $self->vspace(1); # assert one line's worth of vertical space at address-para-start
553 $self->i_start(@_);
554 1;
555}
556
557# ------------------------------------------------------------------------
558sub address_end {
559 my $self = shift;
560
561 $self->i_end(@_); # assert one line's worth of vertical space at address-para-end
562 $self->vspace(1);
563}
564
565# ------------------------------------------------------------------------
566# Handling of list elements
567sub ul_start {
568 my $self = shift;
569
570 $self->vspace(1); # assert one line's worth of vertical space at ul-start
571 $self->adjust_lm(+2);
572 1;
573}
574
575# ------------------------------------------------------------------------
576sub ul_end {
577 my $self = shift;
578
579 $self->adjust_lm(-2); # assert one line's worth of vertical space at ul-end
580 $self->vspace(1);
581}
582
583# ------------------------------------------------------------------------
584sub li_start {
585 my $self = shift;
586
587 $self->bullet( shift->attr('_bullet') || '' );
588 $self->adjust_lm(+2);
589 1;
590}
591
592# ------------------------------------------------------------------------
593sub bullet { shift->out(@_); }
594
595# ------------------------------------------------------------------------
596sub li_end {
597 my $self = shift;
598
599 $self->vspace(1);
600 $self->adjust_lm(-2);
601}
602
603# ------------------------------------------------------------------------
604sub menu_start { shift->ul_start(@_) }
605sub menu_end { shift->ul_end(@_) }
606sub dir_start { shift->ul_start(@_) }
607sub dir_end { shift->ul_end(@_) }
608
609# ------------------------------------------------------------------------
610sub ol_start {
611 my $self = shift;
612
613 $self->vspace(1);
614 $self->adjust_lm(+2);
615 1;
616}
617
618# ------------------------------------------------------------------------
619sub ol_end {
620 my $self = shift;
621
622 $self->adjust_lm(-2);
623 $self->vspace(1);
624}
625
626# ------------------------------------------------------------------------
627sub dl_start {
628 my $self = shift;
629
630 # $self->adjust_lm(+2);
631 $self->vspace(1); # assert one line's worth of vertical space at dl-start
632 1;
633}
634
635# ------------------------------------------------------------------------
636sub dl_end {
637 my $self = shift;
638
639 # $self->adjust_lm(-2);
640 $self->vspace(1); # assert one line's worth of vertical space at dl-end
641}
642
643# ------------------------------------------------------------------------
644sub dt_start {
645 my $self = shift;
646
647 $self->vspace(1); # assert one line's worth of vertical space at dt-start
648 1;
649}
650
651# ------------------------------------------------------------------------
652sub dt_end { }
653
654# ------------------------------------------------------------------------
655sub dd_start {
656 my $self = shift;
657
658 $self->adjust_lm(+6);
659 $self->vspace(0); # hm, what's that do? nothing?
660 1;
661}
662
663# ------------------------------------------------------------------------
664sub dd_end {
665 my $self = shift;
666
667 $self->vspace(1); # assert one line's worth of vertical space at dd-end
668 $self->adjust_lm(-6);
669}
670
671# ------------------------------------------------------------------------
672
673# And now some things that are basically sane fall-throughs for classes
674# that don't really handle tables or forms specially...
675
676# Things not formatted at all
677sub input_start { 0; }
678sub textarea_start { 0; }
679sub select_start { 0; }
680sub option_start { 0; }
681
682# ------------------------------------------------------------------------
683sub td_start {
684 my $self = shift;
685
686 push @{ $self->{'center_stack'} }, $self->{'center'};
687 $self->{center} = 0;
688
689 $self->p_start(@_);
690}
691
692# ------------------------------------------------------------------------
693sub td_end {
694 my $self = shift;
695
696 $self->{'center'} = pop @{ $self->{'center_stack'} };
697 $self->p_end(@_);
698}
699
700# ------------------------------------------------------------------------
701sub th_start {
702 my $self = shift;
703
704 push @{ $self->{'center_stack'} }, $self->{'center'};
705 $self->{center} = 0;
706
707 $self->p_start(@_);
708 $self->b_start(@_);
709}
710
711# ------------------------------------------------------------------------
712sub th_end {
713 my $self = shift;
714
715 $self->b_end(@_);
716 $self->{'center'} = pop @{ $self->{'center_stack'} };
717 $self->p_end(@_);
718}
719
720# But if you wanted to just SKIP tables and forms, you'd do this:
721# sub table_start { shift->out('[TABLE NOT SHOWN]'); 0; }
722# sub form_start { shift->out('[FORM NOT SHOWN]'); 0; }
723
724# ------------------------------------------------------------------------
725sub textflow {
726 my $self = shift;
727
728 if ( $self->{pre} ) {
729
730 # Strip one leading and one trailing newline so that a <pre>
731 # tag can be placed on a line of its own without causing extra
732 # vertical space as part of the preformatted text.
733 $_[0] =~ s/\n$//;
734 $_[0] =~ s/^\n//;
735 $self->pre_out( $_[0] );
736 }
737 elsif ( $self->{blockquote} ) {
738 $_[0] =~ s/\A\s//;
739 $self->blockquote_out( $_[0] );
740 }
741 else {
742 for ( split( /(\s+)/, $_[0] ) ) {
743 next unless length $_;
744 $self->out($_);
745 }
746 }
747}
748
749# ------------------------------------------------------------------------
750sub vspace {
751 my ( $self, $min, $add ) = @_;
752
753 # This method sets the vspace attribute. When vspace is
754 # defined, then a new line should be started. If vspace
755 # is a nonzero value, then that should be taken as the
756 # number of lines to be skipped before following text
757 # is written out.
758 #
759 # You may think it odd to conflate the two concepts of
760 # ending this paragraph, and asserting how much space should
761 # follow; but it happens to work out pretty well.
762
763 my $old = $self->{vspace};
764 if ( defined $old ) {
765 my $new = $old;
766 $new += $add || 0;
767 $new = $min if $new < $min;
768 $self->{vspace} = $new;
769 }
770 else {
771 $self->{vspace} = $min;
772 }
773 ### vspace: $self->{vspace}
774 $old;
775}
776
777# ------------------------------------------------------------------------
778sub collect { push( @{ shift->{output} }, @_ ); }
779
780# ------------------------------------------------------------------------
781sub out { confess "Must be overridden by subclass"; } # Output a word
782sub pre_out { confess "Must be overridden by subclass"; }
783sub adjust_lm { confess "Must be overridden by subclass"; }
784sub adjust_rm { confess "Must be overridden by subclass"; }
785
786# ------------------------------------------------------------------------
787
788
7891;
790
791__END__