/[suikacvs]/markup/html/whatpm/Whatpm/NanoDOM.pm
Suika

Contents of /markup/html/whatpm/Whatpm/NanoDOM.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Tue May 1 10:47:37 2007 UTC (17 years, 6 months ago) by wakaba
Branch: MAIN
Changes since 1.1: +27 -27 lines
s/What::/Whatpm::/ to avoid name confliction

1 wakaba 1.1 =head1 NAME
2    
3 wakaba 1.2 Whatpm::NanoDOM - A Non-Conforming Implementation of DOM Subset
4 wakaba 1.1
5     =head1 DESCRIPTION
6    
7 wakaba 1.2 The C<Whatpm::NanoDOM> module contains a non-conforming implementation
8 wakaba 1.1 of a subset of DOM. It is the intention that this module is
9 wakaba 1.2 used only for the purpose of testing the C<Whatpm::HTML> module.
10 wakaba 1.1
11     See source code if you would like to know what it does.
12    
13     =cut
14    
15 wakaba 1.2 package Whatpm::NanoDOM;
16 wakaba 1.1 use strict;
17    
18 wakaba 1.2 package Whatpm::NanoDOM::Node;
19 wakaba 1.1
20     sub new ($) {
21     my $class = shift;
22     my $self = bless {}, $class;
23     return $self;
24     } # new
25    
26     sub is_equal_node ($$) {
27     return shift eq shift;
28     } # is_equal_node
29    
30     sub parent_node ($) {
31     return shift->{parent_node};
32     } # parent_node
33    
34     ## NOTE: Only applied to Elements and Documents
35     sub child_nodes ($) {
36     return shift->{child_nodes};
37     } # child_nodes
38    
39     ## NOTE: Only applied to Elements and Documents
40     sub append_child ($$) {
41     my ($self, $new_child) = @_;
42     if (defined $new_child->{parent_node}) {
43     my $parent_list = $new_child->{parent_node}->{child_nodes};
44     for (0..$#$parent_list) {
45     if ($parent_list->[$_] eq $new_child) {
46     splice @$parent_list, $_, 1;
47     }
48     }
49     }
50     push @{$self->{child_nodes}}, $new_child;
51     $new_child->{parent_node} = $self; ## TODO: weaken this ref
52     return $new_child;
53     } # append_child
54    
55     ## NOTE: Only applied to Elements and Documents
56     sub insert_before ($$;$) {
57     my ($self, $new_child, $ref_child) = @_;
58     if (defined $new_child->{parent_node}) {
59     my $parent_list = $new_child->{parent_node}->{child_nodes};
60     for (0..$#$parent_list) {
61     if ($parent_list->[$_] eq $new_child) {
62     splice @$parent_list, $_, 1;
63     }
64     }
65     }
66     my $i = @{$self->{child_nodes}};
67     if (defined $ref_child) {
68     for (0..$#{$self->{child_nodes}}) {
69     if ($self->{child_nodes}->[$_] eq $ref_child) {
70     $i = $_;
71     last;
72     }
73     }
74     }
75     splice @{$self->{child_nodes}}, $i, 0, $new_child;
76     $new_child->{parent_node} = $self; ## TODO: weaken this ref
77     return $new_child;
78     } # insert_before
79    
80     ## NOTE: Only applied to Elements and Documents
81     sub remove_child ($$) {
82     my ($self, $old_child) = @_;
83     my $parent_list = $self->{child_nodes};
84     for (0..$#$parent_list) {
85     if ($parent_list->[$_] eq $old_child) {
86     splice @$parent_list, $_, 1;
87     }
88     }
89     delete $old_child->{parent_node};
90     return $old_child;
91     } # remove_child
92    
93     ## NOTE: Only applied to Elements and Documents
94     sub has_child_nodes ($) {
95     return @{shift->{child_nodes}} > 0;
96     } # has_child_nodes
97    
98     ## NOTE: Only applied to Elements and Documents
99     sub last_child ($) {
100     my $self = shift;
101     return @{$self->{child_nodes}} ? $self->{child_nodes}->[-1] : undef;
102     } # last_child
103    
104     ## NOTE: Only applied to Elements and Documents
105     sub previous_sibling ($) {
106     my $self = shift;
107     my $parent = $self->{parent_node};
108     return undef unless defined $parent;
109     my $r;
110     for (@{$parent->{child_nodes}}) {
111     if ($_ eq $self) {
112     return $r;
113     } else {
114     $r = $_;
115     }
116     }
117     return undef;
118     } # previous_sibling
119    
120     sub ELEMENT_NODE () { 1 }
121     sub ATTRIBUTE_NODE () { 2 }
122     sub TEXT_NODE () { 3 }
123     sub CDATA_SECTION_NODE () { 4 }
124     sub ENTITY_REFERENCE_NODE () { 5 }
125     sub ENTITY_NODE () { 6 }
126     sub PROCESSING_INSTRUCTION_NODE () { 7 }
127     sub COMMENT_NODE () { 8 }
128     sub DOCUMENT_NODE () { 9 }
129     sub DOCUMENT_TYPE_NODE () { 10 }
130     sub DOCUMENT_FRAGMENT_NODE () { 11 }
131     sub NOTATION_NODE () { 12 }
132    
133 wakaba 1.2 package Whatpm::NanoDOM::Document;
134     push our @ISA, 'Whatpm::NanoDOM::Node';
135 wakaba 1.1
136     sub new ($) {
137     my $self = shift->SUPER::new;
138     $self->{child_nodes} = [];
139     return $self;
140     } # new
141    
142     ## A manakai extension
143     sub manakai_append_text ($$) {
144     my $self = shift;
145     if (@{$self->{child_nodes}} and
146     $self->{child_nodes}->[-1]->node_type == 3) {
147     $self->{child_nodes}->[-1]->manakai_append_text (shift);
148     } else {
149     my $text = $self->create_text_node (shift);
150     $self->append_child ($text);
151     }
152     } # manakai_append_text
153    
154     sub node_type () { 9 }
155    
156     sub strict_error_checking {
157     return 0;
158     } # strict_error_checking
159    
160     sub create_text_node ($$) {
161     shift;
162 wakaba 1.2 return Whatpm::NanoDOM::Text->new (shift);
163 wakaba 1.1 } # create_text_node
164    
165     sub create_comment ($$) {
166     shift;
167 wakaba 1.2 return Whatpm::NanoDOM::Comment->new (shift);
168 wakaba 1.1 } # create_comment
169    
170     ## The second parameter only supports manakai extended way
171     ## to specify qualified name - "[$prefix, $local_name]"
172     sub create_element_ns ($$$) {
173     my ($self, $nsuri, $qn) = @_;
174 wakaba 1.2 return Whatpm::NanoDOM::Element->new ($nsuri, $qn->[0], $qn->[1]);
175 wakaba 1.1 } # create_element_ns
176    
177     ## A manakai extension
178     sub create_document_type_definition ($$) {
179     shift;
180 wakaba 1.2 return Whatpm::NanoDOM::DocumentType->new (shift);
181 wakaba 1.1 } # create_document_type_definition
182    
183 wakaba 1.2 package Whatpm::NanoDOM::Element;
184     push our @ISA, 'Whatpm::NanoDOM::Node';
185 wakaba 1.1
186     sub new ($$$$) {
187     my $self = shift->SUPER::new;
188     $self->{namespace_uri} = shift;
189     $self->{prefix} = shift;
190     $self->{local_name} = shift;
191     $self->{attributes} = {};
192     $self->{child_nodes} = [];
193     return $self;
194     } # new
195    
196     sub clone_node ($$) {
197     my ($self, $deep) = @_; ## NOTE: Deep cloning is not supported
198     my $clone = bless {
199     namespace_uri => $self->{namespace_uri},
200     prefix => $self->{prefix},
201     local_name => $self->{local_name},
202     child_nodes => [],
203     }, ref $self;
204     for my $ns (keys %{$self->{attributes}}) {
205     for my $ln (keys %{$self->{attributes}->{$ns}}) {
206     my $attr = $self->{attributes}->{$ns}->{$ln};
207     $clone->{attributes}->{$ns}->{$ln} = bless {
208     namespace_uri => $attr->{namespace_uri},
209     prefix => $attr->{prefix},
210     local_name => $attr->{local_name},
211     value => $attr->{value},
212     }, ref $self->{attributes}->{$ns}->{$ln};
213     }
214     }
215     return $clone;
216     } # clone
217    
218     ## A manakai extension
219     sub manakai_append_text ($$) {
220     my $self = shift;
221     if (@{$self->{child_nodes}} and
222     $self->{child_nodes}->[-1]->node_type == 3) {
223     $self->{child_nodes}->[-1]->manakai_append_text (shift);
224     } else {
225 wakaba 1.2 my $text = Whatpm::NanoDOM::Text->new (shift);
226 wakaba 1.1 $self->append_child ($text);
227     }
228     } # manakai_append_text
229    
230     sub attributes ($) {
231     my $self = shift;
232     my $r = [];
233     ## Order MUST be stable
234     for my $ns (sort {$a cmp $b} keys %{$self->{attributes}}) {
235     for my $ln (sort {$a cmp $b} keys %{$self->{attributes}->{$ns}}) {
236     push @$r, $self->{attributes}->{$ns}->{$ln}
237     if defined $self->{attributes}->{$ns}->{$ln};
238     }
239     }
240     return $r;
241     } # attributes
242    
243     sub node_type { 1 }
244    
245     ## TODO: HTML5 capitalization
246     sub tag_name ($) {
247     my $self = shift;
248     if (defined $self->{prefix}) {
249     return $self->{prefix} . ':' . $self->{local_name};
250     } else {
251     return $self->{local_name};
252     }
253     } # tag_name
254    
255     sub has_attribute_ns ($$$) {
256     my ($self, $nsuri, $ln) = @_;
257     return defined $self->{attributes}->{$nsuri}->{$ln};
258     } # has_attribute_ns
259    
260     ## The second parameter only supports manakai extended way
261     ## to specify qualified name - "[$prefix, $local_name]"
262     sub set_attribute_ns ($$$$) {
263     my ($self, $nsuri, $qn, $value) = @_;
264     $self->{attributes}->{$nsuri}->{$qn->[1]}
265 wakaba 1.2 = Whatpm::NanoDOM::Attr->new ($nsuri, $qn->[0], $qn->[1], $value);
266 wakaba 1.1 } # set_attribute_ns
267    
268 wakaba 1.2 package Whatpm::NanoDOM::Attr;
269     push our @ISA, 'Whatpm::NanoDOM::Node';
270 wakaba 1.1
271     sub new ($$$$$) {
272     my $self = shift->SUPER::new;
273     $self->{namespace_uri} = shift;
274     $self->{prefix} = shift;
275     $self->{local_name} = shift;
276     $self->{value} = shift;
277     return $self;
278     } # new
279    
280     sub node_type { 2 }
281    
282     ## TODO: HTML5 case stuff?
283     sub name ($) {
284     my $self = shift;
285     if (defined $self->{prefix}) {
286     return $self->{prefix} . ':' . $self->{local_name};
287     } else {
288     return $self->{local_name};
289     }
290     } # name
291    
292     sub value ($) {
293     return shift->{value};
294     } # value
295    
296 wakaba 1.2 package Whatpm::NanoDOM::CharacterData;
297     push our @ISA, 'Whatpm::NanoDOM::Node';
298 wakaba 1.1
299     sub new ($$) {
300     my $self = shift->SUPER::new;
301     $self->{data} = shift;
302     return $self;
303     } # new
304    
305     ## A manakai extension
306     sub manakai_append_text ($$) {
307     my ($self, $s) = @_;
308     $self->{data} .= $s;
309     } # manakai_append_text
310    
311     sub data ($) {
312     return shift->{data};
313     } # data
314    
315 wakaba 1.2 package Whatpm::NanoDOM::Text;
316     push our @ISA, 'Whatpm::NanoDOM::CharacterData';
317 wakaba 1.1
318     sub node_type () { 3 }
319    
320 wakaba 1.2 package Whatpm::NanoDOM::Comment;
321     push our @ISA, 'Whatpm::NanoDOM::CharacterData';
322 wakaba 1.1
323     sub node_type () { 8 }
324    
325 wakaba 1.2 package Whatpm::NanoDOM::DocumentType;
326     push our @ISA, 'Whatpm::NanoDOM::Node';
327 wakaba 1.1
328     sub new ($$) {
329     my $self = shift->SUPER::new;
330     $self->{name} = shift;
331     return $self;
332     } # new
333    
334     sub node_type () { 10 }
335    
336     sub name ($) {
337     return shift->{name};
338     } # name
339    
340     =head1 SEE ALSO
341    
342 wakaba 1.2 L<Whatpm::HTML>
343 wakaba 1.1
344     =head1 AUTHOR
345    
346     Wakaba <w@suika.fam.cx>.
347    
348     =head1 LICENSE
349    
350     Copyright 2007 Wakaba <w@suika.fam.cx>
351    
352     This library is free software; you can redistribute it
353     and/or modify it under the same terms as Perl itself.
354    
355     =cut
356    
357     1;
358 wakaba 1.2 # $Date: 2007/05/01 10:36:06 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24