1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
# frozen_string_literal: true
require 'hamlit'
require 'thor'
module Hamlit
class CLI < Thor
class_option :escape_html, type: :boolean, default: true
class_option :escape_attrs, type: :boolean, default: true
desc 'render HAML', 'Render haml template'
option :load_path, type: :string, aliases: %w[-I]
option :require, type: :string, aliases: %w[-r]
def render(file)
process_load_options
code = generate_code(file)
puts eval(code, binding, file)
end
desc 'compile HAML', 'Show compile result'
option :actionview, type: :boolean, default: false, aliases: %w[-a]
option :color, type: :boolean, default: true
option :check, type: :boolean, default: false, aliases: %w[-c]
def compile(file)
code = generate_code(file)
if options[:check]
if error = validate_ruby(code, file)
abort error.message.split("\n").first
end
puts "Syntax OK"
return
end
puts_code(code, color: options[:color])
end
desc 'temple HAML', 'Show temple intermediate expression'
option :color, type: :boolean, default: true
def temple(file)
pp_object(generate_temple(file), color: options[:color])
end
desc 'parse HAML', 'Show parse result'
option :color, type: :boolean, default: true
def parse(file)
pp_object(generate_ast(file), color: options[:color])
end
desc 'version', 'Show the used hamlit version'
def version
puts Hamlit::VERSION
end
private
def process_load_options
if options[:load_path]
options[:load_path].split(':').each do |dir|
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
end
end
if options[:require]
require options[:require]
end
end
def read_file(file)
if file == '-'
STDIN.read
else
File.read(file)
end
end
def generate_code(file)
template = read_file(file)
if options[:actionview]
require 'action_view'
require 'action_view/base'
require 'hamlit/rails_template'
handler = Hamlit::RailsTemplate.new
template = ActionView::Template.new(template, 'inline template', handler, { locals: [] })
code = handler.call(template)
<<-end_src
def _inline_template___2144273726781623612_70327218547300(local_assigns, output_buffer)
_old_virtual_path, @virtual_path = @virtual_path, nil;_old_output_buffer = @output_buffer;;#{code}
ensure
@virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
end
end_src
else
Hamlit::Engine.new(engine_options).call(template)
end
end
def generate_ast(file)
template = read_file(file)
Hamlit::Parser.new(engine_options).call(template)
end
def generate_temple(file)
ast = generate_ast(file)
Hamlit::Compiler.new(engine_options).call(ast)
end
def engine_options
Hamlit::Engine.options.to_h.merge(
escape_attrs: options[:escape_attrs],
escape_html: options[:escape_html],
)
end
# Flexible default_task, compatible with haml's CLI
def method_missing(*args)
return super(*args) if args.length > 1
render(args.first.to_s)
end
def puts_code(code, color: true)
begin
require 'irb/color'
rescue LoadError
color = false
end
if color
puts IRB::Color.colorize_code(code)
else
puts code
end
end
# Enable colored pretty printing only for development environment.
def pp_object(arg, color: true)
begin
require 'irb/color_printer'
rescue LoadError
color = false
end
if color
IRB::ColorPrinter.pp(arg)
else
require 'pp'
pp(arg)
end
end
def validate_ruby(code, file)
begin
eval("BEGIN {return nil}; #{code}", binding, file)
rescue ::SyntaxError # Not to be confused with Hamlit::SyntaxError
$!
end
end
end
end
|