digest_email 1.0.1

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.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Peter Hamilton
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,137 @@
1
+ # DigestEmail
2
+
3
+ This is a project put together in a weekend by [Peter Hamilton](http://peterhamilton.github.com).
4
+ The overall aim was to simplify the process of generating weekly Computing Society emails for students.
5
+
6
+ There were several reasons for making this gem:
7
+ - **Fun** - It's not often I have time to make side projects right now. This was a nice non-uni related hack
8
+ - **Learning** - I wanted to do several things - learn more about TDD, create a command line ruby gem etc. This seemed like a great opportunity to tick the boxes
9
+ - **Consistency** - Currently everyone provides their digest info in random formats all over the place. Now they can provide the yaml config for their digest entry and I can just combine them all and generate a digest email
10
+ - **Legacy** - I wanted something future society members could use and improve on
11
+
12
+ The result is a gem which turns [this](https://gist.github.com/4092848) into [this](http://docsoc.s3.amazonaws.com/sample/sample_digest_email.html)
13
+
14
+ ## Background
15
+ I'm responsible for collating together around 4-6 notices which need to go out to our students each week for jobs, clubs, meetings and events. I currently have to write raw HTML for each email which involves a lot of Copy-Paste and inline styles and this weekend I decided to find a way to automate the process.
16
+
17
+ I just collated and generated this weeks digest using this method and it's gone from taking **2 hours** down to **5 minutes**. I'd call that a success.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'digest_email'
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install digest_email
32
+
33
+ ## Usage
34
+
35
+ ### 1. Write a digest file
36
+ I name mine something like 2012-01-01.yml.
37
+
38
+ A digest file must consist of 3 main sections, a header, items and a footer.
39
+
40
+ - Header
41
+ Must contain:
42
+ - `title` - The main digest title
43
+ - `subtitle` - Optional
44
+ - `subsubtitle` - Optional
45
+
46
+ - Items
47
+ Contains a list of items, each of which must contain:
48
+
49
+ - `list_title` - The title which appears in the digest summary at the top
50
+ - `image` - A full url to a hosted image (150px wide recommended)
51
+ - `title` - The title for the item
52
+ - `body` - The body for the item
53
+
54
+ Fields are parsed as markdown using [Maruku](https://github.com/bhollis/maruku) so the body can be easily customised
55
+
56
+ - Footer
57
+ Must contain:
58
+ - `signature` - Will be aligned to the right e.g. "DocSoc 2012/2013"
59
+ - `sponsors_image` - A 600px wide hosted image for the bottom of the email
60
+
61
+ See below for a full example, also available as a [github gist](https://gist.github.com/4092848)
62
+ ```yaml
63
+ # sample_digest_email.yml
64
+ # Parses with the digest_email (http://peterhamilton.github.com/digest_email) gem
65
+ # See the result of running this file through the gem here: http://docsoc.s3.amazonaws.com/sample/sample_digest_email.html
66
+ header:
67
+ title: "Weekly Digest"
68
+ subtitle: November 12th 2012
69
+ subsubtitle:
70
+
71
+ items:
72
+ - list_title: New, Easy Email Digests
73
+ image: https://s3-eu-west-1.amazonaws.com/docsoc/sample/suitcase.jpg
74
+ title: We have nice simple email digests!
75
+ body: |
76
+ This is an example of a simple digest item.
77
+ In this example it might be for a potential industry placement - for example, check out the rather nice suitcase image on the left
78
+
79
+ - list_title: Robotics Hackathon
80
+ image: https://s3-eu-west-1.amazonaws.com/docsoc/sample/walle.jpg
81
+ title: These aren't the droids you're looking for...
82
+ body: |
83
+ Another sample sigest item. This one is all about a fantasy hackathon!
84
+
85
+ For more details contact *[Peter Hamilton](http://peterhamilton.github.com)*
86
+
87
+ footer:
88
+ signature: -- DoCSoc Committee 2012
89
+ sponsors_image: https://s3-eu-west-1.amazonaws.com/docsoc/docsocsponsors.jpg # Bottom Sponsor Banner
90
+ ```
91
+
92
+ ### 2. Write a template
93
+ An HTML file. The digest email renderer will look for the tag {{content}} and replace it with generated digest html.
94
+
95
+ If you need to add styling, you may do so in the header and it will be converted to inline styles for email client compatibility.
96
+
97
+ You can see a sample template at [https://peterhamilton.github.com/digest-email/blob/master/templates/default.html]
98
+
99
+ ### 3. Generate
100
+
101
+ In the command line type `digest_email -h` to see a list of commands
102
+
103
+ ```bash
104
+ digest_email -h
105
+ Usage: digest_email [generate] [OPTIONS]
106
+
107
+ Commands
108
+ generate: renders the email digest
109
+
110
+ Required:
111
+ -f, --file FILE A digest file e.g. 2012-01-01.yml
112
+ -o, --output FILE The file to output the html to e.g index.html
113
+
114
+ Optional:
115
+ -t, --template FILE an HTML file with a {{content}} template tag
116
+ -w, --warnings if present, will show premailer warnings
117
+ -h, --help help
118
+ ```
119
+
120
+ For example to generate a digest email from [this template file](https://peterhamilton.github.com/digest-email/blob/master/templates/default.html) (template.html locally) and [this digest file](https://gist.github.com/4092848) (2012-01-01.yml locally) you would type the following:
121
+
122
+ ```bash
123
+ digest_email -f 2012-01-01.yml -t template.html -o 2012-01-01_digest.html
124
+ ```
125
+
126
+ Which results in the file you can see [here](http://docsoc.s3.amazonaws.com/sample/sample_digest_email.html). From there it's easy to send it out as an email.
127
+
128
+ ## Contributing
129
+ This is a project put together in a few days in my spare time for a fairly specific use case, however if you do see improvements which could be made, I'd love to have people contribute.
130
+
131
+ Just follow the following recommended process:
132
+
133
+ 1. Fork it
134
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
135
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
136
+ 4. Push to the branch (`git push origin my-new-feature`)
137
+ 5. Create new Pull Request
data/bin/digest_email ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'digest_email'
5
+ require 'optparse'
6
+
7
+ options = {}
8
+
9
+ opt_parser = OptionParser.new do |opt|
10
+ opt.banner = "Usage: digest_email [generate] [OPTIONS]"
11
+ opt.separator ""
12
+ opt.separator "Commands"
13
+ opt.separator " generate: renders the email digest"
14
+ opt.separator ""
15
+ opt.separator "Required:"
16
+
17
+ opt.on("-f","--file FILE","A digest file e.g. 2012-01-01.yml") do |template|
18
+ options[:file] = template
19
+ end
20
+
21
+ opt.on("-o","--output FILE","The file to output the html to e.g index.html") do |output|
22
+ options[:output] = output
23
+ end
24
+
25
+ opt.separator ""
26
+
27
+ opt.separator "Optional:"
28
+
29
+ opt.on("-t","--template FILE","an HTML file with a {{content}} template tag") do |template|
30
+ options[:template] = template
31
+ end
32
+
33
+ opt.on("-w","--warnings","if present, will show premailer warnings") do |warnings|
34
+ options[:warnings] = warnings
35
+ end
36
+
37
+ opt.on("-h","--help","help") do
38
+ puts opt_parser
39
+ exit
40
+ end
41
+ end
42
+
43
+
44
+ begin
45
+ opt_parser.parse!(ARGV)
46
+ raise OptionParser::MissingArgument if options[:file].nil?
47
+
48
+ case ARGV[0]
49
+ when "generate"
50
+ begin
51
+ puts "#{Time.now} - Rendering Digest"
52
+ digest_yaml = YAML.load_file(options[:file])
53
+
54
+ template_file = options[:template] || File.join(File.dirname(__FILE__), "..", "templates/default.html")
55
+ warnings = options[:warnings] || false
56
+ template = File.read template_file
57
+
58
+ d = DigestEmail.parse(digest_yaml)
59
+
60
+ File.open(options[:output], 'w') { |file| file.write(d.render template, warnings) }
61
+ puts "#{Time.now} - Done. Digest saved as #{options[:output]}"
62
+ rescue Exception => e
63
+ puts "Error generating digest: #{e}"
64
+ exit
65
+ end
66
+ else
67
+ raise
68
+ end
69
+ rescue
70
+ puts opt_parser
71
+ exit
72
+ end
73
+
74
+
@@ -0,0 +1,45 @@
1
+ require 'digest_email/digest_element'
2
+ require 'premailer'
3
+
4
+ module DigestEmail
5
+ class Digest < DigestElement
6
+
7
+
8
+ def initialize(header, items, footer)
9
+ @header = header
10
+ @items = items
11
+ @footer = footer
12
+ @children = [@header, @items, @footer]
13
+ end
14
+
15
+ def render(template = "{{content}}", show_warnings = false)
16
+ html = [@header.render(@items.children), @items.render, @footer.render].join
17
+ html = template.gsub '{{content}}', wrap(html)
18
+
19
+ # Convert any styles to inline
20
+ premailer = Premailer.new(html, :with_html_string => true)
21
+ html = premailer.to_inline_css
22
+
23
+ # Output any CSS warnings
24
+ if show_warnings
25
+ puts "Email Client Compatibility Warnings:"
26
+ premailer.warnings.each do |w|
27
+ puts "#{w[:message]} (#{w[:level]}) may not render properly in #{w[:clients]}"
28
+ end
29
+ end
30
+ html
31
+ end
32
+
33
+ def wrap(inner)
34
+ ["<div class=\"digest\">",
35
+ "<table>",
36
+ "<tr>",
37
+ "<td>",
38
+ inner,
39
+ "</td>",
40
+ "</tr>",
41
+ "</table>",
42
+ "</div>"].join
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ require 'digest_email/digest_element'
2
+
3
+ module DigestEmail
4
+ class DigestElement
5
+ attr_accessor :children
6
+
7
+ def initialize
8
+ @children = []
9
+ end
10
+
11
+ # Render each child, join all the html and wrap it
12
+ def render
13
+ wrap @children.map(&:render).join("\n")
14
+ end
15
+
16
+ # By default don't wrap with anything
17
+ def wrap(inner)
18
+ inner
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ require 'digest_email/digest_element'
2
+ require 'maruku'
3
+
4
+ module DigestEmail
5
+ class DigestFooter < DigestElement
6
+ attr_accessor :signature, :sponsors_image
7
+
8
+ def initialize(footer)
9
+ super()
10
+ @signature = footer["signature"]
11
+ @sponsors_image = footer["sponsors_image"]
12
+ end
13
+
14
+ def render
15
+ parsed_signature = Maruku.new(@signature).to_html
16
+ html = [
17
+ "<div class=\"digest-email-dot-seperator\"></div>",
18
+ "<div class=\"digest-email-footer-signature\"><div>#{parsed_signature}</div></div>",
19
+ render_sponsors_image
20
+ ]
21
+
22
+ wrap html.join("\n")
23
+ end
24
+
25
+ def render_sponsors_image
26
+ html = ["<div class=\"digest-email-footer-sponsors-image\">"]
27
+ html << ["<img src=\"#{@sponsors_image}\"/>"]
28
+ html << ["</div>"]
29
+ html.join("\n")
30
+ end
31
+
32
+ def wrap(inner)
33
+ "<div class=\"digest-email-footer\">#{inner}</div>"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,65 @@
1
+ require 'digest_email/digest_element'
2
+ require 'maruku'
3
+
4
+ module DigestEmail
5
+ class DigestHeader < DigestElement
6
+ attr_accessor :title, :subtitle, :subsubtitle
7
+
8
+ def initialize(header)
9
+ super()
10
+ @title = header["title"]
11
+
12
+ if header.has_key? "subtitle"
13
+ @subtitle = header["subtitle"]
14
+ else
15
+ @subtitle = nil
16
+ end
17
+
18
+ if header.has_key? "subsubtitle"
19
+ @subsubtitle = header["subsubtitle"]
20
+ else
21
+ @subsubtitle = nil
22
+ end
23
+ end
24
+
25
+ def render(items)
26
+ parsed_title = Maruku.new(@title).to_html
27
+
28
+ html = ["<div class=\"digest-email-header-title\">#{parsed_title}</div>"]
29
+
30
+ unless @subtitle.nil?
31
+ parsed_subtitle = Maruku.new(@subtitle).to_html
32
+ html << ["<div class=\"digest-email-header-subtitle\">",
33
+ parsed_subtitle,
34
+ "</div>"]
35
+ end
36
+
37
+ unless @subsubtitle.nil?
38
+ parsed_subsubtitle = Maruku.new(@subsubtitle).to_html
39
+ html << ["<div class=\"digest-email-header-subsubtitle\">",
40
+ parsed_subsubtitle,
41
+ "</div>"]
42
+ end
43
+
44
+ # Contents List
45
+ html << ["<div class=\"digest-email-dot-seperator\"></div>"]
46
+ html << render_contents_list(items)
47
+ html << ["<div class=\"digest-email-dot-seperator\"></div>"]
48
+
49
+ wrap html.join("\n")
50
+ end
51
+
52
+ def render_contents_list(items)
53
+ html = ["<div class=\"digest-email-header-contents-list\">"]
54
+ html << ["<ol>"]
55
+ html << items.map { |item| "<li>#{item.list_title}</li>" }.join
56
+ html << ["</ol>"]
57
+ html << ["</div>"]
58
+ html.join
59
+ end
60
+
61
+ def wrap(inner)
62
+ "<div class=\"digest-email-header\">#{inner}</div>"
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,42 @@
1
+ require 'digest_email/digest_element'
2
+ require 'maruku'
3
+
4
+ module DigestEmail
5
+ class DigestItem < DigestElement
6
+ attr_accessor :list_title, :title, :image, :body
7
+
8
+ def initialize(item)
9
+ super()
10
+ @list_title = item["list_title"]
11
+ @title = item["title"]
12
+ @image = item["image"]
13
+ @body = item["body"]
14
+ end
15
+
16
+ def render
17
+ parsed_title = Maruku.new(@title).to_html
18
+ parsed_body = Maruku.new(@body).to_html
19
+
20
+ html = [
21
+ render_image,
22
+ "<div class=\"digest-email-item-content-container\">",
23
+ "<div class=\"digest-email-item-title\">#{parsed_title}</div>",
24
+ "<div class=\"digest-email-item-body\">#{parsed_body}</div>",
25
+ "</div>"
26
+ ]
27
+
28
+ wrap html.join("\n")
29
+ end
30
+
31
+ def render_image
32
+ html = ["<div class=\"digest-email-item-image\">"]
33
+ html << ["<img src=\"#{@image}\"/>"]
34
+ html << ["</div>"]
35
+ html.join("\n")
36
+ end
37
+
38
+ def wrap(inner)
39
+ "<div class=\"digest-email-item\">#{inner}<div class=\"clear\"></div></div>"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ require 'digest_email/digest_element'
2
+
3
+ class Array
4
+ # As per http://stackoverflow.com/questions/3676027
5
+ def intersperse(separator)
6
+ (inject([]) { |a,v| a + [v,separator] })[0...-1]
7
+ end
8
+ end
9
+
10
+ module DigestEmail
11
+ class DigestItems < DigestElement
12
+ def initialize(items)
13
+ super()
14
+ @children = items
15
+ end
16
+
17
+ def render
18
+ rendered_items = @children.map(&:render)
19
+ wrap rendered_items.join "\n<div class=\"digest-email-dot-seperator\"></div>\n"
20
+ end
21
+
22
+ def wrap(inner)
23
+ "<div class=\"digest-email-items\">#{inner}</div>"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/digest_parser_validator'
2
+
3
+ module DigestEmail
4
+ class DigestParser
5
+ extend DigestParserValidator
6
+
7
+ def self.parse(digest)
8
+ begin
9
+ validate_indices(digest, ["header", "items", "footer"])
10
+
11
+ header = parse_header(digest["header"])
12
+ body = parse_items(digest["items"])
13
+ footer = parse_footer(digest["footer"])
14
+
15
+ DigestEmail::Digest.new(header, body, footer)
16
+ rescue Exception => e
17
+ raise "Failed to parse digest: #{e.message}"
18
+ end
19
+ end
20
+
21
+ def self.parse_header(header)
22
+ validate_index(header, "title")
23
+ DigestEmail::DigestHeader.new header
24
+ end
25
+
26
+ def self.parse_items(items)
27
+ DigestEmail::DigestItems.new items.map{|item| parse_item(item)}
28
+ end
29
+
30
+ def self.parse_item(item)
31
+ validate_indices(item, ["list_title", "image", "title", "body"])
32
+
33
+ DigestEmail::DigestItem.new item
34
+ end
35
+
36
+ def self.parse_footer(footer)
37
+ validate_indices(footer, ["signature", "sponsors_image"])
38
+ DigestEmail::DigestFooter.new footer
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ module DigestParserValidator
2
+
3
+ # Invalidates index if missing or empty, taking advantage of lazy eval
4
+ def valid_index?(item, index)
5
+ item.has_key?(index) and !item[index].nil? and !item[index].empty?
6
+ end
7
+
8
+ # Validate an index for given hash
9
+ def validate_index(item, index)
10
+ unless valid_index?(item, index)
11
+ raise "Missing digest field #{index.capitalize}"
12
+ end
13
+ end
14
+
15
+ # Validates multiple indices for given hash
16
+ def validate_indices(item, indices)
17
+ indices.each do |index|
18
+ validate_index(item, index)
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,3 @@
1
+ module DigestEmail
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ require "digest_email/version"
2
+ require "digest_email/digest"
3
+ require "digest_email/digest_header"
4
+ require "digest_email/digest_items"
5
+ require "digest_email/digest_item"
6
+ require "digest_email/digest_footer"
7
+ require "digest_email/digest_parser"
8
+
9
+ module DigestEmail
10
+ def self.parse(digest_hash)
11
+ DigestParser.parse digest_hash
12
+ end
13
+ end
@@ -0,0 +1,134 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
5
+ <style type="text/css">
6
+
7
+ /*
8
+ Elements taken from:
9
+ http://meyerweb.com/eric/tools/css/reset/
10
+ v2.0 | 20110126
11
+ License: none (public domain)
12
+ */
13
+
14
+ table {
15
+ -premailer-width: 600;
16
+ }
17
+
18
+ p {
19
+ margin: 5px 0px;
20
+ padding: 0;
21
+ border: 0;
22
+ vertical-align: baseline;
23
+ }
24
+
25
+ /* HTML5 display-role reset for older browsers */
26
+ article, aside, details, figcaption, figure,
27
+ footer, header, hgroup, menu, nav, section {
28
+ display: block;
29
+ }
30
+
31
+ body {
32
+ line-height: 1;
33
+ }
34
+
35
+ blockquote, q {
36
+ quotes: none;
37
+ }
38
+ blockquote:before, blockquote:after,
39
+ q:before, q:after {
40
+ content: '';
41
+ content: none;
42
+ }
43
+ table {
44
+ border-collapse: collapse;
45
+ border-spacing: 0;
46
+ -premailer-width: 600;
47
+ -premailer-cellpadding: 20;
48
+ }
49
+
50
+ /* END RESET */
51
+
52
+ * {
53
+ font-family: Arial, Helvetica, sans-serif!important;
54
+ }
55
+
56
+ body {
57
+ color:#000000;
58
+ padding: 0px;
59
+ margin: 0px;
60
+ color: #444;
61
+ }
62
+
63
+ .digest {
64
+ width: 600px;
65
+ margin: 0 auto;
66
+ }
67
+
68
+ .digest-email-header-title {
69
+ font-size:50px;
70
+ line-height:60px;
71
+ text-align: center;
72
+ }
73
+
74
+ .digest-email-header-subtitle {
75
+ font-size: 20px;
76
+ text-align: center;
77
+ margin-bottom: 10px;
78
+ }
79
+
80
+ .digest-email-header-contents-list {
81
+ font-size: 20px;
82
+ line-height: 25px;
83
+ }
84
+
85
+ .digest-email-item {
86
+ margin: 10px 0px;
87
+ }
88
+
89
+ .digest-email-item-image {
90
+ width: 150px;
91
+ float: left;
92
+ }
93
+
94
+ .digest-email-item-content-container {
95
+ margin-left:10px;
96
+ width: 440px;
97
+ float: left;
98
+ text-align: justify;
99
+ font-size: 14px;
100
+ line-height: 20px;
101
+ }
102
+
103
+ .digest-email-item-title {
104
+ font-weight: bold;
105
+ margin-bottom: 5px;
106
+ }
107
+
108
+ .digest-email-dot-seperator {
109
+ background: url('https://s3-eu-west-1.amazonaws.com/docsoc/dots.jpg');
110
+ background-repeat: repeat-x;
111
+ height: 1px;
112
+ margin: 5px 0px;
113
+ }
114
+
115
+ .digest-email-footer-signature {
116
+ padding-top: 10px;
117
+ text-align: right;
118
+ }
119
+
120
+ .digest-email-footer-sponsors-image {
121
+ margin-top: 15px;
122
+ }
123
+
124
+ .clear {
125
+ clear: both;
126
+ }
127
+
128
+
129
+ </style>
130
+ </head>
131
+ <body>
132
+ {{content}}
133
+ </body>
134
+ </html>
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: digest_email
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter Hamilton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-17 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Gem to generate a weekly email digest
15
+ email:
16
+ - peter@inspiredpixel.net
17
+ executables:
18
+ - digest_email
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/digest_email/digest.rb
23
+ - lib/digest_email/digest_element.rb
24
+ - lib/digest_email/digest_footer.rb
25
+ - lib/digest_email/digest_header.rb
26
+ - lib/digest_email/digest_item.rb
27
+ - lib/digest_email/digest_items.rb
28
+ - lib/digest_email/digest_parser.rb
29
+ - lib/digest_email/digest_parser_validator.rb
30
+ - lib/digest_email/version.rb
31
+ - lib/digest_email.rb
32
+ - templates/default.html
33
+ - bin/digest_email
34
+ - README.md
35
+ - LICENSE.txt
36
+ homepage: ''
37
+ licenses: []
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 1.8.24
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Gem to generate a weekly email digest
60
+ test_files: []