turbograft 0.0.4
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +42 -0
- data/lib/turbograft/cookies.rb +10 -0
- data/lib/turbograft/redirection.rb +15 -0
- data/lib/turbograft/version.rb +3 -0
- data/lib/turbograft/x_domain_blocker.rb +21 -0
- data/lib/turbograft/xhr_headers.rb +46 -0
- data/lib/turbograft/xhr_url_for.rb +15 -0
- data/lib/turbograft.rb +36 -0
- metadata +227 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b2589fafda558edc016e256e95e3e3d05fb231b0
|
4
|
+
data.tar.gz: 68146f1fa64c8132aea61ebf0d48f4a4622792c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d0559b8235247a2e0a6cde2491bccd14846137a0e5433791694210e111f0a99e383bb2577c2b44349b034c6bb9cd7ac2280148ab8c484e52bd833519637c1018
|
7
|
+
data.tar.gz: e2c0ff61852c4b7ec643ee8cc486af92c1d5905b454bc485ef4cdece46fb72fade63b9cd40f4680fa676cba523f841670abc0571042d34701d58f59188f5f1e5
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Shopify Inc.
|
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/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# TurboGraft
|
2
|
+
|
3
|
+
It's like turbolinks, but with partial page replacement and tests
|
4
|
+
|
5
|
+
`Graft` - (noun) a shoot or twig inserted into a slit on the trunk or stem of a living plant, from which it receives sap.
|
6
|
+
|
7
|
+
In botony, one can take parts of a tree and splice it onto another tree. The DOM is a tree. In this library, we're cutting off sub-trees of the DOM and splicing new ones on.
|
8
|
+
|
9
|
+
## Status
|
10
|
+
[](http://badge.fury.io/rb/turbograft)
|
11
|
+
[](http://travis-ci.org/Shopify/turbograft)
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
gem 'turbograft'
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install turbograft
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
TODO
|
30
|
+
|
31
|
+
## Example App
|
32
|
+
|
33
|
+
cd test/example
|
34
|
+
bundle exec rails server
|
35
|
+
|
36
|
+
## Contributing
|
37
|
+
|
38
|
+
1. Fork it ( http://github.com/<my-github-username>/turbograft/fork )
|
39
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
40
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
41
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
42
|
+
5. Create new Pull Request
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module TurboGraft
|
2
|
+
# Sets a request_method cookie containing the request method of the current request.
|
3
|
+
# The Turbolinks script will not initialize if this cookie is set to anything other than GET.
|
4
|
+
module Cookies
|
5
|
+
private
|
6
|
+
def set_request_method_cookie
|
7
|
+
cookies[:request_method] = request.request_method
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module TurboGraft
|
2
|
+
# Provides a means of using Turbolinks to perform redirects. The server
|
3
|
+
# will respond with a JavaScript call to Turbolinks.visit(url).
|
4
|
+
module Redirection
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def redirect_via_turbolinks_to(url = {}, response_status = {})
|
8
|
+
redirect_to(url, response_status)
|
9
|
+
|
10
|
+
self.status = 200
|
11
|
+
self.response_body = "Turbolinks.visit('#{location}');"
|
12
|
+
response.content_type = Mime::JS
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TurboGraft
|
2
|
+
# Changes the response status to 403 Forbidden if all of these conditions are true:
|
3
|
+
# - The current request originated from Turbolinks
|
4
|
+
# - The request is being redirected to a different domain
|
5
|
+
module XDomainBlocker
|
6
|
+
private
|
7
|
+
def same_origin?(a, b)
|
8
|
+
a = URI.parse URI.escape(a)
|
9
|
+
b = URI.parse URI.escape(b)
|
10
|
+
[a.scheme, a.host, a.port] == [b.scheme, b.host, b.port]
|
11
|
+
end
|
12
|
+
|
13
|
+
def abort_xdomain_redirect
|
14
|
+
to_uri = response.headers['Location'] || ""
|
15
|
+
current = request.headers['X-XHR-Referer'] || ""
|
16
|
+
unless to_uri.blank? || current.blank? || same_origin?(current, to_uri)
|
17
|
+
self.status = 403
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module TurboGraft
|
2
|
+
# Intercepts calls to _compute_redirect_to_location (used by redirect_to) for two purposes.
|
3
|
+
#
|
4
|
+
# 1. Corrects the behavior of redirect_to with the :back option by using the X-XHR-Referer
|
5
|
+
# request header instead of the standard Referer request header.
|
6
|
+
#
|
7
|
+
# 2. Stores the return value (the redirect target url) to persist through to the redirect
|
8
|
+
# request, where it will be used to set the X-XHR-Redirected-To response header. The
|
9
|
+
# Turbolinks script will detect the header and use replaceState to reflect the redirected
|
10
|
+
# url.
|
11
|
+
module XHRHeaders
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
def _compute_redirect_to_location(*args)
|
15
|
+
options, request = _normalize_redirect_params(args)
|
16
|
+
|
17
|
+
store_for_turbolinks begin
|
18
|
+
if options == :back && request.headers["X-XHR-Referer"]
|
19
|
+
super(*[(request if args.length == 2), request.headers["X-XHR-Referer"]].compact)
|
20
|
+
else
|
21
|
+
super(*args)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def store_for_turbolinks(url)
|
28
|
+
session[:_turbolinks_redirect_to] = url if request.headers["X-XHR-Referer"]
|
29
|
+
url
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_xhr_redirected_to
|
33
|
+
if session[:_turbolinks_redirect_to]
|
34
|
+
response.headers['X-XHR-Redirected-To'] = session.delete :_turbolinks_redirect_to
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Ensure backwards compatibility
|
39
|
+
# Rails < 4.2: _compute_redirect_to_location(options)
|
40
|
+
# Rails >= 4.2: _compute_redirect_to_location(request, options)
|
41
|
+
def _normalize_redirect_params(args)
|
42
|
+
options, req = args.reverse
|
43
|
+
[options, req || request]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module TurboGraft
|
2
|
+
# Corrects the behavior of url_for (and link_to, which uses url_for) with the :back
|
3
|
+
# option by using the X-XHR-Referer request header instead of the standard Referer
|
4
|
+
# request header.
|
5
|
+
module XHRUrlFor
|
6
|
+
def self.included(base)
|
7
|
+
base.alias_method_chain :url_for, :xhr_referer
|
8
|
+
end
|
9
|
+
|
10
|
+
def url_for_with_xhr_referer(options = {})
|
11
|
+
options = (controller.request.headers["X-XHR-Referer"] || options) if options == :back
|
12
|
+
url_for_without_xhr_referer options
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/turbograft.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "rails"
|
2
|
+
require "active_support"
|
3
|
+
|
4
|
+
require "turbograft/version"
|
5
|
+
require "turbograft/xhr_headers"
|
6
|
+
require "turbograft/xhr_url_for"
|
7
|
+
require "turbograft/cookies"
|
8
|
+
require "turbograft/x_domain_blocker"
|
9
|
+
require "turbograft/redirection"
|
10
|
+
|
11
|
+
module TurboGraft
|
12
|
+
class Engine < ::Rails::Engine
|
13
|
+
initializer :turbograft do |config|
|
14
|
+
ActiveSupport.on_load(:action_controller) do
|
15
|
+
ActionController::Base.class_eval do
|
16
|
+
include XHRHeaders, Cookies, XDomainBlocker, Redirection
|
17
|
+
before_filter :set_xhr_redirected_to, :set_request_method_cookie
|
18
|
+
after_filter :abort_xdomain_redirect
|
19
|
+
end
|
20
|
+
|
21
|
+
ActionDispatch::Request.class_eval do
|
22
|
+
def referer
|
23
|
+
self.headers['X-XHR-Referer'] || super
|
24
|
+
end
|
25
|
+
alias referrer referer
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
ActiveSupport.on_load(:action_view) do
|
30
|
+
(ActionView::RoutingUrlFor rescue ActionView::Helpers::UrlHelper).module_eval do
|
31
|
+
include XHRUrlFor
|
32
|
+
end
|
33
|
+
end unless RUBY_VERSION =~ /^1\.8/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: turbograft
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kristian Plettenberg-Dussault
|
8
|
+
- Justin Li
|
9
|
+
- Nicholas Simmons
|
10
|
+
- Tyler Mercier
|
11
|
+
- Anthony Cameron
|
12
|
+
- Patrick Donovan
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
date: 2014-09-24 00:00:00.000000000 Z
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: coffee-rails
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '0'
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '0'
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: bundler
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :development
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
type: :development
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: rails
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: jquery-rails
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
type: :development
|
82
|
+
prerelease: false
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: minitest-reporters
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
type: :development
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: capybara
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
type: :development
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: selenium-webdriver
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
- !ruby/object:Gem::Dependency
|
131
|
+
name: teaspoon
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
type: :development
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
- !ruby/object:Gem::Dependency
|
145
|
+
name: sqlite3
|
146
|
+
requirement: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
type: :development
|
152
|
+
prerelease: false
|
153
|
+
version_requirements: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: thin
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
type: :development
|
166
|
+
prerelease: false
|
167
|
+
version_requirements: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
- !ruby/object:Gem::Dependency
|
173
|
+
name: byebug
|
174
|
+
requirement: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
description: It's like turbolinks, but with partial page replacement and tests
|
187
|
+
email:
|
188
|
+
- tylermercier@gmail.com
|
189
|
+
executables: []
|
190
|
+
extensions: []
|
191
|
+
extra_rdoc_files: []
|
192
|
+
files:
|
193
|
+
- lib/turbograft.rb
|
194
|
+
- lib/turbograft/cookies.rb
|
195
|
+
- lib/turbograft/redirection.rb
|
196
|
+
- lib/turbograft/version.rb
|
197
|
+
- lib/turbograft/x_domain_blocker.rb
|
198
|
+
- lib/turbograft/xhr_headers.rb
|
199
|
+
- lib/turbograft/xhr_url_for.rb
|
200
|
+
- README.md
|
201
|
+
- MIT-LICENSE
|
202
|
+
homepage: https://github.com/Shopify/turbograft
|
203
|
+
licenses:
|
204
|
+
- MIT
|
205
|
+
metadata: {}
|
206
|
+
post_install_message:
|
207
|
+
rdoc_options: []
|
208
|
+
require_paths:
|
209
|
+
- lib
|
210
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
requirements: []
|
221
|
+
rubyforge_project:
|
222
|
+
rubygems_version: 2.0.14
|
223
|
+
signing_key:
|
224
|
+
specification_version: 4
|
225
|
+
summary: turbolinks with partial page replacement
|
226
|
+
test_files: []
|
227
|
+
has_rdoc:
|