sprockets 4.0.0.beta4 → 4.0.0.beta5

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.
@@ -6,6 +6,56 @@ module Sprockets
6
6
  module SourceMapUtils
7
7
  extend self
8
8
 
9
+ # Public: Transpose source maps into a standard format
10
+ #
11
+ # NOTE: Does not support index maps
12
+ #
13
+ # version => 3
14
+ # file => logical path
15
+ # sources => relative from filename
16
+ #
17
+ # Unnecessary attributes are removed
18
+ #
19
+ # Example
20
+ #
21
+ # map
22
+ # #=> {
23
+ # # "version" => 3,
24
+ # # "file" => "stdin",
25
+ # # "sourceRoot" => "",
26
+ # # "sourceContents" => "blah blah blah",
27
+ # # "sources" => [/root/logical/path.js],
28
+ # # "names" => [..],
29
+ # #}
30
+ # format_source_map(map, input)
31
+ # #=> {
32
+ # # "version" => 3,
33
+ # # "file" => "logical/path.js",
34
+ # # "sources" => ["path.js"],
35
+ # # "names" => [..],
36
+ # #}
37
+ def format_source_map(map, input)
38
+ filename = input[:filename]
39
+ load_path = input[:load_path]
40
+ load_paths = input[:environment].config[:paths]
41
+ mime_exts = input[:environment].config[:mime_exts]
42
+ pipeline_exts = input[:environment].config[:pipeline_exts]
43
+ file = PathUtils.split_subpath(load_path, filename)
44
+ {
45
+ "version" => 3,
46
+ "file" => file,
47
+ "mappings" => map["mappings"],
48
+ "sources" => map["sources"].map do |source|
49
+ source = URIUtils.split_file_uri(source)[2] if source.start_with? "file://"
50
+ source = PathUtils.join(File.dirname(filename), source) unless PathUtils.absolute_path?(source)
51
+ _, source = PathUtils.paths_split(load_paths, source)
52
+ source = PathUtils.relative_path_from(file, source)
53
+ PathUtils.set_pipeline(source, mime_exts, pipeline_exts, :source)
54
+ end,
55
+ "names" => map["names"]
56
+ }
57
+ end
58
+
9
59
  # Public: Concatenate two source maps.
10
60
  #
11
61
  # For an example, if two js scripts are concatenated, the individual source
@@ -16,25 +66,75 @@ module Sprockets
16
66
  # script3 = "#{script1}#{script2}"
17
67
  # map3 = concat_source_maps(map1, map2)
18
68
  #
19
- # a - Array of source mapping Hashes
20
- # b - Array of source mapping Hashes
69
+ # a - Source map hash
70
+ # b - Source map hash
21
71
  #
22
- # Returns a new Array of source mapping Hashes.
72
+ # Returns a new source map hash.
23
73
  def concat_source_maps(a, b)
24
- a ||= []
25
- b ||= []
26
- mappings = a.dup
74
+ return a || b unless a && b
75
+ a, b = make_index_map(a), make_index_map(b)
27
76
 
28
- if a.any?
29
- offset = a.last[:generated][0]
30
- else
77
+ if a["sections"].count == 0 || a["sections"].last["map"]["mappings"].empty?
31
78
  offset = 0
79
+ else
80
+ offset = a["sections"].last["map"]["mappings"].count(';') +
81
+ a["sections"].last["offset"]["line"] + 1
32
82
  end
33
83
 
34
- b.each do |m|
35
- mappings << m.merge(generated: [m[:generated][0] + offset, m[:generated][1]])
84
+ a["sections"] += b["sections"].map do |section|
85
+ {
86
+ "offset" => section["offset"].merge({ "line" => section["offset"]["line"] + offset }),
87
+ "map" => section["map"].merge({
88
+ "sources" => section["map"]["sources"].map do |source|
89
+ PathUtils.relative_path_from(a["file"], PathUtils.join(File.dirname(b["file"]), source))
90
+ end
91
+ })
92
+ }
36
93
  end
37
- mappings
94
+ a
95
+ end
96
+
97
+ # Public: Converts source map to index map
98
+ #
99
+ # Example:
100
+ #
101
+ # map
102
+ # # => {
103
+ # "version" => 3,
104
+ # "file" => "..",
105
+ # "mappings" => "AAAA;AACA;..;AACA",
106
+ # "sources" => [..],
107
+ # "names" => [..]
108
+ # }
109
+ # make_index_map(map)
110
+ # # => {
111
+ # "version" => 3,
112
+ # "file" => "..",
113
+ # "sections" => [
114
+ # {
115
+ # "offset" => { "line" => 0, "column" => 0 },
116
+ # "map" => {
117
+ # "version" => 3,
118
+ # "file" => "..",
119
+ # "mappings" => "AAAA;AACA;..;AACA",
120
+ # "sources" => [..],
121
+ # "names" => [..]
122
+ # }
123
+ # }
124
+ # ]
125
+ # }
126
+ def make_index_map(map)
127
+ return map if map.key? "sections"
128
+ {
129
+ "version" => map["version"],
130
+ "file" => map["file"],
131
+ "sections" => [
132
+ {
133
+ "offset" => { "line" => 0, "column" => 0 },
134
+ "map" => map
135
+ }
136
+ ]
137
+ }
38
138
  end
