File Coverage

blib/lib/HTML/WebMake/FormatConvert.pm
Criterion Covered Total %
statement 15 112 13.3
branch 0 32 0.0
condition 0 6 0.0
subroutine 5 15 33.3
pod 0 10 0.0
total 20 175 11.4


line stmt bran cond sub pod time code
1             #
2              
3             package HTML::WebMake::FormatConvert;
4              
5 1     1   1313 use Pod::Html;
  1         116076  
  1         177  
6              
7             ###########################################################################
8             # Define the converters we support here.
9             # The method used is as follows:
10             #
11             # 1. add a handler method at bottom; see et_to_html() for an example.
12             # 2. add an add_converter() call to this method. The arguments are as
13             # follows:
14             #
15             # arg1: The "source" format, what's found in the tag.
16             # Use MIME format. These are treated as case-insensitive.
17             # arg2: The "target" format, typically 'text/html'.
18             # arg3: A module required to use this converter. The best practice
19             # is to define the complicated conversion logic, if there is
20             # any, in a Perl module and call into that from this object.
21             # Again, see et_to_html() for an example. If no module is
22             # required, leave this as undef.
23             # arg4: the FormatConvert method used to perform the conversion.
24              
25             sub set_converters {
26 0     0 0   my $self = shift;
27              
28 0           $self->add_converter ('text/et', 'text/html',
29             'Text::EtText::EtText2HTML', \&et_to_html);
30              
31 0           $self->add_converter ('text/pod', 'text/html',
32             'Pod::Html', \&pod_to_html);
33              
34 0           $self->add_converter ('text/html', 'text/plain',
35             undef, \&html_to_plain);
36             }
37              
38             ###########################################################################
39              
40              
41 1     1   12 use Carp;
  1         3  
  1         63  
42 1     1   5 use strict;
  1         2  
  1         48  
43              
44 1     1   6 use HTML::WebMake::Main;
  1         2  
  1         27  
45              
46 1         1168 use vars qw{
47             @ISA
48             @OPTIMISED_FORMATS $SETUP_FMTS_LOOKUP
49             %FMT_TO_ZNAME %ZNAME_TO_FMT
50 1     1   8 };
  1         3  
