|
| 1 | +require 'open3' |
| 2 | + |
| 3 | +module Jekyll |
| 4 | + # Generates .webp siblings for every .png / .jpg / .jpeg in the rendered |
| 5 | + # site under assets/img/. Runs on :site, :post_write so it sees the |
| 6 | + # final destination paths Jekyll just copied — no source-tree pollution, |
| 7 | + # no clash with the existing pngquant'd PNGs. |
| 8 | + # |
| 9 | + # Requires the `cwebp` binary (Google's libwebp encoder): |
| 10 | + # - macOS: brew install webp |
| 11 | + # - Ubuntu: apt-get install -y webp |
| 12 | + # |
| 13 | + # If cwebp isn't on PATH the plugin warns once and skips. WebP siblings are |
| 14 | + # still useful to have on disk — `<picture>` markup that prefers them is a |
| 15 | + # follow-up, kept out of this PR per the SEO/OG validator caveat. |
| 16 | + Jekyll::Hooks.register :site, :post_write do |site| |
| 17 | + img_dir = File.join(site.dest, 'assets', 'img') |
| 18 | + next unless File.directory?(img_dir) |
| 19 | + |
| 20 | + unless system('which cwebp > /dev/null 2>&1') |
| 21 | + Jekyll.logger.warn 'WebpGenerator:', 'cwebp not found on PATH — skipping WebP generation' |
| 22 | + next |
| 23 | + end |
| 24 | + |
| 25 | + converted = 0 |
| 26 | + skipped = 0 |
| 27 | + # FNM_CASEFOLD so we match .PNG/.JPG too without double-counting on |
| 28 | + # case-insensitive filesystems (macOS default APFS). |
| 29 | + Dir.glob(File.join(img_dir, '*.{png,jpg,jpeg}'), File::FNM_CASEFOLD).each do |src| |
| 30 | + webp = src.sub(/\.(png|jpe?g)\z/i, '.webp') |
| 31 | + if File.exist?(webp) && File.mtime(webp) >= File.mtime(src) |
| 32 | + skipped += 1 |
| 33 | + next |
| 34 | + end |
| 35 | + _, status = Open3.capture2e('cwebp', '-quiet', '-q', '80', src, '-o', webp) |
| 36 | + if status.success? |
| 37 | + converted += 1 |
| 38 | + else |
| 39 | + Jekyll.logger.warn 'WebpGenerator:', "cwebp failed on #{File.basename(src)}" |
| 40 | + end |
| 41 | + end |
| 42 | + |
| 43 | + Jekyll.logger.info 'WebpGenerator:', "converted #{converted}, skipped #{skipped} (already up to date)" |
| 44 | + end |
| 45 | +end |
0 commit comments