Module: Parselly

Defined in:
lib/parselly.rb,
lib/parselly.rb,
lib/parselly/node.rb,
lib/parselly/lexer.rb,
lib/parselly/parser.rb,
lib/parselly/version.rb

Defined Under Namespace

Classes: LexError, Lexer, Node, ParseError, ParseResult, Parser, SyntaxError

Constant Summary collapse

VERSION =
'1.3.0'

Class Method Summary collapse

Class Method Details

.escaped_hex(char) ⇒ Object



107
108
109
# File 'lib/parselly.rb', line 107

def escaped_hex(char)
  "\\#{char.ord.to_s(16)} "
end

.parse(selector, **options) ⇒ Object



66
67
68
# File 'lib/parselly.rb', line 66

def parse(selector, **options)
  Parser.new.parse(selector, **options)
end

.sanitize(selector) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/parselly.rb', line 70

def sanitize(selector)
  scanner = StringScanner.new(selector)
  result = +''

  # Special case: if the selector is of length 1 and
  # the first character is `-`
  return "\\#{selector}" if selector.length == 1 && scanner.peek(1) == '-'

  until scanner.eos?
    # NULL character (U+0000)
    if scanner.scan(/\0/)
      result << "\uFFFD"
    # Control characters (U+0001 to U+001F, U+007F)
    elsif scanner.scan(/[\x01-\x1F\x7F]/)
      result << escaped_hex(scanner.matched)
    # First character is a digit (U+0030 to U+0039)
    elsif scanner.pos.zero? && scanner.scan(/\d/)
      result << escaped_hex(scanner.matched)
    # Second character is a digit and first is `-`
    elsif scanner.pos == 1 && scanner.peek(1).match?(/\d/) &&
          scanner.string.start_with?('-') && scanner.scan(/\d/)
      result << escaped_hex(scanner.matched)
    # Alphanumeric characters, `-`, `_`
    elsif scanner.scan(/[a-zA-Z0-9\-_]/)
      result << scanner.matched
    # Non-ASCII characters are valid CSS identifier characters.
    elsif scanner.scan(/[^\x00-\x7F]/)
      result << scanner.matched
    # Any other characters, escape them
    elsif scanner.scan(/./)
      result << "\\#{scanner.matched}"
    end
  end

  result
end