Skip to content

Commit

Permalink
Sassc source maps fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler Horth committed Oct 6, 2016
1 parent fe9bc1d commit d30efa6
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 21 deletions.
1 change: 1 addition & 0 deletions lib/sprockets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ module Sprockets
register_bundle_metadata_reducer '*/*', :data, proc { String.new("") }, :concat
register_bundle_metadata_reducer 'application/javascript', :data, proc { String.new("") }, Utils.method(:concat_javascript_sources)
register_bundle_metadata_reducer '*/*', :links, :+
register_bundle_metadata_reducer '*/*', :sources, proc { [] }, :+
register_bundle_metadata_reducer '*/*', :map, SourceMapUtils.method(:concat_source_maps)

require 'sprockets/closure_compressor'
Expand Down
15 changes: 15 additions & 0 deletions lib/sprockets/path_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ def relative_path_from(start, dest)
dest.relative_path_from(start).to_s
end

# Public: Joins path to base path.
#
# base - Root path
# path - Extending path
#
# Example
#
# join('base/path/', '../file.js')
# # => 'base/file.js'
#
# Returns string path starting from base and ending at path
def join(base, path)
(Pathname.new(base) + path).to_s
end

# Internal: Get relative path for root path and subpath.
#
# path - String path
Expand Down
9 changes: 6 additions & 3 deletions lib/sprockets/sass_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ def call(input)

private

def expand_source(source, env)
uri, _ = env.resolve!(source, pipeline: :source)
env.load(uri).digest_path
end

def expand_map_sources(mapping, env)
mapping.each do |map|
uri, _ = env.resolve!(map[:source], pipeline: :source)
source_path = env.load(uri).digest_path
map[:source] = source_path
map[:source] = expand_source(map[:source], env)
end
end

Expand Down
28 changes: 16 additions & 12 deletions lib/sprockets/sassc_processor.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'sprockets/sass_processor'
require 'sprockets/path_utils'
require 'base64'

module Sprockets
Expand All @@ -22,39 +23,42 @@ def call(input)
options = engine_options(input, context)
engine = Autoload::SassC::Engine.new(input[:data], options)

