dir = File.dirname(__FILE__) $LOAD_PATH << dir unless $LOAD_PATH.include?(dir) # = Haml (XHTML Abstraction Markup Language) # # Haml is a markup language # that's used to cleanly and simply describe the XHTML of any web document, # without the use of inline code. # Haml functions as a replacement # for inline page templating systems such as PHP, ERB, and ASP. # However, Haml avoids the need for explicitly coding XHTML into the template, # because it is actually an abstract description of the XHTML, # with some code to generate dynamic content. # # == Features # # * Whitespace active # * Well-formatted markup # * DRY # * Follows CSS conventions # * Integrates Ruby code # * Implements Rails templates with the .haml extension # # == Using Haml # # Haml can be used in two ways: # as a plugin for Ruby on Rails, # and as a standalone Ruby module. # # Sass can be used in several ways: # As a template engine for Ruby on Rails or Merb, # or as a standalone engine. # The first step for all of these is to install the Haml gem: # # gem install haml # # To enable it as a Rails plugin, # then run # # haml --rails path/to/rails/app # # Haml is enabled in Merb by default, # so Merb users don't have to do anything more. # # Once it's installed, all view files with the ".haml" extension # (or ".html.haml" for Merb or edge Rails) # will be compiled using Haml. # # You can access instance variables in Haml templates # the same way you do in ERb templates. # Helper methods are also available in Haml templates. # For example (this example uses Rails, but the principle for Merb is the same): # # # file: app/controllers/movies_controller.rb # # class MoviesController < ApplicationController # def index # @title = "Teen Wolf" # end # end # # -# file: app/views/movies/index.haml # # #content # .title # %h1= @title # = link_to 'Home', home_url # # may be compiled to: # #
#
#

Teen Wolf

# Home #
#
# # === Ruby Module # # Haml can also be used completely separately from Rails and ActionView. # To do this, install the gem with RubyGems: # # gem install haml # # You can then use it by including the "haml" gem in Ruby code, # and using Haml::Engine like so: # # engine = Haml::Engine.new("%p Haml code!") # engine.render #=> "

Haml code!

\n" # # == Characters with meaning to Haml # # Various characters, when placed at a certain point in a line, # instruct Haml to render different types of things. # # === XHTML Tags # # These characters render XHTML tags. # # ==== % # # # The percent character is placed at the beginning of a line. # It's followed immediately by the name of an element, # then optionally by modifiers (see below), a space, # and text to be rendered inside the element. # It creates an element in the form of . # For example: # # %one # %two # %three Hey there # # is compiled to: # # # # Hey there # # # # Any string is a valid element name; # Haml will automatically generate opening and closing tags for any element. # # ==== {} # # Brackets represent a Ruby hash # that is used for specifying the attributes of an element. # It is literally evaluated as a Ruby hash, # so logic will work in it and local variables may be used. # Quote characters within the attribute # will be replaced by appropriate escape sequences. # The hash is placed after the tag is defined. # For example: # # %head{ :name => "doc_head" } # %script{ 'type' => "text/" + "javascript", # :src => "javascripts/script_#{2 + 7}" } # # is compiled to: # # # # # # ===== Attribute Methods # # A Ruby method call that returns a hash # can be substituted for the hash contents. # For example, Haml::Helpers defines the following method: # # def html_attrs(lang = 'en-US') # {:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang} # end # # This can then be used in Haml, like so: # # %html{html_attrs('fr-fr')} # # This is compiled to: # # # # # You can use as many such attribute methods as you want # by separating them with commas, # like a Ruby argument list. # All the hashes will me merged together, from left to right. # For example, if you defined # # def hash1 # {:bread => 'white', :filling => 'peanut butter and jelly'} # end # # def hash2 # {:bread => 'whole wheat'} # end # # then # # %sandwich{hash1, hash2, :delicious => true}/ # # would compile to: # # # # ===== Boolean Attributes # # Some attributes, such as "checked" for input tags or "selected" for option tags, # are "boolean" in the sense that their values don't matter - # it only matters whether or not they're present. # In HTML (but not XHTML), these attributes can be written as # # # # To do this in Haml, just assign a Ruby true value to the attribute: # # %input{:selected => true} # # In XHTML, the only valid value for these attributes is the name of the attribute. # Thus this will render in XHTML as # # # # To set these attributes to false, simply assign them to a Ruby false value. # In both XHTML and HTML # # %input{:selected => false} # # will just render as # # # # ==== [] # # Square brackets follow a tag definition and contain a Ruby object # that is used to set the class and id of that tag. # The class is set to the object's class # (transformed to use underlines rather than camel case) # and the id is set to the object's class, followed by its id. # Because the id of an object is normally an obscure implementation detail, # this is most useful for elements that represent instances of Models. # Additionally, the second argument (if present) will be used as a prefix for # both the id and class attributes. # For example: # # # file: app/controllers/users_controller.rb # # def show # @user = CrazyUser.find(15) # end # # -# file: app/views/users/show.haml # # %div[@user, :greeting] # %bar[290]/ # Hello! # # is compiled to: # #
# # Hello! #
# # ==== / # # The forward slash character, when placed at the end of a tag definition, # causes the tag to be self-closed. # For example: # # %br/ # %meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/ # # is compiled to: # #
# # # Some tags are automatically closed, as long as they have no content. # +meta+, +img+, +link+, +script+, +br+, and +hr+ tags are closed by default. # This list can be customized by setting the :autoclose option (see below). # For example: # # %br # %meta{'http-equiv' => 'Content-Type', :content => 'text/html'} # # is also compiled to: # #
# # # ==== . and # # # The period and pound sign are borrowed from CSS. # They are used as shortcuts to specify the class # and id attributes of an element, respectively. # Multiple class names can be specified in a similar way to CSS, # by chaining the class names together with periods. # They are placed immediately after the tag and before an attributes hash. # For example: # # %div#things # %span#rice Chicken Fried # %p.beans{ :food => 'true' } The magical fruit # %h1.class.otherclass#id La La La # # is compiled to: # #
# Chicken Fried #

