...

Source file src/github.com/andybalholm/cascadia/serialize.go

Documentation: github.com/andybalholm/cascadia

     1  package cascadia
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // implements the reverse operation Sel -> string
    10  
    11  var specialCharReplacer *strings.Replacer
    12  
    13  func init() {
    14  	var pairs []string
    15  	for _, s := range ",!\"#$%&'()*+ -./:;<=>?@[\\]^`{|}~" {
    16  		pairs = append(pairs, string(s), "\\"+string(s))
    17  	}
    18  	specialCharReplacer = strings.NewReplacer(pairs...)
    19  }
    20  
    21  // espace special CSS char
    22  func escape(s string) string { return specialCharReplacer.Replace(s) }
    23  
    24  func (c tagSelector) String() string {
    25  	return c.tag
    26  }
    27  
    28  func (c idSelector) String() string {
    29  	return "#" + escape(c.id)
    30  }
    31  
    32  func (c classSelector) String() string {
    33  	return "." + escape(c.class)
    34  }
    35  
    36  func (c attrSelector) String() string {
    37  	val := c.val
    38  	if c.operation == "#=" {
    39  		val = c.regexp.String()
    40  	} else if c.operation != "" {
    41  		val = fmt.Sprintf(`"%s"`, val)
    42  	}
    43  
    44  	ignoreCase := ""
    45  
    46  	if c.insensitive {
    47  		ignoreCase = " i"
    48  	}
    49  
    50  	return fmt.Sprintf(`[%s%s%s%s]`, c.key, c.operation, val, ignoreCase)
    51  }
    52  
    53  func (c relativePseudoClassSelector) String() string {
    54  	return fmt.Sprintf(":%s(%s)", c.name, c.match.String())
    55  }
    56  
    57  func (c containsPseudoClassSelector) String() string {
    58  	s := "contains"
    59  	if c.own {
    60  		s += "Own"
    61  	}
    62  	return fmt.Sprintf(`:%s("%s")`, s, c.value)
    63  }
    64  
    65  func (c regexpPseudoClassSelector) String() string {
    66  	s := "matches"
    67  	if c.own {
    68  		s += "Own"
    69  	}
    70  	return fmt.Sprintf(":%s(%s)", s, c.regexp.String())
    71  }
    72  
    73  func (c nthPseudoClassSelector) String() string {
    74  	if c.a == 0 && c.b == 1 { // special cases
    75  		s := ":first-"
    76  		if c.last {
    77  			s = ":last-"
    78  		}
    79  		if c.ofType {
    80  			s += "of-type"
    81  		} else {
    82  			s += "child"
    83  		}
    84  		return s
    85  	}
    86  	var name string
    87  	switch [2]bool{c.last, c.ofType} {
    88  	case [2]bool{true, true}:
    89  		name = "nth-last-of-type"
    90  	case [2]bool{true, false}:
    91  		name = "nth-last-child"
    92  	case [2]bool{false, true}:
    93  		name = "nth-of-type"
    94  	case [2]bool{false, false}:
    95  		name = "nth-child"
    96  	}
    97  	s := fmt.Sprintf("+%d", c.b)
    98  	if c.b < 0 { // avoid +-8 invalid syntax
    99  		s = strconv.Itoa(c.b)
   100  	}
   101  	return fmt.Sprintf(":%s(%dn%s)", name, c.a, s)
   102  }
   103  
   104  func (c onlyChildPseudoClassSelector) String() string {
   105  	if c.ofType {
   106  		return ":only-of-type"
   107  	}
   108  	return ":only-child"
   109  }
   110  
   111  func (c inputPseudoClassSelector) String() string {
   112  	return ":input"
   113  }
   114  
   115  func (c emptyElementPseudoClassSelector) String() string {
   116  	return ":empty"
   117  }
   118  
   119  func (c rootPseudoClassSelector) String() string {
   120  	return ":root"
   121  }
   122  
   123  func (c linkPseudoClassSelector) String() string {
   124  	return ":link"
   125  }
   126  
   127  func (c langPseudoClassSelector) String() string {
   128  	return fmt.Sprintf(":lang(%s)", c.lang)
   129  }
   130  
   131  func (c neverMatchSelector) String() string {
   132  	return c.value
   133  }
   134  
   135  func (c enabledPseudoClassSelector) String() string {
   136  	return ":enabled"
   137  }
   138  
   139  func (c disabledPseudoClassSelector) String() string {
   140  	return ":disabled"
   141  }
   142  
   143  func (c checkedPseudoClassSelector) String() string {
   144  	return ":checked"
   145  }
   146  
   147  func (c compoundSelector) String() string {
   148  	if len(c.selectors) == 0 && c.pseudoElement == "" {
   149  		return "*"
   150  	}
   151  	chunks := make([]string, len(c.selectors))
   152  	for i, sel := range c.selectors {
   153  		chunks[i] = sel.String()
   154  	}
   155  	s := strings.Join(chunks, "")
   156  	if c.pseudoElement != "" {
   157  		s += "::" + c.pseudoElement
   158  	}
   159  	return s
   160  }
   161  
   162  func (c combinedSelector) String() string {
   163  	start := c.first.String()
   164  	if c.second != nil {
   165  		start += fmt.Sprintf(" %s %s", string(c.combinator), c.second.String())
   166  	}
   167  	return start
   168  }
   169  
   170  func (c SelectorGroup) String() string {
   171  	ck := make([]string, len(c))
   172  	for i, s := range c {
   173  		ck[i] = s.String()
   174  	}
   175  	return strings.Join(ck, ", ")
   176  }
   177  

View as plain text