diff --git a/lib/sprockets/rails/sourcemapping_url_processor.rb b/lib/sprockets/rails/sourcemapping_url_processor.rb new file mode 100644 index 00000000..599deeb4 --- /dev/null +++ b/lib/sprockets/rails/sourcemapping_url_processor.rb @@ -0,0 +1,22 @@ +module Sprockets + module Rails + # Rewrites source mapping urls with the digested paths and protect against semicolon appending with a dummy comment line + class SourcemappingUrlProcessor + REGEX = /\/\/# sourceMappingURL=(.*\.map)/ + + def self.call(input) + env = input[:environment] + context = env.context_class.new(input) + data = input[:data].gsub(REGEX) do |_match| + ensure_file_is_present = context.resolve($1) + "//# sourceMappingURL=#{context.asset_path($1)}\n//!\n" + rescue Sprockets::FileNotFound + env.logger.warn "Removed sourceMappingURL comment for missing asset '#{$1}' from #{input[:filename]}" + nil + end + + { data: data } + end + end + end +end diff --git a/lib/sprockets/railtie.rb b/lib/sprockets/railtie.rb index d7434523..5651faf7 100644 --- a/lib/sprockets/railtie.rb +++ b/lib/sprockets/railtie.rb @@ -6,6 +6,7 @@ require 'sprockets' require 'sprockets/rails/asset_url_processor' +require 'sprockets/rails/sourcemapping_url_processor' require 'sprockets/rails/context' require 'sprockets/rails/helper' require 'sprockets/rails/quiet_assets' @@ -122,6 +123,10 @@ def configure(&block) Sprockets.register_postprocessor "text/css", ::Sprockets::Rails::AssetUrlProcessor end + initializer :asset_sourcemap_url_processor do |app| + Sprockets.register_postprocessor "application/javascript", ::Sprockets::Rails::SourcemappingUrlProcessor + end + config.assets.version = "" config.assets.debug = false config.assets.compile = true diff --git a/test/test_sourcemapping_url_processor.rb b/test/test_sourcemapping_url_processor.rb new file mode 100644 index 00000000..a35d04b2 --- /dev/null +++ b/test/test_sourcemapping_url_processor.rb @@ -0,0 +1,38 @@ +require 'minitest/autorun' +require 'sprockets/railtie' + + +Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test) +class TestSourceMappingUrlProcessor < Minitest::Test + def setup + @env = Sprockets::Environment.new + end + + def test_successful + @env.context_class.class_eval do + def resolve(path, **kargs) + "/yes" + end + + def asset_path(path, options = {}) + 'mapped-HEXGOESHERE.js.map' + end + end + + input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", filename: 'mapped.js', metadata: {} } + output = Sprockets::Rails::SourcemappingUrlProcessor.call(input) + assert_equal({ data: "var mapped;\n//# sourceMappingURL=mapped-HEXGOESHERE.js.map\n//!\n" }, output) + end + + def test_missing + @env.context_class.class_eval do + def resolve(path, **kargs) + raise Sprockets::FileNotFound + end + end + + input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mappedNOT.js.map", filename: 'mapped.js', metadata: {} } + output = Sprockets::Rails::SourcemappingUrlProcessor.call(input) + assert_equal({ data: "var mapped;\n" }, output) + end +end