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