breezy 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/javascript/breezy.js +6067 -0
  3. data/lib/breezy.rb +0 -7
  4. data/lib/breezy/configuration.rb +9 -3
  5. data/lib/breezy/helpers.rb +1 -1
  6. data/lib/breezy/render.rb +1 -1
  7. data/lib/breezy/version.rb +1 -1
  8. data/lib/generators/breezy/view/templates/view.js +17 -0
  9. data/lib/generators/breezy/view/templates/view.js.breezy +2 -0
  10. data/lib/generators/breezy/view/templates/view.jsx +21 -0
  11. data/lib/generators/breezy/view/view_generator.rb +40 -7
  12. data/lib/install/mobile.rb +54 -0
  13. data/lib/install/templates/mobile/app.js +84 -0
  14. data/lib/install/templates/mobile/app.json +6 -0
  15. data/lib/install/templates/mobile/package.json +32 -0
  16. data/lib/install/templates/mobile/rn-cli.config.js +4 -0
  17. data/lib/install/templates/web/application.js +62 -0
  18. data/lib/install/web.rb +72 -0
  19. data/lib/tasks/install.rake +46 -0
  20. data/test/render_test.rb +2 -2
  21. data/test/test_helper.rb +2 -0
  22. metadata +37 -48
  23. data/README.md +0 -338
  24. data/lib/assets/javascripts/breezy.coffee +0 -4
  25. data/lib/assets/javascripts/breezy/component_url.coffee +0 -61
  26. data/lib/assets/javascripts/breezy/controller.coffee +0 -197
  27. data/lib/assets/javascripts/breezy/csrf_token.coffee +0 -9
  28. data/lib/assets/javascripts/breezy/doubly_linked_list.coffee +0 -57
  29. data/lib/assets/javascripts/breezy/parallel_queue.coffee +0 -35
  30. data/lib/assets/javascripts/breezy/progress_bar.coffee +0 -139
  31. data/lib/assets/javascripts/breezy/remote.coffee +0 -136
  32. data/lib/assets/javascripts/breezy/snapshot.coffee +0 -100
  33. data/lib/assets/javascripts/breezy/start.coffee +0 -60
  34. data/lib/assets/javascripts/breezy/utils.coffee +0 -174
  35. data/lib/breezy/active_support.rb +0 -21
  36. data/lib/breezy_template.rb +0 -320
  37. data/lib/breezy_template/deferment_extension.rb +0 -48
  38. data/lib/breezy_template/dependency_tracker.rb +0 -47
  39. data/lib/breezy_template/digestor.rb +0 -30
  40. data/lib/breezy_template/handler.rb +0 -43
  41. data/lib/breezy_template/partial_extension.rb +0 -87
  42. data/lib/breezy_template/search_extension.rb +0 -108
  43. data/lib/generators/breezy/install/install_generator.rb +0 -61
  44. data/lib/generators/breezy/install/templates/Default.js.jsx +0 -7
  45. data/lib/generators/breezy/install/templates/View.js.jsx +0 -7
  46. data/lib/generators/breezy/install/templates/boot.js +0 -5
  47. data/lib/generators/breezy/view/templates/view.js.jsx +0 -8
  48. data/test/blade_helper.rb +0 -22
  49. data/test/breezy_template_test.rb +0 -1095
  50. data/test/dependency_tracker_test.rb +0 -66
