ghostwriter 0.1.0.placeholder → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.ruby-version +1 -0
- data/.travis.yml +1 -1
- data/CODE_OF_CONDUCT.md +6 -42
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +67 -11
- data/Rakefile +2 -2
- data/bin/console +2 -2
- data/bin/setup +1 -2
- data/dirt-textify.gemspec +27 -0
- data/lib/ghostwriter.rb +3 -5
- data/lib/ghostwriter/version.rb +1 -1
- data/lib/ghostwriter/writer.rb +54 -0
- metadata +37 -22
- data/ghostwriter.gemspec +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MjAxZjQzNDU2NTEyMDgwODc3NTAyYjQyYTRhNGZjOTEwMzg4MTE0Yw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NjBjZWU4OWExMmYyOGU1NDMzNTI4MDhkNzEzMGU3YWFhNjdiM2M0MA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZDcxMDQ5N2IzMTU0YzlhMzZmMDBkODk2NDVhZjEwZTkyOTY0ZDFmMzZiMmYw
|
10
|
+
NDc3ZmY5NjgyNzkxOTUzMDg4YWU2NmNkZDgyMDdkNjc4OTMzMmIzYWY1MWY2
|
11
|
+
OWRhMzgxNjc5ODM4Yjc4NGE5ZTBmODBmNGUzOGU3NDY2YTA5NDk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NTIzYTdjNmRmZTRkMTc4NGIxZWJiYjBhYWVkMDI4ZDM1NTc4NDQ4ZTdkZDZk
|
14
|
+
YTVlN2Y1OGMzYTg3MjlkYmNhMjUyMGQwNTZlMmIzNjYxYmQyMDIxMjJiOTVi
|
15
|
+
N2YzMzczODBkZWMxZmY2MmJkYzJkYjQxZjJlZjBjZTM2OWJkMjQ=
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3
|
data/.travis.yml
CHANGED
data/CODE_OF_CONDUCT.md
CHANGED
@@ -1,49 +1,13 @@
|
|
1
1
|
# Contributor Code of Conduct
|
2
2
|
|
3
|
-
As contributors and maintainers of this project,
|
4
|
-
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
-
contribute through reporting issues, posting feature requests, updating
|
6
|
-
documentation, submitting pull requests or patches, and other activities.
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
7
4
|
|
8
|
-
We are committed to making participation in this project a harassment-free
|
9
|
-
experience for everyone, regardless of level of experience, gender, gender
|
10
|
-
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
-
body size, race, ethnicity, age, religion, or nationality.
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
12
6
|
|
13
|
-
Examples of unacceptable behavior by participants include
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
14
8
|
|
15
|
-
|
16
|
-
* Personal attacks
|
17
|
-
* Trolling or insulting/derogatory comments
|
18
|
-
* Public or private harassment
|
19
|
-
* Publishing other's private information, such as physical or electronic
|
20
|
-
addresses, without explicit permission
|
21
|
-
* Other unethical or unprofessional conduct
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
22
10
|
|
23
|
-
|
24
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
-
threatening, offensive, or harmful.
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
28
12
|
|
29
|
-
|
30
|
-
fairly and consistently applying these principles to every aspect of managing
|
31
|
-
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
-
Conduct may be permanently removed from the project team.
|
33
|
-
|
34
|
-
This code of conduct applies both within project spaces and in public spaces
|
35
|
-
when an individual is representing the project or its community.
|
36
|
-
|
37
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
-
reported by contacting a project maintainer at robin@tenjin.ca. All
|
39
|
-
complaints will be reviewed and investigated and will result in a response that
|
40
|
-
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
-
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
-
incident.
|
43
|
-
|
44
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
-
version 1.3.0, available at
|
46
|
-
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
-
|
48
|
-
[homepage]: http://contributor-covenant.org
|
49
|
-
[version]: http://contributor-covenant.org/version/1/3/0/
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Ghostwriter
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Ghostwriter rewrites your emails to conform to varying email client requirements.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -16,26 +14,84 @@ And then execute:
|
|
16
14
|
|
17
15
|
$ bundle
|
18
16
|
|
19
|
-
Or install it
|
17
|
+
Or install it manually with:
|
20
18
|
|
21
19
|
$ gem install ghostwriter
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
###Stripping HTML
|
24
|
+
|
25
|
+
Transform HTML into plaintext while preserving as much legibility and functionality as possible.
|
26
|
+
It's prime use is in quickly producing an automatic plaintext version of HTML emails.
|
27
|
+
|
28
|
+
Why offer plaintext?
|
29
|
+
|
30
|
+
* Spam filters prefer included plain text alternative
|
31
|
+
* Some email clients and apps can’t handle HTML
|
32
|
+
* Some people explicitly choose plaintext, either by requirement or simple preference
|
33
|
+
|
34
|
+
Create a `Ghostwriter::Writer` with the html you want modified, and call `#textify`:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
html = '<html><body>This is some markup <a href="tenjin.ca">and a link</a><p>Other tags translate, too</p></body></html>'
|
38
|
+
|
39
|
+
Ghostwriter::Writer.new(html).textify
|
40
|
+
|
41
|
+
=> "This is some markup and a link (tenjin.ca)\nOther tags translate, too\n\n"
|
42
|
+
|
43
|
+
```
|
44
|
+
|
45
|
+
`#textify` will use a `<base>` tag if included in the HTML source, or if one is provided explicitly:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
html = '<html><body>Relative links <a href="/contact">Link</a></body></html>'
|
49
|
+
|
50
|
+
Ghostwriter::Writer.new(html).textify(link_base: 'tenjin.ca')
|
51
|
+
|
52
|
+
=> "Relative links Link (tenjin.ca/contact)"
|
53
|
+
|
54
|
+
```
|
26
55
|
|
27
|
-
|
56
|
+
#### Mail Gem Example
|
57
|
+
|
58
|
+
To use `#textify` with the [mail](https://github.com/mikel/mail) gem, just provide the text-part by pasisng the html through Ghostwriter:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'mail'
|
28
62
|
|
29
|
-
|
63
|
+
html = 'My email and a <a href="http://tenjin.ca">link</a>'
|
30
64
|
|
31
|
-
|
65
|
+
mail = Mail.deliver do
|
66
|
+
to 'bob@example.com'
|
67
|
+
from 'dot@example.com'
|
68
|
+
subject 'Using Ghostwriter with Mail'
|
69
|
+
|
70
|
+
html_part do
|
71
|
+
content_type 'text/html; charset=UTF-8'
|
72
|
+
body html
|
73
|
+
end
|
74
|
+
|
75
|
+
text_part do
|
76
|
+
body Ghostwriter::Writer.new(html).textify
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
```
|
32
81
|
|
33
82
|
## Contributing
|
83
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/TenjinInc/ghostwriter
|
34
84
|
|
35
|
-
|
85
|
+
This project is intended to be a friendly space for collaboration, and contributors are expected to adhere to the
|
86
|
+
[Contributor Covenant](contributor-covenant.org) code of conduct.
|
36
87
|
|
88
|
+
### Core Developers
|
89
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
|
90
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
37
91
|
|
38
|
-
|
92
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
|
93
|
+
version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
|
94
|
+
push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
39
95
|
|
96
|
+
## License
|
40
97
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
-
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'ghostwriter'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
data/bin/setup
CHANGED
@@ -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 'ghostwriter/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gemspec|
|
7
|
+
gemspec.name = 'ghostwriter'
|
8
|
+
gemspec.version = Ghostwriter::VERSION
|
9
|
+
gemspec.authors = ['Robin Miller']
|
10
|
+
gemspec.email = ['robin@tenjin.ca']
|
11
|
+
|
12
|
+
gemspec.summary = %q{Intelligently extracts plaintext from an HTML document.}
|
13
|
+
gemspec.description = %q{Transforms HTML into plaintext while preserving legibility and functionality. }
|
14
|
+
gemspec.homepage = 'https://github.com/TenjinInc/ghostwriter'
|
15
|
+
gemspec.license = 'MIT'
|
16
|
+
|
17
|
+
gemspec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
gemspec.bindir = 'exe'
|
19
|
+
gemspec.executables = gemspec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
gemspec.require_paths = ['lib']
|
21
|
+
|
22
|
+
gemspec.add_dependency 'nokogiri', '~> 1.6'
|
23
|
+
|
24
|
+
gemspec.add_development_dependency 'bundler', '~> 1.10'
|
25
|
+
gemspec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
gemspec.add_development_dependency 'rspec', '~> 3.3'
|
27
|
+
end
|
data/lib/ghostwriter.rb
CHANGED
data/lib/ghostwriter/version.rb
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Ghostwriter
|
2
|
+
class Writer
|
3
|
+
def initialize(html)
|
4
|
+
@source_html = html
|
5
|
+
end
|
6
|
+
|
7
|
+
# Intelligently strips HTML down to text.
|
8
|
+
#
|
9
|
+
# Options:
|
10
|
+
# link_base: the url to prefix relative links with
|
11
|
+
def textify(options={})
|
12
|
+
html = @source_html.dup
|
13
|
+
|
14
|
+
html.gsub!(/\n|\t/, ' ')
|
15
|
+
html.squeeze!(' ')
|
16
|
+
|
17
|
+
html.gsub!('</p>', "</p>\n\n")
|
18
|
+
|
19
|
+
doc = Nokogiri::HTML(html)
|
20
|
+
|
21
|
+
doc.search('style').remove
|
22
|
+
doc.search('script').remove
|
23
|
+
|
24
|
+
base = doc.search('base').first #<base> is unique by W3C spec
|
25
|
+
|
26
|
+
base_url = base ? base['href'] : options[:link_base] || ''
|
27
|
+
|
28
|
+
doc.search('a').each do |link_node|
|
29
|
+
href = URI(link_node['href'])
|
30
|
+
href = base_url + href.to_s unless href.absolute?
|
31
|
+
|
32
|
+
link_node.inner_html = "#{link_node.inner_html} (#{href})"
|
33
|
+
end
|
34
|
+
|
35
|
+
doc.search('header, h1, h2, h3, h4, h5, h6').each do |node|
|
36
|
+
node.inner_html = "- #{node.inner_html} -\n".squeeze(' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
doc.search('hr').each do |node|
|
40
|
+
node.replace "\n----------\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
doc.search('br').each do |node|
|
44
|
+
node.replace "\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
# doc.search('p').each do |link_node|
|
48
|
+
# link_node.inner_html = link_node.inner_html + "\n\n"
|
49
|
+
# end
|
50
|
+
|
51
|
+
doc.text.gsub(/^[ ]+|[ ]+$/, '')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
metadata
CHANGED
@@ -1,68 +1,82 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghostwriter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- -
|
31
|
+
- - ~>
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
33
|
+
version: '1.10'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- -
|
38
|
+
- - ~>
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
40
|
+
version: '1.10'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- -
|
45
|
+
- - ~>
|
32
46
|
- !ruby/object:Gem::Version
|
33
47
|
version: '10.0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- -
|
52
|
+
- - ~>
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '10.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- -
|
59
|
+
- - ~>
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
61
|
+
version: '3.3'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- -
|
66
|
+
- - ~>
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
55
|
-
description: Transforms HTML into plaintext while preserving legibility and functionality.
|
56
|
-
Previously known as dirt-textify.
|
68
|
+
version: '3.3'
|
69
|
+
description: ! 'Transforms HTML into plaintext while preserving legibility and functionality. '
|
57
70
|
email:
|
58
71
|
- robin@tenjin.ca
|
59
72
|
executables: []
|
60
73
|
extensions: []
|
61
74
|
extra_rdoc_files: []
|
62
75
|
files:
|
63
|
-
-
|
64
|
-
-
|
65
|
-
-
|
76
|
+
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- .ruby-version
|
79
|
+
- .travis.yml
|
66
80
|
- CODE_OF_CONDUCT.md
|
67
81
|
- Gemfile
|
68
82
|
- LICENSE.txt
|
@@ -70,9 +84,10 @@ files:
|
|
70
84
|
- Rakefile
|
71
85
|
- bin/console
|
72
86
|
- bin/setup
|
73
|
-
-
|
87
|
+
- dirt-textify.gemspec
|
74
88
|
- lib/ghostwriter.rb
|
75
89
|
- lib/ghostwriter/version.rb
|
90
|
+
- lib/ghostwriter/writer.rb
|
76
91
|
homepage: https://github.com/TenjinInc/ghostwriter
|
77
92
|
licenses:
|
78
93
|
- MIT
|
@@ -83,17 +98,17 @@ require_paths:
|
|
83
98
|
- lib
|
84
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
85
100
|
requirements:
|
86
|
-
- -
|
101
|
+
- - ! '>='
|
87
102
|
- !ruby/object:Gem::Version
|
88
103
|
version: '0'
|
89
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
105
|
requirements:
|
91
|
-
- -
|
106
|
+
- - ! '>='
|
92
107
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
108
|
+
version: '0'
|
94
109
|
requirements: []
|
95
110
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.4.
|
111
|
+
rubygems_version: 2.4.3
|
97
112
|
signing_key:
|
98
113
|
specification_version: 4
|
99
114
|
summary: Intelligently extracts plaintext from an HTML document.
|
data/ghostwriter.gemspec
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'ghostwriter/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "ghostwriter"
|
8
|
-
spec.version = Ghostwriter::VERSION
|
9
|
-
spec.authors = ["Robin Miller"]
|
10
|
-
spec.email = ["robin@tenjin.ca"]
|
11
|
-
|
12
|
-
spec.summary = %q{Intelligently extracts plaintext from an HTML document.}
|
13
|
-
spec.description = %q{Transforms HTML into plaintext while preserving legibility and functionality. Previously known as dirt-textify.}
|
14
|
-
spec.homepage = 'https://github.com/TenjinInc/ghostwriter'
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.bindir = "exe"
|
19
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", "~> 1.11"
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
-
end
|