Skip to content

Fix CDN imports, Safari nav, DOM timing, and dev build pipeline#127

Merged
kallewesterling merged 15 commits intomainfrom
dev
Apr 27, 2026
Merged

Fix CDN imports, Safari nav, DOM timing, and dev build pipeline#127
kallewesterling merged 15 commits intomainfrom
dev

Conversation

@kallewesterling
Copy link
Copy Markdown
Collaborator

@kallewesterling kallewesterling commented Apr 27, 2026

Summary

This PR resolves a series of cascading bugs that prevented the dev bundle from working, plus a Safari-specific navigation regression discovered in the process.

CDN imports → npm packages

  • Replaced runtime CDN import() calls for @tsparticles/confetti and shiki with proper npm dependencies. esbuild's IIFE output converts all import() to require() shims, so CDN URL imports threw Dynamic require of "URL" is not supported at runtime; CSP unsafe-eval also blocked the Function() workaround.
  • Used fine-grained shiki imports (shiki/core, per-language .mjs files) instead of the full shiki bundle, keeping the output at ~2 MB instead of ~9.9 MB.
  • Added generate_language_file.js to scan lesson HTML for language identifiers and emit production/data/languages.json so the language list stays in sync with content.

DOM timing (esbuild IIFE runs before DOMContentLoaded)

  • Converted all eagerly-evaluated properties in CG.dom, CG.page, and CG.env to getter accessors so DOM queries only run at call time, not at module parse time.
  • Split the single DOMContentLoaded handler into three separate try/catch blocks (preRoute, route, postRoute) so a failure in one phase doesn't silently swallow the others. showBody() is called unconditionally afterward to prevent a permanently hidden page.
  • Changed the "no handler matched" log from logger.warn to logger.error with a full page-state dump.

Safari/Dia navigation fix

  • Skilljar's native #left-nav-button exists in Chrome's DOM at DOMContentLoaded but not in Safari, so our custom toggle button only fires in Safari. The on: handler was nested inside aria: in the el() call, producing aria-on=\"[object Object]\" in the HTML instead of attaching a click listener — fixed by moving on: to the top level.
  • Skilljar's CSS sets left: -320px on #lp-left-nav.cbp-spmenu:not(.cbp-spmenu-open) with higher specificity than our rule. Added left: 0 !important to our base #lp-left-nav rule so the transform-based open/close animation is not overridden.
  • Introduced setNavOpen(open) which mirrors cbp-spmenu-open on both body (for our CSS) and #lp-left-nav (for Skilljar's CSS), and persists the state to localStorage.lessonNavStateOpen so the user's preference survives page loads in any browser.

hideCompletion event listener

  • hideCompletion() was passing on: { transitionend: … } to setStyle(), which does not handle event listeners — the transitionend callback was never attached. Replaced with native addEventListener/removeEventListener plus a 300 ms safety timeout.

Dev build pipeline

  • Added .github/workflows/sync-dev-gcs.yaml — triggers on pushes to dev with changes under production/** or fonts/**, builds without minification, and syncs only to gs://chainguard-courses-theme/dev/dist/.
  • Added build-dev.mjs which injects the short commit SHA as a /* build: <hash> */ banner in both bundle.js and bundle.css, making it easy to verify which bundle is loaded in the browser without checking filenames.

Test plan

  • Lesson page loads without console errors in Chrome, Safari, and Dia
  • Left nav is visible on desktop load in Safari and Dia (reads localStorage.lessonNavStateOpen; defaults to open)
  • Nav toggle opens and closes the sidebar in all three browsers; state persists across page reloads
  • Code blocks are syntax-highlighted (shiki) on lesson pages
  • Course completion popup fires confetti and dismisses correctly (click, ESC, auto-hide)
  • /* build: <hash> */ banner appears on line 1 of the deployed bundle.js and bundle.css
  • Production build (npm run build) still lints and minifies cleanly

@kallewesterling kallewesterling merged commit c7144a8 into main Apr 27, 2026
8 checks passed
@kallewesterling kallewesterling deleted the dev branch April 27, 2026 17:52
@kallewesterling kallewesterling restored the dev branch April 27, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant