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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.81 by wakaba, Sat May 10 06:04:39 2008 UTC revision 1.97 by wakaba, Sun Sep 21 09:45:02 2008 UTC
# Line 59  our $AttrChecker = { Line 59  our $AttrChecker = {
59          #          #
60        } else {        } else {
61          ## NOTE: An XML "error"          ## NOTE: An XML "error"
62          $self->{onerror}->(node => $attr, level => 'error',          $self->{onerror}->(node => $attr, level => $self->{level}->{xml_error},
63                             type => 'invalid attribute value');                             type => 'invalid attribute value');
64        }        }
65      },      },
# Line 71  our $AttrChecker = { Line 71  our $AttrChecker = {
71        } else {        } else {
72          require Whatpm::LangTag;          require Whatpm::LangTag;
73          Whatpm::LangTag->check_rfc3066_language_tag ($value, sub {          Whatpm::LangTag->check_rfc3066_language_tag ($value, sub {
74            my %opt = @_;            $self->{onerror}->(@_, node => $attr);
75            my $type = 'LangTag:'.$opt{type};          }, $self->{level});
           $type .= ':' . $opt{subtag} if defined $opt{subtag};  
           $self->{onerror}->(node => $attr, type => $type,  
                              value => $opt{value}, level => $opt{level});  
         });  
76        }        }
77    
78        ## NOTE: "The values of the attribute are language identifiers        ## NOTE: "The values of the attribute are language identifiers
79        ## as defined by [IETF RFC 3066], Tags for the Identification        ## as defined by [IETF RFC 3066], Tags for the Identification
80        ## of Languages, or its successor; in addition, the empty string        ## of Languages, or its successor; in addition, the empty string
81        ## may be specified." ("may" in lower case)        ## may be specified." ("may" in lower case)
82        ## NOTE: Is an RFC 3066-valid (but RFC 4647-invalid) language tag        ## NOTE: Is an RFC 3066-valid (but RFC 4646-invalid) language tag
83        ## allowed today?        ## allowed today?
84    
85        ## TODO: test data        ## TODO: test data
86    
87          my $nsuri = $attr->owner_element->namespace_uri;
88          if (defined $nsuri and $nsuri eq $HTML_NS) {
89            my $lang_attr = $attr->owner_element->get_attribute_node_ns
90                (undef, 'lang');
91            if ($lang_attr) {
92              my $lang_attr_value = $lang_attr->value;
93              $lang_attr_value =~ tr/A-Z/a-z/; ## ASCII case-insensitive
94              my $value = $value;
95              $value =~ tr/A-Z/a-z/; ## ASCII case-insensitive
96              if ($lang_attr_value ne $value) {
97                ## NOTE: HTML5 Section "The |lang| and |xml:lang| attributes"
98                $self->{onerror}->(node => $attr,
99                                   type => 'xml:lang ne lang',
100                                   level => $self->{level}->{must});
101              }
102            }
103          }
104    
105        if ($attr->owner_document->manakai_is_html) { # MUST NOT        if ($attr->owner_document->manakai_is_html) { # MUST NOT
106          $self->{onerror}->(node => $attr, type => 'in HTML:xml:lang');          $self->{onerror}->(node => $attr, type => 'in HTML:xml:lang',
107                               level => $self->{level}->{must});
108  ## TODO: Test data...  ## TODO: Test data...
109        }        }
110      },      },
# Line 98  our $AttrChecker = { Line 113  our $AttrChecker = {
113        my $value = $attr->value;        my $value = $attr->value;
114        if ($value =~ /[^\x{0000}-\x{10FFFF}]/) { ## ISSUE: Should we disallow noncharacters?        if ($value =~ /[^\x{0000}-\x{10FFFF}]/) { ## ISSUE: Should we disallow noncharacters?
115          $self->{onerror}->(node => $attr,          $self->{onerror}->(node => $attr,
116                             type => 'invalid attribute value');                             type => 'invalid attribute value',
117                               level => $self->{level}->{fact}, ## TODO: correct?
118                              );
119        }        }
120        ## NOTE: Conformance to URI standard is not checked since there is        ## NOTE: Conformance to URI standard is not checked since there is
121        ## no author requirement on conformance in the XML Base specification.        ## no author requirement on conformance in the XML Base specification.
# Line 111  our $AttrChecker = { Line 128  our $AttrChecker = {
128        $value =~ s/\x20$//;        $value =~ s/\x20$//;
129        ## TODO: NCName in XML 1.0 or 1.1        ## TODO: NCName in XML 1.0 or 1.1
130        ## TODO: declared type is ID?        ## TODO: declared type is ID?
131        if ($self->{id}->{$value}) { ## NOTE: An xml:id error        if ($self->{id}->{$value}) {
132          $self->{onerror}->(node => $attr, level => 'error',          $self->{onerror}->(node => $attr,
133                             type => 'duplicate ID');                             type => 'duplicate ID',
134                               level => $self->{level}->{xml_id_error});
135          push @{$self->{id}->{$value}}, $attr;          push @{$self->{id}->{$value}}, $attr;
136        } else {        } else {
137          $self->{id}->{$value} = [$attr];          $self->{id}->{$value} = [$attr];
# Line 127  our $AttrChecker = { Line 145  our $AttrChecker = {
145        my $value = $attr->value;        my $value = $attr->value;
146        if ($value eq $XML_NS and $ln ne 'xml') {        if ($value eq $XML_NS and $ln ne 'xml') {
147          $self->{onerror}          $self->{onerror}
148            ->(node => $attr, level => 'NC',            ->(node => $attr,
149               type => 'Reserved Prefixes and Namespace Names:=xml');               type => 'Reserved Prefixes and Namespace Names:Name',
150                 text => $value,
151                 level => $self->{level}->{nc});
152        } elsif ($value eq $XMLNS_NS) {        } elsif ($value eq $XMLNS_NS) {
153          $self->{onerror}          $self->{onerror}
154            ->(node => $attr, level => 'NC',            ->(node => $attr,
155               type => 'Reserved Prefixes and Namespace Names:=xmlns');               type => 'Reserved Prefixes and Namespace Names:Name',
156                 text => $value,
157                 level => $self->{level}->{nc});
158        }        }
159        if ($ln eq 'xml' and $value ne $XML_NS) {        if ($ln eq 'xml' and $value ne $XML_NS) {
160          $self->{onerror}          $self->{onerror}
161            ->(node => $attr, level => 'NC',            ->(node => $attr,
162               type => 'Reserved Prefixes and Namespace Names:xmlns:xml=');               type => 'Reserved Prefixes and Namespace Names:Prefix',
163                 text => $ln,
164                 level => $self->{level}->{nc});
165        } elsif ($ln eq 'xmlns') {        } elsif ($ln eq 'xmlns') {
166          $self->{onerror}          $self->{onerror}
167            ->(node => $attr, level => 'NC',            ->(node => $attr,
168               type => 'Reserved Prefixes and Namespace Names:xmlns:xmlns=');               type => 'Reserved Prefixes and Namespace Names:Prefix',
169                 text => $ln,
170                 level => $self->{level}->{nc});
171        }        }
172        ## TODO: If XML 1.0 and empty        ## TODO: If XML 1.0 and empty
173      },      },
# Line 153  our $AttrChecker = { Line 179  our $AttrChecker = {
179        my $value = $attr->value;        my $value = $attr->value;
180        if ($value eq $XML_NS) {        if ($value eq $XML_NS) {
181          $self->{onerror}          $self->{onerror}
182            ->(node => $attr, level => 'NC',            ->(node => $attr,
183               type => 'Reserved Prefixes and Namespace Names:=xml');               type => 'Reserved Prefixes and Namespace Names:Name',
184                 text => $value,
185                 level => $self->{level}->{nc});
186        } elsif ($value eq $XMLNS_NS) {        } elsif ($value eq $XMLNS_NS) {
187          $self->{onerror}          $self->{onerror}
188            ->(node => $attr, level => 'NC',            ->(node => $attr,
189               type => 'Reserved Prefixes and Namespace Names:=xmlns');               type => 'Reserved Prefixes and Namespace Names:Name',
190                 text => $value,
191                 level => $self->{level}->{nc});
192        }        }
193      },      },
194    },    },
# Line 167  our $AttrChecker = { Line 197  our $AttrChecker = {
197  ## ISSUE: Should we really allow these attributes?  ## ISSUE: Should we really allow these attributes?
198  $AttrChecker->{''}->{'xml:space'} = $AttrChecker->{$XML_NS}->{space};  $AttrChecker->{''}->{'xml:space'} = $AttrChecker->{$XML_NS}->{space};
199  $AttrChecker->{''}->{'xml:lang'} = $AttrChecker->{$XML_NS}->{lang};  $AttrChecker->{''}->{'xml:lang'} = $AttrChecker->{$XML_NS}->{lang};
200        ## NOTE: Checker for (null, "xml:lang") attribute is shadowed for
201        ## HTML elements in Whatpm::ContentChecker::HTML.
202  $AttrChecker->{''}->{'xml:base'} = $AttrChecker->{$XML_NS}->{base};  $AttrChecker->{''}->{'xml:base'} = $AttrChecker->{$XML_NS}->{base};
203  $AttrChecker->{''}->{'xml:id'} = $AttrChecker->{$XML_NS}->{id};  $AttrChecker->{''}->{'xml:id'} = $AttrChecker->{$XML_NS}->{id};
204    
# Line 193  our %AnyChecker = ( Line 225  our %AnyChecker = (
225      my ($self, $item, $element_state) = @_;      my ($self, $item, $element_state) = @_;
226      for my $attr (@{$item->{node}->attributes}) {      for my $attr (@{$item->{node}->attributes}) {
227        my $attr_ns = $attr->namespace_uri;        my $attr_ns = $attr->namespace_uri;
228        $attr_ns = '' unless defined $attr_ns;        if (defined $attr_ns) {
229            load_ns_module ($attr_ns);
230          } else {
231            $attr_ns = '';
232          }
233        my $attr_ln = $attr->manakai_local_name;        my $attr_ln = $attr->manakai_local_name;
234                
       load_ns_module ($attr_ns);  
   
235        my $checker = $AttrChecker->{$attr_ns}->{$attr_ln}        my $checker = $AttrChecker->{$attr_ns}->{$attr_ln}
236            || $AttrChecker->{$attr_ns}->{''};            || $AttrChecker->{$attr_ns}->{''};
237        my $status = $AttrStatus->{$attr_ns}->{$attr_ln}        my $status = $AttrStatus->{$attr_ns}->{$attr_ln}
# Line 214  our %AnyChecker = ( Line 248  our %AnyChecker = (
248        if ($checker) {        if ($checker) {
249          $checker->($self, $attr);          $checker->($self, $attr);
250        } else {        } else {
251          $self->{onerror}->(node => $attr, level => 'unsupported',          $self->{onerror}->(node => $attr,
252                             type => 'attribute');                             type => 'unknown attribute',
253                               level => $self->{level}->{uncertain});
254        }        }
255        $self->_attr_status_info ($attr, $status);        $self->_attr_status_info ($attr, $status);
256      }      }
# Line 226  our %AnyChecker = ( Line 261  our %AnyChecker = (
261      if ($self->{minus_elements}->{$child_nsuri}->{$child_ln}) {      if ($self->{minus_elements}->{$child_nsuri}->{$child_ln}) {
262        $self->{onerror}->(node => $child_el,        $self->{onerror}->(node => $child_el,
263                           type => 'element not allowed:minus',                           type => 'element not allowed:minus',
264                           level => $self->{must_level});                           level => $self->{level}->{must});
265      } elsif ($self->{plus_elements}->{$child_nsuri}->{$child_ln}) {      } elsif ($self->{plus_elements}->{$child_nsuri}->{$child_ln}) {
266        #        #
267      } else {      } else {
# Line 236  our %AnyChecker = ( Line 271  our %AnyChecker = (
271    check_child_text => sub { },    check_child_text => sub { },
272    check_end => sub {    check_end => sub {
273      my ($self, $item, $element_state) = @_;      my ($self, $item, $element_state) = @_;
274        ## NOTE: There is a modified copy of the code below for |html:ruby|.
275      if ($element_state->{has_significant}) {      if ($element_state->{has_significant}) {
276        $item->{real_parent_state}->{has_significant} = 1;        $item->{real_parent_state}->{has_significant} = 1;
277      }          }    
# Line 248  our $ElementDefault = { Line 284  our $ElementDefault = {
284        ## NOTE: No "element not defined" error - it is not supported anyway.        ## NOTE: No "element not defined" error - it is not supported anyway.
285    check_start => sub {    check_start => sub {
286      my ($self, $item, $element_state) = @_;      my ($self, $item, $element_state) = @_;
287      $self->{onerror}->(node => $item->{node}, level => 'unsupported',      $self->{onerror}->(node => $item->{node},
288                         type => 'element');                         type => 'unknown element',
289                           level => $self->{level}->{uncertain});
290    },    },
291  };  };
292    
# Line 265  our $HTMLEmbeddedContent = { Line 302  our $HTMLEmbeddedContent = {
302    ## embedded content.    ## embedded content.
303  };    };  
304    
305    our $IsInHTMLInteractiveContent = sub {
306      my ($el, $nsuri, $ln) = @_;
307    
308      ## NOTE: This CODE returns whether an element that is conditionally
309      ## categorizzed as an interactive content is currently in that
310      ## condition or not.  See $HTMLInteractiveContent list defined in
311      ## Whatpm::ContentChecler::HTML for the list of all (conditionally
312      ## or permanently) interactive content.
313    
314      if ($nsuri eq $HTML_NS and ($ln eq 'video' or $ln eq 'audio')) {
315        return $el->has_attribute ('controls');
316      } elsif ($nsuri eq $HTML_NS and $ln eq 'menu') {
317        my $value = $el->get_attribute ('type');
318        $value =~ tr/A-Z/a-z/; # ASCII case-insensitive
319        return ($value eq 'toolbar');
320      } else {
321        return 1;
322      }
323    }; # $IsInHTMLInteractiveContent
324    
325  my $HTMLTransparentElements = {  my $HTMLTransparentElements = {
326    $HTML_NS => {qw/ins 1 del 1 font 1 noscript 1 canvas 1/},    $HTML_NS => {qw/ins 1 del 1 font 1 noscript 1 canvas 1 a 1/},
327    ## NOTE: |html:noscript| is transparent if scripting is disabled    ## NOTE: |html:noscript| is transparent if scripting is disabled
328    ## and not in |head|.    ## and not in |head|.
329  };  };
# Line 289  $Element->{q<http://www.w3.org/1999/02/2 Line 346  $Element->{q<http://www.w3.org/1999/02/2
346      my $rdf = Whatpm::RDFXML->new;      my $rdf = Whatpm::RDFXML->new;
347      ## TODO: Should we make bnodeid unique in a document?      ## TODO: Should we make bnodeid unique in a document?
348      $rdf->{onerror} = $self->{onerror};      $rdf->{onerror} = $self->{onerror};
349        $rdf->{level} = $self->{level};
350      $rdf->{ontriple} = sub {      $rdf->{ontriple} = sub {
351        my %opt = @_;        my %opt = @_;
352        push @$triple,        push @$triple,
# Line 320  $Element->{q<http://www.w3.org/1999/02/2 Line 378  $Element->{q<http://www.w3.org/1999/02/2
378    },    },
379  };  };
380    
381    my $default_error_level = {
382      must => 'm',
383      should => 's',
384      warn => 'w',
385      good => 'w',
386      undefined => 'w',
387      info => 'i',
388    
389      uncertain => 'u',
390    
391      html4_fact => 'm',
392      html5_no_may => 'm',
393    
394      xml_error => 'm', ## TODO: correct?
395      xml_id_error => 'm', ## TODO: ?
396      nc => 'm', ## XML Namespace Constraints ## TODO: correct?
397    
398      ## |Whatpm::URIChecker|
399      uri_syntax => 'm',
400      uri_fact => 'm',
401      uri_lc_must => 'm',
402      uri_lc_should => 'w',
403    
404      ## |Whatpm::IMTChecker|
405      mime_must => 'm', # lowercase "must"
406      mime_fact => 'm',
407      mime_strongly_discouraged => 'w',
408      mime_discouraged => 'w',
409    
410      ## |Whatpm::LangTag|
411      langtag_fact => 'm',
412    
413      ## |Whatpm::RDFXML|
414      rdf_fact => 'm',
415      rdf_grammer => 'm',
416      rdf_lc_must => 'm',
417    
418      ## |Message::Charset::Info| and |Whatpm::Charset::DecodeHandle|
419      charset_variant => 'm',
420        ## An error caused by use of a variant charset that is not conforming
421        ## to the original charset (e.g. use of 0x80 in an ISO-8859-1 document
422        ## which is interpreted as a Windows-1252 document instead).
423      charset_fact => 'm',
424      iso_shall => 'm',
425    };
426    
427  sub check_document ($$$;$) {  sub check_document ($$$;$) {
428    my ($self, $doc, $onerror, $onsubdoc) = @_;    my ($self, $doc, $onerror, $onsubdoc) = @_;
429    $self = bless {}, $self unless ref $self;    $self = bless {}, $self unless ref $self;
# Line 328  sub check_document ($$$;$) { Line 432  sub check_document ($$$;$) {
432      warn "A subdocument is not conformance-checked";      warn "A subdocument is not conformance-checked";
433    };    };
434    
435    $self->{must_level} = 'm';    $self->{level} ||= $default_error_level;
   $self->{fact_level} = 'm';  
   $self->{should_level} = 's';  
   $self->{good_level} = 'w';  
   $self->{info_level} = 'i';  
   $self->{unsupported_level} = 'u';  
