jekyll-theme-zer0 1.26.0 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +558 -5
- data/README.md +10 -27
- data/_data/authors.yml +4 -3
- data/_data/backlog.yml +28 -0
- data/_data/consumers.yml +147 -0
- data/_data/features.yml +142 -23
- data/_data/i18n/fr.yml +98 -0
- data/_data/i18n/languages.yml +36 -0
- data/_data/i18n/manifest.yml +1502 -0
- data/_data/navigation/docs.yml +2 -0
- data/_data/navigation/main.yml +6 -0
- data/_data/series.yml +19 -0
- data/_data/theme-manifest.yml +348 -268
- data/_data/ui-text.yml +36 -246
- data/_includes/README.md +25 -2
- data/_includes/analytics/google-tag-manager-body.html +11 -2
- data/_includes/analytics/google-tag-manager-head.html +16 -6
- data/_includes/analytics/posthog.html +33 -4
- data/_includes/components/abc-letter.html +43 -0
- data/_includes/components/author-avatar-url.html +4 -2
- data/_includes/components/book-card.html +42 -0
- data/_includes/components/book-nav.html +80 -0
- data/_includes/components/book-plate.html +31 -0
- data/_includes/components/book-toc.html +47 -0
- data/_includes/components/bookshelf.html +68 -0
- data/_includes/components/card-grid.html +60 -0
- data/_includes/components/data-card.html +95 -0
- data/_includes/components/env-switcher.html +3 -1
- data/_includes/components/halfmoon.html +5 -1
- data/_includes/components/language-toggle.html +81 -0
- data/_includes/components/page-feedback.html +65 -2
- data/_includes/components/search-modal.html +2 -2
- data/_includes/components/shortcuts-modal.html +1 -1
- data/_includes/components/theme-controls-bar.html +10 -2
- data/_includes/components/theme-customizer.html +8 -2
- data/_includes/components/translation-notice.html +27 -0
- data/_includes/content/intro.html +16 -15
- data/_includes/content/seo.html +9 -3
- data/_includes/core/color-mode-init.html +13 -4
- data/_includes/core/favicon.html +46 -0
- data/_includes/core/footer.html +9 -4
- data/_includes/core/head.html +18 -0
- data/_includes/core/header.html +9 -4
- data/_includes/core/hreflang.html +33 -0
- data/_includes/core/i18n.html +36 -0
- data/_includes/custom/body-end.html +18 -0
- data/_includes/custom/body-start.html +17 -0
- data/_includes/custom/footer.html +18 -0
- data/_includes/custom/head.html +18 -0
- data/_includes/navigation/breadcrumbs.html +1 -1
- data/_includes/navigation/local-graph.html +28 -2
- data/_includes/navigation/nav-tree.html +3 -3
- data/_includes/navigation/navbar.html +5 -4
- data/_includes/navigation/sidebar-config.html +21 -0
- data/_includes/navigation/sidebar-nav.html +4 -0
- data/_includes/navigation/sidebar-pagetree.html +150 -0
- data/_includes/navigation/sidebar-right.html +3 -2
- data/_includes/navigation/unified-drawer.html +9 -3
- data/_includes/obsidian/full-graph.html +165 -136
- data/_layouts/404.html +260 -0
- data/_layouts/README.md +2 -0
- data/_layouts/article.html +7 -1
- data/_layouts/book-abc.html +106 -0
- data/_layouts/book-story.html +91 -0
- data/_layouts/book.html +113 -0
- data/_layouts/collection.html +17 -5
- data/_layouts/default.html +5 -3
- data/_layouts/home.html +5 -2
- data/_layouts/landing.html +9 -0
- data/_layouts/news.html +159 -33
- data/_layouts/root.html +29 -9
- data/_layouts/section.html +61 -17
- data/_sass/components/_book.scss +423 -0
- data/_sass/core/_navbar.scss +13 -0
- data/_sass/core/_obsidian.scss +295 -7
- data/_sass/layouts/_navbar-extras.scss +6 -1
- data/_sass/theme/_backgrounds.scss +21 -8
- data/assets/css/main.scss +1 -0
- data/assets/js/auto-hide-nav.js +5 -1
- data/assets/js/halfmoon.js +26 -0
- data/assets/js/obsidian-graph.js +707 -265
- data/assets/js/obsidian-local-graph.js +161 -54
- data/assets/js/search-modal.js +4 -1
- data/scripts/README.md +20 -26
- data/scripts/bin/audit-consumer +1 -1
- data/scripts/bin/manifest +31 -5
- data/scripts/bin/sync-plugins +0 -1
- data/scripts/bin/validate +5 -1
- data/scripts/dev/rasterize-svg.js +65 -0
- data/scripts/features/generate-preview-images +49 -1390
- data/scripts/features/install-preview-generator +55 -33
- data/scripts/install/README.md +55 -25
- data/scripts/install/ai/client.sh +302 -93
- data/scripts/install/ai/prompts/spec.schema.json +1 -1
- data/scripts/install/ai/prompts/wizard.system.md +8 -17
- data/scripts/install/ai/wizard.sh +10 -5
- data/scripts/install/apply.sh +7 -3
- data/scripts/install/cli.sh +54 -4
- data/scripts/install/config.sh +167 -0
- data/scripts/install/doctor.sh +38 -0
- data/scripts/install/plan.sh +10 -0
- data/scripts/install/spec.sh +15 -7
- data/scripts/install/template.sh +4 -0
- data/scripts/lib/README.md +1 -5
- data/scripts/lib/install/deploy/README.md +3 -9
- data/scripts/lib/preview_generator.py +2261 -1341
- data/scripts/propagate.rb +277 -0
- data/scripts/translate.rb +1204 -0
- metadata +34 -3
- data/_plugins/preview_image_generator.rb +0 -351
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8b72b3e6bf60fc9df7f31ecd56d157770fede085973db6d2153980c3004bc0fc
|
|
4
|
+
data.tar.gz: 369c0158b06d41d52c3f737d9a88a44e2cb9265653db55bf376e0651a502980b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d89cbf414b78be0b73fd22f8102dfacf8e38f10c561b2cc50fb4b492b8840d15e38f3b83243a589cd32f7fe7d72e4eb009a8dba44f09634e5e6611195971566
|
|
7
|
+
data.tar.gz: cbcbec935073100919c21c9f3f542124a291529a93212706b8c7e82773a4361d7b272cc60ec966f077213c6c7ae23d36a60ad129c08bfd33506d382172109a88
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,410 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
Two kinds of section appear below. `## [X.Y.Z]` headings are generated by
|
|
9
|
+
release-please from Conventional Commits and are the authoritative record of
|
|
10
|
+
what shipped in each release. `## Detailed notes — vX.Y.Z` headings are
|
|
11
|
+
hand-written prose covering the same releases in more depth; they sit below
|
|
12
|
+
their version because release-please inserts each new release at the top of the
|
|
13
|
+
file. Only `## [Unreleased]` describes work that has not shipped yet.
|
|
14
|
+
|
|
15
|
+
## [1.28.0](https://github.com/bamr87/zer0-mistakes/compare/v1.27.0...v1.28.0) (2026-08-09)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **books:** children's picture-book collection with immersive layouts and components ([#328](https://github.com/bamr87/zer0-mistakes/issues/328)) ([e059d1a](https://github.com/bamr87/zer0-mistakes/commit/e059d1afdc95073c5ce5bf9d1516b362979ad402))
|
|
21
|
+
* **ci:** deploy the site via Actions so examples reach the live domain ([#353](https://github.com/bamr87/zer0-mistakes/issues/353)) ([959243c](https://github.com/bamr87/zer0-mistakes/commit/959243c0e8e504fe5d8dba44b89016b413bc88da))
|
|
22
|
+
* **docs:** theme-canary reporting contract for downstream theme-scouts (FF-0019) ([#358](https://github.com/bamr87/zer0-mistakes/issues/358)) ([c1c1b30](https://github.com/bamr87/zer0-mistakes/commit/c1c1b309c5504b014602982fc96ec80c3f8f70de))
|
|
23
|
+
* **examples:** add serialized reading-blog example site ([#339](https://github.com/bamr87/zer0-mistakes/issues/339)) ([aca0b53](https://github.com/bamr87/zer0-mistakes/commit/aca0b53b88067bda80fb299f9d5148ccb185d618))
|
|
24
|
+
* **includes:** config-driven favicon, GTM gating, og:image fallback fix, sidebar nav aliases ([#327](https://github.com/bamr87/zer0-mistakes/issues/327)) ([fe8aacc](https://github.com/bamr87/zer0-mistakes/commit/fe8aacc234003f9f170fcb3b8b29c60ac18ed94b))
|
|
25
|
+
* **install:** Claude Code OAuth + multi-provider AI + config-file layer ([#330](https://github.com/bamr87/zer0-mistakes/issues/330)) ([fde414c](https://github.com/bamr87/zer0-mistakes/commit/fde414cce5286f90de1ad02ca6ca40d634be5611))
|
|
26
|
+
* **layouts:** book-abc board-book layout + ABC art-style skins ([#336](https://github.com/bamr87/zer0-mistakes/issues/336)) ([d88038e](https://github.com/bamr87/zer0-mistakes/commit/d88038e806e0d1a492e5d12b4e10e55fd240d692))
|
|
27
|
+
* **navigation:** nav: pages sidebar mode — auto-build the tree from page URLs ([#333](https://github.com/bamr87/zer0-mistakes/issues/333)) ([c0c627d](https://github.com/bamr87/zer0-mistakes/commit/c0c627d5f50051e8f5eb4f0d6681244acaaa8d85))
|
|
28
|
+
* **obsidian:** revamp graph frontend with Obsidian-style controls ([#366](https://github.com/bamr87/zer0-mistakes/issues/366)) ([7143d9c](https://github.com/bamr87/zer0-mistakes/commit/7143d9cd137408ad82981c9f9835204bab3a3db5))
|
|
29
|
+
* **theme:** consumer-adoption hardening — mobile overlay fixes, zero-data resilience, extension hooks ([#338](https://github.com/bamr87/zer0-mistakes/issues/338)) ([84bcce1](https://github.com/bamr87/zer0-mistakes/commit/84bcce15e66b0bc312f513cef4a9dd11f972a049))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* **books:** pin abc-demo permalink so its cover lands at /books/abc-demo/ ([#345](https://github.com/bamr87/zer0-mistakes/issues/345)) ([943f463](https://github.com/bamr87/zer0-mistakes/commit/943f463c73081e7cc3d914c28a2ec2eea3d1b5ae))
|
|
35
|
+
* **ci:** give the Dependabot label job an explicit GH_REPO ([#370](https://github.com/bamr87/zer0-mistakes/issues/370)) ([808b20e](https://github.com/bamr87/zer0-mistakes/commit/808b20ebbdcd5b0bc139b90947297cec6d226787))
|
|
36
|
+
* **ci:** prefer CLAUDE_CODE_OAUTH_TOKEN over ANTHROPIC_API_KEY in all AI workflows ([#334](https://github.com/bamr87/zer0-mistakes/issues/334)) ([043848e](https://github.com/bamr87/zer0-mistakes/commit/043848eb84222240efc121e8112ddc12ab959a64))
|
|
37
|
+
* **ci:** unbreak the production Pages build, frozen since 2026-08-05 ([#356](https://github.com/bamr87/zer0-mistakes/issues/356)) ([05465cf](https://github.com/bamr87/zer0-mistakes/commit/05465cfd5480a6bdfb0d164d56a892f2825ec1cf))
|
|
38
|
+
* **i18n:** exclude admin config page from translation to unbreak Pages deploy ([#349](https://github.com/bamr87/zer0-mistakes/issues/349)) ([3f4890c](https://github.com/bamr87/zer0-mistakes/commit/3f4890cee3dd59b7f1cbc6ec235a863017b075fb))
|
|
39
|
+
* **i18n:** normalise generated prose so translation runs keep CI green ([#342](https://github.com/bamr87/zer0-mistakes/issues/342)) ([70a7234](https://github.com/bamr87/zer0-mistakes/commit/70a723425b8cc6a77e1b845b212a8a7d127a7779))
|
|
40
|
+
* **navigation:** mark only the current page active in the sidebar nav-tree ([#331](https://github.com/bamr87/zer0-mistakes/issues/331)) ([3f1b723](https://github.com/bamr87/zer0-mistakes/commit/3f1b723169258993d4530dd5817740e62734ccd4))
|
|
41
|
+
* **sass:** restore mobile navigation in the example, collapsed to a 60px sliver ([#363](https://github.com/bamr87/zer0-mistakes/issues/363)) ([8c7d87a](https://github.com/bamr87/zer0-mistakes/commit/8c7d87af4fd476f06c16ce58ca4d4cd0e2c4169d))
|
|
42
|
+
|
|
43
|
+
## [Unreleased]
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- **Obsidian graph frontend revamp** — the graph views now mirror the Obsidian
|
|
48
|
+
desktop experience. The full graph page gains a floating **Graph settings**
|
|
49
|
+
card (Filters / Display / Forces): search with `tag:`/`path:` operators,
|
|
50
|
+
per-collection toggles generated from the wiki-index (count badge + color
|
|
51
|
+
swatch, doubling as the legend), show-orphans and show-unresolved switches,
|
|
52
|
+
node-size / link-thickness / label-fade sliders, repel-force and
|
|
53
|
+
link-distance sliders with animated re-layout, plus a zoom / fit / fullscreen
|
|
54
|
+
button stack, an Obsidian-style hover preview card, live dark-mode restyling,
|
|
55
|
+
and localStorage persistence. The local graph panel gains a depth selector
|
|
56
|
+
(1–3) and outgoing/incoming direction switches that re-render the subgraph in
|
|
57
|
+
place. Same vendored cytoscape.js, unchanged `wiki-index.json` contract
|
|
58
|
+
(evidence:
|
|
59
|
+
[`test/visual/evidence/obsidian-graph-revamp/`](test/visual/evidence/obsidian-graph-revamp/README.md);
|
|
60
|
+
regression: `test/visual/features/obsidian-graph.spec.js`).
|
|
61
|
+
|
|
62
|
+
- **Theme-canary reporting contract** (`docs/systems/theme-canary-contract.md`) —
|
|
63
|
+
the canonical upstream bug-intake protocol for downstream theme-scout agents
|
|
64
|
+
(it-journey, lifehacker.dev): required `theme-canary` + `from-<consumer>`
|
|
65
|
+
labels, a deterministic 12-hex dedupe key + hidden body marker, the mandated
|
|
66
|
+
open-AND-closed pre-filing search, a 5-issues-per-consumer-per-run cap, and a
|
|
67
|
+
required evidence format that records the theme version/commit observed (so
|
|
68
|
+
fixed-in-release triage is mechanical). Ships with the matching
|
|
69
|
+
`theme-canary.yml` issue form.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- **Mobile navigation opened as an unusable 60px sliver in the Swerve of Shore
|
|
74
|
+
example.** Its skin set `backdrop-filter` on `.navbar` for a frosted sticky
|
|
75
|
+
header, which — per the CSS spec, alongside `transform`/`filter`/`perspective`
|
|
76
|
+
— makes that element the containing block for its `position: fixed`
|
|
77
|
+
descendants. The theme's main-nav panel (`#bdNavbar`, an `.offcanvas-lg`) is
|
|
78
|
+
one, so it sized itself against the 60px navbar instead of the viewport:
|
|
79
|
+
tapping the hamburger dimmed the page and showed a bare title bar with **0 of
|
|
80
|
+
14 navigation links** reachable. The effect now lives on a `.navbar::before`
|
|
81
|
+
pseudo-element — visually identical, not an ancestor — restoring the
|
|
82
|
+
full-height panel with **14 of 14** links (evidence:
|
|
83
|
+
[`test/visual/evidence/mobile-nav-containing-block/`](test/visual/evidence/mobile-nav-containing-block/README.md)
|
|
84
|
+
— panel 60px → 780px at 390 and 768). A new smoke-tier spec
|
|
85
|
+
(`test/visual/features/mobile-nav-containing-block.spec.js`) guards the
|
|
86
|
+
invariant on the theme and names the offending ancestor when it fails.
|
|
87
|
+
|
|
88
|
+
- **The example's home and blog pages overflowed and ran edge-to-edge on
|
|
89
|
+
phones.** Their feed grid used Bootstrap's `.row` gutters without a container
|
|
90
|
+
to absorb the −12px margins, making the page 13px wider than the screen, and
|
|
91
|
+
neither section carried an inline padding, so 15 of 30 text blocks sat flush
|
|
92
|
+
against the bezel. Now `gx-0 gy-4` plus a 0.75rem mobile gutter matching the
|
|
93
|
+
theme's own 12px inset — zero horizontal overflow at 320–768, banner still
|
|
94
|
+
full-bleed.
|
|
95
|
+
|
|
96
|
+
- **GitHub Pages production deploy no longer fails at all — the site had been
|
|
97
|
+
frozen since 2026-08-05.** Three independent faults, each of which aborted the
|
|
98
|
+
whole production `jekyll build`, so nothing published after #346:
|
|
99
|
+
1. `_layouts/collection.html` sorted `site[page.collection]` without checking
|
|
100
|
+
it resolved. A page can select this layout in front matter while living
|
|
101
|
+
outside any collection, making that lookup `nil`; Liquid's `sort` then
|
|
102
|
+
raises `Cannot sort a null object.` and kills the *entire* build, not just
|
|
103
|
+
the page. It now falls back to an empty list.
|
|
104
|
+
2. `scripts/translate.rb` copied `layout: collection` into the flat `fr/**`
|
|
105
|
+
tree, which is exactly the misconfiguration above — `fr/docs/index.md` was
|
|
106
|
+
the page that took the site down. Collection-only layouts are now dropped
|
|
107
|
+
from generated translations so the `path: fr` default (`layout: default`)
|
|
108
|
+
applies, and the affected page is regenerated.
|
|
109
|
+
3. `CHANGELOG.md` is a published page (`/CHANGELOG/`), so its prose is parsed
|
|
110
|
+
as Liquid. Two entries quoted Liquid tags without a `raw` guard; one of
|
|
111
|
+
them genuinely executed `include_relative` on `_config.yml`, which in turn
|
|
112
|
+
tripped over a literal `mermaid` tag written inside a config comment.
|
|
113
|
+
Both entries are now guarded and the config comment no longer spells the
|
|
114
|
+
tag out.
|
|
115
|
+
|
|
116
|
+
- **Production builds are now verified before merge.** `.github/workflows/pages.yml`
|
|
117
|
+
builds (never deploys) on pull requests. No other job ran `jekyll build`
|
|
118
|
+
against the production config, which is why all three faults above reached
|
|
119
|
+
`main` with CI green.
|
|
120
|
+
|
|
121
|
+
- **GitHub Pages production deploy no longer fails on the translated config
|
|
122
|
+
page.** The admin config utility `pages/_about/settings/config.md` embeds a
|
|
123
|
+
raw `_config.yml` dump via {% raw %}`{% include_relative _config.yml %}`{% endraw %}, but the
|
|
124
|
+
translation pipeline copied the page into `fr/about/settings/` without its
|
|
125
|
+
sibling data file, so the production `github-pages` build died with
|
|
126
|
+
`Could not locate the included file '_config.yml'`. The page is now excluded
|
|
127
|
+
from translation (`translation.exclude` in `_config.yml`) — it has no
|
|
128
|
+
prose to translate anyway — and the stale `fr/about/settings/config.md` plus
|
|
129
|
+
its `_data/i18n/manifest.yml` entry are removed.
|
|
130
|
+
- **Translation runs no longer break the `oneline` check.** `scripts/translate.rb`
|
|
131
|
+
writes whatever the provider returns, and a provider is free to soft-wrap a
|
|
132
|
+
translated paragraph across several lines — no prompt instruction reliably
|
|
133
|
+
prevents it. Wrapped prose then landed in `fr/**`, turned
|
|
134
|
+
`markdown-oneline.yml` red on the translation PR, and stayed red on `main`
|
|
135
|
+
after it merged. Two of the currently committed translations were in exactly
|
|
136
|
+
that state.
|
|
137
|
+
- `translate.rb` now normalises every page it writes through
|
|
138
|
+
`tools/unwrap-prose.py` — the same tool CI runs, so the rule has one source
|
|
139
|
+
of truth instead of a reimplementation that could drift. Best-effort: a
|
|
140
|
+
missing `python3` warns rather than failing an otherwise good run.
|
|
141
|
+
- `.github/workflows/translate.yml` runs the same tool as a guaranteed
|
|
142
|
+
backstop immediately before committing, then `--check`s its own work so a
|
|
143
|
+
silent failure cannot just move the breakage to the PR's CI run.
|
|
144
|
+
- The tool is resolved relative to `translate.rb` rather than `--root`;
|
|
145
|
+
`--root` points at the content tree being translated, so the previous
|
|
146
|
+
lookup missed the tool whenever the two differed.
|
|
147
|
+
- Unwrapped the two affected files, so `oneline` passes on `main` again.
|
|
148
|
+
- Regression test in `test/test_i18n.sh` backed by a new `stub-wrap`
|
|
149
|
+
provider that soft-wraps at 40 columns. Asserting "output is unwrapped"
|
|
150
|
+
against the plain stub would have passed whether or not normalisation ran.
|
|
151
|
+
|
|
152
|
+
### Added
|
|
153
|
+
|
|
154
|
+
- **`examples/` — self-contained demo sites built on the theme.** New top-level
|
|
155
|
+
directory (excluded from the theme's own site build and from the gem) for
|
|
156
|
+
complete Jekyll sites that show the theme configured for a particular kind of
|
|
157
|
+
site. Each has its own `_config.yml`, `Gemfile`, and content, and builds
|
|
158
|
+
against the local theme sources via `_config_dev.yml`.
|
|
159
|
+
- `examples/swerve-of-shore/` — **Swerve of Shore**, a serialized literary
|
|
160
|
+
reading blog rebuilt from
|
|
161
|
+
[swerveofshore.com](https://www.swerveofshore.com/) with the site owner's
|
|
162
|
+
permission. 52 pages, 0 broken internal links. Exercises a `series` output
|
|
163
|
+
collection with nested per-section paths, a data-driven taxonomy
|
|
164
|
+
(`_data/episodes.yml`) that generates the sidebar rail, the episode
|
|
165
|
+
schedule with live entry counts, and a section page for every node — so a
|
|
166
|
+
nav target resolves even where nothing is written yet. Also covers article
|
|
167
|
+
hero images (`show_hero`), entries ordered by number rather than date, the
|
|
168
|
+
shared `post-card` component in a single-column feed, and a full editorial
|
|
169
|
+
light-mode restyle done entirely through `assets/css/user-overrides.css` —
|
|
170
|
+
no theme files touched. The site's identity, taxonomy, entry titles/dates,
|
|
171
|
+
and featured images are reproduced, along with a short quoted excerpt per
|
|
172
|
+
entry (the opening the original publishes in its own RSS feed), attributed
|
|
173
|
+
and linked back. The essays themselves are not reproduced.
|
|
174
|
+
- `examples/README.md` — how to run one and the conventions for adding
|
|
175
|
+
another.
|
|
176
|
+
- **Theme propagation system — releases now reach the sites built on them.**
|
|
177
|
+
Releasing ended at RubyGems; nothing told the five downstream consumers a new
|
|
178
|
+
version existed, so all three pinned sites were still on v1.26.0 when v1.27.0
|
|
179
|
+
shipped and the two unpinned ones had been silently tracking `main`.
|
|
180
|
+
- `_data/consumers.yml` — registry of every consumer, its consumption mode
|
|
181
|
+
(`remote_theme_pinned` / `remote_theme_floating` / `gem` / `path`), and every
|
|
182
|
+
file that holds a version pin.
|
|
183
|
+
- `scripts/propagate.rb` — reports pin drift across the registry
|
|
184
|
+
(`--format text|json|github`, `--strict`) or dispatches a `theme-release`
|
|
185
|
+
event to each consumer (`--dispatch`).
|
|
186
|
+
- `.github/workflows/propagate-theme.yml` — dispatches on release publish;
|
|
187
|
+
weekly drift report. Never pushes to a consumer: each one opens its own PR so
|
|
188
|
+
its own CI gates the bump.
|
|
189
|
+
- `templates/consumer/` — the consumer's half of the contract:
|
|
190
|
+
`bump-theme-pins.sh` (rewrites `remote_theme`, `theme_repo`, and Gemfile gem
|
|
191
|
+
constraints in one pass; `--check`, `--dry-run`, `--latest`, `--pin`),
|
|
192
|
+
`theme-bump.yml` (dispatch + weekly schedule + manual), and a
|
|
193
|
+
`.theme-overrides.yml` starter. The schedule matters most for gem-mode
|
|
194
|
+
consumers, which have no `remote_theme` and so pick up nothing automatically.
|
|
195
|
+
- `docs/systems/theme-propagation.md` — how the whole flow fits together.
|
|
196
|
+
- **`./scripts/bin/manifest --check`** — verifies the committed theme manifest
|
|
197
|
+
matches the working tree, ignoring `generated_at`. `--dry-run` now emits only
|
|
198
|
+
YAML on stdout (progress logs moved to stderr) so its output can be diffed
|
|
199
|
+
directly.
|
|
200
|
+
- **Consumer extension hooks (`_includes/custom/`).** Four empty stubs the
|
|
201
|
+
chrome now includes at fixed points — `custom/head.html` (end of `<head>`),
|
|
202
|
+
`custom/body-start.html` (right after `<body>`, e.g. GTM noscript),
|
|
203
|
+
`custom/footer.html` (after the theme footer), `custom/body-end.html` (last
|
|
204
|
+
thing before `</body>`). A consumer site shadows just the stub to inject
|
|
205
|
+
JSON-LD, fonts, verification tags, or scripts — no more forking
|
|
206
|
+
`core/head.html`/`root.html` and drifting from the theme. Documented in
|
|
207
|
+
`_includes/README.md`.
|
|
208
|
+
- **`components/card-grid.html` + `components/data-card.html`.** A generic,
|
|
209
|
+
data-driven card grid (title/url/icon/badge/meta-pills/buttons schema) for
|
|
210
|
+
org hub dashboards, fleet registries, service grids, and link boards —
|
|
211
|
+
the markup consumer sites have been hand-rolling per page. Includes an
|
|
212
|
+
optional empty-state message.
|
|
213
|
+
- **`_layouts/404.html` — the 404 page as a theme layout.** The full 404
|
|
214
|
+
experience (including the unconfigured-site setup guide) now lives in the
|
|
215
|
+
theme; a consumer's `/404.html` shrinks from a 224-line vendored copy to a
|
|
216
|
+
4-line front-matter stub (`layout: "404"`). Setup mode is branded with
|
|
217
|
+
`site.title` instead of a hardcoded theme welcome, and the stub page's body
|
|
218
|
+
renders below the standard content for site-specific additions.
|
|
219
|
+
- **`color_mode_lock` config.** Pin the site to one color mode: visitor
|
|
220
|
+
preference and OS scheme are ignored, the light/dark/auto switcher is
|
|
221
|
+
removed, and `core/color-mode-init.html` + `halfmoon.js` enforce the lock
|
|
222
|
+
pre-paint. Replaces consumer JS workarounds that re-asserted a mode on every
|
|
223
|
+
`matchMedia` change.
|
|
224
|
+
- **PostHog privacy options** (`posthog.privacy.*`): `respect_gpc` (honor the
|
|
225
|
+
Global Privacy Control signal alongside DNT, default on), `require_consent`
|
|
226
|
+
(start opted out with memory-only persistence until the visitor accepts the
|
|
227
|
+
cookie-consent "analytics" category), and `geoip_disable` (no IP→location
|
|
228
|
+
resolution). Upstreams the deltas consumer sites were maintaining in a
|
|
229
|
+
full fork of `analytics/posthog.html`.
|
|
230
|
+
- **`news:` config surface for the news/section layouts.** `category_base`
|
|
231
|
+
(e.g. `/categories/` instead of the hardcoded `/news/`), `index_url`,
|
|
232
|
+
`hero: false`, `archives_url`, and a `newsletter` block (endpoint-or-mailto,
|
|
233
|
+
or hidden entirely — the old markup shipped a form that submitted nowhere).
|
|
234
|
+
|
|
235
|
+
### Changed
|
|
236
|
+
|
|
237
|
+
- **The news/section layouts work with zero `_data`.** Section navigation
|
|
238
|
+
falls back from `_data/navigation/posts.yml` to `site.categories`; the hero
|
|
239
|
+
falls back to the newest post when nothing is marked `breaking`/`featured`;
|
|
240
|
+
tags links render only when a tags page exists (honoring `site.tags_page`);
|
|
241
|
+
archive month links render only when an archives page exists. A data-less
|
|
242
|
+
consumer now gets a fully working magazine homepage instead of empty chrome
|
|
243
|
+
and 404 links.
|
|
244
|
+
- **Zero-`_data` resilience across components.** The skin quick-select and
|
|
245
|
+
theme customizer fall back to the compiled skin registry when
|
|
246
|
+
`_data/theme_skins.yml` is absent; the page-feedback widget falls back to a
|
|
247
|
+
generic four-type taxonomy when `_data/feedback_types.yml` is absent; the
|
|
248
|
+
landing get-started band (theme install cards) renders only when the site
|
|
249
|
+
ships a `landing.get_started` block — a data-less consumer no longer
|
|
250
|
+
advertises the theme's own install methods.
|
|
251
|
+
- **`home` layout accepts `hide_intro` as an alias of `hide_title`**, matching
|
|
252
|
+
the flag other layouts use for "suppress the generated page header".
|
|
253
|
+
- **`halfmoon.js` honors `color_mode_default`.** The switcher no longer
|
|
254
|
+
overrides the configured default with the OS preference on first visit
|
|
255
|
+
(previously the page could flip modes right after load).
|
|
256
|
+
- The default skin fallback is now `air` everywhere (`root.html`,
|
|
257
|
+
controls bar, customizer) — `dark` was never a compiled skin, so the old
|
|
258
|
+
fallback selected a skin that doesn't exist.
|
|
259
|
+
|
|
260
|
+
### Fixed
|
|
261
|
+
|
|
262
|
+
- **`_data/theme-manifest.yml` was 13 minors stale.** It sat at `1.14.0` while
|
|
263
|
+
the theme shipped to `1.27.0`, so every SHA-256 in it was wrong and
|
|
264
|
+
`scripts/bin/audit-consumer` — which reads it to classify consumer files —
|
|
265
|
+
silently compared against a June snapshot. Root cause: the file's header said
|
|
266
|
+
it regenerated during `scripts/bin/release`, but release-please became the
|
|
267
|
+
canonical release path and knows nothing about it. Regenerated, and now held
|
|
268
|
+
current by a CI gate (`version.rb` ↔ manifest version) plus
|
|
269
|
+
`manifest-sync.yml`, which regenerates it inside the release PR.
|
|
270
|
+
- **`test/fixtures/consumer-gem/_layouts/default.html` had drifted from the
|
|
271
|
+
theme layout it mirrors**, so the "`--fix` deletes IDENTICAL files" audit test
|
|
272
|
+
had been failing since the layout changed in #310 — the fixture was being
|
|
273
|
+
classified `DIFFERS_UNJUSTIFIED` rather than `IDENTICAL`, testing the opposite
|
|
274
|
+
of its intent. Re-synced; the audit suite is green again (21/21).
|
|
275
|
+
- **Mobile overlays no longer trap under the page chrome.** The
|
|
276
|
+
`.zer0-bg-body` background utility isolates the body stacking context and
|
|
277
|
+
pushes the noise overlay to `z-index: -1` instead of force-elevating every
|
|
278
|
+
direct child (`position: relative; z-index: 1`). That old rule made `<main>`
|
|
279
|
+
a stacking context that (a) capped the docs-sidebar offcanvas below the
|
|
280
|
+
fixed header — its close button was unreachable on mobile — and (b) beat
|
|
281
|
+
FAB `position: fixed` rules on specificity, dropping them into flow and
|
|
282
|
+
adding 16px of horizontal scroll on content pages.
|
|
283
|
+
- **Main-nav offcanvas paints above its backdrop on mobile.** The fixed header
|
|
284
|
+
is lifted over Bootstrap's body-level backdrop only while `#bdNavbar` is
|
|
285
|
+
opening/open/closing, so the menu is actually tappable instead of rendering
|
|
286
|
+
dimmed behind the backdrop.
|
|
287
|
+
- **The unified drawer's Search button works.** It targeted `#search-modal`
|
|
288
|
+
but the modal's id is `#siteSearchModal`; it now uses the shared
|
|
289
|
+
`data-search-toggle` binding, which also closes the drawer before opening
|
|
290
|
+
search.
|
|
291
|
+
- The measured header height is published as `--zer0-header-height` on
|
|
292
|
+
`:root` (set by `auto-hide-nav.js`), so stylesheets can align overlays with
|
|
293
|
+
the real header instead of hard-coding its pixel height.
|
|
294
|
+
|
|
295
|
+
### Added
|
|
296
|
+
|
|
297
|
+
- **ABC board books (`book-abc` layout) — the "ABC & Language" series.** A new
|
|
298
|
+
immersive, single-scroll toddler alphabet layout (`_layouts/book-abc.html`)
|
|
299
|
+
driven entirely by an `alphabet:` front-matter list — one big letter, one
|
|
300
|
+
word, one picture per card, with A–Z quick-jump anchors and a cover hero.
|
|
301
|
+
The big letter is HTML typography (never baked into the art), and a card
|
|
302
|
+
whose plate is still `planned` shows a tinted "illustration coming soon"
|
|
303
|
+
placeholder so a book reads end-to-end before any art renders. New
|
|
304
|
+
`_includes/components/abc-letter.html` renders each card; `_sass/components/_book.scss`
|
|
305
|
+
gains `.abc-board` / `.abc-letter-*` styles plus a `.abc-style--<id>` skin per
|
|
306
|
+
shared art-style id. `components/bookshelf.html` now lists both `book` and
|
|
307
|
+
`book-abc` books, grouped into series shelves from `_data/series.yml`;
|
|
308
|
+
`book-card.html` shows a letter count for ABC books. Ships a demo book
|
|
309
|
+
(`pages/_books/abc-demo/`) + default series metadata (`_data/series.yml`).
|
|
310
|
+
Regression test [`test/visual/features/book-abc.spec.js`](test/visual/features/book-abc.spec.js)
|
|
311
|
+
and before/after evidence in
|
|
312
|
+
[`test/visual/evidence/book-abc/`](test/visual/evidence/book-abc/). Docs:
|
|
313
|
+
[`docs/features/abc-books.md`](docs/features/abc-books.md).
|
|
314
|
+
- **`nav: pages` sidebar mode — auto-build the left tree from page URLs.** A new
|
|
315
|
+
sidebar mode (`_includes/navigation/sidebar-pagetree.html`) derives a
|
|
316
|
+
collapsible section tree purely from page permalinks under a `sidebar.base`
|
|
317
|
+
prefix — no curated `_data/navigation/*.yml` file to write or keep in sync.
|
|
318
|
+
Enable per page / collection / site with `sidebar: {nav: pages, base: /docs/,
|
|
319
|
+
order_by: nav_order, title: …}`. It covers plain pages (`site.html_pages`) and
|
|
320
|
+
collection documents (`site.documents`) alike, groups them by first path
|
|
321
|
+
segment, humanizes section labels from the URL (never leaking a generic
|
|
322
|
+
"Index" title), sorts each section by a numeric `order_by` (natural order),
|
|
323
|
+
supports per-page `sidebar_label` / `sidebar_exclude`, and marks only the
|
|
324
|
+
current page active with its section expanded server-side — pure Liquid, so
|
|
325
|
+
it is GitHub Pages / `remote_theme` safe. Documented at
|
|
326
|
+
`/docs/features/sidebar-page-tree/`.
|
|
327
|
+
- **Claude Code OAuth in the AI installer** — the spec-driven installer
|
|
328
|
+
(`scripts/bin/install`) is now multi-provider. `scripts/install/ai/client.sh`
|
|
329
|
+
resolves a provider via `ZER0_AI_PROVIDER` (default `auto`), preferring the
|
|
330
|
+
logged-in `claude` CLI (**Claude Code OAuth** — zero key handling), then the
|
|
331
|
+
Anthropic Messages API (`CLAUDE_CODE_OAUTH_TOKEN` OAuth bearer or
|
|
332
|
+
`ANTHROPIC_API_KEY`), then OpenAI. `install doctor` reports the active
|
|
333
|
+
provider; `--ai-provider` / `--ai-model` / `ZER0_AI_MODEL` tune it; `--no-ai`
|
|
334
|
+
/ `ZER0_NO_AI=1` disable it. User context is sanitized before every call.
|
|
335
|
+
- **Config-file layer for the installer** — new `scripts/install/config.sh`
|
|
336
|
+
discovers and merges `~/.config/zer0/install.yml`, `<target>/zer0.install.yml`,
|
|
337
|
+
`<target>/.zer0/config.yml`, and `--config FILE` (precedence:
|
|
338
|
+
defaults < profile < config < env < flags). Recognises site / github / theme /
|
|
339
|
+
deploy / agents / tasks / ai keys; API keys stay environment-only.
|
|
340
|
+
- **`install suggest`** subcommand — recommend a profile + deploy target
|
|
341
|
+
(AI-assisted with rule-based fallback) — plus `--yes` as an alias for
|
|
342
|
+
`--auto-accept`.
|
|
343
|
+
- Installer regression matrix (`test/test_installer.sh`) now covers AI
|
|
344
|
+
provider resolution, text extraction across provider shapes, the config-file
|
|
345
|
+
layer + precedence, and the `doctor` AI check (all offline).
|
|
346
|
+
|
|
347
|
+
### Changed
|
|
348
|
+
|
|
349
|
+
- Installer spec default `ai.provider` is now `auto` (was `openai`); the AI
|
|
350
|
+
wizard records the provider that actually served the run.
|
|
351
|
+
- **CI workflows now honor `CLAUDE_CODE_OAUTH_TOKEN`** — `ui-audit.yml`,
|
|
352
|
+
`ai-content-review.yml`, and `ci-self-repair.yml` previously gated their
|
|
353
|
+
Claude Code agent tier on `ANTHROPIC_API_KEY` alone, silently ignoring a
|
|
354
|
+
configured OAuth token. They now follow the same house convention as
|
|
355
|
+
`claude.yml` / `issue-autopilot.yml`: `CLAUDE_CODE_OAUTH_TOKEN` preferred,
|
|
356
|
+
`ANTHROPIC_API_KEY` used only when it's absent.
|
|
357
|
+
|
|
358
|
+
### Fixed
|
|
359
|
+
|
|
360
|
+
- **Left-sidebar nav highlighted every item as "active".** `nav-tree.html`
|
|
361
|
+
used {% raw %}`{% assign is_active = page.url == item.url %}`{% endraw %}, but Liquid `assign`
|
|
362
|
+
does not evaluate `==` — it stored `page.url` (always truthy), so every link
|
|
363
|
+
rendered with the active style. Replaced the three broken assigns
|
|
364
|
+
(`is_active`, `child_active`, `gc_active`) with proper conditional assigns so
|
|
365
|
+
only the current page is marked active.
|
|
366
|
+
- **`install deploy` no longer clobbers site content.** `spec_write` treated an
|
|
367
|
+
empty `SPEC_TASKS` as "use the full default task list", so a deploy-only run
|
|
368
|
+
re-ran `config`/`pages`/`nav` and overwrote a customised `_config.yml`,
|
|
369
|
+
`index.md`, and navigation. Empty now serialises to `[]`; `deploy` is
|
|
370
|
+
deploy-only and also skips agent-file rewrites.
|
|
371
|
+
- **github-pages / remote profile emitted a broken `remote_theme`.** The remote
|
|
372
|
+
`_config.yml` template resolved `{{GITHUB_REPO}}` to the *site's* repo; it now
|
|
373
|
+
uses a dedicated `{{THEME_REMOTE}}` variable (default `bamr87/zer0-mistakes`,
|
|
374
|
+
overridable via `THEME_REMOTE`).
|
|
375
|
+
- **Deploy workflow templates had unsubstituted variables.** Added
|
|
376
|
+
`{{DEFAULT_BRANCH}}`, `{{RUBY_VERSION}}`, and `{{SITE_NAME}}` to the template
|
|
377
|
+
renderer, so the generated `jekyll-gh-pages.yml` (and docker-prod/azure-swa
|
|
378
|
+
artifacts) no longer contain literal `{{…}}` tokens. Regression tests assert
|
|
379
|
+
no unresolved tokens survive in any deploy artifact.
|
|
380
|
+
- **Agent files were written twice** when `agents` appeared in both the task
|
|
381
|
+
list and `SPEC_AGENTS`; `apply.sh` now runs the agents task at most once.
|
|
382
|
+
- **The remote / github-pages Gemfile failed to build on Ruby 3.x.** It paired
|
|
383
|
+
the legacy `github-pages` gem with a standalone `jekyll-remote-theme`, which
|
|
384
|
+
bundler resolved to an ancient github-pages 170 (Jekyll 3.6 / kramdown 1.14,
|
|
385
|
+
`rexml` LoadError). The remote Gemfile now pins modern Jekyll +
|
|
386
|
+
`jekyll-remote-theme` + `webrick`, and both the Gemfile and the remote
|
|
387
|
+
`_config.yml` template add `jekyll-include-cache` (required by the theme's
|
|
388
|
+
layouts).
|
|
389
|
+
|
|
390
|
+
## [1.27.0](https://github.com/bamr87/zer0-mistakes/compare/v1.26.0...v1.27.0) (2026-07-22)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
### Features
|
|
394
|
+
|
|
395
|
+
* **analytics:** wire posthog.html into head.html ([#317](https://github.com/bamr87/zer0-mistakes/issues/317)) ([7977fe1](https://github.com/bamr87/zer0-mistakes/commit/7977fe189dec3b62eb9779feac56ec27e513f2c3))
|
|
396
|
+
* **article:** show_hero front-matter flag opts standard posts into the hero image ([#309](https://github.com/bamr87/zer0-mistakes/issues/309)) ([6344473](https://github.com/bamr87/zer0-mistakes/commit/6344473c14c613825ab7ac9083b87f17a2a1e858))
|
|
397
|
+
* **i18n:** AI-generated multilingual support with language toggle ([#316](https://github.com/bamr87/zer0-mistakes/issues/316)) ([72b2ab6](https://github.com/bamr87/zer0-mistakes/commit/72b2ab6980742e26305a22e3aff535f465ade084))
|
|
398
|
+
* **scripts:** Claude-orchestrated preview images — Claude analyzes & reviews, image models render ([#296](https://github.com/bamr87/zer0-mistakes/issues/296)) ([acac205](https://github.com/bamr87/zer0-mistakes/commit/acac2051ec79a81c04efb1af76fb4031e106a852))
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
### Bug Fixes
|
|
402
|
+
|
|
403
|
+
* **a11y:** keep a single <main> landmark per page ([#310](https://github.com/bamr87/zer0-mistakes/issues/310)) ([fae920e](https://github.com/bamr87/zer0-mistakes/commit/fae920eb5c60b5e792e9842c9b112bd5eb60e391)), closes [#299](https://github.com/bamr87/zer0-mistakes/issues/299)
|
|
404
|
+
* **author:** build avatar path with relative_url, never protocol-relative ([#306](https://github.com/bamr87/zer0-mistakes/issues/306)) ([ac597d2](https://github.com/bamr87/zer0-mistakes/commit/ac597d2c029157bb47da5a336812f764a3946da4))
|
|
405
|
+
* **ci:** secret scan matches added lines only, not context/removals/hunk headers ([#301](https://github.com/bamr87/zer0-mistakes/issues/301)) ([1b7175d](https://github.com/bamr87/zer0-mistakes/commit/1b7175ddece3d95aefc406f3b59df682db9fd0f2))
|
|
406
|
+
* **includes:** gate Quick Links Dev row on is_production ([#308](https://github.com/bamr87/zer0-mistakes/issues/308)) ([03b6877](https://github.com/bamr87/zer0-mistakes/commit/03b687713b8552c6ceb6b2ab30ac8caea0d6632d))
|
|
407
|
+
* **obsidian:** graph reads OBSIDIAN_CONFIG.wikiIndexUrl that js-cdn.html emits ([#305](https://github.com/bamr87/zer0-mistakes/issues/305)) ([2875912](https://github.com/bamr87/zer0-mistakes/commit/28759128b7b352a054e642d153e5e38e16aa1e48))
|
|
408
|
+
* **sass:** stack left-side FABs to prevent obsidian/feedback overlap ([#289](https://github.com/bamr87/zer0-mistakes/issues/289)) ([6cc4596](https://github.com/bamr87/zer0-mistakes/commit/6cc4596dff28d164386a16a6637420f84b4571bf))
|
|
409
|
+
* **test:** repoint ZER0-003 to test_install_legacy_flags.sh after retirement ([#292](https://github.com/bamr87/zer0-mistakes/issues/292)) ([fd7a2ce](https://github.com/bamr87/zer0-mistakes/commit/fd7a2ce256e32d2f630bd82732227b54ba13d3dd))
|
|
410
|
+
* **theme:** apply relative_url to preview_path exactly once ([#307](https://github.com/bamr87/zer0-mistakes/issues/307)) ([012e577](https://github.com/bamr87/zer0-mistakes/commit/012e577fe3131e0be42f7d33a6f5161dc666cc81))
|
|
411
|
+
|
|
8
412
|
## [1.26.0](https://github.com/bamr87/zer0-mistakes/compare/v1.25.0...v1.26.0) (2026-07-07)
|
|
9
413
|
|
|
10
414
|
|
|
@@ -12,10 +416,159 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
12
416
|
|
|
13
417
|
* **feedback:** runtime "Improve this page" capture → GitHub issue (logs + AI triage) ([#286](https://github.com/bamr87/zer0-mistakes/issues/286)) ([f7fb20d](https://github.com/bamr87/zer0-mistakes/commit/f7fb20df74c22df7eb823344121c60617f06c7b6))
|
|
14
418
|
|
|
15
|
-
##
|
|
419
|
+
## Detailed notes — v1.27.0
|
|
16
420
|
|
|
17
|
-
###
|
|
421
|
+
### Added
|
|
422
|
+
|
|
423
|
+
- **Multilingual support via AI-generated translations** (ZER0-078) — the
|
|
424
|
+
theme now serves alternate-language versions of the site without storing
|
|
425
|
+
hand-written translations in source. English under `pages/**` +
|
|
426
|
+
`_data/ui-text.yml` `en` is the only human-maintained language; a
|
|
427
|
+
build-time utility ([`scripts/translate.rb`](scripts/translate.rb),
|
|
428
|
+
Claude Code OAuth with API-key fallback, stdlib-only Ruby) generates the
|
|
429
|
+
alternates and the
|
|
430
|
+
[`translate.yml`](.github/workflows/translate.yml) workflow commits them
|
|
431
|
+
via PR — one large `mode=full` dispatch job for the initial conversion,
|
|
432
|
+
plus bounded incremental runs whenever English content changes on `main`:
|
|
433
|
+
- Generated artifacts: `fr/**` page files (plain Jekyll pages with
|
|
434
|
+
explicit `/fr<en-url>` permalinks — GitHub Pages safe-mode friendly, no
|
|
435
|
+
plugin required), `_data/i18n/<lang>.yml` UI strings, and
|
|
436
|
+
`_data/i18n/manifest.yml` (en URL → translations map + SHA-based
|
|
437
|
+
incremental change detection with pruning of deleted sources).
|
|
438
|
+
- Markdown safety by construction: per-line segment translation with
|
|
439
|
+
`⟦N⟧` masking of code, Liquid, wiki-links and URLs, placeholder
|
|
440
|
+
set-equality validation with one retry, code fences never sent.
|
|
441
|
+
- Frontend: navbar **language toggle**
|
|
442
|
+
([`language-toggle.html`](_includes/components/language-toggle.html))
|
|
443
|
+
with per-page availability states and `localStorage` preference,
|
|
444
|
+
`hreflang` alternates in `<head>`, per-page `<html lang>`, and a
|
|
445
|
+
machine-translation disclosure banner linking back to the original.
|
|
446
|
+
- Refactor: UI-string lookup centralized in
|
|
447
|
+
[`core/i18n.html`](_includes/core/i18n.html) and made per-page-language
|
|
448
|
+
aware (cached chrome includes take a `lang` parameter so each language
|
|
449
|
+
gets its own `include_cached` entry); the hand-maintained es/fr/de/ar
|
|
450
|
+
blocks in `_data/ui-text.yml` were **removed** in favor of the
|
|
451
|
+
generated pipeline.
|
|
452
|
+
- Offline test suite `test/test_i18n.sh` (stub provider, no network),
|
|
453
|
+
registered as the `i18n` suite in `test_runner.sh`, plus the
|
|
454
|
+
`language-toggle` Playwright smoke spec; docs in
|
|
455
|
+
[`docs/systems/multilingual-translation.md`](docs/systems/multilingual-translation.md).
|
|
456
|
+
(evidence:
|
|
457
|
+
[`test/visual/evidence/language-toggle/`](test/visual/evidence/language-toggle/README.md)
|
|
458
|
+
and
|
|
459
|
+
[`test/visual/evidence/language-toggle-fr/`](test/visual/evidence/language-toggle-fr/README.md)
|
|
460
|
+
— toggle at 6 widths + generated French page with 0px overflow, code
|
|
461
|
+
blocks byte-identical)
|
|
462
|
+
|
|
463
|
+
- **`show_hero` front-matter flag** — a post of any `post_type` can now opt
|
|
464
|
+
its `preview:` image into the top-of-article hero with `show_hero: true`,
|
|
465
|
+
without being promoted to `featured`/`breaking` (layout width, sidebar,
|
|
466
|
+
typography, and the post-type badge keep their `post_type` defaults);
|
|
467
|
+
existing posts are unchanged by construction — the flag is falsy everywhere
|
|
468
|
+
it isn't set ([#303](https://github.com/bamr87/zer0-mistakes/issues/303)).
|
|
469
|
+
(evidence:
|
|
470
|
+
[`test/visual/evidence/show-hero/`](test/visual/evidence/show-hero/README.md)
|
|
471
|
+
— hero renders only on the opted-in demo post; whole-build before/after
|
|
472
|
+
diff: exactly 1 page differs)
|
|
473
|
+
|
|
474
|
+
- **Claude-orchestrated preview-image engine** (ZER0-004) — the three
|
|
475
|
+
divergent implementations (1,404-line Bash engine, drifted Python
|
|
476
|
+
duplicate, dead Jekyll plugin) are consolidated into ONE Python engine,
|
|
477
|
+
[`scripts/lib/preview_generator.py`](scripts/lib/preview_generator.py).
|
|
478
|
+
Claude directs; an image model renders:
|
|
479
|
+
- **Analyze** (`prompt_engine: claude`, default) — Claude reads each
|
|
480
|
+
article and writes a subject-specific art-direction brief, replacing the
|
|
481
|
+
generic template prompt that produced unrepresentative banners.
|
|
482
|
+
- **Produce** — the configured renderer executes the brief: `openai`
|
|
483
|
+
(gpt-image-2 / DALL-E, default), `xai` (grok-2-image), `stability`,
|
|
484
|
+
**`gemini` (new)** — or `local`, upgraded from a `.txt` stub to a real
|
|
485
|
+
deterministic SVG/PNG banner (sanitized, rasterized via `rsvg-convert` →
|
|
486
|
+
`inkscape` → `magick` → the new Playwright helper
|
|
487
|
+
[`scripts/dev/rasterize-svg.js`](scripts/dev/rasterize-svg.js)).
|
|
488
|
+
- **Review** (`review_engine: claude`, default) — Claude inspects the
|
|
489
|
+
rendered image with vision against the article and style; when it
|
|
490
|
+
misrepresents the subject or contains text artifacts, Claude writes a
|
|
491
|
+
corrected prompt and the engine regenerates once.
|
|
492
|
+
- Claude credential chain: `CLAUDE_CODE_OAUTH_TOKEN` (`claude setup-token`)
|
|
493
|
+
→ `ANTHROPIC_AUTH_TOKEN` → `ANTHROPIC_API_KEY` → a logged-in `claude` CLI
|
|
494
|
+
(zero-setup for Claude Code users); orchestration degrades gracefully to
|
|
495
|
+
template prompts without one.
|
|
496
|
+
- New unit suite [`test/test_preview_generator.py`](test/test_preview_generator.py)
|
|
497
|
+
(83 tests, zero network) wired into `test_core.sh`.
|
|
18
498
|
|
|
499
|
+
### Fixed
|
|
500
|
+
|
|
501
|
+
- **Obsidian graph loads its wiki index on project sites** — the full-graph
|
|
502
|
+
renderer (`assets/js/obsidian-graph.js`) now reads the baseurl-aware
|
|
503
|
+
`window.OBSIDIAN_CONFIG.wikiIndexUrl` that `js-cdn.html` emits (falling back
|
|
504
|
+
to the legacy `OBSIDIAN_WIKI_INDEX_URL` override, then the `<base>`-relative
|
|
505
|
+
path), instead of only the never-set legacy global — whose fallback dropped
|
|
506
|
+
the baseurl and 404'd the `wiki-index.json` fetch on GitHub Pages project
|
|
507
|
+
sites, leaving `/docs/obsidian/graph/` a "Failed to load graph data" alert
|
|
508
|
+
([#294](https://github.com/bamr87/zer0-mistakes/issues/294)). (evidence:
|
|
509
|
+
[`test/visual/evidence/obsidian-graph-index/`](test/visual/evidence/obsidian-graph-index/README.md)
|
|
510
|
+
— wiki-index fetch 404 → 200, alert → rendered graph, on a baseurl'd build)
|
|
511
|
+
|
|
512
|
+
- **Quick Links no longer ships a dead `localhost:4000` Dev row to production
|
|
513
|
+
visitors** — the env-switcher's Development URL row (rendered in the
|
|
514
|
+
site-wide Settings offcanvas on every page) is now wrapped in
|
|
515
|
+
{% raw %}`{% unless is_production %}`{% endraw %}, using the same `env-detect.html` flag the card
|
|
516
|
+
already keys its badge on; serving locally with `JEKYLL_ENV=production`
|
|
517
|
+
still counts as dev context, so the row stays available for Docker workflows
|
|
518
|
+
([#298](https://github.com/bamr87/zer0-mistakes/issues/298)). (evidence:
|
|
519
|
+
[`test/visual/evidence/env-switcher-prod/`](test/visual/evidence/env-switcher-prod/README.md)
|
|
520
|
+
— production Settings-chrome `localhost:4000` occurrences 5 → 0, Dev row
|
|
521
|
+
intact in development)
|
|
522
|
+
- **Author avatars never render as protocol-relative `//assets/…` URLs** —
|
|
523
|
+
`author-avatar-url.html` now builds the relative-path branch in a capture,
|
|
524
|
+
collapses doubled slashes, and applies `relative_url` exactly once, instead
|
|
525
|
+
of the manual `{{ site.baseurl }}/{{ site.public_folder }}{{ avatar }}`
|
|
526
|
+
concatenation that produced `src="//assets/…"` (a URL browsers resolve
|
|
527
|
+
against a host named `assets`) on consumer sites where `public_folder` is
|
|
528
|
+
unset or carries a leading slash
|
|
529
|
+
([#297](https://github.com/bamr87/zer0-mistakes/issues/297)). (evidence:
|
|
530
|
+
[`test/visual/evidence/author-avatar-url/`](test/visual/evidence/author-avatar-url/README.md)
|
|
531
|
+
— 4 protocol-relative avatars → 0, all avatars loading, on a misconfigured
|
|
532
|
+
consumer build)
|
|
533
|
+
|
|
534
|
+
- **Intro hero banner renders on project sites** — `content/intro.html` now
|
|
535
|
+
applies `relative_url` to the banner image exactly once (in the
|
|
536
|
+
`preview_path` assignment logic), instead of a second time at the point of
|
|
537
|
+
use, which doubled the baseurl segment on any site with a non-empty
|
|
538
|
+
`baseurl` (`url('/reponame/reponame/assets/…')` → 404 → gradient-only hero)
|
|
539
|
+
and mangled absolute preview URLs
|
|
540
|
+
([#293](https://github.com/bamr87/zer0-mistakes/issues/293)). (evidence:
|
|
541
|
+
[`test/visual/evidence/intro-banner-baseurl/`](test/visual/evidence/intro-banner-baseurl/README.md)
|
|
542
|
+
— background fetch 404 → 200 on both preview branches of a baseurl'd build)
|
|
543
|
+
|
|
544
|
+
- **Preview-image config keys `enabled`, `assets_prefix`, `auto_prefix` and
|
|
545
|
+
`collections` are now honored by the generator** (the Bash engine ignored
|
|
546
|
+
them), and front-matter `preview:` updates are scoped to the front-matter
|
|
547
|
+
block only — the previous file-wide `sed` could corrupt body lines starting
|
|
548
|
+
with `preview:`. External-URL previews are no longer silently regenerated,
|
|
549
|
+
and a configured model from the wrong vendor family falls back to the
|
|
550
|
+
provider default instead of a guaranteed API error.
|
|
551
|
+
|
|
552
|
+
- **Left-side FAB overlap** — the Obsidian local-graph button and the
|
|
553
|
+
page-feedback "Improve this page" button were both positioned at
|
|
554
|
+
`bottom: 1rem; left: 1rem` and completely overlapped each other. The
|
|
555
|
+
Obsidian FAB is now at slot 2 (`bottom: offset + size + gap`), stacking
|
|
556
|
+
above the feedback FAB — the same pattern the TOC FAB uses above
|
|
557
|
+
back-to-top on the right side. The docs-sidebar restore-mode FAB was
|
|
558
|
+
also offset to slot 2 so it cannot overlap the feedback FAB on mobile.
|
|
559
|
+
Closes #288. (evidence:
|
|
560
|
+
[`test/visual/evidence/fab-stack/`](test/visual/evidence/fab-stack/README.md)
|
|
561
|
+
— feedback↔obsidian FAB overlap 3136px² → 0; regression test
|
|
562
|
+
[`test/visual/features/fab-stack.spec.js`](test/visual/features/fab-stack.spec.js)).
|
|
563
|
+
|
|
564
|
+
### Changed
|
|
565
|
+
|
|
566
|
+
- **Preview-image generation is now Claude-orchestrated by default**
|
|
567
|
+
(`prompt_engine: claude` + `review_engine: claude`; disable with
|
|
568
|
+
`--prompt-engine template --review none`). The renderer default stays
|
|
569
|
+
`openai`. `scripts/features/generate-preview-images` is now a thin wrapper
|
|
570
|
+
delegating to the Python engine (full CLI flag surface preserved;
|
|
571
|
+
`rake preview:*` and the VS Code tasks work unchanged).
|
|
19
572
|
- **CI test tiering** — the PR-blocking Playwright gate is now the new
|
|
20
573
|
`critical` project (118 `@critical`-tagged, user-facing tests: navigation,
|
|
21
574
|
search, mobile survival, theming baseline, security) instead of the full
|
|
@@ -51,7 +604,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
51
604
|
* **navigation:** remove redundant entries from navigation menus ([916eca2](https://github.com/bamr87/zer0-mistakes/commit/916eca269726c984c5c0c9dc9533c83d9975f906))
|
|
52
605
|
* **sass:** mobile audit — contain author card, restore consent z-order, grow tap targets ([#275](https://github.com/bamr87/zer0-mistakes/issues/275)) ([8ec9867](https://github.com/bamr87/zer0-mistakes/commit/8ec9867858ff87e9b8a6fcd4a68ec7e50582c3c1))
|
|
53
606
|
|
|
54
|
-
##
|
|
607
|
+
## Detailed notes — v1.25.0
|
|
55
608
|
|
|
56
609
|
### Changed
|
|
57
610
|
|
|
@@ -161,7 +714,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
161
714
|
* **search:** existence-gate search modal form action for remote-theme consumers ([#257](https://github.com/bamr87/zer0-mistakes/issues/257)) ([b915c4d](https://github.com/bamr87/zer0-mistakes/commit/b915c4dead5eff3d6a2986720ebacdcf2bed5e33))
|
|
162
715
|
* **skins:** map dark + contrast skins to their background assets ([#245](https://github.com/bamr87/zer0-mistakes/issues/245)) ([fb8808e](https://github.com/bamr87/zer0-mistakes/commit/fb8808e5ec754785b8239b01bccfab99569b70fa)), closes [#240](https://github.com/bamr87/zer0-mistakes/issues/240)
|
|
163
716
|
|
|
164
|
-
##
|
|
717
|
+
## Detailed notes — v1.24.0–v1.25.0
|
|
165
718
|
|
|
166
719
|
### Bug Fixes
|
|
167
720
|
|
|
@@ -252,7 +805,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
252
805
|
|
|
253
806
|
* remove Year of AI / org content-hub pivot, restore theme landing page ([#180](https://github.com/bamr87/zer0-mistakes/issues/180)) ([3960f65](https://github.com/bamr87/zer0-mistakes/commit/3960f65b1af4c750216deda0d032a309b0f93b78))
|
|
254
807
|
|
|
255
|
-
##
|
|
808
|
+
## Detailed notes — v1.24.0
|
|
256
809
|
|
|
257
810
|
### Added
|
|
258
811
|
- **Visual-evidence standard + reusable evidence kit.** UI/behavioural changes
|