bade 0.2.5 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/bade.svg)](http://badge.fury.io/rb/bade) [![Build Status](https://
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/bade.svg)](http://badge.fury.io/rb/bade) [![Build Status](https://github.com/epuber-io/bade/actions/workflows/tests.yml/badge.svg)](https://github.com/epuber-io/bade/actions) [![Coverage Status](https://coveralls.io/repos/epuber-io/bade/badge.svg?branch=master&service=github)](https://coveralls.io/github/epuber-io/bade?branch=master) [![Inline docs](https://inch-ci.org/github/epuber-io/bade.svg?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