1 |
dpavlin |
1.5 |
#!/usr/bin/perl |
2 |
dpavlin |
1.1 |
# |
3 |
dpavlin |
1.9 |
# PLies Copyright 2001 Dobrica Pavlinusic <dpavlin@rot13.org> |
4 |
dpavlin |
1.1 |
# |
5 |
|
|
# this tool is based on SlideMaker and XLSies tool |
6 |
|
|
# split a all.htm into slide*.htm |
7 |
|
|
# |
8 |
|
|
# For more information please see presentation about this tool on |
9 |
|
|
# https://www.rot13.org/~dpavlin/presentations/XLSies_to_PLies/ |
10 |
|
|
# |
11 |
|
|
# Copyright 1999 World Wide Web Consortium, |
12 |
|
|
# (Massachusetts Institute of Technology, Institut |
13 |
|
|
# National de Recherche en Informatique et en |
14 |
|
|
# Automatique, Keio University). All Rights Reserved. |
15 |
|
|
# This program is distributed under the W3C's |
16 |
|
|
# Intellectual Property License. This program is |
17 |
|
|
# distributed in the hope that it will be useful, but |
18 |
|
|
# WITHOUT ANY WARRANTY; without even the implied |
19 |
|
|
# warranty of MERCHANTABILITY or FITNESS FOR A |
20 |
|
|
# PARTICULAR PURPOSE. See W3C License |
21 |
|
|
# http://www.w3.org/Consortium/Legal/ for more details. |
22 |
|
|
# |
23 |
|
|
# |
24 |
|
|
############################################################################## |
25 |
|
|
# |
26 |
|
|
# slidemaker credits: |
27 |
|
|
# |
28 |
|
|
# Stephan Montigaud - stephan@w3.org |
29 |
|
|
# created 970601 |
30 |
|
|
# modified by Pierre Fillault |
31 |
|
|
# check the documentation at http://www.w3.org/Talks/YYMMsub/ |
32 |
|
|
# |
33 |
|
|
# modified 19990505 Bert Bos: ALT text of prev/next arrows is now |
34 |
|
|
# "prev"/"next" rather than the title of the prev/next slide; looks better |
35 |
|
|
# in lynx. |
36 |
|
|
# |
37 |
|
|
# version: 4.14 - 19990719 |
38 |
|
|
# $Id: w3cburst.pl,v 1.41 1999/11/02 17:25:50 charles Exp $ |
39 |
|
|
# |
40 |
|
|
# |
41 |
|
|
# XLSies credits: |
42 |
|
|
# |
43 |
|
|
# Sami Lempinen - lempinen@iki.fi |
44 |
|
|
# http://www.snowman.sgic.fi/ssl/xslies/ |
45 |
dpavlin |
1.5 |
# |
46 |
|
|
# Text::FastTemplate: |
47 |
|
|
# Robert Lehr - bozzio@the-lehrs.com |
48 |
|
|
|
49 |
|
|
use Text::FastTemplate; |
50 |
dpavlin |
1.1 |
|
51 |
|
|
############################################################################## |
52 |
|
|
## default values of variables |
53 |
|
|
## |
54 |
|
|
|
55 |
dpavlin |
1.7 |
## show debug output |
56 |
dpavlin |
1.14 |
my $debug=0; |
57 |
dpavlin |
1.7 |
|
58 |
dpavlin |
1.1 |
## default DOCTYPE added on the slides |
59 |
|
|
$doctype = '<html xmlns="http://www.w3.org/TR/REC-html40">'; |
60 |
|
|
|
61 |
|
|
## name of raw HTML file containing the slides |
62 |
|
|
$all = 'all.htm'; |
63 |
|
|
|
64 |
|
|
## table of content built from all.htm - also first page of the presentation |
65 |
|
|
## this is only the basename as we need to generate one toc for each style sheets |
66 |
|
|
## the main toc will not bear any more so the server can understand a request for '/' |
67 |
|
|
## the next ones will bear a number corresponding to the slide index |
68 |
|
|
#$overview = 'Overview'; |
69 |
|
|
$overview = 'index'; |
70 |
|
|
|
71 |
|
|
## name of the file containing the parameters of the presentation |
72 |
|
|
$infos = 'infos.txt'; |
73 |
|
|
|
74 |
|
|
## link to the logo printed on all the slides |
75 |
|
|
$logoLink = ''; |
76 |
|
|
|
77 |
|
|
## default location of the logo - works when slidemaker is used as a package |
78 |
|
|
$logoFile = ''; |
79 |
|
|
|
80 |
|
|
### localization |
81 |
|
|
$loc_toc = "Table of contents"; |
82 |
|
|
$loc_by = "by"; |
83 |
|
|
$loc_amp = "&"; # author separator |
84 |
|
|
$loc_slide = "Slide"; |
85 |
|
|
$loc_of = "of"; # $loc_slide nr $loc_of total |
86 |
|
|
|
87 |
|
|
## alternate representation of the logo |
88 |
|
|
$logoAlt = ''; |
89 |
|
|
|
90 |
|
|
## default values set to none |
91 |
|
|
$logoLink2 = ''; # link to a potential second reference |
92 |
|
|
$logoFile2 = ''; # location of a second logo |
93 |
|
|
$logoAlt2 = ''; # alternate representation of the second logo |
94 |
|
|
|
95 |
|
|
## default accesskeys for navigation icons used in the slides |
96 |
|
|
$prevKey = 'P'; # accesskey for previous slide |
97 |
|
|
$nextKey = 'N'; # accesskey for next slide |
98 |
|
|
$tocKey = 'C'; # accesskey for table of contents |
99 |
|
|
$styleKey = 'S'; # accesskey for changing style sheets |
100 |
|
|
|
101 |
|
|
## default author name |
102 |
|
|
$author = 'Staff'; |
103 |
|
|
|
104 |
|
|
## default presentation title |
105 |
|
|
$talkTitle = 'Talk'; |
106 |
|
|
|
107 |
|
|
## standard style sheets |
108 |
|
|
$cssStandard = '../PLies/css/default.css'; |
109 |
|
|
|
110 |
dpavlin |
1.5 |
## template name |
111 |
|
|
$template = '../PLies/default'; |
112 |
|
|
|
113 |
dpavlin |
1.1 |
## default charset use in meta tag http-equiv (undef to skip) |
114 |
|
|
#$charset = 'ISO-8859-1'; |
115 |
|
|
|
116 |
|
|
## default <body> tag |
117 |
|
|
$body = '<body>'; |
118 |
|
|
|
119 |
|
|
## number of entries on each TOC page |
120 |
|
|
$toc_on_page = 10; |
121 |
|
|
|
122 |
|
|
## use progress bar |
123 |
|
|
$progress_bar = 1; |
124 |
|
|
|
125 |
dpavlin |
1.2 |
## content hight for each slide |
126 |
|
|
$content_hight = "70%"; |
127 |
|
|
|
128 |
dpavlin |
1.1 |
## end of default values for the presentation |
129 |
|
|
############################################################################## |
130 |
|
|
|
131 |
|
|
## globals |
132 |
|
|
my $last_toc_title; |
133 |
dpavlin |
1.5 |
my %page_data; |
134 |
|
|
my %overview_data; |
135 |
dpavlin |
1.1 |
|
136 |
dpavlin |
1.13 |
my $pack = 0; |
137 |
|
|
my @pack_additional; # additional files to pack (pictures, logos...) |
138 |
dpavlin |
1.19 |
my %nesttag = init_nesttag(); |
139 |
dpavlin |
1.13 |
|
140 |
dpavlin |
1.1 |
############################################################################## |
141 |
|
|
## reading user input from $infos |
142 |
|
|
## |
143 |
dpavlin |
1.16 |
my @file; |
144 |
|
|
|
145 |
|
|
############################################################################## |
146 |
|
|
sub parse_infos { |
147 |
|
|
my @file=@_; |
148 |
dpavlin |
1.7 |
do { |
149 |
|
|
if ($file[0] && $file[0] =~ /^[^#\n\r]/) { |
150 |
|
|
$file[0] =~ s/\n//; # remove UNIX \n |
151 |
|
|
$file[0] =~ s/\r//; # remove WINDOWS \r |
152 |
dpavlin |
1.16 |
my ($var,$value) = split(/ *= */,$file[0],2); |
153 |
|
|
$value=~s/'/\\'/g; |
154 |
|
|
$cmd="\$$var = \'$value\';"; |
155 |
|
|
if (defined($value)) { |
156 |
|
|
eval($cmd) || warn "problem with eval of: $cmd"; |
157 |
|
|
} else { |
158 |
|
|
die "no value defined for $var"; |
159 |
|
|
} |
160 |
dpavlin |
1.13 |
print STDERR "$file[0]\n"; |
161 |
dpavlin |
1.7 |
} |
162 |
|
|
} while (shift(@file)); |
163 |
dpavlin |
1.1 |
} |
164 |
dpavlin |
1.16 |
############################################################################## |
165 |
|
|
|
166 |
dpavlin |
1.17 |
parse_infos(@ARGV); # backward compatibility and for pack |
167 |
|
|
|
168 |
dpavlin |
1.16 |
# read parameters from infos.txt and put them in @PARAM |
169 |
|
|
if (open(INFOS, $infos)) { |
170 |
|
|
print STDERR "--- Reading parameters file $infos ---\n"; |
171 |
|
|
@file = <INFOS>; |
172 |
|
|
parse_infos(@file); |
173 |
|
|
} |
174 |
dpavlin |
1.1 |
|
175 |
dpavlin |
1.16 |
# try to read local infos.txt for template |
176 |
|
|
if (-f "$template/$infos" && open(INFOS,"$template/$infos")) { |
177 |
|
|
print STDERR "--- Reading template parameters file $template/$infos ---\n"; |
178 |
|
|
@file = <INFOS>; |
179 |
|
|
parse_infos(@file); |
180 |
|
|
close(INFOS); |
181 |
dpavlin |
1.1 |
} |
182 |
|
|
|
183 |
dpavlin |
1.16 |
## @PARAM is now a table with the user preferences for his presentation |
184 |
|
|
|
185 |
dpavlin |
1.1 |
## use charset |
186 |
|
|
|
187 |
|
|
if ($charset) { |
188 |
|
|
$http_equiv='<meta http-equiv="Content-type" content="text/html; charset='.$charset.'">'; |
189 |
|
|
} else { |
190 |
|
|
$http_equiv=''; |
191 |
|
|
} |
192 |
|
|
|
193 |
dpavlin |
1.13 |
|
194 |
dpavlin |
1.1 |
############################################################################## |
195 |
|
|
## read the raw html presentation |
196 |
|
|
## |
197 |
|
|
|
198 |
|
|
## copy file in memory |
199 |
|
|
my $sep = $/; |
200 |
|
|
$/ = undef; |
201 |
dpavlin |
1.7 |
open(ALL, $all) || die "Error: Cannot open file: $all"; |
202 |
dpavlin |
1.1 |
my $buf = <ALL>; |
203 |
dpavlin |
1.12 |
$buf =~ s/\r//g; # remove WINDOWS \r |
204 |
dpavlin |
1.1 |
close(ALL); |
205 |
|
|
$/ = $sep; |
206 |
|
|
|
207 |
|
|
## Remove comments from the raw presentation |
208 |
|
|
## they do not need to show up on the slides |
209 |
|
|
$buf =~ s/<!--.*?-->//sgo; |
210 |
|
|
|
211 |
dpavlin |
1.13 |
## if $pack is set, output name of css (for inclusion in archive), but |
212 |
|
|
## reset $cssStandard only to filename (without path) |
213 |
|
|
|
214 |
|
|
if ($pack) { |
215 |
|
|
push @pack_additional,$cssStandard; |
216 |
|
|
$cssStandard =~ s/^.*\/([^\/]+)$/$1/g; |
217 |
|
|
} |
218 |
|
|
|
219 |
dpavlin |
1.1 |
## the slidemaker tool assumes that each slide is self contained between 2 sets of h1 tags |
220 |
|
|
## if not it will generate a rather weird output |
221 |
|
|
## split using <h1...> and </h1...> as separator (ignores attributes!) |
222 |
|
|
## h1 or H1 can be used |
223 |
|
|
@table = split(/<\/?[hH]1[^>]*>/, $buf); |
224 |
|
|
|
225 |
|
|
## compute the total number of slides |
226 |
|
|
$total = $#table / 2; |
227 |
|
|
if ($#table % 2 != 0) { |
228 |
|
|
$total = ($#table +1)/2; |
229 |
|
|
} |
230 |
|
|
|
231 |
|
|
## |
232 |
|
|
## raw presentation has been read successfully |
233 |
|
|
############################################################################## |
234 |
|
|
|
235 |
|
|
############################################################################## |
236 |
|
|
## processing the slides |
237 |
|
|
|
238 |
dpavlin |
1.13 |
print STDERR "\n--- Processing $total slides ---\n"; |
239 |
dpavlin |
1.1 |
|
240 |
|
|
## generate the header table of content of the presentation |
241 |
|
|
## which is also the first page of the talk |
242 |
|
|
&openOverview($overview); |
243 |
|
|
|
244 |
|
|
## start the slide count so we can number them |
245 |
|
|
$slideCount = 1; |
246 |
|
|
|
247 |
dpavlin |
1.5 |
## pre-load template slides using $template dir |
248 |
|
|
Text::FastTemplate->defaults( |
249 |
|
|
path => [ $template ] |
250 |
|
|
); |
251 |
|
|
|
252 |
|
|
Text::FastTemplate->preload( [ |
253 |
|
|
{ file => 'slide.html', key => 'slide' }, |
254 |
|
|
{ file => 'overview.html', key => 'overview' }, |
255 |
dpavlin |
1.12 |
{ file => 'title.html', key => 'title' }, |
256 |
dpavlin |
1.5 |
]); |
257 |
dpavlin |
1.1 |
|
258 |
dpavlin |
1.7 |
## unroll relative anchors (#something) into links with slides |
259 |
|
|
|
260 |
|
|
my %anchor_on_slide; |
261 |
|
|
|
262 |
|
|
## step 1: record anchors |
263 |
|
|
for($i=0; $i<$total; $i++) { |
264 |
dpavlin |
1.9 |
my $tmp = $table[($i*2)].$table[($i*2)+1]; |
265 |
dpavlin |
1.7 |
while ($tmp =~ s,<a +name="*([^>"]+)"*>,,i) { |
266 |
|
|
$anchor_on_slide{$1}=($i+1); |
267 |
dpavlin |
1.13 |
print STDERR "\tslide ",($i+1)," anchor: $1\n" if ($debug); |
268 |
dpavlin |
1.7 |
} |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
## step 2: fix links |
272 |
|
|
for($i=0; $i<$total; $i++) { |
273 |
|
|
foreach (keys %anchor_on_slide) { |
274 |
|
|
$table[($i*2)] =~ s,href="*#$_"*>,href="slide$anchor_on_slide{$_}\.html#$_">,gi; |
275 |
|
|
} |
276 |
|
|
} |
277 |
|
|
|
278 |
dpavlin |
1.1 |
## @table is the array containing each slide with its title |
279 |
|
|
## for each slide to be generated |
280 |
|
|
## we delete each slide and its title when generated |
281 |
|
|
## so that the current slide and its title are always at $table[0] (for the title) |
282 |
|
|
## and $table[1] (for the slide content) |
283 |
dpavlin |
1.7 |
|
284 |
|
|
undef $prev_title; |
285 |
|
|
undef $next_title; |
286 |
|
|
|
287 |
dpavlin |
1.1 |
do { |
288 |
|
|
|
289 |
|
|
## get rid of the first element contained by the raw presentation array |
290 |
|
|
shift(@table); |
291 |
|
|
## then $table[0] is the title of the slide to be generated |
292 |
|
|
$table[0] =~ s/\n+/ /g; ## replace return character by a white space |
293 |
|
|
$table[0] =~ s/\r+/ /g; ## replace lf character by a white space |
294 |
|
|
$table[0] =~ s/ +/ /g; ## concatenate several white spaces to only one |
295 |
|
|
$table[0] =~ s/^ //; ## remove all the starting white spaces in the title |
296 |
|
|
$table[0] =~ s/ $//; ## remove all trailing white spaces in the title |
297 |
|
|
## $slideTitle preserves link(s) in the title |
298 |
|
|
$slideTitle = $table[0]; |
299 |
|
|
## need to check if the title contains any anchor |
300 |
|
|
## if so it needs to be removed |
301 |
|
|
## because the title is being used in the table of content to link to the corresponding slide |
302 |
dpavlin |
1.8 |
$table[0] = remove_anchor($table[0]); |
303 |
dpavlin |
1.1 |
|
304 |
|
|
## grab next slide title $table[2] (if there's a next slide) |
305 |
|
|
## to be able to use in the 'next' navigation button |
306 |
|
|
## keep in mind that $table[1] contains the slide corresponding to the title $table[0] |
307 |
dpavlin |
1.7 |
if ($table[2]) { |
308 |
dpavlin |
1.8 |
$next_title= remove_anchor($table[2]); |
309 |
dpavlin |
1.7 |
} |
310 |
dpavlin |
1.1 |
|
311 |
|
|
## the current slide content is stored $table[1] |
312 |
|
|
## there is an attempt to make sure it's clean HTML |
313 |
|
|
## Pierre Fillault's note: use same piece of as used in http://www.w3.org/Web/Tools/CvsCommitScripting |
314 |
|
|
## to make use of the validation service |
315 |
|
|
$slideContent = &clean_html($table[1]) ; |
316 |
|
|
|
317 |
|
|
## extract slide Sub Title <h2> |
318 |
|
|
undef $slideSubTitle; |
319 |
dpavlin |
1.8 |
if ($slideContent =~ s/<[hH]2[^>]*>(.+)<\/[hH]2[^>]*>//sm) { |
320 |
|
|
$slideSubTitle=remove_anchor($1); |
321 |
dpavlin |
1.1 |
} |
322 |
|
|
|
323 |
|
|
## add the title of the current slide to the table of content |
324 |
|
|
&addTitle($slideTitle,$slideSubTitle,$slideCount); |
325 |
|
|
|
326 |
|
|
## generate the current slide |
327 |
|
|
## parameters are: |
328 |
|
|
## title of the slide, its content, the slide number, the title of the previous slide and the title of the next slide |
329 |
dpavlin |
1.7 |
&createSlide($slideTitle,$slideSubTitle,$slideContent ,$slideCount++,$prev_title,$next_title); |
330 |
dpavlin |
1.1 |
|
331 |
|
|
## save the title of the previous slide to be displayed in the 'previous' navigation button |
332 |
dpavlin |
1.8 |
$prev_title=remove_anchor($table[0]); |
333 |
dpavlin |
1.1 |
} |
334 |
|
|
## process the next slide |
335 |
|
|
while (shift(@table)); |
336 |
|
|
|
337 |
|
|
## close the table of content |
338 |
|
|
&closeOverview; |
339 |
|
|
|
340 |
|
|
## generate more toc with the all the style sheets |
341 |
|
|
## as there's no way of loading a style sheet |
342 |
|
|
## except dynamically, but that would be slow |
343 |
|
|
## and would not work on all platforms (ie would fail on Joe's laptop) |
344 |
|
|
&generateTOC; |
345 |
|
|
|
346 |
dpavlin |
1.13 |
## print additional files to pack |
347 |
|
|
print STDOUT join("\n",@pack_additional) if ($pack); |
348 |
dpavlin |
1.1 |
|
349 |
dpavlin |
1.13 |
print STDERR "--- Finished ---\n"; |
350 |
dpavlin |
1.1 |
exit 0; |
351 |
|
|
## |
352 |
|
|
## end of the slidemaker main program |
353 |
|
|
############################################################################## |
354 |
|
|
|
355 |
|
|
|
356 |
|
|
############################################################################## |
357 |
|
|
## generate the header of the table of content |
358 |
|
|
|
359 |
|
|
sub openOverview |
360 |
|
|
{ |
361 |
|
|
## open the file to write to |
362 |
|
|
open(FOO, ">$_[0].html") || die "can't open $_[0].html: $!"; |
363 |
dpavlin |
1.13 |
push @pack_additional,"$_[0].html" if ($pack); |
364 |
dpavlin |
1.1 |
|
365 |
|
|
## the style sheet used in the table of content is |
366 |
|
|
$stylelink = ""; |
367 |
|
|
## here is the standard style sheet |
368 |
|
|
$stylelink .= "<link href=\"$cssStandard\" rel=\"stylesheet\" type=\"text/css\" title=\"Talk\" media=\"screen\">"; |
369 |
|
|
|
370 |
dpavlin |
1.5 |
%overview_data = ( |
371 |
|
|
doctype => $doctype, |
372 |
|
|
title => $title, |
373 |
|
|
http_equiv => $http_equiv, |
374 |
|
|
stylelink => $stylelink, |
375 |
|
|
body => $body, |
376 |
|
|
|
377 |
|
|
logoLink => $logoLink, |
378 |
|
|
logoFile => $logoFile, |
379 |
|
|
logoAlt => $logoAlt, |
380 |
dpavlin |
1.7 |
logoLink2 => $logoLink2, |
381 |
|
|
logoFile2 => $logoFile2, |
382 |
|
|
logoAlt2 => $logoAlt2, |
383 |
dpavlin |
1.5 |
|
384 |
|
|
talkTitle => $talkTitle, |
385 |
|
|
talkSubTitle => $talkSubTitle, |
386 |
|
|
|
387 |
|
|
content_hight => $content_hight, |
388 |
|
|
|
389 |
|
|
author => $author, |
390 |
|
|
authorUrl => $authorUrl, |
391 |
|
|
author2 => $author2, |
392 |
dpavlin |
1.18 |
author2Url => $author2Url, |
393 |
dpavlin |
1.1 |
|
394 |
dpavlin |
1.5 |
date => $date, |
395 |
dpavlin |
1.1 |
|
396 |
dpavlin |
1.16 |
toc_title => $loc_toc, |
397 |
dpavlin |
1.17 |
template_dir => "$template/", |
398 |
dpavlin |
1.5 |
); |
399 |
dpavlin |
1.1 |
|
400 |
|
|
} |
401 |
|
|
## |
402 |
|
|
## the beginning of the table of content has been generated and saved |
403 |
|
|
############################################################################## |
404 |
|
|
|
405 |
|
|
############################################################################## |
406 |
|
|
## generate the footer of the table of content |
407 |
|
|
|
408 |
|
|
sub closeOverview |
409 |
|
|
{ |
410 |
dpavlin |
1.5 |
$overview_data{slide_html} = make_progress_bar(0,$total); |
411 |
|
|
$overview_data{toc_entries} = [ @toc_entries ]; |
412 |
|
|
|
413 |
|
|
my $page= new Text::FastTemplate key => 'overview'; |
414 |
dpavlin |
1.17 |
$page_data{template_dir}='' if ($pack); |
415 |
dpavlin |
1.5 |
print FOO $page->output( \%overview_data ); |
416 |
dpavlin |
1.1 |
|
417 |
|
|
close(FOO); |
418 |
|
|
} |
419 |
|
|
## |
420 |
|
|
## the toc has been completed and saved |
421 |
|
|
############################################################################## |
422 |
|
|
|
423 |
|
|
############################################################################## |
424 |
|
|
## add an item in the toc |
425 |
|
|
|
426 |
|
|
sub addTitle |
427 |
|
|
{ |
428 |
|
|
my ($title,$subtitle,$nr) = @_; |
429 |
|
|
$title =~ s/\r//ig; # remove the windows CR+LF |
430 |
|
|
$title =~ s/<[^>]+>//g; |
431 |
dpavlin |
1.20 |
$subtitle =~ s/<[^>]+>//g; |
432 |
dpavlin |
1.1 |
|
433 |
|
|
if (! $title) { |
434 |
|
|
return 1; |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
# split TOC entries to multiple pages |
438 |
|
|
|
439 |
|
|
if ($nr % $toc_on_page == 0) { |
440 |
|
|
my $toc_nr=int($nr/$toc_on_page); |
441 |
|
|
|
442 |
dpavlin |
1.10 |
$item = { |
443 |
dpavlin |
1.5 |
pre_html => $pre_ul, |
444 |
|
|
accesskey => " ", # space |
445 |
|
|
href => "index-toc$toc_nr.html", |
446 |
|
|
title => "...", |
447 |
|
|
post_html => $post_ul, |
448 |
|
|
more => 1, # use style for more pages link (...) |
449 |
dpavlin |
1.10 |
}; |
450 |
|
|
push @toc_entries, $item; |
451 |
dpavlin |
1.5 |
|
452 |
dpavlin |
1.1 |
&closeOverview; |
453 |
dpavlin |
1.10 |
undef @toc_entries; |
454 |
dpavlin |
1.1 |
&openOverview("$overview-toc$toc_nr"); |
455 |
|
|
$last_toc_title=''; |
456 |
|
|
} |
457 |
|
|
|
458 |
dpavlin |
1.5 |
$pre_ul=$post_ul=''; |
459 |
dpavlin |
1.11 |
if ($last_toc_title eq $title && $subtitle) { |
460 |
dpavlin |
1.1 |
$title = $subtitle; |
461 |
dpavlin |
1.5 |
$pre_ul='<ul>'; |
462 |
|
|
$post_ul='</ul>'; |
463 |
dpavlin |
1.1 |
} else { |
464 |
|
|
$last_toc_title=$title; |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
# add accesskey for first 9 slides (`1' - `9') or just for first |
468 |
|
|
# TOC page, and tabindex for all slides |
469 |
|
|
if ($nr < 10 && $nr < $toc_on_page) { |
470 |
dpavlin |
1.5 |
$item = { |
471 |
|
|
pre_html => $pre_ul, |
472 |
|
|
accesskey => "$nr", |
473 |
|
|
tabindex => "$nr", |
474 |
|
|
href => "slide$nr.html", |
475 |
|
|
title => $title, |
476 |
|
|
post_html => $post_ul, |
477 |
|
|
more => 0, |
478 |
|
|
}; |
479 |
|
|
push @toc_entries,$item; |
480 |
dpavlin |
1.1 |
} else { |
481 |
dpavlin |
1.10 |
$item = { |
482 |
dpavlin |
1.5 |
pre_html => $pre_ul, |
483 |
|
|
tabindex => "$nr", |
484 |
|
|
href => "slide$nr.html", |
485 |
|
|
title => $title, |
486 |
|
|
post_html => $post_ul, |
487 |
dpavlin |
1.10 |
}; |
488 |
|
|
push @toc_entries,$item; |
489 |
dpavlin |
1.1 |
} |
490 |
|
|
} |
491 |
|
|
## |
492 |
|
|
############################################################################## |
493 |
|
|
|
494 |
|
|
############################################################################## |
495 |
|
|
## generate the current slide |
496 |
|
|
|
497 |
|
|
sub createSlide |
498 |
|
|
{ |
499 |
|
|
|
500 |
|
|
# parameters are respectively the slide title, its content, |
501 |
|
|
# its number, the next slide title and the previous slide title |
502 |
|
|
|
503 |
dpavlin |
1.7 |
my ($title,$subtitle,$content,$nr,$prev_title,$next_title) = @_; |
504 |
dpavlin |
1.1 |
|
505 |
|
|
if (! $title) { |
506 |
|
|
return 1; |
507 |
|
|
} |
508 |
|
|
|
509 |
|
|
# work the slide title, the previous and next titles |
510 |
|
|
chomp $title; |
511 |
|
|
$title =~ s/\r//ig; # remove the windows CR+LF |
512 |
|
|
$next_title =~ s/\r//ig; |
513 |
|
|
$prev_title =~ s/\r//ig; |
514 |
|
|
|
515 |
|
|
# Remove any tags from the prev & next titles |
516 |
|
|
$next_title =~ s/<[^>]+>//g; |
517 |
|
|
$prev_title =~ s/<[^>]+>//g; |
518 |
|
|
$title =~ s/<[^>]+>//g; |
519 |
|
|
|
520 |
|
|
# Replace double quotes |
521 |
|
|
# $title =~ s/"/"/g; |
522 |
|
|
$next_title =~ s/"/"/g; |
523 |
|
|
$prev_title =~ s/"/"/g; |
524 |
|
|
|
525 |
|
|
# work the slide content |
526 |
|
|
$content =~ s/<\/body>//i; # remove if any |
527 |
|
|
$content =~ s/<\/html>//i; # remove if any |
528 |
|
|
|
529 |
|
|
$status = sprintf "Slide %2d: %s %s\n", $nr, $title, $subtitle; |
530 |
|
|
$status =~ s/<[^>]+>//g; |
531 |
dpavlin |
1.13 |
print STDERR $status; |
532 |
dpavlin |
1.1 |
|
533 |
dpavlin |
1.19 |
&verify_html($content); # check the html |
534 |
|
|
&check_tags($content); # check open and closed tags |
535 |
dpavlin |
1.1 |
|
536 |
|
|
## write to the slide |
537 |
|
|
open(SLIDE, ">slide$nr.html") || die "can't save slide$nr.html: $!"; |
538 |
dpavlin |
1.13 |
push @pack_additional,"slide$nr.html" if ($pack); |
539 |
dpavlin |
1.1 |
|
540 |
dpavlin |
1.7 |
my $toc_link = "$overview\.html"; |
541 |
dpavlin |
1.1 |
|
542 |
|
|
## initialization of the navigation links |
543 |
dpavlin |
1.7 |
my $next_link = ""; |
544 |
|
|
my $prev_link = ""; |
545 |
dpavlin |
1.1 |
|
546 |
|
|
if ($nr>1) { |
547 |
dpavlin |
1.7 |
$prev_link = "slide".($nr-1).".html"; |
548 |
dpavlin |
1.1 |
# } else { |
549 |
|
|
# ## add a link back to the toc for the first slide --CMN 19991102 |
550 |
dpavlin |
1.7 |
# $prev_link = "$overview\.html"; |
551 |
dpavlin |
1.1 |
} |
552 |
|
|
|
553 |
|
|
if ($nr != $total) { |
554 |
dpavlin |
1.7 |
$next_link = "slide".($nr+1).".html"; |
555 |
dpavlin |
1.1 |
} |
556 |
|
|
|
557 |
|
|
$stylelink = ""; |
558 |
|
|
# here is the standard style sheet |
559 |
|
|
$stylelink .= "<link href=\"$cssStandard\" rel=\"stylesheet\" type=\"text/css\" title=\"Talk\">"; |
560 |
|
|
|
561 |
|
|
my $slide_html=make_progress_bar($nr,$total); |
562 |
|
|
|
563 |
dpavlin |
1.12 |
# undefine body if no content is found (so that template can show |
564 |
|
|
# only title and sub-title |
565 |
|
|
if ($content !~ m/\S/g) { |
566 |
|
|
undef $content; |
567 |
|
|
} |
568 |
|
|
|
569 |
dpavlin |
1.5 |
%page_data = ( |
570 |
|
|
doctype => $doctype, |
571 |
|
|
talkTitle => $talkTitle, |
572 |
|
|
title => $title, |
573 |
dpavlin |
1.7 |
subtitle => $subtitle, |
574 |
dpavlin |
1.5 |
http_equiv => $http_equiv, |
575 |
|
|
stylelink => $stylelink, |
576 |
|
|
body => $body, |
577 |
|
|
|
578 |
dpavlin |
1.7 |
logoLink => $logoLink, |
579 |
|
|
logoFile => $logoFile, |
580 |
|
|
logoAlt => $logoAlt, |
581 |
|
|
logoLink2 => $logoLink2, |
582 |
|
|
logoFile2 => $logoFile2, |
583 |
|
|
logoAlt2 => $logoAlt2, |
584 |
|
|
|
585 |
|
|
|
586 |
dpavlin |
1.5 |
content_hight => $content_hight, |
587 |
|
|
content => $content, |
588 |
dpavlin |
1.7 |
|
589 |
|
|
prev_link => $prev_link, |
590 |
|
|
toc_link => $toc_link, |
591 |
|
|
next_link => $next_link, |
592 |
|
|
prev_title => $prev_title, |
593 |
dpavlin |
1.16 |
toc_title => $loc_toc, |
594 |
dpavlin |
1.7 |
next_title => $next_title, |
595 |
|
|
|
596 |
dpavlin |
1.5 |
author => $author, |
597 |
dpavlin |
1.7 |
authorUrl => $authorUrl, |
598 |
|
|
author2 => $author2, |
599 |
dpavlin |
1.18 |
author2Url => $author2Url, |
600 |
dpavlin |
1.7 |
|
601 |
|
|
date => $date, |
602 |
|
|
|
603 |
dpavlin |
1.5 |
slide_html => $slide_html, |
604 |
|
|
|
605 |
dpavlin |
1.17 |
template_dir => "$template/", |
606 |
dpavlin |
1.5 |
); |
607 |
|
|
|
608 |
dpavlin |
1.12 |
my $page; |
609 |
|
|
if ($content) { |
610 |
|
|
$page= new Text::FastTemplate key => 'slide'; |
611 |
|
|
} else { |
612 |
|
|
$page= new Text::FastTemplate key => 'title'; |
613 |
|
|
} |
614 |
dpavlin |
1.20 |
|
615 |
|
|
if ($pack) { |
616 |
|
|
$page_data{template_dir}=''; |
617 |
|
|
print SLIDE extract_files($page->output( \%page_data )); |
618 |
|
|
} else { |
619 |
|
|
print SLIDE $page->output( \%page_data ); |
620 |
|
|
} |
621 |
|
|
|
622 |
dpavlin |
1.1 |
close(SLIDE); |
623 |
|
|
return 0; |
624 |
|
|
} |
625 |
|
|
|
626 |
|
|
############################################################################## |
627 |
|
|
## generate all the toc of contents needed for each css choosen by the user |
628 |
|
|
## the default toc is not numbered so it can be served by a request to '/' |
629 |
|
|
## (ie it remains Overview.html whereas the other toc are called Overview_#.html) |
630 |
|
|
|
631 |
|
|
sub generateTOC { |
632 |
|
|
|
633 |
|
|
## read the general toc |
634 |
|
|
open(FOO, "<$overview.html"); |
635 |
|
|
@TOC = <FOO>; |
636 |
|
|
close(FOO); |
637 |
|
|
$toc = "@TOC"; |
638 |
|
|
|
639 |
|
|
## for each user CSS file |
640 |
|
|
## starting after the default css |
641 |
|
|
for ($css=1;$css<$nbCssStandard;$css++) { |
642 |
|
|
|
643 |
|
|
## create new TOC |
644 |
|
|
$newTOC = $toc; |
645 |
|
|
|
646 |
|
|
## the links on the toc need also to be modified |
647 |
|
|
## to link to the correct slides |
648 |
|
|
$newTOC =~ s/<a accesskey=\"(\d)\" tabindex=\"(\d+)\" href=\"slide(\d+)-\d+\.html\">/<a accesskey=\"$1\" tabindex=\"$2\" href=\"slide$3-$css\.html">/ig; |
649 |
|
|
$newTOC =~ s/<a tabindex=\"(\d+)\" href=\"slide(\d+)-\d+\.html\">/<a tabindex=\"$1\" href=\"slide$2-$css\.html">/ig; |
650 |
|
|
|
651 |
|
|
## write to new TOC |
652 |
|
|
$outfile = $overview."-".$css.".html"; |
653 |
|
|
open(OUT, ">$outfile"); |
654 |
|
|
print OUT $newTOC; |
655 |
|
|
close(OUT) |
656 |
|
|
} |
657 |
|
|
|
658 |
|
|
|
659 |
|
|
} |
660 |
|
|
|
661 |
|
|
############################################################################## |
662 |
|
|
# check that the html of the slide |
663 |
|
|
# is correct (ALT tags, ...) |
664 |
|
|
# This procedure produces only warning |
665 |
|
|
sub verify_html { |
666 |
|
|
|
667 |
|
|
if ($_[0] =~ /<img([^>]*)>/im) { |
668 |
|
|
if (!($1 =~ /ALT=/im)) { |
669 |
dpavlin |
1.13 |
print STDERR "WARNING: <IMG> without ALT\n"; |
670 |
|
|
print STDERR " <IMG$1>\n" ; |
671 |
dpavlin |
1.1 |
} |
672 |
|
|
} |
673 |
|
|
} |
674 |
|
|
|
675 |
|
|
############################################################################## |
676 |
|
|
# clean the html of the slide |
677 |
|
|
# remove all <div class="comment">blabla</div> |
678 |
|
|
sub clean_html { |
679 |
dpavlin |
1.10 |
my $tmp=$_[0]; |
680 |
|
|
$tmp =~ s/<div\s+class\s*=\s*(?:comment[\s>]|\"comment\").*?<\/div>//igs; |
681 |
|
|
$tmp =~ s,</*font[^>]+>,,ig; |
682 |
|
|
return $tmp; |
683 |
dpavlin |
1.1 |
} |
684 |
|
|
|
685 |
|
|
############################################################################## |
686 |
|
|
# make transparent 1x1 gif (for layout tricks) |
687 |
|
|
sub make_dotgif { |
688 |
|
|
@dot_gif=(71,73,70,56,57,97,1,0,1,0,128,0,0,192,192,192,0,0,0,33, |
689 |
|
|
249,4,1,0,0,0,0,44,0,0,0,0,1,0,1,0,0,2,2,68,1,0,59); |
690 |
|
|
open(GIF,"> $_[0]") || die "can't write gif $_[0]: $!"; |
691 |
|
|
my $dotgif; |
692 |
|
|
foreach (@dot_gif) { |
693 |
|
|
$dotgif.=chr($_); |
694 |
|
|
} |
695 |
|
|
print GIF $dotgif; |
696 |
|
|
close(GIF); |
697 |
|
|
} |
698 |
|
|
|
699 |
|
|
############################################################################## |
700 |
|
|
# make slide progress bar |
701 |
|
|
sub make_progress_bar { |
702 |
|
|
my ($nr,$total) = @_; |
703 |
|
|
|
704 |
|
|
my $pcnt_done=int($nr*100/$total); |
705 |
|
|
my $pcnt_left=100-$pcnt_done; |
706 |
|
|
|
707 |
dpavlin |
1.16 |
if ($progress_bar && uc($progress_bar) ne "NO") { |
708 |
dpavlin |
1.1 |
my $l=$r=" "; |
709 |
|
|
my $t="$nr of $total"; |
710 |
|
|
if ($pcnt_done > 50) { |
711 |
|
|
$l=$t; |
712 |
|
|
} else { |
713 |
|
|
$r=$t; |
714 |
|
|
} |
715 |
dpavlin |
1.15 |
$html='<table border="0" width="50%" cellpadding="0" cellspacing="0" align="right"><tr>'; |
716 |
|
|
if ($pcnt_done != 0) { |
717 |
|
|
$html.='<td width="'.$pcnt_done.'%" class="pcnt-done">'.$l.'</td>'; |
718 |
|
|
} |
719 |
|
|
if ($pcnt_left != 0) { |
720 |
|
|
$html.='<td width="'.$pcnt_left.'%" class="pcnt-left">'.$r.'</td>'; |
721 |
|
|
} |
722 |
|
|
$html.='</tr></table>'; |
723 |
dpavlin |
1.1 |
} else { |
724 |
|
|
$html="$loc_slide $nr $loc_of $total"; |
725 |
|
|
} |
726 |
|
|
|
727 |
|
|
return $html; |
728 |
|
|
} |
729 |
|
|
|
730 |
dpavlin |
1.8 |
############################################################################## |
731 |
dpavlin |
1.13 |
# remove anchors <a href...> from html (for titles) |
732 |
dpavlin |
1.8 |
sub remove_anchor { |
733 |
dpavlin |
1.10 |
my $tmp = $_[0]; |
734 |
|
|
$tmp =~ s/(.*)<A[^>]*>(.*)<\/A>(.*)/$1$2$3/ig; |
735 |
|
|
return $tmp; |
736 |
dpavlin |
1.13 |
} |
737 |
|
|
|
738 |
|
|
############################################################################## |
739 |
dpavlin |
1.20 |
# extract files referenced in presentation and remove dirs from slide html |
740 |
dpavlin |
1.13 |
|
741 |
|
|
sub extract_files { |
742 |
dpavlin |
1.20 |
my $tmp = $slide = $_[0]; |
743 |
dpavlin |
1.17 |
while ($tmp =~ s/href="*([^"\s]+)"*//ism || |
744 |
|
|
$tmp =~ s/src="*([^"\s]+)"*//ism) { |
745 |
dpavlin |
1.13 |
if ("$1" !~ m/[hf]t?tp:/ && -f "$1" && !grep(/$1/,@pack_additional)) { |
746 |
dpavlin |
1.20 |
my $file=$1; |
747 |
|
|
push @pack_additional,$file; |
748 |
|
|
if ($file =~ m,^(.+)/([^/]+),) { |
749 |
|
|
my ($d,$f) = ($1,$2); |
750 |
|
|
$slide =~ s,${d}/${f},${f},g; |
751 |
|
|
} |
752 |
dpavlin |
1.13 |
} |
753 |
|
|
} |
754 |
dpavlin |
1.20 |
return $slide; |
755 |
dpavlin |
1.8 |
} |
756 |
dpavlin |
1.19 |
|
757 |
|
|
############################################################################## |
758 |
|
|
# check tags in slide |
759 |
|
|
# based on code from hindent 1.1.2 by Paul Balyoz <pab@domtools.com> |
760 |
|
|
|
761 |
|
|
sub init_nesttag { |
762 |
|
|
# Tags that require their own end tag <TAG>...</TAG> we will nest them |
763 |
|
|
# properly: (WARNING, you must use lower-case here) |
764 |
|
|
# All other tags (not on this list) will be ignored for indenting purposes. |
765 |
|
|
return ( |
766 |
|
|
'html' => 1, |
767 |
|
|
'head' => 1, |
768 |
|
|
'body' => 1, |
769 |
|
|
'title' => 1, |
770 |
|
|
|
771 |
|
|
'a' => 1, |
772 |
|
|
|
773 |
|
|
'table' => 1, |
774 |
|
|
'tr' => 1, |
775 |
|
|
'th' => 1, |
776 |
|
|
'td' => 1, |
777 |
|
|
|
778 |
|
|
'form' => 1, |
779 |
|
|
'select' => 1, |
780 |
|
|
'textarea' => 1, |
781 |
|
|
|
782 |
|
|
# 'p' => 1, Don't do this one because many people use <P> but not </P> |
783 |
|
|
'ul' => 1, |
784 |
|
|
'ol' => 1, |
785 |
|
|
'dl' => 1, |
786 |
|
|
'blockquote' => 1, |
787 |
|
|
'center' => 1, |
788 |
|
|
'div' => 1, |
789 |
|
|
|
790 |
|
|
'font' => 1, |
791 |
|
|
'pre' => 1, |
792 |
|
|
'tt' => 1, |
793 |
|
|
'i' => 1, |
794 |
|
|
'b' => 1, |
795 |
|
|
'u' => 1, |
796 |
|
|
'strike' => 1, |
797 |
|
|
'big' => 1, |
798 |
|
|
'small' => 1, |
799 |
|
|
'sub' => 1, |
800 |
|
|
'sup' => 1, |
801 |
|
|
'em' => 1, |
802 |
|
|
'strong' => 1, |
803 |
|
|
'dfn' => 1, |
804 |
|
|
'code' => 1, |
805 |
|
|
'samp' => 1, |
806 |
|
|
'kbd' => 1, |
807 |
|
|
'var' => 1, |
808 |
|
|
'cite' => 1, |
809 |
|
|
|
810 |
|
|
'h1' => 1, |
811 |
|
|
'h2' => 1, |
812 |
|
|
'h3' => 1, |
813 |
|
|
'h4' => 1, |
814 |
|
|
'h5' => 1, |
815 |
|
|
'h6' => 1, |
816 |
|
|
|
817 |
|
|
'applet' => 1, |
818 |
|
|
|
819 |
|
|
'map' => 1, |
820 |
|
|
|
821 |
|
|
'frameset' => 1, |
822 |
|
|
'noframes' => 1, |
823 |
|
|
); |
824 |
|
|
} |
825 |
|
|
|
826 |
|
|
sub check_tags { |
827 |
|
|
my $tmp = $_[0]; |
828 |
|
|
my @tagstack; |
829 |
|
|
my $level=0; |
830 |
|
|
|
831 |
|
|
while ($tmp =~ /<(.*?)>/gsm) { |
832 |
|
|
my $tag=$1; $tag=~s/\s.+//g; |
833 |
|
|
# if regular tag, push it on stack; if end-tag, pop it off stack. |
834 |
|
|
# but don't do any of this if it's not a special "nesting" tag! |
835 |
|
|
if ($tag !~ m,^/,) { |
836 |
|
|
if ($nesttag{lc($tag)}) { |
837 |
|
|
push @tagstack,$tag; |
838 |
|
|
$level++; # remember how much for later |
839 |
|
|
} |
840 |
|
|
} else { |
841 |
|
|
$tag =~ s,^/,,; # convert this end-tag to a begin-tag |
842 |
|
|
$tag = lc($tag); |
843 |
|
|
if ($nesttag{lc($tag)}) { |
844 |
|
|
# throw away tags until we find a match |
845 |
|
|
if ($#tagstack > -1) { |
846 |
|
|
while ($tag ne lc(pop @tagstack)) { |
847 |
|
|
$level--; # we threw away extra tags |
848 |
|
|
last if $#tagstack <= 0; |
849 |
|
|
} |
850 |
|
|
$level--; # we threw away extra tags |
851 |
|
|
if ($level < 0) { |
852 |
|
|
print STDERR "WARNING: more end than begin tags around </$tag> !\n"; |
853 |
|
|
} |
854 |
|
|
} |
855 |
|
|
} |
856 |
|
|
} |
857 |
|
|
} |
858 |
|
|
|
859 |
|
|
if ($level > 0) { |
860 |
|
|
print STDERR "WARNING: level=$level, ", $#tagstack+1," tags left on stack after done parsing! Specifically:\n<",join("> <",@tagstack),">\n"; |
861 |
|
|
} |
862 |
|
|
|
863 |
|
|
} |
864 |
|
|
|