lib/jekyll/zopfli/compressor.rb in jekyll-zopfli-2.3.0 vs lib/jekyll/zopfli/compressor.rb in jekyll-zopfli-2.4.0
- old
+ new
@@ -23,11 +23,17 @@
# site files ready for compression.
#
# @return void
def self.compress_site(site)
site.each_site_file do |file|
- compress_file(file.destination(site.dest), extensions: zippable_extensions(site), replace_file: replace_files(site))
+ next unless regenerate? file.destination(site.dest), site
+
+ compress_file(
+ file.destination(site.dest),
+ extensions: zippable_extensions(site),
+ replace_file: replace_files(site)
+ )
end
end
##
# Takes a directory path and maps over the files within compressing them
@@ -43,11 +49,19 @@
#
# @return void
def self.compress_directory(dir, site)
extensions = zippable_extensions(site).join(',')
files = Dir.glob(dir + "/**/*{#{extensions}}")
- files.each { |file| compress_file(file, extensions: zippable_extensions(site), replace_file: replace_files(site)) }
+ files.each do |file|
+ next unless regenerate? file, site
+
+ compress_file(
+ file,
+ extensions: zippable_extensions(site),
+ replace_file: replace_files(site)
+ )
+ end
end
##
# Takes a file name and an array of extensions. If the file name extension
# matches one of the extensions in the array then the file is loaded and
@@ -65,11 +79,11 @@
#
# @return void
def self.compress_file(file_name, extensions: [], replace_file: false)
return unless extensions.include?(File.extname(file_name))
zipped = replace_file ? file_name : "#{file_name}.gz"
- contents = ::Zopfli.deflate(File.read(file_name), format: :gzip)
+ contents = ::Zopfli.deflate(File.binread(file_name), format: :gzip)
File.open(zipped, "w+") do |file|
file << contents
end
File.utime(File.atime(file_name), File.mtime(file_name), zipped)
end
@@ -81,9 +95,35 @@
end
def self.replace_files(site)
replace_files = site.config.dig('zopfli', 'replace_files')
replace_files.nil? ? Jekyll::Zopfli::DEFAULT_CONFIG['replace_files'] : replace_files
+ end
+
+ def self.zipped(file_name, replace_file)
+ replace_file ? file_name : "#{file_name}.gz"
+ end
+
+ # Compresses the file if the site is built incrementally and the
+ # source was modified or the compressed file doesn't exist
+ def self.regenerate?(file, site)
+ zipped = zipped(file, replace_files(site))
+
+ # Definitely generate the file if it doesn't exist yet.
+ return true unless File.exist? zipped
+ # If we are replacing files and this file is not a gzip file, then it
+ # has been edited so we need to re-gzip it in place.
+ return !is_already_gzipped?(file) if replace_files(site)
+
+ # If the modified time of the new file is greater than the modified time
+ # of the old file, then we need to regenerate.
+ File.mtime(file) > File.mtime(zipped)
+ end
+
+ # First two bytes of a gzipped file are 1f and 8b. This tests for those
+ # bytes.
+ def self.is_already_gzipped?(file)
+ ["1f", "8b"] == File.read(file, 2).unpack("H2H2")
end
end
end
end