bade 0.2.4 → 0.3.1
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 +9 -8
- data/Gemfile +12 -3
- data/README.md +3 -3
- data/lib/bade/ast/document.rb +1 -1
- data/lib/bade/ast/node/mixin_node.rb +3 -3
- data/lib/bade/ast/node/static_text_node.rb +4 -2
- data/lib/bade/ast/node/value_node.rb +14 -3
- data/lib/bade/ast/node.rb +12 -3
- data/lib/bade/ast/node_registrator.rb +3 -2
- data/lib/bade/ast/string_serializer.rb +3 -5
- data/lib/bade/generator.rb +74 -24
- data/lib/bade/parser/parser_constants.rb +4 -4
- data/lib/bade/parser/parser_lines.rb +21 -19
- data/lib/bade/parser/parser_mixin.rb +17 -11
- data/lib/bade/parser/parser_ruby_code.rb +17 -7
- data/lib/bade/parser/parser_tag.rb +4 -4
- data/lib/bade/parser/parser_text.rb +3 -3
- data/lib/bade/parser.rb +7 -3
- data/lib/bade/precompiled.rb +6 -3
- data/lib/bade/renderer.rb +69 -20
- data/lib/bade/ruby2_keywords.rb +3 -0
- data/lib/bade/ruby_extensions/string.rb +4 -8
- data/lib/bade/runtime/block.rb +51 -11
- data/lib/bade/runtime/globals_tracker.rb +88 -0
- data/lib/bade/runtime/mixin.rb +47 -32
- data/lib/bade/runtime/render_binding.rb +56 -13
- data/lib/bade/runtime/utils/where.rb +101 -0
- data/lib/bade/runtime.rb +79 -1
- data/lib/bade/version.rb +1 -1
- data/lib/bade.rb +1 -0
- metadata +33 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9363fa63bbc18e9d9cb2af336438820127d766ef7e5b18306ddc37cdd608adfd
|
|
4
|
+
data.tar.gz: 6a6c86dea0211e852507fa26e7ec2d6d35b5b03469f5c6919455749134f102bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37b06b4ef4aa918a88e96c5bfd164ef5d41b9bc0e22949d857b3af143e6dcb462d41f8c10e880f29f4a201e0ca115309e4734e46268f0b1c6fc9f0c7c50802d2
|
|
7
|
+
data.tar.gz: a828c7d9c09450235b719c37381add83dcd0980d256f97b755dd6b5ceb287a1f6baca4f43a04c00523cf45a1d692aac6d7b7abd79f8b5694fe713f3686ceefa0
|
data/Bade.gemspec
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path('
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
|
6
6
|
require 'bade/version'
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
Gem::Specification.new do |spec|
|
|
10
9
|
spec.name = 'bade'
|
|
11
10
|
spec.version = Bade::VERSION
|
|
@@ -14,15 +13,17 @@ Gem::Specification.new do |spec|
|
|
|
14
13
|
spec.summary = 'Minimalistic template engine for Ruby.'
|
|
15
14
|
spec.homepage = 'https://github.com/epuber-io/bade'
|
|
16
15
|
spec.license = 'MIT'
|
|
17
|
-
spec.
|
|
16
|
+
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
|
17
|
+
spec.required_ruby_version = '>= 2.5'
|
|
18
18
|
|
|
19
|
-
spec.files = Dir['bin/**/*'] + Dir['lib/**/*'] + %w
|
|
19
|
+
spec.files = Dir['bin/**/*'] + Dir['lib/**/*'] + %w[Bade.gemspec Gemfile README.md]
|
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
22
22
|
spec.require_paths = ['lib']
|
|
23
23
|
|
|
24
|
-
spec.
|
|
24
|
+
spec.add_dependency 'psych', '>= 2.2', '< 5.0'
|
|
25
|
+
|
|
26
|
+
spec.add_development_dependency 'fakefs', '~> 1.3'
|
|
25
27
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
|
26
|
-
spec.add_development_dependency '
|
|
27
|
-
spec.add_development_dependency 'rubocop', '~> 0.35'
|
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 1.14'
|
|
28
29
|
end
|
data/Gemfile
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source 'https://rubygems.org'
|
|
2
4
|
|
|
3
5
|
gemspec
|
|
4
6
|
|
|
5
|
-
gem 'coveralls', require: false
|
|
6
7
|
gem 'benchmark-ips', require: false
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
|
|
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
|
|
15
|
+
gem 'flamegraph'
|
|
16
|
+
gem 'ruby-prof'
|
|
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
|
@@ -22,19 +22,19 @@ module Bade
|
|
|
22
22
|
|
|
23
23
|
class MixinDeclarationNode < MixinCommonNode
|
|
24
24
|
def allowed_parameter_types
|
|
25
|
-
[
|
|
25
|
+
%i[mixin_param mixin_key_param mixin_block_param]
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
class MixinBlockNode < MixinCommonNode
|
|
30
30
|
def allowed_parameter_types
|
|
31
|
-
[
|
|
31
|
+
%i[mixin_param mixin_key_param]
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
class MixinCallNode < MixinCommonNode
|
|
36
36
|
def allowed_parameter_types
|
|
37
|
-
[
|
|
37
|
+
%i[mixin_param mixin_key_param]
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def blocks
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../../ruby2_keywords'
|
|
4
|
+
|
|
3
5
|
module Bade
|
|
4
6
|
module AST
|
|
5
7
|
class StaticTextNode < Node
|
|
@@ -11,8 +13,8 @@ module Bade
|
|
|
11
13
|
#
|
|
12
14
|
attr_accessor :escaped
|
|
13
15
|
|
|
14
|
-
def initialize(*args)
|
|
15
|
-
super
|
|
16
|
+
ruby2_keywords def initialize(*args)
|
|
17
|
+
super(*args)
|
|
16
18
|
|
|
17
19
|
@escaped = false
|
|
18
20
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../../ruby2_keywords'
|
|
4
|
+
|
|
3
5
|
module Bade
|
|
4
6
|
module AST
|
|
5
7
|
class ValueNode < Node
|
|
@@ -15,17 +17,26 @@ module Bade
|
|
|
15
17
|
#
|
|
16
18
|
attr_accessor :conditional
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
# @return [String, nil]
|
|
21
|
+
#
|
|
22
|
+
attr_accessor :default_value
|
|
23
|
+
|
|
24
|
+
ruby2_keywords def initialize(*args)
|
|
25
|
+
super(*args)
|
|
20
26
|
|
|
21
27
|
@escaped = false
|
|
22
28
|
@conditional = false
|
|
29
|
+
@default_value = nil
|
|
23
30
|
end
|
|
24
31
|
|
|
25
32
|
# @param [ValueNode] other
|
|
26
33
|
#
|
|
27
34
|
def ==(other)
|
|
28
|
-
super &&
|
|
35
|
+
super &&
|
|
36
|
+
value == other.value &&
|
|
37
|
+
escaped == other.escaped &&
|
|
38
|
+
conditional == other.conditional &&
|
|
39
|
+
default_value == other.default_value
|
|
29
40
|
end
|
|
30
41
|
end
|
|
31
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,11 +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
|
-
|
|
27
35
|
@lineno = lineno
|
|
36
|
+
@filename = filename
|
|
28
37
|
end
|
|
29
38
|
|
|
30
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
|
@@ -75,10 +75,9 @@ module Bade
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def buff_code(text)
|
|
78
|
-
@buff << ' ' * @code_indent
|
|
78
|
+
@buff << "#{' ' * @code_indent}#{text}"
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
|
|
82
81
|
# @param document [Bade::Document]
|
|
83
82
|
#
|
|
84
83
|
def visit_document(document)
|
|
@@ -87,6 +86,7 @@ module Bade
|
|
|
87
86
|
end
|
|
88
87
|
|
|
89
88
|
buff_code("# ----- start file #{document.file_path}") unless document.file_path.nil?
|
|
89
|
+
buff_code "__buffs_push(#{location(filename: document.file_path, lineno: 0, label: '<top>')})"
|
|
90
90
|
|
|
91
91
|
new_root = if @optimize
|
|
92
92
|
Optimizer.new(document.root).optimize
|
|
@@ -116,6 +116,8 @@ module Bade
|
|
|
116
116
|
# @param current_node [Node]
|
|
117
117
|
#
|
|
118
118
|
def visit_node(current_node)
|
|
119
|
+
update_location_node(current_node)
|
|
120
|
+
|
|
119
121
|
case current_node.type
|
|
120
122
|
when :root
|
|
121
123
|
visit_node_children(current_node)
|
|
@@ -135,7 +137,7 @@ module Bade
|
|
|
135
137
|
buff_print_text ' -->'
|
|
136
138
|
|
|
137
139
|
when :comment
|
|
138
|
-
comment_text =
|
|
140
|
+
comment_text = "##{current_node.children.map(&:value).join("\n#")}"
|
|
139
141
|
buff_code(comment_text)
|
|
140
142
|
|
|
141
143
|
when :doctype
|
|
@@ -158,8 +160,7 @@ module Bade
|
|
|
158
160
|
buff_print_text output_code
|
|
159
161
|
|
|
160
162
|
when :newline
|
|
161
|
-
#
|
|
162
|
-
|
|
163
|
+
# no-op
|
|
163
164
|
when :import
|
|
164
165
|
base_path = File.expand_path(current_node.value, File.dirname(@document.file_path))
|
|
165
166
|
load_path = if base_path.end_with?('.rb') && File.exist?(base_path)
|
|
@@ -168,8 +169,11 @@ module Bade
|
|
|
168
169
|
"#{base_path}.rb"
|
|
169
170
|
end
|
|
170
171
|
|
|
171
|
-
buff_code "
|
|
172
|
-
|
|
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}"
|
|
173
177
|
else
|
|
174
178
|
raise "Unknown type #{current_node.type}"
|
|
175
179
|
end
|
|
@@ -269,19 +273,22 @@ module Bade
|
|
|
269
273
|
params = mixin_node.params
|
|
270
274
|
result = []
|
|
271
275
|
|
|
272
|
-
|
|
276
|
+
case mixin_node.type
|
|
277
|
+
when :mixin_call
|
|
273
278
|
blocks = mixin_node.blocks
|
|
274
279
|
|
|
275
280
|
other_children = (mixin_node.children - mixin_node.blocks - mixin_node.params)
|
|
276
281
|
if other_children.count { |n| n.type != :newline } > 0
|
|
277
|
-
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)
|
|
278
283
|
def_block_node.name = DEFAULT_BLOCK_NAME
|
|
279
284
|
def_block_node.children = other_children
|
|
280
285
|
|
|
281
286
|
blocks << def_block_node
|
|
282
287
|
end
|
|
283
288
|
|
|
284
|
-
if
|
|
289
|
+
if blocks.empty?
|
|
290
|
+
result << '{}'
|
|
291
|
+
else
|
|
285
292
|
buff_code '__blocks = {}'
|
|
286
293
|
|
|
287
294
|
blocks.each do |block|
|
|
@@ -289,17 +296,18 @@ module Bade
|
|
|
289
296
|
end
|
|
290
297
|
|
|
291
298
|
result << '__blocks.dup'
|
|
292
|
-
else
|
|
293
|
-
result << '{}'
|
|
294
299
|
end
|
|
295
|
-
|
|
300
|
+
when :mixin_decl
|
|
296
301
|
result << '__blocks'
|
|
297
302
|
end
|
|
298
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 }
|
|
299
307
|
|
|
300
|
-
#
|
|
301
|
-
result += params.select { |n| n.type == :
|
|
302
|
-
|
|
308
|
+
# key-value params
|
|
309
|
+
result += params.select { |n| n.type == :mixin_key_param }
|
|
310
|
+
.map { |param| "#{param.name}: #{param.value}" }
|
|
303
311
|
|
|
304
312
|
result.join(', ')
|
|
305
313
|
end
|
|
@@ -311,14 +319,10 @@ module Bade
|
|
|
311
319
|
# @return [nil]
|
|
312
320
|
#
|
|
313
321
|
def block_definition(block_node)
|
|
314
|
-
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"
|
|
315
323
|
|
|
316
324
|
code_indent do
|
|
317
|
-
buff_code '__buffs_push()'
|
|
318
|
-
|
|
319
325
|
visit_node_children(block_node)
|
|
320
|
-
|
|
321
|
-
buff_code '__buffs_pop()'
|
|
322
326
|
end
|
|
323
327
|
|
|
324
328
|
buff_code 'end'
|
|
@@ -352,7 +356,7 @@ module Bade
|
|
|
352
356
|
#
|
|
353
357
|
def visit_block_decl(current_node)
|
|
354
358
|
params = formatted_mixin_params(current_node)
|
|
355
|
-
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}|"
|
|
356
360
|
|
|
357
361
|
code_indent do
|
|
358
362
|
blocks_name_declaration(current_node)
|
|
@@ -362,8 +366,6 @@ module Bade
|
|
|
362
366
|
buff_code '})'
|
|
363
367
|
end
|
|
364
368
|
|
|
365
|
-
|
|
366
|
-
|
|
367
369
|
# @param [String] str
|
|
368
370
|
#
|
|
369
371
|
# @return [Void]
|
|
@@ -371,6 +373,54 @@ module Bade
|
|
|
371
373
|
def escape_double_quotes!(str)
|
|
372
374
|
str.gsub!(/"/, '\"')
|
|
373
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 /)
|
|
385
|
+
when :newline
|
|
386
|
+
true
|
|
387
|
+
else
|
|
388
|
+
false
|
|
389
|
+
end
|
|
390
|
+
return if should_skip
|
|
391
|
+
return if node.lineno.nil?
|
|
392
|
+
|
|
393
|
+
buff_code "__update_lineno(#{node.lineno})"
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# @param [String] filename
|
|
397
|
+
# @param [Fixnum] lineno
|
|
398
|
+
# @param [String] label
|
|
399
|
+
# @return [String]
|
|
400
|
+
def location(filename:, lineno:, label:)
|
|
401
|
+
args = [
|
|
402
|
+
filename ? "path: '#{filename}'" : nil,
|
|
403
|
+
"lineno: #{lineno}",
|
|
404
|
+
"label: '#{label}'",
|
|
405
|
+
].compact
|
|
406
|
+
|
|
407
|
+
"Location.new(#{args.join(',')})"
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# @param [Node] node
|
|
411
|
+
# @return [String]
|
|
412
|
+
def location_node(node)
|
|
413
|
+
label = case node.type
|
|
414
|
+
when :mixin_decl
|
|
415
|
+
"+#{node.name}"
|
|
416
|
+
when :mixin_block
|
|
417
|
+
"#{node.name} in +#{node.parent.name}"
|
|
418
|
+
else
|
|
419
|
+
node.name
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
location(filename: node.filename, lineno: node.lineno, label: label)
|
|
423
|
+
end
|
|
374
424
|
end
|
|
375
425
|
|
|
376
426
|
# backward compatibility
|
|
@@ -9,10 +9,10 @@ module Bade
|
|
|
9
9
|
NAME_RE_STRING = "(#{WORD_RE}(?:#{WORD_RE}|:|-|_)*)".freeze
|
|
10
10
|
|
|
11
11
|
ATTR_NAME_RE_STRING = "\\A\\s*#{NAME_RE_STRING}".freeze
|
|
12
|
-
CODE_ATTR_RE = /#{ATTR_NAME_RE_STRING}\s*&?:\s
|
|
12
|
+
CODE_ATTR_RE = /#{ATTR_NAME_RE_STRING}\s*&?:\s*/.freeze
|
|
13
13
|
|
|
14
|
-
TAG_RE = /\A#{NAME_RE_STRING}
|
|
15
|
-
CLASS_TAG_RE = /\A\.#{NAME_RE_STRING}
|
|
16
|
-
ID_TAG_RE = /\A##{NAME_RE_STRING}
|
|
14
|
+
TAG_RE = /\A#{NAME_RE_STRING}/.freeze
|
|
15
|
+
CLASS_TAG_RE = /\A\.#{NAME_RE_STRING}/.freeze
|
|
16
|
+
ID_TAG_RE = /\A##{NAME_RE_STRING}/.freeze
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -6,19 +6,20 @@ module Bade
|
|
|
6
6
|
|
|
7
7
|
class Parser
|
|
8
8
|
module LineIndicatorRegexps
|
|
9
|
-
IMPORT = /\Aimport
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
IMPORT = /\Aimport /.freeze
|
|
10
|
+
YIELD = /\Ayield(!?)/.freeze
|
|
11
|
+
MIXIN_DECL = /\Amixin #{NAME_RE_STRING}/.freeze
|
|
12
|
+
MIXIN_CALL = /\A\+#{NAME_RE_STRING}/.freeze
|
|
13
|
+
BLOCK_DECLARATION = /\Ablock #{NAME_RE_STRING}/.freeze
|
|
14
|
+
HTML_COMMENT = %r{\A//! }.freeze
|
|
15
|
+
NORMAL_COMMENT = %r{\A//}.freeze
|
|
16
|
+
TEXT_BLOCK_START = /\A\|( ?)/.freeze
|
|
17
|
+
INLINE_HTML = /\A</.freeze
|
|
18
|
+
CODE_BLOCK = /\A-/.freeze
|
|
19
|
+
OUTPUT_BLOCK = /\A(\??)(&?)=/.freeze
|
|
20
|
+
DOCTYPE = /\Adoctype\s/i.freeze
|
|
21
|
+
TAG_CLASS_START_BLOCK = /\A\./.freeze
|
|
22
|
+
TAG_ID_START_BLOCK = /\A#/.freeze
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def reset(lines = nil, stacks = nil)
|
|
@@ -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
|
|
@@ -6,18 +6,19 @@ module Bade
|
|
|
6
6
|
|
|
7
7
|
class Parser
|
|
8
8
|
module MixinRegexps
|
|
9
|
-
TEXT_START = /\A
|
|
10
|
-
BLOCK_EXPANSION = /\A:\s
|
|
11
|
-
OUTPUT_CODE = /\A(&?)
|
|
9
|
+
TEXT_START = /\A /.freeze
|
|
10
|
+
BLOCK_EXPANSION = /\A:\s+/.freeze
|
|
11
|
+
OUTPUT_CODE = /\A(&?)=/.freeze
|
|
12
12
|
|
|
13
|
-
PARAMS_END = /\A\s*\)
|
|
13
|
+
PARAMS_END = /\A\s*\)/.freeze
|
|
14
14
|
|
|
15
|
-
PARAMS_END_SPACES = /^\s
|
|
16
|
-
PARAMS_ARGS_DELIMITER = /\A\s
|
|
15
|
+
PARAMS_END_SPACES = /^\s*$/.freeze
|
|
16
|
+
PARAMS_ARGS_DELIMITER = /\A\s*,/.freeze
|
|
17
17
|
|
|
18
|
-
PARAMS_PARAM_NAME = /\A\s*#{NAME_RE_STRING}
|
|
19
|
-
PARAMS_BLOCK_NAME = /\A\s*&#{NAME_RE_STRING}
|
|
18
|
+
PARAMS_PARAM_NAME = /\A\s*#{NAME_RE_STRING}/.freeze
|
|
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)
|
|
@@ -64,7 +65,7 @@ module Bade
|
|
|
64
65
|
@line = $'
|
|
65
66
|
attr_node = append_node(:mixin_key_param)
|
|
66
67
|
attr_node.name = fixed_trailing_colon($1)
|
|
67
|
-
attr_node.value = parse_ruby_code(ParseRubyCodeRegexps::END_PARAMS_ARG)
|
|
68
|
+
attr_node.value = parse_ruby_code(ParseRubyCodeRegexps::END_PARAMS_ARG, allow_multiline: true)
|
|
68
69
|
|
|
69
70
|
when MixinRegexps::PARAMS_ARGS_DELIMITER
|
|
70
71
|
# args delimiter
|
|
@@ -83,7 +84,7 @@ module Bade
|
|
|
83
84
|
|
|
84
85
|
else
|
|
85
86
|
attr_node = append_node(:mixin_param)
|
|
86
|
-
attr_node.value = parse_ruby_code(ParseRubyCodeRegexps::END_PARAMS_ARG)
|
|
87
|
+
attr_node.value = parse_ruby_code(ParseRubyCodeRegexps::END_PARAMS_ARG, allow_multiline: true)
|
|
87
88
|
end
|
|
88
89
|
end
|
|
89
90
|
end
|
|
@@ -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 = $'
|
|
@@ -6,8 +6,8 @@ module Bade
|
|
|
6
6
|
|
|
7
7
|
class Parser
|
|
8
8
|
module ParseRubyCodeRegexps
|
|
9
|
-
END_NEW_LINE = /\A\s*\n
|
|
10
|
-
END_PARAMS_ARG = /\A\s*[,)]
|
|
9
|
+
END_NEW_LINE = /\A\s*\n/.freeze
|
|
10
|
+
END_PARAMS_ARG = /\A\s*[,)]/.freeze
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# Parse ruby code, ended with outer delimiters
|
|
@@ -16,17 +16,27 @@ module Bade
|
|
|
16
16
|
#
|
|
17
17
|
# @return [Void] parsed ruby code
|
|
18
18
|
#
|
|
19
|
-
def parse_ruby_code(outer_delimiters)
|
|
19
|
+
def parse_ruby_code(outer_delimiters, allow_multiline: false)
|
|
20
20
|
code = String.new
|
|
21
21
|
end_re = if outer_delimiters.is_a?(Regexp)
|
|
22
22
|
outer_delimiters
|
|
23
23
|
else
|
|
24
24
|
/\A\s*[#{Regexp.escape outer_delimiters.to_s}]/
|
|
25
25
|
end
|
|
26
|
+
|
|
26
27
|
delimiters = []
|
|
27
28
|
string_start_quote_char = nil
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
loop do
|
|
31
|
+
break if !allow_multiline && @line.empty?
|
|
32
|
+
break if allow_multiline && @line.empty? && (@lines && @lines.empty?)
|
|
33
|
+
break if delimiters.empty? && @line =~ end_re
|
|
34
|
+
|
|
35
|
+
if @line.empty? && allow_multiline && !(@lines && @lines.empty?)
|
|
36
|
+
next_line
|
|
37
|
+
code << "\n"
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
char = @line[0]
|
|
31
41
|
|
|
32
42
|
# backslash escaped delimiter
|
|
@@ -70,7 +80,7 @@ module Bade
|
|
|
70
80
|
'{' => '}',
|
|
71
81
|
}.freeze
|
|
72
82
|
|
|
73
|
-
RUBY_QUOTES = %w
|
|
83
|
+
RUBY_QUOTES = %w[' "].freeze
|
|
74
84
|
|
|
75
85
|
RUBY_NOT_NESTABLE_DELIMITERS = RUBY_QUOTES
|
|
76
86
|
|
|
@@ -78,7 +88,7 @@ module Bade
|
|
|
78
88
|
RUBY_END_DELIMITERS = (%w(\) ] }) + RUBY_NOT_NESTABLE_DELIMITERS).freeze
|
|
79
89
|
RUBY_ALL_DELIMITERS = (RUBY_START_DELIMITERS + RUBY_END_DELIMITERS).uniq.freeze
|
|
80
90
|
|
|
81
|
-
RUBY_START_DELIMITERS_RE = /\A[#{Regexp.escape RUBY_START_DELIMITERS.join}]
|
|
82
|
-
RUBY_END_DELIMITERS_RE = /\A[#{Regexp.escape RUBY_END_DELIMITERS.join}]
|
|
91
|
+
RUBY_START_DELIMITERS_RE = /\A[#{Regexp.escape RUBY_START_DELIMITERS.join}]/.freeze
|
|
92
|
+
RUBY_END_DELIMITERS_RE = /\A[#{Regexp.escape RUBY_END_DELIMITERS.join}]/.freeze
|
|
83
93
|
end
|
|
84
94
|
end
|