css-rewrite 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +76 -0
- data/lib/css-rewrite.rb +0 -2
- data/lib/css-rewrite/config.rb +2 -2
- data/lib/css-rewrite/postprocessor.rb +16 -2
- data/lib/css-rewrite/rewriter.rb +19 -5
- data/lib/css-rewrite/version.rb +1 -1
- data/spec/config_spec.rb +4 -8
- data/spec/postprocessor_spec.rb +45 -0
- data/spec/precompile_spec.rb +1 -1
- data/spec/rewriter_spec.rb +14 -13
- metadata +4 -6
- data/lib/css-rewrite/call_rewriter.rb +0 -21
- data/lib/css-rewrite/regex_rewriter.rb +0 -22
- data/spec/call_rewriter_spec.rb +0 -40
- data/spec/regex_rewriter_spec.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ceec306108646763d41b4a97611cca6509506718
|
4
|
+
data.tar.gz: 67a34318674dfa93a473810229310ffbfe55adf1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 162bf7a19c513fe517c99cdc620ac02f55aadeeb66347e38866ab2a20df7b80c67585a6c83de1177ef5bbdf9b1f1484b7f25aba1275dabe3c926b7a27c38c0dc
|
7
|
+
data.tar.gz: 6fccb97733b69087c09fd4b59fa970d4098ec2213913e83b14cefeec37523ffa9df1a517044d34e36c365dcf5f011e5371be96c5afd98f0be4436e544b367958
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
## css-rewrite
|
2
|
+
Rewrite URLs in your 3rd-party CSS files using the asset pipeline.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
`gem install css-rewrite`
|
7
|
+
|
8
|
+
or put it in your Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'css-rewrite'
|
12
|
+
```
|
13
|
+
|
14
|
+
## Rationale
|
15
|
+
|
16
|
+
Have you ever pulled a 3rd-party JavaScript or CSS library into your Rails web app? It can take some effort to get it to play nicely with the asset pipeline. You have to hunt through the tangle of potentially minified CSS to find all the URLs to images and fonts that should be using the Rails asset URL helpers. In other words, instead of this:
|
17
|
+
|
18
|
+
```css
|
19
|
+
.some-selector {
|
20
|
+
background-image: url("puppy.png");
|
21
|
+
}
|
22
|
+
```
|
23
|
+
|
24
|
+
you want this:
|
25
|
+
|
26
|
+
```css
|
27
|
+
.some-selector {
|
28
|
+
background-image: image-url("puppy.png");
|
29
|
+
}
|
30
|
+
```
|
31
|
+
|
32
|
+
Every time the author of the CSS library publishes a new version, you have to pull it down and do the hunt-and-replace thing all over again. How tedious.
|
33
|
+
|
34
|
+
That's where css-rewrite comes in. Rather than hunting for and converting URLs by hand, css-rewrite adds a post-processor to the asset pipeline that finds and replaces them for you. Whenever the file is served or precompiled, the URLs will point to the correct asset paths. No manual hunting or replacing necessary.
|
35
|
+
|
36
|
+
### Ok I'm listening. How does it work?
|
37
|
+
|
38
|
+
Behind the scenes, css-rewrite uses the [crass gem](https://github.com/rgrove/crass) to parse and reconstitute CSS. It searches through the parse tree crass generates looking for URLs. When it finds one, it yields it to you for replacement. You (or more accurately your application) can decide what the replacement URL should be using all the power afforded to you by the Ruby programming language.
|
39
|
+
|
40
|
+
## How 'bout some examples?
|
41
|
+
|
42
|
+
Sure! It's pretty straightforward. In an initializer (i.e. config/initializers/css_rewrite.rb), simply configure css-rewrite with a callback. Here's how you might configure it to resolve all URLs in application.css as if they were assets managed by the asset pipeline (which hopefully they are):
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
CssRewrite.configure do |config|
|
46
|
+
config.rewrite(/application\.css$/) do |url|
|
47
|
+
ActionController::Base.helpers.asset_path(url)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
As you can see, the callback approach is pretty flexible; it gives you direct control over the replacement value of each URL. Here's another example that only replaces image URLs:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
CssRewrite.configure do |config|
|
56
|
+
config.rewrite(/application\.css$/) do |url|
|
57
|
+
if %w(.png .jpg .gif).include?(File.extname(url))
|
58
|
+
ActionController::Base.helpers.image_path(url)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
In this last example you'll notice that the block passed to `rewrite` can return `nil`. In such a case, css-rewrite will replace the URL with itself, i.e. won't change the URL at all. In addition, you can call `#rewrite` as many times as you want to set up different rewrite rules. When replacing URLs, css-rewrite will search through the rewriters that apply to the current file in the order they were added. The first one that returns something other than `nil` will be used for URL replacement. All the rewriters that come _after_ the matching one will be skipped. This happens on a per-URL basis.
|
65
|
+
|
66
|
+
## Nice! What else do I need to know?
|
67
|
+
|
68
|
+
That's pretty much it. The URL replacements should happen whenever the earmarked CSS files are requested by the browser or precompiled via `rake assets:precompile`.
|
69
|
+
|
70
|
+
## License
|
71
|
+
|
72
|
+
Licensed under the MIT license. See LICENSE for details.
|
73
|
+
|
74
|
+
## Authors
|
75
|
+
|
76
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/lib/css-rewrite.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module CssRewrite
|
2
|
-
autoload :CallRewriter, 'css-rewrite/call_rewriter'
|
3
2
|
autoload :Config, 'css-rewrite/config'
|
4
3
|
autoload :Postprocessor, 'css-rewrite/postprocessor'
|
5
|
-
autoload :RegexRewriter, 'css-rewrite/regex_rewriter'
|
6
4
|
autoload :Rewriter, 'css-rewrite/rewriter'
|
7
5
|
|
8
6
|
def self.configure
|
data/lib/css-rewrite/config.rb
CHANGED
@@ -4,11 +4,19 @@ module CssRewrite
|
|
4
4
|
class Postprocessor
|
5
5
|
class << self
|
6
6
|
def run(filename, source, context)
|
7
|
+
rewriters = find_rewriters(filename)
|
8
|
+
return source if rewriters.empty?
|
7
9
|
tree = Crass.parse(source, preserve_comments: true)
|
8
10
|
|
9
11
|
replace_urls(tree) do |url|
|
10
|
-
|
11
|
-
|
12
|
+
rewritten_url = nil
|
13
|
+
|
14
|
+
rewriters.each do |rewriter|
|
15
|
+
rewritten_url = rewriter.rewrite(url)
|
16
|
+
break if rewritten_url
|
17
|
+
end
|
18
|
+
|
19
|
+
rewritten_url || url
|
12
20
|
end
|
13
21
|
|
14
22
|
Crass::Parser.stringify(tree)
|
@@ -25,6 +33,12 @@ module CssRewrite
|
|
25
33
|
|
26
34
|
private
|
27
35
|
|
36
|
+
def find_rewriters(filename)
|
37
|
+
Config.instance.rewriters.select do |re|
|
38
|
+
re.matches?(filename)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
28
42
|
def replace_urls(root, &block)
|
29
43
|
return unless root
|
30
44
|
|
data/lib/css-rewrite/rewriter.rb
CHANGED
@@ -1,13 +1,27 @@
|
|
1
1
|
module CssRewrite
|
2
2
|
class Rewriter
|
3
|
-
|
3
|
+
attr_reader :file_filter, :replacement_block
|
4
4
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
5
|
+
def initialize(file_filter, &block)
|
6
|
+
@file_filter = file_filter
|
7
|
+
@replacement_block = block
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches?(filename)
|
11
|
+
case file_filter
|
12
|
+
when String
|
13
|
+
file_filter == filename
|
14
|
+
when Regexp
|
15
|
+
!!(file_filter =~ filename)
|
16
|
+
else
|
17
|
+
if file_filter.respond_to?(:call)
|
18
|
+
file_filter.call(filename)
|
19
|
+
end
|
8
20
|
end
|
21
|
+
end
|
9
22
|
|
10
|
-
|
23
|
+
def rewrite(url)
|
24
|
+
replacement_block.call(url)
|
11
25
|
end
|
12
26
|
end
|
13
27
|
end
|
data/lib/css-rewrite/version.rb
CHANGED
data/spec/config_spec.rb
CHANGED
@@ -24,14 +24,10 @@ describe CssRewrite::Config do
|
|
24
24
|
subject { described_class.instance }
|
25
25
|
|
26
26
|
describe '#rewrite' do
|
27
|
-
it 'adds a
|
28
|
-
expect { subject.rewrite {} }.to
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
it 'adds a regex rewriter to the list of rewriters' do
|
33
|
-
expect { subject.rewrite(/re/) {} }.to change { subject.rewriters.size }.by(1)
|
34
|
-
expect(subject.rewriters.first).to be_a(CssRewrite::RegexRewriter)
|
27
|
+
it 'adds a rewriter to the list of rewriters' do
|
28
|
+
expect { subject.rewrite('application.css') {} }.to(
|
29
|
+
change { subject.rewriters.size }.by(1)
|
30
|
+
)
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CssRewrite::Postprocessor do
|
4
|
+
describe '.run' do
|
5
|
+
before do
|
6
|
+
CssRewrite.configure do |config|
|
7
|
+
config.rewrite(/application\.css$/) { |url| nil }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:filename) { Rails.root.join(*%w(app assets stylesheets application.css)).to_s }
|
12
|
+
let(:source) { File.read(filename) }
|
13
|
+
let(:context) { nil }
|
14
|
+
|
15
|
+
subject { described_class.run(filename, source, context) }
|
16
|
+
|
17
|
+
it 'defaults to using the original url' do
|
18
|
+
expect(subject).to eq(source)
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with more rewriters' do
|
22
|
+
before do
|
23
|
+
CssRewrite.configure do |config|
|
24
|
+
config.rewrite(/application\.css$/) do |url|
|
25
|
+
if url.end_with?('.png')
|
26
|
+
url.gsub(/\.png/, '.foo')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
config.rewrite(/application\.css$/) do |url|
|
31
|
+
if url.end_with?('.jpg')
|
32
|
+
url.gsub(/\.jpg/, '.bar')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'stops after finding a matching rewriter' do
|
39
|
+
expect(subject).to(
|
40
|
+
eq(".my-class {\n background-image: url('foo/bar.foo');\n}\n")
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/precompile_spec.rb
CHANGED
data/spec/rewriter_spec.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CssRewrite::Rewriter do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
expect(rewriter.
|
4
|
+
let(:rewriter) { described_class.new(/application\.css$/, &block) }
|
5
|
+
let(:block) { -> (url) { url.gsub(/\.png$/, '.foo') } }
|
6
|
+
|
7
|
+
describe '#matches?' do
|
8
|
+
it "returns false if the filename doesn't match" do
|
9
|
+
expect(rewriter.matches?('something.js')).to eq(false)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns true if the filename matches' do
|
13
|
+
expect(rewriter.matches?('application.css')).to eq(true)
|
10
14
|
end
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
rewriter = described_class.create(regex, &block)
|
16
|
-
expect(rewriter).to be_a(CssRewrite::RegexRewriter)
|
17
|
-
expect(rewriter.replacement_block).to eq(block)
|
18
|
-
expect(rewriter.regex).to eq(regex)
|
17
|
+
describe '#rewrite' do
|
18
|
+
it 'uses the replacement block to modify the url' do
|
19
|
+
expect(rewriter.rewrite('path/to/image.png')).to eq('path/to/image.foo')
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css-rewrite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cameron Dutro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sprockets
|
@@ -60,23 +60,21 @@ extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
62
|
- Gemfile
|
63
|
+
- README.md
|
63
64
|
- Rakefile
|
64
65
|
- css-rewrite.gemspec
|
65
66
|
- lib/css-rewrite.rb
|
66
|
-
- lib/css-rewrite/call_rewriter.rb
|
67
67
|
- lib/css-rewrite/config.rb
|
68
68
|
- lib/css-rewrite/postprocessor.rb
|
69
69
|
- lib/css-rewrite/railtie.rb
|
70
|
-
- lib/css-rewrite/regex_rewriter.rb
|
71
70
|
- lib/css-rewrite/rewriter.rb
|
72
71
|
- lib/css-rewrite/version.rb
|
73
72
|
- spec/app/assets/stylesheets/application.css
|
74
|
-
- spec/call_rewriter_spec.rb
|
75
73
|
- spec/config/application.rb
|
76
74
|
- spec/config_spec.rb
|
77
75
|
- spec/log/test.log
|
76
|
+
- spec/postprocessor_spec.rb
|
78
77
|
- spec/precompile_spec.rb
|
79
|
-
- spec/regex_rewriter_spec.rb
|
80
78
|
- spec/rewriter_spec.rb
|
81
79
|
- spec/spec_helper.rb
|
82
80
|
homepage: http://github.com/camertron/css-rewrite
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module CssRewrite
|
2
|
-
class CallRewriter
|
3
|
-
def self.applies_to?(*args, &block)
|
4
|
-
args.size == 0 && block.present?
|
5
|
-
end
|
6
|
-
|
7
|
-
attr_reader :replacement_block
|
8
|
-
|
9
|
-
def initialize(&block)
|
10
|
-
@replacement_block = block
|
11
|
-
end
|
12
|
-
|
13
|
-
def matches?(url)
|
14
|
-
true
|
15
|
-
end
|
16
|
-
|
17
|
-
def rewrite(url, filename)
|
18
|
-
replacement_block.call(url, filename)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module CssRewrite
|
2
|
-
class RegexRewriter
|
3
|
-
def self.applies_to?(*args, &block)
|
4
|
-
args.size == 1 && args.first.is_a?(Regexp) && block_given?
|
5
|
-
end
|
6
|
-
|
7
|
-
attr_reader :regex, :replacement_block
|
8
|
-
|
9
|
-
def initialize(regex, &block)
|
10
|
-
@regex = regex
|
11
|
-
@replacement_block = block
|
12
|
-
end
|
13
|
-
|
14
|
-
def matches?(url)
|
15
|
-
!!(regex =~ url)
|
16
|
-
end
|
17
|
-
|
18
|
-
def rewrite(url, filename)
|
19
|
-
replacement_block.call(url, filename)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/spec/call_rewriter_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe CssRewrite::CallRewriter do
|
4
|
-
describe '.applies_to?' do
|
5
|
-
it 'applies if passed a block' do
|
6
|
-
expect(described_class.applies_to? {}).to eq(true)
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'does not apply if passed any arguments' do
|
10
|
-
expect(described_class.applies_to?(1) {}).to eq(false)
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'does not apply if not passed a block' do
|
14
|
-
expect(described_class.applies_to?).to eq(false)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'with a rewriter' do
|
19
|
-
subject { described_class.new(&block) }
|
20
|
-
|
21
|
-
let(:block) do
|
22
|
-
# replaces the extension with ".foo"
|
23
|
-
-> (url, filename) { url.chomp(File.extname(url)) + '.foo' }
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '#matches?' do
|
27
|
-
it 'always matches' do
|
28
|
-
expect(subject.matches?('foo')).to eq(true)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#rewrite' do
|
33
|
-
it 'invokes the replacement block' do
|
34
|
-
expect(subject.rewrite('foo.com/image.jpg', 'foo.css')).to eq(
|
35
|
-
'foo.com/image.foo'
|
36
|
-
)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/spec/regex_rewriter_spec.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe CssRewrite::RegexRewriter do
|
4
|
-
describe '.applies_to?' do
|
5
|
-
it 'applies if passed a regex and a block' do
|
6
|
-
expect(described_class.applies_to?(/re/) {}).to eq(true)
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'does not apply if passed no arguments' do
|
10
|
-
expect(described_class.applies_to? {}).to eq(false)
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'does not apply if not passed a block' do
|
14
|
-
expect(described_class.applies_to?(/re/)).to eq(false)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'with a rewriter' do
|
19
|
-
subject { described_class.new(/.jpg\z/, &block) }
|
20
|
-
|
21
|
-
let(:block) do
|
22
|
-
# replaces the extension with ".foo"
|
23
|
-
-> (url, filename) { url.chomp(File.extname(url)) + '.foo' }
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '#matches?' do
|
27
|
-
it 'matches if the regex matches' do
|
28
|
-
expect(subject.matches?('foo.jpg')).to eq(true)
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'does not match if the regex fails to match' do
|
32
|
-
expect(subject.matches?('foo.png')).to eq(false)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#rewrite' do
|
37
|
-
it 'invokes the replacement block' do
|
38
|
-
expect(subject.rewrite('foo.com/image.jpg', 'foo.css')).to eq(
|
39
|
-
'foo.com/image.foo'
|
40
|
-
)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|