vitrine 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/Guardfile +6 -0
- data/{README.rdoc → README.md} +37 -29
- data/lib/version.rb +1 -1
- data/lib/vitrine.rb +43 -27
- data/test/helper.rb +4 -11
- data/test/test_vitrine.rb +179 -2
- data/vitrine.gemspec +20 -4
- metadata +75 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91d23457bb272e611a621e15a4ec00427d6d7460
|
4
|
+
data.tar.gz: e45473b0d4cefc4b9c740c8e7650345e970268f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48c138e91489e1c1fe73b96e578721cadb15437e3fedc412ec3d3c290993a7b4e787ecb218cb0b51811e6f6e00738de8a31680a7cfce622508df58da4efe825c
|
7
|
+
data.tar.gz: d022f069dd5f28900b2f4919c340ed3fc665c2ffce1214b34db2be9c61cd1693c039e4eee996b9474d0363da56c60f70931093c88fb7fd89264a4a459232c2d9
|
data/Gemfile
CHANGED
@@ -5,6 +5,7 @@ gem 'coffee-script', '~> 2.2'
|
|
5
5
|
gem 'sass', '~> 3'
|
6
6
|
gem 'guard', '~> 2.2'
|
7
7
|
gem 'guard-livereload'
|
8
|
+
gem 'rack-contrib'
|
8
9
|
gem 'rack-livereload'
|
9
10
|
|
10
11
|
# Add dependencies to develop your gem here.
|
@@ -13,4 +14,8 @@ group :development do
|
|
13
14
|
gem "rdoc", "~> 3.12"
|
14
15
|
gem "bundler", "~> 1.0"
|
15
16
|
gem "jeweler", "~> 1.8.7"
|
17
|
+
gem 'rack-test'
|
18
|
+
gem 'guard-test'
|
19
|
+
gem 'minitest'
|
20
|
+
gem 'pry'
|
16
21
|
end
|
data/Guardfile
ADDED
data/{README.rdoc → README.md}
RENAMED
@@ -1,51 +1,51 @@
|
|
1
|
-
|
1
|
+
A nimble web server one-liner for modern web-apps, a bit in the style of
|
2
|
+
[lineman](https://github.com/testdouble/lineman), [serve](https://github.com/visionmedia/serve),
|
3
|
+
another [serve](https://github.com/jlong/serve) and such. Will display your precious stuff on port 4000.
|
2
4
|
|
3
|
-
|
4
|
-
lineman, serve and such. Will display your precious stuff on port 4000.
|
5
|
-
|
6
|
-
== Core idea of Vitrine
|
5
|
+
## Core idea of Vitrine
|
7
6
|
|
8
7
|
You want a server that will automatically wrap your CoffeeScript and SASS assets, and allow
|
9
8
|
some rudimentary templating. This is practically enough for putting together MVP prototypes,
|
10
9
|
especially as far as single-page apps go. You want this server to not coerce you into a specific
|
11
10
|
SCSS framework, you don't want to scaffold anything, you don't want to have any configs defined and
|
12
|
-
you hate running wizards.
|
11
|
+
you hate running wizards. You also don't feel like buying any Mac applications which call out
|
12
|
+
to command-line compilers anyway.
|
13
13
|
|
14
14
|
If most of the above is true, Vitrine is just what you need.
|
15
15
|
|
16
|
-
|
16
|
+
## All you need is some `public`
|
17
17
|
|
18
18
|
Vitrine assumes that there are two directories under the current tree:
|
19
|
-
*
|
20
|
-
*
|
19
|
+
* `public` - for the JS, for CSS and SCSS and in general all the static files served straight out
|
20
|
+
* `views` - for the templates, in any Ruby templating format you have
|
21
|
+
|
22
|
+
## Automatic compilation
|
23
|
+
|
24
|
+
Vitrine is for **development**. It takes runtime compilation to 11 and beyound. Running tasks
|
25
|
+
is all fine and good when you build out the app for production, but when iterating on UI it's essential
|
26
|
+
to be able to just yank the file 3in there and carry on.
|
21
27
|
|
22
|
-
|
28
|
+
### For SCSS/SASS
|
23
29
|
|
24
30
|
Any .scss file you shove into the "public" directory can be referenced as ".css" from your HTML code.
|
25
31
|
Vitrine will automatically compile it via SASS.
|
26
32
|
|
27
|
-
|
33
|
+
### For CoffeeScript, with source maps
|
28
34
|
|
29
|
-
Same thing applies to CoffeeScript - put
|
35
|
+
Same thing applies to CoffeeScript - put `.coffee` files in "public", and reference them as `.js` files.
|
30
36
|
Vitrine will generate you source maps on the fly for pleasant browser debugging.
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
Both SCSS and JS links will fall through to the static versions if you cache them on the server or as a result of
|
35
|
-
asset compilation.
|
36
|
-
|
37
|
-
== Sensible error messages when automatic compilation fails
|
38
|
+
## Sensible error messages when automatic compilation fails
|
38
39
|
|
39
40
|
Vitrine will try to show you sensible errors if your SCSS or CoffeeScript fail to compile due to syntax errors and
|
40
|
-
the like.
|
41
|
+
the like. CoffeeScript errors go to the browser console, and Sass errors go in a generated element on top of your page.
|
41
42
|
|
42
|
-
|
43
|
+
## Do not recompile on every request
|
43
44
|
|
44
|
-
Succesfully compiled assets will be
|
45
|
-
|
46
|
-
dates of the source files are different than before.
|
45
|
+
Succesfully compiled assets will be cached to save time on next reload, and ETagged based on their
|
46
|
+
mtime.
|
47
47
|
|
48
|
-
|
48
|
+
## Automatic Ruby template pickup
|
49
49
|
|
50
50
|
If you have the "views" directory available, Vitrine will try to pick up any usable file for any URL without extensions.
|
51
51
|
From there on, it's going to try to render it with the automatically picked template engine using the
|
@@ -54,19 +54,27 @@ standard Sinatra facilities. You can use HAML, LESS, Slim, ERB, Builder or anyth
|
|
54
54
|
If you are writing an SPA, you can make a file called "catch_all.erb" which is going to be the fall-through template
|
55
55
|
for all missing URLs without extension.
|
56
56
|
|
57
|
-
|
57
|
+
## Automatic reload via Guard
|
58
58
|
|
59
59
|
If your project already has a Guardfile, Vitrine will inject live-reloading hooks into your HTML using
|
60
|
-
rack-livereload, so you won't need browser extensions at all.
|
60
|
+
[rack-livereload](https://github.com/johnbintz/rack-livereload), so you won't need browser extensions at all.
|
61
61
|
|
62
|
-
|
62
|
+
## Sensible caching
|
63
|
+
|
64
|
+
Vitrine will `etag` all the precompiled assets for faster reloading.
|
65
|
+
|
66
|
+
## Packaging and baking
|
63
67
|
|
64
68
|
At this point the best way to bake a Vitrine site is to crawl it externally, but we are going to implement
|
65
69
|
baking at some point. The idea is that you will end up upgrading the site to either a Node app or a Ruby app
|
66
70
|
with it's own +config.ru+ - if after that point you still wish to use Vitrine, you can use it like a Rack
|
67
71
|
middleware.
|
68
72
|
|
69
|
-
|
73
|
+
## Using as a middleware
|
74
|
+
|
75
|
+
Most actions in Vitrine will fall through to 404, so `Vitrine::App` can be used with `Rack::Cascade`
|
76
|
+
|
77
|
+
## Contributing to vitrine
|
70
78
|
|
71
79
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
72
80
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
@@ -76,7 +84,7 @@ middleware.
|
|
76
84
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
77
85
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
78
86
|
|
79
|
-
|
87
|
+
## Copyright
|
80
88
|
|
81
89
|
Copyright (c) 2013 Julik Tarkhanov. See LICENSE.txt for
|
82
90
|
further details.
|
data/lib/version.rb
CHANGED
data/lib/vitrine.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
require 'coffee-script'
|
3
|
-
|
3
|
+
require 'rack/contrib/try_static'
|
4
4
|
require 'sass'
|
5
5
|
require 'pathname'
|
6
6
|
|
@@ -84,19 +84,29 @@ class Vitrine::App < Sinatra::Base
|
|
84
84
|
set :raise_errors, true
|
85
85
|
set :root, File.expand_path(File.dirname(__FILE__))
|
86
86
|
set :views, lambda { File.join(settings.root, "views") }
|
87
|
-
|
88
|
-
|
87
|
+
set :public_dir, lambda { File.join(settings.root, "public") }
|
89
88
|
|
90
89
|
# For extensionless things try to pick out the related templates
|
91
|
-
# from the views directory, and render them with a default layout
|
90
|
+
# from the views directory, and render them with a default layout.
|
91
|
+
# If no template is found fallback to halting on 404
|
92
|
+
# so that Vitrine can be cascaded from.
|
92
93
|
get /^([^\.]+)$/ do | extensionless_path |
|
93
|
-
|
94
|
+
render_template_or_static(extensionless_path)
|
94
95
|
end
|
95
96
|
|
96
|
-
|
97
97
|
# Allow "fake" form submits
|
98
98
|
post /^([^\.]+)$/ do | extensionless_path |
|
99
|
-
|
99
|
+
render_template_or_static(extensionless_path)
|
100
|
+
end
|
101
|
+
|
102
|
+
def render_template_or_static(extensionless_path)
|
103
|
+
probable_html = extensionless_path + "/index.html"
|
104
|
+
html_path = File.join(settings.public_dir, probable_html)
|
105
|
+
if File.exist? html_path
|
106
|
+
send_file html_path
|
107
|
+
else
|
108
|
+
render_template(extensionless_path)
|
109
|
+
end
|
100
110
|
end
|
101
111
|
|
102
112
|
def render_template(extensionless_path)
|
@@ -113,9 +123,7 @@ class Vitrine::App < Sinatra::Base
|
|
113
123
|
possibilites = possible_globs.map do | pattern |
|
114
124
|
Dir.glob(File.join(settings.views, pattern))
|
115
125
|
end.flatten.reject do | e |
|
116
|
-
e =~
|
117
|
-
end.reject do | e |
|
118
|
-
e =~ /(\.+)$/ # and except directory self-links
|
126
|
+
File.basename(e) =~ /^\./ # except invisibles and self-links
|
119
127
|
end
|
120
128
|
|
121
129
|
# Try the first template that has been found
|
@@ -124,12 +132,12 @@ class Vitrine::App < Sinatra::Base
|
|
124
132
|
# If nothing is found just bail
|
125
133
|
unless template_path
|
126
134
|
err = possible_globs.map{|e| e.inspect }.join(', ')
|
127
|
-
|
135
|
+
halt 404, "No template found - tried #{err}"
|
128
136
|
end
|
129
137
|
|
130
138
|
relative_path = Pathname.new(template_path).relative_path_from(Pathname.new(settings.views))
|
131
139
|
|
132
|
-
$stderr.puts "-> #{extensionless_path.inspect} : Rendering via template #{relative_path.to_s.inspect}"
|
140
|
+
# $stderr.puts "-> #{extensionless_path.inspect} : Rendering via template #{relative_path.to_s.inspect}"
|
133
141
|
|
134
142
|
locals = {}
|
135
143
|
# Auto-pick the template engine out of the extension
|
@@ -144,13 +152,18 @@ class Vitrine::App < Sinatra::Base
|
|
144
152
|
content_type 'text/css', :charset => 'utf-8'
|
145
153
|
# TODO: has no handling for .sass
|
146
154
|
scss_source_path = File.join(settings.root, 'public', "#{basename}.scss")
|
147
|
-
mtime_cache(scss_source_path)
|
155
|
+
mtime_cache(scss_source_path) do
|
156
|
+
Sass.compile_file(scss_source_path, cache_location: '/tmp/vitrine/sass-cache')
|
157
|
+
end
|
148
158
|
rescue Errno::ENOENT # Missing SCSS
|
149
159
|
halt 404, "No such CSS or SCSS file found"
|
150
160
|
rescue Exception => e # CSS syntax error or something alike
|
151
|
-
#
|
152
|
-
|
153
|
-
|
161
|
+
# Add a generated DOM element before <body/> to inject
|
162
|
+
# a visible error message
|
163
|
+
error_tpl = 'body:before { background: white; font-family: sans-serif; color: red; font-size: 14px; content: %s }'
|
164
|
+
css_message = error_tpl % [e.class, "\n", "--> ", e.message].join.inspect
|
165
|
+
|
166
|
+
halt 500, css_message
|
154
167
|
end
|
155
168
|
end
|
156
169
|
|
@@ -165,8 +178,7 @@ class Vitrine::App < Sinatra::Base
|
|
165
178
|
rescue Errno::ENOENT # Missing CoffeeScript
|
166
179
|
halt 404, "No coffeescript file found to generate the map for"
|
167
180
|
rescue Exception => e # CS syntax error or something alike
|
168
|
-
|
169
|
-
'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect
|
181
|
+
halt 400, 'Compliation of the related CoffeeScript file failed'
|
170
182
|
end
|
171
183
|
end
|
172
184
|
|
@@ -175,15 +187,16 @@ class Vitrine::App < Sinatra::Base
|
|
175
187
|
# If this file is not found resort back to a coffeescript
|
176
188
|
begin
|
177
189
|
coffee_source = File.join(settings.root, 'public', "#{basename}.coffee")
|
178
|
-
content_type 'text/javascript'
|
190
|
+
content_type 'text/javascript'
|
179
191
|
mtime_cache(coffee_source) do
|
180
192
|
["//# sourceMappingURL=#{basename}.js.map", CoffeeScript.compile(File.read(coffee_source))].join("\n")
|
181
193
|
end
|
182
194
|
rescue Errno::ENOENT # Missing CoffeeScript
|
183
195
|
halt 404, "No such JS file and could not find a .coffee replacement"
|
184
196
|
rescue Exception => e # CS syntax error or something alike
|
185
|
-
#
|
186
|
-
'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect
|
197
|
+
# Inject the syntax error into the browser console
|
198
|
+
console_message = 'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect
|
199
|
+
halt 500, console_message
|
187
200
|
end
|
188
201
|
end
|
189
202
|
|
@@ -199,14 +212,17 @@ class Vitrine::App < Sinatra::Base
|
|
199
212
|
# Store in a temp dir
|
200
213
|
FileUtils.mkdir_p '/tmp/vitrine'
|
201
214
|
p = '/tmp/vitrine/%s' % cache_sha
|
202
|
-
|
215
|
+
if File.exist?(p)
|
216
|
+
etag File.mtime(p)
|
203
217
|
File.read(p)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
218
|
+
else
|
219
|
+
yield.tap do | body |
|
220
|
+
Vitrine.atomic_write(p) do |f|
|
221
|
+
# $stderr.puts "---> Recompiling #{path} for #{request.path_info}"
|
222
|
+
f.write body
|
223
|
+
end
|
224
|
+
etag File.mtime(p)
|
208
225
|
end
|
209
|
-
retry
|
210
226
|
end
|
211
227
|
end
|
212
228
|
|
data/test/helper.rb
CHANGED
@@ -1,18 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler'
|
3
|
-
|
4
|
-
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
|
10
5
|
require 'test/unit'
|
11
|
-
require '
|
6
|
+
require 'rack/test'
|
12
7
|
|
13
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
-
require 'vitrine'
|
16
10
|
|
17
|
-
|
18
|
-
end
|
11
|
+
require 'vitrine'
|
data/test/test_vitrine.rb
CHANGED
@@ -1,7 +1,184 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestVitrine < Test::Unit::TestCase
|
4
|
-
|
5
|
-
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
# Wrap the test run in mktimpdir where we will store our temp application
|
7
|
+
def run(runner)
|
8
|
+
Dir.mktmpdir("vitrine-tests") do | dir_path |
|
9
|
+
@tempdir = dir_path
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_public(name)
|
15
|
+
FileUtils.mkdir_p @tempdir + '/public'
|
16
|
+
File.open(File.join(@tempdir, 'public', name), 'w') do | f |
|
17
|
+
yield f
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def app
|
22
|
+
vitrine = Vitrine::App.new
|
23
|
+
vitrine.settings.set :root, @tempdir
|
24
|
+
vitrine
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_fetch_index_without_index_should_404
|
28
|
+
get '/'
|
29
|
+
assert_equal 404, last_response.status, "Should have responded with 404 since there is no template"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_fetch_index_via_template_renders_index_template
|
33
|
+
FileUtils.mkdir_p File.join(@tempdir, 'views')
|
34
|
+
File.open(File.join(@tempdir, 'views', 'index.erb'), 'w') do | f |
|
35
|
+
f.write '<%= RUBY_VERSION %>'
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/'
|
39
|
+
assert last_response.ok?, "Should have responded with 200 since it picks up a template"
|
40
|
+
assert_equal RUBY_VERSION, last_response.body
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_fetch_subdir_with_index_template_in_subfolder_picks_up_index_template
|
44
|
+
FileUtils.mkdir_p File.join(@tempdir, 'views/things')
|
45
|
+
File.open(File.join(@tempdir, 'views/things/index.erb'), 'w') do | f |
|
46
|
+
f.write '<%= RUBY_VERSION %>'
|
47
|
+
end
|
48
|
+
|
49
|
+
get '/things'
|
50
|
+
|
51
|
+
assert last_response.ok?, "Should have responded with 200 since it picks up a template"
|
52
|
+
assert_equal RUBY_VERSION, last_response.body
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_fetch_subdir_without_extension_can_address_template
|
56
|
+
FileUtils.mkdir_p File.join(@tempdir, 'views')
|
57
|
+
File.open(File.join(@tempdir, 'views', 'things.erb'), 'w') do | f |
|
58
|
+
f.write '<%= RUBY_VERSION %>'
|
59
|
+
end
|
60
|
+
|
61
|
+
get '/things'
|
62
|
+
assert_equal 200, last_response.status, "Should have responded with 200 since it picks up a template"
|
63
|
+
assert_equal RUBY_VERSION, last_response.body
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_fetches_index_in_root_if_present
|
67
|
+
write_public 'index.html' do | f |
|
68
|
+
f.write '<!DOCTYPE html><html></html>'
|
69
|
+
end
|
70
|
+
|
71
|
+
get '/'
|
72
|
+
assert last_response.ok?, "Should have fetched the index.html"
|
73
|
+
end
|
74
|
+
|
75
|
+
# def test_fetches_index_in_subdirectory_if_present
|
76
|
+
# write_public 'items/index.html' do | f |
|
77
|
+
# f.write 'this just in'
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# get '/items'
|
81
|
+
# assert last_response.ok?, "Should have responded with 404 since there is no template"
|
82
|
+
# assert_equal 'this just in', last_response.body
|
83
|
+
# end
|
84
|
+
|
85
|
+
def test_passes_coffeescript_as_raw_file
|
86
|
+
write_public 'nice.coffee' do | f |
|
87
|
+
f.write 'alert "rockage!"'
|
88
|
+
end
|
89
|
+
|
90
|
+
get '/nice.coffee'
|
91
|
+
assert_equal 'application/octet-stream', last_response.content_type
|
92
|
+
assert_equal 'alert "rockage!"', last_response.body
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_compiles_coffeescript_to_js_when_addressed_by_js_extension
|
96
|
+
write_public 'nice.coffee' do | f |
|
97
|
+
f.puts 'alert "rockage!"'
|
98
|
+
end
|
99
|
+
|
100
|
+
get '/nice.js'
|
101
|
+
|
102
|
+
assert_not_nil last_response.headers['ETag'], 'Should set ETag for the compiled version'
|
103
|
+
assert_equal 200, last_response.status
|
104
|
+
assert_equal 'text/javascript;charset=utf-8', last_response.content_type
|
105
|
+
|
106
|
+
assert last_response.body.include?( 'alert("rockage!")'), 'Should include the compiled function'
|
107
|
+
assert last_response.body.include?( '//# sourceMappingURL=/nice.js.map'),
|
108
|
+
'Should include the reference to the source map'
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_sends_vanilla_js_if_its_present
|
112
|
+
write_public 'vanilla.js' do | f |
|
113
|
+
f.puts 'vanilla();'
|
114
|
+
end
|
115
|
+
|
116
|
+
get '/vanilla.js'
|
117
|
+
assert_equal 200, last_response.status
|
118
|
+
assert_equal "vanilla();\n", last_response.body
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_invalid_coffeescript_creates_decent_error_alerts
|
122
|
+
write_public 'faulty.coffee' do | f |
|
123
|
+
f.puts 'function() { junked up }'
|
124
|
+
end
|
125
|
+
|
126
|
+
get '/faulty.js'
|
127
|
+
|
128
|
+
assert_equal 500, last_response.status
|
129
|
+
assert_equal 'text/javascript;charset=utf-8', last_response.content_type
|
130
|
+
err = 'console.error("ExecJS::RuntimeError\n--> SyntaxError: reserved word \"function\"")'
|
131
|
+
assert_equal err, last_response.body
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_caches_compiled_js_by_etag_and_responds_with_304_when_requested_again
|
135
|
+
write_public 'nice.coffee' do | f |
|
136
|
+
f.puts 'alert "rockage!"'
|
137
|
+
end
|
138
|
+
|
139
|
+
get '/nice.js'
|
140
|
+
assert_equal 200, last_response.status
|
141
|
+
assert_not_nil last_response.headers['ETag']
|
142
|
+
|
143
|
+
etag = last_response.headers['ETag']
|
144
|
+
get '/nice.js', {}, rack_env = {'HTTP_IF_NONE_MATCH' => etag}
|
145
|
+
assert_equal 304, last_response.status
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_sends_vanilla_css_if_present
|
149
|
+
write_public 'vanilla.css' do | f |
|
150
|
+
f.write '/* vanilla CSS kode */'
|
151
|
+
end
|
152
|
+
|
153
|
+
get '/vanilla.css'
|
154
|
+
|
155
|
+
assert last_response.ok?
|
156
|
+
assert_equal '/* vanilla CSS kode */', last_response.body
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_compiles_scss_when_requested_as_css
|
160
|
+
write_public 'styles.scss' do | f |
|
161
|
+
f.puts '.foo {'
|
162
|
+
f.puts '.bar { font-size: 10px; }'
|
163
|
+
f.puts '}'
|
164
|
+
end
|
165
|
+
|
166
|
+
get '/styles.css'
|
167
|
+
|
168
|
+
assert last_response.ok?
|
169
|
+
assert_not_nil last_response.headers['ETag'], 'Should set ETag for the compiled version'
|
170
|
+
assert last_response.body.include?('.foo .bar {'), 'Should have compiled the CSS rule'
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_displays_decent_alerts_for_scss_errors
|
174
|
+
write_public 'faulty.scss' do | f |
|
175
|
+
f.puts '.foo {{ junkiness-factor: 24pem; }'
|
176
|
+
end
|
177
|
+
|
178
|
+
get '/faulty.css'
|
179
|
+
|
180
|
+
assert_equal 500, last_response.status
|
181
|
+
assert last_response.body.include?('body:before {'), 'Should include the generated element selector'
|
182
|
+
assert last_response.body.include?('Sass::SyntaxError'), 'Should include the syntax error class'
|
6
183
|
end
|
7
184
|
end
|
data/vitrine.gemspec
CHANGED
@@ -5,23 +5,24 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "vitrine"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.11"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Julik Tarkhanov"]
|
12
|
-
s.date = "2013-11-
|
12
|
+
s.date = "2013-11-25"
|
13
13
|
s.description = " Serves ERB templates with live CoffeeScript and SASS "
|
14
14
|
s.email = "me@julik.nl"
|
15
15
|
s.executables = ["vitrine"]
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE.txt",
|
18
|
-
"README.
|
18
|
+
"README.md"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".document",
|
22
22
|
"Gemfile",
|
23
|
+
"Guardfile",
|
23
24
|
"LICENSE.txt",
|
24
|
-
"README.
|
25
|
+
"README.md",
|
25
26
|
"Rakefile",
|
26
27
|
"bin/vitrine",
|
27
28
|
"lib/atomic_write.rb",
|
@@ -47,20 +48,30 @@ Gem::Specification.new do |s|
|
|
47
48
|
s.add_runtime_dependency(%q<sass>, ["~> 3"])
|
48
49
|
s.add_runtime_dependency(%q<guard>, ["~> 2.2"])
|
49
50
|
s.add_runtime_dependency(%q<guard-livereload>, [">= 0"])
|
51
|
+
s.add_runtime_dependency(%q<rack-contrib>, [">= 0"])
|
50
52
|
s.add_runtime_dependency(%q<rack-livereload>, [">= 0"])
|
51
53
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
52
54
|
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
53
55
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
|
56
|
+
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<guard-test>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<minitest>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
54
60
|
else
|
55
61
|
s.add_dependency(%q<sinatra>, ["~> 1.4"])
|
56
62
|
s.add_dependency(%q<coffee-script>, ["~> 2.2"])
|
57
63
|
s.add_dependency(%q<sass>, ["~> 3"])
|
58
64
|
s.add_dependency(%q<guard>, ["~> 2.2"])
|
59
65
|
s.add_dependency(%q<guard-livereload>, [">= 0"])
|
66
|
+
s.add_dependency(%q<rack-contrib>, [">= 0"])
|
60
67
|
s.add_dependency(%q<rack-livereload>, [">= 0"])
|
61
68
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
62
69
|
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
63
70
|
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
71
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
72
|
+
s.add_dependency(%q<guard-test>, [">= 0"])
|
73
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
74
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
64
75
|
end
|
65
76
|
else
|
66
77
|
s.add_dependency(%q<sinatra>, ["~> 1.4"])
|
@@ -68,10 +79,15 @@ Gem::Specification.new do |s|
|
|
68
79
|
s.add_dependency(%q<sass>, ["~> 3"])
|
69
80
|
s.add_dependency(%q<guard>, ["~> 2.2"])
|
70
81
|
s.add_dependency(%q<guard-livereload>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rack-contrib>, [">= 0"])
|
71
83
|
s.add_dependency(%q<rack-livereload>, [">= 0"])
|
72
84
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
73
85
|
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
74
86
|
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
87
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
88
|
+
s.add_dependency(%q<guard-test>, [">= 0"])
|
89
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
90
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
75
91
|
end
|
76
92
|
end
|
77
93
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vitrine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-contrib
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rack-livereload
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +150,62 @@ dependencies:
|
|
136
150
|
- - ~>
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: 1.8.7
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rack-test
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: guard-test
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: minitest
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: pry
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - '>='
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
139
209
|
description: ' Serves ERB templates with live CoffeeScript and SASS '
|
140
210
|
email: me@julik.nl
|
141
211
|
executables:
|
@@ -143,12 +213,13 @@ executables:
|
|
143
213
|
extensions: []
|
144
214
|
extra_rdoc_files:
|
145
215
|
- LICENSE.txt
|
146
|
-
- README.
|
216
|
+
- README.md
|
147
217
|
files:
|
148
218
|
- .document
|
149
219
|
- Gemfile
|
220
|
+
- Guardfile
|
150
221
|
- LICENSE.txt
|
151
|
-
- README.
|
222
|
+
- README.md
|
152
223
|
- Rakefile
|
153
224
|
- bin/vitrine
|
154
225
|
- lib/atomic_write.rb
|