The magical fruit

#

La La La

#
# # And, # # #content # .articles # .article.title # Doogie Howser Comes Out # .article.date # 2006-11-05 # .article.entry # Neil Patrick Harris would like to dispel any rumors that he is straight # # is compiled to: # #
#
#
Doogie Howser Comes Out
#
2006-11-05
#
# Neil Patrick Harris would like to dispel any rumors that he is straight #
#
#
# # ==== Implicit Div Elements # # Because the div element is used so often, it is the default element. # If you only define a class and/or id using the . or # syntax, # a div element is automatically used. # For example: # # #collection # .item # .description What a cool item! # # is the same as: # # %div{:id => collection} # %div{:class => 'item'} # %div{:class => 'description'} What a cool item! # # and is compiled to: # #
#
#
What a cool item!
#
#
# # ==== > 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 =. # For example: # # %blockquote< # %div # Foo! # # is compiled to: # #
# Foo! #
# # And: # # %img # %img> # %img # # is compiled to: # # # # And: # # %p<= "Foo\nBar" # # is compiled to: # #

Foo # Bar

# # And finally: # # %img # %pre>< # foo # bar # %img # # is compiled to: # #
foo
#   bar
# # ==== = # # = is placed at the end of a tag definition, # after class, id, and attribute declarations. # It's just a shortcut for inserting Ruby code into an element. # It works the same as = without a tag: # it inserts the result of the Ruby code into the template. # However, if the result is short enough, # it is displayed entirely on one line. # For example: # # %p= "hello" # # is not quite the same as: # # %p # = "hello" # # It's compiled to: # #

hello

# # ==== ~ # # ~ works just like =, except that it runs Haml::Helpers#find_and_preserve on its input. # For example, # # ~ "Foo\n
Bar\nBaz
" # # is the same as: # # = find_and_preserve("Foo\n
Bar\nBaz
") # # and is compiled to: # # Foo #
Bar
Baz
# # See also Whitespace Preservation, below. # # === XHTML Helpers # # ==== No Special Character # # If no special character appears at the beginning of a line, # the line is rendered as plain text. # For example: # # %gee # %whiz # Wow this is cool! # # is compiled to: # # # # Wow this is cool! # # # # ==== !!! # # When describing XHTML documents with Haml, # you can have a document type or XML prolog generated automatically # by including the characters !!!. # For example: # # !!! XML # !!! # %html # %head # %title Myspace # %body # %h1 I am the international space station # %p Sign my guestbook # # is compiled to: # # # # # # Myspace # # #

I am the international space station

#

Sign my guestbook

