Edit this page

Was this page helpful?

Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

Bengal 0.5.1

A real CSS engine and a refreshed default theme — a tokenizer-based minifier that can't corrupt your stylesheets, OKLCH palettes with light-dark() dark mode, a dependency-free knowledge graph, and byte-reproducible build output.

Key theme: A real CSS engine, and a default theme that earns its zero-dependency promise. Bengal 0.5.1 replaces the regex-based CSS minifier with a proper CSS Syntax Level 3 engine that tokenizes before it serializes — so it can no longer glue tokens together and silently corrupt a stylesheet — and it re-authors the default theme around modern CSS: OKLCH palettes,light-dark()dark mode, structured data, and a knowledge graph that no longer pulls D3 from a CDN. Build output is now byte-reproducible across rebuilds, and a few free-threading correctness fixes round it out.


Highlights

A real CSS engine

The CSS minifier was a pile of regexes. It is nowbengal.css: a CSS Syntax Level 3 engine that tokenizes the stylesheet before serializing it. The bug that prompted the rewrite — @scope (...) to (...) getting glued into to(...), which made the parser treat to as a function and silently drop the scoped rule — is gone, and the new tokenizer makes that whole class of "identifier glued to (" corruption structurally impossible (#510).

The engine verifies its own work. After minifying, it re-parses its output and compares an independent meaning signature — selector combinators, declaration values, and (at the aggressive level) the resolved cascade — against the input. On any mismatch it returns the input unchanged, so it can never emit corrupted CSS.

minify_css also gained a levelargument:

  • "safe"(default) — lossless whitespace and comment removal. The default build path is unchanged.
  • "optimize" — adds safe value normalizations: named colors when shorter than hex, unquoted url() bodies, length-context unitless zeros (margin:0pxmargin:0), and collapsed shorthands (margin:0 0 0 0margin:0) (#515).
  • "aggressive"— adds cascade-invariant structural rewrites: empty-rule removal, exact-duplicate dedup, and adjacent-rule merging.

Two opt-in passes layer on top:flatten_nesting=True de-sugars native CSS nesting into flat selectors for legacy browser targets while preserving the cascade (#516), and intra-stylesheet dead-code removal strips unused @keyframes, @font-face, and custom properties (#512). Native CSS nesting (&:hover) is now preserved by default rather than flattened (it's Baseline 2023).

A refreshed default theme

The default theme was re-authored around modern CSS and a zero-dependency runtime:

  • No third-party CDNs by default. The theme no longer loads Mermaid, D3, KaTeX, or Google Fonts from third-party CDNs at runtime. Opt in via[capabilities] in bengal.tomlto self-host diagram and math vendors at build time (#533).
  • OKLCH palettes. Colors are now authored in OKLCH for wide-gamut richness, and the five built-in palettes derive their hover, active, border, surface, and state variants automatically from a handful of anchors via relative-color andcolor-mix— retuning a palette no longer means editing a hand-painted hex matrix. The focus ring is palette-aware instead of falling back to a fixed blue (#534).
  • light-dark() dark mode. Dark colors flow through a single light-dark() token set selected by color-scheme, replacing the duplicated dark token matrix. Dark mode now renders correctly in every named palette and follows the OS preference with no flash of the wrong theme (#535).
  • Structured data. Pages emit correctog:type per kind, WebSite/CollectionPage JSON-LD on landing and list surfaces, and BreadcrumbListdata; the docs right-sidebar graph minimap is consolidated into shared partials (#536).
  • One JavaScript model. Interactive regions — table of contents, docs nav, learning-track sidebar, and the REST API catalog — are now custom elements (<bengal-toc>, <bengal-docs-nav>, <bengal-track-nav>, <bengal-api-catalog>) that initialize themselves when they appear (including content inserted after load) and tear their listeners down when removed. This retires the redundant second script-loading registry. Every page still degrades gracefully with JavaScript disabled (#537).

A dependency-free knowledge graph

The graph minimap and the full/graph/ explorer are now rendered by a first-party, dependency-free engine. Node positions are computed at build time and the explorer draws to a canvas, so it stays responsive on large sites. The opt-in d3capability is removed — the graph no longer depends on D3, and the runtime CDN request for it is gone.

Reproducible output

Two builds of unchanged content now produce byte-identical output. The knowledge graph'sgraph/graph.json and the search index.json previously used a per-process randomized hash (and absolute paths), with process-dependent edge and tag ordering; ids are now a stable hash of the site-relative path, and edges and tags sort deterministically. Sitemap and agent.jsonaggregates use stable URL/path ordering so results no longer depend on page discovery order (#431).

Free-threading correctness

Provenance-cache races that could return stale warm-build output under free-threaded Python — when records were loaded or verified concurrently — are fixed (#438), and free-threading detection is consolidated to the canonicalbengal.utils.concurrencyhelper so executor selection and render paths no longer drift on GIL-fallback logic (#381).


Added

  • Opt-in intra-stylesheet removal of unused@keyframes, @font-face, and custom properties (#512).
  • minify_css(..., flatten_nesting=True)de-sugars nested rules into flat selectors for legacy targets while preserving the cascade (#516).

Changed

  • The CSS minifier is now a tokenizing CSS Syntax Level 3 engine (bengal.css) with safe/optimize/aggressive levels; optimize adds safe color, url(), and numeric normalizations (#510, #515).
  • Default theme re-authored in OKLCH with anchor-derived palettes and a palette-aware focus ring (#534).
  • Default theme dark mode uses a singlelight-dark() token set selected by color-scheme, correct in every palette and following OS preference (#535).
  • Default theme no longer loads Mermaid, D3, KaTeX, or Google Fonts from third-party CDNs; opt in via[capabilities]to self-host at build time (#533).
  • Default theme emitsog:type, WebSite/CollectionPage JSON-LD, and BreadcrumbListstructured data; docs sidebar graph minimap consolidated into shared partials (#536).
  • Default theme JavaScript uses one custom-element enhancement model (<bengal-toc>, <bengal-docs-nav>, <bengal-track-nav>, <bengal-api-catalog>), retiring the redundant script registry (#537).
  • The knowledge graph minimap and/graph/explorer are rendered by a dependency-free, first-party engine that computes layout at build time.
  • Core: per-heading search index records for deep-link search results (#546); renderer-agnostic data-table contract decoupled from Tabulator config (#547); optional git-derived last-modified field for pages (#548); code-fence attributes (title, diff, line ranges) parsed through to the highlighter (#549).
  • Free-threading detection consolidated tobengal.utils.concurrencyso executor selection and render paths don't drift on GIL fallback (#381).

Fixed

  • The CSS minifier no longer corrupts@scope (...) to (...) by gluing it into to(...)and dropping the rule; the tokenizing engine makes that class of corruption impossible, and it verifies its own output before emitting (#510).
  • graph/graph.json and the search index.jsonare byte-identical across rebuilds of unchanged content (stable ids, deterministic edge/tag ordering).
  • Sitemap andagent.jsonaggregate output uses stable URL/path ordering, independent of discovery order (#431).
  • Provenance-cache races that could return stale warm-build output under free-threaded Python are fixed (#438).
  • bengal fixnow receives per-source link metadata, so it can suggest repairs for every broken internal link on a page, not just the first few shown in validator details (#508).

Removed

  • The opt-ind3 capability and the runtime D3 CDN request from the /graph/page; the knowledge graph works by default with no third-party scripts.
  • The obsolete@supports (color: color-mix(...)) feature-query fallbacks in the default theme — color-mix()is now Baseline, so the guarded branches apply unconditionally (#534).
  • The legacy CSS code paths: thebengal.assets.css_minifier shim and the regex-based bengal/core/asset/css_transforms.py (lossless_minify_css, remove_duplicate_bare_h1_rules, transform_css_nesting). Import minify_css from bengal.css(#510).

Upgrading

BASH
uv pip install --upgrade bengal
# or
pip install --upgrade bengal

A few things to know:

  • The CSS minifier moved. If you imported CSS helpers from internals, switch tofrom bengal.css import minify_css. The bengal.assets.css_minifier shim and bengal/core/asset/css_transforms.py are gone. Native CSS nesting is now preserved by default rather than flattened; pass flatten_nesting=Trueif you target browsers without nesting support.
  • The default theme is CDN-free by default. If you relied on Mermaid, D3, KaTeX, or Google Fonts loading at runtime, opt in under[capabilities] in bengal.toml to self-host them at build time. The knowledge graph needs no opt-in — it's dependency-free now, and the d3capability is removed.
  • Reproducible builds. Graph and search output is now byte-identical across rebuilds of unchanged content; if you diff or cache build artifacts, expect previously-noisygraph.json/index.json/sitemap output to settle.