refactor(breakpoints): apply custom breakpoints to the built CSS instead of compiling SCSS on the site - #259
Merged
Conversation
Custom breakpoints were produced by compiling the shipped SCSS on the site with scssphp, php-css-parser and rtlcss through a cron queue. The four default values only ever appear inside `@media` preludes of the built CSS, so replacing them there gives the same files for a few milliseconds, with no bundled library to collide with another plugin's copy (the php-css-parser fatal reported on 3.7.0). The `.min` suffix style data existed for the compiler's `-rtl.min.css` naming and left RTL sites with the LTR file whenever breakpoints were default; the RTL unit test fails without its removal. Spec: .specs/002-breakpoints-search-replace
The generator from the previous commit leaves nothing for scssphp, php-css-parser, rtlcss-php and wp-background-processing to do, nor for the SCSS sources the compiler read on the site and rewrote in place, so they leave the plugin and the release zip. A migration keyed 3.7.2 removes the compiled files in uploads, the queue's cron event and its options. Spec: .specs/002-breakpoints-search-replace
A helper plugin sets `gkt_breakpoint_sm` the way Pro does, so the spec can see the main and form stylesheets served from uploads with the custom value and from the plugin again once the helper is inactive. Spec: .specs/002-breakpoints-search-replace
wp-background-processing stored its batches and status through update_site_option(), so on multisite they sit in sitemeta rather than options. The test writes the legacy cron entry the way an old site holds it, on an interval that no longer exists. Spec: .specs/002-breakpoints-search-replace
Three more style handles carried the `.min` suffix data that made RTL sites load the LTR file; the RTL test now covers all four handles. A migration keyed above the current plugin version waited for nothing and ran on every request, so the runner skips it until the release that carries it. A directory PHP cannot open threw out of the CSS walks and took the site down; both walks stop there instead. Spec: .specs/002-breakpoints-search-replace
`vpf_db_version` is the option Visual Portfolio's migrations write, and its higher version blocked every Ghost Kit migration on sites running both plugins. Both migrations are idempotent, so the one extra pass of `v_2_25_1` on existing sites changes nothing. Spec: .specs/002-breakpoints-search-replace
Ending the walk at the first directory PHP could not open cached a truncated file list until the next hash change, and a file listed without its RTL twin sent RTL sites to a 404 because WordPress derives the -rtl.css URL after the filter. The walk now skips such a directory, and a written file whose twin was not written is dropped with it. Spec: .specs/002-breakpoints-search-replace
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Custom breakpoints were applied by compiling the shipped SCSS on the user's site with scssphp, php-css-parser and rtlcss-php, through a cron queue. Those libraries were bundled unprefixed, so a second copy of php-css-parser in another plugin made the site fatal (
Declaration of Sabberworm\CSS\Value\Size::render(...) must be compatible with ..., reported on 3.7.0). The four default values (576, 768, 992, 1200) only ever appear inside@mediapreludes of the built CSS, so the plugin now replaces them there and writes the result touploads/ghostkit/build/, mirroring the plugin paths. The compiler, its four libraries and the SCSS sources leave the plugin and the release zip.The migration keyed
3.7.2waits for the release that bumpsGHOSTKIT_VERSION; the runner now skips migrations keyed above the plugin version, so this branch alone changes nothing on existing sites until the version bump. It also keys onghostkit_db_versioninstead ofvpf_db_version, which is the option Visual Portfolio's migrations write: on a site with both plugins VP's higher version blocked every Ghost Kit migration. Both existing migrations are idempotent, so the one extra pass ofv_2_25_1is harmless.Why replacement rather than prefixing the libraries: prefixing (Strauss) would have closed this one collision and kept the compiler, the in-place rewriting of shipped SCSS, the queue and the RTL naming bug below. The replacement is a single regex pass measured at 1.6 to 9.3 ms over all 66 built files, so it runs synchronously on the same trigger as before (a change of breakpoints or of the plugin version) and the background queue goes with the compiler. The cost is that the build becomes a contract: a
pxwidth inside an@mediaprelude that is not one of the four defaults would ship unreplaced.BreakpointsCssTest::test_build_media_queries_use_known_widthsfails the suite when one appears.The
.minsuffix style data onghostkit, the block styles,ghostkit-editor,ghostkit-adminandghostkit-settingsexisted for the compiler's-rtl.min.cssnaming. WordPress derives the RTL URL withstr_replace( "{$suffix}.css", "-rtl{$suffix}.css", $href ), which never matched ourbuild/*.csshrefs, so RTL sites with default breakpoints were loading the LTR files. The suffix is gone;BreakpointsRtlTestfails on the old code for all four handles.Ghost Kit Pro is not in this PR. The free plugin steps aside when Pro is active, so Pro sites run the core bundled inside Pro until its
core-pluginsubmodule is bumped and itsGhostKit_PRO_Breakpointsdrops the compiler overrides. That is a separate PR. Known and left as is: a Pro installed in a folder not namedghostkit-proloads both cores, the free one wins by sort order, and the un-updated Pro subclass would fatal on the deletedclasses/class-scss-compiler.php. Also left: sites that ran Ghost Kit without Visual Portfolio keep a stalevpf_db_version, which is what the old runner wrote.How to check: activate
ghostkit-test-plugin-custom-breakpoints(mapped in.wp-env.json, setsgkt_breakpoint_smto 700), open any page with a Ghost Kit block, and theghostkit-csslink points at/wp-content/uploads/ghostkit/build/gutenberg/style.css?ver=<hash>with(max-width:700px)inside; deactivate it and the link is the plugin file again.tests/e2e/specs/breakpoints.spec.jsdoes exactly that. Unit tests cover the replacement on literal input, the single pass when a custom value equals another default, the LTR and RTL twins, the src filter, the return to defaults, the migration and the RTL hrefs.