opal-sprockets 0.4.5.1.0.3.7 → 1.0.0

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.
@@ -3,158 +3,147 @@ require 'base64'
3
3
  require 'tilt/opal'
4
4
  require 'sprockets'
5
5
  require 'opal/builder'
6
- require 'opal/sprockets/path_reader'
6
+ require 'opal/sprockets'
7
+
8
+ # Internal: The Processor class is used to make ruby files (with .rb or .opal
9
+ # extensions) available to any sprockets based server. Processor will then
10
+ # get passed any ruby source file to build.
11
+ class Opal::Sprockets::Processor
12
+ @@cache_key = nil
13
+ def self.cache_key
14
+ @@cache_key ||= ['Opal', Opal::VERSION, Opal::Config.config].to_json.freeze
15
+ end
7
16
 
8
- module Opal
9
- # Internal: The Processor class is used to make ruby files (with .rb or .opal
10
- # extensions) available to any sprockets based server. Processor will then
11
- # get passed any ruby source file to build.
12
- class Processor < TiltTemplate
17
+ def self.reset_cache_key!
13
18
  @@cache_key = nil
14
- def self.cache_key
15
- @@cache_key ||= ['Opal', Opal::VERSION, Opal::Config.config].to_json.freeze
19
+ end
20
+
21
+ def self.call(input)
22
+ data, map, dependencies, required = input[:cache].fetch([self.cache_key, input[:filename], input[:data]]) do
23
+ new(input).call
16
24
  end
17
25
 
18
- def self.reset_cache_key!
19
- @@cache_key = nil
26
+ if map
27
+ map = ::Sprockets::SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
20
28
  end
21
29
 
22
- def evaluate(context, locals, &block)
23
- return super unless context.is_a? ::Sprockets::Context
30
+ {
31
+ data: data,
32
+ map: map,
33
+ dependencies: input[:metadata][:dependencies].to_a + dependencies.to_a,
34
+ required: input[:metadata][:required].to_a + required.to_a,
35
+ }
36
+ end
24
37
 
25
- @sprockets = sprockets = context.environment
38
+ def initialize(input)
39
+ @input = input
40
+ @sprockets = input[:environment]
41
+ @context = sprockets.context_class.new(input)
42
+ @data = input[:data]
43
+ end
26
44
 
