2006-09-12 00:14:21 -04:00
module Haml
2009-04-30 20:07:18 -04:00
# This module contains various helpful methods to make it easier to do various tasks.
# {Haml::Helpers} is automatically included in the context
2006-11-21 00:54:26 -05:00
# that a Haml template is parsed in, so all these methods are at your
2006-10-14 19:50:07 -04:00
# disposal from within the template.
2006-09-12 00:14:21 -04:00
module Helpers
2009-04-30 20:07:18 -04:00
# An object that raises an error when \{#to\_s} is called.
2009-04-15 15:44:11 -04:00
# It's used to raise an error when the return value of a helper is used
# when it shouldn't be.
class ErrorReturn
2009-07-19 18:42:06 -04:00
def initialize ( method )
@message = <<MESSAGE
#{method} outputs directly to the Haml template.
Disregard its return value and use the - operator ,
or use capture_haml to get the value as a String .
MESSAGE
2009-04-15 15:44:11 -04:00
end
2009-04-30 20:07:18 -04:00
# Raises an error.
#
# @raise [Haml::Error] The error
2009-04-15 15:44:11 -04:00
def to_s
raise Haml :: Error . new ( @message )
2009-07-19 18:42:06 -04:00
rescue Haml :: Error = > e
e . backtrace . shift
# If the ErrorReturn is used directly in the template,
# we don't want Haml's stuff to get into the backtrace,
# so we get rid of the format_script line.
#
# We also have to subtract one from the Haml line number
# since the value is passed to format_script the line after
# it's actually used.
if e . backtrace . first =~ / ^ \ (eval \ ): \ d+:in `format_script /
e . backtrace . shift
e . backtrace . first . gsub! ( / ^ \ (haml \ ):( \ d+) / ) { | s | " (haml): #{ $1 . to_i - 1 } " }
end
raise e
2009-04-15 15:44:11 -04:00
end
2009-04-30 20:07:18 -04:00
# @return [String] A human-readable string representation
2009-04-15 15:44:11 -04:00
def inspect
" Haml::Helpers::ErrorReturn( #{ @message . inspect } ) "
end
end
2006-11-05 22:01:04 -05:00
self . extend self
2007-03-31 19:21:16 -04:00
2010-04-22 00:05:32 -04:00
@@action_view_defined = false
2006-11-14 13:35:02 -05:00
2009-04-30 20:07:18 -04:00
# @return [Boolean] Whether or not ActionView is loaded
2006-11-14 13:35:02 -05:00
def self . action_view?
2007-03-31 19:21:16 -04:00
@@action_view_defined
2006-11-14 13:35:02 -05:00
end
2006-11-05 22:01:04 -05:00
2009-04-30 20:07:18 -04:00
# Note: this does **not** need to be called when using Haml helpers
# normally in Rails.
2007-07-14 05:00:55 -04:00
#
2009-04-30 20:07:18 -04:00
# Initializes the current object as though it were in the same context
# as a normal ActionView instance using Haml.
2007-07-14 05:00:55 -04:00
# This is useful if you want to use the helpers in a context
# other than the normal setup with ActionView.
# For example:
#
2009-04-30 20:07:18 -04:00
# context = Object.new
# class << context
# include Haml::Helpers
# end
# context.init_haml_helpers
# context.haml_tag :p, "Stuff"
2008-04-08 02:09:17 -04:00
#
2007-07-14 05:00:55 -04:00
def init_haml_helpers
2012-06-04 11:37:23 -04:00
@haml_buffer = Haml :: Buffer . new ( haml_buffer , Options . new . for_buffer )
2007-07-14 05:00:55 -04:00
nil
end
2008-04-24 13:23:01 -04:00
# Runs a block of code in a non-Haml context
2009-04-30 20:07:18 -04:00
# (i.e. \{#is\_haml?} will return false).
2008-04-24 13:23:01 -04:00
#
# 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.
2009-04-30 20:07:18 -04:00
#
# @yield A block which won't register as Haml
2008-04-24 13:23:01 -04:00
def non_haml
2008-04-24 15:03:54 -04:00
was_active = @haml_buffer . active?
@haml_buffer . active = false
2008-11-23 04:57:24 -05:00
yield
ensure
2008-04-24 15:03:54 -04:00
@haml_buffer . active = was_active
2008-04-24 13:23:01 -04:00
end
2009-04-30 20:07:18 -04:00
# Uses \{#preserve} to convert any newlines inside whitespace-sensitive tags
2008-05-13 14:14:46 -04:00
# into the HTML entities for endlines.
2009-04-30 20:07:18 -04:00
#
# @param tags [Array<String>] Tags that should have newlines escaped
2009-05-13 23:29:49 -04:00
#
# @overload find_and_preserve(input, tags = haml_buffer.options[:preserve])
# Escapes newlines within a string.
#
# @param input [String] The string within which to escape newlines
# @overload find_and_preserve(tags = haml_buffer.options[:preserve])
# Escapes newlines within a block of Haml code.
#
# @yield The block within which to escape newlines
2009-04-30 17:31:15 -04:00
def find_and_preserve ( input = nil , tags = haml_buffer . options [ :preserve ] , & block )
return find_and_preserve ( capture_haml ( & block ) , input || tags ) if block
2014-10-05 05:26:13 -04:00
tags = tags . each_with_object ( '' ) do | t , s |
s << '|' unless s . empty?
s << Regexp . escape ( t )
end
re = / <( #{ tags } )([^>]*)>(.*?)(< \/ \ 1>) /im
2011-06-07 22:23:43 -04:00
input . to_s . gsub ( re ) do | s |
s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
2007-09-05 15:38:09 -04:00
" < #{ $1 } #{ $2 } > #{ preserve ( $3 ) } </ #{ $1 } > "
2007-02-06 03:08:32 -05:00
end
end
2009-04-30 20:07:18 -04:00
# Takes any string, finds all the newlines, and converts them to
# HTML entities so they'll render correctly in
2006-11-21 00:54:26 -05:00
# whitespace-sensitive tags without screwing up the indentation.
2009-04-30 20:07:18 -04:00
#
2013-05-24 05:16:09 -04:00
# @overload preserve(input)
2009-05-13 23:29:49 -04:00
# Escapes newlines within a string.
#
# @param input [String] The string within which to escape all newlines
2013-05-24 05:16:09 -04:00
# @overload preserve
2009-05-13 23:29:49 -04:00
# Escapes newlines within a block of Haml code.
#
# @yield The block within which to escape newlines
2009-10-16 00:10:50 -04:00
def preserve ( input = nil , & block )
2008-01-04 20:19:04 -05:00
return preserve ( capture_haml ( & block ) ) if block
2013-02-06 17:13:54 -05:00
s = input . to_s . chomp ( " \n " )
s . gsub! ( / \ n / , '
' )
s . delete! ( " \r " )
s
2006-09-12 00:14:21 -04:00
end
2007-02-06 03:08:32 -05:00
alias_method :flatten , :preserve
2009-04-30 20:07:18 -04:00
# Takes an `Enumerable` object and a block
# and iterates over the enum,
2006-11-27 20:44:40 -05:00
# yielding each element to a Haml block
2009-04-30 20:07:18 -04:00
# and putting the result into `<li>` elements.
2006-11-27 20:44:40 -05:00
# This creates a list of the results of the block.
# For example:
2006-09-19 10:13:49 -04:00
#
2009-04-30 20:07:18 -04:00
# = list_of([['hello'], ['yall']]) do |i|
# = i[0]
2006-09-19 10:13:49 -04:00
#
2006-11-27 20:44:40 -05:00
# Produces:
2006-11-21 00:54:26 -05:00
#
2009-04-30 20:07:18 -04:00
# <li>hello</li>
# <li>yall</li>
2006-09-19 10:13:49 -04:00
#
2012-04-09 19:45:14 -04:00
# And:
2006-11-27 20:44:40 -05:00
#
2009-04-30 20:07:18 -04:00
# = list_of({:title => 'All the stuff', :description => 'A book about all the stuff.'}) do |key, val|
# %h3= key.humanize
# %p= val
2006-11-27 20:44:40 -05:00
#
# Produces:
#
2009-04-30 20:07:18 -04:00
# <li>
# <h3>Title</h3>
# <p>All the stuff</p>
# </li>
# <li>
# <h3>Description</h3>
# <p>A book about all the stuff.</p>
# </li>
#
2012-04-09 19:45:14 -04:00
# While:
#
# = list_of(["Home", "About", "Contact", "FAQ"], {class: "nav", role: "nav"}) do |item|
# %a{ href="#" }= item
#
# Produces:
#
# <li class='nav' role='nav'>
# <a href='#'>Home</a>
# </li>
# <li class='nav' role='nav'>
# <a href='#'>About</a>
# </li>
# <li class='nav' role='nav'>
# <a href='#'>Contact</a>
# </li>
# <li class='nav' role='nav'>
# <a href='#'>FAQ</a>
# </li>
#
# `[[class", "nav"], [role", "nav"]]` could have been used instead of `{class: "nav", role: "nav"}` (or any enumerable collection where each pair of items responds to #to_s)
#
2009-04-30 20:07:18 -04:00
# @param enum [Enumerable] The list of objects to iterate over
2012-04-09 19:45:14 -04:00
# @param [Enumerable<#to_s,#to_s>] opts Each key/value pair will become an attribute pair for each list item element.
2009-04-30 20:07:18 -04:00
# @yield [item] A block which contains Haml code that goes within list items
# @yieldparam item An element of `enum`
2012-04-09 19:45:14 -04:00
def list_of ( enum , opts = { } , & block )
2014-10-05 05:26:13 -04:00
opts_attributes = opts . each_with_object ( '' ) { | ( k , v ) , s | s << " #{ k } =' #{ v } ' " }
enum . each_with_object ( '' ) do | i , ret |
2007-05-15 11:51:50 -04:00
result = capture_haml ( i , & block )
2008-04-08 02:09:17 -04:00
2014-10-05 05:26:13 -04:00
if result . count ( " \n " ) > 1
2013-02-06 17:13:54 -05:00
result . gsub! ( " \n " , " \n " )
2014-10-05 05:26:13 -04:00
result = " \n #{ result . strip! } \n "
2006-11-27 20:44:40 -05:00
else
2014-10-05 05:26:13 -04:00
result . strip!
2006-11-27 20:44:40 -05:00
end
2008-04-08 02:09:17 -04:00
2014-10-05 05:26:13 -04:00
ret << " \n " unless ret . empty?
ret << %Q!<li#{opts_attributes}>#{result}</li>!
end
2006-09-19 10:13:49 -04:00
end
2006-11-07 22:27:37 -05:00
2009-04-30 20:07:18 -04:00
# Returns a hash containing default assignments for the `xmlns`, `lang`, and `xml:lang`
# attributes of the `html` HTML element.
2007-03-17 07:03:36 -04:00
# For example,
#
2009-04-30 20:07:18 -04:00
# %html{html_attrs}
2007-03-17 07:03:36 -04:00
#
# becomes
#
2009-04-30 20:07:18 -04:00
# <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en-US' lang='en-US'>
2007-03-17 07:03:36 -04:00
#
2009-04-30 20:07:18 -04:00
# @param lang [String] The value of `xml:lang` and `lang`
2009-12-01 21:25:49 -05:00
# @return [{#to_s => String}] The attribute hash
2007-03-17 07:03:36 -04:00
def html_attrs ( lang = 'en-US' )
2013-08-03 17:01:50 -04:00
if haml_buffer . options [ :format ] == :xhtml
{ :xmlns = > " http://www.w3.org/1999/xhtml " , 'xml:lang' = > lang , :lang = > lang }
else
{ :lang = > lang }
end
2007-03-17 07:03:36 -04:00
end
2006-11-21 00:54:26 -05:00
# Increments the number of tabs the buffer automatically adds
# to the lines of the template.
# For example:
#
2009-04-30 20:07:18 -04:00
# %h1 foo
# - tab_up
# %p bar
# - tab_down
# %strong baz
2006-11-21 00:54:26 -05:00
#
# Produces:
#
2009-04-30 20:07:18 -04:00
# <h1>foo</h1>
# <p>bar</p>
# <strong>baz</strong>
2006-11-21 00:54:26 -05:00
#
2009-04-30 20:07:18 -04:00
# @param i [Fixnum] The number of tabs by which to increase the indentation
# @see #tab_down
2006-11-07 22:27:37 -05:00
def tab_up ( i = 1 )
2008-02-22 21:40:26 -05:00
haml_buffer . tabulation += i
2006-11-07 22:27:37 -05:00
end
2008-03-05 19:18:31 -05:00
# Decrements the number of tabs the buffer automatically adds
2006-11-21 00:54:26 -05:00
# to the lines of the template.
#
2009-04-30 20:07:18 -04:00
# @param i [Fixnum] The number of tabs by which to decrease the indentation
# @see #tab_up
2006-11-07 22:27:37 -05:00
def tab_down ( i = 1 )
2008-02-22 21:40:26 -05:00
haml_buffer . tabulation -= i
2006-11-07 22:27:37 -05:00
end
2008-04-08 02:09:17 -04:00
2010-03-13 00:31:32 -05:00
# Sets the number of tabs the buffer automatically adds
# to the lines of the template,
# but only for the duration of the block.
# For example:
#
# %h1 foo
# - with_tabs(2) do
# %p bar
# %strong baz
#
# Produces:
#
# <h1>foo</h1>
# <p>bar</p>
# <strong>baz</strong>
#
#
# @param i [Fixnum] The number of tabs to use
2010-03-14 20:31:35 -04:00
# @yield A block in which the indentation will be `i` spaces
2010-03-13 00:31:32 -05:00
def with_tabs ( i )
old_tabs = haml_buffer . tabulation
haml_buffer . tabulation = i
yield
ensure
haml_buffer . tabulation = old_tabs
end
2009-04-30 20:07:18 -04:00
# Surrounds a block of Haml code with strings,
2006-11-20 02:03:31 -05:00
# with no whitespace in between.
2006-11-21 00:54:26 -05:00
# For example:
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# = surround '(', ')' do
# %a{:href => "food"} chicken
2006-11-20 02:03:31 -05:00
#
2006-11-21 00:54:26 -05:00
# Produces:
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# (<a href='food'>chicken</a>)
2006-11-20 02:03:31 -05:00
#
# and
#
2009-04-30 20:07:18 -04:00
# = surround '*' do
# %strong angry
2006-11-20 02:03:31 -05:00
#
2006-11-21 00:54:26 -05:00
# Produces:
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# *<strong>angry</strong>*
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# @param front [String] The string to add before the Haml
# @param back [String] The string to add after the Haml
# @yield A block of Haml to surround
def surround ( front , back = front , & block )
2006-11-20 02:03:31 -05:00
output = capture_haml ( & block )
2008-04-08 02:09:17 -04:00
2006-11-20 02:03:31 -05:00
" #{ front } #{ output . chomp } #{ back } \n "
end
2008-04-08 02:09:17 -04:00
2009-04-30 20:07:18 -04:00
# Prepends a string to the beginning of a Haml block,
2006-11-20 02:03:31 -05:00
# with no whitespace between.
# For example:
#
2009-04-30 20:07:18 -04:00
# = precede '*' do
# %span.small Not really
2006-11-20 02:03:31 -05:00
#
2006-11-21 00:54:26 -05:00
# Produces:
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# *<span class='small'>Not really</span>
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# @param str [String] The string to add before the Haml
# @yield A block of Haml to prepend to
def precede ( str , & block )
" #{ str } #{ capture_haml ( & block ) . chomp } \n "
2006-11-20 02:03:31 -05:00
end
2008-04-08 02:09:17 -04:00
2009-04-30 20:07:18 -04:00
# Appends a string to the end of a Haml block,
2006-11-20 02:03:31 -05:00
# with no whitespace between.
# For example:
#
2009-04-30 20:07:18 -04:00
# click
# = succeed '.' do
# %a{:href=>"thing"} here
2006-11-20 02:03:31 -05:00
#
2006-11-21 00:54:26 -05:00
# Produces:
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# click
# <a href='thing'>here</a>.
2006-11-20 02:03:31 -05:00
#
2009-04-30 20:07:18 -04:00
# @param str [String] The string to add after the Haml
# @yield A block of Haml to append to
def succeed ( str , & block )
" #{ capture_haml ( & block ) . chomp } #{ str } \n "
2006-11-20 02:03:31 -05:00
end
2008-04-08 02:09:17 -04:00
2009-04-30 20:07:18 -04:00
# Captures the result of a block of Haml code,
2006-11-20 01:46:44 -05:00
# gets rid of the excess indentation,
# and returns it as a string.
# For example, after the following,
2006-11-20 01:11:16 -05:00
#
2009-04-30 20:07:18 -04:00
# .foo
# - foo = capture_haml(13) do |a|
# %p= a
2006-11-20 01:11:16 -05:00
#
2009-04-30 20:07:18 -04:00
# the local variable `foo` would be assigned to `"<p>13</p>\n"`.
2006-11-21 00:54:26 -05:00
#
2009-04-30 20:07:18 -04:00
# @param args [Array] Arguments to pass into the block
# @yield [args] A block of Haml code that will be converted to a string
# @yieldparam args [Array] `args`
2006-11-20 01:11:16 -05:00
def capture_haml ( * args , & block )
2011-06-17 15:11:37 -04:00
buffer = eval ( 'if defined? _hamlout then _hamlout else nil end' , block . binding ) || haml_buffer
2008-09-24 05:07:13 -04:00
with_haml_buffer ( buffer ) do
position = haml_buffer . buffer . length
2009-06-03 16:18:04 -04:00
haml_buffer . capture_position = position
2013-11-06 15:51:07 -05:00
value = block . call ( * args )
2008-09-24 05:07:13 -04:00
2010-04-02 14:55:16 -04:00
captured = haml_buffer . buffer . slice! ( position .. - 1 )
2013-11-06 15:51:07 -05:00
if captured == '' and value != haml_buffer . buffer
2013-12-09 23:56:39 -05:00
captured = ( value . is_a? ( String ) ? value : nil )
2008-09-24 05:07:13 -04:00
end
2013-11-06 15:51:07 -05:00
return nil if captured . nil?
return ( haml_buffer . options [ :ugly ] ? captured : prettify ( captured ) )
2008-09-24 05:07:13 -04:00
end
2009-06-03 16:18:04 -04:00
ensure
haml_buffer . capture_position = nil
2006-11-21 01:29:39 -05:00
end
2007-03-15 22:28:03 -04:00
2009-04-30 20:07:18 -04:00
# Outputs text directly to the Haml buffer, with the proper indentation.
#
# @param text [#to_s] The text to output
2008-10-27 13:33:51 -04:00
def haml_concat ( text = " " )
2014-11-19 17:07:09 -05:00
haml_internal_concat text
ErrorReturn . new ( " haml_concat " )
end
# Internal method to write directly to the buffer with control of
2015-02-04 08:48:03 -05:00
# whether the first line should be indented, and if there should be a
2014-11-19 17:07:09 -05:00
# final newline.
#
# Lines added will have the proper indentation. This can be controlled
# for the first line.
#
# Used by #haml_concat and #haml_tag.
#
# @param text [#to_s] The text to output
# @param newline [Boolean] Whether to add a newline after the text
# @param indent [Boolean] Whether to add indentation to the first line
def haml_internal_concat ( text = " " , newline = true , indent = true )
2014-10-08 00:19:26 -04:00
if haml_buffer . options [ :ugly ] || haml_buffer . tabulation == 0
2014-11-19 17:07:09 -05:00
haml_buffer . buffer << " #{ text } #{ " \n " if newline } "
2013-12-08 23:35:07 -05:00
else
2014-11-19 17:07:09 -05:00
haml_buffer . buffer << %[ #{ haml_indent if indent } #{ text . to_s . gsub ( " \n " , " \n #{ haml_indent } " ) } #{ " \n " if newline } ]
2010-01-26 19:06:23 -05:00
end
2007-03-15 22:28:03 -04:00
end
2014-11-19 17:07:09 -05:00
private :haml_internal_concat
# Allows writing raw content. `haml_internal_concat_raw` isn't
# effected by XSS mods. Used by #haml_tag to write the actual tags.
alias :haml_internal_concat_raw :haml_internal_concat
2007-03-15 22:28:03 -04:00
2009-04-30 20:07:18 -04:00
# @return [String] The indentation string for the current line
2008-12-22 18:26:58 -05:00
def haml_indent
' ' * haml_buffer . tabulation
end
2007-03-15 23:02:33 -04:00
# Creates an HTML tag with the given name and optionally text and attributes.
2009-04-30 20:07:18 -04:00
# Can take a block that will run between the opening and closing tags.
# If the block is a Haml block or outputs text using \{#haml\_concat},
2007-03-15 23:02:33 -04:00
# the text will be properly indented.
2008-04-08 02:09:17 -04:00
#
2009-12-10 07:17:35 -05:00
# `name` can be a string using the standard Haml class/id shorthand
# (e.g. "span#foo.bar", "#foo").
# Just like standard Haml tags, these class and id values
# will be merged with manually-specified attributes.
#
2009-04-30 20:07:18 -04:00
# `flags` is a list of symbol flags
2008-06-05 21:32:17 -04:00
# like those that can be put at the end of a Haml tag
2009-04-30 20:07:18 -04:00
# (`:/`, `:<`, and `:>`).
# Currently, only `:/` and `:<` are supported.
2008-06-05 21:32:17 -04:00
#
2009-06-07 04:41:30 -04:00
# `haml_tag` outputs directly to the buffer;
# its return value should not be used.
# If you need to get the results as a string,
# use \{#capture\_haml\}.
#
2007-03-15 23:02:33 -04:00
# For example,
#
2009-04-30 20:07:18 -04:00
# haml_tag :table do
# haml_tag :tr do
2009-12-10 07:17:35 -05:00
# haml_tag 'td.cell' do
2009-04-30 20:07:18 -04:00
# haml_tag :strong, "strong!"
# haml_concat "data"
# end
# haml_tag :td do
# haml_concat "more_data"
# end
2007-03-15 22:28:03 -04:00
# end
# end
#
2007-03-15 23:02:33 -04:00
# outputs
#
2009-04-30 20:07:18 -04:00
# <table>
# <tr>
# <td class='cell'>
# <strong>
# strong!
# </strong>
# data
# </td>
# <td>
# more_data
# </td>
# </tr>
# </table>
#
# @param name [#to_s] The name of the tag
2009-05-13 23:29:49 -04:00
#
2012-05-23 11:14:46 -04:00
# @overload haml_tag(name, *rest, attributes = {})
2009-05-13 23:29:49 -04:00
# @yield The block of Haml code within the tag
# @overload haml_tag(name, text, *flags, attributes = {})
# @param text [#to_s] The text within the tag
2012-05-23 11:14:46 -04:00
# @param flags [Array<Symbol>] Haml end-of-tag flags
2008-06-05 21:32:17 -04:00
def haml_tag ( name , * rest , & block )
2009-07-19 18:42:06 -04:00
ret = ErrorReturn . new ( " haml_tag " )
2009-04-15 15:44:11 -04:00
2008-07-03 23:10:53 -04:00
text = rest . shift . to_s unless [ Symbol , Hash , NilClass ] . any? { | t | rest . first . is_a? t }
2008-06-05 21:32:17 -04:00
flags = [ ]
flags << rest . shift while rest . first . is_a? Symbol
2012-05-29 16:09:25 -04:00
attrs = ( rest . shift || { } )
attrs . keys . each { | key | attrs [ key . to_s ] = attrs . delete ( key ) } unless attrs . empty?
2010-08-22 17:27:26 -04:00
name , attrs = merge_name_and_attributes ( name . to_s , attrs )
2009-12-10 07:17:35 -05:00
2010-07-07 02:59:13 -04:00
attributes = Haml :: Compiler . build_attributes ( haml_buffer . html? ,
2010-10-27 02:24:45 -04:00
haml_buffer . options [ :attr_wrapper ] ,
haml_buffer . options [ :escape_attrs ] ,
2012-01-28 03:10:05 -05:00
haml_buffer . options [ :hyphenate_data_attrs ] ,
2010-10-27 02:24:45 -04:00
attrs )
2008-04-11 12:44:15 -04:00
2008-06-05 21:32:17 -04:00
if text . nil? && block . nil? && ( haml_buffer . options [ :autoclose ] . include? ( name ) || flags . include? ( :/ ) )
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw " < #{ name } #{ attributes } #{ ' /' if haml_buffer . options [ :format ] == :xhtml } > "
2009-04-15 15:44:11 -04:00
return ret
2007-07-08 17:39:11 -04:00
end
2008-06-05 21:32:17 -04:00
if flags . include? ( :/ )
2012-06-25 10:48:56 -04:00
raise Error . new ( Error . message ( :self_closing_content ) ) if text
2012-06-18 17:51:31 -04:00
raise Error . new ( Error . message ( :illegal_nesting_self_closing ) ) if block
2008-06-05 21:32:17 -04:00
end
2008-06-05 21:16:27 -04:00
tag = " < #{ name } #{ attributes } > "
2014-11-19 17:07:09 -05:00
end_tag = " </ #{ name } > "
2008-06-05 21:16:27 -04:00
if block . nil?
2010-01-26 19:06:23 -05:00
text = text . to_s
if text . include? ( " \n " )
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw tag
2010-01-26 19:06:23 -05:00
tab_up
2014-11-19 17:07:09 -05:00
haml_internal_concat text
2010-01-26 19:06:23 -05:00
tab_down
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw end_tag
2010-01-26 19:06:23 -05:00
else
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw tag , false
haml_internal_concat text , false , false
haml_internal_concat_raw end_tag , true , false
2010-01-26 19:06:23 -05:00
end
2009-04-15 15:44:11 -04:00
return ret
2008-06-05 21:16:27 -04:00
end
if text
2012-06-18 17:51:31 -04:00
raise Error . new ( Error . message ( :illegal_nesting_line , name ) )
2007-07-08 17:39:11 -04:00
end
2008-06-05 21:16:27 -04:00
2008-06-05 21:32:17 -04:00
if flags . include? ( :< )
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw tag , false
haml_internal_concat " #{ capture_haml ( & block ) . strip } " , false , false
haml_internal_concat_raw end_tag , true , false
2009-04-15 15:44:11 -04:00
return ret
2008-06-05 21:32:17 -04:00
end
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw tag
2008-06-05 21:16:27 -04:00
tab_up
block . call
tab_down
2014-11-19 17:07:09 -05:00
haml_internal_concat_raw end_tag
2009-04-15 15:44:11 -04:00
ret
2007-03-15 22:28:03 -04:00
end
2008-02-22 21:33:49 -05:00
2013-03-07 19:24:06 -05:00
# Conditionally wrap a block in an element. If `condition` is `true` then
2014-02-18 18:39:47 -05:00
# this method renders the tag described by the arguments in `tag` (using
2013-03-07 19:24:06 -05:00
# \{#haml_tag}) with the given block inside, otherwise it just renders the block.
#
# For example,
#
# - haml_tag_if important, '.important' do
# %p
# A (possibly) important paragraph.
#
# will produce
#
# <div class='important'>
# <p>
# A (possibly) important paragraph.
# </p>
# </div>
#
# if `important` is truthy, and just
#
# <p>
# A (possibly) important paragraph.
# </p>
#
# otherwise.
#
# Like \{#haml_tag}, `haml_tag_if` outputs directly to the buffer and its
# return value should not be used. Use \{#capture_haml} if you need to use
# its results as a string.
#
# @param condition The condition to test to determine whether to render
# the enclosing tag
# @param tag Definition of the enclosing tag. See \{#haml_tag} for details
# (specifically the form that takes a block)
def haml_tag_if ( condition , * tag )
if condition
haml_tag ( * tag ) { yield }
else
yield
end
ErrorReturn . new ( " haml_tag_if " )
end
2008-03-18 15:40:04 -04:00
# Characters that need to be escaped to HTML entities from user input
2013-02-15 20:34:13 -05:00
HTML_ESCAPE = { '&' = > '&' , '<' = > '<' , '>' = > '>' , '"' = > '"' , " ' " = > ''' }
2008-03-18 15:40:04 -04:00
2013-02-12 14:44:29 -05:00
HTML_ESCAPE_REGEX = / [ \ "><&] /
2013-05-23 00:43:04 -04:00
# Returns a copy of `text` with ampersands, angle brackets and quotes
# escaped into HTML entities.
#
# Note that if ActionView is loaded and XSS protection is enabled
# (as is the default for Rails 3.0+, and optional for version 2.3.5+),
# this won't escape text declared as "safe".
#
# @param text [String] The string to sanitize
# @return [String] The sanitized string
def html_escape ( text )
text = text . to_s
text . gsub ( HTML_ESCAPE_REGEX , HTML_ESCAPE )
2008-03-18 15:40:04 -04:00
end
2008-04-08 02:09:17 -04:00
2013-02-14 16:58:33 -05:00
HTML_ESCAPE_ONCE_REGEX = / [ \ "><]|&(?!(?:[a-zA-Z]+| # (?: \ d+|[xX][0-9a-fA-F]+));) /
2013-02-12 14:44:29 -05:00
2013-05-23 00:43:04 -04:00
# Escapes HTML entities in `text`, but without escaping an ampersand
# that is already part of an escaped entity.
#
# @param text [String] The string to sanitize
# @return [String] The sanitized string
def escape_once ( text )
text = text . to_s
text . gsub ( HTML_ESCAPE_ONCE_REGEX , HTML_ESCAPE )
2008-03-14 19:39:19 -04:00
end
2008-04-24 13:23:26 -04:00
# Returns whether or not the current template is a Haml template.
#
2009-04-30 20:07:18 -04:00
# This function, unlike other {Haml::Helpers} functions,
# also works in other `ActionView` templates,
2008-04-24 13:23:26 -04:00
# where it will always return false.
2009-04-30 20:07:18 -04:00
#
# @return [Boolean] Whether or not the current template is a Haml template
2008-04-24 13:23:26 -04:00
def is_haml?
2008-04-24 15:03:54 -04:00
! @haml_buffer . nil? && @haml_buffer . active?
2008-04-24 13:23:26 -04:00
end
2009-04-30 20:07:18 -04:00
# Returns whether or not `block` is defined directly in a Haml template.
#
# @param block [Proc] A Ruby block
# @return [Boolean] Whether or not `block` is defined directly in a Haml template
2008-11-22 23:53:19 -05:00
def block_is_haml? ( block )
2011-06-17 15:11:37 -04:00
eval ( '!!defined?(_hamlout)' , block . binding )
2008-11-22 23:53:19 -05:00
end
2006-11-21 01:29:39 -05:00
private
2009-12-10 07:17:35 -05:00
# Parses the tag name used for \{#haml\_tag}
# and merges it with the Ruby attributes hash.
def merge_name_and_attributes ( name , attributes_hash = { } )
# skip merging if no ids or classes found in name
return name , attributes_hash unless name =~ / ^(.+?)?([ \ . # ].*)$ /
return $1 || " div " , Buffer . merge_attrs (
2010-10-27 02:24:45 -04:00
Haml :: Parser . parse_class_and_id ( $2 ) , attributes_hash )
2009-12-10 07:17:35 -05:00
end
2009-04-30 20:07:18 -04:00
# Runs a block of code with the given buffer as the currently active buffer.
2008-09-24 05:07:13 -04:00
#
2009-04-30 20:07:18 -04:00
# @param buffer [Haml::Buffer] The Haml buffer to use temporarily
# @yield A block in which the given buffer should be used
2008-09-24 05:07:13 -04:00
def with_haml_buffer ( buffer )
@haml_buffer , old_buffer = buffer , @haml_buffer
2010-02-15 20:45:26 -05:00
old_buffer . active , old_was_active = false , old_buffer . active? if old_buffer
@haml_buffer . active , was_active = true , @haml_buffer . active?
2008-09-24 05:07:13 -04:00
yield
ensure
2010-02-15 20:45:26 -05:00
@haml_buffer . active = was_active
old_buffer . active = old_was_active if old_buffer
2008-09-24 05:07:13 -04:00
@haml_buffer = old_buffer
end
2009-04-30 20:07:18 -04:00
# The current {Haml::Buffer} object.
#
# @return [Haml::Buffer]
2008-02-22 21:40:26 -05:00
def haml_buffer
2012-05-15 18:40:07 -04:00
@haml_buffer if defined? @haml_buffer
2006-11-21 01:29:39 -05:00
end
2008-04-08 02:09:17 -04:00
2009-04-30 20:07:18 -04:00
# Gives a proc the same local `_hamlout` and `_erbout` variables
2006-11-21 01:29:39 -05:00
# that the current template has.
2009-04-30 20:07:18 -04:00
#
# @param proc [#call] The proc to bind
# @return [Proc] A new proc with the new variables bound
2008-02-22 21:40:26 -05:00
def haml_bind_proc ( & proc )
_hamlout = haml_buffer
2012-08-21 20:54:27 -04:00
#double assignment is to avoid warnings
_erbout = _erbout = _hamlout . buffer
2006-11-21 01:29:39 -05:00
proc { | * args | proc . call ( * args ) }
end
2013-11-06 15:51:07 -05:00
def prettify ( text )
text = text . split ( / ^ / )
text . delete ( '' )
min_tabs = nil
text . each do | line |
tabs = line . index ( / [^ ] / ) || line . length
min_tabs || = tabs
min_tabs = min_tabs > tabs ? tabs : min_tabs
end
2014-10-05 05:26:13 -04:00
text . each_with_object ( '' ) do | line , str |
str << line . slice ( min_tabs , line . length )
end
2013-11-06 15:51:07 -05:00
end
2006-08-08 17:38:50 -04:00
end
2006-07-31 10:28:44 -04:00
end
2008-04-29 23:06:35 -04:00
2010-04-20 05:20:01 -04:00
# @private
2008-04-29 23:06:35 -04:00
class Object
2009-04-30 20:07:18 -04:00
# Haml overrides various `ActionView` helpers,
# which call an \{#is\_haml?} method
2008-04-29 23:06:35 -04:00
# to determine whether or not the current context object
# is a proper Haml context.
2009-04-30 20:07:18 -04:00
# Because `ActionView` helpers may be included in non-`ActionView::Base` classes,
# it's a good idea to define \{#is\_haml?} for all objects.
2008-04-29 23:06:35 -04:00
def is_haml?
false
end
end