├── .gitignore ├── Gemfile ├── README.md ├── Rakefile ├── bin └── haml2slim ├── haml2slim.gemspec ├── lib ├── haml2slim.rb └── haml2slim │ ├── command.rb │ ├── converter.rb │ └── version.rb └── test ├── fixtures ├── _av_partial_1.haml ├── _av_partial_1_ugly.haml ├── _av_partial_2.haml ├── _av_partial_2_ugly.haml ├── _layout_for_partial.haml ├── _partial.haml ├── _text_area.haml ├── breakage.haml ├── content_for_layout.haml ├── eval_suppressed.haml ├── helpers.haml ├── nuke_inner_whitespace.haml ├── nuke_outer_whitespace.haml ├── original_engine.haml ├── partial_layout.haml ├── partialize.haml ├── partials.haml ├── render_layout.haml ├── silent_script.haml ├── standard.haml ├── tag_parsing.haml └── very_basic.haml ├── helper.rb └── test_haml2slim.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/ 2 | *.gem 3 | .bundle 4 | Gemfile.lock 5 | .rvmrc 6 | .idea -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haml2Slim 2 | 3 | [Haml](https://github.com/nex3/haml) to [Slim](https://github.com/stonean/slim) converter. 4 | 5 | ## Limitation 6 | 7 | Due to the complex logic behind both Haml's and Slim's parsers, there is currently no way of reliably converting between Haml and Slim templates. 8 | 9 | `Haml2Slim` only serves as a preliminary tool for templates conversion. You should __always__ manually verify the converted templates. 10 | 11 | ## Usage 12 | 13 | You may convert files using the included executable `haml2slim`. 14 | 15 | # haml2slim -h 16 | 17 | Usage: haml2slim INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options] 18 | --trace Show a full traceback on error 19 | -d, --delete Delete HAML files 20 | -h, --help Show this message 21 | -v, --version Print version 22 | 23 | Alternatively, to convert files or strings on the fly in your application, you may do so by calling `Haml2Slim.convert!`. 24 | 25 | ## License 26 | 27 | This project is released under the MIT license. 28 | 29 | ## Author 30 | 31 | [Fred Wu](https://github.com/fredwu) 32 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | begin 2 | require 'bundler' 3 | Bundler::GemHelper.install_tasks 4 | rescue Exception => e 5 | end 6 | 7 | require 'rake/testtask' 8 | 9 | Rake::TestTask.new(:test) do |t| 10 | t.libs << 'lib' << 'test' 11 | t.pattern = 'test/**/test_*.rb' 12 | t.verbose = true 13 | end 14 | 15 | task :default => 'test' 16 | -------------------------------------------------------------------------------- /bin/haml2slim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $:.unshift File.dirname(__FILE__) + '/../lib' 4 | require 'haml2slim/command' 5 | 6 | cmd = Haml2Slim::Command.new(ARGV) 7 | cmd.run 8 | -------------------------------------------------------------------------------- /haml2slim.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path("../lib/haml2slim/version", __FILE__) 3 | require "date" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "haml2slim" 7 | s.version = Haml2Slim::VERSION 8 | s.date = Date.today.to_s 9 | s.authors = ["Fred Wu"] 10 | s.email = ["ifredwu@gmail.com"] 11 | s.summary = %q{Haml to Slim converter.} 12 | s.description = %q{Convert Haml templates to Slim templates.} 13 | s.homepage = %q{http://github.com/fredwu/haml2slim} 14 | s.extra_rdoc_files = ["README.md"] 15 | s.rdoc_options = ["--charset=UTF-8"] 16 | s.require_paths = ["lib"] 17 | s.files = `git ls-files -- lib/* bin/* README.md`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | 20 | s.add_dependency "haml", [">= 3.0"] 21 | s.add_dependency "nokogiri" 22 | s.add_dependency "ruby_parser" 23 | s.add_development_dependency 'rake' 24 | s.add_development_dependency "slim", [">= 1.0.0"] 25 | end 26 | -------------------------------------------------------------------------------- /lib/haml2slim.rb: -------------------------------------------------------------------------------- 1 | require 'haml2slim/version' 2 | require 'haml2slim/converter' 3 | 4 | module Haml2Slim 5 | def self.convert!(input) 6 | Converter.new(input) 7 | end 8 | end -------------------------------------------------------------------------------- /lib/haml2slim/command.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | require 'haml2slim' 3 | 4 | module Haml2Slim 5 | class Command 6 | def initialize(args) 7 | @args = args 8 | @options = {} 9 | end 10 | 11 | def run 12 | @opts = OptionParser.new(&method(:set_opts)) 13 | @opts.parse!(@args) 14 | process! 15 | exit 0 16 | rescue Exception => ex 17 | raise ex if @options[:trace] || SystemExit === ex 18 | $stderr.print "#{ex.class}: " if ex.class != RuntimeError 19 | $stderr.puts ex.message 20 | $stderr.puts ' Use --trace for backtrace.' 21 | exit 1 22 | end 23 | 24 | protected 25 | 26 | def set_opts(opts) 27 | opts.banner = "Usage: haml2slim INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]" 28 | 29 | opts.on('--trace', :NONE, 'Show a full traceback on error') do 30 | @options[:trace] = true 31 | end 32 | 33 | opts.on_tail('-h', '--help', 'Show this message') do 34 | puts opts 35 | exit 36 | end 37 | 38 | opts.on_tail('-v', '--version', 'Print version') do 39 | puts "Haml2Slim #{Haml2Slim::VERSION}" 40 | exit 41 | end 42 | 43 | opts.on('-d', '--delete', 'Delete HAML files') do 44 | @options[:delete] = true 45 | end 46 | end 47 | 48 | def process! 49 | args = @args.dup 50 | 51 | @options[:input] = file = args.shift 52 | @options[:output] = destination = args.shift 53 | 54 | @options[:input] = file = "-" unless file 55 | 56 | if File.directory?(@options[:input]) 57 | Dir["#{@options[:input]}/**/*.haml"].each { |file| _process(file, destination) } 58 | else 59 | _process(file, destination) 60 | end 61 | end 62 | 63 | private 64 | 65 | def _process(file, destination = nil) 66 | require 'fileutils' 67 | slim_file = file.sub(/\.haml$/, '.slim') 68 | 69 | if File.directory?(@options[:input]) && destination 70 | FileUtils.mkdir_p(File.dirname(slim_file).sub(@options[:input].chomp('/'), destination)) 71 | slim_file.sub!(@options[:input].chomp('/'), destination) 72 | else 73 | slim_file = destination || slim_file 74 | end 75 | 76 | in_file = if @options[:input] == "-" 77 | $stdin 78 | else 79 | File.open(file, 'r') 80 | end 81 | 82 | @options[:output] = slim_file && slim_file != '-' ? File.open(slim_file, 'w') : $stdout 83 | @options[:output].puts Haml2Slim.convert!(in_file) 84 | @options[:output].close 85 | 86 | File.delete(file) if @options[:delete] 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/haml2slim/converter.rb: -------------------------------------------------------------------------------- 1 | module Haml2Slim 2 | class Converter 3 | def initialize(haml) 4 | @slim = "" 5 | 6 | haml.each_line do |line| 7 | @slim << parse_line(line) 8 | end 9 | end 10 | 11 | def to_s 12 | @slim 13 | end 14 | 15 | def parse_line(line) 16 | indent = line[/^[ \t]*/] 17 | line.strip! 18 | 19 | # removes the HAML's whitespace removal characters ('>' and '<') 20 | line.gsub!(/(>|<)$/, '') 21 | 22 | converted = case line[0, 2] 23 | when '&=' then line.sub(/^&=/, '==') 24 | when '!=' then line.sub(/^!=/, '==') 25 | when '-#' then line.sub(/^-#/, '/') 26 | when '#{' then line 27 | else 28 | case line[0] 29 | when ?%, ?., ?# then parse_tag(line) 30 | when ?: then "#{line[1..-1]}:" 31 | when ?! then line == "!!!" ? line.sub(/^!!!/, 'doctype html') : line.sub(/^!!!/, 'doctype') 32 | when ?-, ?= then line 33 | when ?~ then line.sub(/^~/, '=') 34 | when ?/ then line.sub(/^\//, '/!') 35 | when ?\ then line.sub(/^\\/, '|') 36 | when nil then "" 37 | else "| #{line}" 38 | end 39 | end 40 | 41 | if converted.chomp!(' |') 42 | converted.sub!(/^\| /, '') 43 | converted << ' \\' 44 | end 45 | 46 | "#{indent}#{converted}\n" 47 | end 48 | 49 | def parse_tag(tag_line) 50 | tag_line.sub!(/^%/, '') 51 | tag_line.sub!(/^(\w+)!=/, '\1==') 52 | 53 | if tag_line_contains_attr = tag_line.match(/([^\{]+)\{(.+)\}(.*)/) 54 | tag, attrs, text = *tag_line_contains_attr[1..3] 55 | "#{tag} #{parse_attrs(attrs)} #{text}" 56 | else 57 | tag_line.sub(/^!=/, '=') 58 | end 59 | end 60 | 61 | def parse_attrs(attrs, key_prefix='') 62 | data_temp = {} 63 | attrs.gsub!(/:data\s*=>\s*\{([^\}]*)\}/) do 64 | key = rand(99999).to_s 65 | data_temp[key] = parse_attrs($1, 'data-') 66 | ":#{key} => #{key}" 67 | end 68 | [ 69 | /,?( ?):?"?([^"'{ ]+)"?\s*=>\s*([^,]*)/, 70 | /,?( ?)"?([^"'{ ]+)"?:\s*([^,]*)/ 71 | ].each do |regexp| 72 | attrs.gsub!(regexp) do 73 | space = $1 74 | key = $2 75 | value = $3 76 | wrapped_value = value.to_s =~ /\s+/ ? "(#{value})" : value 77 | "#{space}#{key_prefix}#{key}=#{wrapped_value}" 78 | end 79 | end 80 | data_temp.each do |k, v| 81 | attrs.gsub!("#{k}=#{k}", v) 82 | end 83 | attrs 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/haml2slim/version.rb: -------------------------------------------------------------------------------- 1 | module Haml2Slim 2 | VERSION = '0.4.7' 3 | end 4 | -------------------------------------------------------------------------------- /test/fixtures/_av_partial_1.haml: -------------------------------------------------------------------------------- 1 | %h2 This is a pretty complicated partial 2 | .partial 3 | %p It has several nested partials, 4 | %ul 5 | - 5.times do 6 | %li 7 | %strong Partial: 8 | - @nesting = 5 9 | = render :partial => 'haml/templates/av_partial_2' -------------------------------------------------------------------------------- /test/fixtures/_av_partial_1_ugly.haml: -------------------------------------------------------------------------------- 1 | %h2 This is a pretty complicated partial 2 | .partial 3 | %p It has several nested partials, 4 | %ul 5 | - 5.times do 6 | %li 7 | %strong Partial: 8 | - @nesting = 5 9 | = render :partial => 'haml/templates/av_partial_2_ugly' -------------------------------------------------------------------------------- /test/fixtures/_av_partial_2.haml: -------------------------------------------------------------------------------- 1 | - @nesting -= 1 2 | .partial{:level => @nesting} 3 | %h3 This is a crazy deep-nested partial. 4 | %p== Nesting level #{@nesting} 5 | = render :partial => 'haml/templates/av_partial_2' if @nesting > 0 -------------------------------------------------------------------------------- /test/fixtures/_av_partial_2_ugly.haml: -------------------------------------------------------------------------------- 1 | - @nesting -= 1 2 | .partial{:level => @nesting} 3 | %h3 This is a crazy deep-nested partial. 4 | %p== Nesting level #{@nesting} 5 | = render :partial => 'haml/templates/av_partial_2_ugly' if @nesting > 0 -------------------------------------------------------------------------------- /test/fixtures/_layout_for_partial.haml: -------------------------------------------------------------------------------- 1 | .partial-layout 2 | %h2 This is inside a partial layout 3 | = yield -------------------------------------------------------------------------------- /test/fixtures/_partial.haml: -------------------------------------------------------------------------------- 1 | %p 2 | @foo = 3 | = @foo 4 | - @foo = 'value three' 5 | == Toplevel? #{haml_buffer.toplevel?} 6 | %p 7 | @foo = 8 | = @foo 9 | -------------------------------------------------------------------------------- /test/fixtures/_text_area.haml: -------------------------------------------------------------------------------- 1 | .text_area_test_area 2 | ~ "" 3 | = "" 4 | -------------------------------------------------------------------------------- /test/fixtures/breakage.haml: -------------------------------------------------------------------------------- 1 | %p 2 | %h1 Hello! 3 | = "lots of lines" 4 | - raise "Oh no!" 5 | %p 6 | this is after the exception 7 | %strong yes it is! 8 | ho ho ho. 9 | -------------------------------------------------------------------------------- /test/fixtures/content_for_layout.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %body 5 | #yieldy 6 | = yield :layout 7 | #nosym 8 | = yield 9 | -------------------------------------------------------------------------------- /test/fixtures/eval_suppressed.haml: -------------------------------------------------------------------------------- 1 | = "not me!" 2 | = "nor me!" 3 | - haml_concat "not even me!" 4 | %p= "NO!" 5 | %p~ "UH-UH!" 6 | %h1 Me! 7 | #foo 8 | %p#bar All 9 | %br/ 10 | %p.baz This 11 | Should render 12 | -------------------------------------------------------------------------------- /test/fixtures/helpers.haml: -------------------------------------------------------------------------------- 1 | = h("&&&&&&&&&&&") # This is an ActionView Helper... should load 2 | - foo = capture do # This ActionView Helper is designed for ERB, but should work with haml 3 | %div 4 | %p.title Title 5 | %p.text 6 | Woah this is really crazy 7 | I mean wow, 8 | man. 9 | - 3.times do 10 | = foo 11 | %p foo 12 | - tab_up 13 | %p reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong 14 | - tab_down 15 | .woah 16 | #funky 17 | = capture_haml do 18 | %div 19 | %h1 Big! 20 | %p Small 21 | / Invisible 22 | = capture do 23 | .dilly 24 | %p foo 25 | %h1 bar 26 | = surround '(', ')' do 27 | %strong parentheses! 28 | = precede '*' do 29 | %span.small Not really 30 | click 31 | = succeed '.' do 32 | %a{:href=>"thing"} here 33 | %p baz 34 | - haml_buffer.tabulation = 10 35 | %p boom 36 | - concat "foo\n" 37 | - haml_buffer.tabulation = 0 38 | = list_of({:google => 'http://www.google.com'}) do |name, link| 39 | %a{ :href => link }= name 40 | %p 41 | - haml_concat "foo" 42 | %div 43 | - haml_concat "bar" 44 | - haml_concat "boom" 45 | baz 46 | - haml_concat "boom, again" 47 | - haml_tag :table do 48 | - haml_tag :tr do 49 | - haml_tag :td, {:class => 'cell'} do 50 | - haml_tag :strong, "strong!" 51 | - haml_concat "data" 52 | - haml_tag :td do 53 | - haml_concat "more_data" 54 | - haml_tag :hr 55 | - haml_tag :div, '' 56 | -------------------------------------------------------------------------------- /test/fixtures/nuke_inner_whitespace.haml: -------------------------------------------------------------------------------- 1 | %p 2 | %q< Foo 3 | %p 4 | %q{:a => 1 + 1}< Foo 5 | %p 6 | %q<= "Foo\nBar" 7 | %p 8 | %q{:a => 1 + 1}<= "Foo\nBar" 9 | %p 10 | %q< 11 | Foo 12 | Bar 13 | %p 14 | %q{:a => 1 + 1}< 15 | Foo 16 | Bar 17 | %p 18 | %q< 19 | %div 20 | Foo 21 | Bar 22 | %p 23 | %q{:a => 1 + 1}< 24 | %div 25 | Foo 26 | Bar 27 | 28 | -# Regression test 29 | %p 30 | %q<= "foo" 31 | %q{:a => 1 + 1} 32 | bar 33 | -------------------------------------------------------------------------------- /test/fixtures/nuke_outer_whitespace.haml: -------------------------------------------------------------------------------- 1 | %p 2 | %p 3 | %q> 4 | Foo 5 | %p 6 | %p 7 | %q{:a => 1 + 1}> 8 | Foo 9 | %p 10 | %p 11 | %q> Foo 12 | %p 13 | %p 14 | %q{:a => 1 + 1}> Foo 15 | %p 16 | %p 17 | %q> 18 | = "Foo" 19 | %p 20 | %p 21 | %q{:a => 1 + 1}> 22 | = "Foo" 23 | %p 24 | %p 25 | %q>= "Foo" 26 | %p 27 | %p 28 | %q{:a => 1 + 1}>= "Foo" 29 | %p 30 | %p 31 | %q> 32 | = "Foo\nBar" 33 | %p 34 | %p 35 | %q{:a => 1 + 1}> 36 | = "Foo\nBar" 37 | %p 38 | %p 39 | %q>= "Foo\nBar" 40 | %p 41 | %p 42 | %q{:a => 1 + 1}>= "Foo\nBar" 43 | %p 44 | %p 45 | - tab_up 46 | foo 47 | %q> 48 | Foo 49 | bar 50 | - tab_down 51 | %p 52 | %p 53 | - tab_up 54 | foo 55 | %q{:a => 1 + 1}> 56 | Foo 57 | bar 58 | - tab_down 59 | %p 60 | %p 61 | - tab_up 62 | foo 63 | %q> Foo 64 | bar 65 | - tab_down 66 | %p 67 | %p 68 | - tab_up 69 | foo 70 | %q{:a => 1 + 1}> Foo 71 | bar 72 | - tab_down 73 | %p 74 | %p 75 | - tab_up 76 | foo 77 | %q> 78 | = "Foo" 79 | bar 80 | - tab_down 81 | %p 82 | %p 83 | - tab_up 84 | foo 85 | %q{:a => 1 + 1}> 86 | = "Foo" 87 | bar 88 | - tab_down 89 | %p 90 | %p 91 | - tab_up 92 | foo 93 | %q>= "Foo" 94 | bar 95 | - tab_down 96 | %p 97 | %p 98 | - tab_up 99 | foo 100 | %q{:a => 1 + 1}>= "Foo" 101 | bar 102 | - tab_down 103 | %p 104 | %p 105 | - tab_up 106 | foo 107 | %q> 108 | = "Foo\nBar" 109 | bar 110 | - tab_down 111 | %p 112 | %p 113 | - tab_up 114 | foo 115 | %q{:a => 1 + 1}> 116 | = "Foo\nBar" 117 | bar 118 | - tab_down 119 | %p 120 | %p 121 | - tab_up 122 | foo 123 | %q>= "Foo\nBar" 124 | bar 125 | - tab_down 126 | %p 127 | %p 128 | - tab_up 129 | foo 130 | %q{:a => 1 + 1}>= "Foo\nBar" 131 | bar 132 | - tab_down 133 | %p 134 | %p 135 | %q> 136 | %p 137 | %p 138 | %q>/ 139 | %p 140 | %p 141 | %q{:a => 1 + 1}> 142 | %p 143 | %p 144 | %q{:a => 1 + 1}>/ 145 | -------------------------------------------------------------------------------- /test/fixtures/original_engine.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %title Stop. haml time 5 | #content 6 | %h1 This is a title! 7 | %p Lorem ipsum dolor sit amet, consectetur adipisicing elit 8 | %p{:class => 'foo'} Cigarettes! 9 | %h2 Man alive! 10 | %ul.things 11 | %li Slippers 12 | %li Shoes 13 | %li Bathrobe 14 | %li Coffee 15 | %pre 16 | This is some text that's in a pre block! 17 | Let's see what happens when it's rendered! What about now, since we're on a new line? 18 | -------------------------------------------------------------------------------- /test/fixtures/partial_layout.haml: -------------------------------------------------------------------------------- 1 | %h1 Partial layout used with for block: 2 | - if Haml::Util.ap_geq_3? 3 | = render :layout => 'layout_for_partial.haml' do 4 | %p Some content within a layout 5 | - else 6 | - render :layout => 'layout_for_partial.haml' do 7 | %p Some content within a layout 8 | -------------------------------------------------------------------------------- /test/fixtures/partialize.haml: -------------------------------------------------------------------------------- 1 | = render :file => "#{name}.haml" 2 | -------------------------------------------------------------------------------- /test/fixtures/partials.haml: -------------------------------------------------------------------------------- 1 | - @foo = 'value one' 2 | %p 3 | @foo = 4 | = @foo 5 | - @foo = 'value two' 6 | %p 7 | @foo = 8 | = @foo 9 | = test_partial "partial" 10 | %p 11 | @foo = 12 | = @foo 13 | -------------------------------------------------------------------------------- /test/fixtures/render_layout.haml: -------------------------------------------------------------------------------- 1 | = render :layout => 'layout' do 2 | During 3 | -------------------------------------------------------------------------------- /test/fixtures/silent_script.haml: -------------------------------------------------------------------------------- 1 | %div 2 | %h1 I can count! 3 | - (1..20).each do |i| 4 | = i 5 | %h1 I know my ABCs! 6 | %ul 7 | - ('a'..'z').each do |i| 8 | %li= i 9 | %h1 I can catch errors! 10 | - begin 11 | - String.silly 12 | - rescue NameError => e 13 | = "Oh no! \"#{e}\" happened!" 14 | %p 15 | "false" is: 16 | - if false 17 | = "true" 18 | - else 19 | = "false" 20 | - if true 21 | - 5.times do |i| 22 | - if i % 2 == 1 23 | Odd! 24 | - else 25 | Even! 26 | - else 27 | = "This can't happen!" 28 | - 13 | 29 | .foo 30 | %strong foobar 31 | - 5.times | 32 | do | 33 | |a| | 34 | %strong= a 35 | .test 36 | - "foo | 37 | bar | 38 | baz" | 39 | 40 | %p boom 41 | -------------------------------------------------------------------------------- /test/fixtures/standard.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en-US", "lang" => "en-US"} 3 | %head 4 | %title Hampton Catlin Is Totally Awesome 5 | %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} 6 | %body 7 | / You're In my house now! 8 | .header 9 | Yes, ladies and gentileman. He is just that egotistical. 10 | Fantastic! This should be multi-line output 11 | The question is if this would translate! Ahah! 12 | = 1 + 9 + 8 + 2 #numbers should work and this should be ignored 13 | #body= " Quotes should be loved! Just like people!" 14 | - 120.times do |number| 15 | = number 16 | Wow.| 17 | %p{:code => 1 + 2} 18 | = "Holy cow " + | 19 | "multiline " + | 20 | "tags! " + | 21 | "A pipe (|) even!" | 22 | = [1, 2, 3].collect { |n| "PipesIgnored|" }.join 23 | = [1, 2, 3].collect { |n| | 24 | n.to_s | 25 | }.join("|") | 26 | - bar = 17 27 | %div.silent{:foo => bar} 28 | - foo = String.new 29 | - foo << "this" 30 | - foo << " shouldn't" 31 | - foo << " evaluate" 32 | = foo + " but now it should!" 33 | -# Woah crap a comment! 34 | 35 | -# That was a line that shouldn't close everything. 36 | %ul.really.cool 37 | - ('a'..'f').each do |a| 38 | %li= a 39 | #combo.of_divs_with_underscore= @should_eval = "with this text" 40 | = "foo".each_line do |line| 41 | - nil 42 | .footer 43 | %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" 44 | -------------------------------------------------------------------------------- /test/fixtures/tag_parsing.haml: -------------------------------------------------------------------------------- 1 | %div.tags 2 | %foo 1 3 | %FOO 2 4 | %fooBAR 3 5 | %fooBar 4 6 | %foo_bar 5 7 | %foo-bar 6 8 | %foo:bar 7 9 | %foo.bar 8 10 | %fooBAr_baz:boom_bar 9 11 | %foo13 10 12 | %foo2u 11 13 | %div.classes 14 | %p.foo.bar#baz 15 | .fooBar a 16 | .foo-bar b 17 | .foo_bar c 18 | .FOOBAR d 19 | .foo16 e 20 | .123 f 21 | .foo2u g 22 | -------------------------------------------------------------------------------- /test/fixtures/very_basic.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %body 5 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'minitest/unit' 3 | require 'slim' 4 | require 'haml2slim' 5 | 6 | MiniTest::Unit.autorun -------------------------------------------------------------------------------- /test/test_haml2slim.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | require 'tmpdir' 3 | 4 | class TestHaml2Slim < MiniTest::Unit::TestCase 5 | def setup 6 | create_haml_file 7 | end 8 | 9 | def teardown 10 | cleanup_tmp_files 11 | end 12 | 13 | Dir.glob("test/fixtures/*.haml").each do |file| 14 | define_method("test_template_#{File.basename(file, '.haml')}") do 15 | assert_valid?(file) 16 | end 17 | end 18 | 19 | def test_convert_file 20 | `bin/haml2slim #{haml_file}` 21 | assert_equal true, slim_file? 22 | end 23 | 24 | def test_convert_file_to_destination 25 | slim_path = File.join(tmp_dir, "a.slim") 26 | `bin/haml2slim #{haml_file} #{slim_path}` 27 | assert_equal true, slim_file?(slim_path) 28 | end 29 | 30 | def test_convert_file_to_stdout 31 | File.open(haml_file, "w") do |f| 32 | f.puts "%p\n %h1 Hello" 33 | end 34 | 35 | IO.popen("bin/haml2slim #{haml_file} -", "r") do |f| 36 | assert_equal "p\n h1 Hello\n", f.read 37 | end 38 | end 39 | 40 | def test_convert_stdin_to_stdout 41 | File.open(haml_file, "w") do |f| 42 | f.puts "%p\n %h1 Hello" 43 | end 44 | 45 | IO.popen("cat #{haml_file} | bin/haml2slim", "r") do |f| 46 | assert_equal "p\n h1 Hello\n", f.read 47 | end 48 | end 49 | 50 | def test_convert_directory 51 | `bin/haml2slim #{tmp_dir}` 52 | assert_equal true, slim_file? 53 | end 54 | 55 | def test_convert_directory_to_destination 56 | slim_path = Dir.mktmpdir("haml2slim_2.") 57 | `bin/haml2slim #{tmp_dir} #{slim_path}` 58 | assert_equal true, slim_file?(File.join(slim_path, "dummy.slim")) 59 | FileUtils.rm_rf(slim_path) 60 | end 61 | 62 | def test_delete_haml_file 63 | `bin/haml2slim #{haml_file} -d` 64 | assert_equal false, File.exist?(haml_file) 65 | end 66 | 67 | def test_hash_convert 68 | haml = '%a{:title => 1 + 1, :href => "/#{test_obj.method}", :height => "50px", :width => "50px"}' 69 | slim = 'a title=(1 + 1) href="/#{test_obj.method}" height="50px" width="50px"' 70 | assert_haml_to_slim haml, slim 71 | end 72 | 73 | def test_data_attributes_convert 74 | haml = '%a{:href => "test", :data => {:param1 => var, :param2 => 1 + 1, :param3 => "string"}}' 75 | slim = 'a href="test" data-param1=var data-param2=(1 + 1) data-param3="string"' 76 | assert_haml_to_slim haml, slim 77 | end 78 | 79 | def test_new_syntax_hash_convert 80 | haml = '%a{title: 1 + 1, href: "/#{test_obj.method}", height: "50px", width: "50px"}' 81 | slim = 'a title=(1 + 1) href="/#{test_obj.method}" height="50px" width="50px"' 82 | assert_haml_to_slim haml, slim 83 | end 84 | 85 | def test_no_html_escape_predicate 86 | haml = '!= method_call' 87 | slim = '== method_call' 88 | assert_haml_to_slim haml, slim 89 | end 90 | 91 | def test_no_html_escape_predicate2 92 | haml = '%span!= method_call' 93 | slim = 'span== method_call' 94 | assert_haml_to_slim haml, slim 95 | end 96 | 97 | private 98 | 99 | def assert_haml_to_slim(actual_haml, expected_slim) 100 | File.open(haml_file, "w") do |f| 101 | f.puts actual_haml 102 | end 103 | 104 | IO.popen("cat #{haml_file} | bin/haml2slim", "r") do |f| 105 | assert_equal expected_slim, f.read.strip 106 | end 107 | end 108 | 109 | def tmp_dir 110 | @tmp_dir ||= Dir.mktmpdir("haml2slim.") 111 | end 112 | 113 | def create_haml_file 114 | `touch #{haml_file}` 115 | end 116 | 117 | def haml_file 118 | File.join(tmp_dir, "dummy.haml") 119 | end 120 | 121 | def slim_file?(path = nil) 122 | File.file?(path || File.join(tmp_dir, "dummy.slim")) 123 | end 124 | 125 | def cleanup_tmp_files 126 | FileUtils.rm_rf(tmp_dir) 127 | end 128 | 129 | def assert_valid?(source) 130 | haml = File.open(source) 131 | slim = Haml2Slim.convert!(haml) 132 | assert_instance_of String, Slim::Engine.new.call(slim.to_s) 133 | end 134 | end 135 | --------------------------------------------------------------------------------