tamale 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +55 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +17 -0
- data/README.md +27 -0
- data/Rakefile +5 -0
- data/lib/tamale.rb +236 -0
- data/lib/tamale/version.rb +3 -0
- data/spec/tamale_spec.rb +83 -0
- data/tamale.gemspec +12 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 69c3ea40f44ddfe39d514a8d03c9eaa338ff9180
|
4
|
+
data.tar.gz: 0cb42e2e2fcd1bddded53f1fe8132b28cb237540
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 326cc04edbb8fe4243cdec771f4fd311942be7d4a1da0239466e562b6ce385af34a9d4ee1b46fda34c81a5537a4495b872122eb58473ac6d02d9791063b0815e
|
7
|
+
data.tar.gz: 1a52ed8d6267a2b07f6c19605b341b258c852abe1432bd8ea2b3c9e6a5a09c3bcc6be76b0bc33f072d63f1e85d3b82e3af5740bd52235836291478d5ffdc340c
|
data/.gitignore
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
51
|
+
|
52
|
+
## Specific to macOS:
|
53
|
+
|
54
|
+
.DS_Store
|
55
|
+
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Tamale
|
2
|
+
|
3
|
+
Tamale is a DSL for generating HTML.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
For use with bundler, add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'tamale'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then run bundle from the command line:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
template = Tamale.new { |title|
|
21
|
+
div(id: 'app') {
|
22
|
+
h1 { text title }
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
template.render('Hot Tamale!')
|
27
|
+
```
|
data/Rakefile
ADDED
data/lib/tamale.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
class Tamale
|
2
|
+
def initialize(&template)
|
3
|
+
@template = template
|
4
|
+
end
|
5
|
+
|
6
|
+
def render(*args)
|
7
|
+
Context.new(@template, *args).call
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
module Tags
|
13
|
+
module Normal
|
14
|
+
TAGS = [
|
15
|
+
:a,
|
16
|
+
:abbr,
|
17
|
+
:acronym,
|
18
|
+
:address,
|
19
|
+
:applet,
|
20
|
+
:article,
|
21
|
+
:aside,
|
22
|
+
:audio,
|
23
|
+
:b,
|
24
|
+
:basefont,
|
25
|
+
:bdi,
|
26
|
+
:bdo,
|
27
|
+
:bgsound,
|
28
|
+
:big,
|
29
|
+
:blink,
|
30
|
+
:blockquote,
|
31
|
+
:body,
|
32
|
+
:button,
|
33
|
+
:canvas,
|
34
|
+
:caption,
|
35
|
+
:center,
|
36
|
+
:cite,
|
37
|
+
:code,
|
38
|
+
:colgroup,
|
39
|
+
:command,
|
40
|
+
:content,
|
41
|
+
:data,
|
42
|
+
:datalist,
|
43
|
+
:dd,
|
44
|
+
:del,
|
45
|
+
:details,
|
46
|
+
:dfn,
|
47
|
+
:dialog,
|
48
|
+
:dir,
|
49
|
+
:div,
|
50
|
+
:dl,
|
51
|
+
:dt,
|
52
|
+
:element,
|
53
|
+
:em,
|
54
|
+
:fieldset,
|
55
|
+
:figcaption,
|
56
|
+
:figure,
|
57
|
+
:font,
|
58
|
+
:footer,
|
59
|
+
:form,
|
60
|
+
:frame,
|
61
|
+
:frameset,
|
62
|
+
:h1,
|
63
|
+
:h2,
|
64
|
+
:h3,
|
65
|
+
:h4,
|
66
|
+
:h5,
|
67
|
+
:h6,
|
68
|
+
:head,
|
69
|
+
:header,
|
70
|
+
:hgroup,
|
71
|
+
:html,
|
72
|
+
:i,
|
73
|
+
:iframe,
|
74
|
+
:image,
|
75
|
+
:ins,
|
76
|
+
:isindex,
|
77
|
+
:kbd,
|
78
|
+
:label,
|
79
|
+
:legend,
|
80
|
+
:li,
|
81
|
+
:listing,
|
82
|
+
:main,
|
83
|
+
:map,
|
84
|
+
:mark,
|
85
|
+
:marquee,
|
86
|
+
:menu,
|
87
|
+
:meter,
|
88
|
+
:multicol,
|
89
|
+
:nav,
|
90
|
+
:nobr,
|
91
|
+
:noembed,
|
92
|
+
:noframes,
|
93
|
+
:noscript,
|
94
|
+
:object,
|
95
|
+
:ol,
|
96
|
+
:optgroup,
|
97
|
+
:option,
|
98
|
+
:output,
|
99
|
+
:p,
|
100
|
+
:picture,
|
101
|
+
:plaintext,
|
102
|
+
:pre,
|
103
|
+
:progress,
|
104
|
+
:q,
|
105
|
+
:rp,
|
106
|
+
:rt,
|
107
|
+
:rtc,
|
108
|
+
:ruby,
|
109
|
+
:s,
|
110
|
+
:samp,
|
111
|
+
:script,
|
112
|
+
:section,
|
113
|
+
:select,
|
114
|
+
:shadow,
|
115
|
+
:slot,
|
116
|
+
:small,
|
117
|
+
:spacer,
|
118
|
+
:span,
|
119
|
+
:strike,
|
120
|
+
:strong,
|
121
|
+
:style,
|
122
|
+
:sub,
|
123
|
+
:summary,
|
124
|
+
:sup,
|
125
|
+
:table,
|
126
|
+
:tbody,
|
127
|
+
:td,
|
128
|
+
:template,
|
129
|
+
:textarea,
|
130
|
+
:tfoot,
|
131
|
+
:th,
|
132
|
+
:thead,
|
133
|
+
:time,
|
134
|
+
:title,
|
135
|
+
:tr,
|
136
|
+
:tt,
|
137
|
+
:u,
|
138
|
+
:ul,
|
139
|
+
:var,
|
140
|
+
:video,
|
141
|
+
:xmp,
|
142
|
+
]
|
143
|
+
|
144
|
+
def self.format(opening, contents, closing)
|
145
|
+
"<#{opening}>#{contents}</#{closing}>"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
module Void
|
150
|
+
TAGS = [
|
151
|
+
:area,
|
152
|
+
:base,
|
153
|
+
:br,
|
154
|
+
:col,
|
155
|
+
:embed,
|
156
|
+
:hr,
|
157
|
+
:img,
|
158
|
+
:input,
|
159
|
+
:keygen,
|
160
|
+
:link,
|
161
|
+
:menuitem,
|
162
|
+
:meta,
|
163
|
+
:param,
|
164
|
+
:source,
|
165
|
+
:track,
|
166
|
+
:wbr,
|
167
|
+
]
|
168
|
+
|
169
|
+
def self.format(opening, contents, closing)
|
170
|
+
"<#{opening} />"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class Builder
|
176
|
+
def initialize(type)
|
177
|
+
@type = type
|
178
|
+
end
|
179
|
+
|
180
|
+
def tags
|
181
|
+
@type.const_get(:TAGS)
|
182
|
+
end
|
183
|
+
|
184
|
+
def build(tag, attributes, contents = nil)
|
185
|
+
opening = build_opening(tag, attributes)
|
186
|
+
|
187
|
+
@type.format(opening, contents, tag)
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def build_opening(tag, attributes)
|
193
|
+
attributes.keys.inject(tag) { |acc, key| acc << " #{key}=\"#{attributes[key]}\"" }
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Context
|
198
|
+
@@normal_builder = Builder.new(Tags::Normal).tap do |builder|
|
199
|
+
builder.tags.each do |tag|
|
200
|
+
class_eval <<-RUBY
|
201
|
+
def #{tag}(attributes = {})
|
202
|
+
contents = Context.new(Proc.new).call if block_given?
|
203
|
+
|
204
|
+
@acc << @@normal_builder.build('#{tag}', attributes, contents)
|
205
|
+
end
|
206
|
+
RUBY
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
@@void_builder = Builder.new(Tags::Void).tap do |builder|
|
211
|
+
builder.tags.each do |tag|
|
212
|
+
class_eval <<-RUBY
|
213
|
+
def #{tag}(attributes = {})
|
214
|
+
@acc << @@void_builder.build('#{tag}', attributes)
|
215
|
+
end
|
216
|
+
RUBY
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def initialize(template, *args)
|
221
|
+
@template = template
|
222
|
+
@args = args
|
223
|
+
@acc = ''
|
224
|
+
end
|
225
|
+
|
226
|
+
def call
|
227
|
+
instance_exec(*@args, &@template)
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def text(val)
|
233
|
+
@acc << val.to_s
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
data/spec/tamale_spec.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../lib/tamale'
|
3
|
+
|
4
|
+
describe 'Tamale#render' do
|
5
|
+
before do
|
6
|
+
@template = Tamale.new { |left, right|
|
7
|
+
text "#{left}#{right}"
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'calls template with arguments' do
|
12
|
+
assert_equal('foobar', @template.render('foo', 'bar'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'Text elements' do
|
17
|
+
before do
|
18
|
+
@template = Tamale.new { |value|
|
19
|
+
div { text 'simple' }
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'renders an html string' do
|
24
|
+
assert_equal('<div>simple</div>', @template.render)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'Nested elements' do
|
29
|
+
before do
|
30
|
+
@template = Tamale.new {
|
31
|
+
ul {
|
32
|
+
li { text 'one' }
|
33
|
+
li { text 'two' }
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'renders in proper context' do
|
39
|
+
assert_equal('<ul><li>one</li><li>two</li></ul>', @template.render)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'Multinested elements' do
|
44
|
+
before do
|
45
|
+
@template = Tamale.new {
|
46
|
+
ul {
|
47
|
+
li {
|
48
|
+
text 'one'; text 'two'
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'renders in proper context' do
|
55
|
+
assert_equal('<ul><li>onetwo</li></ul>', @template.render)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'Void elements' do
|
60
|
+
before do
|
61
|
+
@template = Tamale.new {
|
62
|
+
div {
|
63
|
+
input(type: 'text')
|
64
|
+
}
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'never prints a closing tag' do
|
69
|
+
assert_equal('<div><input type="text" /></div>', @template.render)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'Normal elements' do
|
74
|
+
before do
|
75
|
+
@template = Tamale.new {
|
76
|
+
div { div }
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'always prints a closing tag' do
|
81
|
+
assert_equal('<div><div></div></div>', @template.render)
|
82
|
+
end
|
83
|
+
end
|
data/tamale.gemspec
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative './lib/tamale/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'tamale'
|
5
|
+
s.summary = 'Tamale'
|
6
|
+
s.version = Tamale::VERSION
|
7
|
+
s.authors = ['Steve Weiss']
|
8
|
+
s.email = ['weissst@mail.gvsu.edu']
|
9
|
+
s.homepage = 'https://github.com/sirscriptalot/tamale'
|
10
|
+
s.license = 'MIT'
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tamale
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steve Weiss
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
- weissst@mail.gvsu.edu
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Gemfile
|
22
|
+
- Gemfile.lock
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- lib/tamale.rb
|
26
|
+
- lib/tamale/version.rb
|
27
|
+
- spec/tamale_spec.rb
|
28
|
+
- tamale.gemspec
|
29
|
+
homepage: https://github.com/sirscriptalot/tamale
|
30
|
+
licenses:
|
31
|
+
- MIT
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.6.8
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: Tamale
|
53
|
+
test_files: []
|