# # # # You can also specify the version and type of XHTML after the !!!. # XHTML 1.0 Strict, Transitional, and Frameset and XHTML 1.1 are supported. # The default version is 1.0 and the default type is Transitional. # For example: # # !!! 1.1 # # is compiled to: # # # # and # # !!! Strict # # is compiled to: # # # # If you're not using the UTF-8 character set for your document, # you can specify which encoding should appear # in the XML prolog in a similar way. # For example: # # !!! XML iso-8859-1 # # is compiled to: # # # # ==== / # # The forward slash character, when placed at the beginning of a line, # wraps all text after it in an HTML comment. # For example: # # %peanutbutterjelly # / This is the peanutbutterjelly element # I like sandwiches! # # is compiled to: # # # # I like sandwiches! # # # The forward slash can also wrap indented sections of code. For example: # # / # %p This doesn't render... # %div # %h1 Because it's commented out! # # is compiled to: # # # # You can also use Internet Explorer conditional comments # (about)[http://www.quirksmode.org/css/condcom.html] # by enclosing the condition in square brackets after the /. # For example: # # /[if IE] # %a{ :href => 'http://www.mozilla.com/en-US/firefox/' } # %h1 Get Firefox # # is compiled to: # # # # ==== \ # # The backslash character escapes the first character of a line, # allowing use of otherwise interpreted characters as plain text. # For example: # # %title # = @title # \- MySite # # is compiled to: # # # MyPage # - MySite # # # ==== | # # The pipe character designates a multiline string. # It's placed at the end of a line # and means that all following lines that end with | # will be evaluated as though they were on the same line. # For example: # # %whoo # %hoo I think this might get | # pretty long so I should | # probably make it | # multiline so it doesn't | # look awful. | # %p This is short. # # is compiled to: # # # # I think this might get pretty long so I should probably make it multiline so it doesn't look awful. # # # # ==== : # # The colon character designates a filter. # This allows you to pass an indented block of text as input # to another filtering program and add the result to the output of Haml. # The syntax is simply a colon followed by the name of the filter. # For example, # # %p # :markdown # Textile # ======= # # Hello, *World* # # is compiled to # #

#

Textile

# #

Hello, World

#

# # Filters can have Ruby code interpolated, like with ==. # For example, # # - flavor = "raspberry" # #content # :textile # I *really* prefer _#{h flavor}_ jam. # # is compiled to # #
#

I really prefer raspberry jam.

#
# # Haml has the following filters defined: # # [plain] Does not parse the filtered text. # This is useful for large blocks of text without HTML tags, # when you don't want lines starting with . or - # to be parsed. # # [javascript] Surrounds the filtered text with ' # # would be compiled to # # <script>alert("I'm evil!");</script> # # ==== - # # The hyphen character makes the text following it into "silent script": # Ruby script that is evaluated, but not output. # # It is not recommended that you use this widely; # almost all processing code and logic should be restricted # to the Controller, the Helper, or partials. # # For example: # # - foo = "hello" # - foo << " there" # - foo << " you!" # %p= foo # # is compiled to: # #

# hello there you! #

# # ==== == # # Two equals characters interpolates Ruby code into plain text, # similarly to Ruby string interpolation. # For example, # # %p== This is #{h quality} cake! # # is the same as # # %p= "This is #{h quality} cake!" # # and might compile to # #

This is scrumptious cake!

# # Backslashes can be used to escape "#{" strings, # but they don't act as escapes anywhere else in the string. # For example: # # %p # == \\ Look at \\#{h word} lack of backslash: \#{foo} # # might compile to # #

# \\ Look at \yon lack of backslash: #{foo} #

# # ==== &= # # An ampersand followed by one or two equals characters # evaluates Ruby code just like the equals without the ampersand, # but sanitizes any HTML-sensitive characters in the result of the code. # For example: # # &= "I like cheese & crackers" # # compiles to # # I like cheese & crackers # # If the :escape_html option is set, # &= behaves identically to =. # # ==== != # # An exclamation mark followed by one or two equals characters # evaluates Ruby code just like the equals would, # but never sanitizes the HTML. # # By default, the single equals doesn't sanitize HTML either. # However, if the :escape_html option is set, = will sanitize the HTML, but != still won't. # For example, if :escape_html is set: # # = "I feel !" # != "I feel !" # # compiles to # # I feel <strong>! # I feel ! # # ===== Blocks # # Ruby blocks, like XHTML tags, don't need to be explicitly closed in Haml. # Rather, they're automatically closed, based on indentation. # A block begins whenever the indentation is increased # after a silent script command. # It ends when the indentation decreases # (as long as it's not an +else+ clause or something similar). # For example: # # - (42...47).each do |i| # %p= i # %p See, I can count! # # is compiled to: # #

# 42 #

#

# 43 #

#

# 44 #

#

# 45 #

#

# 46 #

# # Another example: # # %p # - case 2 # - when 1 # = "1!" # - when 2 # = "2?" # - when 3 # = "3." # # is compiled to: # #

# 2? #

# # ==== -# # # The hyphen followed immediately by the pound sign # signifies a silent comment. # Any text following this isn't rendered in the resulting document # at all. # # For example: # # %p foo # -# This is a comment # %p bar # # is compiled to: # #

