Skip to content

Instantly share code, notes, and snippets.

@yoko
Forked from ChristianPeters/css_splitter.rake
Created March 27, 2012 12:35
Show Gist options
  • Save yoko/2215499 to your computer and use it in GitHub Desktop.
Save yoko/2215499 to your computer and use it in GitHub Desktop.
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.
require 'rake'
require 'css_splitter'
desc 'split css files'
namespace :css do
task :split do
infile = ENV['infile'] || raise("missing infile")
outdir = ENV['outdir'] || File.dirname(infile)
max_selectors = ENV['max_selectors'] || 4095
CssSplitter.split(infile, outdir, max_selectors)
end
task :count_selectors do
css_file = ENV['css_file'] || raise("missing css file")
CssSplitter.count_selectors(css_file)
end
end
# coding:utf-8
# from https://gist.github.com/1131536
module CssSplitter
def self.split(infile, outdir = File.dirname(infile), max_selectors = 4095)
raise "infile could not be found" unless File.exists? infile
rules = IO.readlines(infile, "}")
return if rules.first.nil?
ruleset = rules.first.partition(/^\@charset[^;]+;/)
charset_statement, rules[0] = ruleset[1,2] unless ruleset[1].empty?
return if rules.nil?
# The infile remains the first file
file_id = 1
selectors_count = 0
filename = File.join(outdir, File.basename(infile, File.extname(infile)) + File.extname(infile))
output = File.new(filename, "w")
output.write charset_statement if charset_statement
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 if charset_statement
puts "splited #{filename}"
# Reset count with current rule count
selectors_count = rule_selectors_count
end
output.write rule if output
end
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.inject(0) {|count, rule| count + 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)
rule.partition(/\{/).first.scan(/,/).count.to_i + 1
end
end
@yoko
Copy link
Author

yoko commented Mar 27, 2012

  • @charsetがないと最初のセレクターが消える問題修正(マルチバイト文字列がファイル内に存在しない時に@charsetを自動で削るSCSSの挙動と相性が悪いので直した)
  • ルールが重複しないように改善

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