vitrine 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91d23457bb272e611a621e15a4ec00427d6d7460
4
- data.tar.gz: e45473b0d4cefc4b9c740c8e7650345e970268f1
3
+ metadata.gz: ad38905bb36040591304042eb96301dd54844848
4
+ data.tar.gz: df1a08482625e54ba47255a640913d288898a79b
5
5
  SHA512:
6
- metadata.gz: 48c138e91489e1c1fe73b96e578721cadb15437e3fedc412ec3d3c290993a7b4e787ecb218cb0b51811e6f6e00738de8a31680a7cfce622508df58da4efe825c
7
- data.tar.gz: d022f069dd5f28900b2f4919c340ed3fc665c2ffce1214b34db2be9c61cd1693c039e4eee996b9474d0363da56c60f70931093c88fb7fd89264a4a459232c2d9
6
+ metadata.gz: 104b112da1f12d430e449d1ecc59ed80ff07045c9f8141ee91c3be7f6dba79570b3108c674702d638ab7ca3a61a17c9435a89c651960a63a679b05bd9ae7f619
7
+ data.tar.gz: 89d843fd806e0f41b95e438ba3cdef583cdb7d1ea105405f99c18a8a393862a6a70fbcb491f5f43db897b0604866b2e026f4d4549893033ca16879b20a68a428
data/README.md CHANGED
@@ -67,12 +67,18 @@ Vitrine will `etag` all the precompiled assets for faster reloading.
67
67
 
68
68
  At this point the best way to bake a Vitrine site is to crawl it externally, but we are going to implement
69
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
70
- with it's own +config.ru+ - if after that point you still wish to use Vitrine, you can use it like a Rack
70
+ with it's own `config.ru` - if after that point you still wish to use Vitrine, you can use it like a Rack
71
71
  middleware.
72
72
 
73
73
  ## Using as a middleware
74
74
 
75
- Most actions in Vitrine will fall through to 404, so `Vitrine::App` can be used with `Rack::Cascade`
75
+ Most actions in Vitrine will fall through to 404, so `Vitrine::App` can be used as a middleware handler.
76
+ Put Vitrine into your application stack and it will complement your main application very nicely. But don't
77
+ forget to set `:root` - like so:
78
+
79
+ use Vitrine::App.new do | vitrine |
80
+ vitrine.settings.set :root => File.dirname(__FILE__)
81
+ end
76
82
 
77
83
  ## Contributing to vitrine
78
84
 
