/[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 - (hide annotations) (download)
Thu Aug 14 15:50:42 2008 UTC (16 years, 3 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 wakaba 1.1 package WebHACC::Result;
2     use strict;
3    
4     sub new ($) {
5 wakaba 1.9 return bless {
6     global_status => 'conforming',
7     # or, 'should-error', 'non-conforming', 'uncertain'
8     subdoc_results => [],
9     }, shift;
10 wakaba 1.1 } # new
11    
12 wakaba 1.2 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 wakaba 1.9 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 wakaba 1.2 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 wakaba 1.6 ## Line & column numbers (prepare values)
88 wakaba 1.1
89     my $line;
90     my $column;
91    
92 wakaba 1.2 if (defined $opt{node}) {
93     $line = $opt{node}->get_user_data ('manakai_source_line');
94 wakaba 1.1 if (defined $line) {
95 wakaba 1.2 $column = $opt{node}->get_user_data ('manakai_source_column');
96 wakaba 1.7 } elsif ($opt{node}->isa ('Message::IF::Node')) {
97 wakaba 1.2 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 wakaba 1.1 } else {
104 wakaba 1.2 my $parent = $opt{node}->parent_node;
105 wakaba 1.1 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 wakaba 1.2 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 wakaba 1.1 }
120     }
121 wakaba 1.6 $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 wakaba 1.1
141     if (defined $line) {
142     if (defined $column and $column > 0) {
143 wakaba 1.6 $out->xref ('Line #', text => $line, target => 'line-' . $line);
144     $out->text (' ');
145     $out->nl_text ('column #', text => $column);
146 wakaba 1.1 } else {
147 wakaba 1.6 $out->xref ('Line #', text => $line, target => 'line-' . $line);
148 wakaba 1.1 }
149 wakaba 1.3 $has_location = 1;
150 wakaba 1.1 }
151    
152 wakaba 1.2 ## Node path
153    
154     if (defined $opt{node}) {
155     $out->html (' ');
156     $out->node_link ($opt{node});
157 wakaba 1.3 $has_location = 1;
158 wakaba 1.1 }
159    
160 wakaba 1.2 if (defined $opt{index}) {
161     if ($opt{index_has_link}) {
162     $out->html (' ');
163 wakaba 1.6 $out->xref ('Index #', text => (0+$opt{index}),
164 wakaba 1.2 target => 'index-' . (0+$opt{index}));
165 wakaba 1.1 } else {
166 wakaba 1.6 $out->html (' ');
167     $out->nl_text ('Index #', text => (0+$opt{index}));
168 wakaba 1.1 }
169 wakaba 1.3 $has_location = 1;
170 wakaba 1.1 }
171    
172 wakaba 1.2 if (defined $opt{value}) {
173     $out->html (' ');
174     $out->code ($opt{value});
175 wakaba 1.3 $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 wakaba 1.5 $out->text ('Unknown location');
197 wakaba 1.3 }
198 wakaba 1.1 }
199 wakaba 1.2
200     $out->start_tag ('dd', class => $class);
201 wakaba 1.4
202     ## Error level
203 wakaba 1.9 $out->nl_text ('Error level ' . $error_level);
204     $out->text (': ');
205 wakaba 1.4
206     ## Error message
207 wakaba 1.6 $out->nl_text ($error_type_text, node => $opt{node}, text => $opt{text});
208 wakaba 1.2
209 wakaba 1.4 ## Additional error description
210 wakaba 1.2 if (defined $opt{text}) {
211     $out->html (' (<q>');
212     $out->text ($opt{text});
213     $out->html ('</q>)');
214     }
215 wakaba 1.4
216     ## Link to a long description
217 wakaba 1.2
218     my $fragment = $opt{type};
219     $fragment =~ tr/ /-/;
220     $fragment = $out->encode_url_component ($fragment);
221     $out->text (' [');
222 wakaba 1.4 $out->link ('Description', url => '../error-description#' . $fragment,
223     rel => 'help');
224 wakaba 1.2 $out->text (']');
225    
226 wakaba 1.9 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 wakaba 1.2 } elsif ($error_level eq 'w') {
235 wakaba 1.9 $self->{layers}->{$error_layer}->{warning}++;
236 wakaba 1.2 } elsif ($error_level eq 'u') {
237 wakaba 1.9 $self->{layers}->{$error_layer}->{uncertain}++;
238     $self->{global_status} = 'uncertain'
239     unless $self->{global_status} eq 'non-conforming';
240 wakaba 1.2 } elsif ($error_level eq 'i') {
241 wakaba 1.9 $self->{layers}->{$error_layer}->{info}++;
242 wakaba 1.2 }
243     } # add_error
244    
245     sub generate_result_section ($) {
246 wakaba 1.9 my $self = shift;
247    
248     my $result = $self;
249 wakaba 1.2
250     my $out = $result->output;
251    
252 wakaba 1.9 $out->start_section (role => 'result');
253 wakaba 1.2
254 wakaba 1.9 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 wakaba 1.2 } else {
330 wakaba 1.9 $global_status = $maindoc_status;
331 wakaba 1.2 }
332    
333 wakaba 1.9 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 wakaba 1.2 } else {
425 wakaba 1.9 $out->html ($max_score < 0 ?
426     '&#x2212;' . substr ($max_score, 1) : $max_score);
427 wakaba 1.2 }
428 wakaba 1.9 $out->end_tag ('strong');
429    
430     $out->text (' / ' . $x->{score_base});
431 wakaba 1.2 }
432 wakaba 1.9
433     $out->end_tag ('table');
434 wakaba 1.2
435 wakaba 1.9 my $parent = $self->parent_result;
436     if ($parent) {
437     $global_status->{input} = $out->input;
438     push @{$parent->{subdoc_results}}, $global_status;
439     }
440 wakaba 1.2
441 wakaba 1.9 $out->nl_text ('This checker is work in progress.');
442 wakaba 1.2 $out->end_section;
443     } # generate_result_section
444 wakaba 1.1
445     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24