Class: CSS::MediaQueries::Parser

Inherits:
Object
  • Object
show all
Includes:
TokenCursor
Defined in:
lib/css/media_queries/parser.rb

Overview

Parser for ‘<media-query-list>` per Media Queries Level 4 §3. drafts.csswg.org/mediaqueries-4/

Accepts either a String (which is tokenized and re-component-valued so ‘(…)` becomes a `SimpleBlock`) or an Array of component values (for use against an `@media` rule’s prelude from the main parser).

Constant Summary collapse

MODIFIER_KEYWORDS =
%w[not only].freeze
LOGICAL_KEYWORDS =
%w[and or not].freeze

Constants included from TokenCursor

TokenCursor::EOF_TOKEN

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TokenCursor

#consume, #eof?, #init_cursor, #parse_error!, #peek, #peek_token, #skip_whitespace

Constructor Details

#initialize(items) ⇒ Parser

Returns a new instance of Parser.



27
28
29
# File 'lib/css/media_queries/parser.rb', line 27

def initialize(items)
  init_cursor(items)
end

Class Method Details

.parse(input) ⇒ Object



16
17
18
# File 'lib/css/media_queries/parser.rb', line 16

def parse(input)
  new(items_from(input)).parse_media_query_list
end

Instance Method Details

#parse_media_queryObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/css/media_queries/parser.rb', line 53

def parse_media_query
  skip_whitespace

  saved = @pos

  # Try the `[not | only]? <media-type> [and <condition-without-or>]?` form.
  modifier = consume_modifier
  skip_whitespace if modifier

  if (item = peek).is_a?(Token) && item.type == :ident && !LOGICAL_KEYWORDS.include?(item.value.downcase)
    type = consume.value.downcase
    skip_whitespace

    condition = nil

    if keyword?('and')
      consume
      skip_whitespace
      condition = parse_media_condition(allow_or: false)
    end

    return MediaQuery.new(modifier:, type:, condition:)
  end

  # Otherwise this is a pure media-condition (no type / modifier).
  @pos = saved

  MediaQuery.new(modifier: nil, type: nil, condition: parse_media_condition(allow_or: true))
end

#parse_media_query_listObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/css/media_queries/parser.rb', line 31

def parse_media_query_list
  skip_whitespace

  queries = [parse_media_query]

  loop do
    skip_whitespace
    break unless peek_token.type == :comma

    consume
    queries << parse_media_query
  end

  skip_whitespace

  unless eof?
    parse_error!("trailing tokens after media query list: #{describe(peek)}")
  end

  MediaQueryList.new(queries:)
end