rails / tailwindcss-rails

MIT License
1.39k stars 171 forks source link

Rails underscore escaping issues #340

Closed tumes closed 6 months ago

tumes commented 6 months ago

I am fairly certain this is a legit bug, though I may be overthinking. I was attempting to use tailwind to style against Rails' field_with_errors form validation wrappers using groups with arbitrary values. So I end up with something like:

<div class="group">
  <div class="field_with_errors">
    ...invalid input...
  </div>
  <div class="group-has-[.field\_with\_errors]:block hidden">
    ..some inline errors..
  </div>
</div>

This works in the context of regular html, but if, for example, I am including a group-has-* declaration inside of a Rails form helper, backslashes are escaped, meaning I have to write something like:

<%= form.label :tos, class: "group-has-[.field\\_with\\_errors]:block hidden" %>

Which appears to produce the following CSS in the final output

.group:has(.field\_with\_errors) .group-has-\[\.field\\\\_with\\\\_errors\]\:text-red-800 {
    --tw-text-opacity: 1;
    color: rgb(153 27 27/var(--tw-text-opacity))
}

.group:has(.field_with_errors) .group-has-\[\.field\\_with\\_errors\]\:text-red-800 {
    --tw-text-opacity: 1;
    color: rgb(153 27 27/var(--tw-text-opacity))
}

Which is a little weird! This is not critical, there are a million ways around this (change the field_with_errors generation proc, writing regular styles to catch this case, putting some dummy classes in an unused view to coerce it into producing the right final CSS, etc. etc.), but it seems to have uncovered a quirky edge case collision between how tailwind and Rails treat escape characters and it'd be nice to not produce wonky, ultimately unused CSS.

flavorjones commented 6 months ago

@tumes If you wrap this in single quotes:

  <%= form.label :tos, class: 'group-has-[.field\_with\_errors]:block hidden' %>

then the generated CSS is slightly better:

.group:has(.field_with_errors) .group-has-\[\.field\\_with\\_errors\]\:block {
  display: block;
}

Beyond that, I don't really know what advice to give you. It's not really a bug unless there's a fix for it; and tailwindcss and ruby are behaving according to well-formed string escaping rules.

Ruby isn't the only language that makes this awkward, see for example the conversation here re: other JS frameworks, and although there was some chatter about changing the meaning of underscores in tailwind, it would almost certainly end up being a breaking change.

flavorjones commented 6 months ago

Also please note -- re: the comment about "unused CSS" -- if you re-start the tailwindcss:watch process, you should only see one version of the CSS. Modifying markup causes tailwindcss to append to the existing rules, and so re-starting the process will rewrite the CSS from scratch.