turbograft 0.2.3 → 0.3.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 +4 -4
- data/README.md +2 -1
- data/lib/assets/javascripts/turbograft/turbohead.coffee +215 -0
- data/lib/assets/javascripts/turbograft/turbolinks.coffee +42 -39
- data/lib/turbograft/version.rb +1 -1
- data/lib/turbograft/xhr_url_for.rb +2 -6
- data/lib/turbograft.rb +3 -3
- metadata +4 -4
- data/lib/turbograft.js +0 -978
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5a814c49eaff1fbe7cf0bb02f67ef8d96fe8ff9
|
4
|
+
data.tar.gz: dd94aabbd02817b9ce92f99f87651daa94975176
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cfa4e748a8278ab568aac8b985eaa46df40fbf6ca063785fd66be1408ad55221d146683d0edeeba1f047a1ede182dc45f000353639886d1ffc27df958320168
|
7
|
+
data.tar.gz: 262fa76bf7948cd31f889e881c3b63d8a88a41d697a8d1fc37ac06d5db306905fa3508512791b0435b2e95eb18eda1662ec6f1d7b278c61d3ef2132723992c16
|
data/README.md
CHANGED
@@ -188,5 +188,6 @@ document.addEventListener 'page:after-node-removed', (event) ->
|
|
188
188
|
|
189
189
|
## Testing
|
190
190
|
|
191
|
-
- `./server` and visit http://localhost:3000/teaspoon to run the JS test suite
|
191
|
+
- `./server` and visit http://localhost:3000/teaspoon to run the JS test suite in the browser
|
192
|
+
- `bundle exec teaspoon` will run the JS test suite from the command line. Uses Selenium by default, but can be configured using the TEASPOON_DRIVER environment variable
|
192
193
|
- `bundle exec rake test` to run the browser test suite
|
@@ -0,0 +1,215 @@
|
|
1
|
+
class window.TurboHead
|
2
|
+
constructor: (@activeDocument, @upstreamDocument) ->
|
3
|
+
|
4
|
+
update: (successCallback, failureCallback) ->
|
5
|
+
activeAssets = extractTrackedAssets(@activeDocument)
|
6
|
+
upstreamAssets = extractTrackedAssets(@upstreamDocument)
|
7
|
+
{activeScripts, newScripts} = processScripts(activeAssets, upstreamAssets)
|
8
|
+
|
9
|
+
if hasScriptConflict(activeScripts, newScripts)
|
10
|
+
return failureCallback()
|
11
|
+
|
12
|
+
updateLinkTags(activeAssets, upstreamAssets)
|
13
|
+
updateScriptTags(@activeDocument, newScripts, successCallback)
|
14
|
+
|
15
|
+
updateLinkTags = (activeAssets, upstreamAssets) ->
|
16
|
+
activeLinks = activeAssets.filter(filterForNodeType('LINK'))
|
17
|
+
upstreamLinks = upstreamAssets.filter(filterForNodeType('LINK'))
|
18
|
+
remainingActiveLinks = removeStaleLinks(activeLinks, upstreamLinks)
|
19
|
+
reorderedActiveLinks = reorderActiveLinks(remainingActiveLinks, upstreamLinks)
|
20
|
+
insertNewLinks(reorderedActiveLinks, upstreamLinks)
|
21
|
+
|
22
|
+
updateScriptTags = (activeDocument, newScripts, callback) ->
|
23
|
+
asyncSeries(
|
24
|
+
newScripts.map((scriptNode) -> insertScriptTask(activeDocument, scriptNode)),
|
25
|
+
callback
|
26
|
+
)
|
27
|
+
|
28
|
+
extractTrackedAssets = (doc) ->
|
29
|
+
for node in doc.head.children when node.dataset.turbolinksTrack?
|
30
|
+
node
|
31
|
+
|
32
|
+
filterForNodeType = (nodeType) ->
|
33
|
+
(node) -> node.nodeName == nodeType
|
34
|
+
|
35
|
+
hasScriptConflict = (activeScripts, newScripts) ->
|
36
|
+
hasExistingScriptAssetName = (upstreamNode) ->
|
37
|
+
activeScripts.some (activeNode) ->
|
38
|
+
upstreamNode.dataset.turbolinksTrackScriptAs == activeNode.dataset.turbolinksTrackScriptAs
|
39
|
+
|
40
|
+
newScripts.some(hasExistingScriptAssetName)
|
41
|
+
|
42
|
+
asyncSeries = (tasks, callback) ->
|
43
|
+
return callback() if tasks.length == 0
|
44
|
+
task = tasks.shift()
|
45
|
+
task(-> asyncSeries(tasks, callback))
|
46
|
+
|
47
|
+
insertScriptTask = (activeDocument, scriptNode) ->
|
48
|
+
# We need to clone script tags in order to ensure that the browser executes them.
|
49
|
+
newNode = activeDocument.createElement('SCRIPT')
|
50
|
+
newNode.setAttribute(attr.name, attr.value) for attr in scriptNode.attributes
|
51
|
+
newNode.appendChild(activeDocument.createTextNode(scriptNode.innerHTML))
|
52
|
+
|
53
|
+
return (done) ->
|
54
|
+
onScriptEvent = (event) ->
|
55
|
+
triggerEvent('page:script-error', event) if event.type == 'error'
|
56
|
+
newNode.removeEventListener('load', onScriptEvent)
|
57
|
+
newNode.removeEventListener('error', onScriptEvent)
|
58
|
+
done()
|
59
|
+
newNode.addEventListener('load', onScriptEvent)
|
60
|
+
newNode.addEventListener('error', onScriptEvent)
|
61
|
+
activeDocument.head.appendChild(newNode)
|
62
|
+
triggerEvent('page:after-script-inserted', newNode)
|
63
|
+
|
64
|
+
processScripts = (activeAssets, upstreamAssets) ->
|
65
|
+
activeScripts = activeAssets.filter(filterForNodeType('SCRIPT'))
|
66
|
+
upstreamScripts = upstreamAssets.filter(filterForNodeType('SCRIPT'))
|
67
|
+
hasNewSrc = (upstreamNode) ->
|
68
|
+
activeScripts.every (activeNode) ->
|
69
|
+
upstreamNode.src != activeNode.src
|
70
|
+
|
71
|
+
newScripts = upstreamScripts.filter(hasNewSrc)
|
72
|
+
|
73
|
+
{activeScripts, newScripts}
|
74
|
+
|
75
|
+
removeStaleLinks = (activeLinks, upstreamLinks) ->
|
76
|
+
isStaleLink = (link) ->
|
77
|
+
upstreamLinks.every (upstreamLink) ->
|
78
|
+
upstreamLink.href != link.href
|
79
|
+
|
80
|
+
staleLinks = activeLinks.filter(isStaleLink)
|
81
|
+
|
82
|
+
for staleLink in staleLinks
|
83
|
+
removedLink = document.head.removeChild(staleLink)
|
84
|
+
triggerEvent('page:after-link-removed', removedLink)
|
85
|
+
|
86
|
+
activeLinks.filter((link) -> !isStaleLink(link))
|
87
|
+
|
88
|
+
reorderAlreadyExists = (link1, link2, reorders) ->
|
89
|
+
reorders.some (reorderPair) ->
|
90
|
+
link1 in reorderPair && link2 in reorderPair
|
91
|
+
|
92
|
+
generateReorderGraph = (activeLinks, upstreamLinks) ->
|
93
|
+
reorders = []
|
94
|
+
for activeLink1 in activeLinks
|
95
|
+
for activeLink2 in activeLinks
|
96
|
+
continue if activeLink1.href == activeLink2.href
|
97
|
+
continue if reorderAlreadyExists(activeLink1, activeLink2, reorders)
|
98
|
+
|
99
|
+
upstreamLink1 = upstreamLinks.filter((link) -> link.href == activeLink1.href)[0]
|
100
|
+
upstreamLink2 = upstreamLinks.filter((link) -> link.href == activeLink2.href)[0]
|
101
|
+
|
102
|
+
orderHasChanged =
|
103
|
+
(activeLinks.indexOf(activeLink1) < activeLinks.indexOf(activeLink2)) !=
|
104
|
+
(upstreamLinks.indexOf(upstreamLink1) < upstreamLinks.indexOf(upstreamLink2))
|
105
|
+
|
106
|
+
reorders.push([activeLink1, activeLink2]) if orderHasChanged
|
107
|
+
reorders
|
108
|
+
|
109
|
+
nextMove = (activeLinks, reorders) ->
|
110
|
+
changesAssociatedTo = (link) ->
|
111
|
+
reorders.filter (reorderPair) ->
|
112
|
+
link in reorderPair
|
113
|
+
|
114
|
+
linksSortedByMovePriority = activeLinks
|
115
|
+
.slice()
|
116
|
+
.sort (link1, link2) ->
|
117
|
+
changesAssociatedTo(link2).length - changesAssociatedTo(link1).length
|
118
|
+
|
119
|
+
linkToMove = linksSortedByMovePriority[0]
|
120
|
+
|
121
|
+
linksToPassBy = changesAssociatedTo(linkToMove).map (reorderPair) ->
|
122
|
+
(reorderPair.filter (link) -> link.href != linkToMove.href)[0]
|
123
|
+
|
124
|
+
{linkToMove, linksToPassBy}
|
125
|
+
|
126
|
+
reorderActiveLinks = (activeLinks, upstreamLinks) ->
|
127
|
+
activeLinksCopy = activeLinks.slice()
|
128
|
+
pendingReorders = generateReorderGraph(activeLinksCopy, upstreamLinks)
|
129
|
+
|
130
|
+
removeReorder = (link1, link2) ->
|
131
|
+
reorderToRemove = (pendingReorders.filter (reorderPair) ->
|
132
|
+
link1 in reorderPair && link2 in reorderPair)[0]
|
133
|
+
indexToRemove = pendingReorders.indexOf(reorderToRemove)
|
134
|
+
pendingReorders.splice(indexToRemove, 1)
|
135
|
+
|
136
|
+
addNewReorder = (link1, link2) ->
|
137
|
+
pendingReorders.push [link1, link2]
|
138
|
+
|
139
|
+
markReorderAsFinished = (linkToMove, linkToPass, remainingLinksToPass) ->
|
140
|
+
removeReorder(linkToMove, linkToPass)
|
141
|
+
removalIndex = remainingLinksToPass.indexOf(linkToPass)
|
142
|
+
remainingLinksToPass.splice(removalIndex, 1)
|
143
|
+
|
144
|
+
removeLink = (linkToRemove, indexOfLink) ->
|
145
|
+
removedLink = document.head.removeChild(linkToRemove)
|
146
|
+
triggerEvent('page:after-link-removed', removedLink)
|
147
|
+
activeLinksCopy.splice(indexOfLink, 1)
|
148
|
+
|
149
|
+
performMove = (linkToMove, linksToPassBy) ->
|
150
|
+
moveDirection = if activeLinksCopy.indexOf(linkToMove) > activeLinksCopy.indexOf(linksToPassBy[0]) then 'UP' else 'DOWN'
|
151
|
+
startIndex = activeLinksCopy.indexOf(linkToMove)
|
152
|
+
|
153
|
+
switch moveDirection
|
154
|
+
when 'UP'
|
155
|
+
for i in [(startIndex - 1)..0]
|
156
|
+
currentLink = activeLinksCopy[i]
|
157
|
+
if currentLink in linksToPassBy
|
158
|
+
markReorderAsFinished(linkToMove, currentLink, linksToPassBy)
|
159
|
+
|
160
|
+
if linksToPassBy.length == 0
|
161
|
+
removeLink(linkToMove, startIndex)
|
162
|
+
|
163
|
+
document.head.insertBefore(linkToMove, activeLinksCopy[i])
|
164
|
+
activeLinksCopy.splice(i, 0, linkToMove)
|
165
|
+
triggerEvent('page:after-link-inserted', linkToMove)
|
166
|
+
return
|
167
|
+
else
|
168
|
+
addNewReorder(linkToMove, currentLink, pendingReorders)
|
169
|
+
when 'DOWN'
|
170
|
+
for i in [(startIndex + 1)...activeLinksCopy.length]
|
171
|
+
currentLink = activeLinksCopy[i]
|
172
|
+
if currentLink in linksToPassBy
|
173
|
+
markReorderAsFinished(linkToMove, currentLink, linksToPassBy)
|
174
|
+
|
175
|
+
if linksToPassBy.length == 0
|
176
|
+
removeLink(linkToMove, startIndex)
|
177
|
+
|
178
|
+
targetIndex = i - 1
|
179
|
+
if targetIndex == activeLinksCopy.length - 1
|
180
|
+
document.head.appendChild(linkToMove)
|
181
|
+
activeLinksCopy.push(linkToMove)
|
182
|
+
else
|
183
|
+
document.head.insertBefore(linkToMove, activeLinksCopy[targetIndex + 1])
|
184
|
+
activeLinksCopy.splice(targetIndex + 1, 0, linkToMove)
|
185
|
+
triggerEvent('page:after-link-inserted', linkToMove)
|
186
|
+
return
|
187
|
+
else
|
188
|
+
addNewReorder(linkToMove, currentLink, pendingReorders)
|
189
|
+
|
190
|
+
while pendingReorders.length > 0
|
191
|
+
{linkToMove, linksToPassBy} = nextMove(activeLinksCopy, pendingReorders)
|
192
|
+
performMove(linkToMove, linksToPassBy)
|
193
|
+
|
194
|
+
activeLinksCopy
|
195
|
+
|
196
|
+
insertNewLinks = (activeLinks, upstreamLinks) ->
|
197
|
+
isNewLink = (link) ->
|
198
|
+
activeLinks.every (activeLink) ->
|
199
|
+
activeLink.href != link.href
|
200
|
+
|
201
|
+
upstreamLinks
|
202
|
+
.filter(isNewLink)
|
203
|
+
.reverse() # This is because we can't insert before a sibling that hasn't been inserted yet.
|
204
|
+
.forEach (newUpstreamLink) ->
|
205
|
+
index = upstreamLinks.indexOf(newUpstreamLink)
|
206
|
+
newActiveLink = newUpstreamLink.cloneNode()
|
207
|
+
if index == upstreamLinks.length - 1
|
208
|
+
document.head.appendChild(newActiveLink)
|
209
|
+
activeLinks.push(newActiveLink)
|
210
|
+
else
|
211
|
+
targetIndex = activeLinks.indexOf((activeLinks.filter (link) ->
|
212
|
+
link.href == upstreamLinks[index + 1].href)[0])
|
213
|
+
document.head.insertBefore(newActiveLink, activeLinks[targetIndex])
|
214
|
+
activeLinks.splice(targetIndex, 0, newActiveLink)
|
215
|
+
triggerEvent('page:after-link-inserted', newActiveLink)
|
@@ -63,7 +63,6 @@ removeNode = (node) ->
|
|
63
63
|
class window.Turbolinks
|
64
64
|
createDocument = null
|
65
65
|
currentState = null
|
66
|
-
loadedAssets = null
|
67
66
|
referer = null
|
68
67
|
|
69
68
|
fetch = (url, options = {}) ->
|
@@ -80,6 +79,10 @@ class window.Turbolinks
|
|
80
79
|
|
81
80
|
fetchReplacement url, options
|
82
81
|
|
82
|
+
@fullPageNavigate: (url) ->
|
83
|
+
triggerEvent('page:before-full-refresh', url: url)
|
84
|
+
document.location.href = url
|
85
|
+
|
83
86
|
@pushState: (state, title, url) ->
|
84
87
|
window.history.pushState(state, title, url)
|
85
88
|
|
@@ -89,12 +92,18 @@ class window.Turbolinks
|
|
89
92
|
fetchReplacement = (url, options) ->
|
90
93
|
triggerEvent 'page:fetch', url: url.absolute
|
91
94
|
|
92
|
-
xhr
|
95
|
+
if xhr?
|
96
|
+
# Workaround for sinon xhr.abort()
|
97
|
+
# https://github.com/sinonjs/sinon/issues/432#issuecomment-216917023
|
98
|
+
xhr.readyState = 0
|
99
|
+
xhr.statusText = "abort"
|
100
|
+
xhr.abort()
|
101
|
+
|
93
102
|
xhr = new XMLHttpRequest
|
103
|
+
|
94
104
|
xhr.open 'GET', url.withoutHashForIE10compatibility(), true
|
95
105
|
xhr.setRequestHeader 'Accept', 'text/html, application/xhtml+xml, application/xml'
|
96
106
|
xhr.setRequestHeader 'X-XHR-Referer', referer
|
97
|
-
|
98
107
|
options.headers ?= {}
|
99
108
|
|
100
109
|
for k,v of options.headers
|
@@ -102,13 +111,17 @@ class window.Turbolinks
|
|
102
111
|
|
103
112
|
xhr.onload = ->
|
104
113
|
if xhr.status >= 500
|
105
|
-
|
114
|
+
Turbolinks.fullPageNavigate(url.absolute)
|
106
115
|
else
|
107
116
|
Turbolinks.loadPage(url, xhr, options)
|
117
|
+
xhr = null
|
108
118
|
|
109
|
-
xhr.
|
110
|
-
|
111
|
-
|
119
|
+
xhr.onerror = ->
|
120
|
+
# Workaround for sinon xhr.abort()
|
121
|
+
if xhr.statusText == "abort"
|
122
|
+
xhr = null
|
123
|
+
return
|
124
|
+
Turbolinks.fullPageNavigate(url.absolute)
|
112
125
|
|
113
126
|
xhr.send()
|
114
127
|
|
@@ -117,17 +130,27 @@ class window.Turbolinks
|
|
117
130
|
@loadPage: (url, xhr, options = {}) ->
|
118
131
|
triggerEvent 'page:receive'
|
119
132
|
options.updatePushState ?= true
|
120
|
-
|
121
|
-
if doc = processResponse(xhr, options.partialReplace)
|
133
|
+
if upstreamDocument = processResponse(xhr, options.partialReplace)
|
122
134
|
reflectNewUrl url if options.updatePushState
|
123
|
-
nodes = changePage(extractTitleAndBody(doc)..., options)
|
124
|
-
reflectRedirectedUrl(xhr) if options.updatePushState
|
125
|
-
triggerEvent 'page:load', nodes
|
126
|
-
options.onLoadFunction?()
|
127
|
-
else
|
128
|
-
document.location.href = url.absolute
|
129
135
|
|
130
|
-
|
136
|
+
new TurboHead(document, upstreamDocument).update(
|
137
|
+
onHeadUpdateSuccess = ->
|
138
|
+
nodes = changePage(
|
139
|
+
upstreamDocument.querySelector('title')?.textContent,
|
140
|
+
removeNoscriptTags(upstreamDocument.querySelector('body')),
|
141
|
+
CSRFToken.get(upstreamDocument).token,
|
142
|
+
'runScripts',
|
143
|
+
options
|
144
|
+
)
|
145
|
+
reflectRedirectedUrl(xhr) if options.updatePushState
|
146
|
+
options.onLoadFunction?()
|
147
|
+
triggerEvent 'page:load', nodes
|
148
|
+
,
|
149
|
+
onHeadUpdateError = ->
|
150
|
+
Turbolinks.fullPageNavigate(url.absolute)
|
151
|
+
)
|
152
|
+
else
|
153
|
+
Turbolinks.fullPageNavigate(url.absolute)
|
131
154
|
|
132
155
|
changePage = (title, body, csrfToken, runScripts, options = {}) ->
|
133
156
|
document.title = title if title
|
@@ -210,7 +233,7 @@ class window.Turbolinks
|
|
210
233
|
newNode = newNode.cloneNode(true)
|
211
234
|
replaceNode(newNode, existingNode)
|
212
235
|
|
213
|
-
if newNode.nodeName == 'SCRIPT' && newNode.
|
236
|
+
if newNode.nodeName == 'SCRIPT' && newNode.dataset.turbolinksEval != "false"
|
214
237
|
executeScriptTag(newNode)
|
215
238
|
else
|
216
239
|
refreshedNodes.push(newNode)
|
@@ -307,29 +330,9 @@ class window.Turbolinks
|
|
307
330
|
validContent = ->
|
308
331
|
xhr.getResponseHeader('Content-Type').match /^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/
|
309
332
|
|
310
|
-
extractTrackAssets = (doc) ->
|
311
|
-
for node in doc.querySelector('head').childNodes when node.getAttribute?('data-turbolinks-track')?
|
312
|
-
node.getAttribute('src') or node.getAttribute('href')
|
313
|
-
|
314
|
-
assetsChanged = (doc) ->
|
315
|
-
loadedAssets ||= extractTrackAssets document
|
316
|
-
fetchedAssets = extractTrackAssets doc
|
317
|
-
fetchedAssets.length isnt loadedAssets.length or intersection(fetchedAssets, loadedAssets).length isnt loadedAssets.length
|
318
|
-
|
319
|
-
intersection = (a, b) ->
|
320
|
-
[a, b] = [b, a] if a.length > b.length
|
321
|
-
value for value in a when value in b
|
322
|
-
|
323
333
|
if !clientOrServerError() && validContent()
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
if doc && (!changed || partial)
|
328
|
-
return doc
|
329
|
-
|
330
|
-
extractTitleAndBody = (doc) ->
|
331
|
-
title = doc.querySelector 'title'
|
332
|
-
[ title?.textContent, removeNoscriptTags(doc.querySelector('body')), CSRFToken.get(doc).token, 'runScripts' ]
|
334
|
+
upstreamDocument = createDocument(xhr.responseText)
|
335
|
+
return upstreamDocument
|
333
336
|
|
334
337
|
installHistoryChangeHandler = (event) ->
|
335
338
|
if event.state?.turbolinks
|
data/lib/turbograft/version.rb
CHANGED
@@ -3,13 +3,9 @@ module TurboGraft
|
|
3
3
|
# option by using the X-XHR-Referer request header instead of the standard Referer
|
4
4
|
# request header.
|
5
5
|
module XHRUrlFor
|
6
|
-
def
|
7
|
-
base.alias_method_chain :url_for, :xhr_referer
|
8
|
-
end
|
9
|
-
|
10
|
-
def url_for_with_xhr_referer(options = {})
|
6
|
+
def url_for(options = {})
|
11
7
|
options = (controller.request.headers["X-XHR-Referer"] || options) if options == :back
|
12
|
-
|
8
|
+
super(options)
|
13
9
|
end
|
14
10
|
end
|
15
11
|
end
|
data/lib/turbograft.rb
CHANGED
@@ -21,8 +21,8 @@ module TurboGraft
|
|
21
21
|
Config.controllers.each do |klass|
|
22
22
|
klass.constantize.class_eval do
|
23
23
|
include XHRHeaders, Cookies, XDomainBlocker, Redirection
|
24
|
-
|
25
|
-
|
24
|
+
before_action :set_xhr_redirected_to, :set_request_method_cookie
|
25
|
+
after_action :abort_xdomain_redirect
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -36,7 +36,7 @@ module TurboGraft
|
|
36
36
|
|
37
37
|
ActiveSupport.on_load(:action_view) do
|
38
38
|
(ActionView::RoutingUrlFor rescue ActionView::Helpers::UrlHelper).module_eval do
|
39
|
-
|
39
|
+
prepend XHRUrlFor
|
40
40
|
end
|
41
41
|
end unless RUBY_VERSION =~ /^1\.8/
|
42
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbograft
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristian Plettenberg-Dussault
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2016-
|
16
|
+
date: 2016-08-24 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: coffee-rails
|
@@ -228,8 +228,8 @@ files:
|
|
228
228
|
- lib/assets/javascripts/turbograft/link.coffee
|
229
229
|
- lib/assets/javascripts/turbograft/page.coffee
|
230
230
|
- lib/assets/javascripts/turbograft/remote.coffee
|
231
|
+
- lib/assets/javascripts/turbograft/turbohead.coffee
|
231
232
|
- lib/assets/javascripts/turbograft/turbolinks.coffee
|
232
|
-
- lib/turbograft.js
|
233
233
|
- lib/turbograft.rb
|
234
234
|
- lib/turbograft/cookies.rb
|
235
235
|
- lib/turbograft/redirection.rb
|
@@ -257,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
257
257
|
version: '0'
|
258
258
|
requirements: []
|
259
259
|
rubyforge_project:
|
260
|
-
rubygems_version: 2.
|
260
|
+
rubygems_version: 2.5.1
|
261
261
|
signing_key:
|
262
262
|
specification_version: 4
|
263
263
|
summary: turbolinks with partial page replacement
|