/[suikacvs]/test/html-webhacc/WebHACC/Result.pm
Suika

Contents of /test/html-webhacc/WebHACC/Result.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download)
Sun Jul 20 16:53:10 2008 UTC (16 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.1: +230 -32 lines
++ ChangeLog	20 Jul 2008 16:48:51 -0000
2008-07-21  Wakaba  <wakaba@suika.fam.cx>

	* cc.cgi: Errors and results are now handled by WebHACC::Result.
	Decode |uri| parameter as UTF-8.  HTTP header dump and
	input error are now handled by WebHACC::Input.

++ html/WebHACC/Language/ChangeLog	20 Jul 2008 16:53:06 -0000
2008-07-21  Wakaba  <wakaba@suika.fam.cx>

	* Base.pm (_get_cc_url, _encode_url_component): Remove (now
	supported by WebHACC::Output).

	* CSS.pm, CacheManifest.pm, DOM.pm, Default.pm,
	HTML.pm, WebIDL.pm, XML.pm: Error reporting is now delegated to
	WebHACC::Result.

++ html/WebHACC/ChangeLog	20 Jul 2008 16:50:41 -0000
2008-07-21  Wakaba  <wakaba@suika.fam.cx>

	* Input.pm (generate_transfer_sections, generate_http_header_section):
	New (partially comes from cc.cgi).

	* Output.pm (link): Call |start_tag| such that attributes
	can be set.
	(link_to_webhacc): New.
	(encode_url_component): From WebHACC::Language::Base.

	* Result.pm: Support for error outputting and result table
	generation.

1 package WebHACC::Result;
2 use strict;
3
4 sub new ($) {
5 return bless {}, shift;
6 } # new
7
8 sub output ($;$) {
9 if (@_ > 1) {
10 if (defined $_[1]) {
11 $_[0]->{output} = $_[1];
12 } else {
13 delete $_[0]->{output};
14 }
15 }
16
17 return $_[0]->{output};
18 } # output
19
20 sub add_error ($%) {
21 my ($self, %opt) = @_;
22
23 my $out = $self->output;
24
25 my $error_level = $opt{level};
26 if (not defined $error_level) {
27 $error_level = 'm'; ## NOTE: Unknown - an error of the implementation
28 } elsif ({
29 m => 1, s => 1, w => 1, i => 1, u => 1,
30 }->{$error_level}) {
31 #
32 } else {
33 $error_level = 'm'; ## NOTE: Unknown - an error of the implementation
34 }
35
36 my $error_layer = $opt{layer};
37 if (not defined $error_layer) {
38 $error_layer = 'syntax'; ## NOTE: Unknown - an error of the implementation
39 } elsif ({
40 transfer => 1,
41 encode => 1,
42 charset => 1,
43 syntax => 1,
44 structure => 1,
45 semantics => 1,
46 }->{$error_layer}) {
47 #
48 } else {
49 $error_layer = 'syntax'; ## NOTE: Unknown - an error of the implementation
50 }
51
52 my $error_type_text = $opt{type};
53
54 my $class = qq[level-$error_level layer-$error_layer];
55
56 $out->start_tag ('dt', class => $class);
57
58 ## URL
59
60 if (defined $opt{url}) {
61 $out->url ($opt{url});
62 }
63
64 ## Line & column number
65
66 my $line;
67 my $column;
68
69 if (defined $opt{node}) {
70 $line = $opt{node}->get_user_data ('manakai_source_line');
71 if (defined $line) {
72 $column = $opt{node}->get_user_data ('manakai_source_column');
73 } else {
74 if ($opt{node}->node_type == $opt{node}->ATTRIBUTE_NODE) {
75 my $owner = $opt{node}->owner_element;
76 if ($owner) {
77 $line = $owner->get_user_data ('manakai_source_line');
78 $column = $owner->get_user_data ('manakai_source_column');
79 }
80 } else {
81 my $parent = $opt{node}->parent_node;
82 if ($parent) {
83 $line = $parent->get_user_data ('manakai_source_line');
84 $column = $parent->get_user_data ('manakai_source_column');
85 }
86 }
87 }
88 }
89 unless (defined $line) {
90 if (defined $opt{token} and defined $opt{token}->{line}) {
91 $line = $opt{token}->{line};
92 $column = $opt{token}->{column};
93 } elsif (defined $opt{line}) {
94 $line = $opt{line};
95 $column = $opt{column};
96 }
97 }
98
99 if (defined $line) {
100 if (defined $column and $column > 0) {
101 $out->xref ('Line ' . $line, target => 'line-' . $line);
102 $out->text (' column ' . $column);
103 } else {
104 $line = $line - 1 || 1;
105 $out->xref ('Line ' . $line, target => 'line-' . $line);
106 }
107 }
108
109 ## Node path
110
111 if (defined $opt{node}) {
112 $out->html (' ');
113 $out->node_link ($opt{node});
114 }
115
116 if (defined $opt{index}) {
117 if ($opt{index_has_link}) {
118 $out->html (' ');
119 $out->xref ('Index ' . (0+$opt{index}),
120 target => 'index-' . (0+$opt{index}));
121 } else {
122 $out->text (' Index ' . (0+$opt{index}));
123 }
124 }
125
126 if (defined $opt{value}) {
127 $out->html (' ');
128 $out->code ($opt{value});
129 }
130
131 $out->start_tag ('dd', class => $class);
132 $out->text ($error_type_text);
133
134 if (defined $opt{text}) {
135 $out->html (' (<q>');
136 $out->text ($opt{text});
137 $out->html ('</q>)');
138 }
139
140 my $fragment = $opt{type};
141 $fragment =~ tr/ /-/;
142 $fragment = $out->encode_url_component ($fragment);
143 $out->text (' [');
144 $out->link ('Description', url => '../error-description#' . $fragment);
145 $out->text (']');
146
147
148 # my ($type, $cls, $msg) = main::get_text ($opt{type}, $opt{level});
149 # $out->html (qq[<dt class="$cls">] . $result->get_error_label ($input, \%opt));
150
151 $error_layer = 'char'
152 if $error_layer eq 'charset' or $error_layer eq 'encode';
153 if ($error_level eq 's') {
154 $self->{$error_layer}->{should}++;
155 $self->{$error_layer}->{score_min} -= 2;
156 $self->{conforming_min} = 0;
157 } elsif ($error_level eq 'w') {
158 $self->{$error_layer}->{warning}++;
159 } elsif ($error_level eq 'u') {
160 $self->{$error_layer}->{unsupported}++;
161 $self->{unsupported} = 1;
162 } elsif ($error_level eq 'i') {
163 #
164 } else {
165 $self->{$error_layer}->{must}++;
166 $self->{$error_layer}->{score_max} -= 2;
167 $self->{$error_layer}->{score_min} -= 2;
168 $self->{conforming_min} = 0;
169 $self->{conforming_max} = 0;
170 }
171 } # add_error
172
173 sub generate_result_section ($) {
174 my $result = shift;
175
176 my $out = $result->output;
177
178 $out->start_section (id => 'result-summary',
179 title => 'Result');
180
181 if ($result->{unsupported} and $result->{conforming_max}) {
182 $out->html (qq[<p class=uncertain id=result-para>The conformance
183 checker cannot decide whether the document is conforming or
184 not, since the document contains one or more unsupported
185 features. The document might or might not be conforming.</p>]);
186 } elsif ($result->{conforming_min}) {
187 $out->html (qq[<p class=PASS id=result-para>No conformance-error is
188 found in this document.</p>]);
189 } elsif ($result->{conforming_max}) {
190 $out->html (qq[<p class=SEE-RESULT id=result-para>This document
191 is <strong>likely <em>non</em>-conforming</strong>, but in rare case
192 it might be conforming.</p>]);
193 } else {
194 $out->html (qq[<p class=FAIL id=result-para>This document is
195 <strong><em>non</em>-conforming</strong>.</p>]);
196 }
197
198 $out->html (qq[<table>
199 <colgroup><col><colgroup><col><col><col><colgroup><col>
200 <thead>
201 <tr><th scope=col></th>
202 <th scope=col><a href="../error-description#level-m"><em class=rfc2119>MUST</em>-level
203 Errors</a></th>
204 <th scope=col><a href="../error-description#level-s"><em class=rfc2119>SHOULD</em>-level
205 Errors</a></th>
206 <th scope=col><a href="../error-description#level-w">Warnings</a></th>
207 <th scope=col>Score</th></tr></thead><tbody>]);
208
209 ## TODO: Introduce "N/A" value (e.g. Character layer is not applicable
210 ## to binary formats)
211
212 my $must_error = 0;
213 my $should_error = 0;
214 my $warning = 0;
215 my $score_min = 0;
216 my $score_max = 0;
217 my $score_base = 20;
218 my $score_unit = $score_base / 100;
219 for (
220 [Transfer => 'transfer', ''],
221 [Character => 'char', ''],
222 [Syntax => 'syntax', '#parse-errors'],
223 [Structure => 'structure', '#document-errors'],
224 ) {
225 $must_error += ($result->{$_->[1]}->{must} += 0);
226 $should_error += ($result->{$_->[1]}->{should} += 0);
227 $warning += ($result->{$_->[1]}->{warning} += 0);
228 $score_min += (($result->{$_->[1]}->{score_min} *= $score_unit) += $score_base);
229 $score_max += (($result->{$_->[1]}->{score_max} *= $score_unit) += $score_base);
230
231 my $uncertain = $result->{$_->[1]}->{unsupported} ? '?' : '';
232 my $label = $_->[0];
233 if ($result->{$_->[1]}->{must} or
234 $result->{$_->[1]}->{should} or
235 $result->{$_->[1]}->{warning} or
236 $result->{$_->[1]}->{unsupported}) {
237 $label = qq[<a href="$_->[2]">$label</a>];
238 }
239
240 $out->html (qq[<tr class="@{[$uncertain ? 'uncertain' : '']}"><th scope=row>$label</th><td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{must}$uncertain</td><td class="@{[$result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">$result->{$_->[1]}->{should}$uncertain</td><td>$result->{$_->[1]}->{warning}$uncertain</td>]);
241 if ($uncertain) {
242 $out->html (qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : $result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">&#x2212;&#x221E;..$result->{$_->[1]}->{score_max}]);
243 } elsif ($result->{$_->[1]}->{score_min} != $result->{$_->[1]}->{score_max}) {
244 $out->html (qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : 'SEE-RESULT']}">$result->{$_->[1]}->{score_min}..$result->{$_->[1]}->{score_max}]);
245 } else {
246 $out->html (qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{score_min}]);
247 }
248 $out->html (qq[ / 20]);
249 }
250
251 $score_max += $score_base;
252
253 $out->html (qq[
254 <tr class=uncertain><th scope=row>Semantics</th><td>0?</td><td>0?</td><td>0?</td><td>&#x2212;&#x221E;..$score_base / 20
255 </tbody>
256 <tfoot><tr class=uncertain><th scope=row>Total</th>
257 <td class="@{[$must_error ? 'FAIL' : '']}">$must_error?</td>
258 <td class="@{[$should_error ? 'SEE-RESULT' : '']}">$should_error?</td>
259 <td>$warning?</td>
260 <td class="@{[$must_error ? 'FAIL' : $should_error ? 'SEE-RESULT' : '']}"><strong>&#x2212;&#x221E;..$score_max</strong> / 100
261 </table>
262
263 <p><strong>Important</strong>: This conformance checking service
264 is <em>under development</em>. The result above might be <em>wrong</em>.</p>]);
265 $out->end_section;
266 } # generate_result_section
267
268 sub _get_error_label ($$) {
269 my $self = shift;
270 my ($input, $err) = @_;
271
272
273 } # get_error_label
274
275 sub get_error_level_label ($) {
276 my $self = shift;
277 my $err = shift;
278
279 my $r = '';
280
281 if (not defined $err->{level} or $err->{level} eq 'm') {
282 $r = qq[<strong><a href="../error-description#level-m"><em class=rfc2119>MUST</em>-level
283 error</a></strong>: ];
284 } elsif ($err->{level} eq 's') {
285 $r = qq[<strong><a href="../error-description#level-s"><em class=rfc2119>SHOULD</em>-level
286 error</a></strong>: ];
287 } elsif ($err->{level} eq 'w') {
288 $r = qq[<strong><a href="../error-description#level-w">Warning</a></strong>:
289 ];
290 } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {
291 $r = qq[<strong><a href="../error-description#level-u">Not
292 supported</a></strong>: ];
293 } elsif ($err->{level} eq 'i') {
294 $r = qq[<strong><a href="../error-description#level-i">Information</a></strong>: ];
295 } else {
296 my $elevel = htescape ($err->{level});
297 $r = qq[<strong><a href="../error-description#level-$elevel">$elevel</a></strong>:
298 ];
299 }
300
301 return $r;
302 } # get_error_level_label
303
304 sub get_node_path ($) {
305 my $self = shift;
306 my $node = shift;
307 my @r;
308 while (defined $node) {
309 my $rs;
310 if ($node->node_type == 1) {
311 $rs = $node->node_name;
312 $node = $node->parent_node;
313 } elsif ($node->node_type == 2) {
314 $rs = '@' . $node->node_name;
315 $node = $node->owner_element;
316 } elsif ($node->node_type == 3) {
317 $rs = '"' . $node->data . '"';
318 $node = $node->parent_node;
319 } elsif ($node->node_type == 9) {
320 @r = ('') unless @r;
321 $rs = '';
322 $node = $node->parent_node;
323 } else {
324 $rs = '#' . $node->node_type;
325 $node = $node->parent_node;
326 }
327 unshift @r, $rs;
328 }
329 return join '/', @r;
330 } # get_node_path
331
332 use Scalar::Util qw/refaddr/;
333
334 sub get_node_link ($$) {
335 my $self = shift;
336 return qq[<a href="#$_[0]->{id_prefix}node-@{[refaddr $_[1]]}">] .
337 ($self->get_node_path ($_[1])) . qq[</a>];
338 ## BUG: ^ must be escaped
339 } # get_node_link
340
341 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24