data/bin/vitrine CHANGED
@@ -1,5 +1,20 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  lib = File.dirname(__FILE__) + '/../lib'
4
- require lib + '/vitrine'
5
- Vitrine.run
3
+ require lib + '/server'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+
8
+ op = OptionParser.new
9
+ op.banner = "Usage: cd ~/sites/my-glorious-app; vitrine -p 9292"
10
+ op.on("-p", "--port NUMBER", Integer, "Run on the specified port (default is 4000)") do | port |
11
+ options[:port] = port
12
+ end
13
+
14
+ op.on("-r", "--root DIR", String, "Override the root directory (defaults to CWD)") do | rootdir |
15
+ options[:root] = rootdir
16
+ end
17
+
18
+ op.parse!
19
+
20
+ Vitrine::Server.start(options)
data/lib/server.rb ADDED
@@ -0,0 +1,76 @@
1
+ require_relative 'vitrine'
2
+ require 'rack-livereload'
3
+
4
+ module Vitrine::Server
5
+ DEFAULTS = { root: Dir.getwd, port: 4000, :address => '127.0.0.1' }
6
+
7
+ def self.check_dirs_present!(options)
8
+ views = options[:root] + '/views'
9
+ unless File.exist?(views) and File.directory?(views)
10
+ $stderr.puts "WARNING: `views' directory not found under the current tree, you might want to create it"
11
+ end
12
+
13
+ public_folder = options[:root] + '/public'
14
+ unless File.exist?(public_folder) and File.directory?(public_folder)
15
+ $stderr.puts "ERROR: `public' directory not found under the current tree, you should create it. Vitrine won't run without it"
16
+ exit 1
17
+ end
18
+ end
19
+
20
+ # Builds the Rack application with all the wrappers
21
+ def self.build_app(options)
22
+ Rack::Builder.new do
23
+ use Rack::ShowStatus
24
+ use Rack::ShowExceptions
25
+
26
+ guardfile_path = options[:root] + '/Guardfile'
27
+ if File.exist?(guardfile_path)
28
+ $stderr.puts "Attaching LiveReload via Guardfile at #{guardfile_path.inspect}"
29
+ # Assume livereload is engaged
30
+ use Rack::LiveReload
31
+ else
32
+ $stderr.puts "No Guardfile found, so there won't be any livereload injection"
33
+ end
34
+
35
+ vitrine = Vitrine::App.new
36
+ vitrine.settings.set :root, options[:root]
37
+ run vitrine
38
+ end
39
+ end
40
+
41
+ # Pick a server handler engine and run the passed
42
+ # app on it, honoring the passed options
43
+ def self.start_server(app, options)
44
+ begin
45
+ # Try Thin
46
+ thin = Rack::Handler.get('thin')
47
+ thin.run app, :Port => options[:port], :Host => options[:address] do |server|
48
+ puts "Thin #{Thin::VERSION::STRING} available at http://#{options[:address]}:#{options[:port]}"
49
+ end
50
+ rescue LoadError
51
+ begin
52
+ # Then Mongrel
53
+ mongrel = Rack::Handler.get('mongrel')
54
+ mongrel.run app, :Port => options[:port], :Host => options[:address] do |server|
55
+ puts "Mongrel #{Mongrel::Const::MONGREL_VERSION} available at http://#{options[:address]}:#{options[:port]}"
56
+ end
57
+ rescue LoadError
58
+ # Then WEBrick
59
+ puts "Install Mongrel or Thin for better performance."
60
+ webrick = Rack::Handler.get('webrick')
61
+ webrick.run app, :Port => options[:port], :Host => options[:address] do |server|
62
+ trap("INT") { server.shutdown }
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ # Run the server, largely stolen from Serve
69
+ def self.start(passed_options = {})
70
+ options = DEFAULTS.merge(passed_options)
71
+ check_dirs_present!(options)
72
+
73
+ app = build_app(options)
74
+ start_server(app, options)
75
+ end
76
+ end
data/lib/sourcemaps.rb CHANGED
@@ -2,14 +2,14 @@ require 'pathname'
2
2
  require 'json'
3
3
 
4
4
  module Vitrine
5
- def self.build_coffeescript_source_map_body(full_coffeescript_file_path, public_dir_path)
5
+ def self.build_coffeescript_source_map_body(full_coffeescript_file_path, public_folder_path)
6
6
 
7
7
  script = File.read(full_coffeescript_file_path)
8
8
 
9
9
  # We need to feed paths ON THE SERVER so that the browser can connect the coffee file, the map and the JS file
10
10
  # - specify coffee source file explicitly (see http://coffeescript.org/documentation/docs/sourcemap.html#section-8)
11
11
  # The paths need to be slash-prepended (server-absolute)
12
- relative_path = '/' + Pathname.new(full_coffeescript_file_path).relative_path_from(Pathname.new(public_dir_path)).to_s
12
+ relative_path = '/' + Pathname.new(full_coffeescript_file_path).relative_path_from(Pathname.new(public_folder_path)).to_s
13
13
  relative_js_path = '/' + relative_path.gsub(/\.coffee$/, '.js')
14
14
 
15
15
  options = {sourceMap: true}
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vitrine
2
- VERSION = '0.0.11'
2
+ VERSION = '0.0.12'
3
3
  end
data/lib/vitrine.rb CHANGED
@@ -8,71 +8,6 @@ require_relative 'version'
8
8
  require_relative 'atomic_write'
9
9
  require_relative 'sourcemaps'
10
10
 
