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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Fri May 4 09:18:20 2007 UTC (19 years, 2 months ago) by wakaba
Branch: MAIN
++ whatpm/Whatpm/ChangeLog	4 May 2007 09:16:36 -0000
	* ContentChecker.pm: New module.

2007-05-04  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 package Whatpm::ContentChecker;
2     use strict;
3    
4     my $ElementDefault = {
5     checker => sub {
6     my (undef, $el, $onerror) = @_;
7     my $children = [];
8     my @nodes = (@{$el->child_nodes});
9     while (@nodes) {
10     my $node = shift @nodes;
11     my $nt = $node->node_type;
12     if ($nt == 1) {
13     push @$children, $node;
14     } elsif ($nt == 5) {
15     unshift @nodes, @{$node->child_nodes};
16     }
17     }
18     return ($children);
19     },
20     };
21    
22     my $Element = {};
23    
24     my $HTML_NS = q<http://www.w3.org/1999/xhtml>;
25    
26     my $HTMLMetadataElements = [
27     [$HTML_NS, 'link'],
28     [$HTML_NS, 'meta'],
29     [$HTML_NS, 'style'],
30     [$HTML_NS, 'script'],
31     [$HTML_NS, 'event-source'],
32     [$HTML_NS, 'command'],
33     [$HTML_NS, 'title'],
34     ];
35    
36     my $HTMLSectioningElements = [
37     [$HTML_NS, 'body'],
38     [$HTML_NS, 'section'],
39     [$HTML_NS, 'nav'],
40     [$HTML_NS, 'article'],
41     [$HTML_NS, 'blockquote'],
42     [$HTML_NS, 'aside'],
43     ];
44    
45     my $HTMLBlockLevelElements = [
46     [$HTML_NS, 'section'],
47     [$HTML_NS, 'nav'],
48     [$HTML_NS, 'article'],
49     [$HTML_NS, 'blockquote'],
50     [$HTML_NS, 'aside'],
51     [$HTML_NS, 'header'],
52     [$HTML_NS, 'footer'],
53     [$HTML_NS, 'address'],
54     [$HTML_NS, 'p'],
55     [$HTML_NS, 'hr'],
56     [$HTML_NS, 'dialog'],
57     [$HTML_NS, 'pre'],
58     [$HTML_NS, 'ol'],
59     [$HTML_NS, 'ul'],
60     [$HTML_NS, 'dl'],
61     [$HTML_NS, 'ins'],
62     [$HTML_NS, 'del'],
63     [$HTML_NS, 'figure'],
64     [$HTML_NS, 'map'],
65     [$HTML_NS, 'table'],
66     [$HTML_NS, 'script'],
67     [$HTML_NS, 'noscript'],
68     [$HTML_NS, 'event-source'],
69     [$HTML_NS, 'details'],
70     [$HTML_NS, 'datagrid'],
71     [$HTML_NS, 'menu'],
72     [$HTML_NS, 'div'],
73     [$HTML_NS, 'font'],
74     ];
75    
76     my $HTMLStrictlyInlineLevelElements = [
77     [$HTML_NS, 'br'],
78     [$HTML_NS, 'a'],
79     [$HTML_NS, 'q'],
80     [$HTML_NS, 'cite'],
81     [$HTML_NS, 'em'],
82     [$HTML_NS, 'strong'],
83     [$HTML_NS, 'small'],
84     [$HTML_NS, 'm'],
85     [$HTML_NS, 'dfn'],
86     [$HTML_NS, 'abbr'],
87     [$HTML_NS, 'time'],
88     [$HTML_NS, 'meter'],
89     [$HTML_NS, 'progress'],
90     [$HTML_NS, 'code'],
91     [$HTML_NS, 'var'],
92     [$HTML_NS, 'samp'],
93     [$HTML_NS, 'kbd'],
94     [$HTML_NS, 'sub'],
95     [$HTML_NS, 'sup'],
96     [$HTML_NS, 'span'],
97     [$HTML_NS, 'i'],
98     [$HTML_NS, 'b'],
99     [$HTML_NS, 'bdo'],
100     [$HTML_NS, 'ins'],
101     [$HTML_NS, 'del'],
102     [$HTML_NS, 'img'],
103     [$HTML_NS, 'iframe'],
104     [$HTML_NS, 'embed'],
105     [$HTML_NS, 'object'],
106     [$HTML_NS, 'video'],
107     [$HTML_NS, 'audio'],
108     [$HTML_NS, 'canvas'],
109     [$HTML_NS, 'area'],
110     [$HTML_NS, 'script'],
111     [$HTML_NS, 'noscript'],
112     [$HTML_NS, 'event-source'],
113     [$HTML_NS, 'command'],
114     [$HTML_NS, 'font'],
115     ];
116    
117     my $HTMLStructuredInlineLevelElements = [
118     [$HTML_NS, 'blockquote'],
119     [$HTML_NS, 'pre'],
120     [$HTML_NS, 'ol'],
121     [$HTML_NS, 'ul'],
122     [$HTML_NS, 'dl'],
123     [$HTML_NS, 'table'],
124     [$HTML_NS, 'menu'],
125     ];
126    
127     my $HTMLInteractiveElements = [
128     [$HTML_NS, 'a'],
129     [$HTML_NS, 'details'],
130     [$HTML_NS, 'datagrid'],
131     ];
132    
133     my $HTMLTransparentElements = [
134     [$HTML_NS, 'ins'],
135     [$HTML_NS, 'font'],
136     ];
137     # TODO: script, if scripting is disabled
138    
139     # TODO: semi-transparent video, audio
140    
141     my $HTMLEmbededElements = [
142     [$HTML_NS, 'img'],
143     [$HTML_NS, 'iframe'],
144     [$HTML_NS, 'embed'],
145     [$HTML_NS, 'object'],
146     [$HTML_NS, 'video'],
147     [$HTML_NS, 'audio'],
148     [$HTML_NS, 'canvas'],
149     ];
150    
151     ## Empty
152     my $HTMLEmptyChecker = sub {
153     my (undef, $el, $onerror) = @_;
154     my $children = [];
155     my @nodes = (@{$el->child_nodes});
156    
157     while (@nodes) {
158     my $node = shift @nodes;
159     my $nt = $node->node_type;
160     if ($nt == 1) {
161     $onerror->(node => $node, type => 'element not allowed');
162     TP: {
163     for (@{$HTMLTransparentElements}) {
164     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
165     unshift @nodes, @{$node->child_nodes};
166     last TP;
167     }
168     }
169     push @$children, $node;
170     } # TP
171     } elsif ($nt == 3 or $nt == 4) {
172     $onerror->(node => $node, type => 'character not allowed');
173     } elsif ($nt == 5) {
174     unshift @nodes, @{$node->child_nodes};
175     }
176     }
177     return ($children);
178     };
179    
180     ## Text
181     my $HTMLTextChecker = sub {
182     my (undef, $el, $onerror) = @_;
183     my $children = [];
184     my @nodes = (@{$el->child_nodes});
185    
186     while (@nodes) {
187     my $node = shift @nodes;
188     my $nt = $node->node_type;
189     if ($nt == 1) {
190     $onerror->(node => $node, type => 'element not allowed');
191     TP: {
192     for (@{$HTMLTransparentElements}) {
193     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
194     unshift @nodes, @{$node->child_nodes};
195     last TP;
196     }
197     }
198     push @$children, $node;
199     } # TP
200     } elsif ($nt == 5) {
201     unshift @nodes, @{$node->child_nodes};
202     }
203     }
204     return ($children);
205     };
206    
207     ## Zero or more |html:style| elements,
208     ## followed by zero or more block-level elements
209     my $HTMLStylableBlockChecker = sub {
210     my (undef, $el, $onerror) = @_;
211     my $children = [];
212     my @nodes = (@{$el->child_nodes});
213    
214     my $has_non_style;
215     while (@nodes) {
216     my $node = shift @nodes;
217     my $nt = $node->node_type;
218     if ($nt == 1) {
219     if ($node->manakai_element_type_match ($HTML_NS, 'style')) {
220     if ($has_non_style) {
221     $onerror->(node => $node, type => 'element not allowed');
222     }
223     } else {
224     $has_non_style = 1;
225     CHK: {
226     for (@{$HTMLBlockLevelElements}) {
227     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
228     last CHK;
229     }
230     }
231     $onerror->(node => $node, type => 'element not allowed');
232     } # CHK
233     }
234     TP: {
235     for (@{$HTMLTransparentElements}) {
236     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
237     unshift @nodes, @{$node->child_nodes};
238     last TP;
239     }
240     }
241     push @$children, $node;
242     } # TP
243     } elsif ($nt == 3 or $nt == 4) {
244     if ($node->data =~ /[^\x09-\x0D\x20]/) {
245     $onerror->(node => $node, type => 'character not allowed');
246     }
247     } elsif ($nt == 5) {
248     unshift @nodes, @{$node->child_nodes};
249     }
250     }
251     return ($children);
252     }; # $HTMLStylableBlockChecker
253    
254     ## Zero or more block-level elements
255     my $HTMLBlockChecker = sub {
256     my (undef, $el, $onerror) = @_;
257     my $children = [];
258     my @nodes = (@{$el->child_nodes});
259    
260     while (@nodes) {
261     my $node = shift @nodes;
262     my $nt = $node->node_type;
263     if ($nt == 1) {
264     CHK: {
265     for (@{$HTMLBlockLevelElements}) {
266     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
267     last CHK;
268     }
269     }
270     $onerror->(node => $node, type => 'element not allowed');
271     } # CHK
272     TP: {
273     for (@{$HTMLTransparentElements}) {
274     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
275     unshift @nodes, @{$node->child_nodes};
276     last TP;
277     }
278     }
279     push @$children, $node;
280     } # TP
281     } elsif ($nt == 3 or $nt == 4) {
282     if ($node->data =~ /[^\x09-\x0D\x20]/) {
283     $onerror->(node => $node, type => 'character not allowed');
284     }
285     } elsif ($nt == 5) {
286     unshift @nodes, @{$node->child_nodes};
287     }
288     }
289     return ($children);
290     }; # $HTMLBlockChecker
291    
292     ## Inline-level content
293     my $HTMLInlineChecker = sub {
294     my (undef, $el, $onerror) = @_;
295     my $children = [];
296     my @nodes = (@{$el->child_nodes});
297    
298     while (@nodes) {
299     my $node = shift @nodes;
300     my $nt = $node->node_type;
301     if ($nt == 1) {
302     CHK: {
303     for (@{$HTMLStrictlyInlineLevelElements},
304     @{$HTMLStructuredInlineLevelElements}) {
305     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
306     last CHK;
307     }
308     }
309     $onerror->(node => $node, type => 'element not allowed');
310     } # CHK
311     TP: {
312     for (@{$HTMLTransparentElements}) {
313     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
314     unshift @nodes, @{$node->child_nodes};
315     last TP;
316     }
317     }
318     push @$children, $node;
319     } # TP
320     } elsif ($nt == 5) {
321     unshift @nodes, @{$node->child_nodes};
322     }
323     }
324     return ($children);
325     }; # $HTMLStrictlyInlineChecker
326    
327     my $HTMLSignificantInlineChecker = $HTMLInlineChecker;
328     ## TODO: check significant content
329    
330     ## Strictly inline-level content
331     my $HTMLStrictlyInlineChecker = sub {
332     my (undef, $el, $onerror) = @_;
333     my $children = [];
334     my @nodes = (@{$el->child_nodes});
335    
336     while (@nodes) {
337     my $node = shift @nodes;
338     my $nt = $node->node_type;
339     if ($nt == 1) {
340     CHK: {
341     for (@{$HTMLStrictlyInlineLevelElements}) {
342     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
343     last CHK;
344     }
345     }
346     $onerror->(node => $node, type => 'element not allowed');
347     } # CHK
348     TP: {
349     for (@{$HTMLTransparentElements}) {
350     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
351     unshift @nodes, @{$node->child_nodes};
352     last TP;
353     }
354     }
355     push @$children, $node;
356     } # TP
357     } elsif ($nt == 5) {
358     unshift @nodes, @{$node->child_nodes};
359     }
360     }
361     return ($children);
362     }; # $HTMLStrictlyInlineChecker
363    
364     my $HTMLSignificantStrictlyInlineChecker = $HTMLStrictlyInlineChecker;
365     ## TODO: check significant content
366    
367     my $HTMLBlockOrInlineChecker = sub {
368     my (undef, $el, $onerror) = @_;
369     my $children = [];
370     my @nodes = (@{$el->child_nodes});
371    
372     my $content = 'block-or-inline'; # or 'block' or 'inline'
373     my @block_not_inline;
374     while (@nodes) {
375     my $node = shift @nodes;
376     my $nt = $node->node_type;
377     if ($nt == 1) {
378     if ($content eq 'block') {
379     CHK: {
380     for (@{$HTMLBlockLevelElements}) {
381     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
382     last CHK;
383     }
384     }
385     $onerror->(node => $node, type => 'element not allowed');
386     } # CHK
387     } elsif ($content eq 'inline') {
388     CHK: {
389     for (@{$HTMLStrictlyInlineLevelElements},
390     @{$HTMLStructuredInlineLevelElements}) {
391     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
392     last CHK;
393     }
394     }
395     $onerror->(node => $node, type => 'element not allowed');
396     } # CHK
397     } else {
398     my $is_block;
399     my $is_inline;
400     for (@{$HTMLBlockLevelElements}) {
401     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
402     $is_block = 1;
403     last;
404     }
405     }
406    
407     for (@{$HTMLStrictlyInlineLevelElements},
408     @{$HTMLStructuredInlineLevelElements}) {
409     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
410     $is_inline = 1;
411     last;
412     }
413     }
414    
415     push @block_not_inline, $node if $is_block and not $is_inline;
416     unless ($is_block) {
417     $content = 'inline';
418     for (@block_not_inline) {
419     $onerror->(node => $_, type => 'element not allowed');
420     }
421     unless ($is_inline) {
422     $onerror->(node => $node, type => 'element not allowed');
423     }
424     }
425     }
426     TP: {
427     for (@{$HTMLTransparentElements}) {
428     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
429     unshift @nodes, @{$node->child_nodes};
430     last TP;
431     }
432     }
433     push @$children, $node;
434     } # TP
435     } elsif ($nt == 3 or $nt == 4) {
436     if ($node->data =~ /[^\x09-\x0D\x20]/) {
437     if ($content eq 'block') {
438     $onerror->(node => $node, type => 'character not allowed');
439     } else {
440     $content = 'inline';
441     for (@block_not_inline) {
442     $onerror->(node => $_, type => 'element not allowed');
443     }
444     }
445     }
446     } elsif ($nt == 5) {
447     unshift @nodes, @{$node->child_nodes};
448     }
449     }
450     return ($children);
451     };
452    
453     my $HTMLStyledBlockOrInlineChecker = sub {
454     my (undef, $el, $onerror) = @_;
455     my $children = [];
456     my @nodes = (@{$el->child_nodes});
457    
458     my $has_non_style;
459     my $content = 'block-or-inline'; # or 'block' or 'inline'
460     my @block_not_inline;
461     while (@nodes) {
462     my $node = shift @nodes;
463     my $nt = $node->node_type;
464     if ($nt == 1) {
465     if ($node->manakai_element_type_match ($HTML_NS, 'style')) {
466     if ($has_non_style) {
467     $onerror->(node => $node, type => 'element not allowed');
468     }
469     } elsif ($content eq 'block') {
470     $has_non_style = 1;
471     CHK: {
472     for (@{$HTMLBlockLevelElements}) {
473     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
474     last CHK;
475     }
476     }
477     $onerror->(node => $node, type => 'element not allowed');
478     } # CHK
479     } elsif ($content eq 'inline') {
480     $has_non_style = 1;
481     CHK: {
482     for (@{$HTMLStrictlyInlineLevelElements},
483     @{$HTMLStructuredInlineLevelElements}) {
484     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
485     last CHK;
486     }
487     }
488     $onerror->(node => $node, type => 'element not allowed');
489     } # CHK
490     } else {
491     $has_non_style = 1;
492     my $is_block;
493     my $is_inline;
494     for (@{$HTMLBlockLevelElements}) {
495     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
496     $is_block = 1;
497     last;
498     }
499     }
500    
501     for (@{$HTMLStrictlyInlineLevelElements},
502     @{$HTMLStructuredInlineLevelElements}) {
503     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
504     $is_inline = 1;
505     last;
506     }
507     }
508    
509     push @block_not_inline, $node if $is_block and not $is_inline;
510     unless ($is_block) {
511     $content = 'inline';
512     for (@block_not_inline) {
513     $onerror->(node => $_, type => 'element not allowed');
514     }
515     unless ($is_inline) {
516     $onerror->(node => $node, type => 'element not allowed');
517     }
518     }
519     }
520     TP: {
521     for (@{$HTMLTransparentElements}) {
522     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
523     unshift @nodes, @{$node->child_nodes};
524     last TP;
525     }
526     }
527     push @$children, $node;
528     } # TP
529     } elsif ($nt == 3 or $nt == 4) {
530     if ($node->data =~ /[^\x09-\x0D\x20]/) {
531     $has_non_style = 1;
532     if ($content eq 'block') {
533     $onerror->(node => $node, type => 'character not allowed');
534     } else {
535     $content = 'inline';
536     for (@block_not_inline) {
537     $onerror->(node => $_, type => 'element not allowed');
538     }
539     }
540     }
541     } elsif ($nt == 5) {
542     unshift @nodes, @{$node->child_nodes};
543     }
544     }
545     return ($children);
546     };
547    
548     my $HTMLTransparentChecker = $HTMLBlockOrInlineChecker;
549    
550     $Element->{$HTML_NS}->{html} = {
551     checker => sub {
552     my (undef, $el, $onerror) = @_;
553     my $children = [];
554     my @nodes = (@{$el->child_nodes});
555    
556     my $phase = 'before head';
557     while (@nodes) {
558     my $node = shift @nodes;
559     my $nt = $node->node_type;
560     if ($nt == 1) {
561     if ($phase eq 'before head') {
562     if ($node->manakai_element_type_match ($HTML_NS, 'head')) {
563     $phase = 'after head';
564     } elsif ($node->manakai_element_type_match ($HTML_NS, 'body')) {
565     $onerror->(node => $node, type => 'element missing before:head');
566     $phase = 'after body';
567     } else {
568     $onerror->(node => $node, type => 'element not allowed');
569     # before head
570     }
571     } elsif ($phase eq 'after head') {
572     if ($node->manakai_element_type_match ($HTML_NS, 'body')) {
573     $phase = 'after body';
574     } else {
575     $onerror->(node => $node, type => 'element not allowed');
576     # after head
577     }
578     } else { #elsif ($phase eq 'after body') {
579     $onerror->(node => $node, type => 'element not allowed');
580     # after body
581     }
582     TP: {
583     for (@{$HTMLTransparentElements}) {
584     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
585     unshift @nodes, @{$node->child_nodes};
586     last TP;
587     }
588     }
589     push @$children, $node;
590     } # TP
591     } elsif ($nt == 3 or $nt == 4) {
592     if ($node->data =~ /[^\x09-\x0D\x20]/) {
593     $onerror->(node => $node, type => 'character not allowed');
594     }
595     } elsif ($nt == 5) {
596     unshift @nodes, @{$node->child_nodes};
597     }
598     }
599     return ($children);
600     },
601     };
602    
603     $Element->{$HTML_NS}->{head} = {
604     checker => sub {
605     my (undef, $el, $onerror) = @_;
606     my $children = [];
607     my @nodes = (@{$el->child_nodes});
608    
609     my $has_meta_charset;
610     my $has_title;
611     my $has_base;
612     my $has_non_base;
613     while (@nodes) {
614     my $node = shift @nodes;
615     my $nt = $node->node_type;
616     if ($nt == 1) {
617     if ($node->manakai_element_type_match ($HTML_NS, 'title')) {
618     $has_non_base = 1;
619     unless ($has_title) {
620     $has_title = 1;
621     } else {
622     $onerror->(node => $node, type => 'duplicate:title');
623     }
624     } elsif ($node->manakai_element_type_match ($HTML_NS, 'meta')) {
625     $has_non_base = 1;
626     if ($node->has_attribute_ns (undef, 'charset')) {
627     unless ($has_meta_charset) {
628     if ($has_base) {
629     $onerror->(node => $node, type => 'element not allowed');
630     ## NOTE: See |base|'s "contexts" field in the spec
631     }
632     $has_meta_charset = 1;
633     } else {
634     $onerror->(node => $node, type => 'duplicate:meta charset');
635     }
636     } else {
637     # metadata element
638     }
639     } elsif ($node->manakai_element_type_match ($HTML_NS, 'base')) {
640     unless ($has_base) {
641     if ($has_non_base) {
642     $onerror->(node => $node, type => 'element not allowed');
643     }
644     $has_base = 1;
645     } else {
646     $onerror->(node => $node, type => 'duplicate:base');
647     }
648     } else {
649     $has_non_base = 1;
650     CHK: {
651     for (@{$HTMLMetadataElements}) {
652     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
653     last CHK;
654     }
655     }
656     $onerror->(node => $node, type => 'element not allowed');
657     } # CHK
658     }
659     TP: {
660     for (@{$HTMLTransparentElements}) {
661     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
662     unshift @nodes, @{$node->child_nodes};
663     last TP;
664     }
665     }
666     push @$children, $node;
667     } # TP
668     } elsif ($nt == 3 or $nt == 4) {
669     if ($node->data =~ /[^\x09-\x0D\x20]/) {
670     $onerror->(node => $node, type => 'character not allowed');
671     }
672     } elsif ($nt == 5) {
673     unshift @nodes, @{$node->child_nodes};
674     }
675     }
676     unless ($has_title) {
677     $onerror->(node => $el, type => 'element missing in:title');
678     }
679     return ($children);
680     },
681     };
682    
683     $Element->{$HTML_NS}->{title} = {
684     checker => $HTMLTextChecker,
685     };
686    
687     $Element->{$HTML_NS}->{base} = {
688     checker => $HTMLEmptyChecker,
689     };
690    
691     $Element->{$HTML_NS}->{link} = {
692     checker => $HTMLEmptyChecker,
693     };
694    
695     $Element->{$HTML_NS}->{meta} = {
696     checker => $HTMLEmptyChecker,
697     };
698    
699     ## NOTE: |html:style| has no conformance creteria on content model
700    
701     $Element->{$HTML_NS}->{body} = {
702     checker => $HTMLBlockChecker,
703     };
704    
705     $Element->{$HTML_NS}->{section} = {
706     checker => $HTMLStylableBlockChecker,
707     };
708    
709     $Element->{$HTML_NS}->{nav} = {
710     checker => $HTMLBlockOrInlineChecker,
711     };
712    
713     $Element->{$HTML_NS}->{article} = {
714     checker => $HTMLStylableBlockChecker,
715     };
716    
717     $Element->{$HTML_NS}->{blockquote} = {
718     checker => $HTMLBlockChecker,
719     };
720    
721     $Element->{$HTML_NS}->{aside} = {
722     checker => $HTMLStyledBlockOrInlineChecker,
723     };
724    
725     $Element->{$HTML_NS}->{h1} = {
726     checker => $HTMLSignificantStrictlyInlineChecker,
727     };
728    
729     $Element->{$HTML_NS}->{h2} = {
730     checker => $HTMLSignificantStrictlyInlineChecker,
731     };
732    
733     $Element->{$HTML_NS}->{h3} = {
734     checker => $HTMLSignificantStrictlyInlineChecker,
735     };
736    
737     $Element->{$HTML_NS}->{h4} = {
738     checker => $HTMLSignificantStrictlyInlineChecker,
739     };
740    
741     $Element->{$HTML_NS}->{h5} = {
742     checker => $HTMLSignificantStrictlyInlineChecker,
743     };
744    
745     $Element->{$HTML_NS}->{h6} = {
746     checker => $HTMLSignificantStrictlyInlineChecker,
747     };
748    
749     ## TODO: header
750    
751     ## TODO: footer
752    
753     $Element->{$HTML_NS}->{address} = {
754     checker => $HTMLInlineChecker,
755     };
756    
757     $Element->{$HTML_NS}->{p} = {
758     checker => $HTMLSignificantInlineChecker,
759     };
760    
761     $Element->{$HTML_NS}->{hr} = {
762     checker => $HTMLEmptyChecker,
763     };
764    
765     $Element->{$HTML_NS}->{br} = {
766     checker => $HTMLEmptyChecker,
767     };
768    
769     $Element->{$HTML_NS}->{dialog} = {
770     checker => sub {
771     my (undef, $el, $onerror) = @_;
772     my $children = [];
773     my @nodes = (@{$el->child_nodes});
774    
775     my $phase = 'before dt';
776     while (@nodes) {
777     my $node = shift @nodes;
778     my $nt = $node->node_type;
779     if ($nt == 1) {
780     if ($phase eq 'before dt') {
781     if ($node->manakai_element_type_match ($HTML_NS, 'dt')) {
782     $phase = 'before dd';
783     } elsif ($node->manakai_element_type_match ($HTML_NS, 'dd')) {
784     $onerror->(node => $node, type => 'element missing before:dt');
785     $phase = 'before dt';
786     } else {
787     $onerror->(node => $node, type => 'element not allowed');
788     }
789     } else { # before dd
790     if ($node->manakai_element_type_match ($HTML_NS, 'dd')) {
791     $phase = 'before dt';
792     } elsif ($node->manakai_element_type_match ($HTML_NS, 'dt')) {
793     $onerror->(node => $node, type => 'element missing before:dd');
794     $phase = 'before dd';
795     } else {
796     $onerror->(node => $node, type => 'element not allowed');
797     }
798     }
799     TP: {
800     for (@{$HTMLTransparentElements}) {
801     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
802     unshift @nodes, @{$node->child_nodes};
803     last TP;
804     }
805     }
806     push @$children, $node;
807     } # TP
808     } elsif ($nt == 3 or $nt == 4) {
809     if ($node->data =~ /[^\x09-\x0D\x20]/) {
810     $onerror->(node => $node, type => 'character not allowed');
811     }
812     } elsif ($nt == 5) {
813     unshift @nodes, @{$node->child_nodes};
814     }
815     }
816     if ($phase eq 'before dd') {
817     $onerror->(node => $el, type => 'element missing before:dd');
818     }
819     return ($children);
820     },
821     };
822    
823     $Element->{$HTML_NS}->{pre} = {
824     checker => $HTMLStrictlyInlineChecker,
825     };
826    
827     $Element->{$HTML_NS}->{ol} = {
828     checker => sub {
829     my (undef, $el, $onerror) = @_;
830     my $children = [];
831     my @nodes = (@{$el->child_nodes});
832    
833     while (@nodes) {
834     my $node = shift @nodes;
835     my $nt = $node->node_type;
836     if ($nt == 1) {
837     unless ($node->manakai_element_type_match ($HTML_NS, 'li')) {
838     $onerror->(node => $node, type => 'element not allowed');
839     }
840     TP: {
841     for (@{$HTMLTransparentElements}) {
842     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
843     unshift @nodes, @{$node->child_nodes};
844     last TP;
845     }
846     }
847     push @$children, $node;
848     } # TP
849     } elsif ($nt == 3 or $nt == 4) {
850     if ($node->data =~ /[^\x09-\x0D\x20]/) {
851     $onerror->(node => $node, type => 'character not allowed');
852     }
853     } elsif ($nt == 5) {
854     unshift @nodes, @{$node->child_nodes};
855     }
856     }
857     return ($children);
858     },
859     };
860    
861     $Element->{$HTML_NS}->{ul} = {
862     checker => $Element->{$HTML_NS}->{ol}->{checker},
863     };
864    
865     ## TODO: li
866    
867     $Element->{$HTML_NS}->{dl} = {
868     checker => sub {
869     my (undef, $el, $onerror) = @_;
870     my $children = [];
871     my @nodes = (@{$el->child_nodes});
872    
873     my $phase = 'before dt';
874     while (@nodes) {
875     my $node = shift @nodes;
876     my $nt = $node->node_type;
877     if ($nt == 1) {
878     if ($phase eq 'in dds') {
879     if ($node->manakai_element_type_match ($HTML_NS, 'dd')) {
880     #$phase = 'in dds';
881     } elsif ($node->manakai_element_type_match ($HTML_NS, 'dt')) {
882     $phase = 'in dts';
883     } else {
884     $onerror->(node => $node, type => 'element not allowed');
885     }
886     } elsif ($phase eq 'in dts') {
887     if ($node->manakai_element_type_match ($HTML_NS, 'dt')) {
888     #$phase = 'in dts';
889     } elsif ($node->manakai_element_type_match ($HTML_NS, 'dd')) {
890     $phase = 'in dds';
891     } else {
892     $onerror->(node => $node, type => 'element not allowed');
893     }
894     } else { # before dt
895     if ($node->manakai_element_type_match ($HTML_NS, 'dt')) {
896     $phase = 'in dts';
897     } elsif ($node->manakai_element_type_match ($HTML_NS, 'dd')) {
898     $onerror->(node => $node, type => 'element missing before:dt');
899     $phase = 'in dds';
900     } else {
901     $onerror->(node => $node, type => 'element not allowed');
902     }
903     }
904     TP: {
905     for (@{$HTMLTransparentElements}) {
906     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
907     unshift @nodes, @{$node->child_nodes};
908     last TP;
909     }
910     }
911     push @$children, $node;
912     } # TP
913     } elsif ($nt == 3 or $nt == 4) {
914     if ($node->data =~ /[^\x09-\x0D\x20]/) {
915     $onerror->(node => $node, type => 'character not allowed');
916     }
917     } elsif ($nt == 5) {
918     unshift @nodes, @{$node->child_nodes};
919     }
920     }
921     if ($phase eq 'in dts') {
922     $onerror->(node => $el, type => 'element missing before:dd');
923     }
924     return ($children);
925     },
926     };
927    
928     $Element->{$HTML_NS}->{dt} = {
929     checker => $HTMLStrictlyInlineChecker,
930     };
931    
932     ## TODO: dd
933    
934     ## TODO: a
935    
936     ## TODO: q
937    
938     $Element->{$HTML_NS}->{cite} = {
939     checker => $HTMLStrictlyInlineChecker,
940     };
941    
942     ## TODO: em
943    
944     ## TODO: strong, small, m, dfn
945    
946     $Element->{$HTML_NS}->{abbr} = {
947     checker => $HTMLStrictlyInlineChecker,
948     };
949    
950     $Element->{$HTML_NS}->{time} = {
951     checker => $HTMLStrictlyInlineChecker,
952     };
953    
954     $Element->{$HTML_NS}->{meter} = {
955     checker => $HTMLStrictlyInlineChecker,
956     };
957    
958     $Element->{$HTML_NS}->{progress} = {
959     checker => $HTMLStrictlyInlineChecker,
960     };
961    
962     ## TODO: code
963    
964     $Element->{$HTML_NS}->{var} = {
965     checker => $HTMLStrictlyInlineChecker,
966     };
967    
968     ## TODO: samp
969    
970     $Element->{$HTML_NS}->{kbd} = {
971     checker => $HTMLStrictlyInlineChecker,
972     };
973    
974     $Element->{$HTML_NS}->{sub} = {
975     checker => $HTMLStrictlyInlineChecker,
976     };
977    
978     $Element->{$HTML_NS}->{sup} = {
979     checker => $HTMLStrictlyInlineChecker,
980     };
981    
982     ## TODO: span
983    
984     $Element->{$HTML_NS}->{i} = {
985     checker => $HTMLStrictlyInlineChecker,
986     };
987    
988     $Element->{$HTML_NS}->{b} = {
989     checker => $HTMLStrictlyInlineChecker,
990     };
991    
992     $Element->{$HTML_NS}->{bdo} = {
993     checker => $HTMLStrictlyInlineChecker,
994     };
995    
996     $Element->{$HTML_NS}->{ins} = {
997     checker => $HTMLTransparentChecker,
998     };
999    
1000     $Element->{$HTML_NS}->{del} = {
1001     checker => sub {
1002     my ($self, $el, $onerror) = @_;
1003    
1004     my $parent = $el->manakai_parent_element;
1005     if (defined $parent) {
1006     my $nsuri = $parent->namespace_uri;
1007     $nsuri = '' unless defined $nsuri;
1008     my $ln = $parent->manakai_local_name;
1009     my $eldef = $Element->{$nsuri}->{$ln} ||
1010     $Element->{$nsuri}->{''} ||
1011     $ElementDefault;
1012     return $eldef->{checker}->($self, $el, $onerror);
1013     } else {
1014     return $HTMLBlockOrInlineChecker->($self, $el, $onerror);
1015     }
1016     },
1017     };
1018    
1019     ## TODO: figure
1020    
1021     $Element->{$HTML_NS}->{img} = {
1022     checker => $HTMLEmptyChecker,
1023     };
1024    
1025     $Element->{$HTML_NS}->{iframe} = {
1026     checker => $HTMLTextChecker,
1027     };
1028    
1029     $Element->{$HTML_NS}->{embed} = {
1030     checker => $HTMLEmptyChecker,
1031     };
1032    
1033     $Element->{$HTML_NS}->{param} = {
1034     checker => $HTMLEmptyChecker,
1035     };
1036    
1037     ## TODO: object
1038    
1039     ## TODO: video, audio
1040    
1041     $Element->{$HTML_NS}->{source} = {
1042     checker => $HTMLEmptyChecker,
1043     };
1044    
1045     $Element->{$HTML_NS}->{canvas} = {
1046     checker => $HTMLInlineChecker,
1047     };
1048    
1049     $Element->{$HTML_NS}->{map} = {
1050     checker => $HTMLBlockChecker,
1051     };
1052    
1053     $Element->{$HTML_NS}->{area} = {
1054     checker => $HTMLEmptyChecker,
1055     };
1056     ## TODO: only in map
1057    
1058     $Element->{$HTML_NS}->{table} = {
1059     checker => sub {
1060     my (undef, $el, $onerror) = @_;
1061     my $children = [];
1062     my @nodes = (@{$el->child_nodes});
1063    
1064     my $phase = 'before caption';
1065     my $has_tfoot;
1066     while (@nodes) {
1067     my $node = shift @nodes;
1068     my $nt = $node->node_type;
1069     if ($nt == 1) {
1070     if ($phase eq 'in tbodys') {
1071     if ($node->manakai_element_type_match ($HTML_NS, 'tbody')) {
1072     #$phase = 'in tbodys';
1073     } elsif (not $has_tfoot and
1074     $node->manakai_element_type_match ($HTML_NS, 'tfoot')) {
1075     $phase = 'after tfoot';
1076     $has_tfoot = 1;
1077     } else {
1078     $onerror->(node => $node, type => 'element not allowed');
1079     }
1080     } elsif ($phase eq 'in trs') {
1081     if ($node->manakai_element_type_match ($HTML_NS, 'tr')) {
1082     #$phase = 'in trs';
1083     } elsif (not $has_tfoot and
1084     $node->manakai_element_type_match ($HTML_NS, 'tfoot')) {
1085     $phase = 'after tfoot';
1086     $has_tfoot = 1;
1087     } else {
1088     $onerror->(node => $node, type => 'element not allowed');
1089     }
1090     } elsif ($phase eq 'after thead') {
1091     if ($node->manakai_element_type_match ($HTML_NS, 'tbody')) {
1092     $phase = 'in tbodys';
1093     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tr')) {
1094     $phase = 'in trs';
1095     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tfoot')) {
1096     $phase = 'in tbodys';
1097     $has_tfoot = 1;
1098     } else {
1099     $onerror->(node => $node, type => 'element not allowed');
1100     }
1101     } elsif ($phase eq 'in colgroup') {
1102     if ($node->manakai_element_type_match ($HTML_NS, 'colgroup')) {
1103     $phase = 'in colgroup';
1104     } elsif ($node->manakai_element_type_match ($HTML_NS, 'thead')) {
1105     $phase = 'after thead';
1106     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tbody')) {
1107     $phase = 'in tbodys';
1108     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tr')) {
1109     $phase = 'in trs';
1110     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tfoot')) {
1111     $phase = 'in tbodys';
1112     $has_tfoot = 1;
1113     } else {
1114     $onerror->(node => $node, type => 'element not allowed');
1115     }
1116     } elsif ($phase eq 'before caption') {
1117     if ($node->manakai_element_type_match ($HTML_NS, 'caption')) {
1118     $phase = 'in colgroup';
1119     } elsif ($node->manakai_element_type_match ($HTML_NS, 'colgroup')) {
1120     $phase = 'in colgroup';
1121     } elsif ($node->manakai_element_type_match ($HTML_NS, 'thead')) {
1122     $phase = 'after thead';
1123     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tbody')) {
1124     $phase = 'in tbodys';
1125     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tr')) {
1126     $phase = 'in trs';
1127     } elsif ($node->manakai_element_type_match ($HTML_NS, 'tfoot')) {
1128     $phase = 'in tbodys';
1129     $has_tfoot = 1;
1130     } else {
1131     $onerror->(node => $node, type => 'element not allowed');
1132     }
1133     } else { # after tfoot
1134     $onerror->(node => $node, type => 'element not allowed');
1135     }
1136     TP: {
1137     for (@{$HTMLTransparentElements}) {
1138     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1139     unshift @nodes, @{$node->child_nodes};
1140     last TP;
1141     }
1142     }
1143     push @$children, $node;
1144     } # TP
1145     } elsif ($nt == 3 or $nt == 4) {
1146     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1147     $onerror->(node => $node, type => 'character not allowed');
1148     }
1149     } elsif ($nt == 5) {
1150     unshift @nodes, @{$node->child_nodes};
1151     }
1152     }
1153     return ($children);
1154     },
1155     };
1156    
1157     $Element->{$HTML_NS}->{caption} = {
1158     checker => $HTMLSignificantStrictlyInlineChecker,
1159     };
1160    
1161     $Element->{$HTML_NS}->{colgroup} = {
1162     checker => sub {
1163     my (undef, $el, $onerror) = @_;
1164     my $children = [];
1165     my @nodes = (@{$el->child_nodes});
1166    
1167     while (@nodes) {
1168     my $node = shift @nodes;
1169     my $nt = $node->node_type;
1170     if ($nt == 1) {
1171     unless ($node->manakai_element_type_match ($HTML_NS, 'col')) {
1172     $onerror->(node => $node, type => 'element not allowed');
1173     }
1174     TP: {
1175     for (@{$HTMLTransparentElements}) {
1176     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1177     unshift @nodes, @{$node->child_nodes};
1178     last TP;
1179     }
1180     }
1181     push @$children, $node;
1182     } # TP
1183     } elsif ($nt == 3 or $nt == 4) {
1184     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1185     $onerror->(node => $node, type => 'character not allowed');
1186     }
1187     } elsif ($nt == 5) {
1188     unshift @nodes, @{$node->child_nodes};
1189     }
1190     }
1191     return ($children);
1192     },
1193     };
1194    
1195     $Element->{$HTML_NS}->{col} = {
1196     checker => $HTMLEmptyChecker,
1197     };
1198    
1199     $Element->{$HTML_NS}->{tbody} = {
1200     checker => sub {
1201     my (undef, $el, $onerror) = @_;
1202     my $children = [];
1203     my @nodes = (@{$el->child_nodes});
1204    
1205     my $has_tr;
1206     while (@nodes) {
1207     my $node = shift @nodes;
1208     my $nt = $node->node_type;
1209     if ($nt == 1) {
1210     if ($node->manakai_element_type_match ($HTML_NS, 'tr')) {
1211     $has_tr = 1;
1212     } else {
1213     $onerror->(node => $node, type => 'element not allowed');
1214     }
1215     TP: {
1216     for (@{$HTMLTransparentElements}) {
1217     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1218     unshift @nodes, @{$node->child_nodes};
1219     last TP;
1220     }
1221     }
1222     push @$children, $node;
1223     } # TP
1224     } elsif ($nt == 3 or $nt == 4) {
1225     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1226     $onerror->(node => $node, type => 'character not allowed');
1227     }
1228     } elsif ($nt == 5) {
1229     unshift @nodes, @{$node->child_nodes};
1230     }
1231     }
1232     unless ($has_tr) {
1233     $onerror->(node => $el, type => 'element missing in:tr');
1234     }
1235     return ($children);
1236     },
1237     };
1238    
1239     $Element->{$HTML_NS}->{thead} = {
1240     checker => $Element->{$HTML_NS}->{tbody},
1241     };
1242    
1243     $Element->{$HTML_NS}->{tfoot} = {
1244     checker => $Element->{$HTML_NS}->{tbody},
1245     };
1246    
1247     $Element->{$HTML_NS}->{tr} = {
1248     checker => sub {
1249     my (undef, $el, $onerror) = @_;
1250     my $children = [];
1251     my @nodes = (@{$el->child_nodes});
1252    
1253     my $has_td;
1254     while (@nodes) {
1255     my $node = shift @nodes;
1256     my $nt = $node->node_type;
1257     if ($nt == 1) {
1258     if ($node->manakai_element_type_match ($HTML_NS, 'td') or
1259     $node->manakai_element_type_match ($HTML_NS, 'th')) {
1260     $has_td = 1;
1261     } else {
1262     $onerror->(node => $node, type => 'element not allowed');
1263     }
1264     TP: {
1265     for (@{$HTMLTransparentElements}) {
1266     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1267     unshift @nodes, @{$node->child_nodes};
1268     last TP;
1269     }
1270     }
1271     push @$children, $node;
1272     } # TP
1273     } elsif ($nt == 3 or $nt == 4) {
1274     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1275     $onerror->(node => $node, type => 'character not allowed');
1276     }
1277     } elsif ($nt == 5) {
1278     unshift @nodes, @{$node->child_nodes};
1279     }
1280     }
1281     unless ($has_td) {
1282     $onerror->(node => $el, type => 'element missing in:td or th');
1283     }
1284     return ($children);
1285     },
1286     };
1287    
1288     $Element->{$HTML_NS}->{td} = {
1289     checker => $HTMLBlockOrInlineChecker,
1290     };
1291    
1292     $Element->{$HTML_NS}->{th} = {
1293     checker => $HTMLBlockOrInlineChecker,
1294     };
1295    
1296     ## TODO: forms
1297    
1298     ## TODO: script
1299    
1300     ## TODO: noscript
1301    
1302     $Element->{$HTML_NS}->{'event-source'} = {
1303     checker => $HTMLEmptyChecker,
1304     };
1305    
1306     $Element->{$HTML_NS}->{details} = {
1307     checker => sub {
1308     my (undef, $el, $onerror) = @_;
1309     my $children = [];
1310     my @nodes = (@{$el->child_nodes});
1311    
1312     my $has_legend;
1313     my $has_non_legend;
1314     my $content = 'block-or-inline'; # or 'block' or 'inline'
1315     my @block_not_inline;
1316     while (@nodes) {
1317     my $node = shift @nodes;
1318     my $nt = $node->node_type;
1319     if ($nt == 1) {
1320     if (not $has_legend and
1321     $node->manakai_element_type_match ($HTML_NS, 'legend')) {
1322     $has_legend = 1;
1323     if ($has_non_legend) {
1324     $onerror->(node => $node, type => 'element not allowed');
1325     }
1326     } elsif ($content eq 'block') {
1327     $has_non_legend = 1;
1328     CHK: {
1329     for (@{$HTMLBlockLevelElements}) {
1330     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1331     last CHK;
1332     }
1333     }
1334     $onerror->(node => $node, type => 'element not allowed');
1335     } # CHK
1336     } elsif ($content eq 'inline') {
1337     $has_non_legend = 1;
1338     CHK: {
1339     for (@{$HTMLStrictlyInlineLevelElements},
1340     @{$HTMLStructuredInlineLevelElements}) {
1341     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1342     last CHK;
1343     }
1344     }
1345     $onerror->(node => $node, type => 'element not allowed');
1346     } # CHK
1347     } else {
1348     $has_non_legend = 1;
1349     my $is_block;
1350     my $is_inline;
1351     for (@{$HTMLBlockLevelElements}) {
1352     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1353     $is_block = 1;
1354     last;
1355     }
1356     }
1357    
1358     for (@{$HTMLStrictlyInlineLevelElements},
1359     @{$HTMLStructuredInlineLevelElements}) {
1360     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1361     $is_inline = 1;
1362     last;
1363     }
1364     }
1365    
1366     push @block_not_inline, $node if $is_block and not $is_inline;
1367     unless ($is_block) {
1368     $content = 'inline';
1369     for (@block_not_inline) {
1370     $onerror->(node => $_, type => 'element not allowed');
1371     }
1372     unless ($is_inline) {
1373     $onerror->(node => $node, type => 'element not allowed');
1374     }
1375     }
1376     }
1377     TP: {
1378     for (@{$HTMLTransparentElements}) {
1379     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1380     unshift @nodes, @{$node->child_nodes};
1381     last TP;
1382     }
1383     }
1384     push @$children, $node;
1385     } # TP
1386     } elsif ($nt == 3 or $nt == 4) {
1387     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1388     $has_non_legend = 1;
1389     if ($content eq 'block') {
1390     $onerror->(node => $node, type => 'character not allowed');
1391     } else {
1392     $content = 'inline';
1393     for (@block_not_inline) {
1394     $onerror->(node => $_, type => 'element not allowed');
1395     }
1396     }
1397     }
1398     } elsif ($nt == 5) {
1399     unshift @nodes, @{$node->child_nodes};
1400     }
1401     }
1402     unless ($has_legend) {
1403     $onerror->(node => $el, type => 'element missing in:legend');
1404     }
1405     return ($children);
1406     },
1407     };
1408    
1409     $Element->{$HTML_NS}->{datagrid} = {
1410     checker => $HTMLBlockChecker,
1411     };
1412    
1413     $Element->{$HTML_NS}->{command} = {
1414     checker => $HTMLEmptyChecker,
1415     };
1416    
1417     $Element->{$HTML_NS}->{menu} = {
1418     checker => sub {
1419     my (undef, $el, $onerror) = @_;
1420     my $children = [];
1421     my @nodes = (@{$el->child_nodes});
1422    
1423     my $content = 'li or inline';
1424     while (@nodes) {
1425     my $node = shift @nodes;
1426     my $nt = $node->node_type;
1427     if ($nt == 1) {
1428     if ($node->manakai_element_type_match ($HTML_NS, 'li')) {
1429     if ($content eq 'inline') {
1430     $onerror->(node => $node, type => 'element not allowed');
1431     } elsif ($content eq 'li or inline') {
1432     $content = 'li';
1433     }
1434     } else {
1435     CHK: {
1436     for (@{$HTMLStrictlyInlineLevelElements},
1437     @{$HTMLStructuredInlineLevelElements}) {
1438     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1439     $content = 'inline';
1440     last CHK;
1441     }
1442     }
1443     $onerror->(node => $node, type => 'element not allowed');
1444     } # CHK
1445     }
1446     TP: {
1447     for (@{$HTMLTransparentElements}) {
1448     if ($node->manakai_element_type_match ($_->[0], $_->[1])) {
1449     unshift @nodes, @{$node->child_nodes};
1450     last TP;
1451     }
1452     }
1453     push @$children, $node;
1454     } # TP
1455     } elsif ($nt == 3 or $nt == 4) {
1456     if ($node->data =~ /[^\x09-\x0D\x20]/) {
1457     if ($content eq 'li') {
1458     $onerror->(node => $node, type => 'character not allowed');
1459     } elsif ($content eq 'li or inline') {
1460     $content = 'inline';
1461     }
1462     }
1463     } elsif ($nt == 5) {
1464     unshift @nodes, @{$node->child_nodes};
1465     }
1466     }
1467     return ($children);
1468     },
1469     };
1470    
1471     ## TODO: legend
1472    
1473     $Element->{$HTML_NS}->{div} = {
1474     checker => $HTMLStyledBlockOrInlineChecker,
1475     };
1476    
1477     $Element->{$HTML_NS}->{font} = {
1478     checker => $HTMLTransparentChecker,
1479     };
1480    
1481     my $Attr = {
1482    
1483     };
1484    
1485     sub check_element ($$$) {
1486     my ($self, $el, $onerror) = @_;
1487    
1488     my @nodes = ($el);
1489     while (@nodes) {
1490     my $node = shift @nodes;
1491     my $nsuri = $node->namespace_uri;
1492     $nsuri = '' unless defined $nsuri;
1493     my $ln = $node->manakai_local_name;
1494     my $eldef = $Element->{$nsuri}->{$ln} ||
1495     $Element->{$nsuri}->{''} ||
1496     $ElementDefault;
1497     my ($children) = $eldef->{checker}->($self, $node, $onerror);
1498     push @nodes, @$children;
1499     }
1500     } # check_element
1501    
1502     1;
1503     # $Date:$

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24