lib/vitrine.rb in vitrine-0.0.7 vs lib/vitrine.rb in vitrine-0.0.9
- old
+ new
@@ -1,14 +1,18 @@
require 'sinatra/base'
require 'coffee-script'
+#require 'coffee-script-source'
require 'sass'
require 'pathname'
require_relative 'version'
+require_relative 'atomic_write'
+require_relative 'sourcemaps'
module Vitrine
DEFAULTS = { root: Dir.getwd, port: 4000, host: '127.0.0.1' }
+ SEED = rand
def self.check_dirs_present!
views = DEFAULTS[:root] + '/views'
unless File.exist?(views) and File.directory?(views)
$stderr.puts "WARNING: `views' directory not found under the current tree, you might want to create it"
@@ -131,41 +135,84 @@
locals = {}
# Auto-pick the template engine out of the extension
template_engine = File.extname(template_path).gsub(/^\./, '')
render(template_engine, File.read(template_path), :layout => get_layout, :locals => locals)
end
+
- def get_layout
- layouts = Dir.glob(File.join(settings.views, 'layout.*'))
- layouts.any? ? :layout : false
- end
-
# Try to find SCSS replacement for missing CSS
get /(.+)\.css/ do | basename |
begin
content_type 'text/css', :charset => 'utf-8'
+ # TODO: has no handling for .sass
scss_source_path = File.join(settings.root, 'public', "#{basename}.scss")
- Sass.compile_file(scss_source_path)
+ mtime_cache(scss_source_path) { Sass.compile_file(scss_source_path) }
rescue Errno::ENOENT # Missing SCSS
halt 404, "No such CSS or SCSS file found"
rescue Exception => e # CSS syntax error or something alike
# use smart CSS to inject an error message into the document
'body:before { color: red; font-size: 2em; content: %s }' % [e.class,
"\n", "--> ", e.message].join.inspect
end
end
+ # Generate a sourcemap for CoffeeScript files
+ get /(.+)\.js\.map$/ do | basename |
+ begin
+ coffee_source = File.join(settings.root, 'public', "#{basename}.coffee")
+ content_type 'application/json', :charset => 'utf-8'
+ mtime_cache(coffee_source) do
+ Vitrine.build_coffeescript_source_map_body(coffee_source, File.join(settings.root, 'public'))
+ end
+ rescue Errno::ENOENT # Missing CoffeeScript
+ halt 404, "No coffeescript file found to generate the map for"
+ rescue Exception => e # CS syntax error or something alike
+ # inject it into the document
+ 'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect
+ end
+ end
+
# Try to find CoffeeScript replacement for missing JS
- get /(.+)\.js/ do | basename |
+ get /(.+)\.js$/ do | basename |
# If this file is not found resort back to a coffeescript
begin
- coffee_source = File.read(File.join(settings.root, 'public', "#{basename}.coffee"))
+ coffee_source = File.join(settings.root, 'public', "#{basename}.coffee")
content_type 'text/javascript', :charset => 'utf-8'
- CoffeeScript.compile(coffee_source)
+ mtime_cache(coffee_source) do
+ ["//# sourceMappingURL=#{basename}.js.map", CoffeeScript.compile(File.read(coffee_source))].join("\n")
+ end
rescue Errno::ENOENT # Missing CoffeeScript
halt 404, "No such JS file and could not find a .coffee replacement"
rescue Exception => e # CS syntax error or something alike
# inject it into the document
'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect
end
- end
+ end
+
+
+ def mtime_cache(path, &blk)
+ # Mix in the request URL into the cache key so that we can hash
+ # .map sourcemaps and .js compiles based off of the same file path
+ # and mtime
+
+ key = [File.expand_path(path), File.mtime(path), request.path_info, Vitrine::SEED]
+ cache_sha = Digest::SHA1.hexdigest(Marshal.dump(key))
+
+ p = File.join('/tmp', cache_sha)
+ if File.exist?(p)
+ return File.read(p)
+ else
+ Vitrine.atomic_write(p) do |f|
+ $stderr.puts "---> Recompiling #{path}"
+ body = yield
+ f.write(body)
+ return body
+ end
+ end
+ end
+
+ def get_layout
+ layouts = Dir.glob(File.join(settings.views, 'layout.*'))
+ layouts.any? ? :layout : false
+ end
+
end
\ No newline at end of file