class Sass::SCSS::StaticParser

A parser for a static SCSS tree. Parses with SCSS extensions, like nested rules and parent selectors, but without dynamic SassScript. This is useful for e.g. {#parse_selector parsing selectors} after resolving the interpolation.

Constants

PREFIXED_SELECTOR_PSEUDO_CLASSES
SELECTOR_PSEUDO_CLASSES

Public Class Methods

new(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true) click to toggle source

@see Parser#initialize @param allow_parent_ref [Boolean] Whether to allow the

parent-reference selector, `&`, when parsing the document.

@comment

rubocop:disable ParameterLists
Calls superclass method Sass::SCSS::Parser.new
# File lib/sass/scss/static_parser.rb, line 56
def initialize(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true)
  # rubocop:enable ParameterLists
  super(str, filename, importer, line, offset)
  @allow_parent_ref = allow_parent_ref
end

Public Instance Methods

parse_keyframes_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 44
def parse_keyframes_selector
  init_scanner!
  sel = expr!(:keyframes_selector)
  expected("keyframes selector") unless @scanner.eos?
  sel
end
parse_selector() click to toggle source

Parses the text as a selector.

@param filename [String, nil] The file in which the selector appears,

or nil if there is no such file.
Used for error reporting.

@return [Selector::CommaSequence] The parsed selector @raise [Sass::SyntaxError] if there's a syntax error in the selector

# File lib/sass/scss/static_parser.rb, line 18
def parse_selector
  init_scanner!
  seq = expr!(:selector_comma_sequence)
  expected("selector") unless @scanner.eos?
  seq.line = @line
  seq.filename = @filename
  seq
end
parse_static_at_root_query() click to toggle source

Parses a static at-root query.

@return [(Symbol, Array<String>)] The type of the query

(`:with` or `:without`) and the values that are being filtered.

@raise [Sass::SyntaxError] if there's a syntax error in the query,

or if it doesn't take up the entire input string.
# File lib/sass/scss/static_parser.rb, line 33
def parse_static_at_root_query
  init_scanner!
  tok!(/\(/); ss
  type = tok!(/\b(without|with)\b/).to_sym; ss
  tok!(/:/); ss
  directives = expr!(:at_root_directive_list); ss
  tok!(/\)/)
  expected("@at-root query list") unless @scanner.eos?
  return type, directives
end

Private Instance Methods

a_n_plus_b() click to toggle source
# File lib/sass/scss/static_parser.rb, line 327
def a_n_plus_b
  if (parity = tok(/even|odd/i))
    return parity
  end

  if tok(/[+-]?[0-9]+/)
    ss
    return true unless tok(/n/)
  else
    return unless tok(/[+-]?n/i)
  end
  ss

  return true unless tok(/[+-]/)
  ss
  @expected = "number"
  tok!(/[0-9]+/)
  true
end
attrib() click to toggle source
# File lib/sass/scss/static_parser.rb, line 227
def attrib
  return unless tok(/\[/)
  ss
  ns, name = attrib_name!
  ss

  op = tok(/=/) ||
       tok(INCLUDES) ||
       tok(DASHMATCH) ||
       tok(PREFIXMATCH) ||
       tok(SUFFIXMATCH) ||
       tok(SUBSTRINGMATCH)
  if op
    @expected = "identifier or string"
    ss
    val = tok(IDENT) || tok!(STRING)
    ss
  end
  flags = tok(IDENT) || tok(STRING)
  tok!(/\]/)

  Selector::Attribute.new(name, ns, op, val, flags)
end
attrib_name!() click to toggle source
# File lib/sass/scss/static_parser.rb, line 251
def attrib_name!
  if (name_or_ns = tok(IDENT))
    # E, E|E
    if tok(/\|(?!=)/)
      ns = name_or_ns
      name = tok(IDENT)
    else
      name = name_or_ns
    end
  else
    # *|E or |E
    ns = tok(/\*/) || ""
    tok!(/\|/)
    name = tok!(IDENT)
  end
  return ns, name
end
class_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 188
def class_selector
  return unless tok(/\./)
  @expected = "class name"
  Selector::Class.new(tok!(IDENT))
end
combinator() click to toggle source
# File lib/sass/scss/static_parser.rb, line 138
def combinator
  tok(PLUS) || tok(GREATER) || tok(TILDE) || reference_combinator
end
element_name() click to toggle source
# File lib/sass/scss/static_parser.rb, line 206
def element_name
  ns, name = Sass::Util.destructure(qualified_name(:allow_star_name))
  return unless ns || name

  if name == '*'
    Selector::Universal.new(ns)
  else
    Selector::Element.new(name, ns)
  end
end
id_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 194
def id_selector
  return unless tok(/#(?!\{)/)
  @expected = "id name"
  Selector::Id.new(tok!(NAME))
end
interp_ident(ident = IDENT) click to toggle source
# File lib/sass/scss/static_parser.rb, line 77
def interp_ident(ident = IDENT); (s = tok(ident)) && [s]; end
interp_string() click to toggle source
# File lib/sass/scss/static_parser.rb, line 75
def interp_string; (s = tok(STRING)) && [s]; end
interp_uri() click to toggle source
# File lib/sass/scss/static_parser.rb, line 76
def interp_uri; (s = tok(URI)) && [s]; end
interpolation(warn_for_color = false) click to toggle source
# File lib/sass/scss/static_parser.rb, line 73
def interpolation(warn_for_color = false); nil; end
keyframes_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 347
def keyframes_selector
  ss
  str do
    return unless keyframes_selector_component
    ss
    while tok(/,/)
      ss
      expr!(:keyframes_selector_component)
      ss
    end
  end
end
keyframes_selector_component() click to toggle source
# File lib/sass/scss/static_parser.rb, line 360
def keyframes_selector_component
  tok(IDENT) || tok(PERCENTAGE)
end
moz_document_function() click to toggle source
# File lib/sass/scss/static_parser.rb, line 64
def moz_document_function
  val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) || function(!:allow_var)
  return unless val
  ss
  [val]
end
parent_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 183
def parent_selector
  return unless @allow_parent_ref && tok(/&/)
  Selector::Parent.new(tok(NAME))
end
placeholder_selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 200
def placeholder_selector
  return unless tok(/%/)
  @expected = "placeholder name"
  Selector::Placeholder.new(tok!(IDENT))
end
prefixed_selector_pseudo() click to toggle source
# File lib/sass/scss/static_parser.rb, line 317
def prefixed_selector_pseudo
  prefix = str do
    expr = str {expr!(:a_n_plus_b)}
    ss
    return expr, nil unless tok(/of/)
    ss
  end
  return prefix, expr!(:selector_comma_sequence)
end
pseudo() click to toggle source
# File lib/sass/scss/static_parser.rb, line 273
def pseudo
  s = tok(/::?/)
  return unless s
  @expected = "pseudoclass or pseudoelement"
  name = tok!(IDENT)
  if tok(/\(/)
    ss
    deprefixed = deprefix(name)
    if s == ':' && SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
      sel = selector_comma_sequence
    elsif s == ':' && PREFIXED_SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
      arg, sel = prefixed_selector_pseudo
    else
      arg = expr!(:pseudo_args)
    end

    tok!(/\)/)
  end
  Selector::Pseudo.new(s == ':' ? :class : :element, name, arg, sel)
end
pseudo_args() click to toggle source
# File lib/sass/scss/static_parser.rb, line 294
def pseudo_args
  arg = expr!(:pseudo_expr)
  while tok(/,/)
    arg << ',' << str {ss}
    arg.concat expr!(:pseudo_expr)
  end
  arg
end
pseudo_expr() click to toggle source
# File lib/sass/scss/static_parser.rb, line 303
def pseudo_expr
  res = pseudo_expr_token
  return unless res
  res << str {ss}
  while (e = pseudo_expr_token)
    res << e << str {ss}
  end
  res
end
pseudo_expr_token() click to toggle source
# File lib/sass/scss/static_parser.rb, line 313
def pseudo_expr_token
  tok(PLUS) || tok(/[-*]/) || tok(NUMBER) || tok(STRING) || tok(IDENT)
end
qualified_name(allow_star_name = false) click to toggle source
# File lib/sass/scss/static_parser.rb, line 217
def qualified_name(allow_star_name = false)
  name = tok(IDENT) || tok(/\*/) || (tok?(/\|/) && "")
  return unless name
  return nil, name unless tok(/\|/)

  return name, tok!(IDENT) unless allow_star_name
  @expected = "identifier or *"
  return name, tok(IDENT) || tok!(/\*/)
end
reference_combinator() click to toggle source
# File lib/sass/scss/static_parser.rb, line 142
def reference_combinator
  return unless tok(/\//)
  res = '/'
  ns, name = expr!(:qualified_name)
  res << ns << '|' if ns
  res << name << tok!(/\//)
  res
end
script_value() click to toggle source
# File lib/sass/scss/static_parser.rb, line 72
def script_value; nil; end
selector() click to toggle source
# File lib/sass/scss/static_parser.rb, line 109
      def selector
        start_pos = source_position
        # The combinator here allows the "> E" hack
        val = combinator || simple_selector_sequence
        return unless val
        nl = str {ss}.include?("\n")
        res = []
        res << val
        res << "\n" if nl

        while (val = combinator || simple_selector_sequence)
          res << val
          res << "\n" if str {ss}.include?("\n")
        end
        seq = Selector::Sequence.new(res.compact)

        if seq.members.any? {|sseq| sseq.is_a?(Selector::SimpleSequence) && sseq.subject?}
          location = " of #{@filename}" if @filename
          Sass::Util.sass_warn <<MESSAGE
DEPRECATION WARNING on line #{start_pos.line}, column #{start_pos.offset}#{location}:
The subject selector operator "!" is deprecated and will be removed in a future release.
This operator has been replaced by ":has()" in the CSS spec.
For example: #{seq.subjectless}
MESSAGE
        end

        seq
      end
selector_comma_sequence() click to toggle source
# File lib/sass/scss/static_parser.rb, line 85
def selector_comma_sequence
  sel = selector
  return unless sel
  selectors = [sel]
  ws = ''
  while tok(/,/)
    ws << str {ss}
    if (sel = selector)
      selectors << sel
      if ws.include?("\n")
        selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members)
      end
      ws = ''
    end
  end
  Selector::CommaSequence.new(selectors)
end
selector_string() click to toggle source
# File lib/sass/scss/static_parser.rb, line 103
def selector_string
  sel = selector
  return unless sel
  sel.to_s
end
simple_selector_sequence() click to toggle source
# File lib/sass/scss/static_parser.rb, line 151
def simple_selector_sequence
  start_pos = source_position
  e = element_name || id_selector || class_selector || placeholder_selector || attrib ||
      pseudo || parent_selector
  return unless e
  res = [e]

  # The tok(/\*/) allows the "E*" hack
  while (v = id_selector || class_selector || placeholder_selector ||
             attrib || pseudo || (tok(/\*/) && Selector::Universal.new(nil)))
    res << v
  end

  pos = @scanner.pos
  line = @line
  if (sel = str? {simple_selector_sequence})
    @scanner.pos = pos
    @line = line
    begin
      # If we see "*E", don't force a throw because this could be the
      # "*prop: val" hack.
      expected('"{"') if res.length == 1 && res[0].is_a?(Selector::Universal)
      throw_error {expected('"{"')}
    rescue Sass::SyntaxError => e
      e.message << "\n\n\"#{sel}\" may only be used at the beginning of a compound selector."
      raise e
    end
  end

  Selector::SimpleSequence.new(res, tok(/!/), range(start_pos))
end
special_directive(name, start_pos) click to toggle source
Calls superclass method Sass::SCSS::Parser#special_directive
# File lib/sass/scss/static_parser.rb, line 80
def special_directive(name, start_pos)
  return unless %w[media import charset -moz-document].include?(name)
  super
end
use_css_import?() click to toggle source
# File lib/sass/scss/static_parser.rb, line 78
def use_css_import?; true; end
var_expr() click to toggle source
# File lib/sass/scss/static_parser.rb, line 74
def var_expr; nil; end
variable() click to toggle source
# File lib/sass/scss/static_parser.rb, line 71
def variable; nil; end