Skip to content

feat(core): upgrade to Gulp 5, modernise build system and expand test coverage - #175

Open
cebreus wants to merge 274 commits into
developfrom
gulp5
Open

feat(core): upgrade to Gulp 5, modernise build system and expand test coverage#175
cebreus wants to merge 274 commits into
developfrom
gulp5

Conversation

@cebreus

@cebreus cebreus commented Jun 8, 2026

Copy link
Copy Markdown
Owner

🎯 Overview

Major refactor. Upgrade Gulp 5, Node >=24.10.0, modular pipeline, strict Fail-Closed testing. Final v5.0.0 candidate.

🚀 Key Changes

1. Build & Gulp 5

  • Gulp 5: Fast streaming, incremental build, parallel tasks.
  • Domain modules: Split gulpfile.jshtml-rendering, image-pipeline, sass-pipeline.
  • Styles: Explicit CSS bundles, shared route Sass abstracts, strict PurgeCSS.
  • Pipeline: Central route content, better Sharp image opt.

2. Testing (Fail-Closed)

  • Native Node: Use node:test + node:assert. No third-party runner.
  • Coverage: Unit, integration, e2e.
  • Visual: Add parity test. Build vs export stable.

3. DX & Tooling

  • Hooks: Husky out, Lefthook in. Fast pre-commit.
  • ESLint: Flat Config v10, clean rules.
  • Cleanup: Purge legacy init-template.js, dummy components, boilerplate.
  • Quality: Strict ESLint/Stylelint. Fix JSDoc warnings. Old tools out.

4. Showcase

  • New page: Template examples, markdown parsing, route-local styles.

5. Docs & AI

  • memories/: Curated agent guidelines (architectural-gotchas, etc).
  • Guides: Rewrite core docs.

⚠️ Breaking Changes

  • Node >=24.10.0 required.
  • ESM only. No CommonJS.
  • Removed: Legacy init scripts, default components, dummy vectors.

cebreus and others added 30 commits July 11, 2026 23:23
README linked /about and /showcase pages that do not exist on the
stale v4.x deploy; point docs at the repo and mark showcase as WIP.
Add quickstart section. Record branch model and menu-pipeline intent
in memories/architectural-gotchas.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Move `favicon.ico` and `manifest.webmanifest` to build root
- Generate HTML snippet to temporary path for dynamic inclusion
- Remove static `favicons.njk` component
- Add granular icon configuration and theme color
- Integrate favicon generation into `serve` and watch tasks
- Extract metadata and generated low quality placeholders from images.

- Update HTML processing to inject local image metadata into templates.

- Add custom Nunjucks filter to apply placeholder classes.

- Add unit and integration tests for the new image catalog pipeline.
- Document how the image task generates 20px WebP LQS for local bitmaps.
- Define project conventions for BEM and Bootstrap utility class application.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sass pipeline: preserve all include paths, cache-miss on missing dependency
manifest, fail non-dev builds on compilation errors, reject duplicate
outputFilename targets, build-mode options for route styles, refresh manifest
after every compilation.

Data & routing: normalized pageId, menu entries from rendered frontmatter,
route containment validation, private-route filtering in HTML task,
flat home asset candidates, ENOENT-only catches, boolean env flag parsing,
warn on empty paths, complete utils barrel.

Assets & serve: fail WebP/AVIF conversion errors, transcode mismatched
image payloads, drop invalid SVGs, strict SVG signature detection, verify
referenced font assets (and restore missing Outfit woffs), fail on skipped
SRI tags, constrained clean-build deletion, execFile-based template linting
with failure propagation outside watch mode.

Tooling: BUILD\_MODE whitelist, promise-adapted copy task, .mjs/.cjs lint
coverage, sequenced lint-staged fixers, scoped remark rule via nested
config, workflow actions pinned to commit SHAs, robust hook scripts.

Tests: hardened sandbox helpers (mkdtemp, containment, confined cleanup),
per-test console mocks, deterministic assertions, guaranteed teardown in
e2e/visual suites, same-origin crawl, real-fixture coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upstreamed from sebastienbagnoud.eu: html-validate rejects
itemscope="" and friends (attribute-boolean-style). Normalize
boolean attributes in rendering, SRI, and revision passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fail-fast pass: debug-build and process-fonts throw on missing
outputs/arguments/binaries, generate-sri and purge-css validate
parameters, generate-revision rewrites HTML before deleting originals,
core cleanup failures propagate with cause.

Correctness: HTML comment cleaner uses a raw-text-aware scanner and
rejects assets outside the build output, epoch-zero dates preserved and
invalid dates rejected, SVG detection handles preambles, unsupported
image targets reject, conversions detected from source bytes, sass
cache manifest fingerprints build options, JS bundles bypass
entry-point mtime filtering, release script creates temp config
exclusively, fold-lines preserves CRLF, lint-staged formats Handlebars,
clean-workflows grants explicit actions:write scope.

Tests updated to the new contracts; suite 189/189, lint and build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- pass real source file to PostCSS so Tailwind content scanning works
- serve a 503 error page instead of stale output when a dev build fails
- make watch tasks recoverable via createRecoverableDevTask
- fail fast on duplicate pageId, missing debug sources, placeholder SEO
- propagate image optimization failures instead of publishing corrupt files
- resolve font URLs against the CSS directory and fix fonts.css paths
- rename validate\* helpers that throw to assert\*

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- compare 404 desktop light/dark screenshots to committed PNGs
- test:visual:update regenerates baselines after intended design changes
- catches regressions parity tests are blind to (build and export equally broken)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
.env.local stays a local-only file; ignore rules never applied to it
because it was already tracked. Example now carries the dev defaults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
del still brace/glob-expands patterns under force:true even after the
raw pattern string passes the root check, so `{build,..}` (no slash
before '..', so path.resolve() never sees it as a traversal) reached
deleteAsync unvalidated and could delete outside the allowed root.
Now every expanded match is validated via a dry run before deletion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- reset stateful regex lastIndex before each file-filter test
- recompute protected ranges before removing void closing tags
- lint-templates always rethrows failures (no dev-mode swallow)
- process-fonts confines font URLs to the output root and requires files
- process-html reads config.version instead of the raw env var
- sass cache fingerprint now includes tool versions and an optional
  caller cache key, wired through both the write and read paths
  (they previously diverged on the cacheKey field, which masked stale
  reuse whenever plugin config changed)
- process-sass reads the fail-on-error env flag lazily, not at
  module-load time (env files load after this module's static import)
- process-js defaults buildConfig so the documented single-arg call
  no longer throws
- generate-favicons writes the generated-path and root favicon.ico
- private-streams transforms forward sync errors via cb(error)
- fonts integration test now exercises the real validation path
  instead of short-circuiting on the skip-cache mtime check

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
github-pages-deploy-pnpm.yml previously deployed the Pages artifact
before e2e ran, so a failing e2e run left a broken site live. Split
into build -> e2e-tests -> deploy, with deploy needing both to pass.
E2E now runs against a fresh local build instead of the live site.

.release-it.yml's regex-bumper block targeted content/pages/index.md
and gulpconfig.build.js (neither exists) and layout-default.njk
(exists, no data-version attribute) — dead config, removed. No
rendered output currently carries the package.json version string.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Exclude build outputs, caches, and node\_modules from search
- Associate Nunjucks and Handlebars files for language support
- Enable Emmet completions for Nunjucks templates
- Update Bootstrap CDN reference to version 5.3.8
- Fix 'maxlenght' typo in attribute sorter configuration
- Add recommendations for stylelint, Playwright, HTML validation
- Adjust workbench color customizations for activity bar and status bar
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.

3 participants