/[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.9 - (show annotations) (download)
Thu Aug 14 15:50:42 2008 UTC (16 years, 10 months ago) by wakaba
Branch: MAIN
Changes since 1.8: +231 -117 lines
++ ChangeLog	14 Aug 2008 15:42:17 -0000
	* cc.cgi: Generate result summary sections for
	each subdocument.

	* error-description-source.xml: New entries to
	support localization of result sections.

2008-08-14  Wakaba  <wakaba@suika.fam.cx>

	* cc-style.css: Support for revised version of result summary
	section styling.

2008-08-14  Wakaba  <wakaba@suika.fam.cx>

++ html/WebHACC/Language/ChangeLog	14 Aug 2008 15:50:38 -0000
	* Base.pm, CSS.pm, CacheManifest.pm, DOM.pm, Default.pm,
	HTML.pm, WebIDL.pm, XML.pm: Set |layer_applicable|
	or |layer_uncertain| flag appropriately.

2008-08-14  Wakaba  <wakaba@suika.fam.cx>

++ html/WebHACC/ChangeLog	14 Aug 2008 15:48:38 -0000
	* Input.pm: Methods |generate_transfer_sections|
	and |generate_http_header_section| are moved to HTTP
	subclass, since they are irrelevant to non-HTTP inputs.
	(_get_document): Forbidden host error was not represented
	by WebHACC::Input::Error subclass.
	(WebHACC::Input::Error generate_transfer_sections): Use
	role name for the section.
	(WebHACC::Input::HTTPError generate_transfer_sections): New method
	added, since the main superclass, i.e. WebHACC::Input::Error,
	no longer dumps HTTP headers due to the change mentioned above.

	* Output.pm (start_section): New roles "transfer-errors" and "result".

	* Result.pm (parent_result): New attribute.
	(layer_applicable, layer_uncertain): New methods to set flags.
	(add_error): Natural language strings are now handled
	by the catalog mechanism.  Use new scoring mechanism.
	(generate_result_section): Use catalog for all natural
	language strings.  Table generation is now much more sophiscated
	that it was.  Support for subdoc result summary.  Support
	for the column of the number of informational message.  Support
	for "N/A" status.

2008-08-14  Wakaba  <wakaba@suika.fam.cx>

1 package WebHACC::Result;
2 use strict;
3
4 sub new ($) {
5 return bless {
6 global_status => 'conforming',
7 # or, 'should-error', 'non-conforming', 'uncertain'
8 subdoc_results => [],
9 }, shift;
10 } # new
11
12 sub output ($;$) {
13 if (@_ > 1) {
14 if (defined $_[1]) {
15 $_[0]->{output} = $_[1];
16 } else {
17 delete $_[0]->{output};
18 }
19 }
20
21 return $_[0]->{output};
22 } # output
23
24 sub parent_result ($;$) {
25 if (@_ > 1) {
26 if (defined $_[1]) {
27 $_[0]->{parent_result} = $_[1];
28 } else {
29 delete $_[0]->{parent_result};
30 }
31 }
32
33 return $_[0]->{parent_result};
34 } # parent_result
35
36 sub layer_applicable ($$) {
37 my $self = shift;
38 my $layer = shift;
39 $self->{layers}->{$layer}->{applicable} = 1;
40 } # layer_applicable
41
42 sub layer_uncertain ($$) {
43 my $self = shift;
44 my $layer = shift;
45 $self->{layers}->{$layer}->{uncertain} ||= 1;
46 $self->{layers}->{$layer}->{applicable} = 1;
47 $self->{global_status} = 'uncertain'
48 unless $self->{global_status} eq 'non-conforming';
49 } # layer_uncertain
50
51 sub add_error ($%) {
52 my ($self, %opt) = @_;
53
54 my $out = $self->output;
55
56 my $error_level = $opt{level};
57 if (not defined $error_level) {
58 $error_level = 'm'; ## NOTE: Unknown - an error of the implementation
59 } elsif ({
60 m => 1, s => 1, w => 1, i => 1, u => 1,
61 }->{$error_level}) {
62 #
63 } else {
64 $error_level = 'm'; ## NOTE: Unknown - an error of the implementation
65 }
66
67 my $error_layer = $opt{layer};
68 if (not defined $error_layer) {
69 $error_layer = 'syntax'; ## NOTE: Unknown - an error of the implementation
70 } elsif ({
71 transfer => 1,
72 encode => 1,
73 charset => 1,
74 syntax => 1,
75 structure => 1,
76 semantics => 1,
77 }->{$error_layer}) {
78 #
79 } else {
80 $error_layer = 'syntax'; ## NOTE: Unknown - an error of the implementation
81 }
82
83 my $error_type_text = $opt{type};
84
85 my $class = qq[level-$error_level layer-$error_layer];
86
87 ## Line & column numbers (prepare values)
88
89 my $line;
90 my $column;
91
92 if (defined $opt{node}) {
93 $line = $opt{node}->get_user_data ('manakai_source_line');
94 if (defined $line) {
95 $column = $opt{node}->get_user_data ('manakai_source_column');
96 } elsif ($opt{node}->isa ('Message::IF::Node')) {
97 if ($opt{node}->node_type == $opt{node}->ATTRIBUTE_NODE) {
98 my $owner = $opt{node}->owner_element;
99 if ($owner) {
100 $line = $owner->get_user_data ('manakai_source_line');
101 $column = $owner->get_user_data ('manakai_source_column');
102 }
103 } else {
104 my $parent = $opt{node}->parent_node;
105 if ($parent) {
106 $line = $parent->get_user_data ('manakai_source_line');
107 $column = $parent->get_user_data ('manakai_source_column');
108 }
109 }
110 }
111 }
112 unless (defined $line) {
113 if (defined $opt{token} and defined $opt{token}->{line}) {
114 $line = $opt{token}->{line};
115 $column = $opt{token}->{column};
116 } elsif (defined $opt{line}) {
117 $line = $opt{line};
118 $column = $opt{column};
119 }
120 }
121 $line = $line - 1 || 1
122 if defined $line and not (defined $column and $column > 0);
123
124 $out->start_tag ('dt', class => $class,
125 'data-type' => $opt{type},
126 'data-level' => $error_level,
127 'data-layer' => $error_layer,
128 ($line ? ('data-line' => $line) : ()),
129 ($column ? ('data-column' => $column) : ()));
130 my $has_location;
131
132 ## URL
133
134 if (defined $opt{url}) {
135 $out->url ($opt{url});
136 $has_location = 1;
137 }
138
139 ## Line & column numbers (real output)
140
141 if (defined $line) {
142 if (defined $column and $column > 0) {
143 $out->xref ('Line #', text => $line, target => 'line-' . $line);
144 $out->text (' ');
145 $out->nl_text ('column #', text => $column);
146 } else {
147 $out->xref ('Line #', text => $line, target => 'line-' . $line);
148 }
149 $has_location = 1;
150 }
151
152 ## Node path
153
154 if (defined $opt{node}) {
155 $out->html (' ');
156 $out->node_link ($opt{node});
157 $has_location = 1;
158 }
159
160 if (defined $opt{index}) {
161 if ($opt{index_has_link}) {
162 $out->html (' ');
163 $out->xref ('Index #', text => (0+$opt{index}),
164 target => 'index-' . (0+$opt{index}));
165 } else {
166 $out->html (' ');
167 $out->nl_text ('Index #', text => (0+$opt{index}));
168 }
169 $has_location = 1;
170 }
171
172 if (defined $opt{value}) {
173 $out->html (' ');
174 $out->code ($opt{value});
175 $has_location = 1;
176 }
177
178 unless ($has_location) {
179 if (defined $opt{input}) {
180 if (defined $opt{input}->{container_node}) {
181 my $original_input = $out->input;
182 $out->input ($opt{input}->{parent_input});
183 $out->node_link ($opt{input}->{container_node});
184 $out->input ($original_input);
185 $has_location = 1;
186 } elsif (defined $opt{input}->{request_uri}) {
187 $out->url ($opt{input}->{request_uri});
188 $has_location = 1;
189 } elsif (defined $opt{input}->{uri}) {
190 $out->url ($opt{input}->{uri});
191 $has_location = 1;
192 }
193 }
194
195 unless ($has_location) {
196 $out->text ('Unknown location');
197 }
198 }
199
200 $out->start_tag ('dd', class => $class);
201
202 ## Error level
203 $out->nl_text ('Error level ' . $error_level);
204 $out->text (': ');
205
206 ## Error message
207 $out->nl_text ($error_type_text, node => $opt{node}, text => $opt{text});
208
209 ## Additional error description
210 if (defined $opt{text}) {
211 $out->html (' (<q>');
212 $out->text ($opt{text});
213 $out->html ('</q>)');
214 }
215
216 ## Link to a long description
217
218 my $fragment = $opt{type};
219 $fragment =~ tr/ /-/;
220 $fragment = $out->encode_url_component ($fragment);
221 $out->text (' [');
222 $out->link ('Description', url => '../error-description#' . $fragment,
223 rel => 'help');
224 $out->text (']');
225
226 if ($error_level eq 'm') {
227 $self->{layers}->{$error_layer}->{must}++;
228 $self->{global_status} = 'non-conforming';
229 } elsif ($error_level eq 's') {
230 $self->{layers}->{$error_layer}->{should}++;
231 $self->{global_status} = 'should-error'
232 unless {'non-conforming' => 1,
233 uncertain => 1}->{$self->{global_status}};
234 } elsif ($error_level eq 'w') {
235 $self->{layers}->{$error_layer}->{warning}++;
236 } elsif ($error_level eq 'u') {
237 $self->{layers}->{$error_layer}->{uncertain}++;
238 $self->{global_status} = 'uncertain'
239 unless $self->{global_status} eq 'non-conforming';
240 } elsif ($error_level eq 'i') {
241 $self->{layers}->{$error_layer}->{info}++;
242 }
243 } # add_error
244
245 sub generate_result_section ($) {
246 my $self = shift;
247
248 my $result = $self;
249
250 my $out = $result->output;
251
252 $out->start_section (role => 'result');
253
254 my $para_class = {
255 'conforming' => 'result-para no-error',
256 'should-error' => 'result-para should-errors',
257 'non-conforming' => 'result-para must-errors',
258 'uncertain' => 'result-para uncertain',
259 }->{$self->{global_status}};
260 $out->start_tag ('p', class => $para_class);
261 $out->nl_text ('Conformance is ' . $self->{global_status});
262 $out->end_tag ('p');
263
264 $out->html (qq[<table>
265 <colgroup><col><col><colgroup><col><col><col><col><colgroup><col>
266 <thead>
267 <tr><th scope=col colspan=2>]);
268 for ('Error level m', 'Error level s', 'Error level w',
269 'Error level i', 'Score') {
270 $out->start_tag ('th');
271 $out->nl_text ($_);
272 }
273
274 my $maindoc_status = {must => 0, should => 0, warning => 0, info => 0,
275 uncertain => 0, applicable => 1};
276 my $subdocs_status = {must => 0, should => 0, warning => 0, info => 0,
277 uncertain => 0, applicable => 1};
278 my $global_status = {must => 0, should => 0, warning => 0, info => 0,
279 uncertain => 0, applicable => 1};
280
281 my $score_unit = 2;
282
283 my @row = (
284 sub {
285 $out->start_tag ('tbody');
286 $out->start_tag ('tr');
287 $out->start_tag ('th', colspan => 7, scope => 'col');
288 $out->nl_text ('Main document');
289 },
290 {label => 'Transfer', status => $self->{layers}->{transfer},
291 target => 'transfer-errors', score_base => 20,
292 parent_status => $maindoc_status},
293 {label => 'Encode', status => $self->{layers}->{encode},
294 score_base => 10,
295 parent_status => $maindoc_status},
296 {label => 'Charset', status => $self->{layers}->{charset},
297 score_base => 10,
298 parent_status => $maindoc_status},
299 {label => 'Syntax', status => $self->{layers}->{syntax},
300 target => 'parse-errors', score_base => 20,
301 parent_status => $maindoc_status},
302 {label => 'Structure', status => $self->{layers}->{structure},
303 target => 'document-errors', score_base => 20,
304 parent_status => $maindoc_status},
305 {label => 'Semantics', status => $self->{layers}->{semantics},
306 score_base => 20,
307 parent_status => $maindoc_status},
308 );
309
310 if (@{$self->{subdoc_results}}) {
311 push @row, {label => 'Subtotal', status => $maindoc_status,
312 score_base => 100,
313 parent_status => $global_status, is_total => 1};
314 push @row, sub {
315 $out->start_tag ('tbody');
316 $out->start_tag ('tr');
317 $out->start_tag ('th', colspan => 7, scope => 'col');
318 $out->nl_text ('Subdocuments');
319 };
320 for (@{$self->{subdoc_results}}) {
321 push @row, {label => '#' . $_->{input}->full_subdocument_index,
322 status => $_,
323 target => $_->{input}->id_prefix . 'result-summary',
324 score_base => 100, parent_status => $subdocs_status};
325 }
326 push @row, {label => 'Subtotal', status => $subdocs_status,
327 score_base => 100 * @{$self->{subdoc_results}},
328 parent_status => $global_status, is_total => 1};
329 } else {
330 $global_status = $maindoc_status;
331 }
332
333 push @row, sub {
334 $out->start_tag ('tfoot');
335 };
336 push @row, {label => 'Total', status => $global_status,
337 score_base => 100 * (@{$self->{subdoc_results}} + 1),
338 parent_status => {}, is_total => 1};
339
340 for my $x (@row) {
341 if (ref $x eq 'CODE') {
342 $x->();
343 next;
344 }
345
346 $x->{parent_status}->{$_} += $x->{status}->{$_}
347 for qw/must should warning info uncertain/;
348
349 my $row_class = $x->{status}->{uncertain} ? 'uncertain' : '';
350 $row_class .= ' total' if $x->{is_total};
351 $out->start_tag ('tr', class => $row_class);
352 my $uncertain = $x->{status}->{uncertain} ? '?' : '';
353
354 $out->start_tag ('td', class => 'subrow') unless $x->{is_total};
355
356 ## Layer name
357 $out->start_tag ('th', colspan => $x->{is_total} ? 2 : 1,
358 scope => 'row');
359 if (defined $x->{target} and
360 ($x->{status}->{must} or $x->{status}->{should} or
361 $x->{status}->{warning} or $x->{status}->{info} or
362 $x->{status}->{uncertain})) {
363 $out->xref ($x->{label}, target => $x->{target});
364 } else {
365 $out->nl_text ($x->{label});
366 }
367
368 ## MUST-level errors
369 $out->start_tag ('td', class => $x->{status}->{must} ? 'must-errors' : '');
370 if ($x->{status}->{applicable}) {
371 $out->text (($x->{status}->{must} or 0) . $uncertain);
372 } else {
373 $out->nl_text ('N/A');
374 }
375
376 ## SHOULD-level errors
377 $out->start_tag ('td',
378 class => $x->{status}->{should} ? 'should-errors' : '');
379 if ($x->{status}->{applicable}) {
380 $out->text (($x->{status}->{should} or 0) . $uncertain);
381 } else {
382 $out->nl_text ('N/A');
383 }
384
385 ## Warnings
386 $out->start_tag ('td', class => $x->{status}->{warning} ? 'warnings' : '');
387 if ($x->{status}->{applicable}) {
388 $out->text (($x->{status}->{warning} or 0) . $uncertain);
389 } else {
390 $out->nl_text ('N/A');
391 }
392
393 ## Informations
394 $out->start_tag ('td', class => $x->{status}->{info} ? 'infos' : '');
395 if ($x->{status}->{applicable}) {
396 $out->text (($x->{status}->{info} or 0) . $uncertain);
397 } else {
398 $out->nl_text ('N/A');
399 }
400
401 ## Score
402 $out->start_tag ('td',
403 class => $x->{status}->{must} ? 'score must-errors' :
404 $x->{status}->{should} ? 'score should-errors' :
405 'score');
406
407 my $max_score = $x->{score_base};
408 $max_score -= $x->{status}->{must} * $score_unit;
409 my $min_score = $max_score;
410 $min_score -= $x->{status}->{should} * $score_unit;
411
412 $out->start_tag ('strong');
413 if ($x->{status}->{uncertain}) {
414 $out->html ('&#x2212;&#x221E; '); # negative inifinity
415 $out->nl_text ('...');
416 $out->html ($max_score < 0 ?
417 ' &#x2212;' . substr ($max_score, 1) : ' ' . $max_score);
418 } elsif ($min_score != $max_score) {
419 $out->html ($min_score < 0 ?
420 '&#x2212;' . substr ($min_score, 1) . ' ': $min_score . ' ');
421 $out->nl_text ('...');
422 $out->html ($max_score < 0 ?
423 ' &#x2212;' . substr ($max_score, 1) : ' ' . $max_score);
424 } else {
425 $out->html ($max_score < 0 ?
426 '&#x2212;' . substr ($max_score, 1) : $max_score);
427 }
428 $out->end_tag ('strong');
429
430 $out->text (' / ' . $x->{score_base});
431 }
432
433 $out->end_tag ('table');
434
435 my $parent = $self->parent_result;
436 if ($parent) {
437 $global_status->{input} = $out->input;
438 push @{$parent->{subdoc_results}}, $global_status;
439 }
440
441 $out->nl_text ('This checker is work in progress.');
442 $out->end_section;
443 } # generate_result_section
444
445 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24