39
139
 
40
140
  # Public: Combine two seperate source map transformations into a single
@@ -49,25 +149,95 @@ module Sprockets
49
149
  # map can be combined with the Uglifier map so the source lines of the
50
150
  # minified output can be traced back to the original CoffeeScript file.
51
151
  #
52
- # original_map = [{ :source => "index.coffee", :generated => [2, 0], :original => [1, 0] }]
53
- # second_map = [{ :source => "index.js", :generated => [1, 1], :original => [2, 0] }]
54
- # combine_source_maps(original_map, second_map)
55
- # # => [{:source=>"index.coffee", :generated => [1, 1], :original => [1, 0]}]
56
- #
57
- # Returns a new Array of source mapping Hashes.
58
- def combine_source_maps(original_map, second_map)
59
- original_map ||= []
60
- return second_map.dup if original_map.empty?
152
+ # Returns a source map hash.
153
+ def combine_source_maps(first, second)
154
+ return second unless first
155
+
156
+ _first = decode_source_map(first)
157
+ _second = decode_source_map(second)
61
158
 
62
- new_map = []
159
+ new_mappings = []
63
160
 
64
- second_map.each do |m|
65
- original_line = bsearch_mappings(original_map, m[:original])
66
- next unless original_line
67
- new_map << original_line.merge(generated: m[:generated])
161
+ _second[:mappings].each do |m|
162
+ first_line = bsearch_mappings(_first[:mappings], m[:original])
163
+ new_mappings << first_line.merge(generated: m[:generated]) if first_line
68
164
  end
69
165
 
70
- new_map
166
+ _first[:mappings] = new_mappings
167
+
168
+ encode_source_map(_first)
169
+ end
170
+
171
+ # Public: Decompress source map
172
+ #
173
+ # Example:
174
+ #
175
+ # decode_source_map(map)
176
+ # # => {
177
+ # version: 3,
178
+ # file: "..",
179
+ # mappings: [
180
+ # { source: "..", generated: [0, 0], original: [0, 0], name: ".."}, ..
181
+ # ],
182
+ # sources: [..],
183
+ # names: [..]
184
+ # }
185
+ #
186
+ # map - Source map hash (v3 spec)
187
+ #
188
+ # Returns an uncompressed source map hash
189
+ def decode_source_map(map)
190
+ return nil unless map
191
+
192
+ mappings, sources, names = [], [], []
193
+ if map["sections"]
194
+ map["sections"].each do |s|
195
+ mappings += decode_source_map(s["map"])[:mappings].each do |m|
196
+ m[:generated][0] += s["offset"]["line"]
197
+ m[:generated][1] += s["offset"]["column"]
198
+ end
199
+ sources |= s["map"]["sources"]
200
+ names |= s["map"]["names"]
201
+ end
202
+ else
203
+ mappings = decode_vlq_mappings(map["mappings"], sources: map["sources"], names: map["names"])
204
+ sources = map["sources"]
205
+ names = map["names"]
206
+ end
207
+ {
208
+ version: 3,
209
+ file: map["file"],
210
+ mappings: mappings,
211
+ sources: sources,
212
+ names: names
213
+ }
214
+ end
215
+
216
+ # Public: Compress source map
217
+ #
218
+ # Example:
219
+ #
220
+ # encode_source_map(map)
221
+ # # => {
222
+ # "version" => 3,
223
+ # "file" => "..",
224
+ # "mappings" => "AAAA;AACA;..;AACA",
225
+ # "sources" => [..],
226
+ # "names" => [..]
227
+ # }
228
+ #
229
+ # map - Source map hash (uncompressed)
230
+ #
231
+ # Returns a compressed source map hash according to source map spec v3
232
+ def encode_source_map(map)
233
+ return nil unless map
234
+ {
235
+ "version" => map[:version],
236
+ "file" => map[:file],
237
+ "mappings" => encode_vlq_mappings(map[:mappings], sources: map[:sources], names: map[:names]),
238
+ "sources" => map[:sources],
239
+ "names" => map[:names]
240
+ }
71
241
  end
72
242
 
73
243
  # Public: Compare two source map offsets.
@@ -114,49 +284,6 @@ module Sprockets
114
284
  end
115
285
  end
116
286
 
