require 'hanami/helpers/html_helper/html_builder' module Hanami module Helpers # HTML builder # # By including Hanami::Helpers::HtmlHelper it will inject one private method: html. # This is a HTML5 markup builder. # # Features: # * Support for complex markup without the need of concatenation # * Auto closing HTML5 tags # * Custom tags # * Content tag auto escape (XSS protection) # * Support for view local variables # # Usage: # # * It knows how to close tags according to HTML5 spec (1) # * It accepts content as first argument (2) # * It accepts another builder as first argument (3) # * It accepts content as block which returns a string (4) # * It accepts content as a block with nested markup builders (5) # * It builds attributes from given hash (6) # * It combines attributes and block (7) # # @since 0.1.0 # # @see Hanami::Helpers::HtmlHelper#html # # @example Usage # # 1 # html.div # =>
# html.img # => # # # 2 # html.div('hello') # =>
hello
# # # 3 # html.div(html.p('hello')) # =>

hello

# # # 4 # html.div { 'hello' } # # => # #
# # hello # #
# # # 5 # html.div do # p 'hello' # end # # => # #
# #

hello

# #
# # # 6 # html.div('hello', id: 'el', 'data-x': 'y') # =>
hello
# # # 7 # html.div(id: 'yay') { 'hello' } # # => # #
# # hello # #
# # # 8 # html do # li 'Hello' # li 'Hanami' # end # # => # #
  • Hello
  • # #
  • Hanami
  • # # # # @example Complex markup # # # # NOTICE THE LACK OF CONCATENATION BETWEEN div AND input BLOCKS <3 # # # # html.form(action: '/users', method: 'POST') do # div do # label 'First name', for: 'user-first-name' # input type: 'text', id: 'user-first-name', name: 'user[first_name]', value: 'L' # end # # input type: 'submit', value: 'Save changes' # end # # => # #
    # #
    # # # # # #
    # # # #
    # # # # @example Custom tags # html.tag(:custom, 'Foo', id: 'next') # => Foo # html.empty_tag(:xr, id: 'next') # => # # # # @example Auto escape # html.div('hello') # =>
    hello # html.div { 'hello' } # =>
    hello # html.div(html.p('hello')) # =>

    hello

    # html.div do # p 'hello' # end # =>

    hello

    # # # # html.div("") # # => "
    <script>alert('xss')</script>
    " # # html.div { "" } # # => "
    <script>alert('xss')</script>
    " # # html.div(html.p("")) # # => "

    <script>alert('xss')</script>

    " # # html.div do # p "" # end # # => "

    <script>alert('xss')</script>

    " # # # @example Basic usage # # # # THE VIEW CAN BE A SIMPLE RUBY OBJECT # # # # require 'hanami/helpers' # # class MyView # include Hanami::Helpers::HtmlHelper # # # Generates # # # def sidebar # html.aside(id: 'sidebar') do # div 'hello' # end # end # end # # # @example View context # # # # LOCAL VARIABLES FROM VIEWS ARE AVAILABLE INSIDE THE NESTED BLOCKS OF HTML BUILDER # # # # require 'hanami/view' # require 'hanami/helpers' # # Book = Struct.new(:title) # # module Books # class Show # include Hanami::View # include Hanami::Helpers::HtmlHelper # # def title_widget # html.div do # h1 book.title # end # end # end # end # # book = Book.new('The Work of Art in the Age of Mechanical Reproduction') # rendered = Books::Show.render(format: :html, book: book) # # rendered # # =>
    # #

    The Work of Art in the Age of Mechanical Reproduction

    # #
    module HtmlHelper private # Instantiate an HTML builder # # @param blk [Proc,Hanami::Helpers::HtmlHelper::HtmlBuilder,NilClass] the optional content block # # @return [Hanami::Helpers::HtmlHelper::HtmlBuilder] the HTML builder # # @since 0.1.0 # # @see Hanami::Helpers::HtmlHelper # @see Hanami::Helpers::HtmlHelper::HtmlBuilder def html(&blk) if block_given? HtmlBuilder.new.fragment(&blk) else HtmlBuilder.new end end end end end