I'm using Haml in a Rails 3 app, and its newlines drive me nuts! For example,
%span
foo
renders as
<span>
foo
</span>
But I'd much rather want
<span>foo</foo>
The reason (apart from being cleaner XML) is that extra newlines are a problem for my Selenium tests because they mess up the ability to do XPath queries like "//span[.='foo']"
. So I'd have to write '\nfoo\n'
instead (ew!), or use //span[contains(text(), 'foo')]
, which matches too broadly.
I know I could use the alligator operators ("<" and ">") to strip whitespace, but since I don't ever have a case where I want the newlines to appear in the output, I'd just end up adding them mechanically at the end of each line. And that just seems very unDRY.
So now I see two solutions:
nuke_inner_whitespace
/ nuke_outer_whitespace
variables spread around the Haml code that might do the job, but I'm not sure how to change them without resorting to gratuitous monkey-patching.gsub!("\n", "")
to all rendered HTML. (For textarea's and pre's, I could still use ~ "foo\nbar"
to make Haml emit foo
bar
.) But where's the right place to hook into Rails? I'm a little lost in the code.Any pointers or other suggestions appreciated!
Update: I've used Jason's monkey patch below for a while now and I'm beginning to think that it's not worth it. E.g. if I want to get <span>[del]</span> <span>foo</span>
, it's difficult to not have the blank space in between nuked. Even the following will render as [del]foo
on the page:
%span
= '[del] '
%span
foo
So I think I'm going back to adding alligator operators manually (see my self-answer down below). Live and learn.
Thanks again to Jason! :)
If you place a less-than sign at the end of the element name the whitespace around the content will be suppressed:
%span<
foo
See whitespace removal in the Haml reference for more details.
There doesn't appear to be any clean way to force these flags on for all tags but the following monkey patch works fine with Haml 3.0.24:
module Haml::Precompiler
def parse_tag_with_nuked_whitespace(line)
result = parse_tag_without_nuked_whitespace line
unless result.size == 9 && [false,true].include?(result[4]) && [false,true].include?(result[5])
raise "Unexpected parse_tag output: #{result.inspect}"
end
result[4] = true # nuke_outer_whitespace
result[5] = true # nuke_inner_whitespace
result
end
alias_method_chain :parse_tag, :nuked_whitespace
end
It probably wouldn't be hard to fork Haml and add an option to the Engine options to always nuke whitespace. The parse_tag method could check this option if enabled and set the inner and outer flags to true. I'll leave this as an exercise for the reader. :)
A few ways to do it:
%span foo
%span= "foo"
- foo = ["f", "o", "o"].join("")
%span= foo
%span #{"foo"}
- foo = ["f", "o", "o"].join("")
%span #{foo}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With