Mange / roadie

Making HTML emails comfortable for the Ruby rockstars

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Selector with nth-child does not work

PikachuEXE opened this issue · comments

Rails 3.2.12, Roadie 2.3.4, nokogiri 1.5.6
I want alternative row background color effect
So I tried:

  .job-row:nth-child(2n) {
    background-color: $grey-lighter;
  }

  .job-row:nth-child(2n+1) {
    background-color: $grey-lighter;
  }

The code itself has no error.
I tested it by pasting the selector to inspector in Chrome
I am not sure if its the problem of roadie or one of dependencies

I am using this for the effect right now

.job-row(class: cycle('row-odd', 'row-even'))

I can confirm this with a simple test case. I hope to fix this soon.

Nice 👍
CSS3 selectors are really helpful :P

Please help me by testing the master branch. I expect you to get warnings while generating emails if you have a complex CSS.

I'd like to see which warnings you get to see if I need to expand the blacklist before releasing this.

Thanks for the report!

Let me test it after this deployment :P

I got error after using master
It seems importing from bootstrap cause this error
Which includes the following: (might update later)

@import "bootstrap/buttons";

Here is the stack trace:

Nokogiri::CSS::SyntaxError - unexpected ':' after ':':
  (gem) nokogiri-1.5.8/lib/nokogiri/css/parser_extras.rb:87:in `on_error'
  /usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/racc/parser.rb:258:in `do_parse'
  (gem) nokogiri-1.5.8/lib/nokogiri/css/parser_extras.rb:62:in `parse'
  (gem) nokogiri-1.5.8/lib/nokogiri/css/parser_extras.rb:79:in `xpath_for'
  (gem) nokogiri-1.5.8/lib/nokogiri/css.rb:23:in `xpath_for'
  (gem) nokogiri-1.5.8/lib/nokogiri/xml/node.rb:211:in `block in css'
  (gem) nokogiri-1.5.8/lib/nokogiri/xml/node.rb:210:in `css'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:159:in `each_element_in_selector'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:137:in `block (3 levels) in elements_with_declarations'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:154:in `block in each_good_selector'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:153:in `each_good_selector'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:136:in `block (2 levels) in elements_with_declarations'
  (gem) css_parser-1.3.4/lib/css_parser/parser.rb:178:in `block in each_rule_set'
  (gem) css_parser-1.3.4/lib/css_parser/parser.rb:176:in `each_rule_set'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:135:in `block in elements_with_declarations'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:134:in `elements_with_declarations'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:119:in `inline_css_rules'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:54:in `block in execute'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:77:in `block in adjust_html'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:76:in `adjust_html'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:49:in `execute'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie.rb:6:in `inline_css'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:61:in `inline_style_response'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:48:in `block in collect_responses_and_parts_order_with_inline_styles'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:48:in `collect_responses_and_parts_order_with_inline_styles'
  (gem) actionmailer-3.2.12/lib/action_mailer/base.rb:648:in `mail'
  /usr/local/rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:29:in `mail_with_inline_styles'
  app/mailers/individual_mailer.rb:11:in `job_summary'

So in bootstrap
There are some code like:

button.btn,
input[type="submit"].btn {

  // Firefox 3.6 only I believe
  &::-moz-focus-inner {
    padding: 0;
    border: 0;
  }

  // IE7 has some default padding on button controls
  *padding-top: 3px;
  *padding-bottom: 3px;

  &.btn-large {
    *padding-top: 7px;
    *padding-bottom: 7px;
  }
  &.btn-small {
    *padding-top: 3px;
    *padding-bottom: 3px;
  }
  &.btn-mini {
    *padding-top: 1px;
    *padding-bottom: 1px;
  }
}

The rule of input[type="submit"].btn::-moz-focus-inner (with two :) is the cause of error
(When I commented it out then the mail can be generate)

But this is quite common for browser support
See this article

Need another fix :P

