derelicte 0.0.1-java

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: ccaedcd6c8d51acebdb783ccffcd591d41c91585
4
+ data.tar.gz: 2a4345aab83316215d91eb1b7353a55da60c7cdb
5
+ SHA512:
6
+ metadata.gz: 275a0759779c45f3c59dd26f5e06093d7c224181f07373818a5b64faeaed6fcca62c0d414eb0ba1aea44cf34787a7a8ebde3d4927821242aed9289310effd043
7
+ data.tar.gz: fb9d2393398a19974b7aa4eb677a0ab72ff6d340b72d66dc538488e98ef7db1bbad138bc3704c8a2a6d940407edb81d765a521721737287e3830a9d5936bfbdf
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ derelicte
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ jruby-1.7.10
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in java_css_inliner.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Michael Ries
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # Derelicte
2
+
3
+ ![Derelicte Gif](http://24.media.tumblr.com/d7c64874eeae527c2661cda9c107984c/tumblr_msas87gWdt1qaehqco1_400.gif)
4
+
5
+ A JRuby specific gem that takes an html template and css file and inlines the css rules into style attributes. This is mostly useful for sending emails.
6
+
7
+ This gem attempts to make the inlining process very performant. If you want a richer feature set please see [Roadie](https://github.com/Mange/roadie) or [PreMailer](http://premailer.dialect.ca/).
8
+
9
+ This gem was only created because I was involved in a project where the above options were too slow to be feasible in day-to-day operations.
10
+
11
+ ## How much time are we talking about?
12
+
13
+ I used an example welcome email from my current job that uses the [Zurb Ink](https://github.com/zurb/ink) email css framework. It has a slightly complex DOM and lots of CSS. Both benchmarks have a warmup phase where they inline 1,000 emails before being measured (to account for JVM and JIT warming up)
14
+
15
+ ```bash
16
+ user system total real
17
+ roadie 3 0.430000 0.030000 0.460000 ( 0.499000)
18
+ derelicte 0.000000 0.000000 0.000000 ( 0.010000)
19
+ ```
20
+
21
+ Saving roughly 50x is not too shabby, but we definitely make some tradeoffs to get that performance.
22
+
23
+ Derelicte uses a handful of native jars (can only used with JRuby) and does not change url paths or inline images via base64 data in tags.
24
+
25
+ ## Usage
26
+
27
+ Simplest possible usage:
28
+
29
+ ```ruby
30
+ html = "<p>ohai</p>"
31
+ css = "p { color: #ff0000; }"
32
+
33
+ inliner = CSS::Inliner.new
34
+ inlined_html = inliner.inline(html, css) # => "<p style=\"color: #ff0000;\">ohai</p>"
35
+ ```
36
+
37
+
38
+ ## Current Issues
39
+
40
+ * doctypes with full URLs (like xhtml) will make the process extremely slow since the standard java libraries attempt to fetch and parse the DTD. It is highly recommended that you simply use an HTML 5 style doctype (<code><!DOCTYPE html></code>)
41
+ * Since we use a basic XML parser it is pretty sensitive to bad markup. Things like unclosed breaks will cause it to choke. Make sure you double-check your templates.
42
+
43
+ ```html
44
+ <!-- Things that will break the XML parsing -->
45
+ <br>
46
+ <img href="/icon.png">
47
+ <meta charset='utf-8'>
48
+ <hr>
49
+
50
+ <!-- These things are okay for the XML parser -->
51
+ <br/>
52
+ <img href="/icon.png" />
53
+ <meta charset='utf-8' />
54
+ <hr/>
55
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/derelicte.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'derelicte/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "derelicte"
8
+ spec.version = Derelicte::VERSION
9
+ spec.authors = ["Michael Ries"]
10
+ spec.email = ["michael@riesd.com"]
11
+ spec.summary = "JRuby specific css inliner aiming for maximum performance"
12
+ spec.description = "A JRuby specific gem that takes an html template and css file and inlines the css rules into style attributes. This is mostly useful for sending emails."
13
+ spec.homepage = "https://github.com/hqmq/derelicte"
14
+ spec.license = "MIT"
15
+ spec.platform = "java"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec", "~> 2.14"
25
+ spec.add_development_dependency "better_receive", '~> 0.6'
26
+ spec.add_development_dependency "pry-nav"
27
+ end
data/lib/derelicte.rb ADDED
@@ -0,0 +1,40 @@
1
+ require "derelicte/version"
2
+
3
+ # Load jars
4
+ require 'jars/antlr-runtime-3.1.jar'
5
+ require 'jars/slf4j-api-1.5.2.jar'
6
+ require 'jars/slf4j-nop-1.5.2.jar'
7
+ require 'jars/xml-apis-1.3.04.jar'
8
+ require 'jars/jstyleparser-1.7.0.jar'
9
+
10
+ # Load local classes
11
+ require 'derelicte/inliner'
12
+ require 'derelicte/inliner_job'
13
+
14
+ module Derelicte
15
+ DOCTYPE = "<!DOCTYPE html>"
16
+
17
+ def self.css_analyzer_from_str(str)
18
+ stylesheet = Java::CzVutbrWebCss::CSSFactory.parse(str)
19
+ Java::CzVutbrWebDomassign::Analyzer.new(stylesheet)
20
+ end
21
+
22
+ def self.doc_from_str(str)
23
+ reader = java.io.StringReader.new(str.to_java_string)
24
+ source = Java::OrgXmlSax::InputSource.new(reader)
25
+ fac = Java::JavaxXmlParsers::DocumentBuilderFactory.newInstance()
26
+ fac.set_validating(false)
27
+ fac.set_namespace_aware(false)
28
+ builder = fac.new_document_builder
29
+ builder.parse(source)
30
+ end
31
+
32
+ def self.doc_to_str(doc)
33
+ serializer = doc.get_implementation
34
+ .get_feature('LS','3.0')
35
+ .create_ls_serializer
36
+ serializer.get_dom_config.set_parameter('xml-declaration', false)
37
+ doc_str = serializer.write_to_string(doc)
38
+ DOCTYPE + "\n" + doc_str
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ module Derelicte
2
+ class Inliner
3
+ def inline(html_str, css_str)
4
+ doc = ::Derelicte.doc_from_str(html_str)
5
+ analyzer = ::Derelicte.css_analyzer_from_str(css_str)
6
+ job = InlinerJob.new(doc, analyzer)
7
+ job.apply_rules_to_doc
8
+ ::Derelicte.doc_to_str(job.doc)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ require 'pry-nav'
2
+ module Derelicte
3
+ class InlinerJob
4
+ attr_reader :doc
5
+
6
+ def initialize(doc, analyzer)
7
+ @doc, @analyzer = doc, analyzer
8
+ end
9
+
10
+ def apply_rules_to_doc
11
+ each_elements do |element|
12
+ apply_rules_to(element)
13
+ end
14
+ end
15
+
16
+ private
17
+ attr_reader :analyzer
18
+
19
+ def apply_rules_to(element)
20
+ rules = assignments.get(element)
21
+ return nil if rules.nil?
22
+ rule_str = rules.map(&:to_s).map(&:chomp).join
23
+ element.set_attribute('style', rule_str)
24
+ end
25
+
26
+ def assignments
27
+ @assignments ||= analyzer.assing_declarations_to_dom(doc, "screen", false)
28
+ end
29
+
30
+ def each_elements
31
+ elements = doc.get_elements_by_tag_name "*"
32
+ 0.upto(elements.get_length - 1).each do |idx|
33
+ element = elements.item(idx)
34
+ yield(element)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Derelicte
2
+ VERSION = "0.0.1"
3
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,40 @@
1
+ require 'bundler/setup'
2
+ require 'java_css_inliner'
3
+ require 'benchmark'
4
+ require 'fileutils'
5
+
6
+ files_dir = File.join(File.dirname(__FILE__), 'files')
7
+ html_file = File.join(files_dir, 'ink_boilerplate.html')
8
+ css_file = File.join(files_dir, 'ink.css')
9
+ html_str = File.read(html_file)
10
+ css_str = File.read(css_file)
11
+
12
+ output_dir = File.join(File.dirname(__FILE__), '..', 'tmp')
13
+ output_file = File.join(output_dir, 'ink_boilerplate.inlined.html')
14
+ FileUtils.mkdir_p(output_dir)
15
+
16
+ inliner = CSS::Inliner.new
17
+
18
+ # Get an initial benchmark
19
+ Benchmark.bm(40) do |bm|
20
+ bm.report('initial run') do
21
+ inliner.inline(html_str, css_str)
22
+ end
23
+ end
24
+
25
+ # Write a sample file out to disk for inspection
26
+ File.open(output_file, 'w') do |f|
27
+ f.write inliner.inline(html_str, css_str)
28
+ end
29
+
30
+ # Warmup the JIT
31
+ 500.times do
32
+ inliner.inline(html_str, css_str)
33
+ end
34
+
35
+ # Benchmark the JIT optimized time
36
+ Benchmark.bm(40) do |bm|
37
+ bm.report('after warmup') do
38
+ inliner.inline(html_str, css_str)
39
+ end
40
+ end
@@ -0,0 +1,648 @@
1
+ /**********************************************
2
+ * Ink v1.0.4 - Copyright 2013 ZURB Inc *
3
+ **********************************************/
4
+
5
+ /* Client-specific Styles & Reset */
6
+
7
+ #outlook a {
8
+ padding:0;
9
+ }
10
+
11
+ body{
12
+ width:100% !important;
13
+ -webkit-text-size-adjust:100%;
14
+ -ms-text-size-adjust:100%;
15
+ margin:0;
16
+ padding:0;
17
+ }
18
+
19
+ .ExternalClass {
20
+ width:100%;
21
+ }
22
+
23
+ .ExternalClass,
24
+ .ExternalClass p,
25
+ .ExternalClass span,
26
+ .ExternalClass font,
27
+ .ExternalClass td,
28
+ .ExternalClass div {
29
+ line-height: 100%;
30
+ }
31
+
32
+ #backgroundTable {
33
+ margin:0;
34
+ padding:0;
35
+ width:100% !important;
36
+ line-height: 100% !important;
37
+ }
38
+
39
+ img {
40
+ outline:none;
41
+ text-decoration:none;
42
+ -ms-interpolation-mode: bicubic;
43
+ width: auto;
44
+ max-width: 100%;
45
+ float: left;
46
+ clear: both;
47
+ display: block;
48
+ }
49
+
50
+ center {
51
+ width: 100%;
52
+ min-width: 580px;
53
+ }
54
+
55
+ a img {
56
+ border: none;
57
+ }
58
+
59
+ p {
60
+ margin: 0 0 0 10px;
61
+ }
62
+
63
+ table {
64
+ border-spacing: 0;
65
+ border-collapse: collapse;
66
+ }
67
+
68
+ td {
69
+ word-break: break-word;
70
+ -webkit-hyphens: auto;
71
+ -moz-hyphens: auto;
72
+ hyphens: auto;
73
+ border-collapse: collapse !important;
74
+ }
75
+
76
+ table, tr, td {
77
+ padding: 0;
78
+ vertical-align: top;
79
+ text-align: left;
80
+ }
81
+
82
+ hr {
83
+ color: #d9d9d9;
84
+ background-color: #d9d9d9;
85
+ height: 1px;
86
+ border: none;
87
+ }
88
+
89
+ /* Responsive Grid */
90
+
91
+ table.body {
92
+ height: 100%;
93
+ width: 100%;
94
+ }
95
+
96
+ table.container {
97
+ width: 580px;
98
+ margin: 0 auto;
99
+ text-align: inherit;
100
+ }
101
+
102
+ table.row {
103
+ padding: 0px;
104
+ width: 100%;
105
+ position: relative;
106
+ }
107
+
108
+ table.container table.row {
109
+ display: block;
110
+ }
111
+
112
+ td.wrapper {
113
+ padding: 10px 20px 0px 0px;
114
+ position: relative;
115
+ }
116
+
117
+ table.columns,
118
+ table.column {
119
+ margin: 0 auto;
120
+ }
121
+
122
+ table.columns td,
123
+ table.column td {
124
+ padding: 0px 0px 10px;
125
+ }
126
+
127
+ table.columns td.sub-columns,
128
+ table.column td.sub-columns,
129
+ table.columns td.sub-column,
130
+ table.column td.sub-column {
131
+ padding-right: 10px;
132
+ }
133
+
134
+ td.sub-column, td.sub-columns {
135
+ min-width: 0px;
136
+ }
137
+
138
+ table.row td.last,
139
+ table.container td.last {
140
+ padding-right: 0px;
141
+ }
142
+
143
+ table.one { width: 30px; }
144
+ table.two { width: 80px; }
145
+ table.three { width: 130px; }
146
+ table.four { width: 180px; }
147
+ table.five { width: 230px; }
148
+ table.six { width: 280px; }
149
+ table.seven { width: 330px; }
150
+ table.eight { width: 380px; }
151
+ table.nine { width: 430px; }
152
+ table.ten { width: 480px; }
153
+ table.eleven { width: 530px; }
154
+ table.twelve { width: 580px; }
155
+
156
+ table.one center { min-width: 30px; }
157
+ table.two center { min-width: 80px; }
158
+ table.three center { min-width: 130px; }
159
+ table.four center { min-width: 180px; }
160
+ table.five center { min-width: 230px; }
161
+ table.six center { min-width: 280px; }
162
+ table.seven center { min-width: 330px; }
163
+ table.eight center { min-width: 380px; }
164
+ table.nine center { min-width: 430px; }
165
+ table.ten center { min-width: 480px; }
166
+ table.eleven center { min-width: 530px; }
167
+ table.twelve center { min-width: 580px; }
168
+
169
+ .body .columns td.one,
170
+ .body .column td.one, { width: 8.333333% !important; }
171
+ .body .columns td.two,
172
+ .body .column td.two { width: 16.666666% !important; }
173
+ .body .columns td.three,
174
+ .body .column td.three { width: 25% !important; }
175
+ .body .columns td.four,
176
+ .body .column td.four { width: 33.333333% !important; }
177
+ .body .columns td.five,
178
+ .body .column td.five { width: 41.666666% !important; }
179
+ .body .columns td.six,
180
+ .body .column td.six { width: 50% !important; }
181
+ .body .columns td.seven,
182
+ .body .column td.seven { width: 58.333333% !important; }
183
+ .body .columns td.eight,
184
+ .body .column td.eight { width: 66.666666% !important; }
185
+ .body .columns td.nine,
186
+ .body .column td.nine { width: 75% !important; }
187
+ .body .columns td.ten,
188
+ .body .column td.ten { width: 83.333333% !important; }
189
+ .body .columns td.eleven,
190
+ .body .column td.eleven { width: 91.666666% !important; }
191
+ .body .columns td.twelve,
192
+ .body .column td.twelve { width: 100% !important; }
193
+
194
+ td.offset-by-one { padding-left: 50px; }
195
+ td.offset-by-two { padding-left: 100px; }
196
+ td.offset-by-three { padding-left: 150px; }
197
+ td.offset-by-four { padding-left: 200px; }
198
+ td.offset-by-five { padding-left: 250px; }
199
+ td.offset-by-six { padding-left: 300px; }
200
+ td.offset-by-seven { padding-left: 350px; }
201
+ td.offset-by-eight { padding-left: 400px; }
202
+ td.offset-by-nine { padding-left: 450px; }
203
+ td.offset-by-ten { padding-left: 500px; }
204
+ td.offset-by-eleven { padding-left: 550px; }
205
+
206
+ td.sub-offset-by-one { padding-left: 5.172413% !important; }
207
+ td.sub-offset-by-two { padding-left: 13.793102% !important; }
208
+ td.sub-offset-by-three { padding-left: 22.413791% !important; }
209
+ td.sub-offset-by-four { padding-left: 31.034480% !important; }
210
+ td.sub-offset-by-five { padding-left: 39.655169% !important; }
211
+ td.sub-offset-by-six { padding-left: 48.275858% !important; }
212
+ td.sub-offset-by-seven { padding-left: 56.896547% !important; }
213
+ td.sub-offset-by-eight { padding-left: 65.517236% !important; }
214
+ td.sub-offset-by-nine { padding-left: 74.137925% !important; }
215
+ td.sub-offset-by-ten { padding-left: 82.758614% !important; }
216
+ td.sub-offset-by-eleven { padding-left: 91.379303% !important; }
217
+
218
+ td.expander {
219
+ visibility: hidden;
220
+ width: 0px;
221
+ padding: 0 !important;
222
+ }
223
+
224
+ table.columns .text-pad,
225
+ table.column .text-pad {
226
+ padding-left: 10px;
227
+ padding-right: 10px;
228
+ }
229
+
230
+ table.columns .left-text-pad,
231
+ table.columns .text-pad-left,
232
+ table.column .left-text-pad,
233
+ table.column .text-pad-left {
234
+ padding-left: 10px;
235
+ }
236
+
237
+ table.columns .right-text-pad,
238
+ table.columns .text-pad-right,
239
+ table.column .right-text-pad,
240
+ table.column .text-pad-right {
241
+ padding-right: 10px;
242
+ }
243
+
244
+ /* Block Grid */
245
+
246
+ .block-grid {
247
+ width: 100%;
248
+ max-width: 580px;
249
+ }
250
+
251
+ .block-grid td {
252
+ display: inline-block;
253
+ padding:10px;
254
+ }
255
+
256
+ .two-up td {
257
+ width:270px;
258
+ }
259
+
260
+ .three-up td {
261
+ width:173px;
262
+ }
263
+
264
+ .four-up td {
265
+ width:125px;
266
+ }
267
+
268
+ .five-up td {
269
+ width:96px;
270
+ }
271
+
272
+ .six-up td {
273
+ width:76px;
274
+ }
275
+
276
+ .seven-up td {
277
+ width:62px;
278
+ }
279
+
280
+ .eight-up td {
281
+ width:52px;
282
+ }
283
+
284
+ /* Alignment & Visibility Classes */
285
+
286
+ table.center, td.center {
287
+ text-align: center;
288
+ }
289
+
290
+ h1.center,
291
+ h2.center,
292
+ h3.center,
293
+ h4.center,
294
+ h5.center,
295
+ h6.center {
296
+ text-align: center;
297
+ }
298
+
299
+ span.center {
300
+ display: block;
301
+ width: 100%;
302
+ text-align: center;
303
+ }
304
+
305
+ img.center {
306
+ margin: 0 auto;
307
+ float: none;
308
+ }
309
+
310
+ .show-for-small,
311
+ .hide-for-desktop {
312
+ display: none;
313
+ }
314
+
315
+ /* Typography */
316
+
317
+ body, table.body, h1, h2, h3, h4, h5, h6, p {
318
+ color: #222222;
319
+ font-family: "Helvetica", "Arial", sans-serif;
320
+ font-weight: normal;
321
+ padding:0;
322
+ margin: 0;
323
+ text-align: left;
324
+ line-height: 1.3;
325
+ }
326
+
327
+ h1, h2, h3, h4, h5, h6 {
328
+ word-break: normal;
329
+ }
330
+
331
+ h1 {font-size: 40px;}
332
+ h2 {font-size: 36px;}
333
+ h3 {font-size: 32px;}
334
+ h4 {font-size: 28px;}
335
+ h5 {font-size: 24px;}
336
+ h6 {font-size: 20px;}
337
+ body, table.body, p {font-size: 14px;line-height:19px;}
338
+
339
+ p {
340
+ padding-bottom: 10px;
341
+ }
342
+
343
+ small {
344
+ font-size: 10px;
345
+ }
346
+
347
+ a {
348
+ color: #2ba6cb;
349
+ text-decoration: none;
350
+ }
351
+
352
+ a:hover {
353
+ color: #2795b6 !important;
354
+ }
355
+
356
+ a:active {
357
+ color: #2795b6 !important;
358
+ }
359
+
360
+ a:visited {
361
+ color: #2ba6cb !important;
362
+ }
363
+
364
+ h1 a,
365
+ h2 a,
366
+ h3 a,
367
+ h4 a,
368
+ h5 a,
369
+ h6 a {
370
+ color: #2ba6cb;
371
+ }
372
+
373
+ h1 a:active,
374
+ h2 a:active,
375
+ h3 a:active,
376
+ h4 a:active,
377
+ h5 a:active,
378
+ h6 a:active {
379
+ color: #2ba6cb !important;
380
+ }
381
+
382
+ h1 a:visited,
383
+ h2 a:visited,
384
+ h3 a:visited,
385
+ h4 a:visited,
386
+ h5 a:visited,
387
+ h6 a:visited {
388
+ color: #2ba6cb !important;
389
+ }
390
+
391
+ /* Panels */
392
+
393
+ td.panel {
394
+ background: #f2f2f2;
395
+ border: 1px solid #d9d9d9;
396
+ padding: 10px !important;
397
+ }
398
+
399
+ /* Buttons */
400
+
401
+ table.button,
402
+ table.tiny-button,
403
+ table.small-button,
404
+ table.medium-button,
405
+ table.large-button {
406
+ width: 100%;
407
+ overflow: hidden;
408
+ }
409
+
410
+ table.button td,
411
+ table.tiny-button td,
412
+ table.small-button td,
413
+ table.medium-button td,
414
+ table.large-button td {
415
+ display: block;
416
+ width: auto !important;
417
+ text-align: center;
418
+ background: #2ba6cb;
419
+ border: 1px solid #2284a1;
420
+ color: #ffffff;
421
+ padding: 8px 0;
422
+ }
423
+
424
+ table.tiny-button td {
425
+ padding: 5px 0 4px;
426
+ }
427
+
428
+ table.small-button td {
429
+ padding: 8px 0 7px;
430
+ }
431
+
432
+ table.medium-button td {
433
+ padding: 12px 0 10px;
434
+ }
435
+
436
+ table.large-button td {
437
+ padding: 21px 0 18px;
438
+ }
439
+
440
+ table.button td a,
441
+ table.tiny-button td a,
442
+ table.small-button td a,
443
+ table.medium-button td a,
444
+ table.large-button td a {
445
+ font-weight: bold;
446
+ text-decoration: none;
447
+ font-family: Helvetica, Arial, sans-serif;
448
+ color: #ffffff;
449
+ font-size: 16px;
450
+ }
451
+
452
+ table.tiny-button td a {
453
+ font-size: 12px;
454
+ font-weight: normal;
455
+ }
456
+
457
+ table.small-button td a {
458
+ font-size: 16px;
459
+ }
460
+
461
+ table.medium-button td a {
462
+ font-size: 20px;
463
+ }
464
+
465
+ table.large-button td a {
466
+ font-size: 24px;
467
+ }
468
+
469
+ table.button:hover td,
470
+ table.button:visited td,
471
+ table.button:active td {
472
+ background: #2795b6 !important;
473
+ }
474
+
475
+ table.button:hover td a,
476
+ table.button:visited td a,
477
+ table.button:active td a {
478
+ color: #fff !important;
479
+ }
480
+
481
+ table.button:hover td,
482
+ table.tiny-button:hover td,
483
+ table.small-button:hover td,
484
+ table.medium-button:hover td,
485
+ table.large-button:hover td {
486
+ background: #2795b6 !important;
487
+ }
488
+
489
+ table.button:hover td a,
490
+ table.button:active td a,
491
+ table.button td a:visited,
492
+ table.tiny-button:hover td a,
493
+ table.tiny-button:active td a,
494
+ table.tiny-button td a:visited,
495
+ table.small-button:hover td a,
496
+ table.small-button:active td a,
497
+ table.small-button td a:visited,
498
+ table.medium-button:hover td a,
499
+ table.medium-button:active td a,
500
+ table.medium-button td a:visited,
501
+ table.large-button:hover td a,
502
+ table.large-button:active td a,
503
+ table.large-button td a:visited {
504
+ color: #ffffff !important;
505
+ }
506
+
507
+ table.secondary td {
508
+ background: #e9e9e9;
509
+ border-color: #d0d0d0;
510
+ color: #555;
511
+ }
512
+
513
+ table.secondary td a {
514
+ color: #555;
515
+ }
516
+
517
+ table.secondary:hover td {
518
+ background: #d0d0d0 !important;
519
+ color: #555;
520
+ }
521
+
522
+ table.secondary:hover td a,
523
+ table.secondary td a:visited,
524
+ table.secondary:active td a {
525
+ color: #555 !important;
526
+ }
527
+
528
+ table.success td {
529
+ background: #5da423;
530
+ border-color: #457a1a;
531
+ }
532
+
533
+ table.success:hover td {
534
+ background: #457a1a !important;
535
+ }
536
+
537
+ table.alert td {
538
+ background: #c60f13;
539
+ border-color: #970b0e;
540
+ }
541
+
542
+ table.alert:hover td {
543
+ background: #970b0e !important;
544
+ }
545
+
546
+ table.radius td {
547
+ -webkit-border-radius: 3px;
548
+ -moz-border-radius: 3px;
549
+ border-radius: 3px;
550
+ }
551
+
552
+ table.round td {
553
+ -webkit-border-radius: 500px;
554
+ -moz-border-radius: 500px;
555
+ border-radius: 500px;
556
+ }
557
+
558
+ /* Outlook First */
559
+
560
+ body.outlook p {
561
+ display: inline !important;
562
+ }
563
+
564
+ /* Media Queries */
565
+
566
+ @media only screen and (max-width: 600px) {
567
+
568
+ table[class="body"] img {
569
+ width: auto !important;
570
+ height: auto !important;
571
+ }
572
+
573
+ table[class="body"] center {
574
+ min-width: 0 !important;
575
+ }
576
+
577
+ table[class="body"] .container {
578
+ width: 95% !important;
579
+ }
580
+
581
+ table[class="body"] .row {
582
+ width: 100% !important;
583
+ display: block !important;
584
+ }
585
+
586
+ table[class="body"] .wrapper {
587
+ display: block !important;
588
+ padding-right: 0 !important;
589
+ }
590
+
591
+ table[class="body"] .columns,
592
+ table[class="body"] .column {
593
+ table-layout: fixed !important;
594
+ float: none !important;
595
+ width: 100% !important;
596
+ padding-right: 0px !important;
597
+ padding-left: 0px !important;
598
+ display: block !important;
599
+ }
600
+
601
+ table[class="body"] .wrapper.first .columns,
602
+ table[class="body"] .wrapper.first .column {
603
+ display: table !important;
604
+ }
605
+
606
+ table[class="body"] table.columns td,
607
+ table[class="body"] table.column td {
608
+ width: 100% !important;
609
+ }
610
+
611
+ table[class="body"] td.offset-by-one,
612
+ table[class="body"] td.offset-by-two,
613
+ table[class="body"] td.offset-by-three,
614
+ table[class="body"] td.offset-by-four,
615
+ table[class="body"] td.offset-by-five,
616
+ table[class="body"] td.offset-by-six,
617
+ table[class="body"] td.offset-by-seven,
618
+ table[class="body"] td.offset-by-eight,
619
+ table[class="body"] td.offset-by-nine,
620
+ table[class="body"] td.offset-by-ten,
621
+ table[class="body"] td.offset-by-eleven {
622
+ padding-left: 0 !important;
623
+ }
624
+
625
+ table[class="body"] .expander {
626
+ width: 9999px !important;
627
+ }
628
+
629
+ table[class="body"] .right-text-pad,
630
+ table[class="body"] .text-pad-right {
631
+ padding-left: 10px !important;
632
+ }
633
+
634
+ table[class="body"] .left-text-pad,
635
+ table[class="body"] .text-pad-left {
636
+ padding-right: 10px !important;
637
+ }
638
+
639
+ table[class="body"] .hide-for-small,
640
+ table[class="body"] .show-for-desktop {
641
+ display: none !important;
642
+ }
643
+
644
+ table[class="body"] .show-for-small,
645
+ table[class="body"] .hide-for-desktop {
646
+ display: inherit !important;
647
+ }
648
+ }
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <meta name="viewport" content="width=device-width"/>
6
+ </head>
7
+ <body>
8
+ <table class="body">
9
+ <tr>
10
+ <td class="center" align="center" valign="top">
11
+ <center>
12
+
13
+ <!-- Email Content -->
14
+
15
+ </center>
16
+ </td>
17
+ </tr>
18
+ </table>
19
+ </body>
20
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
5
+ <meta content="width=device-width" name="viewport"/>
6
+ <title>My Stable CU</title>
7
+ </head>
8
+ <body>
9
+ <p>ohai</p>
10
+ </body>
11
+ </html>
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Derelicte::Inliner do
4
+ let(:css) { "p { color: #ff0000; }" }
5
+ let(:html) { "<div><p>ohai</p></div>" }
6
+
7
+ subject { described_class.new }
8
+ it "should apply css rules to html elements" do
9
+ inlined_html = subject.inline(html, css)
10
+ expect(inlined_html).to include('<div><p style="color: #ff0000;">ohai</p></div>')
11
+ end
12
+
13
+ it "should keep doctypes intact" do
14
+ html = file_contents('simple_dom.html')
15
+ inlined_html = subject.inline(html, "")
16
+ expect(inlined_html).to eq(html.chomp)
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ require 'better_receive'
4
+ require 'derelicte'
5
+
6
+ RSpec.configure do |c|
7
+ c.color = true
8
+ c.order = :rand
9
+ end
10
+
11
+ def file_contents(basename)
12
+ path = File.join( File.dirname(__FILE__), 'files', basename )
13
+ File.read(path)
14
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: derelicte
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: java
6
+ authors:
7
+ - Michael Ries
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: '1.5'
25
+ prerelease: false
26
+ type: :development
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ prerelease: false
40
+ type: :development
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: '2.14'
53
+ prerelease: false
54
+ type: :development
55
+ - !ruby/object:Gem::Dependency
56
+ name: better_receive
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: '0.6'
67
+ prerelease: false
68
+ type: :development
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-nav
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ prerelease: false
82
+ type: :development
83
+ description: A JRuby specific gem that takes an html template and css file and inlines the css rules into style attributes. This is mostly useful for sending emails.
84
+ email:
85
+ - michael@riesd.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - .ruby-gemset
92
+ - .ruby-version
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - derelicte.gemspec
98
+ - lib/derelicte.rb
99
+ - lib/derelicte/inliner.rb
100
+ - lib/derelicte/inliner_job.rb
101
+ - lib/derelicte/version.rb
102
+ - lib/jars/antlr-runtime-3.1.jar
103
+ - lib/jars/jstyleparser-1.7.0.jar
104
+ - lib/jars/slf4j-api-1.5.2.jar
105
+ - lib/jars/slf4j-nop-1.5.2.jar
106
+ - lib/jars/xml-apis-1.3.04.jar
107
+ - spec/benchmarks.rb
108
+ - spec/files/ink.css
109
+ - spec/files/ink_boilerplate.html
110
+ - spec/files/simple_dom.html
111
+ - spec/lib/derelicte/inliner_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/hqmq/derelicte
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.2.1
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: JRuby specific css inliner aiming for maximum performance
137
+ test_files:
138
+ - spec/benchmarks.rb
139
+ - spec/files/ink.css
140
+ - spec/files/ink_boilerplate.html
141
+ - spec/files/simple_dom.html
142
+ - spec/lib/derelicte/inliner_spec.rb
143
+ - spec/spec_helper.rb