Skip to content

Instantly share code, notes, and snippets.

@paneq
Forked from arika/rails_erb_syntax_check.rb
Last active January 9, 2018 13:34
Show Gist options
  • Save paneq/5a297e722095598fbe5f7b0215774f79 to your computer and use it in GitHub Desktop.
Save paneq/5a297e722095598fbe5f7b0215774f79 to your computer and use it in GitHub Desktop.
Rails(Action View) ERB template syntax checker
require 'action_view'
require 'tmpdir'
require 'fileutils'
require 'optparse'
def check_syntax(path, options = {})
erb = content(path)
code = ruby_code(erb)
eval("BEGIN { puts('ok'); return true }; #{code}", nil, path, 0)
rescue SyntaxError
puts "#{path}: syntax error"
puts $! if options[:verbose]
git_diff(path, options) if options[:show_diff]
end
def git_diff(path, options = {})
code = ruby_code(content(path), true)
gcode = ruby_code(git_content(path), true)
gpath = path + '~'
diff_cmd = ['diff', *options[:diff_opts].uniq.flatten]
Dir.mktmpdir do |td|
dir, file = File.split(path)
Dir.chdir(td) do
FileUtils.mkdir_p(dir)
open(path, 'w') {|o| o.print code }
open(gpath, 'w') {|o| o.print gcode }
system(*(diff_cmd << gpath << path))
end
end
end
def show_code(path, options = {})
code = ruby_code(content(path), true)
print code
end
def content(path)
open(path, 'r') {|i| i.read }
end
def git_content(path)
`git show HEAD:#{path}`
end
def ruby_code(erb_text, notext = false)
erb = ActionView::Template::Handlers::Erubis.new
erb.extend(Erubis::NoTextEnhancer) if notext
erb.convert!(erb_text)
erb.src
end
options = {mode: :check, diff_opts: %w(-u)}
OptionParser.new do |o|
o.banner = "usage: #{$0} [options] path [path ...]"
o.separator ''
o.on('-c', 'syntax check') { options[:mode] = :check }
o.on('-s', 'show code') { options[:mode] = :code }
o.on('-d', 'show code diff') { options[:mode] = :diff }
o.on('-v', 'verbose') { options[:verbose] = true }
o.separator ''
o.on('-U NUM', Integer, 'number of context lines') do |num|
options[:show_diff] = true
options[:diff_opts] << ['-U', num.to_s]
end
o.on('-b', 'ignore changes in the amount of white spaces') do
options[:diff_opts] << ['-b']
end
o.on('-w', 'ignore all spaces') do
options[:diff_opts] << ['-w']
end
o.separator ''
o.on_tail('-h', 'print usage') do
puts o
exit
end
end.parse!
if ARGV.empty?
abort 'no files specified'
end
ARGV.each do |path|
case options[:mode]
when :check
check_syntax(path, options)
when :code
show_code(path, options)
when :diff
git_diff(path, options)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment