1 #!/usr/bin/perl -w |
|
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 } |
|