package HTML::Valid::Tagset;
use parent Exporter;
our @EXPORT_OK = qw/
    %boolean_attr
    %canTighten
    %emptyElement
    %isBlock
    %isBodyElement
    %isCDATA_Parent
    %isFormElement
    %isHTML2
    %isHTML3
    %isHTML4
    %isHTML5
    %isHeadElement
    %isHeadOrBodyElement
    %isInline
    %isKnown
    %isList
    %isObsolete
    %isPhraseMarkup
    %isProprietary
    %isTableElement
    %is_Possible_Strict_P_Content
    %linkElements
    %optionalEndTag
    @allTags
    @p_closure_barriers
    test_taginfo
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);
use warnings;
use strict;
use utf8;
use HTML::Valid;

our $VERSION=$HTML::Valid::VERSION;

use vars qw(
    $VERSION
);

use constant {
# Rejected #define __LEXER_H__
# Rejected #define digit       1u
# Rejected #define letter      2u
# Rejected #define namechar    4u
# Rejected #define white       8u
# Rejected #define newline     16u
# Rejected #define lowercase   32u
# Rejected #define uppercase   64u
# Rejected #define digithex    128u
# Rejected #define CM_UNKNOWN      0
CM_EMPTY => (1 << 0),
CM_HTML => (1 << 1),
CM_HEAD => (1 << 2),
CM_BLOCK => (1 << 3),
CM_INLINE => (1 << 4),
CM_LIST => (1 << 5),
CM_DEFLIST => (1 << 6),
CM_TABLE => (1 << 7),
CM_ROWGRP => (1 << 8),
CM_ROW => (1 << 9),
CM_FIELD => (1 << 10),
CM_OBJECT => (1 << 11),
CM_PARAM => (1 << 12),
CM_FRAMES => (1 << 13),
CM_HEADING => (1 << 14),
CM_OPT => (1 << 15),
CM_IMG => (1 << 16),
CM_MIXED => (1 << 17),
CM_NO_INDENT => (1 << 18),
CM_OBSOLETE => (1 << 19),
CM_NEW => (1 << 20),
CM_OMITST => (1 << 21),
# Rejected #define xxxx                   0u
HT20 => 1,
HT32 => 2,
H40S => 4,
H40T => 8,
H40F => 16,
H41S => 32,
H41T => 64,
H41F => 128,
X10S => 256,
X10T => 512,
X10F => 1024,
XH11 => 2048,
XB10 => 4096,
VERS_SUN => 8192,
VERS_NETSCAPE => 16384,
VERS_MICROSOFT => 32768,
VERS_XML => 65536,
HT50 => 131072,
XH50 => 262144,
# Rejected #define VERS_UNKNOWN       (xxxx)
VERS_HTML20 => (1),
VERS_HTML32 => (2),
VERS_HTML40_STRICT => (4|32|256),
VERS_HTML40_LOOSE => (8|64|512),
VERS_FRAMESET => (16|128|1024),
VERS_XHTML11 => (2048),
VERS_BASIC => (4096),
VERS_HTML5 => (131072|262144),
VERS_HTML40 => ((4|32|256)|(8|64|512)|(16|128|1024)),
VERS_IFRAME => ((8|64|512)|(16|128|1024)),
VERS_LOOSE => ((1)|(2)|((8|64|512)|(16|128|1024))),
VERS_EVENTS => (((4|32|256)|(8|64|512)|(16|128|1024))|(2048)),
VERS_FROM32 => ((2)|((4|32|256)|(8|64|512)|(16|128|1024))),
VERS_FROM40 => (((4|32|256)|(8|64|512)|(16|128|1024))|(2048)|(4096)),
VERS_XHTML => (256|512|1024|2048|4096|262144),
VERS_ALL => ((1)|(2)|(((4|32|256)|(8|64|512)|(16|128|1024))|(2048)|(4096))|262144|131072),
VERS_PROPRIETARY => (16384|32768|8192),
};

my $taginfo = HTML::Valid::tag_information ();

our @allTags = sort keys %$taginfo;

our %emptyElement;
our %optionalEndTag;
our %linkElements;
our %boolean_attr;
our %isHeadElement;
our %isBodyElement;
our %isPhraseMarkup;
our %isProprietary;
our %isHeadOrBodyElement;
our %isList;
our %isTableElement;
our %isFormElement;
our %isKnown;
our %canTighten;
our %isHTML5;
our %isHTML4;
our %isHTML3;
our %isHTML2;
our %isObsolete;
our %isInline;
our %isBlock;

for my $tag (@allTags) {
    $isKnown{$tag} = 1;
    my $ti = $taginfo->{$tag};
    my $versions = $ti->[0];
    my $model = $ti->[1];
    if ($model & CM_EMPTY) {
	$emptyElement{$tag} = 1;
    }
    if ($model & CM_OPT) {
	$optionalEndTag{$tag} = 1;
    }
    if ($model & CM_FIELD) {
	$isFormElement{$tag} = 1;
    }
    # See tidy-html5.c
    if ($model & (CM_TABLE|CM_ROWGRP|CM_ROW)) {
	$isTableElement{$tag} = 1;
    }
    if ($model & CM_HEAD) {
	$isHeadElement{$tag} = 1;
	if ($model & ~CM_HEAD) {
	    $isHeadOrBodyElement{$tag} = 1;
	    $isBodyElement{$tag} = 1;
	}
    }
    else {
	$isBodyElement{$tag} = 1;
    }
    if ($model & CM_OBSOLETE) {
	$isObsolete{$tag} = 1;
    }
    if ($model & CM_INLINE) {
	$isPhraseMarkup{$tag} = 1;
	$isInline{$tag} = 1;
    }
    if ($versions & VERS_HTML5) {
	$isHTML5{$tag} = 1;
    }
    if ($versions & VERS_HTML40) {
	$isHTML4{$tag} = 1;
    }
    if ($versions & VERS_HTML32) {
	$isHTML3{$tag} = 1;
    }
    if ($versions & VERS_HTML20) {
	$isHTML2{$tag} = 1;
    }
    if ($versions & VERS_PROPRIETARY) {
	$isProprietary{$tag} = 1;
    }
}


# Start of compatibility with HTML::Tagset

@isFormElement{qw/input button label/} = (1)x3;

# Does not exist in tidy-html classifications.

%isList         = map {; $_ => 1 } qw(ul ol dir menu);

%canTighten = %isKnown;
delete @canTighten{
  keys(%isPhraseMarkup), 'input', 'select',
  'xmp', 'listing', 'plaintext', 'pre',
};

# End of compatibility with HTML::Tagset

# @p_closure_barriers is a conceptual error in HTML::Tagset, see the
# documentation under "Issues with HTML::Tagset".

our @p_closure_barriers = ();

# %isCDATA_Parent is a conceptual error in HTML::Tagset, see the
# documentation under "Issues with HTML::Tagset".

our %isCDATA_Parent = %isKnown;

# %is_Possible_Strict_P_Content is just the inline elements, the
# content of HTML::Tagset makes absolutely no sense here and is
# contradictory to the specification it claims to be based on.

our %is_Possible_Strict_P_Content = %isInline;

# Private routine, for testing we got the tag info.

sub test_taginfo
{
    my ($tag) = @_;
    return $taginfo->{$tag};
}

1;
