Merge branch 'stable' of github.com:chriseppstein/compass into stable
This commit is contained in:
commit
1f17603aea
@ -7,8 +7,8 @@ GIT
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
compass (0.11.3.e4a22c4)
|
compass (0.11.3.a6a7069)
|
||||||
chunky_png (~> 1.1)
|
chunky_png (~> 1.2)
|
||||||
fssm (>= 0.2.7)
|
fssm (>= 0.2.7)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ Gem::Specification.new do |gemspec|
|
|||||||
gemspec.summary = %q{A Real Stylesheet Framework}
|
gemspec.summary = %q{A Real Stylesheet Framework}
|
||||||
|
|
||||||
gemspec.add_dependency 'sass', '~> 3.1'
|
gemspec.add_dependency 'sass', '~> 3.1'
|
||||||
gemspec.add_dependency 'chunky_png', '~> 1.1'
|
gemspec.add_dependency 'chunky_png', '~> 1.2'
|
||||||
gemspec.add_dependency 'fssm', '>= 0.2.7'
|
gemspec.add_dependency 'fssm', '>= 0.2.7'
|
||||||
|
|
||||||
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
||||||
|
@ -308,9 +308,12 @@ the asset host configuration is ignored.
|
|||||||
---
|
---
|
||||||
|
|
||||||
**`asset_cache_buster`** – Pass this function a block of code that defines the
|
**`asset_cache_buster`** – Pass this function a block of code that defines the
|
||||||
cache buster strategy to be used. The block must return nil or a string that can
|
cache buster strategy to be used. The block must return nil, a string or a hash.
|
||||||
be appended to a url as a query parameter. The returned string must not include
|
If the returned value is a hash the values of :path and/or :query is used to generate
|
||||||
the starting `?`. The block will be passed the root-relative url of the asset.
|
a cache busted path to the asset. If a string value is returned, it is added as a query string.
|
||||||
|
The returned values for query strings must not include the starting `?`.
|
||||||
|
|
||||||
|
The block will be passed the root-relative url of the asset.
|
||||||
If the block accepts two arguments, it will also be passed a path
|
If the block accepts two arguments, it will also be passed a path
|
||||||
that points to the asset on disk — which may or may not exist.
|
that points to the asset on disk — which may or may not exist.
|
||||||
|
|
||||||
@ -324,6 +327,18 @@ that points to the asset on disk — which may or may not exist.
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Busting the cache via path:
|
||||||
|
|
||||||
|
asset_cache_buster do |path, real_path|
|
||||||
|
if File.exists?(real_path)
|
||||||
|
pathname = Pathname.new(path)
|
||||||
|
modified_time = File.mtime(real_path).strftime("%s")
|
||||||
|
new_path = "%s/%s-%s%s" % [pathname.dirname, pathname.basename(pathname.extname), modified_time, pathname.extname]
|
||||||
|
|
||||||
|
{:path => new_path, :query => nil}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
To disable the asset cache buster:
|
To disable the asset cache buster:
|
||||||
|
|
||||||
asset_cache_buster :none
|
asset_cache_buster :none
|
||||||
|
@ -145,6 +145,7 @@ Feature: Command Line
|
|||||||
Scenario: Basic help
|
Scenario: Basic help
|
||||||
When I run: compass help
|
When I run: compass help
|
||||||
Then I should see the following "primary" commands:
|
Then I should see the following "primary" commands:
|
||||||
|
| clean |
|
||||||
| compile |
|
| compile |
|
||||||
| create |
|
| create |
|
||||||
| init |
|
| init |
|
||||||
@ -179,6 +180,27 @@ Feature: Command Line
|
|||||||
And I run: compass compile
|
And I run: compass compile
|
||||||
And a css file tmp/layout.css is reported overwritten
|
And a css file tmp/layout.css is reported overwritten
|
||||||
|
|
||||||
|
Scenario: Cleaning a project
|
||||||
|
Given I am using the existing project in test/fixtures/stylesheets/compass
|
||||||
|
When I run: compass compile
|
||||||
|
And I run: compass clean
|
||||||
|
Then the following files are reported removed:
|
||||||
|
| .sass-cache/ |
|
||||||
|
| tmp/border_radius.css |
|
||||||
|
| tmp/box.css |
|
||||||
|
| tmp/box_shadow.css |
|
||||||
|
| tmp/columns.css |
|
||||||
|
| tmp/fonts.css |
|
||||||
|
| images/flag-s03c3b29b35.png |
|
||||||
|
And the following files are removed:
|
||||||
|
| .sass-cache/ |
|
||||||
|
| tmp/border_radius.css |
|
||||||
|
| tmp/box.css |
|
||||||
|
| tmp/box_shadow.css |
|
||||||
|
| tmp/columns.css |
|
||||||
|
| tmp/fonts.css |
|
||||||
|
| images/flag-s03c3b29b35.png |
|
||||||
|
|
||||||
Scenario: Watching a project for changes
|
Scenario: Watching a project for changes
|
||||||
Given ruby supports fork
|
Given ruby supports fork
|
||||||
Given I am using the existing project in test/fixtures/stylesheets/compass
|
Given I am using the existing project in test/fixtures/stylesheets/compass
|
||||||
@ -218,7 +240,6 @@ Feature: Command Line
|
|||||||
| sass_dir | sass |
|
| sass_dir | sass |
|
||||||
| css_dir | assets/css |
|
| css_dir | assets/css |
|
||||||
|
|
||||||
@now
|
|
||||||
Scenario Outline: Print out a configuration value
|
Scenario Outline: Print out a configuration value
|
||||||
Given I am using the existing project in test/fixtures/stylesheets/compass
|
Given I am using the existing project in test/fixtures/stylesheets/compass
|
||||||
When I run: compass config -p <property>
|
When I run: compass config -p <property>
|
||||||
|
@ -116,10 +116,30 @@ Then /^a directory ([^ ]+) is (not )?created$/ do |directory, negated|
|
|||||||
File.directory?(directory).should == !negated
|
File.directory?(directory).should == !negated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /an? \w+ file ([^ ]+) is (not )?removed/ do |filename, negated|
|
||||||
|
File.exists?(filename).should == !!negated
|
||||||
|
end
|
||||||
|
|
||||||
Then /an? \w+ file ([^ ]+) is (not )?created/ do |filename, negated|
|
Then /an? \w+ file ([^ ]+) is (not )?created/ do |filename, negated|
|
||||||
File.exists?(filename).should == !negated
|
File.exists?(filename).should == !negated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then "the following files are reported removed:" do |table|
|
||||||
|
table.rows.each do |css_file|
|
||||||
|
Then %Q{a css file #{css_file.first} is reported removed}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Then "the following files are removed:" do |table|
|
||||||
|
table.rows.each do |css_file|
|
||||||
|
Then %Q{a css file #{css_file.first} is removed}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /an? \w+ file ([^ ]+) is reported removed/ do |filename|
|
||||||
|
@last_result.should =~ /remove.*#{Regexp.escape(filename)}/
|
||||||
|
end
|
||||||
|
|
||||||
Then /an? \w+ file ([^ ]+) is reported created/ do |filename|
|
Then /an? \w+ file ([^ ]+) is reported created/ do |filename|
|
||||||
@last_result.should =~ /create.*#{Regexp.escape(filename)}/
|
@last_result.should =~ /create.*#{Regexp.escape(filename)}/
|
||||||
end
|
end
|
||||||
|
@ -65,7 +65,10 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove(file_name)
|
def remove(file_name)
|
||||||
if File.exists?(file_name)
|
if File.directory?(file_name)
|
||||||
|
FileUtils.rm_rf file_name
|
||||||
|
log_action :remove, basename(file_name)+"/", options
|
||||||
|
elsif File.exists?(file_name)
|
||||||
File.unlink file_name
|
File.unlink file_name
|
||||||
log_action :remove, basename(file_name), options
|
log_action :remove, basename(file_name), options
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ end
|
|||||||
require 'compass/commands/registry'
|
require 'compass/commands/registry'
|
||||||
|
|
||||||
%w(base generate_grid_background default help list_frameworks project_base
|
%w(base generate_grid_background default help list_frameworks project_base
|
||||||
update_project watch_project create_project imports installer_command
|
update_project watch_project create_project clean_project imports installer_command
|
||||||
print_version project_stats stamp_pattern sprite validate_project
|
print_version project_stats stamp_pattern sprite validate_project
|
||||||
write_configuration interactive unpack_extension).each do |lib|
|
write_configuration interactive unpack_extension).each do |lib|
|
||||||
require "compass/commands/#{lib}"
|
require "compass/commands/#{lib}"
|
||||||
|
79
lib/compass/commands/clean_project.rb
Normal file
79
lib/compass/commands/clean_project.rb
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
require 'compass/commands/project_base'
|
||||||
|
require 'compass/compiler'
|
||||||
|
|
||||||
|
module Compass
|
||||||
|
module Commands
|
||||||
|
module CleanProjectOptionsParser
|
||||||
|
def set_options(opts)
|
||||||
|
opts.banner = %Q{
|
||||||
|
Usage: compass clean [path/to/project] [options]
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Remove generated files and the sass cache.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CleanProject < UpdateProject
|
||||||
|
|
||||||
|
register :clean
|
||||||
|
|
||||||
|
def initialize(working_path, options)
|
||||||
|
super
|
||||||
|
assert_project_directory_exists!
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
compiler = new_compiler_instance
|
||||||
|
compiler.clean!
|
||||||
|
Compass::SpriteImporter.find_all_sprite_map_files(Compass.configuration.images_path).each do |sprite|
|
||||||
|
remove sprite
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def determine_cache_location
|
||||||
|
Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache")
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def option_parser(arguments)
|
||||||
|
parser = Compass::Exec::CommandOptionParser.new(arguments)
|
||||||
|
parser.extend(Compass::Exec::GlobalOptionsParser)
|
||||||
|
parser.extend(Compass::Exec::ProjectOptionsParser)
|
||||||
|
parser.extend(CleanProjectOptionsParser)
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage
|
||||||
|
option_parser([]).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def primary; true; end
|
||||||
|
|
||||||
|
def description(command)
|
||||||
|
"Remove generated files and the sass cache"
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse!(arguments)
|
||||||
|
parser = option_parser(arguments)
|
||||||
|
parser.parse!
|
||||||
|
parse_arguments!(parser, arguments)
|
||||||
|
parser.options
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_arguments!(parser, arguments)
|
||||||
|
if arguments.size > 0
|
||||||
|
parser.options[:project_name] = arguments.shift if File.directory?(arguments.first)
|
||||||
|
unless arguments.empty?
|
||||||
|
parser.options[:sass_files] = arguments.dup
|
||||||
|
parser.options[:force] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -16,8 +16,10 @@ module Compass::Commands
|
|||||||
matching.first
|
matching.first
|
||||||
elsif name =~ /^-/
|
elsif name =~ /^-/
|
||||||
nil
|
nil
|
||||||
else
|
elsif matching.size > 1
|
||||||
raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}"
|
raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}"
|
||||||
|
else
|
||||||
|
raise Compass::Error, "Command not found: #{name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def abbreviation?(name)
|
def abbreviation?(name)
|
||||||
|
@ -54,6 +54,7 @@ module Compass
|
|||||||
compiler_opts = {:sass => Compass.sass_engine_options}
|
compiler_opts = {:sass => Compass.sass_engine_options}
|
||||||
compiler_opts.merge!(options)
|
compiler_opts.merge!(options)
|
||||||
compiler_opts[:sass_files] = explicit_sass_files
|
compiler_opts[:sass_files] = explicit_sass_files
|
||||||
|
compiler_opts[:cache_location] = determine_cache_location
|
||||||
compiler_opts
|
compiler_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clean!
|
def clean!
|
||||||
FileUtils.rm_rf options[:cache_location]
|
remove options[:cache_location]
|
||||||
css_files.each do |css_file|
|
css_files.each do |css_file|
|
||||||
FileUtils.rm_f css_file
|
remove css_file
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -71,8 +71,10 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
# When called with a block, defines the cache buster strategy to be used.
|
# When called with a block, defines the cache buster strategy to be used.
|
||||||
# The block must return nil or a string that can be appended to a url as a query parameter.
|
# If the block returns nil or a string, then it is appended to the url as a query parameter.
|
||||||
# The returned string must not include the starting '?'.
|
# In this case, the returned string must not include the starting '?'.
|
||||||
|
# The block may also return a hash with :path and/or :query values and it
|
||||||
|
# will replace the original path and query string with the busted values returned.
|
||||||
# The block will be passed the root-relative url of the asset.
|
# The block will be passed the root-relative url of the asset.
|
||||||
# If the block accepts two arguments, it will also be passed a File object
|
# If the block accepts two arguments, it will also be passed a File object
|
||||||
# that points to the asset on disk -- which may or may not exist.
|
# that points to the asset on disk -- which may or may not exist.
|
||||||
|
@ -13,6 +13,7 @@ module Compass::Exec
|
|||||||
def run!
|
def run!
|
||||||
begin
|
begin
|
||||||
perform!
|
perform!
|
||||||
|
return 0
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
raise e if e.is_a? SystemExit
|
raise e if e.is_a? SystemExit
|
||||||
if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError)
|
if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError)
|
||||||
@ -22,7 +23,6 @@ module Compass::Exec
|
|||||||
end
|
end
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -91,9 +91,7 @@ module Compass::SassExtensions::Functions::Urls
|
|||||||
if cache_buster.is_a?(Sass::Script::String)
|
if cache_buster.is_a?(Sass::Script::String)
|
||||||
path += "?#{cache_buster.value}"
|
path += "?#{cache_buster.value}"
|
||||||
else
|
else
|
||||||
if buster = compute_cache_buster(path, real_path)
|
path = cache_busted_path(path, real_path)
|
||||||
path += "?#{buster}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -137,6 +135,23 @@ module Compass::SassExtensions::Functions::Urls
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cache_busted_path(path, real_path)
|
||||||
|
cache_buster = compute_cache_buster(path, real_path)
|
||||||
|
if cache_buster.nil?
|
||||||
|
return path
|
||||||
|
elsif cache_buster.is_a?(String)
|
||||||
|
cache_buster = {:query => cache_buster}
|
||||||
|
else
|
||||||
|
path = cache_buster[:path] if cache_buster[:path]
|
||||||
|
end
|
||||||
|
|
||||||
|
if cache_buster[:query]
|
||||||
|
"%s?%s" % [path, cache_buster[:query]]
|
||||||
|
else
|
||||||
|
path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def compute_cache_buster(path, real_path)
|
def compute_cache_buster(path, real_path)
|
||||||
if Compass.configuration.asset_cache_buster
|
if Compass.configuration.asset_cache_buster
|
||||||
args = [path]
|
args = [path]
|
||||||
|
@ -5,6 +5,13 @@ module Compass
|
|||||||
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
|
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
|
||||||
VALID_EXTENSIONS = ['.png']
|
VALID_EXTENSIONS = ['.png']
|
||||||
|
|
||||||
|
# finds all sprite files
|
||||||
|
def self.find_all_sprite_map_files(path)
|
||||||
|
hex = "[0-9a-f]"
|
||||||
|
glob = "*-{,s}#{hex*10}{#{VALID_EXTENSIONS.join(",")}}"
|
||||||
|
Dir.glob(File.join(path, "**", glob))
|
||||||
|
end
|
||||||
|
|
||||||
def self.load(uri, options)
|
def self.load(uri, options)
|
||||||
klass = Compass::SpriteImporter.new
|
klass = Compass::SpriteImporter.new
|
||||||
klass.uri, klass.options = uri, options
|
klass.uri, klass.options = uri, options
|
||||||
|
29
test/fixtures/stylesheets/busted_image_urls/config.rb
vendored
Normal file
29
test/fixtures/stylesheets/busted_image_urls/config.rb
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Require any additional compass plugins here.
|
||||||
|
project_type = :stand_alone
|
||||||
|
css_dir = "tmp"
|
||||||
|
sass_dir = "sass"
|
||||||
|
images_dir = "images"
|
||||||
|
output_style = :compact
|
||||||
|
# To enable relative image paths using the images_url() function:
|
||||||
|
# http_images_path = :relative
|
||||||
|
http_images_path = "/images"
|
||||||
|
line_comments = false
|
||||||
|
|
||||||
|
asset_cache_buster do |path, file|
|
||||||
|
pathname = Pathname.new(path)
|
||||||
|
|
||||||
|
case pathname.basename(pathname.extname).to_s
|
||||||
|
when "grid"
|
||||||
|
new_path = "%s/%s-BUSTED%s" % [pathname.dirname, pathname.basename(pathname.extname), pathname.extname]
|
||||||
|
{:path => new_path, :query => nil}
|
||||||
|
when "feed"
|
||||||
|
"query_string"
|
||||||
|
when "dk"
|
||||||
|
{:query => "query_string"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
asset_host do |path|
|
||||||
|
"http://assets%d.example.com" % (path.size % 4)
|
||||||
|
end
|
9
test/fixtures/stylesheets/busted_image_urls/css/screen.css
vendored
Normal file
9
test/fixtures/stylesheets/busted_image_urls/css/screen.css
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.showgrid { background-image: url('http://assets0.example.com/images/grid-BUSTED.png'); }
|
||||||
|
|
||||||
|
.inlinegrid { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUEAYAAACv1qP4AAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAZ0lEQVRYw+3QwQ2AIBAFUTEUwI3+uzN7gDscsIgxEuO8An52J11X73OudfxMraXkzHfO3Y98nQEhA0IGhAwIGRAyIGRAyICQASEDQgaEDAgZEDIgZEDIgJABoZzSGK3tPuN9ERFP7Nw4fg+c5g8V1wAAAABJRU5ErkJggg=='); }
|
||||||
|
|
||||||
|
.no-buster { background-image: url('http://assets0.example.com/images/grid.png'); }
|
||||||
|
|
||||||
|
.feed { background-image: url('http://assets0.example.com/images/feed.png?query_string'); }
|
||||||
|
|
||||||
|
.dk { background-image: url('http://assets0.example.com/images/flags/dk.png?query_string'); }
|
BIN
test/fixtures/stylesheets/busted_image_urls/images/feed.png
vendored
Normal file
BIN
test/fixtures/stylesheets/busted_image_urls/images/feed.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 691 B |
BIN
test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png
vendored
Normal file
BIN
test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 808 B |
BIN
test/fixtures/stylesheets/busted_image_urls/images/grid.png
vendored
Normal file
BIN
test/fixtures/stylesheets/busted_image_urls/images/grid.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 199 B |
14
test/fixtures/stylesheets/busted_image_urls/sass/screen.sass
vendored
Normal file
14
test/fixtures/stylesheets/busted_image_urls/sass/screen.sass
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.showgrid
|
||||||
|
background-image: image-url("grid.png")
|
||||||
|
|
||||||
|
.inlinegrid
|
||||||
|
background-image: inline-image("grid.png")
|
||||||
|
|
||||||
|
.no-buster
|
||||||
|
background-image: image-url("grid.png", $only-path: false, $cache-buster: false)
|
||||||
|
|
||||||
|
.feed
|
||||||
|
background-image: image-url("feed.png")
|
||||||
|
|
||||||
|
.dk
|
||||||
|
background-image: image-url("flags/dk.png")
|
@ -73,6 +73,17 @@ class CompassTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_busted_image_urls
|
||||||
|
within_project('busted_image_urls') do |proj|
|
||||||
|
each_css_file(proj.css_path) do |css_file|
|
||||||
|
assert_no_errors css_file, 'busted_image_urls'
|
||||||
|
end
|
||||||
|
each_sass_file do |sass_file|
|
||||||
|
assert_renders_correctly sass_file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_image_urls
|
def test_image_urls
|
||||||
within_project('image_urls') do |proj|
|
within_project('image_urls') do |proj|
|
||||||
each_css_file(proj.css_path) do |css_file|
|
each_css_file(proj.css_path) do |css_file|
|
||||||
|
Loading…
Reference in New Issue
Block a user