premailer / css_parser

Ruby CSS Parser
Other
279 stars 110 forks source link

Split css selector #86

Closed lucasdchamps closed 7 years ago

lucasdchamps commented 7 years ago

I was wondering if it's possible with css_parser to split a composition of selectors.

For example, given 'span.action_item>.dropdown_menu>a'

Splitting this composition would give ['span', '.action_item', '.dropdown_menu', 'a']

My goal is to list all elementary selectors in my project.

Thank you very much for you help :)

akzhan commented 7 years ago

Do you think about something like

class String
  def matches(regex)
    position = 0
    Enumerator.new do |yielder|
      while match = regex.match(self, position)
        yielder << match
        position = match.end(0)
      end
    end
  end
end

'span.action_item>.dropdown_menu>a'.matches(/((?:^|\W)+\w+)/).to_a # => [#<MatchData "span" 1:"span">, #<MatchData ".action_item" 1:".action_item">, #<MatchData ">.dropdown_menu" 1:">.dropdown_menu">, #<MatchData ">a" 1:">a">]
lucasdchamps commented 7 years ago

Something like this indeed, but it should match '.dropdown_menu' instead of '>.dropdown_menu'

Are you sure the regex covers all composition use cases?

I would be glad to add this functionality to css_parser if others need it.

akzhan commented 7 years ago

Regular expressions cannot cover all cases of CSS selectors.

'span.action_item > .dropdown_menu > a'.split(/(?:\s|>|~)+/).map do |s|
  s.matches(/((?:^|\W+)\w+)/).to_a
end.flatten
akzhan commented 7 years ago

this will be pushed to the gem unless errata (without String mixin).

lucasdchamps commented 7 years ago

Thanks! I checked in the css specs and as you said, regexps are not sufficient, it would require a grammar but it's a bit overkill just for this feature.

I think your piece of code covers most of the cases 👍