Skip to content
Newer
Older
100644 158 lines (135 sloc) 4.72 KB
a758545 @ffmike Move haml conversion to its own file
authored
1 require 'cgi'
2
3 module Rails
4 class TemplateRunner
5 def get_indent(line)
6 line = line.to_s
7 space_areas = line.scan(/^\s+/)
8 space_areas.empty? ? 0 : (space_areas.first.size / 2)
9 end
10
11 def block_start?(line)
12 block_starters = [/\s+do/, /^-\s+while/, /^-\s+module/, /^-\s+begin/,
13 /^-\s+case/, /^-\s+class/, /^-\s+unless/, /^-\s+for/,
14 /^-\s+until/, /^-\s*if/]
15
16 line = line.to_s
17 line.strip =~ /^-/ && block_starters.any?{|bs| line.strip =~ bs}
18 end
19
20 def block_end?(line)
21 line = line.to_s
22 line.strip =~ /^-\send$/
23 end
24
25 def ie_block_start?(line)
26 line = line.to_s
27 line =~ /\[if/i && line =~ /IE/ && line.strip =~ /\]>$/
28 end
29
30 def ie_block_end?(line)
31 line = line.to_s
32 line =~ /<!\[endif\]/i
33 end
34
35 def comment_line?(line)
36 line = line.to_s
37 line.strip =~ /^\//
38 end
39
40 def indent(line, steps = 0)
41 line = line.to_s
42 exceptions = [/\s+else\W/, /^-\s+elsif/, /^-\s+when/, /^-\s+ensure/, /^-\s+rescue/]
43 return if exceptions.any?{|ex| line.strip =~ ex}
44
45 steps ||= 0
46 line = line.to_s
47 (" " * steps) + line
48 end
49
50 def alter_lines(lines, altered_lines)
51 altered_lines.each do |pair|
52 line_number, text = pair
53 lines[line_number] = text
54 end
55 lines
56 end
57
58 def indent_lines(lines, indented_lines)
59 indented_lines.each do |pair|
60 line_number, indent_by = pair
61 lines[line_number] = indent(lines[line_number], indent_by)
62 end
63 lines
64 end
65
66 def remove_lines(lines, goner_lines)
67 goner_lines.each do |i|
68 lines[i] = nil
69 end
70 lines.compact
71 end
72
73 def erb_to_haml(folder)
74 in_root do
75 Dir[File.join(folder, "**/*.erb")].each do |origin|
76 destination = origin.gsub(/\.erb$/, '.haml')
77 run "html2haml -rx #{origin} #{destination}"
78
79 # Auto-fix for haml indentation. Likely not very reliable.
80 stack = []
81 lines = File.readlines(destination)
82 line_number = lines.size
83 goner_lines = []
84 indented_lines = []
85 altered_lines = []
86 inside_ie_block = false
87 just_passed_ie_block = false
88
89 lines.reverse_each do |line|
90 line_number -= 1
91
92 if just_passed_ie_block
93 altered_lines << [line_number, line.sub('/', "/" + just_passed_ie_block)]
94 just_passed_ie_block = false
95 elsif ie_block_start?(line)
96 goner_lines << line_number
97 inside_ie_block = false
98 stack.pop
99 just_passed_ie_block = line.strip.chop
100 elsif ie_block_end?(line)
101 goner_lines << line_number
102 inside_ie_block = true
103 stack << get_indent(line)
104 elsif inside_ie_block
105 match = line.match(/<haml[^>]*>([^<]+)<\/haml/)
106 string = match && match[1]
107 string = string ? "= #{CGI::unescapeHTML(CGI::unescapeHTML(string.strip))}\n" : "#{line.strip}\n"
108 altered_lines << [line_number, string]
109 indented_lines << [line_number, stack.last]
110 elsif block_end?(line)
111 stack << 1
112 goner_lines << line_number
113 elsif block_start?(line)
114 stack.pop
115 else
116 indented_lines << [line_number, stack.last]
117 end
118 end
119
120 lines = alter_lines(lines, altered_lines)
121 lines = indent_lines(lines, indented_lines)
122 lines = remove_lines(lines, goner_lines)
123
124 altered_lines = []
125 indented_lines = []
126 goner_lines = []
127
128 line_number = -1
129 lines.each_cons(3) do |three_lines|
130 line_number += 1
131 line2_number = line_number + 1
132 middle_indented_by_one = (get_indent(three_lines[1]) - get_indent(three_lines[0]) == 1)
133 top_indented_more = (get_indent(three_lines[0]) >= get_indent(three_lines[2]))
134 commented = (three_lines[0].to_s.strip =~ /^\//)
135
136 if(top_indented_more && middle_indented_by_one && !commented)
137 if (three_lines[1].strip =~ /^=/)
138 altered_lines << [line_number, (three_lines[0].rstrip + three_lines[1].lstrip)]
139 else
140 altered_lines << [line_number, (three_lines[0].rstrip + " " + three_lines[1].lstrip)]
141 end
142 goner_lines << line2_number
143 end
144 end
145
146 lines = alter_lines(lines, altered_lines)
147 lines = remove_lines(lines, goner_lines)
148
149 File.open(destination, "w") do |f|
150 f.write(lines.join)
151 end
152
153 File.delete(origin)
154 end
155 end
156 end
157 end
158 end
Something went wrong with that request. Please try again.