Created
October 4, 2016 16:48
-
-
Save elia/4582426a573a0e5448c9dd7ab4deb310 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'opal/deprecations' | |
# Opal::SimpleServer is a very basic Rack server for Opal assets, it relies on | |
# Opal::Builder and Ruby corelib/stdlib. It's meant to be used just for local | |
# development. | |
# | |
# For a more complete implementation see opal-sprockets (Rubygems) or | |
# opal-webpack (NPM). | |
# | |
# @example (CLI) | |
# rackup -ropal -ropal/simple_server -b 'Opal.append_path("app"); run Opal::SimpleServer.new' | |
class Opal::SimpleServer | |
require 'set' | |
require 'erb' | |
# @param cache [#[](key), #[]=(key, value)] | |
# The cache will be used to store | |
def initialize(options = {}) | |
@cache = {} | |
@debug = options.fetch(:debug, true) | |
@prefix = options.fetch(:prefix, 'assets') | |
@main = options.fetch(:main, 'application') | |
yield self if block_given? | |
freeze | |
end | |
attr_accessor :main, :index_path | |
# @deprecated | |
# It's here for compatibility with Opal::Sprockets::Server | |
def append_path(path) | |
Opal.deprecation 'Please use `Opal.append_path(path)` instead.' | |
Opal.append_path path | |
end | |
def call(env) | |
case env['PATH_INFO'] | |
when %r{\A/#{@prefix}/(.*)\.map\z} | |
path, cache_invalidator = $1.split('?', 2) | |
call_map(path) | |
when %r{\A/#{@prefix}/(.*)\z} | |
path, cache_invalidator = $1.split('?', 2) | |
call_asset(path) | |
else call_index | |
end | |
end | |
def call_asset(path) | |
asset = fetch_asset(path) | |
[ | |
200, | |
{ 'Content-Type' => 'application/javascript', | |
'X-SourceMap' => "/#{@prefix}/#{path}.map#{cache_invalidator}}" }, | |
[asset[:data]] | |
] | |
end | |
def call_map(path) | |
asset = fetch_asset(path) | |
[ | |
200, | |
{ 'Content-Type' => 'application/json' }, | |
[asset[:map]] | |
] | |
end | |
def fetch_asset(path) | |
builder = Opal::Builder.new | |
builder.build(path.gsub(/(\.(?:rb|js|opal))*\z/, '')) | |
{ | |
data: builder.to_s, | |
map: builder.source_map.to_json | |
} | |
end | |
def javascript_include_tag(path) | |
%{<script src="/#{@prefix}/#{path}.js#{cache_invalidator}"></script>} | |
end | |
def cache_invalidator | |
"?#{Time.now.to_i}" if @debug | |
end | |
def call_index | |
if @index_path | |
contents = File.read(@index_path) | |
html = ERB.new(contents).result binding | |
else | |
html = <<-HTML | |
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf8"> | |
#{javascript_include_tag(main)} | |
</head> | |
<body></body> | |
</html> | |
HTML | |
end | |
[200, {'Content-Type' => 'text/html'}, [html]] | |
end | |
def fetch_cache(key) | |
unless (data = @cache[key]) | |
data = yield | |
@cache[key] = data | |
end | |
data | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment