lib/vitrine.rb in vitrine-0.0.13 vs lib/vitrine.rb in vitrine-0.0.14

- old
+ new

@@ -1,30 +1,33 @@ require 'sinatra/base' require 'coffee-script' require 'rack/contrib/try_static' require 'sass' require 'pathname' +require 'fileutils' require_relative 'version' require_relative 'atomic_write' require_relative 'sourcemaps' +require_relative 'asset_compiler' # A little idiosyncrastic asset server. # Does very simple things: # * sensible detector for default pages (they render from Sinatra view templates) # * automatic compilation of CoffeeScript and SASS assets - just request them with .js and .css # and Vitrine will find them and compile them for you on the spot class Vitrine::App < Sinatra::Base - set :static, true set :show_exceptions, false set :raise_errors, true # Sets whether Vitrine will output messages about dynamic assets set :silent, true - set :public_folder, ->{ File.join(settings.root, 'public') } + set :public_folder, ->{ File.join(settings.root, 'public') } + use Vitrine::AssetCompiler + # For extensionless things try to pick out the related templates # from the views directory, and render them with a default layout. # If no template is found fallback to halting on 404 # so that Vitrine can be cascaded from. get /^([^\.]+)$/ do | extensionless_path | @@ -86,91 +89,11 @@ 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 - - # 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") - mtime_cache(scss_source_path) do - # TODO: Examine http://sass-lang.com/documentation/file.SASS_REFERENCE.html - Sass.compile_file(scss_source_path, cache_location: '/tmp/vitrine/sass-cache') - end - rescue Errno::ENOENT # Missing SCSS - halt 404, "No such CSS or SCSS file found" - rescue Exception => e # CSS syntax error or something alike - # Add a generated DOM element before <body/> to inject - # a visible error message - error_tpl = 'body:before { background: white; font-family: sans-serif; color: red; font-size: 14px; content: %s }' - css_message = error_tpl % [e.class, "\n", "--> ", e.message].join.inspect - # If we halt with 500 this will not be shown as CSS - halt 200, css_message - 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 - halt 400, 'Compliation of the related CoffeeScript file failed' - end - end - - # Try to find CoffeeScript replacement for missing JS - get /(.+)\.js$/ do | basename | - # If this file is not found resort back to a coffeescript - begin - coffee_source = File.join(settings.root, 'public', "#{basename}.coffee") - content_type 'text/javascript' - 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 the syntax error into the browser console - console_message = 'console.error(%s)' % [e.class, "\n", "--> ", e.message].join.inspect - halt 500, console_message - end - end - - require 'fileutils' - - 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, settings.root] - cache_sha = Digest::SHA1.hexdigest(Marshal.dump(key)) - - # Store in a temp dir - FileUtils.mkdir_p '/tmp/vitrine' - p = '/tmp/vitrine/%s' % cache_sha - if File.exist?(p) - etag File.mtime(p) - File.read(p) - else - yield.tap do | body | - Vitrine.atomic_write(p) do |f| - log "---> Recompiling #{path} for #{request.path_info}" - f.write body - end - etag File.mtime(p) - end - end - end def get_layout layouts = Dir.glob(File.join(settings.views, 'layout.*')) layouts.any? ? :layout : false end \ No newline at end of file