hyperloop 0.0.4 → 0.5.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +41 -16
  3. data/LICENSE +21 -0
  4. data/hyperloop.gemspec +29 -30
  5. data/lib/generators/hyper/component_generator.rb +20 -0
  6. data/lib/generators/hyper/router_generator.rb +19 -0
  7. data/lib/generators/hyper/templates/component_template.rb +41 -0
  8. data/lib/generators/hyper/templates/router_template.rb +44 -0
  9. data/lib/generators/hyperloop/install_generator.rb +46 -0
  10. data/lib/hyperloop.rb +16 -8
  11. data/lib/hyperloop/version.rb +1 -1
  12. metadata +63 -222
  13. data/.ruby-version +0 -1
  14. data/.travis.yml +0 -4
  15. data/Gemfile +0 -4
  16. data/LICENSE.txt +0 -22
  17. data/README.md +0 -107
  18. data/Rakefile +0 -6
  19. data/bin/hyperloop +0 -7
  20. data/lib/hyperloop/application.rb +0 -103
  21. data/lib/hyperloop/cli.rb +0 -11
  22. data/lib/hyperloop/generators/site.rb +0 -47
  23. data/lib/hyperloop/generators/site/Gemfile +0 -3
  24. data/lib/hyperloop/generators/site/_partial.html.erb +0 -1
  25. data/lib/hyperloop/generators/site/about.html.erb +0 -3
  26. data/lib/hyperloop/generators/site/app.css +0 -2
  27. data/lib/hyperloop/generators/site/app.js +0 -2
  28. data/lib/hyperloop/generators/site/application.html.erb +0 -23
  29. data/lib/hyperloop/generators/site/bootstrap.css +0 -6805
  30. data/lib/hyperloop/generators/site/config.ru +0 -4
  31. data/lib/hyperloop/generators/site/current-time.coffee +0 -3
  32. data/lib/hyperloop/generators/site/index.html.erb +0 -11
  33. data/lib/hyperloop/generators/site/jquery.js +0 -8829
  34. data/lib/hyperloop/generators/site/main.scss +0 -7
  35. data/lib/hyperloop/generators/site/socool.jpg +0 -0
  36. data/lib/hyperloop/response.rb +0 -10
  37. data/lib/hyperloop/view.rb +0 -73
  38. data/lib/hyperloop/view/registry.rb +0 -90
  39. data/lib/hyperloop/view/scope.rb +0 -23
  40. data/spec/application_spec.rb +0 -300
  41. data/spec/fixtures/assets/app/assets/images/my-gif.gif +0 -0
  42. data/spec/fixtures/assets/app/assets/images/my-jpg.jpg +0 -0
  43. data/spec/fixtures/assets/app/assets/images/my-png.png +0 -0
  44. data/spec/fixtures/assets/app/assets/javascripts/app.js +0 -1
  45. data/spec/fixtures/assets/app/assets/javascripts/my-scripts.coffee +0 -1
  46. data/spec/fixtures/assets/app/assets/shouldfail/shouldfail.css +0 -3
  47. data/spec/fixtures/assets/app/assets/stylesheets/app.css +0 -1
  48. data/spec/fixtures/assets/app/assets/stylesheets/my-styles.scss +0 -3
  49. data/spec/fixtures/assets/app/views/index.html.erb +0 -7
  50. data/spec/fixtures/assets/app/views/layouts/application.html.erb +0 -15
  51. data/spec/fixtures/assets/vendor/assets/javascripts/vendored.js +0 -1
  52. data/spec/fixtures/assets/vendor/assets/stylesheets/vendored.css +0 -3
  53. data/spec/fixtures/erb/app/views/about.html.erb +0 -10
  54. data/spec/fixtures/erb/app/views/index.html.erb +0 -10
  55. data/spec/fixtures/layouts/app/views/index.html.erb +0 -3
  56. data/spec/fixtures/layouts/app/views/layouts/application.html.erb +0 -12
  57. data/spec/fixtures/layouts/app/views/subdir/index.html.erb +0 -3
  58. data/spec/fixtures/partials/app/views/index.html.erb +0 -3
  59. data/spec/fixtures/partials/app/views/layouts/application.html.erb +0 -12
  60. data/spec/fixtures/partials/app/views/subdir/_partial.html.erb +0 -1
  61. data/spec/fixtures/partials/app/views/subdir/index.html.erb +0 -3
  62. data/spec/fixtures/partials/app/views/subdir/nonroot.html.erb +0 -3
  63. data/spec/fixtures/simple/app/views/about.html +0 -10
  64. data/spec/fixtures/simple/app/views/index.html +0 -10
  65. data/spec/fixtures/subdirectories/app/views/about.html +0 -10
  66. data/spec/fixtures/subdirectories/app/views/index.html +0 -10
  67. data/spec/fixtures/subdirectories/app/views/subdir1/index.html +0 -10
  68. data/spec/fixtures/subdirectories/app/views/subdir1/kanye.html +0 -10
  69. data/spec/response_spec.rb +0 -8
  70. data/spec/spec_helper.rb +0 -139
  71. data/spec/view/registry_spec.rb +0 -56
  72. data/spec/view/scope_spec.rb +0 -21
  73. data/spec/view_spec.rb +0 -93
