nitrolinks-rails 0.1.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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +48 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/nitrolinks/utilities.coffee +168 -0
- data/app/assets/javascripts/nitrolinks.coffee +223 -0
- data/lib/nitrolinks/rails/controller.rb +44 -0
- data/lib/nitrolinks/rails/engine.rb +21 -0
- data/lib/nitrolinks/rails/version.rb +5 -0
- data/lib/nitrolinks/rails.rb +8 -0
- data/nitrolinks-rails.gemspec +26 -0
- data/vendor/assets/javascripts/set-dom.js +1 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 24302bf169536da10cb236af115866831fa6386f
|
4
|
+
data.tar.gz: e9ce52c3071979143845632d695b42fcadd0e3a5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 349d7988a2ec9060822049d635eb21b3f0b6349d0b4efffbce8314e443fa00886ce81f0de5408eb8b76e60dc87809367dcd30e588aff681a61f8693c91debebc
|
7
|
+
data.tar.gz: c2117dc35daaaaba0e7755e37d37ad8ce5f818fd731d6184ef41a3d17c512060f833f30e65478467a103a68f6cf8879052cbae07cbda7c6e146ee1ecce6c137f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Nitrolinks
|
2
|
+
|
3
|
+
Nitrolinks is PJAX-like library for making website navigation fast and more like
|
4
|
+
modern web apps. Nitrolinks is inspired by and borrows heavily from
|
5
|
+
[Turbolinks](https://github.com/turbolinks/turbolinks) implementation on the
|
6
|
+
Rails-side.
|
7
|
+
|
8
|
+
## Warning! Not Production-Ready
|
9
|
+
This is an experiment and not yet heavily tested. Please don't use in critical
|
10
|
+
applications.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'nitrolinks-rails'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install nitrolinks-rails
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Include nitrolinks in your application.js
|
31
|
+
|
32
|
+
```javascript
|
33
|
+
//= require nitrolinks
|
34
|
+
```
|
35
|
+
|
36
|
+
## Development
|
37
|
+
|
38
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
39
|
+
release a new version, update the version number in `version.rb`, and then run
|
40
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
41
|
+
git commits and tags, and push the `.gem` file to
|
42
|
+
[rubygems.org](https://rubygems.org).
|
43
|
+
|
44
|
+
## Contributing
|
45
|
+
|
46
|
+
Bug reports and pull requests are welcome on GitHub at
|
47
|
+
[https://github.com/asartlo/nitrolinks-rails](https://github.com/asartlo/nitrolinks-rails).
|
48
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# Pondo Utilities
|
2
|
+
@pu = ((document, window) ->
|
3
|
+
whenReady = (fn) ->
|
4
|
+
document.addEventListener("DOMContentLoaded", fn)
|
5
|
+
->
|
6
|
+
document.removeEventListener("DOMContentLoaded", fn)
|
7
|
+
|
8
|
+
ifElseFn = (test, fn1, fn2) ->
|
9
|
+
if test then fn1 else fn2
|
10
|
+
|
11
|
+
merge = (a, b) ->
|
12
|
+
Object.assign(a, b)
|
13
|
+
|
14
|
+
async = (fn, interval = 0) ->
|
15
|
+
->
|
16
|
+
args = arguments
|
17
|
+
setTimeout(
|
18
|
+
->
|
19
|
+
fn.apply(fn, args)
|
20
|
+
interval
|
21
|
+
)
|
22
|
+
|
23
|
+
eventFactory = ifElseFn(
|
24
|
+
window.CustomEvent,
|
25
|
+
(event, data) ->
|
26
|
+
new CustomEvent(event, detail: data, bubbles: true, cancelable: true)
|
27
|
+
(event, data) ->
|
28
|
+
theEvent = document.createEvent('CustomEvent')
|
29
|
+
theEvent.initCustomEvent event, true, true, data
|
30
|
+
theEvent
|
31
|
+
)
|
32
|
+
|
33
|
+
animationEndEvents = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'
|
34
|
+
animateCss = (el, animation, fn) ->
|
35
|
+
classList = el.classList
|
36
|
+
classList.add('animated')
|
37
|
+
classList.add(animation)
|
38
|
+
listenOnce el, animationEndEvents, ->
|
39
|
+
fn() if fn
|
40
|
+
classList.remove('animated')
|
41
|
+
classList.remove(animation)
|
42
|
+
|
43
|
+
listenOnce = (el, eventsStr, fn) ->
|
44
|
+
events = eventsStr.split(/\s/)
|
45
|
+
unloader = ->
|
46
|
+
for event in events
|
47
|
+
el.removeEventListener(event, handler)
|
48
|
+
|
49
|
+
handler = (e) ->
|
50
|
+
fn.call el, e
|
51
|
+
unloader()
|
52
|
+
|
53
|
+
for event in events
|
54
|
+
el.addEventListener event, handler
|
55
|
+
|
56
|
+
unloader
|
57
|
+
|
58
|
+
eventDelegate = (event, selector, handler) ->
|
59
|
+
document.addEventListener event, (e) ->
|
60
|
+
target = e.target
|
61
|
+
while target and target != this
|
62
|
+
if target.matches(selector)
|
63
|
+
e.current = target
|
64
|
+
handler.call target, e
|
65
|
+
break
|
66
|
+
target = target.parentNode
|
67
|
+
return
|
68
|
+
|
69
|
+
eventListen = (event, handler) ->
|
70
|
+
document.addEventListener event, (e) ->
|
71
|
+
handler.call document, e
|
72
|
+
|
73
|
+
triggerEvent = (event, data = {}) ->
|
74
|
+
triggerElementEvent(document, event, data)
|
75
|
+
|
76
|
+
triggerElementEvent = (el, event, data = {}) ->
|
77
|
+
el.dispatchEvent eventFactory(event, data)
|
78
|
+
event
|
79
|
+
|
80
|
+
handleLinkClicks = (fn) ->
|
81
|
+
eventDelegate 'click', 'a[href]', (e) ->
|
82
|
+
link = e.current
|
83
|
+
url = new URL(link.href)
|
84
|
+
fn(url, e)
|
85
|
+
|
86
|
+
handleFormSubmits = (fn) ->
|
87
|
+
eventDelegate 'submit', 'form', (e) ->
|
88
|
+
form = e.current
|
89
|
+
fn(form, e)
|
90
|
+
|
91
|
+
getContentOfElement = (selector, defaultValue = null) ->
|
92
|
+
node = document.querySelector(selector)
|
93
|
+
if node then node.content else defaultValue
|
94
|
+
|
95
|
+
isCurrentPageReloaded = ->
|
96
|
+
window.performance.navigation.type == 1
|
97
|
+
|
98
|
+
select = (selector) ->
|
99
|
+
document.querySelectorAll(selector)
|
100
|
+
|
101
|
+
selectAnd = (selector, fn) ->
|
102
|
+
found = select(selector)
|
103
|
+
fn.call(fn, found)
|
104
|
+
|
105
|
+
selectAndEach = (selector, fn) ->
|
106
|
+
selectAnd selector, (elements) ->
|
107
|
+
for element in elements
|
108
|
+
fn.call(fn, element)
|
109
|
+
|
110
|
+
hide = (el) ->
|
111
|
+
el.style.display = 'none'
|
112
|
+
|
113
|
+
# Stolen from Turbolinks
|
114
|
+
uuid = ->
|
115
|
+
result = ""
|
116
|
+
for i in [1..36]
|
117
|
+
if i in [9, 14, 19, 24]
|
118
|
+
result += "-"
|
119
|
+
else if i is 15
|
120
|
+
result += "4"
|
121
|
+
else if i is 20
|
122
|
+
result += (Math.floor(Math.random() * 4) + 8).toString(16)
|
123
|
+
else
|
124
|
+
result += Math.floor(Math.random() * 15).toString(16)
|
125
|
+
result
|
126
|
+
|
127
|
+
doc = document
|
128
|
+
docEl = doc.documentElement
|
129
|
+
requestFullScreenFn = docEl.requestFullscreen or docEl.mozRequestFullScreen or docEl.webkitRequestFullScreen or docEl.msRequestFullscreen
|
130
|
+
cancelFullScreenFn = doc.exitFullscreen or doc.mozCancelFullScreen or doc.webkitExitFullscreen or doc.msExitFullscreen
|
131
|
+
|
132
|
+
isFullScreen = ->
|
133
|
+
doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement
|
134
|
+
|
135
|
+
requestFullScreen = ->
|
136
|
+
unless isFullScreen()
|
137
|
+
requestFullScreenFn.call docEl
|
138
|
+
|
139
|
+
cancelFullScreen = ->
|
140
|
+
if isFullScreen()
|
141
|
+
cancelFullScreenFn.call doc
|
142
|
+
|
143
|
+
return {
|
144
|
+
getContentOfElement: getContentOfElement
|
145
|
+
ifElseFn: ifElseFn
|
146
|
+
merge: merge
|
147
|
+
listenOnce: listenOnce
|
148
|
+
createEvent: eventFactory
|
149
|
+
whenReady: whenReady
|
150
|
+
eventDelegate: eventDelegate
|
151
|
+
eventListen: eventListen
|
152
|
+
triggerEvent: triggerEvent
|
153
|
+
triggerElementEvent: triggerElementEvent
|
154
|
+
handleLinkClicks: handleLinkClicks
|
155
|
+
handleFormSubmits: handleFormSubmits
|
156
|
+
async: async
|
157
|
+
isCurrentPageReloaded: isCurrentPageReloaded
|
158
|
+
uuid: uuid
|
159
|
+
animateCss: animateCss
|
160
|
+
select: select
|
161
|
+
selectAnd: selectAnd
|
162
|
+
selectAndEach: selectAndEach
|
163
|
+
hide: hide
|
164
|
+
requestFullScreen: requestFullScreen
|
165
|
+
cancelFullScreen: cancelFullScreen
|
166
|
+
}
|
167
|
+
)(document, window)
|
168
|
+
|
@@ -0,0 +1,223 @@
|
|
1
|
+
#= require set-dom
|
2
|
+
#= require nitrolinks/utilities
|
3
|
+
|
4
|
+
@nitro = ((document, window, pu, setDOM) ->
|
5
|
+
getCsrfToken = ->
|
6
|
+
pu.getContentOfElement('meta[name="csrf-token"]')
|
7
|
+
|
8
|
+
getCsrfParam = ->
|
9
|
+
pu.getContentOfElement('meta[name="csrf-param"]')
|
10
|
+
|
11
|
+
nitro = {
|
12
|
+
appHost: window.location.origin
|
13
|
+
csrfToken: getCsrfToken()
|
14
|
+
csrfParam: getCsrfParam()
|
15
|
+
}
|
16
|
+
|
17
|
+
# TODO: This holds too much information to just store in sessionStorage
|
18
|
+
cache = (key, value) ->
|
19
|
+
window.sessionStorage.setItem(key, JSON.stringify(value))
|
20
|
+
|
21
|
+
getCache = (key) ->
|
22
|
+
JSON.parse(window.sessionStorage.getItem(key))
|
23
|
+
|
24
|
+
getAppElement = ->
|
25
|
+
document.getElementsByTagName('html')[0]
|
26
|
+
|
27
|
+
isUrlAllowed = (url) ->
|
28
|
+
from = window.location
|
29
|
+
url.origin == nitro.appHost && isNewNavigation(from, url)
|
30
|
+
|
31
|
+
isNewNavigation = (fromUrl, toUrl) ->
|
32
|
+
if toUrl.pathname != fromUrl.pathname || toUrl.search != fromUrl.search
|
33
|
+
true
|
34
|
+
else
|
35
|
+
!isHashChanged(fromUrl, toUrl)
|
36
|
+
|
37
|
+
isHashChanged = (fromUrl, toUrl) ->
|
38
|
+
if toUrl.hash != fromUrl.hash
|
39
|
+
true
|
40
|
+
else
|
41
|
+
urlIsHashed(toUrl) || urlIsHashed(fromUrl)
|
42
|
+
|
43
|
+
urlIsHashed = (url) ->
|
44
|
+
url.toString().match(/#/)
|
45
|
+
|
46
|
+
urlPath = (urlStr) ->
|
47
|
+
urlPathFromUrl(new URL(urlStr))
|
48
|
+
|
49
|
+
urlPathFromUrl = (url) ->
|
50
|
+
if url.origin == url.toString()
|
51
|
+
url.pathname
|
52
|
+
else
|
53
|
+
url.toString().replace(url.origin, '')
|
54
|
+
|
55
|
+
hasEmptyHash = (url) ->
|
56
|
+
url.toString().match(/#/) && url.hash == ""
|
57
|
+
|
58
|
+
fullPath = (urlStr) ->
|
59
|
+
if urlStr.indexOf(nitro.appHost) != 0
|
60
|
+
"#{nitro.appHost}/#{urlStr.match(/^\/?(.+$)/)[1]}"
|
61
|
+
else
|
62
|
+
urlStr
|
63
|
+
|
64
|
+
pushTheState = (state, location) ->
|
65
|
+
window.history.pushState(state, null, location)
|
66
|
+
|
67
|
+
replaceTheState = (state, location) ->
|
68
|
+
window.history.replaceState(state, null, location)
|
69
|
+
|
70
|
+
onPopState = (fn) ->
|
71
|
+
window.addEventListener 'popstate',
|
72
|
+
(e) ->
|
73
|
+
state = e.state
|
74
|
+
return unless state
|
75
|
+
fn(getState(state))
|
76
|
+
|
77
|
+
|
78
|
+
pu.whenReady ->
|
79
|
+
state = window.history.state
|
80
|
+
if hasState(state) && !pu.isCurrentPageReloaded()
|
81
|
+
loadState(getState(state))
|
82
|
+
else
|
83
|
+
location = urlPath(window.location)
|
84
|
+
method = 'get'
|
85
|
+
appCode = getAppElement().outerHTML
|
86
|
+
renderState(preloadContent(appCode))
|
87
|
+
state = saveState(location, method, appCode)
|
88
|
+
replaceTheState(state, location)
|
89
|
+
pu.triggerEvent 'nitrolinks:load', url: location
|
90
|
+
|
91
|
+
pu.handleLinkClicks (url, e) ->
|
92
|
+
if isUrlAllowed(url)
|
93
|
+
e.preventDefault()
|
94
|
+
visit(url, method: 'get')
|
95
|
+
e.stopPropagation()
|
96
|
+
|
97
|
+
pu.handleFormSubmits (form, e) ->
|
98
|
+
url = new URL(form.action)
|
99
|
+
data = null
|
100
|
+
method = form.method.toLowerCase()
|
101
|
+
if method == 'get'
|
102
|
+
url.search = $(form).serialize()
|
103
|
+
else if method == 'post'
|
104
|
+
data = new FormData(form)
|
105
|
+
if isUrlAllowed(url)
|
106
|
+
e.preventDefault()
|
107
|
+
visit(url, method: form.method, body: data)
|
108
|
+
e.stopPropagation()
|
109
|
+
|
110
|
+
fetchComplete = (url, theOptions = {}) ->
|
111
|
+
options = pu.merge({method: 'get', pushState: true}, theOptions)
|
112
|
+
(response) ->
|
113
|
+
# return unless response.ok
|
114
|
+
method = options.method
|
115
|
+
pushState = options.pushState
|
116
|
+
response.text().then (contents) ->
|
117
|
+
pageSource = extractPageSource(contents)
|
118
|
+
unless pageSource
|
119
|
+
pu.triggerEvent 'nitrolinks:load-blank'
|
120
|
+
return
|
121
|
+
if response.headers.has("nitrolinks-location")
|
122
|
+
location = urlPath(response.headers.get("nitrolinks-location"))
|
123
|
+
else
|
124
|
+
location = urlPath(url)
|
125
|
+
|
126
|
+
state = saveState(location, method, pageSource)
|
127
|
+
renderState(preloadContent(pageSource))
|
128
|
+
pushTheState(state, location) if pushState
|
129
|
+
|
130
|
+
pu.triggerEvent 'nitrolinks:load-from-fetch', url: location
|
131
|
+
pu.triggerEvent 'nitrolinks:load', url: location
|
132
|
+
|
133
|
+
extractPageSource = (text) ->
|
134
|
+
code = text.trim()
|
135
|
+
match = code.match(/<html[^>]*>([\s\S]+)<\/html>/)
|
136
|
+
return null unless match
|
137
|
+
(match[0]).trim()
|
138
|
+
|
139
|
+
visit = (url, theOptions = {}) ->
|
140
|
+
options = pu.merge({method: 'get', pushState: true}, theOptions)
|
141
|
+
event = pu.triggerEvent 'nitrolinks:visit'
|
142
|
+
return if event.defaultPrevented
|
143
|
+
fetch(url, nitroFetchOptions(options)).then(
|
144
|
+
fetchComplete(url, options)
|
145
|
+
).catch( (error, a) ->
|
146
|
+
window.location = url
|
147
|
+
)
|
148
|
+
|
149
|
+
visitCached = (stateObj) ->
|
150
|
+
pu.triggerEvent 'nitrolinks:visit'
|
151
|
+
renderState(preloadContent(stateObj.content))
|
152
|
+
pu.triggerEvent 'nitrolinks:load-from-cache', url: stateObj.url
|
153
|
+
pu.triggerEvent 'nitrolinks:load', url: stateObj.url
|
154
|
+
|
155
|
+
nitroFetchOptions = (options) ->
|
156
|
+
headers = {
|
157
|
+
"nitrolinks-referrer": window.location.href
|
158
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
159
|
+
}
|
160
|
+
if options.method == 'post'
|
161
|
+
headers["x-csrf-token"] = getCsrfToken()
|
162
|
+
method: options.method
|
163
|
+
redirect: 'follow'
|
164
|
+
credentials: 'include'
|
165
|
+
body: options.body
|
166
|
+
headers: headers
|
167
|
+
|
168
|
+
|
169
|
+
loadState = (stateObj) ->
|
170
|
+
if stateObj.url
|
171
|
+
url = new URL(fullPath(stateObj.url))
|
172
|
+
else
|
173
|
+
url = false
|
174
|
+
if stateObj.content
|
175
|
+
visitCached(stateObj)
|
176
|
+
else if url && stateObj.method
|
177
|
+
visit(url, method: stateObj.method, pushState: false)
|
178
|
+
else if url
|
179
|
+
visit(url, method: 'get', pushState: false)
|
180
|
+
else
|
181
|
+
visit(window.location.href, method: 'get', pushState: false)
|
182
|
+
|
183
|
+
onPopState(loadState)
|
184
|
+
|
185
|
+
renderState = (content) ->
|
186
|
+
setDOM(getAppElement(), content)
|
187
|
+
|
188
|
+
preloadContent = (content) ->
|
189
|
+
# TODO: Is there a better way to do this?
|
190
|
+
content.replace('<html', '<html class="js"')
|
191
|
+
|
192
|
+
saveState = (url, method, body) ->
|
193
|
+
key = pu.uuid()
|
194
|
+
cache(key, url: url, method: method, body: body)
|
195
|
+
return key
|
196
|
+
|
197
|
+
getState = (state) ->
|
198
|
+
savedState = getCache(state)
|
199
|
+
if state && savedState
|
200
|
+
{
|
201
|
+
method: savedState.method
|
202
|
+
url: savedState.url
|
203
|
+
content: savedState.body
|
204
|
+
}
|
205
|
+
else
|
206
|
+
{
|
207
|
+
method: null
|
208
|
+
url: null
|
209
|
+
content: null
|
210
|
+
}
|
211
|
+
|
212
|
+
hasState = (state) ->
|
213
|
+
savedState = getCache(state)
|
214
|
+
state && savedState
|
215
|
+
|
216
|
+
parseState = (state) ->
|
217
|
+
match = (state || '').match(/^(\w+):(.+)$/)
|
218
|
+
method: match[1], url: match[2]
|
219
|
+
|
220
|
+
return {
|
221
|
+
}
|
222
|
+
)(document, window, pu, setDOM)
|
223
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Nitrolinks
|
2
|
+
module Rails
|
3
|
+
|
4
|
+
module Controller
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :set_nitrolinks_location_header_from_session if respond_to?(:before_action)
|
9
|
+
end
|
10
|
+
|
11
|
+
def nitrolinks_request?
|
12
|
+
request.headers.key? "nitrolinks-referrer"
|
13
|
+
end
|
14
|
+
|
15
|
+
def redirect_to(url = {}, options = {})
|
16
|
+
super.tap do
|
17
|
+
if nitrolinks_request?
|
18
|
+
store_nitrolinks_location_in_session(location)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def nitrolinks_location(location)
|
26
|
+
response.headers["Nitrolinks-Location"] = location
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def store_nitrolinks_location_in_session(location)
|
32
|
+
session[:nitrolinks_location] = location if session
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_nitrolinks_location_header_from_session
|
36
|
+
if session && session[:nitrolinks_location]
|
37
|
+
nitrolinks_location(session.delete(:nitrolinks_location))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nitrolinks
|
2
|
+
module Rails
|
3
|
+
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace Nitrolinks
|
6
|
+
|
7
|
+
config.nitrolinks = ActiveSupport::OrderedOptions.new
|
8
|
+
config.nitrolinks.auto_include = true
|
9
|
+
|
10
|
+
initializer :turbolinks do |app|
|
11
|
+
ActiveSupport.on_load(:action_controller) do
|
12
|
+
if app.config.nitrolinks.auto_include
|
13
|
+
include Controller
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nitrolinks/rails/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "nitrolinks-rails"
|
8
|
+
spec.version = Nitrolinks::Rails::VERSION
|
9
|
+
spec.authors = ["Wayne Duran"]
|
10
|
+
spec.email = ["asartalo@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Single-page Apps feel with less overhead"
|
13
|
+
spec.description = "Like Pjax and Turbolinks but with smarter DOM updating"
|
14
|
+
spec.homepage = "https://github.com/asartalo/nitrolinks-rails"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "rails", "~> 5.1"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).setDOM=e()}}(function(){return function e(t,n,r){function i(d,a){if(!n[d]){if(!t[d]){var u="function"==typeof require&&require;if(!a&&u)return u(d,!0);if(o)return o(d,!0);var f=new Error("Cannot find module '"+d+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[d]={exports:{}};t[d][0].call(l.exports,function(e){var n=t[d][1][e];return i(n||e)},l,l.exports,e,t,n,r)}return n[d].exports}for(var o="function"==typeof require&&require,d=0;d<r.length;d++)i(r[d]);return i}({1:[function(e,t){"use strict";function n(e,t){s(e&&e.nodeType,"You must provide a valid node to update."),e.nodeType===N&&(e=e.documentElement),t.nodeType===g?o(e,t):r(e,"string"==typeof t?p(t,e.nodeName):t),e[v]||(e[v]=!0,l(e))}function r(e,t){if(e.nodeType===t.nodeType)if(e.nodeType===y){if(a(e,t))return;if(o(e,t),e.nodeName===t.nodeName)i(e.attributes,t.attributes);else{for(var n=t.cloneNode();e.firstChild;)n.appendChild(e.firstChild);e.parentNode.replaceChild(n,e)}}else e.nodeValue!==t.nodeValue&&(e.nodeValue=t.nodeValue);else e.parentNode.replaceChild(t,c(e)),l(t)}function i(e,t){var n,r,i,o,d;for(n=e.length;n--;)o=(r=e[n]).namespaceURI,d=r.localName,(i=t.getNamedItemNS(o,d))||e.removeNamedItemNS(o,d);for(n=t.length;n--;)o=(r=t[n]).namespaceURI,d=r.localName,(i=e.getNamedItemNS(o,d))?i.value!==r.value&&(i.value=r.value):(t.removeNamedItemNS(o,d),e.setNamedItemNS(r))}function o(e,t){for(var n,i,o,a,u,f,m=e.firstChild,s=t.firstChild,p=0;m;)p++,i=d(n=m),m=m.nextSibling,i&&(f||(f={}),f[i]=n);for(m=e.firstChild;s;)p--,o=s,s=s.nextSibling,f&&(a=d(o))&&(u=f[a])?(delete f[a],u!==m?e.insertBefore(u,m):m=m.nextSibling,r(u,o)):m?(n=m,m=m.nextSibling,d(n)?(e.insertBefore(o,n),l(o)):r(n,o)):(e.appendChild(o),l(o));for(i in f)p--,e.removeChild(c(f[i]));for(;--p>=0;)e.removeChild(c(e.lastChild))}function d(e){if(e.nodeType===y){var t=e.getAttribute(n.KEY)||e.id;return t?h+t:void 0}}function a(e,t){return f(e)&&f(t)||u(e)===u(t)||e.isEqualNode(t)}function u(e){return e.getAttribute(n.CHECKSUM)||NaN}function f(e){return null!=e.getAttribute(n.IGNORE)}function l(e){return m(e,"mount")}function c(e){return m(e,"dismount")}function m(e,t){if(d(e)){var n=document.createEvent("Event"),r={value:e};n.initEvent(t,!1,!1),Object.defineProperty(n,"target",r),Object.defineProperty(n,"srcElement",r),e.dispatchEvent(n)}for(var i=e.firstChild;i;)i=m(i,t).nextSibling;return e}function s(e,t){if(!e)throw new Error("set-dom: "+t)}n.KEY="data-key",n.IGNORE="data-ignore",n.CHECKSUM="data-checksum";var p=e(2),h="_set-dom-",v=h+"mounted",y=1,N=9,g=11;t.exports=n},{2:2}],2:[function(e,t){"use strict";var n=window.DOMParser&&new window.DOMParser,r=!1,i=!1;try{n.parseFromString("<br/>","text/html")&&(r=!0)}catch(e){var o=document.implementation.createHTMLDocument(""),d=o.documentElement,a=o.body;try{d.innerHTML+="",i=!0}catch(e){n.parseFromString("<br/>","application/xhtml+xml");var u=/(<body[^>]*>)([\s\S]*)<\/body>/}}t.exports=r?function(e,t){var r=n.parseFromString(e,"text/html");return"HTML"===t?r.documentElement:r.body.firstChild}:function(e,t){if("HTML"===t){if(i)return d.innerHTML=e,d;var r=e.match(u);if(r){var o=r[2],f=r.index+r[1].length,l=f+o.length;e=e.slice(0,f)+e.slice(l),a.innerHTML=o}for(var c=n.parseFromString(e,"application/xhtml+xml"),m=c.body;a.firstChild;)m.appendChild(a.firstChild);return c.documentElement}return a.innerHTML=e,a.firstChild}},{}]},{},[1])(1)});
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nitrolinks-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wayne Duran
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.13'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.13'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: Like Pjax and Turbolinks but with smarter DOM updating
|
70
|
+
email:
|
71
|
+
- asartalo@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- app/assets/javascripts/nitrolinks.coffee
|
83
|
+
- app/assets/javascripts/nitrolinks/utilities.coffee
|
84
|
+
- lib/nitrolinks/rails.rb
|
85
|
+
- lib/nitrolinks/rails/controller.rb
|
86
|
+
- lib/nitrolinks/rails/engine.rb
|
87
|
+
- lib/nitrolinks/rails/version.rb
|
88
|
+
- nitrolinks-rails.gemspec
|
89
|
+
- vendor/assets/javascripts/set-dom.js
|
90
|
+
homepage: https://github.com/asartalo/nitrolinks-rails
|
91
|
+
licenses: []
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.5.1
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Single-page Apps feel with less overhead
|
113
|
+
test_files: []
|