ghost_in_the_post 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +24 -0
- data/lib/ghost_in_the_post.rb +47 -0
- data/lib/ghost_in_the_post/automatic.rb +19 -0
- data/lib/ghost_in_the_post/ghost_on_command.rb +10 -0
- data/lib/ghost_in_the_post/ghost_on_delivery.rb +12 -0
- data/lib/ghost_in_the_post/mail_ghost.rb +30 -0
- data/lib/ghost_in_the_post/mailer.rb +18 -0
- data/lib/ghost_in_the_post/phantom/staticize.js +27 -0
- data/lib/ghost_in_the_post/phantom_transform.rb +91 -0
- data/lib/ghost_in_the_post/version.rb +3 -0
- data/spec/dummy/Gemfile +3 -0
- data/spec/dummy/Gemfile.lock +115 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/test.js +1 -0
- data/spec/dummy/app/mailers/auto_mailer.rb +13 -0
- data/spec/dummy/app/mailers/mailer.rb +13 -0
- data/spec/dummy/app/views/auto_mailer/normal_email.html.erb +13 -0
- data/spec/dummy/app/views/auto_mailer/normal_email.text +1 -0
- data/spec/dummy/app/views/mailer/normal_email.html.erb +12 -0
- data/spec/dummy/app/views/mailer/normal_email.text +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +13 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +11 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/ghost_in_the_post.rb +5 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/log/development.log +216 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1hVihiFdBkDBsuCvA1I2vuFa9N6p-5zQ-qKvf4vz7jA.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/23mzeUAO-pIzGJ1n84Dbg25udWeSiBcd6e_QsDihWQc.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6544SZAu2zCeDrdro4h3izdKNXVvHzstwz12UxeiJoA.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/BMI0IB92xLhvUPcr_K0JuSk8zczmrEEbJCd3qwHauhQ.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/GtqgDsC0JMsKfj0x5uQrbPcSS3QIPIzLKrq2fGJDBf0.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/IFLV6zTaBXU1ccodbD3QJ4xUIOEix_Fbb7j8wsxrHw8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Lc8lcXR-AibSZCIbx_imdfIOmD-zbZ_pwSNMs0o0Dos.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/O9gjtBITAGlfzUwc2DT5N0GW2bo2b2yQ64gnQljLogM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/OQXwnC5z5STtd87Tr2dz1QBt4iZ8PoZTH8KBtBlUGnE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/OZ04c215C4Euu3scfhmxmte0o_tZOVWTqrv61cpy7H4.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_Bn81xMZj4dS_W5s9uSDhtEdpRZtsc21rcKEYAPCsZY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_Cw52w24AWZEbxLmduyWBMA6Y1OmJiEm1VNn7pY4rtk.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_HO5Nyj_TzTxVwa4OOf_0UJfBCmjgkv7NsRU29AD5Oo.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/eN_ueL7m-D9xkEZpaLKwCxdrNzyz-MW9jcdJ5TdF9j8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/efKfhZKxLC7ERXlMb5CQMqYwbvWS-A--pH-0fqzvRiQ.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/goEv0RKoifagsjFSdEHY-23E9ybQn_t1HHEZq7PlKQI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/n6_6RjvPX2rCv5dytbSnnDrGwAj1ZcPfninuNUeP_iE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/nXo-w2o4zQBM_uSUnniuP53t5erBbSZPecMED9YnzQI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oB1njyQ78MOMRf_5TvuYzHleeI8eke5-FDIIVl7qas0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qxbw0jMkxTNeM5T2QovOD9vTyvjHVjBN5tZdwBf519A.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y98HqYF9nxOk8t_j3BKv9Nc4LuSAEzhER7rCCvOM6xI.cache +1 -0
- data/spec/lib/ghost_in_the_post/automatic_spec.rb +42 -0
- data/spec/lib/ghost_in_the_post/ghost_on_command_spec.rb +26 -0
- data/spec/lib/ghost_in_the_post/mail_ghost_spec.rb +73 -0
- data/spec/lib/ghost_in_the_post/mailer_spec.rb +38 -0
- data/spec/lib/ghost_in_the_post/phantom_transform_spec.rb +134 -0
- data/spec/lib/ghost_in_the_post_spec.rb +60 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/mailer_support.rb +23 -0
- data/spec/support/quiet_load.rb +6 -0
- metadata +238 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d5264602db0f4c3dff7764e85b40b297046a9a55
|
4
|
+
data.tar.gz: 289c490672985941a51227c4a9133ec1ba9e175c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c7b6aca158ff83c738d9cb85d01d7011d9cae5d8e47a8f5ed6650dc394086a216217ab2e7c557796fbe02583b0c6489d959caa90c00e3ff1376bc3c38aa20f75
|
7
|
+
data.tar.gz: 40ae64bdf2f34875db66564f55de75b23563ed87595fe10102fc894e78ea091abf67e0d0c9572106c65fc1e358a74f0be406d1a19bf9d44737eb481f1ddc9fb2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Tim Anema
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
require 'rdoc/task'
|
7
|
+
require "bundler/gem_tasks"
|
8
|
+
|
9
|
+
desc "Run specs"
|
10
|
+
task :spec do
|
11
|
+
sh "bundle exec rspec -f progress"
|
12
|
+
end
|
13
|
+
|
14
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'GhostInThePost'
|
17
|
+
rdoc.options << '--line-numbers'
|
18
|
+
rdoc.rdoc_files.include('README.rdoc')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
task :default => :spec
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rails'
|
2
|
+
module GhostInThePost
|
3
|
+
ATTRIBUTE_NAMES = [
|
4
|
+
:phantomjs_path,
|
5
|
+
:includes,
|
6
|
+
:remove_js_tags,
|
7
|
+
]
|
8
|
+
private_constant :ATTRIBUTE_NAMES
|
9
|
+
cattr_reader(*ATTRIBUTE_NAMES)
|
10
|
+
|
11
|
+
@@phantomjs_path = nil #setting this to nil helps testing
|
12
|
+
@@includes = []
|
13
|
+
@@remove_js_tags = true
|
14
|
+
|
15
|
+
def self.config=(new_config={})
|
16
|
+
self.complain_about_unknown_keys(new_config.keys)
|
17
|
+
@@phantomjs_path = new_config[:phantomjs_path]
|
18
|
+
@@includes = Array(new_config[:includes])
|
19
|
+
@@remove_js_tags = new_config[:remove_js_tags].nil? ? true : new_config[:remove_js_tags]
|
20
|
+
raise ArgumentError, "GhostInThePost.config.phantomjs_path is not set" if self.phantomjs_path.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.phantomjs_path
|
24
|
+
@@phantomjs_path or raise ArgumentError, "GhostInThePost.config.phantomjs_path is not set"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.complain_about_unknown_keys(keys)
|
30
|
+
invalid_keys = keys - ATTRIBUTE_NAMES
|
31
|
+
if invalid_keys.size > 0
|
32
|
+
raise ArgumentError, "Unknown configuration parameters: #{invalid_keys}", caller(1)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
require "ghost_in_the_post/version"
|
39
|
+
|
40
|
+
require "ghost_in_the_post/phantom_transform"
|
41
|
+
require "ghost_in_the_post/mail_ghost"
|
42
|
+
|
43
|
+
require "ghost_in_the_post/ghost_on_command"
|
44
|
+
require "ghost_in_the_post/ghost_on_delivery"
|
45
|
+
|
46
|
+
require "ghost_in_the_post/mailer"
|
47
|
+
require "ghost_in_the_post/automatic"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GhostInThePost
|
2
|
+
module Automatic
|
3
|
+
attr_accessor :included_scripts
|
4
|
+
|
5
|
+
def include_script(*paths)
|
6
|
+
@included_scripts ||= []
|
7
|
+
@included_scripts += paths
|
8
|
+
end
|
9
|
+
|
10
|
+
def mail(*args, &block)
|
11
|
+
super.tap do |email|
|
12
|
+
email.extend GhostOnCommand
|
13
|
+
email.extend GhostOnDelivery
|
14
|
+
email.included_scripts = @included_scripts
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module GhostInThePost
|
2
|
+
class MailGhost
|
3
|
+
attr_reader :email, :included_scripts
|
4
|
+
|
5
|
+
def initialize(email, included_scripts)
|
6
|
+
@email = email
|
7
|
+
@included_scripts = Array(included_scripts).compact
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute
|
11
|
+
improve_body if email.content_type =~ /^text\/html/
|
12
|
+
improve_html_part(email.html_part) if email.html_part
|
13
|
+
email
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def improve_body
|
19
|
+
email.body = ghost_html(email.body.decoded)
|
20
|
+
end
|
21
|
+
|
22
|
+
def improve_html_part(html_part)
|
23
|
+
html_part.body = ghost_html(html_part.body.decoded)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ghost_html(old_html)
|
27
|
+
PhantomTransform.new(old_html, included_scripts).transform
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module GhostInThePost
|
2
|
+
module Mailer
|
3
|
+
attr_accessor :included_scripts
|
4
|
+
|
5
|
+
def include_script(*paths)
|
6
|
+
@included_scripts ||= []
|
7
|
+
@included_scripts += paths
|
8
|
+
end
|
9
|
+
|
10
|
+
def mail(*args, &block)
|
11
|
+
super.tap do |email|
|
12
|
+
email.extend GhostOnCommand
|
13
|
+
email.included_scripts = included_scripts
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"use strict";
|
2
|
+
var system = require('system'),
|
3
|
+
page = require('webpage').create(),
|
4
|
+
html = system.args[1], //the email to be processed
|
5
|
+
no_script = system.args[2] == "true",
|
6
|
+
include = system.args[3]; //the injected js file
|
7
|
+
|
8
|
+
page.onLoadFinished = function(status) {
|
9
|
+
//load included scripts to be loaded on the dom
|
10
|
+
if(!!include){
|
11
|
+
page.injectJs(include);
|
12
|
+
}
|
13
|
+
if(no_script) {
|
14
|
+
page.evaluate(function(){
|
15
|
+
var script_tags = document.getElementsByTagName("script");
|
16
|
+
for(var i = 0; i < script_tags.length; i++) {
|
17
|
+
script_tags[i].parentNode.removeChild(script_tags[i]);
|
18
|
+
}
|
19
|
+
})
|
20
|
+
}
|
21
|
+
//write out to console to export contents
|
22
|
+
console.log(page.content);
|
23
|
+
phantom.exit(); //get out of here
|
24
|
+
};
|
25
|
+
//load html content
|
26
|
+
page.setContent(html, 'http://www.whatever.com');
|
27
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module GhostInThePost
|
2
|
+
class PhantomTransform
|
3
|
+
PHANTOMJS_SCRIPT = File.expand_path('../phantom/staticize.js', __FILE__)
|
4
|
+
|
5
|
+
def initialize(html, included_scripts=[])
|
6
|
+
@html = html
|
7
|
+
@included_scripts = Array(included_scripts).compact
|
8
|
+
end
|
9
|
+
|
10
|
+
def transform
|
11
|
+
injectable_scripts.any? ? transform_with_injections : simple_transform
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def command
|
17
|
+
[
|
18
|
+
GhostInThePost.phantomjs_path,
|
19
|
+
PHANTOMJS_SCRIPT,
|
20
|
+
@html,
|
21
|
+
GhostInThePost.remove_js_tags
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
#there is scripts to inject so create a tmp file to put them all in
|
26
|
+
def transform_with_injections
|
27
|
+
#set output to just html so that if there is an error that is caught it will
|
28
|
+
#at least return valid html
|
29
|
+
output = @html
|
30
|
+
begin
|
31
|
+
#generate a tempfile with all the js that we need so that phantom can inject
|
32
|
+
#easily and not have to max out a single command
|
33
|
+
file = Tempfile.new(['inject', '.js'])
|
34
|
+
injectable_scripts.map do |script|
|
35
|
+
asset = find_asset_in_pipeline(script)
|
36
|
+
file.write(asset.to_s) unless asset.nil?
|
37
|
+
end.compact
|
38
|
+
file.close #closing the file makes it accessible by phantom
|
39
|
+
|
40
|
+
#generate the html with the javascript
|
41
|
+
output = IO.popen(command + [file.path]){|io| io.read}
|
42
|
+
|
43
|
+
file.unlink
|
44
|
+
rescue => e
|
45
|
+
#clean up the temp file
|
46
|
+
file.unlink
|
47
|
+
end
|
48
|
+
output
|
49
|
+
end
|
50
|
+
|
51
|
+
#no scripts to inject so just run the command
|
52
|
+
def simple_transform
|
53
|
+
IO.popen(command){|io| io.read}
|
54
|
+
end
|
55
|
+
|
56
|
+
def injectable_scripts
|
57
|
+
@injectable_scripts ||= (GhostInThePost.includes + @included_scripts)
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_asset_in_pipeline(name)
|
61
|
+
normalized_name = normalize_asset_name(name)
|
62
|
+
Rails.application.assets[normalized_name] || Rails.application.assets[remove_asset_digest(normalized_name)]
|
63
|
+
end
|
64
|
+
|
65
|
+
def normalize_asset_name(href)
|
66
|
+
remove_asset_prefix(href.split('?').first)
|
67
|
+
end
|
68
|
+
|
69
|
+
DIGEST_PATTERN = /
|
70
|
+
- # Digest comes after a dash
|
71
|
+
(?:
|
72
|
+
[a-z0-9]{32} | # Old style is 32 character hash
|
73
|
+
[a-z0-9]{64} # New style is 64 characters
|
74
|
+
)
|
75
|
+
\. # Dot for the file extension
|
76
|
+
/x.freeze
|
77
|
+
|
78
|
+
def remove_asset_digest(path)
|
79
|
+
path.gsub(DIGEST_PATTERN, '.')
|
80
|
+
end
|
81
|
+
|
82
|
+
def remove_asset_prefix(path)
|
83
|
+
path.sub(Regexp.new("^#{Regexp.quote(asset_prefix)}/?"), "")
|
84
|
+
end
|
85
|
+
|
86
|
+
def asset_prefix
|
87
|
+
::Rails.application.try(:config).try(:assets).try(:prefix) || "/assets"
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
data/spec/dummy/Gemfile
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../..
|
3
|
+
specs:
|
4
|
+
ghost_in_the_post (0.0.1)
|
5
|
+
rails (~> 4.2.3)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actionmailer (4.2.3)
|
11
|
+
actionpack (= 4.2.3)
|
12
|
+
actionview (= 4.2.3)
|
13
|
+
activejob (= 4.2.3)
|
14
|
+
mail (~> 2.5, >= 2.5.4)
|
15
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
16
|
+
actionpack (4.2.3)
|
17
|
+
actionview (= 4.2.3)
|
18
|
+
activesupport (= 4.2.3)
|
19
|
+
rack (~> 1.6)
|
20
|
+
rack-test (~> 0.6.2)
|
21
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
22
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
23
|
+
actionview (4.2.3)
|
24
|
+
activesupport (= 4.2.3)
|
25
|
+
builder (~> 3.1)
|
26
|
+
erubis (~> 2.7.0)
|
27
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
28
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
29
|
+
activejob (4.2.3)
|
30
|
+
activesupport (= 4.2.3)
|
31
|
+
globalid (>= 0.3.0)
|
32
|
+
activemodel (4.2.3)
|
33
|
+
activesupport (= 4.2.3)
|
34
|
+
builder (~> 3.1)
|
35
|
+
activerecord (4.2.3)
|
36
|
+
activemodel (= 4.2.3)
|
37
|
+
activesupport (= 4.2.3)
|
38
|
+
arel (~> 6.0)
|
39
|
+
activesupport (4.2.3)
|
40
|
+
i18n (~> 0.7)
|
41
|
+
json (~> 1.7, >= 1.7.7)
|
42
|
+
minitest (~> 5.1)
|
43
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
44
|
+
tzinfo (~> 1.1)
|
45
|
+
arel (6.0.3)
|
46
|
+
builder (3.2.2)
|
47
|
+
concurrent-ruby (1.0.0)
|
48
|
+
concurrent-ruby (1.0.0-java)
|
49
|
+
erubis (2.7.0)
|
50
|
+
globalid (0.3.6)
|
51
|
+
activesupport (>= 4.1.0)
|
52
|
+
i18n (0.7.0)
|
53
|
+
json (1.8.3)
|
54
|
+
json (1.8.3-java)
|
55
|
+
loofah (2.0.3)
|
56
|
+
nokogiri (>= 1.5.9)
|
57
|
+
mail (2.6.3)
|
58
|
+
mime-types (>= 1.16, < 3)
|
59
|
+
mime-types (2.99)
|
60
|
+
mini_portile2 (2.0.0)
|
61
|
+
minitest (5.8.4)
|
62
|
+
nokogiri (1.6.7.2)
|
63
|
+
mini_portile2 (~> 2.0.0.rc2)
|
64
|
+
nokogiri (1.6.7.2-java)
|
65
|
+
rack (1.6.4)
|
66
|
+
rack-test (0.6.3)
|
67
|
+
rack (>= 1.0)
|
68
|
+
rails (4.2.3)
|
69
|
+
actionmailer (= 4.2.3)
|
70
|
+
actionpack (= 4.2.3)
|
71
|
+
actionview (= 4.2.3)
|
72
|
+
activejob (= 4.2.3)
|
73
|
+
activemodel (= 4.2.3)
|
74
|
+
activerecord (= 4.2.3)
|
75
|
+
activesupport (= 4.2.3)
|
76
|
+
bundler (>= 1.3.0, < 2.0)
|
77
|
+
railties (= 4.2.3)
|
78
|
+
sprockets-rails
|
79
|
+
rails-deprecated_sanitizer (1.0.3)
|
80
|
+
activesupport (>= 4.2.0.alpha)
|
81
|
+
rails-dom-testing (1.0.7)
|
82
|
+
activesupport (>= 4.2.0.beta, < 5.0)
|
83
|
+
nokogiri (~> 1.6.0)
|
84
|
+
rails-deprecated_sanitizer (>= 1.0.1)
|
85
|
+
rails-html-sanitizer (1.0.3)
|
86
|
+
loofah (~> 2.0)
|
87
|
+
railties (4.2.3)
|
88
|
+
actionpack (= 4.2.3)
|
89
|
+
activesupport (= 4.2.3)
|
90
|
+
rake (>= 0.8.7)
|
91
|
+
thor (>= 0.18.1, < 2.0)
|
92
|
+
rake (10.5.0)
|
93
|
+
sprockets (3.5.2)
|
94
|
+
concurrent-ruby (~> 1.0)
|
95
|
+
rack (> 1, < 3)
|
96
|
+
sprockets-rails (3.0.1)
|
97
|
+
actionpack (>= 4.0)
|
98
|
+
activesupport (>= 4.0)
|
99
|
+
sprockets (>= 3.0.0)
|
100
|
+
thor (0.19.1)
|
101
|
+
thread_safe (0.3.5)
|
102
|
+
thread_safe (0.3.5-java)
|
103
|
+
tzinfo (1.2.2)
|
104
|
+
thread_safe (~> 0.1)
|
105
|
+
|
106
|
+
PLATFORMS
|
107
|
+
java
|
108
|
+
ruby
|
109
|
+
|
110
|
+
DEPENDENCIES
|
111
|
+
ghost_in_the_post!
|
112
|
+
rails (= 4.2.3)
|
113
|
+
|
114
|
+
BUNDLED WITH
|
115
|
+
1.10.6
|