package cascadia

import (
	
	
	
	

	
)
Matcher is the interface for basic selector functionality. Match returns whether a selector matches n.
type Matcher interface {
	Match(n *html.Node) bool
}
Sel is the interface for all the functionality provided by selectors. It is currently the same as Matcher, but other methods may be added in the future.
type Sel interface {
	Matcher
	Specificity() Specificity
}
Parse parses a selector.
func ( string) (Sel, error) {
	 := &parser{s: }
	,  := .parseSelector()
	if  != nil {
		return nil, 
	}

	if .i < len() {
		return nil, fmt.Errorf("parsing %q: %d bytes left over", , len()-.i)
	}

	return , nil
}
ParseGroup parses a selector, or a group of selectors separated by commas.
func ( string) (SelectorGroup, error) {
	 := &parser{s: }
	,  := .parseSelectorGroup()
	if  != nil {
		return nil, 
	}

	if .i < len() {
		return nil, fmt.Errorf("parsing %q: %d bytes left over", , len()-.i)
	}

	return , nil
}
A Selector is a function which tells whether a node matches or not. This type is maintained for compatibility; I recommend using the newer and more idiomatic interfaces Sel and Matcher.
type Selector func(*html.Node) bool
Compile parses a selector and returns, if successful, a Selector object that can be used to match against html.Node objects.
func ( string) (Selector, error) {
	,  := ParseGroup()
	if  != nil {
		return nil, 
	}

	return Selector(.Match), nil
}
MustCompile is like Compile, but panics instead of returning an error.
func ( string) Selector {
	,  := Compile()
	if  != nil {
		panic()
	}
	return 
}
MatchAll returns a slice of the nodes that match the selector, from n and its children.
func ( Selector) ( *html.Node) []*html.Node {
	return .matchAllInto(, nil)
}

func ( Selector) ( *html.Node,  []*html.Node) []*html.Node {
	if () {
		 = append(, )
	}

	for  := .FirstChild;  != nil;  = .NextSibling {
		 = .(, )
	}

	return 
}

func ( *html.Node,  Matcher,  []*html.Node) []*html.Node {
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Match() {
			 = append(, )
		}
		 = (, , )
	}

	return 
}
QueryAll returns a slice of all the nodes that match m, from the descendants of n.
func ( *html.Node,  Matcher) []*html.Node {
	return queryInto(, , nil)
}
Match returns true if the node matches the selector.
func ( Selector) ( *html.Node) bool {
	return ()
}
MatchFirst returns the first node that matches s, from n and its children.
func ( Selector) ( *html.Node) *html.Node {
	if .Match() {
		return 
	}

	for  := .FirstChild;  != nil;  = .NextSibling {
		 := .()
		if  != nil {
			return 
		}
	}
	return nil
}
Query returns the first node that matches m, from the descendants of n. If none matches, it returns nil.
func ( *html.Node,  Matcher) *html.Node {
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Match() {
			return 
		}
		if  := (, );  != nil {
			return 
		}
	}

	return nil
}
Filter returns the nodes in nodes that match the selector.
func ( Selector) ( []*html.Node) ( []*html.Node) {
	for ,  := range  {
		if () {
			 = append(, )
		}
	}
	return 
}
Filter returns the nodes that match m.
func ( []*html.Node,  Matcher) ( []*html.Node) {
	for ,  := range  {
		if .Match() {
			 = append(, )
		}
	}
	return 
}

type tagSelector struct {
	tag string
}
Matches elements with a given tag name.
func ( tagSelector) ( *html.Node) bool {
	return .Type == html.ElementNode && .Data == .tag
}

func ( tagSelector) () Specificity {
	return Specificity{0, 0, 1}
}

type classSelector struct {
	class string
}
Matches elements by class attribute.
func ( classSelector) ( *html.Node) bool {
	return matchAttribute(, "class", func( string) bool {
		return matchInclude(.class, )
	})
}

func ( classSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type idSelector struct {
	id string
}
Matches elements by id attribute.
func ( idSelector) ( *html.Node) bool {
	return matchAttribute(, "id", func( string) bool {
		return  == .id
	})
}

func ( idSelector) () Specificity {
	return Specificity{1, 0, 0}
}

type attrSelector struct {
	key, val, operation string
	regexp              *regexp.Regexp
}
Matches elements by attribute value.
func ( attrSelector) ( *html.Node) bool {
	switch .operation {
	case "":
		return matchAttribute(, .key, func(string) bool { return true })
	case "=":
		return matchAttribute(, .key, func( string) bool { return  == .val })
	case "!=":
		return attributeNotEqualMatch(.key, .val, )
matches elements where the attribute named key is a whitespace-separated list that includes val.
		return matchAttribute(, .key, func( string) bool { return matchInclude(.val, ) })
	case "|=":
		return attributeDashMatch(.key, .val, )
	case "^=":
		return attributePrefixMatch(.key, .val, )
	case "$=":
		return attributeSuffixMatch(.key, .val, )
	case "*=":
		return attributeSubstringMatch(.key, .val, )
	case "#=":
		return attributeRegexMatch(.key, .regexp, )
	default:
		panic(fmt.Sprintf("unsuported operation : %s", .operation))
	}
}
matches elements where the attribute named key satisifes the function f.
func ( *html.Node,  string,  func(string) bool) bool {
	if .Type != html.ElementNode {
		return false
	}
	for ,  := range .Attr {
		if .Key ==  && (.Val) {
			return true
		}
	}
	return false
}
attributeNotEqualMatch matches elements where the attribute named key does not have the value val.
func (,  string,  *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}
	for ,  := range .Attr {
		if .Key ==  && .Val ==  {
			return false
		}
	}
	return true
}
returns true if s is a whitespace-separated list that includes val.
func (,  string) bool {
	for  != "" {
		 := strings.IndexAny(, " \t\r\n\f")
		if  == -1 {
			return  == 
		}
		if [:] ==  {
			return true
		}
		 = [+1:]
	}
	return false
}
matches elements where the attribute named key equals val or starts with val plus a hyphen.
func (,  string,  *html.Node) bool {
	return matchAttribute(, ,
		func( string) bool {
			if  ==  {
				return true
			}
			if len() <= len() {
				return false
			}
			if [:len()] ==  && [len()] == '-' {
				return true
			}
			return false
		})
}
attributePrefixMatch returns a Selector that matches elements where the attribute named key starts with val.
func (,  string,  *html.Node) bool {
	return matchAttribute(, ,
		func( string) bool {
			if strings.TrimSpace() == "" {
				return false
			}
			return strings.HasPrefix(, )
		})
}
attributeSuffixMatch matches elements where the attribute named key ends with val.
func (,  string,  *html.Node) bool {
	return matchAttribute(, ,
		func( string) bool {
			if strings.TrimSpace() == "" {
				return false
			}
			return strings.HasSuffix(, )
		})
}
attributeSubstringMatch matches nodes where the attribute named key contains val.
func (,  string,  *html.Node) bool {
	return matchAttribute(, ,
		func( string) bool {
			if strings.TrimSpace() == "" {
				return false
			}
			return strings.Contains(, )
		})
}
attributeRegexMatch matches nodes where the attribute named key matches the regular expression rx
func ( string,  *regexp.Regexp,  *html.Node) bool {
	return matchAttribute(, ,
		func( string) bool {
			return .MatchString()
		})
}

func ( attrSelector) () Specificity {
	return Specificity{0, 1, 0}
}
---------------- Pseudo class selectors ---------------- we use severals concrete types of pseudo-class selectors

type relativePseudoClassSelector struct {
	name  string // one of "not", "has", "haschild"
	match SelectorGroup
}