27
- # In Sprockets 3 logical_path has an odd behavior when the filename is "index"
28
- # thus we need to bake our own logical_path
29
- filename = context.respond_to?(:filename) ? context.filename : context.pathname.to_s
30
- root_path_regexp = Regexp.escape(context.root_path)
31
- logical_path = filename.gsub(%r{^#{root_path_regexp}/?(.*?)#{sprockets_extnames_regexp}}, '\1')
45
+ attr_reader :input, :sprockets, :context, :data
32
46
 
33
- compiler_options = self.compiler_options.merge(file: logical_path)
47
+ # In Sprockets 3 logical_path has an odd behavior when the filename is "index"
48
+ # thus we need to bake our own logical_path
49
+ def logical_path
50
+ @logical_path ||= context.filename.gsub(%r{^#{Regexp.escape(context.root_path)}/?(.*?)}, '\1')
51
+ end
34
52
 
35
- compiler = Compiler.new(data, compiler_options)
36
- result = compiler.compile
53
+ def call
54
+ compiler_options = Opal::Config.compiler_options.merge(requirable: true, file: logical_path)
37
55
 
38
- process_requires(compiler.requires, context)
39
- process_required_trees(compiler.required_trees, context)
56
+ compiler = Opal::Compiler.new(data, compiler_options)
57
+ result = compiler.compile
40
58
 
41
- if Opal::Config.source_map_enabled
42
- map_data = compiler.source_map.as_json
43
- # Opal 0.11 doesn't fill sourcesContent
44
- add_sources_content_if_missing(map_data, data)
45
- "#{result}\n#{to_data_uri_comment(map_data.to_json)}"
46
- else
47
- result.to_s
48
- end
49
- end
59
+ process_requires(compiler.requires, context)
60
+ process_required_trees(compiler.required_trees, context)
50
61
 
51
- def self.sprockets_extnames_regexp(sprockets)
52
- joined_extnames = (['.js']+sprockets.engines.keys).map { |ext| Regexp.escape(ext) }.join('|')
53
- Regexp.new("(#{joined_extnames})*$")
62
+ if Opal::Config.source_map_enabled
63
+ map = compiler.source_map.as_json.transform_keys!(&:to_s)
64
+ map["sources"][0] = input[:filename]
65
+ map = ::Sprockets::SourceMapUtils.format_source_map(map, input)
54
66
  end
55
67
 
56
- def sprockets_extnames_regexp
57
- @sprockets_extnames_regexp ||= self.class.sprockets_extnames_regexp(@sprockets)
58
- end
68
+ [result.to_s, map , context.metadata[:dependencies], context.metadata[:required]]
69
+ end
59
70
 
60
- def process_requires(requires, context)
61
- requires.each do |required|
62
- required = required.to_s.sub(sprockets_extnames_regexp, '')
63
- context.require_asset required unless ::Opal::Config.stubbed_files.include? required
64
- end
71
+ def sprockets_extnames_regexp
72
+ @sprockets_extnames_regexp ||= Opal::Sprockets.sprockets_extnames_regexp(@sprockets)
73
+ end
74
+
75
+ def process_requires(requires, context)
76
+ requires.each do |required|
77
+ required = required.to_s.sub(sprockets_extnames_regexp, '')
78
+ context.require_asset required unless ::Opal::Config.stubbed_files.include? required
65
79
  end
80
+ end
66
81
 
67
- # Internal: Add files required with `require_tree` as asset dependencies.
68
- #
69
- # Mimics (v2) Sprockets::DirectiveProcessor#process_require_tree_directive
70
- def process_required_trees(required_trees, context)
71
- return if required_trees.empty?
82
+ # Internal: Add files required with `require_tree` as asset dependencies.
83
+ #
84
+ # Mimics (v2) Sprockets::DirectiveProcessor#process_require_tree_directive
85
+ def process_required_trees(required_trees, context)
86
+ return if required_trees.empty?
72
87
 
73
- # This is the root dir of the logical path, we need this because
74
- # the compiler gives us the path relative to the file's logical path.
75
- dirname = File.dirname(file).gsub(/#{Regexp.escape File.dirname(context.logical_path)}#{REGEXP_END}/, '')
76
- dirname = Pathname(dirname)
88
+ # This is the root dir of the logical path, we need this because
89
+ # the compiler gives us the path relative to the file's logical path.
90
+ dirname = File.dirname(input[:filename]).gsub(/#{Regexp.escape File.dirname(context.logical_path)}#{Opal::REGEXP_END}/, '')
91
+ dirname = Pathname(dirname)
77
92
 
78
- required_trees.each do |original_required_tree|
79
- required_tree = Pathname(original_required_tree)
93
+ required_trees.each do |original_required_tree|
94
+ required_tree = Pathname(original_required_tree)
80
95
 
81
- unless required_tree.relative?
82
- raise ArgumentError, "require_tree argument must be a relative path: #{required_tree.inspect}"
83
- end
96
+ unless required_tree.relative?
97
+ raise ArgumentError, "require_tree argument must be a relative path: #{required_tree.inspect}"
98
+ end
84
99
 
85
- required_tree = dirname.join(file, '..', required_tree)
100
+ required_tree = dirname.join(input[:filename], '..', required_tree)
86
101
 
87
- unless required_tree.directory?
88
- raise ArgumentError, "require_tree argument must be a directory: #{{source: original_required_tree, pathname: required_tree}.inspect}"
89
- end
102
+ unless required_tree.directory?
103
+ raise ArgumentError, "require_tree argument must be a directory: #{{source: original_required_tree, pathname: required_tree}.inspect}"
104
+ end
90
105
 
91
- context.depend_on required_tree.to_s
106
+ context.depend_on required_tree.to_s
92
107
 
93
- environment = context.environment
108
+ environment = context.environment
94
109
 
95
- processor = ::Sprockets::DirectiveProcessor.new
96
- processor.instance_variable_set('@dirname', File.dirname(file))
97
- processor.instance_variable_set('@environment', environment)
98
- path = processor.__send__(:expand_relative_dirname, :require_tree, original_required_tree)
99
- absolute_paths = environment.__send__(:stat_sorted_tree_with_dependencies, path).first.map(&:first)
110
+ processor = ::Sprockets::DirectiveProcessor.new
111
+ processor.instance_variable_set('@dirname', File.dirname(input[:filename]))
112
+ processor.instance_variable_set('@environment', environment)
113
+ path = processor.__send__(:expand_relative_dirname, :require_tree, original_required_tree)
114
+ absolute_paths = environment.__send__(:stat_sorted_tree_with_dependencies, path).first.map(&:first)
100
115
 
101
- absolute_paths.each do |path|
102
- path = Pathname(path)
103
- pathname = path.relative_path_from(dirname).to_s
116
+ absolute_paths.each do |path|
117
+ path = Pathname(path)
118
+ pathname = path.relative_path_from(dirname).to_s
119
+ pathname_noext = pathname.sub(sprockets_extnames_regexp, '')
104
120
 
105
- if name.to_s == file then next
106
- elsif path.directory? then context.depend_on(path.to_s)
107
- else context.require_asset(pathname)
108
- end
121
+ if path.to_s == logical_path then next
122
+ elsif ::Opal::Config.stubbed_files.include?(pathname_noext) then next
123
+ elsif path.directory? then context.depend_on(path.to_s)
124
+ else context.require_asset(pathname_noext)
109
125
  end
110
126
  end
111
127
  end
128
+ end
112
129
 
113
- # @deprecated
114
- def self.stubbed_files
115
- warn "Deprecated: `::Opal::Processor.stubbed_files' is deprecated, use `::Opal::Config.stubbed_files' instead"
116
- puts caller(5)
117
- ::Opal::Config.stubbed_files
118
- end
119
-
120
- # @deprecated
121
- def self.stub_file(name)
122
- warn "Deprecated: `::Opal::Processor.stub_file' is deprecated, use `::Opal::Config.stubbed_files << #{name.inspect}.to_s' instead"
123
- puts caller(5)
124
- ::Opal::Config.stubbed_files << name.to_s
125
- end
126
-
127
-
128
- private
129
-
130
- def add_sources_content_if_missing(data, content)
131
- data[:sourcesContent] = data.delete(:sourcesContent) || data.delete('sourcesContent') || [content]
132
- end
130
+ private
133
131
 
134
- def to_data_uri_comment(map_to_json)
135
- "//# sourceMappingURL=data:application/json;base64,#{Base64.encode64(map_to_json).delete("\n")}"
136
- end
132
+ def to_data_uri_comment(map_to_json)
133
+ "//# sourceMappingURL=data:application/json;base64,#{Base64.encode64(map_to_json).delete("\n")}"
134
+ end
137
135
 
138
- def stubbed_files
139
- ::Opal::Config.stubbed_files
140
- end
136
+ def stubbed_files
137
+ ::Opal::Config.stubbed_files
141
138
  end
142
- end
143
139
 
144
- module Opal::Sprockets::Processor
145
140
  module PlainJavaScriptLoader
146
141
  def self.call(input)
147
142
  sprockets = input[:environment]
148
- asset = OpenStruct.new(input)
149
-
150
- opal_extnames = sprockets.engines.map do |ext, engine|
151
- ext if engine <= ::Opal::Processor
152
- end.compact
153
143
 
154
- path_extnames = -> path { File.basename(path).scan(/\.[^.]+/) }
155
- processed_by_opal = -> asset { (path_extnames[asset.filename] & opal_extnames).any? }
144
+ opal_extnames_regexp = Opal::Sprockets.sprockets_extnames_regexp(sprockets, opal_only: true)
156
145
 
157
- if processed_by_opal[asset]
146
+ if input[:filename] =~ opal_extnames_regexp
158
147
  input[:data]
159
148
  else
160
149
  "#{input[:data]}\n#{Opal::Sprockets.loaded_asset(input[:name])}"
@@ -163,7 +152,15 @@ module Opal::Sprockets::Processor
163
152
  end
164
153
  end
165
154
 
166
- Sprockets.register_engine '.rb', Opal::Processor, mime_type: 'application/javascript', silence_deprecation: true
167
- Sprockets.register_engine '.opal', Opal::Processor, mime_type: 'application/javascript', silence_deprecation: true
168
- Sprockets.register_postprocessor 'application/javascript', Opal::Sprockets::Processor::PlainJavaScriptLoader
155
+ Sprockets.register_mime_type 'application/ruby', extensions: ['.rb', '.opal', '.js.rb', '.js.opal']
156
+ Sprockets.register_transformer 'application/ruby', 'application/javascript', Opal::Sprockets::Processor
157
+ Opal::Sprockets.register_mime_type 'application/ruby'
158
+
159
+ Sprockets.register_mime_type 'application/ruby+ruby', extensions: ['.rb.erb', '.opal.erb', '.js.rb.erb', '.js.opal.erb']
160
+ Sprockets.register_transformer 'application/ruby+ruby', 'application/ruby', Sprockets::ERBProcessor
161
+ Opal::Sprockets.register_mime_type 'application/ruby+ruby'
169
162
 
163
+ Sprockets.register_preprocessor 'application/ruby', Sprockets::DirectiveProcessor.new(comments: ["#"])
164
+ Sprockets.register_preprocessor 'application/ruby+ruby', Sprockets::DirectiveProcessor.new(comments: ["#"])
165
+
166
+ Sprockets.register_postprocessor 'application/javascript', Opal::Sprockets::Processor::PlainJavaScriptLoader
@@ -2,115 +2,111 @@ require 'erb'
2
2
  require 'rack'
3
3
  require 'sprockets'
4
4
 
5
- module Opal
6
- module Sprockets
7
- class Server
8
- attr_accessor :debug, :use_index, :index_path, :main, :public_root,
9
- :public_urls, :sprockets, :prefix
10
-
11
- def initialize options = {}
12
- @use_index = true
13
- @public_root = nil
14
- @public_urls = ['/']
15
- @sprockets = options.fetch(:sprockets, ::Sprockets::Environment.new)
16
- @debug = options.fetch(:debug, true)
17
- @prefix = options.fetch(:prefix, '/assets')
18
-
19
- Opal.paths.each { |p| @sprockets.append_path(p) }
20
-
21
- yield self if block_given?
22
- create_app
23
- end
5
+ class Opal::Sprockets::Server
6
+ attr_accessor :debug, :use_index, :index_path, :main, :public_root,
7
+ :public_urls, :sprockets, :prefix
8
+
9
+ def initialize options = {}
10
+ @use_index = true
11
+ @public_root = nil
12
+ @public_urls = ['/']
13
+ @sprockets = options.fetch(:sprockets, ::Sprockets::Environment.new)
14
+ @debug = options.fetch(:debug, true)
15
+ @prefix = options.fetch(:prefix, '/assets')
16
+
17
+ Opal.paths.each { |p| @sprockets.append_path(p) }
18
+
19
+ yield self if block_given?
20
+ create_app
21
+ end
24
22
 
25
- def public_dir=(dir)
26
- @public_root = dir
27
- @public_urls = ["/"]
28
- end
23
+ def public_dir=(dir)
24
+ @public_root = dir
25
+ @public_urls = ["/"]
26
+ end
29
27
 
30
- def source_map=(enabled)
31
- Opal::Config.source_map_enabled = enabled
32
- end
28
+ def source_map=(enabled)
29
+ Opal::Config.source_map_enabled = enabled
30
+ end
33
31
 
34
- def source_map_enabled
35
- Opal::Config.source_map_enabled
36
- end
32
+ def source_map_enabled
33
+ Opal::Config.source_map_enabled
34
+ end
37
35
 
38
- def append_path path
39
- @sprockets.append_path path
40
- end
36
+ def append_path path
37
+ @sprockets.append_path path
38
+ end
41
39
 
42
- def use_gem gem_name
43
- @sprockets.use_gem gem_name
44
- end
40
+ def use_gem gem_name
41
+ @sprockets.use_gem gem_name
42
+ end
45
43
 
46
- def create_app
47
- server, sprockets, prefix = self, @sprockets, self.prefix
48
- sprockets.logger.level ||= Logger::DEBUG
49
-
50
- @app = Rack::Builder.app do
51
- not_found = lambda { |env| [404, {}, []] }
52
- use Rack::Deflater
53
- use Rack::ShowExceptions
54
- use Index, server if server.use_index
55
- map(prefix) { run sprockets }
56
- run Rack::Static.new(not_found, root: server.public_root, urls: server.public_urls)
57
- end
58
- end
44
+ def create_app
45
+ server, sprockets, prefix = self, @sprockets, self.prefix
46
+ sprockets.logger.level ||= Logger::DEBUG
47
+
48
+ @app = Rack::Builder.app do
49
+ not_found = lambda { |env| [404, {}, []] }
50
+ use Rack::Deflater
51
+ use Rack::ShowExceptions
52
+ use Index, server if server.use_index
53
+ map(prefix) { run sprockets }
54
+ run Rack::Static.new(not_found, root: server.public_root, urls: server.public_urls)
55
+ end
56
+ end
57
+
58
+ def call(env)
59
+ @app.call env
60
+ end
61
+
62
+ class Index
63
+
64
+ def initialize(app, server)
65
+ @app = app
66
+ @server = server
67
+ @index_path = server.index_path
68
+ end
59
69
 
60
- def call(env)
70
+ def call(env)
71
+ if %w[/ /index.html].include? env['PATH_INFO']
72
+ [200, { 'Content-Type' => 'text/html' }, [html]]
73
+ else
61
74
  @app.call env
62
75
  end
76
+ end
63
77
 
64
- class Index
65
-
66
- def initialize(app, server)
67
- @app = app
68
- @server = server
69
- @index_path = server.index_path
70
- end
71
-
72
- def call(env)
73
- if %w[/ /index.html].include? env['PATH_INFO']
74
- [200, { 'Content-Type' => 'text/html' }, [html]]
75
- else
76
- @app.call env
77
- end
78
- end
79
-
80
- # Returns the html content for the root path. Supports ERB
81
- def html
82
- if @index_path
83
- raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
84
- Tilt.new(@index_path).render(self)
85
- else
86
- raise "Main asset path not configured (set 'main' within Opal::Server.new block)" if @server.main.nil?
87
- source
88
- end
89
- end
90
-
91
- def javascript_include_tag name
92
- sprockets = @server.sprockets
93
- prefix = @server.prefix
94
- debug = @server.debug
95
-
96
- ::Opal::Sprockets.javascript_include_tag(name, sprockets: sprockets, prefix: prefix, debug: debug)
97
- end
98
-
99
- def source
100
- <<-HTML
101
- <!DOCTYPE html>
102
- <html>
103
- <head>
104
- <meta charset="utf-8">
105
- <title>Opal Server</title>
106
- </head>
107
- <body>
108
- #{javascript_include_tag @server.main}
109
- </body>
110
- </html>
111
- HTML
112
- end
78
+ # Returns the html content for the root path. Supports ERB
79
+ def html
80
+ if @index_path
81
+ raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
82
+ Tilt.new(@index_path).render(self)
83
+ else
84
+ raise "Main asset path not configured (set 'main' within Opal::Server.new block)" if @server.main.nil?
85
+ source
113
86
  end
114
87
  end
88
+
89
+ def javascript_include_tag name
90
+ sprockets = @server.sprockets
91
+ prefix = @server.prefix
92
+ debug = @server.debug
93
+
94
+ ::Opal::Sprockets.javascript_include_tag(name, sprockets: sprockets, prefix: prefix, debug: debug)
95
+ end
96
+
97
+ def source
98
+ <<-HTML
99
+ <!DOCTYPE html>
100
+ <html>
101
+ <head>
102
+ <meta charset="utf-8">
103
+ <title>Opal Server</title>
104
+ </head>
105
+ <body>
106
+ #{javascript_include_tag @server.main}
107
+ </body>
108
+ </html>
109
+ HTML
110
+ end
115
111
  end
116
112
  end