bade 0.1.4 → 0.2.0
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 +1 -0
- data/Gemfile +3 -0
- data/README.md +3 -2
- data/lib/bade.rb +1 -0
- data/lib/bade/ast/document.rb +53 -0
- data/lib/bade/ast/node.rb +50 -0
- data/lib/bade/ast/node/doctype_node.rb +25 -0
- data/lib/bade/ast/node/key_value_node.rb +21 -0
- data/lib/bade/ast/node/mixin_node.rb +45 -0
- data/lib/bade/ast/node/tag_node.rb +23 -0
- data/lib/bade/ast/node/value_node.rb +32 -0
- data/lib/bade/ast/node_registrator.rb +82 -0
- data/lib/bade/ast/string_serializer.rb +72 -0
- data/lib/bade/generator.rb +353 -6
- data/lib/bade/parser.rb +199 -129
- data/lib/bade/precompiled.rb +61 -0
- data/lib/bade/renderer.rb +151 -31
- data/lib/bade/ruby_extensions/array.rb +45 -0
- data/lib/bade/ruby_extensions/string.rb +50 -20
- data/lib/bade/runtime.rb +2 -0
- data/lib/bade/runtime/block.rb +56 -10
- data/lib/bade/runtime/mixin.rb +43 -0
- data/lib/bade/runtime/render_binding.rb +53 -9
- data/lib/bade/version.rb +2 -1
- metadata +16 -14
- data/lib/bade/document.rb +0 -33
- data/lib/bade/generator/html_generator.rb +0 -80
- data/lib/bade/generator/ruby_generator.rb +0 -336
- data/lib/bade/node.rb +0 -116
- data/lib/bade/node/doctype_node.rb +0 -21
- data/lib/bade/node/key_value_node.rb +0 -10
- data/lib/bade/node/mixin_node.rb +0 -69
- data/lib/bade/node/tag_node.rb +0 -29
- data/lib/bade/ruby_extensions/object.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab630e2e6b7eec2139fbc4b14699985eefed370a
|
4
|
+
data.tar.gz: a132ae2fd1e1fd2d39dc8a9957f1e410dfcc821b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2624ab09740f0ee43309ffef7de6d5508e3880576ee0c461902b5762012c096ce7e829dcab577f1913fc29755956dc0cee256168e8d45bb579c3e81e9f6e0478
|
7
|
+
data.tar.gz: f859d3d06ca8bc9d1303c6afe7fa96f5a8e5a8a96d6c2d0bd67542392c2a9e4c29bb5736254786f051a6408b72db94ea41fabe415f7cdd10637ac3b26e2dea1b
|
data/Bade.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.summary = %q{Minimalistic template engine for Ruby.}
|
15
15
|
spec.homepage = 'https://github.com/epuber-io/bade'
|
16
16
|
spec.license = 'MIT'
|
17
|
+
spec.required_ruby_version = '>= 2.0'
|
17
18
|
|
18
19
|
spec.files = Dir['bin/**/*'] + Dir['lib/**/*'] + %w(Bade.gemspec Gemfile README.md)
|
19
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,8 @@ Minimalistic template engine written in Ruby for Ruby. Developed mainly to help
|
|
8
8
|
|
9
9
|
The language is in development state, breaking changes can be made in future. Current version supports minimal list of features to make it working in production for my purposes.
|
10
10
|
|
11
|
+
This gem acts only as library, it does not provide CLI tool, yet.
|
12
|
+
|
11
13
|
|
12
14
|
## Installation
|
13
15
|
|
@@ -19,7 +21,7 @@ gem 'bade'
|
|
19
21
|
|
20
22
|
And then execute:
|
21
23
|
|
22
|
-
$ bundle
|
24
|
+
$ bundle install
|
23
25
|
|
24
26
|
Or install it yourself as:
|
25
27
|
|
@@ -40,7 +42,6 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/epuber
|
|
40
42
|
|
41
43
|
## TODO
|
42
44
|
|
43
|
-
- [ ] move all cards from Trello to GitHub
|
44
45
|
- [ ] create documentation about syntax
|
45
46
|
- [ ] create several examples
|
46
47
|
|
data/lib/bade.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'node'
|
4
|
+
|
5
|
+
|
6
|
+
module Bade
|
7
|
+
module AST
|
8
|
+
class Document
|
9
|
+
# Root node of this document
|
10
|
+
#
|
11
|
+
# @return [Bade::Node]
|
12
|
+
#
|
13
|
+
attr_reader :root
|
14
|
+
|
15
|
+
# Path to this document, but only if it is defined from file
|
16
|
+
#
|
17
|
+
# @return [String, nil]
|
18
|
+
#
|
19
|
+
attr_reader :file_path
|
20
|
+
|
21
|
+
# @return [Array<Bade::Document>]
|
22
|
+
#
|
23
|
+
attr_reader :sub_documents
|
24
|
+
|
25
|
+
# @param root [Bade::Node]
|
26
|
+
#
|
27
|
+
def initialize(root: Node.new(:root), file_path: nil)
|
28
|
+
@root = root
|
29
|
+
|
30
|
+
@file_path = file_path.dup.freeze unless file_path.nil?
|
31
|
+
@sub_documents = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def freeze
|
35
|
+
super
|
36
|
+
|
37
|
+
root.freeze
|
38
|
+
sub_documents.freeze
|
39
|
+
sub_documents.each(&:freeze)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param other [Bade::Document]
|
43
|
+
#
|
44
|
+
# @return [Bool]
|
45
|
+
#
|
46
|
+
def ==(other)
|
47
|
+
return false unless Document === other
|
48
|
+
|
49
|
+
root == other.root && sub_documents == other.sub_documents
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
module Bade
|
5
|
+
module AST
|
6
|
+
class Node
|
7
|
+
# --- MAIN INFO ---
|
8
|
+
|
9
|
+
# @return [Symbol] type of this node
|
10
|
+
#
|
11
|
+
attr_reader :type
|
12
|
+
|
13
|
+
# @return [Array<Bade::Node>]
|
14
|
+
#
|
15
|
+
attr_accessor :children
|
16
|
+
|
17
|
+
# --- METADATA ---
|
18
|
+
|
19
|
+
# @return [Int] line number
|
20
|
+
#
|
21
|
+
attr_reader :lineno
|
22
|
+
|
23
|
+
def initialize(type, lineno: nil)
|
24
|
+
@type = type
|
25
|
+
@children = []
|
26
|
+
|
27
|
+
@lineno = lineno
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
require_relative 'string_serializer'
|
32
|
+
StringSerializer.new(self).to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param other [Node]
|
40
|
+
#
|
41
|
+
# @return [Bool]
|
42
|
+
#
|
43
|
+
def ==(other)
|
44
|
+
return false unless self.class == other.class
|
45
|
+
|
46
|
+
type == other.type && children == other.children
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../node'
|
4
|
+
|
5
|
+
|
6
|
+
module Bade
|
7
|
+
module AST
|
8
|
+
class DoctypeNode < ValueNode
|
9
|
+
# @return [String]
|
10
|
+
#
|
11
|
+
def xml_output
|
12
|
+
case value
|
13
|
+
when 'xml'
|
14
|
+
'<?xml version="1.0" encoding="utf-8" ?>'
|
15
|
+
|
16
|
+
when 'html'
|
17
|
+
'<!DOCTYPE html>'
|
18
|
+
|
19
|
+
else
|
20
|
+
raise Parser::ParserInternalError 'Unknown doctype type'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bade
|
4
|
+
module AST
|
5
|
+
class KeyValueNode < Node
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @return [Any]
|
11
|
+
#
|
12
|
+
attr_accessor :value
|
13
|
+
|
14
|
+
# @param other [KeyValueNode]
|
15
|
+
#
|
16
|
+
def ==(other)
|
17
|
+
super && name == other.name && value == other.value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bade
|
4
|
+
module AST
|
5
|
+
class MixinCommonNode < Node
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @return [Array<Node>]
|
11
|
+
#
|
12
|
+
def params
|
13
|
+
children.select { |n| allowed_parameter_types.include?(n.type) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [MixinCommonNode] other
|
17
|
+
#
|
18
|
+
def ==(other)
|
19
|
+
super && name == other.name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class MixinDeclarationNode < MixinCommonNode
|
24
|
+
def allowed_parameter_types
|
25
|
+
[:mixin_param, :mixin_key_param, :mixin_block_param]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class MixinBlockNode < MixinCommonNode
|
30
|
+
def allowed_parameter_types
|
31
|
+
[:mixin_param, :mixin_key_param]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class MixinCallNode < MixinCommonNode
|
36
|
+
def allowed_parameter_types
|
37
|
+
[:mixin_param, :mixin_key_param]
|
38
|
+
end
|
39
|
+
|
40
|
+
def blocks
|
41
|
+
children.select { |a| a.type == :mixin_block }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bade
|
4
|
+
module AST
|
5
|
+
class TagNode < Node
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @param [TagNode] other
|
11
|
+
#
|
12
|
+
def ==(other)
|
13
|
+
super && name == other.name
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array<KeyValueNode>]
|
17
|
+
#
|
18
|
+
def attributes
|
19
|
+
children.select { |n| n.type == :tag_attr }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bade
|
4
|
+
module AST
|
5
|
+
class ValueNode < Node
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
attr_accessor :value
|
9
|
+
|
10
|
+
# @return [Bool]
|
11
|
+
#
|
12
|
+
attr_accessor :escaped
|
13
|
+
|
14
|
+
# @return [Bool]
|
15
|
+
#
|
16
|
+
attr_accessor :conditional
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
super
|
20
|
+
|
21
|
+
@escaped = false
|
22
|
+
@conditional = false
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [ValueNode] other
|
26
|
+
#
|
27
|
+
def ==(other)
|
28
|
+
super && value == other.value && escaped == other.escaped && conditional == other.conditional
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
module Bade
|
5
|
+
module AST
|
6
|
+
class NodeRegistrator
|
7
|
+
require_relative 'node/key_value_node'
|
8
|
+
require_relative 'node/tag_node'
|
9
|
+
require_relative 'node/value_node'
|
10
|
+
require_relative 'node/mixin_node'
|
11
|
+
require_relative 'node/doctype_node'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# @return [Hash<Symbol, Class>]
|
15
|
+
#
|
16
|
+
def registered_types
|
17
|
+
@registered_types ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Method to map some node type to backing node class
|
21
|
+
#
|
22
|
+
# @param [Symbol] type type of the node
|
23
|
+
# @param [Class] klass registering class
|
24
|
+
#
|
25
|
+
# @return [nil]
|
26
|
+
#
|
27
|
+
def register_type(klass, type)
|
28
|
+
raise StandardError, "Class #{klass} should be subclass of #{Node}" unless klass <= Node
|
29
|
+
|
30
|
+
registered_types[type] = klass
|
31
|
+
end
|
32
|
+
|
33
|
+
# Method to create node backing instance
|
34
|
+
#
|
35
|
+
# @param [Symbol] type type of the node
|
36
|
+
# @param [Fixnum] lineno line number of the node appearance
|
37
|
+
#
|
38
|
+
# @return [Bade::AST::Node]
|
39
|
+
#
|
40
|
+
def create(type, lineno)
|
41
|
+
klass = registered_types[type]
|
42
|
+
|
43
|
+
if klass.nil?
|
44
|
+
raise ::KeyError, "Undefined node type #{type.inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
klass.new(type, lineno: lineno)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
register_type ValueNode, :text
|
52
|
+
register_type ValueNode, :newline
|
53
|
+
register_type ValueNode, :code
|
54
|
+
register_type ValueNode, :output
|
55
|
+
|
56
|
+
register_type DoctypeNode, :doctype
|
57
|
+
|
58
|
+
register_type ValueNode, :import
|
59
|
+
|
60
|
+
# --- Comments
|
61
|
+
|
62
|
+
register_type Node, :comment
|
63
|
+
register_type Node, :html_comment
|
64
|
+
|
65
|
+
# --- Tags
|
66
|
+
|
67
|
+
register_type TagNode, :tag
|
68
|
+
register_type KeyValueNode, :tag_attr
|
69
|
+
|
70
|
+
# --- Mixins
|
71
|
+
|
72
|
+
register_type ValueNode, :mixin_param
|
73
|
+
register_type KeyValueNode, :mixin_key_param
|
74
|
+
register_type ValueNode, :mixin_block_param
|
75
|
+
|
76
|
+
register_type MixinBlockNode, :mixin_block
|
77
|
+
|
78
|
+
register_type MixinCallNode, :mixin_call
|
79
|
+
register_type MixinDeclarationNode, :mixin_decl
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
module Bade
|
5
|
+
module AST
|
6
|
+
class StringSerializer
|
7
|
+
# @return [AST::Node, AST::Document]
|
8
|
+
#
|
9
|
+
attr_reader :root
|
10
|
+
|
11
|
+
# @param [AST::Node, AST::Document] root
|
12
|
+
#
|
13
|
+
def initialize(root)
|
14
|
+
@root = root
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
case root
|
19
|
+
when Node
|
20
|
+
node_to_s(root, 0)
|
21
|
+
when Document
|
22
|
+
node_to_s(root.root, 0)
|
23
|
+
else
|
24
|
+
raise AttributeError, "Root attribute passed into initializer must be subclass of #{Node} or #{Document}, is #{root.class}!"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [Node] node
|
29
|
+
# @param [Fixnum] level
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
#
|
33
|
+
def node_to_s(node, level)
|
34
|
+
type_s = node.type.inspect
|
35
|
+
indent = ' ' * level
|
36
|
+
|
37
|
+
children_s = ''
|
38
|
+
if node.children.count > 0
|
39
|
+
children_s = "\n" + node.children.map { |n| node_to_s(n, level + 1) }.join("\n") + "\n#{indent}"
|
40
|
+
end
|
41
|
+
|
42
|
+
other = ''
|
43
|
+
|
44
|
+
case node
|
45
|
+
when TagNode
|
46
|
+
other = node.name
|
47
|
+
when KeyValueNode
|
48
|
+
other = "#{node.name}:#{node.value}"
|
49
|
+
when ValueNode
|
50
|
+
escaped_sign = if node.escaped
|
51
|
+
'& '
|
52
|
+
elsif node.escaped.nil?
|
53
|
+
'&(nil) '
|
54
|
+
else
|
55
|
+
''
|
56
|
+
end
|
57
|
+
other = "#{escaped_sign}#{node.value}"
|
58
|
+
when MixinCommonNode
|
59
|
+
other = node.name
|
60
|
+
when Node
|
61
|
+
# nothing
|
62
|
+
else
|
63
|
+
raise "Unknown node class #{node.class} of type #{node.type} for serializing"
|
64
|
+
end
|
65
|
+
|
66
|
+
other = ' ' + other if other && other.length > 0
|
67
|
+
|
68
|
+
"#{indent}(#{type_s}#{other}#{children_s})"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|