css-rewrite 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []