2 # Common functions for HTML/XHTML output generation
3 # Copyright (C) 2003 Jan Kratochvil <project-www.jankratochvil.net@jankratochvil.net>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; exactly version 2 of June 1991 is required
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 require 5.6.0; # at least 'use warnings;' but we need some 5.6.0+ modules anyway
21 our $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; };
28 use Carp qw(cluck confess);
32 our @ISA=qw(My::Web Exporter);
37 # Do not: path_abs_disk("/project/SUBDIRS");
38 # as we would need $W->{"r"} for the possibly relative path resolving.
39 return My::Web::dir_top_abs_disk()."/project/SUBDIRS";
45 my($class,$ListItem,%args)=@_;
47 print "<h1>".$W->{"title"}."</h1>\n";
48 do { print $_ if $_; } for ($args{"project_text_after_title"});
49 print $ListItem->{"description"};
51 print($args{"before_project_data"}||"");
52 return if $args{"no_project_data"};
54 {"key"=>"summary","text"=>"Summary"},
55 {"key"=>"license","text"=>"License","format"=>sub ($) {
57 "PD"=>"Public Domain",
58 "GPL"=>a_href("http://www.gnu.org/licenses/gpl.html","GNU General Public License"),
59 "LGPL"=>a_href("http://www.gnu.org/licenses/lgpl.html","GNU Lesser General Public License"),
64 {"key"=>"maintenance","text"=>"State","format"=>sub ($) {
66 "active"=>"Ready to use. Project is now actively developed.",
67 "ready"=>"Ready to use. Maintained.",
68 "dead"=>"Dead code, no longer supported.",
69 "merge"=>"Functions belong to existing other project.",
70 "obsolete"=>"Obsoleted.",
71 "update"=>"Package needs updating to recent software.",
72 "accepted"=>"This patch got already integrated by the original package maintainer.",
73 "pending"=>"Patch is ready to be applied to the mainstream.",
74 "ignored"=>"Patch was ignored. It is not applied in the mainstream.",
78 for ($known{($_[0]=~/^([^-]*)-?/)[0] || ""}) {
84 {"key"=>"aminet","text"=>a_href('http://www.aminet.net/','Aminet'),"format"=>sub ($) {
86 a_href('http://www.aminet.net/'.$_[0].".lha",$_[0].".lha"),
87 "(".a_href('http://www.aminet.net/'.$_[0].".readme","readme").")");
89 {"key"=>qr(^download\b),"text"=>sub ($) {
92 return "Download".$_[0];
95 return a_href($_[0],CGI::escapeHTML(File::Basename::basename($_[0])),"size"=>2);
97 {"key"=>qr(^link\b),"text"=>sub ($) {
102 return($_[0]=~/^<a\b/ ? $_[0] : a_href($_[0],CGI::escapeHTML($_[0])));
104 {"key"=>qr(^cvs\b),"text"=>sub ($) {
114 $branch=$1 if $val=~s/:(.*)//;
115 return join("<br />\n\t\t",
116 CGI::escapeHTML("cvs -d ".$W->{"pserver"}.":".$W->{"pserver_path"}." -z3"
117 ." checkout".(!$branch ? "" : " -r $branch -kk")
118 .($val!~m#/# ? "" : " -d ".File::Basename::basename($val))
121 map({ a_href($_->[1],$_->[0]); }
122 ["ViewCVS CVS repository",$W->{"project_viewcvs"}.$val."/".(!$branch ? "" : '?only_with_tag='.$branch)],
123 ["Download CVS snapshot" ,
124 $W->{"project_viewcvs"}.$val."/".File::Basename::basename($val).".tar.gz?tarball=1"
125 .(!$branch ? "" : '&only_with_tag='.$branch)],
126 ["CVS ChangeLog" ,"/project/ChangeLog.pm?cvs=$val"])));
128 {"key"=>"ownership","text"=>"Ownership"},
129 {"key"=>"sponsorship","text"=>"Sponsorship"},
130 {"key"=>"language","text"=>"Programming language","format"=>sub ($) {
131 return a_href("http://java.sun.com/",CGI::escapeHTML($_[0]))
133 return a_href("http://www.php.net/",CGI::escapeHTML($_[0]))
141 my($tableit,$val,$key,$ListItem)=@_;
145 if ($tableit->{"text"}) {
147 $r.=(!ref $_ ? $_ : &{$_}($key)) for ($tableit->{"text"});
150 if ($tableit->{"format"}) {
151 do { $val=$_ if defined $_; } for (&{$tableit->{"format"}}($val,$key));
153 return join("",map("<tr><td>".$_->[0]."</td><td>".$_->[1]."</td></tr>\n",@$val))
160 print '<table border="0" class="print_project">'."\n";
161 for my $tableit (@table) {
162 if (!ref $tableit->{"key"}) {
163 print tableit_func($tableit,$ListItem->{$tableit->{"key"}},$tableit->{"key"},$ListItem)
164 if $ListItem->{$tableit->{"key"}} && !$used_key{$tableit->{"key"}}++;
167 for my $key (@{$ListItem->{"keys_array"}}) {
168 my $keyregex=$tableit->{"key"};
169 next if $key!~/$keyregex/;
170 print tableit_func($tableit,$ListItem->{$key},$key,$ListItem);
178 sub hashlikearray_get_keys(@)
180 my(@hashlikearray)=@_;
183 while (@hashlikearray) {
184 push @r,shift @hashlikearray; # key
185 shift @hashlikearray; # val
190 sub project_arrayref_to_hashref($$)
192 my($self,$arrayref)=@_;
194 Wuse 'My::Hash::Sub::Readonly';
196 tie %$r,"My::Hash::Sub::Readonly",(
198 "keys_array"=>[ hashlikearray_get_keys(@$arrayref) ],
205 my($class,$hashref)=@_;
207 cluck if !$hashref->{"name"} || !$hashref->{"summary"};
208 return $hashref->{"name"}.": ".$hashref->{"summary"},
211 # Returns: hashref if !wantarray(), list if wantarray().
219 My::Web->make_file(LIST_FILENAME());
221 open F,LIST_FILENAME() or do {
222 cluck "Error opening \"".LIST_FILENAME()."\": $!";
225 my @r=split(" ",do { undef $/; <F>; });
226 close F or cluck "Error closing \"".LIST_FILENAME()."\": $!";
227 cluck "No projects found?" if !@r;
229 %list_cache=map(($_=>1),@list_cache);
231 return \%list_cache if !wantarray();
235 # Returns: hashlist of hashrefs if !$name.
236 sub name_to_hashref($;$)
240 cluck if !wantarray() && !$name;
241 # Do not cache the result to get all the items &Wrequire-mapped.
242 return map(($_=>$class->name_to_hashref($_)),$class->list()) if !$name;
243 cluck join(" ","Project name \"$name\" not listed in 'list_cache':",$class->list())
244 if !$class->list()->{$name};
245 # Do not cache &Wrequire to gets its $Id$ markers / usage map.
246 Wrequire "project::${name}::Index";
248 if (!$cache{$name}) {
249 my $arrayref=eval('\@project::'.$name.'::Index::ListItem');
250 do { warn "Broken project/$name/Index.pm"; return undef(); } if !@$arrayref;
251 $cache{$name}=$class->project_arrayref_to_hashref($arrayref);
253 return $cache{$name};
256 # $args{"ListItem"}=\%...;
261 $args{"__PACKAGE__"}||=caller();
262 $args{"project_name"}||=($args{"__PACKAGE__"}=~/^project::(\w+)::Index$/)[0]
263 or cluck "Error finding project name of the package: ".$args{"__PACKAGE__"};
264 my $ListItem=$class->name_to_hashref($args{"project_name"});
265 my $W=$class->SUPER::init(
266 "title"=>$class->title($ListItem),
267 map(("rel_$_"=>'/project/Rel.pm?rel='.$_.'&project='.$args{"project_name"}),qw(prev next)),
268 "rel_up"=>'/project/',
269 # "rel_start"=>"/", # TODO:homepage
271 "head"=>($args{"head"}||"").<<"HERE",
272 <link rel="stylesheet" type="text/css" href="@{[ uri_escaped(path_web "/project/Lib.css") ]}" />
274 "heading_novskip"=>1,
277 print $class->platforms($ListItem->{"platform"});
278 $class->print_project($ListItem,%args);
284 "unixdevel"=>"UNIX-devel",
294 my($class,$view_selected)=@_;
298 my($current,$href,$content)=@_;
300 return a_href($href,$content) if $current ne $view_selected;
301 return "<b>".$content."</b> (current)";
305 <h1>Project List of @{[ a_href 'http://www.jankratochvil.net/','Jan Kratochvil' ]}</h1>
308 <li>@{[ &{$view}('Detailed' ,'/project/','Detailed project listing per platform') ]}</li>
309 <li>@{[ &{$view}('BriefPlatform','/project/List.pm?platform=platform',
310 'Brief project listing per platform') ]}</li>
311 <li>@{[ &{$view}('BriefUnified' ,'/project/List.pm',
312 'Unified brief project listing') ]}</li>
320 my($class,$platform_selected,%args)=@_;
323 $r.='<table border="0" width="100%"><tr><td align="center">'."\n";
324 $r.='<table><tr>'."\n";
326 $r.='<table border="1" style="border-collapse: collapse; border-style: solid; border-width: 1px;">'."\n";
328 $r.='<td style="padding: 5px; font-weight: bold;">'."\n";
335 $r.='<table border="1" style="border-collapse: collapse; border-style: solid;">'."\n";
337 my @platforms=@platforms;
339 my $platform_sym =shift @platforms;
340 my $platform_name=shift @platforms;
341 my $chosen=($platform_selected && $platform_selected eq $platform_sym);
342 $r.='<td style="padding: 5px;">';
343 $r.=a_href((!$platform_selected ? "" : "/project/").'#'.$platform_sym,$platform_name,
345 ? 'style="text-decoration: underline; font-weight: bold;"'
346 : 'style="text-decoration: inherit; /* revoke underline */"'));
352 $r.='</tr></table>'."\n";
353 $r.='</td></tr></table>'."\n";
354 if (!$args{"novskip"}) {
356 $r.=My::Web::vskip "6ex";
365 my $item=$class->name_to_hashref($name);
366 my $title=$class->title($item);
369 print $class->platforms($item->{"platform"},"novskip"=>1);
371 $r.='<table border="0" width="100%"><tr><td align="center">'."\n";
372 $r.='<table border="1" style="border-collapse: collapse; border-style: solid;">'."\n";
373 $r.='<tr><td style="font-size: larger;">'."\n";
374 $r.=a_href "/project/$name/",$title;
375 $r.='</td></tr>'."\n";
377 $r.='</td></tr></table>'."\n";