11
- module Vitrine
12
- DEFAULTS = { root: Dir.getwd, port: 4000, host: '127.0.0.1' }
13
-
14
- def self.check_dirs_present!
15
- views = DEFAULTS[:root] + '/views'
16
- unless File.exist?(views) and File.directory?(views)
17
- $stderr.puts "WARNING: `views' directory not found under the current tree, you might want to create it"
18
- end
19
-
20
- public_dir = DEFAULTS[:root] + '/public'
21
- unless File.exist?(public_dir) and File.directory?(public_dir)
22
- $stderr.puts "ERROR: `public' directory not found under the current tree, you should create it. Vitrine won't run without it"
23
- exit 1
24
- end
25
- end
26
-
27
- # Run the server, largely stolen from Serve
28
- def self.run(options = DEFAULTS)
29
- check_dirs_present!
30
-
31
- app = Rack::Builder.new do
32
- use Rack::ShowStatus
33
- use Rack::ShowExceptions
34
-
35
- guardfile_path = options[:root] + '/Guardfile'
36
- if File.exist?(guardfile_path)
37
- $stderr.puts "Attaching LiveReload via Guardfile at #{guardfile_path.inspect}"
38
- # Assume livereload is engaged
39
- use Rack::LiveReload
40
- else
41
- $stderr.puts "No Guardfile found, so there won't be any livereload injection"
42
- end
43
-
44
- vitrine = Vitrine::App.new
45
- vitrine.settings.set :root, options[:root]
46
- run vitrine
47
- end
48
-
49
- begin
50
- # Try Thin
51
- thin = Rack::Handler.get('thin')
52
- thin.run app, :Port => options[:port], :Host => options[:address] do |server|
53
- puts "Thin #{Thin::VERSION::STRING} available at http://#{options[:address]}:#{options[:port]}"
54
- end
55
- rescue LoadError
56
- begin
57
- # Then Mongrel
58
- mongrel = Rack::Handler.get('mongrel')
59
- mongrel.run app, :Port => options[:port], :Host => options[:address] do |server|
60
- puts "Mongrel #{Mongrel::Const::MONGREL_VERSION} available at http://#{options[:address]}:#{options[:port]}"
61
- end
62
- rescue LoadError
63
- # Then WEBrick
64
- puts "Install Mongrel or Thin for better performance."
65
- webrick = Rack::Handler.get('webrick')
66
- webrick.run app, :Port => options[:port], :Host => options[:address] do |server|
67
- trap("INT") { server.shutdown }
68
- end
69
- end
70
- end
71
- end
72
- end
73
-
74
- require 'rack-livereload'
75
-
76
11
  # A little idiosyncrastic asset server.
77
12
  # Does very simple things:
78
13
  # * sensible detector for default pages (they render from Sinatra view templates)
@@ -80,11 +15,13 @@ require 'rack-livereload'
80
15
  # and Vitrine will find them and compile them for you on the spot
81
16
  class Vitrine::App < Sinatra::Base
82
17
  set :static, true
18
+
83
19
  set :show_exceptions, false
84
20
  set :raise_errors, true
85
- set :root, File.expand_path(File.dirname(__FILE__))
86
- set :views, lambda { File.join(settings.root, "views") }
87
- set :public_dir, lambda { File.join(settings.root, "public") }
21
+
22
+ # Sets whether Vitrine will output messages about dynamic assets
23
+ set :silent, true
24
+ set :public_folder, ->{ File.join(settings.root, 'public') }
88
25
 
89
26
  # For extensionless things try to pick out the related templates
90
27
  # from the views directory, and render them with a default layout.
@@ -101,8 +38,11 @@ class Vitrine::App < Sinatra::Base
101
38
 
102
39
  def render_template_or_static(extensionless_path)
103
40
  probable_html = extensionless_path + "/index.html"
104
- html_path = File.join(settings.public_dir, probable_html)
41
+
42
+ html_path = File.join(settings.public_folder, probable_html)
105
43
  if File.exist? html_path
44
+ # Might want to investigate...
45
+ # https://github.com/elitheeli/sinatra-index/blob/master/lib/sinatra-index.rb
106
46
  send_file html_path
107
47
  else
108
48
  render_template(extensionless_path)
@@ -129,15 +69,19 @@ class Vitrine::App < Sinatra::Base
129
69
  # Try the first template that has been found
130
70
  template_path = possibilites.shift
131
71
 
132
- # If nothing is found just bail
72
+ # If nothing is found try downstream or bail
133
73
  unless template_path
