module Jekyll::Zopfli::Compressor
The module that does the compressing using Zopfli
.
Public Class Methods
Takes a directory path and maps over the files within compressing them in place.
@example
Jekyll::Zopfli::Compressor.compress_directory("~/blog/_site", site)
@param dir [Pathname, String] The path to a directory of files ready for
compression.
@param site [Jekyll::Site] An instance of the `Jekyll::Site` used for
config.
@return void
# File lib/jekyll/zopfli/compressor.rb, line 51 def self.compress_directory(dir, site) extensions = zippable_extensions(site).join(',') files = Dir.glob(File.join(dir, "**", "*{#{extensions}}")) 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 compressed using Zopfli
, outputting the gzipped file under the name of the original file with an extra .gz extension.
@example
Jekyll::Zopfli::Compressor.compress_file("~/blog/_site/index.html", ['.html')
@param file_name [String] The file name of the file we want to compress @param extensions [Array<String>] The extensions of files that will be
compressed.
@param replace_file [Boolean] Whether the original file should be
replaced or written alongside the original with a `.gz` extension
@return void
# File lib/jekyll/zopfli/compressor.rb, line 81 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.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
Takes an instance of Jekyll::Site
and maps over the site files compressing them in the destination directory. @example
site = Jekyll::Site.new(site_config) Jekyll::Zopfli::Compressor.compress_site(site)
@param site [Jekyll::Site] A Jekyll::Site object that has generated its
site files ready for compression.
@return void
# File lib/jekyll/zopfli/compressor.rb, line 26 def self.compress_site(site) site.each_site_file do |file| 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
Private Class Methods
First two bytes of a gzipped file are 1f and 8b. This tests for those bytes.
# File lib/jekyll/zopfli/compressor.rb, line 123 def self.is_already_gzipped?(file) ["1f", "8b"] == File.read(file, 2).unpack("H2H2") end
Compresses the file if the site is built incrementally and the source was modified or the compressed file doesn't exist
# File lib/jekyll/zopfli/compressor.rb, line 107 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
# File lib/jekyll/zopfli/compressor.rb, line 97 def self.replace_files(site) site.config.dig("zopfli", "replace_files") || Jekyll::Zopfli::DEFAULT_CONFIG.fetch("replace_files") end
# File lib/jekyll/zopfli/compressor.rb, line 93 def self.zippable_extensions(site) site.config.dig("zopfli", "extensions") || Jekyll::Zopfli::DEFAULT_CONFIG.fetch("extensions") end
# File lib/jekyll/zopfli/compressor.rb, line 101 def self.zipped(file_name, replace_file) replace_file ? file_name : "#{file_name}.gz" end