Skip to content

Commit 0a56eec

Browse files
authored
Fix sourcemapping url replacement (#484)
* Fix sourcemapping url replacement * Improve naming * Add test for dealing with the deep nest issue
1 parent 05dbab2 commit 0a56eec

File tree

2 files changed

+59
-16
lines changed

2 files changed

+59
-16
lines changed

lib/sprockets/rails/sourcemapping_url_processor.rb

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,50 @@ module Rails
44
class SourcemappingUrlProcessor
55
REGEX = /\/\/# sourceMappingURL=(.*\.map)/
66

7-
def self.call(input)
8-
env = input[:environment]
9-
context = env.context_class.new(input)
10-
data = input[:data].gsub(REGEX) do |_match|
11-
context.resolve($1) # Ensure file is present
12-
"//# sourceMappingURL=#{context.asset_path($1)}\n//!\n"
13-
rescue Sprockets::FileNotFound
14-
env.logger.warn "Removed sourceMappingURL comment for missing asset '#{$1}' from #{input[:filename]}"
15-
nil
7+
class << self
8+
def call(input)
9+
env = input[:environment]
10+
context = env.context_class.new(input)
11+
data = input[:data].gsub(REGEX) do |_match|
12+
sourcemap_logical_path = combine_sourcemap_logical_path(sourcefile: input[:name], sourcemap: $1)
13+
14+
begin
15+
resolved_sourcemap_comment(sourcemap_logical_path, context: context)
16+
rescue Sprockets::FileNotFound
17+
removed_sourcemap_comment(sourcemap_logical_path, filename: input[:filename], env: env)
18+
end
19+
end
20+
21+
{ data: data }
1622
end
1723

18-
{ data: data }
24+
private
25+
def combine_sourcemap_logical_path(sourcefile:, sourcemap:)
26+
if (parts = sourcefile.split("/")).many?
27+
parts[0..-2].append(sourcemap).join("/")
28+
else
29+
sourcemap
30+
end
31+
end
32+
33+
def resolved_sourcemap_comment(sourcemap_logical_path, context:)
34+
"//# sourceMappingURL=#{sourcemap_asset_path(sourcemap_logical_path, context: context)}\n//!\n"
35+
end
36+
37+
def sourcemap_asset_path(sourcemap_logical_path, context:)
38+
# FIXME: Work-around for bug where if the sourcemap is nested two levels deep, it'll resolve as the source file
39+
# that's being mapped, rather than the map itself. So context.resolve("a/b/c.js.map") will return "c.js?"
40+
if context.resolve(sourcemap_logical_path) =~ /\.map/
41+
context.asset_path(sourcemap_logical_path)
42+
else
43+
raise Sprockets::FileNotFound, "Failed to resolve source map asset due to nesting depth"
44+
end
45+
end
46+
47+
def removed_sourcemap_comment(sourcemap_logical_path, filename:, env:)
48+
env.logger.warn "Removed sourceMappingURL comment for missing asset '#{sourcemap_logical_path}' from #{filename}"
49+
nil
50+
end
1951
end
2052
end
2153
end

test/test_sourcemapping_url_processor.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'minitest/autorun'
22
require 'sprockets/railtie'
33

4-
54
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
65
class TestSourceMappingUrlProcessor < Minitest::Test
76
def setup
@@ -11,17 +10,29 @@ def setup
1110
def test_successful
1211
@env.context_class.class_eval do
1312
def resolve(path, **kargs)
14-
"/yes"
13+
"/assets/mapped.js.map"
1514
end
1615

1716
def asset_path(path, options = {})
18-
'mapped-HEXGOESHERE.js.map'
17+
"/assets/mapped-HEXGOESHERE.js.map"
18+
end
19+
end
20+
21+
input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
22+
output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
23+
assert_equal({ data: "var mapped;\n//# sourceMappingURL=/assets/mapped-HEXGOESHERE.js.map\n//!\n" }, output)
24+
end
25+
26+
def test_resolving_erroneously_without_map_extension
27+
@env.context_class.class_eval do
28+
def resolve(path, **kargs)
29+
"/assets/mapped.js"
1930
end
2031
end
2132

22-
input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", filename: 'mapped.js', metadata: {} }
33+
input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
2334
output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
24-
assert_equal({ data: "var mapped;\n//# sourceMappingURL=mapped-HEXGOESHERE.js.map\n//!\n" }, output)
35+
assert_equal({ data: "var mapped;\n" }, output)
2536
end
2637

2738
def test_missing
@@ -31,7 +42,7 @@ def resolve(path, **kargs)
3142
end
3243
end
3344

34-
input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mappedNOT.js.map", filename: 'mapped.js', metadata: {} }
45+
input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mappedNOT.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
3546
output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
3647
assert_equal({ data: "var mapped;\n" }, output)
3748
end

0 commit comments

Comments
 (0)