134
74
  err = possible_globs.map{|e| e.inspect }.join(', ')
135
- halt 404, "No template found - tried #{err}"
75
+ if @app
76
+ return forward
77
+ else
78
+ halt 404, "No template found - tried #{err}, and no downstream Rack handler present"
79
+ end
136
80
  end
137
81
 
138
82
  relative_path = Pathname.new(template_path).relative_path_from(Pathname.new(settings.views))
139
83
 
140
- # $stderr.puts "-> #{extensionless_path.inspect} : Rendering via template #{relative_path.to_s.inspect}"
84
+ log "-> #{extensionless_path.inspect} : Rendering via template #{relative_path.to_s.inspect}"
141
85
 
142
86
  locals = {}
143
87
  # Auto-pick the template engine out of the extension
@@ -153,6 +97,7 @@ class Vitrine::App < Sinatra::Base
153
97
  # TODO: has no handling for .sass
154
98
  scss_source_path = File.join(settings.root, 'public', "#{basename}.scss")
155
99
  mtime_cache(scss_source_path) do
100
+ # TODO: Examine http://sass-lang.com/documentation/file.SASS_REFERENCE.html
156
101
  Sass.compile_file(scss_source_path, cache_location: '/tmp/vitrine/sass-cache')
157
102
  end
158
103
  rescue Errno::ENOENT # Missing SCSS
@@ -218,7 +163,7 @@ class Vitrine::App < Sinatra::Base
218
163
  else
219
164
  yield.tap do | body |
220
165
  Vitrine.atomic_write(p) do |f|
221
- # $stderr.puts "---> Recompiling #{path} for #{request.path_info}"
166
+ log "---> Recompiling #{path} for #{request.path_info}"
222
167
  f.write body
223
168
  end
224
169
  etag File.mtime(p)
@@ -231,4 +176,7 @@ class Vitrine::App < Sinatra::Base
231
176
  layouts.any? ? :layout : false
232
177
  end
233
178
 
179
+ def log(msg)
180
+ $stderr.puts(msg) unless settings.silent?
181
+ end
234
182
  end
data/test/helper.rb CHANGED
@@ -9,3 +9,34 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
9
  $LOAD_PATH.unshift(File.dirname(__FILE__))
10
10
 
11
11
  require 'vitrine'
12
+
13
+ module VitrineTesting
14
+
15
+ # Wrap the test run in mktimpdir where we will store our temp application
16
+ def run(runner)
17
+ Dir.mktmpdir("vitrine-tests") do | dir_path |
18
+ @tempdir = dir_path
19
+ super
20
+ end
21
+ ensure
22
+ @tempdir = nil
23
+ end
24
+
25
+ def temporary_app_dir
26
+ raise "Not within a tempdir block" unless @tempdir
27
+ @tempdir
28
+ end
29
+
30
+ # Write a file out into 'public', creating the subdir tree
31
+ def write_public(name)
32
+ location = FileUtils.mkdir_p(File.dirname(File.join(@tempdir, 'public', name)))
33
+ File.open(File.join(@tempdir, 'public', name), 'w') do | f |
34
+ yield f
35
+ end
36
+ end
37
+
38
+ # Return the vitrine default Vitrine app
39
+ def app
40
+ Vitrine::App.new.tap { |a| a.settings.set :root, @tempdir }
41
+ end
42
+ end
data/test/test_vitrine.rb CHANGED
@@ -1,28 +1,7 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestVitrine < Test::Unit::TestCase
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
4
+ include Rack::Test::Methods, VitrineTesting
26
5
 
27
6
  def test_fetch_index_without_index_should_404
28
7
  get '/'
@@ -72,15 +51,15 @@ class TestVitrine < Test::Unit::TestCase
72
51
  assert last_response.ok?, "Should have fetched the index.html"
73
52
  end
74
53
 
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
54
+ def test_fetches_index_in_subdirectory_if_present
55
+ write_public 'items/index.html' do | f |
56
+ f.write 'this just in'
57
+ end
58
+
59
+ get '/items'
60
+ assert last_response.ok?, "Should have responded with 404 since there is no template"
61
+ assert_equal 'this just in', last_response.body
62
+ end
84
63
 
