hamlit-2.11.0/0000755000175000017500000000000013574632775012436 5ustar josephjosephhamlit-2.11.0/.gitignore0000644000175000017500000000022213574632775014422 0ustar josephjoseph/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ .sass-cache .ruby-version *.bundle *.so *.su *.o *.a *.swp hamlit-2.11.0/lib/0000755000175000017500000000000013574632775013204 5ustar josephjosephhamlit-2.11.0/lib/hamlit/0000755000175000017500000000000013574632775014462 5ustar josephjosephhamlit-2.11.0/lib/hamlit/ruby_expression.rb0000644000175000017500000000114413574632775020247 0ustar josephjoseph# frozen_string_literal: true require 'ripper' module Hamlit class RubyExpression < Ripper class ParseError < StandardError; end def self.syntax_error?(code) self.new(code).parse false rescue ParseError true end def self.string_literal?(code) return false if syntax_error?(code) type, instructions = Ripper.sexp(code) return false if type != :program return false if instructions.size > 1 type, _ = instructions.first type == :string_literal end private def on_parse_error(*) raise ParseError end end end hamlit-2.11.0/lib/hamlit/utils.rb0000644000175000017500000000101413574632775016143 0ustar josephjoseph# frozen_string_literal: true module Hamlit module Utils # Java extension is not implemented for JRuby yet. # TruffleRuby does not implement `rb_ary_sort_bang`, etc. if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby' require 'cgi/escape' def self.escape_html(html) CGI.escapeHTML(html.to_s) end else require 'hamlit/hamlit' # Hamlit::Utils.escape_html end def self.escape_html_safe(html) html.html_safe? ? html : escape_html(html) end end end hamlit-2.11.0/lib/hamlit/string_splitter.rb0000644000175000017500000000072413574632775020246 0ustar josephjosephrequire 'ripper' require 'hamlit/ruby_expression' module Hamlit module StringSplitter # `code` param must be valid string literal def self.compile(code) unless Ripper.respond_to?(:lex) # truffleruby doesn't have Ripper.lex return [[:dynamic, code]] end begin Temple::Filters::StringSplitter.compile(code) rescue Temple::FilterError => e raise Hamlit::InternalError.new(e.message) end end end end hamlit-2.11.0/lib/hamlit/compiler/0000755000175000017500000000000013574632775016274 5ustar josephjosephhamlit-2.11.0/lib/hamlit/compiler/silent_script_compiler.rb0000644000175000017500000000077313574632775023404 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Compiler class SilentScriptCompiler def compile(node, &block) if node.children.empty? [:multi, [:code, node.value[:text]], [:newline]] else compile_with_children(node, &block) end end private def compile_with_children(node, &block) [:multi, [:block, node.value[:text], [:multi, [:newline], yield(node)], ], ] end end end end hamlit-2.11.0/lib/hamlit/compiler/children_compiler.rb0000644000175000017500000000541513574632775022310 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Compiler class ChildrenCompiler def initialize @lineno = 1 end def compile(node, &block) temple = [:multi] return temple if node.children.empty? temple << :whitespace if prepend_whitespace?(node) node.children.each do |n| rstrip_whitespace!(temple) if nuke_prev_whitespace?(n) insert_newlines!(temple, n) temple << yield(n) temple << :whitespace if insert_whitespace?(n) end rstrip_whitespace!(temple) if nuke_inner_whitespace?(node) confirm_whitespace(temple) end private def insert_newlines!(temple, node) (node.line - @lineno).times do temple << [:newline] end @lineno = node.line case node.type when :script, :silent_script @lineno += 1 when :filter @lineno += (node.value[:text] || '').split("\n").size when :tag node.value[:attributes_hashes].each do |attribute_hash| @lineno += attribute_hash.count("\n") end @lineno += 1 if node.children.empty? && node.value[:parse] end end def confirm_whitespace(temple) temple.map do |exp| case exp when :whitespace [:static, "\n"] else exp end end end def prepend_whitespace?(node) return false unless %i[comment tag].include?(node.type) !nuke_inner_whitespace?(node) end def nuke_inner_whitespace?(node) case when node.type == :tag node.value[:nuke_inner_whitespace] when node.parent.nil? false else nuke_inner_whitespace?(node.parent) end end def nuke_prev_whitespace?(node) case node.type when :tag node.value[:nuke_outer_whitespace] when :silent_script !node.children.empty? && nuke_prev_whitespace?(node.children.first) else false end end def nuke_outer_whitespace?(node) return false if node.type != :tag node.value[:nuke_outer_whitespace] end def rstrip_whitespace!(temple) if temple[-1] == :whitespace temple.delete_at(-1) end end def insert_whitespace?(node) return false if nuke_outer_whitespace?(node) case node.type when :doctype node.value[:type] != 'xml' when :comment, :plain, :tag true when :script node.children.empty? && !nuke_inner_whitespace?(node) when :filter !%w[ruby].include?(node.value[:name]) else false end end end end end hamlit-2.11.0/lib/hamlit/compiler/doctype_compiler.rb0000644000175000017500000000170113574632775022161 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Compiler class DoctypeCompiler def initialize(options = {}) @format = options[:format] end def compile(node) case node.value[:type] when 'xml' xml_doctype when '' html_doctype(node) else [:html, :doctype, node.value[:type]] end end private def html_doctype(node) version = node.value[:version] || :transitional case @format when :xhtml [:html, :doctype, version] when :html4 [:html, :doctype, :transitional] when :html5 [:html, :doctype, :html] else [:html, :doctype, @format] end end def xml_doctype case @format when :xhtml [:static, "\n"] else [:multi] end end end end end hamlit-2.11.0/lib/hamlit/compiler/script_compiler.rb0000644000175000017500000000604613574632775022025 0ustar josephjoseph# frozen_string_literal: true require 'temple/static_analyzer' require 'hamlit/ruby_expression' require 'hamlit/string_splitter' module Hamlit class Compiler class ScriptCompiler def initialize(identity) @identity = identity end def compile(node, &block) unless Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby return dynamic_compile(node, &block) end no_children = node.children.empty? case when no_children && node.value[:escape_interpolation] compile_interpolated_plain(node) when no_children && RubyExpression.string_literal?(node.value[:text]) delegate_optimization(node) when no_children && Temple::StaticAnalyzer.static?(node.value[:text]) static_compile(node) else dynamic_compile(node, &block) end end private # String-interpolated plain text must be compiled with this method # because we have to escape only interpolated values. def compile_interpolated_plain(node) temple = [:multi] StringSplitter.compile(node.value[:text]).each do |type, value| case type when :static temple << [:static, value] when :dynamic temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]] end end temple << [:newline] end # :dynamic is optimized in other filter: StringSplitter def delegate_optimization(node) [:multi, [:escape, node.value[:escape_html], [:dynamic, node.value[:text]]], [:newline], ] end def static_compile(node) str = eval(node.value[:text]).to_s if node.value[:escape_html] str = Hamlit::Utils.escape_html(str) elsif node.value[:preserve] str = ::Hamlit::HamlHelpers.find_and_preserve(str, %w(textarea pre code)) end [:multi, [:static, str], [:newline]] end def dynamic_compile(node, &block) var = @identity.generate temple = compile_script_assign(var, node, &block) temple << compile_script_result(var, node) end def compile_script_assign(var, node, &block) if node.children.empty? [:multi, [:code, "#{var} = (#{node.value[:text]}"], [:newline], [:code, ')'], ] else [:multi, [:block, "#{var} = #{node.value[:text]}", [:multi, [:newline], yield(node)], ], ] end end def compile_script_result(result, node) if !node.value[:escape_html] && node.value[:preserve] result = find_and_preserve(result) else result = "(#{result}).to_s" end [:escape, node.value[:escape_html], [:dynamic, result]] end def find_and_preserve(code) %Q[::Hamlit::HamlHelpers.find_and_preserve(#{code}, %w(textarea pre code))] end def escape_html(temple) [:escape, true, temple] end end end end hamlit-2.11.0/lib/hamlit/compiler/comment_compiler.rb0000644000175000017500000000166113574632775022161 0ustar josephjosephmodule Hamlit class Compiler class CommentCompiler def compile(node, &block) if node.value[:conditional] compile_conditional_comment(node, &block) else compile_html_comment(node, &block) end end private def compile_html_comment(node, &block) if node.children.empty? [:html, :comment, [:static, " #{node.value[:text]} "]] else [:html, :comment, yield(node)] end end def compile_conditional_comment(node, &block) condition = node.value[:conditional] if node.value[:conditional] =~ /\A\[(\[*[^\[\]]+\]*)\]/ condition = $1 end content = if node.children.empty? [:static, " #{node.value[:text]} "] else yield(node) end [:html, :condcomment, condition, content, node.value[:revealed]] end end end end hamlit-2.11.0/lib/hamlit/compiler/tag_compiler.rb0000644000175000017500000000454213574632775021273 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/parser/haml_util' require 'hamlit/attribute_compiler' require 'hamlit/string_splitter' module Hamlit class Compiler class TagCompiler def initialize(identity, options) @autoclose = options[:autoclose] @identity = identity @attribute_compiler = AttributeCompiler.new(identity, options) end def compile(node, &block) attrs = @attribute_compiler.compile(node) contents = compile_contents(node, &block) [:html, :tag, node.value[:name], attrs, contents] end private def compile_contents(node, &block) case when !node.children.empty? yield(node) when node.value[:value].nil? && self_closing?(node) nil when node.value[:parse] return compile_interpolated_plain(node) if node.value[:escape_interpolation] if Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby return delegate_optimization(node) if RubyExpression.string_literal?(node.value[:value]) return delegate_optimization(node) if Temple::StaticAnalyzer.static?(node.value[:value]) end var = @identity.generate [:multi, [:code, "#{var} = (#{node.value[:value]}"], [:newline], [:code, ')'], [:escape, node.value[:escape_html], [:dynamic, var]] ] else [:static, node.value[:value]] end end # :dynamic is optimized in other filters: StringSplitter or StaticAnalyzer def delegate_optimization(node) [:multi, [:escape, node.value[:escape_html], [:dynamic, node.value[:value]]], [:newline], ] end # We should handle interpolation here to escape only interpolated values. def compile_interpolated_plain(node) temple = [:multi] StringSplitter.compile(node.value[:value]).each do |type, value| case type when :static temple << [:static, value] when :dynamic temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]] end end temple << [:newline] end def self_closing?(node) return true if @autoclose && @autoclose.include?(node.value[:name]) node.value[:self_closing] end end end end hamlit-2.11.0/lib/hamlit/attribute_builder.rb0000644000175000017500000001214313574632775020521 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/object_ref' module Hamlit::AttributeBuilder BOOLEAN_ATTRIBUTES = %w[disabled readonly multiple checked autobuffer autoplay controls loop selected hidden scoped async defer reversed ismap seamless muted required autofocus novalidate formnovalidate open pubdate itemscope allowfullscreen default inert sortable truespeed typemustmatch download].freeze # Java extension is not implemented for JRuby yet. # TruffleRuby does not implement `rb_ary_sort_bang`, etc. if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby' class << self def build(escape_attrs, quote, format, object_ref, *hashes) hashes << Hamlit::ObjectRef.parse(object_ref) if object_ref buf = [] hash = merge_all_attrs(hashes) keys = hash.keys.sort! keys.each do |key| case key when 'id'.freeze buf << " id=#{quote}#{build_id(escape_attrs, *hash[key])}#{quote}" when 'class'.freeze buf << " class=#{quote}#{build_class(escape_attrs, *hash[key])}#{quote}" when 'data'.freeze buf << build_data(escape_attrs, quote, *hash[key]) when *BOOLEAN_ATTRIBUTES, /\Adata-/ build_boolean!(escape_attrs, quote, format, buf, key, hash[key]) else buf << " #{key}=#{quote}#{escape_html(escape_attrs, hash[key].to_s)}#{quote}" end end buf.join end def build_id(escape_attrs, *values) escape_html(escape_attrs, values.flatten.select { |v| v }.join('_')) end def build_class(escape_attrs, *values) if values.size == 1 value = values.first case when value.is_a?(String) # noop when value.is_a?(Array) value = value.flatten.select { |v| v }.map(&:to_s).sort.uniq.join(' ') when value value = value.to_s else return '' end return escape_html(escape_attrs, value) end classes = [] values.each do |value| case when value.is_a?(String) classes += value.split(' ') when value.is_a?(Array) classes += value.select { |v| v } when value classes << value.to_s end end escape_html(escape_attrs, classes.map(&:to_s).sort.uniq.join(' ')) end def build_data(escape_attrs, quote, *hashes) build_data_attribute(:data, escape_attrs, quote, *hashes) end def build_aria(escape_attrs, quote, *hashes) build_data_attribute(:aria, escape_attrs, quote, *hashes) end private def build_data_attribute(key, escape_attrs, quote, *hashes) attrs = [] if hashes.size > 1 && hashes.all? { |h| h.is_a?(Hash) } data_value = merge_all_attrs(hashes) else data_value = hashes.last end hash = flatten_attributes(key => data_value) hash.sort_by(&:first).each do |key, value| case value when true attrs << " #{key}" when nil, false # noop else attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}" end end attrs.join end def flatten_attributes(attributes) flattened = {} attributes.each do |key, value| case value when attributes when Hash flatten_attributes(value).each do |k, v| if k.nil? flattened[key] = v else flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v end end else flattened[key] = value if value end end flattened end def merge_all_attrs(hashes) merged = {} hashes.each do |hash| hash.each do |key, value| key = key.to_s case key when 'id'.freeze, 'class'.freeze, 'data'.freeze merged[key] ||= [] merged[key] << value else merged[key] = value end end end merged end def build_boolean!(escape_attrs, quote, format, buf, key, value) case value when true case format when :xhtml buf << " #{key}=#{quote}#{key}#{quote}" else buf << " #{key}" end when false, nil # omitted else buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}" end end def escape_html(escape_attrs, str) if escape_attrs Hamlit::Utils.escape_html(str) else str end end end else # Hamlit::AttributeBuilder.build # Hamlit::AttributeBuilder.build_id # Hamlit::AttributeBuilder.build_class # Hamlit::AttributeBuilder.build_data # Hamlit::AttributeBuilder.build_aria require 'hamlit/hamlit' end end hamlit-2.11.0/lib/hamlit/attribute_compiler.rb0000644000175000017500000001036713574632775020713 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/attribute_builder' require 'hamlit/attribute_parser' require 'hamlit/ruby_expression' module Hamlit class AttributeCompiler def initialize(identity, options) @identity = identity @quote = options[:attr_quote] @format = options[:format] @escape_attrs = options[:escape_attrs] end def compile(node) hashes = [] if node.value[:object_ref] != :nil || !Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby return runtime_compile(node) end node.value[:attributes_hashes].each do |attribute_str| hash = AttributeParser.parse(attribute_str) return runtime_compile(node) unless hash hashes << hash end static_compile(node.value[:attributes], hashes) end private def runtime_compile(node) attrs = node.value[:attributes_hashes] attrs.unshift(node.value[:attributes].inspect) if node.value[:attributes] != {} args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect].push(node.value[:object_ref]) + attrs [:html, :attrs, [:dynamic, "::Hamlit::AttributeBuilder.build(#{args.join(', ')})"]] end def static_compile(static_hash, dynamic_hashes) temple = [:html, :attrs] keys = [*static_hash.keys, *dynamic_hashes.map(&:keys).flatten].uniq.sort keys.each do |key| values = [[:static, static_hash[key]], *dynamic_hashes.map { |h| [:dynamic, h[key]] }] values.select! { |_, exp| exp != nil } case key when 'id' compile_id!(temple, key, values) when 'class' compile_class!(temple, key, values) when 'data', 'aria' compile_data!(temple, key, values) when *AttributeBuilder::BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/ compile_boolean!(temple, key, values) else compile_common!(temple, key, values) end end temple end def compile_id!(temple, key, values) build_code = attribute_builder(:id, values) if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } temple << [:html, :attr, key, [:static, eval(build_code).to_s]] else temple << [:html, :attr, key, [:dynamic, build_code]] end end def compile_class!(temple, key, values) build_code = attribute_builder(:class, values) if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } temple << [:html, :attr, key, [:static, eval(build_code).to_s]] else temple << [:html, :attr, key, [:dynamic, build_code]] end end def compile_data!(temple, key, values) args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", values.map { |v| literal_for(v) }] build_code = "::Hamlit::AttributeBuilder.build_#{key}(#{args.join(', ')})" if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } temple << [:static, eval(build_code).to_s] else temple << [:dynamic, build_code] end end def compile_boolean!(temple, key, values) exp = literal_for(values.last) if Temple::StaticAnalyzer.static?(exp) value = eval(exp) case value when true then temple << [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]] when false, nil else temple << [:html, :attr, key, [:fescape, @escape_attrs, [:static, value.to_s]]] end else var = @identity.generate temple << [ :case, "(#{var} = (#{exp}))", ['true', [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]]], ['false, nil', [:multi]], [:else, [:multi, [:static, " #{key}=#{@quote}"], [:fescape, @escape_attrs, [:dynamic, var]], [:static, @quote]]], ] end end def compile_common!(temple, key, values) temple << [:html, :attr, key, [:fescape, @escape_attrs, values.last]] end def attribute_builder(type, values) args = [@escape_attrs.inspect, *values.map { |v| literal_for(v) }] "::Hamlit::AttributeBuilder.build_#{type}(#{args.join(', ')})" end def literal_for(value) type, exp = value type == :static ? "#{exp.inspect}.freeze" : exp end end end hamlit-2.11.0/lib/hamlit/version.rb0000644000175000017500000000010513574632775016470 0ustar josephjoseph# frozen_string_literal: true module Hamlit VERSION = '2.11.0' end hamlit-2.11.0/lib/hamlit/rails_helpers.rb0000644000175000017500000000255613574632775017653 0ustar josephjoseph# frozen_string_literal: false require 'hamlit/helpers' # Currently this Hamlit::Helpers depends on # ActionView internal implementation. (not desired) module Hamlit module RailsHelpers include Helpers extend self DEFAULT_PRESERVE_TAGS = %w[textarea pre code].freeze def find_and_preserve(input = nil, tags = DEFAULT_PRESERVE_TAGS, &block) return find_and_preserve(capture_haml(&block), input || tags) if block tags = tags.each_with_object('') do |t, s| s << '|' unless s.empty? s << Regexp.escape(t) end re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im input.to_s.gsub(re) do |s| s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible "<#{$1}#{$2}>#{preserve($3)}" end end def preserve(input = nil, &block) return preserve(capture_haml(&block)) if block super.html_safe end def surround(front, back = front, &block) output = capture_haml(&block) "#{escape_once(front)}#{output.chomp}#{escape_once(back)}\n".html_safe end def precede(str, &block) "#{escape_once(str)}#{capture_haml(&block).chomp}\n".html_safe end def succeed(str, &block) "#{capture_haml(&block).chomp}#{escape_once(str)}\n".html_safe end def capture_haml(*args, &block) capture(*args, &block) end end end hamlit-2.11.0/lib/hamlit/escapable.rb0000644000175000017500000000055513574632775016733 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/utils' module Hamlit class Escapable < Temple::Filters::Escapable def initialize(opts = {}) super @escape_code = options[:escape_code] || "::Hamlit::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))" @escaper = eval("proc {|v| #{@escape_code % 'v'} }") end end end hamlit-2.11.0/lib/hamlit/filters.rb0000644000175000017500000000360413574632775016462 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/filters/base' require 'hamlit/filters/text_base' require 'hamlit/filters/tilt_base' require 'hamlit/filters/coffee' require 'hamlit/filters/css' require 'hamlit/filters/erb' require 'hamlit/filters/escaped' require 'hamlit/filters/javascript' require 'hamlit/filters/less' require 'hamlit/filters/markdown' require 'hamlit/filters/plain' require 'hamlit/filters/preserve' require 'hamlit/filters/ruby' require 'hamlit/filters/sass' require 'hamlit/filters/scss' require 'hamlit/filters/cdata' module Hamlit class Filters @registered = {} class << self attr_reader :registered def remove_filter(name) registered.delete(name.to_s.downcase.to_sym) if constants.map(&:to_s).include?(name.to_s) remove_const name.to_sym end end private def register(name, compiler) registered[name] = compiler end end register :coffee, Coffee register :coffeescript, CoffeeScript register :css, Css register :erb, Erb register :escaped, Escaped register :javascript, Javascript register :less, Less register :markdown, Markdown register :plain, Plain register :preserve, Preserve register :ruby, Ruby register :sass, Sass register :scss, Scss register :cdata, Cdata def initialize(options = {}) @options = options @compilers = {} end def compile(node) node.value[:text] ||= '' find_compiler(node).compile(node) end private def find_compiler(node) name = node.value[:name].to_sym compiler = Filters.registered[name] raise FilterNotFound.new("FilterCompiler for '#{name}' was not found", node.line.to_i - 1) unless compiler @compilers[name] ||= compiler.new(@options) end end end hamlit-2.11.0/lib/hamlit/object_ref.rb0000644000175000017500000000132113574632775017106 0ustar josephjoseph# frozen_string_literal: true module Hamlit module ObjectRef class << self def parse(args) object, prefix = args return {} unless object suffix = underscore(object.class) { 'class' => [prefix, suffix].compact.join('_'), 'id' => [prefix, suffix, object.id || 'new'].compact.join('_'), } end private # Haml::Buffer.underscore def underscore(camel_cased_word) word = camel_cased_word.to_s.dup word.gsub!(/::/, '_') word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.tr!('-', '_') word.downcase! word end end end end hamlit-2.11.0/lib/hamlit/filters/0000755000175000017500000000000013574632775016132 5ustar josephjosephhamlit-2.11.0/lib/hamlit/filters/tilt_base.rb0000644000175000017500000000305513574632775020430 0ustar josephjoseph# frozen_string_literal: true require 'tilt' module Hamlit class Filters class TiltBase < Base def self.render(name, source, indent_width: 0) text = ::Tilt["t.#{name}"].new { source }.render return text if indent_width == 0 text.gsub!(/^/, ' ' * indent_width) end def explicit_require?(needed_registration) Gem::Version.new(Tilt::VERSION) >= Gem::Version.new('2.0.0') && !Tilt.registered?(needed_registration) end private def compile_with_tilt(node, name, indent_width: 0) if ::Hamlit::HamlUtil.contains_interpolation?(node.value[:text]) dynamic_compile(node, name, indent_width: indent_width) else static_compile(node, name, indent_width: indent_width) end end def static_compile(node, name, indent_width: 0) temple = [:multi, [:static, TiltBase.render(name, node.value[:text], indent_width: indent_width)]] node.value[:text].split("\n").size.times do temple << [:newline] end temple end def dynamic_compile(node, name, indent_width: 0) # original: Haml::Filters#compile text = ::Hamlit::HamlUtil.slow_unescape_interpolation(node.value[:text]).gsub(/(\\+)n/) do |s| escapes = $1.size next s if escapes % 2 == 0 "#{'\\' * (escapes - 1)}\n" end text.prepend("\n").sub!(/\n"\z/, '"') [:dynamic, "::Hamlit::Filters::TiltBase.render('#{name}', #{text}, indent_width: #{indent_width})"] end end end end hamlit-2.11.0/lib/hamlit/filters/text_base.rb0000644000175000017500000000141213574632775020433 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class TextBase < Base def compile_text!(temple, node, prefix) text = node.value[:text].rstrip.gsub(/^/, prefix) if ::Hamlit::HamlUtil.contains_interpolation?(node.value[:text]) # original: Haml::Filters#compile text = ::Hamlit::HamlUtil.slow_unescape_interpolation(text).gsub(/(\\+)n/) do |s| escapes = $1.size next s if escapes % 2 == 0 "#{'\\' * (escapes - 1)}\n" end text.prepend("\n") temple << [:dynamic, text] else node.value[:text].split("\n").size.times do temple << [:newline] end temple << [:static, text] end end end end end hamlit-2.11.0/lib/hamlit/filters/sass.rb0000644000175000017500000000060013574632775017424 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Sass < TiltBase def compile(node) require 'tilt/sass' if explicit_require?('sass') temple = [:multi] temple << [:static, ""] temple end end end end hamlit-2.11.0/lib/hamlit/filters/scss.rb0000644000175000017500000000060013574632775017426 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Scss < TiltBase def compile(node) require 'tilt/sass' if explicit_require?('scss') temple = [:multi] temple << [:static, ""] temple end end end end hamlit-2.11.0/lib/hamlit/filters/plain.rb0000644000175000017500000000131313574632775017560 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/string_splitter' module Hamlit class Filters class Plain < Base def compile(node) text = node.value[:text] text = text.rstrip unless ::Hamlit::HamlUtil.contains_interpolation?(text) # for compatibility [:multi, *compile_plain(text)] end private def compile_plain(text) string_literal = ::Hamlit::HamlUtil.unescape_interpolation(text) StringSplitter.compile(string_literal).map do |temple| type, str = temple case type when :dynamic [:escape, false, [:dynamic, str]] else temple end end end end end end hamlit-2.11.0/lib/hamlit/filters/escaped.rb0000644000175000017500000000074613574632775020072 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Escaped < Base def compile(node) text = node.value[:text].rstrip temple = compile_text(text) [:escape, true, temple] end private def compile_text(text) if ::Hamlit::HamlUtil.contains_interpolation?(text) [:dynamic, ::Hamlit::HamlUtil.slow_unescape_interpolation(text)] else [:static, text] end end end end end hamlit-2.11.0/lib/hamlit/filters/javascript.rb0000644000175000017500000000135613574632775020632 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Javascript < TextBase def compile(node) case @format when :xhtml compile_xhtml(node) else compile_html(node) end end private def compile_html(node) temple = [:multi] temple << [:static, ""] temple end def compile_xhtml(node) temple = [:multi] temple << [:static, ""] temple end end end end hamlit-2.11.0/lib/hamlit/filters/markdown.rb0000644000175000017500000000033613574632775020303 0ustar josephjosephmodule Hamlit class Filters class Markdown < TiltBase def compile(node) require 'tilt/redcarpet' if explicit_require?('markdown') compile_with_tilt(node, 'markdown') end end end end hamlit-2.11.0/lib/hamlit/filters/erb.rb0000644000175000017500000000026013574632775017225 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Erb < TiltBase def compile(node) compile_with_tilt(node, 'erb') end end end end hamlit-2.11.0/lib/hamlit/filters/base.rb0000644000175000017500000000032013574632775017364 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/parser/haml_util' module Hamlit class Filters class Base def initialize(options = {}) @format = options[:format] end end end end hamlit-2.11.0/lib/hamlit/filters/preserve.rb0000644000175000017500000000076013574632775020315 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Preserve < Base def compile(node) text = node.value[:text].rstrip + "\n" text = text.gsub("\n", ' ') compile_text(text) end private def compile_text(text) if ::Hamlit::HamlUtil.contains_interpolation?(text) [:dynamic, ::Hamlit::HamlUtil.slow_unescape_interpolation(text)] else [:static, text] end end end end end hamlit-2.11.0/lib/hamlit/filters/cdata.rb0000644000175000017500000000060413574632775017533 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Cdata < TextBase def compile(node) compile_cdata(node) end private def compile_cdata(node) temple = [:multi] temple << [:static, ""] temple end end end end hamlit-2.11.0/lib/hamlit/filters/css.rb0000644000175000017500000000134013574632775017245 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Css < TextBase def compile(node) case @format when :xhtml compile_xhtml(node) else compile_html(node) end end private def compile_html(node) temple = [:multi] temple << [:static, ""] temple end def compile_xhtml(node) temple = [:multi] temple << [:static, ""] temple end end end end hamlit-2.11.0/lib/hamlit/filters/ruby.rb0000644000175000017500000000025113574632775017436 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Ruby < Base def compile(node) [:code, node.value[:text]] end end end end hamlit-2.11.0/lib/hamlit/filters/coffee.rb0000644000175000017500000000064513574632775017713 0ustar josephjoseph# frozen_string_literal: true module Hamlit class Filters class Coffee < TiltBase def compile(node) require 'tilt/coffee' if explicit_require?('coffee') temple = [:multi] temple << [:static, ""] temple end end CoffeeScript = Coffee end end hamlit-2.11.0/lib/hamlit/filters/less.rb0000644000175000017500000000110013574632775017415 0ustar josephjoseph# frozen_string_literal: true # LESS support is deprecated since it requires therubyracer.gem, # which is hard to maintain. # # It's not supported in Sprockets 3.0+ too. # https://github.com/sstephenson/sprockets/pull/547 module Hamlit class Filters class Less < TiltBase def compile(node) require 'tilt/less' if explicit_require?('less') temple = [:multi] temple << [:static, "'] temple end end end end hamlit-2.11.0/lib/hamlit/railtie.rb0000644000175000017500000000027113574632775016440 0ustar josephjoseph# frozen_string_literal: true require 'rails' module Hamlit class Railtie < ::Rails::Railtie initializer :hamlit do |app| require 'hamlit/rails_template' end end end hamlit-2.11.0/lib/hamlit/helpers.rb0000644000175000017500000000056513574632775016457 0ustar josephjoseph# frozen_string_literal: true module Hamlit module Helpers extend self # The same as original Haml::Helpers#preserve without block support. def preserve(input) # https://github.com/haml/haml/blob/4.1.0.beta.1/lib/haml/helpers.rb#L130-L133 s = input.to_s.chomp("\n") s.gsub!(/\n/, ' ') s.delete!("\r") s end end end hamlit-2.11.0/lib/hamlit/attribute_parser.rb0000644000175000017500000000505313574632775020371 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/ruby_expression' module Hamlit class AttributeParser class ParseSkip < StandardError end def self.parse(text) self.new.parse(text) end def parse(text) exp = wrap_bracket(text) return if RubyExpression.syntax_error?(exp) hash = {} tokens = Ripper.lex(exp)[1..-2] || [] each_attr(tokens) do |attr_tokens| key = parse_key!(attr_tokens) hash[key] = attr_tokens.map { |t| t[2] }.join.strip end hash rescue ParseSkip nil end private def wrap_bracket(text) text = text.strip return text if text[0] == '{' "{#{text}}" end def parse_key!(tokens) _, type, str = tokens.shift case type when :on_sp parse_key!(tokens) when :on_label str.tr(':', '') when :on_symbeg _, _, key = tokens.shift assert_type!(tokens.shift, :on_tstring_end) if str != ':' skip_until_hash_rocket!(tokens) key when :on_tstring_beg _, _, key = tokens.shift next_token = tokens.shift unless next_token[1] == :on_label_end assert_type!(next_token, :on_tstring_end) skip_until_hash_rocket!(tokens) end key else raise ParseSkip end end def assert_type!(token, type) raise ParseSkip if token[1] != type end def skip_until_hash_rocket!(tokens) until tokens.empty? _, type, str = tokens.shift break if type == :on_op && str == '=>' end end def each_attr(tokens) attr_tokens = [] open_tokens = Hash.new { |h, k| h[k] = 0 } tokens.each do |token| _, type, _ = token case type when :on_comma if open_tokens.values.all?(&:zero?) yield(attr_tokens) attr_tokens = [] next end when :on_lbracket open_tokens[:array] += 1 when :on_rbracket open_tokens[:array] -= 1 when :on_lbrace open_tokens[:block] += 1 when :on_rbrace open_tokens[:block] -= 1 when :on_lparen open_tokens[:paren] += 1 when :on_rparen open_tokens[:paren] -= 1 when :on_embexpr_beg open_tokens[:embexpr] += 1 when :on_embexpr_end open_tokens[:embexpr] -= 1 when :on_sp next if attr_tokens.empty? end attr_tokens << token end yield(attr_tokens) unless attr_tokens.empty? end end end hamlit-2.11.0/lib/hamlit/dynamic_merger.rb0000644000175000017500000000365413574632775020004 0ustar josephjoseph# frozen_string_literal: true module Hamlit # Compile [:multi, [:static, 'foo'], [:dynamic, 'bar']] to [:dynamic, '"foo#{bar}"'] class DynamicMerger < Temple::Filter def on_multi(*exps) exps = exps.dup result = [:multi] buffer = [] until exps.empty? type, arg = exps.first if type == :dynamic && arg.count("\n") == 0 buffer << exps.shift elsif type == :static && exps.size > (count = arg.count("\n")) && exps[1, count].all? { |e| e == [:newline] } (1 + count).times { buffer << exps.shift } elsif type == :newline && exps.size > (count = count_newline(exps)) && exps[count].first == :static && count == exps[count].last.count("\n") (count + 1).times { buffer << exps.shift } else result.concat(merge_dynamic(buffer)) buffer = [] result << compile(exps.shift) end end result.concat(merge_dynamic(buffer)) result.size == 2 ? result[1] : result end private def merge_dynamic(exps) # Merge exps only when they have both :static and :dynamic unless exps.any? { |type,| type == :static } && exps.any? { |type,| type == :dynamic } return exps end strlit_body = String.new exps.each do |type, arg| case type when :static strlit_body << arg.dump.sub!(/\A"/, '').sub!(/"\z/, '').gsub('\n', "\n") when :dynamic strlit_body << "\#{#{arg}}" when :newline # newline is added by `gsub('\n', "\n")` else raise "unexpected type #{type.inspect} is given to #merge_dynamic" end end [[:dynamic, "%Q\0#{strlit_body}\0"]] end def count_newline(exps) count = 0 exps.each do |exp| if exp == [:newline] count += 1 else return count end end return count end end end hamlit-2.11.0/lib/hamlit/compiler.rb0000644000175000017500000000505013574632775016621 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/compiler/children_compiler' require 'hamlit/compiler/comment_compiler' require 'hamlit/compiler/doctype_compiler' require 'hamlit/compiler/script_compiler' require 'hamlit/compiler/silent_script_compiler' require 'hamlit/compiler/tag_compiler' require 'hamlit/filters' require 'hamlit/identity' module Hamlit class Compiler def initialize(options = {}) identity = Identity.new @children_compiler = ChildrenCompiler.new @comment_compiler = CommentCompiler.new @doctype_compiler = DoctypeCompiler.new(options) @filter_compiler = Filters.new(options) @script_compiler = ScriptCompiler.new(identity) @silent_script_compiler = SilentScriptCompiler.new @tag_compiler = TagCompiler.new(identity, options) end def call(ast) return runtime_error(ast) if ast.is_a?(HamlError) compile(ast) rescue Error => e runtime_error(e) end private def compile(node) case node.type when :root compile_children(node) when :comment compile_comment(node) when :doctype compile_doctype(node) when :filter compile_filter(node) when :plain compile_plain(node) when :script compile_script(node) when :silent_script compile_silent_script(node) when :tag compile_tag(node) when :haml_comment [:multi] else raise InternalError.new("Unexpected node type: #{node.type}") end end def compile_children(node) @children_compiler.compile(node) { |n| compile(n) } end def compile_comment(node) @comment_compiler.compile(node) { |n| compile_children(n) } end def compile_doctype(node) @doctype_compiler.compile(node) end def compile_filter(node) @filter_compiler.compile(node) end def compile_plain(node) [:static, node.value[:text]] end def compile_script(node) @script_compiler.compile(node) { |n| compile_children(n) } end def compile_silent_script(node) @silent_script_compiler.compile(node) { |n| compile_children(n) } end def compile_tag(node) @tag_compiler.compile(node) { |n| compile_children(n) } end def runtime_error(error) [:multi].tap do |temple| error.line.times { temple << [:newline] } if error.line temple << [:code, %Q[raise #{error.class}.new(%q[#{error.message}], #{error.line.inspect})]] end end end end hamlit-2.11.0/lib/hamlit/rails_template.rb0000644000175000017500000000326613574632775020023 0ustar josephjoseph# frozen_string_literal: true require 'temple' require 'hamlit/engine' require 'hamlit/rails_helpers' require 'hamlit/parser/haml_helpers' require 'hamlit/parser/haml_util' module Hamlit class RailsTemplate # Compatible with: https://github.com/judofyr/temple/blob/v0.7.7/lib/temple/mixins/options.rb#L15-L24 class << self def options @options ||= { generator: Temple::Generators::RailsOutputBuffer, use_html_safe: true, streaming: true, buffer_class: 'ActionView::OutputBuffer', } end def set_options(opts) options.update(opts) end end def call(template, source = nil) source ||= template.source options = RailsTemplate.options # https://github.com/haml/haml/blob/4.0.7/lib/haml/template/plugin.rb#L19-L20 # https://github.com/haml/haml/blob/4.0.7/lib/haml/options.rb#L228 if template.respond_to?(:type) && template.type == 'text/xml' options = options.merge(format: :xhtml) end Engine.new(options).call(source) end def supports_streaming? RailsTemplate.options[:streaming] end end ActionView::Template.register_template_handler(:haml, RailsTemplate.new) # https://github.com/haml/haml/blob/4.0.7/lib/haml/template.rb module HamlHelpers require 'hamlit/parser/haml_xss_mods' include Hamlit::HamlHelpers::XssMods end module HamlUtil undef :rails_xss_safe? if defined? rails_xss_safe? def rails_xss_safe?; true; end end end # Haml extends Haml::Helpers in ActionView each time. # It costs much, so Hamlit includes a compatible module at first. ActionView::Base.send :include, Hamlit::RailsHelpers hamlit-2.11.0/lib/hamlit/html.rb0000644000175000017500000000122413574632775015752 0ustar josephjoseph# frozen_string_literal: true module Hamlit class HTML < Temple::HTML::Fast DEPRECATED_FORMATS = %i[html4 html5].freeze def initialize(opts = {}) if DEPRECATED_FORMATS.include?(opts[:format]) opts = opts.dup opts[:format] = :html end super(opts) end # This dispatcher supports Haml's "revealed" conditional comment. def on_html_condcomment(condition, content, revealed = false) on_html_comment [:multi, [:static, "[#{condition}]>#{'' if revealed}"], content, [:static, "#{'' if revealed}" close = "#{'" unless block_given? push_merged_text("#{open} ") if @node.value[:parse] push_script(@node.value[:text], :in_tag => true, :nuke_inner_whitespace => true) else push_merged_text(@node.value[:text], 0, false) end push_merged_text(" #{close}\n", 0, false) return end push_text(open, 1) @output_tabs += 1 yield if block_given? @output_tabs -= 1 push_text(close, -1) end def compile_doctype doctype = text_for_doctype push_text doctype if doctype end def compile_filter unless filter = Filters.defined[@node.value[:name]] name = @node.value[:name] if ["maruku", "textile"].include?(name) raise ::Hamlit::HamlError.new(::Hamlit::HamlError.message(:install_haml_contrib, name), @node.line - 1) else raise ::Hamlit::HamlError.new(::Hamlit::HamlError.message(:filter_not_defined, name), @node.line - 1) end end filter.internal_compile(self, @node.value[:text]) end def text_for_doctype if @node.value[:type] == "xml" return nil if @options.html? wrapper = @options.attr_wrapper return "" end if @options.html5? '' else if @options.xhtml? if @node.value[:version] == "1.1" '' elsif @node.value[:version] == "5" '' else case @node.value[:type] when "strict"; '' when "frameset"; '' when "mobile"; '' when "rdfa"; '' when "basic"; '' else '' end end elsif @options.html4? case @node.value[:type] when "strict"; '' when "frameset"; '' else '' end end end end # Evaluates `text` in the context of the scope object, but # does not output the result. def push_silent(text, can_suppress = false) flush_merged_text return if can_suppress && @options.suppress_eval? newline = (text == "end") ? ";" : "\n" @precompiled << "#{resolve_newlines}#{text}#{newline}" @output_line = @output_line + text.count("\n") + newline.count("\n") end # Adds `text` to `@buffer` with appropriate tabulation # without parsing it. def push_merged_text(text, tab_change = 0, indent = true) text = !indent || @dont_indent_next_line || @options.ugly ? text : "#{' ' * @output_tabs}#{text}" @to_merge << [:text, text, tab_change] @dont_indent_next_line = false end # Concatenate `text` to `@buffer` without tabulation. def concat_merged_text(text) @to_merge << [:text, text, 0] end def push_text(text, tab_change = 0) push_merged_text("#{text}\n", tab_change) end def flush_merged_text return if @to_merge.empty? mtabs = 0 @to_merge.map! do |type, val, tabs| case type when :text mtabs += tabs inspect_obj(val)[1...-1] when :script if mtabs != 0 && !@options.ugly val = "_hamlout.adjust_tabs(#{mtabs}); " + val end mtabs = 0 "\#{#{val}}" else raise ::Hamlit::HamlSyntaxError.new("[HAML BUG] Undefined entry in ::Hamlit::HamlCompiler@to_merge.") end end str = @to_merge.join unless str.empty? @precompiled << if @options.ugly "_hamlout.buffer << \"#{str}\";" else "_hamlout.push_text(\"#{str}\", #{mtabs}, #{@dont_tab_up_next_text.inspect});" end end @to_merge = [] @dont_tab_up_next_text = false end # Causes `text` to be evaluated in the context of # the scope object and the result to be added to `@buffer`. # # If `opts[:preserve_script]` is true, Haml::Helpers#find_and_preserve is run on # the result before it is added to `@buffer` def push_script(text, opts = {}) return if @options.suppress_eval? args = [:preserve_script, :in_tag, :preserve_tag, :escape_html, :nuke_inner_whitespace] args.map! {|name| !!opts[name]} args << !block_given? << @options.ugly no_format = @options.ugly && !(opts[:preserve_script] || opts[:preserve_tag] || opts[:escape_html]) # Prerender tabulation unless we're in a tag push_merged_text '' unless opts[:in_tag] unless block_given? format_script_method = "_hamlout.format_script((#{text}\n),#{args.join(',')});" push_generated_script(no_format ? "#{text}\n" : format_script_method) concat_merged_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace] return end flush_merged_text push_silent "haml_temp = #{text}" yield push_silent('end', :can_suppress) unless @node.value[:dont_push_end] format_script_method = "_hamlout.format_script(haml_temp,#{args.join(',')});" @precompiled << "_hamlout.buffer << #{no_format ? "haml_temp.to_s;" : format_script_method}" concat_merged_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace] || @options.ugly end def push_generated_script(text) @to_merge << [:script, resolve_newlines + text] @output_line += text.count("\n") end # This is a class method so it can be accessed from Buffer. def self.build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes = {}) # @TODO this is an absolutely ridiculous amount of arguments. At least # some of this needs to be moved into an instance method. quote_escape = attr_wrapper == '"' ? """ : "'" other_quote_char = attr_wrapper == '"' ? "'" : '"' join_char = hyphenate_data_attrs ? '-' : '_' attributes.each do |key, value| if value.is_a?(Hash) data_attributes = attributes.delete(key) data_attributes = flatten_data_attributes(data_attributes, '', join_char) data_attributes = build_data_keys(data_attributes, hyphenate_data_attrs, key) attributes = data_attributes.merge(attributes) end end result = attributes.collect do |attr, value| next if value.nil? value = filter_and_join(value, ' ') if attr == 'class' value = filter_and_join(value, '_') if attr == 'id' if value == true next " #{attr}" if is_html next " #{attr}=#{attr_wrapper}#{attr}#{attr_wrapper}" elsif value == false next end escaped = if escape_attrs == :once ::Hamlit::HamlHelpers.escape_once(value.to_s) elsif escape_attrs ::Hamlit::HamlHelpers.html_escape(value.to_s) else value.to_s end value = ::Hamlit::HamlHelpers.preserve(escaped) if escape_attrs # We want to decide whether or not to escape quotes value.gsub!(/"|"/, '"') this_attr_wrapper = attr_wrapper if value.include? attr_wrapper if value.include? other_quote_char value.gsub!(attr_wrapper, quote_escape) else this_attr_wrapper = other_quote_char end end else this_attr_wrapper = attr_wrapper end " #{attr}=#{this_attr_wrapper}#{value}#{this_attr_wrapper}" end result.compact! result.sort! result.join end def self.filter_and_join(value, separator) return '' if (value.respond_to?(:empty?) && value.empty?) if value.is_a?(Array) value.flatten! value.map! {|item| item ? item.to_s : nil} value.compact! value = value.join(separator) else value = value ? value.to_s : nil end !value.nil? && !value.empty? && value end def self.build_data_keys(data_hash, hyphenate, attr_name="data") Hash[data_hash.map do |name, value| if name == nil [attr_name, value] elsif hyphenate ["#{attr_name}-#{name.to_s.tr('_', '-')}", value] else ["#{attr_name}-#{name}", value] end end] end def self.flatten_data_attributes(data, key, join_char, seen = []) return {key => data} unless data.is_a?(Hash) return {key => nil} if seen.include? data.object_id seen << data.object_id data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, (k, v)| joined = key == '' ? k : [key, k].join(join_char) hash.merge! flatten_data_attributes(v, joined, join_char, seen) end end def prerender_tag(name, self_close, attributes) attributes_string = ::Hamlit::HamlCompiler.build_attributes( @options.html?, @options.attr_wrapper, @options.escape_attrs, @options.hyphenate_data_attrs, attributes) "<#{name}#{attributes_string}#{self_close && @options.xhtml? ? ' /' : ''}>" end def resolve_newlines diff = @node.line - @output_line return "" if diff <= 0 @output_line = @node.line "\n" * diff end # Get rid of and whitespace at the end of the buffer # or the merged text def rstrip_buffer!(index = -1) last = @to_merge[index] if last.nil? push_silent("_hamlout.rstrip!", false) @dont_tab_up_next_text = true return end case last.first when :text last[1].rstrip! if last[1].empty? @to_merge.slice! index rstrip_buffer! index end when :script last[1].gsub!(/\(haml_temp, (.*?)\);$/, '(haml_temp.rstrip, \1);') rstrip_buffer! index - 1 else raise ::Hamlit::HamlSyntaxError.new("[HAML BUG] Undefined entry in ::Hamlit::HamlCompiler@to_merge.") end end end end hamlit-2.11.0/lib/hamlit/parser/haml_util.rb0000644000175000017500000002363113574632775020266 0ustar josephjoseph# encoding: utf-8 begin require 'erubis/tiny' rescue LoadError require 'erb' end require 'set' require 'stringio' require 'strscan' module Hamlit # A module containing various useful functions. module HamlUtil extend self # Silence all output to STDERR within a block. # # @yield A block in which no output will be printed to STDERR def silence_warnings the_real_stderr, $stderr = $stderr, StringIO.new yield ensure $stderr = the_real_stderr end ## Rails XSS Safety # Whether or not ActionView's XSS protection is available and enabled, # as is the default for Rails 3.0+, and optional for version 2.3.5+. # Overridden in haml/template.rb if this is the case. # # @return [Boolean] def rails_xss_safe? false end # Returns the given text, marked as being HTML-safe. # With older versions of the Rails XSS-safety mechanism, # this destructively modifies the HTML-safety of `text`. # # It only works if you are using ActiveSupport or the parameter `text` # implements the #html_safe method. # # @param text [String, nil] # @return [String, nil] `text`, marked as HTML-safe def html_safe(text) return unless text text.html_safe end # Checks that the encoding of a string is valid # and cleans up potential encoding gotchas like the UTF-8 BOM. # If it's not, yields an error string describing the invalid character # and the line on which it occurs. # # @param str [String] The string of which to check the encoding # @yield [msg] A block in which an encoding error can be raised. # Only yields if there is an encoding error # @yieldparam msg [String] The error message to be raised # @return [String] `str`, potentially with encoding gotchas like BOMs removed def check_encoding(str) if str.valid_encoding? # Get rid of the Unicode BOM if possible # Shortcut for UTF-8 which might be the majority case if str.encoding == Encoding::UTF_8 return str.gsub(/\A\uFEFF/, '') elsif str.encoding.name =~ /^UTF-(16|32)(BE|LE)?$/ return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding)), '') else return str end end encoding = str.encoding newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding(Encoding::ASCII_8BIT)) str.force_encoding(Encoding::ASCII_8BIT).split(newlines).each_with_index do |line, i| begin line.encode(encoding) rescue Encoding::UndefinedConversionError => e yield < "\"foo\#{::Hamlit::HamlHelpers.html_escape((bar))}baz\\\"\"" def slow_unescape_interpolation(str, escape_html = nil) res = '' rest = ::Hamlit::HamlUtil.handle_interpolation str.dump do |scan| escapes = (scan[2].size - 1) / 2 char = scan[3] # '{', '@' or '$' res << scan.matched[0...-3 - escapes] if escapes % 2 == 1 res << "\##{char}" else interpolated = if char == '{' balance(scan, ?{, ?}, 1)[0][0...-1] else scan.scan(/\w+/) end content = eval('"' + interpolated + '"') content.prepend(char) if char == '@' || char == '$' content = "::Hamlit::HamlHelpers.html_escape((#{content}))" if escape_html res << "\#{#{content}}" end end res + rest end # Customized Haml::Util.unescape_interpolation to handle escape by Hamlit. # It wraps double quotes to given `str` with escaping `"`. # # ex) unescape_interpolation('foo#{bar}baz"') #=> "\"foo\#{bar}baz\\\"\"" def unescape_interpolation(str) res = '' rest = ::Hamlit::HamlUtil.handle_interpolation str.dump do |scan| escapes = (scan[2].size - 1) / 2 char = scan[3] # '{', '@' or '$' res << scan.matched[0...-3 - escapes] if escapes % 2 == 1 res << "\##{char}" else interpolated = if char == '{' balance(scan, ?{, ?}, 1)[0][0...-1] else scan.scan(/\w+/) end content = eval('"' + interpolated + '"') content.prepend(char) if char == '@' || char == '$' res << "\#{#{content}}" end end res + rest end private # Parses a magic comment at the beginning of a Haml file. # The parsing rules are basically the same as Ruby's. # # @return [(Boolean, String or nil)] # Whether the document begins with a UTF-8 BOM, # and the declared encoding of the document (or nil if none is declared) def parse_haml_magic_comment(str) scanner = StringScanner.new(str.dup.force_encoding(Encoding::ASCII_8BIT)) bom = scanner.scan(/\xEF\xBB\xBF/n) return bom unless scanner.scan(/-\s*#\s*/n) if coding = try_parse_haml_emacs_magic_comment(scanner) return bom, coding end return bom unless scanner.scan(/.*?coding[=:]\s*([\w-]+)/in) return bom, scanner[1] end def try_parse_haml_emacs_magic_comment(scanner) pos = scanner.pos return unless scanner.scan(/.*?-\*-\s*/n) # From Ruby's parse.y return unless scanner.scan(/([^\s'":;]+)\s*:\s*("(?:\\.|[^"])*"|[^"\s;]+?)[\s;]*-\*-/n) name, val = scanner[1], scanner[2] return unless name =~ /(en)?coding/in val = $1 if val =~ /^"(.*)"$/n return val ensure scanner.pos = pos end end end hamlit-2.11.0/lib/hamlit/parser/haml_error.rb0000644000175000017500000000610213574632775020434 0ustar josephjosephmodule Hamlit # An exception raised by Haml code. class HamlError < StandardError MESSAGES = { :bad_script_indent => '"%s" is indented at wrong level: expected %d, but was at %d.', :cant_run_filter => 'Can\'t run "%s" filter; you must require its dependencies first', :cant_use_tabs_and_spaces => "Indentation can't use both tabs and spaces.", :deeper_indenting => "The line was indented %d levels deeper than the previous line.", :filter_not_defined => 'Filter "%s" is not defined.', :gem_install_filter_deps => '"%s" filter\'s %s dependency missing: try installing it or adding it to your Gemfile', :illegal_element => "Illegal element: classes and ids must have values.", :illegal_nesting_content => "Illegal nesting: nesting within a tag that already has content is illegal.", :illegal_nesting_header => "Illegal nesting: nesting within a header command is illegal.", :illegal_nesting_line => "Illegal nesting: content can't be both given on the same line as %%%s and nested within it.", :illegal_nesting_plain => "Illegal nesting: nesting within plain text is illegal.", :illegal_nesting_self_closing => "Illegal nesting: nesting within a self-closing tag is illegal.", :inconsistent_indentation => "Inconsistent indentation: %s used for indentation, but the rest of the document was indented using %s.", :indenting_at_start => "Indenting at the beginning of the document is illegal.", :install_haml_contrib => 'To use the "%s" filter, please install the haml-contrib gem.', :invalid_attribute_list => 'Invalid attribute list: %s.', :invalid_filter_name => 'Invalid filter name ":%s".', :invalid_tag => 'Invalid tag: "%s".', :missing_if => 'Got "%s" with no preceding "if"', :no_ruby_code => "There's no Ruby code for %s to evaluate.", :self_closing_content => "Self-closing tags can't have content.", :unbalanced_brackets => 'Unbalanced brackets.', :no_end => <<-END You don't need to use "- end" in Haml. Un-indent to close a block: - if foo? %strong Foo! - else Not foo. %p This line is un-indented, so it isn't part of the "if" block END } def self.message(key, *args) string = MESSAGES[key] or raise "[HAML BUG] No error messages for #{key}" (args.empty? ? string : string % args).rstrip end # The line of the template on which the error occurred. # # @return [Fixnum] attr_reader :line # @param message [String] The error message # @param line [Fixnum] See \{#line} def initialize(message = nil, line = nil) super(message) @line = line end end # SyntaxError is the type of exception raised when Haml encounters an # ill-formatted document. # It's not particularly interesting, # except in that it's a subclass of {Haml::Error}. class HamlSyntaxError < HamlError; end end hamlit-2.11.0/lib/hamlit/parser/haml_buffer.rb0000644000175000017500000002623613574632775020566 0ustar josephjosephrequire 'hamlit/parser/haml_helpers' require 'hamlit/parser/haml_util' require 'hamlit/parser/haml_compiler' module Hamlit # This class is used only internally. It holds the buffer of HTML that # is eventually output as the resulting document. # It's called from within the precompiled code, # and helps reduce the amount of processing done within `instance_eval`ed code. class HamlBuffer ID_KEY = 'id'.freeze CLASS_KEY = 'class'.freeze DATA_KEY = 'data'.freeze include ::Hamlit::HamlHelpers include ::Hamlit::HamlUtil # The string that holds the compiled HTML. This is aliased as # `_erbout` for compatibility with ERB-specific code. # # @return [String] attr_accessor :buffer # The options hash passed in from {Haml::Engine}. # # @return [{String => Object}] # @see Haml::Options#for_buffer attr_accessor :options # The {Buffer} for the enclosing Haml document. # This is set for partials and similar sorts of nested templates. # It's `nil` at the top level (see \{#toplevel?}). # # @return [Buffer] attr_accessor :upper # nil if there's no capture_haml block running, # and the position at which it's beginning the capture if there is one. # # @return [Fixnum, nil] attr_accessor :capture_position # @return [Boolean] # @see #active? attr_writer :active # @return [Boolean] Whether or not the format is XHTML def xhtml? not html? end # @return [Boolean] Whether or not the format is any flavor of HTML def html? html4? or html5? end # @return [Boolean] Whether or not the format is HTML4 def html4? @options[:format] == :html4 end # @return [Boolean] Whether or not the format is HTML5. def html5? @options[:format] == :html5 end # @return [Boolean] Whether or not this buffer is a top-level template, # as opposed to a nested partial def toplevel? upper.nil? end # Whether or not this buffer is currently being used to render a Haml template. # Returns `false` if a subtemplate is being rendered, # even if it's a subtemplate of this buffer's template. # # @return [Boolean] def active? @active end # @return [Fixnum] The current indentation level of the document def tabulation @real_tabs + @tabulation end # Sets the current tabulation of the document. # # @param val [Fixnum] The new tabulation def tabulation=(val) val = val - @real_tabs @tabulation = val > -1 ? val : 0 end # @param upper [Buffer] The parent buffer # @param options [{Symbol => Object}] An options hash. # See {Haml::Engine#options\_for\_buffer} def initialize(upper = nil, options = {}) @active = true @upper = upper @options = options @buffer = new_encoded_string @tabulation = 0 # The number of tabs that Engine thinks we should have # @real_tabs + @tabulation is the number of tabs actually output @real_tabs = 0 end # Appends text to the buffer, properly tabulated. # Also modifies the document's indentation. # # @param text [String] The text to append # @param tab_change [Fixnum] The number of tabs by which to increase # or decrease the document's indentation # @param dont_tab_up [Boolean] If true, don't indent the first line of `text` def push_text(text, tab_change, dont_tab_up) if @tabulation > 0 # Have to push every line in by the extra user set tabulation. # Don't push lines with just whitespace, though, # because that screws up precompiled indentation. text.gsub!(/^(?!\s+$)/m, tabs) text.sub!(tabs, '') if dont_tab_up end @real_tabs += tab_change @buffer << text end # Modifies the indentation of the document. # # @param tab_change [Fixnum] The number of tabs by which to increase # or decrease the document's indentation def adjust_tabs(tab_change) @real_tabs += tab_change end # the number of arguments here is insane, but passing in an options hash instead of named arguments # causes a significant performance regression def format_script(result, preserve_script, in_tag, preserve_tag, escape_html, nuke_inner_whitespace, interpolated, ugly) result_name = escape_html ? html_escape(result.to_s) : result.to_s if ugly result = nuke_inner_whitespace ? result_name.strip : result_name result = preserve(result, preserve_script, preserve_tag) fix_textareas!(result) if toplevel? && result.include?(' 0 if has_newline result.gsub! "\n", "\n#{tabs(tabulation)}" # Add tabulation if it wasn't precompiled result = "#{tabs(tabulation)}#{result}" if in_tag_no_nuke end fix_textareas!(result) if toplevel? && result.include?(' String}] The attribute hash to merge into # @param from [{String => #to_s}] The attribute hash to merge from # @return [{String => String}] `to`, after being merged def self.merge_attrs(to, from) from[ID_KEY] = ::Hamlit::HamlCompiler.filter_and_join(from[ID_KEY], '_') if from[ID_KEY] if to[ID_KEY] && from[ID_KEY] to[ID_KEY] << "_#{from.delete(ID_KEY)}" elsif to[ID_KEY] || from[ID_KEY] from[ID_KEY] ||= to[ID_KEY] end from[CLASS_KEY] = ::Hamlit::HamlCompiler.filter_and_join(from[CLASS_KEY], ' ') if from[CLASS_KEY] if to[CLASS_KEY] && from[CLASS_KEY] # Make sure we don't duplicate class names from[CLASS_KEY] = (from[CLASS_KEY].to_s.split(' ') | to[CLASS_KEY].split(' ')).sort.join(' ') elsif to[CLASS_KEY] || from[CLASS_KEY] from[CLASS_KEY] ||= to[CLASS_KEY] end from.keys.each do |key| next unless from[key].kind_of?(Hash) || to[key].kind_of?(Hash) from_data = from.delete(key) # forces to_data & from_data into a hash from_data = { nil => from_data } if from_data && !from_data.is_a?(Hash) to[key] = { nil => to[key] } if to[key] && !to[key].is_a?(Hash) if from_data && !to[key] to[key] = from_data elsif from_data && to[key] to[key].merge! from_data end end to.merge!(from) end private def preserve(result, preserve_script, preserve_tag) return ::Hamlit::HamlHelpers.preserve(result) if preserve_tag return ::Hamlit::HamlHelpers.find_and_preserve(result, options[:preserve]) if preserve_script result end # Works like #{find_and_preserve}, but allows the first newline after a # preserved opening tag to remain unencoded, and then outdents the content. # This change was motivated primarily by the change in Rails 3.2.3 to emit # a newline after textarea helpers. # # @param input [String] The text to process # @since Haml 4.0.1 # @private def fix_textareas!(input) pattern = /<(textarea)([^>]*)>(\n| )(.*?)<\/textarea>/im input.gsub!(pattern) do |s| match = pattern.match(s) content = match[4] if match[3] == ' ' content.sub!(/\A /, ' ') else content.sub!(/\A[ ]*/, '') end "<#{match[1]}#{match[2]}>\n#{content}" end end def new_encoded_string "".encode(Encoding.find(options[:encoding])) end @@tab_cache = {} # Gets `count` tabs. Mostly for internal use. def tabs(count = 0) tabs = [count + @tabulation, 0].max @@tab_cache[tabs] ||= ' ' * tabs end # Takes an array of objects and uses the class and id of the first # one to create an attributes hash. # The second object, if present, is used as a prefix, # just like you can do with `dom_id()` and `dom_class()` in Rails def parse_object_ref(ref) prefix = ref[1] ref = ref[0] # Let's make sure the value isn't nil. If it is, return the default Hash. return {} if ref.nil? class_name = if ref.respond_to?(:haml_object_ref) ref.haml_object_ref else underscore(ref.class) end ref_id = if ref.respond_to?(:to_key) key = ref.to_key key.join('_') unless key.nil? else ref.id end id = "#{class_name}_#{ref_id || 'new'}" if prefix class_name = "#{ prefix }_#{ class_name}" id = "#{ prefix }_#{ id }" end {ID_KEY => id, CLASS_KEY => class_name} end # Changes a word from camel case to underscores. # Based on the method of the same name in Rails' Inflector, # but copied here so it'll run properly without Rails. def underscore(camel_cased_word) word = camel_cased_word.to_s.dup word.gsub!(/::/, '_') word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.tr!('-', '_') word.downcase! word end end end hamlit-2.11.0/lib/hamlit/parser/README.md0000644000175000017500000000242713574632775017242 0ustar josephjoseph# lib/hamlit/parser/haml\_\*.rb Hamlit::HamlFoo is originally Haml::Foo in haml gem. This directory is NOT intended to be updated other than following Haml's changes. ## License lib/hamlit/parser/haml\_\*.rb is: Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. hamlit-2.11.0/lib/hamlit/parser/MIT-LICENSE0000644000175000017500000000207613574632775017417 0ustar josephjosephCopyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. hamlit-2.11.0/lib/hamlit/parser/haml_options.rb0000644000175000017500000002435513574632775021010 0ustar josephjosephrequire 'hamlit/parser/haml_parser' require 'hamlit/parser/haml_compiler' require 'hamlit/parser/haml_error' module Hamlit # This class encapsulates all of the configuration options that Haml # understands. Please see the {file:REFERENCE.md#options Haml Reference} to # learn how to set the options. class HamlOptions @defaults = { :attr_wrapper => "'", :autoclose => %w(area base basefont br col command embed frame hr img input isindex keygen link menuitem meta param source track wbr), :encoding => "UTF-8", :escape_attrs => true, :escape_html => false, :filename => '(haml)', :format => :html5, :hyphenate_data_attrs => true, :line => 1, :mime_type => 'text/html', :preserve => %w(textarea pre code), :remove_whitespace => false, :suppress_eval => false, :ugly => false, :cdata => false, :parser_class => ::Hamlit::HamlParser, :compiler_class => ::Hamlit::HamlCompiler, :trace => false } @valid_formats = [:html4, :html5, :xhtml] @buffer_option_keys = [:autoclose, :preserve, :attr_wrapper, :ugly, :format, :encoding, :escape_html, :escape_attrs, :hyphenate_data_attrs, :cdata] # The default option values. # @return Hash def self.defaults @defaults end # An array of valid values for the `:format` option. # @return Array def self.valid_formats @valid_formats end # An array of keys that will be used to provide a hash of options to # {Haml::Buffer}. # @return Hash def self.buffer_option_keys @buffer_option_keys end # 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. attr_reader :attr_wrapper # A list of tag names that should be automatically self-closed if they have # no content. This can also contain regular expressions that match tag names # (or any object which responds to `#===`). Defaults to `['meta', 'img', # 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base']`. attr_accessor :autoclose # The encoding to use for the HTML output. # This can be a string or an `Encoding` Object. Note that Haml **does not** # automatically re-encode Ruby values; any strings coming from outside the # application should be converted before being passed into the Haml # template. Defaults to `Encoding.default_internal`; if that's not set, # defaults to the encoding of the Haml template; if that's `US-ASCII`, # defaults to `"UTF-8"`. attr_reader :encoding # Sets whether or not to escape HTML-sensitive characters in attributes. If # this is true, all HTML-sensitive characters in attributes are escaped. If # it's set to false, no HTML-sensitive characters in attributes are escaped. # If it's set to `:once`, existing HTML escape sequences are preserved, but # other HTML-sensitive characters are escaped. # # Defaults to `true`. attr_accessor :escape_attrs # Sets whether or not to escape HTML-sensitive characters in script. If this # is true, `=` behaves like {file:REFERENCE.md#escaping_html `&=`}; # otherwise, it behaves like {file:REFERENCE.md#unescaping_html `!=`}. Note # that if this is set, `!=` should be used for yielding to subtemplates and # rendering partials. See also {file:REFERENCE.md#escaping_html Escaping HTML} and # {file:REFERENCE.md#unescaping_html Unescaping HTML}. # # Defaults to false. attr_accessor :escape_html # 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. attr_accessor :filename # If set to `true`, Haml will convert underscores to hyphens in all # {file:REFERENCE.md#html5_custom_data_attributes Custom Data Attributes} As # of Haml 4.0, this defaults to `true`. attr_accessor :hyphenate_data_attrs # The line offset of the Haml template being parsed. This is useful for # inline templates, similar to the last argument to `Kernel#eval`. attr_accessor :line # Determines the output format. The default is `:html5`. The other options # are `:html4` and `:xhtml`. If the output is set to XHTML, then Haml # automatically generates self-closing tags and wraps the output of the # Javascript and CSS-like filters inside CDATA. When the output is set to # `:html5` or `:html4`, XML prologs are ignored. In all cases, an appropriate # doctype is generated from `!!!`. # # If the mime_type of the template being rendered is `text/xml` then a # format of `:xhtml` will be used even if the global output format is set to # `:html4` or `:html5`. attr :format # The mime type that the rendered document will be served with. If this is # set to `text/xml` then the format will be overridden to `:xhtml` even if # it has set to `:html4` or `:html5`. attr_accessor :mime_type # 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 # {file:REFERENCE.md#whitespace_preservation Whitespace Preservation}. attr_accessor :preserve # If set to `true`, all tags are treated as if both # {file:REFERENCE.md#whitespace_removal__and_ whitespace removal} options # were present. Use with caution as this may cause whitespace-related # formatting errors. # # Defaults to `false`. attr_reader :remove_whitespace # 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_accessor :suppress_eval # If set to `true`, Haml makes no attempt to properly indent or format the # HTML output. This significantly improves rendering performance but makes # viewing the source unpleasant. # # Defaults to `true` in Rails production mode, and `false` everywhere else. attr_accessor :ugly # Whether to include CDATA sections around javascript and css blocks when # using the `:javascript` or `:css` filters. # # This option also affects the `:sass`, `:scss`, `:less` and `:coffeescript` # filters. # # Defaults to `false` for html, `true` for xhtml. Cannot be changed when using # xhtml. attr_accessor :cdata # The parser class to use. Defaults to Haml::Parser. attr_accessor :parser_class # The compiler class to use. Defaults to Haml::Compiler. attr_accessor :compiler_class # Enable template tracing. If true, it will add a 'data-trace' attribute to # each tag generated by Haml. The value of the attribute will be the # source template name and the line number from which the tag was generated, # separated by a colon. On Rails applications, the path given will be a # relative path as from the views directory. On non-Rails applications, # the path will be the full path. attr_accessor :trace def initialize(values = {}, &block) defaults.each {|k, v| instance_variable_set :"@#{k}", v} values.each {|k, v| send("#{k}=", v) if defaults.has_key?(k) && !v.nil?} yield if block_given? end # Retrieve an option value. # @param key The value to retrieve. def [](key) send key end # Set an option value. # @param key The key to set. # @param value The value to set for the key. def []=(key, value) send "#{key}=", value end [:escape_attrs, :hyphenate_data_attrs, :remove_whitespace, :suppress_eval, :ugly].each do |method| class_eval(<<-END) def #{method}? !! @#{method} end END end # @return [Boolean] Whether or not the format is XHTML. def xhtml? not html? end # @return [Boolean] Whether or not the format is any flavor of HTML. def html? html4? or html5? end # @return [Boolean] Whether or not the format is HTML4. def html4? format == :html4 end # @return [Boolean] Whether or not the format is HTML5. def html5? format == :html5 end def attr_wrapper=(value) @attr_wrapper = value || self.class.defaults[:attr_wrapper] end # Undef :format to suppress warning. It's defined above with the `:attr` # macro in order to make it appear in Yard's list of instance attributes. undef :format def format mime_type == "text/xml" ? :xhtml : @format end def format=(value) unless self.class.valid_formats.include?(value) raise ::Hamlit::HamlError, "Invalid output format #{value.inspect}" end @format = value end undef :cdata def cdata xhtml? || @cdata end def remove_whitespace=(value) @ugly = true if value @remove_whitespace = value end def encoding=(value) return unless value @encoding = value.is_a?(Encoding) ? value.name : value.to_s @encoding = "UTF-8" if @encoding.upcase == "US-ASCII" end # Returns a subset of options: those that {Haml::Buffer} cares about. # All of the values here are such that when `#inspect` is called on the hash, # it can be `Kernel#eval`ed to get the same result back. # # See {file:REFERENCE.md#options the Haml options documentation}. # # @return [{Symbol => Object}] The options hash def for_buffer self.class.buffer_option_keys.inject({}) do |hash, key| hash[key] = send(key) hash end end private def defaults self.class.defaults end end end hamlit-2.11.0/lib/hamlit.rb0000644000175000017500000000031113574632775015002 0ustar josephjoseph# frozen_string_literal: true require 'hamlit/engine' require 'hamlit/error' require 'hamlit/version' require 'hamlit/template' begin require 'rails' require 'hamlit/railtie' rescue LoadError end hamlit-2.11.0/test/0000755000175000017500000000000013574632775013415 5ustar josephjosephhamlit-2.11.0/test/hamlit/0000755000175000017500000000000013574632775014673 5ustar josephjosephhamlit-2.11.0/test/hamlit/attribute_parser_test.rb0000644000175000017500000001155313574632775021643 0ustar josephjosephdescribe Hamlit::AttributeParser do describe '.parse' do def assert_parse(expected, haml) actual = Hamlit::AttributeParser.parse(haml) if expected.nil? assert_nil actual else assert_equal expected, actual end end it { assert_parse({}, '') } it { assert_parse({}, '{}') } describe 'invalid hash' do it { assert_parse(nil, ' hash ') } it { assert_parse(nil, 'hash, foo: bar') } it { assert_parse(nil, ' {hash} ') } it { assert_parse(nil, ' { hash, foo: bar } ') } end describe 'dynamic key' do it { assert_parse(nil, 'foo => bar') } it { assert_parse(nil, '[] => bar') } it { assert_parse(nil, '[1,2,3] => bar') } end describe 'foo: bar' do it { assert_parse({ '_' => '1' }, '_:1,') } it { assert_parse({ 'foo' => 'bar' }, ' foo: bar ') } it { assert_parse({ 'a' => 'b', 'c' => ':d' }, 'a: b, c: :d') } it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, 'a: [], c: "d"') } it { assert_parse({ '_' => '1' }, ' { _:1, } ') } it { assert_parse({ 'foo' => 'bar' }, ' { foo: bar } ') } it { assert_parse({ 'a' => 'b', 'c' => ':d' }, ' { a: b, c: :d } ') } it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, ' { a: [], c: "d" } ') } end describe ':foo => bar' do it { assert_parse({ 'foo' => ':bar' }, ' :foo => :bar ') } it { assert_parse({ '_' => '"foo"' }, ':_=>"foo"') } it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ':a => [], c: "", :b => "#{3}"') } it { assert_parse({ 'foo' => ':bar' }, ' { :foo => :bar } ') } it { assert_parse({ '_' => '"foo"' }, ' { :_=>"foo" } ') } it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ' { :a => [], c: "", :b => "#{3}" } ') } it { assert_parse(nil, ':"f#{o}o" => bar') } it { assert_parse(nil, ':"#{f}oo" => bar') } it { assert_parse(nil, ':"#{foo}" => bar') } end describe '"foo" => bar' do it { assert_parse({ 'foo' => '[1]' }, '"foo"=>[1]') } it { assert_parse({ 'foo' => 'nya' }, " 'foo' => nya ") } it { assert_parse({ 'foo' => 'bar' }, '%q[foo] => bar ') } it { assert_parse({ 'foo' => '[1]' }, ' { "foo"=>[1] } ') } it { assert_parse({ 'foo' => 'nya' }, " { 'foo' => nya } ") } it { assert_parse({ 'foo' => 'bar' }, ' { %q[foo] => bar } ') } it { assert_parse(nil, '"f#{o}o" => bar') } it { assert_parse(nil, '"#{f}oo" => bar') } it { assert_parse(nil, '"#{foo}" => bar') } it { assert_parse({ 'f#{o}o' => 'bar' }, '%q[f#{o}o] => bar ') } it { assert_parse({ 'f#{o}o' => 'bar' }, ' { %q[f#{o}o] => bar, } ') } it { assert_parse(nil, '%Q[f#{o}o] => bar ') } end if RUBY_VERSION >= '2.2.0' describe '"foo": bar' do it { assert_parse({ 'foo' => '()' }, '"foo":()') } it { assert_parse({ 'foo' => 'nya' }, " 'foo': nya ") } it { assert_parse({ 'foo' => '()' }, ' { "foo":() , }') } it { assert_parse({ 'foo' => 'nya' }, " { 'foo': nya , }") } it { assert_parse(nil, '"f#{o}o": bar') } it { assert_parse(nil, '"#{f}oo": bar') } it { assert_parse(nil, '"#{foo}": bar') } end end describe 'nested array' do it { assert_parse({ 'foo' => '[1,2,]' }, 'foo: [1,2,],') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, 'foo: [1,2,[3,4],5],') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, 'foo: [1,2,[3,4],5],bar: [[1,2],],') } it { assert_parse({ 'foo' => '[1,2,]' }, ' { foo: [1,2,], } ') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, ' { foo: [1,2,[3,4],5], } ') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, ' { foo: [1,2,[3,4],5],bar: [[1,2],], } ') } end describe 'nested hash' do it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, 'foo: { }, bar: {}') } it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, 'foo: { bar: baz, hoge: fuga, }, ') } it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, 'data: { confirm: true, disable: false }, :hello => { world: foo, },') } it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, ' { foo: { }, bar: {} } ') } it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, ' { foo: { bar: baz, hoge: fuga, }, } ') } it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, ' { data: { confirm: true, disable: false }, :hello => { world: foo, }, } ') } end describe 'nested method' do it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, 'foo: bar(a, b), hoge: piyo(a, b,),') } it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, ' { foo: bar(a, b), hoge: piyo(a, b,), } ') } end end if RUBY_ENGINE != 'truffleruby' # truffleruby doesn't have Ripper.lex end hamlit-2.11.0/test/hamlit/line_number_test.rb0000644000175000017500000001336313574632775020564 0ustar josephjosephrequire_relative '../test_helper' describe Hamlit::Engine do include RenderHelper describe 'script' do it 'renders optimized script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 2 HTML = '1' = __LINE__ HAML end it 'renders dynamic script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 2 HTML = 'a'.gsub(/a/, '1') = __LINE__ HAML end it 'renders dynamic script with children' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 3 3 24 HTML = __LINE__ = __LINE__.times do = __LINE__ = __LINE__ HAML end end describe 'silent script' do it 'renders silent script' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 2:3 4 HTML - __LINE__.times do - a = __LINE__ = "#{a}:#{__LINE__}" = __LINE__ HAML end it 'renders silent script with children' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 1:2 HTML - a = __LINE__ = "#{a}:#{__LINE__}" HAML end end describe 'old attributes' do it 'renders multi-line old attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 2 3 HTML %span{ a: __LINE__, b: __LINE__ }= __LINE__ = __LINE__ HAML end it 'renders optimized old attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 5 6 HTML %span{ a: 'a', b: 'b' } = __LINE__ %span{ a: 'a', b: 'b' }= __LINE__ = __LINE__ HAML end end describe 'new attributes' do it 'renders multi-line new attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 3 HTML %span(a=__LINE__ b=__LINE__)= __LINE__ = __LINE__ HAML end end describe 'filters' do describe 'coffee filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 5 HTML :coffee jQuery ($) -> console.log('#{__LINE__}') console.log('#{__LINE__}') = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML :coffee jQuery ($) -> console.log('3') console.log('4') = __LINE__ HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment describe 'css filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 6 HTML :css body { width: 3px; height: 4px; } = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 6 HTML :css body { width: #{__LINE__}px; height: #{__LINE__}px; } = __LINE__ HAML end it 'renders dynamic filter with trailing newlines' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 8 HTML :css body { width: #{__LINE__}px; height: #{__LINE__}px; } = __LINE__ HAML end end describe 'javascript filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML :javascript console.log("2"); console.log("3"); = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 5 HTML :javascript console.log("#{__LINE__}"); console.log("#{__LINE__}"); = __LINE__ HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment end describe 'dynamic merger' do it 'renders optimized string' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) foo1 2 3bar 5baz HTML foo#{__LINE__} #{__LINE__} #{__LINE__}bar - 1.to_s #{__LINE__}baz HAML end end end if RUBY_ENGINE != 'truffleruby' # negetive line numbers are broken in truffleruby hamlit-2.11.0/test/hamlit/cli_test.rb0000644000175000017500000000063713574632775017034 0ustar josephjosephrequire 'hamlit/cli' describe Hamlit::CLI do describe '#temple' do def redirect_output out, $stdout = $stdout, StringIO.new yield ensure $stdout = out end it 'does not crash when compiling a tag' do redirect_output do f = Tempfile.open('hamlit') f.write('%input{ hash }') f.close Hamlit::CLI.new.temple(f.path) end end end end hamlit-2.11.0/test/hamlit/dynamic_merger_test.rb0000644000175000017500000000433613574632775021252 0ustar josephjosephdescribe Hamlit::DynamicMerger do describe '#call' do def assert_compile(expected, input) actual = Hamlit::DynamicMerger.new.compile(input) assert_equal expected, actual end def assert_noop(input) actual = Hamlit::DynamicMerger.new.compile(input) assert_equal input, actual end def strlit(body) "%Q\0#{body}\0" end specify { assert_compile([:static, 'foo'], [:multi, [:static, 'foo']]) } specify { assert_compile([:dynamic, 'foo'], [:multi, [:dynamic, 'foo']]) } specify { assert_noop([:multi, [:static, 'foo'], [:newline]]) } specify { assert_noop([:multi, [:dynamic, 'foo'], [:newline]]) } specify { assert_noop([:multi, [:static, "foo\n"], [:newline]]) } specify { assert_noop([:multi, [:static, 'foo'], [:dynamic, "foo\n"], [:newline]]) } specify { assert_noop([:multi, [:static, "foo\n"], [:dynamic, 'foo'], [:newline]]) } specify do assert_compile([:dynamic, strlit("\#{foo}foo\n")], [:multi, [:dynamic, 'foo'], [:static, "foo\n"], [:newline]]) end specify do assert_compile([:multi, [:dynamic, strlit("\#{foo}foo\n\n")], [:newline], [:code, 'foo'], ], [:multi, [:dynamic, 'foo'], [:static, "foo\n\n"], [:newline], [:newline], [:newline], [:code, 'foo'], ]) end specify do assert_compile([:multi, [:dynamic, strlit("\#{foo}foo\n")], [:code, 'bar'], [:dynamic, strlit("\#{foo}foo\n")], ], [:multi, [:dynamic, 'foo'], [:static, "foo\n"], [:newline], [:code, 'bar'], [:dynamic, 'foo'], [:static, "foo\n"], [:newline], ]) end specify do assert_compile([:multi, [:newline], [:dynamic, strlit("foo\n\#{foo}")]], [:multi, [:newline], [:newline], [:static, "foo\n"], [:dynamic, 'foo']]) end specify { assert_compile([:static, "\n"], [:multi, [:static, "\n"]]) } specify { assert_compile([:newline], [:multi, [:newline]]) } end end hamlit-2.11.0/test/hamlit/string_splitter_test.rb0000644000175000017500000000414613574632775021520 0ustar josephjosephdescribe Hamlit::StringSplitter do describe '.compile' do def assert_compile(expected, code) actual = Hamlit::StringSplitter.compile(code) assert_equal expected, actual end it { assert_compile([], %q|''|) } it { assert_compile([], %q|""|) } it { assert_compile([[:static, 'hello']], %q|"hello"|) } it { assert_compile([[:static, 'hello '], [:static, 'world']], %q|"hello #{}world"|) } it { assert_compile([[:dynamic, 'hello']], %q|"#{hello}"|) } it { assert_compile([[:static, 'nya'], [:dynamic, '123']], %q|"nya#{123}"|) } it { assert_compile([[:dynamic, '()'], [:static, '()']], %q|"#{()}()"|) } it { assert_compile([[:static, ' '], [:dynamic, %q[ " #{ '#{}' } " ]]], %q|" #{ " #{ '#{}' } " }"|) } it { assert_compile([[:static, 'a'], [:dynamic, 'b'], [:static, 'c'], [:dynamic, 'd'], [:static, 'e']], %q|%Q[a#{b}c#{d}e]|) } it { assert_compile([[:static, 'a#{b}c#{d}e']], %q|%q[a#{b}c#{d}e]|) } it { assert_compile([[:static, '#{}'], [:dynamic, '123']], %q|"\#{}#{123}"|) } it { assert_compile([[:dynamic, " '}' "]], %q|"#{ '}' }"|) } it { assert_compile([[:static, 'a']], %q| "a" # hello |) } it { assert_compile([[:static, '"']], %q|"\""|) } it { assert_compile([[:static, '\\"']], %q|"\\\\\\""|) } it { assert_compile([[:static, '\"']], %q|'\"'|) } it { assert_compile([[:static, '\"']], %q|'\\"'|) } it { assert_compile([[:static, '\\"']], %q|'\\\"'|) } describe 'invalid argument' do it 'raises internal error' do assert_raises Hamlit::InternalError do Hamlit::StringSplitter.compile('1') end end it 'raises internal error' do assert_raises Hamlit::InternalError do Hamlit::StringSplitter.compile('[]') end end it 'raises internal error' do if /java/ === RUBY_PLATFORM skip 'Ripper of JRuby is behaving in a different way' end assert_raises Hamlit::InternalError do Hamlit::StringSplitter.compile('"]') end end end end if RUBY_ENGINE != 'truffleruby' # truffleruby doesn't have Ripper.lex end hamlit-2.11.0/test/hamlit/helpers_test.rb0000644000175000017500000000032013574632775017714 0ustar josephjosephdescribe Hamlit::Helpers do describe '.preserve' do it 'works without block' do result = Hamlit::Helpers.preserve("hello\nworld") assert_equal 'hello world', result end end end hamlit-2.11.0/test/hamlit/template_test.rb0000644000175000017500000000303313574632775020071 0ustar josephjosephdescribe Hamlit::Template do # Simple imitation of Sinatra::Templates#compila_template def compile_template(engine, data, options = {}) template = Tilt[engine] template.new(nil, 1, options) { data } end specify 'Tilt returns Hamlit::Template for haml engine' do assert_equal Hamlit::Template, Tilt[:haml] end it 'renders properly via tilt' do result = compile_template(:haml, %q|%p hello world|).render(Object.new, {}) assert_equal %Q|

