inky-rb 0.0.2
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/.gitignore +2 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +29 -0
- data/Rakefile +7 -0
- data/inky-0.0.0.gem +0 -0
- data/inky.gemspec +17 -0
- data/lib/component_factory.rb +116 -0
- data/lib/inky.rb +65 -0
- data/lib/inky/rails/engine.rb +11 -0
- data/lib/inky/rails/template_handler.rb +18 -0
- data/lib/inky/rails/version.rb +5 -0
- data/spec/components_spec.rb +258 -0
- data/spec/grid_spec.rb +268 -0
- data/spec/spec_helper.rb +14 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fbf8c53c8d48a846016305a76c103d83fbede347
|
4
|
+
data.tar.gz: 4af2ec4313392cc40b67a97692f8a2bf0c3a07ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 017fb453f67dd9277efd68dd5834ac3b297cbca27420d42093f819bf7628ff95ebfeabc4d8e2d5981ea8352c26ce38bc3ddbd3f1105decfe670d727928affd0b
|
7
|
+
data.tar.gz: 1e7ec1e72349d03a3c5afce68f1b72b4499f6d0daebf874c6aba742edd2100989f25dbfc97c540a1a4a0657b447e7af896f574139f2eb7df1e9d626e9e9f4195
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
inky (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.5)
|
10
|
+
rake (11.1.2)
|
11
|
+
rspec-core (3.4.1)
|
12
|
+
rspec-support (~> 3.4.0)
|
13
|
+
rspec-expectations (3.4.0)
|
14
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
15
|
+
rspec-support (~> 3.4.0)
|
16
|
+
rspec-support (3.4.1)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (~> 1.6)
|
23
|
+
inky!
|
24
|
+
rake
|
25
|
+
rspec-core
|
26
|
+
rspec-expectations
|
27
|
+
|
28
|
+
BUNDLED WITH
|
29
|
+
1.10.6
|
data/Rakefile
ADDED
data/inky-0.0.0.gem
ADDED
Binary file
|
data/inky.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'inky-rb'
|
3
|
+
s.version = '0.0.2'
|
4
|
+
s.date = '2016-02-12'
|
5
|
+
s.summary = 'Inky is an HTML-based templating language that converts simple HTML into complex, responsive email-ready HTML. Designed for Foundation for Emails, a responsive email framework from ZURB. '
|
6
|
+
s.description = 'Inky is an HTML-based templating language that converts simple HTML into complex, responsive email-ready HTML. Designed for Foundation for Emails, a responsive email framework from ZURB. '
|
7
|
+
s.authors = ["ZURB"]
|
8
|
+
s.email = ['foundation@zurb.com']
|
9
|
+
|
10
|
+
s.files = `git ls-files -z`.split("\x0")
|
11
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
12
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
13
|
+
|
14
|
+
s.add_dependency "foundation_emails", "~> 2"
|
15
|
+
s.add_development_dependency "bundler", "~> 1.6"
|
16
|
+
s.add_development_dependency "rake"
|
17
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module ComponentFactory
|
2
|
+
def component_factory(elem)
|
3
|
+
inner = elem.children.map(&:to_s).join
|
4
|
+
# TODO: Handle changed names
|
5
|
+
transform_method = :"_transform_#{self.component_lookup[elem.name]}"
|
6
|
+
if self.respond_to?(transform_method)
|
7
|
+
REXML::Document.new(self.send(transform_method, elem, inner)).root
|
8
|
+
else
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def _has_class(elem, klass)
|
14
|
+
!!elem.attributes['class'] && elem.attributes['class'].split(' ').include?(klass)
|
15
|
+
end
|
16
|
+
|
17
|
+
def _class_array(elem, defaults = [])
|
18
|
+
(elem.attributes['class'] ? (defaults.concat(elem.attributes['class'].split(' '))) : defaults).uniq
|
19
|
+
end
|
20
|
+
|
21
|
+
def _transform_button(component, inner)
|
22
|
+
expand = _has_class(component, 'expand')
|
23
|
+
if component.attributes['href']
|
24
|
+
if expand
|
25
|
+
inner = "<a href=\"#{component.attributes['href']}\" align=\"center\" class=\"float-center\">#{inner}</a>"
|
26
|
+
else
|
27
|
+
inner = "<a href=\"#{component.attributes['href']}\">#{inner}</a>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
inner = "<center>#{inner}</center>" if expand
|
31
|
+
|
32
|
+
classes = _class_array(component, ['button'])
|
33
|
+
if expand
|
34
|
+
return "<table class=\"#{classes.join(' ')}\"><tr><td><table><tr><td>#{inner}</td></tr></table></td><td class=\"expander\"></td></tr></table>"
|
35
|
+
else
|
36
|
+
return "<table class=\"#{classes.join(' ')}\"><tr><td><table><tr><td>#{inner}</td></tr></table></td></tr></table>"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def _transform_menu(component, inner)
|
41
|
+
classes = _class_array(component, ['menu'])
|
42
|
+
"<table class=\"#{classes.join(' ')}\"><tr><td><table><tr>#{inner}</tr></table></td></tr></table>"
|
43
|
+
end
|
44
|
+
|
45
|
+
def _transform_menu_item(component, inner)
|
46
|
+
"<th class=\"menu-item\"><a href=\"#{component.attributes['href']}\">#{inner}</a></th>"
|
47
|
+
end
|
48
|
+
|
49
|
+
def _transform_container(component, inner)
|
50
|
+
classes = _class_array(component, ['container'])
|
51
|
+
"<table class=\"#{classes.join(' ')}\"><tbody><tr><td>#{inner}</td></tr></tbody></table>"
|
52
|
+
end
|
53
|
+
|
54
|
+
def _transform_row(component, inner)
|
55
|
+
classes = _class_array(component, ['row'])
|
56
|
+
"<table class=\"#{classes.join(' ')}\"><tbody><tr>#{inner}</tr></tbody></table>"
|
57
|
+
end
|
58
|
+
|
59
|
+
# in inky.js this is factored out into makeClumn. TBD if we need that here.
|
60
|
+
def _transform_columns(component, inner)
|
61
|
+
|
62
|
+
col_count = component.parent.elements.size
|
63
|
+
small_size = component.attributes['small'] || self.column_count
|
64
|
+
large_size = component.attributes['large'] || component.attributes['small'] || (self.column_count / col_count).to_i
|
65
|
+
|
66
|
+
classes = _class_array(component, ["small-#{small_size}", "large-#{large_size}", "columns"])
|
67
|
+
|
68
|
+
|
69
|
+
classes.push('first') unless component.previous_element
|
70
|
+
classes.push('last') unless component.next_element
|
71
|
+
|
72
|
+
subrows = component.elements.to_a("//*[contains(@class,'row')]").concat(component.elements.to_a("//row"))
|
73
|
+
expander = ''
|
74
|
+
if large_size.to_i == self.column_count && subrows.size == 0
|
75
|
+
expander = "<th class=\"expander\"></th>"
|
76
|
+
end
|
77
|
+
"<th class=\"#{classes.join(' ')}\"><table><tr><th>#{inner}</th>#{expander}</tr></table></th>"
|
78
|
+
end
|
79
|
+
|
80
|
+
def _transform_block_grid(component, inner)
|
81
|
+
classes = _class_array(component, ['block-grid', "up-#{component.attributes['up']}"])
|
82
|
+
"<table class=\"#{classes.join(' ')}\"><tr>#{inner}</tr></table>"
|
83
|
+
end
|
84
|
+
|
85
|
+
def _transform_center(component, inner)
|
86
|
+
# NOTE: Using children instead of elements because elements.to_a
|
87
|
+
# sometimes appears to miss elements that show up in size
|
88
|
+
component.elements.to_a.each do |child|
|
89
|
+
child.add_attribute('align', 'center')
|
90
|
+
child_classes = _class_array(child, ['float-center'])
|
91
|
+
child.add_attribute('class', child_classes.join(' '))
|
92
|
+
items = component.elements.to_a("//*[contains(@class,'menu-item')]").concat(component.elements.to_a("//item"))
|
93
|
+
items.each do |item|
|
94
|
+
item_classes = _class_array(item, ['float-center'])
|
95
|
+
item.add_attribute('class', item_classes.join(' '))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
return component.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
def _transform_callout(component, inner)
|
102
|
+
classes = _class_array(component, ['callout-inner'])
|
103
|
+
return "<table class=\"callout\"><tr><th class=\"#{classes.join(' ')}\">#{inner}</th><th class=\"expander\"></th></tr></table>"
|
104
|
+
end
|
105
|
+
|
106
|
+
def _transform_spacer(component, inner)
|
107
|
+
classes = _class_array(component, ['spacer'])
|
108
|
+
size = component.attributes['size'] || 16
|
109
|
+
return "<table class=\"#{classes.join(' ')}\"><tbody><tr><td height=\"#{size}px\" style=\"font-size:#{size}px;line-height:#{size}px;\"> </td></tr></tbody></table>"
|
110
|
+
end
|
111
|
+
|
112
|
+
def _transform_wrapper(component, inner)
|
113
|
+
classes = _class_array(component, ['wrapper'])
|
114
|
+
return "<table class=\"#{classes.join(' ')}\" align=\"center\"><tr><td class=\"wrapper-inner\">#{inner}</td></tr></table>"
|
115
|
+
end
|
116
|
+
end
|
data/lib/inky.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Inky
|
2
|
+
class Core
|
3
|
+
require 'rexml/document'
|
4
|
+
require 'component_factory'
|
5
|
+
attr_accessor :components, :column_count, :component_lookup, :component_tags
|
6
|
+
|
7
|
+
include ComponentFactory
|
8
|
+
def initialize(options = {})
|
9
|
+
self.components = {
|
10
|
+
button: 'button',
|
11
|
+
row: 'row',
|
12
|
+
columns: 'columns',
|
13
|
+
container: 'container',
|
14
|
+
inky: 'inky',
|
15
|
+
block_grid: 'block-grid',
|
16
|
+
menu: 'menu',
|
17
|
+
center: 'center',
|
18
|
+
callout: 'callout',
|
19
|
+
spacer: 'spacer',
|
20
|
+
wrapper: 'wrapper',
|
21
|
+
menu_item: 'item'
|
22
|
+
}.merge(options[:components] || {})
|
23
|
+
|
24
|
+
self.component_lookup = self.components.invert
|
25
|
+
|
26
|
+
self.column_count = options[:column_count] || 12
|
27
|
+
|
28
|
+
self.component_tags = self.components.values
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def release_the_kraken(xml_string)
|
33
|
+
xml_string = xml_string.gsub(/doctype/i, 'DOCTYPE')
|
34
|
+
xml_doc = REXML::Document.new(xml_string)
|
35
|
+
if self.components_exist?(xml_doc)
|
36
|
+
self.transform_doc(xml_doc.root)
|
37
|
+
end
|
38
|
+
return xml_doc.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def components_exist?(xml_doc)
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def transform_doc(elem)
|
47
|
+
if elem.respond_to?(:children)
|
48
|
+
elem.children.each do |child|
|
49
|
+
transform_doc(child)
|
50
|
+
end
|
51
|
+
component = self.component_factory(elem)
|
52
|
+
elem.replace_with(component) if component
|
53
|
+
end
|
54
|
+
elem
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
begin
|
59
|
+
# Only valid in rails environments
|
60
|
+
require 'foundation_emails'
|
61
|
+
require 'inky/rails/engine'
|
62
|
+
require 'inky/rails/template_handler'
|
63
|
+
require 'inky/rails/version'
|
64
|
+
rescue LoadError
|
65
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Inky
|
2
|
+
module Rails
|
3
|
+
class TemplateHandler
|
4
|
+
def self.erb_handler
|
5
|
+
@@erb_handler ||= ActionView::Template.registered_template_handler(:erb)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.call(template)
|
9
|
+
compiled_source = erb_handler.call(template)
|
10
|
+
"Inky::Core.new.release_the_kraken(begin; #{compiled_source};end)"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveSupport.on_load(:action_view) do
|
17
|
+
ActionView::Template.register_template_handler :inky, Inky::Rails::TemplateHandler
|
18
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Center" do
|
4
|
+
it "applies a text-center class and center alignment attribute to the first child" do
|
5
|
+
input = '<center><div></div></center>';
|
6
|
+
expected = <<-HTML
|
7
|
+
<center>
|
8
|
+
<div align="center" class="float-center"></div>
|
9
|
+
</center>
|
10
|
+
HTML
|
11
|
+
|
12
|
+
compare(input, expected);
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't choke if center tags are nested" do
|
16
|
+
input = '<center><center>a</center></center>'
|
17
|
+
|
18
|
+
expected = <<-HTML
|
19
|
+
<center>
|
20
|
+
<center align="center" class="float-center">
|
21
|
+
a
|
22
|
+
</center>
|
23
|
+
</center>
|
24
|
+
HTML
|
25
|
+
|
26
|
+
compare(input, expected);
|
27
|
+
end
|
28
|
+
|
29
|
+
it "applies the class float-center to <item> elements" do
|
30
|
+
input = '<center><menu><item href="#"></item></menu></center>'
|
31
|
+
|
32
|
+
expected = <<-HTML
|
33
|
+
<center>
|
34
|
+
<table class="float-center menu " align="center">
|
35
|
+
<tr>
|
36
|
+
<td>
|
37
|
+
<table>
|
38
|
+
<tr>
|
39
|
+
<th class="float-center menu-item">
|
40
|
+
<a href="#"></a>
|
41
|
+
</th>
|
42
|
+
</tr>
|
43
|
+
</table>
|
44
|
+
</td>
|
45
|
+
</tr>
|
46
|
+
</table>
|
47
|
+
</center>
|
48
|
+
HTML
|
49
|
+
|
50
|
+
compare(input, expected);
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
RSpec.describe "Button" do
|
55
|
+
it "creates a simple button" do
|
56
|
+
input = '<button href="http://zurb.com">Button</button>';
|
57
|
+
expected = <<-HTML
|
58
|
+
<table class="button">
|
59
|
+
<tr>
|
60
|
+
<td>
|
61
|
+
<table>
|
62
|
+
<tr>
|
63
|
+
<td><a href="http://zurb.com">Button</a></td>
|
64
|
+
</tr>
|
65
|
+
</table>
|
66
|
+
</td>
|
67
|
+
</tr>
|
68
|
+
</table>
|
69
|
+
HTML
|
70
|
+
compare(input, expected);
|
71
|
+
end
|
72
|
+
it 'creates a button with classes' do
|
73
|
+
input = '<button class="small alert" href="http://zurb.com">Button</button>'
|
74
|
+
expected = <<-HTML
|
75
|
+
<table class="button small alert">
|
76
|
+
<tr>
|
77
|
+
<td>
|
78
|
+
<table>
|
79
|
+
<tr>
|
80
|
+
<td><a href="http://zurb.com">Button</a></td>
|
81
|
+
</tr>
|
82
|
+
</table>
|
83
|
+
</td>
|
84
|
+
</tr>
|
85
|
+
</table>
|
86
|
+
HTML
|
87
|
+
|
88
|
+
compare(input, expected)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'creates a correct expanded button' do
|
92
|
+
input = '<button class="expand" href="http://zurb.com">Button</button>'
|
93
|
+
expected = <<-HTML
|
94
|
+
<table class="button expand">
|
95
|
+
<tr>
|
96
|
+
<td>
|
97
|
+
<table>
|
98
|
+
<tr>
|
99
|
+
<td>
|
100
|
+
<center><a href="http://zurb.com" align="center" class="float-center">Button</a></center>
|
101
|
+
</td>
|
102
|
+
</tr>
|
103
|
+
</table>
|
104
|
+
</td>
|
105
|
+
<td class="expander"></td>
|
106
|
+
</tr>
|
107
|
+
</table>
|
108
|
+
HTML
|
109
|
+
|
110
|
+
compare(input, expected)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
RSpec.describe "Menu" do
|
115
|
+
it 'creates a menu with item tags inside' do
|
116
|
+
input = <<-INKY
|
117
|
+
<menu>
|
118
|
+
<item href="http://zurb.com">Item</item>
|
119
|
+
</menu>
|
120
|
+
INKY
|
121
|
+
expected = <<-HTML
|
122
|
+
<table class="menu">
|
123
|
+
<tr>
|
124
|
+
<td>
|
125
|
+
<table>
|
126
|
+
<tr>
|
127
|
+
<th class="menu-item"><a href="http://zurb.com">Item</a></th>
|
128
|
+
</tr>
|
129
|
+
</table>
|
130
|
+
</td>
|
131
|
+
</tr>
|
132
|
+
</table>
|
133
|
+
HTML
|
134
|
+
|
135
|
+
compare(input, expected)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'creates a menu with classes' do
|
139
|
+
input = <<-INKY
|
140
|
+
<menu class="vertical">
|
141
|
+
</menu>
|
142
|
+
INKY
|
143
|
+
expected = <<-HTML
|
144
|
+
<table class="menu vertical">
|
145
|
+
<tr>
|
146
|
+
<td>
|
147
|
+
<table>
|
148
|
+
<tr>
|
149
|
+
</tr>
|
150
|
+
</table>
|
151
|
+
</td>
|
152
|
+
</tr>
|
153
|
+
</table>
|
154
|
+
HTML
|
155
|
+
|
156
|
+
compare(input, expected)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'works without using an item tag' do
|
160
|
+
input = <<-INKY
|
161
|
+
<menu>
|
162
|
+
<th class="menu-item"><a href="http://zurb.com">Item 1</a></th>
|
163
|
+
</menu>
|
164
|
+
INKY
|
165
|
+
expected = <<-HTML
|
166
|
+
<table class="menu">
|
167
|
+
<tr>
|
168
|
+
<td>
|
169
|
+
<table>
|
170
|
+
<tr>
|
171
|
+
<th class="menu-item"><a href="http://zurb.com">Item 1</a></th>
|
172
|
+
</tr>
|
173
|
+
</table>
|
174
|
+
</td>
|
175
|
+
</tr>
|
176
|
+
</table>
|
177
|
+
HTML
|
178
|
+
|
179
|
+
compare(input, expected)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
RSpec.describe "Callout" do
|
184
|
+
it "creates a callout with correct syntax" do
|
185
|
+
input = '<callout>Callout</callout>';
|
186
|
+
expected = <<-HTML
|
187
|
+
<table class="callout">
|
188
|
+
<tr>
|
189
|
+
<th class="callout-inner">Callout</th>
|
190
|
+
<th class="expander"></th>
|
191
|
+
</tr>
|
192
|
+
</table>
|
193
|
+
HTML
|
194
|
+
|
195
|
+
compare(input, expected);
|
196
|
+
end
|
197
|
+
|
198
|
+
it "copies classes to the final HTML" do
|
199
|
+
input = '<callout class="primary">Callout</callout>'
|
200
|
+
expected = <<-HTML
|
201
|
+
<table class="callout">
|
202
|
+
<tr>
|
203
|
+
<th class="callout-inner primary">Callout</th>
|
204
|
+
<th class="expander"></th>
|
205
|
+
</tr>
|
206
|
+
</table>
|
207
|
+
HTML
|
208
|
+
|
209
|
+
compare(input, expected);
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
RSpec.describe "Spacer" do
|
214
|
+
it 'creates a spacer element with correct size' do
|
215
|
+
input = '<spacer size="10"></spacer>';
|
216
|
+
expected = <<-HTML
|
217
|
+
<table class="spacer">
|
218
|
+
<tbody>
|
219
|
+
<tr>
|
220
|
+
<td height="10px" style="font-size:10px;line-height:10px;"> </td>
|
221
|
+
</tr>
|
222
|
+
</tbody>
|
223
|
+
</table>
|
224
|
+
HTML
|
225
|
+
|
226
|
+
compare(input, expected);
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'copies classes to the final spacer HTML' do
|
230
|
+
input = '<spacer size="10" class="bgcolor"></spacer>'
|
231
|
+
expected = <<-HTML
|
232
|
+
<table class="spacer bgcolor">
|
233
|
+
<tbody>
|
234
|
+
<tr>
|
235
|
+
<td height="10px" style="font-size:10px;line-height:10px;"> </td>
|
236
|
+
</tr>
|
237
|
+
</tbody>
|
238
|
+
</table>
|
239
|
+
HTML
|
240
|
+
|
241
|
+
compare(input, expected);
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
RSpec.describe "Wrapper" do
|
246
|
+
it 'creates a wrapper that you can attach classes to' do
|
247
|
+
input = '<wrapper class="header"></wrapper>'
|
248
|
+
expected = <<-HTML
|
249
|
+
<table class="wrapper header" align="center">
|
250
|
+
<tr>
|
251
|
+
<td class="wrapper-inner"></td>
|
252
|
+
</tr>
|
253
|
+
</table>
|
254
|
+
HTML
|
255
|
+
|
256
|
+
compare(input, expected);
|
257
|
+
end
|
258
|
+
end
|
data/spec/grid_spec.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Container" do
|
4
|
+
it "creates a container table" do
|
5
|
+
input = '<container></container>'
|
6
|
+
expected = <<-HTML
|
7
|
+
<table class="container">
|
8
|
+
<tbody>
|
9
|
+
<tr>
|
10
|
+
<td></td>
|
11
|
+
</tr>
|
12
|
+
</tbody>
|
13
|
+
</table>
|
14
|
+
HTML
|
15
|
+
|
16
|
+
compare(input, expected)
|
17
|
+
end
|
18
|
+
it 'works when parsing a full HTML document' do
|
19
|
+
input = <<-INKY
|
20
|
+
<!doctype html> <html>
|
21
|
+
<head></head>
|
22
|
+
<body>
|
23
|
+
<container></container>
|
24
|
+
</body>
|
25
|
+
</html>
|
26
|
+
INKY
|
27
|
+
expected = <<-HTML
|
28
|
+
<!DOCTYPE html>
|
29
|
+
<html>
|
30
|
+
<head></head>
|
31
|
+
<body>
|
32
|
+
<table class="container">
|
33
|
+
<tbody>
|
34
|
+
<tr>
|
35
|
+
<td></td>
|
36
|
+
</tr>
|
37
|
+
</tbody>
|
38
|
+
</table>
|
39
|
+
</body>
|
40
|
+
</html>
|
41
|
+
HTML
|
42
|
+
compare(input, expected)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
RSpec.describe 'Grid' do
|
47
|
+
it 'creates a row' do
|
48
|
+
input = '<row></row>'
|
49
|
+
expected = <<-HTML
|
50
|
+
<table class="row">
|
51
|
+
<tbody>
|
52
|
+
<tr></tr>
|
53
|
+
</tbody>
|
54
|
+
</table>
|
55
|
+
HTML
|
56
|
+
|
57
|
+
compare(input, expected)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'creates a single column with first and last classes' do
|
61
|
+
input = '<columns large="12" small="12">One</columns>'
|
62
|
+
expected = <<-HTML
|
63
|
+
<th class="small-12 large-12 columns first last">
|
64
|
+
<table>
|
65
|
+
<tr>
|
66
|
+
<th>One</th>
|
67
|
+
<th class="expander"></th>
|
68
|
+
</tr>
|
69
|
+
</table>
|
70
|
+
</th>
|
71
|
+
HTML
|
72
|
+
|
73
|
+
compare(input, expected)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'creates two columns, one first, one last' do
|
77
|
+
input = <<-INKY
|
78
|
+
<body>
|
79
|
+
<columns large="6" small="12">One</columns>
|
80
|
+
<columns large="6" small="12">Two</columns>
|
81
|
+
</body>
|
82
|
+
INKY
|
83
|
+
expected = <<-HTML
|
84
|
+
<body>
|
85
|
+
<th class="small-12 large-6 columns first">
|
86
|
+
<table>
|
87
|
+
<tr>
|
88
|
+
<th>One</th>
|
89
|
+
</tr>
|
90
|
+
</table>
|
91
|
+
</th>
|
92
|
+
<th class="small-12 large-6 columns last">
|
93
|
+
<table>
|
94
|
+
<tr>
|
95
|
+
<th>Two</th>
|
96
|
+
</tr>
|
97
|
+
</table>
|
98
|
+
</th>
|
99
|
+
</body>
|
100
|
+
HTML
|
101
|
+
|
102
|
+
compare(input, expected)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'creates 3+ columns, first is first, last is last' do
|
106
|
+
input = <<-INKY
|
107
|
+
<body>
|
108
|
+
<columns large="4" small="12">One</columns>
|
109
|
+
<columns large="4" small="12">Two</columns>
|
110
|
+
<columns large="4" small="12">Three</columns>
|
111
|
+
</body>
|
112
|
+
INKY
|
113
|
+
expected = <<-INKY
|
114
|
+
<body>
|
115
|
+
<th class="small-12 large-4 columns first">
|
116
|
+
<table>
|
117
|
+
<tr>
|
118
|
+
<th>One</th>
|
119
|
+
</tr>
|
120
|
+
</table>
|
121
|
+
</th>
|
122
|
+
<th class="small-12 large-4 columns">
|
123
|
+
<table>
|
124
|
+
<tr>
|
125
|
+
<th>Two</th>
|
126
|
+
</tr>
|
127
|
+
</table>
|
128
|
+
</th>
|
129
|
+
<th class="small-12 large-4 columns last">
|
130
|
+
<table>
|
131
|
+
<tr>
|
132
|
+
<th>Three</th>
|
133
|
+
</tr>
|
134
|
+
</table>
|
135
|
+
</th>
|
136
|
+
</body>
|
137
|
+
INKY
|
138
|
+
|
139
|
+
compare(input, expected)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'transfers classes to the final HTML' do
|
143
|
+
input = '<columns class="small-offset-8 hide-for-small">One</columns>'
|
144
|
+
expected = <<-HTML
|
145
|
+
<th class="small-12 large-12 columns small-offset-8 hide-for-small first last">
|
146
|
+
<table>
|
147
|
+
<tr>
|
148
|
+
<th>One</th>
|
149
|
+
<th class="expander"></th>
|
150
|
+
</tr>
|
151
|
+
</table>
|
152
|
+
</th>
|
153
|
+
HTML
|
154
|
+
|
155
|
+
compare(input, expected)
|
156
|
+
end
|
157
|
+
|
158
|
+
#if it just has small, borrow from small for large
|
159
|
+
it 'automatically assigns large columns if no large attribute is assigned' do
|
160
|
+
input = <<-HTML
|
161
|
+
<body>
|
162
|
+
<columns small="4">One</columns>
|
163
|
+
<columns small="8">Two</columns>
|
164
|
+
</body>
|
165
|
+
HTML
|
166
|
+
expected = <<-INKY
|
167
|
+
<body>
|
168
|
+
<th class="small-4 large-4 columns first">
|
169
|
+
<table>
|
170
|
+
<tr>
|
171
|
+
<th>One</th>
|
172
|
+
</tr>
|
173
|
+
</table>
|
174
|
+
</th>
|
175
|
+
<th class="small-8 large-8 columns last">
|
176
|
+
<table>
|
177
|
+
<tr>
|
178
|
+
<th>Two</th>
|
179
|
+
</tr>
|
180
|
+
</table>
|
181
|
+
</th>
|
182
|
+
</body>
|
183
|
+
INKY
|
184
|
+
|
185
|
+
compare(input, expected)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'automatically assigns small columns as full width if only large defined' do
|
189
|
+
input = <<-INKY
|
190
|
+
<body>
|
191
|
+
<columns large="4">One</columns>
|
192
|
+
<columns large="8">Two</columns>
|
193
|
+
</body>
|
194
|
+
INKY
|
195
|
+
expected = <<-HTML
|
196
|
+
<body>
|
197
|
+
<th class="small-12 large-4 columns first">
|
198
|
+
<table>
|
199
|
+
<tr>
|
200
|
+
<th>One</th>
|
201
|
+
</tr>
|
202
|
+
</table>
|
203
|
+
</th>
|
204
|
+
<th class="small-12 large-8 columns last">
|
205
|
+
<table>
|
206
|
+
<tr>
|
207
|
+
<th>Two</th>
|
208
|
+
</tr>
|
209
|
+
</table>
|
210
|
+
</th>
|
211
|
+
</body>
|
212
|
+
HTML
|
213
|
+
|
214
|
+
compare(input, expected)
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'supports nested grids' do
|
218
|
+
input = '<row><columns><row></row></columns></row>'
|
219
|
+
expected = <<-HTML
|
220
|
+
<table class="row">
|
221
|
+
<tbody>
|
222
|
+
<tr>
|
223
|
+
<th class="small-12 large-12 columns first last">
|
224
|
+
<table>
|
225
|
+
<tr>
|
226
|
+
<th>
|
227
|
+
<table class="row">
|
228
|
+
<tbody>
|
229
|
+
<tr></tr>
|
230
|
+
</tbody>
|
231
|
+
</table>
|
232
|
+
</th>
|
233
|
+
</tr>
|
234
|
+
</table>
|
235
|
+
</th>
|
236
|
+
</tr>
|
237
|
+
</tbody>
|
238
|
+
</table>
|
239
|
+
HTML
|
240
|
+
|
241
|
+
compare(input, expected)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
RSpec.describe 'Block Grid' do
|
246
|
+
it 'returns the correct block grid syntax' do
|
247
|
+
input = '<block-grid up="4"></block-grid>'
|
248
|
+
expected = <<-HTML
|
249
|
+
<table class="block-grid up-4">
|
250
|
+
<tr></tr>
|
251
|
+
</table>
|
252
|
+
HTML
|
253
|
+
|
254
|
+
compare(input, expected)
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'copies classes to the final HTML output' do
|
258
|
+
input = '<block-grid up="4" class="show-for-large"></block-grid>'
|
259
|
+
expected = <<-HTML
|
260
|
+
<table class="block-grid up-4 show-for-large">
|
261
|
+
<tr></tr>
|
262
|
+
</table>
|
263
|
+
HTML
|
264
|
+
|
265
|
+
compare(input, expected)
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'inky'
|
2
|
+
|
3
|
+
require 'rexml/document'
|
4
|
+
def compare(input, expected)
|
5
|
+
inky = Inky::Core.new
|
6
|
+
output = inky.release_the_kraken(input)
|
7
|
+
|
8
|
+
# TODO: Figure out a better way to do html compare in ruby..
|
9
|
+
# this is overly dependent on things like class ordering, making it
|
10
|
+
# fragile
|
11
|
+
output_str = REXML::Document.new(output).to_s.gsub(/\s/, '')
|
12
|
+
expected_str = REXML::Document.new(expected).to_s.gsub(/\s/, '')
|
13
|
+
expect(output_str).to eql(expected_str)
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: inky-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ZURB
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: foundation_emails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: 'Inky is an HTML-based templating language that converts simple HTML
|
56
|
+
into complex, responsive email-ready HTML. Designed for Foundation for Emails, a
|
57
|
+
responsive email framework from ZURB. '
|
58
|
+
email:
|
59
|
+
- foundation@zurb.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- Gemfile
|
66
|
+
- Gemfile.lock
|
67
|
+
- Rakefile
|
68
|
+
- inky-0.0.0.gem
|
69
|
+
- inky.gemspec
|
70
|
+
- lib/component_factory.rb
|
71
|
+
- lib/inky.rb
|
72
|
+
- lib/inky/rails/engine.rb
|
73
|
+
- lib/inky/rails/template_handler.rb
|
74
|
+
- lib/inky/rails/version.rb
|
75
|
+
- spec/components_spec.rb
|
76
|
+
- spec/grid_spec.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
homepage:
|
79
|
+
licenses: []
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.5.1
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Inky is an HTML-based templating language that converts simple HTML into
|
101
|
+
complex, responsive email-ready HTML. Designed for Foundation for Emails, a responsive
|
102
|
+
email framework from ZURB.
|
103
|
+
test_files:
|
104
|
+
- spec/components_spec.rb
|
105
|
+
- spec/grid_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
has_rdoc:
|