I got no warning (or I don't know where to look)
And the CSS3 selectors are working as expected
When I commented out that rule

Great :D

Thanks for the test! I'll add that pseudo selector to the test cases and see what I can do about it.

I'm not sure if this is the same error, or caused by something different, but I'm having similar problems:

nokogiri (1.5.9) lib/nokogiri/css/parser_extras.rb:87:in `on_error'
    /Users/hayk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/racc/parser.rb:258:in `_racc_do_parse_c'
    /Users/hayk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/racc/parser.rb:258:in `do_parse'
    nokogiri (1.5.9) lib/nokogiri/css/parser_extras.rb:62:in `parse'
    nokogiri (1.5.9) lib/nokogiri/css/parser_extras.rb:79:in `xpath_for'
    nokogiri (1.5.9) lib/nokogiri/css.rb:23:in `xpath_for'
    nokogiri (1.5.9) lib/nokogiri/xml/node.rb:211:in `block in css'
    nokogiri (1.5.9) lib/nokogiri/xml/node.rb:210:in `map'
    nokogiri (1.5.9) lib/nokogiri/xml/node.rb:210:in `css'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:159:in `each_element_in_selector'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:137:in `block (3 levels) in elements_with_declarations'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:154:in `block in each_good_selector'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:153:in `each'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:153:in `each_good_selector'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:136:in `block (2 levels) in elements_with_declarations'
    css_parser (1.3.4) lib/css_parser/parser.rb:178:in `block in each_rule_set'
    css_parser (1.3.4) lib/css_parser/parser.rb:176:in `each'
    css_parser (1.3.4) lib/css_parser/parser.rb:176:in `each_rule_set'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:135:in `block in elements_with_declarations'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:134:in `tap'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:134:in `elements_with_declarations'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:119:in `inline_css_rules'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:54:in `block in execute'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:77:in `block in adjust_html'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:76:in `tap'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:76:in `adjust_html'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/inliner.rb:49:in `execute'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie.rb:6:in `inline_css'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:61:in `inline_style_response'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:48:in `block in collect_responses_and_parts_order_with_inline_styles'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:48:in `map'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:48:in `collect_responses_and_parts_order_with_inline_styles'
    actionmailer (3.2.13) lib/action_mailer/base.rb:648:in `mail'
    /Users/hayk/.rvm/gems/ruby-2.0.0-p0/bundler/gems/roadie-d4be3ccdde50/lib/roadie/action_mailer_extensions.rb:29:in `mail_with_inline_styles'
    app/mailers/notification.rb:13:in `notify_client'

@hayksaakian What is the error message?

In one instance (if i set :css => :bootstrap)
unexpected '!' after ''

If I use :css => :application I get

unexpected '(' after ''

I don't import the whole bootstrap style since not all of them are useful in emails
Maybe try to import a file (mailer for me) and try importing things you need

Try to only import the things you need from bootstrap
So we can find out what really need to be fixed first

Oops duplicated due to cached page o.o

I've pushed some changes to the master branch now. Most importantly:

  • ::-moz-focus-inner (and similar) should no longer cause any errors
  • Roadie warns about which specific selector is causing errors now; e.g. by looking at the program output you should get a better message to use when reporting an issue and/or finding the style in your own files.

@hayksaakian please try the latest master and see which selector is causing your errors.

::-moz-focus-inner is passing :)
Trying to use application now

EDIT:
application has too many rules to inject (time out using mail preview)
And I don't use application anyway
Let's wait for @hayksaakian to try it out

Still does not seem to work

I put the relevant logs here:
https://gist.github.com/hayksaakian/5315927

it seems like there's some javascript making it's way into the template / inlining process

Most of the "selectors" are JS code
How come?

I was using the absolute latest master on github, but perhaps there's a specific commit you'd (@Mange ) prefer I try?

@hayksaakian No, it was the correct commit.

I think you have invalid HTML, or have put JS inside a <style> tag. This problem was always there, but Roadie was just silently ignoring those errors before. I think you should try to disable Roadie and look at the outputted HTML from a vanilla email and see what happened.

If you cannot find anything, you may paste the code in here (or email with if the data is sensitive).

application has too many rules to inject (time out using mail preview)

Whoa. Either that is one massive stylesheet or I need to optimize Roadie more. How big is it?

I waited for more than 2 minutes
So I killed the process

Not sure how big it is (I will try to precompile tomorrow)
But I don't think I would ever use application for mailer style file

Well, the browsers are all able to parse and apply your application in the matter of milliseconds (I assume), so the performance isn't that great. Perhaps I've done something very inefficient somewhere in the code.

Then let me try again tomorrow :)

I got 2 errors while playing with application.scss

Roadie cannot use ".control-group input:not([type=\"checkbox\"]):not([type=\"radio\"])" when inlining stylesheets
Roadie got error when looking for ".some-list tr:nth-child(4n-3)": parse error on IDENT 'n-3'
Roadie got error when looking for ".some-list tr:nth-child(4n-3)": parse error on IDENT 'n-3'

When I started looking, it looked like having a minus sign there was incompatible, but I went straight to the source and lo and behold, it should be supported!

I'll open an issue with Nokogiri about this.

Roadie cannot use ".control-group input:not([type=\"checkbox\"]):not([type=\"radio\"])" when inlining stylesheets

This is most likely Nokogiri that does not support multiple :not on the same selectors. I cannot find any test in the Nokogiri repo that actually parses this, but I do find examples of it in the W3C specifications.

This might also be a prime candidate for a Nokogiri issue. I'll see about it.


Something to note: None of these worked before, but this problem is visible now so developers can work around them. :-)

It's great to find these problems before I actually need them

I got error similar to @hayksaakian (with JS code in warning)
if I require stylesheet from vendor with:
require_tree ../../../vendor/assets/stylesheets
Very strange...

I've opened a PR for the first issue here: sparklemotion/nokogiri#886

Second issue will be opened later when I get the time.


Which vendor stylesheets do you use? One of them should be the culprit.

I've opened the second issue now: sparklemotion/nokogiri#887

Let's hope they get merged! 😸

Both of them are merged :D

I'm going to release a new minor release with these fixes in them. Thanks for helping me test, guys!

2.4.0 has now been released. When Nokogiri releases 1.6.1 you should be able to inline :not:not and other goodies.