bade 0.2.5 → 0.3.2
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 +4 -4
- data/Bade.gemspec +5 -4
- data/Gemfile +6 -2
- data/README.md +3 -3
- data/lib/bade/ast/document.rb +1 -1
- data/lib/bade/ast/node/value_node.rb +10 -1
- data/lib/bade/ast/node.rb +12 -2
- data/lib/bade/ast/node_registrator.rb +3 -2
- data/lib/bade/ast/string_serializer.rb +3 -5
- data/lib/bade/generator.rb +74 -19
- data/lib/bade/parser/parser_lines.rb +8 -6
- data/lib/bade/parser/parser_mixin.rb +7 -1
- data/lib/bade/parser.rb +5 -3
- data/lib/bade/precompiled.rb +2 -2
- data/lib/bade/renderer.rb +66 -20
- data/lib/bade/ruby2_keywords.rb +1 -0
- data/lib/bade/ruby_extensions/string.rb +3 -11
- data/lib/bade/runtime/block.rb +47 -9
- data/lib/bade/runtime/globals_tracker.rb +88 -0
- data/lib/bade/runtime/mixin.rb +21 -6
- data/lib/bade/runtime/render_binding.rb +56 -13
- data/lib/bade/runtime/utils/where.rb +101 -0
- data/lib/bade/runtime.rb +108 -1
- data/lib/bade/version.rb +1 -1
- data/lib/bade.rb +1 -0
- metadata +17 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5a90545fdee8d531bb87e12dd7943c0486daf3eac68f1d0c69ba216c7595f452
|
|
4
|
+
data.tar.gz: cdbf2cbc427cb9dd590768d493f99c91f22ac51a0a3caa172abb0b6c96b81b57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88708cad2d3145bfe33fb2ca65acbd795b3f8b3074da64f53e8d053d09925a3f750627893c303c2000fe4e9e8328abf4b9fe60a8e1c925a4ccb8966f37887fff
|
|
7
|
+
data.tar.gz: 8b21e240977c4f4c0c0387c244dcfb215141e453e04fde9f47762cb59ec22f43ee8056a17c39f41037d52b2a3d2bde8f66ad2b7623d8f8819f9444eebb075741
|
data/Bade.gemspec
CHANGED
|
@@ -14,16 +14,17 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.summary = 'Minimalistic template engine for Ruby.'
|
|
15
15
|
spec.homepage = 'https://github.com/epuber-io/bade'
|
|
16
16
|
spec.license = 'MIT'
|
|
17
|
-
spec.
|
|
17
|
+
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
|
18
|
+
spec.required_ruby_version = '>= 2.5'
|
|
18
19
|
|
|
19
20
|
spec.files = Dir['bin/**/*'] + Dir['lib/**/*'] + %w[Bade.gemspec Gemfile README.md]
|
|
20
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
22
23
|
spec.require_paths = ['lib']
|
|
23
24
|
|
|
24
|
-
spec.add_dependency 'psych', '>= 2.2', '<
|
|
25
|
+
spec.add_dependency 'psych', '>= 2.2', '< 5.0'
|
|
25
26
|
|
|
26
|
-
spec.add_development_dependency '
|
|
27
|
+
spec.add_development_dependency 'fakefs', '~> 1.3'
|
|
27
28
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
|
28
|
-
spec.add_development_dependency 'rubocop', '~>
|
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 1.14'
|
|
29
30
|
end
|
data/Gemfile
CHANGED
|
@@ -5,9 +5,13 @@ source 'https://rubygems.org'
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
gem 'benchmark-ips', require: false
|
|
8
|
-
gem 'coveralls', require: false
|
|
9
8
|
|
|
10
|
-
group :
|
|
9
|
+
group :dev, optional: true do
|
|
10
|
+
gem 'debase', require: false
|
|
11
|
+
gem 'ruby-debug-ide', require: false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
group :benchmarks, optional: true do
|
|
11
15
|
gem 'flamegraph'
|
|
12
16
|
gem 'ruby-prof'
|
|
13
17
|
end
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
# Bade
|
|
3
3
|
|
|
4
|
-
[](http://badge.fury.io/rb/bade) [](http://badge.fury.io/rb/bade) [](https://github.com/epuber-io/bade/actions) [](https://coveralls.io/github/epuber-io/bade?branch=master) [](https://inch-ci.org/github/epuber-io/bade)
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Minimalistic template engine written in Ruby for Ruby. Developed mainly to help with creating e-books. Highly influenced by [Jade](http://jade-lang.com) and [Slim](http://slim-lang.com).
|
|
@@ -30,7 +30,7 @@ Or install it yourself as:
|
|
|
30
30
|
|
|
31
31
|
## Development
|
|
32
32
|
|
|
33
|
-
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
|
|
33
|
+
After checking out the repo, run `bundle install --with dev` to install dependencies. Then, run `rake spec` to run the tests.
|
|
34
34
|
|
|
35
35
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
36
36
|
|
|
@@ -40,7 +40,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
|
|
|
40
40
|
Bug reports and pull requests are welcome on GitHub at https://github.com/epuber-io/bade. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## TODO
|
|
44
44
|
|
|
45
45
|
- [ ] create documentation about syntax
|
|
46
46
|
- [ ] create several examples
|
data/lib/bade/ast/document.rb
CHANGED
|
@@ -17,17 +17,26 @@ module Bade
|
|
|
17
17
|
#
|
|
18
18
|
attr_accessor :conditional
|
|
19
19
|
|
|
20
|
+
# @return [String, nil]
|
|
21
|
+
#
|
|
22
|
+
attr_accessor :default_value
|
|
23
|
+
|
|
20
24
|
ruby2_keywords def initialize(*args)
|
|
21
25
|
super(*args)
|
|
22
26
|
|
|
23
27
|
@escaped = false
|
|
24
28
|
@conditional = false
|
|
29
|
+
@default_value = nil
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
# @param [ValueNode] other
|
|
28
33
|
#
|
|
29
34
|
def ==(other)
|
|
30
|
-
super &&
|
|
35
|
+
super &&
|
|
36
|
+
value == other.value &&
|
|
37
|
+
escaped == other.escaped &&
|
|
38
|
+
conditional == other.conditional &&
|
|
39
|
+
default_value == other.default_value
|
|
31
40
|
end
|
|
32
41
|
end
|
|
33
42
|
end
|
data/lib/bade/ast/node.rb
CHANGED
|
@@ -10,7 +10,11 @@ module Bade
|
|
|
10
10
|
#
|
|
11
11
|
attr_reader :type
|
|
12
12
|
|
|
13
|
-
# @return [
|
|
13
|
+
# @return [Bade::AST::Node, nil]
|
|
14
|
+
#
|
|
15
|
+
attr_accessor :parent
|
|
16
|
+
|
|
17
|
+
# @return [Array<Bade::AST::Node>]
|
|
14
18
|
#
|
|
15
19
|
attr_accessor :children
|
|
16
20
|
|
|
@@ -20,10 +24,16 @@ module Bade
|
|
|
20
24
|
#
|
|
21
25
|
attr_reader :lineno
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
# @return [String] filename
|
|
28
|
+
#
|
|
29
|
+
attr_reader :filename
|
|
30
|
+
|
|
31
|
+
def initialize(type, parent = nil, lineno: nil, filename: nil)
|
|
24
32
|
@type = type
|
|
33
|
+
@parent = parent
|
|
25
34
|
@children = []
|
|
26
35
|
@lineno = lineno
|
|
36
|
+
@filename = filename
|
|
27
37
|
end
|
|
28
38
|
|
|
29
39
|
def to_s
|
|
@@ -38,12 +38,12 @@ module Bade
|
|
|
38
38
|
#
|
|
39
39
|
# @return [Bade::AST::Node]
|
|
40
40
|
#
|
|
41
|
-
def create(type, lineno)
|
|
41
|
+
def create(type, parent, lineno: nil, filename: nil)
|
|
42
42
|
klass = registered_types[type]
|
|
43
43
|
|
|
44
44
|
raise ::KeyError, "Undefined node type #{type.inspect}" if klass.nil?
|
|
45
45
|
|
|
46
|
-
klass.new(type, lineno: lineno)
|
|
46
|
+
klass.new(type, parent, lineno: lineno, filename: filename)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -55,6 +55,7 @@ module Bade
|
|
|
55
55
|
register_type DoctypeNode, :doctype
|
|
56
56
|
|
|
57
57
|
register_type ValueNode, :import
|
|
58
|
+
register_type ValueNode, :yield
|
|
58
59
|
|
|
59
60
|
# --- Comments
|
|
60
61
|
|
|
@@ -37,13 +37,13 @@ module Bade
|
|
|
37
37
|
|
|
38
38
|
children_s = ''
|
|
39
39
|
if node.children.count > 0
|
|
40
|
-
children_s = "\n
|
|
40
|
+
children_s = "\n#{node.children.map { |n| node_to_s(n, level + 1) }.join("\n")}\n#{indent}"
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
other = ''
|
|
44
44
|
|
|
45
45
|
case node
|
|
46
|
-
when TagNode
|
|
46
|
+
when TagNode, MixinCommonNode
|
|
47
47
|
other = node.name
|
|
48
48
|
when KeyValueNode
|
|
49
49
|
other = "#{node.name}:#{node.value}"
|
|
@@ -56,15 +56,13 @@ module Bade
|
|
|
56
56
|
''
|
|
57
57
|
end
|
|
58
58
|
other = "#{escaped_sign}#{node.value}"
|
|
59
|
-
when MixinCommonNode
|
|
60
|
-
other = node.name
|
|
61
59
|
when Node
|
|
62
60
|
# nothing
|
|
63
61
|
else
|
|
64
62
|
raise "Unknown node class #{node.class} of type #{node.type} for serializing"
|
|
65
63
|
end
|
|
66
64
|
|
|
67
|
-
other =
|
|
65
|
+
other = " #{other}" if other && !other.empty?
|
|
68
66
|
|
|
69
67
|
"#{indent}(#{type_s}#{other}#{children_s})"
|
|
70
68
|
end
|
data/lib/bade/generator.rb
CHANGED
|
@@ -41,6 +41,7 @@ module Bade
|
|
|
41
41
|
code_indent do
|
|
42
42
|
buff_code "self.#{NEW_LINE_NAME} = #{NEW_LINE_NAME}"
|
|
43
43
|
buff_code "self.#{BASE_INDENT_NAME} = #{BASE_INDENT_NAME}"
|
|
44
|
+
buff_code "__buffs_push(#{location(filename: document.file_path, lineno: 0, label: '<top>')})"
|
|
44
45
|
|
|
45
46
|
visit_document(document)
|
|
46
47
|
|
|
@@ -75,7 +76,7 @@ module Bade
|
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def buff_code(text)
|
|
78
|
-
@buff << ' ' * @code_indent
|
|
79
|
+
@buff << "#{' ' * @code_indent}#{text}"
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
# @param document [Bade::Document]
|
|
@@ -115,6 +116,8 @@ module Bade
|
|
|
115
116
|
# @param current_node [Node]
|
|
116
117
|
#
|
|
117
118
|
def visit_node(current_node)
|
|
119
|
+
update_location_node(current_node)
|
|
120
|
+
|
|
118
121
|
case current_node.type
|
|
119
122
|
when :root
|
|
120
123
|
visit_node_children(current_node)
|
|
@@ -134,7 +137,7 @@ module Bade
|
|
|
134
137
|
buff_print_text ' -->'
|
|
135
138
|
|
|
136
139
|
when :comment
|
|
137
|
-
comment_text =
|
|
140
|
+
comment_text = "##{current_node.children.map(&:value).join("\n#")}"
|
|
138
141
|
buff_code(comment_text)
|
|
139
142
|
|
|
140
143
|
when :doctype
|
|
@@ -166,8 +169,11 @@ module Bade
|
|
|
166
169
|
"#{base_path}.rb"
|
|
167
170
|
end
|
|
168
171
|
|
|
169
|
-
buff_code "
|
|
170
|
-
|
|
172
|
+
buff_code "__load('#{load_path}')" unless load_path.nil?
|
|
173
|
+
when :yield
|
|
174
|
+
block_name = DEFAULT_BLOCK_NAME
|
|
175
|
+
method = current_node.conditional ? 'call' : 'call!'
|
|
176
|
+
buff_code "#{block_name}.#{method}"
|
|
171
177
|
else
|
|
172
178
|
raise "Unknown type #{current_node.type}"
|
|
173
179
|
end
|
|
@@ -267,19 +273,22 @@ module Bade
|
|
|
267
273
|
params = mixin_node.params
|
|
268
274
|
result = []
|
|
269
275
|
|
|
270
|
-
|
|
276
|
+
case mixin_node.type
|
|
277
|
+
when :mixin_call
|
|
271
278
|
blocks = mixin_node.blocks
|
|
272
279
|
|
|
273
280
|
other_children = (mixin_node.children - mixin_node.blocks - mixin_node.params)
|
|
274
281
|
if other_children.count { |n| n.type != :newline } > 0
|
|
275
|
-
def_block_node = AST::NodeRegistrator.create(:mixin_block, mixin_node.lineno)
|
|
282
|
+
def_block_node = AST::NodeRegistrator.create(:mixin_block, mixin_node, lineno: mixin_node.lineno)
|
|
276
283
|
def_block_node.name = DEFAULT_BLOCK_NAME
|
|
277
284
|
def_block_node.children = other_children
|
|
278
285
|
|
|
279
286
|
blocks << def_block_node
|
|
280
287
|
end
|
|
281
288
|
|
|
282
|
-
if
|
|
289
|
+
if blocks.empty?
|
|
290
|
+
result << '{}'
|
|
291
|
+
else
|
|
283
292
|
buff_code '__blocks = {}'
|
|
284
293
|
|
|
285
294
|
blocks.each do |block|
|
|
@@ -287,17 +296,18 @@ module Bade
|
|
|
287
296
|
end
|
|
288
297
|
|
|
289
298
|
result << '__blocks.dup'
|
|
290
|
-
else
|
|
291
|
-
result << '{}'
|
|
292
299
|
end
|
|
293
|
-
|
|
300
|
+
when :mixin_decl
|
|
294
301
|
result << '__blocks'
|
|
295
302
|
end
|
|
296
303
|
|
|
304
|
+
# positional params
|
|
305
|
+
result += params.select { |n| n.type == :mixin_param }
|
|
306
|
+
.map { |param| param.default_value ? "#{param.value} = #{param.default_value}" : param.value }
|
|
297
307
|
|
|
298
|
-
#
|
|
299
|
-
result += params.select { |n| n.type == :
|
|
300
|
-
|
|
308
|
+
# key-value params
|
|
309
|
+
result += params.select { |n| n.type == :mixin_key_param }
|
|
310
|
+
.map { |param| "#{param.name}: #{param.value}" }
|
|
301
311
|
|
|
302
312
|
result.join(', ')
|
|
303
313
|
end
|
|
@@ -309,14 +319,10 @@ module Bade
|
|
|
309
319
|
# @return [nil]
|
|
310
320
|
#
|
|
311
321
|
def block_definition(block_node)
|
|
312
|
-
buff_code "__blocks['#{block_node.name}'] = __create_block('#{block_node.name}') do"
|
|
322
|
+
buff_code "__blocks['#{block_node.name}'] = __create_block('#{block_node.name}', #{location_node(block_node)}) do"
|
|
313
323
|
|
|
314
324
|
code_indent do
|
|
315
|
-
buff_code '__buffs_push()'
|
|
316
|
-
|
|
317
325
|
visit_node_children(block_node)
|
|
318
|
-
|
|
319
|
-
buff_code '__buffs_pop()'
|
|
320
326
|
end
|
|
321
327
|
|
|
322
328
|
buff_code 'end'
|
|
@@ -350,7 +356,7 @@ module Bade
|
|
|
350
356
|
#
|
|
351
357
|
def visit_block_decl(current_node)
|
|
352
358
|
params = formatted_mixin_params(current_node)
|
|
353
|
-
buff_code "#{MIXINS_NAME}['#{current_node.name}'] = __create_mixin('#{current_node.name}', &lambda { |#{params}|"
|
|
359
|
+
buff_code "#{MIXINS_NAME}['#{current_node.name}'] = __create_mixin('#{current_node.name}', #{location_node(current_node)}, &lambda { |#{params}|"
|
|
354
360
|
|
|
355
361
|
code_indent do
|
|
356
362
|
blocks_name_declaration(current_node)
|
|
@@ -367,6 +373,55 @@ module Bade
|
|
|
367
373
|
def escape_double_quotes!(str)
|
|
368
374
|
str.gsub!(/"/, '\"')
|
|
369
375
|
end
|
|
376
|
+
|
|
377
|
+
# @param [Bade::AST::Node]
|
|
378
|
+
# @return [Void]
|
|
379
|
+
def update_location_node(node)
|
|
380
|
+
should_skip = case node.type
|
|
381
|
+
when :code
|
|
382
|
+
value = node.value.strip
|
|
383
|
+
|
|
384
|
+
%w[end else }].include?(value) || value.match(/^(when|elsif) /)
|
|
385
|
+
when :newline
|
|
386
|
+
true
|
|
387
|
+
else
|
|
388
|
+
false
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
return if should_skip
|
|
392
|
+
return if node.lineno.nil?
|
|
393
|
+
|
|
394
|
+
buff_code "__update_lineno(#{node.lineno})"
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# @param [String] filename
|
|
398
|
+
# @param [Fixnum] lineno
|
|
399
|
+
# @param [String] label
|
|
400
|
+
# @return [String]
|
|
401
|
+
def location(filename:, lineno:, label:)
|
|
402
|
+
args = [
|
|
403
|
+
filename ? "path: '#{filename}'" : nil,
|
|
404
|
+
"lineno: #{lineno}",
|
|
405
|
+
"label: '#{label}'",
|
|
406
|
+
].compact
|
|
407
|
+
|
|
408
|
+
"Location.new(#{args.join(',')})"
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
# @param [Node] node
|
|
412
|
+
# @return [String]
|
|
413
|
+
def location_node(node)
|
|
414
|
+
label = case node.type
|
|
415
|
+
when :mixin_decl
|
|
416
|
+
"+#{node.name}"
|
|
417
|
+
when :mixin_block
|
|
418
|
+
"#{node.name} in +#{node.parent.name}"
|
|
419
|
+
else
|
|
420
|
+
node.name
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
location(filename: node.filename, lineno: node.lineno, label: label)
|
|
424
|
+
end
|
|
370
425
|
end
|
|
371
426
|
|
|
372
427
|
# backward compatibility
|
|
@@ -7,6 +7,7 @@ module Bade
|
|
|
7
7
|
class Parser
|
|
8
8
|
module LineIndicatorRegexps
|
|
9
9
|
IMPORT = /\Aimport /.freeze
|
|
10
|
+
YIELD = /\Ayield(!?)/.freeze
|
|
10
11
|
MIXIN_DECL = /\Amixin #{NAME_RE_STRING}/.freeze
|
|
11
12
|
MIXIN_CALL = /\A\+#{NAME_RE_STRING}/.freeze
|
|
12
13
|
BLOCK_DECLARATION = /\Ablock #{NAME_RE_STRING}/.freeze
|
|
@@ -135,6 +136,11 @@ module Bade
|
|
|
135
136
|
@line = $'
|
|
136
137
|
parse_import
|
|
137
138
|
|
|
139
|
+
when LineIndicatorRegexps::YIELD
|
|
140
|
+
@line = $'
|
|
141
|
+
node = append_node(:yield, add: true)
|
|
142
|
+
node.conditional = $1.nil?
|
|
143
|
+
|
|
138
144
|
when LineIndicatorRegexps::MIXIN_DECL
|
|
139
145
|
# Mixin declaration
|
|
140
146
|
@line = $'
|
|
@@ -195,12 +201,8 @@ module Bade
|
|
|
195
201
|
@line = $' if $1
|
|
196
202
|
parse_tag($&)
|
|
197
203
|
|
|
198
|
-
when LineIndicatorRegexps::TAG_CLASS_START_BLOCK
|
|
199
|
-
# Found class
|
|
200
|
-
parse_tag 'div'
|
|
201
|
-
|
|
202
|
-
when LineIndicatorRegexps::TAG_ID_START_BLOCK
|
|
203
|
-
# Found id name -> implicit div
|
|
204
|
+
when LineIndicatorRegexps::TAG_CLASS_START_BLOCK, LineIndicatorRegexps::TAG_ID_START_BLOCK
|
|
205
|
+
# Found a class or id selector.
|
|
204
206
|
parse_tag 'div'
|
|
205
207
|
|
|
206
208
|
else
|
|
@@ -18,6 +18,7 @@ module Bade
|
|
|
18
18
|
PARAMS_PARAM_NAME = /\A\s*#{NAME_RE_STRING}/.freeze
|
|
19
19
|
PARAMS_BLOCK_NAME = /\A\s*&#{NAME_RE_STRING}/.freeze
|
|
20
20
|
PARAMS_KEY_PARAM_NAME = CODE_ATTR_RE
|
|
21
|
+
PARAMS_PARAM_DEFAULT_START = /\A\s*=/.freeze
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def parse_mixin_call(mixin_name)
|
|
@@ -114,7 +115,12 @@ module Bade
|
|
|
114
115
|
|
|
115
116
|
when MixinRegexps::PARAMS_PARAM_NAME
|
|
116
117
|
@line = $'
|
|
117
|
-
append_node(:mixin_param, value: $1)
|
|
118
|
+
attr_node = append_node(:mixin_param, value: $1)
|
|
119
|
+
|
|
120
|
+
if @line =~ MixinRegexps::PARAMS_PARAM_DEFAULT_START
|
|
121
|
+
@line = $'
|
|
122
|
+
attr_node.default_value = parse_ruby_code(ParseRubyCodeRegexps::END_PARAMS_ARG)
|
|
123
|
+
end
|
|
118
124
|
|
|
119
125
|
when MixinRegexps::PARAMS_BLOCK_NAME
|
|
120
126
|
@line = $'
|
data/lib/bade/parser.rb
CHANGED
|
@@ -17,6 +17,8 @@ module Bade
|
|
|
17
17
|
attr_reader :error, :file, :line, :lineno, :column
|
|
18
18
|
|
|
19
19
|
def initialize(error, file, line, lineno, column)
|
|
20
|
+
super(error)
|
|
21
|
+
|
|
20
22
|
@error = error
|
|
21
23
|
@file = file || '(__TEMPLATE__)'
|
|
22
24
|
@line = line.to_s
|
|
@@ -27,7 +29,7 @@ module Bade
|
|
|
27
29
|
def to_s
|
|
28
30
|
line = @line.lstrip
|
|
29
31
|
column = @column + line.size - @line.size
|
|
30
|
-
|
|
32
|
+
<<~MSG
|
|
31
33
|
#{error}
|
|
32
34
|
#{file}, Line #{lineno}, Column #{@column}
|
|
33
35
|
#{line}
|
|
@@ -60,7 +62,7 @@ module Bade
|
|
|
60
62
|
@file_path = file_path
|
|
61
63
|
|
|
62
64
|
@tab_re = /\G((?: {#{tabsize}})*) {0,#{tabsize - 1}}\t/
|
|
63
|
-
@tab =
|
|
65
|
+
@tab = "\1#{' ' * tabsize}"
|
|
64
66
|
|
|
65
67
|
reset
|
|
66
68
|
end
|
|
@@ -106,7 +108,7 @@ module Bade
|
|
|
106
108
|
@stacks << @stacks.last.dup while indent >= @stacks.length
|
|
107
109
|
|
|
108
110
|
parent = @stacks[indent].last
|
|
109
|
-
node = AST::NodeRegistrator.create(type, @lineno)
|
|
111
|
+
node = AST::NodeRegistrator.create(type, parent, lineno: @lineno, filename: @file_path)
|
|
110
112
|
parent.children << node
|
|
111
113
|
|
|
112
114
|
node.value = value unless value.nil?
|
data/lib/bade/precompiled.rb
CHANGED
|
@@ -26,9 +26,9 @@ module Bade
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
hash = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.0')
|
|
29
|
-
|
|
29
|
+
Psych.safe_load(file, filename: file.path, permitted_classes: [Symbol])
|
|
30
30
|
else
|
|
31
|
-
|
|
31
|
+
Psych.safe_load(file, [Symbol])
|
|
32
32
|
end
|
|
33
33
|
raise LoadError, 'YAML file is not in valid format' unless hash.is_a?(Hash)
|
|
34
34
|
|
data/lib/bade/renderer.rb
CHANGED
|
@@ -9,7 +9,7 @@ require_relative 'precompiled'
|
|
|
9
9
|
|
|
10
10
|
module Bade
|
|
11
11
|
class Renderer
|
|
12
|
-
class LoadError < ::RuntimeError
|
|
12
|
+
class LoadError < Bade::Runtime::RuntimeError
|
|
13
13
|
# @return [String]
|
|
14
14
|
#
|
|
15
15
|
attr_reader :loading_path
|
|
@@ -22,18 +22,29 @@ module Bade
|
|
|
22
22
|
# @param [String] reference_path reference file from which is load performed
|
|
23
23
|
# @param [String] msg standard message
|
|
24
24
|
#
|
|
25
|
-
def initialize(loading_path, reference_path, msg =
|
|
26
|
-
super(msg)
|
|
25
|
+
def initialize(loading_path, reference_path, msg, template_backtrace = [])
|
|
26
|
+
super(msg, template_backtrace)
|
|
27
27
|
@loading_path = loading_path
|
|
28
28
|
@reference_path = reference_path
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
class << self
|
|
33
|
+
def _globals_tracker
|
|
34
|
+
@globals_tracker ||= Bade::Runtime::GlobalsTracker.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# When set to true it will remove all constants that template created. Off by default.
|
|
38
|
+
#
|
|
39
|
+
# @return [Boolean]
|
|
40
|
+
attr_accessor :clear_constants
|
|
34
41
|
end
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
# @param clear_constants [Boolean] When set to true it will remove all constants that template created. Off by default.
|
|
44
|
+
def initialize(clear_constants: Bade::Renderer.clear_constants)
|
|
45
|
+
@optimize = false
|
|
46
|
+
@clear_constants = clear_constants
|
|
47
|
+
end
|
|
37
48
|
|
|
38
49
|
# @return [String]
|
|
39
50
|
#
|
|
@@ -59,6 +70,10 @@ module Bade
|
|
|
59
70
|
#
|
|
60
71
|
attr_accessor :optimize
|
|
61
72
|
|
|
73
|
+
# @return [Boolean] When set to true it will remove all constants that template created. Off by default.
|
|
74
|
+
#
|
|
75
|
+
attr_accessor :clear_constants
|
|
76
|
+
|
|
62
77
|
|
|
63
78
|
# ----------------------------------------------------------------------------- #
|
|
64
79
|
# Internal attributes
|
|
@@ -77,8 +92,8 @@ module Bade
|
|
|
77
92
|
#
|
|
78
93
|
# @return [Renderer] preconfigured instance of this class
|
|
79
94
|
#
|
|
80
|
-
def self.from_source(source, file_path = nil)
|
|
81
|
-
inst = new
|
|
95
|
+
def self.from_source(source, file_path = nil, clear_constants: Bade::Renderer.clear_constants)
|
|
96
|
+
inst = new(clear_constants: clear_constants)
|
|
82
97
|
inst.source_text = source
|
|
83
98
|
inst.file_path = file_path
|
|
84
99
|
inst
|
|
@@ -88,14 +103,14 @@ module Bade
|
|
|
88
103
|
#
|
|
89
104
|
# @return [Renderer] preconfigured instance of this class
|
|
90
105
|
#
|
|
91
|
-
def self.from_file(file)
|
|
106
|
+
def self.from_file(file, clear_constants: Bade::Renderer.clear_constants)
|
|
92
107
|
path = if file.is_a?(File)
|
|
93
108
|
file.path
|
|
94
109
|
else
|
|
95
110
|
file
|
|
96
111
|
end
|
|
97
112
|
|
|
98
|
-
from_source(nil, path)
|
|
113
|
+
from_source(nil, path, clear_constants: clear_constants)
|
|
99
114
|
end
|
|
100
115
|
|
|
101
116
|
# Method to create Renderer from Precompiled object, for example when you want to reuse precompiled object from disk
|
|
@@ -104,8 +119,8 @@ module Bade
|
|
|
104
119
|
#
|
|
105
120
|
# @return [Renderer] preconfigured instance of this class
|
|
106
121
|
#
|
|
107
|
-
def self.from_precompiled(precompiled)
|
|
108
|
-
inst = new
|
|
122
|
+
def self.from_precompiled(precompiled, clear_constants: Bade::Renderer.clear_constants)
|
|
123
|
+
inst = new(clear_constants: clear_constants)
|
|
109
124
|
inst.precompiled = precompiled
|
|
110
125
|
inst
|
|
111
126
|
end
|
|
@@ -125,11 +140,20 @@ module Bade
|
|
|
125
140
|
self
|
|
126
141
|
end
|
|
127
142
|
|
|
143
|
+
# @return [self]
|
|
128
144
|
def with_binding(binding)
|
|
129
145
|
self.lambda_binding = binding
|
|
130
146
|
self
|
|
131
147
|
end
|
|
132
148
|
|
|
149
|
+
# @param [RenderBinding] binding
|
|
150
|
+
# @return [self]
|
|
151
|
+
def with_render_binding(binding)
|
|
152
|
+
self.lambda_binding = nil
|
|
153
|
+
self.render_binding = binding
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
|
|
133
157
|
def optimized
|
|
134
158
|
self.optimize = true
|
|
135
159
|
self
|
|
@@ -173,10 +197,12 @@ module Bade
|
|
|
173
197
|
# @return [Proc]
|
|
174
198
|
#
|
|
175
199
|
def lambda_instance
|
|
176
|
-
|
|
177
|
-
lambda_binding
|
|
178
|
-
|
|
179
|
-
|
|
200
|
+
_catching_globals do
|
|
201
|
+
if lambda_binding
|
|
202
|
+
lambda_binding.eval(lambda_string, file_path || Bade::Runtime::TEMPLATE_FILE_NAME)
|
|
203
|
+
else
|
|
204
|
+
render_binding.instance_eval(lambda_string, file_path || Bade::Runtime::TEMPLATE_FILE_NAME)
|
|
205
|
+
end
|
|
180
206
|
end
|
|
181
207
|
end
|
|
182
208
|
|
|
@@ -197,13 +223,22 @@ module Bade
|
|
|
197
223
|
Generator::NEW_LINE_NAME.to_sym => new_line,
|
|
198
224
|
Generator::BASE_INDENT_NAME.to_sym => indent,
|
|
199
225
|
}
|
|
200
|
-
run_vars.
|
|
226
|
+
run_vars.compact! # remove nil values
|
|
201
227
|
|
|
202
|
-
|
|
228
|
+
begin
|
|
229
|
+
return _catching_globals do
|
|
230
|
+
lambda_instance.call(**run_vars)
|
|
231
|
+
end
|
|
232
|
+
rescue Bade::Runtime::RuntimeError => e
|
|
233
|
+
raise e
|
|
234
|
+
rescue Exception => e
|
|
235
|
+
msg = "Exception raised during execution of template: #{e}"
|
|
236
|
+
raise Bade::Runtime::RuntimeError.wrap_existing_error(msg, e, render_binding.__location_stack)
|
|
237
|
+
ensure
|
|
238
|
+
self.class._globals_tracker.clear_constants if @clear_constants
|
|
239
|
+
end
|
|
203
240
|
end
|
|
204
241
|
|
|
205
|
-
|
|
206
|
-
|
|
207
242
|
private
|
|
208
243
|
|
|
209
244
|
# @param [String] content source code of the template
|
|
@@ -275,5 +310,16 @@ module Bade
|
|
|
275
310
|
end
|
|
276
311
|
end
|
|
277
312
|
end
|
|
313
|
+
|
|
314
|
+
def _catching_globals(&block)
|
|
315
|
+
if @clear_constants
|
|
316
|
+
self.class._globals_tracker.catch(&block)
|
|
317
|
+
else
|
|
318
|
+
block.call
|
|
319
|
+
end
|
|
320
|
+
end
|
|
278
321
|
end
|
|
279
322
|
end
|
|
323
|
+
|
|
324
|
+
# Set default value to clear_constants
|
|
325
|
+
Bade::Renderer.clear_constants = false
|
data/lib/bade/ruby2_keywords.rb
CHANGED