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 +5 -13
- data/README.md +49 -8
- data/bin/upload_source_map +10 -4
- data/lib/squash/javascript/capistrano.rb +16 -0
- data/lib/squash/javascript/patches.rb +33 -0
- data/lib/squash/javascript/railtie.rb +5 -0
- data/lib/squash/javascript/source_mapping_coffeescript_template.rb +27 -0
- data/lib/squash/javascript/source_mapping_javascript_minifier.rb +36 -0
- data/lib/squash/javascript/tasks/sourcemaps.rake +73 -0
- data/lib/squash/javascript.rb +4 -1
- data/lib/tasks/squash.cap +30 -0
- data/vendor/assets/javascripts/squash_javascript/{client.coffee → client.js.coffee} +1 -1
- data/vendor/assets/javascripts/squash_javascript/tracekit.js +1000 -996
- data/vendor/assets/javascripts/squash_javascript.min.js +24 -24
- data/vendor/assets/javascripts/squash_javascript.orig.js +1 -1
- metadata +47 -29
- data/lib/squash/javascript/source_map.rb +0 -181
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NWVkMTA3NTMzYTQyZDExYjlmMDdiNzNmNDJhM2IzMTgxNjYzMmM4NA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f8d9f1fd8dff2720d5a08a2842c3d47b7432f43f
|
4
|
+
data.tar.gz: 39c29285f2daca8d0caf179d33fd99d0dd7504c9
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
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
|
262
|
-
|
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
|
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
|
|
data/bin/upload_source_map
CHANGED
@@ -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
|
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(
|
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,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
|
data/lib/squash/javascript.rb
CHANGED
@@ -22,5 +22,8 @@ module Squash
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
require 'squash/javascript/
|
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: '
|
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) ->
|