premailer/css_parser

Return line number

Closed this issue · 4 comments

It would be nice to return a line number during each_selector for the current selector to use as a reference.

rex commented

THIS. So much this. I'm building a small frontend auditing tool for my job intended to read in massive legacy stylesheets and display statistics/information as well as offer suggestions on how to reorganize them into a modular SCSS/SASS structure. I was hoping to implement functionality into this tool that would allow users (read: devs) to search for selectors and be able to locate these selectors in a given file by a given line number.

Is there a way for each_selector() to pass an additional parameter line to make this functionality easy to implement? In a perfect world, there would even be an additional parameter file to make it even easier. Perhaps the two could even be combined, vis-a-vis a Javascript stack trace (e.g. foo/bar/baz.css#27 for line 27 of foo/bar/baz.css?

Looks like will be contributed by #85

You can now get byte offsets for a rule, from that you should be able to get the line number by re-loading the original file yourself.

I haven't tested this myself but you should be able to do something like:

def find_lines_by_selector(uri, selector)
  # download the css file yourself
  css_content = open(uri).read

  # let CssParser parse the file
  parser = CssParser.new
  parser.load_uri!(uri, capture_offsets: true)

  # collect lines where we find a matching selector
  matching_lines = []
  parser.each_rule_set(media_types) do |rule_set, media_type|
    # see if this rule set contains the selector
    if rule_set.selectors.include?(selector)
      # it does, so get the original content from the start fo the file, up until
      # the start of this rule, then count the number of lines
      matching_lines << css_content[0..rule_set.offset.first].lines.count
    end
  end
end

Eventually it would be nice to have the option to cache the CSS file within the parser if we intend to use it like this.

Just note that is't released as 1.5.0.pre