bade 0.1.3
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 +7 -0
- data/Bade.gemspec +26 -0
- data/Gemfile +4 -0
- data/README.md +49 -0
- data/lib/bade/document.rb +33 -0
- data/lib/bade/generator/html_generator.rb +80 -0
- data/lib/bade/generator/ruby_generator.rb +336 -0
- data/lib/bade/generator.rb +16 -0
- data/lib/bade/node/doctype_node.rb +21 -0
- data/lib/bade/node/key_value_node.rb +10 -0
- data/lib/bade/node/mixin_node.rb +69 -0
- data/lib/bade/node/tag_node.rb +29 -0
- data/lib/bade/node.rb +116 -0
- data/lib/bade/parser.rb +652 -0
- data/lib/bade/renderer.rb +148 -0
- data/lib/bade/ruby_extensions/object.rb +11 -0
- data/lib/bade/ruby_extensions/string.rb +74 -0
- data/lib/bade/runtime/block.rb +40 -0
- data/lib/bade/runtime/render_binding.rb +53 -0
- data/lib/bade/runtime.rb +7 -0
- data/lib/bade/version.rb +4 -0
- data/lib/bade.rb +8 -0
- metadata +108 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
|
2
|
+
require_relative 'node'
|
3
|
+
require_relative 'parser'
|
4
|
+
require_relative 'generator'
|
5
|
+
require_relative 'runtime'
|
6
|
+
|
7
|
+
|
8
|
+
module Bade
|
9
|
+
class Renderer
|
10
|
+
# @return [String]
|
11
|
+
#
|
12
|
+
attr_accessor :source_text
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
attr_accessor :file_path
|
17
|
+
|
18
|
+
# @return [Hash]
|
19
|
+
#
|
20
|
+
attr_accessor :locals
|
21
|
+
|
22
|
+
# @param source [String]
|
23
|
+
#
|
24
|
+
# @return [self]
|
25
|
+
#
|
26
|
+
def self.from_source(source, file_path = nil)
|
27
|
+
inst = new
|
28
|
+
inst.source_text = source
|
29
|
+
inst.file_path = file_path
|
30
|
+
inst
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param file [String, File]
|
34
|
+
#
|
35
|
+
# @return [self]
|
36
|
+
#
|
37
|
+
def self.from_file(file)
|
38
|
+
file_obj = if file.is_a?(String)
|
39
|
+
File.new(file, 'r')
|
40
|
+
else
|
41
|
+
file
|
42
|
+
end
|
43
|
+
|
44
|
+
from_source(file_obj.read, file_obj.path)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
# absolute path => document
|
50
|
+
@parsed_documents = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# ----------------------------------------------------------------------------- #
|
55
|
+
# DSL methods
|
56
|
+
|
57
|
+
|
58
|
+
# @param locals [Hash]
|
59
|
+
#
|
60
|
+
# @return [self]
|
61
|
+
#
|
62
|
+
def with_locals(locals = {})
|
63
|
+
self.locals = locals
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# ----------------------------------------------------------------------------- #
|
69
|
+
# Getters
|
70
|
+
|
71
|
+
# @return [Bade::Node]
|
72
|
+
#
|
73
|
+
def root_document
|
74
|
+
@parsed ||= (
|
75
|
+
if file_path.nil?
|
76
|
+
_parse_document_from_text(source_text)
|
77
|
+
else
|
78
|
+
_parse_document_from_file(file_path)
|
79
|
+
end
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [String]
|
84
|
+
#
|
85
|
+
def lambda_string(new_line: '\n', indent: ' ')
|
86
|
+
RubyGenerator.document_to_lambda_string(root_document, new_line: new_line, indent: indent)
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# ----------------------------------------------------------------------------- #
|
91
|
+
# Render
|
92
|
+
|
93
|
+
# @return [String]
|
94
|
+
#
|
95
|
+
def render(binding: nil, new_line: '\n', indent: ' ')
|
96
|
+
lambda_str = lambda_string(new_line: new_line, indent: indent)
|
97
|
+
scope = binding || Runtime::RenderBinding.new(locals || {}).get_binding
|
98
|
+
|
99
|
+
lambda_instance = eval(lambda_str, scope, file_path || '(__template__)')
|
100
|
+
lambda_instance.call
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# @param file_path [String]
|
108
|
+
#
|
109
|
+
# @return [Bade::Document]
|
110
|
+
#
|
111
|
+
def _parse_document_from_file(file_path)
|
112
|
+
parser = Parser.new(file_path: file_path)
|
113
|
+
|
114
|
+
new_path = if File.exists?(file_path)
|
115
|
+
file_path
|
116
|
+
elsif File.exists?("#{file_path}.bade")
|
117
|
+
"#{file_path}.bade"
|
118
|
+
end
|
119
|
+
|
120
|
+
raise "Not existing file with path #{file_path}" if new_path.nil?
|
121
|
+
|
122
|
+
parsed_document = @parsed_documents[new_path]
|
123
|
+
return parsed_document unless parsed_document.nil?
|
124
|
+
|
125
|
+
document = parser.parse(File.read(new_path))
|
126
|
+
|
127
|
+
parser.dependency_paths.each do |path|
|
128
|
+
sub_path = File.expand_path(path, File.dirname(new_path))
|
129
|
+
document.sub_documents << _parse_document_from_file(sub_path)
|
130
|
+
end
|
131
|
+
|
132
|
+
document
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param text [String]
|
136
|
+
#
|
137
|
+
# @return [Bade::Document]
|
138
|
+
#
|
139
|
+
def _parse_document_from_text(text)
|
140
|
+
parser = Parser.new
|
141
|
+
document = parser.parse(text)
|
142
|
+
|
143
|
+
raise 'You cannot use import when it is loaded from source text' if parser.dependency_paths.length > 0
|
144
|
+
|
145
|
+
document
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Creates new string surrounded by single quotes
|
4
|
+
#
|
5
|
+
# @return [String]
|
6
|
+
#
|
7
|
+
def single_quote
|
8
|
+
%('#{self}')
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# Remove indent
|
13
|
+
#
|
14
|
+
# @param [Int] indent
|
15
|
+
# @param [Int] tabsize
|
16
|
+
#
|
17
|
+
def remove_indent(indent, tabsize)
|
18
|
+
self.dup.remove_indent!(indent, tabsize)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Remove indent
|
23
|
+
#
|
24
|
+
# @param [Int] indent
|
25
|
+
# @param [Int] tabsize
|
26
|
+
#
|
27
|
+
def remove_indent!(indent, tabsize)
|
28
|
+
count = 0
|
29
|
+
self.each_char do |char|
|
30
|
+
|
31
|
+
if indent <= 0
|
32
|
+
break
|
33
|
+
elsif char == ' '
|
34
|
+
indent -= 1
|
35
|
+
elsif char == "\t"
|
36
|
+
if indent - tabsize < 0
|
37
|
+
raise StandardError, 'malformed tabs'
|
38
|
+
end
|
39
|
+
|
40
|
+
indent -= tabsize
|
41
|
+
else
|
42
|
+
break
|
43
|
+
end
|
44
|
+
|
45
|
+
count += 1
|
46
|
+
end
|
47
|
+
|
48
|
+
self[0 ... self.length] = self[count ... self.length]
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Calculate indent for line
|
53
|
+
#
|
54
|
+
# @param [Int] tabsize
|
55
|
+
#
|
56
|
+
# @return [Int] indent size
|
57
|
+
#
|
58
|
+
def get_indent(tabsize)
|
59
|
+
count = 0
|
60
|
+
|
61
|
+
self.each_char do |char|
|
62
|
+
if char == ' '
|
63
|
+
count += 1
|
64
|
+
elsif char == "\t"
|
65
|
+
count += tabsize
|
66
|
+
else
|
67
|
+
break
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
count
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module Bade
|
3
|
+
module Runtime
|
4
|
+
class RuntimeError < ::StandardError; end
|
5
|
+
|
6
|
+
class Block
|
7
|
+
|
8
|
+
# @return [Proc]
|
9
|
+
#
|
10
|
+
attr_reader :block
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# @param [String] name
|
17
|
+
#
|
18
|
+
def initialize(name, &block)
|
19
|
+
@name = name
|
20
|
+
@block = lambda &block unless block.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(*args)
|
24
|
+
@block.call(*args) unless @block.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def call!(*args)
|
28
|
+
if @block.nil?
|
29
|
+
raise RuntimeError, "`#{@name}` must have block definition"
|
30
|
+
else
|
31
|
+
@block.call(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def block(name, &block)
|
38
|
+
Runtime::Block.new(name, &block)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require_relative 'block'
|
3
|
+
|
4
|
+
module Bade
|
5
|
+
module Runtime
|
6
|
+
class RenderBinding
|
7
|
+
class KeyError < ::StandardError; end
|
8
|
+
|
9
|
+
# @param vars [Hash]
|
10
|
+
#
|
11
|
+
def initialize(vars = {})
|
12
|
+
@vars = vars
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(name, *args)
|
16
|
+
raise KeyError, "Not found value for key `#{name}'" unless @vars.key?(name)
|
17
|
+
@vars[name]
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Binding]
|
21
|
+
#
|
22
|
+
def get_binding
|
23
|
+
binding
|
24
|
+
end
|
25
|
+
|
26
|
+
# Shortcut for creating blocks
|
27
|
+
#
|
28
|
+
def __create_block(*args, &block)
|
29
|
+
Bade::Runtime::Block.new(*args, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Escape input text with html escapes
|
33
|
+
#
|
34
|
+
# @param [String] text
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
#
|
38
|
+
def html_escaped(text)
|
39
|
+
text.sub('&', '&')
|
40
|
+
.sub('<', '<')
|
41
|
+
.sub('>', '>')
|
42
|
+
.sub('"', '"')
|
43
|
+
end
|
44
|
+
|
45
|
+
def tag_render_attribute(name, *values)
|
46
|
+
values = values.compact
|
47
|
+
return if values.empty?
|
48
|
+
|
49
|
+
%Q{ #{name}="#{values.join(' ')}"}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/bade/runtime.rb
ADDED
data/lib/bade/version.rb
ADDED
data/lib/bade.rb
ADDED
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bade
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roman Kříž
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.4'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- samnung@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- Bade.gemspec
|
63
|
+
- Gemfile
|
64
|
+
- README.md
|
65
|
+
- lib/bade.rb
|
66
|
+
- lib/bade/document.rb
|
67
|
+
- lib/bade/generator.rb
|
68
|
+
- lib/bade/generator/html_generator.rb
|
69
|
+
- lib/bade/generator/ruby_generator.rb
|
70
|
+
- lib/bade/node.rb
|
71
|
+
- lib/bade/node/doctype_node.rb
|
72
|
+
- lib/bade/node/key_value_node.rb
|
73
|
+
- lib/bade/node/mixin_node.rb
|
74
|
+
- lib/bade/node/tag_node.rb
|
75
|
+
- lib/bade/parser.rb
|
76
|
+
- lib/bade/renderer.rb
|
77
|
+
- lib/bade/ruby_extensions/object.rb
|
78
|
+
- lib/bade/ruby_extensions/string.rb
|
79
|
+
- lib/bade/runtime.rb
|
80
|
+
- lib/bade/runtime/block.rb
|
81
|
+
- lib/bade/runtime/render_binding.rb
|
82
|
+
- lib/bade/version.rb
|
83
|
+
homepage: https://github.com/samnung/bade
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.4.5.1
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Minimalistic template engine for Ruby.
|
107
|
+
test_files: []
|
108
|
+
has_rdoc:
|