tamale 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tamale (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ tamale!
15
+
16
+ BUNDLED WITH
17
+ 1.14.6
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
@@ -0,0 +1,5 @@
1
+ task :spec do
2
+ Dir.glob('./spec/**/*_spec.rb').each { |file| require file }
3
+ end
4
+
5
+ task default: :spec
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
@@ -0,0 +1,3 @@
1
+ module Tamale
2
+ VERSION = '0.1.0'
3
+ end
@@ -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: []