lib/opal/sprockets/server.rb



require 'erb'
require 'rack'
require 'sprockets'

class Opal::Sprockets::Server
  attr_accessor :debug, :use_index, :index_path, :main, :public_root,
                :public_urls, :sprockets, :prefix

  def initialize options = {}
    @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::Config.source_map_enabled = enabled
  end

  def source_map_enabled
    Opal::Config.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

    @app = Rack::Builder.app do
      not_found = lambda { |env| [404, {}, []] }
      use Rack::Deflater
      use Rack::ShowExceptions
      use Index, server if server.use_index
      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
        raise "Main asset path not configured (set 'main' within Opal::Server.new block)" if @server.main.nil?
        source
      end
    end

    def javascript_include_tag name
      sprockets = @server.sprockets
      prefix = @server.prefix
      debug = @server.debug

      ::Opal::Sprockets.javascript_include_tag(name, sprockets: sprockets, prefix: prefix, debug: debug)
    end

    def source
      <<-HTML
        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="utf-8">
          <title>Opal Server</title>
        </head>
        <body>
          #{javascript_include_tag @server.main}
        </body>
        </html>
      HTML
    end
  end
end