Created
April 16, 2012 12:29
-
-
Save ChristianPeters/2398394 to your computer and use it in GitHub Desktop.
Adapted for Rails Asset Pipeline: Split CSS files so that there are no more than a given number of selectors in one style sheet. This is a tool to cope with Internet Explorer's limitation of max. 4095 selectors per stylesheet.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#... | |
module MyProject | |
class Application < Rails::Application | |
config.assets.precompile += %w( ie6.css ie6_portion2.css ie7.css ie7_portion2.css ie8.css ie8_portion2.css ie9.css ie9_portion2.css) | |
#... | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'css_splitter' | |
Rails.application.assets.register_engine '.split2', CssSplitter::SprocketsEngine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//= include 'ie8.css' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-#... | |
-# Rails Dev Boost compiles all templates that are included here regardless of browser requests | |
-# FIXME: Consider to remove Rails Dev Boost and this switch after updating to Rails 3.2 | |
-# Switch testing_for to e.g. :ie7 when testing for ie7 | |
- testing_for = nil | |
- if !Rails.env.development? || testing_for == :ie6 | |
/[if IE 6] | |
= stylesheet_link_tag :ie6 | |
= stylesheet_link_tag :ie6_portion2 | |
- if !Rails.env.development? || testing_for == :ie7 | |
/[if IE 7] | |
= stylesheet_link_tag :ie7 | |
= stylesheet_link_tag :ie7_portion2 | |
- if !Rails.env.development? || testing_for == :ie8 | |
/[if IE 8] | |
= stylesheet_link_tag :ie8 | |
= stylesheet_link_tag :ie8_portion2 | |
- if !Rails.env.development? || [:ie6, :ie7, :ie8].include?(testing_for) | |
/[if lt IE 9] | |
= javascript_include_tag "//html5shim.googlecode.com/svn/trunk/html5.js" | |
= javascript_include_tag 'ie/selectivizr' | |
- if !Rails.env.development? || testing_for == :ie9 | |
/[if IE 9] | |
= stylesheet_link_tag :ie9 | |
= stylesheet_link_tag :ie9_portion2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'tilt' | |
module CssSplitter | |
class SprocketsEngine < Tilt::Template | |
def self.engine_initialized? | |
true | |
end | |
def prepare | |
end | |
def evaluate(scope, locals, &block) | |
part = scope.pathname.extname =~ /(\d+)$/ && $1 || 0 | |
CssSplitter.split_string data, part.to_i | |
end | |
end | |
MAX_SELECTORS_DEFAULT = 4095 | |
def self.split(infile, outdir = File.dirname(infile), max_selectors = MAX_SELECTORS_DEFAULT) | |
raise "infile could not be found" unless File.exists? infile | |
rules = IO.readlines(infile, "}") | |
return if rules.first.nil? | |
charset_statement, rules[0] = rules.first.partition(/^\@charset[^;]+;/)[1,2] | |
return if rules.nil? | |
file_id = 1 # The infile remains the first file | |
selectors_count = 0 | |
output = nil | |
rules.each do |rule| | |
rule_selectors_count = count_selectors_of_rule rule | |
selectors_count += rule_selectors_count | |
# Nothing happens until the selectors limit is reached for the first time | |
if selectors_count > max_selectors | |
# Close current file if there is already one | |
output.close if output | |
# Prepare next file | |
file_id += 1 | |
filename = File.join(outdir, File.basename(infile, File.extname(infile)) + "_#{file_id.to_s}" + File.extname(infile)) | |
output = File.new(filename, "w") | |
output.write charset_statement | |
# Reset count with current rule count | |
selectors_count = rule_selectors_count | |
end | |
output.write rule if output | |
end | |
end | |
def self.split_string(css_string, part = 1, max_selectors = MAX_SELECTORS_DEFAULT) | |
rules = split_string_into_rules(css_string) | |
extract_part rules, part, max_selectors | |
end | |
def self.split_string_into_rules(css_string) | |
strip_comments(css_string).chomp.scan /[^}]*}/ | |
end | |
def self.extract_part(rules, part = 1, max_selectors = MAX_SELECTORS_DEFAULT) | |
return if rules.first.nil? | |
charset_statement, rules[0] = rules.first.partition(/^\@charset[^;]+;/)[1,2] | |
return if rules.nil? | |
output = charset_statement | |
selectors_count = 0 | |
selector_range = max_selectors * (part - 1) + 1 .. max_selectors * part | |
rules.each do |rule| | |
rule_selectors_count = count_selectors_of_rule rule | |
selectors_count += rule_selectors_count | |
if selector_range.cover? selectors_count | |
output << rule | |
elsif selectors_count > selector_range.end | |
break | |
end | |
end | |
output | |
end | |
def self.count_selectors(css_file) | |
raise "file could not be found" unless File.exists? css_file | |
rules = IO.readlines(css_file, '}') | |
return if rules.first.nil? | |
charset_statement, rules[0] = rules.first.partition(/^\@charset[^;]+;/)[1,2] | |
return if rules.first.nil? | |
rules.sum {|rule| count_selectors_of_rule(rule)}.tap do |result| | |
puts File.basename(css_file) + " contains #{result} selectors." | |
end | |
end | |
def self.count_selectors_of_rule(rule) | |
strip_comments(rule).partition(/\{/).first.scan(/,/).count.to_i + 1 | |
end | |
private | |
def self.strip_comments(s) | |
s.gsub(/\/\/.*$/, "").gsub(/\/\*.*?\*\//, "") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @ChristianPeters,
pretty nifty workaround with the
.splitx
file endings.Any plans to turn this into a gem?