Skip to content

Instantly share code, notes, and snippets.

@henrahmagix
Created March 1, 2013 15:37
Show Gist options
  • Save henrahmagix/5065448 to your computer and use it in GitHub Desktop.
Save henrahmagix/5065448 to your computer and use it in GitHub Desktop.
An arbitrary long CSS selector splitter to go in your `config.rb` for Compass projects.
# Split selectors that are too long so IE8 doesn't ignore them.
on_stylesheet_saved do |path|
CssSelectorSplitter.split(path) unless path[/\d+$/]
end
# The following is a default config.rb created by `compass create`.
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
class CssSelectorSplitter
# This has some horribly arbitrary code, documented below.
#
# max_length: 1000~ seemed to work, but needs more testing to find
# actual breakpoint.
#
# selector.each_slice(5): Determine greatest slice before exceeding
# max_length.
def self.split(infile, outfile = infile, max_length = 1024)
raise "infile could not be found" unless File.exists? infile
rules = IO.readlines(infile, "}")
return if rules.first.nil?
return if rules.nil?
output = nil
new_file_string = ''
rules.each do |rule|
# Get the selector length.
# @TODO: This can get the sections instead so we don't do so again
# below, but that means running on every rule rather than just
# those that are too long, and potentially increase runtime.
selector_length = length_of_selector_in_rule rule
if selector_length > max_length
# If the length of this selector is larger than max_length,
# split it up into smaller strings and give each the same
# properties.
puts 'splitting selector of length ' + selector_length.to_s
new_rule = []
# Split the rule into the selector and properties.
sections = rule.split(/(\{[^}]*\})/)
selector = sections[0].split(/,/)
style = sections[1]
# @TODO: Swap arbitrary each_slice position of 5 for greatest
# position that doesn't exceed max_length characters.
selector.each_slice(5).each_with_index do |small_selector, index|
small_selector = small_selector.join(',')
# Add a space to the end if not already there. Ruby returns
# the character code of a string index, not a new string
# like Javascript would.
if small_selector[-1] != 32
small_selector += ' '
end
# Add the style to this new, smaller selector, and put in
# our collection array to be joined into a string at the
# end of this loop.
# @TODO: Add system EOL.
new_rule[index] = small_selector + style
end
# Add the split rule to our string of infile.
new_file_string += new_rule.join('')
else
# Otherwise add the rule as-is to the infile string.
new_file_string += rule
end
end
# Write out the new copy of infile. outfile is either infile or a passed
# filepath, so infile is overwritten by default.
output = File.new(outfile, "w")
output.write new_file_string if new_file_string
puts 'overwrite ' + outfile.to_s
end
def self.length_of_selector_in_rule(rule)
# Split the rule on '{'. The first part is the selector string.
return rule.partition('{')[0].length
end
end
@henrahmagix
Copy link
Author

Please feel free to send me your updates on this to make it less arbitrary (read: less shite) and I'll more than happily merge them in =)

@c89williams
Copy link

Thank you so much for your work on this! It is exactly what I was looking for.

A shame this Gist was so hard to find, took me well over an hour to stumble here (came from your Compass issue: Compass/compass#1193).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment