roadie-3.2.2/ 0000755 0000041 0000041 00000000000 13123110273 013002 5 ustar www-data www-data roadie-3.2.2/roadie.gemspec 0000644 0000041 0000041 00000002123 13123110273 015610 0 ustar www-data www-data # roadie.gemspec # -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require 'roadie/version' Gem::Specification.new do |s| s.name = 'roadie' s.version = Roadie::VERSION s.platform = Gem::Platform::RUBY s.authors = ['Magnus Bergmark'] s.email = ['magnus.bergmark@gmail.com'] s.homepage = 'http://github.com/Mange/roadie' s.summary = %q{Making HTML emails comfortable for the Ruby rockstars} s.description = %q{Roadie tries to make sending HTML emails a little less painful by inlining stylesheets and rewriting relative URLs for you.} s.license = "MIT" s.required_ruby_version = ">= 1.9" s.add_dependency 'nokogiri', '~> 1.5' s.add_dependency 'css_parser', '~> 1.4' s.add_development_dependency 'rspec', '~> 3.0' s.add_development_dependency 'rspec-collection_matchers', '~> 1.0' s.add_development_dependency 'webmock', '~> 3.0' s.extra_rdoc_files = %w[README.md Changelog.md] s.require_paths = %w[lib] s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- spec/*`.split("\n") end roadie-3.2.2/Rakefile 0000644 0000041 0000041 00000000307 13123110273 014447 0 ustar www-data www-data # encoding: utf-8 require 'bundler/setup' Bundler::GemHelper.install_tasks desc "Run specs" task :spec do sh "bundle exec rspec -f progress" end desc "Default: Run specs" task :default => :spec roadie-3.2.2/Gemfile 0000644 0000041 0000041 00000000333 13123110273 014274 0 ustar www-data www-data source 'https://rubygems.org' gemspec # Added here so it does not show up on the Gemspec; I only want it for CI builds gem 'codecov', group: :test, require: false group :guard do gem 'guard' gem 'guard-rspec' end roadie-3.2.2/.autotest 0000644 0000041 0000041 00000000364 13123110273 014656 0 ustar www-data www-data # Override autotest default magic to rerun all tests every time a # change is detected on the file system. class Autotest def get_to_green begin rerun_all_tests wait_for_changes unless all_good end until all_good end end roadie-3.2.2/Changelog.md 0000644 0000041 0000041 00000027277 13123110273 015232 0 ustar www-data www-data ### dev [full changelog](https://github.com/Mange/roadie/compare/v3.2.2...master) * Nothing yet. ### 3.2.2 [full changelog](https://github.com/Mange/roadie/compare/v3.2.1...v3.2.2) * Enhancements * Support Nokogiri 1.x. * Support `css_parser` 1.x. * Make tests pass on Ruby 2.4.0 (upgrade Webmock). ### 3.2.1 [full changelog](https://github.com/Mange/roadie/compare/v3.2.0...v3.2.1) * Enhancements * Support Nokogiri 1.7.x. ### 3.2.0 [full changelog](https://github.com/Mange/roadie/compare/v3.1.1...v3.2.0) * Deprecations: * Dropped support for MRI 1.9.3. * Dropped support for MRI 2.0. * Upgrades: * Use `css_parser` 1.4.x instead of 1.3.x. * Bug fixes: * Strip UTF-8 BOM (Byte Order Mark) from stylesheets before parsing / concatenating - [Bartłomiej Wójtowicz](https://github.com/qbart) (#128) * Enhancements: * Build against Ruby MRI 2.3.0 too. * Don't add extra whitespace between table cells. ### 3.1.1 [full changelog](https://github.com/Mange/roadie/compare/v3.1.0...v3.1.1) * Enhancements: * Duplicate style properties are now removed when inlining. * This means that `color: green; color: red; color: green` will now be `color: red; color: green`. * The size of your emails should be the same, or smaller. ### 3.1.0 [full changelog](https://github.com/Mange/roadie/compare/v3.1.0.rc1...v3.1.0) * Enchancements: * `NetHttpProvider` validates the whitelist hostnames; passing an invalid hostname will raise `ArgumentError`. * `NetHttpProvider` supports scheme-less URLs (`//foo.com/`), defaulting to `https`. ### 3.1.0.rc1 [full changelog](https://github.com/Mange/roadie/compare/v3.0.5...v3.1.0.rc1) * Enhancements: * Allow user to specify asset providers for referenced assets with full URLs and inline them (#107) * Pass `Document` instance to transformation callbacks (#86) * Made `nokogiri` dependency more forgiving. * Supports `1.5.0`...`1.7.0` now instead of `1.6.0`...`1.7.0`. Some people out there are stuck on this older version of Nokogiri, and I don't want to leave them out. * Output better errors when no assets can be found. * The error will now show which providers were tried and in which order, along with the error message from the specific providers. * `Roadie::FilesystemProvider` shows the given path when inspected. * `data-roadie-ignore` attributes will now be removed from markup; hiding "development markers" in the final email. * Add a `Roadie::CachedProvider` asset provider that wraps other providers and cache them. * Add a `Roadie::PathRewriterProvider` asset provider that rewrites asset names for other providers. * This saves you from having to create custom providers if you require small tweaks to the lookup in order to use an official provider. * **Deprecations:** * `Roadie::Stylesheet#each_inlinable_block` is now deprecated. You can iterate and filter the `blocks` at your own discresion. ### 3.0.5 [full changelog](https://github.com/Mange/roadie/compare/v3.0.4...v3.0.5) * Bug fixes: * Don't try to inline external stylesheets. (#106) * Don't generate absolute URLs for anchor links. (Mange/roadie-rails#40) ### 3.0.4 [full changelog](https://github.com/Mange/roadie/compare/v3.0.3...v3.0.4) * Bug fixes: * Schemeless URLs was accepted as-is, which isn't supported in a lot of email clients. (#104) ### 3.0.3 [full changelog](https://github.com/Mange/roadie/compare/v3.0.2...v3.0.3) * Bug fixes: * CSS was mutated when parsed, breaking caches and memoized sources - [Brendan Mulholland (bmulholland)](https://github.com/bmulholland) (Mange/roadie-rails#32) ### 3.0.2 [full changelog](https://github.com/Mange/roadie/compare/v3.0.1...v3.0.2) * Bug fixes: * Some `data:` URLs could cause exceptions. (#97) * Correctly parse properties with semicolons in their values - [Aidan Feldman (afeld)](https://github.com/afeld) (#100) ### 3.0.1 [full changelog](https://github.com/Mange/roadie/compare/v3.0.0...v3.0.1) * Enhancements: * `CssNotFound` can take a provider which will be shown in error messages. * Bug fixes: * URL rewriter no longer raises on absolute URLs that cannot be parsed by `URI`. Absolute URLs are completely ignored. * URL rewriter supports urls without a scheme (like `//assets.myapp.com/foo`). * URL rewriter no longer crashes on absolute URLs without a path (like `myapp://`). ### 3.0.0 [full changelog](https://github.com/Mange/roadie/compare/v3.0.0.pre1...v3.0.0) * Enhancements: * `Roadie::ProviderList` responds to `#empty?` and `#last` * `Roadie::FilesystemProvider` ignores query string in filename. Older versions of Rails generated `` tags with query strings in their URLs, like such: `/stylesheets/email.css?1380694096` * Blacklist `:enabled`, `:disabled` and `:checked` pseudo functions - [Tyler Hunt (tylerhunt)](https://github.com/tylerhunt). * Add MRI 2.1.2 to Travis build matrix - [Grey Baker (greysteil)](https://github.com/greysteil). * Try to detect an upgrade from Roadie 2 and mention how to make it work with the new version. * Styles emitted in the `style` attribute should now be ordered as they were in the source CSS. ### 3.0.0.pre1 [full changelog](https://github.com/Mange/roadie/compare/v2.4.2...v3.0.0.pre1) Complete rewrite of most of the code and a new direction for the gem. * Breaking changes: * Removed Rails support into a separate Gem (`roadie-rails`). * Removed Sprockets dependency and AssetPipelineProvider. * Changed the entire public API. * Changed the API of custom providers. * Dropped support for Ruby 1.8.7. * Change `data-immutable` to `data-roadie-ignore`. * New features: * Rewriting the URLs of `img[src]`. * A way to inject stylesheets without having to adjust template. * A before callback to compliment the after callback. * Enhancements: * Better support for stylesheets using CSS fallbacks. This means that styles like this is now inlined: `width: 5em; width: 3rem;`, while Roadie would previously remove the first of the two. This sadly means that the HTML file will be much larger than before if you're using a non-optimized stylesheet (for example including your application stylesheet to the email). This was a bad idea even before this change, and this might get you to change. * Using HTML5 doctype instead of XHTML * Full support for JRuby * Experimental support for Rubinius ### 2.4.2 [full changelog](https://github.com/Mange/roadie/compare/v2.4.1...v2.4.2) * Bug fixes: * Fix Nokogiri version to allow only 1.5.x on ruby 1.8.7 * Blacklist :before, :after, :-ms-input-placeholder, :-moz-placeholder selectors – [Brian Bauer (bbauer)][https://github.com/bbauer]. * Build failed on 1.8.7 due to a change in `css_parser` ### 2.4.1 [full changelog](https://github.com/Mange/roadie/compare/v2.4.0...v2.4.1) * Bug fixes: * Allow Nokogiri 1.5.x again; 1.6.x is unsupported in Ruby 1.8.7. ### 2.4.0 [full changelog](https://github.com/Mange/roadie/compare/v2.3.4...v2.4.0) * Enhancements: * Support Rails 4.0, with the help of: * [Ryunosuke SATO (tricknotes)](https://github.com/tricknotes) * [Dylan Markow](https://github.com/dmarkow) * Keep `!important` when outputting styles to help combat web mail styles being `!important` * Support `:nth-child`, `:last-child`, etc. * To make this work, Roadie have to catch errors from Nokogiri and ignore them. A warning will be printed when this happens so users can open issues with the project and tests can be expanded. * Support for custom inliner (#58) — [Harish Shetty (kandadaboggu)](https://github.com/kandadaboggu) with friends * Bug fixes: * Don't crash when URL options have protocols with "://" in them (#52). * Other: * Be more specific on which versions are required; require newer `css_parser` * Officially support MRI 2.0.0 * Add experimental support for JRuby * Remove documentation that talks about passing CSS filenames as symbols; unsupported in Rails 4. (Thanks to [PikachuEXE](https://github.com/PikachuEXE)) ### 2.3.4 [full changelog](https://github.com/Mange/roadie/compare/v2.3.3...v2.3.4) * Enhancements: * Add `config.roadie.enabled` that can be set to `false` to disable Roadie completely. * Bug fixes: * Proc objects to the `:css` option is now run in the context of the mailer instance, mirroring similar options from ActionMailer. * Fix some tests that would always pass * Improve JRuby compatibility * Update Gemfile.lock and fix issues with newer gem versions ### 2.3.3 [full changelog](https://github.com/Mange/roadie/compare/v2.3.2...v2.3.3) * Enhancements: * Allow proc objects to the `:css` option * Bug fixes: * Ignore HTML comments and CDATA sections in CSS (support TinyMCE) ### 2.3.2 [full changelog](https://github.com/Mange/roadie/compare/v2.3.1...v2.3.2) * Bug fixes: * Don't fail on selectors which start with @ (#28) — [Roman Shterenzon (romanbsd)](https://github.com/romanbsd) ### 2.3.1 [full changelog](https://github.com/Mange/roadie/compare/v2.3.0...v2.3.1) * Bug fixes: * Does not work with Rails 3.0 unless provider set specifically (#23) ### 2.3.0 [full changelog](https://github.com/Mange/roadie/compare/v2.3.0.pre1...v2.3.0) * Nothing, really ### 2.3.0.pre1 [full changelog](https://github.com/Mange/roadie/compare/v2.2.0...v2.3.0.pre1) * Enhancements: * Support Rails 3.2.pre1 - [Morton Jonuschat (yabawock)](https://github.com/yabawock) * Sped up the Travis builds * Official support for Rails 3.0 again * Dependencies allow 3.0 * Travis builds 3.0 among the others ### 2.2.0 [full changelog](https://github.com/Mange/roadie/compare/v2.1.0...v2.2.0) * Enhancements: * Support for the `url_options` method inside mailer instances * You can now dynamically alter the URL options on a per-email basis ### 2.1.0 [full changelog](https://github.com/Mange/roadie/compare/v2.1.0.pre2...v2.1.0) * Full release! ### 2.1.0.pre2 [full changelog](https://github.com/Mange/roadie/compare/v2.1.0.pre1...v2.1.0.pre2) * Bug: Roadie broke `url_for` inside mailer views ### 2.1.0.pre1 [full changelog](https://github.com/Mange/roadie/compare/v2.0.0...v2.1.0.pre1) * Enhancements: * Support normal filesystem instead of only Asset pipeline * Enable users to create their own way of fetching CSS * Improve test coverage a bit * Use a railtie to hook into Rails * Use real Rails for testing integration ### 2.0.0 [full changelog](https://github.com/Mange/roadie/compare/v1.1.3...v2.0.0) * Enhancements: * Support the Asset pipeline - [Arttu Tervo (arttu)](https://github.com/arttu) * Dependencies: * Requires Rails 3.1 to work. You can keep on using the 1.x series in Rails 3.0 ### 1.1.3 [full changelog](https://github.com/Mange/roadie/compare/v1.1.2...v1.1.3) * Do not add another ".css" to filenames if already present - [Aliaxandr (saks)](https://github.com/saks) ### 1.1.2 [full changelog](https://github.com/Mange/roadie/compare/v1.1.1...v1.1.2) * Support for Rails 3.1.0 and later inside gemspec ### 1.1.1 [full changelog](https://github.com/Mange/roadie/compare/v1.1.0...v1.1.1) * Support for Rails 3.1.x (up to and including RC4) * Rails 3.0.x is still supported * Added CI via [Travis CI](http://travis-ci.org) ### 1.1.0 [full changelog](https://github.com/Mange/roadie/compare/v1.0.1...v1.1.0) * Enhancements: * Support for inlining `` elements (thanks to [aliix](https://github.com/aliix)) ### 1.0.1 [full changelog](https://github.com/Mange/roadie/compare/v1.0.0...v1.0.1) * Enhancements: * Full, official support for Ruby 1.9.2 (in addition to 1.8.7) * Dependencies: * Explicilty depend on nokogiri >= 1.4.4 ### 1.0.0 [full changelog](https://github.com/Mange/roadie/compare/legacy...v1.0.0) Roadie fork! * Enhancements: * Support for Rails 3.0 * Code cleanup * Support `!important` * Tests * + some other enhancements * Deprecations: * Removed support for Rails 2.x roadie-3.2.2/spec/ 0000755 0000041 0000041 00000000000 13123110273 013734 5 ustar www-data www-data roadie-3.2.2/spec/spec_helper.rb 0000644 0000041 0000041 00000000612 13123110273 016551 0 ustar www-data www-data require 'rspec/collection_matchers' require 'webmock/rspec' if ENV['CI'] require 'simplecov' SimpleCov.start require 'codecov' SimpleCov.formatter = SimpleCov::Formatter::Codecov end $: << File.dirname(__FILE__) + '/../lib' require 'roadie' RSpec.configure do |config| config.run_all_when_everything_filtered = true end Dir['./spec/support/**/*.rb'].each { |file| require file } roadie-3.2.2/spec/lib/ 0000755 0000041 0000041 00000000000 13123110273 014502 5 ustar www-data www-data roadie-3.2.2/spec/lib/roadie/ 0000755 0000041 0000041 00000000000 13123110273 015745 5 ustar www-data www-data roadie-3.2.2/spec/lib/roadie/selector_spec.rb 0000644 0000041 0000041 00000003430 13123110273 021124 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' module Roadie describe Selector do it "can be coerced into String" do expect("I love " + Selector.new("html")).to eq("I love html") end it "can be inlined when simple" do expect(Selector.new("html body #main p.class")).to be_inlinable end it "cannot be inlined when containing pseudo functions" do %w[ p:active p:focus p:hover p:link p:target p:visited p:-ms-input-placeholder p:-moz-placeholder p:before p:after p:enabled p:disabled p:checked ].each do |bad_selector| expect(Selector.new(bad_selector)).not_to be_inlinable end expect(Selector.new('p.active')).to be_inlinable end it "cannot be inlined when containing pseudo elements" do expect(Selector.new('p::some-element')).not_to be_inlinable end it "cannot be inlined when selector is an at-rule" do expect(Selector.new('@keyframes progress-bar-stripes')).not_to be_inlinable end it "has a calculated specificity" do selector = "html p.active.nice #main.deep-selector" expect(Selector.new(selector).specificity).to eq(CssParser.calculate_specificity(selector)) end it "can be told about the specificity at initialization" do selector = "html p.active.nice #main.deep-selector" expect(Selector.new(selector, 1337).specificity).to eq(1337) end it "is equal to other selectors when they match the same things" do expect(Selector.new("foo")).to eq(Selector.new("foo ")) expect(Selector.new("foo")).not_to eq("foo") end it "strips the given selector" do expect(Selector.new(" foo \n").to_s).to eq(Selector.new("foo").to_s) end end end roadie-3.2.2/spec/lib/roadie/markup_improver_spec.rb 0000644 0000041 0000041 00000005477 13123110273 022543 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' module Roadie describe MarkupImprover do def improve(html) dom = Nokogiri::HTML.parse html MarkupImprover.new(dom, html).improve dom end # JRuby up to at least 1.6.0 has a bug where the doctype of a document cannot be changed. # See https://github.com/sparklemotion/nokogiri/issues/984 def pending_for_buggy_jruby # No reason to check for version yet since no existing version has a fix. skip "Pending until Nokogiri issue #984 is fixed and released" if defined?(JRuby) end describe "automatic doctype" do it "inserts a HTML5 doctype if no doctype is present" do pending_for_buggy_jruby expect(improve("").internal_subset.to_xml).to eq("") end it "does not insert duplicate doctypes" do html = improve('
').to_html expect(html.scan('DOCTYPE').size).to eq(1) end it "leaves other doctypes alone" do dtd = "" html = "#{dtd}" expect(improve(html).internal_subset.to_xml.strip).to eq(dtd) end end describe "basic HTML structure" do it "inserts a element as the root" do expect(improve("Hello world!
" subject(:document) { described_class.new sample_html } it "is initialized with HTML" do doc = Document.new "" expect(doc.html).to eq("") end it "has an accessor for URL options" do document.url_options = {host: "foo.bar"} expect(document.url_options).to eq({host: "foo.bar"}) end it "has a setting for keeping uninlinable styles" do expect(document.keep_uninlinable_css).to be true document.keep_uninlinable_css = false expect(document.keep_uninlinable_css).to be false end it "has a ProviderList for normal and external providers" do expect(document.asset_providers).to be_instance_of(ProviderList) expect(document.external_asset_providers).to be_instance_of(ProviderList) end it "defaults to having just a FilesystemProvider in the normal provider list" do expect(document).to have(1).asset_providers expect(document).to have(0).external_asset_providers provider = document.asset_providers.first expect(provider).to be_instance_of(FilesystemProvider) end it "allows changes to the normal asset providers" do other_provider = double "Other proider" old_list = document.asset_providers document.asset_providers = [other_provider] expect(document.asset_providers).to be_instance_of(ProviderList) expect(document.asset_providers.each.to_a).to eq([other_provider]) document.asset_providers = old_list expect(document.asset_providers).to eq(old_list) end it "allows changes to the external asset providers" do other_provider = double "Other proider" old_list = document.external_asset_providers document.external_asset_providers = [other_provider] expect(document.external_asset_providers).to be_instance_of(ProviderList) expect(document.external_asset_providers.each.to_a).to eq([other_provider]) document.external_asset_providers = old_list expect(document.external_asset_providers).to eq(old_list) end it "can store callbacks for inlining" do callable = double "Callable" document.before_transformation = callable document.after_transformation = callable expect(document.before_transformation).to eq(callable) expect(document.after_transformation).to eq(callable) end describe "transforming" do it "runs the before and after callbacks" do document = Document.new "" before = ->{} after = ->{} document.before_transformation = before document.after_transformation = after expect(before).to receive(:call).with(instance_of(Nokogiri::HTML::Document), document).ordered expect(Inliner).to receive(:new).ordered.and_return double.as_null_object expect(after).to receive(:call).with(instance_of(Nokogiri::HTML::Document), document).ordered document.transform end # TODO: Remove on next major version. it "works on callables that don't expect more than one argument" do document = Document.new "" document.before_transformation = ->(first) { } document.after_transformation = ->(first = nil) { } expect { document.transform }.to_not raise_error # It still supplies the second argument, if possible. document.after_transformation = ->(first, second = nil) { raise "Oops" unless second } expect { document.transform }.to_not raise_error end end end describe Document, "(integration)" do it "can transform the document" do document = Document.new <<-HTMLHello, world!
HTML document.add_css "p { color: green; }" result = Nokogiri::HTML.parse document.transform expect(result).to have_selector('html > head > title') expect(result.at_css('title').text).to eq("Greetings") expect(result).to have_selector('html > body > p') paragraph = result.at_css('p') expect(paragraph.text).to eq("Hello, world!") expect(paragraph.to_xml).to eq('Hello, world!
') end it "extracts styles from the HTML" do document = Document.new <<-HTMLHello, world!
HTML document.asset_providers = TestProvider.new({ "/sample.css" => "p { color: red; text-align: right; }", }) document.add_css "p { color: green; text-size: 2em; }" result = Nokogiri::HTML.parse document.transform expect(result).to have_styling([ %w[color red], %w[text-align right], %w[color green], %w[text-size 2em] ]).at_selector("p") end end end roadie-3.2.2/spec/lib/roadie/stylesheet_spec.rb 0000644 0000041 0000041 00000004502 13123110273 021476 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' module Roadie describe Stylesheet do it "is initialized with a name and CSS" do stylesheet = Stylesheet.new("foo.css", "body { color: green; }") expect(stylesheet.name).to eq("foo.css") end it "has a list of blocks" do stylesheet = Stylesheet.new("foo.css", <<-CSS) body { color: green !important; font-size: 200%; } a, i { color: red; } CSS expect(stylesheet).to have(3).blocks expect(stylesheet.blocks.map(&:to_s)).to eq([ "body{color:green !important;font-size:200%}", "a{color:red}", "i{color:red}", ]) end if VERSION < "4.0" it "can iterate all inlinable blocks" do inlinable = double(inlinable?: true, selector: "good", properties: "props") bad = double(inlinable?: false, selector: "bad", properties: "props") stylesheet = Stylesheet.new("example.css", "") allow(stylesheet).to receive_messages blocks: [bad, inlinable, bad] expect(stylesheet.each_inlinable_block.to_a).to eq([ ["good", "props"], ]) end else it "should no longer have #each_inlinable_block" do fail "Remove #each_inlinable_block" end end it "has a string representation of the contents" do stylesheet = Stylesheet.new("example.css", "body { color: green;}a{ color: red; font-size: small }") expect(stylesheet.to_s).to eq("body{color:green}\na{color:red;font-size:small}") end it "understands data URIs" do # http://css-tricks.com/data-uris/ stylesheet = Stylesheet.new("foo.css", <<-CSS) h1 { background-image: url(data:image/gif;base64,R0lGODl) } CSS expect(stylesheet).to have(1).blocks expect(stylesheet.blocks.map(&:to_s)).to eq([ "h1{background-image:url(data:image/gif;base64,R0lGODl)}" ]) end it "does not mutate the input CSS" do input = "/* comment */ body { color: green; }" input_copy = input.dup expect { Stylesheet.new("name", input) }.to_not change { input }.from(input_copy) end it "strips UTF-8 Byte Order Mark" do input = "\xEF\xBB\xBFbody { color: green; }" stylesheet = Stylesheet.new("bom.css", input) expect(stylesheet.to_s).to eq "body{color:green}" end end end roadie-3.2.2/spec/lib/roadie/deduplicator_spec.rb 0000644 0000041 0000041 00000001064 13123110273 021764 0 ustar www-data www-data require "spec_helper" module Roadie describe Deduplicator do it "removes identical pairs, keeping the last one" do input = [ ["a", "1"], ["b", "2"], ["a", "3"], ["a", "1"], ] expect(Deduplicator.apply(input)).to eq [ ["b", "2"], ["a", "3"], ["a", "1"], ] end it "returns input when no duplicates are present" do input = [ ["a", "1"], ["a", "3"], ["a", "2"], ] expect(Deduplicator.apply(input)).to eq input end end end roadie-3.2.2/spec/lib/roadie/style_block_spec.rb 0000644 0000041 0000041 00000002113 13123110273 021613 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' module Roadie describe StyleBlock do it "has a selector and a list of properties" do properties = [] selector = double "Selector" block = StyleBlock.new(selector, properties) expect(block.selector).to eq(selector) expect(block.properties).to eq(properties) end it "delegates #specificity to the selector" do selector = double "Selector", specificity: 45 expect(StyleBlock.new(selector, []).specificity).to eq(45) end it "delegates #inlinable? to the selector" do selector = double "Selector", inlinable?: "maybe" expect(StyleBlock.new(selector, []).inlinable?).to eq("maybe") end it "delegates #selector_string to selector#to_s" do selector = double "Selector", to_s: "yey" expect(StyleBlock.new(selector, []).selector_string).to eq("yey") end it "has a string representation" do properties = [double(to_s: "bar"), double(to_s: "baz")] expect(StyleBlock.new(double(to_s: "foo"), properties).to_s).to eq("foo{bar;baz}") end end end roadie-3.2.2/spec/lib/roadie/style_property_spec.rb 0000644 0000041 0000041 00000003442 13123110273 022413 0 ustar www-data www-data require 'spec_helper' module Roadie describe StyleProperty do it "is initialized with a property, value, if it is marked as important, and the specificity" do StyleProperty.new('color', 'green', true, 45).tap do |declaration| expect(declaration.property).to eq('color') expect(declaration.value).to eq('green') expect(declaration).to be_important expect(declaration.specificity).to eq(45) end end describe "string representation" do it "is the property and the value joined with a colon" do expect(StyleProperty.new('color', 'green', false, 1).to_s).to eq('color:green') expect(StyleProperty.new('font-size', '1.1em', false, 1).to_s).to eq('font-size:1.1em') end it "contains the !important flag when set" do expect(StyleProperty.new('color', 'green', true, 1).to_s).to eq('color:green !important') end end describe "comparing" do def declaration(specificity, important = false) StyleProperty.new('color', 'green', important, specificity) end it "compares on specificity" do expect(declaration(5)).to eq(declaration(5)) expect(declaration(4)).to be < declaration(5) expect(declaration(6)).to be > declaration(5) end context "with an important declaration" do it "is less than the important declaration regardless of the specificity" do expect(declaration(99, false)).to be < declaration(1, true) end it "compares like normal when both declarations are important" do expect(declaration(5, true)).to eq(declaration(5, true)) expect(declaration(4, true)).to be < declaration(5, true) expect(declaration(6, true)).to be > declaration(5, true) end end end end end roadie-3.2.2/spec/lib/roadie/null_url_rewriter_spec.rb 0000644 0000041 0000041 00000000714 13123110273 023065 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' require 'shared_examples/url_rewriter' module Roadie describe NullUrlRewriter do let(:generator) { double "URL generator" } subject(:rewriter) { NullUrlRewriter.new(generator) } it_behaves_like "url rewriter" it "does nothing when transforming DOM" do dom = double "DOM tree" expect { NullUrlRewriter.new(generator).transform_dom dom }.to_not raise_error end end end roadie-3.2.2/spec/lib/roadie/css_not_found_spec.rb 0000644 0000041 0000041 00000001415 13123110273 022150 0 ustar www-data www-data require 'spec_helper' module Roadie describe CssNotFound do it "is initialized with a name" do error = CssNotFound.new('style.css') expect(error.css_name).to eq('style.css') expect(error.message).to eq('Could not find stylesheet "style.css"') end it "can be initialized with an extra message" do expect(CssNotFound.new('file.css', "directory is missing").message).to eq( 'Could not find stylesheet "file.css": directory is missing' ) end it "shows information about used provider when given" do provider = double("Some cool provider") expect(CssNotFound.new('style.css', nil, provider).message).to eq( %(Could not find stylesheet "style.css"\nUsed provider:\n#{provider}) ) end end end roadie-3.2.2/spec/lib/roadie/cached_provider_spec.rb 0000644 0000041 0000041 00000003013 13123110273 022422 0 ustar www-data www-data require 'spec_helper' require 'roadie/rspec' require 'shared_examples/asset_provider' module Roadie describe CachedProvider do let(:upstream) { TestProvider.new("good.css" => "body { color: green; }") } let(:cache) { Hash.new } subject(:provider) { CachedProvider.new(upstream, cache) } it_behaves_like "roadie asset provider", valid_name: "good.css", invalid_name: "bad.css" it "stores retrieved stylesheets in the cache" do found = nil expect { found = provider.find_stylesheet("good.css") }.to change(cache, :keys).to(["good.css"]) expect(cache["good.css"]).to eq found end it "reads from the cache first" do found = upstream.find_stylesheet!("good.css") cache["good.css"] = found expect(upstream).to_not receive(:find_stylesheet) expect(provider.find_stylesheet("good.css")).to eq found expect(provider.find_stylesheet!("good.css")).to eq found end it "stores failed lookups in the cache" do expect { provider.find_stylesheet("foo.css") }.to change(cache, :keys).to(["foo.css"]) expect(cache["foo.css"]).to be_nil end it "stores failed lookups even when raising errors" do expect { provider.find_stylesheet!("bar.css") }.to raise_error CssNotFound expect(cache.keys).to include "bar.css" expect(cache["bar.css"]).to be_nil end it "defaults to a hash for cache storage" do expect(CachedProvider.new(upstream).cache).to be_kind_of Hash end end end roadie-3.2.2/spec/lib/roadie/inliner_spec.rb 0000644 0000041 0000041 00000017366 13123110273 020761 0 ustar www-data www-data # encoding: UTF-8 require 'spec_helper' module Roadie describe Inliner do before { @stylesheet = "".freeze } def use_css(css) @stylesheet = Stylesheet.new("example", css) end def rendering(html, stylesheet = @stylesheet) dom = Nokogiri::HTML.parse html Inliner.new([stylesheet], dom).inline dom end describe "inlining styles" do it "inlines simple attributes" do use_css 'p { color: green }' expect(rendering('')).to have_styling('color' => 'green') end it "keeps multiple versions of the same property to support progressive enhancement" do # https://github.com/premailer/css_parser/issues/44 pending "css_parser issue #44" use_css 'p { color: #eee; color: rgba(255, 255, 255, 0.9); }' expect(rendering('')).to have_styling( [['color', 'green'], ['color', 'rgba(255, 255, 255, 0.9)']] ) end it "de-duplicates identical styles" do use_css ' p { color: green; } .message { color: blue; } .positive { color: green; } ' expect(rendering('')).to have_styling( [['color', 'blue'], ['color', 'green']] ) end it "inlines browser-prefixed attributes" do use_css 'p { -vendor-color: green }' expect(rendering('')).to have_styling('-vendor-color' => 'green') end it "inlines CSS3 attributes" do use_css 'p { border-radius: 2px; }' expect(rendering('')).to have_styling('border-radius' => '2px') end it "keeps the order of the styles that are inlined" do use_css 'h1 { padding: 2px; margin: 5px; }' expect(rendering('')).to have_styling([['padding', '2px'], ['margin', '5px']]) end it "combines multiple selectors into one" do use_css 'p { color: green; } .tip { float: right; }' expect(rendering('')).to have_styling([['color', 'green'], ['float', 'right']]) end it "uses the attributes with the highest specificity when conflicts arises" do use_css ".safe { color: green; } p { color: red; }" expect(rendering('')).to have_styling([['color', 'red'], ['color', 'green']]) end it "sorts styles by specificity order" do use_css 'p { important: no; } #important { important: very; } .important { important: yes; }' expect(rendering('')).to have_styling([ %w[important no], %w[important yes] ]) expect(rendering('')).to have_styling([ %w[important no], %w[important yes], %w[important very] ]) end it "supports multiple selectors for the same rules" do use_css 'p, a { color: green; }' rendering('').tap do |document| expect(document).to have_styling('color' => 'green').at_selector('p') expect(document).to have_styling('color' => 'green').at_selector('a') end end it "keeps !important properties" do use_css "a { text-decoration: underline !important; } a.hard-to-spot { text-decoration: none; }" expect(rendering('')).to have_styling([ ['text-decoration', 'none'], ['text-decoration', 'underline !important'] ]) end it "combines with already present inline styles" do use_css "p { color: green }" expect(rendering('')).to have_styling([['color', 'green'], ['font-size', '1.1em']]) end it "does not override inline styles" do use_css "p { text-transform: uppercase; color: red }" # The two color properties are kept to make css fallbacks work correctly expect(rendering('')).to have_styling([ ['text-transform', 'uppercase'], ['color', 'red'], ['color', 'green'], ]) end it "does not apply link and dynamic pseudo selectors" do use_css " p:active { color: red } p:focus { color: red } p:hover { color: red } p:link { color: red } p:target { color: red } p:visited { color: red } p.active { width: 100%; } " expect(rendering('')).to have_styling('width' => '100%') end it "does not crash on any pseudo element selectors" do use_css " p.some-element { width: 100%; } p::some-element { color: red; } " expect(rendering('')).to have_styling('width' => '100%') end it "warns on selectors that crash Nokogiri" do dom = Nokogiri::HTML.parse "" stylesheet = Stylesheet.new "foo.css", "p[%^=foo] { color: red; }" inliner = Inliner.new([stylesheet], dom) expect(Utils).to receive(:warn).with( %{Cannot inline "p[%^=foo]" from "foo.css" stylesheet. If this is valid CSS, please report a bug.} ) inliner.inline end it "works with nth-child" do use_css " p { color: red; } p:nth-child(2n) { color: green; } " result = rendering(" ") expect(result).to have_styling([['color', 'red']]).at_selector('p:first') expect(result).to have_styling([['color', 'red'], ['color', 'green']]).at_selector('p:last') end context "with uninlinable selectors" do before do allow(Roadie::Utils).to receive(:warn) end it "puts them in a new HTML scanner = AssetScanner.new dom, normal_provider, external_provider stylesheets = scanner.find_css expect(stylesheets).to have(2).stylesheets expect(stylesheets[0].to_s).to include("green") expect(stylesheets[1].to_s).to include("red") expect(stylesheets.first.name).to eq("(inline)") end it "does not find any embedded stylesheets marked for ignoring" do dom = dom_document <<-HTML HTML scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to have(1).stylesheet end it "finds normal referenced stylesheets through the normal provider" do stylesheet = double "A stylesheet" expect(normal_provider).to receive(:find_stylesheet!).with("/some/url.css").and_return stylesheet dom = dom_fragment %() scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([stylesheet]) end it "finds external referenced stylesheets through the external provider" do stylesheet = double "A stylesheet" external_provider = TestProvider.new expect(external_provider).to receive(:find_stylesheet!).with("//example.com/style.css").and_return stylesheet dom = dom_fragment %() scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([stylesheet]) end it "ignores referenced print stylesheets" do dom = dom_fragment %() expect(normal_provider).not_to receive(:find_stylesheet!) scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([]) end it "does not look for externally referenced stylesheets from empty ProviderList" do external_provider = ProviderList.empty dom = dom_fragment %() expect(external_provider).not_to receive(:find_stylesheet!) scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([]) end it "does not look for ignored referenced stylesheets" do dom = dom_fragment %() expect(normal_provider).not_to receive(:find_stylesheet!) scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([]) end it 'ignores HTML comments and CDATA sections' do # TinyMCE posts invalid CSS. We support that just to be pragmatic. dom = dom_fragment %() scanner = AssetScanner.new dom, normal_provider, external_provider stylesheet = scanner.find_css.first expect(stylesheet.to_s).to include("green") expect(stylesheet.to_s).not_to include("!--") expect(stylesheet.to_s).not_to include("CDATA") end it "does not pick up scripts generating styles" do dom = dom_fragment <<-HTML HTML scanner = AssetScanner.new dom, normal_provider, external_provider expect(scanner.find_css).to eq([]) end end describe "extracting" do it "returns the stylesheets found, and removes them from the DOM" do dom = dom_document <<-HTMLCheck out these awesome prices!
HTML document.add_css <<-CSS em { color: red; } h1 { text-align: center; } CSS result = parse_html document.transform expect(result).to have_styling('text-align' => 'center').at_selector('h1') expect(result).to have_styling('color' => 'red').at_selector('p > em') end it "stores styles that cannot be inlined in the " do document = Roadie::Document.new <<-HTMLCheck out these awesome prices!
HTML css = <<-CSS em:hover { color: red; } p:fung-shuei { color: spirit; } CSS document.add_css css expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/) result = parse_html document.transform expect(result).to have_selector("html > head > style") styles = result.at_css("html > head > style").text expect(styles).to include Roadie::Stylesheet.new("", css).to_s end it "can be configured to skip styles that cannot be inlined" do document = Roadie::Document.new <<-HTMLCheck out these awesome prices!
HTML css = <<-CSS em:hover { color: red; } p:fung-shuei { color: spirit; } CSS document.add_css css document.keep_uninlinable_css = false expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/) result = parse_html document.transform expect(result).to_not have_selector("html > head > style") end it "inlines css from disk" do document = Roadie::Document.new <<-HTMLCheck out these awesome prices!
HTML result = parse_html document.transform expect(result).to have_styling('font-size' => '200%').at_selector('p > em') end it "crashes when stylesheets cannot be found, unless using NullProvider" do document = Roadie::Document.new <<-HTML HTML expect { document.transform }.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/) document.asset_providers << Roadie::NullProvider.new expect { document.transform }.to_not raise_error end it "ignores external css if no external providers are added" do document = Roadie::Document.new <<-HTMLCheck out these awesome prices!
HTML document.external_asset_providers = [] result = parse_html document.transform expect(result).to have_selector('head > link') expect(result).to have_styling([]).at_selector('p > em') end it "inlines external css if configured" do document = Roadie::Document.new <<-HTMLCheck out these awesome prices!
HTML document.external_asset_providers = TestProvider.new( "http://example.com/big_em.css" => "em { font-size: 200%; }" ) result = parse_html document.transform expect(result).to have_styling('font-size' => '200%').at_selector('p > em') expect(result).to_not have_selector('head > link') end it "does not inline the same properties several times" do document = Roadie::Document.new <<-HTMLHello world
HTML document.asset_providers = TestProvider.new("hello.css" => <<-CSS) p { color: red; } .hello { color: red; } .world { color: red; } CSS result = parse_html document.transform expect(result).to have_styling([ ['color', 'red'] ]).at_selector('p') end it "makes URLs absolute" do document = Roadie::Document.new <<-HTMLOne | 1 |
Two | 2 |