bade 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7fce9a16c6a092fa176cd6adf94f87f09dc805ef
4
- data.tar.gz: dd198f4a76c878eac584c0a03c5269f6174055c2
3
+ metadata.gz: ab630e2e6b7eec2139fbc4b14699985eefed370a
4
+ data.tar.gz: a132ae2fd1e1fd2d39dc8a9957f1e410dfcc821b
5
5
  SHA512:
6
- metadata.gz: 18c57022d6ababf11353a754bf99890fab414b21b6e4e64542f2543a8f79a74b53f1548555ffee7bfb0757932d651290bdf7b4b464889c11bbd8e105f1d755e1
7
- data.tar.gz: 4fc5473929741d309c794671c2508dea40a60f42ea2f8910756f8fcbc42c32aa1accf9bfd4fa9d41501ec3cef2324e9bb0a669a483be19a21739bd41062051e7
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
@@ -3,3 +3,6 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'coveralls', require: false
6
+ gem 'benchmark-ips', require: false
7
+ gem 'ruby-prof'
8
+ gem 'flamegraph'
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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Bade
3
4
  require_relative 'bade/version'
@@ -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