/[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.3 - (hide annotations) (download)
Mon Jul 21 05:24:32 2008 UTC (16 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.2: +54 -3 lines
++ ChangeLog	21 Jul 2008 05:20:07 -0000
	* cc.cgi: Information sections are now handled by WebHACC::Input
	module.  Input objects for subdocuments now owns their
	own subclass.

2008-07-21  Wakaba  <wakaba@suika.fam.cx>

++ html/WebHACC/Language/ChangeLog	21 Jul 2008 05:24:27 -0000
	* Base.pm: Use new method for node links.

	* CSS.pm: Typo fixes.  Pass |input| object as an argument
	to the CSSOM validation not supported error.

2008-07-21  Wakaba  <wakaba@suika.fam.cx>

++ html/WebHACC/ChangeLog	21 Jul 2008 05:23:21 -0000
	* Input.pm: A new subclass for subdocuments are added.
	Methods for information sections are added (from cc.cgi).

	* Output.pm (code): Support for attributes.
	(script, dt): New methods.
	(node_link): New method (from get_node_link in WebHACC::Result,
	which comes from cc.cgi).

	* Result.pm (add_error): Show some text even if no location
	infomration is available.  Use input object, if available,
	as fallback for location information.
	(get_error_label, get_node_path, get_node_link): Removed.
	The first method is no longer used.  The latters are now
	supported as |node_link| method in WebHACC::Output.

2008-07-21  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     sub new ($) {
20     return bless {nav => []}, shift;
21     } # new
22    
23     sub input ($;$) {
24     if (@_ > 1) {
25     if (defined $_[1]) {
26     $_[0]->{input} = $_[1];
27     } else {
28     delete $_[0]->{input};
29     }
30     }
31    
32     return $_[0]->{input};
33     } # input
34    
35     sub handle ($;$) {
36     if (@_ > 1) {
37     if (defined $_[1]) {
38     $_[0]->{handle} = $_[1];
39     } else {
40     delete $_[0]->{handle};
41     }
42     }
43    
44     return $_[0]->{handle};
45     } # handle
46    
47     sub set_utf8 ($) {
48     binmode shift->{handle}, ':utf8';
49     } # set_utf8
50    
51     sub set_flush ($) {
52     shift->{handle}->autoflush (1);
53     } # set_flush
54    
55     sub unset_flush ($) {
56     shift->{handle}->autoflush (0);
57     } # unset_flush
58    
59     sub html ($$) {
60     shift->{handle}->print (shift);
61     } # html
62    
63     sub text ($$) {
64     shift->html ($htescape->(shift));
65     } # text
66    
67     sub url ($$%) {
68     my ($self, $url, %opt) = @_;
69     $self->html (q[<code class=uri>&lt;]);
70     $self->link ($url, %opt, url => $url);
71     $self->html (q[></code>]);
72     } # url
73    
74     sub start_tag ($$%) {
75     my ($self, $tag_name, %opt) = @_;
76     $self->html ('<' . $htescape->($tag_name)); # escape for safety
77     if (exists $opt{id}) {
78     my $id = $self->input->id_prefix . $opt{id};
79     $self->html (' id="' . $htescape->($id) . '"');
80     delete $opt{id};
81     }
82     for (keys %opt) { # for safety
83     $self->html (' ' . $htescape->($_) . '="' . $htescape->($opt{$_}) . '"');
84     }
85     $self->html ('>');
86     } # start_tag
87    
88     sub end_tag ($$) {
89     shift->html ('</' . $htescape->(shift) . '>');
90     } # end_tag
91    
92     sub start_section ($%) {
93     my ($self, %opt) = @_;
94     $self->html ('<div class=section');
95     if (defined $opt{id}) {
96     my $id = $self->input->id_prefix . $opt{id};
97     $self->html (' id="' . $htescape->($id) . '"');
98     push @{$self->{nav}}, [$id => $opt{short_title} || $opt{title}]
99     unless $self->input->nested;
100     }
101     $self->html ('><h2>' . $htescape->($opt{title}) . '</h2>');
102     } # start_section
103    
104     sub end_section ($) {
105     my $self = shift;
106     $self->html ('</div>');
107     $self->{handle}->flush;
108     } # end_section
109    
110     sub start_code_block ($) {
111     shift->html ('<pre><code>');
112     } # start_code_block
113    
114     sub end_code_block ($) {
115     shift->html ('</code></pre>');
116     } # end_code_block
117    
118 wakaba 1.3 sub code ($$;%) {
119     my ($self, $content, %opt) = @_;
120     $self->start_tag ('code', %opt);
121     $self->text ($content);
122     $self->html ('</code>');
123 wakaba 1.1 } # code
124    
125 wakaba 1.3 sub script ($$;%) {
126     my ($self, $content, %opt) = @_;
127     $self->start_tag ('script', %opt);
128     $self->html ($content);
129     $self->html ('</script>');
130     } # script
131    
132     sub dt ($$;%) {
133     my ($self, $content, %opt) = @_;
134     $self->start_tag ('dt', %opt);
135     $self->text ($content);
136     } # dt
137    
138 wakaba 1.1 sub link ($$%) {
139     my ($self, $content, %opt) = @_;
140 wakaba 1.2 $self->start_tag ('a', %opt, href => $opt{url});
141 wakaba 1.1 $self->text ($content);
142     $self->html ('</a>');
143     } # link
144    
145     sub xref ($$%) {
146     my ($self, $content, %opt) = @_;
147     $self->html ('<a href="#' . $htescape->($self->input->id_prefix . $opt{target}) . '">');
148     $self->text ($content);
149     $self->html ('</a>');
150     } # xref
151    
152 wakaba 1.2 sub link_to_webhacc ($$%) {
153     my ($self, $content, %opt) = @_;
154     $opt{url} = './?uri=' . $self->encode_url_component ($opt{url});
155     $self->link ($content, %opt);
156     } # link_to_webhacc
157    
158 wakaba 1.3
159     my $get_node_path = sub ($) {
160     my $node = shift;
161     my @r;
162     while (defined $node) {
163     my $rs;
164     if ($node->node_type == 1) {
165     $rs = $node->node_name;
166     $node = $node->parent_node;
167     } elsif ($node->node_type == 2) {
168     $rs = '@' . $node->node_name;
169     $node = $node->owner_element;
170     } elsif ($node->node_type == 3) {
171     $rs = '"' . $node->data . '"';
172     $node = $node->parent_node;
173     } elsif ($node->node_type == 9) {
174     @r = ('') unless @r;
175     $rs = '';
176     $node = $node->parent_node;
177     } else {
178     $rs = '#' . $node->node_type;
179     $node = $node->parent_node;
180     }
181     unshift @r, $rs;
182     }
183     return join '/', @r;
184     }; # $get_node_path
185    
186     sub node_link ($$) {
187     my ($self, $node) = @_;
188     $self->xref ($get_node_path->($node), target => 'node-' . refaddr $node);
189     } # node_link
190    
191 wakaba 1.1 sub nav_list ($) {
192     my $self = shift;
193     $self->html (q[<ul class="navigation" id="nav-items">]);
194     for (@{$self->{nav}}) {
195 wakaba 1.3 $self->html (qq[<li><a href="#@{[$htescape->($_->[0])]}">@{[$htescape->($_->[1])]}</a>]);
196 wakaba 1.1 }
197     $self->html ('</ul>');
198     } # nav_list
199 wakaba 1.2
200    
201     sub encode_url_component ($$) {
202     shift;
203     require Encode;
204     my $s = Encode::encode ('utf8', shift);
205     $s =~ s/([^0-9A-Za-z_.~-])/sprintf '%%%02X', ord $1/ge;
206     return $s;
207     } # encode_url_component
208 wakaba 1.1
209     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24