436    
437    ## TODO: If application/rdf+xml, RDF/XML mode should be invoked.    ## TODO: If application/rdf+xml, RDF/XML mode should be invoked.
438    
439    my $docel = $doc->document_element;    my $docel = $doc->document_element;
440    unless (defined $docel) {    unless (defined $docel) {
441      ## ISSUE: Should we check content of Document node?      ## ISSUE: Should we check content of Document node?
442      $onerror->(node => $doc, type => 'no document element');      $onerror->(node => $doc, type => 'no document element',
443                   level => $self->{level}->{must});
444      ## ISSUE: Is this non-conforming (to what spec)?  Or just a warning?      ## ISSUE: Is this non-conforming (to what spec)?  Or just a warning?
445      return {      return {
446              class => {},              class => {},
# Line 351  sub check_document ($$$;$) { Line 451  sub check_document ($$$;$) {
451    ## ISSUE: Unexpanded entity references and HTML5 conformance    ## ISSUE: Unexpanded entity references and HTML5 conformance
452        
453    my $docel_nsuri = $docel->namespace_uri;    my $docel_nsuri = $docel->namespace_uri;
454    $docel_nsuri = '' unless defined $docel_nsuri;    if (defined $docel_nsuri) {
455    load_ns_module ($docel_nsuri);      load_ns_module ($docel_nsuri);
456      } else {
457        $docel_nsuri = '';
458      }
459    my $docel_def = $Element->{$docel_nsuri}->{$docel->manakai_local_name} ||    my $docel_def = $Element->{$docel_nsuri}->{$docel->manakai_local_name} ||
460      $Element->{$docel_nsuri}->{''} ||      $Element->{$docel_nsuri}->{''} ||
461      $ElementDefault;      $ElementDefault;
# Line 362  sub check_document ($$$;$) { Line 465  sub check_document ($$$;$) {
465      unless ($doc->manakai_is_html) {      unless ($doc->manakai_is_html) {
466        #        #
467      } else {      } else {
468        $onerror->(node => $docel, type => 'element not allowed:root:xml');        $onerror->(node => $docel, type => 'element not allowed:root:xml',
469                     level => $self->{level}->{must});
470      }      }
471    } else {    } else {
472      $onerror->(node => $docel, type => 'element not allowed:root');      $onerror->(node => $docel, type => 'element not allowed:root',
473                   level => $self->{level}->{must});
474    }    }
475    
476    ## TODO: Check for other items other than document element    ## TODO: Check for other items other than document element
# Line 383  sub check_document ($$$;$) { Line 488  sub check_document ($$$;$) {
488        if (not $doc->manakai_has_bom and        if (not $doc->manakai_has_bom and
489            not defined $doc->manakai_charset) {            not defined $doc->manakai_charset) {
490          unless ($charset->{is_html_ascii_superset}) {          unless ($charset->{is_html_ascii_superset}) {
491            $onerror->(node => $doc, level => $self->{must_level},            $onerror->(node => $doc,
492                       type => 'non ascii superset:'.$charset_name);                       level => $self->{level}->{must},
493                         type => 'non ascii superset',
494                         text => $charset_name);
495          }          }
496                    
497          if (not $self->{has_charset} and ## TODO: This does not work now.          if (not $self->{has_charset} and ## TODO: This does not work now.
498              not $charset->{iana_names}->{'us-ascii'}) {              not $charset->{iana_names}->{'us-ascii'}) {
499            $onerror->(node => $doc, level => $self->{must_level},            $onerror->(node => $doc,
500                       type => 'no character encoding declaration:'.$charset_name);                       level => $self->{level}->{must},
501                         type => 'no character encoding declaration',
502                         text => $charset_name);
503          }          }
504        }        }
505    
# Line 399  sub check_document ($$$;$) { Line 508  sub check_document ($$$;$) {
508        } elsif ($charset->{iana_names}->{'jis_x0212-1990'} or        } elsif ($charset->{iana_names}->{'jis_x0212-1990'} or
509                 $charset->{iana_names}->{'x-jis0208'} or                 $charset->{iana_names}->{'x-jis0208'} or
510                 $charset->{iana_names}->{'utf-32'} or ## ISSUE: UTF-32BE? UTF-32LE?                 $charset->{iana_names}->{'utf-32'} or ## ISSUE: UTF-32BE? UTF-32LE?
511                 $charset->{is_ebcdic_based}) {                 ($charset->{category} & Message::Charset::Info::CHARSET_CATEGORY_EBCDIC ())) {
512          $onerror->(node => $doc,          $onerror->(node => $doc,
513                     type => 'character encoding:'.$charset_name,                     type => 'bad character encoding',
514                     level => $self->{should_level});                     text => $charset_name,
515                       level => $self->{level}->{should},
516                       layer => 'encode');
517        } elsif ($charset->{iana_names}->{'cesu-8'} or        } elsif ($charset->{iana_names}->{'cesu-8'} or
518                 $charset->{iana_names}->{'utf-8'} or ## ISSUE: UNICODE-1-1-UTF-7?                 $charset->{iana_names}->{'utf-8'} or ## ISSUE: UNICODE-1-1-UTF-7?
519                 $charset->{iana_names}->{'bocu-1'} or                 $charset->{iana_names}->{'bocu-1'} or
520                 $charset->{iana_names}->{'scsu'}) {                 $charset->{iana_names}->{'scsu'}) {
521          $onerror->(node => $doc,          $onerror->(node => $doc,
522                     type => 'character encoding:'.$charset_name,                     type => 'disallowed character encoding',
523                     level => $self->{must_level});                     text => $charset_name,
524                       level => $self->{level}->{must},
525                       layer => 'encode');
526        } else {        } else {
527          $onerror->(node => $doc,          $onerror->(node => $doc,
528                     type => 'character encoding:'.$charset_name,                     type => 'non-utf-8 character encoding',
529                     level => $self->{good_level});                     text => $charset_name,
530                       level => $self->{level}->{good},
531                       layer => 'encode');
532        }        }
533      }      }
534    } elsif ($doc->manakai_is_html) {    } elsif ($doc->manakai_is_html) {
535      ## NOTE: MUST and SHOULD requirements above cannot be tested,      ## NOTE: MUST and SHOULD requirements above cannot be tested,
536      ## since the document has no input charset encoding information.      ## since the document has no input charset encoding information.
537      $onerror->(node => $doc,      $onerror->(node => $doc,
538                 type => 'character encoding:',                 type => 'character encoding unchecked',
539                 level => 'unsupported');                 level => $self->{level}->{info},
540                   layer => 'encode');
541    }    }
542    
543    return $return;    return $return;
# Line 437  sub check_element ($$$;$) { Line 553  sub check_element ($$$;$) {
553      warn "A subdocument is not conformance-checked";      warn "A subdocument is not conformance-checked";
554    };    };
555    
556    $self->{must_level} = 'm';    $self->{level} ||= $default_error_level;
   $self->{fact_level} = 'm';  
   $self->{should_level} = 's';  
   $self->{good_level} = 'w';  
   $self->{info_level} = 'i';  
   $self->{unsupported_level} = 'u';  