hello world

\n|, result end it 'has preserve method' do result = compile_template(:haml, %q|= preserve "hello\nworld"|).render(Object.new, {}) assert_equal %Q|hello&#x000A;world\n|, result end describe 'escape_attrs' do it 'escapes attrs by default' do result = compile_template(:haml, %q|%div{ data: ' after HTML before :javascript after HAML end it 'compiles javascript filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) before after HTML before :javascript alert('hello'); after HAML end it 'accepts illegal indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript if { alert('hello'); } :javascript if { alert('hello'); } HAML end it 'accepts illegal indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript if { alert('a'); } HAML end it 'parses string interpolation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript var a = "#{'<&>'}"; HAML end end end hamlit-2.11.0/test/hamlit/filters/css_test.rb0000644000175000017500000000120513574632775020515 0ustar josephjosephdescribe Hamlit::Filters do include RenderHelper describe '#compile' do it 'renders css' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :css .foo { width: 100px; } HAML end it 'parses string interpolation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :css .foo { content: "#{'<&>'}"; } HAML end end end hamlit-2.11.0/test/hamlit/filters/plain_test.rb0000644000175000017500000000100313574632775021024 0ustar josephjosephdescribe Hamlit::Filters do include RenderHelper describe '#compile' do it 'does not escape content without interpolation' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML :coffee foo = -> alert('hello') HAML end it 'renders coffeescript filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :coffeescript foo = -> alert('hello') HAML end it 'renders coffeescript filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML :coffee foo = -> alert("#{'<&>'}") HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment end hamlit-2.11.0/test/hamlit/engine/0000755000175000017500000000000013574632775016140 5ustar josephjosephhamlit-2.11.0/test/hamlit/engine/tag_test.rb0000644000175000017500000000757613574632775020316 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'tag' do it 'renders one-line tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span hello HAML end it 'accepts multi-line =' do assert_render(<<-HTML.unindent, <<-HAML.unindent) o HTML %span= 'hello'.gsub('hell', '') HAML end it 'renders multi-line tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span hello HAML end it 'renders a nested tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML %span %b hello %i %small world HAML end it 'renders multi-line texts' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML %span %b hello world HAML end it 'ignores empty lines' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span %b hello HAML end it 'renders classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span.foo-1.bar_A hello HAML end it 'renders ids only last one' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span#Bar_0#bar- hello HAML end it 'renders ids and classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span#a.b#c.d hello HAML end it 'renders implicit div tag starting with id' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #hello.world HAML end it 'renders implicit div tag starting with class' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
foo
HTML .world#hello foo HAML end it 'renders large-case tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) foo HTML %SPAN foo HAML end it 'renders h1 tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %h1 foo HAML end it 'renders tag including hyphen or underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent) <-_>foo HTML %-_ foo HAML end it 'does not render silent script just after a tag' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) raise 'a' HTML %span- raise 'a' HAML end it 'renders a text just after attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a HTML %span{a: 2}a HAML end it 'strips a text' do assert_render(<<-HTML.unindent, <<-HAML.unindent) foo HTML %span foo HAML end it 'ignores spaces after tag' do assert_render(<<-HTML.unindent, "%span \n a") a HTML end it 'parses self-closing tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent, format: :xhtml)
HTML %div/ %div HAML end end end hamlit-2.11.0/test/hamlit/engine/whitespace_test.rb0000644000175000017500000000501513574632775021661 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'whitespace removal' do it 'removes outer whitespace by >' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ab c d e f HTML %span> a %span b %span c %span> d %span e %span f HAML end it 'removes outer whitespace by > from inside of block' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a b c HTML %span a - if true %span> b %span c HAML end it 'removes whitespaces inside block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) foofoo2bar HTML %span< = 2.times do = 'foo' %span> bar HAML end it 'removes whitespace inside script inside silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
foofoofoo
HTML .bar< - 3.times do = 'foo' HAML end it 'removes whitespace inside script recursively' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
bar1bar1bar1bar12
HTML .foo< - 1.times do = 2.times do - 2.times do = 1.times do = 'bar' HAML end it 'does not remove whitespace after string interpolation' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)
helloworld
HTML %div< #{'hello'} world HAML end it 'removes whitespace inside script inside silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
12
HTML .bar< - 1.times do = '1' = '2' HAML end it 'does not nuke internal recursively' do assert_render(%Q|
\nhello\n
|, <<-HAML.unindent) %div>< %span> hello HAML end it 'does not nuke inside script' do assert_render(%Q|
\nhello\n1
|, <<-HAML.unindent) %div>< = 1.times do %span> hello HAML end end end hamlit-2.11.0/test/hamlit/engine/multiline_test.rb0000644000175000017500000000143713574632775021533 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'multiline' do it 'joins multi-lines ending with pipe' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a b HTML a | b | HAML end it 'renders multi lines' do assert_render(<<-HTML.unindent, <<-HAML.unindent) abc 'd' HTML = 'a' + | 'b' + | 'c' | 'd' HAML end it 'accepts invalid indent' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
12
3
HTML %span %div = '1' + | '2' | %div 3 HAML end end end hamlit-2.11.0/test/hamlit/engine/old_attribute_test.rb0000644000175000017500000003260113574632775022367 0ustar josephjosephrequire_relative '../../test_helper' describe Hamlit::Engine do include RenderHelper describe 'old attributes' do it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{class: 'foo'} bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ data: 2 } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :class => 'foo' } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :class => 'foo', id: 'bar' } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :'data-disabled' => true } bar HAML end it 'accepts method call including comma' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %body{ class: "#{"ab".gsub(/a/, 'b')}", data: { confirm: 'really?', disabled: true }, id: 'c'.gsub(/c/, 'a') } HAML end it 'accepts tag content' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ class: 'foo' } bar HAML end it 'renders multi-byte chars as static attribute value' do assert_render(<<-HTML.unindent, <<-HAML.unindent) こんにちは HTML %img{ alt: 'こんにちは' } HAML end it 'sorts static attributes by name' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span{ :foo => "bar", :hoge => "piyo"} %span{ :hoge => "piyo", :foo => "bar"} HAML end describe 'runtime attributes' do it 'renders runtime hash attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { foo: 'bar' } %span{ hash } HAML end it 'renders multiples hashes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - h1 = { a: 'b' } - h2 = { c: 'd' } - h3 = { e: 'f' } %span{ h1, h2, h3 } HAML end it 'renders multiples hashes and literal hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - h1 = { a: 'b' } - h2 = { c: 'd' } - h3 = { e: 'f' } %span{ h1, h2, h3, g: 'h', i: 'j' } HAML end it 'does not crash when nil is given' do if /java/ === RUBY_PLATFORM skip 'maybe due to Ripper of JRuby' end if RUBY_ENGINE == 'truffleruby' skip 'truffleruby raises NoMethodError' end assert_raises ArgumentError do render_hamlit("%div{ nil }") end end end describe 'joinable attributes' do it 'joins class with a space' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML - val = ['a', 'b', 'c'] %p{ class: val } %p{ class: %w[a b c] } %p{ class: ['a', 'b', 'c'] } HAML end it 'joins attribute class and element class' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .foo{ class: ['bar'] } .foo{ class: ['bar', 'foo'] } .foo{ class: ['bar', nil] } .foo{ class: ['bar', 'baz'] } HAML end it 'joins id with an underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML - val = ['a', 'b', 'c'] %p{ id: val } %p{ id: %w[a b c] } %p{ id: ['a', 'b', 'c'] } HAML end it 'does not join others' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %a{ data: { value: [count: 1] } } HAML end end describe 'deletable attributes' do it 'deletes attributes whose value is nil or false' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { checked: false } %input{ hash } %input{ checked: false } %input{ checked: nil } - checked = nil %input{ checked: checked } - checked = false %input{ checked: checked } HAML end it 'deletes some limited attributes with dynamic value' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = false #foo.bar{ autofocus: val } #foo.bar{ checked: val } #foo.bar{ data: { disabled: val } } #foo.bar{ disabled: val } #foo.bar{ formnovalidate: val } #foo.bar{ multiple: val } #foo.bar{ readonly: val } #foo.bar{ required: val } HAML end it 'does not delete non-boolean attributes, for optimization' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %a{ href: false } - val = false %a{ href: val } - hash = { href: false } %a{ hash } %a{ disabled: false } - val = false %a{ disabled: val } - hash = { disabled: false } %a{ hash } %a{ href: nil } - val = nil %a{ href: val } - hash = { href: nil } %a{ hash } %a{ disabled: nil } - val = nil %a{ disabled: val } - hash = { disabled: nil } %a{ hash } HAML end end describe 'html escape' do it 'escapes attribute values on static attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %a{title: "'"} %a{title: "'\""} %a{href: '/search?foo=bar&hoge='} HAML end it 'escapes attribute values on dynamic attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = "'\"" - href = '/search?foo=bar&hoge=' %a{title: title} %a{href: href} HAML end it 'escapes attribute values on hash attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = { title: "'\"" } - href = { href: '/search?foo=bar&hoge=' } %a{ title } %a{ href } HAML end end describe 'nested data attributes' do it 'renders data attribute by hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { bar: 'baz' } %span.foo{ data: hash } HAML end it 'renders true attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ data: { disabled: true } } bar HAML end it 'renders nested hash whose value is variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML - hash = { disabled: true } %span{ data: hash } bar HAML end it 'changes an underscore in a nested key to a hyphen' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ data: { raw_src: 'foo' } } HAML end it 'changes an underscore in a nested dynamic attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { raw_src: 'foo' } %div{ data: hash } HAML end end describe 'nested aria attributes' do it 'renders aria attribute by hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { bar: 'baz' } %span.foo{ aria: hash } HAML end it 'renders true attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ aria: { disabled: true } } bar HAML end it 'renders nested hash whose value is variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML - hash = { disabled: true } %span{ aria: hash } bar HAML end it 'changes an underscore in a nested key to a hyphen' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ aria: { raw_src: 'foo' } } HAML end it 'changes an underscore in a nested dynamic attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { raw_src: 'foo' } %div{ aria: hash } HAML end end if RUBY_ENGINE != 'truffleruby' # aria attribute is not working in truffleruby describe 'element class with attribute class' do it 'does not generate double classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .item{ class: 'first' } HAML end it 'does not generate double classes for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'val' .element{ class: val } HAML end it 'does not generate double classes for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { class: 'val' } .element{ hash } HAML end end describe 'element id with attribute id' do it 'does not generate double ids' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #item{ id: 'first' } HAML end it 'does not generate double ids for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'first' #item{ id: val } HAML end it 'does not generate double ids for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { id: 'first' } #item{ hash } HAML end it 'does not generate double ids and classes for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { id: 'first', class: 'foo' } #item.bar{ hash } HAML end end if RUBY_VERSION >= "2.2.0" describe 'Ruby 2.2 syntax' do it 'renders static attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %meta{ content: 'IE=edge', 'http-equiv': 'X-UA-Compatible' } HAML end it 'renders dynamic attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { content: 'IE=edge' } %meta{ hash, 'http-equiv': 'X-UA-Compatible' } HAML end end end end end hamlit-2.11.0/test/hamlit/engine/silent_script_test.rb0000644000175000017500000001006513574632775022410 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'silent script' do it 'renders nothing' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - _ = nil - _ = 3 - _ = 'foo' HAML end it 'renders silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML - foo = 3 - bar = 2 = foo + bar HAML end it 'renders nested block' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 1 2 3 4 HTML - 2.times do |i| = i 2 - 3.upto(4).each do |i| = i HAML end it 'renders if' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - if true ok HAML end it 'renders if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok ok HTML - if true ok - else ng - if false ng - else ok HAML end it 'renders nested if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML %span - if false ng - else ok HAML end it 'renders empty elsif statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - if false - elsif false HAML end it 'renders empty else statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - if false ng - else HAML end it 'renders empty when statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - case - when false HAML end it 'accept if inside if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - if false - if true ng - else ok HAML end it 'renders if-elsif' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok ok HTML - if false - elsif true ok - if false - elsif false - else ok HAML end it 'renders case-when' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) ok HTML - case 'foo' - when /\Ao/ ng - when /\Af/ ok - else ng HAML end it 'renders case-when with multiple candidates' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - case 'a' - when 'a', 'b' ok HAML end it 'renders begin-rescue' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML - begin - raise 'error' - rescue hello - ensure world HAML end it 'renders rescue with error' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML - begin - raise 'error' - rescue RuntimeError => _e hello HAML end it 'joins a next line if a current line ends with ","' do assert_render(<<-HTML.unindent, "- foo = [', \n ']\n= foo") [", "] HTML end it 'accepts illegal indent in continuing code' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
3
HTML %span %div - obj = Object.new; def obj.foo(a, b); a + b; end - num = obj.foo(1, 2) = num HAML end it 'renders comment-only nested silent script' do assert_render('', <<-HAML.unindent) - if true - # comment only HAML end end end hamlit-2.11.0/test/hamlit/engine/comment_test.rb0000644000175000017500000000300613574632775021165 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'comment' do it 'renders html comment' do assert_render(%Q|\n|, '/ comments') end it 'strips html comment ignoring around spcaes' do assert_render(%Q|\n|, '/ comments ') end it 'accepts backslash-only line in a comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML / \ HAML end it 'renders a deeply indented comment starting with backslash' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML / \ a / a HAML end it 'ignores multiline comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) ok HTML -# if true - raise 'ng' = invalid script too deep indent ok HAML end it 'renders conditional comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML /[[if IE]] %span hello world HAML end it 'renders conditional comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML /[if lt IE 9] hello HAML end end end hamlit-2.11.0/test/hamlit/engine/text_test.rb0000644000175000017500000001236013574632775020512 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'text' do it 'renders string interpolation' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a3aa" ["1", 2] b " ! a{:a=>3} HTML #{ "a#{3}a" }a" #{["1", 2]} b " ! a#{{ a: 3 }} HAML end it 'escapes all operators by backslash' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a = 'a' - HTML = 'a' - \= 'a' \- HAML end it 'renders == operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) = = <a> HTML === == = == == #{''} HAML end it 'renders !== operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <a> = = HTML == #{''} !== #{''} !=== !== = HAML end it 'leaves empty spaces after backslash' do assert_render(" a\n", '\ a') end it 'renders spaced - properly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)
foo
- bar
- baz
HTML %div foo .test - bar .test - baz HAML end describe 'inline operator' do it 'renders ! operator' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %span!#{''} %span! #{''} ! #{''} HAML end it 'renders & operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <nyaa> <nyaa> <nyaa> HTML %span& #{''} %span&#{''} & #{''} HAML end it 'renders !, & operator right before a non-space character' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)     !hello !hello HTML   \  !hello \!hello HAML end it 'renders &, ! operator inside a tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent)   nbsp; nbsp; !hello hello hello HTML %span   %span  %span& nbsp; %span !hello %span!hello %span! hello HAML end it 'does not accept backslash operator' do assert_render(<<-'HTML'.unindent, <<-'HAML'.unindent) \ foo HTML %span\ foo HAML end it 'renders != operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span!= '' HAML end it 'renders !== operator' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %span!==#{''} %span!== #{''} !==#{''} !== #{''} HAML end it 'renders &= operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent) <nyaa> HTML %span&= '' HAML end it 'renders &== operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) = = <p> HTML &=== &== = &== #{'