foo

#

bar

# # You can also nest text beneath a silent comment. # None of this text will be rendered. # For example: # # %p foo # -# # This won't be displayed # Nor will this # %p bar # # is compiled to: # #

foo

#

bar

# # == Other Useful Things # # === Whitespace Preservation # # Sometimes you don't want Haml to indent all your text. # For example, tags like +pre+ and +textarea+ are whitespace-sensitive; # indenting the text makes them render wrong. # # Haml deals with this by "preserving" newlines before they're put into the document -- # converting them to the XHTML whitespace escape code, . # Then Haml won't try to re-format the indentation. # # Literal +textarea+ and +pre+ tags automatically preserve their content. # Dynamically can't be caught automatically, # and so should be passed through Haml::Helpers#find_and_preserve or the ~ command, # which has the same effect (see above). # # Blocks of literal text can be preserved using the :preserve filter (see above). # # === Helpers # # Haml offers a bunch of helpers that are useful # for doing stuff like preserving whitespace, # creating nicely indented output for user-defined helpers, # and other useful things. # The helpers are all documented in the Haml::Helpers and Haml::Helpers::ActionViewExtensions modules. # # === Haml Options # # Options can be set by setting the hash Haml::Template.options # from environment.rb in Rails, # or by passing an options hash to Haml::Engine. # Available options are: # # [:output] Determines the output format. The default is :xhtml. # Other options are :html4 and :html5, which are # identical to :xhtml except there are no self-closing tags, # XML prolog is ignored and correct DOCTYPEs are generated. # # [:escape_html] Sets whether or not to escape HTML-sensitive characters in script. # If this is true, = behaves like &=; # otherwise, it behaves like !=. # Note that this escapes tag attributes. # Defaults to false. # # [:suppress_eval] Whether or not attribute hashes and Ruby scripts # designated by = or ~ should be # evaluated. If this is true, said scripts are # rendered as empty strings. Defaults to false. # # [:attr_wrapper] The character that should wrap element attributes. # This defaults to ' (an apostrophe). Characters # of this type within the attributes will be escaped # (e.g. by replacing them with ') if # the character is an apostrophe or a quotation mark. # # [:filename] The name of the Haml file being parsed. # This is only used as information when exceptions are raised. # This is automatically assigned when working through ActionView, # so it's really only useful for the user to assign # when dealing with Haml programatically. # # [:line] The line offset of the Haml template being parsed. # This is useful for inline templates, # similar to the last argument to Kernel#eval. # # [:filters] A hash of filters that can be applied to Haml code. # The keys are the string names of the filters; # the values are references to the classes of the filters. # User-defined filters should always have lowercase keys, # and should have the interface described in Haml::Filters::Base. # # [:autoclose] A list of tag names that should be automatically self-closed # if they have no content. # Defaults to ['meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base']. # # [:preserve] A list of tag names that should automatically have their newlines preserved # using the Haml::Helpers#preserve helper. # This means that any content given on the same line as the tag will be preserved. # For example: # # %textarea= "Foo\nBar" # # compiles to: # # # # Defaults to ['textarea', 'pre']. # # See also Whitespace Preservation, above. # module Haml # Returns a hash representing the version of Haml. # The :major, :minor, and :teeny keys have their respective numbers. # The :string key contains a human-readable string representation of the version. # If Haml is checked out from Git, # the :rev key will have the revision hash. def self.version return @@version if defined?(@@version) numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i } @@version = { :major => numbers[0], :minor => numbers[1], :teeny => numbers[2] } @@version[:string] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.') if File.exists?(scope('REVISION')) rev = File.read(scope('REVISION')).strip rev = nil if rev !~ /a-f0-9+/ end if rev.nil? && File.exists?(scope('.git/HEAD')) rev = File.read(scope('.git/HEAD')).strip if rev =~ /^ref: (.*)$/ rev = File.read(scope(".git/#{$1}")).strip end end if rev @@version[:rev] = rev @@version[:string] << "." << rev[0...7] end @@version end # Returns the path of file relative to the Haml root. def self.scope(file) # :nodoc: File.join(File.dirname(__FILE__), '..', file) end # A string representing the version of Haml. # A more fine-grained representation is generated by Haml.version. VERSION = version[:string] unless defined?(Haml::VERSION) # This method is called by init.rb, # which is run by Rails on startup. # We use it rather than putting stuff straight into init.rb # so we can change the initialization behavior # without modifying the file itself. def self.init_rails(binding) %w[haml/template sass sass/plugin].each(&method(:require)) end end require 'haml/engine'