Class: CSS::Selectors::Parser
- Inherits:
-
Object
- Object
- CSS::Selectors::Parser
- Includes:
- TokenCursor
- Defined in:
- lib/css/selectors/parser.rb
Overview
Parser for CSS Selectors Level 4. Covers compound and complex selectors, the four standard combinators (descendant, child, next- sibling, subsequent-sibling), pseudo-classes / pseudo-elements (with recursive parsing of ‘:not/:is/:where/:has` and AnB parsing of `:nth-*`), attribute selectors with case-insensitive `i` / `s` flags, and the `&` nesting selector.
Out of scope (intermediate plan): namespace prefixes, the column combinator ‘||`, and forgiving vs strict selector list distinctions.
Constant Summary collapse
- SELECTOR_LIST_PSEUDOS =
‘:has()` is intentionally excluded — it takes a relative selector list (each item may start with a combinator) which would require extending the ComplexSelector AST. Falls back to opaque component values for now.
%w[is where not matches].freeze
- ANB_PSEUDOS =
%w[nth-child nth-last-child nth-of-type nth-last-of-type].freeze
- ATTR_MATCHERS =
{ '~' => :includes, '|' => :dash, '^' => :prefix, '$' => :suffix, '*' => :substring }.freeze
- BRACKET_TYPE_FOR_OPEN =
BRACKET_OPEN_CHAR.invert.freeze
- BRACKET_CLOSE_TYPE_FOR_OPEN =
BRACKET_OPEN_CHAR.to_h {|type, ch| [ch, BRACKET_CLOSE_TYPE.fetch(type)] }.freeze
Constants included from TokenCursor
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(tokens) ⇒ Parser
constructor
A new instance of Parser.
- #parse_complex_selector ⇒ Object
- #parse_selector_complete ⇒ Object
-
#parse_selector_list ⇒ Object
A comma-separated list of complex selectors, terminated by EOF or ‘)` (for use inside functional pseudos like `:is(…)`).
- #parse_selector_list_complete ⇒ Object
Methods included from TokenCursor
#consume, #eof?, #init_cursor, #parse_error!, #peek, #peek_token, #skip_whitespace
Constructor Details
#initialize(tokens) ⇒ Parser
Returns a new instance of Parser.
79 80 81 |
# File 'lib/css/selectors/parser.rb', line 79 def initialize(tokens) init_cursor(tokens) end |
Class Method Details
.parse_selector(input) ⇒ Object
35 36 37 |
# File 'lib/css/selectors/parser.rb', line 35 def parse_selector(input) new(tokens_from(input)).parse_selector_complete end |
.parse_selector_list(input) ⇒ Object
31 32 33 |
# File 'lib/css/selectors/parser.rb', line 31 def parse_selector_list(input) new(tokens_from(input)).parse_selector_list_complete end |
Instance Method Details
#parse_complex_selector ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/css/selectors/parser.rb', line 126 def parse_complex_selector skip_whitespace compounds = [parse_compound_selector] combinators = [] loop do combo = try_consume_combinator break if combo.nil? compounds << parse_compound_selector combinators << combo end ComplexSelector.new(compounds:, combinators:) end |
#parse_selector_complete ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/css/selectors/parser.rb', line 93 def parse_selector_complete skip_whitespace cs = parse_complex_selector skip_whitespace parse_error!("trailing tokens after selector: #{peek.type}") unless peek.type == :eof cs end |
#parse_selector_list ⇒ Object
A comma-separated list of complex selectors, terminated by EOF or ‘)` (for use inside functional pseudos like `:is(…)`).
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/css/selectors/parser.rb', line 107 def parse_selector_list skip_whitespace parse_error!('empty selector list') if list_terminator?(peek) selectors = [parse_complex_selector] loop do skip_whitespace break unless peek.type == :comma consume skip_whitespace selectors << parse_complex_selector end SelectorList.new(selectors:) end |
#parse_selector_list_complete ⇒ Object
83 84 85 86 87 88 89 90 91 |
# File 'lib/css/selectors/parser.rb', line 83 def parse_selector_list_complete list = parse_selector_list skip_whitespace parse_error!("trailing tokens after selector list: #{peek.type}") unless peek.type == :eof list end |