lib/opal/sprockets/server.rb
require 'rack/file' require 'rack/static' require 'rack/urlmap' require 'rack/builder' require 'rack/deflater' require 'rack/directory' require 'rack/showexceptions' require 'opal/source_map' require 'sprockets' require 'sourcemap' require 'erb' require 'opal/sprockets/source_map_server' require 'opal/sprockets/source_map_header_patch' module Opal class Server SOURCE_MAPS_PREFIX_PATH = '/__OPAL_SOURCE_MAPS__' attr_accessor :debug, :use_index, :index_path, :main, :public_root, :public_urls, :sprockets, :prefix def initialize debug_or_options = {} unless Hash === debug_or_options warn "passing a boolean to control debug is deprecated.\n"+ "Please pass an Hash instead: Server.new(debug: true)" options = {:debug => debug_or_options} else options = debug_or_options end @use_index = true @public_root = nil @public_urls = ['/'] @sprockets = options.fetch(:sprockets, ::Sprockets::Environment.new) @debug = options.fetch(:debug, true) @prefix = options.fetch(:prefix, '/assets') Opal.paths.each { |p| @sprockets.append_path(p) } yield self if block_given? create_app end def public_dir=(dir) @public_root = dir @public_urls = ["/"] end def source_map=(enabled) Opal::Processor.source_map_enabled = enabled end def source_map_enabled Opal::Processor.source_map_enabled end def append_path path @sprockets.append_path path end def use_gem gem_name @sprockets.use_gem gem_name end def create_app server, sprockets, prefix = self, @sprockets, self.prefix sprockets.logger.level ||= Logger::DEBUG source_map_enabled = self.source_map_enabled if source_map_enabled maps_prefix = SOURCE_MAPS_PREFIX_PATH maps_app = SourceMapServer.new(sprockets, maps_prefix) ::Opal::Sprockets::SourceMapHeaderPatch.inject!(maps_prefix) end @app = Rack::Builder.app do not_found = lambda { |env| [404, {}, []] } use Rack::Deflater use Rack::ShowExceptions use Index, server if server.use_index if source_map_enabled map(maps_prefix) do require 'rack/conditionalget' require 'rack/etag' use Rack::ConditionalGet use Rack::ETag run maps_app end end map(prefix) { run sprockets } run Rack::Static.new(not_found, root: server.public_root, urls: server.public_urls) end end def call(env) @app.call env end class Index def initialize(app, server) @app = app @server = server @index_path = server.index_path end def call(env) if %w[/ /index.html].include? env['PATH_INFO'] [200, { 'Content-Type' => 'text/html' }, [html]] else @app.call env end end # Returns the html content for the root path. Supports ERB def html if @index_path raise "index does not exist: #{@index_path}" unless File.exist?(@index_path) Tilt.new(@index_path).render(self) else source end end def javascript_include_tag name sprockets = @server.sprockets prefix = @server.prefix asset = sprockets[name] raise "Cannot find asset: #{name}" if asset.nil? scripts = [] if @server.debug asset.to_a.map do |dependency| scripts << %{<script src="#{prefix}/#{dependency.logical_path}?body=1"></script>} end else scripts << %{<script src="#{prefix}/#{name}.js"></script>} end scripts << %{<script>#{Opal::Processor.load_asset_code(sprockets, name)}</script>} scripts.join "\n" end def source <<-HTML <!DOCTYPE html> <html> <head> <title>Opal Server</title> </head> <body> #{javascript_include_tag @server.main} </body> </html> HTML end end end end