]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blob - IkiWiki/Plugin/table.pm
26e434b1fa2264fdb9c24ceb8031775bf49f64fe
[git.ikiwiki.info.git] / IkiWiki / Plugin / table.pm
1 package IkiWiki::Plugin::table;
2 # by Victor Moral <victor@taquiones.net>
4 use warnings;
5 use strict;
7 use IkiWiki;
8 use IkiWiki::Plugin::mdwn;
10 sub import { #{{{
11         hook(type => "preprocess", id => "table", call => \&preprocess);
12 } # }}}
14 sub preprocess (@) { #{{{
15         my %params =(
16                 format  => 'auto',
17                 header  => 'yes',
18                 @_
19         );
21         if (exists $params{file}) {
22                 if (! $pagesources{$params{file}}) {
23                         return "[[table ".gettext("cannot find file")."]]";
24                 }
25                 $params{data} = readfile(srcfile($params{file}));
26         }
28         if (lc $params{format} eq 'auto') {
29                 # first try the more simple format
30                 if (is_dsv_data($params{data})) {
31                         $params{format} = 'dsv';
32                 }
33                 else {
34                         $params{format} = 'csv';
35                 }
36         }
38         my @data;
39         if (lc $params{format} eq 'csv') {
40                 @data=split_csv($params{data}, $params{delimiter});
41         }
42         elsif (lc $params{format} eq 'dsv') {
43                 @data=split_dsv($params{data}, $params{delimiter});
44         }
45         else {
46                 return "[[table ".gettext("unknown data format")."]]";
47         }
49         my $header;
50         if (lc($params{header}) eq "yes") {
51                 $header=shift @data;
52         }
53         if (! @data) {
54                 return "[[table ".gettext("empty data")."]]";
55         }
57         my @lines;
58         push @lines, defined $params{class}
59                         ? "<table class=\"".$params{class}.'">'
60                         : '<table>';
61         push @lines, "\t<thead>","\t\t<tr>",
62                 (map {
63                         "\t\t\t<th>".
64                         htmlize($params{page}, $params{destpage}, $_).
65                         "</th>"
66                 } @$header),
67                 "\t\t</tr>", "\t</thead>" if defined $header;
68         push @lines, "\t<tbody>";
69         foreach my $record (@data) {
70                 push @lines, "\t\t<tr>",
71                         (map {
72                                 "\t\t\t<td>".
73                                 htmlize($params{page}, $params{destpage}, $_).
74                                 "</td>"
75                         } @$record),
76                         "\t\t</tr>";
77         }
78         push @lines, "\t</tbody>" if defined $header;
79         push @lines, '</table>';
80         my $html = join("\n", @lines);
82         if (exists $params{file}) {
83                 return $html."\n\n".
84                         htmllink($params{page}, $params{destpage}, $params{file},
85                                 linktext => gettext('Direct data download'));
86         }
87         else {  
88                 return $html;
89         }            
90 } #}}}
92 sub is_dsv_data ($) { #{{{
93         my $text = shift;
95         my ($line) = split(/\n/, $text);
96         return $line =~ m{.+\|};
97 }
99 sub split_csv ($$) { #{{{
100         my @text_lines = split(/\n/, shift);
101         my $delimiter = shift;
103         eval q{use Text::CSV};
104         error($@) if $@;
105         my $csv = Text::CSV->new({ 
106                 sep_char        => defined $delimiter ? $delimiter : ",",
107                 binary          => 1,
108         }) || error("could not create a Text::CSV object");
109         
110         my $l=0;
111         my @data;
112         foreach my $line (@text_lines) {
113                 $l++;
114                 if ($csv->parse($line)) {
115                         push(@data, [ $csv->fields() ]);
116                 }
117                 else {
118                         debug(sprintf(gettext('parse fail at line %d: %s'), 
119                                 $l, $csv->error_input()));
120                 }
121         }
123         return @data;
124 } #}}}
126 sub split_dsv ($$) { #{{{
127         my @text_lines = split(/\n/, shift);
128         my $delimiter = shift;
129         $delimiter="|" unless defined $delimiter;
131         my @data;
132         foreach my $line (@text_lines) {
133                 push @data, [ split(/\Q$delimiter\E/, $line) ];
134         }
135     
136         return @data;
137 } #}}}
139 sub htmlize ($$$){ #{{{
140         my $page = shift;
141         my $destpage = shift;
142         my $text = shift;
144         $text=IkiWiki::htmlize($page, pagetype($pagesources{$page}),
145                 IkiWiki::preprocess($page, $destpage, $text));
147         # hack to get rid of enclosing junk added by markdown
148         $text=~s!^<p>!!;
149         $text=~s!</p>$!!;
150         chomp $text;
152         return $text;