Haml: 控制文本周围的空白

在我的 Rails 模板中,我想使用 HAML 来完成这种效果的最终 HTML:

I will first <a href="http://example.com">link somewhere</a>, then render this half of the sentence if a condition is met

这个模板非常接近:

I will first
= link_to 'link somewhere', 'http://example.com'
- if @condition
, then render this half of the sentence if a condition is met

但是,您可能会注意到,这会在链接和逗号之间产生一个空格。有什么实际的方法可以避免这种空格吗?我知道有一些语法可以去除标签周围的空白,但是这种语法可以仅仅应用于文本吗?我真的不喜欢用额外的标记来完成这个任务。

39760 次浏览

There's the angle bracket "whitespace munching" syntax, otherwise write a helper method for it.

Alright, here's the solution I'm settling on:

Helper

def one_line(&block)
haml_concat capture_haml(&block).gsub("\n", '').gsub('\\n', "\n")
end

View

I will first
- one_line do
= link_to 'link somewhere', 'http://example.com'
- if @condition
, then render this half of the sentence
\\n
if a condition is met

That way, whitespace is excluded by default, but I can still explicitly include it with a "\n" line. (It needs the double-backslash because otherwise HAML interprets it as an actual newline.) Let me know if there's a better option out there!

Once approach I've taken to this sort of thing is to use string interpolation:

I will first #{link_to 'Link somewhere'}#{', then render this half of the sentence if a condition is met' if condition}

I don't like the look of the literal string in the interpolation, but I've used it with previously declared strings or dynamically generated strings before.

You can also do this using Haml's "trim whitespace" modifier. Inserting > after a Haml declaration will prevent whitespace from being added around it:

I will first
%a{:href => 'http://example.com'}> link somewhere
- if @condition
, then render this half of the sentence if a condition is met

produces:

I will first<a href='http://example.com'>link somewhere</a>, then render this half of the sentence if a condition is met

However, as you can see, the > modifier also strips the whitespace in front of the link, removing the desired space between the words and the link. I haven't figured a pretty way around this yet, except to add &nbsp; to the end of "I will first", like so:

I will first&nbsp;
%a{:href => 'http://example.com'}> link somewhere
- if @condition
, then render this half of the sentence if a condition is met

Which finally produces the desired output without lots of hard-to-read interpolation:

I will first&nbsp;<span><a href="http://example.com">link somewhere</a></span>, then render this half of the sentence if a condition is met

You can do this to keep the leading space:

%a{:href => 'http://example.com'}>= ' link somewhere'

The space is in the quotes.

Although not well documented, this is cleanly achieved using HAML whitespace preservation (>) combined with an ASCII space (& #32;), and not with helpers:

%a{:href=>'/home'}> Home link
,&#32;
%a{:href=>'/page'} Next link

This will produce what you want:

<a href='/home'>Anchor text</a>,&#32;
<a href='/page'>More text</a>

But I agree, HAML needs to come up with a better way of doing this, as it does add unnecessary ASCII characters to the page (but it's still more efficient than using helpers).

I came across a similar problem and found this so I thought I would post another solution which doesn't require a helper method. Use Ruby interpolation #{} to wrap the link and if statements:

I will first
#{link_to 'link somewhere', 'http://example.com'}#{if true : ", then render this half of the sentence if a condition is met" end}

This works in 3.0.18, it may also work in earlier releases.

A better way to do this has been introduced via Haml's helpers:

surround

= surround '(', ')' do
%a{:href => "food"} chicken
Produces:
(<a href='food'>chicken</a>)

succeed:

click
= succeed '.' do
%a{:href=>"thing"} here
Produces:
click
<a href='thing'>here</a>.

precede:

= precede '*' do
%span.small Not really
Produces:
*<span class='small'>Not really</span>

To answer the original question:

I will first
= succeed ',' do
= link_to 'link somewhere', 'http://example.com'
- if @condition
then render this half of the sentence if a condition is met
Produces:
I will first
<a href="http://example.com">link somewhere</a>,
then render this half of the sentence if a condition is met

Yet another option that I've used in the past:

- if @condition
%span> , then some more text after the link.

You could also always do:

= link_to url_path do
= ["part_1", "part_2"].join(", ")

You can use the 'aligator syntax' of HAML

Whitespace Removal: > and <

and < give you more control over the whitespace near a tag. > will remove all whitespace surrounding a tag, while < will remove all whitespace immediately within a tag. You can think of them as alligators eating the whitespace: > faces out of the tag and eats the whitespace on the outside, and < faces into the tag and eats the whitespace on the inside. They’re placed at the end of a tag definition, after class, id, and attribute declarations but before / or =.

http://haml.info/docs/yardoc/file.REFERENCE.html#whitespace_removal__and_

The solution that I got working is:

I will first
= link_to 'link somewhere', 'http://example.com'
- if @condition
= ", then render this half of the sentence if a condition is met"

You can use =, though = is used to output the result of Rails code, but here it will server the purpose.

The preserve function worked for me

.white-space-pre= preserve "TEXT"