Created
January 30, 2024 03:05
-
-
Save DanielHeath/43116cd40b970af63695806326a87a7a to your computer and use it in GitHub Desktop.
Had enough of Slim in your rails app? Slim2ERB does a reasonable job of auto-converting any files that don't generate eyebleeding source.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'slim/erb_converter' | |
def reject_newlines_in(content) | |
result = [] | |
content.each do |item| | |
next if item == [:newline] | |
if item.is_a? Array | |
result.push(reject_newlines_in(item)) | |
else | |
result.push(item) | |
end | |
end | |
result | |
end | |
Temple::HTML::Pretty | |
module Temple | |
module HTML | |
# @api public | |
class Pretty < Fast | |
def on_dynamic(code) | |
[:multi, [:static, indent], [:dynamic, code]] | |
end | |
def on_code(code) | |
[:multi, [:static, indent], [:dynamic, code]] | |
end | |
def on_html_tag(name, attrs, content = nil) | |
name = name.to_s | |
closed = !content || (empty_exp?(content) && options[:autoclose].include?(name)) | |
indent = tag_indent(name) | |
@pretty = false | |
result = [:multi, [:static, "#{indent}<#{name}"], compile(attrs)] | |
result << [:static, (closed && @format != :html ? ' /' : '') + '>'] | |
@pretty = true | |
if content | |
content = reject_newlines_in(content) | |
@indent += 1 | |
result << compile(content) | |
@indent -= 1 | |
end | |
unless closed | |
result << [:static, "#{content && !empty_exp?(content) ? indent : ''}</#{name}>"] | |
end | |
@pretty = true | |
result | |
end | |
# Return indentation before tag | |
def tag_indent(name) | |
flag = @indent_next != nil | |
@indent_next = true | |
flag ? indent : '' | |
end | |
end | |
end | |
end | |
Temple::Generators::ERB | |
module Temple | |
module Generators | |
# Implements an ERB generator. | |
# | |
# @api public | |
class ERB < Generator | |
def on_dynamic(code) | |
"<%= #{code.strip} %>" | |
end | |
def on_code(code) | |
"<% #{code.strip} %>" | |
end | |
end | |
end | |
end | |
Slim::Controls | |
module Slim | |
class Controls < Filter | |
# Handle output expression `[:slim, :output, escape, code, content]` | |
# | |
# @param [Boolean] escape Escape html | |
# @param [String] code Ruby code | |
# @param [Array] content Temple expression | |
# @return [Array] Compiled temple expression | |
def on_slim_output(escape, code, content) | |
[:multi, [:escape, escape, [:dynamic, code]], compile(content)] | |
end | |
end | |
end | |
Slim::CodeAttributes | |
module Slim | |
# @api private | |
class CodeAttributes < Filter | |
# Handle attribute expression `[:html, :attr, name, value]` | |
# | |
# @param [String] name Attribute name | |
# @param [Array] value Value expression | |
# @return [Array] Compiled temple expression | |
def on_html_attr(name, value) | |
if value[0] == :slim && value[1] == :attrvalue && !options[:merge_attrs][name] | |
# We handle the attribute as a boolean attribute | |
escape, code = value[2], value[3] | |
case code | |
when 'true' | |
[:html, :attr, name, [:multi]] | |
when 'false', 'nil' | |
[:multi] | |
else | |
begin | |
return [:html, :attr, name, [:escape, escape, [:static, eval(code)]]] | |
rescue | |
raise DoNotConvert, 'not supported' | |
end | |
tmp = unique_name | |
[:multi, | |
[:code, "#{tmp} = #{code}"], | |
[:if, tmp, | |
[:if, "#{tmp} == true", | |
[:html, :attr, name, [:multi]], | |
[:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]] | |
end | |
else | |
# Attribute with merging | |
@attr = name | |
super | |
end | |
end | |
# Handle attribute expression `[:slim, :attrvalue, escape, code]` | |
# | |
# @param [Boolean] escape Escape html | |
# @param [String] code Ruby code | |
# @return [Array] Compiled temple expression | |
def on_slim_attrvalue(escape, code) | |
# We perform attribute merging on Array values | |
if delimiter = options[:merge_attrs][@attr] | |
raise DoNotConvert, 'not supported' | |
tmp = unique_name | |
[:multi, | |
[:code, "#{tmp} = #{code}"], | |
[:if, "Array === #{tmp}", | |
[:multi, | |
[:code, "#{tmp} = #{tmp}.flatten"], | |
[:code, "#{tmp}.map!(&:to_s)"], | |
[:code, "#{tmp}.reject!(&:empty?)"], | |
[:escape, escape, [:dynamic, "#{tmp}.join(#{delimiter.inspect})"]]], | |
[:escape, escape, [:dynamic, tmp]]]] | |
else | |
[:escape, escape, [:dynamic, code]] | |
end | |
end | |
end | |
end | |
class DoNotConvert < StandardError | |
end | |
Slim::Splat::Filter | |
module Slim | |
module Splat | |
class Filter < ::Slim::Filter | |
def on_html_attrs(*attrs) | |
if attrs.any? {|attr| splat?(attr) } | |
raise DoNotConvert, 'unsupported splat' | |
builder, block = make_builder(attrs) | |
[:multi, | |
block, | |
[:dynamic, "#{builder}.build_attrs"]] | |
else | |
super | |
end | |
end | |
end | |
end | |
end | |
converter = Slim::ERBConverter.new(disable_capture: true, pre_tags: [], pretty: true, format: :html, escape_code: '%s') | |
def strip_converted(str) | |
str.sub(/<% _temple_html_pretty\d+ = \/\(\?\!\)\/ %>/, '').sub(/_temple_html_pretty\d+ = \/\(\?\!\)\/;/, '').lines.map(&:rstrip).reject(&:blank?).join("\n") | |
end | |
Dir.glob('app/views/**/*.slim').each do |path| | |
begin | |
File.write(path.sub(/slim$/, 'erb'), strip_converted(converter.call(File.read(path))) + "\n") | |
File.delete(path) | |
rescue DoNotConvert | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment