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

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)


16
17
18
# File 'lib/haml/helpers.rb', line 16

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)


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

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



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/haml/helpers.rb', line 256

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.



399
400
401
# File 'lib/haml/helpers.rb', line 399

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

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

call-seq:

find_and_preserve(input, tags = haml_buffer.options[:preserve])
find_and_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.



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

def find_and_preserve(input = '', tags = haml_buffer.options[:preserve], &block)
  return find_and_preserve(capture_haml(&block)) 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



288
289
290
291
# File 'lib/haml/helpers.rb', line 288

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



294
295
296
# File 'lib/haml/helpers.rb', line 294

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>


344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
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
# File 'lib/haml/helpers.rb', line 344

def haml_tag(name, *rest, &block)
  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 nil
  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
  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
  end

  haml_concat tag
  tab_up
  block.call
  tab_down
  haml_concat "</#{name}>"
  nil
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'>


154
155
156
# File 'lib/haml/helpers.rb', line 154

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.



393
394
395
# File 'lib/haml/helpers.rb', line 393

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"


39
40
41
42
# File 'lib/haml/helpers.rb', line 39

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)


408
409
410
# File 'lib/haml/helpers.rb', line 408

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>


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/haml/helpers.rb', line 126

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.



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

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>


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

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.



86
87
88
89
90
# File 'lib/haml/helpers.rb', line 86

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

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

#puts(*args) ⇒ Object

:nodoc:



278
279
280
281
282
283
284
285
# File 'lib/haml/helpers.rb', line 278

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


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

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>*


206
207
208
209
210
211
# File 'lib/haml/helpers.rb', line 206

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.



182
183
184
# File 'lib/haml/helpers.rb', line 182

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>


174
175
176
# File 'lib/haml/helpers.rb', line 174

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