author | wenzelm |
Wed, 18 Oct 2000 23:33:04 +0200 | |
changeset 10255 | bb66874b4750 |
parent 9920 | 9734f2717203 |
permissions | -rwxr-xr-x |
9920
9734f2717203
improved WWW page generation (still somewhat experimental);
wenzelm
parents:
8056
diff
changeset
|
1 |
#!/usr/bin/perl -w |
8056 | 2 |
|
3 |
# Genpage - Webpage Generator. |
|
4 |
# |
|
5 |
# Copyright (C) Joe Vaughan <joev@freddyfrog.com> 1998-1999 |
|
6 |
# Some portions Copyright (C) Ronan Waide <waider@waider.ie> 1999 |
|
7 |
# Some portions Copyright (C) Rocco Caputo <troc@netrus.net> 1999 |
|
8 |
# |
|
9 |
# This program is free software; you can redistribute it and/or modify |
|
10 |
# it under the terms of the GNU General Public License as published by |
|
11 |
# the Free Software Foundation; either version 2 of the License, or |
|
12 |
# (at your option) any later version. |
|
13 |
# |
|
14 |
# This program is distributed in the hope that it will be useful, |
|
15 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
# GNU General Public License for more details. |
|
18 |
# |
|
19 |
# You should have received a copy of the GNU General Public License |
|
20 |
# along with this program; if not, write to the Free Software |
|
21 |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
22 |
||
23 |
$|=1; |
|
24 |
||
25 |
$version = "1.0b3"; |
|
26 |
||
27 |
# following fix for Mac Perl submitted by Dair Grant <dair@webthing.net> |
|
28 |
# I shoulda thought of this, but I don't have a mac :) Thanks Dair. |
|
29 |
# |
|
30 |
# dair, construct a path procedurally |
|
31 |
sub build_path |
|
32 |
{ |
|
33 |
||
34 |
# Retrieve our parameters |
|
35 |
# |
|
36 |
my $thePath = $_[0]; |
|
37 |
my $theItem = $_[1]; |
|
38 |
||
39 |
||
40 |
||
41 |
# If we're running on a Mac, munge the path/item/separator |
|
42 |
# |
|
43 |
if ($^O eq "MacOS") |
|
44 |
{ |
|
45 |
$thePath =~ s/:$//; # Strip off trailing ':' |
|
46 |
$theItem =~ s/^:$//; # Drop theItem == ':' |
|
47 |
$pathDiv = ":"; # Use Mac separator |
|
48 |
} |
|
49 |
else |
|
50 |
{ |
|
51 |
$pathDiv = "/"; # Use Unix separator |
|
52 |
} |
|
53 |
||
54 |
||
55 |
||
56 |
# Return the path to the item |
|
57 |
# |
|
58 |
return($thePath . $pathDiv . $theItem); |
|
59 |
} |
|
60 |
||
61 |
||
62 |
||
63 |
# Some handy variables. |
|
64 |
$numfiles = 0; |
|
65 |
$numcontentfiles = 0; |
|
66 |
$numignoredfiles = 0; |
|
67 |
$numskippedfiles = 0; |
|
68 |
$numcpfiles = 0; |
|
69 |
$numdirfiles =0; |
|
70 |
||
71 |
use Getopt::Std; |
|
72 |
use File::Find; |
|
73 |
use File::Copy 'cp'; |
|
74 |
||
75 |
# Current Working Dir. |
|
76 |
$pwd = `pwd`; |
|
77 |
chomp ($pwd); |
|
78 |
||
79 |
getopts('dt:c:o:fqhi:') || die "Invalid args, use $0 -h for help\n"; |
|
80 |
||
81 |
# $opt_d is debug flag |
|
82 |
# $opt_t is template file. If not set, use standard template. |
|
83 |
# $opt_c is content directory. If not set, use standard content dir. |
|
84 |
# $opt_o is output dir, if not set, use standard output dir. |
|
85 |
# $opt_q sets quiet mode (no stdout output) |
|
86 |
# $opt_f sets a force flag - force generation even if output file is present |
|
87 |
# and newer. |
|
88 |
# $opt_h runs usage and exits |
|
89 |
||
90 |
# dair, build paths procedurally |
|
91 |
$opt_t ||= build_path("", "layout") . build_path("", "template.html"); |
|
92 |
$opt_c ||= build_path("", "content"); |
|
93 |
$opt_o ||= build_path("", "www"); |
|
94 |
$opt_f ||= 0; |
|
95 |
$opt_d ||= 0; |
|
96 |
$opt_q ||= 0; |
|
97 |
$opt_h ||= 0; |
|
98 |
$opt_i ||= 'CVS|.*,v$'; |
|
99 |
||
100 |
# dair, build paths procedurally |
|
101 |
$opt_t = build_path($pwd, $opt_t); |
|
102 |
$opt_c = build_path($pwd, $opt_c); |
|
103 |
$opt_o = build_path($pwd, $opt_o); |
|
104 |
||
105 |
||
106 |
if ($opt_h) { &usage; } |
|
107 |
||
108 |
if (!$opt_q) { |
|
109 |
print "Genpage, version $version starting run...\n"; |
|
110 |
} |
|
111 |
||
112 |
if ($opt_d) { print "pwd = $pwd\n"; } |
|
113 |
||
114 |
#Swallow template file whole... |
|
115 |
open( TEMPLATE, "<$opt_t" ) || die "Can\'t open template file $opt_t: $!\n"; |
|
116 |
{ |
|
117 |
local $/; |
|
118 |
undef $/; |
|
119 |
$template = <TEMPLATE>; |
|
120 |
close( TEMPLATE ); |
|
121 |
} |
|
122 |
if (!$opt_q) {print "Using template file: $opt_t\n";} |
|
123 |
||
124 |
# Go through files in content dir and if it's a content file then |
|
125 |
# process it otherwise, copy it (and it's dir structure) to the output dir. |
|
126 |
||
127 |
# if the output dir doesn't exist, create it. |
|
128 |
if (! -d $opt_o) |
|
129 |
{ |
|
130 |
mkdir $opt_o, 0755; |
|
131 |
if (!$opt_q) |
|
132 |
{ |
|
133 |
print "Creating output directory: $opt_o\n"; |
|
134 |
} |
|
135 |
} |
|
136 |
||
137 |
if (!$opt_q) |
|
138 |
{ |
|
139 |
print "Processing files:\n"; |
|
140 |
} |
|
141 |
||
142 |
if (! -d $opt_c) { die "Can\'t open content dir\n" } |
|
143 |
||
144 |
find( \&process_file, $opt_c ); |
|
145 |
||
146 |
if (!$opt_q) |
|
147 |
{ |
|
148 |
#numfiles reports one too many... |
|
149 |
$numfiles--; |
|
150 |
print "\nFinished.\n\n"; |
|
151 |
print "Run Summary.\n===========\n"; |
|
152 |
print "$numfiles total files and directories processed.\n"; |
|
153 |
print "$numcontentfiles content files parsed.\n"; |
|
154 |
print "$numskippedfiles content files skipped.\n"; |
|
155 |
print "$numcpfiles files copied.\n"; |
|
156 |
print "$numdirfiles directories created\n"; |
|
157 |
print "$numignoredfiles files or directories ignored.\n"; |
|
158 |
} |
|
159 |
||
160 |
exit; |
|
161 |
||
162 |
############################################################################## |
|
163 |
# Process_file the current file. |
|
164 |
############################################################################## |
|
165 |
sub process_file |
|
166 |
{ |
|
167 |
if (!$opt_q) |
|
168 |
{ |
|
169 |
print "."; |
|
170 |
} |
|
171 |
||
172 |
$numfiles++; |
|
173 |
my $filename = $_; |
|
174 |
my $dir = $File::Find::dir; |
|
175 |
(undef,$reldir) = split( $opt_c, $dir); |
|
176 |
if (!defined ($reldir) ) { $reldir = ""; } |
|
177 |
||
178 |
# dair, build paths procedurally |
|
179 |
$outdir = build_path($opt_o, $reldir); |
|
180 |
$outfile = build_path($outdir, $filename); |
|
181 |
$infile = build_path($dir, $filename); |
|
182 |
||
183 |
# Ignore CVS stuff, ./ etc. |
|
184 |
if ($infile =~ /$opt_i/) { |
|
185 |
$numignoredfiles++; |
|
186 |
return; |
|
187 |
} |
|
188 |
||
189 |
# Find returns ./ in each directory... avoid. |
|
190 |
||
191 |
if ($infile =~ /\/.$/) { |
|
192 |
return; |
|
193 |
} |
|
194 |
||
195 |
# Ok, If the file is a dir, we create it (if necessary) |
|
196 |
# if it's a content file, we parse it, otherwise, we |
|
197 |
# copy it to the appropriate location. |
|
198 |
||
199 |
if ( -d $infile ) { |
|
200 |
if ($opt_d) { print "Making dir $outfile\n"; }; |
|
201 |
mkdir $outfile, 0755 unless -d $outfile; |
|
202 |
$numdirfiles++; |
|
203 |
return; |
|
204 |
} |
|
205 |
||
206 |
if ($filename =~ /^(.*)\.content$/) |
|
207 |
{ |
|
208 |
||
209 |
# dair, build paths procedurally |
|
210 |
$outfile = build_path($outdir, "$1.html"); |
|
211 |
||
212 |
if ($opt_d) {print "Parsing: $infile\n Outputing to: $outfile\n";}; |
|
213 |
process_content($infile,$outfile); |
|
214 |
} |
|
215 |
else |
|
216 |
{ |
|
217 |
if ($opt_d) { print "Copying: $infile => $outfile\n"; }; |
|
218 |
cp($infile,$outfile); |
|
219 |
$numcpfiles++; |
|
220 |
} |
|
221 |
$_ = $filename; # because we broke it... |
|
222 |
} |
|
223 |
||
224 |
############################################################################## |
|
225 |
# Process the tags in the template, substituting in the content file |
|
226 |
# components and other things like inline function definitions and |
|
227 |
# "include" directives |
|
228 |
############################################################################## |
|
229 |
||
230 |
sub process_content |
|
231 |
{ |
|
232 |
||
233 |
$inputfile = shift; |
|
234 |
$outputfile = shift; |
|
235 |
my @content = ""; |
|
236 |
||
237 |
$temp = $template; |
|
238 |
||
239 |
if ($opt_d) { print "processing $inputfile to $outputfile\n";} |
|
240 |
||
241 |
# Make-like check for last modification times to see if it's necessary |
|
242 |
# to re-gen this page. |
|
243 |
||
244 |
if ( -f $outputfile) |
|
245 |
{ |
|
246 |
||
247 |
if (!$opt_f && ( -M $outputfile < -M $inputfile)) |
|
248 |
{ |
|
249 |
$numskippedfiles++; |
|
250 |
if ($opt_d) { |
|
251 |
print "skipping $inputfile because $outputfile is newer\n"; |
|
252 |
} |
|
253 |
return; |
|
254 |
} |
|
255 |
} |
|
256 |
# Read content file |
|
257 |
open( CONTENT, "<$inputfile" ) || die $!; |
|
258 |
@content = <CONTENT>; |
|
259 |
close( CONTENT ); |
|
260 |
||
261 |
$numcontentfiles++; |
|
262 |
||
263 |
undef %page; |
|
264 |
undef $tag; |
|
265 |
foreach $line ( @content ) |
|
266 |
{ |
|
267 |
if ( $line =~ /^\s*\%(.+)\%/ ) |
|
268 |
{ |
|
269 |
$tag = $1; |
|
270 |
next; |
|
271 |
} |
|
272 |
next if !defined( $tag ); |
|
273 |
||
274 |
$line .= "\n" if $line !~ /\n$/; |
|
275 |
||
276 |
if ( defined( $page{ $tag } )) |
|
277 |
{ |
|
278 |
$page{ $tag } .= $line; |
|
279 |
} |
|
280 |
else |
|
281 |
{ |
|
282 |
$page{ $tag } = $line; |
|
283 |
} |
|
284 |
} |
|
285 |
||
286 |
open( HTML, ">$outputfile" ) || die $1; |
|
287 |
||
288 |
while ($temp =~ /^(.*?)<!--\s*_GP_\s*(.*?)\s*-->(.*)$/s) |
|
289 |
{ |
|
290 |
local $replacement = ""; |
|
291 |
my ($left, $middle, $right) = ($1, $2, $3); |
|
292 |
if (!defined($replacement = eval ($middle))) |
|
293 |
{ |
|
294 |
$replacement = ""; |
|
295 |
} |
|
296 |
||
297 |
if ($@) { |
|
298 |
$middle =~ s/\s+/ /g; |
|
299 |
print STDERR "error evaluating { $middle }: $@\n"; |
|
300 |
} |
|
301 |
else { |
|
302 |
if ($opt_d) { |
|
303 |
print "evaluation output: $replacement\n"; |
|
304 |
} |
|
305 |
} |
|
306 |
||
307 |
$temp = $left . $replacement . $right; |
|
308 |
} |
|
309 |
print HTML $temp; |
|
310 |
close( HTML ); |
|
311 |
} |
|
312 |
||
313 |
||
314 |
sub include |
|
315 |
{ |
|
316 |
my ($file) = shift; |
|
317 |
my ($section) = shift; |
|
318 |
||
319 |
if ($opt_d) { |
|
320 |
print "include: file = $file\n"; |
|
321 |
} |
|
322 |
if (!open( INCLUDE, "<$file" )) { |
|
323 |
return "<!-- include: file not found: $file -->"; |
|
324 |
} |
|
325 |
||
326 |
if (defined($section)) { |
|
327 |
undef %incpage; |
|
328 |
undef $inctag; |
|
329 |
||
330 |
@content = <INCLUDE>; |
|
331 |
close (INCLUDE); |
|
332 |
||
333 |
foreach $line ( @content ) |
|
334 |
{ |
|
335 |
if ( $line =~ /^\s*\%(.+)\%/ ) |
|
336 |
{ |
|
337 |
$inctag = $1; |
|
338 |
next; |
|
339 |
} |
|
340 |
next if !defined( $inctag ); |
|
341 |
$line .= "\n" if $line !~ /\n$/; |
|
342 |
||
343 |
if ( defined( $incpage{ $inctag } )) |
|
344 |
{ |
|
345 |
$incpage{ $inctag } .= $line; |
|
346 |
} |
|
347 |
else |
|
348 |
{ |
|
349 |
$incpage{ $inctag } = $line; |
|
350 |
} |
|
351 |
} |
|
352 |
if (defined( $incpage{$section}) ) { |
|
353 |
$inline = $incpage{$section}; |
|
354 |
} |
|
355 |
else { |
|
356 |
$inline = "<!-- include: no such section - $section - in $file -->"; |
|
357 |
} |
|
358 |
} |
|
359 |
else |
|
360 |
{ |
|
361 |
local $/; |
|
362 |
undef $/; |
|
363 |
$inline = <INCLUDE>; |
|
364 |
close( INCLUDE ); |
|
365 |
} |
|
366 |
return "$inline"; |
|
367 |
} |
|
368 |
||
369 |
sub content |
|
370 |
{ |
|
371 |
my $tag = shift; |
|
372 |
||
373 |
if ($opt_d) { print "content: tag = $tag\n"; } |
|
374 |
if (defined( $page{ $tag } )) |
|
375 |
{ |
|
376 |
$output = $page { $tag }; |
|
377 |
if ($opt_d) { print "content: output = $output\n"; } |
|
378 |
return "$output"; |
|
379 |
} |
|
380 |
else |
|
381 |
{ |
|
382 |
return "<!-- content: undefined tag: $tag -->"; |
|
383 |
} |
|
384 |
} |
|
385 |
||
386 |
sub version |
|
387 |
{ |
|
388 |
return ( "<a href=\"http://www.mnemonic.org/genpage/\">Genpage</a> - Version: $version" ); |
|
389 |
} |
|
390 |
||
391 |
sub usage |
|
392 |
{ |
|
393 |
print <<EOT; |
|
394 |
usage: genpage [-dqfh] [-c <content dir>] [-o <output dir>] |
|
395 |
[-t <template file>] [ -i <ignore regexp> ] |
|
396 |
||
397 |
||
398 |
-d debug mode. Turn on debugging (very verbose!) |
|
399 |
-q quiet mode. Don't print anything while running. |
|
400 |
-f force mode. Force the parsing of content files. |
|
401 |
-h help. Print this help text. |
|
402 |
-c <content dir> The directory where your content tree exists. |
|
403 |
Defaults to ./content. |
|
404 |
-o <output dir> The directory to put the output website. |
|
405 |
Defaults to ./www |
|
406 |
-t <template file> The template to use to generate the site. |
|
407 |
Defaults to ./layout/template.html |
|
408 |
-i <ignore regexp> Regular expression telling genpage to ignore certain |
|
409 |
files or directories. defaults to "CVS|.*,v$" |
|
410 |
||
411 |
Genpage $version Copyright (C) Joe Vaughan <joev\@mnemonic.org> 1999 |
|
412 |
This program is released under the terms of the GNU Public License |
|
413 |
Please read the accompanying COPYING file for details. |
|
414 |
||
415 |
For detailed instructions on how to use Genpage, please consult the |
|
416 |
accompanying documentation. If you have questions, comments or |
|
417 |
suggestions for Genpage please contact the author. |
|
418 |
EOT |
|
419 |
exit; |
|
420 |
} |