@@ -1,4 +0,0 @@
1
- #= require_self
2
- #= require breezy/start
3
-
4
- @Breezy = {}
@@ -1,61 +0,0 @@
1
- # The ComponentUrl class converts a basic URL string into an object
2
- # that behaves similarly to document.location.
3
- #
4
- # If an instance is created from a relative URL, the current document
5
- # is used to fill in the missing attributes (protocol, host, port).
6
- uniqueId = ->
7
- new Date().getTime().toString(36)
8
-
9
- class Breezy.ComponentUrl
10
- constructor: (@original = document.location.href) ->
11
- return @original if @original.constructor is Breezy.ComponentUrl
12
- @_parse()
13
-
14
- withoutHash: -> @href.replace(@hash, '').replace('#', '')
15
-
16
- # Intention revealing function alias
17
- withoutHashForIE10compatibility: -> @withoutHash()
18
-
19
- hasNoHash: -> @hash.length is 0
20
-
21
- crossOrigin: ->
22
- @origin isnt (new Breezy.ComponentUrl).origin
23
-
24
- formatForXHR: (options = {}) ->
25
- (if options.cache then @withMimeBust() else @withAntiCacheParam()).withoutHashForIE10compatibility()
26
-
27
- withMimeBust: ->
28
- new Breezy.ComponentUrl(
29
- if /([?&])__=[^&]*/.test @absolute
30
- @absolute
31
- else
32
- new Breezy.ComponentUrl(@withoutHash() + (if /\?/.test(@absolute) then "&" else "?") + "__=0" + @hash)
33
- )
34
-
35
- withAntiCacheParam: ->
36
- new Breezy.ComponentUrl(
37
- if /([?&])_=[^&]*/.test @absolute
38
- @absolute.replace /([?&])_=[^&]*/, "$1_=#{uniqueId()}"
39
- else
40
- new Breezy.ComponentUrl(@withoutHash() + (if /\?/.test(@absolute) then "&" else "?") + "_=#{uniqueId()}" + @hash)
41
- )
42
-
43
- _parse: ->
44
- (@link ?= document.createElement 'a').href = @original
45
- { @href, @protocol, @host, @hostname, @port, @pathname, @search, @hash } = @link
46
-
47
- if @protocol == ':'
48
- @protocol = document.location.protocol
49
- if @protocol == ''
50
- @protocol = document.location.protocol
51
- if @port == ''
52
- @port = document.location.port
53
- if @hostname == ''
54
- @hostname = document.location.hostname
55
- if @pathname == ''
56
- @pathname = '/'
57
-
58
- @origin = [@protocol, '//', @hostname].join ''
59
- @origin += ":#{@port}" unless @port.length is 0
60
- @relative = [@pathname, @search, @hash].join ''
61
- @absolute = @href
@@ -1,197 +0,0 @@
1
- #= require breezy/doubly_linked_list
2
- #= require breezy/snapshot
3
- #= require breezy/progress_bar
4
- #= require breezy/parallel_queue
5
- #= require breezy/component_url
6
-
7
- PAGE_CACHE_SIZE = 20
8
-
9
- class Breezy.Controller
10
- constructor: ->
11
- @atomCache = {}
12
- @history = new Breezy.Snapshot(this)
13
- @transitionCacheEnabled = false
14
- @requestCachingEnabled = true
15
-
16
- @progressBar = new Breezy.ProgressBar 'html'
17
- @pq = new Breezy.ParallelQueue
18
- @http = null
19
-
20
- @history.rememberCurrentUrlAndState()
21
-
22
- currentPage: =>
23
- @history.currentPage
24
-
25
- request: (url, options = {}) =>
26
- options = Breezy.Utils.reverseMerge options,
27
- pushState: true
28
-
29
- url = new Breezy.ComponentUrl url
30
- return if @pageChangePrevented(url.absolute, options.target)
31
-
32
- if url.crossOrigin()
33
- document.location.href = url.absolute
34
- return
35
-
36
- @history.cacheCurrentPage()
37
- if @progressBar? and !options.async
38
- @progressBar?.start()
39
- restorePoint = @history.transitionCacheFor(url.absolute)
40
-
41
- if @transitionCacheEnabled and restorePoint and restorePoint.transition_cache
42
- @history.reflectNewUrl(url)
43
- @restore(restorePoint)
44
- options.showProgressBar = false
45
-
46
- options.cacheRequest ?= @requestCachingEnabled
47
- options.showProgressBar ?= true
48
-
49
- Breezy.Utils.triggerEvent Breezy.EVENTS.FETCH, url: url.absolute, options.target
50
-
51
- if options.async
52
- options.showProgressBar = false
53
- req = @createRequest(url, options)
54
- req.onError = ->
55
- Breezy.Utils.triggerEvent Breezy.EVENTS.ERROR, null, options.target
56
- @pq.push(req)
57
- req.send(options.payload)
58
- else
59
- @pq.drain()
60
- @http?.abort()
61
- @http = @createRequest(url, options)
62
- @http.send(options.payload)
63
-
64
- enableTransitionCache: (enable = true) =>
65
- @transitionCacheEnabled = enable
66
-
67
- disableRequestCaching: (disable = true) =>
68
- @requestCachingEnabled = not disable
69
- disable
70
-
71
- restore: (cachedPage, options = {}) =>
72
- @http?.abort()
73
- @history.changePage(cachedPage, options)
74
-
75
- @progressBar?.done()
76
- Breezy.Utils.triggerEvent Breezy.EVENTS.RESTORE
77
- Breezy.Utils.triggerEvent Breezy.EVENTS.LOAD, cachedPage
78
-
79
- replace: (nextPage, options = {}) =>
80
- Breezy.Utils.withDefaults(nextPage, @history.currentBrowserState)
81
- @history.changePage(nextPage, options)
82
- Breezy.Utils.triggerEvent Breezy.EVENTS.LOAD, @currentPage()
83
-
84
- crossOriginRedirect: =>
85
- redirect = @http.getResponseHeader('Location')
86
- crossOrigin = (new Breezy.ComponentUrl(redirect)).crossOrigin()
87
-
88
- if redirect? and crossOrigin
89
- redirect
90
-
91
- pageChangePrevented: (url, target) =>
92
- !Breezy.Utils.triggerEvent Breezy.EVENTS.BEFORE_CHANGE, url: url, target
93
-
94
- cache: (key, value) =>
95
- return @atomCache[key] if value == null
96
- @atomCache[key] ||= value
97
-
98
- # Events
99
- onLoadEnd: => @http = null
100
-
101
- onLoad: (xhr, url, options) =>
102
- Breezy.Utils.triggerEvent Breezy.EVENTS.RECEIVE, url: url.absolute, options.target
103
- nextPage = @processResponse(xhr)
104
- if xhr.status == 0
105
- return
106
-
107
- if nextPage
108
- if options.async && url.pathname != @currentPage().pathname
109
-
110
- unless options.ignoreSamePathConstraint
111
- @progressBar?.done()
112
- Breezy.Utils.warn("Async response path is different from current page path")
113
- return
114
-
115
- if options.pushState
116
- @history.reflectNewUrl url
117
-
118
- Breezy.Utils.withDefaults(nextPage, @history.currentBrowserState)
119
-
120
- if nextPage.action != 'graft'
121
- @history.changePage(nextPage, options)
122
- Breezy.Utils.triggerEvent Breezy.EVENTS.LOAD, @currentPage()
123
- else
124
- ##clean this up
125
- @history.graftByKeypath("data.#{nextPage.path}", nextPage.data)
126
-
127
- if options.showProgressBar
128
- @progressBar?.done()
129
- @history.constrainPageCacheTo()
130
- else
131
- if options.async
132
- Breezy.Utils.triggerEvent Breezy.EVENTS.ERROR, xhr, options.target
133
- else
134
- @progressBar?.done()
135
- document.location.href = @crossOriginRedirect() or url.absolute
136
-
137
- onProgress: (event) =>
138
- @progressBar.advanceFromEvent(event)
139
-
140
- onError: (url) =>
141
- document.location.href = url.absolute
142
-
143
- createRequest: (url, opts)=>
144
- jsAccept = 'text/javascript, application/x-javascript, application/javascript'
145
- requestMethod = opts.requestMethod || 'GET'
146
-
147
- xhr = new XMLHttpRequest
148
- xhr.open requestMethod, url.formatForXHR(cache: opts.cacheRequest), true
149
- xhr.setRequestHeader 'Accept', jsAccept
150
- xhr.setRequestHeader 'X-XHR-Referer', document.location.href
151
- xhr.setRequestHeader 'X-Silent', opts.silent if opts.silent
152
- xhr.setRequestHeader 'X-Requested-With', 'XMLHttpRequest'
153
- xhr.setRequestHeader 'Content-Type', opts.contentType if opts.contentType
154
-
155
- csrfToken = Breezy.CSRFToken.get().token
156
- xhr.setRequestHeader('X-CSRF-Token', csrfToken) if csrfToken
157
-
158
- if !opts.silent
159
- xhr.onload = =>
160
- self = ` this `
161
- redirectedUrl = self.getResponseHeader 'X-XHR-Redirected-To'
162
- actualUrl = redirectedUrl || url
163
- @onLoad(self, actualUrl, opts)
164
- else
165
- xhr.onload = =>
166
- @progressBar?.done()
167
-
168
- xhr.onprogress = @onProgress if @progressBar and opts.showProgressBar
169
- xhr.onloadend = @onLoadEnd
170
- xhr.onerror = =>
171
- @onError(url)
172
- xhr
173
-
174
- processResponse: (xhr) ->
175
- if @hasValidResponse(xhr)
176
- return @responseContent(xhr)
177
-
178
- hasValidResponse: (xhr) ->
179
- not @clientOrServerError(xhr) and @validContent(xhr) and not @downloadingFile(xhr)
180
-
181
- responseContent: (xhr) ->
182
- new Function("'use strict'; return " + xhr.responseText )()
183
-
184
- clientOrServerError: (xhr) ->
185
- 400 <= xhr.status < 600
186
-
187
- validContent: (xhr) ->
188
- contentType = xhr.getResponseHeader('Content-Type')
189
- jsContent = /^(?:text\/javascript|application\/x-javascript|application\/javascript)(?:;|$)/
190
-
191
- contentType? and contentType.match jsContent
192
-
193
- downloadingFile: (xhr) ->
194
- (disposition = xhr.getResponseHeader('Content-Disposition'))? and
195
- disposition.match /^attachment/
196
-
197
-
@@ -1,9 +0,0 @@
1
- class Breezy.CSRFToken
2
- @get: (doc = document) ->
3
- node: tag = doc.querySelector 'meta[name="csrf-token"]'
4
- token: tag?.getAttribute? 'content'
5
-
6
- @update: (latest) ->
7
- current = @get()
8
- if current.token? and latest? and current.token isnt latest
9
- current.node.setAttribute 'content', latest
@@ -1,57 +0,0 @@
1
- class Breezy.DoublyLinkedList
2
- constructor: ->
3
- @head = @tail = null
4
- @length = 0
5
-
6
- createNode: (obj) ->
7
- return {prev: null, element: obj, next: null}
8
-
9
- push: (obj) ->
10
- if (@tail)
11
- ele = @createNode(obj)
12
- ele.prev = @tail
13
- @tail = @tail.next = ele
14
- @length += 1
15
- else
16
- @head = @tail = @createNode(obj)
17
- @length += 1
18
-
19
- pop: ()->
20
- if (@tail)
21
- element = @tail
22
- @tail = element.prev
23
- element.prev = null
24
- if (@tail)
25
- @tail.next = null
26
- if (@head == element)
27
- @head = null
28
- @length -= 1
29
-
30
- element.element
31
- else
32
- null
33
-
34
- shift: ()->
35
- if (@head)
36
- element = @head
37
- @head = element.next
38
- element.next = null
39
- if (@head)
40
- @head.prev = null
41
- if (@tail == element)
42
- @tail = null
43
- @length -= 1
44
-
45
- element.element
46
- else
47
- null
48
-
49
- unshift: (obj)->
50
- if (@head)
51
- ele = @createNode(obj)
52
- ele.next = @head
53
- @head = @head.prev = ele
54
- @length += 1
55
- else
56
- @head = @tail = @createNode(obj)
57
- @length += 1
@@ -1,35 +0,0 @@
1
- #= require breezy/doubly_linked_list
2
-
3
- class Breezy.ParallelQueue
4
- constructor: ->
5
- @dll = new Breezy.DoublyLinkedList
6
- @active = true
7
-
8
- push:(xhr)->
9
- @dll.push(xhr)
10
- xhr._originalOnLoad = xhr.onload.bind(xhr)
11
-
12
- xhr.onload = =>
13
- if @active
14
- xhr._isDone = true
15
- node = @dll.head
16
- while(node)
17
- qxhr = node.element
18
- if !qxhr._isDone
19
- node = null
20
- else
21
- node = node.next
22
- @dll.shift()
23
- qxhr._originalOnLoad()
24
-
25
- drain: ->
26
- @active = false
27
- node = @dll.head
28
- while(node)
29
- qxhr = node.element
30
- qxhr.abort()
31
- qxhr._isDone = true
32
- node = node.next
33
- @dll = new Breezy.DoublyLinkedList
34
- @active = true
35
-
@@ -1,139 +0,0 @@
1
- class Breezy.ProgressBar
2
- className = 'breezy-progress-bar'
3
- # Setting the opacity to a value < 1 fixes a display issue in Safari 6 and
4
- # iOS 6 where the progress bar would fill the entire page.
5
- originalOpacity = 0.99
6
-
7
- constructor: (@elementSelector) ->
8
- @value = 0
9
- @content = ''
10
- @speed = 300
11
- @opacity = originalOpacity
12
- @delay = 400
13
- @active = null
14
- @install()
15
-
16
- install: ->
17
- if @active
18
- return
19
-
20
- @active = true
21
- @element = document.querySelector(@elementSelector)
22
- @element.classList.add(className)
23
- @styleElement = document.createElement('style')
24
- document.head.appendChild(@styleElement)
25
- @_updateStyle()
26
-
27
- uninstall: ->
28
- if !@active
29
- return
30
-
31
- @active = false
32
- @element.classList.remove(className)
33
- document.head.removeChild(@styleElement)
34
-
35
- start: ({delay} = {})->
36
- clearTimeout(@displayTimeout)
37
- if @delay
38
- @display = false
39
- @displayTimeout = setTimeout =>
40
- @display = true
41
- , @delay
42
- else
43
- @display = true
44
-
45
- if @value > 0
46
- @_reset()
47
- @_reflow()
48
-
49
- @advanceTo(5)
50
-
51
- advanceTo: (value) ->
52
- if value > @value <= 100
53
- @value = value
54
- @_updateStyle()
55
-
56
- if @value is 100
57
- @_stopTrickle()
58
- else if @value > 0
59
- @_startTrickle()
60
-
61
- advanceFromEvent: (event) =>
62
- percent = if event.lengthComputable
63
- event.loaded / event.total * 100
64
- else
65
- @value + (100 - @value) / 10
66
- @advanceTo(percent)
67
-
68
- done: ->
69
- if @value > 0
70
- @advanceTo(100)
71
- @_finish()
72
-
73
- setDelay: (milliseconds) =>
74
- @delay = milliseconds
75
-
76
- _finish: ->
77
- @fadeTimer = setTimeout =>
78
- @opacity = 0
79
- @_updateStyle()
80
- , @speed / 2
81
-
82
- @resetTimer = setTimeout(@_reset, @speed)
83
-
84
- _reflow: ->
85
- @element.offsetHeight
86
-
87
- _reset: =>
88
- @_stopTimers()
89
- @value = 0
90
- @opacity = originalOpacity
91
- @_withSpeed(0, => @_updateStyle(true))
92
-
93
- _stopTimers: ->
94
- @_stopTrickle()
95
- clearTimeout(@fadeTimer)
96
- clearTimeout(@resetTimer)
97
-
98
- _startTrickle: ->
99
- return if @trickleTimer
100
- @trickleTimer = setTimeout(@_trickle, @speed)
101
-
102
- _stopTrickle: ->
103
- clearTimeout(@trickleTimer)
104
- delete @trickleTimer
105
-
106
- _trickle: =>
107
- @advanceTo(@value + Math.random() / 2)
108
- @trickleTimer = setTimeout(@_trickle, @speed)
109
-
110
- _withSpeed: (speed, fn) ->
111
- originalSpeed = @speed
112
- @speed = speed
113
- result = fn()
114
- @speed = originalSpeed
115
- result
116
-
117
- _updateStyle: (forceRepaint = false) ->
118
- @_changeContentToForceRepaint() if forceRepaint
119
- @styleElement.textContent = @_createCSSRule()
120
-
121
- _changeContentToForceRepaint: ->
122
- @content = if @content is '' then ' ' else ''
123
-
124
- _createCSSRule: ->
125
- """
126
- #{@elementSelector}.#{className}::before {
127
- content: '#{@content}';
128
- position: fixed;
129
- top: 0;
130
- left: 0;
131
- z-index: 2000;
132
- background-color: #0076ff;
133
- height: 3px;
134
- opacity: #{@opacity};
135
- width: #{if @display then @value else 0}%;
136
- transition: width #{@speed}ms ease-out, opacity #{@speed / 2}ms ease-in;
137
- transform: translate3d(0,0,0);
138
- }
139
- """