opal-sprockets 0.4.0.0.10.0.3.0.0 → 0.4.0.0.11.dev.3.1.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +7 -0
- data/lib/opal/sprockets/environment.rb +23 -0
- data/lib/opal/sprockets/erb.rb +29 -0
- data/lib/opal/sprockets/path_reader.rb +36 -0
- data/lib/opal/sprockets/processor.rb +151 -0
- data/lib/opal/sprockets/server.rb +135 -0
- data/lib/opal/sprockets/source_map_header_patch.rb +41 -0
- data/lib/opal/sprockets/source_map_server.rb +115 -0
- data/lib/opal/sprockets/version.rb +3 -3
- data/lib/opal/sprockets.rb +92 -0
- data/lib/opal-sprockets.rb +0 -4
- data/opal-sprockets.gemspec +4 -4
- metadata +19 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32661426be37d64787c573dce2cc35f816489310
|
4
|
+
data.tar.gz: de0cef69723ae23293fc0b79f812e62cd703ad7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2094ff150dbb679d7734cf4df0ee5e10e725cb9eecd64e3d24f66b29fabfe257fa5d6006ff4b1fda306ad43a224f05490b3bba39d5e58dff7256be8fde1f600
|
7
|
+
data.tar.gz: af5c8dab0703e5a7f1ebebaa3f4e80b4f09e80c0f7112f62ba744874f4bca1c3adfb147aa0e592dccdb10363d6aae1889ca7b24a8b79e46d5b2dd6b16917f307
|
data/Gemfile
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
3
|
|
4
|
+
opal_path = File.expand_path('../opal')
|
5
|
+
if File.exist? opal_path
|
6
|
+
gem 'opal', path: opal_path
|
7
|
+
else
|
8
|
+
gem 'opal', github: 'opal/opal'
|
9
|
+
end
|
10
|
+
|
4
11
|
rack_version = ENV['RACK_VERSION']
|
5
12
|
sprockets_version = ENV['SPROCKETS_VERSION']
|
6
13
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require 'opal/sprockets/processor'
|
3
|
+
require 'opal/sprockets/erb'
|
4
|
+
|
5
|
+
module Opal
|
6
|
+
class Environment < ::Sprockets::Environment
|
7
|
+
def initialize *args
|
8
|
+
super
|
9
|
+
append_opal_paths
|
10
|
+
end
|
11
|
+
|
12
|
+
def use_gem gem_name
|
13
|
+
Opal.use_gem gem_name
|
14
|
+
append_opal_paths
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def append_opal_paths
|
20
|
+
Opal.paths.each { |p| append_path p }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'sprockets'
|
3
|
+
require 'opal/sprockets/processor'
|
4
|
+
|
5
|
+
module Opal
|
6
|
+
module ERB
|
7
|
+
class Processor < ::Opal::Processor
|
8
|
+
def initialize_engine
|
9
|
+
super
|
10
|
+
require_template_library 'opal/erb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate(context, locals, &block)
|
14
|
+
compiler = Opal::ERB::Compiler.new(@data, context.logical_path.sub(/#{REGEXP_START}templates\//, ''))
|
15
|
+
@data = compiler.prepared_source
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if Sprockets.respond_to? :register_transformer
|
23
|
+
extra_args = [{mime_type: 'application/javascript', silence_deprecation: true}]
|
24
|
+
else
|
25
|
+
extra_args = []
|
26
|
+
end
|
27
|
+
|
28
|
+
Tilt.register 'opalerb', Opal::ERB::Processor
|
29
|
+
Sprockets.register_engine '.opalerb', Opal::ERB::Processor, *extra_args
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Opal
|
2
|
+
module Sprockets
|
3
|
+
|
4
|
+
class PathReader
|
5
|
+
def initialize(env, context)
|
6
|
+
@env ||= env
|
7
|
+
@context ||= context
|
8
|
+
end
|
9
|
+
|
10
|
+
def read path
|
11
|
+
if path.end_with? '.js'
|
12
|
+
context.depend_on_asset(path)
|
13
|
+
env[path, bundle: true].to_s
|
14
|
+
else
|
15
|
+
context.depend_on(path)
|
16
|
+
File.open(expand(path), 'rb:UTF-8'){|f| f.read}
|
17
|
+
end
|
18
|
+
rescue ::Sprockets::FileNotFound
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def expand path
|
23
|
+
env.resolve(path) or
|
24
|
+
# Sprockets 3 just returns nil for unknown paths
|
25
|
+
raise ::Sprockets::FileNotFound, path.inspect
|
26
|
+
end
|
27
|
+
|
28
|
+
def paths
|
29
|
+
env.paths
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :env, :context
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'tilt/opal'
|
3
|
+
require 'sprockets'
|
4
|
+
require 'opal/builder'
|
5
|
+
require 'opal/sprockets/path_reader'
|
6
|
+
require 'opal/sprockets/source_map_server'
|
7
|
+
|
8
|
+
$OPAL_SOURCE_MAPS = {}
|
9
|
+
|
10
|
+
module Opal
|
11
|
+
# Internal: The Processor class is used to make ruby files (with .rb or .opal
|
12
|
+
# extensions) available to any sprockets based server. Processor will then
|
13
|
+
# get passed any ruby source file to build.
|
14
|
+
class Processor < TiltTemplate
|
15
|
+
@@cache_key = nil
|
16
|
+
def self.cache_key
|
17
|
+
@@cache_key ||= ['Opal', Opal::VERSION, Opal::Config.config].to_json.freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reset_cache_key!
|
21
|
+
@@cache_key = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def evaluate(context, locals, &block)
|
25
|
+
return super unless context.is_a? ::Sprockets::Context
|
26
|
+
|
27
|
+
@sprockets = sprockets = context.environment
|
28
|
+
|
29
|
+
# In Sprockets 3 logical_path has an odd behavior when the filename is "index"
|
30
|
+
# thus we need to bake our own logical_path
|
31
|
+
filename = context.respond_to?(:filename) ? context.filename : context.pathname.to_s
|
32
|
+
root_path_regexp = Regexp.escape(context.root_path)
|
33
|
+
logical_path = filename.gsub(%r{^#{root_path_regexp}/?(.*?)#{sprockets_extnames_regexp}}, '\1')
|
34
|
+
|
35
|
+
compiler_options = self.compiler_options.merge(file: logical_path)
|
36
|
+
|
37
|
+
# Opal will be loaded immediately to as the runtime redefines some crucial
|
38
|
+
# methods such that need to be implemented as soon as possible:
|
39
|
+
#
|
40
|
+
# E.g. It forwards .toString() to .$to_s() for Opal objects including Array.
|
41
|
+
# If .$to_s() is not implemented and some other lib is loaded before
|
42
|
+
# corelib/* .toString results in an `undefined is not a function` error.
|
43
|
+
compiler_options.merge!(requirable: false) if logical_path == 'opal'
|
44
|
+
|
45
|
+
compiler = Compiler.new(data, compiler_options)
|
46
|
+
result = compiler.compile
|
47
|
+
|
48
|
+
process_requires(compiler.requires, context)
|
49
|
+
process_required_trees(compiler.required_trees, context)
|
50
|
+
|
51
|
+
if Opal::Config.source_map_enabled
|
52
|
+
map_contents = compiler.source_map.as_json.to_json
|
53
|
+
::Opal::SourceMapServer.set_map_cache(sprockets, logical_path, map_contents)
|
54
|
+
end
|
55
|
+
|
56
|
+
result.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.sprockets_extnames_regexp(sprockets)
|
60
|
+
joined_extnames = (['.js']+sprockets.engines.keys).map { |ext| Regexp.escape(ext) }.join('|')
|
61
|
+
Regexp.new("(#{joined_extnames})*$")
|
62
|
+
end
|
63
|
+
|
64
|
+
def sprockets_extnames_regexp
|
65
|
+
@sprockets_extnames_regexp ||= self.class.sprockets_extnames_regexp(@sprockets)
|
66
|
+
end
|
67
|
+
|
68
|
+
def process_requires(requires, context)
|
69
|
+
requires.each do |required|
|
70
|
+
required = required.to_s.sub(sprockets_extnames_regexp, '')
|
71
|
+
context.require_asset required unless ::Opal::Config.stubbed_files.include? required
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Internal: Add files required with `require_tree` as asset dependencies.
|
76
|
+
#
|
77
|
+
# Mimics (v2) Sprockets::DirectiveProcessor#process_require_tree_directive
|
78
|
+
def process_required_trees(required_trees, context)
|
79
|
+
return if required_trees.empty?
|
80
|
+
|
81
|
+
# This is the root dir of the logical path, we need this because
|
82
|
+
# the compiler gives us the path relative to the file's logical path.
|
83
|
+
dirname = File.dirname(file).gsub(/#{Regexp.escape File.dirname(context.logical_path)}#{REGEXP_END}/, '')
|
84
|
+
dirname = Pathname(dirname)
|
85
|
+
|
86
|
+
required_trees.each do |original_required_tree|
|
87
|
+
required_tree = Pathname(original_required_tree)
|
88
|
+
|
89
|
+
unless required_tree.relative?
|
90
|
+
raise ArgumentError, "require_tree argument must be a relative path: #{required_tree.inspect}"
|
91
|
+
end
|
92
|
+
|
93
|
+
required_tree = dirname.join(file, '..', required_tree)
|
94
|
+
|
95
|
+
unless required_tree.directory?
|
96
|
+
raise ArgumentError, "require_tree argument must be a directory: #{{source: original_required_tree, pathname: required_tree}.inspect}"
|
97
|
+
end
|
98
|
+
|
99
|
+
context.depend_on required_tree.to_s
|
100
|
+
|
101
|
+
environment = context.environment
|
102
|
+
|
103
|
+
processor = ::Sprockets::DirectiveProcessor.new
|
104
|
+
processor.instance_variable_set('@dirname', File.dirname(file))
|
105
|
+
processor.instance_variable_set('@environment', environment)
|
106
|
+
path = processor.__send__(:expand_relative_dirname, :require_tree, original_required_tree)
|
107
|
+
absolute_paths = environment.__send__(:stat_sorted_tree_with_dependencies, path).first.map(&:first)
|
108
|
+
|
109
|
+
absolute_paths.each do |path|
|
110
|
+
path = Pathname(path)
|
111
|
+
pathname = path.relative_path_from(dirname).to_s
|
112
|
+
|
113
|
+
if name.to_s == file then next
|
114
|
+
elsif path.directory? then context.depend_on(path.to_s)
|
115
|
+
else context.require_asset(pathname)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @deprecated
|
122
|
+
def self.stubbed_files
|
123
|
+
warn "Deprecated: `::Opal::Processor.stubbed_files' is deprecated, use `::Opal::Config.stubbed_files' instead"
|
124
|
+
puts caller(5)
|
125
|
+
::Opal::Config.stubbed_files
|
126
|
+
end
|
127
|
+
|
128
|
+
# @deprecated
|
129
|
+
def self.stub_file(name)
|
130
|
+
warn "Deprecated: `::Opal::Processor.stub_file' is deprecated, use `::Opal::Config.stubbed_files << #{name.inspect}.to_s' instead"
|
131
|
+
puts caller(5)
|
132
|
+
::Opal::Config.stubbed_files << name.to_s
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def stubbed_files
|
139
|
+
::Opal::Config.stubbed_files
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
if Sprockets.respond_to? :register_transformer
|
145
|
+
extra_args = [{mime_type: 'application/javascript', silence_deprecation: true}]
|
146
|
+
else
|
147
|
+
extra_args = []
|
148
|
+
end
|
149
|
+
|
150
|
+
Sprockets.register_engine '.rb', Opal::Processor, *extra_args
|
151
|
+
Sprockets.register_engine '.opal', Opal::Processor, *extra_args
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'opal/source_map'
|
3
|
+
require 'sprockets'
|
4
|
+
require 'sourcemap'
|
5
|
+
require 'erb'
|
6
|
+
require 'opal/sprockets/source_map_server'
|
7
|
+
require 'opal/sprockets/source_map_header_patch'
|
8
|
+
|
9
|
+
module Opal
|
10
|
+
module Sprockets
|
11
|
+
class Server
|
12
|
+
SOURCE_MAPS_PREFIX_PATH = '/__OPAL_SOURCE_MAPS__'
|
13
|
+
|
14
|
+
attr_accessor :debug, :use_index, :index_path, :main, :public_root,
|
15
|
+
:public_urls, :sprockets, :prefix
|
16
|
+
|
17
|
+
def initialize options = {}
|
18
|
+
@use_index = true
|
19
|
+
@public_root = nil
|
20
|
+
@public_urls = ['/']
|
21
|
+
@sprockets = options.fetch(:sprockets, ::Sprockets::Environment.new)
|
22
|
+
@debug = options.fetch(:debug, true)
|
23
|
+
@prefix = options.fetch(:prefix, '/assets')
|
24
|
+
|
25
|
+
Opal.paths.each { |p| @sprockets.append_path(p) }
|
26
|
+
|
27
|
+
yield self if block_given?
|
28
|
+
create_app
|
29
|
+
end
|
30
|
+
|
31
|
+
def public_dir=(dir)
|
32
|
+
@public_root = dir
|
33
|
+
@public_urls = ["/"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def source_map=(enabled)
|
37
|
+
Opal::Config.source_map_enabled = enabled
|
38
|
+
end
|
39
|
+
|
40
|
+
def source_map_enabled
|
41
|
+
Opal::Config.source_map_enabled
|
42
|
+
end
|
43
|
+
|
44
|
+
def append_path path
|
45
|
+
@sprockets.append_path path
|
46
|
+
end
|
47
|
+
|
48
|
+
def use_gem gem_name
|
49
|
+
@sprockets.use_gem gem_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_app
|
53
|
+
server, sprockets, prefix = self, @sprockets, self.prefix
|
54
|
+
sprockets.logger.level ||= Logger::DEBUG
|
55
|
+
source_map_enabled = self.source_map_enabled
|
56
|
+
if source_map_enabled
|
57
|
+
maps_prefix = SOURCE_MAPS_PREFIX_PATH
|
58
|
+
maps_app = SourceMapServer.new(sprockets, maps_prefix)
|
59
|
+
::Opal::Sprockets::SourceMapHeaderPatch.inject!(maps_prefix)
|
60
|
+
end
|
61
|
+
|
62
|
+
@app = Rack::Builder.app do
|
63
|
+
not_found = lambda { |env| [404, {}, []] }
|
64
|
+
use Rack::Deflater
|
65
|
+
use Rack::ShowExceptions
|
66
|
+
use Index, server if server.use_index
|
67
|
+
if source_map_enabled
|
68
|
+
map(maps_prefix) do
|
69
|
+
use Rack::ConditionalGet
|
70
|
+
use Rack::ETag
|
71
|
+
run maps_app
|
72
|
+
end
|
73
|
+
end
|
74
|
+
map(prefix) { run sprockets }
|
75
|
+
run Rack::Static.new(not_found, root: server.public_root, urls: server.public_urls)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def call(env)
|
80
|
+
@app.call env
|
81
|
+
end
|
82
|
+
|
83
|
+
class Index
|
84
|
+
|
85
|
+
def initialize(app, server)
|
86
|
+
@app = app
|
87
|
+
@server = server
|
88
|
+
@index_path = server.index_path
|
89
|
+
end
|
90
|
+
|
91
|
+
def call(env)
|
92
|
+
if %w[/ /index.html].include? env['PATH_INFO']
|
93
|
+
[200, { 'Content-Type' => 'text/html' }, [html]]
|
94
|
+
else
|
95
|
+
@app.call env
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the html content for the root path. Supports ERB
|
100
|
+
def html
|
101
|
+
if @index_path
|
102
|
+
raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
|
103
|
+
Tilt.new(@index_path).render(self)
|
104
|
+
else
|
105
|
+
raise "Main asset path not configured (set 'main' within Opal::Server.new block)" if @server.main.nil?
|
106
|
+
source
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def javascript_include_tag name
|
111
|
+
sprockets = @server.sprockets
|
112
|
+
prefix = @server.prefix
|
113
|
+
debug = @server.debug
|
114
|
+
|
115
|
+
::Opal::Sprockets.javascript_include_tag(name, sprockets: sprockets, prefix: prefix, debug: debug)
|
116
|
+
end
|
117
|
+
|
118
|
+
def source
|
119
|
+
<<-HTML
|
120
|
+
<!DOCTYPE html>
|
121
|
+
<html>
|
122
|
+
<head>
|
123
|
+
<meta charset="utf-8">
|
124
|
+
<title>Opal Server</title>
|
125
|
+
</head>
|
126
|
+
<body>
|
127
|
+
#{javascript_include_tag @server.main}
|
128
|
+
</body>
|
129
|
+
</html>
|
130
|
+
HTML
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'sprockets/server'
|
2
|
+
|
3
|
+
module Opal
|
4
|
+
module Sprockets
|
5
|
+
module SourceMapHeaderPatch
|
6
|
+
# Adds the source map header to all sprocket responses for assets
|
7
|
+
# with a .rb or .opal extension in the extension chain.
|
8
|
+
def headers_with_opal_source_maps(env, asset, length)
|
9
|
+
headers_without_opal_source_maps(env, asset, length).tap do |current_headers|
|
10
|
+
if asset.pathname.to_s =~ /\.(rb|opal)\b/
|
11
|
+
base_path = asset.logical_path.gsub('.js', '')
|
12
|
+
current_headers['X-SourceMap'] = "#{::Opal::Sprockets::SourceMapHeaderPatch.prefix}/#{base_path}.map"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.included(base)
|
18
|
+
# Poor man's alias_method_chain :)
|
19
|
+
base.send(:alias_method, :headers_without_opal_source_maps, :headers)
|
20
|
+
base.send(:alias_method, :headers, :headers_with_opal_source_maps)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.inject!(prefix)
|
24
|
+
self.prefix = prefix
|
25
|
+
unless ::Sprockets::Server.ancestors.include?(self)
|
26
|
+
::Sprockets::Server.send :include, self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.prefix
|
31
|
+
@prefix
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.prefix= val
|
35
|
+
@prefix = val
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Opal
|
2
|
+
class SourceMapServer
|
3
|
+
# Carelessly taken from Sprockets::Caching (Sprockets v2)
|
4
|
+
class Cache
|
5
|
+
def initialize
|
6
|
+
@cache = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :cache
|
10
|
+
|
11
|
+
def cache_get(key)
|
12
|
+
# `Cache#get(key)` for Memcache
|
13
|
+
if cache.respond_to?(:get)
|
14
|
+
cache.get(key)
|
15
|
+
|
16
|
+
# `Cache#[key]` so `Hash` can be used
|
17
|
+
elsif cache.respond_to?(:[])
|
18
|
+
cache[key]
|
19
|
+
|
20
|
+
# `Cache#read(key)` for `ActiveSupport::Cache` support
|
21
|
+
elsif cache.respond_to?(:read)
|
22
|
+
cache.read(key)
|
23
|
+
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def cache_set(key, value)
|
30
|
+
# `Cache#set(key, value)` for Memcache
|
31
|
+
if cache.respond_to?(:set)
|
32
|
+
cache.set(key, value)
|
33
|
+
|
34
|
+
# `Cache#[key]=value` so `Hash` can be used
|
35
|
+
elsif cache.respond_to?(:[]=)
|
36
|
+
cache[key] = value
|
37
|
+
|
38
|
+
# `Cache#write(key, value)` for `ActiveSupport::Cache` support
|
39
|
+
elsif cache.respond_to?(:write)
|
40
|
+
cache.write(key, value)
|
41
|
+
end
|
42
|
+
|
43
|
+
value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.get_map_cache(sprockets, logical_path)
|
48
|
+
logical_path = logical_path.gsub(/\.js#{REGEXP_END}/, '')
|
49
|
+
cache_key = cache_key_for_path(logical_path+'.map')
|
50
|
+
cache(sprockets).cache_get(cache_key)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.set_map_cache(sprockets, logical_path, map_contents)
|
54
|
+
logical_path = logical_path.gsub(/\.js#{REGEXP_END}/, '')
|
55
|
+
cache_key = cache_key_for_path(logical_path+'.map')
|
56
|
+
cache(sprockets).cache_set(cache_key, map_contents)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.cache(sprockets)
|
60
|
+
@cache ||= sprockets.cache ? sprockets : Cache.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.cache_key_for_path(logical_path)
|
64
|
+
base_name = logical_path.gsub(/\.js#{REGEXP_END}/, '')
|
65
|
+
File.join('opal', 'source_maps', base_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def initialize sprockets, prefix = '/'
|
70
|
+
@sprockets = sprockets
|
71
|
+
@prefix = prefix
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_reader :sprockets, :prefix
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
"#<#{self.class}:#{object_id}>"
|
78
|
+
end
|
79
|
+
|
80
|
+
def call(env)
|
81
|
+
prefix_regex = %r{^(?:#{prefix}/|/)}
|
82
|
+
path_info = env['PATH_INFO'].to_s.sub(prefix_regex, '')
|
83
|
+
|
84
|
+
case path_info
|
85
|
+
when %r{^(.*)\.self\.map$}
|
86
|
+
path = $1
|
87
|
+
asset = sprockets[path+'.js']
|
88
|
+
return not_found(path) if asset.nil?
|
89
|
+
|
90
|
+
# "logical_name" of a BundledAsset keeps the .js extension
|
91
|
+
source = SourceMapServer.get_map_cache(sprockets, asset.logical_path)
|
92
|
+
return not_found(asset) if source.nil?
|
93
|
+
|
94
|
+
map = JSON.parse(source)
|
95
|
+
map['sources'] = map['sources'].map {|s| "#{prefix}/#{s}"}
|
96
|
+
source = map.to_json
|
97
|
+
|
98
|
+
return [200, {"Content-Type" => "text/json"}, [source.to_s]]
|
99
|
+
when %r{^(.*)\.rb$}
|
100
|
+
begin
|
101
|
+
asset = sprockets.resolve(path_info.sub(/\.rb#{REGEXP_END}/,''))
|
102
|
+
rescue Sprockets::FileNotFound
|
103
|
+
return not_found(path_info)
|
104
|
+
end
|
105
|
+
return [200, {"Content-Type" => "text/ruby"}, [Pathname(asset).read]]
|
106
|
+
else
|
107
|
+
not_found(path_info)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def not_found(*messages)
|
112
|
+
not_found = [404, {}, [{not_found: messages}.inspect]]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Opal
|
2
2
|
module Sprockets
|
3
3
|
BASE_VERSION = '0.4.0'
|
4
|
-
OPAL_VERSION = '0.
|
5
|
-
SPROCKETS_VERSION = '3.
|
6
|
-
VERSION = "#{BASE_VERSION}.#{OPAL_VERSION}.#{SPROCKETS_VERSION}.
|
4
|
+
OPAL_VERSION = '0.11.dev'
|
5
|
+
SPROCKETS_VERSION = '3.1'
|
6
|
+
VERSION = "#{BASE_VERSION}.#{OPAL_VERSION}.#{SPROCKETS_VERSION}.beta1"
|
7
7
|
end
|
8
8
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'opal'
|
2
|
+
require 'opal/sprockets/processor'
|
3
|
+
require 'opal/sprockets/erb'
|
4
|
+
require 'opal/sprockets/server'
|
5
|
+
|
6
|
+
module Opal
|
7
|
+
module Sprockets
|
8
|
+
# Bootstraps modules loaded by sprockets on `Opal.modules` marking any
|
9
|
+
# non-Opal asset as already loaded.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# Opal::Sprockets.load_asset(Rails.application.assets, 'application')
|
14
|
+
#
|
15
|
+
# @example Will output the following JavaScript:
|
16
|
+
#
|
17
|
+
# if (typeof(Opal) !== 'undefined') {
|
18
|
+
# Opal.loaded("opal");
|
19
|
+
# Opal.loaded("jquery.self");
|
20
|
+
# Opal.load("application");
|
21
|
+
# }
|
22
|
+
#
|
23
|
+
# @param name [String] The logical name of the main asset to be loaded (without extension)
|
24
|
+
# @param sprockets [Sprockets::Environment]
|
25
|
+
#
|
26
|
+
# @return [String] JavaScript code
|
27
|
+
def self.load_asset(name, sprockets)
|
28
|
+
asset = sprockets[name.sub(/(\.(js|rb|opal))*#{REGEXP_END}/, '.js')]
|
29
|
+
return '' if asset.nil?
|
30
|
+
|
31
|
+
opal_extnames = sprockets.engines.map do |ext, engine|
|
32
|
+
ext if engine <= ::Opal::Processor
|
33
|
+
end.compact
|
34
|
+
|
35
|
+
module_name = -> asset { asset.logical_path.sub(/\.js#{REGEXP_END}/, '') }
|
36
|
+
path_extnames = -> path { File.basename(path).scan(/\.[^.]+/) }
|
37
|
+
mark_loaded = -> paths { "Opal.loaded([#{paths.map(&:inspect).join(',')}]);" }
|
38
|
+
processed_by_opal = -> asset { (path_extnames[asset.pathname] & opal_extnames).any? }
|
39
|
+
stubbed_files = ::Opal::Config.stubbed_files
|
40
|
+
|
41
|
+
non_opal_assets = ([asset]+asset.dependencies)
|
42
|
+
.select { |asset| not(processed_by_opal[asset]) }
|
43
|
+
.map { |asset| module_name[asset] }
|
44
|
+
|
45
|
+
loaded = ['opal'] + non_opal_assets + stubbed_files.to_a
|
46
|
+
|
47
|
+
if processed_by_opal[asset]
|
48
|
+
load_asset_code = "Opal.load(#{module_name[asset].inspect});"
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
"if (typeof(Opal) !== 'undefined') { "\
|
53
|
+
"#{mark_loaded[loaded]} "\
|
54
|
+
"#{load_asset_code} "\
|
55
|
+
"}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generate a `<script>` tag for Opal assets.
|
59
|
+
#
|
60
|
+
# @param [String] name The logical name of the asset to be loaded (without extension)
|
61
|
+
# @param [Hash] options The options about sprockets
|
62
|
+
# @option options [Sprockets::Environment] :sprockets The sprockets instance
|
63
|
+
# @option options [String] :prefix The prefix String at which is mounted Sprockets, e.g. '/assets'
|
64
|
+
# @option options [Boolean] :debug Wether to enable debug mode along with sourcemaps support
|
65
|
+
#
|
66
|
+
# @return a string of HTML code containing `<script>` tags.
|
67
|
+
def self.javascript_include_tag(name, options = {})
|
68
|
+
sprockets = options.fetch(:sprockets)
|
69
|
+
prefix = options.fetch(:prefix)
|
70
|
+
debug = options.fetch(:debug)
|
71
|
+
|
72
|
+
# Avoid double slashes
|
73
|
+
prefix = prefix.chop if prefix.end_with? '/'
|
74
|
+
|
75
|
+
asset = sprockets[name]
|
76
|
+
raise "Cannot find asset: #{name}" if asset.nil?
|
77
|
+
scripts = []
|
78
|
+
|
79
|
+
if debug
|
80
|
+
asset.to_a.map do |dependency|
|
81
|
+
scripts << %{<script src="#{prefix}/#{dependency.logical_path}?body=1"></script>}
|
82
|
+
end
|
83
|
+
else
|
84
|
+
scripts << %{<script src="#{prefix}/#{name}.js"></script>}
|
85
|
+
end
|
86
|
+
|
87
|
+
scripts << %{<script>#{::Opal::Sprockets.load_asset(name, sprockets)}</script>}
|
88
|
+
|
89
|
+
scripts.join "\n"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/opal-sprockets.rb
CHANGED
data/opal-sprockets.gemspec
CHANGED
@@ -4,11 +4,11 @@ require File.expand_path('../lib/opal/sprockets/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'opal-sprockets'
|
6
6
|
s.version = Opal::Sprockets::VERSION
|
7
|
-
s.
|
8
|
-
s.email = '
|
7
|
+
s.author = 'Adam Beynon'
|
8
|
+
s.email = 'adam.beynon@gmail.com'
|
9
9
|
s.homepage = 'http://opalrb.org'
|
10
|
-
s.summary = 'Sprockets support for
|
11
|
-
s.description = 'Sprockets
|
10
|
+
s.summary = 'Sprockets support for opal'
|
11
|
+
s.description = 'Sprockets suppoer for opal.'
|
12
12
|
|
13
13
|
s.files = `git ls-files`.split("\n")
|
14
14
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-sprockets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.0.0.
|
4
|
+
version: 0.4.0.0.11.dev.3.1.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Elia Schito
|
8
7
|
- Adam Beynon
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2016-
|
11
|
+
date: 2016-09-28 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: sprockets
|
@@ -17,28 +16,28 @@ dependencies:
|
|
17
16
|
requirements:
|
18
17
|
- - "~>"
|
19
18
|
- !ruby/object:Gem::Version
|
20
|
-
version: '3.
|
19
|
+
version: '3.1'
|
21
20
|
type: :runtime
|
22
21
|
prerelease: false
|
23
22
|
version_requirements: !ruby/object:Gem::Requirement
|
24
23
|
requirements:
|
25
24
|
- - "~>"
|
26
25
|
- !ruby/object:Gem::Version
|
27
|
-
version: '3.
|
26
|
+
version: '3.1'
|
28
27
|
- !ruby/object:Gem::Dependency
|
29
28
|
name: opal
|
30
29
|
requirement: !ruby/object:Gem::Requirement
|
31
30
|
requirements:
|
32
31
|
- - "~>"
|
33
32
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
33
|
+
version: 0.11.dev
|
35
34
|
type: :runtime
|
36
35
|
prerelease: false
|
37
36
|
version_requirements: !ruby/object:Gem::Requirement
|
38
37
|
requirements:
|
39
38
|
- - "~>"
|
40
39
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
40
|
+
version: 0.11.dev
|
42
41
|
- !ruby/object:Gem::Dependency
|
43
42
|
name: tilt
|
44
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,8 +94,8 @@ dependencies:
|
|
95
94
|
- - ">="
|
96
95
|
- !ruby/object:Gem::Version
|
97
96
|
version: '0'
|
98
|
-
description: Sprockets
|
99
|
-
email:
|
97
|
+
description: Sprockets suppoer for opal.
|
98
|
+
email: adam.beynon@gmail.com
|
100
99
|
executables: []
|
101
100
|
extensions: []
|
102
101
|
extra_rdoc_files: []
|
@@ -113,6 +112,14 @@ files:
|
|
113
112
|
- example/config.ru
|
114
113
|
- example/index.html
|
115
114
|
- lib/opal-sprockets.rb
|
115
|
+
- lib/opal/sprockets.rb
|
116
|
+
- lib/opal/sprockets/environment.rb
|
117
|
+
- lib/opal/sprockets/erb.rb
|
118
|
+
- lib/opal/sprockets/path_reader.rb
|
119
|
+
- lib/opal/sprockets/processor.rb
|
120
|
+
- lib/opal/sprockets/server.rb
|
121
|
+
- lib/opal/sprockets/source_map_header_patch.rb
|
122
|
+
- lib/opal/sprockets/source_map_server.rb
|
116
123
|
- lib/opal/sprockets/version.rb
|
117
124
|
- opal-sprockets.gemspec
|
118
125
|
- spec/fixtures/complex_sprockets.js.rb.erb
|
@@ -152,15 +159,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
152
159
|
version: '0'
|
153
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
161
|
requirements:
|
155
|
-
- - "
|
162
|
+
- - ">"
|
156
163
|
- !ruby/object:Gem::Version
|
157
|
-
version:
|
164
|
+
version: 1.3.1
|
158
165
|
requirements: []
|
159
166
|
rubyforge_project:
|
160
167
|
rubygems_version: 2.6.4
|
161
168
|
signing_key:
|
162
169
|
specification_version: 4
|
163
|
-
summary: Sprockets support for
|
170
|
+
summary: Sprockets support for opal
|
164
171
|
test_files:
|
165
172
|
- spec/fixtures/complex_sprockets.js.rb.erb
|
166
173
|
- spec/fixtures/file_with_directives.js
|