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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (hide annotations) (download)
Thu Aug 14 15:50:42 2008 UTC (16 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.14: +11 -0 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::Output;
2     use strict;
3 wakaba 1.3
4 wakaba 1.1 require IO::Handle;
5 wakaba 1.3 use Scalar::Util qw/refaddr/;
6 wakaba 1.1
7     my $htescape = sub ($) {
8     my $s = $_[0];
9     $s =~ s/&/&amp;/g;
10     $s =~ s/</&lt;/g;
11     $s =~ s/>/&gt;/g;
12     $s =~ s/"/&quot;/g;
13     $s =~ s{([\x00-\x09\x0B-\x1F\x7F-\xA0\x{FEFF}\x{FFFC}-\x{FFFF}])}{
14     sprintf '<var>U+%04X</var>', ord $1;
15     }ge;
16     return $s;
17     };
18    
19 wakaba 1.10 my $htescape_value = sub ($) {
20     my $s = $_[0];
21     $s =~ s/&/&amp;/g;
22     $s =~ s/</&lt;/g;
23     $s =~ s/>/&gt;/g;
24     $s =~ s/"/&quot;/g;
25     return $s;
26     };
27    
28 wakaba 1.1 sub new ($) {
29 wakaba 1.9 require WebHACC::Input;
30     return bless {nav => [], section_rank => 1,
31     input => WebHACC::Input->new}, shift;
32 wakaba 1.1 } # new
33    
34     sub input ($;$) {
35     if (@_ > 1) {
36     if (defined $_[1]) {
37     $_[0]->{input} = $_[1];
38     } else {
39 wakaba 1.9 $_[0]->{input} = WebHACC::Input->new;
40 wakaba 1.1 }
41     }
42    
43     return $_[0]->{input};
44     } # input
45    
46     sub handle ($;$) {
47     if (@_ > 1) {
48     if (defined $_[1]) {
49     $_[0]->{handle} = $_[1];
50     } else {
51     delete $_[0]->{handle};
52     }
53     }
54    
55     return $_[0]->{handle};
56     } # handle
57    
58     sub set_utf8 ($) {
59     binmode shift->{handle}, ':utf8';
60     } # set_utf8
61    
62     sub set_flush ($) {
63     shift->{handle}->autoflush (1);
64     } # set_flush
65    
66     sub unset_flush ($) {
67     shift->{handle}->autoflush (0);
68     } # unset_flush
69    
70     sub html ($$) {
71     shift->{handle}->print (shift);
72     } # html
73    
74     sub text ($$) {
75     shift->html ($htescape->(shift));
76     } # text
77    
78     sub url ($$%) {
79     my ($self, $url, %opt) = @_;
80     $self->html (q[<code class=uri>&lt;]);
81     $self->link ($url, %opt, url => $url);
82     $self->html (q[></code>]);
83     } # url
84    
85     sub start_tag ($$%) {
86     my ($self, $tag_name, %opt) = @_;
87 wakaba 1.10 $self->html ('<' . $htescape_value->($tag_name)); # escape for safety
88 wakaba 1.1 if (exists $opt{id}) {
89     my $id = $self->input->id_prefix . $opt{id};
90 wakaba 1.10 $self->html (' id="' . $htescape_value->($id) . '"');
91 wakaba 1.1 delete $opt{id};
92     }
93     for (keys %opt) { # for safety
94 wakaba 1.10 $self->html (' ' . $htescape_value->($_) . '="' .
95     $htescape_value->($opt{$_}) . '"');
96 wakaba 1.1 }
97     $self->html ('>');
98     } # start_tag
99    
100     sub end_tag ($$) {
101 wakaba 1.10 shift->html ('</' . $htescape_value->(shift) . '>');
102 wakaba 1.1 } # end_tag
103    
104     sub start_section ($%) {
105     my ($self, %opt) = @_;
106 wakaba 1.4
107 wakaba 1.13 my $class = 'section';
108 wakaba 1.4 if (defined $opt{role}) {
109     if ($opt{role} eq 'parse-errors') {
110     $opt{id} ||= 'parse-errors';
111 wakaba 1.7 $opt{title} ||= 'Parse Errors Section';
112     $opt{short_title} ||= 'Parse Errors';
113 wakaba 1.14 $class .= ' errors';
114 wakaba 1.4 delete $opt{role};
115     } elsif ($opt{role} eq 'structure-errors') {
116     $opt{id} ||= 'document-errors';
117     $opt{title} ||= 'Structural Errors';
118     $opt{short_title} ||= 'Struct. Errors';
119 wakaba 1.14 $class .= ' errors';
120 wakaba 1.4 delete $opt{role};
121 wakaba 1.15 } elsif ($opt{role} eq 'transfer-errors') {
122     $opt{id} ||= 'transfer-errors';
123     $opt{title} ||= 'Transfer Errors';
124     $opt{short_title} ||= 'Trans. Errors';
125     $class .= ' errors';
126     delete $opt{role};
127 wakaba 1.4 } elsif ($opt{role} eq 'reformatted') {
128     $opt{id} ||= 'document-tree';
129     $opt{title} ||= 'Reformatted Document Source';
130     $opt{short_title} ||= 'Reformatted';
131 wakaba 1.14 $class .= ' dump';
132 wakaba 1.4 delete $opt{role}
133     } elsif ($opt{role} eq 'tree') {
134     $opt{id} ||= 'document-tree';
135     $opt{title} ||= 'Document Tree';
136     $opt{short_title} ||= 'Tree';
137 wakaba 1.14 $class .= ' dump';
138 wakaba 1.4 delete $opt{role};
139     } elsif ($opt{role} eq 'structure') {
140     $opt{id} ||= 'document-structure';
141     $opt{title} ||= 'Document Structure';
142     $opt{short_title} ||= 'Structure';
143 wakaba 1.14 $class .= ' dump';
144 wakaba 1.4 delete $opt{role};
145 wakaba 1.13 } elsif ($opt{role} eq 'subdoc') {
146     $class .= ' subdoc';
147 wakaba 1.14 delete $opt{role};
148     } elsif ($opt{role} eq 'source') {
149     $opt{id} ||= 'source-string';
150     $opt{title} ||= 'Document Source';
151     $opt{short_title} ||= 'Source';
152     $class .= ' source';
153 wakaba 1.15 delete $opt{role};
154     } elsif ($opt{role} eq 'result') {
155     $opt{id} ||= 'result-summary';
156     $opt{title} ||= 'Result';
157     $class .= ' result';
158 wakaba 1.13 delete $opt{role};
159 wakaba 1.4 }
160     }
161    
162     $self->{section_rank}++;
163 wakaba 1.13 $self->html (qq[<div class="$class"]);
164 wakaba 1.1 if (defined $opt{id}) {
165 wakaba 1.13 my $prefix = $self->input->id_prefix;
166     $opt{parent_id} ||= $prefix;
167     my $id = $prefix . $opt{id};
168 wakaba 1.11 $self->html (' id="' . $htescape->($id) . '">');
169 wakaba 1.13 if ($self->{section_rank} == 2 or length $opt{parent_id}) {
170 wakaba 1.11 my $st = $opt{short_title} || $opt{title};
171     push @{$self->{nav}},
172     [$id => $st => $opt{text}];
173    
174     $self->start_tag ('script');
175 wakaba 1.13 $self->html (qq[ addSectionLink ('$id', ']);
176 wakaba 1.11 $self->nl_text ($st, text => $opt{text});
177 wakaba 1.12 if (defined $opt{parent_id}) {
178     $self->html (q[', '] . $opt{parent_id});
179     }
180 wakaba 1.11 $self->html (q[') ]);
181     $self->end_tag ('script');
182     }
183     } else {
184     $self->html ('>');
185 wakaba 1.1 }
186 wakaba 1.4 my $section_rank = $self->{section_rank};
187     $section_rank = 6 if $section_rank > 6;
188 wakaba 1.11 $self->html ('<h' . $section_rank . '>');
189 wakaba 1.7 $self->nl_text ($opt{title}, text => $opt{text});
190     $self->html ('</h' . $section_rank . '>');
191 wakaba 1.1 } # start_section
192    
193     sub end_section ($) {
194     my $self = shift;
195     $self->html ('</div>');
196     $self->{handle}->flush;
197 wakaba 1.4 $self->{section_rank}--;
198 wakaba 1.1 } # end_section
199 wakaba 1.4
200     sub start_error_list ($%) {
201     my ($self, %opt) = @_;
202    
203     if (defined $opt{role}) {
204     if ($opt{role} eq 'parse-errors') {
205     $opt{id} ||= 'parse-errors-list';
206     delete $opt{role};
207     } elsif ($opt{role} eq 'structure-errors') {
208     $opt{id} ||= 'document-errors-list';
209     delete $opt{role};
210     }
211     }
212    
213     $self->start_tag ('dl', %opt);
214     } # start_error_list
215    
216     sub end_error_list ($%) {
217     my ($self, %opt) = @_;
218    
219     if (defined $opt{role}) {
220     if ($opt{role} eq 'parse-errors') {
221     delete $opt{role};
222     $self->end_tag ('dl');
223     ## NOTE: For parse error list, the |add_source_to_parse_error_list|
224     ## method is invoked at the end of |generate_source_string_section|,
225     ## since that generation method is invoked after the error list
226     ## is generated.
227     } elsif ($opt{role} eq 'structure-errors') {
228     delete $opt{role};
229     $self->end_tag ('dl');
230     $self->add_source_to_parse_error_list ('document-errors-list');
231     } else {
232     $self->end_tag ('dl');
233     }
234     } else {
235     $self->end_tag ('dl');
236     }
237     } # end_error_list
238    
239     sub add_source_to_parse_error_list ($$) {
240     my $self = shift;
241    
242     $self->script (q[addSourceToParseErrorList ('] . $self->input->id_prefix .
243 wakaba 1.9 q[', '] . shift () . q[')]);
244 wakaba 1.4 } # add_source_to_parse_error_list
245 wakaba 1.1
246     sub start_code_block ($) {
247     shift->html ('<pre><code>');
248     } # start_code_block
249    
250     sub end_code_block ($) {
251     shift->html ('</code></pre>');
252     } # end_code_block
253    
254 wakaba 1.3 sub code ($$;%) {
255     my ($self, $content, %opt) = @_;
256     $self->start_tag ('code', %opt);
257     $self->text ($content);
258     $self->html ('</code>');
259 wakaba 1.1 } # code
260    
261 wakaba 1.3 sub script ($$;%) {
262     my ($self, $content, %opt) = @_;
263     $self->start_tag ('script', %opt);
264     $self->html ($content);
265     $self->html ('</script>');
266     } # script
267    
268     sub dt ($$;%) {
269     my ($self, $content, %opt) = @_;
270     $self->start_tag ('dt', %opt);
271 wakaba 1.7 $self->nl_text ($content, text => $opt{text});
272 wakaba 1.3 } # dt
273    
274 wakaba 1.9 sub select ($$%) {
275     my ($self, $options, %opt) = @_;
276    
277     my $selected = $opt{selected};
278     delete $opt{selected};
279    
280     $self->start_tag ('select', %opt);
281    
282     my @options = @$options;
283     while (@options) {
284     my $opt = shift @options;
285     if ($opt->{options}) {
286     $self->html ('<optgroup label="');
287     $self->nl_text ($opt->{label});
288     $self->html ('">');
289     unshift @options, @{$opt->{options}}, {end_options => 1};
290     } elsif ($opt->{end_options}) {
291     $self->end_tag ('optgroup');
292     } else {
293     $self->start_tag ('option', value => $opt->{value},
294     ((defined $selected and $opt->{value} eq $selected)
295     ? (selected => '') : ()));
296     $self->nl_text (defined $opt->{label} ? $opt->{label} : $opt->{value});
297     }
298     }
299    
300     $self->end_tag ('select');
301     } # select
302    
303 wakaba 1.1 sub link ($$%) {
304     my ($self, $content, %opt) = @_;
305 wakaba 1.2 $self->start_tag ('a', %opt, href => $opt{url});
306 wakaba 1.1 $self->text ($content);
307     $self->html ('</a>');
308     } # link
309    
310     sub xref ($$%) {
311     my ($self, $content, %opt) = @_;
312     $self->html ('<a href="#' . $htescape->($self->input->id_prefix . $opt{target}) . '">');
313 wakaba 1.7 $self->nl_text ($content, text => $opt{text});
314 wakaba 1.1 $self->html ('</a>');
315     } # xref
316    
317 wakaba 1.2 sub link_to_webhacc ($$%) {
318     my ($self, $content, %opt) = @_;
319     $opt{url} = './?uri=' . $self->encode_url_component ($opt{url});
320     $self->link ($content, %opt);
321     } # link_to_webhacc
322    
323 wakaba 1.3 my $get_node_path = sub ($) {
324     my $node = shift;
325     my @r;
326     while (defined $node) {
327     my $rs;
328     if ($node->node_type == 1) {
329     $rs = $node->node_name;
330     $node = $node->parent_node;
331     } elsif ($node->node_type == 2) {
332     $rs = '@' . $node->node_name;
333     $node = $node->owner_element;
334     } elsif ($node->node_type == 3) {
335     $rs = '"' . $node->data . '"';
336     $node = $node->parent_node;
337     } elsif ($node->node_type == 9) {
338     @r = ('') unless @r;
339     $rs = '';
340     $node = $node->parent_node;
341     } else {
342     $rs = '#' . $node->node_type;
343     $node = $node->parent_node;
344     }
345     unshift @r, $rs;
346     }
347     return join '/', @r;
348     }; # $get_node_path
349    
350 wakaba 1.10 my $get_object_path = sub ($) {
351     my $node = shift;
352     my @r;
353     while (defined $node) {
354     my $ref = ref $node;
355     $ref =~ /([^:]+)$/;
356     my $rs = $1;
357     my $node_name = $node->node_name;
358     if (defined $node_name) {
359     $rs .= ' <code>' . $htescape->($node_name) . '</code>';
360     }
361     $node = undef;
362     unshift @r, $rs;
363     }
364     return join '/', @r;
365     }; # $get_object_path
366    
367 wakaba 1.3 sub node_link ($$) {
368     my ($self, $node) = @_;
369 wakaba 1.10 if ($node->isa ('Message::IF::Node')) {
370     $self->xref ($get_node_path->($node), target => 'node-' . refaddr $node);
371     } else {
372     $self->html ($get_object_path->($node));
373     }
374 wakaba 1.3 } # node_link
375    
376 wakaba 1.7 {
377     my $Msg = {};
378    
379     sub load_text_catalog ($$) {
380     my $self = shift;
381    
382     my $lang = shift; # MUST be a canonical lang name
383     my $file_name = qq[cc-msg.$lang.txt];
384     $lang = 'en' unless -f $file_name;
385     $self->{primary_language} = $lang;
386    
387     open my $file, '<:utf8', $file_name or die "$0: $file_name: $!";
388     while (<$file>) {
389     if (s/^([^;]+);([^;]*);//) {
390     my ($type, $cls, $msg) = ($1, $2, $_);
391     $msg =~ tr/\x0D\x0A//d;
392     $Msg->{$type} = [$cls, $msg];
393     }
394     }
395     } # load_text_catalog
396    
397     sub nl_text ($$;%) {
398     my ($self, $type, %opt) = @_;
399     my $node = $opt{node};
400    
401     my @arg;
402     {
403     if (defined $Msg->{$type}) {
404     my $msg = $Msg->{$type}->[1];
405     if ($msg =~ /<var>/) {
406     $msg =~ s{<var>\$([0-9]+)</var>}{
407     defined $arg[$1] ? $htescape->($arg[$1]) : '(undef)';
408     }ge;
409     $msg =~ s{<var>{\@([A-Za-z0-9:_.-]+)}</var>}{
410     UNIVERSAL::can ($node, 'get_attribute_ns')
411     ? $htescape->($node->get_attribute_ns (undef, $1)) : ''
412     }ge;
413     $msg =~ s{<var>{\@}</var>}{
414     UNIVERSAL::can ($node, 'value') ? $htescape->($node->value) : ''
415     }ge;
416     $msg =~ s{<var>{text}</var>}{
417     defined $opt{text} ? $htescape->($opt{text}) : ''
418     }ge;
419     $msg =~ s{<var>{local-name}</var>}{
420     UNIVERSAL::can ($node, 'manakai_local_name')
421     ? $htescape->($node->manakai_local_name) : ''
422     }ge;
423     $msg =~ s{<var>{element-local-name}</var>}{
424     (UNIVERSAL::can ($node, 'owner_element') and
425     $node->owner_element)
426     ? $htescape->($node->owner_element->manakai_local_name) : ''
427     }ge;
428     }
429     $self->html ($msg);
430     return;
431     } elsif ($type =~ s/:([^:]*)$//) {
432     unshift @arg, $1;
433     redo;
434     }
435     }
436     $self->text ($type);
437     } # nl_text
438    
439     }
440    
441 wakaba 1.1 sub nav_list ($) {
442     my $self = shift;
443     $self->html (q[<ul class="navigation" id="nav-items">]);
444     for (@{$self->{nav}}) {
445 wakaba 1.7 $self->html (qq[<li><a href="#@{[$htescape->($_->[0])]}">]);
446     $self->nl_text ($_->[1], text => $_->[2]);
447     $self->html ('</a>');
448 wakaba 1.1 }
449     $self->html ('</ul>');
450     } # nav_list
451 wakaba 1.2
452 wakaba 1.5 sub http_header ($) {
453     shift->html (qq[Content-Type: text/html; charset=utf-8\n\n]);
454     } # http_header
455    
456     sub http_error ($$) {
457     my $self = shift;
458     my $code = 0+shift;
459     my $text = {
460     404 => 'Not Found',
461     }->{$code};
462     $self->html (qq[Status: $code $text\nContent-Type: text/html ; charset=us-ascii\n\n$code $text]);
463     } # http_error
464    
465     sub html_header ($) {
466     my $self = shift;
467 wakaba 1.7 $self->html (q[<!DOCTYPE html>]);
468     $self->start_tag ('html', lang => $self->{primary_language});
469     $self->html (q[<head><title>]);
470     $self->nl_text (q[WebHACC:Title]);
471     $self->html (q[</title>
472 wakaba 1.5 <link rel="stylesheet" href="../cc-style.css" type="text/css">
473 wakaba 1.8 <script src="../cc-script.js"></script>
474 wakaba 1.5 </head>
475 wakaba 1.11 <body onclick=" return onbodyclick (event) " onload=" onbodyload () ">
476 wakaba 1.7 <h1>]);
477     $self->nl_text (q[WebHACC:Heading]);
478 wakaba 1.11 $self->html (q[</h1><script> insertNavSections () </script>]);
479 wakaba 1.5 } # html_header
480 wakaba 1.9
481     sub generate_input_section ($$) {
482     my ($out, $cgi) = @_;
483    
484     my $options = sub ($) {
485     my $context = shift;
486    
487 wakaba 1.12 $out->html (q[<div class="details default"><p class=legend onclick="nextSibling.style.display = nextSibling.style.display == 'block' ? 'none' : 'block'; parentNode.className = nextSibling.style.display == 'none' ? 'details' : 'details open'">]);
488 wakaba 1.9 $out->nl_text (q[Options]);
489     $out->start_tag ('div');
490    
491     if ($context eq 'url') {
492     $out->start_tag ('p');
493     $out->start_tag ('label');
494     $out->start_tag ('input', type => 'checkbox', name => 'error-page',
495     value => 1,
496     ($cgi->get_parameter ('error-page')
497     ? (checked => '') : ()));
498     $out->nl_text ('Check error page');
499     $out->end_tag ('label');
500     }
501    
502     $out->start_tag ('p');
503     $out->start_tag ('label');
504     $out->nl_text (q[Content type]);
505     $out->text (': ');
506     $out->select ([
507     {value => '', label => 'As specified'},
508     {value => 'application/atom+xml'},
509     {value => 'application/xhtml+xml'},
510     {value => 'application/xml'},
511     {value => 'text/html'},
512     {value => 'text/xml'},
513     {value => 'text/css'},
514     {value => 'text/cache-manifest'},
515     {value => 'text/x-webidl'},
516     ], name => 'i', selected => scalar $cgi->get_parameter ('i'));
517     $out->end_tag ('label');
518    
519     if ($context ne 'text') {
520     $out->start_tag ('p');
521     $out->start_tag ('label');
522     $out->nl_text (q[Charset]);
523     $out->text (q[: ]);
524     $out->select ([
525     {value => '', label => 'As specified'},
526     {label => 'Japanese charsets', options => [
527     {value => 'Windows-31J'},
528     {value => 'Shift_JIS'},
529     {value => 'EUC-JP'},
530     {value => 'ISO-2022-JP'},
531     ]},
532     {label => 'European charsets', options => [
533     {value => 'Windows-1252'},
534     {value => 'ISO-8859-1'},
535     {value => 'US-ASCII'},
536     ]},
537     {label => 'Asian charsets', options => [
538     {value => 'Windows-874'},
539     {value => 'ISO-8859-11'},
540     {value => 'TIS-620'},
541     ]},
542     {label => 'Unicode charsets', options => [
543     {value => 'UTF-8'},
544     {value => 'UTF-8n'},
545     ]},
546     ], name => 'charset',
547     selected => scalar $cgi->get_parameter ('charset'));
548     $out->end_tag ('label');
549     }
550    
551     if ($context eq 'text') {
552     $out->start_tag ('p');
553     $out->start_tag ('label');
554     $out->nl_text ('Setting innerHTML');
555     $out->text (': ');
556     $out->start_tag ('input', name => 'e',
557     value => scalar $cgi->get_parameter ('e'));
558     $out->end_tag ('label');
559     }
560    
561     $out->html (q[</div></div>]);
562     }; # $options
563    
564     $out->start_section (id => 'input', title => 'Input');
565 wakaba 1.12 $out->html (q[<script> insertNavSections ('input') </script>]);
566 wakaba 1.9
567 wakaba 1.12 $out->start_section (id => 'input-url', title => 'By URL',
568     parent_id => 'input');
569 wakaba 1.10 $out->start_tag ('form', action => './#result-summary',
570     'accept-charset' => 'utf-8',
571 wakaba 1.9 method => 'get');
572     $out->start_tag ('input', type => 'hidden', name => '_charset_');
573    
574     $out->start_tag ('p');
575     $out->start_tag ('label');
576     $out->nl_text ('URL');
577     $out->text (': ');
578     $out->start_tag ('input',
579     name => 'uri',
580     type => 'url',
581     value => $cgi->get_parameter ('uri'));
582     $out->end_tag ('label');
583    
584     $out->start_tag ('p');
585     $out->start_tag ('button', type => 'submit');
586     $out->nl_text ('Check');
587 wakaba 1.12 $out->end_tag ('button');
588    
589     $options->('url');
590 wakaba 1.9
591     $out->end_tag ('form');
592     $out->end_section;
593    
594     $out->end_tag ('fieldset');
595    
596     ## TODO: File upload
597    
598 wakaba 1.12 $out->start_section (id => 'input-text', title => 'By direct input',
599     parent_id => 'input');
600 wakaba 1.10 $out->start_tag ('form', action => './#result-summary',
601     'accept-charset' => 'utf-8',
602 wakaba 1.9 method => 'post');
603     $out->start_tag ('input', type => 'hidden', name => '_charset_');
604    
605     $out->start_tag ('p');
606     $out->start_tag ('label');
607     $out->nl_text ('Document source to check');
608     $out->text (': ');
609     $out->start_tag ('br');
610     $out->start_tag ('textarea',
611     name => 's');
612     my $s = $cgi->get_parameter ('s');
613 wakaba 1.10 $out->html ($htescape_value->($s)) if defined $s;
614 wakaba 1.9 $out->end_tag ('textarea');
615     $out->end_tag ('label');
616    
617     $out->start_tag ('p');
618     $out->start_tag ('button', type => 'submit',
619     onclick => 'form.method = form.s.value.length > 512 ? "post" : "get"');
620     $out->nl_text ('Check');
621     $out->end_tag ('button');
622    
623 wakaba 1.12 $options->('text');
624    
625 wakaba 1.9 $out->end_tag ('form');
626     $out->end_section;
627 wakaba 1.12
628     $out->script (q[
629     if (!document.webhaccNavigated &&
630     document.getElementsByTagName ('textarea')[0].value.length > 0) {
631     showTab ('input-text');
632     document.webhaccNavigated = false;
633     }
634     ]);
635 wakaba 1.9
636     $out->end_section;
637     } # generate_input_section
638 wakaba 1.2
639     sub encode_url_component ($$) {
640     shift;
641     require Encode;
642     my $s = Encode::encode ('utf8', shift);
643     $s =~ s/([^0-9A-Za-z_.~-])/sprintf '%%%02X', ord $1/ge;
644     return $s;
645     } # encode_url_component
646 wakaba 1.1
647     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24