117
- # Public: Decode Source Map JSON into Ruby objects.
118
- #
119
- # json - String source map JSON
120
- #
121
- # Returns Hash.
122
- def decode_json_source_map(json)
123
- map = JSON.parse(json)
124
- map['mappings'] = decode_vlq_mappings(map['mappings'], sources: map['sources'], names: map['names'])
125
- map
126
- end
127
-
128
- # Public: Encode mappings to Source Map JSON.
129
- #
130
- # mappings - Array of Hash or String VLQ encoded mappings
131
- # sources - Array of String sources
132
- # names - Array of String names
133
- # filename - String filename
134
- #
135
- # Returns JSON String.
136
- def encode_json_source_map(mappings, sources: nil, names: nil, filename: nil)
137
- case mappings
138
- when String
139
- when Array
140
- mappings.each do |m|
141
- m[:source] = PathUtils.relative_path_from(filename, m[:source])
142
- end if filename
143
- sources = sources.map { |s| PathUtils.relative_path_from(filename, s) } if filename && sources
144
- sources = (Array(sources) + mappings.map { |m| m[:source] }).uniq.compact
145
- names ||= mappings.map { |m| m[:name] }.uniq.compact
146
- mappings = encode_vlq_mappings(mappings, sources: sources, names: names)
147
- else
148
- raise TypeError, "could not encode mappings: #{mappings}"
149
- end
150
-
151
- JSON.generate({
152
- "version" => 3,
153
- "file" => filename,
154
- "mappings" => mappings,
155
- "sources" => sources,
156
- "names" => names
157
- })
158
- end
159
-
160
287
  # Public: Decode VLQ mappings and match up sources and symbol names.
161
288
  #
162
289
  # str - VLQ string from 'mappings' attribute
@@ -44,16 +44,22 @@ module Sprockets
44
44
  end
45
45
 
46
46
  def call(input)
47
- if Autoload::Uglifier::VERSION.to_i < 2
48
- raise "uglifier 1.x is no longer supported, please upgrade to 2.x"
47
+ case Autoload::Uglifier::VERSION.to_i
48
+ when 1
49
+ raise "uglifier 1.x is no longer supported, please upgrade to 2.x or newer"
50
+ when 2
51
+ input_options = { source_filename: input[:filename] }
52
+ else
53
+ input_options = { source_map: { filename: input[:filename] } }
49
54
  end
50
- @uglifier ||= Autoload::Uglifier.new(@options)
51
55
 
52
- js, map = @uglifier.compile_with_map(input[:data])
53
- map = SourceMapUtils.combine_source_maps(
54
- input[:metadata][:map],
55
- SourceMapUtils.decode_json_source_map(map)["mappings"]
56
- )
56
+ uglifier = Autoload::Uglifier.new(@options.merge(input_options))
57
+
58
+ js, map = uglifier.compile_with_map(input[:data])
59
+
60
+ map = SourceMapUtils.format_source_map(JSON.parse(map), input)
61
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
62
+
57
63
  { data: js, map: map }
58
64
  end
59
65
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Sprockets
3
- VERSION = "4.0.0.beta4"
3
+ VERSION = "4.0.0.beta5"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sprockets
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.beta4
4
+ version: 4.0.0.beta5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-17 00:00:00.000000000 Z
12
+ date: 2017-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -251,14 +251,14 @@ dependencies:
251
251
  name: uglifier
252
252
  requirement: !ruby/object:Gem::Requirement
253
253
  requirements:
254
- - - "~>"
254
+ - - ">="
255
255
  - !ruby/object:Gem::Version
256
256
  version: '2.3'
257
257
  type: :development
258
258
  prerelease: false
259
259
  version_requirements: !ruby/object:Gem::Requirement
260
260
  requirements:
261
- - - "~>"
261
+ - - ">="
262
262
  - !ruby/object:Gem::Version
263
263
  version: '2.3'
264
264
  - !ruby/object:Gem::Dependency
@@ -353,6 +353,7 @@ files:
353
353
  - lib/sprockets/manifest.rb
354
354
  - lib/sprockets/manifest_utils.rb
355
355
  - lib/sprockets/mime.rb
356
+ - lib/sprockets/npm.rb
356
357
  - lib/sprockets/path_dependency_utils.rb
357
358
  - lib/sprockets/path_digest_utils.rb
358
359
  - lib/sprockets/path_utils.rb
@@ -393,7 +394,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
393
394
  requirements:
394
395
  - - ">="
395
396
  - !ruby/object:Gem::Version
396
- version: 2.0.0
397
+ version: 2.2.0
397
398
  required_rubygems_version: !ruby/object:Gem::Requirement
398
399
  requirements:
399
400
  - - ">"
@@ -401,7 +402,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
401
402
  version: 1.3.1
402
403
  requirements: []
403
404
  rubyforge_project: sprockets
404
- rubygems_version: 2.5.1
405
+ rubygems_version: 2.6.13
405
406
  signing_key:
406
407
  specification_version: 4
407
408
  summary: Rack-based asset packaging system