squash_javascript 1.0.3 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- Yzg2ZTI5ZWVkNzI4NmQ4NzQ3MzA5OTc4ZGJlNGE0OGNjZDdlMGY4Yw==
5
- data.tar.gz: !binary |-
6
- NWVkMTA3NTMzYTQyZDExYjlmMDdiNzNmNDJhM2IzMTgxNjYzMmM4NA==
2
+ SHA1:
3
+ metadata.gz: f8d9f1fd8dff2720d5a08a2842c3d47b7432f43f
4
+ data.tar.gz: 39c29285f2daca8d0caf179d33fd99d0dd7504c9
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NGU0MmQ1MDc5MjNjNTYzNDlkZmY2Mzk0NmRhNWQwNGEwMDRkOWQ5ZTBmNGVl
10
- OWI3ZTkyZDgyMmMzNjg1OTdjMGI0NTc5OWIwMzdlMGNmMzQ1OGMwMGZjZjI1
11
- ODc0MjE1NzA0NjkwMmU2ZGM5YjAzZjAyNmI0ZDAxYTRjMzEwYmI=
12
- data.tar.gz: !binary |-
13
- MzhkODM0MzVmNjM0YmI4NTE2NmRmNzcxODZmOTVhODU1NmUzZmI1NjkwNmRj
14
- NDA0ZjQxOWE0NmM0NmVlZDBmNzZlM2EwMGEwMzJhZDk2ODk1YTIwOWI0ZDgz
15
- ODNlNzkzNzNiMWZkOTk2MDNkNjU5Y2ZhYjBlZWU1NmE5NWQ3OTk=
6
+ metadata.gz: d6a8223c1f281122cb38da8c24cd68bd2574bd21372dd3a1541181375835f9cb84d510d525327bcae127388f0e2c24e1302ce3eaeaac36bfee189f51c8e01033
7
+ data.tar.gz: 4938f74e4e02ed2afa346bc5463a0e2f93edf9b1cea24a95ac74ad452edc1ad1ec4b70eeac6c972b116eef32888a086e33efb9139efb8f6b7af48ecb8a92fe48
data/README.md CHANGED
@@ -42,11 +42,15 @@ The library is included in this project. For Rails projects, a Sprockets include
42
42
  file is provided. For non-Rails projects, the output of `rake minify` rolls in
43
43
  the library.
44
44
 
45
- Unfortunately, TraceKit was causing unexpected behavior on Chrome and Firefox,
46
- and parts of it are commented out. (The jQuery hooks were disabled.)
45
+ **The included version of TraceKit has been modified somewhat:**
46
+
47
+ * `window.onerror` support was expanded to include changes in recent versions of
48
+ modern browsers (namely, passing the column and error object as parameters).
49
+ * TraceKit was causing unexpected behavior on Chrome and Firefox, and parts of
50
+ it are commented out. (The jQuery hooks were disabled.)
47
51
 
48
52
  Installation
49
- -----
53
+ ------------
50
54
 
51
55
  ### Rails
52
56
 
@@ -252,20 +256,57 @@ still be re-raised, but the failsafe error will be "eaten."
252
256
  Source Mapping
253
257
  --------------
254
258
 
255
- If you can generate a source map for your minified JavaScript files (Clojure
259
+ ### Rails and Sprockets
260
+
261
+ Squash JavaScript can integrate with Sprockets to automatically generate source
262
+ maps for each stage of the asset compilation pipeline, then integrate with
263
+ Capistrano to upload the source maps to Squash. To use this feature, configure
264
+ your project like so:
265
+
266
+ 1. Replace your JavaScript compiler gem with Closure, if you aren't already
267
+ using it.
268
+
269
+ ```` diff
270
+ -gem 'uglifier'
271
+ +gem 'closure-compiler'
272
+ ````
273
+
274
+ 2. Use Squash's source-mapping Tilt engines for CoffeeScript and JavaScript.
275
+
276
+ These Tilt engines wrap existing Tilt template engines, but also generate
277
+ source maps to `tmp/sourcemaps`.
278
+
279
+ ```` ruby
280
+ Sprockets.register_engine '.coffee', Squash::Javascript::SourceMappingCoffeescriptTemplate
281
+ config.assets.js_compressor = Squash::Javascript::SourceMappingJavascriptMinifier
282
+ ````
283
+
284
+ 3. Add the Squash Capistrano tasks to your Capfile:
285
+
286
+ ```` ruby
287
+ require 'squash/javascript/capistrano'
288
+ ````
289
+
290
+ If you do not use Capistrano 3, you can use the `rake sourcemaps:upload:all`
291
+ task to upload your generated source maps to Squash.
292
+
293
+ ### Other Projects
294
+
295
+ If you can generate a source map for your minified JavaScript files (Closure
256
296
  can), you can use this gem to upload that source map to Squash, where it will
257
297
  be used to convert minified stack traces to their original format, which can
258
298
  then benefit from Git-blaming, context, and other features of Squash.
259
299
 
260
300
  To upload the source map to squash, run the `upload_source_map` binary included
261
- with this gem, and pass it four arguments: 1) your API key, 2) the environment
262
- name, 3) the path to the JSON source map, and 4) the URL where this file will be
263
- hosted. Example:
301
+ with this gem, and pass it four arguments: 1) your Squash host, 2) your API key,
302
+ 3) the environment name, and 4) the path to the JSON source map. Example:
264
303
 
