Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westonganger/e84297d0f5a892fba3e46510bdc73fa7 to your computer and use it in GitHub Desktop.
Save westonganger/e84297d0f5a892fba3e46510bdc73fa7 to your computer and use it in GitHub Desktop.
Naive ERB to Slim Converter (because slimrb does a really terrible job converting)
#!/usr/bin/env ruby
### USAGE: `./convert_slim_to_erb path/to/views/`
### LIMITATIONS:
### - Does not add closing tags such as `<% end %>` or `</div>`
SELF_CLOSING_TAGS = ["input","br","hr","img","meta","area","base","col","embed","link","source","track","wbr","param"].freeze
@line = nil
@indent = nil
@next_line = nil
@next_indent = nil
@ruby_block_indent = nil
Object.class_eval do
def present?
self && !self.strip.empty?
end
def blank?
!present?
end
def presence
self if present?
end
end
def get_indent(str)
str[/^\ */]
end
def prepend_attr(attr, value)
return if value.to_s.blank?
if value.is_a?(Array)
value = value.join(" ")
end
if !@line.include?("#{attr}=")
@line.sub!(">", " #{attr}=\"#{value}\">")
else
@line.sub!("#{attr}=\"", "#{attr}=\"#{value} ") # double quotes
@line.sub!("#{attr}=\'", "#{attr}='#{value} ") # single quotes
end
return true
end
### SCRIPT START
files = ARGV[0].presence || "views/"
files = `find #{files} -name '*.slim'`.split("\n")
files.each do |file|
@content = ""
@lines = File.readlines(file)
@total_num_lines = @lines.size
@lines.each_with_index do |line, i|
puts "Line: #{i+1} of #{@total_num_lines}, File: #{file}"
@line = line
@indent = get_indent(@line)
if @line.strip.blank?
@content << "\n"
next
else
if @ruby_block_indent
if @indent.size > @ruby_block_indent.size
@content << @line
next
else
if @ruby_block_indent
@content << "#{@ruby_block_indent}%>\n\n"
end
@ruby_block_indent = nil
end
else
### TODO: Add close tag functionality
# if @prev_indent && @indent.size <= @prev_indent.size
# if @prev_el_type.present?
# @content << "#{@prev_indent}</#{@prev_el_type}>\n\n"
# elsif ["else","elsif","when"].none?{|x| @line.strip.sub("-","").strip.start_with?(x) }
# @content.sub!(/\n\n\n$/, "\n")
# @content.sub!(/\n\n$/, "\n")
# @content << "#{@prev_indent[2..-1]}<% end %>\n\n"
# end
# end
end
end
if @line.strip.start_with?("ruby:")
@line.sub!("ruby:", "<%")
@ruby_block_indent = @indent
elsif @line.strip.start_with?("-")
@line.sub!("#{@indent}-", "#{@indent}<%")
@line.sub!(/$/, " %>")
elsif @line.strip.start_with?("=")
@line.sub!("#{@indent}=", "#{@indent}<%=")
@line.sub!(/$/, " %>")
elsif @line.strip.start_with?("|")
@line.sub!("#{@indent}|", "#{@indent}")
else
### Normal element
part1 = @line.split(" ").first
element = part1.split(/\.|#/).first
if element.blank?
element = "div"
el_match = /^/
else
el_match = element
end
classes = part1.sub(el_match, "").split(".").map{|y| y.split("#").first }.compact
ids = part1.sub(el_match, "").split("#").map{|y| y.split(".").first }.compact
prepend_attr("class", classes)
prepend_attr("id", ids)
@line.sub!(part1, element)
parts = @line.split(" ")
html_attrs = []
element = @line.split(" ").first
parts = @line.sub(element, "").strip.split('" ')
inner_html = nil
parts.map(&:strip).each_with_index do |part,i|
if part.strip.start_with?("-")
part.sub!("-", "<%")
part.sub!(/$/, " %>")
inner_html = part
elsif part.strip.start_with?("=")
part.sub!("=", "<%=")
part.sub!(/$/, " %>")
inner_html = part
elsif part.strip.start_with?("|")
part.sub!("|", "<%")
part.sub!(/$/, " %>")
inner_html = part
elsif part.match?(/.+=[\"|\']/)
html_attrs << part
end
if inner_html
break
end
end
@line = "#{@indent}<#{element}#{' ' if !html_attrs.empty?}#{html_attrs.join(" ")}#{'/' if SELF_CLOSING_TAGS.include?(element)}>#{inner_html}"
if inner_html
@line << "</#{element}>"
end
@line << "\n"
end
@content << @line
end
File.open(file.sub('slim', 'erb'), "wb") do |f|
f.write @content
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment