jekyll-compress-flow 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00c00c4a18a5ad58211bbaee01455e9973f9e238ce9795e426435405e9caf0ad
4
- data.tar.gz: de0178bae5907891dff7f0eb65337df6333b958a5108f1e4f138f229c3776300
3
+ metadata.gz: 7698a216c6b11cc78eb4dbf1fc8642b3b76e41dcb93a3f0f6e72ed939207a9ab
4
+ data.tar.gz: 50876d915cc373992f28fff651357c468bd9306e9651e7a280ec7e81a531825d
5
5
  SHA512:
6
- metadata.gz: 98e314c5f525eea612d4c04301c1bbe81fea6e9355820d4c348b60bde68d9d3deb6eee7e1ebdc344da1b316ecccd3cbaab725f9a720505abb3856d764c4ecfc5
7
- data.tar.gz: 1dbad2fcdde09b6b07c49b4d6652ea10fa49e7cbdd368ff6bb20c75cd3b0e62dd9869e5d5cd13086cefe1af6eb5de543af0bb3bc69f5a280b8c2315134703685
6
+ metadata.gz: 7f862ea2ee85d52f9b58e8abb5b79808cca7ec951c69fb1ab80fd3a81085292e3084e9ac7ddef365ebad1fdc75971905600adeab6f2a341d2425c3d5aacd9e1d
7
+ data.tar.gz: 7a750ebe879c078a28224ae84d3ec738f273b567c562f3a78face1625ce5b005b78d23b37119731a85c13f34a1f36536472d28f884b4af2a52ba13cfa89ad5a1
data/CHANGELOG.md CHANGED
@@ -4,6 +4,46 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## 0.2.2 — 2026-11-10
8
+
9
+ ### Added
10
+
11
+ - `rake docs:demo` — captures the checked-in illustrative overview as
12
+ animated AVIF + WebP + static PNG (headless Chrome + ffmpeg + img2webp;
13
+ build-host tools), embedded in README via `<picture>`. Examples are
14
+ schematic, not generated from a live Jekyll build.
15
+
16
+ ### Changed
17
+
18
+ - CI: Semgrep moved from an inline `pip3 install` pin to the pinned
19
+ `semgrep/semgrep` container image (tag + sha256 digest). Image bumped
20
+ to 1.182.1 (certificate trust fix for the eMudhra CA compromise).
21
+ CI Node bumped from 24 to 26 (Active LTS "Lithium" since 2026-10-28).
22
+ - CI: `sonarqube-scan-action` bumped to v8.4.0; `markdownlint-cli2`
23
+ bumped to 0.24.0; `ruby/setup-ruby` v1.335.0 → v1.338.0; in-range
24
+ gem updates (rubocop 1.92.2, parser 3.3.13.0, addressable 2.9.2,
25
+ csv 3.3.7, sass-embedded 1.108.1, rspec-* 3.13.x patches);
26
+ `BUNDLED WITH` 4.0.23 → 4.0.24.
27
+ - CI: Ruby 4.0 added to the test matrix (latest stable major;
28
+ `required_ruby_version >= 3.3.0` already permits it).
29
+ - Gemspec `description` rewritten as an RDoc `==`-headed blurb so
30
+ rubygems.org renders it as markup instead of a single plain paragraph.
31
+
32
+ ## 0.2.1 — 2026-10-06
33
+
34
+ ### Added
35
+
36
+ - `Jekyll::CompressFlow::Interface.to_h` — the config surface
37
+ (`compress_flow` keys plus `formats:`/`priority:` enums) derived from
38
+ `DEFAULTS`, serialized to a committed `interface.yml` by
39
+ `rake interface`; `interface_spec.rb` pins manifest freshness.
40
+
41
+ ### Changed
42
+
43
+ - Register the compression dispatcher at low priority (10) by default, after
44
+ normal-priority processing and Fingerprint Flow (default 12); allow per-site
45
+ `compress_flow.priority` values from 0 through 10.
46
+
7
47
  ## 0.2.0 — 2026-10-03
8
48
 
9
49
  ### Added
data/README.md CHANGED
@@ -25,6 +25,19 @@ simply happens at build time instead of request time.
25
25
 
