add a simple summary to mediawiki edits
[scpubgit/System-Introspector-Report.git] / lib / System / Introspector / Report / Publish / MediaWiki / Producer.pm
1 package System::Introspector::Report::Publish::MediaWiki::Producer;
2 use Moo;
3 use HTML::Zoom;
4
5 sub render {
6   my ($self, $stream) = @_;
7   return $self->_clear_body(join "\n", map {
8     ref($_) ? $self->_render_table($_) : $_;
9   } @$stream);
10 }
11
12 sub _clear_body {
13   my ($self, $string) = @_;
14   $string =~ s{\n\n+}{\n\n}g;
15   return $string;
16 }
17
18 sub _wrap {
19   my ($self, $type, $id, $body) = @_;
20   chomp $body;
21   return join "\n",
22     sprintf('<!-- SI:%s begin %s -->', uc($type), $id),
23     $body,
24     sprintf('<!-- SI:%s end %s -->', uc($type), $id),
25 }
26
27 sub _render_table {
28   my ($self, $report) = @_;
29   my $id     = $report->{id};
30   my $str_id = ref($id) ? join(':', @$id) : $id;
31   my $markup = $self->_load_markup;
32   $markup = $self->_apply_table_head($markup, $report);
33   $markup = $self->_apply_table_body($markup, $report);
34   my $description = $report->{description} || [''];
35   return join "\n",
36     $self->_wrap('title', $str_id, $self->_render_title($report)),
37     @$description,
38     $self->_wrap('table', $str_id, $markup->to_html),
39     '';
40 }
41
42 sub _render_title {
43   my ($self, $report) = @_;
44   return sprintf '== %s ==', $report->{title};
45 }
46
47 my $_prepare_column_content = sub {
48   my ($content) = @_;
49   return ''
50     unless defined $content;
51   my @lines = split qr{\n}, $content;
52   return ''
53     unless @lines;
54   if (@lines == 1) {
55     return $content;
56   }
57   else {
58     my ($first, @rest) = @lines;
59     return HTML::Zoom->from_events([
60       { type => 'TEXT', raw => $first },
61       map {
62         my $string = $_;
63         ( @{ HTML::Zoom->from_html('<br/>')->to_events },
64           { type => 'TEXT', raw => $string });
65       } @rest,
66     ]);
67   }
68 };
69
70 sub _apply_table_body {
71   my ($self, $markup, $report) = @_;
72   my $index = 0;
73   my $rows  = $report->{rows};
74   my @cols  = map $_->{key}, @{$report->{columns}};
75   return $markup->repeat('.data-row', sub {
76     return HTML::Zoom::CodeStream->new({
77       code => sub {
78         return if $index > $#$rows;
79         my $row = $rows->[$index++];
80         return sub {
81           $_->repeat('td', [ map {
82             my $col_idx = $_;
83             my $col = $cols[$_];
84             my $value = $row->{$col};
85             sub {
86               $_->apply_if($col !~ m{^__}, sub {
87                   $_->add_to_attribute('td', class => "si-column-$col");
88                 })
89                 ->replace_content('td', $value->$_prepare_column_content)
90                 ->apply_if($col_idx != $#cols, sub {
91                   $_->add_after('td', "\n    ");
92                 });
93             };
94           } 0 .. $#cols ]);
95         };
96       },
97     });
98   })->memoize;
99 }
100
101 my $_trim = sub {
102   my $string = shift;
103   $string =~ s{(?:^\s+|\s+$)}{}g;
104   return $string;
105 };
106
107 sub _apply_table_head {
108   my ($self, $markup, $report) = @_;
109   my @cols = @{$report->{columns}};
110   return $markup
111     ->repeat('th', [map {
112       my $col_idx = $_;
113       my $col = $cols[$_];
114       my $label = $col->{label};
115       sub {
116         $_->apply_if($col->{key} !~ m{^__}, sub {
117             $_->add_to_attribute('th', class => 'si-colhead-' . $col->{key});
118           })
119           ->replace_content('th', defined($label) ? $label->$_trim : 'Unnamed')
120           ->apply_if($col_idx != $#cols, sub {
121             $_->add_after('th', "\n    ");
122           });
123       };
124     } 0 .. $#cols ])
125     ->memoize;
126 }
127
128 my $_template = do {
129   local $/;
130   scalar <DATA>;
131 };
132
133 sub _load_markup {
134   return HTML::Zoom->from_html($_template);
135 }
136
137 1;
138
139 __DATA__
140 <table class="si-report">
141   <tr>
142     <th>Header</th>
143   </tr>
144   <tr class="data-row">
145     <td>Value</td>
146   </tr>
147 </table>