func ( relativePseudoClassSelector) ( *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}
	switch .name {
matches elements that do not match a.
		return !.match.Match()
matches elements with any descendant that matches a.
		return hasDescendantMatch(, .match)
matches elements with a child that matches a.
		return hasChildMatch(, .match)
	default:
		panic(fmt.Sprintf("unsupported relative pseudo class selector : %s", .name))
	}
}
hasChildMatch returns whether n has any child that matches a.
func ( *html.Node,  Matcher) bool {
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Match() {
			return true
		}
	}
	return false
}
hasDescendantMatch performs a depth-first search of n's descendants, testing whether any of them match a. It returns true as soon as a match is found, or false if no match is found.
func ( *html.Node,  Matcher) bool {
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Match() || (.Type == html.ElementNode && (, )) {
			return true
		}
	}
	return false
}
Specificity returns the specificity of the most specific selectors in the pseudo-class arguments. See https://www.w3.org/TR/selectors/#specificity-rules
func ( relativePseudoClassSelector) () Specificity {
	var  Specificity
	for ,  := range .match {
		 := .Specificity()
		if .Less() {
			 = 
		}
	}
	return 
}

type containsPseudoClassSelector struct {
	own   bool
	value string
}

func ( containsPseudoClassSelector) ( *html.Node) bool {
	var  string
matches nodes that directly contain the given text
matches nodes that contain the given text.
matches nodes whose text directly matches the specified regular expression
		 = nodeOwnText()
matches nodes whose text matches the specified regular expression
		 = nodeText()
	}
	return .regexp.MatchString()
}
writeNodeText writes the text contained in n and its descendants to b.
func ( *html.Node,  *bytes.Buffer) {
	switch .Type {
	case html.TextNode:
		.WriteString(.Data)
	case html.ElementNode:
		for  := .FirstChild;  != nil;  = .NextSibling {
			(, )
		}
	}
}
nodeText returns the text contained in n and its descendants.
func ( *html.Node) string {
	var  bytes.Buffer
	writeNodeText(, &)
	return .String()
}
nodeOwnText returns the contents of the text nodes that are direct children of n.
func ( *html.Node) string {
	var  bytes.Buffer
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Type == html.TextNode {
			.WriteString(.Data)
		}
	}
	return .String()
}

func ( regexpPseudoClassSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type nthPseudoClassSelector struct {
	a, b         int
	last, ofType bool
}

func ( nthPseudoClassSelector) ( *html.Node) bool {
	if .a == 0 {
		if .last {
			return simpleNthLastChildMatch(.b, .ofType, )
		} else {
			return simpleNthChildMatch(.b, .ofType, )
		}
	}
	return nthChildMatch(.a, .b, .last, .ofType, )
}
nthChildMatch implements :nth-child(an+b). If last is true, implements :nth-last-child instead. If ofType is true, implements :nth-of-type instead.
func (,  int, ,  bool,  *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}

	 := .Parent
	if  == nil {
		return false
	}

	if .Type == html.DocumentNode {
		return false
	}

	 := -1
	 := 0
	for  := .FirstChild;  != nil;  = .NextSibling {
		if (.Type != html.ElementNode) || ( && .Data != .Data) {
			continue
		}
		++
		if  ==  {
			 = 
			if ! {
				break
			}
		}
	}

This shouldn't happen, since n should always be one of its parent's children.
		return false
	}

	if  {
		 =  -  + 1
	}

	 -= 
	if  == 0 {
		return  == 0
	}

	return % == 0 && / >= 0
}
simpleNthChildMatch implements :nth-child(b). If ofType is true, implements :nth-of-type instead.
func ( int,  bool,  *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}

	 := .Parent
	if  == nil {
		return false
	}

	if .Type == html.DocumentNode {
		return false
	}

	 := 0
	for  := .FirstChild;  != nil;  = .NextSibling {
		if .Type != html.ElementNode || ( && .Data != .Data) {
			continue
		}
		++
		if  ==  {
			return  == 
		}
		if  >=  {
			return false
		}
	}
	return false
}
simpleNthLastChildMatch implements :nth-last-child(b). If ofType is true, implements :nth-last-of-type instead.
func ( int,  bool,  *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}

	 := .Parent
	if  == nil {
		return false
	}

	if .Type == html.DocumentNode {
		return false
	}

	 := 0
	for  := .LastChild;  != nil;  = .PrevSibling {
		if .Type != html.ElementNode || ( && .Data != .Data) {
			continue
		}
		++
		if  ==  {
			return  == 
		}
		if  >=  {
			return false
		}
	}
	return false
}
Specificity for nth-child pseudo-class. Does not support a list of selectors
Match implements :only-child. If `ofType` is true, it implements :only-of-type instead.
func ( onlyChildPseudoClassSelector) ( *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}

	 := .Parent
	if  == nil {
		return false
	}

	if .Type == html.DocumentNode {
		return false
	}

	 := 0
	for  := .FirstChild;  != nil;  = .NextSibling {
		if (.Type != html.ElementNode) || (.ofType && .Data != .Data) {
			continue
		}
		++
		if  > 1 {
			return false
		}
	}

	return  == 1
}

func ( onlyChildPseudoClassSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type inputPseudoClassSelector struct{}
Matches input, select, textarea and button elements.
func ( inputPseudoClassSelector) ( *html.Node) bool {
	return .Type == html.ElementNode && (.Data == "input" || .Data == "select" || .Data == "textarea" || .Data == "button")
}

func ( inputPseudoClassSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type emptyElementPseudoClassSelector struct{}
Matches empty elements.
func ( emptyElementPseudoClassSelector) ( *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}

	for  := .FirstChild;  != nil;  = .NextSibling {
		switch .Type {
		case html.ElementNode, html.TextNode:
			return false
		}
	}

	return true
}

func ( emptyElementPseudoClassSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type rootPseudoClassSelector struct{}
Match implements :root
func ( rootPseudoClassSelector) ( *html.Node) bool {
	if .Type != html.ElementNode {
		return false
	}
	if .Parent == nil {
		return false
	}
	return .Parent.Type == html.DocumentNode
}

func ( rootPseudoClassSelector) () Specificity {
	return Specificity{0, 1, 0}
}

type compoundSelector struct {
	selectors []Sel
}
Matches elements if each sub-selectors matches.
func ( compoundSelector) ( *html.Node) bool {
	if len(.selectors) == 0 {
		return .Type == html.ElementNode
	}

	for ,  := range .selectors {
		if !.Match() {
			return false
		}
	}
	return true
}

func ( compoundSelector) () Specificity {
	var  Specificity
	for ,  := range .selectors {
		 = .Add(.Specificity())
	}
	return 
}

type combinedSelector struct {
	first      Sel
	combinator byte
	second     Sel
}

func ( combinedSelector) ( *html.Node) bool {
	if .first == nil {
		return false // maybe we should panic
	}
	switch .combinator {
	case 0:
		return .first.Match()
	case ' ':
		return descendantMatch(.first, .second, )
	case '>':
		return childMatch(.first, .second, )
	case '+':
		return siblingMatch(.first, .second, true, )
	case '~':
		return siblingMatch(.first, .second, false, )
	default:
		panic("unknown combinator")
	}
}
matches an element if it matches d and has an ancestor that matches a.
func (,  Matcher,  *html.Node) bool {
	if !.Match() {
		return false
	}

	for  := .Parent;  != nil;  = .Parent {
		if .Match() {
			return true
		}
	}

	return false
}
matches an element if it matches d and its parent matches a.
func (,  Matcher,  *html.Node) bool {
	return .Match() && .Parent != nil && .Match(.Parent)
}
matches an element if it matches s2 and is preceded by an element that matches s1. If adjacent is true, the sibling must be immediately before the element.
func (,  Matcher,  bool,  *html.Node) bool {
	if !.Match() {
		return false
	}

	if  {
		for  = .PrevSibling;  != nil;  = .PrevSibling {
			if .Type == html.TextNode || .Type == html.CommentNode {
				continue
			}
			return .Match()
		}
		return false
	}
Walk backwards looking for element that matches s1
	for  := .PrevSibling;  != nil;  = .PrevSibling {
		if .Match() {
			return true
		}
	}

	return false
}

func ( combinedSelector) () Specificity {
	 := .first.Specificity()
	if .second != nil {
		 = .Add(.second.Specificity())
	}
	return 
}
A SelectorGroup is a list of selectors, which matches if any of the individual selectors matches.
Match returns true if the node matches one of the single selectors.
func ( SelectorGroup) ( *html.Node) bool {
	for ,  := range  {
		if .Match() {
			return true
		}
	}
	return false