class WWW_App module HTML SELF_CLOSING_TAGS = [:br, :input, :link, :meta, :hr, :img] NO_NEW_LINES = [:p, :code, :span].freeze TAGS = %w[ title body div span img b em i strong u a abbr blockquote cite br cite code ul ol li p pre q sup sub form input button link script ].map(&:to_sym) TAGS_TO_ATTRIBUTES = { :all => [:id, :class], :a => [:href, :rel], :form => [:action, :method, :accept_charset], :input => [:type, :name, :value], :style => [:type], :script => [:type, :src, :language], :link => [:rel, :type, :sizes, :href, :title], :meta => [:name, :http_equiv, :property, :content, :charset], :img => [:src], # :width, :height will be used by CSS only. :html => [:lang] } ATTRIBUTES_TO_TAGS = TAGS_TO_ATTRIBUTES.inject({}) { |memo, (tag, attrs)| attrs.each { |a| memo[a] ||= [] memo[a] << tag } memo } ATTRIBUTES = ATTRIBUTES_TO_TAGS.keys ATTRIBUTES_TO_TAGS.each { |name, tags| eval <<-EOF, nil, __FILE__, __LINE__ + 1 def #{name} val alter_attribute :#{name}, val block_given? ? close { yield } : self end EOF } TAGS.each { |name| eval <<-EOF, nil, __FILE__, __LINE__ + 1 def #{name} str = :none create(:#{name}, str) block_given? ? close { yield } : self end EOF } def alter_attribute name, val allowed = @tag && ATTRIBUTES_TO_TAGS[name] && ATTRIBUTES_TO_TAGS[name].include?(@tag[:tag_name]) fail "#{name.inspect} not allowed to be set here." unless allowed @tag[name] = val block_given? ? close { yield } : self end def meta *args fail "No block allowed." if block_given? fail "Not allowed here." if parent create(:meta, *args) end def title str = :none fail ":title not allowed here" if parent if !block_given? && str != :none create { text str } else create :title do yield end end end def id new_id if !@tag fail "No HTML tag found. Try using _.id(#{new_id.inspect})" end if !ancestor?(:group) old_id = @tag[:id] if old_id && old_id != new_id fail("Id already set: #{old_id} new: #{new_id}") end if @html_ids[new_id] fail(HTML_ID_Duplicate, "Id already used: #{new_id.inspect}, tag index: #{@html_ids[new_id]}") end @html_ids[ new_id ] = new_id end @tag[:id] = new_id if block_given? close { yield } else self end end # === def id def is_fragment? !is_doc? end def is_doc? @is_doc ||= begin found = false tags = @tags.dup while !found && !tags.empty? t = tags.shift found = begin (t[:tag_name] == :body && (t[:id] || t[:css]) ) || t[:tag_name] == :style || t[:tag_name] == :script || t[:tag_name] == :meta || t[:css] || (t[:tag_name] == :title && t[:parent] && t[:parent][:tag_name] == :body) end if !found && t[:children] tags = t[:children].concat(tags) end end found end end # === def is_doc? def lang name fail "Tag has to be placed tomost of the page." if parent fail "Block not allowed here." if block_given? create :html_tag_attr do @tag[:lang] = name.to_s.downcase.gsub(/[^a-z0-9\_\-]+/, ''.freeze) @tag[:lang] = 'en' if @tag[:lang].empty? end self end # # Example: # div.^(:alert, :red_hot) { 'my content' } # def ^ *names @tag[:class] ||= [] @tag[:class].concat(names) if block_given? close { yield } else self end end def render_if name fail ::ArgumentError, "Not a symbol: #{name.inspect}" unless name.is_a?(Symbol) raw_text %^{{#coll.#{name}}}^ yield raw_text %^{{/coll.#{name}}}^ nil end def render_unless name fail ::ArgumentError, "Not a symbol: #{name.inspect}" unless name.is_a?(Symbol) raw_text %!{{^coll.#{name}}}! yield raw_text %!{{/coll.#{name}}}! nil end def input *args case when args.size === 3 create(:input, :type=>args[0].to_s, :name=>args[1].to_s, :value=>args[2], :closed=>true) go_up else super end end def script src = nil if src.is_a?(String) && src['.js'.freeze] return create(:script, :src=>src) { } end attrs = { :type => src || "text/mustache" } create :script, attrs close { yield } if block_given? self end end # === module HTML end # === class WWW_App