class Jekyll::Minibundle::AssetBundle

Constants

TEMPFILE_PREFIX

Public Class Methods

new(config) click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
12     def initialize(config)
13       @type = config.fetch(:type)
14       @asset_paths = config.fetch(:asset_paths)
15       @destination_path = config.fetch(:destination_path)
16       @site_dir = config.fetch(:site_dir)
17       @minifier_cmd = config.fetch(:minifier_cmd)
18 
19       unless @minifier_cmd
20         raise <<~MESSAGE
21           Missing minification command for bundling #{bundle_destination_path.inspect}. Specify it in
22           1) minibundle.minifier_commands.#{@type} setting in _config.yml,
23           2) $JEKYLL_MINIBUNDLE_CMD_#{@type.to_s.upcase} environment variable, or
24           3) minifier_cmd setting inside minibundle block.
25         MESSAGE
26       end
27 
28       @tempfile = Tempfile.new([TEMPFILE_PREFIX, ".#{@type}"])
29     end

Public Instance Methods

close() click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
31 def close
32   @tempfile.close!
33   @tempfile = nil
34 end
make_bundle() click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
42 def make_bundle
43   raise IllegalStateError, 'Cannot make bundle with closed AssetBundle' unless @tempfile
44 
45   exit_status = spawn_minifier(@minifier_cmd) do |input|
46     $stdout.puts  # place newline after "(Re)generating..." log messages
47     Log.info("Bundling #{bundle_destination_path}:")
48     @asset_paths.each do |asset|
49       Log.info(" #{relative_path_from(asset, @site_dir)}")
50       IO.foreach(asset) { |line| input.write(line) }
51       input.puts(';') if @type == :js
52     end
53   end
54 
55   if exit_status != 0
56     msg = "Bundling #{bundle_destination_path.inspect} failed with exit status #{exit_status}, command: #{@minifier_cmd.inspect}"
57     log_minifier_error(msg)
58     raise msg
59   end
60 
61   self
62 end
path() click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
36 def path
37   raise IllegalStateError, 'Cannot get path of closed AssetBundle' unless @tempfile
38 
39   @tempfile.path
40 end

Private Instance Methods

bundle_destination_path() click to toggle source
    # File lib/jekyll/minibundle/asset_bundle.rb
100 def bundle_destination_path
101   "#{@destination_path}.#{@type}"
102 end
log_minifier_error(message) click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
87 def log_minifier_error(message)
88   last_bytes = Files.read_last(@tempfile.path, 2000)
89 
90   return if last_bytes.empty?
91 
92   Log.error("#{message}, last #{last_bytes.size} bytes of minifier output:")
93 
94   last_bytes
95     .gsub(/[^[:print:]\t\n]/) { |ch| "\\x#{ch.unpack1('H2')}" }
96     .split("\n")
97     .each { |line| Log.error(line) }
98 end
relative_path_from(path, base) click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
66 def relative_path_from(path, base)
67   path.sub(%r{\A#{base}/}, '')
68 end
spawn_minifier(cmd) { |wr| ... } click to toggle source
   # File lib/jekyll/minibundle/asset_bundle.rb
70 def spawn_minifier(cmd)
71   pid = nil
72   rd, wr = IO.pipe
73   Dir.chdir(@site_dir) do
74     pid = spawn(cmd, out: [@tempfile.path, 'w'], in: rd)
75   end
76   rd.close
77   yield wr
78   wr.close
79   _, status = Process.waitpid2(pid)
80   status.exitstatus
81 rescue StandardError => e
82   raise "Bundling #{bundle_destination_path.inspect} failed: #{e}"
83 ensure
84   [rd, wr].each { |io| io.close unless io.closed? }
85 end