/[pub]/test/html-webhacc/cc.cgi
Suika

Diff of /test/html-webhacc/cc.cgi

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.33 by wakaba, Sun Feb 10 02:42:01 2008 UTC revision 1.52 by wakaba, Fri Jul 18 14:44:16 2008 UTC
# Line 20  sub htescape ($) { Line 20  sub htescape ($) {
20    return $s;    return $s;
21  } # htescape  } # htescape
22    
23      my @nav;
24      my %time;
25      require Message::DOM::DOMImplementation;
26      my $dom = Message::DOM::DOMImplementation->new;
27    {
28    use Message::CGI::HTTP;    use Message::CGI::HTTP;
29    my $http = Message::CGI::HTTP->new;    my $http = Message::CGI::HTTP->new;
30    
# Line 31  sub htescape ($) { Line 36  sub htescape ($) {
36    binmode STDOUT, ':utf8';    binmode STDOUT, ':utf8';
37    $| = 1;    $| = 1;
38    
   require Message::DOM::DOMImplementation;  
   my $dom = Message::DOM::DOMImplementation->new;  
   
39    load_text_catalog ('en'); ## TODO: conneg    load_text_catalog ('en'); ## TODO: conneg
40    
   my @nav;  
41    print STDOUT qq[Content-Type: text/html; charset=utf-8    print STDOUT qq[Content-Type: text/html; charset=utf-8
42    
43  <!DOCTYPE html>  <!DOCTYPE html>
# Line 53  sub htescape ($) { Line 54  sub htescape ($) {
54    $| = 0;    $| = 0;
55    my $input = get_input_document ($http, $dom);    my $input = get_input_document ($http, $dom);
56    my $char_length = 0;    my $char_length = 0;
   my %time;  
57    
58    print qq[    print qq[
59  <div id="document-info" class="section">  <div id="document-info" class="section">
# Line 86  if (defined $input->{s}) { Line 86  if (defined $input->{s}) {
86      <dd>$char_length byte@{[$char_length == 1 ? '' : 's']}</dd>      <dd>$char_length byte@{[$char_length == 1 ? '' : 's']}</dd>
87  </dl>  </dl>
88  </div>  </div>
89    
90    <script src="../cc-script.js"></script>
91  ];  ];
92    
93      $input->{id_prefix} = '';
94      #$input->{nested} = 0;
95    my $result = {conforming_min => 1, conforming_max => 1};    my $result = {conforming_min => 1, conforming_max => 1};
96    check_and_print ($input => $result);    check_and_print ($input => $result);
97    print_result_section ($result);    print_result_section ($result);
# Line 116  if (defined $input->{s}) { Line 120  if (defined $input->{s}) {
120    }    }
121    
122  exit;  exit;
123    }
124    
125  sub add_error ($$$) {  sub add_error ($$$) {
126    my ($layer, $err, $result) = @_;    my ($layer, $err, $result) = @_;
# Line 129  sub add_error ($$$) { Line 134  sub add_error ($$$) {
134      } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {      } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {
135        $result->{$layer}->{unsupported}++;        $result->{$layer}->{unsupported}++;
136        $result->{unsupported} = 1;        $result->{unsupported} = 1;
137        } elsif ($err->{level} eq 'i') {
138          #
139      } else {      } else {
140        $result->{$layer}->{must}++;        $result->{$layer}->{must}++;
141        $result->{$layer}->{score_max} -= 2;        $result->{$layer}->{score_max} -= 2;
# Line 147  sub add_error ($$$) { Line 154  sub add_error ($$$) {
154    
155  sub check_and_print ($$) {  sub check_and_print ($$) {
156    my ($input, $result) = @_;    my ($input, $result) = @_;
   $input->{id_prefix} = '';  
   #$input->{nested} = 1/0;  
157    
158    print_http_header_section ($input, $result);    print_http_header_section ($input, $result);
159    
160    my $doc;    my $doc;
161    my $el;    my $el;
162      my $cssom;
163    my $manifest;    my $manifest;
164      my $idl;
165      my @subdoc;
166    
167    if ($input->{media_type} eq 'text/html') {    if ($input->{media_type} eq 'text/html') {
168      ($doc, $el) = print_syntax_error_html_section ($input, $result);      ($doc, $el) = print_syntax_error_html_section ($input, $result);
169      print_source_string_section      print_source_string_section
170          (\($input->{s}), $input->{charset} || $doc->input_encoding);          ($input,
171             \($input->{s}),
172             $input->{charset} || $doc->input_encoding);
173    } elsif ({    } elsif ({
174              'text/xml' => 1,              'text/xml' => 1,
175              'application/atom+xml' => 1,              'application/atom+xml' => 1,
176              'application/rss+xml' => 1,              'application/rss+xml' => 1,
177              'application/svg+xml' => 1,              'image/svg+xml' => 1,
178              'application/xhtml+xml' => 1,              'application/xhtml+xml' => 1,
179              'application/xml' => 1,              'application/xml' => 1,
180                ## TODO: Should we make all XML MIME Types fall
181                ## into this category?
182    
183                'application/rdf+xml' => 1, ## NOTE: This type has different model.
184             }->{$input->{media_type}}) {             }->{$input->{media_type}}) {
185      ($doc, $el) = print_syntax_error_xml_section ($input, $result);      ($doc, $el) = print_syntax_error_xml_section ($input, $result);
186      print_source_string_section (\($input->{s}), $doc->input_encoding);      print_source_string_section ($input,
187                                     \($input->{s}),
188                                     $doc->input_encoding);
189      } elsif ($input->{media_type} eq 'text/css') {
190        $cssom = print_syntax_error_css_section ($input, $result);
191        print_source_string_section
192            ($input, \($input->{s}),
193             $cssom->manakai_input_encoding);
194    } elsif ($input->{media_type} eq 'text/cache-manifest') {    } elsif ($input->{media_type} eq 'text/cache-manifest') {
195  ## TODO: MUST be text/cache-manifest  ## TODO: MUST be text/cache-manifest
196      $manifest = print_syntax_error_manifest_section ($input, $result);      $manifest = print_syntax_error_manifest_section ($input, $result);
197      print_source_string_section (\($input->{s}), 'utf-8');      print_source_string_section ($input, \($input->{s}),
198                                     'utf-8');
199      } elsif ($input->{media_type} eq 'text/x-webidl') { ## TODO: type
200        $idl = print_syntax_error_webidl_section ($input, $result);
201        print_source_string_section ($input, \($input->{s}),
202                                     'utf-8'); ## TODO: charset
203    } else {    } else {
204      ## TODO: Change HTTP status code??      ## TODO: Change HTTP status code??
205      print_result_unknown_type_section ($input, $result);      print_result_unknown_type_section ($input, $result);
206    }    }
207    
208    if (defined $doc or defined $el) {    if (defined $doc or defined $el) {
209        $doc->document_uri ($input->{uri});
210        $doc->manakai_entity_base_uri ($input->{base_uri});
211      print_structure_dump_dom_section ($input, $doc, $el);      print_structure_dump_dom_section ($input, $doc, $el);
212      my $elements = print_structure_error_dom_section      my $elements = print_structure_error_dom_section
213          ($input, $doc, $el, $result);          ($input, $doc, $el, $result, sub {
214              push @subdoc, shift;
215            });
216      print_table_section ($input, $elements->{table}) if @{$elements->{table}};      print_table_section ($input, $elements->{table}) if @{$elements->{table}};
217      print_listing_section ({      print_listing_section ({
218        id => 'identifiers', label => 'IDs', heading => 'Identifiers',        id => 'identifiers', label => 'IDs', heading => 'Identifiers',
# Line 193  sub check_and_print ($$) { Line 223  sub check_and_print ($$) {
223      print_listing_section ({      print_listing_section ({
224        id => 'classes', label => 'Classes', heading => 'Classes',        id => 'classes', label => 'Classes', heading => 'Classes',
225      }, $input, $elements->{class}) if keys %{$elements->{class}};      }, $input, $elements->{class}) if keys %{$elements->{class}};
226        print_uri_section ($input, $elements->{uri}) if keys %{$elements->{uri}};
227        print_rdf_section ($input, $elements->{rdf}) if @{$elements->{rdf}};
228      } elsif (defined $cssom) {
229        print_structure_dump_cssom_section ($input, $cssom);
230        ## TODO: CSSOM validation
231        add_error ('structure', {level => 'u'} => $result);
232    } elsif (defined $manifest) {    } elsif (defined $manifest) {
233      print_structure_dump_manifest_section ($input, $manifest);      print_structure_dump_manifest_section ($input, $manifest);
234      print_structure_error_manifest_section ($input, $manifest, $result);      print_structure_error_manifest_section ($input, $manifest, $result);
235      } elsif (defined $idl) {
236        print_structure_dump_webidl_section ($input, $idl);
237        print_structure_error_webidl_section ($input, $idl, $result);
238      }
239    
240      my $id_prefix = 0;
241      for my $subinput (@subdoc) {
242        $subinput->{id_prefix} = 'subdoc-' . ++$id_prefix;
243        $subinput->{nested} = 1;
244        $subinput->{base_uri} = $subinput->{container_node}->base_uri
245            unless defined $subinput->{base_uri};
246        my $ebaseuri = htescape ($subinput->{base_uri});
247        push @nav, ['#' . $subinput->{id_prefix} => 'Sub #' . $id_prefix];
248        print STDOUT qq[<div id="$subinput->{id_prefix}" class=section>
249          <h2>Subdocument #$id_prefix</h2>
250    
251          <dl>
252          <dt>Internet Media Type</dt>
253            <dd><code class="MIME" lang="en">@{[htescape $subinput->{media_type}]}</code>
254          <dt>Container Node</dt>
255            <dd>@{[get_node_link ($input, $subinput->{container_node})]}</dd>
256          <dt>Base <abbr title="Uniform Resource Identifiers">URI</abbr></dt>
257            <dd><code class=URI>&lt;<a href="$ebaseuri">$ebaseuri</a>></code></dd>
258          </dl>];              
259    
260        $subinput->{id_prefix} .= '-';
261        check_and_print ($subinput => $result);
262    
263        print STDOUT qq[</div>];
264    }    }
265  } # check_and_print  } # check_and_print
266    
# Line 203  sub print_http_header_section ($$) { Line 268  sub print_http_header_section ($$) {
268    my ($input, $result) = @_;    my ($input, $result) = @_;
269    return unless defined $input->{header_status_code} or    return unless defined $input->{header_status_code} or
270        defined $input->{header_status_text} or        defined $input->{header_status_text} or
271        @{$input->{header_field}};        @{$input->{header_field} or []};
272        
273    push @nav, ['#source-header' => 'HTTP Header'] unless $input->{nested};    push @nav, ['#source-header' => 'HTTP Header'] unless $input->{nested};
274    print STDOUT qq[<div id="$input->{id_prefix}source-header" class="section">    print STDOUT qq[<div id="$input->{id_prefix}source-header" class="section">
# Line 243  sub print_syntax_error_html_section ($$) Line 308  sub print_syntax_error_html_section ($$)
308  <div id="$input->{id_prefix}parse-errors" class="section">  <div id="$input->{id_prefix}parse-errors" class="section">
309  <h2>Parse Errors</h2>  <h2>Parse Errors</h2>
310    
311  <dl>];  <dl id="$input->{id_prefix}parse-errors-list">];
312    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};
313    
314    my $onerror = sub {    my $onerror = sub {
315      my (%opt) = @_;      my (%opt) = @_;
316      my ($type, $cls, $msg) = get_text ($opt{type}, $opt{level});      my ($type, $cls, $msg) = get_text ($opt{type}, $opt{level});
317      if ($opt{column} > 0) {      print STDOUT qq[<dt class="$cls">], get_error_label ($input, \%opt),
318        print STDOUT qq[<dt class="$cls"><a href="#line-$opt{line}">Line $opt{line}</a> column $opt{column}</dt>\n];          qq[</dt>];
     } else {  
       $opt{line} = $opt{line} - 1 || 1;  
       print STDOUT qq[<dt class="$cls"><a href="#line-$opt{line}">Line $opt{line}</a></dt>\n];  
     }  
319      $type =~ tr/ /-/;      $type =~ tr/ /-/;
320      $type =~ s/\|/%7C/g;      $type =~ s/\|/%7C/g;
321      $msg .= qq[ [<a href="../error-description#@{[htescape ($type)]}">Description</a>]];      $msg .= qq[ [<a href="../error-description#@{[htescape ($type)]}">Description</a>]];
# Line 266  sub print_syntax_error_html_section ($$) Line 327  sub print_syntax_error_html_section ($$)
327    
328    my $doc = $dom->create_document;    my $doc = $dom->create_document;
329    my $el;    my $el;
330    my $inner_html_element = $http->get_parameter ('e');    my $inner_html_element = $input->{inner_html_element};
331    if (defined $inner_html_element and length $inner_html_element) {    if (defined $inner_html_element and length $inner_html_element) {
332      $input->{charset} ||= 'windows-1252'; ## TODO: for now.      $input->{charset} ||= 'windows-1252'; ## TODO: for now.
333      my $time1 = time;      my $time1 = time;
334      my $t = Encode::decode ($input->{charset}, $input->{s});      my $t = \($input->{s});
335        unless ($input->{is_char_string}) {
336          $t = \(Encode::decode ($input->{charset}, $$t));
337        }
338      $time{decode} = time - $time1;      $time{decode} = time - $time1;
339            
340      $el = $doc->create_element_ns      $el = $doc->create_element_ns
341          ('http://www.w3.org/1999/xhtml', [undef, $inner_html_element]);          ('http://www.w3.org/1999/xhtml', [undef, $inner_html_element]);
342      $time1 = time;      $time1 = time;
343      Whatpm::HTML->set_inner_html ($el, $t, $onerror);      Whatpm::HTML->set_inner_html ($el, $$t, $onerror);
344      $time{parse} = time - $time1;      $time{parse} = time - $time1;
345    } else {    } else {
346      my $time1 = time;      my $time1 = time;
347      Whatpm::HTML->parse_byte_string      if ($input->{is_char_string}) {
348          ($input->{charset}, $input->{s} => $doc, $onerror);        Whatpm::HTML->parse_char_string ($input->{s} => $doc, $onerror);
349        } else {
350          Whatpm::HTML->parse_byte_string
351              ($input->{charset}, $input->{s} => $doc, $onerror);
352        }
353      $time{parse_html} = time - $time1;      $time{parse_html} = time - $time1;
354    }    }
355    $doc->manakai_charset ($input->{official_charset})    $doc->manakai_charset ($input->{official_charset})
# Line 301  sub print_syntax_error_xml_section ($$) Line 369  sub print_syntax_error_xml_section ($$)
369  <div id="$input->{id_prefix}parse-errors" class="section">  <div id="$input->{id_prefix}parse-errors" class="section">
370  <h2>Parse Errors</h2>  <h2>Parse Errors</h2>
371    
372  <dl>];  <dl id="$input->{id_prefix}parse-errors-list">];
373    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{prefix};    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{prefix};
374    
375    my $onerror = sub {    my $onerror = sub {
376      my $err = shift;      my $err = shift;
377      my $line = $err->location->line_number;      my $line = $err->location->line_number;
378      print STDOUT qq[<dt><a href="#line-$line">Line $line</a> column ];      print STDOUT qq[<dt><a href="#$input->{id_prefix}line-$line">Line $line</a> column ];
379      print STDOUT $err->location->column_number, "</dt><dd>";      print STDOUT $err->location->column_number, "</dt><dd>";
380      print STDOUT htescape $err->text, "</dd>\n";      print STDOUT htescape $err->text, "</dd>\n";
381    
# Line 321  sub print_syntax_error_xml_section ($$) Line 389  sub print_syntax_error_xml_section ($$)
389      return 1;      return 1;
390    };    };
391    
392      my $t = \($input->{s});
393      if ($input->{is_char_string}) {
394        require Encode;
395        $t = \(Encode::encode ('utf8', $$t));
396        $input->{charset} = 'utf-8';
397      }
398    
399    my $time1 = time;    my $time1 = time;
400    open my $fh, '<', \($input->{s});    open my $fh, '<', $t;
401    my $doc = Message::DOM::XMLParserTemp->parse_byte_stream    my $doc = Message::DOM::XMLParserTemp->parse_byte_stream
402        ($fh => $dom, $onerror, charset => $input->{charset});        ($fh => $dom, $onerror, charset => $input->{charset});
403    $time{parse_xml} = time - $time1;    $time{parse_xml} = time - $time1;
# Line 334  sub print_syntax_error_xml_section ($$) Line 409  sub print_syntax_error_xml_section ($$)
409    return ($doc, undef);    return ($doc, undef);
410  } # print_syntax_error_xml_section  } # print_syntax_error_xml_section
411    
412    sub get_css_parser () {
413      our $CSSParser;
414      return $CSSParser if $CSSParser;
415    
416      require Whatpm::CSS::Parser;
417      my $p = Whatpm::CSS::Parser->new;
418    
419      $p->{prop}->{$_} = 1 for qw/
420        alignment-baseline
421        background background-attachment background-color background-image
422        background-position background-position-x background-position-y
423        background-repeat border border-bottom border-bottom-color
424        border-bottom-style border-bottom-width border-collapse border-color
425        border-left border-left-color
426        border-left-style border-left-width border-right border-right-color
427        border-right-style border-right-width
428        border-spacing -manakai-border-spacing-x -manakai-border-spacing-y
429        border-style border-top border-top-color border-top-style border-top-width
430        border-width bottom
431        caption-side clear clip color content counter-increment counter-reset
432        cursor direction display dominant-baseline empty-cells float font
433        font-family font-size font-size-adjust font-stretch
434        font-style font-variant font-weight height left
435        letter-spacing line-height
436        list-style list-style-image list-style-position list-style-type
437        margin margin-bottom margin-left margin-right margin-top marker-offset
438        marks max-height max-width min-height min-width opacity -moz-opacity
439        orphans outline outline-color outline-style outline-width overflow
440        overflow-x overflow-y
441        padding padding-bottom padding-left padding-right padding-top
442        page page-break-after page-break-before page-break-inside
443        position quotes right size table-layout
444        text-align text-anchor text-decoration text-indent text-transform
445        top unicode-bidi vertical-align visibility white-space width widows
446        word-spacing writing-mode z-index
447      /;
448      $p->{prop_value}->{display}->{$_} = 1 for qw/
449        block clip inline inline-block inline-table list-item none
450        table table-caption table-cell table-column table-column-group
451        table-header-group table-footer-group table-row table-row-group
452        compact marker
453      /;
454      $p->{prop_value}->{position}->{$_} = 1 for qw/
455        absolute fixed relative static
456      /;
457      $p->{prop_value}->{float}->{$_} = 1 for qw/
458        left right none
459      /;
460      $p->{prop_value}->{clear}->{$_} = 1 for qw/
461        left right none both
462      /;
463      $p->{prop_value}->{direction}->{ltr} = 1;
464      $p->{prop_value}->{direction}->{rtl} = 1;
465      $p->{prop_value}->{marks}->{crop} = 1;
466      $p->{prop_value}->{marks}->{cross} = 1;
467      $p->{prop_value}->{'unicode-bidi'}->{$_} = 1 for qw/
468        normal bidi-override embed
469      /;
470      for my $prop_name (qw/overflow overflow-x overflow-y/) {
471        $p->{prop_value}->{$prop_name}->{$_} = 1 for qw/
472          visible hidden scroll auto -webkit-marquee -moz-hidden-unscrollable
473        /;
474      }
475      $p->{prop_value}->{visibility}->{$_} = 1 for qw/
476        visible hidden collapse
477      /;
478      $p->{prop_value}->{'list-style-type'}->{$_} = 1 for qw/
479        disc circle square decimal decimal-leading-zero
480        lower-roman upper-roman lower-greek lower-latin
481        upper-latin armenian georgian lower-alpha upper-alpha none
482        hebrew cjk-ideographic hiragana katakana hiragana-iroha
483        katakana-iroha
484      /;
485      $p->{prop_value}->{'list-style-position'}->{outside} = 1;
486      $p->{prop_value}->{'list-style-position'}->{inside} = 1;
487      $p->{prop_value}->{'page-break-before'}->{$_} = 1 for qw/
488        auto always avoid left right
489      /;
490      $p->{prop_value}->{'page-break-after'}->{$_} = 1 for qw/
491        auto always avoid left right
492      /;
493      $p->{prop_value}->{'page-break-inside'}->{auto} = 1;
494      $p->{prop_value}->{'page-break-inside'}->{avoid} = 1;
495      $p->{prop_value}->{'background-repeat'}->{$_} = 1 for qw/
496        repeat repeat-x repeat-y no-repeat
497      /;
498      $p->{prop_value}->{'background-attachment'}->{scroll} = 1;
499      $p->{prop_value}->{'background-attachment'}->{fixed} = 1;
500      $p->{prop_value}->{'font-size'}->{$_} = 1 for qw/
501        xx-small x-small small medium large x-large xx-large
502        -manakai-xxx-large -webkit-xxx-large
503        larger smaller
504      /;
505      $p->{prop_value}->{'font-style'}->{normal} = 1;
506      $p->{prop_value}->{'font-style'}->{italic} = 1;
507      $p->{prop_value}->{'font-style'}->{oblique} = 1;
508      $p->{prop_value}->{'font-variant'}->{normal} = 1;
509      $p->{prop_value}->{'font-variant'}->{'small-caps'} = 1;
510      $p->{prop_value}->{'font-stretch'}->{$_} = 1 for
511          qw/normal wider narrower ultra-condensed extra-condensed
512            condensed semi-condensed semi-expanded expanded
513            extra-expanded ultra-expanded/;
514      $p->{prop_value}->{'text-align'}->{$_} = 1 for qw/
515        left right center justify begin end
516      /;
517      $p->{prop_value}->{'text-transform'}->{$_} = 1 for qw/
518        capitalize uppercase lowercase none
519      /;
520      $p->{prop_value}->{'white-space'}->{$_} = 1 for qw/
521        normal pre nowrap pre-line pre-wrap -moz-pre-wrap
522      /;
523      $p->{prop_value}->{'writing-mode'}->{$_} = 1 for qw/
524        lr rl tb lr-tb rl-tb tb-rl
525      /;
526      $p->{prop_value}->{'text-anchor'}->{$_} = 1 for qw/
527        start middle end
528      /;
529      $p->{prop_value}->{'dominant-baseline'}->{$_} = 1 for qw/
530        auto use-script no-change reset-size ideographic alphabetic
531        hanging mathematical central middle text-after-edge text-before-edge
532      /;
533      $p->{prop_value}->{'alignment-baseline'}->{$_} = 1 for qw/
534        auto baseline before-edge text-before-edge middle central
535        after-edge text-after-edge ideographic alphabetic hanging
536        mathematical
537      /;
538      $p->{prop_value}->{'text-decoration'}->{$_} = 1 for qw/
539        none blink underline overline line-through
540      /;
541      $p->{prop_value}->{'caption-side'}->{$_} = 1 for qw/
542        top bottom left right
543      /;
544      $p->{prop_value}->{'table-layout'}->{auto} = 1;
545      $p->{prop_value}->{'table-layout'}->{fixed} = 1;
546      $p->{prop_value}->{'border-collapse'}->{collapse} = 1;
547      $p->{prop_value}->{'border-collapse'}->{separate} = 1;
548      $p->{prop_value}->{'empty-cells'}->{show} = 1;
549      $p->{prop_value}->{'empty-cells'}->{hide} = 1;
550      $p->{prop_value}->{cursor}->{$_} = 1 for qw/
551        auto crosshair default pointer move e-resize ne-resize nw-resize n-resize
552        se-resize sw-resize s-resize w-resize text wait help progress
553      /;
554      for my $prop (qw/border-top-style border-left-style
555                       border-bottom-style border-right-style outline-style/) {
556        $p->{prop_value}->{$prop}->{$_} = 1 for qw/
557          none hidden dotted dashed solid double groove ridge inset outset
558        /;
559      }
560      for my $prop (qw/color background-color
561                       border-bottom-color border-left-color border-right-color
562                       border-top-color border-color/) {
563        $p->{prop_value}->{$prop}->{transparent} = 1;
564        $p->{prop_value}->{$prop}->{flavor} = 1;
565        $p->{prop_value}->{$prop}->{'-manakai-default'} = 1;
566      }
567      $p->{prop_value}->{'outline-color'}->{invert} = 1;
568      $p->{prop_value}->{'outline-color'}->{'-manakai-invert-or-currentcolor'} = 1;
569      $p->{pseudo_class}->{$_} = 1 for qw/
570        active checked disabled empty enabled first-child first-of-type
571        focus hover indeterminate last-child last-of-type link only-child
572        only-of-type root target visited
573        lang nth-child nth-last-child nth-of-type nth-last-of-type not
574        -manakai-contains -manakai-current
575      /;
576      $p->{pseudo_element}->{$_} = 1 for qw/
577        after before first-letter first-line
578      /;
579    
580      return $CSSParser = $p;
581    } # get_css_parser
582    
583    sub print_syntax_error_css_section ($$) {
584      my ($input, $result) = @_;
585    
586      print STDOUT qq[
587    <div id="$input->{id_prefix}parse-errors" class="section">
588    <h2>Parse Errors</h2>
589    
590    <dl id="$input->{id_prefix}parse-errors-list">];
591      push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};
592    
593      my $p = get_css_parser ();
594      $p->init;
595      $p->{onerror} = sub {
596        my (%opt) = @_;
597        my ($type, $cls, $msg) = get_text ($opt{type}, $opt{level});
598        if ($opt{token}) {
599          print STDOUT qq[<dt class="$cls"><a href="#$input->{id_prefix}line-$opt{token}->{line}">Line $opt{token}->{line}</a> column $opt{token}->{column}];
600        } else {
601          print STDOUT qq[<dt class="$cls">Unknown location];
602        }
603        if (defined $opt{value}) {
604          print STDOUT qq[ (<code>@{[htescape ($opt{value})]}</code>)];
605        } elsif (defined $opt{token}) {
606          print STDOUT qq[ (<code>@{[htescape (Whatpm::CSS::Tokenizer->serialize_token ($opt{token}))]}</code>)];
607        }
608        $type =~ tr/ /-/;
609        $type =~ s/\|/%7C/g;
610        $msg .= qq[ [<a href="../error-description#@{[htescape ($type)]}">Description</a>]];
611        print STDOUT qq[<dd class="$cls">], get_error_level_label (\%opt);
612        print STDOUT qq[$msg</dd>\n];
613    
614        add_error ('syntax', \%opt => $result);
615      };
616      $p->{href} = $input->{uri};
617      $p->{base_uri} = $input->{base_uri};
618    
619    #  if ($parse_mode eq 'q') {
620    #    $p->{unitless_px} = 1;
621    #    $p->{hashless_color} = 1;
622    #  }
623    
624    ## TODO: Make $input->{s} a ref.
625    
626      my $s = \$input->{s};
627      my $charset;
628      unless ($input->{is_char_string}) {
629        require Encode;
630        if (defined $input->{charset}) {## TODO: IANA->Perl
631          $charset = $input->{charset};
632          $s = \(Encode::decode ($input->{charset}, $$s));
633        } else {
634          ## TODO: charset detection
635          $s = \(Encode::decode ($charset = 'utf-8', $$s));
636        }
637      }
638      
639      my $cssom = $p->parse_char_string ($$s);
640      $cssom->manakai_input_encoding ($charset) if defined $charset;
641    
642      print STDOUT qq[</dl></div>];
643    
644      return $cssom;
645    } # print_syntax_error_css_section
646    
647  sub print_syntax_error_manifest_section ($$) {  sub print_syntax_error_manifest_section ($$) {
648    my ($input, $result) = @_;    my ($input, $result) = @_;
649    
# Line 343  sub print_syntax_error_manifest_section Line 653  sub print_syntax_error_manifest_section
653  <div id="$input->{id_prefix}parse-errors" class="section">  <div id="$input->{id_prefix}parse-errors" class="section">
654  <h2>Parse Errors</h2>  <h2>Parse Errors</h2>
655    
656  <dl>];  <dl id="$input->{id_prefix}parse-errors-list">];
657    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};    push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};
658    
659    my $onerror = sub {    my $onerror = sub {
# Line 360  sub print_syntax_error_manifest_section Line 670  sub print_syntax_error_manifest_section
670      add_error ('syntax', \%opt => $result);      add_error ('syntax', \%opt => $result);
671    };    };
672    
673      my $m = $input->{is_char_string} ? 'parse_char_string' : 'parse_byte_string';
674    my $time1 = time;    my $time1 = time;
675    my $manifest = Whatpm::CacheManifest->parse_byte_string    my $manifest = Whatpm::CacheManifest->$m
676        ($input->{s}, $input->{uri}, $input->{base_uri}, $onerror);        ($input->{s}, $input->{uri}, $input->{base_uri}, $onerror);
677    $time{parse_manifest} = time - $time1;    $time{parse_manifest} = time - $time1;
678    
# Line 370  sub print_syntax_error_manifest_section Line 681  sub print_syntax_error_manifest_section
681    return $manifest;    return $manifest;
682  } # print_syntax_error_manifest_section  } # print_syntax_error_manifest_section
683    
684  sub print_source_string_section ($$) {  sub print_syntax_error_webidl_section ($$) {
685      my ($input, $result) = @_;
686    
687      require Whatpm::WebIDL;
688    
689      print STDOUT qq[
690    <div id="$input->{id_prefix}parse-errors" class="section">
691    <h2>Parse Errors</h2>
692    
693    <dl id="$input->{id_prefix}parse-errors-list">];
694      push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};
695    
696      my $onerror = sub {
697        my (%opt) = @_;
698        my ($type, $cls, $msg) = get_text ($opt{type}, $opt{level});
699        print STDOUT qq[<dt class="$cls">], get_error_label ($input, \%opt),
700            qq[</dt>];
701        $type =~ tr/ /-/;
702        $type =~ s/\|/%7C/g;
703        $msg .= qq[ [<a href="../error-description#@{[htescape ($type)]}">Description</a>]];
704        print STDOUT qq[<dd class="$cls">], get_error_level_label (\%opt);
705        print STDOUT qq[$msg</dd>\n];
706    
707        add_error ('syntax', \%opt => $result);
708      };
709    
710    require Encode;    require Encode;
711    my $enc = Encode::find_encoding ($_[1]); ## TODO: charset name -> Perl name    my $s = $input->{is_char_string} ? $input->{s} : Encode::decode ($input->{charset} || 'utf-8', $input->{s}); ## TODO: charset
712    return unless $enc;    my $parser = Whatpm::WebIDL::Parser->new;
713      my $idl = $parser->parse_char_string ($input->{s}, $onerror);
714    
715      print STDOUT qq[</dl></div>];
716    
717      return $idl;
718    } # print_syntax_error_webidl_section
719    
720    sub print_source_string_section ($$$) {
721      my $input = shift;
722      my $s;
723      unless ($input->{is_char_string}) {
724        open my $byte_stream, '<', $_[0];
725        require Message::Charset::Info;
726        my $charset = Message::Charset::Info->get_by_iana_name ($_[1]);
727        my ($char_stream, $e_status) = $charset->get_decode_handle
728            ($byte_stream, allow_error_reporting => 1, allow_fallback => 1);
729        return unless $char_stream;
730    
731        $char_stream->onerror (sub {
732          my (undef, $type, %opt) = @_;
733          if ($opt{octets}) {
734            ${$opt{octets}} = "\x{FFFD}";
735          }
736        });
737    
738        my $t = '';
739        while (1) {
740          my $c = $char_stream->getc;
741          last unless defined $c;
742          $t .= $c;
743        }
744        $s = \$t;
745        ## TODO: Output for each line, don't concat all of lines.
746      } else {
747        $s = $_[0];
748      }
749    
   my $s = \($enc->decode (${$_[0]}));  
750    my $i = 1;                                my $i = 1;                            
751    push @nav, ['#source-string' => 'Source'] unless $input->{nested};    push @nav, ['#source-string' => 'Source'] unless $input->{nested};
752    print STDOUT qq[<div id="$input->{id_prefix}source-string" class="section">    print STDOUT qq[<div id="$input->{id_prefix}source-string" class="section">
753  <h2>Document Source</h2>  <h2>Document Source</h2>
754  <ol lang="">\n];  <ol lang="">\n];
755    if (length $$s) {    if (length $$s) {
756      while ($$s =~ /\G([^\x0A]*?)\x0D?\x0A/gc) {      while ($$s =~ /\G([^\x0D\x0A]*?)(?>\x0D\x0A?|\x0A)/gc) {
757        print STDOUT qq[<li id="$input->{id_prefix}line-$i">], htescape $1,        print STDOUT qq[<li id="$input->{id_prefix}line-$i">], htescape $1,
758            "</li>\n";            "</li>\n";
759        $i++;        $i++;
760      }      }
761      if ($$s =~ /\G([^\x0A]+)/gc) {      if ($$s =~ /\G([^\x0D\x0A]+)/gc) {
762        print STDOUT qq[<li id="$input->{id_prefix}line-$i">], htescape $1,        print STDOUT qq[<li id="$input->{id_prefix}line-$i">], htescape $1,
763            "</li>\n";            "</li>\n";
764      }      }
765    } else {    } else {
766      print STDOUT q[<li id="$input->{id_prefix}line-1"></li>];      print STDOUT q[<li id="$input->{id_prefix}line-1"></li>];
767    }    }
768    print STDOUT "</ol></div>";    print STDOUT "</ol></div>
769    <script>
770      addSourceToParseErrorList ('$input->{id_prefix}', 'parse-errors-list');
771    </script>";
772  } # print_input_string_section  } # print_input_string_section
773    
774  sub print_document_tree ($) {  sub print_document_tree ($$) {
775    my $node = shift;    my ($input, $node) = @_;
776    
777    my $r = '<ol class="xoxo">';    my $r = '<ol class="xoxo">';
778    
779    my @node = ($node);    my @node = ($node);
# Line 496  sub print_structure_dump_dom_section ($$ Line 871  sub print_structure_dump_dom_section ($$
871  <div id="$input->{id_prefix}document-tree" class="section">  <div id="$input->{id_prefix}document-tree" class="section">
872  <h2>Document Tree</h2>  <h2>Document Tree</h2>
873  ];  ];
874    push @nav, ['#document-tree' => 'Tree'] unless $input->{nested};    push @nav, [qq[#$input->{id_prefix}document-tree] => 'Tree']
875          unless $input->{nested};
876    
877    print_document_tree ($el || $doc);    print_document_tree ($input, $el || $doc);
878    
879    print STDOUT qq[</div>];    print STDOUT qq[</div>];
880  } # print_structure_dump_dom_section  } # print_structure_dump_dom_section
881    
882    sub print_structure_dump_cssom_section ($$) {
883      my ($input, $cssom) = @_;
884    
885      print STDOUT qq[
886    <div id="$input->{id_prefix}document-tree" class="section">
887    <h2>Document Tree</h2>
888    ];
889      push @nav, [qq[#$input->{id_prefix}document-tree] => 'Tree']
890          unless $input->{nested};
891    
892      ## TODO:
893      print STDOUT "<pre>".htescape ($cssom->css_text)."</pre>";
894    
895      print STDOUT qq[</div>];
896    } # print_structure_dump_cssom_section
897    
898  sub print_structure_dump_manifest_section ($$) {  sub print_structure_dump_manifest_section ($$) {
899    my ($input, $manifest) = @_;    my ($input, $manifest) = @_;
900    
# Line 510  sub print_structure_dump_manifest_sectio Line 902  sub print_structure_dump_manifest_sectio
902  <div id="$input->{id_prefix}dump-manifest" class="section">  <div id="$input->{id_prefix}dump-manifest" class="section">
903  <h2>Cache Manifest</h2>  <h2>Cache Manifest</h2>
904  ];  ];
905    push @nav, ['#dump-manifest' => 'Caceh Manifest'] unless $input->{nested};    push @nav, [qq[#$input->{id_prefix}dump-manifest] => 'Cache Manifest']
906          unless $input->{nested};
907    
908    print STDOUT qq[<dl><dt>Explicit entries</dt>];    print STDOUT qq[<dl><dt>Explicit entries</dt>];
909      my $i = 0;
910    for my $uri (@{$manifest->[0]}) {    for my $uri (@{$manifest->[0]}) {
911      my $euri = htescape ($uri);      my $euri = htescape ($uri);
912      print STDOUT qq[<dd><code class=uri>&lt;<a href="$euri">$euri</a>></code></dd>];      print STDOUT qq[<dd id="$input->{id_prefix}index-@{[$i++]}"><code class=uri>&lt;<a href="$euri">$euri</a>></code></dd>];
913    }    }
914    
915    print STDOUT qq[<dt>Fallback entries</dt><dd>    print STDOUT qq[<dt>Fallback entries</dt><dd>
# Line 524  sub print_structure_dump_manifest_sectio Line 918  sub print_structure_dump_manifest_sectio
918    for my $uri (sort {$a cmp $b} keys %{$manifest->[1]}) {    for my $uri (sort {$a cmp $b} keys %{$manifest->[1]}) {
919      my $euri = htescape ($uri);      my $euri = htescape ($uri);
920      my $euri2 = htescape ($manifest->[1]->{$uri});      my $euri2 = htescape ($manifest->[1]->{$uri});
921      print STDOUT qq[<tr><td><code class=uri>&lt;<a href="$euri">$euri</a>></code></td>      print STDOUT qq[<tr><td id="$input->{id_prefix}index-@{[$i++]}"><code class=uri>&lt;<a href="$euri">$euri</a>></code></td>
922          <td><code class=uri>&lt;<a href="$euri2">$euri2</a>></code></td>];          <td id="$input->{id_prefix}index-@{[$i++]}"><code class=uri>&lt;<a href="$euri2">$euri2</a>></code></td>];
923    }    }
924    
925    print STDOUT qq[</table><dt>Online whitelist</dt>];    print STDOUT qq[</table><dt>Online whitelist</dt>];
926    for my $uri (@{$manifest->[2]}) {    for my $uri (@{$manifest->[2]}) {
927      my $euri = htescape ($uri);      my $euri = htescape ($uri);
928      print STDOUT qq[<dd><code class=uri>&lt;<a href="$euri">$euri</a>></code></dd>];      print STDOUT qq[<dd id="$input->{id_prefix}index-@{[$i++]}"><code class=uri>&lt;<a href="$euri">$euri</a>></code></dd>];
929    }    }
930    
931    print STDOUT qq[</dl></div>];    print STDOUT qq[</dl></div>];
932  } # print_structure_dump_manifest_section  } # print_structure_dump_manifest_section
933    
934  sub print_structure_error_dom_section ($$$$) {  sub print_structure_dump_webidl_section ($$) {
935    my ($input, $doc, $el, $result) = @_;    my ($input, $idl) = @_;
936    
937      print STDOUT qq[
938    <div id="$input->{id_prefix}dump-webidl" class="section">
939    <h2>WebIDL</h2>
940    ];
941      push @nav, [qq[#$input->{id_prefix}dump-webidl] => 'WebIDL']
942          unless $input->{nested};
943    
944      print STDOUT "<pre>";
945      print STDOUT htescape ($idl->idl_text);
946      print STDOUT "</pre>";
947    
948      print STDOUT qq[</div>];
949    } # print_structure_dump_webidl_section
950    
951    sub print_structure_error_dom_section ($$$$$) {
952      my ($input, $doc, $el, $result, $onsubdoc) = @_;
953    
954    print STDOUT qq[<div id="$input->{id_prefix}document-errors" class="section">    print STDOUT qq[<div id="$input->{id_prefix}document-errors" class="section">
955  <h2>Document Errors</h2>  <h2>Document Errors</h2>
956    
957  <dl>];  <dl id=document-errors-list>];
958    push @nav, ['#document-errors' => 'Document Error'] unless $input->{nested};    push @nav, [qq[#$input->{id_prefix}document-errors] => 'Document Error']
959          unless $input->{nested};
960    
961    require Whatpm::ContentChecker;    require Whatpm::ContentChecker;
962    my $onerror = sub {    my $onerror = sub {
# Line 562  sub print_structure_error_dom_section ($ Line 974  sub print_structure_error_dom_section ($
974    my $elements;    my $elements;
975    my $time1 = time;    my $time1 = time;
976    if ($el) {    if ($el) {
977      $elements = Whatpm::ContentChecker->check_element ($el, $onerror);      $elements = Whatpm::ContentChecker->check_element
978            ($el, $onerror, $onsubdoc);
979    } else {    } else {
980      $elements = Whatpm::ContentChecker->check_document ($doc, $onerror);      $elements = Whatpm::ContentChecker->check_document
981            ($doc, $onerror, $onsubdoc);
982    }    }
983    $time{check} = time - $time1;    $time{check} = time - $time1;
984    
985    print STDOUT qq[</dl></div>];    print STDOUT qq[</dl>
986    <script>
987      addSourceToParseErrorList ('$input->{id_prefix}', 'document-errors-list');
988    </script></div>];
989    
990    return $elements;    return $elements;
991  } # print_structure_error_dom_section  } # print_structure_error_dom_section
# Line 580  sub print_structure_error_manifest_secti Line 997  sub print_structure_error_manifest_secti
997  <h2>Document Errors</h2>  <h2>Document Errors</h2>
998    
999  <dl>];  <dl>];
1000    push @nav, ['#document-errors' => 'Document Error'] unless $input->{nested};    push @nav, [qq[#$input->{id_prefix}document-errors] => 'Document Error']
1001          unless $input->{nested};
1002    
1003    require Whatpm::CacheManifest;    require Whatpm::CacheManifest;
1004    Whatpm::CacheManifest->check_manifest ($manifest, sub {    Whatpm::CacheManifest->check_manifest ($manifest, sub {
# Line 597  sub print_structure_error_manifest_secti Line 1015  sub print_structure_error_manifest_secti
1015    print STDOUT qq[</div>];    print STDOUT qq[</div>];
1016  } # print_structure_error_manifest_section  } # print_structure_error_manifest_section
1017    
1018    sub print_structure_error_webidl_section ($$$) {
1019      my ($input, $idl, $result) = @_;
1020    
1021      print STDOUT qq[<div id="$input->{id_prefix}document-errors" class="section">
1022    <h2>Document Errors</h2>
1023    
1024    <dl>];
1025      push @nav, [qq[#$input->{id_prefix}document-errors] => 'Document Error']
1026          unless $input->{nested};
1027    
1028    ## TODO:
1029    
1030      print STDOUT qq[</div>];
1031    } # print_structure_error_webidl_section
1032    
1033  sub print_table_section ($$) {  sub print_table_section ($$) {
1034    my ($input, $tables) = @_;    my ($input, $tables) = @_;
1035        
1036    push @nav, ['#tables' => 'Tables'] unless $input->{nested};    push @nav, [qq[#$input->{id_prefix}tables] => 'Tables']
1037          unless $input->{nested};
1038    print STDOUT qq[    print STDOUT qq[
1039  <div id="$input->{id_prefix}tables" class="section">  <div id="$input->{id_prefix}tables" class="section">
1040  <h2>Tables</h2>  <h2>Tables</h2>
# Line 615  sub print_table_section ($$) { Line 1049  sub print_table_section ($$) {
1049    require JSON;    require JSON;
1050        
1051    my $i = 0;    my $i = 0;
1052    for my $table_el (@$tables) {    for my $table (@$tables) {
1053      $i++;      $i++;
1054      print STDOUT qq[<div class="section" id="$input->{id_prefix}table-$i"><h3>] .      print STDOUT qq[<div class="section" id="$input->{id_prefix}table-$i"><h3>] .
1055          get_node_link ($input, $table_el) . q[</h3>];          get_node_link ($input, $table->{element}) . q[</h3>];
1056    
1057      ## TODO: Make |ContentChecker| return |form_table| result      delete $table->{element};
1058      ## so that this script don't have to run the algorithm twice.  
1059      my $table = Whatpm::HTMLTable->form_table ($table_el);      for (@{$table->{column_group}}, @{$table->{column}}, $table->{caption},
1060                 @{$table->{row}}) {
     for (@{$table->{column_group}}, @{$table->{column}}, $table->{caption}) {  
1061        next unless $_;        next unless $_;
1062        delete $_->{element};        delete $_->{element};
1063      }      }
# Line 660  sub print_table_section ($$) { Line 1093  sub print_table_section ($$) {
1093  sub print_listing_section ($$$) {  sub print_listing_section ($$$) {
1094    my ($opt, $input, $ids) = @_;    my ($opt, $input, $ids) = @_;
1095        
1096    push @nav, ['#' . $opt->{id} => $opt->{label}] unless $input->{nested};    push @nav, ['#' . $input->{id_prefix} . $opt->{id} => $opt->{label}]
1097          unless $input->{nested};
1098    print STDOUT qq[    print STDOUT qq[
1099  <div id="$input->{id_prefix}$opt->{id}" class="section">  <div id="$input->{id_prefix}$opt->{id}" class="section">
1100  <h2>$opt->{heading}</h2>  <h2>$opt->{heading}</h2>
# Line 676  sub print_listing_section ($$$) { Line 1110  sub print_listing_section ($$$) {
1110    print STDOUT qq[</dl></div>];    print STDOUT qq[</dl></div>];
1111  } # print_listing_section  } # print_listing_section
1112    
1113    sub print_uri_section ($$$) {
1114      my ($input, $uris) = @_;
1115    
1116      ## NOTE: URIs contained in the DOM (i.e. in HTML or XML documents),
1117      ## except for those in RDF triples.
1118      ## TODO: URIs in CSS
1119      
1120      push @nav, ['#' . $input->{id_prefix} . 'uris' => 'URIs']
1121          unless $input->{nested};
1122      print STDOUT qq[
1123    <div id="$input->{id_prefix}uris" class="section">
1124    <h2>URIs</h2>
1125    
1126    <dl>];
1127      for my $uri (sort {$a cmp $b} keys %$uris) {
1128        my $euri = htescape ($uri);
1129        print STDOUT qq[<dt><code class=uri>&lt;<a href="$euri">$euri</a>></code>];
1130        my $eccuri = htescape (get_cc_uri ($uri));
1131        print STDOUT qq[<dd><a href="$eccuri">Check conformance of this document</a>];
1132        print STDOUT qq[<dd>Found at: <ul>];
1133        for my $entry (@{$uris->{$uri}}) {
1134          print STDOUT qq[<li>], get_node_link ($input, $entry->{node});
1135          if (keys %{$entry->{type} or {}}) {
1136            print STDOUT ' (';
1137            print STDOUT join ', ', map {
1138              {
1139                hyperlink => 'Hyperlink',
1140                resource => 'Link to an external resource',
1141                namespace => 'Namespace URI',
1142                cite => 'Citation or link to a long description',
1143                embedded => 'Link to an embedded content',
1144                base => 'Base URI',
1145                action => 'Submission URI',
1146              }->{$_}
1147                or
1148              htescape ($_)
1149            } keys %{$entry->{type}};
1150            print STDOUT ')';
1151          }
1152        }
1153        print STDOUT qq[</ul>];
1154      }
1155      print STDOUT qq[</dl></div>];
1156    } # print_uri_section
1157    
1158    sub print_rdf_section ($$$) {
1159      my ($input, $rdfs) = @_;
1160      
1161      push @nav, ['#' . $input->{id_prefix} . 'rdf' => 'RDF']
1162          unless $input->{nested};
1163      print STDOUT qq[
1164    <div id="$input->{id_prefix}rdf" class="section">
1165    <h2>RDF Triples</h2>
1166    
1167    <dl>];
1168      my $i = 0;
1169      for my $rdf (@$rdfs) {
1170        print STDOUT qq[<dt id="$input->{id_prefix}rdf-@{[$i++]}">];
1171        print STDOUT get_node_link ($input, $rdf->[0]);
1172        print STDOUT qq[<dd><dl>];
1173        for my $triple (@{$rdf->[1]}) {
1174          print STDOUT '<dt>' . get_node_link ($input, $triple->[0]) . '<dd>';
1175          print STDOUT get_rdf_resource_html ($triple->[1]);
1176          print STDOUT ' ';
1177          print STDOUT get_rdf_resource_html ($triple->[2]);
1178          print STDOUT ' ';
1179          print STDOUT get_rdf_resource_html ($triple->[3]);
1180        }
1181        print STDOUT qq[</dl>];
1182      }
1183      print STDOUT qq[</dl></div>];
1184    } # print_rdf_section
1185    
1186    sub get_rdf_resource_html ($) {
1187      my $resource = shift;
1188      if (defined $resource->{uri}) {
1189        my $euri = htescape ($resource->{uri});
1190        return '<code class=uri>&lt;<a href="' . $euri . '">' . $euri .
1191            '</a>></code>';
1192      } elsif (defined $resource->{bnodeid}) {
1193        return htescape ('_:' . $resource->{bnodeid});
1194      } elsif ($resource->{nodes}) {
1195        return '(rdf:XMLLiteral)';
1196      } elsif (defined $resource->{value}) {
1197        my $elang = htescape (defined $resource->{language}
1198                                  ? $resource->{language} : '');
1199        my $r = qq[<q lang="$elang">] . htescape ($resource->{value}) . '</q>';
1200        if (defined $resource->{datatype}) {
1201          my $euri = htescape ($resource->{datatype});
1202          $r .= '^^<code class=uri>&lt;<a href="' . $euri . '">' . $euri .
1203              '</a>></code>';
1204        } elsif (length $resource->{language}) {
1205          $r .= '@' . htescape ($resource->{language});
1206        }
1207        return $r;
1208      } else {
1209        return '??';
1210      }
1211    } # get_rdf_resource_html
1212    
1213  sub print_result_section ($) {  sub print_result_section ($) {
1214    my $result = shift;    my $result = shift;
1215    
# Line 741  Errors</a></th> Line 1275  Errors</a></th>
1275    
1276      print STDOUT 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>];      print STDOUT 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>];
1277      if ($uncertain) {      if ($uncertain) {
1278        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : $result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">&#x2212;&#x221E;..$result->{$_->[1]}->{score_max}</td>];        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : $result->{$_->[1]}->{should} ? 'SEE-RESULT' : '']}">&#x2212;&#x221E;..$result->{$_->[1]}->{score_max}];
1279      } elsif ($result->{$_->[1]}->{score_min} != $result->{$_->[1]}->{score_max}) {      } elsif ($result->{$_->[1]}->{score_min} != $result->{$_->[1]}->{score_max}) {
1280        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : 'SEE-RESULT']}">$result->{$_->[1]}->{score_min}..$result->{$_->[1]}->{score_max}</td></tr>];        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : 'SEE-RESULT']}">$result->{$_->[1]}->{score_min}..$result->{$_->[1]}->{score_max}];
1281      } else {      } else {
1282        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{score_min}</td></tr>];        print qq[<td class="@{[$result->{$_->[1]}->{must} ? 'FAIL' : '']}">$result->{$_->[1]}->{score_min}];
1283      }      }
1284        print qq[ / 20];
1285    }    }
1286    
1287    $score_max += $score_base;    $score_max += $score_base;
1288    
1289    print STDOUT qq[    print STDOUT qq[
1290  <tr class=uncertain><th scope=row>Semantics</th><td>0?</td><td>0?</td><td>0?</td><td>&#x2212;&#x221E;..$score_base</td></tr>  <tr class=uncertain><th scope=row>Semantics</th><td>0?</td><td>0?</td><td>0?</td><td>&#x2212;&#x221E;..$score_base / 20
1291  </tbody>  </tbody>
1292  <tfoot><tr class=uncertain><th scope=row>Total</th>  <tfoot><tr class=uncertain><th scope=row>Total</th>
1293  <td class="@{[$must_error ? 'FAIL' : '']}">$must_error?</td>  <td class="@{[$must_error ? 'FAIL' : '']}">$must_error?</td>
1294  <td class="@{[$should_error ? 'SEE-RESULT' : '']}">$should_error?</td>  <td class="@{[$should_error ? 'SEE-RESULT' : '']}">$should_error?</td>
1295  <td>$warning?</td>  <td>$warning?</td>
1296  <td class="@{[$must_error ? 'FAIL' : $should_error ? 'SEE-RESULT' : '']}"><strong>&#x2212;&#x221E;..$score_max</strong></td></tr></tfoot>  <td class="@{[$must_error ? 'FAIL' : $should_error ? 'SEE-RESULT' : '']}"><strong>&#x2212;&#x221E;..$score_max</strong> / 100
1297  </table>  </table>
1298    
1299  <p><strong>Important</strong>: This conformance checking service  <p><strong>Important</strong>: This conformance checking service
# Line 772  sub print_result_unknown_type_section ($ Line 1307  sub print_result_unknown_type_section ($
1307    
1308    my $euri = htescape ($input->{uri});    my $euri = htescape ($input->{uri});
1309    print STDOUT qq[    print STDOUT qq[
1310  <div id="parse-errors" class="section">  <div id="$input->{id_prefix}parse-errors" class="section">
1311  <h2>Errors</h2>  <h2>Errors</h2>
1312    
1313  <dl>  <dl>
# Line 785  sub print_result_unknown_type_section ($ Line 1320  sub print_result_unknown_type_section ($
1320  </dl>  </dl>
1321  </div>  </div>
1322  ];  ];
1323    push @nav, ['#parse-errors' => 'Errors'];    push @nav, [qq[#$input->{id_prefix}parse-errors] => 'Errors']
1324          unless $input->{nested};
1325    add_error (char => {level => 'u'} => $result);    add_error (char => {level => 'u'} => $result);
1326    add_error (syntax => {level => 'u'} => $result);    add_error (syntax => {level => 'u'} => $result);
1327    add_error (structure => {level => 'u'} => $result);    add_error (structure => {level => 'u'} => $result);
# Line 804  sub get_error_label ($$) { Line 1340  sub get_error_label ($$) {
1340    
1341    my $r = '';    my $r = '';
1342    
1343    if (defined $err->{line}) {    my $line;
1344      if ($err->{column} > 0) {    my $column;
1345        $r = qq[<a href="#line-$err->{line}">Line $err->{line}</a> column $err->{column}];      
1346      if (defined $err->{node}) {
1347        $line = $err->{node}->get_user_data ('manakai_source_line');
1348        if (defined $line) {
1349          $column = $err->{node}->get_user_data ('manakai_source_column');
1350      } else {      } else {
1351        $err->{line} = $err->{line} - 1 || 1;        if ($err->{node}->node_type == $err->{node}->ATTRIBUTE_NODE) {
1352        $r = qq[<a href="#line-$err->{line}">Line $err->{line}</a>];          my $owner = $err->{node}->owner_element;
1353            $line = $owner->get_user_data ('manakai_source_line');
1354            $column = $owner->get_user_data ('manakai_source_column');
1355          } else {
1356            my $parent = $err->{node}->parent_node;
1357            if ($parent) {
1358              $line = $parent->get_user_data ('manakai_source_line');
1359              $column = $parent->get_user_data ('manakai_source_column');
1360            }
1361          }
1362        }
1363      }
1364      unless (defined $line) {
1365        if (defined $err->{token} and defined $err->{token}->{line}) {
1366          $line = $err->{token}->{line};
1367          $column = $err->{token}->{column};
1368        } elsif (defined $err->{line}) {
1369          $line = $err->{line};
1370          $column = $err->{column};
1371        }
1372      }
1373    
1374      if (defined $line) {
1375        if (defined $column and $column > 0) {
1376          $r = qq[<a href="#$input->{id_prefix}line-$line">Line $line</a> column $column];
1377        } else {
1378          $line = $line - 1 || 1;
1379          $r = qq[<a href="#$input->{id_prefix}line-$line">Line $line</a>];
1380      }      }
1381    }    }
1382    
1383    if (defined $err->{node}) {    if (defined $err->{node}) {
1384      $r .= ' ' if length $r;      $r .= ' ' if length $r;
1385      $r = get_node_link ($input, $err->{node});      $r .= get_node_link ($input, $err->{node});
1386    }    }
1387    
1388    if (defined $err->{index}) {    if (defined $err->{index}) {
1389      $r .= ' ' if length $r;      if (length $r) {
1390      $r .= 'Index ' . (0+$err->{index});        $r .= ', Index ' . (0+$err->{index});
1391        } else {
1392          $r .= "<a href='#$input->{id_prefix}index-@{[0+$err->{index}]}'>Index "
1393              . (0+$err->{index}) . '</a>';
1394        }
1395    }    }
1396    
1397    if (defined $err->{value}) {    if (defined $err->{value}) {
# Line 848  sub get_error_level_label ($) { Line 1419  sub get_error_level_label ($) {
1419    } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {    } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {
1420      $r = qq[<strong><a href="../error-description#level-u">Not      $r = qq[<strong><a href="../error-description#level-u">Not
1421          supported</a></strong>: ];          supported</a></strong>: ];
1422      } elsif ($err->{level} eq 'i') {
1423        $r = qq[<strong><a href="../error-description#level-i">Information</a></strong>: ];
1424    } else {    } else {
1425      my $elevel = htescape ($err->{level});      my $elevel = htescape ($err->{level});
1426      $r = qq[<strong><a href="../error-description#level-$elevel">$elevel</a></strong>:      $r = qq[<strong><a href="../error-description#level-$elevel">$elevel</a></strong>:
# Line 863  sub get_node_path ($) { Line 1436  sub get_node_path ($) {
1436    while (defined $node) {    while (defined $node) {
1437      my $rs;      my $rs;
1438      if ($node->node_type == 1) {      if ($node->node_type == 1) {
1439        $rs = $node->manakai_local_name;        $rs = $node->node_name;
1440        $node = $node->parent_node;        $node = $node->parent_node;
1441      } elsif ($node->node_type == 2) {      } elsif ($node->node_type == 2) {
1442        $rs = '@' . $node->manakai_local_name;        $rs = '@' . $node->node_name;
1443        $node = $node->owner_element;        $node = $node->owner_element;
1444      } elsif ($node->node_type == 3) {      } elsif ($node->node_type == 3) {
1445        $rs = '"' . $node->data . '"';        $rs = '"' . $node->data . '"';
# Line 944  sub get_text ($) { Line 1517  sub get_text ($) {
1517    
1518  }  }
1519    
1520    sub encode_uri_component ($) {
1521      require Encode;
1522      my $s = Encode::encode ('utf8', shift);
1523      $s =~ s/([^0-9A-Za-z_.~-])/sprintf '%%%02X', ord $1/ge;
1524      return $s;
1525    } # encode_uri_component
1526    
1527    sub get_cc_uri ($) {
1528      return './?uri=' . encode_uri_component ($_[0]);
1529    } # get_cc_uri
1530    
1531  sub get_input_document ($$) {  sub get_input_document ($$) {
1532    my ($http, $dom) = @_;    my ($http, $dom) = @_;
1533    
# Line 1092  EOH Line 1676  EOH
1676      return $r;      return $r;
1677    }    }
1678    
1679      $r->{inner_html_element} = $http->get_parameter ('e');
1680    
1681    return $r;    return $r;
1682  } # get_input_document  } # get_input_document
1683    
# Line 1124  Wakaba <w@suika.fam.cx>. Line 1710  Wakaba <w@suika.fam.cx>.
1710    
1711  =head1 LICENSE  =head1 LICENSE
1712    
1713  Copyright 2007 Wakaba <w@suika.fam.cx>  Copyright 2007-2008 Wakaba <w@suika.fam.cx>
1714    
1715  This library is free software; you can redistribute it  This library is free software; you can redistribute it
1716  and/or modify it under the same terms as Perl itself.  and/or modify it under the same terms as Perl itself.

Legend:
Removed from v.1.33  
changed lines
  Added in v.1.52

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24