hamlit 2.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +45 -0
- data/CHANGELOG.md +676 -0
- data/Gemfile +28 -0
- data/LICENSE.txt +44 -0
- data/README.md +150 -0
- data/REFERENCE.md +266 -0
- data/Rakefile +117 -0
- data/benchmark/boolean_attribute.haml +6 -0
- data/benchmark/class_attribute.haml +5 -0
- data/benchmark/common_attribute.haml +3 -0
- data/benchmark/data_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/boolean_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/class_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/common_attribute.haml +2 -0
- data/benchmark/dynamic_attributes/data_attribute.haml +2 -0
- data/benchmark/dynamic_attributes/id_attribute.haml +2 -0
- data/benchmark/dynamic_boolean_attribute.haml +4 -0
- data/benchmark/etc/attribute_builder.haml +5 -0
- data/benchmark/etc/real_sample.haml +888 -0
- data/benchmark/etc/real_sample.rb +11 -0
- data/benchmark/etc/static_analyzer.haml +1 -0
- data/benchmark/etc/string_interpolation.haml +2 -0
- data/benchmark/etc/tags.haml +3 -0
- data/benchmark/etc/tags_loop.haml +2 -0
- data/benchmark/ext/build_data.rb +17 -0
- data/benchmark/ext/build_id.rb +13 -0
- data/benchmark/id_attribute.haml +3 -0
- data/benchmark/plain.haml +4 -0
- data/benchmark/script.haml +4 -0
- data/benchmark/slim/LICENSE +21 -0
- data/benchmark/slim/context.rb +11 -0
- data/benchmark/slim/run-benchmarks.rb +94 -0
- data/benchmark/slim/view.erb +23 -0
- data/benchmark/slim/view.haml +18 -0
- data/benchmark/slim/view.slim +17 -0
- data/benchmark/utils/benchmark_ips_extension.rb +43 -0
- data/bin/bench +77 -0
- data/bin/console +11 -0
- data/bin/ruby +3 -0
- data/bin/setup +7 -0
- data/bin/stackprof +27 -0
- data/bin/test +24 -0
- data/exe/hamlit +6 -0
- data/ext/hamlit/extconf.rb +10 -0
- data/ext/hamlit/hamlit.c +553 -0
- data/ext/hamlit/hescape.c +108 -0
- data/ext/hamlit/hescape.h +20 -0
- data/hamlit.gemspec +45 -0
- data/lib/hamlit.rb +11 -0
- data/lib/hamlit/attribute_builder.rb +173 -0
- data/lib/hamlit/attribute_compiler.rb +123 -0
- data/lib/hamlit/attribute_parser.rb +110 -0
- data/lib/hamlit/cli.rb +130 -0
- data/lib/hamlit/compiler.rb +97 -0
- data/lib/hamlit/compiler/children_compiler.rb +112 -0
- data/lib/hamlit/compiler/comment_compiler.rb +36 -0
- data/lib/hamlit/compiler/doctype_compiler.rb +46 -0
- data/lib/hamlit/compiler/script_compiler.rb +102 -0
- data/lib/hamlit/compiler/silent_script_compiler.rb +24 -0
- data/lib/hamlit/compiler/tag_compiler.rb +74 -0
- data/lib/hamlit/engine.rb +37 -0
- data/lib/hamlit/error.rb +15 -0
- data/lib/hamlit/escapable.rb +13 -0
- data/lib/hamlit/filters.rb +75 -0
- data/lib/hamlit/filters/base.rb +12 -0
- data/lib/hamlit/filters/cdata.rb +20 -0
- data/lib/hamlit/filters/coffee.rb +17 -0
- data/lib/hamlit/filters/css.rb +33 -0
- data/lib/hamlit/filters/erb.rb +10 -0
- data/lib/hamlit/filters/escaped.rb +22 -0
- data/lib/hamlit/filters/javascript.rb +33 -0
- data/lib/hamlit/filters/less.rb +20 -0
- data/lib/hamlit/filters/markdown.rb +10 -0
- data/lib/hamlit/filters/plain.rb +29 -0
- data/lib/hamlit/filters/preserve.rb +22 -0
- data/lib/hamlit/filters/ruby.rb +10 -0
- data/lib/hamlit/filters/sass.rb +15 -0
- data/lib/hamlit/filters/scss.rb +15 -0
- data/lib/hamlit/filters/text_base.rb +25 -0
- data/lib/hamlit/filters/tilt_base.rb +49 -0
- data/lib/hamlit/force_escapable.rb +29 -0
- data/lib/hamlit/helpers.rb +15 -0
- data/lib/hamlit/html.rb +14 -0
- data/lib/hamlit/identity.rb +13 -0
- data/lib/hamlit/object_ref.rb +30 -0
- data/lib/hamlit/parser.rb +49 -0
- data/lib/hamlit/parser/MIT-LICENSE +20 -0
- data/lib/hamlit/parser/README.md +30 -0
- data/lib/hamlit/parser/haml_buffer.rb +348 -0
- data/lib/hamlit/parser/haml_compiler.rb +553 -0
- data/lib/hamlit/parser/haml_error.rb +61 -0
- data/lib/hamlit/parser/haml_helpers.rb +727 -0
- data/lib/hamlit/parser/haml_options.rb +286 -0
- data/lib/hamlit/parser/haml_parser.rb +800 -0
- data/lib/hamlit/parser/haml_util.rb +288 -0
- data/lib/hamlit/parser/haml_xss_mods.rb +109 -0
- data/lib/hamlit/rails_helpers.rb +51 -0
- data/lib/hamlit/rails_template.rb +59 -0
- data/lib/hamlit/railtie.rb +10 -0
- data/lib/hamlit/ruby_expression.rb +32 -0
- data/lib/hamlit/string_splitter.rb +88 -0
- data/lib/hamlit/template.rb +28 -0
- data/lib/hamlit/utils.rb +18 -0
- data/lib/hamlit/version.rb +4 -0
- metadata +361 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'hamlit/ruby_expression'
|
3
|
+
|
4
|
+
module Hamlit
|
5
|
+
class AttributeParser
|
6
|
+
class ParseSkip < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.parse(text)
|
10
|
+
self.new.parse(text)
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(text)
|
14
|
+
exp = wrap_bracket(text)
|
15
|
+
return if RubyExpression.syntax_error?(exp)
|
16
|
+
|
17
|
+
hash = {}
|
18
|
+
tokens = Ripper.lex(exp)[1..-2] || []
|
19
|
+
each_attr(tokens) do |attr_tokens|
|
20
|
+
key = parse_key!(attr_tokens)
|
21
|
+
hash[key] = attr_tokens.map { |t| t[2] }.join.strip
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
rescue ParseSkip
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def wrap_bracket(text)
|
31
|
+
text = text.strip
|
32
|
+
return text if text[0] == '{'
|
33
|
+
"{#{text}}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_key!(tokens)
|
37
|
+
_, type, str = tokens.shift
|
38
|
+
case type
|
39
|
+
when :on_sp
|
40
|
+
parse_key!(tokens)
|
41
|
+
when :on_label
|
42
|
+
str.tr(':', '')
|
43
|
+
when :on_symbeg
|
44
|
+
_, _, key = tokens.shift
|
45
|
+
assert_type!(tokens.shift, :on_tstring_end) if str != ':'
|
46
|
+
skip_until_hash_rocket!(tokens)
|
47
|
+
key
|
48
|
+
when :on_tstring_beg
|
49
|
+
_, _, key = tokens.shift
|
50
|
+
next_token = tokens.shift
|
51
|
+
unless next_token[1] == :on_label_end
|
52
|
+
assert_type!(next_token, :on_tstring_end)
|
53
|
+
skip_until_hash_rocket!(tokens)
|
54
|
+
end
|
55
|
+
key
|
56
|
+
else
|
57
|
+
raise ParseSkip
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_type!(token, type)
|
62
|
+
raise ParseSkip if token[1] != type
|
63
|
+
end
|
64
|
+
|
65
|
+
def skip_until_hash_rocket!(tokens)
|
66
|
+
until tokens.empty?
|
67
|
+
_, type, str = tokens.shift
|
68
|
+
break if type == :on_op && str == '=>'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def each_attr(tokens)
|
73
|
+
attr_tokens = []
|
74
|
+
open_tokens = Hash.new { |h, k| h[k] = 0 }
|
75
|
+
|
76
|
+
tokens.each do |token|
|
77
|
+
_, type, _ = token
|
78
|
+
case type
|
79
|
+
when :on_comma
|
80
|
+
if open_tokens.values.all?(&:zero?)
|
81
|
+
yield(attr_tokens)
|
82
|
+
attr_tokens = []
|
83
|
+
next
|
84
|
+
end
|
85
|
+
when :on_lbracket
|
86
|
+
open_tokens[:array] += 1
|
87
|
+
when :on_rbracket
|
88
|
+
open_tokens[:array] -= 1
|
89
|
+
when :on_lbrace
|
90
|
+
open_tokens[:block] += 1
|
91
|
+
when :on_rbrace
|
92
|
+
open_tokens[:block] -= 1
|
93
|
+
when :on_lparen
|
94
|
+
open_tokens[:paren] += 1
|
95
|
+
when :on_rparen
|
96
|
+
open_tokens[:paren] -= 1
|
97
|
+
when :on_embexpr_beg
|
98
|
+
open_tokens[:embexpr] += 1
|
99
|
+
when :on_embexpr_end
|
100
|
+
open_tokens[:embexpr] -= 1
|
101
|
+
when :on_sp
|
102
|
+
next if attr_tokens.empty?
|
103
|
+
end
|
104
|
+
|
105
|
+
attr_tokens << token
|
106
|
+
end
|
107
|
+
yield(attr_tokens) unless attr_tokens.empty?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/hamlit/cli.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'hamlit'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Hamlit
|
6
|
+
class CLI < Thor
|
7
|
+
class_option :escape_html, type: :boolean, default: true
|
8
|
+
class_option :escape_attrs, type: :boolean, default: true
|
9
|
+
|
10
|
+
desc 'render HAML', 'Render haml template'
|
11
|
+
option :load_path, type: :string, aliases: %w[-I]
|
12
|
+
option :require, type: :string, aliases: %w[-r]
|
13
|
+
def render(file)
|
14
|
+
process_load_options
|
15
|
+
code = generate_code(file)
|
16
|
+
puts eval(code)
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'compile HAML', 'Show compile result'
|
20
|
+
option :actionview, type: :boolean, default: false, aliases: %w[-a]
|
21
|
+
option :color, type: :boolean, default: false, aliases: %w[-c]
|
22
|
+
def compile(file)
|
23
|
+
code = generate_code(file)
|
24
|
+
puts_code(code, color: options[:color])
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'temple HAML', 'Show temple intermediate expression'
|
28
|
+
option :color, type: :boolean, default: false, aliases: %w[-c]
|
29
|
+
def temple(file)
|
30
|
+
pp_object(generate_temple(file), color: options[:color])
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'parse HAML', 'Show parse result'
|
34
|
+
option :color, type: :boolean, default: false, aliases: %w[-c]
|
35
|
+
def parse(file)
|
36
|
+
pp_object(generate_ast(file), color: options[:color])
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'version', 'Show the used hamlit version'
|
40
|
+
def version
|
41
|
+
puts Hamlit::VERSION
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def process_load_options
|
47
|
+
if options[:load_path]
|
48
|
+
options[:load_path].split(':').each do |dir|
|
49
|
+
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if options[:require]
|
54
|
+
require options[:require]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def read_file(file)
|
59
|
+
if file == '-'
|
60
|
+
STDIN.read
|
61
|
+
else
|
62
|
+
File.read(file)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def generate_code(file)
|
67
|
+
template = read_file(file)
|
68
|
+
if options[:actionview]
|
69
|
+
require 'action_view'
|
70
|
+
require 'action_view/base'
|
71
|
+
require 'hamlit/rails_template'
|
72
|
+
handler = Hamlit::RailsTemplate.new
|
73
|
+
template = ActionView::Template.new(template, 'inline template', handler, { locals: [] })
|
74
|
+
code = handler.call(template)
|
75
|
+
<<-end_src
|
76
|
+
def _inline_template___2144273726781623612_70327218547300(local_assigns, output_buffer)
|
77
|
+
_old_virtual_path, @virtual_path = @virtual_path, nil;_old_output_buffer = @output_buffer;;#{code}
|
78
|
+
ensure
|
79
|
+
@virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
|
80
|
+
end
|
81
|
+
end_src
|
82
|
+
else
|
83
|
+
Hamlit::Engine.new(engine_options).call(template)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def generate_ast(file)
|
88
|
+
template = read_file(file)
|
89
|
+
Hamlit::Parser.new(engine_options).call(template)
|
90
|
+
end
|
91
|
+
|
92
|
+
def generate_temple(file)
|
93
|
+
ast = generate_ast(file)
|
94
|
+
Hamlit::Compiler.new(engine_options).call(ast)
|
95
|
+
end
|
96
|
+
|
97
|
+
def engine_options
|
98
|
+
Hamlit::Engine.options.to_h.merge(
|
99
|
+
escape_attrs: options[:escape_attrs],
|
100
|
+
escape_html: options[:escape_html],
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Flexible default_task, compatible with haml's CLI
|
105
|
+
def method_missing(*args)
|
106
|
+
return super(*args) if args.length > 1
|
107
|
+
render(args.first.to_s)
|
108
|
+
end
|
109
|
+
|
110
|
+
def puts_code(code, color: false)
|
111
|
+
if color
|
112
|
+
require 'pry'
|
113
|
+
puts Pry.Code(code).highlighted
|
114
|
+
else
|
115
|
+
puts code
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Enable colored pretty printing only for development environment.
|
120
|
+
def pp_object(arg, color: false)
|
121
|
+
if color
|
122
|
+
require 'pry'
|
123
|
+
Pry::ColorPrinter.pp(arg)
|
124
|
+
else
|
125
|
+
require 'pp'
|
126
|
+
pp(arg)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'hamlit/compiler/children_compiler'
|
3
|
+
require 'hamlit/compiler/comment_compiler'
|
4
|
+
require 'hamlit/compiler/doctype_compiler'
|
5
|
+
require 'hamlit/compiler/script_compiler'
|
6
|
+
require 'hamlit/compiler/silent_script_compiler'
|
7
|
+
require 'hamlit/compiler/tag_compiler'
|
8
|
+
require 'hamlit/filters'
|
9
|
+
require 'hamlit/identity'
|
10
|
+
|
11
|
+
module Hamlit
|
12
|
+
class Compiler
|
13
|
+
def initialize(options = {})
|
14
|
+
identity = Identity.new
|
15
|
+
@children_compiler = ChildrenCompiler.new
|
16
|
+
@comment_compiler = CommentCompiler.new
|
17
|
+
@doctype_compiler = DoctypeCompiler.new(options)
|
18
|
+
@filter_compiler = Filters.new(options)
|
19
|
+
@script_compiler = ScriptCompiler.new(identity)
|
20
|
+
@silent_script_compiler = SilentScriptCompiler.new
|
21
|
+
@tag_compiler = TagCompiler.new(identity, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(ast)
|
25
|
+
return runtime_error(ast) if ast.is_a?(HamlError)
|
26
|
+
compile(ast)
|
27
|
+
rescue Error => e
|
28
|
+
runtime_error(e)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def compile(node)
|
34
|
+
case node.type
|
35
|
+
when :root
|
36
|
+
compile_children(node)
|
37
|
+
when :comment
|
38
|
+
compile_comment(node)
|
39
|
+
when :doctype
|
40
|
+
compile_doctype(node)
|
41
|
+
when :filter
|
42
|
+
compile_filter(node)
|
43
|
+
when :plain
|
44
|
+
compile_plain(node)
|
45
|
+
when :script
|
46
|
+
compile_script(node)
|
47
|
+
when :silent_script
|
48
|
+
compile_silent_script(node)
|
49
|
+
when :tag
|
50
|
+
compile_tag(node)
|
51
|
+
when :haml_comment
|
52
|
+
[:multi]
|
53
|
+
else
|
54
|
+
raise InternalError.new("Unexpected node type: #{node.type}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def compile_children(node)
|
59
|
+
@children_compiler.compile(node) { |n| compile(n) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def compile_comment(node)
|
63
|
+
@comment_compiler.compile(node) { |n| compile_children(n) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def compile_doctype(node)
|
67
|
+
@doctype_compiler.compile(node)
|
68
|
+
end
|
69
|
+
|
70
|
+
def compile_filter(node)
|
71
|
+
@filter_compiler.compile(node)
|
72
|
+
end
|
73
|
+
|
74
|
+
def compile_plain(node)
|
75
|
+
[:static, node.value[:text]]
|
76
|
+
end
|
77
|
+
|
78
|
+
def compile_script(node)
|
79
|
+
@script_compiler.compile(node) { |n| compile_children(n) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def compile_silent_script(node)
|
83
|
+
@silent_script_compiler.compile(node) { |n| compile_children(n) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def compile_tag(node)
|
87
|
+
@tag_compiler.compile(node) { |n| compile_children(n) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def runtime_error(error)
|
91
|
+
[:multi].tap do |temple|
|
92
|
+
error.line.times { temple << [:newline] } if error.line
|
93
|
+
temple << [:code, %Q[raise #{error.class}.new(%q[#{error.message}], #{error.line.inspect})]]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Hamlit
|
3
|
+
class Compiler
|
4
|
+
class ChildrenCompiler
|
5
|
+
def initialize
|
6
|
+
@lineno = 1
|
7
|
+
end
|
8
|
+
|
9
|
+
def compile(node, &block)
|
10
|
+
temple = [:multi]
|
11
|
+
return temple if node.children.empty?
|
12
|
+
|
13
|
+
temple << :whitespace if prepend_whitespace?(node)
|
14
|
+
node.children.each do |n|
|
15
|
+
rstrip_whitespace!(temple) if nuke_prev_whitespace?(n)
|
16
|
+
insert_newlines!(temple, n)
|
17
|
+
temple << yield(n)
|
18
|
+
temple << :whitespace if insert_whitespace?(n)
|
19
|
+
end
|
20
|
+
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
|
21
|
+
confirm_whitespace(temple)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def insert_newlines!(temple, node)
|
27
|
+
(node.line - @lineno).times do
|
28
|
+
temple << [:newline]
|
29
|
+
end
|
30
|
+
@lineno = node.line
|
31
|
+
|
32
|
+
case node.type
|
33
|
+
when :script, :silent_script
|
34
|
+
@lineno += 1
|
35
|
+
when :filter
|
36
|
+
@lineno += (node.value[:text] || '').split("\n").size
|
37
|
+
when :tag
|
38
|
+
node.value[:attributes_hashes].each do |attribute_hash|
|
39
|
+
@lineno += attribute_hash.count("\n")
|
40
|
+
end
|
41
|
+
@lineno += 1 if node.children.empty? && node.value[:parse]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def confirm_whitespace(temple)
|
46
|
+
temple.map do |exp|
|
47
|
+
case exp
|
48
|
+
when :whitespace
|
49
|
+
[:static, "\n"]
|
50
|
+
else
|
51
|
+
exp
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def prepend_whitespace?(node)
|
57
|
+
return false unless %i[comment tag].include?(node.type)
|
58
|
+
!nuke_inner_whitespace?(node)
|
59
|
+
end
|
60
|
+
|
61
|
+
def nuke_inner_whitespace?(node)
|
62
|
+
case
|
63
|
+
when node.type == :tag
|
64
|
+
node.value[:nuke_inner_whitespace]
|
65
|
+
when node.parent.nil?
|
66
|
+
false
|
67
|
+
else
|
68
|
+
nuke_inner_whitespace?(node.parent)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def nuke_prev_whitespace?(node)
|
73
|
+
case node.type
|
74
|
+
when :tag
|
75
|
+
node.value[:nuke_outer_whitespace]
|
76
|
+
when :silent_script
|
77
|
+
!node.children.empty? && nuke_prev_whitespace?(node.children.first)
|
78
|
+
else
|
79
|
+
false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def nuke_outer_whitespace?(node)
|
84
|
+
return false if node.type != :tag
|
85
|
+
node.value[:nuke_outer_whitespace]
|
86
|
+
end
|
87
|
+
|
88
|
+
def rstrip_whitespace!(temple)
|
89
|
+
if temple[-1] == :whitespace
|
90
|
+
temple.delete_at(-1)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def insert_whitespace?(node)
|
95
|
+
return false if nuke_outer_whitespace?(node)
|
96
|
+
|
97
|
+
case node.type
|
98
|
+
when :doctype
|
99
|
+
node.value[:type] != 'xml'
|
100
|
+
when :comment, :plain, :tag
|
101
|
+
true
|
102
|
+
when :script
|
103
|
+
node.children.empty? && !nuke_inner_whitespace?(node)
|
104
|
+
when :filter
|
105
|
+
!%w[ruby].include?(node.value[:name])
|
106
|
+
else
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|