sync: dev to extern-contrib#993
Merged
Merged
Conversation
Bootstrap 5.3.3 CSS was previously fetched from CDN at document-idle, causing a flash of the old light-themed page before dark mode took effect. Changes: - Add @run-at document-start so an early shim can run before first paint - Add @resource BootstrapCSS + @require Bootstrap JS bundle so both are cached by the userscript manager (no CDN round-trip on page load) - Add @grant GM_getResourceText - Early synchronous IIFE: reads saved theme/settings from localStorage, sets data-bs-theme on <html> immediately, injects Bootstrap CSS and the MonochromeUI or default skin CSS before the browser paints anything, and uses a MutationObserver to drop the page's own old Bootstrap/theme link tags before they are ever fetched - Extract MonochromeSkinCSS and NewBootstrapSkinCSS to top-level consts so they are available both to the early block and to the late Style element (which still applies them at document-end for any dynamic page additions) - Remove Bootstrap CSS + JS from the runtime CDN resources array - Remove the now-redundant post-load link-removal loop, data-bs-theme assignment, and earlyStyle CSS-variable injection from the NewBootstrap block - Add DOMContentLoaded wait at the start of the main async IIFE so all existing DOM-dependent code continues to work correctly under document-start https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
The early block now owns the MonochromeSkinCSS / NewBootstrapSkinCSS injection. The Style element created at document-end is kept (other code appends to it further down the IIFE), but it no longer re-sets the skin CSS that was already applied synchronously at document-start. https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
If GM_getResourceText("BootstrapCSS") returns null (the @resource has
not been downloaded yet on first install or update), the early block was
still setting up the MutationObserver that blocked the page's original
Bootstrap CSS — leaving the page with no Bootstrap CSS at all.
Fix: bail out of the early block before the observer is set up when the
resource is unavailable, so the page's original stylesheets load as a
fallback (flash still happens, but the page renders correctly).
Also add a CDN fallback entry to the runtime resources array: on the
rare load where the @resource wasn't ready, Bootstrap 5.3.3 CSS is
fetched from CDN instead, maintaining the same behaviour as before this
PR. Subsequent page loads use the cached @resource and no CDN request.
https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
The browser preload scanner starts fetching old Bootstrap/theme
stylesheets before the document-start MutationObserver can remove
the link elements. Once fetched, those stylesheets are applied and
override our early-injected Bootstrap 5 + skin CSS — causing the new
UI to render for a moment and then immediately revert.
Restoring the IIFE-time link removal loop fixes this: removing a
<link> from the DOM un-applies its stylesheet from the CSSOM
immediately, regardless of whether the preload scanner had already
fetched it. The two layers now work together:
1. MutationObserver (document-start): best-effort early block that
prevents old CSS from ever loading when the timing works out.
2. Link removal loop (document-idle): guaranteed cleanup that
removes any preload-scanner-fetched stylesheets after the DOM
is ready, eliminating the revert.
https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
The visible flash was caused by old Bootstrap 3 CSS sitting in the CSSOM from the moment DOMContentLoaded fired until the IIFE's link removal loop ran — a window that includes a full loginpage.php network round-trip. Move the definitive link removal into the early block's DOMContentLoaded handler so it fires at the earliest possible moment after the DOM is ready, before any async work in the main IIFE. The observer is also disconnected at the same time. The IIFE-level link removal loop is kept as a belt-and-suspenders fallback for edge cases (e.g. early block disabled due to cache miss). https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
No JavaScript approach can reliably prevent the browser preload scanner
from fetching and visibly applying old Bootstrap CSS before DOMContentLoaded.
Attempting to evict stylesheets at DOMContentLoaded still leaves a window
where old CSS is visible, causing CLS.
Instead, hide the page immediately at document-start with
html { opacity: 0 !important; }
so the user never sees the intermediate broken state. The page is revealed
in the DOMContentLoaded handler, after old stylesheet links have been
removed and the correct Bootstrap 5 + skin CSS is already in place.
A 3-second safety-net timeout ensures the page is always revealed even
if something unexpected prevents DOMContentLoaded from firing.
This is the standard FOUC prevention pattern. The hidden window is just
HTML parse time (~50-150 ms for a server-rendered page), after which the
user sees the correct final state with zero CLS.
The hide style is only injected when the @resource is available
(_earlyBootstrapInjected = true), so the fallback path (cache miss on
first install) continues to show the page immediately.
https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
The DOMContentLoaded listener registered inside the early IIFE's sandbox context was not firing reliably, causing the opacity:0 FOUC prevention style to only be removed by the 3-second safety-net timeout — resulting in a mandatory 3 s blank page on every load. Fix: expose the FOUC style element and MutationObserver via top-level variables (_foucStyle, _earlyObs) and perform the reveal + link cleanup at the top of the main async IIFE, immediately after its DOMContentLoaded wait. The IIFE's own DOMContentLoaded mechanism is proven to work, so the reveal is now reliable. The early block still hides the page at document-start and arms the MutationObserver for best-effort link interception; the IIFE takes care of teardown and the final CSSOM cleanup at DOMContentLoaded time, before the loginpage.php fetch begins. https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
When GM_getResourceText("BootstrapCSS") returns null (first install or
@resource not yet cached), the early block exits before injecting
MonochromeSkinCSS/NewBootstrapSkinCSS. The Style element in the IIFE
now injects the skin CSS (plus AddAnimation/AddColorText overrides)
whenever _earlyBootstrapInjected is false, so the skin is always
applied regardless of cache state.
https://claude.ai/code/session_01B1RgyUvtsWWhS2hdNiUhZb
fix: eliminate dark-mode flash in MonochromeUI/NewBootstrap
Deploying xmoj-script-dev-channel with
|
| Latest commit: |
2ff4536
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://ab308179.xmoj-script-dev-channel.pages.dev |
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.
sync-branches: New code has just landed in dev, so let's bring extern-contrib up to speed!
Summary by cubic
Sync extern-contrib with dev to ship 3.5.3. Fixes the dark-mode flash in MonochromeUI/NewBootstrap by applying the correct theme and Bootstrap CSS before first paint and cleaning out old styles early.
Written for commit 2ff4536. Summary will update on new commits.