data = Utils.module_include(Autoload::SassC::Script::Functions, @functions) do
engine.render
css = Utils.module_include(Autoload::SassC::Script::Functions, @functions) do
engine.render.sub(/^\n^\/\*# sourceMappingURL=.*\*\/$/m, '')
end

match_data = data.match(/(.*)\n\/\*# sourceMappingURL=data:application\/json;base64,(.+) \*\//m)
css, map = match_data[1], Base64.decode64(match_data[2])
map = SourceMapUtils.decode_json_source_map(engine.source_map)
sources = map['sources'].map do |s|
expand_source(PathUtils.join(File.dirname(input[:filename]), s), input[:environment])
end

map = map["mappings"].each do |m|
m[:source] = PathUtils.join(File.dirname(input[:filename]), m[:source])
end

map = SourceMapUtils.combine_source_maps(
input[:metadata][:map],
change_source(SourceMapUtils.decode_json_source_map(map)["mappings"], input[:source_path])
expand_map_sources(map, input[:environment])
)

engine.dependencies.each do |dependency|
context.metadata[:dependencies] << URIUtils.build_file_digest_uri(dependency.filename)
end

context.metadata.merge(data: css, map: map)
context.metadata.merge(data: css, map: map, sources: sources)
end

private

def change_source(mappings, source)
mappings.each { |m| m[:source] = source }
end

def engine_options(input, context)
merge_options({
filename: input[:filename],
syntax: self.class.syntax,
load_paths: input[:environment].paths,
importer: @importer_class,
source_map_embed: true,
source_map_file: '.',
source_map_contents: true,
source_map_file: "#{input[:filename]}.map",
omit_source_map_url: true,
sprockets: {
context: context,
environment: input[:environment],
Expand Down
9 changes: 5 additions & 4 deletions lib/sprockets/source_map_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ def self.call(input)

env = input[:environment]

uri, _ = env.resolve!(input[:filename], accept: accept)
asset = env.load(uri)
map = asset.metadata[:map] || []
uri, _ = env.resolve!(input[:filename], accept: accept)
asset = env.load(uri)
map = asset.metadata[:map] || []
sources = asset.metadata[:sources]

# TODO: Because of the default piplene hack we have to apply dependencies
# from compiled asset to the source map, otherwise the source map cache
Expand All @@ -39,7 +40,7 @@ def self.call(input)
links << uri
end

json = env.encode_json_source_map(map, filename: asset.logical_path)
json = env.encode_json_source_map(map, sources: sources, filename: asset.logical_path)

{ data: json, links: links, dependencies: dependencies }
end
Expand Down
3 changes: 2 additions & 1 deletion lib/sprockets/source_map_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ def encode_json_source_map(mappings, sources: nil, names: nil, filename: nil)
mappings.each do |m|
m[:source] = PathUtils.relative_path_from(filename, m[:source])
end if filename
sources ||= mappings.map { |m| m[:source] }.uniq.compact
sources = sources.map { |s| PathUtils.relative_path_from(filename, s) } if filename && sources
sources = (Array(sources) + mappings.map { |m| m[:source] }).uniq.compact
names ||= mappings.map { |m| m[:name] }.uniq.compact
mappings = encode_vlq_mappings(mappings, sources: sources, names: names)
else
Expand Down
2 changes: 1 addition & 1 deletion sprockets.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "rack-test", "~> 0.6"
s.add_development_dependency "rake", "~> 10.0"
s.add_development_dependency "sass", "~> 3.4"
s.add_development_dependency "sassc", "~> 1.7"
s.add_development_dependency "sassc", ">= 1.10.1", "< 2.0"
s.add_development_dependency "uglifier", "~> 2.3"
s.add_development_dependency "yui-compressor", "~> 0.12"
s.add_development_dependency "zopfli", "~> 0.0.4"
Expand Down
35 changes: 35 additions & 0 deletions test/test_source_maps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,39 @@ def setup
"names" => []
}, map)
end

test "compile scss source map with imported dependencies" do
asset = silence_warnings do
@env.find_asset("sass/with-import.css")
end
assert asset
assert_equal fixture_path('source-maps/sass/with-import.scss'), asset.filename
assert_equal "text/css", asset.content_type

assert_match "body {\n color: red; }", asset.source

asset = silence_warnings do
@env.find_asset("sass/with-import.css.map")
end
assert asset
assert_equal fixture_path('source-maps/sass/with-import.scss'), asset.filename
assert_equal "sass/with-import.css.map", asset.logical_path
assert_equal "application/css-sourcemap+json", asset.content_type
assert_equal [
"file://#{fixture_path_for_uri('source-maps/sass/_imported.scss')}?type=text/scss&pipeline=source",
"file://#{fixture_path_for_uri('source-maps/sass/with-import.scss')}?type=text/scss&pipeline=source"
], normalize_uris(asset.links)

assert map = JSON.parse(asset.source)
assert_equal({
"version" => 3,
"file" => "sass/with-import.css",
"mappings" => "ACAA,AAAA,IAAI,CAAC;EAAE,KAAK,EAAE,GAAI,GAAI;;ADEtB,AAAA,GAAG,CAAC;EAAE,KAAK,EAAE,IAAK,GAAI",
"sources" => [
"with-import.source-5d53742ba113ac26396986bf14ab5c7e19ef193e494d5d868a9362e3e057cb26.scss",
"_imported.source-9767e91e9d4b0334e59a1d389e9801bc6a2c5c4a5500a3c2c7915687965b2c16.scss"
],
"names" => []
}, map)
end
end

0 comments on commit d30efa6

Please sign in to comment.