26
26
  [Compare different formats](https://speedvitals.com/blog/zstd-vs-brotli-vs-gzip/)
27
27
 
28
+ <!-- markdownlint-disable MD033 -->
29
+ <picture>
30
+ <source
31
+ srcset="docs/assets/jekyll-compress-flow-demo.avif"
32
+ type="image/avif">
33
+ <source
34
+ srcset="docs/assets/jekyll-compress-flow-demo.webp"
35
+ type="image/webp">
36
+ <img src="docs/assets/jekyll-compress-flow-demo.png"
37
+ alt="jekyll-compress-flow demo">
38
+ </picture>
39
+ <!-- markdownlint-enable MD033 -->
40
+
28
41
  ## Prerequisites
29
42
 
30
43
  The plugin shells out to the platform compressor CLIs — install them on
@@ -32,7 +45,7 @@ the **build host** (not the web server; visitors need nothing):
32
45
 
33
46
  | Tool | Generates | Minimum | Tested baseline |
34
47
  | ---- | --------- | ------- | --------------- |
35
- | `brotli` | `.br` | 1.1.0 | 1.2.0 (macOS) |
48
+ | `brotli` | `.br` | 1.1.0 | 1.2.1 (macOS) |
36
49
  | `zstd` | `.zst` | 1.5.5 | 1.5.7 (macOS) |
37
50
  | `gzip` | `.gz` | any | preinstalled on macOS/Linux; ships with Git for Windows |
38
51
 
@@ -124,16 +137,22 @@ configured to negotiate them via `Accept-Encoding`:
124
137
  ```yaml
125
138
  compress_flow:
126
139
  enabled: true # default: Jekyll.env == "production"
140
+ priority: 10 # integer 0..10; default 10, after fingerprinting
127
141
  formats: [br, zst, gz] # subset of the three; unknown names abort
128
142
  extensions: [html, css, js, json, xml, svg, txt, map]
129
143
  min_size: 0 # bytes — skip tiny files
130
144
  fail_on_error: true # false: warn + skip instead of failing build
131
145
  ```
132
146
 
147
+ The post-write dispatcher accepts integer priorities from 0 through 10 so
148
+ site-specific compression remains after the default Fingerprint Flow range
149
+ (11–19).
150
+
133
151
  ## Behavior
134
152
 
135
- - Runs on `:site, :post_write`, after every file is written — works
136
- with any generator (pages, posts, feeds, sitemap, search JSON).
153
+ - Runs on `:site, :post_write` at low priority (10), after normal-priority
154
+ post-processors and the priority-12 Fingerprint Flow pass — works with any
155
+ generator (pages, posts, feeds, sitemap, search JSON).
137
156
  - Compressed siblings are never re-compressed (extensions not in the
138
157
  list); images/fonts/PDFs are skipped (already compressed formats).
139
158
  - A missing CLI tool aborts the build once per format
data/interface.yml ADDED
@@ -0,0 +1,20 @@
1
+ # Generated by `rake interface` — do not edit.
2
+ # Public tag/config surface for tooling (editor extensions, doc linters).
3
+ ---
4
+ gem: jekyll-compress-flow
5
+ version: 0.2.2
6
+ tags: {}
7
+ filters: []
8
+ config:
9
+ compress_flow:
10
+ - enabled
11
+ - extensions
12
+ - fail_on_error
13
+ - formats
14
+ - min_size
15
+ - priority
16
+ enums:
17
+ formats:
18
+ - br
19
+ - gz
20
+ - zst
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module CompressFlow
5
+ # Machine-readable description of the plugin's public interface:
6
+ # config keys and enum values (this plugin registers no Liquid tags).
7
+ # `rake interface` writes this as interface.yml (shipped in the gem) so
8
+ # tooling like editor extensions can consume it without parsing Ruby.
9
+ module Interface
10
+ def self.to_h
11
+ {
12
+ "gem" => "jekyll-compress-flow",
13
+ "version" => VERSION,
14
+ "tags" => {},
15
+ "filters" => [],
16
+ "config" => { "compress_flow" => DEFAULTS.keys.sort },
17
+ "enums" => { "formats" => FORMATS.keys.sort }
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module CompressFlow
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.2"
6
6
  end
7
7
  end
@@ -4,6 +4,7 @@ require "jekyll"
4
4
  require "open3"
5
5
 
6
6
  require_relative "compress_flow/version"
7
+ require_relative "compress_flow/interface"
7
8
 
8
9
  module Jekyll
9
10
  # Generates .br/.zst/.gz siblings for text assets in the build output so a
@@ -23,8 +24,11 @@ module Jekyll
23
24
  "gz" => { "tool" => "gzip", "args" => %w[-f -9 -k] }
24
25
  }.freeze
25
26
 
27
+ DEFAULT_POST_WRITE_PRIORITY = 10
28
+ POST_WRITE_PRIORITIES = (0..DEFAULT_POST_WRITE_PRIORITY)
26
29
  DEFAULTS = {
27
30
  "enabled" => nil, # nil => Jekyll.env == "production"
31
+ "priority" => DEFAULT_POST_WRITE_PRIORITY,
28
32
  "extensions" => %w[html css js json xml svg txt map],
29
33
  "formats" => %w[br zst gz],
30
34
  "min_size" => 0,
@@ -33,6 +37,14 @@ module Jekyll
33
37
 
34
38
  module_function
35
39
 
40
+ def post_write_priority(config)
41
+ priority = config.transform_keys(&:to_s).fetch("priority", DEFAULT_POST_WRITE_PRIORITY)
42
+ return priority if priority.is_a?(Integer) && POST_WRITE_PRIORITIES.cover?(priority)
43
+
44
+ raise Jekyll::Errors::FatalException,
45
+ "CompressFlow: compress_flow.priority must be an integer from 0 through 10"
46
+ end
47
+
36
48
  # Entry point — compress all matching files under +dest+.
37
49
  # +config+ is the site's `compress_flow:` mapping (string or symbol keys).
38
50
  def run(dest, config = {})
@@ -87,6 +99,9 @@ module Jekyll
87
99
  end
88
100
 
89
101
  def compress(file, format, cfg)
102
+ # Array-form system(): no shell — tool/args are literals from the frozen
103
+ # FORMATS table; file is a data argument globbed under the build dest.
104
+ # nosemgrep: ruby.lang.security.dangerous-exec.dangerous-exec
90
105
  ok = system(format["tool"], *format["args"], file, out: File::NULL, err: File::NULL)
91
106
  fail_or_warn(cfg, "#{format['tool']} failed on #{file}") unless ok
92
107
  end
@@ -95,6 +110,8 @@ module Jekyll
95
110
  # banner could not be parsed (or no pattern is defined — e.g. Apple gzip
96
111
  # vs GNU gzip use incomparable version strings), nil when not installed.
97
112
  def tool_version(tool, pattern)
113
+ # Array-form capture2e: no shell — tool is a literal from frozen FORMATS.
114
+ # nosemgrep: ruby.lang.security.dangerous-exec.dangerous-exec
98
115
  out, status = Open3.capture2e(tool, "--version")
99
116
  return nil unless status.success?
100
117
  return :unversioned unless pattern && (match = out.match(pattern))
@@ -114,6 +131,12 @@ module Jekyll
114
131
  end
115
132
  end
116
133
 
117
- Jekyll::Hooks.register :site, :post_write do |site|
118
- Jekyll::CompressFlow.run(site.dest, site.config["compress_flow"] || {})
134
+ Jekyll::CompressFlow::POST_WRITE_PRIORITIES.each do |hook_priority|
135
+ registered_priority = hook_priority
136
+ Jekyll::Hooks.register :site, :post_write, priority: registered_priority do |site|
137
+ config = site.config["compress_flow"] || {}
138
+ next unless Jekyll::CompressFlow.post_write_priority(config) == registered_priority
139
+
140
+ Jekyll::CompressFlow.run(site.dest, config)
141
+ end
119
142
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-compress-flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Svend Gundestrup
@@ -29,10 +29,13 @@ dependencies:
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
31
  version: '5.0'
32
- description: A Jekyll plugin that writes Brotli, Zstandard and gzip siblings next
33
- to text assets at the end of a build, so a precompressed-capable static server (e.g.
34
- Caddy's file_server precompressed) can serve them without per-request compression
35
- CPU.
32
+ description: |
33
+ == Precompressed siblings for Jekyll output
34
+
35
+ Writes .br, .zst and .gz siblings next to text assets at the end of a
36
+ build, so a precompressed-capable static server (for example Caddy's
37
+ file_server precompressed) can serve them without per-request
38
+ compression CPU.
36
39
  email:
37
40
  - svend@gundestrup.dk
38
41
  executables: []
@@ -42,8 +45,10 @@ files:
42
45
  - CHANGELOG.md
43
46
  - LICENSE
44
47
  - README.md
48
+ - interface.yml
45
49
  - lib/jekyll-compress-flow.rb
46
50
  - lib/jekyll/compress_flow.rb
51
+ - lib/jekyll/compress_flow/interface.rb
47
52
  - lib/jekyll/compress_flow/version.rb
48
53
  homepage: https://github.com/gundestrup/jekyll-compress-flow
49
54
  licenses: