Haml: Control whitespace around text

2019-01-08 02:47发布

问题:

In my Rails template, I'd like to accomplish final HTML to this effect using HAML:

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

The template that comes close:

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 may, however, note that this produces a space between the link and the comma. Is there any practical way to avoid this whitespace? I know there's syntax to remove whitespace around tags, but can this same syntax be applied to just text? I really don't like the solution of extra markup to accomplish this.

回答1:

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


回答2:

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


回答3:

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!



回答4:

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_



回答5:

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.



回答6:

You can do this to keep the leading space:

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

The space is in the quotes.



回答7:

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).



回答8:

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



回答9:

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.



回答10:

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

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


回答11:

You could also always do:

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


回答12:

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.



回答13:

The preserve function worked for me

.white-space-pre= preserve "TEXT"