85
64
  def test_passes_coffeescript_as_raw_file
86
65
  write_public 'nice.coffee' do | f |
@@ -108,6 +87,24 @@ class TestVitrine < Test::Unit::TestCase
108
87
  'Should include the reference to the source map'
109
88
  end
110
89
 
90
+ def test_compiles_coffeescript_sourcemap
91
+
92
+ FileUtils.mkdir_p File.join(@tempdir, 'public', 'js')
93
+
94
+ write_public 'js/nice.coffee' do | f |
95
+ f.puts 'alert "rockage!"'
96
+ end
97
+
98
+ # Sourcemap will only ever get requested AFTER the corresponding JS file
99
+ get '/js/nice.js'
100
+ assert last_response.ok?
101
+
102
+ get '/js/nice.js.map'
103
+ ref = {"version"=>3, "file"=>"", "sourceRoot"=>"", "sources"=>["/js/nice.coffee"],
104
+ "names"=>[], "mappings"=>"AAAA;CAAA,CAAA,GAAA,KAAA;CAAA"}
105
+ assert_equal ref, JSON.parse(last_response.body)
106
+ end
107
+
111
108
  def test_sends_vanilla_js_if_its_present
112
109
  write_public 'vanilla.js' do | f |
113
110
  f.puts 'vanilla();'
@@ -0,0 +1,35 @@
1
+ require 'helper'
2
+ require 'rack/lobster'
3
+
4
+ class TestVitrineInRackStack < Test::Unit::TestCase
5
+ include Rack::Test::Methods, VitrineTesting
6
+
7
+ def app
8
+ td = temporary_app_dir
9
+ outer = Rack::Builder.new do
10
+ use Vitrine::App do | v |
11
+ v.settings.set root: td
12
+ end
13
+ map "/lobster" do
14
+ run Rack::Lobster.new
15
+ end
16
+ end
17
+ outer.to_app
18
+ end
19
+
20
+ def test_lobster
21
+ get '/lobster'
22
+ assert last_response.ok?
23
+ assert_match /Lobstericious/, last_response.body, "Should have forwarded to downstream Lobster"
24
+ end
25
+
26
+ def test_fetch_js
27
+ write_public('hello.coffee') do | f |
28
+ f << 'window.alert("Hello Coffee")'
29
+ end
30
+
31
+ get '/hello.js'
32
+ assert last_response.ok?
33
+ assert_include last_response.body, 'window.alert("Hello Coffee")', "Should include the JS fragment"
34
+ end
35
+ end
data/vitrine.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "vitrine"
8
- s.version = "0.0.11"
8
+ s.version = "0.0.12"
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-25"
12
+ s.date = "2013-12-19"
13
13
  s.description = " Serves ERB templates with live CoffeeScript and SASS "
14
14
  s.email = "me@julik.nl"
15
15
  s.executables = ["vitrine"]
@@ -26,11 +26,13 @@ Gem::Specification.new do |s|
26
26
  "Rakefile",
27
27
  "bin/vitrine",
28
28
  "lib/atomic_write.rb",
29
+ "lib/server.rb",
29
30
  "lib/sourcemaps.rb",
30
31
  "lib/version.rb",
31
32
  "lib/vitrine.rb",
32
33
  "test/helper.rb",
33
34
  "test/test_vitrine.rb",
35
+ "test/test_vitrine_in_rack_stack.rb",
34
36
  "vitrine.gemspec"
35
37
  ]
36
38
  s.homepage = "http://github.com/julik/vitrine"
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.11
4
+ version: 0.0.12
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-25 00:00:00.000000000 Z
11
+ date: 2013-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -223,11 +223,13 @@ files:
223
223
  - Rakefile
224
224
  - bin/vitrine
225
225
  - lib/atomic_write.rb
226
+ - lib/server.rb
226
227
  - lib/sourcemaps.rb
227
228
  - lib/version.rb
228
229
  - lib/vitrine.rb
229
230
  - test/helper.rb
230
231
  - test/test_vitrine.rb
232
+ - test/test_vitrine_in_rack_stack.rb
231
233
  - vitrine.gemspec
232
234
  homepage: http://github.com/julik/vitrine
233
235
  licenses: