Module: Haml::Helpers

Extended by:
Helpers
Includes:
ActionViewExtensions
Included in:
Buffer, Helpers
Defined in:
lib/haml/helpers.rb,
lib/haml/helpers/action_view_extensions.rb

Overview

This module contains various helpful methods to make it easier to do various tasks. Haml::Helpers is automatically included in the context that a Haml template is parsed in, so all these methods are at your disposal from within the template.

Defined Under Namespace

Modules: ActionViewExtensions Classes: ErrorReturn

Constant Summary collapse

HTML_ESCAPE =

Characters that need to be escaped to HTML entities from user input

{ '&'=>'&amp;', '<'=>'&lt;', '>'=>'&gt;', '"'=>'&quot;', "'"=>'&#039;', }
@@action_view_defined =
defined?(ActionView)
@@force_no_action_view =
false

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActionViewExtensions

#page_class

Class Method Details

.action_view?Boolean

Returns whether or not ActionView is installed on the system.

Returns:

  • (Boolean)


33
34
35
# File 'lib/haml/helpers.rb', line 33

def self.action_view?
  @@action_view_defined
end

Instance Method Details

#block_is_haml?(block) ⇒ Boolean

Returns whether or not block is defined directly in a Haml template.

Returns:

  • (Boolean)


436
437
438
439
440
441
# File 'lib/haml/helpers.rb', line 436

def block_is_haml?(block)
  eval('_hamlout', block.binding)
  true
rescue
  false
end

#capture_haml(*args, &block) ⇒ Object

Captures the result of the given block of Haml code, gets rid of the excess indentation, and returns it as a string. For example, after the following,

.foo
  - foo = capture_haml(13) do |a|
    %p= a

the local variable foo would be assigned to “<p>13</p>n”.



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/haml/helpers.rb', line 273

def capture_haml(*args, &block)
  buffer = eval('_hamlout', block.binding) rescue haml_buffer
  with_haml_buffer(buffer) do
    position = haml_buffer.buffer.length

    block.call(*args)

    captured = haml_buffer.buffer.slice!(position..-1).split(/^/)

    min_tabs = nil
    captured.each do |line|
      tabs = line.index(/[^ ]/) || line.length
      min_tabs ||= tabs
      min_tabs = min_tabs > tabs ? tabs : min_tabs
    end

    captured.map do |line|
      line[min_tabs..-1]
    end.join
  end
end

#escape_once(text) ⇒ Object

Escapes HTML entities in text, but without escaping an ampersand that is already part of an escaped entity.



422
423
424
# File 'lib/haml/helpers.rb', line 422

def escape_once(text)
  text.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |s| HTML_ESCAPE[s] }
end

#find_and_preserve(input = nil, tags = haml_buffer.options[:preserve], &block) ⇒ Object

call-seq:

find_and_preserve(input, tags = haml_buffer.options[:preserve])
find_and_preserve(tags = haml_buffer.options[:preserve]) {...}

Uses preserve to convert any newlines inside whitespace-sensitive tags into the HTML entities for endlines. tags is an array of tags to preserve. It defaults to the value of the :preserve option.



87
88
89
90
91
92
93
94
# File 'lib/haml/helpers.rb', line 87

def find_and_preserve(input = nil, tags = haml_buffer.options[:preserve], &block)
  return find_and_preserve(capture_haml(&block), input || tags) if block

  input = input.to_s
  input.gsub(/<(#{tags.map(&Regexp.method(:escape)).join('|')})([^>]*)>(.*?)(<\/\1>)/im) do
    "<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
  end
end

#haml_concat(text = "") ⇒ Object

Outputs text directly to the Haml buffer, with the proper tabulation



305
306
307
308
# File 'lib/haml/helpers.rb', line 305

def haml_concat(text = "")
  haml_buffer.buffer << haml_indent << text.to_s << "\n"
  nil
end

#haml_indentObject

Returns the string that should be used to indent the current line



311
312
313
# File 'lib/haml/helpers.rb', line 311

def haml_indent
  '  ' * haml_buffer.tabulation
end

#haml_tag(name, *rest, &block) ⇒ Object

call-seq:

haml_tag(name, *flags, attributes = {}) {...}
haml_tag(name, text, *flags, attributes = {}) {...}

Creates an HTML tag with the given name and optionally text and attributes. Can take a block that will be executed between when the opening and closing tags are output. If the block is a Haml block or outputs text using haml_concat, the text will be properly indented.

flags is a list of symbol flags like those that can be put at the end of a Haml tag (:/, :<, and :>). Currently, only :/ and :< are supported.

For example,

haml_tag :table do
  haml_tag :tr do
    haml_tag :td, {:class => 'cell'} do
      haml_tag :strong, "strong!"
      haml_concat "data"
    end
    haml_tag :td do
      haml_concat "more_data"
    end
  end
end

outputs

<table>
  <tr>
    <td class='cell'>
      <strong>
        strong!
      </strong>
      data
    </td>
    <td>
      more_data
    </td>
  </tr>
</table>


361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/haml/helpers.rb', line 361

def haml_tag(name, *rest, &block)
  ret = ErrorReturn.new(<<MESSAGE)
haml_tag outputs directly to the Haml template.
Disregard its return value and use the - operator.
MESSAGE

  name = name.to_s
  text = rest.shift.to_s unless [Symbol, Hash, NilClass].any? {|t| rest.first.is_a? t}
  flags = []
  flags << rest.shift while rest.first.is_a? Symbol
  attributes = Haml::Precompiler.build_attributes(haml_buffer.html?,
                                                  haml_buffer.options[:attr_wrapper],
                                                  rest.shift || {})

  if text.nil? && block.nil? && (haml_buffer.options[:autoclose].include?(name) || flags.include?(:/))
    haml_concat "<#{name}#{attributes} />"
    return ret
  end

  if flags.include?(:/)
    raise Error.new("Self-closing tags can't have content.") if text
    raise Error.new("Illegal nesting: nesting within a self-closing tag is illegal.") if block
  end

  tag = "<#{name}#{attributes}>"
  if block.nil?
    tag << text.to_s << "</#{name}>"
    haml_concat tag
    return ret
  end

  if text
    raise Error.new("Illegal nesting: content can't be both given to haml_tag :#{name} and nested within it.")
  end

  if flags.include?(:<)
    tag << capture_haml(&block).strip << "</#{name}>"
    haml_concat tag
    return ret
  end

  haml_concat tag
  tab_up
  block.call
  tab_down
  haml_concat "</#{name}>"

  ret
end

#html_attrs(lang = 'en-US') ⇒ Object

Returns a hash containing default assignments for the xmlns and xml:lang attributes of the html HTML element. It also takes an optional argument for the value of xml:lang and lang, which defaults to ‘en-US’. For example,

%html{html_attrs}

becomes

<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en-US' lang='en-US'>


171
172
173
# File 'lib/haml/helpers.rb', line 171

def html_attrs(lang = 'en-US')
  {:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
end

#html_escape(text) ⇒ Object

Returns a copy of text with ampersands, angle brackets and quotes escaped into HTML entities.



416
417
418
# File 'lib/haml/helpers.rb', line 416

def html_escape(text)
  text.to_s.gsub(/[\"><&]/) { |s| HTML_ESCAPE[s] }
end

#init_haml_helpersObject

Note: this does not need to be called when using Haml helpers normally in Rails.

Initializes the current object as though it were in the same context as a normal ActionView rendering using Haml. This is useful if you want to use the helpers in a context other than the normal setup with ActionView. For example:

context = Object.new
class << context
  include Haml::Helpers
end
context.init_haml_helpers
context.haml_tag :p, "Stuff"


56
57
58
59
# File 'lib/haml/helpers.rb', line 56

def init_haml_helpers
  @haml_buffer = Haml::Buffer.new(@haml_buffer, Haml::Engine.new('').send(:options_for_buffer))
  nil
end

#is_haml?Boolean

Returns whether or not the current template is a Haml template.

This function, unlike other Haml::Helpers functions, also works in other ActionView templates, where it will always return false.

Returns:

  • (Boolean)


431
432
433
# File 'lib/haml/helpers.rb', line 431

def is_haml?
  !@haml_buffer.nil? && @haml_buffer.active?
end

#list_of(array, &block) ⇒ Object

Takes an Enumerable object and a block and iterates over the object, yielding each element to a Haml block and putting the result into <li> elements. This creates a list of the results of the block. For example:

= list_of([['hello'], ['yall']]) do |i|
  = i[0]

Produces:

<li>hello</li>
<li>yall</li>

And

= list_of({:title => 'All the stuff', :description => 'A book about all the stuff.'}) do |key, val|
  %h3= key.humanize
  %p= val

Produces:

<li>
  <h3>Title</h3>
  <p>All the stuff</p>
</li>
<li>
  <h3>Description</h3>
  <p>A book about all the stuff.</p>
</li>


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/haml/helpers.rb', line 143

def list_of(array, &block) # :yields: item
  to_return = array.collect do |i|
    result = capture_haml(i, &block)

    if result.count("\n") > 1
      result.gsub!("\n", "\n  ")
      result = "\n  #{result.strip}\n"
    else
      result.strip!
    end

    "<li>#{result}</li>"
  end
  to_return.join("\n")
end

#non_hamlObject

call-seq:

non_haml { ... }

Runs a block of code in a non-Haml context (i.e. #is_haml? will return false).

This is mainly useful for rendering sub-templates such as partials in a non-Haml language, particularly where helpers may behave differently when run from Haml.

Note that this is automatically applied to Rails partials.



71
72
73
74
75
76
77
# File 'lib/haml/helpers.rb', line 71

def non_haml
  was_active = @haml_buffer.active?
  @haml_buffer.active = false
  yield
ensure
  @haml_buffer.active = was_active
end

#precede(char, &block) ⇒ Object

Prepends the given character to the beginning of the Haml block, with no whitespace between. For example:

= precede '*' do
  %span.small Not really

Produces:

*<span class='small'>Not really</span>


241
242
243
# File 'lib/haml/helpers.rb', line 241

def precede(char, &block)
  "#{char}#{capture_haml(&block).chomp}\n"
end

#preserve(input = '', &block) ⇒ Object Also known as: flatten

call-seq:

preserve(input)
preserve {...}

Takes any string, finds all the endlines and converts them to HTML entities for endlines so they’ll render correctly in whitespace-sensitive tags without screwing up the indentation.



103
104
105
106
107
# File 'lib/haml/helpers.rb', line 103

def preserve(input = '', &block)
  return preserve(capture_haml(&block)) if block

  input.chomp("\n").gsub(/\n/, '&#x000A;').gsub(/\r/, '')
end

#puts(*args) ⇒ Object

:nodoc:



295
296
297
298
299
300
301
302
# File 'lib/haml/helpers.rb', line 295

def puts(*args) # :nodoc:
  warn <<END
DEPRECATION WARNING:
The Haml #puts helper is deprecated and will be removed in version 2.4.
Use the #haml_concat helper instead.
END
  haml_concat(*args)
end

#succeed(char, &block) ⇒ Object

Appends the given character to the end of the Haml block, with no whitespace between. For example:

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

Produces:

click
<a href='thing'>here</a>.


258
259
260
# File 'lib/haml/helpers.rb', line 258

def succeed(char, &block)
  "#{capture_haml(&block).chomp}#{char}\n"
end

#surround(front, back = nil, &block) ⇒ Object

Surrounds the given block of Haml code with the given characters, with no whitespace in between. For example:

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

Produces:

(<a href='food'>chicken</a>)

and

= surround '*' do
  %strong angry

Produces:

*<strong>angry</strong>*


223
224
225
226
227
228
# File 'lib/haml/helpers.rb', line 223

def surround(front, back = nil, &block)
  back ||= front
  output = capture_haml(&block)

  "#{front}#{output.chomp}#{back}\n"
end

#tab_down(i = 1) ⇒ Object

Decrements the number of tabs the buffer automatically adds to the lines of the template.

See also tab_up.



199
200
201
# File 'lib/haml/helpers.rb', line 199

def tab_down(i = 1)
  haml_buffer.tabulation -= i
end

#tab_up(i = 1) ⇒ Object

Increments the number of tabs the buffer automatically adds to the lines of the template. For example:

%h1 foo
- tab_up
%p bar
- tab_down
%strong baz

Produces:

<h1>foo</h1>
  <p>bar</p>
<strong>baz</strong>


191
192
193
# File 'lib/haml/helpers.rb', line 191

def tab_up(i = 1)
  haml_buffer.tabulation += i
end