265
304
  ````
266
- upload_source_map abc-123-abc-123-abc-123 production artifacts/mapping.json https://my.application/assets/minified.js
305
+ upload_source_map http://your.squash.host abc-123-abc-123-abc-123 production artifacts/mapping.json
267
306
  ````
268
307
 
308
+ Use `--help` to learn about additional options.
309
+
269
310
  Specs
270
311
  -----
271
312
 
@@ -36,9 +36,15 @@ project_dir = Dir.getwd
36
36
  ignore_root = false
37
37
  revision = nil
38
38
  options = {}
39
+ from = 'hosted'
40
+ to = 'original'
39
41
 
40
42
  parser = OptionParser.new do |parser|
41
- parser.banner = "Usage: upload_source_map [options] YOUR_SQUASH_HOST YOUR_API_KEY ENVIRONMENT /path/to/mapping.json https://url.for/minified/asset.js"
43
+ parser.banner = "Usage: upload_source_map [options] YOUR_SQUASH_HOST YOUR_API_KEY ENVIRONMENT /path/to/mapping.json"
44
+
45
+ parser.on('-f', '--from S', "The type of stack trace element this source map converts from (hosted [default], concatenated, etc.)") { |f| from = f }
46
+ parser.on('-t', '--to S', "The type of stack trace element this source map converts to (compiled, original [default], coffee, etc.)") { |t| to = t }
47
+
42
48
  parser.on('-o', '--open-timeout N', Integer, "HTTP connection open timeout") { |ot| options[:open_timeout] = ot }
43
49
  parser.on('-r', '--read-timeout N', Integer, "HTTP connection data received timeout") { |rt| options[:read_timeout] = rt }
44
50
  parser.on('-k', '--[no-]skip-verification', "Do not perform SSL peer verification") { |sv| options[:skip_verification] = sv }
@@ -62,14 +68,14 @@ host = ARGV.shift
62
68
  api_key = ARGV.shift
63
69
  environment = ARGV.shift
64
70
  map_file = ARGV.shift
65
- route = ARGV.shift
66
71
  revision = revision || git_revision(project_dir)
67
72
 
68
- map = Squash::Javascript::SourceMap.from_sourcemap(map_file, route, root: ignore_root ? project_dir : nil)
69
73
  Squash::Uploader.new(host, options).transmit '/api/1.0/sourcemap.json',
70
74
  {
71
75
  'api_key' => api_key,
72
76
  'environment' => environment,
73
77
  'revision' => revision,
74
- 'sourcemap' => Base64.encode64(Zlib::Deflate.deflate(map.to_yaml))
78
+ 'sourcemap' => Base64.encode64(Zlib::Deflate.deflate(File.read(map_file))),
79
+ 'from' => from,
80
+ 'to' => to
75
81
  }
