breezy 0.1.4 → 0.2.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.
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
- """