diff --git a/.gitignore b/.gitignore
index 1dfe31e..a9ecfb8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.bundle/
+Gemfile.lock
log/*.log
pkg/
test/dummy/db/*.sqlite3
diff --git a/.travis.yml b/.travis.yml
index 33fb9e8..f09ded4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,9 @@
+sudo: false
language: ruby
bundler_args: --without development
rvm:
- - "1.9.3"
\ No newline at end of file
+ - "1.9.3"
+ - "2.1"
+ - "2.2"
+gemfile:
+ - "Gemfile"
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89a9235..cd411e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,43 @@
+# 0.4.6
+
+* [fix] Implement new engine interface for future sprockets versions #70
+* [bugfix] Fix issue where helper is not a defined method on controller (e.g. ActionController::API:Class) #65
+
+# 0.4.5
+
+* [bugfix] fix sprockets engine registering for older sprocket-rails versions #68
+
+# 0.4.4
+
+* [bugfix] fix compatibility with with sprockts-rails version 3.x, see #62
+
+# 0.4.3
+
+* [bugfix] for media queries with whitespace in front of them #57
+
+# 0.4.2
+
+* [bugfix] correctly split stylesheets even if @keyframes are directly on the rule limit #55 by [@rubenswieringa](https://github.com/rubenswieringa)
+
+# 0.4.1
+
+* [Improvement] All `*_splitN.css` files default to `debug: false` in development to prevent empty file bug.
+
+# 0.4.0
+
+* **Breaking changes!**
+* The `CssSplitter::SprocketsEngine` is now registered as a bundle_processor to avoid issues with sprockets directives #29
+ * `.split2` extension is no longer necessary/supported, now we rely on `_splitN` at the end of the filename
+ * Now you need to use the `require` rather than the `include` directive in the split stylesheet
+ * Prohibition against using `require_tree .` and `require_self` directives no longer applies
+ * Better tests
+ * Thanks a lot to [@Umofomia](https://github.com/Umofomia)
+* loosen dependency on `rails` (depend on `sprockets` instead), to make gem compatible to other frameworks like `middleman`
+
+# 0.2.0
+
+* loosen dependency to make it compatible with rails 4
+
# 0.1.1
* Added license info ("MIT") to gemspec
@@ -17,4 +57,4 @@
# 0.0.1
-Initial commit
\ No newline at end of file
+Initial commit
diff --git a/Gemfile b/Gemfile
index 4042fd6..74fab5c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,16 +6,10 @@ source "http://rubygems.org"
gemspec
group :development do
- gem "pry-debugger"
+ gem 'pry-byebug'
end
+
+gem "rails"
gem "sass-rails"
gem "jquery-rails"
gem "uglifier"
-
-# Declare any dependencies that are still in development here instead of in
-# your gemspec. These might include edge Rails or gems from your path or
-# Git. Remember to move these dependencies to your gemspec before releasing
-# your gem to rubygems.org.
-
-# To use debugger
-# gem 'debugger'
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index 90fb3a8..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,126 +0,0 @@
-PATH
- remote: .
- specs:
- css_splitter (0.1.1)
- rails (~> 3.1)
-
-GEM
- remote: http://rubygems.org/
- specs:
- actionmailer (3.2.13)
- actionpack (= 3.2.13)
- mail (~> 2.5.3)
- actionpack (3.2.13)
- activemodel (= 3.2.13)
- activesupport (= 3.2.13)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.4)
- rack (~> 1.4.5)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.2.1)
- activemodel (3.2.13)
- activesupport (= 3.2.13)
- builder (~> 3.0.0)
- activerecord (3.2.13)
- activemodel (= 3.2.13)
- activesupport (= 3.2.13)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activeresource (3.2.13)
- activemodel (= 3.2.13)
- activesupport (= 3.2.13)
- activesupport (3.2.13)
- i18n (= 0.6.1)
- multi_json (~> 1.0)
- arel (3.0.2)
- builder (3.0.4)
- coderay (1.0.9)
- columnize (0.3.6)
- debugger (1.5.0)
- columnize (>= 0.3.1)
- debugger-linecache (~> 1.2.0)
- debugger-ruby_core_source (~> 1.2.0)
- debugger-linecache (1.2.0)
- debugger-ruby_core_source (1.2.0)
- erubis (2.7.0)
- execjs (1.4.0)
- multi_json (~> 1.0)
- hike (1.2.1)
- i18n (0.6.1)
- journey (1.0.4)
- jquery-rails (2.2.1)
- railties (>= 3.0, < 5.0)
- thor (>= 0.14, < 2.0)
- json (1.7.7)
- mail (2.5.3)
- i18n (>= 0.4.0)
- mime-types (~> 1.16)
- treetop (~> 1.4.8)
- method_source (0.8.1)
- mime-types (1.21)
- multi_json (1.7.1)
- polyglot (0.3.3)
- pry (0.9.12)
- coderay (~> 1.0.5)
- method_source (~> 0.8)
- slop (~> 3.4)
- pry-debugger (0.2.2)
- debugger (~> 1.3)
- pry (~> 0.9.10)
- rack (1.4.5)
- rack-cache (1.2)
- rack (>= 0.4)
- rack-ssl (1.3.3)
- rack
- rack-test (0.6.2)
- rack (>= 1.0)
- rails (3.2.13)
- actionmailer (= 3.2.13)
- actionpack (= 3.2.13)
- activerecord (= 3.2.13)
- activeresource (= 3.2.13)
- activesupport (= 3.2.13)
- bundler (~> 1.0)
- railties (= 3.2.13)
- railties (3.2.13)
- actionpack (= 3.2.13)
- activesupport (= 3.2.13)
- rack-ssl (~> 1.3.2)
- rake (>= 0.8.7)
- rdoc (~> 3.4)
- thor (>= 0.14.6, < 2.0)
- rake (10.0.3)
- rdoc (3.12.2)
- json (~> 1.4)
- sass (3.2.6)
- sass-rails (3.2.6)
- railties (~> 3.2.0)
- sass (>= 3.1.10)
- tilt (~> 1.3)
- slop (3.4.4)
- sprockets (2.2.2)
- hike (~> 1.2)
- multi_json (~> 1.0)
- rack (~> 1.0)
- tilt (~> 1.1, != 1.3.0)
- thor (0.17.0)
- tilt (1.3.6)
- treetop (1.4.12)
- polyglot
- polyglot (>= 0.3.1)
- tzinfo (0.3.37)
- uglifier (1.3.0)
- execjs (>= 0.3.0)
- multi_json (~> 1.0, >= 1.0.2)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- css_splitter!
- jquery-rails
- pry-debugger
- sass-rails
- uglifier
diff --git a/README.md b/README.md
index a52bd97..d1b3805 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,11 @@
-# CssSplitter [](https://travis-ci.org/zweilove/css_splitter) [](https://gemnasium.com/zweilove/css_splitter)
+# CssSplitter [](https://travis-ci.org/zweilove/css_splitter)
Gem for splitting up stylesheets that go beyond the IE limit of 4096 selectors, for Rails 3.1+ apps using the Asset Pipeline. You can read this [blogpost](http://railslove.com/blog/2013/03/08/overcoming-ies-4096-selector-limit-using-the-css-splitter-gem) for an explanation of this gem's background story.
+### Development status
+
+Fortunately, the problem of too large CSS files is long gone. This repo is unmaintained.
+It remains as an artefact of dark times in the history of web browsers.
## Installation
@@ -16,22 +20,26 @@ CssSplitter integrates with the Rails 3.1+ Asset Pipeline to generate additional
## Dependencies
-* Rails 3.1+
-* Asset Pipeline
+* Sprockets 2.0+
+* e.g. Rails 3.1+ with the asset pipeline
## Documentation
### 1. Splitting your stylesheets
-The first step is indentifying the stylesheets that have more than 4095 selectors and therefore need to be split for IE.
+The first step is identifying the stylesheets that have more than 4095 selectors and therefore need to be split for IE.
+
+Once you know which stylesheets need to be split, you need to create a second "container file" for those stylesheets with the `_split2` suffix appended to the base filename that will contain the styles beyond the 4095 selector limit. The extension of this file should be just `.css` without any additional preprocessor extensions.
-Once you know which stylesheets need to be split, you need to create a second "container file" for those stylesheets with the file extension `.split2`, that will contain the styles beyond the 4095 selector limit.
+For example, if you want to split `too_big_stylesheet.css.scss`, you need to create a new file `too_big_stylesheet_split2.css` in the same directory. The only content of that container, will contain a `require` directive to the name of the original asset, e.g.:
-For example, if you want to split `too_big_stylesheet.css`, you need to create a new file `too_big_stylesheet_split2.css.split2` in the same directory. The only content of that container, will be an include of the original file, e.g.:
+ # app/assets/stylesheets/too_big_stylesheet_split2.css
- # app/assets/stylesheets/too_big_stylesheet_split2.css.split2
+ /*
+ *= require 'too_big_stylesheet'
+ */
- //= include 'too_big_stylesheet.css'
+If your stylesheet is big enough to need splitting into more than two more files, simply create additional `_split3`, `_split4`, etc. files, the contents of which should be identical to the `_split2` file.
You also need to remember to add those new files to the asset pipeline, so they will be compiled. For example:
@@ -43,12 +51,10 @@ You also need to remember to add those new files to the asset pipeline, so they
Here is a checklist of requirements for your split stylesheet:
-1. It needs to have different filename than orginal, e.g. `original_stylesheet_split2` or `application_split2`
-2. It needs to have `.split2` as the terminal file extension, e.g. `.css.split2` or `.css.sass.split2`
-3. It needs to include the content of the orginal stylesheet, e.g. through `//= include 'application'`
-4. It needs to be added to list of precompiled assets
-
-
+1. It needs to have the `_splitN` suffix appended to the original asset name, e.g. `original_stylesheet_split2` or `application_split2`
+2. It needs to have `.css` as a file extension.
+3. It needs to require the orginal stylesheet.
+4. It needs to be added to list of precompiled assets.
### 2. Including your split stylesheets
@@ -60,62 +66,46 @@ You can just use our `split_stylesheet_link_tag` helper, which would look someth
<%= split_stylesheet_link_tag "too_big_stylesheet", :media => "all" %>
# output
-
+
+If your stylesheet is split into more than two files, add the `split_count` option to specify the total number of files.
+
+ <%= split_stylesheet_link_tag "too_big_stylesheet", :split_count => 3 %>
+
Or you can just create similar HTML as in the above example yourself. If you want to use the `split_stylesheet_link_tag` helper you need to make sure the gem is loaded in production, so you can't put it in the `:assets` group in your Gemfile.
## How it works
-Basically, CssSplitter is registering a new `Sprockets::Engine` for the `.split2` file extension, that will fill those files with all the selectors beyond the 4095th. Unfortunately, those `.split2` files need to be created manually, because we haven't figured out a way for a `Sprockets::Engine` to output multiple files. They need to present before the compile step.
+Basically, CssSplitter is registering a new Sprockets bundle processor that looks for CSS assets named with the `_splitN` suffix and will fill those files with all the selectors beyond the 4095th. Unfortunately, those `_splitN` files need to be created manually, because we haven't figured out a way for a `Sprockets::Engine` to output multiple files. They need to present before the compile step.
If you have more questions about how it works, look at the code or contact us.
## Gotchas
-#### Having a JS asset with the same name as the the split stylesheet
-
-If you want to split a style (e.g. `assets/stylesheets/application.*`) and have a JS asset with the same name (`assets/javascripts/application.*`) in your asset load_path (as is the default in Rails), you need to include the stylesheet along with the file extension `// = include 'application.css'` because otherwise it will try to include the JS asset of the same name instead. Sprocket's `= include` directive doesn't seem to differentiate between different types/folders and just takes the first asset it can find for any given name (see #10).
-
-#### Don't use Sprocket's `= require_tree .` or `= require_self` for stylesheets
-It's recommended that you **always use Sass's `@import`** for all your stylesheets in favor of Sprocket's `= require` directives, just as the official `sass-rails` gem says: https://github.com/rails/sass-rails#important-note
+#### Differences from previous versions
-If you have a `.split2` stylesheet in your tree that in turn includes the base stylesheet like shown below, you will end up with a nasty `Sprockets::CircularDependencyError`!
+Note that if you used versions below `0.4.0` of this gem, the naming and contents of the split files have changed. Split files no longer need to have the `.split2` extension and now use the `require` directive rather than the `include` directive. The previous prohibition against using `require_tree .` and `require_self` directives also no longer applies. For more details see the [CHANGELOG.md](CHANGELOG.md#040)
- /* assets/stylesheets/application.css */
- /* = require_tree .
-
- /* assets/stylesheets/application_split2.css.split2 */
- /* = include 'application.css' */
+#### Empty *_split2.css file
-If you have `require_self` in the stylesheet that you're splitting, as shown below, the `.split2` will end up having **both** the original stylesheet and the split contents. You'll end up with an even bigger stylesheet.
+Since 0.4.1 in development split stylesheets have `debug: false` option by default. This prevents the empty `*_split2.css` file issue. You can always explicitly go one way or the other setting `debug` option directly in the `split_stylesheet_link_tag` like this:
- /* assets/stylesheets/application.css */
- /* = require_self
-
- /* assets/stylesheets/application_split2.css.split2 */
- /* = include 'application.css' */
+```
+<%= split_stylesheet_link_tag "application", debug: false %>
+```
+## Credits & License
-## Limitations & Known Issues
-
-**More than 8190 selectors**
-
-Currently the gem only supports stylesheets that need to be split into 2 files. It could theoretically create more splits (e.g. if you should have more than 8190 selectors), but in that case you should probably refactor your stylesheets anyway. Contact us, if you have this requirement.
-
-**@media queries**
-
-The selector counting algorithm is currently not counting `@media` queries correctly. For each `@media` query it is adding one additional selector to the count (which is actually not a problem in most cases).
-
-If you have a `@media` query spawning right over the 4096 selector barrier, it will probably get ripped apart into the two splits and ultimately produce broken CSS. You can either try to move the `@media` queries (e.g. before the 4096 selector barrier) or help us fix this issue.
-
+This is a joint project by the two German Rails shops [Zweitag](https://zweitag.de) and [Railslove](https://railslove.com), therefore the GitHub name "Zweilove".
-## Credits & License
+The original code was written by Christian Peters and Thomas Hollstegge (see this [Gist](https://gist.github.com/2398394)) and turned into a gem by Jakob Hilden.
-This is a joint project by the two German Rails shops [Zweitag](http://zweitag.de) and [Railslove](http://railslove.com), therefore the GitHub name "Zweilove".
+**Major Contributors**
-The original code was written by [Christian Peters](mailto:christian.peters@zweitag.de) and [Thomas Hollstegge](mailto:thomas.hollstegge@zweitag.de) (see this [Gist](https://gist.github.com/2398394)) and turned into a gem by [Jakob Hilden](mailto:jakobhilden@gmail.com).
+* [@Umofomia](https://github.com/Umofomia)
+* [@kruszczynski](https://github.com/kruszczynski)
-This project rocks and uses MIT-LICENSE.
+This project uses MIT-LICENSE.
diff --git a/app/helpers/css_splitter/application_helper.rb b/app/helpers/css_splitter/application_helper.rb
index 644a071..ecfd2ef 100644
--- a/app/helpers/css_splitter/application_helper.rb
+++ b/app/helpers/css_splitter/application_helper.rb
@@ -1,18 +1,24 @@
module CssSplitter
module ApplicationHelper
def split_stylesheet_link_tag(*sources)
- original_sources = sources.dup
+ options = sources.extract_options!
+ split_count = options.delete(:split_count) || 2
- options = sources.extract_options!
- sources.collect!{ |source| "#{source}_split2" }
- sources << options
+ sources.map do |source|
+ split_sources = (2..split_count).map { |index| "#{source}_split#{index}" }
+ split_options = options.dup
+ if Rails.env == 'development' && !split_options.key?(:debug)
+ split_options[:debug] = false
+ end
+ split_sources << split_options
- [
- stylesheet_link_tag(*original_sources),
- ""
- ].join("\n").html_safe
+ [
+ stylesheet_link_tag(source, options),
+ ""
+ ]
+ end.flatten.join("\n").html_safe
end
end
-end
\ No newline at end of file
+end
diff --git a/css_splitter.gemspec b/css_splitter.gemspec
index 84286e8..4a19196 100644
--- a/css_splitter.gemspec
+++ b/css_splitter.gemspec
@@ -17,5 +17,7 @@ Gem::Specification.new do |s|
s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"]
s.test_files = Dir["test/**/*"]
- s.add_dependency "rails", "~> 3.1"
+ s.add_dependency "sprockets", ">= 2.0.0"
+
+ s.add_development_dependency "rails", ">= 3.1"
end
diff --git a/lib/css_splitter.rb b/lib/css_splitter.rb
index 7a19c44..a5b2457 100644
--- a/lib/css_splitter.rb
+++ b/lib/css_splitter.rb
@@ -1,4 +1,4 @@
-require "css_splitter/engine"
+require "css_splitter/engine" if defined?(Rails)
require "css_splitter/sprockets_engine"
require "css_splitter/splitter"
diff --git a/lib/css_splitter/engine.rb b/lib/css_splitter/engine.rb
index 4352159..05a1fae 100644
--- a/lib/css_splitter/engine.rb
+++ b/lib/css_splitter/engine.rb
@@ -1,14 +1,19 @@
module CssSplitter
class Engine < ::Rails::Engine
- isolate_namespace CssSplitter
-
initializer 'css_splitter.sprockets_engine', after: 'sprockets.environment', group: :all do |app|
- app.assets.register_engine '.split2', CssSplitter::SprocketsEngine
+ if app.config.assets.public_methods.include? :configure
+ app.config.assets.configure do |assets|
+ assets.register_bundle_processor 'text/css', CssSplitter::SprocketsEngine
+ end
+ else
+ app.assets.register_bundle_processor 'text/css', CssSplitter::SprocketsEngine
+ end
end
initializer 'css_splitter.action_controller' do |app|
ActiveSupport.on_load :action_controller do
- helper CssSplitter::ApplicationHelper
+ # Not all controllers use helpers (such as API based controllers)
+ helper CssSplitter::ApplicationHelper if respond_to?(:helper)
end
end
end
diff --git a/lib/css_splitter/splitter.rb b/lib/css_splitter/splitter.rb
index c979faf..f5f6a25 100644
--- a/lib/css_splitter/splitter.rb
+++ b/lib/css_splitter/splitter.rb
@@ -12,7 +12,28 @@ def self.split_string(css_string, split = 1, max_selectors = MAX_SELECTORS_DEFAU
# splits string into array of rules (also strips comments)
def self.split_string_into_rules(css_string)
- strip_comments(css_string).chomp.scan /[^}]*}/
+ partial_rules = strip_comments(css_string).chomp.scan /[^}]*}/
+ whole_rules = []
+ bracket_balance = 0
+ in_media_query = false
+
+ partial_rules.each do |rule|
+ if rule =~ /^\s*@media/
+ in_media_query = true
+ elsif bracket_balance == 0
+ in_media_query = false
+ end
+
+ if bracket_balance == 0 || in_media_query
+ whole_rules << rule
+ else
+ whole_rules.last << rule
+ end
+
+ bracket_balance += get_rule_bracket_balance rule
+ end
+
+ whole_rules
end
# extracts the specified part of an overlong CSS string
@@ -26,23 +47,50 @@ def self.extract_part(rules, part = 1, max_selectors = MAX_SELECTORS_DEFAULT)
selectors_count = 0
selector_range = max_selectors * (part - 1) + 1 .. max_selectors * part # e.g (4096..8190)
+ current_media = nil
+ selectors_in_media = 0
+ first_hit = true
rules.each do |rule|
+ media_part = extract_media(rule)
+ if media_part
+ current_media = media_part
+ selectors_in_media = 0
+ end
+
rule_selectors_count = count_selectors_of_rule rule
selectors_count += rule_selectors_count
+ if rule =~ /\A\s*}\z$/
+ current_media = nil
+ # skip the line if the close bracket is the first rule for the new file
+ next if first_hit
+ end
+
if selector_range.cover? selectors_count # add rule to current output if within selector_range
+ if media_part
+ output << media_part
+ elsif first_hit && current_media
+ output << current_media
+ end
+ selectors_in_media += rule_selectors_count if current_media.present?
output << rule
+ first_hit = false
elsif selectors_count > selector_range.end # stop writing to output
break
end
end
+ if current_media.present? and selectors_in_media > 0
+ output << '}'
+ end
+
output
end
# count selectors of one individual CSS rule
def self.count_selectors_of_rule(rule)
- strip_comments(rule).partition(/\{/).first.scan(/,/).count.to_i + 1
+ parts = strip_comments(rule).partition(/\{/)
+ parts.second.empty? ? 0 : parts.first.scan(/,/).count.to_i + 1
end
@@ -61,6 +109,12 @@ def self.count_selectors(css_file)
private
+ def self.extract_media(rule)
+ if rule.sub!(/^\s*(@media[^{]*{)([^{}]*{[^}]*})$/) { $2 }
+ $1
+ end
+ end
+
# extracts potential charset declaration from the first rule
def self.extract_charset(rule)
if rule.include?('charset')
@@ -74,6 +128,10 @@ def self.strip_comments(s)
s.gsub(/\/\*.*?\*\//m, "")
end
+ def self.get_rule_bracket_balance ( rule )
+ rule.scan( /}/ ).size - rule.scan( /{/ ).size
+ end
+
end
end
diff --git a/lib/css_splitter/sprockets_engine.rb b/lib/css_splitter/sprockets_engine.rb
index 9f40c03..551af8c 100644
--- a/lib/css_splitter/sprockets_engine.rb
+++ b/lib/css_splitter/sprockets_engine.rb
@@ -10,10 +10,30 @@ def self.engine_initialized?
def prepare
end
+ def self.call(input)
+ data_in = input[:data]
+
+ # Instantiate Sprockets::Context to pass along helper methods for Tilt
+ # processors
+ context = input[:environment].context_class.new(input)
+
+ # Pass the asset file contents as a block to the template engine,
+ # then get the results of the engine rendering
+ engine = self.new { data_in }
+ rendered_data = engine.render(context, {})
+
+ # Return the data and any metadata (ie file dependencies, etc)
+ context.metadata.merge(data: rendered_data.to_str)
+ end
+
def evaluate(scope, locals, &block)
- split = scope.pathname.extname =~ /(\d+)$/ && $1 || 0 # determine which is the current split (e.g. split2, split3)
- CssSplitter::Splitter.split_string data, split.to_i
+ # Evaluate the split if the asset is named with a trailing _split2, _split3, etc.
+ if scope.logical_path =~ /_split(\d+)$/
+ CssSplitter::Splitter.split_string(data, $1.to_i)
+ else
+ data
+ end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/css_splitter/version.rb b/lib/css_splitter/version.rb
index d866b50..57859d1 100644
--- a/lib/css_splitter/version.rb
+++ b/lib/css_splitter/version.rb
@@ -1,3 +1,3 @@
module CssSplitter
- VERSION = "0.1.1"
+ VERSION = "0.4.6"
end
diff --git a/test/css_splitter_test.rb b/test/css_splitter_test.rb
index 7fd8634..012cf89 100644
--- a/test/css_splitter_test.rb
+++ b/test/css_splitter_test.rb
@@ -1,7 +1,40 @@
require 'test_helper'
class CssSplitterTest < ActiveSupport::TestCase
+
+ setup :clear_assets_cache
+
test "truth" do
assert_kind_of Module, CssSplitter
end
+
+ test "asset pipeline stylesheet splitting" do
+ part1 = "#test{background-color:red}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
+ part2 = "#test{background-color:green}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
+ part3 = "#test{background-color:blue}"
+
+ assert_equal "#{part1}#{part2}#{part3}", assets["erb_stylesheet"].to_s.gsub(/\s/, '')
+ assert_equal "#{part2}", assets["erb_stylesheet_split2"].to_s.gsub(/\s/, '')
+ assert_equal "#{part3}", assets["erb_stylesheet_split3"].to_s.gsub(/\s/, '')
+ end
+
+ test "asset pipeline stylesheet splitting on stylesheet combined using requires" do
+ red = "#test{background-color:red}" * 100
+ green = "#test{background-color:green}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
+ blue = "#test{background-color:blue}"
+ assert_equal "#{red}#{green}#{blue}", assets["combined"].to_s.gsub(/\s/, '')
+ assert_equal "#{"#test{background-color:green}" * 100}#{blue}", assets["combined_split2"].to_s.gsub(/\s/, '')
+ end
+
+ private
+
+ def clear_assets_cache
+ assets_cache = Rails.root.join("tmp/cache/assets")
+ assets_cache.rmtree if assets_cache.exist?
+ end
+
+ def assets
+ Rails.application.assets
+ end
+
end
diff --git a/test/dummy/app/assets/stylesheets/combined.css.scss b/test/dummy/app/assets/stylesheets/combined.css.scss
new file mode 100644
index 0000000..5fd8ab4
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/combined.css.scss
@@ -0,0 +1,4 @@
+//= require 'red_100'
+//= require 'green_max'
+
+#test { background-color: blue; }
diff --git a/test/dummy/app/assets/stylesheets/combined_split2.css b/test/dummy/app/assets/stylesheets/combined_split2.css
new file mode 100644
index 0000000..cc3963c
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/combined_split2.css
@@ -0,0 +1,3 @@
+/*
+ *= require 'combined'
+ */
diff --git a/test/dummy/app/assets/stylesheets/erb_stylesheet.css.scss.erb b/test/dummy/app/assets/stylesheets/erb_stylesheet.css.scss.erb
new file mode 100644
index 0000000..de64edc
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/erb_stylesheet.css.scss.erb
@@ -0,0 +1,7 @@
+<% CssSplitter::Splitter::MAX_SELECTORS_DEFAULT.times do %>
+#test { background-color: red; }
+<% end %>
+<% CssSplitter::Splitter::MAX_SELECTORS_DEFAULT.times do %>
+#test { background-color: green; }
+<% end %>
+#test { background-color: blue; }
diff --git a/test/dummy/app/assets/stylesheets/erb_stylesheet_split2.css b/test/dummy/app/assets/stylesheets/erb_stylesheet_split2.css
new file mode 100644
index 0000000..2c6b6e1
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/erb_stylesheet_split2.css
@@ -0,0 +1,3 @@
+/*
+ *= require 'erb_stylesheet.css'
+ */
diff --git a/test/dummy/app/assets/stylesheets/erb_stylesheet_split3.css b/test/dummy/app/assets/stylesheets/erb_stylesheet_split3.css
new file mode 100644
index 0000000..2c6b6e1
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/erb_stylesheet_split3.css
@@ -0,0 +1,3 @@
+/*
+ *= require 'erb_stylesheet.css'
+ */
diff --git a/test/dummy/app/assets/stylesheets/green_max.css.scss.erb b/test/dummy/app/assets/stylesheets/green_max.css.scss.erb
new file mode 100644
index 0000000..df75a7f
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/green_max.css.scss.erb
@@ -0,0 +1,3 @@
+<% CssSplitter::Splitter::MAX_SELECTORS_DEFAULT.times do %>
+#test { background-color: green; }
+<% end %>
diff --git a/test/dummy/app/assets/stylesheets/red_100.css.scss.erb b/test/dummy/app/assets/stylesheets/red_100.css.scss.erb
new file mode 100644
index 0000000..ae6effd
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/red_100.css.scss.erb
@@ -0,0 +1,3 @@
+<% 100.times do %>
+#test { background-color: red; }
+<% end %>
diff --git a/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css b/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css
new file mode 100644
index 0000000..23b2f80
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css
@@ -0,0 +1,3 @@
+/*
+ *= require 'test_stylesheet_with_media_queries'
+ */
diff --git a/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css.split2 b/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css.split2
deleted file mode 100644
index b8ab087..0000000
--- a/test/dummy/app/assets/stylesheets/test_stylesheet_with_media_queries_split2.css.split2
+++ /dev/null
@@ -1 +0,0 @@
-//= include 'test_stylesheet_with_media_queries'
\ No newline at end of file
diff --git a/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css b/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css
new file mode 100644
index 0000000..1cf401d
--- /dev/null
+++ b/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css
@@ -0,0 +1,3 @@
+/*
+ *= require 'too_big_stylesheet.css'
+ */
diff --git a/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css.split2 b/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css.split2
deleted file mode 100644
index ffa49f3..0000000
--- a/test/dummy/app/assets/stylesheets/too_big_stylesheet_split2.css.split2
+++ /dev/null
@@ -1 +0,0 @@
-//= include 'too_big_stylesheet.css'
\ No newline at end of file
diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb
index 9fa37cd..f9e8544 100644
--- a/test/dummy/app/views/layouts/application.html.erb
+++ b/test/dummy/app/views/layouts/application.html.erb
@@ -5,7 +5,7 @@
<%= stylesheet_link_tag "application", :media => "all" %>
- <%= split_stylesheet_link_tag "too_big_stylesheet", :media => "all" %>
+ <%= split_stylesheet_link_tag "too_big_stylesheet", :media => "all", :debug => true %>
<%= csrf_meta_tags %>
diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb
index 9f787b4..7a5b60e 100644
--- a/test/dummy/config/application.rb
+++ b/test/dummy/config/application.rb
@@ -3,7 +3,6 @@
# require 'rails/all'
require "action_controller/railtie"
require "action_mailer/railtie"
-require "active_resource/railtie"
require "rails/test_unit/railtie"
require "sprockets/railtie"
@@ -39,7 +38,8 @@ class Application < Rails::Application
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
-
+ config.sass.line_comments = false
+ config.assets.compress = true
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
@@ -56,9 +56,6 @@ class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
-
- # Version of your assets, change this if you want to expire all your assets
- config.assets.version = '1.0'
end
end
diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb
index 50105b3..ef8997c 100644
--- a/test/dummy/config/environments/development.rb
+++ b/test/dummy/config/environments/development.rb
@@ -34,4 +34,6 @@
# Expands the lines which load the assets
config.assets.debug = true
+
+ config.eager_load = false
end
diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb
index b178724..d92c150 100644
--- a/test/dummy/config/environments/production.rb
+++ b/test/dummy/config/environments/production.rb
@@ -9,7 +9,7 @@
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
- config.serve_static_assets = false
+ config.serve_static_files = false
# Compress JavaScripts and CSS
config.assets.compress = true
@@ -31,7 +31,7 @@
# config.force_ssl = true
# See everything in the log (default is :info)
- # config.log_level = :debug
+ config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
@@ -45,9 +45,6 @@
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
- # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
- config.assets.precompile += %w( too_big_stylesheet.css too_big_stylesheet_split2.css test_stylesheet_with_media_queries.css test_stylesheet_with_media_queries_split2.css )
-
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
@@ -64,4 +61,6 @@
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ config.eager_load = true
end
diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb
index 6feb3d2..3171e7c 100644
--- a/test/dummy/config/environments/test.rb
+++ b/test/dummy/config/environments/test.rb
@@ -8,7 +8,7 @@
config.cache_classes = true
# Configure static asset server for tests with Cache-Control for performance
- config.serve_static_assets = true
+ config.serve_static_files = true
config.static_cache_control = "public, max-age=3600"
# Log error messages when you accidentally call methods on nil
@@ -29,9 +29,14 @@
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
+ # run tests in a random order
+ config.active_support.test_order = :random
+
# Raise exception on mass assignment protection for Active Record models
# config.active_record.mass_assignment_sanitizer = :strict
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
+
+ config.eager_load = false
end
diff --git a/test/dummy/config/initializers/assets.rb b/test/dummy/config/initializers/assets.rb
new file mode 100644
index 0000000..91073da
--- /dev/null
+++ b/test/dummy/config/initializers/assets.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = '1.0'
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
+Rails.application.config.assets.precompile += %w( too_big_stylesheet.css too_big_stylesheet_split2.css test_stylesheet_with_media_queries.css test_stylesheet_with_media_queries_split2.css )
\ No newline at end of file
diff --git a/test/dummy/config/secrets.yml b/test/dummy/config/secrets.yml
new file mode 100644
index 0000000..5dc368e
--- /dev/null
+++ b/test/dummy/config/secrets.yml
@@ -0,0 +1,4 @@
+test:
+ secret_key_base: c2a98602cc1537b2e38d4f279f20d24db66ff86fe523ab5197529f2ea907b6d70e2dca2fa3da50dcc9cad7bb1b861f0c45b6920fc576cc3e170d8c1ded61887f
+development:
+ secret_key_base: c2a98602cc1537b2e38d4f279f20d24db66ff86fe523ab5197529f2ea907b6d70e2dca2fa3da50dcc9cad7bb1b861f0c45b6920fc576cc3e170d8c1ded61887f
\ No newline at end of file
diff --git a/test/unit/helpers/css_splitter/application_helper_test.rb b/test/unit/helpers/css_splitter/application_helper_test.rb
index 1fedb0a..4dc8d39 100644
--- a/test/unit/helpers/css_splitter/application_helper_test.rb
+++ b/test/unit/helpers/css_splitter/application_helper_test.rb
@@ -5,13 +5,41 @@ class ApplicationHelperTest < ActionView::TestCase
test "should work w/out options" do
output = split_stylesheet_link_tag("too_big_stylesheet")
- assert_equal "\n", output
+ assert_equal "\n", output
end
test "should work with options and multiple stylesheets" do
output = split_stylesheet_link_tag("too_big_stylesheet", "foo", media: "print")
- assert_equal "\n\n", output
+ assert_equal "\n\n\n", output
end
+ test "should work with split_count option" do
+ output = split_stylesheet_link_tag("too_big_stylesheet", split_count: 3)
+ assert_equal "\n", output
+ end
+
+ class RailsEnvDefault < ActionView::TestCase
+ setup do
+ Rails.env = 'development'
+ end
+
+ teardown do
+ Rails.env = 'test'
+ end
+
+ test "should default to false on splits" do
+ output = split_stylesheet_link_tag("too_big_stylesheet")
+ assert_equal "\n", output
+ end
+
+ test "should respect the debug=true option" do
+ output = split_stylesheet_link_tag("too_big_stylesheet", debug: true)
+ assert_equal "\n", output
+ end
+ test "should respect the debug=false option" do
+ output = split_stylesheet_link_tag("too_big_stylesheet", debug: false)
+ assert_equal "\n", output
+ end
+ end
end
end
diff --git a/test/unit/splitter_test.rb b/test/unit/splitter_test.rb
index 42bb29e..f9713ea 100644
--- a/test/unit/splitter_test.rb
+++ b/test/unit/splitter_test.rb
@@ -2,12 +2,15 @@
class CssSplitterTest < ActiveSupport::TestCase
test "#count_selectors" do
- assert_equal 2938, CssSplitter::Splitter.count_selectors('test/unit/too_many_selectors.css')
+ assert_equal 2937, CssSplitter::Splitter.count_selectors('test/unit/too_many_selectors.css')
end
test "#count_selectors_of_rule" do
assert_equal 1, CssSplitter::Splitter.count_selectors_of_rule('foo { color: baz; }')
assert_equal 2, CssSplitter::Splitter.count_selectors_of_rule('foo, bar { color: baz; }')
+
+ # split_string_into_rules splits the closing brace of a media query into its own rule
+ assert_equal 0, CssSplitter::Splitter.count_selectors_of_rule('}')
end
# --- split_string_into_rules ---
@@ -32,6 +35,21 @@ class CssSplitterTest < ActiveSupport::TestCase
assert_equal ["a{foo:url(//assets.server.com);}", "b{bar:url(//assets/server.com);}"], CssSplitter::Splitter.split_string_into_rules(simple)
end
+ test '#split_string_into_rules containing media queries' do
+ has_media = "a{foo:bar;}@media print{b{baz:qux;}c{quux:corge;}}d{grault:garply;}"
+ assert_equal ["a{foo:bar;}", "@media print{b{baz:qux;}", "c{quux:corge;}", "}", "d{grault:garply;}"], CssSplitter::Splitter.split_string_into_rules(has_media)
+ end
+
+ test '#split_string_into_rules containing media queries with leading whitespace' do
+ has_media = "a{foo:bar;}\n @media print{b{baz:qux;}c{quux:corge;}}d{grault:garply;}"
+ assert_equal ["a{foo:bar;}", "\n @media print{b{baz:qux;}", "c{quux:corge;}", "}", "d{grault:garply;}"], CssSplitter::Splitter.split_string_into_rules(has_media)
+ end
+
+ test "#split_string_into_rules containing keyframes" do
+ has_keyframes = "a{foo:bar;}@keyframes rubes{from{baz:qux;}50%{quux:corge;}}d{grault:garply;}"
+ assert_equal ["a{foo:bar;}", "@keyframes rubes{from{baz:qux;}50%{quux:corge;}}", "d{grault:garply;}"], CssSplitter::Splitter.split_string_into_rules(has_keyframes)
+ end
+
# --- extract_charset ---
test '#extract_charset with no charset' do
@@ -44,12 +62,134 @@ class CssSplitterTest < ActiveSupport::TestCase
assert_equal ['@charset "UTF-8";', ' .foo { color: black; }'], CssSplitter::Splitter.send(:extract_charset, first_rule)
end
+ # --- extract_media ---
+
+ test '#extract_media with no media block' do
+ first_rule = ".foo { color: black; }"
+ assert_equal nil, CssSplitter::Splitter.send(:extract_media, first_rule)
+ end
+
+ test '#extract_media with media block' do
+ first_rule = <