@@ -0,0 +1,16 @@
1
+ # Copyright 2014 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ load(File.dirname(__FILE__) + '/../../tasks/squash.cap')
16
+
@@ -0,0 +1,33 @@
1
+ require 'source_map'
2
+ require 'sprockets'
3
+
4
+ # @private
5
+ class Sprockets::Asset
6
+ def sourcemap
7
+ relative_path = if pathname.to_s.include?(Rails.root.to_s)
8
+ pathname.relative_path_from(Rails.root)
9
+ else
10
+ pathname
11
+ end.to_s
12
+ # any extensions after the ".js" can be removed, because they will have
13
+ # already been processed
14
+ relative_path.gsub! /(?<=\.js)\..*$/, ''
15
+ resource_path = [Rails.application.config.assets.prefix, logical_path].join('/')
16
+
17
+ mappings = Array.new
18
+ to_s.lines.each_with_index do |_, index|
19
+ offset = SourceMap::Offset.new(index, 0)
20
+ mappings << SourceMap::Mapping.new(relative_path, offset, offset)
21
+ end
22
+ SourceMap::Map.new(mappings, resource_path)
23
+ end
24
+ end
25
+
26
+ # @private
27
+ class Sprockets::BundledAsset < Sprockets::Asset
28
+ def sourcemap
29
+ to_a.inject(SourceMap::Map.new) do |map, asset|
30
+ map + asset.sourcemap
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ class Squash::Javascript::Railtie < Rails::Railtie
2
+ rake_tasks do
3
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rake')].each { |f| load f }
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ require 'digest/sha2'
2
+
3
+ class Squash::Javascript::SourceMappingCoffeescriptTemplate < Tilt::CoffeeScriptTemplate
4
+ def evaluate(scope, locals, &block)
5
+ @output ||= begin
6
+ result = CoffeeScript.compile(data, options.merge(sourceMap: true))
7
+
8
+ relative_path = if file.include?(Rails.root.to_s)
9
+ Pathname.new(file).relative_path_from(Rails.root)
10
+ else
11
+ Pathname.new(file)
12
+ end
13
+
14
+ map = JSON.parse(result['v3SourceMap'])
15
+ map['file'] = relative_path.to_s.sub(/\.coffee$/, '')
16
+ map['sources'] = [relative_path.to_s]
17
+
18
+ map_path = Rails.root.join('tmp', 'sourcemaps', 'compiled', Digest::SHA2.hexdigest(relative_path.to_s) + '.json')
19
+ FileUtils.mkdir_p map_path.dirname
20
+ Rails.root.join('tmp', 'sourcemaps', map_path).open('w') do |f|
21
+ f.puts map.to_json
22
+ end
23
+
24
+ result['js']
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'digest/md5'
2
+
3
+ class Squash::Javascript::SourceMappingJavascriptMinifier < Tilt::Template
4
+ def prepare() end
5
+
6
+ def evaluate(context, locals)
7
+ source_map_file = Tempfile.new('sourcemap')
8
+ compressor = Closure::Compiler.new(create_source_map: source_map_file.path)
9
+ minified = compressor.compress(data)
10
+
11
+ minified_file = Tempfile.new('minified')
12
+ minified_file.write minified
13
+
14
+ map = JSON.parse(source_map_file.read)
15
+ minified_filename = [Rails.application.config.assets.prefix, "#{context.logical_path}-#{digest(minified)}.js"].join('/')
16
+ concatenated_filename = [Rails.application.config.assets.prefix, "#{context.logical_path}.js"].join('/')
17
+ map['file'] = minified_filename
18
+ map['sources'] = [concatenated_filename]
19
+
20
+ path = source_map_path(digest(minified))
21
+ FileUtils.mkdir_p path.dirname
22
+ File.open(path, 'w') { |f| f.puts map.to_json }
23
+
24
+ return minified
25
+ end
26
+
27
+ private
28
+
29
+ def digest(io)
30
+ Rails.application.assets.digest.update(io).hexdigest
31
+ end
32
+
33
+ def source_map_path(digest)
34
+ Rails.root.join 'tmp', 'sourcemaps', 'minified', "#{digest}.json"
35
+ end
36
+ end
@@ -0,0 +1,73 @@
1
+ require 'squash/uploader'
2
+
3
+ namespace :sourcemaps do
4
+ namespace :upload do
5
+ task all: [:minified, :concatenated, :compiled]
6
+
7
+ task minified: :environment do
8
+ manifest_path = Rails.root.join('public',
9
+ Rails.application.config.assets.prefix.sub(/^\//, ''),
10
+ 'manifest-*.json')
11
+ manifest_path = Dir.glob(manifest_path.to_s).first
12
+ raise "You must precompile your static assets before running this task." unless manifest_path
13
+
14
+ manifest = JSON.parse(File.read(manifest_path))
15
+ manifest['files'].each do |path, metadata|
16
+ sourcemap_path = Rails.root.join('tmp', 'sourcemaps', 'minified', "#{metadata['digest']}.json")
17
+ if sourcemap_path.exist?
18
+ Squash::Uploader.new(Squash::Ruby.configuration(:api_host),
19
+ skip_verification: Squash::Ruby.configuration(:skip_verification)
20
+ ).transmit '/api/1.0/sourcemap.json',
21
+ {
22
+ 'api_key' => Squash::Ruby.configuration(:api_key),
23
+ 'environment' => Rails.env,
24
+ 'revision' => Squash::Ruby.current_revision,
25
+ 'sourcemap' => Base64.encode64(Zlib::Deflate.deflate(File.read(sourcemap_path))),
26
+ 'from' => 'hosted',
27
+ 'to' => 'concatenated'
28
+ }
29
+ end
30
+ end
31
+ end
32
+
33
+ task concatenated: :environment do
34
+ Rails.application.assets.each_logical_path(Rails.application.config.assets.precompile) do |path|
35
+ next unless path.end_with?('.js')
36
+ asset = Rails.application.assets.find_asset(path)
37
+ next unless asset.kind_of?(Sprockets::BundledAsset)
38
+ map = asset.sourcemap
39
+ Squash::Uploader.new(Squash::Ruby.configuration(:api_host),
40
+ skip_verification: Squash::Ruby.configuration(:skip_verification)
41
+ ).transmit '/api/1.0/sourcemap.json',
42
+ {
43
+ 'api_key' => Squash::Ruby.configuration(:api_key),
44
+ 'environment' => Rails.env,
45
+ 'revision' => Squash::Ruby.current_revision,
46
+ 'sourcemap' => Base64.encode64(Zlib::Deflate.deflate(map.as_json.to_json)),
47
+ 'from' => 'concatenated',
48
+ 'to' => 'compiled',
49
+ }
50
+ end
51
+ end
52
+
53
+ task compiled: :environment do
54
+ Dir.glob(Rails.root.join('tmp', 'sourcemaps', 'compiled', '*.json')).each do |file|
55
+ Squash::Uploader.new(Squash::Ruby.configuration(:api_host),
56
+ skip_verification: Squash::Ruby.configuration(:skip_verification)
57
+ ).transmit '/api/1.0/sourcemap.json',
58
+ {
59
+ 'api_key' => Squash::Ruby.configuration(:api_key),
60
+ 'environment' => Rails.env,
61
+ 'revision' => Squash::Ruby.current_revision,
62
+ 'sourcemap' => Base64.encode64(Zlib::Deflate.deflate(File.read(file))),
63
+ 'from' => 'compiled',
64
+ 'to' => 'original'
65
+ }
66
+ end
67
+ end
68
+ end
69
+
70
+ task :clean do
71
+ system 'rm', '-rf', 'tmp/sourcemaps/*'
72
+ end
73
+ end
@@ -22,5 +22,8 @@ module Squash
22
22
  end
23
23
  end
24
24
 
25
- require 'squash/javascript/source_map'
25
+ require 'squash/javascript/patches'
26
+ require 'squash/javascript/source_mapping_coffeescript_template'
27
+ require 'squash/javascript/source_mapping_javascript_minifier'
26
28
  require 'squash/javascript/engine'
29
+ require 'squash/javascript/railtie'
@@ -0,0 +1,30 @@
1
+ # Copyright 2014 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ namespace :squash do
16
+ namespace :sourcemaps do
17
+ desc "Uploads JavaScript source maps to Squash"
18
+ task :upload do
19
+ on roles(:web), limit: 1 do
20
+ within release_path do
21
+ with rails_env: fetch(:rails_env) do
22
+ rake 'sourcemaps:upload:all'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ after 'deploy:finishing', 'squash:sourcemaps:upload'
@@ -203,7 +203,7 @@ class _SquashJavascript
203
203
  for line in stack
204
204
  context = line.context
205
205
  context = null if context && any(context, (cline) -> cline && cline.length > 200)
206
- backtraces.push {url: line.url, line: line.line, column: line.column, symbol: line.func, context: context, type: 'minified'}
206
+ backtraces.push {url: line.url, line: line.line, column: line.column, symbol: line.func, context: context, type: 'js:hosted'}
207
207
  return [ {name: "Active Thread", faulted: true, backtrace: backtraces} ]
208
208
 
209
209
  ISODateString = (d) ->