turbograft 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|