'} HAML end it 'renders ~ operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent, escape_html: false) 1 HTML %span~ 1 HAML end end describe 'string interpolation' do it { assert_render("\n", '#{}') } it { assert_render("1\n", '1#{}') } it { assert_render("12\n", '1#{2}') } it { assert_render("}1\n", '}#{1}') } it { assert_render("12\n", '#{1}2') } it { assert_render("12345\n", '1#{ "2#{3}4" }5') } it { assert_render("123456789\n", '#{1}2#{3}4#{5}6#{7}8#{9}') } it { assert_render(%Q{'"!@$%^&*|=1112\n}, %q{'"!@$%^&*|=#{1}1#{1}2}) } it { assert_render("あ1\n", 'あ#{1}') } it { assert_render("あいう\n", 'あ#{"い"}う') } it { assert_render("a<b>c\n", 'a#{""}c') } if RUBY_ENGINE != 'truffleruby' # escape is not working in truffleruby end end end hamlit-2.11.0/test/hamlit/engine/doctype_test.rb0000644000175000017500000000067013574632775021176 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'doctype' do it 'renders html5 doctype' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML !!! HAML end it 'renders xml doctype' do assert_render(<<-HTML.unindent, <<-HAML.unindent, format: :xhtml) HTML !!! XML HAML end end end hamlit-2.11.0/test/hamlit/engine/attributes_test.rb0000644000175000017500000005050413574632775021716 0ustar josephjosephrequire_relative '../../test_helper' describe Hamlit::Engine do include RenderHelper describe 'id attributes' do describe 'compatilibity' do it { assert_haml(%q|#a|) } it { assert_haml(%q|#a{ id: nil }|) } it { assert_haml(%q|#a{ id: nil }(id=nil)|) } it { assert_haml(%q|#a{ id: false }|) } it { assert_haml(%q|#a{ id: 'b' }|) } it { assert_haml(%q|#b{ id: 'a' }|) } it { assert_haml(%q|%a{ 'id' => 60 }|) } if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0') it { assert_haml(%q|%p{class: "a #{"1".concat "2", "3"}"} foo|) } end it { assert_haml(%q|#a{ id: 'b' }(id=id)|, locals: { id: 'c' }) } it { assert_haml(%q|#c{ id: a = 'a' }(id=id)|, locals: { id: 'b' }) } it { assert_haml(%q|#d#c{ id: a = 'b' }(id=id)|, locals: { id: 'a' }) } it { assert_haml(%q|#d#c{ id: %w[b e] }(id=id)|, locals: { id: 'a' }) } it { assert_haml(%q|%div{ hash }|, locals: { hash: { id: 'a' } }) } it { assert_haml(%q|#b{ hash }|, locals: { hash: { id: 'a' } }) } it { assert_haml(%q|#b{ hash }(id='c')|, locals: { hash: { id: 'a' }, id: 'c' }) } it { assert_haml(%q|#b{ hash }(id=id)|, locals: { hash: { id: 'a' }, id: 'c' }) } end describe 'incompatibility' do it { assert_render(%Q|

\n|, %q|#a{ id: [] }|) } it { assert_render(%Q|
\n|, %q|%div{ id: [nil, false] }|) } it { assert_render(%Q|
\n|, %q|#d#c{ id: [] }(id=id)|, locals: { id: 'a' }) } it { assert_render(%Q|
\n|, %q|%div{ id: nil }|) } it { assert_render(%Q|\n|, %q|%input{ id: false }|) } it { assert_render(%Q|\n|, %q|%input{ id: val }|, locals: { val: false }) } it { assert_render(%Q|\n|, %q|%input{ hash }|, locals: { hash: { id: false } }) } end end describe 'class attributes' do describe 'compatibility' do it { assert_haml(%q|.bar.foo|) } it { assert_haml(%q|.foo.bar|) } it { assert_haml(%q|%div(class='bar foo')|) } it { assert_haml(%q|%div(class='foo bar')|) } it { assert_haml(%q|%div{ class: 'bar foo' }|) } it { assert_haml(%q|.b{ class: 'a' }|) } it { assert_haml(%q|.a{ class: 'b a' }|) } it { assert_haml(%q|.b.a{ class: 'b a' }|) } it { assert_haml(%q|.b{ class: 'b a' }|) } it { assert_haml(%q|.a{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b.a{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b{ class: 'c a' }|) } it { assert_haml(%q|.b{ class: 'a c' }|) } it { assert_haml(%q|.a{ class: [] }|) } it { assert_haml(%q|.a{ class: %w[c b] }|) } it { assert_haml(%q|.a.c(class='b')|) } it { assert_haml(%q|%a{ 'class' => 60 }|) } it { assert_haml(%q|%div{ class: 'b a' }(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div(class=klass){ class: 'b a' }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a.d(class=klass){ class: 'c d' }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a.d(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a{:class => klass}|, locals: { klass: nil }) } it { assert_haml(%q|.a{:class => nil}(class=klass)|, locals: { klass: nil }) } it { assert_haml(%q|.a{:class => nil}|) } it { assert_haml(%q|.a{:class => false}|) } it { assert_haml(%q|.b{ hash, class: 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.b{ hash, :class => 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.b{ hash, 'class' => 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.a{ hash }|, locals: { hash: { class: 'd' } }) } it { assert_haml(%q|.b{ hash, class: 'a' }(class='c')|, locals: { hash: { class: 'd' } }) } it { assert_haml(%q|.b{ hash, class: 'a' }(class=klass)|, locals: { hash: { class: 'd' }, klass: nil }) } it { assert_haml(%q|%div{ class: 'b a' }|) } it { assert_haml(%q|%div{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div(class='b a')|) } it { assert_haml(%q|%div(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div{ class: [false, 'a', nil] }|) } it { assert_haml(%q|%div{ class: %q[b a] }|) } it { assert_haml(%q|%div{ class: %q[b a b] }|) } it { assert_haml(%q|%span.c2{class: ["c1", "c3", :c2]}|) } it { assert_haml(%q|%span{class: [1, nil, false, true]}|) } it do assert_haml(<<-HAML.unindent) - v = [1, nil, false, true] %span{class: v} HAML end it do assert_haml(<<-HAML.unindent) - h1 = {class: 'c1', id: ['id1', 'id3']} - h2 = {class: [{}, 'c2'], id: 'id2'} %span#main.content{h1, h2} hello HAML end end describe 'incompatibility' do it { assert_render(%Q|
\n|, %q|%div{ class: nil }|) } it { assert_render(%Q|
\n|, %q|%div{ class: false }|) } it { assert_render(%Q|
\n|, %q|%div{ class: false }|) } it { assert_render(%Q|
\n|, %q|%div{ class: val }|, locals: { val: false }) } it { assert_render(%Q|
\n|, %q|%div{ hash }|, locals: { hash: { class: false } }) } end end describe 'data attributes' do it { assert_haml(%q|#foo.bar{ data: { disabled: val } }|, locals: { val: false }) } it { skip; assert_haml(%q|%div{:data => hash}|, locals: { hash: { :a => { :b => 'c' } }.tap { |h| h[:d] = h } }) } it { skip; assert_haml(%q|%div{ hash }|, locals: { hash: { data: { :a => { :b => 'c' } }.tap { |h| h[:d] = h } } }) } it { assert_haml(%q|%div{:data => {:foo_bar => 'blip', :baz => 'bang'}}|) } it { assert_haml(%q|%div{ data: { raw_src: 'foo' } }|) } it { assert_haml(%q|%a{ data: { value: [count: 1] } }|) } it { assert_haml(%q|%a{ 'data-disabled' => true }|) } it { assert_haml(%q|%a{ :'data-disabled' => true }|) } it { assert_haml(%q|%a{ data: { nil => 3 } }|) } it { assert_haml(%q|%a{ data: 3 }|) } it { assert_haml(%q|%a(data=3)|) } it { assert_haml(%q|%a{ 'data-bar' => 60 }|) } it { assert_haml(%q|%a{ data: { overlay_modal: 'foo' } }|) } it { assert_haml(%q|%a{ data: { overlay_modal: true } }|) } it { assert_haml(%q|%a{ data: { overlay_modal: false } }|) } it { assert_haml(%q|%a{ data: true }|) } it { assert_haml(%q|%a{ data: { nil => true } }|) } it { assert_haml(%q|%a{ data: { false => true } }|) } it { skip; assert_haml(%q|%a{ { data: { 'foo-bar' => 1 } }, data: { foo: { bar: 2 } } }|) } it { assert_haml(%q|%a{ { data: { foo: { bar: 2 } } }, data: { 'foo-bar' => 2 } }|) } it { assert_haml(%q|%a{ { data: { :'foo-bar' => 1 } }, data: { 'foo-bar' => 2 } }|) } it do assert_haml(<<-HAML.unindent) - old = { disabled: true, checked: false, href: false, 'hello-world' => '<>/' } - new = { disabled: false, checked: true, href: '<>/', hello: {}, 'hello_hoge' => true, foo: { 'bar&baz' => 'hoge' } } - hash = { data: { href: true, hash: true } } %a(data=new){ hash, data: old } HAML end it do assert_haml(<<-HAML.unindent) - h1 = { data: 'should be overwritten' } - h2 = { data: nil } %div{ h1, h2 } HAML end end describe 'boolean attributes' do it { assert_haml(%q|%input{ disabled: nil }|) } it { assert_haml(%q|%input{ disabled: false }|) } it { assert_haml(%q|%input{ disabled: true }|) } it { assert_haml(%q|%input{ disabled: 'false' }|) } it { assert_haml(%q|%input{ disabled: val = nil }|) } it { assert_haml(%q|%input{ disabled: val = false }|) } it { assert_haml(%q|%input{ disabled: val = true }|) } it { assert_haml(%q|%input{ disabled: val = 'false' }|) } it { assert_haml(%q|%input{ disabled: nil }(disabled=true)|) } it { assert_haml(%q|%input{ disabled: false }(disabled=true)|) } it { assert_haml(%q|%input{ disabled: true }(disabled=false)|) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { disabled: false } }) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { disabled: nil } }) } it { assert_haml(%q|input(disabled=true){ disabled: nil }|) } it { assert_haml(%q|input(disabled=true){ disabled: false }|) } it { assert_haml(%q|input(disabled=false){ disabled: true }|) } it { assert_haml(%q|%input(disabled=val){ disabled: false }|, locals: { val: true }) } it { assert_haml(%q|%input(disabled=val){ disabled: false }|, locals: { val: false }) } it { assert_haml(%q|%input(disabled=nil)|) } it { assert_haml(%q|%input(disabled=false)|) } it { assert_haml(%q|%input(disabled=true)|) } it { assert_haml(%q|%input(disabled='false')|) } it { assert_haml(%q|%input(disabled=val)|, locals: { val: 'false' }) } it { assert_haml(%q|%input(disabled='false'){ disabled: true }|) } it { assert_haml(%q|%input(disabled='false'){ disabled: false }|) } it { assert_haml(%q|%input(disabled='false'){ disabled: nil }|) } it { assert_haml(%q|%input(disabled=''){ disabled: nil }|) } it { assert_haml(%q|%input(checked=true)|) } it { assert_haml(%q|%input(checked=true)|, format: :xhtml) } it { assert_haml(%q|%input{ 'data-overlay_modal' => nil }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => false }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => true }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => 'false' }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = nil }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = false }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = true }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = 'false' }|) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { 'data-overlay_modal' => false } }) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { 'data-overlay_modal' => true } }) } it { assert_haml(%q|%a{ 'disabled' => 60 }|) } end describe 'common attributes' do describe 'compatibility' do it { assert_haml(%Q|%a{ href: '/search?foo=bar&hoge=' }|) } it { assert_haml(%Q|- h = {foo: 1, 'foo' => 2}\n%span{ h }|) } it { assert_haml(%q|%span(foo='new'){ foo: 'old' }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span(foo=new){ foo: 'old' }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span(foo=new){ foo: old }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: 'old' }(foo='new')|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: 'old' }(foo=new)|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: old }(foo=new)|, locals: { new: 'new', old: 'old' }) } it do assert_haml(<<-HAML.unindent) - h1 = { foo: 1 } - h2 = { foo: 2 } %div{ h1, h2 } HAML end it do assert_haml(<<-'HAML'.unindent) - h = { "class\0with null" => 'is not class' } %div{ h } HAML end it { assert_haml(%q|%a{ 'href' => 60 }|) } end describe 'incompatibility' do it { assert_render(%Q|
\n|, %q|%a{ href: "'\"" }|) } it { assert_render(%Q|\n|, %q|%input{ value: nil }|) } it { assert_render(%Q|\n|, %q|%input{ value: false }|) } it { assert_render(%Q|\n|, %q|%input{ value: val }|, locals: { val: false }) } it { assert_render(%Q|\n|, %q|%input{ hash }|, locals: { hash: { value: false } }) } it do assert_render(%Q|
\n|, <<-HAML.unindent) - h1 = { foo: 'should be overwritten' } - h2 = { foo: nil } %div{ h1, h2 } HAML end end end describe 'object reference' do ::TestObject = Struct.new(:id) unless defined?(::TestObject) it { assert_render(%Q|\n|, %q|%a[foo]|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|\n|, %q|%a[foo, nil]|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|\n|, %q|%a[foo]|, locals: { foo: TestObject.new(nil) }) } it { assert_render(%Q|\n|, %q|%a[foo, 'pre']|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|
\n|, %q|.static#static[TestObject.new(10)]|) } it { assert_render(%Q|
\n|, %q|.static#static[nil]|) } it do assert_render( %Q|\n|, %q|%a.static#static[foo, 'pre']{ id: dynamic, class: dynamic }|, locals: { foo: TestObject.new(10), dynamic: 'dynamic' }, ) end end describe 'engine options' do describe 'attr_quote' do it { assert_render(%Q|\n|, %q|%a{ href: '/' }|) } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?') } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?*) } it { assert_render(%Q|\n|, %q|%a{ id: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ id: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { id: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ class: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { class: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ data: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ data: { url: '/' } }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ data: val }|, attr_quote: ?", locals: { val: { url: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { data: { url: '/' } } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, attr_quote: ?", locals: { hash: { disabled: '/' } }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, attr_quote: ?", format: :xhtml, locals: { hash: { disabled: true } }) } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ href: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { href: '/' } }) } end describe 'escape_attrs' do it { assert_render(%Q|\n|, %q|%a{ id: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ id: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { id: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ id: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ id: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { id: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ class: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { class: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ class: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { class: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ data: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { data: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ data: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { data: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { disabled: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { disabled: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ href: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ href: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { href: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ href: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ href: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { href: '&<>"/' } }) } end describe 'format' do it { assert_render(%Q|\n|, %q|%a{ disabled: true }|, format: :html) } it { assert_render(%Q|\n|, %q|%a{ disabled: val }|, format: :html, locals: { val: true }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, format: :html, locals: { hash: { disabled: true } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: true }|, format: :xhtml) } it { assert_render(%Q|\n|, %q|%a{ disabled: val }|, format: :xhtml, locals: { val: true }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, format: :xhtml, locals: { hash: { disabled: true } }) } end end end hamlit-2.11.0/test/hamlit/engine/script_test.rb0000644000175000017500000000605013574632775021031 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'script' do it 'renders one-line script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 12 HTML = 1 + 2 %span= 3 * 4 HAML end it 'renders dynamic interpolated string' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello nya world HTML - nya = 'nya' = "hello #{nya} world" HAML end it 'renders array with escape_html: false' do assert_render(<<-HTML.unindent, <<-HAML.unindent, escape_html: false) ["<", ">"] HTML = ['<', '>'] HAML end it 'renders one-line script with comment' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ## ["#", "#"] HTML = # comment_only = '#' + "#" # = 3 # = ['#', "#"] # comment HAML end it 'renders multi-lines script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 4 / 2 -1 HTML %span = 1 + 2 4 / 2 %a= 3 - 4 HAML end it 'renders block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 1 2 34 HTML = 3.times do |i| = i 4 HAML end it 'renders tag internal block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 1 HTML %span = 1.times do |i| = i HAML end it 'renders block and a variable with spaces' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 HTML - 1.times do | i | = i HAML end it 'accepts a continuing script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 HTML - obj = Object.new; def obj.foo(a, b); a + b; end = obj.foo(1, 2) HAML end it 'renders !=' do assert_render(<<-HTML.unindent.strip, <<-HAML.unindent, escape_html: false) <"&> <"&> HTML != '<"&>' != '<"&>'.tap do |str| -# no operation HAML end it 'renders &=' do assert_render(<<-HTML.unindent.strip, <<-HAML.unindent, escape_html: false) <"&> <"&> HTML &= '<"&>' &= '<"&>'.tap do |str| -# no operation HAML end it 'regards ~ operator as =' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <code>hello world</code> HTML ~ "hello\nworld" HAML end it 'renders comment-only nested script' do assert_render('1', <<-HAML.unindent) = 1.times do # comment - # comment only HAML end it 'renders inline script with comment' do assert_render(%Q|3\n|, %q|%span= 1 + 2 # comments|) end end end hamlit-2.11.0/test/hamlit/engine/new_attribute_test.rb0000644000175000017500000000523713574632775022407 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'new attributes' do it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(class='foo') bar HAML end it 'renders multiple attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(a=1 b=2) bar HAML end it 'renders hyphenated attributes properly' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(data-foo='bar') bar HAML end it 'renders multiply hyphenated attributes properly' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(data-x-foo='bar') bar HAML end describe 'html escape' do it 'escapes attribute values on static attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %a(title="'") %a(title = "'\"") %a(href='/search?foo=bar&hoge=') HAML end it 'escapes attribute values on dynamic attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = "'\"" - href = '/search?foo=bar&hoge=' %a(title=title) %a(href=href) HAML end end describe 'element class with attribute class' do it 'does not generate double classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .item(class='first') HAML end it 'does not generate double classes for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'val' .element(class=val) HAML end end describe 'element id with attribute id' do it 'concatenates ids with underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #item(id='first') HAML end it 'concatenates ids with underscore for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'first' #item(id=val) HAML end end end end hamlit-2.11.0/test/hamlit/engine/indent_test.rb0000644000175000017500000000136013574632775021005 0ustar josephjosephdescribe Hamlit::Engine do include RenderHelper describe 'tab indent' do it 'accepts tab indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML %p \t%a HAML end it 'accepts N-space indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %p %span foo HAML end it 'accepts N-tab indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %p \t%span \t\tfoo HAML end end end hamlit-2.11.0/test/hamlit/error_test.rb0000644000175000017500000000240613574632775017412 0ustar josephjosephdescribe Hamlit::Engine do describe 'HamlSyntaxError' do it 'raises on runtime' do code = Hamlit::Engine.new.call(" %a") assert_raises(Hamlit::HamlSyntaxError) do eval code end end it 'returns error with lines before error' do code = Hamlit::Engine.new.call("\n\n %a") begin eval code rescue Hamlit::HamlSyntaxError => e assert_equal(2, e.line) end end describe 'Hamlit v1 syntax' do it 'returns an error with proper line number' do code = Hamlit::Engine.new.call(<<-HAML.unindent) %span - if true %div{ data: { hello: 'world', } } HAML begin eval code rescue Hamlit::HamlSyntaxError => e assert_equal(3, e.line) end end end end describe 'FilterNotFound' do it 'raises on runtime' do code = Hamlit::Engine.new.call(":k0kubun") assert_raises(Hamlit::FilterNotFound) do eval code end end it 'returns error with lines before error' do code = Hamlit::Engine.new.call("\n\n:k0kubun") begin eval code rescue Hamlit::FilterNotFound => e assert_equal(2, e.line) end end end end hamlit-2.11.0/test/hamlit/rails_template_test.rb0000644000175000017500000001123213574632775021263 0ustar josephjoseph# Explicitly requiring rails_template because rails initializers is not executed here. require 'hamlit/rails_template' describe Hamlit::RailsTemplate do def render(haml) ActionView::Template.register_template_handler(:haml, Hamlit::RailsTemplate.new) base = Class.new(ActionView::Base) do def compiled_method_container self.class end end.new(ActionView::LookupContext.new('')) base.render(inline: haml, type: :haml) end specify 'html escape' do assert_equal %Q|<script>alert("a");</script>\n|, render(<<-HAML.unindent) = '' HAML assert_equal %Q|\n|, render(<<-HAML.unindent) = ''.html_safe HAML skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_equal %Q|<script>alert("a");</script>\n|, render(<<-'HAML'.unindent) #{''} HAML assert_equal %Q|\n|, render(<<-'HAML'.unindent) #{''.html_safe} HAML end specify 'attribute escape' do assert_equal %Q|\n|, render(<<-HAML.unindent) %a{ href: '' } HAML assert_equal %Q|\n|, render(<<-HAML.unindent) %a{ href: '

} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_content_in_a_css_filter_HTML_ haml = %q{:css hello %p} _html = %q{

} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_content_in_a_javascript_filter_HTML_ haml = %q{:javascript a(); %p} _html = %q{

} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end class Rubystyleinterpolation < MiniTest::Test def test_interpolation_inside_inline_content haml = %q{%p #{var}} _html = %q{

value

} locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_no_interpolation_when_escaped haml = %q{%p \#{var}} _html = %q{

#{var}

} locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_interpolation_when_the_escape_character_is_escaped haml = %q{%p \\#{var}} _html = %q{

\value

} locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_interpolation_inside_filtered_content haml = %q{:plain #{var} interpolated: #{var}} _html = %q{value interpolated: value} locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end class Htmlescaping < MiniTest::Test def test_code_following_ haml = %q{&= '<"&>'} _html = %q{<"&>} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_code_following_eq_when_escape_haml_is_set_to_true haml = %q{= '<"&>'} _html = %q{<"&>} locals = {} options = {:escape_html=>"true"} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_code_following_neq_when_escape_haml_is_set_to_true haml = %q{!= '<"&>'} _html = %q{<"&>} locals = {} options = {:escape_html=>"true"} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end class Booleanattributes < MiniTest::Test def test_boolean_attribute_with_XHTML haml = %q{%input(checked=true)} _html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_boolean_attribute_with_HTML haml = %q{%input(checked=true)} _html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end class Whitespacepreservation < MiniTest::Test def test_following_the_operator haml = %q{~ "Foo\n
Bar\nBaz
"} _html = %q{Foo
Bar
Baz
} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_inside_a_textarea_tag haml = %q{%textarea hello hello} _html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_inside_a_pre_tag haml = %q{%pre hello hello} _html = %q{
hello
hello
} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end class Whitespaceremoval < MiniTest::Test def test_a_tag_with_appended_and_inline_content haml = %q{%li hello %li> world %li again} _html = %q{
  • hello
  • world
  • again
  • } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_a_tag_with_appended_and_nested_content haml = %q{%li hello %li> world %li again} _html = %q{
  • hello
  • world
  • again
  • } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end def test_a_tag_with_appended haml = %q{%p< hello world} _html = %q{

    hello world

    } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) hamlit_result = UglyTest.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end end end if RUBY_ENGINE != 'truffleruby' # truffleruby cannot run Haml hamlit-2.11.0/test/haml/haml-spec/tests.yml0000644000175000017500000003112313574632775020074 0ustar josephjoseph--- headers: an XHTML XML prolog: haml: "!!! XML" html: "" config: format: xhtml an XHTML default (transitional) doctype: haml: "!!!" html: config: format: xhtml an XHTML 1.1 doctype: haml: "!!! 1.1" html: config: format: xhtml an XHTML 1.2 mobile doctype: haml: "!!! mobile" html: config: format: xhtml an XHTML 1.1 basic doctype: haml: "!!! basic" html: config: format: xhtml an XHTML 1.0 frameset doctype: haml: "!!! frameset" html: config: format: xhtml an HTML 5 doctype with XHTML syntax: haml: "!!! 5" html: "" config: format: xhtml an HTML 5 XML prolog (silent): haml: "!!! XML" html: '' config: format: html5 an HTML 5 doctype: haml: "!!!" html: "" config: format: html5 an HTML 4 XML prolog (silent): haml: "!!! XML" html: '' config: format: html4 an HTML 4 default (transitional) doctype: haml: "!!!" html: config: format: html4 an HTML 4 frameset doctype: haml: "!!! frameset" html: config: format: html4 an HTML 4 strict doctype: haml: "!!! strict" html: config: format: html4 basic Haml tags and CSS: a simple Haml tag: haml: "%p" html: "

    " a self-closing tag (XHTML): haml: "%meta" html: "" config: format: xhtml a self-closing tag (HTML4): haml: "%meta" html: "" config: format: html4 a self-closing tag (HTML5): haml: "%meta" html: "" config: format: html5 a self-closing tag ('/' modifier + XHTML): haml: "%zzz/" html: "" config: format: xhtml a self-closing tag ('/' modifier + HTML5): haml: "%zzz/" html: "" config: format: html5 a tag with a CSS class: haml: "%p.class1" html: "

    " a tag with multiple CSS classes: haml: "%p.class1.class2" html: "

    " a tag with a CSS id: haml: "%p#id1" html: "

    " a tag with multiple CSS id's: haml: "%p#id1#id2" html: "

    " a tag with a class followed by an id: haml: "%p.class1#id1" html: "

    " a tag with an id followed by a class: haml: "%p#id1.class1" html: "

    " an implicit div with a CSS id: haml: "#id1" html: "
    " an implicit div with a CSS class: haml: ".class1" html: "
    " multiple simple Haml tags: haml: |- %div %div %p html: |-

    tags with unusual HTML characters: a tag with colons: haml: "%ns:tag" html: "" a tag with underscores: haml: "%snake_case" html: "" a tag with dashes: haml: "%dashed-tag" html: "" a tag with camelCase: haml: "%camelCase" html: "" a tag with PascalCase: haml: "%PascalCase" html: "" tags with unusual CSS identifiers: an all-numeric class: haml: ".123" html: "
    " a class with underscores: haml: ".__" html: "
    " a class with dashes: haml: ".--" html: "
    " tags with inline content: Inline content simple tag: haml: "%p hello" html: "

    hello

    " Inline content tag with CSS: haml: "%p.class1 hello" html: "

    hello

    " Inline content multiple simple tags: haml: |- %div %div %p text html: |-

    text

    tags with nested content: Nested content simple tag: haml: |- %p hello html: |-

    hello

    Nested content tag with CSS: haml: |- %p.class1 hello html: |-

    hello

    Nested content multiple simple tags: haml: |- %div %div %p text html: |-

    text

    tags with HTML-style attributes: HTML-style one attribute: haml: "%p(a='b')" html: "

    " HTML-style multiple attributes: haml: "%p(a='b' c='d')" html: "

    " HTML-style attributes separated with newlines: haml: |- %p(a='b' c='d') html: "

    " HTML-style interpolated attribute: haml: '%p(a="#{var}")' html: "

    " locals: var: value HTML-style 'class' as an attribute: haml: "%p(class='class1')" html: "

    " HTML-style tag with a CSS class and 'class' as an attribute: haml: "%p.class2(class='class1')" html: "

    " HTML-style tag with 'id' as an attribute: haml: "%p(id='1')" html: "

    " HTML-style tag with a CSS id and 'id' as an attribute: haml: "%p#id(id='1')" html: "

    " HTML-style tag with a variable attribute: haml: "%p(class=var)" html: "

    " locals: var: hello HTML-style tag with a CSS class and 'class' as a variable attribute: haml: ".hello(class=var)" html: "
    " locals: var: world HTML-style tag multiple CSS classes (sorted correctly): haml: ".z(class=var)" html: "
    " locals: var: a HTML-style tag with an atomic attribute: haml: "%a(flag)" html: "" tags with Ruby-style attributes: Ruby-style one attribute: haml: "%p{:a => 'b'}" html: "

    " optional: true Ruby-style attributes hash with whitespace: haml: "%p{ :a => 'b' }" html: "

    " optional: true Ruby-style interpolated attribute: haml: '%p{:a =>"#{var}"}' html: "

    " optional: true locals: var: value Ruby-style multiple attributes: haml: "%p{ :a => 'b', 'c' => 'd' }" html: "

    " optional: true Ruby-style attributes separated with newlines: haml: |- %p{ :a => 'b', 'c' => 'd' } html: "

    " optional: true Ruby-style 'class' as an attribute: haml: "%p{:class => 'class1'}" html: "

    " optional: true Ruby-style tag with a CSS class and 'class' as an attribute: haml: "%p.class2{:class => 'class1'}" html: "

    " optional: true Ruby-style tag with 'id' as an attribute: haml: "%p{:id => '1'}" html: "

    " optional: true Ruby-style tag with a CSS id and 'id' as an attribute: haml: "%p#id{:id => '1'}" html: "

    " optional: true Ruby-style tag with a CSS id and a numeric 'id' as an attribute: haml: "%p#id{:id => 1}" html: "

    " optional: true Ruby-style tag with a variable attribute: haml: "%p{:class => var}" html: "

    " optional: true locals: var: hello Ruby-style tag with a CSS class and 'class' as a variable attribute: haml: ".hello{:class => var}" html: "
    " optional: true locals: var: world Ruby-style tag multiple CSS classes (sorted correctly): haml: ".z{:class => var}" html: "
    " optional: true locals: var: a silent comments: an inline silent comment: haml: "-# hello" html: '' a nested silent comment: haml: |- -# hello html: '' a multiply nested silent comment: haml: |- -# %div foo html: '' a multiply nested silent comment with inconsistent indents: haml: |- -# %div foo html: '' markup comments: an inline markup comment: haml: "/ comment" html: "" a nested markup comment: haml: |- / comment comment2 html: |- conditional comments: a conditional comment: haml: |- /[if IE] %p a html: |- internal filters: content in an 'escaped' filter: haml: |- :escaped <&"> html: "<&">" content in a 'preserve' filter: haml: |- :preserve hello %p html: |- hello

    content in a 'plain' filter: haml: |- :plain hello %p html: |- hello

    content in a 'css' filter (XHTML): haml: |- :css hello %p html: |-

    config: format: xhtml content in a 'javascript' filter (XHTML): haml: |- :javascript a(); %p html: |-

    config: format: xhtml content in a 'css' filter (HTML): haml: |- :css hello %p html: |-

    config: format: html5 content in a 'javascript' filter (HTML): haml: |- :javascript a(); %p html: |-

    config: format: html5 Ruby-style interpolation: interpolation inside inline content: haml: "%p #{var}" html: "

    value

    " optional: true locals: var: value no interpolation when escaped: haml: "%p \\#{var}" html: "

    #{var}

    " optional: true locals: var: value interpolation when the escape character is escaped: haml: "%p \\\\#{var}" html: "

    \\value

    " optional: true locals: var: value interpolation inside filtered content: haml: |- :plain #{var} interpolated: #{var} html: 'value interpolated: value' optional: true locals: var: value HTML escaping: code following '&=': haml: '&= ''<"&>''' html: "<"&>" code following '=' when escape_haml is set to true: haml: = '<"&>' html: "<"&>" config: escape_html: 'true' code following '!=' when escape_haml is set to true: haml: '!= ''<"&>''' html: <"&> config: escape_html: 'true' boolean attributes: boolean attribute with XHTML: haml: "%input(checked=true)" html: "" config: format: xhtml boolean attribute with HTML: haml: "%input(checked=true)" html: "" config: format: html5 whitespace preservation: following the '~' operator: haml: ~ "Foo\n
    Bar\nBaz
    " html: |- Foo
    Bar
    Baz
    optional: true inside a textarea tag: haml: |- %textarea hello hello html: |- inside a pre tag: haml: |- %pre hello hello html: |-
    hello
          hello
    whitespace removal: a tag with '>' appended and inline content: haml: |- %li hello %li> world %li again html: "
  • hello
  • world
  • again
  • " a tag with '>' appended and nested content: haml: |- %li hello %li> world %li again html: |-
  • hello
  • world
  • again
  • a tag with '<' appended: haml: |- %p< hello world html: |-

    hello world

    hamlit-2.11.0/test/haml/haml-spec/Rakefile0000644000175000017500000000456413574632775017665 0ustar josephjoseph$:.unshift File.expand_path('../../lib', __FILE__) require 'yaml' require 'unindent' require 'open-uri' def escape_name(name, replacer) name.gsub(/[\s\-\(\)\.\.+'\/<>&=~\!]+/, replacer) end def generate_spec(mode) spec = <<-SPEC.unindent require "minitest/autorun" require "hamlit" require "haml" # This is a spec converted by haml-spec. # See: https://github.com/haml/haml-spec class #{mode.capitalize}Test < MiniTest::Test HAML_DEFAULT_OPTIONS = { ugly: #{mode == :ugly}, escape_html: true }.freeze HAMLIT_DEFAULT_OPTIONS = { escape_html: true }.freeze def self.haml_result(haml, options, locals) Haml::Engine.new(haml, HAML_DEFAULT_OPTIONS.merge(options)).render(Object.new, locals) end def self.hamlit_result(haml, options, locals) eval Hamlit::Engine.new(haml, HAMLIT_DEFAULT_OPTIONS.merge(options)).render(Object.new, locals) end SPEC contexts = YAML.load(File.read(File.expand_path('./tests.yml', __dir__))) contexts.each_with_index do |context, index| spec += "\n" if index != 0 spec += " class #{escape_name(context[0], '').capitalize} < MiniTest::Test\n" tests = [] context[1].each do |name, test| tests << { name: name, html: test['html'], haml: test['haml'], locals: test['locals'], config: test['config'], } end spec += tests.map { |test| locals = Hash[(test[:locals] || {}).map {|x, y| [x.to_sym, y]}] options = Hash[(test[:config] || {}).map {|x, y| [x.to_sym, y]}] options[:format] = options[:format].to_sym if options[:format] generate_specify(test, locals, options, mode) }.join("\n") spec += " end\n" end spec += "end\n" File.write("#{mode}_test.rb", spec) end def generate_specify(test, locals, options, mode) <<-SPEC def test_#{escape_name(test[:name], '_')} haml = %q{#{test[:haml]}} html = %q{#{test[:html]}} locals = #{locals} options = #{options} haml_result = #{mode.capitalize}Test.haml_result(haml, options, locals) hamlit_result = #{mode.capitalize}Test.hamlit_result(haml, options, locals) assert_equal haml_result, hamlit_result end SPEC end desc 'Convert tests.yml into ugly tests' task :pretty do generate_spec(:pretty) end desc 'Convert tests.yml into ugly tests' task :ugly do generate_spec(:ugly) end hamlit-2.11.0/test/haml/haml-spec/README.md0000644000175000017500000001022313574632775017464 0ustar josephjoseph# Haml Spec # Haml Spec provides a basic suite of tests for Haml interpreters. It is intented for developers who are creating or maintaining an implementation of the [Haml](http://haml-lang.com) markup language. At the moment, there are test runners for the [original Haml](http://github.com/nex3/haml) in Ruby, [Lua Haml](http://github.com/norman/lua-haml) and the [Text::Haml](http://github.com/vti/text-haml) Perl port. Support for other versions of Haml will be added if their developers/maintainers are interested in using it. ## The Tests ## The tests are kept in JSON format for portability across languages. Each test is a JSON object with expected input, output, local variables and configuration parameters (see below). The test suite only provides tests for features which are portable, therefore no tests for script are provided, nor for external filters such as :markdown or :textile. The one major exception to this are the tests for interpolation, which you may need to modify with a regular expression to run under PHP or Perl, which require a sigil before variable names. These tests are included despite being less than 100% portable because interpolation is an important part of Haml and can be tricky to implement. These tests are flagged as "optional" so that you can avoid running them if your implementation of Haml will not support this feature. ## Running the Tests ## ### Ruby ### The Ruby test runner uses minitest, the same as the Ruby Haml implementation. To run the tests you probably only need to install `haml`, `minitest` and possibly `ruby` if your platform doesn't come with it by default. If you're using Ruby 1.8.x, you'll also need to install `json`: sudo gem install haml sudo gem install minitest # for Ruby 1.8.x; check using "ruby --version" if unsure sudo gem install json Then, running the Ruby test suite is easy: ruby ruby_haml_test.rb At the moment, running the tests with Ruby 1.8.7 fails because of issues with the JSON library. Please use 1.9.2 until this is resolved. ### Lua ### The Lua test depends on [Penlight](http://stevedonovan.github.com/Penlight/), [Telescope](http://github.com/norman/telescope), [jason4lua](http://json.luaforge.net/), and [Lua Haml](http://github.com/norman/lua-haml). Install and run `tsc lua_haml_spec.lua`. ### Getting it ### You can access the [Git repository](http://github.com/norman/haml-spec) at: git://github.com/norman/haml-spec.git Patches are *very* welcome, as are test runners for your Haml implementation. As long as any test you add run against Ruby Haml and are not redundant, I'll be very happy to add them. ### Test JSON format ### "test name" : { "haml" : "haml input", "html" : "expected html output", "result" : "expected test result", "locals" : "local vars", "config" : "config params", "optional" : true|false } * test name: This should be a *very* brief description of what's being tested. It can be used by the test runners to name test methods, or to exclude certain tests from being run. * haml: The Haml code to be evaluated. Always required. * html: The HTML output that should be generated. Required unless "result" is "error". * result: Can be "pass" or "error". If it's absent, then "pass" is assumed. If it's "error", then the goal of the test is to make sure that malformed Haml code generates an error. * locals: An object containing local variables needed for the test. * config: An object containing configuration parameters used to run the test. The configuration parameters should be usable directly by Ruby's Haml with no modification. If your implementation uses config parameters with different names, you may need to process them to make them match your implementation. If your implementation has options that do not exist in Ruby's Haml, then you should add tests for this in your implementation's test rather than here. * optional: whether or not the test is optional ## License ## This project is released under the [WTFPL](http://sam.zoy.org/wtfpl/) in order to be as usable as possible in any project, commercial or free. ## Author ## [Norman Clarke](mailto:norman@njclarke.com) hamlit-2.11.0/test/haml/haml-spec/LICENSE0000644000175000017500000000074413574632775017221 0ustar josephjoseph DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Copyright (C) 2004 Sam Hocevar Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. hamlit-2.11.0/test/haml/markaby/0000755000175000017500000000000013574632775015764 5ustar josephjosephhamlit-2.11.0/test/haml/markaby/standard.mab0000644000175000017500000000367013574632775020253 0ustar josephjosephself << '' html(:xmlns=>'http://www.w3.org/1999/xhtml', 'xml:lang'=>'en-US') do head do title "Hampton Catlin Is Totally Awesome" meta("http-equiv" => "Content-Type", :content => "text/html; charset=utf-8") end body do # You're In my house now! div :class => "header" do self << %|Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah!| self << 1 + 9 + 8 + 2 #numbers should work and this should be ignored end div(:id => "body") { self << "Quotes should be loved! Just like people!"} 120.times do |number| number end self << "Wow.|" p do self << "Holy cow " + "multiline " + "tags! " + "A pipe (|) even!" self << [1, 2, 3].collect { |n| "PipesIgnored|" } self << [1, 2, 3].collect { |n| n.to_s }.join("|") end div(:class => "silent") do foo = String.new foo << "this" foo << " shouldn't" foo << " evaluate" self << foo + " but now it should!" # Woah crap a comment! end # That was a line that shouldn't close everything. ul(:class => "really cool") do ('a'..'f').each do |a| li a end end div((@should_eval = "with this text"), :id => "combo", :class => "of_divs_with_underscore") [ 104, 101, 108, 108, 111 ].map do |byte| byte.chr end div(:class => "footer") do strong("This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works", :class => "shout") end end end hamlit-2.11.0/test/haml/template_test.rb0000644000175000017500000002274113574632775017543 0ustar josephjosephrequire 'test_helper' require 'haml/mocks/article' require 'action_pack/version' require 'hamlit/rails_template' module Haml::Filters::Test include Haml::Filters::Base def render(text) "TESTING HAHAHAHA!" end end module Hamlit::RailsHelpers def test_partial(name, locals = {}) Hamlit::Template.new { File.read(File.join(TemplateTest::TEMPLATE_PATH, "_#{name}.haml")) }.render(self, locals) end end class Egocentic def method_missing(*args) self end end class DummyController attr_accessor :logger def initialize @logger = Egocentic.new end def self.controller_path '' end def controller_path '' end end class TemplateTest < Haml::TestCase TEMPLATE_PATH = File.join(File.dirname(__FILE__), "templates") TEMPLATES = [ 'very_basic', #'standard', #'helpers', #'whitespace_handling', 'original_engine', 'list', 'helpful', 'silent_script', 'tag_parsing', #'just_stuff', #'partials', #'nuke_outer_whitespace', #'nuke_inner_whitespace', #'render_layout', #'partial_layout', 'partial_layout_erb', ] def setup @base = create_base # filters template uses :sass # Sass::Plugin.options.update(:line_comments => true, :style => :compact) end def create_base vars = { 'article' => Article.new, 'foo' => 'value one' } context = ActionView::LookupContext.new(TEMPLATE_PATH) base = ActionView::Base.new(context, vars) # This is needed by RJS in (at least) Rails 3 base.instance_variable_set(:@template, base) # This is used by form_for. # It's usually provided by ActionController::Base. def base.protect_against_forgery?; false; end def base.compiled_method_container() self.class; end base end def render(text, options = {}) return @base.render(:inline => text, :type => :haml) if options == :action_view options = options.merge(:format => :xhtml) super(text, options, @base) end def load_result(name) @result = '' File.new(File.dirname(__FILE__) + "/results/#{name}.xhtml").each_line { |l| @result += l } @result end def assert_renders_correctly(name, &render_method) old_options = Haml::Template.options.dup Haml::Template.options[:escape_html] = false render_method ||= proc { |n| @base.render(:file => n) } silence_warnings do load_result(name).split("\n").zip(render_method[name].split("\n")).each_with_index do |pair, line| message = "template: #{name}\nline: #{line}" assert_equal(pair.first, pair.last, message) end end rescue ActionView::Template::Error => e if e.message =~ /Can't run [\w:]+ filter; required (one of|file) ((?:'\w+'(?: or )?)+)(, but none were found| not found)/ puts "\nCouldn't require #{$2}; skipping a test." else raise e end ensure Haml::Template.options = old_options end def test_empty_render_should_remain_empty assert_equal('', render('')) end TEMPLATES.each do |template| define_method "test_template_should_render_correctly [template: #{template}]" do assert_renders_correctly template end end def test_templates skip TEMPLATES end def test_render_method_returning_null_with_ugly; skip @base.instance_eval do def empty nil end def render_something(&block) capture(self, &block) end end content_to_render = "%h1 This is part of the broken view.\n= render_something do |thing|\n = thing.empty do\n = 'test'" result = render(content_to_render, :ugly => true) expected_result = "

    This is part of the broken view.

    \n" assert_equal(expected_result, result) end def test_simple_rendering_with_ugly skip assert_haml_ugly("%p test\n= capture { 'foo' }") end def test_templates_should_render_correctly_with_render_proc; skip assert_renders_correctly("standard") do |name| engine = Hamlit::HamlEngine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :format => :xhtml) engine.render_proc(@base).call end end def test_templates_should_render_correctly_with_def_method; skip assert_renders_correctly("standard") do |name| engine = Haml::HamlEngine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :format => :xhtml) engine.def_method(@base, "render_standard") @base.render_standard end end def test_instance_variables_should_work_inside_templates @base.instance_variable_set(:@content_for_layout, 'something') assert_haml_ugly("%p= @content_for_layout", scope: @base) @base.instance_eval("@author = 'Hampton Catlin'") assert_haml_ugly(".author= @author", scope: @base) @base.instance_eval("@author = 'Hampton'") assert_haml_ugly("= @author", scope: @base) @base.instance_eval("@author = 'Catlin'") assert_haml_ugly("= @author", scope: @base) end def test_instance_variables_should_work_inside_attributes skip @base.instance_eval("@author = 'hcatlin'") assert_haml_ugly("%p{:class => @author} foo") end def test_template_renders_should_eval assert_equal("2\n", render("= 1+1")) end def test_haml_options; skip old_options = Haml::Template.options.dup Haml::Template.options[:suppress_eval] = true old_base, @base = @base, create_base assert_renders_correctly("eval_suppressed") ensure skip @base = old_base Haml::Template.options = old_options end def test_with_output_buffer_with_ugly; skip assert_equal(< true))

    foo baz

    HTML %p foo -# Parenthesis required due to Rails 3.0 deprecation of block helpers -# that return strings. - (with_output_buffer do bar = "foo".gsub(/./) do |s| - "flup" - end) baz HAML end def test_exceptions_should_work_correctly; skip begin render("- raise 'oops!'") rescue Exception => e assert_equal("oops!", e.message) assert_match(/^\(haml\):1/, e.backtrace[0]) else assert false end template = < e assert_match(/^\(haml\):5/, e.backtrace[0]) else assert false end end def test_form_builder_label_with_block; skip output = render(< :article, :html => {:class => nil, :id => nil}, :url => '' do |f| = f.label :title do Block content HAML fragment = Nokogiri::HTML.fragment output assert_equal "Block content", fragment.css('form label').first.content.strip end ## XSS Protection Tests def test_escape_html_option_set; skip assert Haml::Template.options[:escape_html] end def test_xss_protection; skip assert_equal("Foo & Bar\n", render('= "Foo & Bar"', :action_view)) end def test_xss_protection_with_safe_strings; skip assert_equal("Foo & Bar\n", render('= Haml::Util.html_safe("Foo & Bar")', :action_view)) end def test_xss_protection_with_bang; skip assert_haml_ugly('!= "Foo & Bar"', :action_view) end def test_xss_protection_in_interpolation; skip assert_equal("Foo & Bar\n", render('Foo #{"&"} Bar', :action_view)) end def test_xss_protection_in_attributes; skip assert_equal("
    \n", render('%div{ "data-html" => "bar" }', :action_view)) end def test_xss_protection_in_attributes_with_safe_strings; skip assert_equal("
    \n", render('%div{ "data-html" => "bar".html_safe }', :action_view)) end def test_xss_protection_with_bang_in_interpolation; skip assert_haml_ugly('! Foo #{"&"} Bar', :action_view) end def test_xss_protection_with_safe_strings_in_interpolation; skip assert_equal("Foo & Bar\n", render('Foo #{Haml::Util.html_safe("&")} Bar', :action_view)) end def test_xss_protection_with_mixed_strings_in_interpolation; skip assert_equal("Foo & Bar & Baz\n", render('Foo #{Haml::Util.html_safe("&")} Bar #{"&"} Baz', :action_view)) end def test_rendered_string_is_html_safe; skip assert(render("Foo").html_safe?) end def test_rendered_string_is_html_safe_with_action_view assert(render("Foo", :action_view).html_safe?) end def test_xss_html_escaping_with_non_strings assert_haml_ugly("= html_escape(4)") end def test_xss_protection_with_concat; skip assert_equal("Foo & Bar", render('- concat "Foo & Bar"', :action_view)) end def test_xss_protection_with_concat_with_safe_string; skip assert_equal("Foo & Bar", render('- concat(Haml::Util.html_safe("Foo & Bar"))', :action_view)) end def test_xss_protection_with_safe_concat; skip assert_equal("Foo & Bar", render('- safe_concat "Foo & Bar"', :action_view)) end ## Regression def test_xss_protection_with_nested_haml_tag; skip assert_equal(<
    • Content!
    HTML - haml_tag :div do - haml_tag :ul do - haml_tag :li, "Content!" HAML end if defined?(ActionView::Helpers::PrototypeHelper) def test_rjs assert_equal(< Foo %p %p %q{:a => 1 + 1}> Foo %p %p %q> Foo %p %p %q{:a => 1 + 1}> Foo %p %p %q> = "Foo" %p %p %q{:a => 1 + 1}> = "Foo" %p %p %q>= "Foo" %p %p %q{:a => 1 + 1}>= "Foo" %p %p %q> = "Foo\nBar" %p %p %q{:a => 1 + 1}> = "Foo\nBar" %p %p %q>= "Foo\nBar" %p %p %q{:a => 1 + 1}>= "Foo\nBar" %p %p - tab_up foo %q> Foo bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}> Foo bar - tab_down %p %p - tab_up foo %q> Foo bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}> Foo bar - tab_down %p %p - tab_up foo %q> = "Foo" bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}> = "Foo" bar - tab_down %p %p - tab_up foo %q>= "Foo" bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}>= "Foo" bar - tab_down %p %p - tab_up foo %q> = "Foo\nBar" bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}> = "Foo\nBar" bar - tab_down %p %p - tab_up foo %q>= "Foo\nBar" bar - tab_down %p %p - tab_up foo %q{:a => 1 + 1}>= "Foo\nBar" bar - tab_down %p %p %q> %p %p %q>/ %p %p %q{:a => 1 + 1}> %p %p %q{:a => 1 + 1}>/ hamlit-2.11.0/test/haml/templates/action_view.haml0000644000175000017500000000336513574632775021515 0ustar josephjoseph!!! %html{html_attrs} %head %title Hampton Catlin Is Totally Awesome %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} %body %h1 This is very much like the standard template, except that it has some ActionView-specific stuff. It's only used for benchmarking. .crazy_partials= render :partial => 'templates/av_partial_1' / You're In my house now! .header Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! = 1 + 9 + 8 + 2 #numbers should work and this should be ignored #body= " Quotes should be loved! Just like people!" - 120.times do |number| - number Wow.| %p = "Holy cow " + | "multiline " + | "tags! " + | "A pipe (|) even!" | = [1, 2, 3].collect { |n| "PipesIgnored|" } = [1, 2, 3].collect { |n| | n.to_s | }.join("|") | %div.silent - foo = String.new - foo << "this" - foo << " shouldn't" - foo << " evaluate" = foo + " but now it should!" -# Woah crap a comment! -# That was a line that shouldn't close everything. %ul.really.cool - ('a'..'f').each do |a| %li= a #combo.of_divs_with_underscore= @should_eval = "with this text" = [ 104, 101, 108, 108, 111 ].map do |byte| - byte.chr .footer %strong.shout= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works" hamlit-2.11.0/test/haml/templates/_layout.erb0000644000175000017500000000003313574632775020476 0ustar josephjosephBefore <%= yield -%> After hamlit-2.11.0/test/haml/templates/partialize.haml0000644000175000017500000000004113574632775021336 0ustar josephjoseph= render :file => "#{name}.haml" hamlit-2.11.0/test/haml/templates/with_bom.haml0000644000175000017500000000000713574632775021004 0ustar josephjosephBOMGhamlit-2.11.0/test/haml/templates/_partial.haml0000644000175000017500000000015113574632775020767 0ustar josephjoseph%p @foo = = @foo - @foo = 'value three' == Toplevel? #{haml_buffer.toplevel?} %p @foo = = @foo hamlit-2.11.0/test/haml/templates/silent_script.haml0000644000175000017500000000126613574632775022066 0ustar josephjoseph%div %h1 I can count! - (1..20).each do |i| = i %h1 I know my ABCs! %ul - ('a'..'z').each do |i| %li= i %h1 I can catch errors! - begin - raise "foo" - rescue RuntimeError => e = "Oh no! \"#{e}\" happened!" %p "false" is: - if false = "true" - else = "false" - if true - 5.times do |i| - if i % 2 == 1 Odd! - else Even! - unless true Testing else indent - case 1 - when 2 Also testing else indent - else = "This can't happen!" - 13 | .foo %strong foobar - 5.times | do | |a| | %strong= a .test - "foo | bar | baz" | %p boom hamlit-2.11.0/test/haml/templates/_av_partial_1.haml0000644000175000017500000000033513574632775021701 0ustar josephjoseph%h2 This is a pretty complicated partial .partial %p It has several nested partials, %ul - 5.times do %li %strong Partial: - @nesting = 5 = render :partial => 'templates/av_partial_2'hamlit-2.11.0/test/haml/templates/_text_area.haml0000644000175000017500000000013613574632775021312 0ustar josephjoseph.text_area_test_area ~ "" = "" hamlit-2.11.0/test/haml/templates/_av_partial_2_ugly.haml0000644000175000017500000000027513574632775022745 0ustar josephjoseph- @nesting -= 1 .partial{:level => @nesting} %h3 This is a crazy deep-nested partial. %p== Nesting level #{@nesting} = render :partial => 'templates/av_partial_2_ugly' if @nesting > 0hamlit-2.11.0/test/haml/templates/_av_partial_2.haml0000644000175000017500000000027013574632775021700 0ustar josephjoseph- @nesting -= 1 .partial{:level => @nesting} %h3 This is a crazy deep-nested partial. %p== Nesting level #{@nesting} = render :partial => 'templates/av_partial_2' if @nesting > 0hamlit-2.11.0/test/haml/templates/breakage.haml0000644000175000017500000000017513574632775020743 0ustar josephjoseph%p %h1 Hello! = "lots of lines" - raise "Oh no!" %p this is after the exception %strong yes it is! ho ho ho. hamlit-2.11.0/test/haml/templates/_av_partial_1_ugly.haml0000644000175000017500000000034213574632775022737 0ustar josephjoseph%h2 This is a pretty complicated partial .partial %p It has several nested partials, %ul - 5.times do %li %strong Partial: - @nesting = 5 = render :partial => 'templates/av_partial_2_ugly'hamlit-2.11.0/test/haml/templates/helpful.haml0000644000175000017500000000046513574632775020643 0ustar josephjoseph%div[@article] %h1= @article.title %div= @article.body #id[@article] id .class[@article] class #id.class[@article] id class %div{:class => "article full"}[@article]= "boo" %div{'class' => "article full"}[@article]= "moo" %div.articleFull[@article]= "foo" %span[@not_a_real_variable_and_will_be_nil] Boo hamlit-2.11.0/test/haml/templates/original_engine.haml0000644000175000017500000000071413574632775022332 0ustar josephjoseph!!! %html %head %title Stop. haml time #content %h1 This is a title! %p Lorem ipsum dolor sit amet, consectetur adipisicing elit %p{:class => 'foo'} Cigarettes! %h2 Man alive! %ul.things %li Slippers %li Shoes %li Bathrobe %li Coffee %pre This is some text that's in a pre block! Let's see what happens when it's rendered! What about now, since we're on a new line? hamlit-2.11.0/test/haml/templates/very_basic.haml0000644000175000017500000000003213574632775021320 0ustar josephjoseph!!! %html %head %body hamlit-2.11.0/test/haml/templates/list.haml0000644000175000017500000000013513574632775020151 0ustar josephjoseph!Not a Doctype! %ul %li a %li b %li c %li d %li e %li f %li g %li h %li i hamlit-2.11.0/test/haml/templates/_text_area_helper.html.haml0000644000175000017500000000014213574632775023611 0ustar josephjoseph- defined?(text_area_helper) and nil # silence a warning .foo .bar = text_area :post, :body hamlit-2.11.0/test/haml/templates/standard_ugly.haml0000644000175000017500000000317413574632775022044 0ustar josephjoseph!!! %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en-US", "lang" => "en-US"} %head %title Hampton Catlin Is Totally Awesome %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} %body / You're In my house now! .header Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! = 1 + 9 + 8 + 2 #numbers should work and this should be ignored #body= " Quotes should be loved! Just like people!" - 120.times do |number| = number Wow.| %p{:code => 1 + 2} = "Holy cow " + | "multiline " + | "tags! " + | "A pipe (|) even!" | = [1, 2, 3].collect { |n| "PipesIgnored|" }.join = [1, 2, 3].collect { |n| | n.to_s | }.join("|") | - bar = 17 %div.silent{:foo => bar} - foo = String.new - foo << "this" - foo << " shouldn't" - foo << " evaluate" = foo + " but now it should!" -# Woah crap a comment! -# That was a line that shouldn't close everything. %ul.really.cool - ('a'..'f').each do |a| %li= a #combo.of_divs_with_underscore= @should_eval = "with this text" = "foo".each_line do |line| - nil .footer %strong.shout= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works" hamlit-2.11.0/test/haml/templates/partial_layout_erb.erb0000644000175000017500000000020613574632775022705 0ustar josephjoseph

    Partial layout used with for block:

    <%= render :layout => 'layout_for_partial' do -%> Some content within a layout <% end %> hamlit-2.11.0/test/haml/templates/standard.haml0000644000175000017500000000317413574632775021004 0ustar josephjoseph!!! %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en-US", "lang" => "en-US"} %head %title Hampton Catlin Is Totally Awesome %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} %body / You're In my house now! .header Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! = 1 + 9 + 8 + 2 #numbers should work and this should be ignored #body= " Quotes should be loved! Just like people!" - 120.times do |number| = number Wow.| %p{:code => 1 + 2} = "Holy cow " + | "multiline " + | "tags! " + | "A pipe (|) even!" | = [1, 2, 3].collect { |n| "PipesIgnored|" }.join = [1, 2, 3].collect { |n| | n.to_s | }.join("|") | - bar = 17 %div.silent{:foo => bar} - foo = String.new - foo << "this" - foo << " shouldn't" - foo << " evaluate" = foo + " but now it should!" -# Woah crap a comment! -# That was a line that shouldn't close everything. %ul.really.cool - ('a'..'f').each do |a| %li= a #combo.of_divs_with_underscore= @should_eval = "with this text" = "foo".each_line do |line| - nil .footer %strong.shout= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works" hamlit-2.11.0/test/haml/templates/whitespace_handling.haml0000644000175000017500000000645713574632775023213 0ustar josephjoseph#whitespace_test = test_partial "text_area", :value => "Oneline" = test_partial "text_area", :value => "Two\nlines" ~ test_partial "text_area", :value => "Oneline" ~ test_partial "text_area", :value => "Two\nlines" #flattened~ test_partial "text_area", :value => "Two\nlines" .hithere ~ "Foo bar" ~ "
    foo bar
    " ~ "
    foo\nbar
    " %p~ "
    foo\nbar
    " %p~ "foo\nbar" .foo ~ 13 ~ "".each_line do |l| - haml_concat l.strip #whitespace_test = test_partial "text_area", :value => "Oneline" = test_partial "text_area", :value => "Two\nlines" = find_and_preserve test_partial("text_area", :value => "Oneline") = find_and_preserve test_partial("text_area", :value => "Two\nlines") #flattened= find_and_preserve test_partial("text_area", :value => "Two\nlines") .hithere = find_and_preserve("Foo bar") = find_and_preserve("
    foo bar
    ") = find_and_preserve("
    foo\nbar
    ") %p= find_and_preserve("
    foo\nbar
    ") %p= find_and_preserve("foo\nbar") %pre :preserve ___ ,o88888 ,o8888888' ,:o:o:oooo. ,8O88Pd8888" ,.::.::o:ooooOoOoO. ,oO8O8Pd888'" ,.:.::o:ooOoOoOO8O8OOo.8OOPd8O8O" , ..:.::o:ooOoOOOO8OOOOo.FdO8O8" , ..:.::o:ooOoOO8O888O8O,COCOO" , . ..:.::o:ooOoOOOO8OOOOCOCO" . ..:.::o:ooOoOoOO8O8OCCCC"o . ..:.::o:ooooOoCoCCC"o:o . ..:.::o:o:,cooooCo"oo:o: ` . . ..:.:cocoooo"'o:o:::' .` . ..::ccccoc"'o:o:o:::' :.:. ,c:cccc"':.:.:.:.:.' ..:.:"'`::::c:"'..:.:.:.:.:.' http://www.chris.com/ASCII/ ...:.'.:.::::"' . . . . .' .. . ....:."' ` . . . '' . . . ...."' .. . ."' -hrr- . It's a planet! %strong This shouldn't be bold! %strong This should! %textarea :preserve ___ ___ ___ ___ /\__\ /\ \ /\__\ /\__\ /:/ / /::\ \ /::| | /:/ / /:/__/ /:/\:\ \ /:|:| | /:/ / /::\ \ ___ /::\~\:\ \ /:/|:|__|__ /:/ / /:/\:\ /\__\ /:/\:\ \:\__\ /:/ |::::\__\ /:/__/ \/__\:\/:/ / \/__\:\/:/ / \/__/~~/:/ / \:\ \ \::/ / \::/ / /:/ / \:\ \ /:/ / /:/ / /:/ / \:\ \ /:/ / /:/ / /:/ / \:\__\ \/__/ \/__/ \/__/ \/__/ Many thanks to http://www.network-science.de/ascii/ %strong indeed! .foo = find_and_preserve(13) %pre :preserve __ ______ __ ______ .----.| |--.|__ |.----.| |--..--------.| __ | | __|| ||__ || __|| < | || __ | |____||__|__||______||____||__|__||__|__|__||______| %pre :preserve foo bar hamlit-2.11.0/test/haml/templates/partial_layout.haml0000644000175000017500000000016613574632775022233 0ustar josephjoseph%h1 Partial layout used with for block: = render :layout => 'layout_for_partial' do %p Some content within a layout hamlit-2.11.0/test/haml/templates/partials.haml0000644000175000017500000000020513574632775021013 0ustar josephjoseph- @foo = 'value one' %p @foo = = @foo - @foo = 'value two' %p @foo = = @foo = test_partial "partial" %p @foo = = @foo hamlit-2.11.0/test/haml/templates/action_view_ugly.haml0000644000175000017500000000337213574632775022553 0ustar josephjoseph!!! %html{html_attrs} %head %title Hampton Catlin Is Totally Awesome %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} %body %h1 This is very much like the standard template, except that it has some ActionView-specific stuff. It's only used for benchmarking. .crazy_partials= render :partial => 'templates/av_partial_1_ugly' / You're In my house now! .header Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! = 1 + 9 + 8 + 2 #numbers should work and this should be ignored #body= " Quotes should be loved! Just like people!" - 120.times do |number| - number Wow.| %p = "Holy cow " + | "multiline " + | "tags! " + | "A pipe (|) even!" | = [1, 2, 3].collect { |n| "PipesIgnored|" } = [1, 2, 3].collect { |n| | n.to_s | }.join("|") | %div.silent - foo = String.new - foo << "this" - foo << " shouldn't" - foo << " evaluate" = foo + " but now it should!" -# Woah crap a comment! -# That was a line that shouldn't close everything. %ul.really.cool - ('a'..'f').each do |a| %li= a #combo.of_divs_with_underscore= @should_eval = "with this text" = [ 104, 101, 108, 108, 111 ].map do |byte| - byte.chr .footer %strong.shout= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works" hamlit-2.11.0/test/haml/templates/helpers.haml0000644000175000017500000000226113574632775020642 0ustar josephjoseph= h("&&&&&&&&&&&") # This is an ActionView Helper... should load - foo = capture do # This ActionView Helper is designed for ERB, but should work with haml %div %p.title Title %p.text Woah this is really crazy I mean wow, man. - 3.times do = foo %p foo - tab_up %p reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong - tab_down .woah #funky = capture_haml do %div %h1 Big! %p Small / Invisible = capture do .dilly %p foo %h1 bar = surround '(', ')' do %strong parentheses! = precede '*' do %span.small Not really click = succeed '.' do %a{:href=>"thing"} here %p baz - haml_buffer.tabulation = 10 %p boom - concat "foo\n" - haml_buffer.tabulation = 0 = list_of({:google => 'http://www.google.com'}) do |name, link| %a{ :href => link }= name %p - haml_concat "foo" %div - haml_concat "bar" - haml_concat "boom" baz - haml_concat "boom, again" - haml_tag :table do - haml_tag :tr do - haml_tag :td, {:class => 'cell'} do - haml_tag :strong, "strong!" - haml_concat "data" - haml_tag :td do - haml_concat "more_data" - haml_tag :hr - haml_tag :div, '' hamlit-2.11.0/test/haml/templates/eval_suppressed.haml0000644000175000017500000000021313574632775022377 0ustar josephjoseph= "not me!" = "nor me!" - haml_concat "not even me!" %p= "NO!" %p~ "UH-UH!" %h1 Me! #foo %p#bar All %br/ %p.baz This Should render hamlit-2.11.0/test/haml/templates/render_layout.haml0000644000175000017500000000005113574632775022047 0ustar josephjoseph= render :layout => 'layout' do During hamlit-2.11.0/test/haml/templates/tag_parsing.haml0000644000175000017500000000041513574632775021475 0ustar josephjoseph%div.tags %foo 1 %FOO 2 %fooBAR 3 %fooBar 4 %foo_bar 5 %foo-bar 6 %foo:bar 7 %foo.bar 8 %fooBAr_baz:boom_bar 9 %foo13 10 %foo2u 11 %div.classes %p.foo.bar#baz#boom .fooBar a .foo-bar b .foo_bar c .FOOBAR d .foo16 e .123 f .foo2u g hamlit-2.11.0/test/haml/templates/nuke_inner_whitespace.haml0000644000175000017500000000046413574632775023554 0ustar josephjoseph%p %q< Foo %p %q{:a => 1 + 1}< Foo %p %q<= "Foo\nBar" %p %q{:a => 1 + 1}<= "Foo\nBar" %p %q< Foo Bar %p %q{:a => 1 + 1}< Foo Bar %p %q< %div Foo Bar %p %q{:a => 1 + 1}< %div Foo Bar -# Regression test %p %q<= "foo" %q{:a => 1 + 1} bar hamlit-2.11.0/test/haml/templates/content_for_layout.haml0000644000175000017500000000012513574632775023112 0ustar josephjoseph!!! %html %head %body #yieldy = yield :layout #nosym = yield hamlit-2.11.0/test/haml/templates/_layout_for_partial.haml0000644000175000017500000000007713574632775023241 0ustar josephjoseph.partial-layout %h2 This is inside a partial layout = yieldhamlit-2.11.0/test/haml/templates/just_stuff.haml0000644000175000017500000000325513574632775021400 0ustar josephjoseph!!! XML !!! XML ISO-8859-1 !!! XML UtF-8 Foo bar !!! !!! 1.1 !!! 1.1 Strict !!! Strict foo bar !!! FRAMESET %strong{:apos => "Foo's bar!"} Boo! == Embedded? false! == Embedded? #{true}! - embedded = true == Embedded? #{embedded}! == Embedded? #{"twice! #{true}"}! == Embedded? #{"one"} af"t"er #{"another"}! %p== Embedded? false! %p== Embedded? #{true}! - embedded = true %p== Embedded? #{embedded}! %p== Embedded? #{"twice! #{true}"}! %p== Embedded? #{"one"} af"t"er #{"another"}! = "stuff followed by whitespace" - if true %strong block with whitespace %p \Escape \- character \%p foo \yee\ha \ don't lstrip me / Short comment / This is a block comment cool, huh? %strong there can even be sub-tags! = "Or script!" -# Haml comment -# Nested Haml comment - raise 'dead' %p{ :class => "" } class attribute should appear! %p{ :gorbachev => nil } this attribute shouldn't appear /[if lte IE6] conditional comment! /[if gte IE7] %p Block conditional comment %div %h1 Cool, eh? /[if gte IE5.2] Woah a period. = "test" | "test" | -# Hard tabs shouldn't throw errors. - case :foo - when :bar %br Blah - when :foo %br - case :foo - when :bar %meta{ :foo => 'blah'} - when :foo %meta{ :foo => 'bar'} %img %hr %link %script Inline content %br Nested content %p.foo{:class => true ? 'bar' : 'baz'}[@article] Blah %p.foo{:class => false ? 'bar' : ''}[@article] Blah %p.foo{:class => %w[bar baz]}[@article] Blah %p.qux{:class => 'quux'}[@article] Blump %p#foo{:id => %w[bar baz]}[@article] Whee == #{"Woah inner quotes"} %p.dynamic_quote{:quotes => "single '", :dyn => 1 + 2} %p.dynamic_self_closing{:dyn => 1 + 2}/ %body :plain hello %div %img hamlit-2.11.0/test/haml/filters_test.rb0000644000175000017500000002032113574632775017370 0ustar josephjosephrequire 'test_helper' class FiltersTest < Haml::TestCase test "should be registered as filters when including Hamlit::Filters::Base" do; skip begin refute Hamlit::Filters.defined.has_key? "bar" Module.new {def self.name; "Foo::Bar"; end; include Hamlit::Filters::Base} assert Hamlit::Filters.defined.has_key? "bar" ensure Hamlit::Filters.remove_filter "Bar" end end test "should raise error when attempting to register a defined Tilt filter" do; skip begin assert_raises RuntimeError do 2.times do Hamlit::Filters.register_tilt_filter "Foo" end end ensure Hamlit::Filters.remove_filter "Foo" end end test "should raise error when a Tilt filters dependencies are unavailable for extension" do; skip begin assert_raises Hamlit::Error do # ignore warnings from Tilt silence_warnings do Hamlit::Filters.register_tilt_filter "Textile" Hamlit::Filters.defined["textile"].template_class end end ensure Hamlit::Filters.remove_filter "Textile" end end test "should raise error when a Tilt filters dependencies are unavailable for filter without extension" do; skip begin assert_raises Hamlit::Error do Hamlit::Filters.register_tilt_filter "Maruku" Hamlit::Filters.defined["maruku"].template_class end ensure Hamlit::Filters.remove_filter "Maruku" end end test "should raise informative error about Maruku being moved to haml-contrib" do; skip begin render(":maruku\n # foo") flunk("Should have raised error with message about the haml-contrib gem.") rescue Hamlit::Error => e assert_equal e.message, Hamlit::Error.message(:install_haml_contrib, "maruku") end end test "should raise informative error about Textile being moved to haml-contrib" do; skip begin render(":textile\n h1. foo") flunk("Should have raised error with message about the haml-contrib gem.") rescue Hamlit::Error => e assert_equal e.message, Hamlit::Error.message(:install_haml_contrib, "textile") end end test "should respect escaped newlines and interpolation" do assert_haml_ugly(":plain\n \\n\#{""}") end test "should process an filter with no content" do assert_equal("\n", render(':plain')) end test "should be compatible with ugly mode" do expectation = "foo\n" assert_equal(expectation, render(":plain\n foo")) end test "should pass options to Tilt filters that precompile" do; skip begin orig_erb_opts = Hamlit::Filters::Erb.options haml = ":erb\n <%= 'foo' %>" refute_match('test_var', Haml::Engine.new(haml).compiler.precompiled) Hamlit::Filters::Erb.options = {:outvar => 'test_var'} assert_match('test_var', Haml::Engine.new(haml).compiler.precompiled) ensure Hamlit::Filters::Erb.options = orig_erb_opts end end test "should pass options to Tilt filters that don't precompile" do; skip begin filter = Class.new(Tilt::Template) do def self.name "Foo" end def prepare @engine = {:data => data, :options => options} end def evaluate(scope, locals, &block) @output = @engine[:options].to_a.join end end Hamlit::Filters.register_tilt_filter "Foo", :template_class => filter Hamlit::Filters::Foo.options[:foo] = "bar" haml = ":foo" assert_equal "foobar\n", render(haml) ensure Hamlit::Filters.remove_filter "Foo" end end test "interpolated code should be escaped if escape_html is set" do; skip assert_haml_ugly(":plain\n \#{''}") end end if RUBY_ENGINE != 'truffleruby' # truffleruby does not implement Ripper.lex class ErbFilterTest < Haml::TestCase test "multiline expressions should work" do; skip assert_haml_ugly(%Q{:erb\n <%= "foo" +\n "bar" +\n "baz" %>}) end test "should evaluate in the same context as Haml" do; skip haml = ":erb\n <%= foo %>" html = "bar\n" scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding} assert_equal(html, render(haml, :scope => scope)) end test "should use Rails's XSS safety features" do; skip assert_equal("<img>\n", render(":erb\n <%= '' %>")) assert_equal("\n", render(":erb\n <%= ''.html_safe %>")) end end class JavascriptFilterTest < Haml::TestCase test "should interpolate" do; skip scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding} haml = ":javascript\n \#{foo}" html = render(haml, :scope => scope) assert_match(/bar/, html) end test "should never HTML-escape non-interpolated ampersands" do; skip html = "\n" haml = %Q{:javascript\n & < > \#{"&"}} assert_equal(html, render(haml, :escape_html => true)) end test "should not include type in HTML 5 output" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5)) end test "should always include CDATA when format is xhtml" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :xhtml, :cdata => false)) end test "should omit CDATA when cdata option is false" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => false)) end test "should include CDATA when cdata option is true" do; skip html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => true)) end test "should default to no CDATA when format is html5" do haml = ":javascript\n foo bar" out = render(haml, :format => :html5) refute_match('//', out) end end class CSSFilterTest < Haml::TestCase test "should wrap output in CDATA and a CSS tag when output is XHTML" do html = "\n" haml = ":css\n foo" assert_equal(html, render(haml, :format => :xhtml)) end test "should not include type in HTML 5 output" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5)) end test "should always include CDATA when format is xhtml" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :xhtml, :cdata => false)) end test "should omit CDATA when cdata option is false" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => false)) end test "should include CDATA when cdata option is true" do; skip html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => true)) end test "should default to no CDATA when format is html5" do haml = ":css\n foo bar" out = render(haml, :format => :html5) refute_match('', out) end end class CDATAFilterTest < Haml::TestCase test "should wrap output in CDATA tag" do html = "\n" haml = ":cdata\n foo" assert_equal(html, render(haml)) end end class EscapedFilterTest < Haml::TestCase test "should escape ampersands" do html = "&\n" haml = ":escaped\n &" assert_equal(html, render(haml)) end end class RubyFilterTest < Haml::TestCase test "can write to haml_io" do; skip haml = ":ruby\n haml_io.puts 'hello'\n" html = "hello\n" assert_equal(html, render(haml)) end test "haml_io appends to output" do; skip haml = "hello\n:ruby\n haml_io.puts 'hello'\n" html = "hello\nhello\n" assert_equal(html, render(haml)) end test "can create local variables" do; skip haml = ":ruby\n a = 7\n=a" html = "7\n" assert_equal(html, render(haml)) end end hamlit-2.11.0/test/haml/erb/0000755000175000017500000000000013574632775015106 5ustar josephjosephhamlit-2.11.0/test/haml/erb/_av_partial_1.erb0000644000175000017500000000044313574632775020302 0ustar josephjoseph

    This is a pretty complicated partial

    It has several nested partials,

      <% 5.times do %>
    • Partial: <% @nesting = 5 %> <%= render :partial => 'erb/av_partial_2' %> <% end %>
    hamlit-2.11.0/test/haml/erb/standard.erb0000644000175000017500000000371713574632775017410 0ustar josephjoseph Hampton Catlin Is Totally Awesome
    Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! <%= 1 + 9 + 8 + 2 %> <%# numbers should work and this should be ignored %>
    <% 120.times do |number| -%> <%= number %> <% end -%>
    <%= " Quotes should be loved! Just like people!" %>
    Wow.

    <%= "Holy cow " + "multiline " + "tags! " + "A pipe (|) even!" %> <%= [1, 2, 3].collect { |n| "PipesIgnored|" }.join %> <%= [1, 2, 3].collect { |n| n.to_s }.join("|") %>

    <% bar = 17 %>
    <% foo = String.new foo << "this" foo << " shouldn't" foo << " evaluate" %> <%= foo + "but now it should!" %> <%# Woah crap a comment! %>