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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.50 - (hide annotations) (download)
Tue May 6 08:47:09 2008 UTC (18 years, 2 months ago) by wakaba
Branch: MAIN
Changes since 1.49: +5 -7 lines
++ ChangeLog	6 May 2008 08:47:05 -0000
	* cc.cgi: Use table object returned by the checker; don't
	form a table by itself.

	* table-script.js: Use different coloring for empty data cells.

	* cc.cgi, table.cgi: Remove table reference for JSON convertion.

2008-05-06  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 #!/usr/bin/perl
2     use strict;
3 wakaba 1.23 use utf8;
4 wakaba 1.1
5     use lib qw[/home/httpd/html/www/markup/html/whatpm
6 wakaba 1.16 /home/wakaba/work/manakai2/lib];
7 wakaba 1.1 use CGI::Carp qw[fatalsToBrowser];
8 wakaba 1.2 use Scalar::Util qw[refaddr];
9 wakaba 1.16 use Time::HiRes qw/time/;
10 wakaba 1.1
11 wakaba 1.2 sub htescape ($) {
12     my $s = $_[0];
13     $s =~ s/&/&amp;/g;
14     $s =~ s/</&lt;/g;
15     $s =~ s/>/&gt;/g;
16     $s =~ s/"/&quot;/g;
17 wakaba 1.12 $s =~ s{([\x00-\x09\x0B-\x1F\x7F-\xA0\x{FEFF}\x{FFFC}-\x{FFFF}])}{
18     sprintf '<var>U+%04X</var>', ord $1;
19     }ge;
20 wakaba 1.2 return $s;
21     } # htescape
22    
23 wakaba 1.35 my @nav;
24     my %time;
25     require Message::DOM::DOMImplementation;
26     my $dom = Message::DOM::DOMImplementation->new;
27     {
28 wakaba 1.16 use Message::CGI::HTTP;
29     my $http = Message::CGI::HTTP->new;
30 wakaba 1.1
31 wakaba 1.16 if ($http->get_meta_variable ('PATH_INFO') ne '/') {
32 wakaba 1.8 print STDOUT "Status: 404 Not Found\nContent-Type: text/plain; charset=us-ascii\n\n400";
33     exit;
34     }
35    
36 wakaba 1.12 binmode STDOUT, ':utf8';
37 wakaba 1.14 $| = 1;
38 wakaba 1.12
39 wakaba 1.7 load_text_catalog ('en'); ## TODO: conneg
40    
41 wakaba 1.2 print STDOUT qq[Content-Type: text/html; charset=utf-8
42    
43     <!DOCTYPE html>
44     <html lang="en">
45     <head>
46     <title>Web Document Conformance Checker (BETA)</title>
47 wakaba 1.3 <link rel="stylesheet" href="../cc-style.css" type="text/css">
48 wakaba 1.2 </head>
49     <body>
50 wakaba 1.13 <h1><a href="../cc-interface">Web Document Conformance Checker</a>
51     (<em>beta</em>)</h1>
52 wakaba 1.14 ];
53 wakaba 1.2
54 wakaba 1.14 $| = 0;
55     my $input = get_input_document ($http, $dom);
56 wakaba 1.16 my $char_length = 0;
57 wakaba 1.14
58     print qq[
59 wakaba 1.4 <div id="document-info" class="section">
60 wakaba 1.2 <dl>
61 wakaba 1.9 <dt>Request URI</dt>
62     <dd><code class="URI" lang="">&lt;<a href="@{[htescape $input->{request_uri}]}">@{[htescape $input->{request_uri}]}</a>&gt;</code></dd>
63 wakaba 1.2 <dt>Document URI</dt>
64 wakaba 1.25 <dd><code class="URI" lang="">&lt;<a href="@{[htescape $input->{uri}]}" id=anchor-document-uri>@{[htescape $input->{uri}]}</a>&gt;</code>
65     <script>
66     document.title = '<'
67     + document.getElementById ('anchor-document-uri').href + '> \\u2014 '
68     + document.title;
69     </script></dd>
70 wakaba 1.2 ]; # no </dl> yet
71 wakaba 1.3 push @nav, ['#document-info' => 'Information'];
72 wakaba 1.1
73 wakaba 1.9 if (defined $input->{s}) {
74 wakaba 1.16 $char_length = length $input->{s};
75 wakaba 1.9
76     print STDOUT qq[
77     <dt>Base URI</dt>
78     <dd><code class="URI" lang="">&lt;<a href="@{[htescape $input->{base_uri}]}">@{[htescape $input->{base_uri}]}</a>&gt;</code></dd>
79     <dt>Internet Media Type</dt>
80     <dd><code class="MIME" lang="en">@{[htescape $input->{media_type}]}</code>
81 wakaba 1.25 @{[$input->{media_type_overridden} ? '<em>(overridden)</em>' : defined $input->{official_type} ? $input->{media_type} eq $input->{official_type} ? '' : '<em>(sniffed; official type is: <code class=MIME lang=en>'.htescape ($input->{official_type}).'</code>)' : '<em>(sniffed)</em>']}</dd>
82 wakaba 1.9 <dt>Character Encoding</dt>
83     <dd>@{[defined $input->{charset} ? '<code class="charset" lang="en">'.htescape ($input->{charset}).'</code>' : '(none)']}
84     @{[$input->{charset_overridden} ? '<em>(overridden)</em>' : '']}</dd>
85 wakaba 1.16 <dt>Length</dt>
86     <dd>$char_length byte@{[$char_length == 1 ? '' : 's']}</dd>
87 wakaba 1.9 </dl>
88     </div>
89 wakaba 1.39
90     <script src="../cc-script.js"></script>
91 wakaba 1.9 ];
92    
93 wakaba 1.35 $input->{id_prefix} = '';
94     #$input->{nested} = 0;
95 wakaba 1.20 my $result = {conforming_min => 1, conforming_max => 1};
96 wakaba 1.31 check_and_print ($input => $result);
97 wakaba 1.19 print_result_section ($result);
98 wakaba 1.9 } else {
99 wakaba 1.18 print STDOUT qq[</dl></div>];
100     print_result_input_error_section ($input);
101 wakaba 1.9 }
102 wakaba 1.3
103 wakaba 1.2 print STDOUT qq[
104 wakaba 1.3 <ul class="navigation" id="nav-items">
105     ];
106     for (@nav) {
107     print STDOUT qq[<li><a href="$_->[0]">$_->[1]</a></li>];
108     }
109     print STDOUT qq[
110     </ul>
111 wakaba 1.2 </body>
112     </html>
113     ];
114 wakaba 1.1
115 wakaba 1.24 for (qw/decode parse parse_html parse_xml parse_manifest
116     check check_manifest/) {
117 wakaba 1.16 next unless defined $time{$_};
118     open my $file, '>>', ".cc-$_.txt" or die ".cc-$_.txt: $!";
119     print $file $char_length, "\t", $time{$_}, "\n";
120     }
121    
122 wakaba 1.1 exit;
123 wakaba 1.35 }
124 wakaba 1.1
125 wakaba 1.19 sub add_error ($$$) {
126     my ($layer, $err, $result) = @_;
127     if (defined $err->{level}) {
128     if ($err->{level} eq 's') {
129     $result->{$layer}->{should}++;
130     $result->{$layer}->{score_min} -= 2;
131     $result->{conforming_min} = 0;
132     } elsif ($err->{level} eq 'w' or $err->{level} eq 'g') {
133     $result->{$layer}->{warning}++;
134 wakaba 1.30 } elsif ($err->{level} eq 'u' or $err->{level} eq 'unsupported') {
135 wakaba 1.19 $result->{$layer}->{unsupported}++;
136     $result->{unsupported} = 1;
137 wakaba 1.37 } elsif ($err->{level} eq 'i') {
138     #
139 wakaba 1.19 } else {
140     $result->{$layer}->{must}++;
141     $result->{$layer}->{score_max} -= 2;
142     $result->{$layer}->{score_min} -= 2;
143     $result->{conforming_min} = 0;
144     $result->{conforming_max} = 0;
145     }
146     } else {
147     $result->{$layer}->{must}++;
148     $result->{$layer}->{score_max} -= 2;
149     $result->{$layer}->{score_min} -= 2;
150     $result->{conforming_min} = 0;
151     $result->{conforming_max} = 0;
152     }
153     } # add_error
154    
155 wakaba 1.31 sub check_and_print ($$) {
156     my ($input, $result) = @_;
157    
158     print_http_header_section ($input, $result);
159    
160     my $doc;
161     my $el;
162 wakaba 1.35 my $cssom;
163 wakaba 1.31 my $manifest;
164 wakaba 1.34 my @subdoc;
165 wakaba 1.31
166     if ($input->{media_type} eq 'text/html') {
167     ($doc, $el) = print_syntax_error_html_section ($input, $result);
168     print_source_string_section
169 wakaba 1.35 ($input,
170     \($input->{s}),
171     $input->{charset} || $doc->input_encoding);
172 wakaba 1.31 } elsif ({
173     'text/xml' => 1,
174     'application/atom+xml' => 1,
175     'application/rss+xml' => 1,
176 wakaba 1.45 'image/svg+xml' => 1,
177 wakaba 1.31 'application/xhtml+xml' => 1,
178     'application/xml' => 1,
179 wakaba 1.45 ## TODO: Should we make all XML MIME Types fall
180     ## into this category?
181    
182     'application/rdf+xml' => 1, ## NOTE: This type has different model.
183 wakaba 1.31 }->{$input->{media_type}}) {
184     ($doc, $el) = print_syntax_error_xml_section ($input, $result);
185 wakaba 1.35 print_source_string_section ($input,
186     \($input->{s}),
187     $doc->input_encoding);
188     } elsif ($input->{media_type} eq 'text/css') {
189     $cssom = print_syntax_error_css_section ($input, $result);
190     print_source_string_section
191     ($input, \($input->{s}),
192     $cssom->manakai_input_encoding);
193 wakaba 1.31 } elsif ($input->{media_type} eq 'text/cache-manifest') {
194     ## TODO: MUST be text/cache-manifest
195     $manifest = print_syntax_error_manifest_section ($input, $result);
196 wakaba 1.35 print_source_string_section ($input, \($input->{s}),
197     'utf-8');
198 wakaba 1.31 } else {
199     ## TODO: Change HTTP status code??
200     print_result_unknown_type_section ($input, $result);
201     }
202    
203     if (defined $doc or defined $el) {
204 wakaba 1.34 $doc->document_uri ($input->{uri});
205     $doc->manakai_entity_base_uri ($input->{base_uri});
206 wakaba 1.32 print_structure_dump_dom_section ($input, $doc, $el);
207     my $elements = print_structure_error_dom_section
208 wakaba 1.34 ($input, $doc, $el, $result, sub {
209     push @subdoc, shift;
210     });
211 wakaba 1.32 print_table_section ($input, $elements->{table}) if @{$elements->{table}};
212 wakaba 1.33 print_listing_section ({
213     id => 'identifiers', label => 'IDs', heading => 'Identifiers',
214     }, $input, $elements->{id}) if keys %{$elements->{id}};
215     print_listing_section ({
216     id => 'terms', label => 'Terms', heading => 'Terms',
217     }, $input, $elements->{term}) if keys %{$elements->{term}};
218     print_listing_section ({
219     id => 'classes', label => 'Classes', heading => 'Classes',
220     }, $input, $elements->{class}) if keys %{$elements->{class}};
221 wakaba 1.48 print_uri_section ($input, $elements->{uri}) if keys %{$elements->{uri}};
222 wakaba 1.45 print_rdf_section ($input, $elements->{rdf}) if @{$elements->{rdf}};
223 wakaba 1.35 } elsif (defined $cssom) {
224     print_structure_dump_cssom_section ($input, $cssom);
225     ## TODO: CSSOM validation
226 wakaba 1.36 add_error ('structure', {level => 'u'} => $result);
227 wakaba 1.31 } elsif (defined $manifest) {
228 wakaba 1.32 print_structure_dump_manifest_section ($input, $manifest);
229     print_structure_error_manifest_section ($input, $manifest, $result);
230 wakaba 1.31 }
231 wakaba 1.34
232     my $id_prefix = 0;
233     for my $subinput (@subdoc) {
234     $subinput->{id_prefix} = 'subdoc-' . ++$id_prefix;
235     $subinput->{nested} = 1;
236     $subinput->{base_uri} = $subinput->{container_node}->base_uri
237     unless defined $subinput->{base_uri};
238     my $ebaseuri = htescape ($subinput->{base_uri});
239     push @nav, ['#' . $subinput->{id_prefix} => 'Sub #' . $id_prefix];
240     print STDOUT qq[<div id="$subinput->{id_prefix}" class=section>
241     <h2>Subdocument #$id_prefix</h2>
242    
243     <dl>
244     <dt>Internet Media Type</dt>
245     <dd><code class="MIME" lang="en">@{[htescape $subinput->{media_type}]}</code>
246     <dt>Container Node</dt>
247     <dd>@{[get_node_link ($input, $subinput->{container_node})]}</dd>
248     <dt>Base <abbr title="Uniform Resource Identifiers">URI</abbr></dt>
249     <dd><code class=URI>&lt;<a href="$ebaseuri">$ebaseuri</a>></code></dd>
250     </dl>];
251    
252 wakaba 1.35 $subinput->{id_prefix} .= '-';
253 wakaba 1.34 check_and_print ($subinput => $result);
254    
255     print STDOUT qq[</div>];
256     }
257 wakaba 1.31 } # check_and_print
258    
259 wakaba 1.19 sub print_http_header_section ($$) {
260     my ($input, $result) = @_;
261 wakaba 1.9 return unless defined $input->{header_status_code} or
262     defined $input->{header_status_text} or
263 wakaba 1.34 @{$input->{header_field} or []};
264 wakaba 1.9
265 wakaba 1.32 push @nav, ['#source-header' => 'HTTP Header'] unless $input->{nested};
266     print STDOUT qq[<div id="$input->{id_prefix}source-header" class="section">
267 wakaba 1.9 <h2>HTTP Header</h2>
268    
269     <p><strong>Note</strong>: Due to the limitation of the
270     network library in use, the content of this section might
271     not be the real header.</p>
272    
273     <table><tbody>
274     ];
275    
276     if (defined $input->{header_status_code}) {
277     print STDOUT qq[<tr><th scope="row">Status code</th>];
278     print STDOUT qq[<td><code>@{[htescape ($input->{header_status_code})]}</code></td></tr>];
279     }
280     if (defined $input->{header_status_text}) {
281     print STDOUT qq[<tr><th scope="row">Status text</th>];
282     print STDOUT qq[<td><code>@{[htescape ($input->{header_status_text})]}</code></td></tr>];
283     }
284    
285     for (@{$input->{header_field}}) {
286     print STDOUT qq[<tr><th scope="row"><code>@{[htescape ($_->[0])]}</code></th>];
287     print STDOUT qq[<td><code>@{[htescape ($_->[1])]}</code></td></tr>];
288     }
289    
290     print STDOUT qq[</tbody></table></div>];
291     } # print_http_header_section
292    
293 wakaba 1.19 sub print_syntax_error_html_section ($$) {
294     my ($input, $result) = @_;
295 wakaba 1.18
296     require Encode;
297     require Whatpm::HTML;
298    
299     print STDOUT qq[
300 wakaba 1.32 <div id="$input->{id_prefix}parse-errors" class="section">
301 wakaba 1.18 <h2>Parse Errors</h2>
302    
303 wakaba 1.39 <dl id="$input->{id_prefix}parse-errors-list">];
304 wakaba 1.32 push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{nested};
305 wakaba 1.18
306     my $onerror = sub {
307     my (%opt) = @_;
308     my ($type, $cls, $msg) = get_text ($opt{type}, $opt{level});
309 wakaba 1.38 print STDOUT qq[<dt class="$cls">], get_error_label ($input, \%opt),
310     qq[</dt>];
311 wakaba 1.18 $type =~ tr/ /-/;
312     $type =~ s/\|/%7C/g;
313     $msg .= qq[ [<a href="../error-description#@{[htescape ($type)]}">Description</a>]];
314 wakaba 1.23 print STDOUT qq[<dd class="$cls">], get_error_level_label (\%opt);
315     print STDOUT qq[$msg</dd>\n];
316 wakaba 1.19
317     add_error ('syntax', \%opt => $result);
318 wakaba 1.18 };
319    
320     my $doc = $dom->create_document;
321     my $el;
322 wakaba 1.35 my $inner_html_element = $input->{inner_html_element};
323 wakaba 1.18 if (defined $inner_html_element and length $inner_html_element) {
324 wakaba 1.26 $input->{charset} ||= 'windows-1252'; ## TODO: for now.
325 wakaba 1.24 my $time1 = time;
326 wakaba 1.48 my $t = \($input->{s});
327     unless ($input->{is_char_string}) {
328     $t = \(Encode::decode ($input->{charset}, $$t));
329     }
330 wakaba 1.24 $time{decode} = time - $time1;
331    
332 wakaba 1.18 $el = $doc->create_element_ns
333     ('http://www.w3.org/1999/xhtml', [undef, $inner_html_element]);
334 wakaba 1.24 $time1 = time;
335 wakaba 1.48 Whatpm::HTML->set_inner_html ($el, $$t, $onerror);
336 wakaba 1.24 $time{parse} = time - $time1;
337 wakaba 1.18 } else {
338 wakaba 1.24 my $time1 = time;
339 wakaba 1.48 if ($input->{is_char_string}) {
340     Whatpm::HTML->parse_char_string ($input->{s} => $doc, $onerror);
341     } else {
342     Whatpm::HTML->parse_byte_string
343     ($input->{charset}, $input->{s} => $doc, $onerror);
344     }
345 wakaba 1.24 $time{parse_html} = time - $time1;
346 wakaba 1.18 }
347 wakaba 1.26 $doc->manakai_charset ($input->{official_charset})
348     if defined $input->{official_charset};
349 wakaba 1.24
350 wakaba 1.18 print STDOUT qq[</dl></div>];
351    
352     return ($doc, $el);
353     } # print_syntax_error_html_section
354    
355 wakaba 1.19 sub print_syntax_error_xml_section ($$) {
356     my ($input, $result) = @_;
357 wakaba 1.18
358     require Message::DOM::XMLParserTemp;
359    
360     print STDOUT qq[
361 wakaba 1.32 <div id="$input->{id_prefix}parse-errors" class="section">
362 wakaba 1.18 <h2>Parse Errors</h2>
363    
364 wakaba 1.39 <dl id="$input->{id_prefix}parse-errors-list">];
365 wakaba 1.32 push @nav, ['#parse-errors' => 'Parse Error'] unless $input->{prefix};
366 wakaba 1.18
367     my $onerror = sub {
368     my $err = shift;
369     my $line = $err->location->line_number;
370 wakaba 1.35 print STDOUT qq[<dt><a href="#$input->{id_prefix}line-$line">Line $line</a> column ];
371 wakaba 1.18 print STDOUT $err->location->column_number, "</dt><dd>";
372     print STDOUT htescape $err->text, "</dd>\n";
373 wakaba 1.19
374     add_error ('syntax', {type => $err->text,
375     level => [
376     $err->SEVERITY_FATAL_ERROR => 'm',
377     $err->SEVERITY_ERROR => 'm',
378     $err->SEVERITY_WARNING => 's',
379     ]->[$err->severity]} => $result);
380    
381 wakaba 1.18 return 1;
382     };
383    
384 wakaba 1.48 my $t = \($input->{s});
385     if ($input->{is_char_string}) {
386     require Encode;
387     $t = \(Encode::encode ('utf8', $$t));
388     $input->{charset} = 'utf-8';
389     }
390    
391 wakaba 1.18 my $time1 = time;
392 wakaba 1.48 open my $fh, '<', $t;
393 wakaba 1.18 my $doc = Message::DOM::XMLParserTemp->parse_byte_stream
394     ($fh => $dom, $onerror, charset => $input->{charset});
395     $time{parse_xml} = time - $time1;
396 wakaba 1.26 $doc->manakai_charset ($input->{official_charset})
397     if defined $input->{official_charset};
398 wakaba 1.18
399     print STDOUT qq[</dl></div>];
400    
401     return ($doc, undef);
402     } # print_syntax_error_xml_section
403    
404 wakaba 1.35 sub get_css_parser () {
405     our $CSSParser;
406     return $CSSParser if $CSSParser;
407    
408     require Whatpm::CSS::Parser;
409     my $p = Whatpm::CSS::Parser->new;
410    
411     $p->{prop}->{$_} = 1 for qw/
412 wakaba 1.37 alignment-baseline
413 wakaba 1.35 background background-attachment background-color background-image
414     background-position background-position-x background-position-y
415     background-repeat border border-bottom border-bottom-color
416     border-bottom-style border-bottom-width border-collapse border-color
417     border-left border-left-color
418     border-left-style border-left-width border-right border-right-color
419     border-right-style border-right-width
420     border-spacing -manakai-border-spacing-x -manakai-border-spacing-y
421     border-style border-top border-top-color border-top-style border-top-width
422     border-width bottom
423     caption-side clear clip color content counter-increment counter-reset
424 wakaba 1.37 cursor direction display dominant-baseline empty-cells float font
425 wakaba 1.35 font-family font-size font-size-adjust font-stretch
426     font-style font-variant font-weight height left
427     letter-spacing line-height
428     list-style list-style-image list-style-position list-style-type
429     margin margin-bottom margin-left margin-right margin-top marker-offset
430     marks max-height max-width min-height min-width opacity -moz-opacity
431     orphans outline outline-color outline-style outline-width overflow
432     overflow-x overflow-y
433     padding padding-bottom padding-left padding-right padding-top
434     page page-break-after page-break-before page-break-inside
435     position quotes right size table-layout
436 wakaba 1.37 text-align text-anchor text-decoration text-indent text-transform
437 wakaba 1.35 top unicode-bidi vertical-align visibility white-space width widows
438 wakaba 1.37 word-spacing writing-mode z-index
439 wakaba 1.35 /;
440     $p->{prop_value}->{display}->{$_} = 1 for qw/
441     block clip inline inline-block inline-table list-item none
442     table table-caption table-cell table-column table-column-group
443     table-header-group table-footer-group table-row table-row-group
444     compact marker
445     /;
446     $p->{prop_value}->{position}->{$_} = 1 for qw/
447     absolute fixed relative static
448     /;
449     $p->{prop_value}->{float}->{$_} = 1 for qw/
450     left right none
451     /;
452     $p->{prop_value}->{clear}->{$_} = 1 for qw/
453     left right none both
454     /;
455     $p->{prop_value}->{direction}->{ltr} = 1;
456     $p->{prop_value}->{direction}->{rtl} = 1;
457     $p->{prop_value}->{marks}->{crop} = 1;
458     $p->{prop_value}->{marks}->{cross} = 1;
459     $p->{prop_value}->{'unicode-bidi'}->{$_} = 1 for qw/
460     normal bidi-override embed
461     /;
462     for my $prop_name (qw/overflow overflow-x overflow-y/) {
463     $p->{prop_value}->{$prop_name}->{$_} = 1 for qw/
464     visible hidden scroll auto -webkit-marquee -moz-hidden-unscrollable
465     /;
466     }
467     $p->{prop_value}->{visibility}->{$_} = 1 for qw/
468     visible hidden collapse
469     /;
470     $p->{prop_value}->{'list-style-type'}->{$_} = 1 for qw/
471     disc circle square decimal decimal-leading-zero
472     lower-roman upper-roman lower-greek lower-latin
473     upper-latin armenian georgian lower-alpha upper-alpha none
474     hebrew cjk-ideographic hiragana katakana hiragana-iroha
475     katakana-iroha
476     /;
477     $p->{prop_value}->{'list-style-position'}->{outside} = 1;
478     $p->{prop_value}->{'list-style-position'}->{inside} = 1;
479     $p->{prop_value}->{'page-break-before'}->{$_} = 1 for qw/
480     auto always avoid left right
481     /;
482     $p->{prop_value}->{'page-break-after'}->{$_} = 1 for qw/
483     auto always avoid left right
484     /;
485     $p->{prop_value}->{'page-break-inside'}->{auto} = 1;
486     $p->{prop_value}->{'page-break-inside'}->{avoid} = 1;
487     $p->{prop_value}->{'background-repeat'}->{$_} = 1 for qw/
488     repeat repeat-x repeat-y no-repeat
489     /;
490     $p->{prop_value}->{'background-attachment'}->{scroll} = 1;
491     $p->{prop_value}->{'background-attachment'}->{fixed} = 1;
492     $p->{prop_value}->{'font-size'}->{$_} = 1 for qw/
493     xx-small x-small small medium large x-large xx-large
494     -manakai-xxx-large -webkit-xxx-large
495     larger smaller
496     /;
497     $p->{prop_value}->{'font-style'}->{normal} = 1;
498     $p->{prop_value}->{'font-style'}->{italic} = 1;
499     $p->{prop_value}->{'font-style'}->{oblique} = 1;
500     $p->{prop_value}->{'font-variant'}->{normal} = 1;
501     $p->{prop_value}->{'font-variant'}->{'small-caps'} = 1;
502     $p->{prop_value}->{'font-stretch'}->{$_} = 1 for
503     qw/normal wider narrower ultra-condensed extra-condensed
504     condensed semi-condensed semi-expanded expanded
505     extra-expanded ultra-expanded/;
506     $p->{prop_value}->{'text-align'}->{$_} = 1 for qw/
507     left right center justify begin end
508     /;
509     $p->{prop_value}->{'text-transform'}->{$_} = 1 for qw/
510     capitalize uppercase lowercase none
511     /;
512     $p->{prop_value}->{'white-space'}->{$_} = 1 for qw/
513 wakaba 1.36 normal pre nowrap pre-line pre-wrap -moz-pre-wrap
514 wakaba 1.35 /;
515 wakaba 1.37 $p->{prop_value}->{'writing-mode'}->{$_} = 1 for qw/
516     lr rl tb lr-tb rl-tb tb-rl
517     /;
518     $p->{prop_value}->{'text-anchor'}->{$_} = 1 for qw/
519     start middle end
520     /;
521     $p->{prop_value}->{'dominant-baseline'}->{$_} = 1 for qw/
522     auto use-script no-change reset-size ideographic alphabetic
523     hanging mathematical central middle text-after-edge text-before-edge
524     /;
525     $p->{prop_value}->{'alignment-baseline'}->{$_} = 1 for qw/
526     auto baseline before-edge text-before-edge middle central
527     after-edge text-after-edge ideographic alphabetic hanging
528     mathematical
529     /;
530 wakaba 1.35 $p->{prop_value}->{'text-decoration'}->{$_} = 1 for qw/
531     none blink underline overline line-through
532     /;
533     $p->{prop_value}->{'caption-side'}->{$_} = 1 for qw/
534     top bottom left right
535     /;
536     $p->{prop_value}->{'table-layout'}->{auto} = 1;
537     $p->{prop_value}->{'table-layout'}->{fixed} = 1;
538 wakaba 1.36 $p->{prop_value}->{'border-collapse'}->{collapse} = 1;
539 wakaba 1.35 $p->{prop_value}->{'border-collapse'}->{separate} = 1;
540     $p->{prop_value}->{'empty-cells'}->{show} = 1;
541     $p->{prop_value}->{'empty-cells'}->{hide} = 1;
542     $p->{prop_value}->{cursor}->{$_} = 1 for qw/
543     auto crosshair default pointer move e-resize ne-resize nw-resize n-resize
544     se-resize sw-resize s-resize w-resize text wait help progress
545     /;
546     for my $prop (qw/border-top-style border-left-style