51              
52              
53              
54              
55             # these are optimised into integers instead of strings, to save
56             # memory
57             @OPTIMISED_FORMATS = qw(
58             text/plain text/html text/et text/pod
59             );
60              
61             %FMT_TO_ZNAME = ();
62             %ZNAME_TO_FMT = ();
63             $SETUP_FMTS_LOOKUP = 0;
64              
65             ###########################################################################
66              
67             sub new ($$) {
68 0     0 0   my $class = shift;
69 0   0       $class = ref($class) || $class;
70 0           my ($main) = @_;
71              
72 0           my $self = {
73             'main' => $main,
74             'module_table' => { },
75             'callback_table' => { }
76             };
77 0           bless ($self, $class);
78              
79 0           $self->set_converters();
80 0           $self;
81             }
82              
83 0     0 0   sub dbg { HTML::WebMake::Main::dbg (@_); }
84              
85             # -------------------------------------------------------------------------
86              
87             sub format_name_to_zname { # STATIC
88 0     0 0   my ($name) = @_;
89              
90 0 0         if (!$SETUP_FMTS_LOOKUP) {
91 0           $SETUP_FMTS_LOOKUP = 1;
92 0           my $i = 0;
93 0           foreach my $fmt (@OPTIMISED_FORMATS) {
94 0           $FMT_TO_ZNAME{$fmt} = $i;
95 0           $ZNAME_TO_FMT{$i} = $fmt;
96 0           $i++;
97             }
98             }
99              
100 0 0         if (!defined $name) { return undef; }
  0            
101 0           my $zname = $FMT_TO_ZNAME{$name};
102 0 0         if (defined $zname) { return $zname; }
  0            
103 0           return $name;
104             }
105              
106             sub format_zname_to_name { # STATIC
107 0     0 0   my ($zname) = @_;
108              
109 0 0         if (!defined $zname) { return undef; }
  0            
110 0           my $name = $ZNAME_TO_FMT{$zname};
111 0 0         if (defined $name) { return $name; }
  0            
112 0           return $zname;
113             }
114              
115             # -------------------------------------------------------------------------
116              
117             sub add_converter {
118 0     0 0   my ($self, $infmt, $outfmt, $module, $callback) = @_;
119 0           my $key = $infmt." > ".$outfmt;
120 0           $key =~ tr/A-Z/a-z/;
121 0           $self->{module_table}->{$key} = $module;
122 0           $self->{callback_table}->{$key} = $callback;
123             }
124              
125             # -------------------------------------------------------------------------
126              
127             sub convert {
128 0     0 0   my ($self, $contobj, $infmt, $outfmt, $txt, $ignore_cache) = @_;
129              
130 0 0         if ($infmt eq $outfmt) { return $txt; }
  0            
131 0           my $key = $infmt." > ".$outfmt;
132 0           $key =~ tr/A-Z/a-z/;
133              
134 0 0         if (!$ignore_cache) {
135 0           my $cached = $self->{main}->getcache()->get_format_conversion
136             ($contobj, $key, $txt);
137              
138 0 0         if (defined $cached) { return $cached; }
  0            
139             }
140              
141 0           my $meth = $self->{callback_table}->{$key};
142 0 0         if (!defined $meth) {
143 0           croak ("Do not know how to convert from \"$infmt\" to \"$outfmt\"!\n");
144             }
145              
146 0           my $mod = $self->{module_table}->{$key};
147 0 0 0       if (defined $mod && !eval 'require '.$mod.';1;') {
148 0           die "FormatConvert: cannot load $mod module: $!\n";
149             }
150              
151 0           $txt = &$meth ($self, $contobj, $txt);
152              
153 0 0         if (!$ignore_cache) {
154 0           $self->{main}->getcache()->store_format_conversion
155             ($contobj, $key, $txt);
156             }
157 0           $txt;
158             }
159              
160             # -------------------------------------------------------------------------
161              
162             # for prospective format implementors: note the three args:
163             # $self = this object, as usual
164             # $contobj = the content object; you can read attributes from this.
165             # See the example in pod_to_html() below.
166             # $txt = the text to convert.
167              
168             sub et_to_html {
169 0     0 0   my ($self, $contobj, $txt) = @_;
170              
171 0 0         if (!defined $self->{ettext}) {
172 0 0         eval '
173             use Text::EtText::EtText2HTML;
174             $self->{ettext} = new Text::EtText::EtText2HTML;
175             1;' or
176             die "FormatConvert: cannot create Text::EtText::EtText2HTML object: $!";
177              
178 0           $self->{ettext}->{glossary} = $self->{main}->getglossary();
179 0           $self->{ettext}->set_option ('EtTextHrefsRelativeToTop', '1');
180 0           $self->{ettext}->set_options (%{$self->{main}->{options}});
  0            
181             }
182              
183 0           $self->{ettext}->text2html ($txt);
184             }
185              
186             # -------------------------------------------------------------------------
187              
188             sub pod_to_html {
189 0     0 0   my ($self, $contobj, $txt) = @_;
190 0           local ($_);
191              
192 0           my @args = ();
193 0 0         if (defined $contobj->{podargs}) {
194 0           @args = split (' ', $contobj->{podargs});
195             }
196              
197             # tut! Pod::Html can only handle file input
198 0           my $tmpin = $self->{main}->tmpdir().'.tmp_wm_pod_i.'.$$;
199 0           my $tmpout = $self->{main}->tmpdir().'.tmp.wm_pod_o.'.$$;
200              
201 0 0         open (POD_IN, ">$tmpin") or die "Cannot write to $tmpin";
202 0           print POD_IN $txt; undef $txt;
  0            
203 0           close POD_IN;
204              
205 0 0         open (POD_OUT, "+>$tmpout") or die "Cannot write to $tmpout";
206 0           my $start = tell(POD_OUT);
207              
208 0           pod2html ('--infile='.$tmpin, '--outfile='.$tmpout, '--title=x', @args);
209              
210 0           seek (POD_OUT, $start, 0);
211 0           $_ = join ('', );
212 0           close POD_OUT;
213              
214 0           unlink ($tmpin, $tmpout);
215 0           unlink ("pod2htmd.x~~"); # more pod spoor
216 0           unlink ("pod2html.x~~");
217              
218             # And now, some POD cleaning; the POD HTML isn't great unfortunately.
219              
220             # strip anything not inside the body from POD output, for
221             # our purposes.
222 0           s/^.*?//gs;
223 0           s/<\/BODY>.*?$//gs;
224              
225             # remove stray

start tags with no end tags.

226 0           s/

\s+(

|
)/$1/gis;

227              
228             # clean up method lists
229 0           s/(
.*?)
/$1<\/dt>
/gis;
230 0           s/(
.*?)
/$1<\/dd>
/gis;
231 0           s/(
.*?)<\/dl>/$1<\/dd><\/dl>/gis;
232              
233             # remove empty paras
234 0           s/

\s*<\/p>//gis;

235              
236 0           $_;
237             }
238              
239             # -------------------------------------------------------------------------
240              
241             sub html_to_plain {
242 0     0 0   my ($self, $contobj, $txt) = @_;
243              
244             # keep it (very) simple
245 0           $txt =~ s/

/\n/gis;

246 0           $txt =~ s/<[^>]+>//gs;
247 0           $txt;
248             }
249              
250             # -------------------------------------------------------------------------
251              
252             1;