557    
558    $self->{plus_elements} = {};    $self->{plus_elements} = {};
559    $self->{minus_elements} = {};    $self->{minus_elements} = {};
560    $self->{id} = {};    $self->{id} = {};
561      $self->{form} = {};
562    $self->{term} = {};    $self->{term} = {};
563    $self->{usemap} = [];    $self->{usemap} = [];
564    $self->{ref} = []; # datetemplate data references    $self->{ref} = []; # datetemplate data references
# Line 480  next unless $code;## TODO: temp. Line 592  next unless $code;## TODO: temp.
592        $code->(@$item);        $code->(@$item);
593      } elsif ($item->{type} eq 'element') {      } elsif ($item->{type} eq 'element') {
594        my $el_nsuri = $item->{node}->namespace_uri;        my $el_nsuri = $item->{node}->namespace_uri;
595        $el_nsuri = '' unless defined $el_nsuri;        if (defined $el_nsuri) {
596            load_ns_module ($el_nsuri);
597          } else {
598            $el_nsuri = '';
599          }
600        my $el_ln = $item->{node}->manakai_local_name;        my $el_ln = $item->{node}->manakai_local_name;
601          
       load_ns_module ($el_nsuri);  
   
602        my $element_state = {};        my $element_state = {};
603        my $eldef = $Element->{$el_nsuri}->{$el_ln} ||        my $eldef = $Element->{$el_nsuri}->{$el_ln} ||
604            $Element->{$el_nsuri}->{''} ||            $Element->{$el_nsuri}->{''} ||
# Line 502  next unless $code;## TODO: temp. Line 616  next unless $code;## TODO: temp.
616              $eldef->{status} & FEATURE_STATUS_WD ? 'wd' : 'non-standard';              $eldef->{status} & FEATURE_STATUS_WD ? 'wd' : 'non-standard';
617          $self->{onerror}->(node => $item->{node},          $self->{onerror}->(node => $item->{node},
618                             type => 'status:'.$status.':element',                             type => 'status:'.$status.':element',
619                             level => $self->{info_level});                             level => $self->{level}->{info});
620        }        }
621        if (not ($eldef->{status} & FEATURE_ALLOWED)) {        if (not ($eldef->{status} & FEATURE_ALLOWED)) {
622          $self->{onerror}->(node => $item->{node},          $self->{onerror}->(node => $item->{node},
623                             type => 'element not defined',                             type => 'element not defined',
624                             level => $self->{must_level});                             level => $self->{level}->{must});
625        } elsif ($eldef->{status} & FEATURE_DEPRECATED_SHOULD) {        } elsif ($eldef->{status} & FEATURE_DEPRECATED_SHOULD) {
626          $self->{onerror}->(node => $item->{node},          $self->{onerror}->(node => $item->{node},
627                             type => 'deprecated:element',                             type => 'deprecated:element',
628                             level => $self->{should_level});                             level => $self->{level}->{should});
629        } elsif ($eldef->{status} & FEATURE_DEPRECATED_INFO) {        } elsif ($eldef->{status} & FEATURE_DEPRECATED_INFO) {
630          $self->{onerror}->(node => $item->{node},          $self->{onerror}->(node => $item->{node},
631                             type => 'deprecated:element',                             type => 'deprecated:element',
632                             level => $self->{info_level});                             level => $self->{level}->{info});
633        }        }
634    
635        my @new_item;        my @new_item;
# Line 584  next unless $code;## TODO: temp. Line 698  next unless $code;## TODO: temp.
698            }            }
699          } elsif ($child_nt == 3 or # TEXT_NODE          } elsif ($child_nt == 3 or # TEXT_NODE
700                   $child_nt == 4) { # CDATA_SECTION_NODE                   $child_nt == 4) { # CDATA_SECTION_NODE
701            my $has_significant = ($child->data =~ /[^\x09-\x0D\x20]/);            my $has_significant = ($child->data =~ /[^\x09\x0A\x0C\x0D\x20]/);
702            push @new_item, [$content_def->{check_child_text},            push @new_item, [$content_def->{check_child_text},
703                             $self, $item, $child, $has_significant,                             $self, $item, $child, $has_significant,
704                             $content_state, $element_state];                             $content_state, $element_state];
# Line 622  next unless $code;## TODO: temp. Line 736  next unless $code;## TODO: temp.
736              if ($el eq $_->[1]->owner_element) {              if ($el eq $_->[1]->owner_element) {
737                $self->{onerror}->(node => $_->[1],                $self->{onerror}->(node => $_->[1],
738                                   type => 'fragment points itself',                                   type => 'fragment points itself',
739                                   level => $self->{must_level});                                   level => $self->{level}->{must});
740              }              }
741                            
742              last F;              last F;
# Line 633  next unless $code;## TODO: temp. Line 747  next unless $code;## TODO: temp.
747        ## if the fragment identifier identifies no element?        ## if the fragment identifier identifies no element?
748    
749        $self->{onerror}->(node => $_->[1], type => 'template:not template',        $self->{onerror}->(node => $_->[1], type => 'template:not template',
750                           level => $self->{must_level});                           level => $self->{level}->{must});
751      } # F      } # F
752    }    }
753        
# Line 646  next unless $code;## TODO: temp. Line 760  next unless $code;## TODO: temp.
760        if ($self->{id}->{$_->[0]}->[0]->owner_element        if ($self->{id}->{$_->[0]}->[0]->owner_element
761                eq $_->[1]->owner_element) {                eq $_->[1]->owner_element) {
762          $self->{onerror}->(node => $_->[1], type => 'fragment points itself',          $self->{onerror}->(node => $_->[1], type => 'fragment points itself',
763                             level => $self->{must_level});                             level => $self->{level}->{must});
764        }        }
765      } else {      } else {
766        $self->{onerror}->(node => $_->[1], type => 'fragment points nothing',        $self->{onerror}->(node => $_->[1], type => 'fragment points nothing',
767                           level => $self->{must_level});                           level => $self->{level}->{must});
768      }      }
769    }    }
770    
# Line 658  next unless $code;## TODO: temp. Line 772  next unless $code;## TODO: temp.
772    
773    for (@{$self->{usemap}}) {    for (@{$self->{usemap}}) {
774      unless ($self->{map}->{$_->[0]}) {      unless ($self->{map}->{$_->[0]}) {
775        $self->{onerror}->(node => $_->[1], type => 'no referenced map');        $self->{onerror}->(node => $_->[1], type => 'no referenced map',
776                             level => $self->{level}->{must});
777      }      }
778    }    }
779    
780    for (@{$self->{contextmenu}}) {    for (@{$self->{contextmenu}}) {
781      unless ($self->{menu}->{$_->[0]}) {      unless ($self->{menu}->{$_->[0]}) {
782        $self->{onerror}->(node => $_->[1], type => 'no referenced menu');        $self->{onerror}->(node => $_->[1], type => 'no referenced menu',
783                             level => $self->{level}->{must});
784      }      }
785    }    }
786    
# Line 672  next unless $code;## TODO: temp. Line 788  next unless $code;## TODO: temp.
788    delete $self->{minus_elements};    delete $self->{minus_elements};
789    delete $self->{onerror};    delete $self->{onerror};
790    delete $self->{id};    delete $self->{id};
791      delete $self->{form};
792    delete $self->{usemap};    delete $self->{usemap};
793    delete $self->{ref};    delete $self->{ref};
794    delete $self->{template};    delete $self->{template};
# Line 735  sub _attr_status_info ($$$) { Line 852  sub _attr_status_info ($$$) {
852    if (not ($status_code & FEATURE_ALLOWED)) {    if (not ($status_code & FEATURE_ALLOWED)) {
853      $self->{onerror}->(node => $attr,      $self->{onerror}->(node => $attr,
854                         type => 'attribute not defined',                         type => 'attribute not defined',
855                         level => $self->{must_level});                         level => $self->{level}->{must});
856    } elsif ($status_code & FEATURE_DEPRECATED_SHOULD) {    } elsif ($status_code & FEATURE_DEPRECATED_SHOULD) {
857      $self->{onerror}->(node => $attr,      $self->{onerror}->(node => $attr,
858                         type => 'deprecated:attr',                         type => 'deprecated:attr',
859                         level => $self->{should_level});                         level => $self->{level}->{should});
860    } elsif ($status_code & FEATURE_DEPRECATED_INFO) {    } elsif ($status_code & FEATURE_DEPRECATED_INFO) {
861      $self->{onerror}->(node => $attr,      $self->{onerror}->(node => $attr,
862                         type => 'deprecated:attr',                         type => 'deprecated:attr',
863                         level => $self->{info_level});                         level => $self->{level}->{info});
864    }    }
865    
866    my $status;    my $status;
# Line 760  sub _attr_status_info ($$$) { Line 877  sub _attr_status_info ($$$) {
877    }    }
878    $self->{onerror}->(node => $attr,    $self->{onerror}->(node => $attr,
879                       type => 'status:'.$status.':attr',                       type => 'status:'.$status.':attr',
880                       level => $self->{info_level});                       level => $self->{level}->{info});
881  } # _attr_status_info  } # _attr_status_info
882    
883  sub _add_minuses ($@) {  sub _add_minuses ($@) {
# Line 875  sub _check_get_children ($$$) { Line 992  sub _check_get_children ($$$) {
992                last CN;                last CN;
993              }              }
994            } elsif ($cnt == 3 or $cnt == 4) {            } elsif ($cnt == 3 or $cnt == 4) {
995              if ($cn->data =~ /[^\x09-\x0D\x20]/) {              if ($cn->data =~ /[^\x09\x0A\x0C\x0D\x20]/) {
996                last CN;                last CN;
997              }              }
998            }            }
# Line 896  sub _check_get_children ($$$) { Line 1013  sub _check_get_children ($$$) {
1013              last CN;              last CN;
1014            }            }
1015          } elsif ($cnt == 3 or $cnt == 4) {          } elsif ($cnt == 3 or $cnt == 4) {
1016            if ($cn->data =~ /[^\x09-\x0D\x20]/) {            if ($cn->data =~ /[^\x09\x0A\x0C\x0D\x20]/) {
1017              last CN;              last CN;
1018            }            }
1019          }          }

Legend:
Removed from v.1.81  
changed lines
  Added in v.1.97

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24