opal-sprockets 0.4.5.1.0.3.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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