css-rewrite 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fc776cbf9f90435b4988cf29c875cbb2ce2e691c
4
+ data.tar.gz: afdc21aa137284b0242ade4d4355641b29f1718c
5
+ SHA512:
6
+ metadata.gz: f5218b6f5ddd5be6bbc8fd333c91833d9847c35c61ea2207a72b63cd2bee5537975cde43b8efe845e14910d0054b40a3ba113f674673b8103a3626bf71a50bdb
7
+ data.tar.gz: db6eb3a7cc43d1853b1d8f58663a74b935adc45bd4bc4f1981853efb3db2852eaec81f88926a45bdeac2c09a079f42929a395c816397959c58481d5aece2070e
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile-rails-4.2.x', __FILE__)
2
+ Bundler.load
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
4
+
5
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
6
+
7
+ require 'bundler'
8
+ require 'pry-byebug'
9
+ require 'rspec/core/rake_task'
10
+ require 'rubygems/package_task'
11
+
12
+ require 'rails'
13
+ require 'sprockets/railtie'
14
+ require 'css-rewrite'
15
+
16
+ Bundler::GemHelper.install_tasks
17
+
18
+ task default: :spec
19
+
20
+ desc 'Run specs'
21
+ RSpec::Core::RakeTask.new do |t|
22
+ t.pattern = './spec/**/*_spec.rb'
23
+ end
@@ -0,0 +1,22 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'css-rewrite/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'css-rewrite'
6
+ s.version = ::CssRewrite::VERSION
7
+ s.authors = ['Cameron Dutro']
8
+ s.email = ['camertron@gmail.com']
9
+ s.homepage = 'http://github.com/camertron/css-rewrite'
10
+
11
+ s.description = s.summary = 'Rewrite URLs in your 3rd-party CSS files using the asset pipeline.'
12
+
13
+ s.platform = Gem::Platform::RUBY
14
+ s.has_rdoc = true
15
+
16
+ s.add_dependency 'sprockets', '~> 3.0'
17
+ s.add_dependency 'railties', '>= 4.0'
18
+ s.add_dependency 'crass'
19
+
20
+ s.require_path = 'lib'
21
+ s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'README.md', 'Rakefile', 'css-rewrite.gemspec']
22
+ end
@@ -0,0 +1,21 @@
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
@@ -0,0 +1,23 @@
1
+ module CssRewrite
2
+ class Config
3
+ def self.instance
4
+ @instance ||= new
5
+ end
6
+
7
+ def self.reset
8
+ @instance = nil
9
+ end
10
+
11
+ attr_reader :rewriters
12
+
13
+ def rewrite(*args, &block)
14
+ rewriters << Rewriter.create(*args, &block)
15
+ end
16
+
17
+ private
18
+
19
+ def initialize
20
+ @rewriters = []
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ require 'crass'
2
+
3
+ module CssRewrite
4
+ class Postprocessor
5
+ class << self
6
+ def run(filename, source, context)
7
+ tree = Crass.parse(source, preserve_comments: true)
8
+
9
+ replace_urls(tree) do |url|
10
+ rewriter = Config.instance.rewriters.find { |re| re.matches?(url) }
11
+ rewriter ? rewriter.rewrite(url, filename) : url
12
+ end
13
+
14
+ Crass::Parser.stringify(tree)
15
+ end
16
+
17
+ def call(input)
18
+ filename = input[:filename]
19
+ source = input[:data]
20
+ context = input[:environment].context_class.new(input)
21
+
22
+ result = run(filename, source, context)
23
+ context.metadata.merge(data: result)
24
+ end
25
+
26
+ private
27
+
28
+ def replace_urls(root, &block)
29
+ return unless root
30
+
31
+ root.each do |node|
32
+ if node[:node] == :url
33
+ new_value = yield node[:value]
34
+ node[:raw].sub!(node[:value], new_value)
35
+ node[:value] = new_value
36
+ elsif node[:node] == :function && node[:name] == 'url'
37
+ old_value = node[:value].first[:value]
38
+ new_value = yield old_value
39
+ node[:value].first[:value] = new_value
40
+ node[:value].first[:raw].sub!(old_value, new_value)
41
+ end
42
+
43
+ replace_urls(node[:children], &block)
44
+ replace_urls(node[:block], &block)
45
+ end
46
+ end
47
+ end
48
+
49
+ def initialize(filename, &block)
50
+ @filename = filename
51
+ @source = block.call
52
+ end
53
+
54
+ def render(context, empty_hash_wtf)
55
+ self.class.run(@filename, @source, context)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: UTF-8
2
+
3
+ module CssRewrite
4
+ class Railtie < ::Rails::Railtie
5
+ config.assets.configure do |env|
6
+ if env.respond_to?(:register_transformer)
7
+ env.register_postprocessor 'text/css', 'text/css', CssRewrite::Postprocessor
8
+ end
9
+
10
+ if env.respond_to?(:register_engine)
11
+ args = ['.css', CssRewrite::Postprocessor]
12
+
13
+ if Sprockets::VERSION.start_with?('3')
14
+ args << { mime_type: 'text/css', silence_deprecation: true }
15
+ end
16
+
17
+ env.register_engine(*args)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
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
@@ -0,0 +1,13 @@
1
+ module CssRewrite
2
+ class Rewriter
3
+ REWRITERS = [CssRewrite::RegexRewriter, CssRewrite::CallRewriter]
4
+
5
+ def self.create(*args, &block)
6
+ rewriter = REWRITERS.find do |rewriter|
7
+ rewriter.applies_to?(*args, &block)
8
+ end
9
+
10
+ rewriter.new(*args, &block)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module CssRewrite
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,13 @@
1
+ module CssRewrite
2
+ autoload :CallRewriter, 'css-rewrite/call_rewriter'
3
+ autoload :Config, 'css-rewrite/config'
4
+ autoload :Postprocessor, 'css-rewrite/postprocessor'
5
+ autoload :RegexRewriter, 'css-rewrite/regex_rewriter'
6
+ autoload :Rewriter, 'css-rewrite/rewriter'
7
+
8
+ def self.configure
9
+ yield Config.instance
10
+ end
11
+ end
12
+
13
+ require 'css-rewrite/railtie' if defined?(Rails)
@@ -0,0 +1,3 @@
1
+ .my-class {
2
+ background-image: url('foo/bar.png');
3
+ }
@@ -0,0 +1,40 @@
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
@@ -0,0 +1,12 @@
1
+ module CssRewrite
2
+ class DummyApplication < ::Rails::Application
3
+ config.eager_load = false
4
+ config.active_support.deprecation = :stderr
5
+
6
+ config.assets.enabled = true
7
+ config.assets.compile = true
8
+ config.assets.allow_debugging = true
9
+ config.assets.digest = true
10
+ config.assets.manifest = 'spec/public/assets/.sprockets-manifest.json'
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssRewrite::Config do
4
+ describe '.instance' do
5
+ it 'returns the only instance' do
6
+ expect(described_class.instance).to be_a(described_class)
7
+ expect(described_class.instance.object_id).to(
8
+ eq(described_class.instance.object_id)
9
+ )
10
+ end
11
+ end
12
+
13
+ describe '.reset' do
14
+ it 'clears the existing instance' do
15
+ old_config = described_class.instance
16
+ described_class.reset
17
+ expect(old_config.object_id).to_not(
18
+ eq(described_class.instance.object_id)
19
+ )
20
+ end
21
+ end
22
+
23
+ context 'with a config instance' do
24
+ subject { described_class.instance }
25
+
26
+ describe '#rewrite' do
27
+ it 'adds a call rewriter to the list of rewriters' do
28
+ expect { subject.rewrite {} }.to change { subject.rewriters.size }.by(1)
29
+ expect(subject.rewriters.first).to be_a(CssRewrite::CallRewriter)
30
+ end
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)
35
+ end
36
+ end
37
+ end
38
+ end
data/spec/log/test.log ADDED
File without changes
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Asset precompile' do
4
+ def precompile!
5
+ Rake::Task['assets:precompile'].reenable
6
+ Rake::Task['assets:precompile'].invoke
7
+ end
8
+
9
+ before do
10
+ CssRewrite.configure do |config|
11
+ config.rewrite do |url, filename|
12
+ url.chomp(File.extname(url)) + '.foo'
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:manifest_file) { app.config.assets.manifest }
18
+
19
+ it 'replaces urls in precompiled css assets' do
20
+ precompile!
21
+
22
+ manifest = JSON.parse(File.read(manifest_file))
23
+ css_file = manifest['assets']['application.css']
24
+ css_path = File.join('spec', 'public', app.config.assets.prefix, css_file)
25
+ css = File.read(css_path)
26
+
27
+ expect(css).to eq(
28
+ ".my-class {\n background-image: url('foo/bar.foo');\n}\n"
29
+ )
30
+ end
31
+ end
@@ -0,0 +1,44 @@
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
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssRewrite::Rewriter do
4
+ describe '.create' do
5
+ it 'creates a call rewriter from the given args' do
6
+ block = -> {}
7
+ rewriter = described_class.create(&block)
8
+ expect(rewriter).to be_a(CssRewrite::CallRewriter)
9
+ expect(rewriter.replacement_block).to eq(block)
10
+ end
11
+
12
+ it 'creates a regex rewriter' do
13
+ block = -> {}
14
+ regex = /re/
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)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+
3
+ $:.push(File.dirname(__FILE__))
4
+
5
+ require 'rspec'
6
+ require 'pry-byebug'
7
+
8
+ require 'rails'
9
+ require 'rake'
10
+ require 'sprockets/railtie'
11
+
12
+ ENV['RAILS_ENV'] ||= 'test'
13
+
14
+ require 'css-rewrite'
15
+
16
+ Dir.chdir('spec') do
17
+ require File.expand_path('../config/application', __FILE__)
18
+ CssRewrite::DummyApplication.initialize!
19
+ CssRewrite::DummyApplication.load_tasks # used by precompilation specs
20
+ end
21
+
22
+ module LetDeclarations
23
+ extend RSpec::SharedContext
24
+
25
+ let(:app) { Rails.application }
26
+ let(:assets) { app.assets }
27
+
28
+ let(:assets_dir) do
29
+ CssRewrite::DummyApplication.root.join('public/assets')
30
+ end
31
+
32
+ let(:tmp_dir) do
33
+ CssRewrite::DummyApplication.root.join('tmp')
34
+ end
35
+ end
36
+
37
+ RSpec.configure do |config|
38
+ config.include(LetDeclarations)
39
+
40
+ config.before do
41
+ FileUtils.rm_rf(tmp_dir)
42
+ FileUtils.rm_rf(assets_dir)
43
+ FileUtils.mkdir_p(assets_dir)
44
+ end
45
+
46
+ config.after(:each) do
47
+ CssRewrite::Config.reset
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: css-rewrite
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Cameron Dutro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sprockets
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: crass
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Rewrite URLs in your 3rd-party CSS files using the asset pipeline.
56
+ email:
57
+ - camertron@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - Rakefile
64
+ - css-rewrite.gemspec
65
+ - lib/css-rewrite.rb
66
+ - lib/css-rewrite/call_rewriter.rb
67
+ - lib/css-rewrite/config.rb
68
+ - lib/css-rewrite/postprocessor.rb
69
+ - lib/css-rewrite/railtie.rb
70
+ - lib/css-rewrite/regex_rewriter.rb
71
+ - lib/css-rewrite/rewriter.rb
72
+ - lib/css-rewrite/version.rb
73
+ - spec/app/assets/stylesheets/application.css
74
+ - spec/call_rewriter_spec.rb
75
+ - spec/config/application.rb
76
+ - spec/config_spec.rb
77
+ - spec/log/test.log
78
+ - spec/precompile_spec.rb
79
+ - spec/regex_rewriter_spec.rb
80
+ - spec/rewriter_spec.rb
81
+ - spec/spec_helper.rb
82
+ homepage: http://github.com/camertron/css-rewrite
83
+ licenses: []
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.6.11
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Rewrite URLs in your 3rd-party CSS files using the asset pipeline.
105
+ test_files: []