@@ -1,7 +0,0 @@
1
- nav {
2
- background-color: #ddd;
3
-
4
- li {
5
- background-color: #bbb;
6
- }
7
- }
@@ -1,10 +0,0 @@
1
- require "rack"
2
-
3
- module Hyperloop
4
- class Response < Rack::Response
5
- def initialize(*)
6
- super
7
- headers["Content-Type"] ||= "text/html"
8
- end
9
- end
10
- end
@@ -1,73 +0,0 @@
1
- require "erb"
2
- require "tilt"
3
-
4
- module Hyperloop
5
- class View
6
- def initialize(view_registry, full_path, layout_path=nil)
7
- @view_registry = view_registry
8
- @full_path = full_path
9
- @data = File.read(@full_path)
10
-
11
- # Only load layout data if all of these things are true:
12
- #
13
- # 1. We're not in a partial
14
- # 2. A layout path was provided
15
- # 3. There's a file at the provided layout path
16
- if !partial? && layout_path && File.file?(layout_path)
17
- @layout_data = File.read(layout_path)
18
- end
19
- end
20
-
21
- # Public: The format of the view. Derived from the view's extension.
22
- #
23
- # Returns a string.
24
- def format
25
- @format ||= File.extname(@full_path)[1..-1].intern
26
- end
27
-
28
- # Public: The name of the view. Derived from the view's filename without
29
- # any extensions or leading underscores. Not guaranteed to be unique amongst
30
- # other views in an app.
31
- #
32
- # Returns a string.
33
- def name
34
- @name ||= filename.split(".").first.sub(/^_/, "")
35
- end
36
-
37
- # Public: Is this view a partial?
38
- #
39
- # Returns a boolean.
40
- def partial?
41
- @partial ||= filename.start_with?("_")
42
- end
43
-
44
- # Public: Render the view.
45
- #
46
- # request - Rack request object that the view is being rendered in response
47
- # to.
48
- #
49
- # Returns a string.
50
- def render(request)
51
- case format
52
- when :html
53
- @data
54
- when :erb
55
- scope = Scope.new(request, @view_registry)
56
- view_html = Tilt["erb"].new { @data }.render(scope)
57
-
58
- if @layout_data
59
- layout_template = Tilt["erb"].new { @layout_data }
60
- layout_template.render(scope) { view_html }
61
- else
62
- view_html
63
- end
64
- end
65
- end
66
-
67
- private
68
-
69
- def filename
70
- @filename ||= File.basename(@full_path)
71
- end
72
- end
73
- end
@@ -1,90 +0,0 @@
1
- module Hyperloop
2
- class View
3
- class Registry
4
- def initialize(root)
5
- views_root = File.join([root, "app/views"].compact)
6
- layout_path = views_root + "/layouts/application.html.erb"
7
-
8
- # Get all the view paths. These look like:
9
- #
10
- # some/path/app/views/whatever.html.erb
11
- # some/path/app/views/subdir/whatever.html.erb
12
- # some/path/app/views/subdir/_partial.html.erb
13
- view_paths = Dir.glob(views_root + "/**/*").reject {|fn| File.directory?(fn)}
14
- view_paths -= [layout_path]
15
-
16
- @template_views = {}
17
- @partial_views = {}
18
-
19
- view_paths.each do |path|
20
- view = View.new(self, path, layout_path)
21
-
22
- # The path under app/views. This will be something like:
23
- #
24
- # /whatever.html.erb
25
- # /subdir/whatever.html.erb
26
- # /subdir/_partial.html.erb
27
- relative_path = path.sub(views_root, "")
28
-
29
- # The path under app/views without a file extension (and without the
30
- # starting _ for partials). This will be something like:
31
- #
32
- # /whatever
33
- # /subdir/whatever
34
- # /subdir/partial
35
- request_dir = File.dirname(relative_path)
36
- request_path = File.join(request_dir, view.name)
37
-
38
- if view.partial?
39
- # Chop off the leading forward slash for partials.
40
- @partial_views[request_path.sub(/^\//, "")] = view
41
- else
42
- @template_views[request_path] = view
43
- @template_views[request_dir] = view if view.name == "index"
44
- end
45
- end
46
- end
47
-
48
- # Public: Get the template view for the specified path.
49
- #
50
- # path - Relative path for the view. Should start under the app/views
51
- # directory and not include file extensions. Should start with a forward
52
- # slash.
53
- #
54
- # Example:
55
- #
56
- # Assuming there's a file at path/to/yoursite/app/views/subdir/whatever.html.erb
57
- #
58
- # bad: registry.find_template_view("/app/views/subdir/whatever.html.erb")
59
- # bad: registry.find_template_view("/subdir/whatever.html.erb")
60
- # bad: registry.find_template_view("subdir/whatever")
61
- # good: registry.find_template_view("/subdir/whatever")
62
- #
63
- # Returns a Hyperloop::View or nil if no view was found.
64
- def find_template_view(path)
65
- @template_views[path]
66
- end
67
-
68
- # Public: Get the partial view for the specified path.
69
- #
70
- # path - Relative path for the view. Should start under the app/views
71
- # directory and not include file extensions, leading underscores, or
72
- # leading forward slashes.
73
- #
74
- # Example:
75
- #
76
- # Assuming there's a file at path/to/yoursite/app/views/subdir/_partial.html.erb
77
- #
78
- # bad: registry.find_partial_view("app/views/subdir/_partial.html.erb")
79
- # bad: registry.find_partial_view("subdir/_partial.html.erb")
80
- # bad: registry.find_partial_view("subdir/_partial")
81
- # bad: registry.find_partial_view("/subdir/partial")
82
- # good: registry.find_partial_view("subdir/partial")
83
- #
84
- # Returns a Hyperloop::View or nil if no view was found.
85
- def find_partial_view(path)
86
- @partial_views[path]
87
- end
88
- end
89
- end
90
- end
@@ -1,23 +0,0 @@
1
- require "tilt"
2
-
3
- module Hyperloop
4
- class View
5
- class Scope
6
- attr_reader :request
7
-
8
- def initialize(request, view_registry)
9
- @request = request
10
- @view_registry = view_registry
11
- end
12
-
13
- # Public: Render the specified partial.
14
- #
15
- # path - Path to look for the partial at.
16
- #
17
- # Returns a string.
18
- def render(path)
19
- @view_registry.find_partial_view(path).render(request)
20
- end
21
- end
22
- end
23
- end
@@ -1,300 +0,0 @@
1
- require File.expand_path("../spec_helper", __FILE__)
2
-
3
- describe Hyperloop::Application do
4
- describe "with a flat views directory" do
5
- before :each do
6
- @app = Hyperloop::Application.new(prepare_fixture(:simple))
7
- end
8
-
9
- it "responds successfully to a request for root" do
10
- response = mock_request(@app).get("/")
11
-
12
- expect(response).to be_ok
13
- expect(response.content_type).to eql("text/html")
14
- expect(text_in(response.body, "h1")).to eql("Simple")
15
- end
16
-
17
- it "responds successfully to a request for a different page" do
18
- response = mock_request(@app).get("/about")
19
-
20
- expect(response).to be_ok
21
- expect(text_in(response.body, "h1")).to eql("About")
22
- end
23
-
24
- it "responds successfully to a request with a trailing slash" do
25
- response = mock_request(@app).get("/about/")
26
-
27
- expect(response).to be_ok
28
- expect(text_in(response.body, "h1")).to eql("About")
29
- end
30
-
31
- it "404s on a request for a nonexistent page" do
32
- response = mock_request(@app).get("/nonexistent")
33
-
34
- expect(response).to be_not_found
35
- end
36
- end
37
-
38
- describe "with subdirectories" do
39
- before :each do
40
- @app = Hyperloop::Application.new(prepare_fixture(:subdirectories))
41
- end
42
-
43
- it "responds successfully to a request for the subdirectory root" do
44
- response = mock_request(@app).get("/subdir1")
45
-
46
- expect(response).to be_ok
47
- expect(text_in(response.body, "h1")).to eql("Subdirectory Index")
48
- end
49
-
50
- it "responds successfully to a request for a different page in the subdirectory" do
51
- response = mock_request(@app).get("/subdir1/kanye")
52
-
53
- expect(response).to be_ok
54
- expect(text_in(response.body, "h1")).to eql("Hurry up with my damn croissant")
55
- end
56
- end
57
-
58
- describe "with ERB" do
59
- before :each do
60
- @app = Hyperloop::Application.new(prepare_fixture(:erb))
61
- end
62
-
63
- it "renders embedded Ruby in the root page" do
64
- response = mock_request(@app).get("/")
65
-
66
- expect(response).to be_ok
67
- expect(text_in(response.body, "h1")).to eql("WE ARE USING ERB")
68
- end
69
- end
70
-
71
- describe "with a layout" do
72
- before :each do
73
- @app = Hyperloop::Application.new(prepare_fixture(:layouts))
74
- end
75
-
76
- it "renders the root view within the layout" do
77
- response = mock_request(@app).get("/")
78
-
79
- expect(response).to be_ok
80
- expect(text_in(response.body, "h1")).to eql("Layout Header")
81
- expect(text_in(response.body, "h2")).to eql("This is the root page!")
82
- end
83
-
84
- it "renders subdirectory views within the layout" do
85
- response = mock_request(@app).get("/subdir")
86
-
87
- expect(response).to be_ok
88
- expect(text_in(response.body, "h1")).to eql("Layout Header")
89
- expect(text_in(response.body, "h2")).to eql("This is a page in a subdirectory!")
90
- end
91
- end
92
-
93
- describe "with assets" do
94
- before :each do
95
- @app = Hyperloop::Application.new(prepare_fixture(:assets))
96
- end
97
-
98
- it "responds successfully to a request for root" do
99
- response = mock_request(@app).get("/")
100
-
101
- expect(response).to be_ok
102
- expect(text_in(response.body, "h1")).to eql("This app has so many assets")
103
- end
104
-
105
- it "responds successfully to a request for the css app bundle" do
106
- response = mock_request(@app).get("/assets/stylesheets/app.css")
107
-
108
- expect(response).to be_ok
109
- expect(response.content_type).to eql("text/css")
110
- expect(response.body).to match(/display: ?block/)
111
- end
112
-
113
- it "responds successfully to a request for the javascript app bundle" do
114
- response = mock_request(@app).get("/assets/javascripts/app.js")
115
-
116
- expect(response).to be_ok
117
- expect(response.content_type).to eql("application/javascript")
118
- expect(response.body).to match(/alert\("such javascript wow"\)/)
119
- end
120
-
121
- it "responds successfully to a request for a vendored css file" do
122
- response = mock_request(@app).get("/assets/stylesheets/vendored.css")
123
-
124
- expect(response).to be_ok
125
- expect(response.content_type).to eql("text/css")
126
- expect(response.body).to match(/margin: ?0/)
127
- end
128
-
129
- it "responds successfully to a request for a vendored javascript bundle" do
130
- response = mock_request(@app).get("/assets/javascripts/vendored.js")
131
-
132
- expect(response).to be_ok
133
- expect(response.content_type).to eql("application/javascript")
134
- expect(response.body).to match(/alert\("i am vendored"\)/)
135
- end
136
-
137
- it "responds successfully to a request for a gif" do
138
- response = mock_request(@app).get("/assets/images/my-gif.gif")
139
-
140
- expect(response).to be_ok
141
- expect(response.content_type).to eql("image/gif")
142
- expect(Digest::SHA1.hexdigest(response.body)).to eql("bcbc6e6fc1eb77b2ca676e17425df93a56495bb2")
143
- end
144
-
145
- it "responds successfully to a request for a jpg" do
146
- response = mock_request(@app).get("/assets/images/my-jpg.jpg")
147
-
148
- expect(response).to be_ok
149
- expect(response.content_type).to eql("image/jpeg")
150
- expect(Digest::SHA1.hexdigest(response.body)).to eql("ae6a26b513d6648446da1395ee73e9cf32c8c668")
151
- end
152
-
153
- it "responds successfully to a request for a png" do
154
- response = mock_request(@app).get("/assets/images/my-png.png")
155
-
156
- expect(response).to be_ok
157
- expect(response.content_type).to eql("image/png")
158
- expect(Digest::SHA1.hexdigest(response.body)).to eql("adf65c25a8e3e39c49ecf581433278d7eac4d1a2")
159
- end
160
-
161
- it "404s on a request for an asset without namespacing by type" do
162
- response = mock_request(@app).get("/assets/app.js")
163
- expect(response).to be_not_found
164
- end
165
-
166
- it "404s on a request for an asset namespaced by the wrong type" do
167
- response = mock_request(@app).get("/assets/stylesheets/app.js")
168
- expect(response).to be_not_found
169
- end
170
-
171
- it "404s on a request for an asset namespaced by an unknown type" do
172
- response = mock_request(@app).get("/assets/shouldfail/shouldfail.css")
173
- expect(response).to be_not_found
174
- end
175
-
176
- it "404s on a request for a nonexistent asset" do
177
- response = mock_request(@app).get("/assets/javascripts/nonexistent.js")
178
-
179
- expect(response).to be_not_found
180
- end
181
- end
182
-
183
- describe "live reloading" do
184
- context "with assets" do
185
- before :each do
186
- @root = prepare_fixture(:assets)
187
- @app = Hyperloop::Application.new(@root)
188
- end
189
-
190
- it "reloads changed assets" do
191
- # On the first request, stylesheet should have `display: block` and not
192
- # `display: inline`.
193
- response = mock_request(@app).get("/assets/stylesheets/app.css")
194
- expect(response).to be_ok
195
- expect(response.body).to match(/display: ?block/)
196
- expect(response.body).not_to match(/display: ?inline/)
197
-
198
- change_fixture(@root, "app/assets/stylesheets/my-styles.scss",
199
- :pattern => "display: block",
200
- :replacement => "display: inline"
201
- )
202
-
203
- # On the second request, stylesheet should have `display: inline` and not
204
- # `display: block`.
205
- response = mock_request(@app).get("/assets/stylesheets/app.css")
206
- expect(response).to be_ok
207
- expect(response.body).to match(/display: ?inline/)
208
- expect(response.body).not_to match(/display: ?block/)
209
- end
210
- end
211
-
212
- context "with views" do
213
- before :each do
214
- @root = prepare_fixture(:partials)
215
- @app = Hyperloop::Application.new(@root)
216
- end
217
-
218
- it "reloads changed layouts" do
219
- # On the first request, <title> text should not be "Changed"
220
- response = mock_request(@app).get("/")
221
- expect(response).to be_ok
222
- expect(text_in(response.body, "title")).not_to eql("Changed")
223
-
224
- change_fixture(@root, "app/views/layouts/application.html.erb",
225
- :pattern => /<title>[^<]*<\/title>/,
226
- :replacement => "<title>Changed</title>"
227
- )
228
-
229
- # On the second request, <title> text should be "Changed"
230
- response = mock_request(@app).get("/")
231
- expect(response).to be_ok
232
- expect(text_in(response.body, "title")).to eql("Changed")
233
- end
234
-
235
- it "reloads changed partials" do
236
- # On the first request, <p> text should not be "Changed"
237
- response = mock_request(@app).get("/")
238
- expect(response).to be_ok
239
- expect(text_in(response.body, "p.spec-in-partial")).not_to eql("Changed")
240
-
241
- change_fixture(@root, "app/views/subdir/_partial.html.erb",
242
- :pattern => /<p class="spec-in-partial">[^<]*<\/p>/,
243
- :replacement => "<p class=\"spec-in-partial\">Changed</p>"
244
- )
245
-
246
- # On the second request, <p> text should be "Changed"
247
- response = mock_request(@app).get("/")
248
- expect(response).to be_ok
249
- expect(text_in(response.body, "p.spec-in-partial")).to eql("Changed")
250
- end
251
-
252
- it "reloads changed views" do
253
- # On the first request, <h2> text should not be "Changed"
254
- response = mock_request(@app).get("/")
255
- expect(response).to be_ok
256
- expect(text_in(response.body, "h2")).not_to eql("Changed")
257
-
258
- change_fixture(@root, "app/views/index.html.erb",
259
- :pattern => /<h2>[^<]*<\/h2>/,
260
- :replacement => "<h2>Changed</h2>"
261
- )
262
-
263
- # On the second request, <h2> text should be "Changed"
264
- response = mock_request(@app).get("/")
265
- expect(response).to be_ok
266
- expect(text_in(response.body, "h2")).to eql("Changed")
267
- end
268
- end
269
-
270
- context "in production" do
271
- before :each do
272
- set_rack_env :production
273
- end
274
-
275
- after :each do
276
- reset_rack_env
277
- end
278
-
279
- it "doesn't reload changed views" do
280
- root = prepare_fixture(:erb)
281
- app = Hyperloop::Application.new(root)
282
-
283
- # On the first request, <title> text should be "ERB"
284
- response = mock_request(app).get("/")
285
- expect(response).to be_ok
286
- expect(text_in(response.body, "title")).to eql("ERB")
287
-
288
- change_fixture(root, "app/views/index.html.erb",
289
- :pattern => "<title>ERB</title>",
290
- :replacement => "<title>Changed</title>"
291
- )
292
-
293
- # On the second request, <title> text should still be "ERB"
294
- response = mock_request(app).get("/")
295
- expect(response).to be_ok
296
- expect(text_in(response.body, "title")).to eql("ERB")
297
- end
298
- end
299
- end
300
- end