actionmailer-text 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3ddc55262abf2f426d3eec82eeb5744a8ee9e88e
4
- data.tar.gz: 79bfe536b8778822c2b7f7283e352e86c4d46432
2
+ SHA256:
3
+ metadata.gz: a131c593f2e132ffc762a6b548ea188ad7312ed543d13bab0f6006aa1228559c
4
+ data.tar.gz: 5b653dc3f0ee2f1bc955452efa414c5cd79aa409b1377c78db21d0c203ab63c1
5
5
  SHA512:
6
- metadata.gz: 9209f5852e814dda8519470ffce74ea094786703dc279e81d510dbc25ea63a1a795085dcb264ed5b2f7253f0159f6b3fcbfef41d3ef56125271c5b6cc10ed6e2
7
- data.tar.gz: 8eb68179d47ae461e0adde2f047a5c044f86f09f3b2f1899c39373f153d338c0dc0ae827cdc9ac2a0dcd83713550c1451cd6d6c263bcaf0d049d439cb20af6af
6
+ metadata.gz: ded5d23fc8c3824f93b5c0aa9e7757a24acda261241a91db9829503a3cc892f149476dd896e2d2105ff9a9d401733eecf3740e6777f6a0c25050b28c087e7483
7
+ data.tar.gz: 0ab108ace5b96f31c5f98afc72d758a9047b7f9d5f3e4b0b9592c320129d94dfcadcfff547ca03c99480c0598e4a5c2ea0bbad7d527b20b0d01bf3be78d4d26b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ### 0.2.0 (2026-10-19)
2
+
3
+ * [#17](https://github.com/dblock/actionmailer-text/pull/17): Add a maintainer release guide - [@dblock](https://github.com/dblock).
4
+ * [#12](https://github.com/dblock/actionmailer-text/pull/12): Avoid backtracking when wrapping long tokens and preserve unbroken URLs, ported from [Kit/actionmailer-text](https://github.com/Kit/actionmailer-text) - [@scanferla](https://github.com/scanferla).
5
+ * [#14](https://github.com/dblock/actionmailer-text/pull/14): Support `generate_text only:` and `except:` to select mailer actions for automatic plaintext generation - [@dblock](https://github.com/dblock).
6
+ * [#13](https://github.com/dblock/actionmailer-text/pull/13): Parse HTML with Nokogiri while preserving the converter API and core text formatting, inspired by [NomNomCameron/actionmailer-textgiri](https://github.com/NomNomCameron/actionmailer-textgiri) - [@NomNomCameron](https://github.com/NomNomCameron).
7
+ * [#15](https://github.com/dblock/actionmailer-text/pull/15): Require Ruby 3.1 or newer and RuboCop 1.92, disable Metrics and line-length cops, and regenerate the lint baseline after checking safe autocorrections - [@dblock](https://github.com/dblock).
8
+ * [#16](https://github.com/dblock/actionmailer-text/pull/16): Prepare version 0.2.0 and add agent contribution guidance - [@dblock](https://github.com/dblock).
9
+ * [#11](https://github.com/dblock/actionmailer-text/pull/11): Replace Travis CI with GitHub Actions coverage for Rails 6.1 through 8.1, modernize development dependencies, and expand mailer regression tests - [@dblock](https://github.com/dblock).
10
+ * [#4](https://github.com/dblock/actionmailer-text/pull/4): Ignore empty links - [@apalancat](https://github.com/apalancat).
11
+ * [#8](https://github.com/dblock/actionmailer-text/pull/8): Decode HTML entities in newer Rails versions - [@mthurman](https://github.com/mthurman).
12
+
13
+ ### 0.1.1 (2015-04-25)
14
+
15
+ * [#1](https://github.com/dblock/actionmailer-text/pull/1): Ignore elements outside the body - [@woahdae](https://github.com/woahdae).
16
+
1
17
  ### 0.1.0 (2015-04-07)
2
18
 
3
19
  * Initial public release - [@dblock](https://github.com/dblock).
data/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  ActionMailer::Text
2
2
  ==================
3
3
 
4
- [![Build Status](https://travis-ci.org/dblock/actionmailer-text.png)](https://travis-ci.org/dblock/actionmailer-text)
4
+ [![CI](https://github.com/dblock/actionmailer-text/actions/workflows/ci.yml/badge.svg)](https://github.com/dblock/actionmailer-text/actions/workflows/ci.yml)
5
5
  [![Gem Version](https://badge.fury.io/rb/actionmailer-text.svg)](http://badge.fury.io/rb/actionmailer-text)
6
6
 
7
7
  Automatically insert a text/plain part into your HTML multipart e-mails.
8
8
 
9
9
  ## Installation
10
10
 
11
+ Requires Ruby 3.1 or newer. Use a Ruby version supported by your selected Rails release.
12
+
11
13
  ```ruby
12
14
  gem 'actionmailer-text'
13
15
  ```
@@ -30,10 +32,30 @@ end
30
32
 
31
33
  ```
32
34
 
35
+ ### Selecting actions
36
+
37
+ Including `ActionMailer::Text` generates plaintext for every action by default. To limit generation to specific actions, declare `generate_text` in your mailer:
38
+
39
+ ```ruby
40
+ class WelcomeMailer < ActionMailer::Base
41
+ include ActionMailer::Text
42
+
43
+ generate_text only: [:welcome]
44
+ end
45
+ ```
46
+
47
+ Use `generate_text except: [:receipt]` to generate plaintext for every action except those listed. Action names accept strings or symbols, individually or in arrays. Use either `only:` or `except:`, not both. An empty `only: []` disables generation for all actions; an empty `except: []` excludes none.
48
+
49
+ Filters are inherited by subclasses. A subclass can replace the inherited filter with its own `generate_text` declaration, or call `generate_text` without arguments to restore generation for every action. Filtering only controls automatic generation: explicitly rendered text parts are always preserved.
50
+
33
51
  ## Details
34
52
 
35
53
  The MIME standard allows systems to send e-mail with multiple parts: plain/text for business-efficient devices such as the Blackberry, and text/html for web-based e-mail readers, such as GMail. Furthermore, ActionMailer supports multiple template formats: create an .html.haml template along with a .txt.haml template to generate both. We also know that text/plain email helps deliverability, but we believe a disproportionately small amount of text e-mails are actually read - the vast majority of devices are capable of parsing some HTML. This gem lets you get the text/plain part for free.
36
54
 
55
+ HTML is parsed with Nokogiri. Generated text preserves repeated content, includes image alt text and link destinations, and formats headings, lists, paragraphs, and line breaks. Existing explicit text parts are left unchanged.
56
+
57
+ Escaped markup remains literal text, image alt text does not require a self-closing tag, comments and script/style content are omitted, and malformed HTML is repaired before conversion. Fragment text surrounding paragraphs may gain paragraph breaks as Nokogiri normalizes the document. Nested list items appear on separate lines; ordered lists use `*` bullets, and nesting is flattened rather than indented.
58
+
37
59
  See [this blog post](http://artsy.github.io/blog/2012/05/16/generating-automatic-plain-text-mime-parts-with-rails-actionmailer) for details.
38
60
 
39
61
  ## Contributing
@@ -1,110 +1,103 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- # Extracted from the premailer gem.
4
- #
5
- # https://raw.github.com/alexdunae/premailer/master/lib/premailer/html_to_plain_text.rb
6
- #
7
-
8
- require 'htmlentities'
3
+ require 'nokogiri'
9
4
 
10
5
  module ActionMailer
11
6
  module Text
7
+ # Converts HTML into plaintext with link destinations and basic structural formatting.
12
8
  module HtmlToPlainText
13
9
  def convert_to_text(html, line_length = 65, from_charset = 'UTF-8')
14
10
  HtmlToPlainText.convert_to_text(html, line_length, from_charset)
15
11
  end
16
12
 
17
- # Returns the text in UTF-8 format with all HTML tags removed
18
- #
19
- # TODO: add support for DL, OL
13
+ # Returns UTF-8 text, preserving the converter's paragraph, link, and heading formatting.
20
14
  def self.convert_to_text(html, line_length = 65, _from_charset = 'UTF-8')
21
- txt = html
22
-
23
- # decode HTML entities
24
- he = HTMLEntities.new
25
- txt = he.decode(txt)
26
-
27
- # replace image by their alt attribute
28
- txt.gsub!(/<img.+?alt=\"([^\"]*)\"[^>]*\/>/i, '\1')
29
- txt.gsub!(/<img.+?alt='([^\']*)\'[^>]*\/>/i, '\1')
15
+ document = Nokogiri::HTML.parse(html.to_str, nil, 'UTF-8')
16
+ txt = render_children(document.at_css('body') || document, line_length)
17
+ txt = custom_word_wrap(txt, line_length) if line_length
18
+ txt.gsub!(/\r\n?/, "\n")
19
+ txt.tr!("\u00a0", ' ')
20
+ txt.gsub!(/\n[ \t]+/, "\n")
21
+ txt.gsub!(/[ \t]+\n/, "\n")
22
+ txt.gsub!(/\n{3,}/, "\n\n")
23
+ txt.gsub!(/ {2,}/, ' ')
24
+ txt.strip
25
+ end
30
26
 
31
- # links
32
- txt.gsub!(/<a.+?href=\"([^\"]*)\"[^>]*>(.+?)<\/a>/mi) do |_s|
33
- Regexp.last_match[2].strip + ' ( ' + Regexp.last_match[1].strip + ' )'
27
+ def self.render_children(node, line_length)
28
+ node.children.each_with_object(''.dup) do |child, text|
29
+ if child.element? && child.name == 'li'
30
+ text.rstrip!
31
+ text << "\n" unless text.empty?
32
+ end
33
+ text << render_node(child, line_length)
34
34
  end
35
+ end
35
36
 
36
- txt.gsub!(/<a.+?href='([^\']*)\'[^>]*>(.+?)<\/a>/mi) do |_s|
37
- Regexp.last_match[2].strip + ' ( ' + Regexp.last_match[1].strip + ' )'
37
+ def self.render_node(node, line_length)
38
+ return render_text(node) if node.text?
39
+ return '' unless node.element?
40
+ return '' if %w[script style].include?(node.name)
41
+ return node['alt'].to_s if node.name == 'img'
42
+ return "\n" if node.name == 'br'
43
+
44
+ text = render_children(node, line_length)
45
+ case node.name
46
+ when 'a'
47
+ node['href'] && !text.strip.empty? ? "#{text.strip} ( #{node['href'].strip} )" : text
48
+ when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
49
+ render_heading(text, node.name, line_length)
50
+ when 'li'
51
+ "* #{text.lstrip}\n"
52
+ when 'ul', 'ol'
53
+ "\n#{text.strip}\n"
54
+ when 'p'
55
+ "#{text}\n\n"
56
+ else
57
+ text
38
58
  end
59
+ end
39
60
 
40
- # handle headings (H1-H6)
41
- txt.gsub!(/(<\/h[1-6]>)/i, "\n\\1") # move closing tags to new lines
42
- txt.gsub!(/[\s]*<h([1-6]+)[^>]*>[\s]*(.*)[\s]*<\/h[1-6]+>/i) do |_s|
43
- hlevel = Regexp.last_match[1].to_i
61
+ def self.render_text(node)
62
+ previous = node.previous_sibling
63
+ following = node.next_sibling
64
+ return ' ' if node.content.strip.empty? && !previous.nil? && !following.nil? &&
65
+ previous.name == 'span' && following.name == 'span'
44
66
 
45
- htext = Regexp.last_match[2]
46
- htext.gsub!(/<br[\s]*\/?>/i, "\n") # handle <br>s
47
- htext.gsub!(/<\/?[^>]*>/i, '') # strip tags
67
+ node.content
68
+ end
48
69
 
49
- # determine maximum line length
50
- hlength = 0
51
- htext.each_line do |l|
52
- llength = l.strip.length
53
- hlength = llength if llength > hlength
54
- end
55
- hlength = line_length if line_length && hlength > line_length
70
+ def self.render_heading(text, tag, line_length)
71
+ text = text.strip
72
+ length = text.lines.map { |line| line.strip.length }.max || 0
73
+ length = [length, line_length].min if line_length
74
+ rule = (tag == 'h1' ? '*' : '-') * length
75
+ heading = %w[h1 h2].include?(tag) ? "#{rule}\n#{text}\n#{rule}" : "#{text}\n#{rule}"
76
+ "\n\n#{heading}\n\n"
77
+ end
78
+
79
+ def self.custom_word_wrap(txt, line_length)
80
+ txt.split("\n").map { |line| wrap_long_line(line, line_length) }.join("\n")
81
+ end
56
82
 
57
- case hlevel
58
- when 1 # H1, asterisks above and below
59
- htext = ('*' * hlength) + "\n" + htext + "\n" + ('*' * hlength)
60
- when 2 # H1, dashes above and below
61
- htext = ('-' * hlength) + "\n" + htext + "\n" + ('-' * hlength)
62
- else # H3-H6, dashes below
63
- htext = htext + "\n" + ('-' * hlength)
83
+ def self.wrap_long_line(line, line_length)
84
+ return line if line.length <= line_length
85
+
86
+ wrapped = []
87
+ while line.length > line_length
88
+ index = line[0, line_length + 1].rindex(/\s/)
89
+ index = line.index(/\s/, line_length) if index.nil? || index.zero?
90
+ unless index
91
+ wrapped << line
92
+ line = ''
93
+ break
64
94
  end
65
95
 
66
- "\n\n" + htext + "\n\n"
96
+ wrapped << line[0, index]
97
+ line = line[index, line.length - index].lstrip
67
98
  end
68
-
69
- # wrap spans
70
- txt.gsub!(/(<\/span>)[\s]+(<span)/mi, '\1 \2')
71
-
72
- # lists -- TODO: should handle ordered lists
73
- txt.gsub!(/[\s]*(<li[^>]*>)[\s]*/i, '* ')
74
- # list not followed by a newline
75
- txt.gsub!(/<\/li>[\s]*(?![\n])/i, "\n")
76
-
77
- # paragraphs and line breaks
78
- txt.gsub!(/<\/p>/i, "\n\n")
79
- txt.gsub!(/<br[\/ ]*>/i, "\n")
80
-
81
- # strip remaining tags
82
- txt.gsub!(/<\/?[^>]*>/, '')
83
-
84
- txt = custom_word_wrap(txt, line_length) if line_length
85
-
86
- # remove linefeeds (\r\n and \r -> \n)
87
- txt.gsub!(/\r\n?/, "\n")
88
-
89
- # strip extra spaces
90
- txt.gsub!(/\302\240+/, ' ') # non-breaking spaces -> spaces
91
- txt.gsub!(/\n[ \t]+/, "\n") # space at start of lines
92
- txt.gsub!(/[ \t]+\n/, "\n") # space at end of lines
93
-
94
- # no more than two consecutive newlines
95
- txt.gsub!(/[\n]{3,}/, "\n\n")
96
-
97
- # no more than two consecutive spaces
98
- txt.gsub!(/ {2,}/, ' ')
99
-
100
- txt.strip
101
- end
102
-
103
- # Taken from Rails' word_wrap helper (http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-word_wrap)
104
- def self.custom_word_wrap(txt, line_length)
105
- txt.split("\n").collect do |line|
106
- line.length > line_length ? line.gsub(/(.{1,#{line_length}})(\s+|$)/, "\\1\n").strip : line
107
- end * "\n"
99
+ wrapped << line unless line.empty?
100
+ wrapped.join("\n").strip
108
101
  end
109
102
  end
110
103
  end
@@ -1,20 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionMailer
4
+ # Adds a generated plaintext alternative to HTML mail unless an explicit text part exists.
2
5
  module Text
3
6
  def self.included(klass)
4
7
  klass.class_eval do
5
8
  include ActionMailer::Text::HtmlToPlainText
9
+
10
+ class_attribute :text_generation_filter, instance_writer: false
11
+ extend ClassMethods
12
+ end
13
+ end
14
+
15
+ # Configures inherited action filters for automatic plaintext generation.
16
+ module ClassMethods
17
+ def generate_text(only: nil, except: nil)
18
+ raise ArgumentError, 'Specify only or except, not both' unless only.nil? || except.nil?
19
+
20
+ self.text_generation_filter = {
21
+ only: normalize_text_actions(only),
22
+ except: normalize_text_actions(except)
23
+ }.freeze
24
+ end
25
+
26
+ private
27
+
28
+ def normalize_text_actions(actions)
29
+ return if actions.nil?
30
+
31
+ Array(actions).map do |action|
32
+ raise ArgumentError, 'Action names must be strings or symbols' unless action.is_a?(String) || action.is_a?(Symbol)
33
+
34
+ action.to_s.dup.freeze
35
+ end.freeze
6
36
  end
7
37
  end
8
38
 
9
39
  def collect_responses(headers)
10
- responses = super headers
40
+ responses = super
41
+ return responses unless generate_text_for_action?
42
+
11
43
  html_part = responses.detect { |response| response[:content_type] == 'text/html' }
12
44
  text_part = responses.detect { |response| response[:content_type] == 'text/plain' }
13
45
  if html_part && !text_part
14
46
  responses.insert 0, content_type: 'text/plain', body: convert_to_text(html_part[:body], nil)
15
- headers[:parts_order] = ['text/plain'] + headers[:parts_order] unless headers[:parts_order].include?('text/plain')
47
+ unless headers[:parts_order].include?('text/plain')
48
+ headers[:parts_order] =
49
+ ['text/plain'] + headers[:parts_order]
50
+ end
16
51
  end
17
52
  responses
18
53
  end
54
+
55
+ private
56
+
57
+ def generate_text_for_action?
58
+ filter = self.class.text_generation_filter
59
+ return true unless filter
60
+ return filter[:only].include?(action_name) if filter[:only]
61
+
62
+ !filter[:except] || !filter[:except].include?(action_name)
63
+ end
19
64
  end
20
65
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionMailer
2
4
  module Text
3
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
4
6
  end
5
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'action_mailer'
2
4
  require 'actionmailer-text/version'
3
5
  require 'actionmailer-text/html_to_plain_text'
@@ -1 +1,3 @@
1
- require 'email-example-spec'
1
+ # frozen_string_literal: true
2
+
3
+ require 'actionmailer-text'
metadata CHANGED
@@ -1,90 +1,79 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionmailer-text
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-07 00:00:00.000000000 Z
11
+ date: 2026-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: htmlentities
28
+ name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
41
- description:
40
+ version: '1.6'
41
+ description:
42
42
  email: dblock@dblock.org
43
43
  executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
47
  - CHANGELOG.md
48
- - CONTRIBUTING.md
49
- - Gemfile
50
- - Gemfile.lock
51
48
  - LICENSE.md
52
49
  - README.md
53
- - Rakefile
54
- - actionmailer-text.gemspec
55
50
  - lib/actionmailer-text.rb
56
51
  - lib/actionmailer-text/html_to_plain_text.rb
57
52
  - lib/actionmailer-text/text.rb
58
53
  - lib/actionmailer-text/version.rb
59
54
  - lib/actionmailer_text.rb
60
- - pkg/actionmailer-text-0.1.0.gem
61
- - spec/actionmailer-text/multipart_spec.rb
62
- - spec/actionmailer-text/version_spec.rb
63
- - spec/spec_helper.rb
64
- - spec/support/fixtures/welcome_email.multipart
65
- - spec/support/templates/welcome_email.html.erb
66
- homepage: http://github.com/dblock/actionmailer-text
55
+ homepage: https://github.com/dblock/actionmailer-text
67
56
  licenses:
68
57
  - MIT
69
- metadata: {}
70
- post_install_message:
58
+ metadata:
59
+ rubygems_mfa_required: 'true'
60
+ post_install_message:
71
61
  rdoc_options: []
72
62
  require_paths:
73
63
  - lib
74
64
  required_ruby_version: !ruby/object:Gem::Requirement
75
65
  requirements:
76
- - - '>='
66
+ - - ">="
77
67
  - !ruby/object:Gem::Version
78
- version: '0'
68
+ version: '3.1'
79
69
  required_rubygems_version: !ruby/object:Gem::Requirement
80
70
  requirements:
81
- - - '>='
71
+ - - ">="
82
72
  - !ruby/object:Gem::Version
83
73
  version: 1.3.6
84
74
  requirements: []
85
- rubyforge_project:
86
- rubygems_version: 2.4.5
87
- signing_key:
75
+ rubygems_version: 3.5.16
76
+ signing_key:
88
77
  specification_version: 4
89
78
  summary: Automatically insert a text/plain part into your HTML multipart e-mails.
90
79
  test_files: []
data/CONTRIBUTING.md DELETED
@@ -1,125 +0,0 @@
1
- # Contributing to ActionMailer::Text
2
-
3
- This project is work of [many contributors](https://github.com/dblock/actionmailer-text/graphs/contributors).
4
-
5
- You're encouraged to submit [pull requests](https://github.com/dblock/actionmailer-text/pulls), [propose features and discuss issues](https://github.com/dblock/actionmailer-text/issues).
6
-
7
- In the examples below, substitute your Github username for `contributor` in URLs.
8
-
9
- ## Fork the Project
10
-
11
- Fork the [project on Github](https://github.com/dblock/actionmailer-text) and check out your copy.
12
-
13
- ```
14
- git clone https://github.com/contributor/actionmailer-text.git
15
- cd actionmailer-text
16
- git remote add upstream https://github.com/dblock/actionmailer-text.git
17
- ```
18
-
19
- ## Create a Topic Branch
20
-
21
- Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
22
-
23
- ```
24
- git checkout master
25
- git pull upstream master
26
- git checkout -b my-feature-branch
27
- ```
28
-
29
- ## Bundle Install and Test
30
-
31
- Ensure that you can build the project and run tests.
32
-
33
- ```
34
- bundle install
35
- bundle exec rake
36
- ```
37
-
38
- ## Write Tests
39
-
40
- Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build.
41
- Add to [spec](spec).
42
-
43
- We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
44
-
45
- ## Write Code
46
-
47
- Implement your feature or bug fix.
48
-
49
- Ruby style is enforced with [Rubocop](https://github.com/bbatsov/rubocop).
50
- Run `bundle exec rubocop` and fix any style issues highlighted.
51
-
52
- Make sure that `bundle exec rake` completes without errors.
53
-
54
- ## Write Documentation
55
-
56
- Document any external behavior in the [README](README.md).
57
-
58
- ## Update Changelog
59
-
60
- Add a line to [CHANGELOG](CHANGELOG.md) under *Next Release*.
61
- Make it look like every other line, including your name and link to your Github account.
62
-
63
- ## Commit Changes
64
-
65
- Make sure git knows your name and email address:
66
-
67
- ```
68
- git config --global user.name "Your Name"
69
- git config --global user.email "contributor@example.com"
70
- ```
71
-
72
- Writing good commit logs is important. A commit log should describe what changed and why.
73
-
74
- ```
75
- git add ...
76
- git commit
77
- ```
78
-
79
- ## Push
80
-
81
- ```
82
- git push origin my-feature-branch
83
- ```
84
-
85
- ## Make a Pull Request
86
-
87
- Go to https://github.com/contributor/grape and select your feature branch.
88
- Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
89
-
90
- ## Rebase
91
-
92
- If you've been working on a change for a while, rebase with upstream/master.
93
-
94
- ```
95
- git fetch upstream
96
- git rebase upstream/master
97
- git push origin my-feature-branch -f
98
- ```
99
-
100
- ## Update CHANGELOG Again
101
-
102
- Update the [CHANGELOG](CHANGELOG.md) with the pull request number. A typical entry looks as follows.
103
-
104
- ```
105
- * [#123](https://github.com/dblock/actionmailer-text/pull/123): Reticulated splines - [@contributor](https://github.com/contributor).
106
- ```
107
-
108
- Amend your previous commit and force push the changes.
109
-
110
- ```
111
- git commit --amend
112
- git push origin my-feature-branch -f
113
- ```
114
-
115
- ## Check on Your Pull Request
116
-
117
- Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
118
-
119
- ## Be Patient
120
-
121
- It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
122
-
123
- ## Thank You
124
-
125
- Please do know that we really appreciate and value your time and work. We love you, really.
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source 'http://rubygems.org'
2
-
3
- gemspec
4
-
5
- gem 'rake', '~> 10.4'
6
- gem 'rubocop', '0.30.0'
7
- gem 'rspec', '~> 3.2'
8
- gem 'email-example-spec', '~> 0.1.0'
data/Gemfile.lock DELETED
@@ -1,109 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- actionmailer-text (0.1.0)
5
- actionmailer
6
- htmlentities
7
-
8
- GEM
9
- remote: http://rubygems.org/
10
- specs:
11
- actionmailer (4.2.1)
12
- actionpack (= 4.2.1)
13
- actionview (= 4.2.1)
14
- activejob (= 4.2.1)
15
- mail (~> 2.5, >= 2.5.4)
16
- rails-dom-testing (~> 1.0, >= 1.0.5)
17
- actionpack (4.2.1)
18
- actionview (= 4.2.1)
19
- activesupport (= 4.2.1)
20
- rack (~> 1.6)
21
- rack-test (~> 0.6.2)
22
- rails-dom-testing (~> 1.0, >= 1.0.5)
23
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
24
- actionview (4.2.1)
25
- activesupport (= 4.2.1)
26
- builder (~> 3.1)
27
- erubis (~> 2.7.0)
28
- rails-dom-testing (~> 1.0, >= 1.0.5)
29
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
30
- activejob (4.2.1)
31
- activesupport (= 4.2.1)
32
- globalid (>= 0.3.0)
33
- activesupport (4.2.1)
34
- i18n (~> 0.7)
35
- json (~> 1.7, >= 1.7.7)
36
- minitest (~> 5.1)
37
- thread_safe (~> 0.3, >= 0.3.4)
38
- tzinfo (~> 1.1)
39
- ast (2.0.0)
40
- astrolabe (1.3.0)
41
- parser (>= 2.2.0.pre.3, < 3.0)
42
- builder (3.2.2)
43
- diff-lcs (1.2.5)
44
- email-example-spec (0.1.0)
45
- actionmailer
46
- erubis (2.7.0)
47
- globalid (0.3.3)
48
- activesupport (>= 4.1.0)
49
- htmlentities (4.3.1)
50
- i18n (0.7.0)
51
- json (1.8.2)
52
- loofah (2.0.1)
53
- nokogiri (>= 1.5.9)
54
- mail (2.6.3)
55
- mime-types (>= 1.16, < 3)
56
- mime-types (2.4.3)
57
- mini_portile (0.6.2)
58
- minitest (5.5.1)
59
- nokogiri (1.6.6.2)
60
- mini_portile (~> 0.6.0)
61
- parser (2.2.0.3)
62
- ast (>= 1.1, < 3.0)
63
- powerpack (0.1.0)
64
- rack (1.6.0)
65
- rack-test (0.6.3)
66
- rack (>= 1.0)
67
- rails-deprecated_sanitizer (1.0.3)
68
- activesupport (>= 4.2.0.alpha)
69
- rails-dom-testing (1.0.6)
70
- activesupport (>= 4.2.0.beta, < 5.0)
71
- nokogiri (~> 1.6.0)
72
- rails-deprecated_sanitizer (>= 1.0.1)
73
- rails-html-sanitizer (1.0.2)
74
- loofah (~> 2.0)
75
- rainbow (2.0.0)
76
- rake (10.4.2)
77
- rspec (3.2.0)
78
- rspec-core (~> 3.2.0)
79
- rspec-expectations (~> 3.2.0)
80
- rspec-mocks (~> 3.2.0)
81
- rspec-core (3.2.2)
82
- rspec-support (~> 3.2.0)
83
- rspec-expectations (3.2.0)
84
- diff-lcs (>= 1.2.0, < 2.0)
85
- rspec-support (~> 3.2.0)
86
- rspec-mocks (3.2.1)
87
- diff-lcs (>= 1.2.0, < 2.0)
88
- rspec-support (~> 3.2.0)
89
- rspec-support (3.2.2)
90
- rubocop (0.30.0)
91
- astrolabe (~> 1.3)
92
- parser (>= 2.2.0.1, < 3.0)
93
- powerpack (~> 0.1)
94
- rainbow (>= 1.99.1, < 3.0)
95
- ruby-progressbar (~> 1.4)
96
- ruby-progressbar (1.7.5)
97
- thread_safe (0.3.5)
98
- tzinfo (1.2.2)
99
- thread_safe (~> 0.1)
100
-
101
- PLATFORMS
102
- ruby
103
-
104
- DEPENDENCIES
105
- actionmailer-text!
106
- email-example-spec (~> 0.1.0)
107
- rake (~> 10.4)
108
- rspec (~> 3.2)
109
- rubocop (= 0.30.0)
data/Rakefile DELETED
@@ -1,16 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/gem_tasks'
3
-
4
- Bundler.setup :default, :development
5
-
6
- require 'rspec/core'
7
- require 'rspec/core/rake_task'
8
-
9
- RSpec::Core::RakeTask.new(:spec) do |spec|
10
- spec.pattern = FileList['spec/**/*_spec.rb']
11
- end
12
-
13
- require 'rubocop/rake_task'
14
- RuboCop::RakeTask.new
15
-
16
- task default: [:rubocop, :spec]
@@ -1,18 +0,0 @@
1
- $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
- require 'actionmailer-text/version'
3
-
4
- Gem::Specification.new do |s|
5
- s.name = 'actionmailer-text'
6
- s.version = ActionMailer::Text::VERSION
7
- s.authors = ['Daniel Doubrovkine']
8
- s.email = 'dblock@dblock.org'
9
- s.platform = Gem::Platform::RUBY
10
- s.required_rubygems_version = '>= 1.3.6'
11
- s.files = Dir['**/*']
12
- s.require_paths = ['lib']
13
- s.homepage = 'http://github.com/dblock/actionmailer-text'
14
- s.licenses = ['MIT']
15
- s.summary = 'Automatically insert a text/plain part into your HTML multipart e-mails.'
16
- s.add_dependency 'actionmailer'
17
- s.add_dependency 'htmlentities'
18
- end
Binary file
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActionMailer::Text do
4
- let(:mailer) do
5
- Class.new(ActionMailer::Base) do
6
- include ActionMailer::Text
7
-
8
- default from: 'Joe User <joe@example.org>'
9
-
10
- def welcome_mail(username)
11
- @username = username
12
- mail to: 'user@example.org', subject: 'Welcome!' do |format|
13
- format.html { render 'templates/welcome_email' }
14
- end
15
- end
16
- end
17
- end
18
- subject do
19
- mailer.welcome_mail('username')
20
- end
21
- it 'generates a text part' do
22
- expect(subject.parts.size).to eq 2
23
- end
24
- it 'inserts text part first' do
25
- expect(subject.parts.first.content_type).to eq 'text/plain; charset=UTF-8'
26
- end
27
- it 'inserts html part last' do
28
- expect(subject.parts.last.content_type).to eq 'text/html; charset=UTF-8'
29
- end
30
- it 'matches output' do
31
- expect(subject).to match_email_example_in 'welcome_email.multipart'
32
- end
33
- end
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActionMailer::Text do
4
- it 'has a version' do
5
- expect(ActionMailer::Text::VERSION).to_not be nil
6
- end
7
- end
data/spec/spec_helper.rb DELETED
@@ -1,12 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
-
3
- require 'rubygems'
4
- require 'rspec'
5
- require 'actionmailer-text'
6
- require 'email-example-spec'
7
-
8
- ActionMailer::Base.view_paths = File.join(File.dirname(__FILE__), 'support')
9
-
10
- EmailExampleSpec.configure do |config|
11
- config.fixture_path = File.join(File.dirname(__FILE__), 'support/fixtures')
12
- end
@@ -1,32 +0,0 @@
1
- Date: Thu, 01 Jan 1970 00:00:00 +0000
2
- From: Joe User <joe@example.org>
3
- To: user@example.org
4
- Message-ID: 1
5
- Subject: Welcome!
6
- Mime-Version: 1.0
7
- Content-Type: multipart/alternative;
8
- boundary=boundary;
9
- charset=UTF-8
10
- Content-Transfer-Encoding: 7bit
11
-
12
-
13
- --boundary
14
- Content-Type: text/plain;
15
- charset=UTF-8
16
- Content-Transfer-Encoding: 7bit
17
-
18
- Hi username,
19
-
20
- Thanks for joining our service! Please check back often.
21
- --boundary
22
- Content-Type: text/html;
23
- charset=UTF-8
24
- Content-Transfer-Encoding: 7bit
25
-
26
- <body>
27
- <p>Hi username,</p>
28
- <p>Thanks for joining our service! Please check back often.</p>
29
- </body>
30
-
31
-
32
- --boundary--
@@ -1,5 +0,0 @@
1
- <body>
2
- <p>Hi <%= @username %>,</p>
3
- <p>Thanks for joining our service! Please check back often.</p>
4
- </body>
5
-