-
Notifications
You must be signed in to change notification settings - Fork 795
Expand file tree
/
Copy pathgzip.rb
More file actions
99 lines (89 loc) · 3.22 KB
/
Copy pathgzip.rb
File metadata and controls
99 lines (89 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# frozen_string_literal: true
module Sprockets
module Utils
class Gzip
# Private: Generates a gzipped file based off of reference asset.
#
# ZlibArchiver.call(file, source, mtime)
#
# Compresses a given `source` using stdlib Zlib algorithm
# writes contents to the `file` passed in. Sets `mtime` of
# written file to passed in `mtime`
module ZlibArchiver
def self.call(file, source, mtime)
gz = Zlib::GzipWriter.new(file, Zlib::BEST_COMPRESSION)
gz.mtime = mtime
gz.write(source)
gz.close
File.utime(mtime, mtime, file.path)
end
end
# Private: Generates a gzipped file based off of reference asset.
#
# ZopfliArchiver.call(file, source, mtime)
#
# Compresses a given `source` using the zopfli gem
# writes contents to the `file` passed in. Sets `mtime` of
# written file to passed in `mtime`
module ZopfliArchiver
def self.call(file, source, mtime)
compressed_source = Autoload::Zopfli.deflate(source, format: :gzip, mtime: mtime)
file.write(compressed_source)
file.close
nil
end
end
attr_reader :content_type, :source, :charset, :archiver
# Private: Generates a gzipped file based off of reference file.
def initialize(asset, archiver: ZlibArchiver)
@content_type = asset.content_type
@source = asset.source
@charset = asset.charset
@archiver = archiver
end
# What non-text mime types should we compress? This list comes from:
# https://www.fastly.com/blog/new-gzip-settings-and-deciding-what-compress
COMPRESSABLE_MIME_TYPES = {
"application/vnd.ms-fontobject" => true,
"application/x-font-opentype" => true,
"application/x-font-ttf" => true,
"image/x-icon" => true,
"image/svg+xml" => true
}
# Private: Returns whether or not an asset can be compressed.
#
# We want to compress any file that is text based.
# You do not want to compress binary
# files as they may already be compressed and running them
# through a compression algorithm would make them larger.
#
# Return Boolean.
def can_compress?
# The "charset" of a mime type is present if the value is
# encoded text. We can check this value to see if the asset
# can be compressed.
#
# We also check against our list of non-text compressible mime types
@charset || COMPRESSABLE_MIME_TYPES.include?(@content_type)
end
# Private: Opposite of `can_compress?`.
#
# Returns Boolean.
def cannot_compress?
!can_compress?
end
# Private: Generates a gzipped file based off of reference asset.
#
# Compresses the target asset's contents and puts it into a file with
# the same name plus a `.gz` extension in the same folder as the original.
# Does not modify the target asset.
#
# Returns nothing.
def compress(file, target)
mtime = Sprockets::PathUtils.stat(target).mtime
archiver.call(file, source, mtime)
nil
end
end
end
end